vm.go raw

   1  // Copyright 2024 CloudWeGo Authors
   2  //
   3  // Licensed under the Apache License, Version 2.0 (the "License");
   4  // you may not use this file except in compliance with the License.
   5  // You may obtain a copy of the License at
   6  //
   7  //     http://www.apache.org/licenses/LICENSE-2.0
   8  //
   9  // Unless required by applicable law or agreed to in writing, software
  10  // distributed under the License is distributed on an "AS IS" BASIS,
  11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12  // See the License for the specific language governing permissions and
  13  // limitations under the License.
  14  
  15  package vm
  16  
  17  import (
  18  	"encoding"
  19  	"encoding/json"
  20  	"fmt"
  21  	"math"
  22  	"reflect"
  23  	"unsafe"
  24  
  25  	"github.com/bytedance/sonic/internal/encoder/alg"
  26  	"github.com/bytedance/sonic/internal/encoder/ir"
  27  	"github.com/bytedance/sonic/internal/encoder/vars"
  28  	"github.com/bytedance/sonic/internal/rt"
  29  )
  30  
  31  const (
  32  	_S_cond = iota
  33  	_S_init
  34  )
  35  
  36  var (
  37  	_T_json_Marshaler         = rt.UnpackType(vars.JsonMarshalerType)
  38  	_T_encoding_TextMarshaler = rt.UnpackType(vars.EncodingTextMarshalerType)
  39  )
  40  
  41  func print_instr(buf []byte, pc int, op ir.Op, ins *ir.Instr, p unsafe.Pointer) {
  42  	if len(buf) > 20 {
  43  		fmt.Println(string(buf[len(buf)-20:]))
  44  	} else {
  45  		fmt.Println(string(buf))
  46  	}
  47  	fmt.Printf("pc %04d, op %v, ins %#v, ptr: %x\n", pc, op, ins.Disassemble(), p)
  48  }
  49  
  50  func Execute(b *[]byte, p unsafe.Pointer, s *vars.Stack, flags uint64, prog *ir.Program) (error) {
  51  	pl := len(*prog)
  52  	if pl <= 0 {
  53  		return nil
  54  	}
  55  
  56  	var buf = *b
  57  	var x int
  58  	var q unsafe.Pointer
  59  	var f uint64
  60  
  61  	var pro = &(*prog)[0]
  62  	for pc := 0; pc < pl; {
  63  		ins := (*ir.Instr)(rt.Add(unsafe.Pointer(pro), ir.OpSize*uintptr(pc)))
  64  		pc++
  65  		op := ins.Op()
  66  
  67  		switch op {
  68  		case ir.OP_goto:
  69  			pc = ins.Vi()
  70  			continue
  71  		case ir.OP_byte:
  72  			v := ins.Byte()
  73  			buf = append(buf, v)
  74  		case ir.OP_text:
  75  			v := ins.Vs()
  76  			buf = append(buf, v...)
  77  		case ir.OP_deref:
  78  			p = *(*unsafe.Pointer)(p)
  79  		case ir.OP_index:
  80  			p = rt.Add(p, uintptr(ins.I64()))
  81  		case ir.OP_load:
  82  			// NOTICE: load CANNOT change f!
  83  			x, _, p, q = s.Load() 
  84  		case ir.OP_save:
  85  			if !s.Save(x, f, p, q) {
  86  				return vars.ERR_too_deep
  87  			}
  88  		case ir.OP_drop:
  89  			x, f, p, q = s.Drop()
  90  		case ir.OP_drop_2:
  91  			s.Drop()
  92  			x, f, p, q = s.Drop()
  93  		case ir.OP_recurse:
  94  			vt, pv := ins.Vp2()
  95  			f := flags
  96  			if pv {
  97  				f |= (1 << alg.BitPointerValue)
  98  			}
  99  			*b = buf
 100  			if vt.Indirect() {
 101  				if err := EncodeTypedPointer(b, vt, (*unsafe.Pointer)(rt.NoEscape(unsafe.Pointer(&p))), s, f); err != nil {
 102  					return err
 103  				}
 104  			} else {
 105  				vp := (*unsafe.Pointer)(p)
 106  				if err := EncodeTypedPointer(b, vt, vp, s, f); err != nil {
 107  					return err
 108  				}
 109  			}
 110  			buf = *b
 111  		case ir.OP_is_nil:
 112  			if is_nil(p) {
 113  				pc = ins.Vi()
 114  				continue
 115  			}
 116  		case ir.OP_is_nil_p1:
 117  			if (*rt.GoEface)(p).Value == nil {
 118  				pc = ins.Vi()
 119  				continue
 120  			}
 121  		case ir.OP_null:
 122  			buf = append(buf, 'n', 'u', 'l', 'l')
 123  		case ir.OP_str:
 124  			v := *(*string)(p)
 125  			buf = alg.Quote(buf, v, false)
 126  		case ir.OP_bool:
 127  			if *(*bool)(p) {
 128  				buf = append(buf, 't', 'r', 'u', 'e')
 129  			} else {
 130  				buf = append(buf, 'f', 'a', 'l', 's', 'e')
 131  			}
 132  		case ir.OP_i8:
 133  			v := *(*int8)(p)
 134  			buf = alg.I64toa(buf, int64(v))
 135  		case ir.OP_i16:
 136  			v := *(*int16)(p)
 137  			buf = alg.I64toa(buf, int64(v))
 138  		case ir.OP_i32:
 139  			v := *(*int32)(p)
 140  			buf = alg.I64toa(buf, int64(v))
 141  		case ir.OP_i64:
 142  			v := *(*int64)(p)
 143  			buf = alg.I64toa(buf, int64(v))
 144  		case ir.OP_u8:
 145  			v := *(*uint8)(p)
 146  			buf = alg.U64toa(buf, uint64(v))
 147  		case ir.OP_u16:
 148  			v := *(*uint16)(p)
 149  			buf = alg.U64toa(buf, uint64(v))
 150  		case ir.OP_u32:
 151  			v := *(*uint32)(p)
 152  			buf = alg.U64toa(buf, uint64(v))
 153  		case ir.OP_u64:
 154  			v := *(*uint64)(p)
 155  			buf = alg.U64toa(buf, uint64(v))
 156  		case ir.OP_f32:
 157  			v := *(*float32)(p)
 158  			if math.IsNaN(float64(v)) || math.IsInf(float64(v), 0) {
 159  				if flags&(1<<alg.BitEncodeNullForInfOrNan) != 0 {
 160  					buf = append(buf, 'n', 'u', 'l', 'l')
 161  					continue
 162  				}
 163  				return vars.ERR_nan_or_infinite
 164  			}
 165  			buf = alg.F32toa(buf, v)
 166  		case ir.OP_f64:
 167  			v := *(*float64)(p)
 168  			if math.IsNaN(v) || math.IsInf(v, 0) {
 169  				if flags&(1<<alg.BitEncodeNullForInfOrNan) != 0 {
 170  					buf = append(buf, 'n', 'u', 'l', 'l')
 171  					continue
 172  				}
 173  				return vars.ERR_nan_or_infinite
 174  			}
 175  			buf = alg.F64toa(buf, v)
 176  		case ir.OP_bin:
 177  			v := *(*[]byte)(p)
 178  			buf = rt.EncodeBase64(buf, v)
 179  		case ir.OP_quote:
 180  			v := *(*string)(p)
 181  			buf = alg.Quote(buf, v, true)
 182  		case ir.OP_number:
 183  			v := *(*json.Number)(p)
 184  			if v == "" {
 185  				buf = append(buf, '0')
 186  			} else if !rt.IsValidNumber(string(v)) {
 187  				return vars.Error_number(v)
 188  			} else {
 189  				buf = append(buf, v...)
 190  			}
 191  		case ir.OP_eface:
 192  			*b = buf
 193  			if err := EncodeTypedPointer(b, *(**rt.GoType)(p), (*unsafe.Pointer)(rt.Add(p, 8)), s, flags); err != nil {
 194  				return err
 195  			}
 196  			buf = *b
 197  		case ir.OP_iface:
 198  			*b = buf
 199  			if err := EncodeTypedPointer(b,  (*(**rt.GoItab)(p)).Vt, (*unsafe.Pointer)(rt.Add(p, 8)), s, flags); err != nil {
 200  				return err
 201  			}
 202  			buf = *b
 203  		case ir.OP_is_zero_map:
 204  			v := *(*unsafe.Pointer)(p)
 205  			if v == nil || rt.Maplen(v) == 0 {
 206  				pc = ins.Vi()
 207  				continue
 208  			}
 209  		case ir.OP_map_iter:
 210  			v := *(*unsafe.Pointer)(p)
 211  			vt := ins.Vr()
 212  			it, err := alg.IteratorStart(rt.MapType(vt), v, flags)
 213  			if err != nil {
 214  				return err
 215  			}
 216  			q = unsafe.Pointer(it)
 217  		case ir.OP_map_stop:
 218  			it := (*alg.MapIterator)(q)
 219  			alg.IteratorStop(it)
 220  			q = nil
 221  		case ir.OP_map_value_next:
 222  			it := (*alg.MapIterator)(q)
 223  			p = it.It.V
 224  			alg.IteratorNext(it)
 225  		case ir.OP_map_check_key:
 226  			it := (*alg.MapIterator)(q)
 227  			if it.It.K == nil {
 228  				pc = ins.Vi()
 229  				continue
 230  			}
 231  			p = it.It.K
 232  		case ir.OP_marshal_text:
 233  			vt, itab := ins.Vtab()
 234  			var it rt.GoIface
 235  			switch vt.Kind() {
 236  				case reflect.Interface        : 
 237  				if is_nil(p) {
 238  					buf = append(buf, 'n', 'u', 'l', 'l')
 239  					continue
 240  				}
 241  				it = rt.AssertI2I(_T_encoding_TextMarshaler, *(*rt.GoIface)(p))
 242  				case reflect.Ptr, reflect.Map : it = convT2I(p, true, itab)
 243  				default                       : it = convT2I(p, !vt.Indirect(), itab)
 244  			}
 245  			if err := alg.EncodeTextMarshaler(&buf, *(*encoding.TextMarshaler)(unsafe.Pointer(&it)), (flags)); err != nil {
 246  				return err
 247  			}
 248  		case ir.OP_marshal_text_p:
 249  			_, itab := ins.Vtab()
 250  			it := convT2I(p, false, itab)
 251  			if err := alg.EncodeTextMarshaler(&buf, *(*encoding.TextMarshaler)(unsafe.Pointer(&it)), (flags)); err != nil {
 252  				return err
 253  			}
 254  		case ir.OP_map_write_key:
 255  			if has_opts(flags, alg.BitSortMapKeys) {
 256  				v := *(*string)(p)
 257  				buf = alg.Quote(buf, v, false)
 258  				pc = ins.Vi()
 259  				continue
 260  			}
 261  		case ir.OP_slice_len:
 262  			v := (*rt.GoSlice)(p)
 263  			x = v.Len
 264  			p = v.Ptr
 265  			//TODO: why?
 266  			f |= 1<<_S_init 
 267  		case ir.OP_slice_next:
 268  			if x == 0 {
 269  				pc = ins.Vi()
 270  				continue
 271  			}
 272  			x--
 273  			if has_opts(f, _S_init) {
 274  				f &= ^uint64(1 << _S_init)
 275  			} else {
 276  				p = rt.Add(p, uintptr(ins.Vlen()))
 277  			}
 278  		case ir.OP_cond_set:
 279  			f |= 1<<_S_cond
 280  		case ir.OP_cond_testc:
 281  			if has_opts(f, _S_cond) {
 282  				f &= ^uint64(1 << _S_cond)
 283  				pc = ins.Vi()
 284  				continue
 285  			}
 286  		case ir.OP_is_zero:
 287  			fv := ins.VField()
 288  			if alg.IsZero(p, fv) {
 289  				pc = ins.Vi()
 290  				continue
 291  			}
 292  		case ir.OP_is_zero_1:
 293  			if *(*uint8)(p) == 0 {
 294  				pc = ins.Vi()
 295  				continue
 296  			}
 297  		case ir.OP_is_zero_2:
 298  			if *(*uint16)(p) == 0 {
 299  				pc = ins.Vi()
 300  				continue
 301  			}
 302  		case ir.OP_is_zero_4:
 303  			if *(*uint32)(p) == 0 {
 304  				pc = ins.Vi()
 305  				continue
 306  			}
 307  		case ir.OP_is_zero_8:
 308  			if *(*uint64)(p) == 0 {
 309  				pc = ins.Vi()
 310  				continue
 311  			}
 312  		case ir.OP_empty_arr:
 313  			if has_opts(flags, alg.BitNoNullSliceOrMap) {
 314  				buf = append(buf, '[', ']')
 315  			} else {
 316  				buf = append(buf, 'n', 'u', 'l', 'l')
 317  			}
 318  		case ir.OP_empty_obj:
 319  			if has_opts(flags, alg.BitNoNullSliceOrMap) {
 320  				buf = append(buf, '{', '}')
 321  			} else {
 322  				buf = append(buf, 'n', 'u', 'l', 'l')
 323  			}
 324  		case ir.OP_marshal:
 325  			vt, itab := ins.Vtab()
 326  			var it rt.GoIface
 327  			switch vt.Kind() {
 328  				case reflect.Interface        : 
 329  				if is_nil(p) {
 330  					buf = append(buf, 'n', 'u', 'l', 'l')
 331  					continue
 332  				}
 333  				it = rt.AssertI2I(_T_json_Marshaler, *(*rt.GoIface)(p))
 334  				case reflect.Ptr, reflect.Map : it = convT2I(p, true, itab)
 335  				default                       : it = convT2I(p, !vt.Indirect(), itab)
 336  			}
 337  			if err := alg.EncodeJsonMarshaler(&buf, *(*json.Marshaler)(unsafe.Pointer(&it)), (flags)); err != nil {
 338  				return err
 339  			}
 340  		case ir.OP_marshal_p:
 341  			_, itab := ins.Vtab()
 342  			it := convT2I(p, false, itab)
 343  			if err := alg.EncodeJsonMarshaler(&buf, *(*json.Marshaler)(unsafe.Pointer(&it)), (flags)); err != nil {
 344  				return err
 345  			}
 346  		case ir.OP_unsupported:
 347  			return vars.Error_unsuppoted(ins.GoType())
 348  		default:
 349  			panic(fmt.Sprintf("not implement %s at %d", ins.Op().String(), pc))
 350  		}
 351  	}
 352  
 353  	*b = buf
 354  	return nil
 355  }
 356  
 357  
 358  func has_opts(opts uint64, bit int) bool {
 359  	return opts & (1<<bit) != 0
 360  }
 361  
 362  func is_nil(p unsafe.Pointer) bool {
 363  	return *(*unsafe.Pointer)(p) == nil
 364  }
 365  
 366  func convT2I(ptr unsafe.Pointer, deref bool, itab *rt.GoItab) (rt.GoIface) {
 367  	if deref {
 368  		ptr = *(*unsafe.Pointer)(ptr)
 369  	}
 370  	return rt.GoIface{
 371  		Itab:  itab,
 372  		Value: ptr,
 373  	}
 374  }
 375