mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-01-23 14:50:21 +00:00
4d423102c1
Bumps [github.com/gin-contrib/gzip](https://github.com/gin-contrib/gzip) from 1.0.1 to 1.1.0. - [Release notes](https://github.com/gin-contrib/gzip/releases) - [Changelog](https://github.com/gin-contrib/gzip/blob/master/.goreleaser.yaml) - [Commits](https://github.com/gin-contrib/gzip/compare/v1.0.1...v1.1.0) --- updated-dependencies: - dependency-name: github.com/gin-contrib/gzip dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
375 lines
9 KiB
Go
375 lines
9 KiB
Go
// Copyright 2024 CloudWeGo Authors
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package vm
|
|
|
|
import (
|
|
"encoding"
|
|
"encoding/json"
|
|
"fmt"
|
|
"math"
|
|
"reflect"
|
|
"unsafe"
|
|
|
|
"github.com/bytedance/sonic/internal/encoder/alg"
|
|
"github.com/bytedance/sonic/internal/encoder/ir"
|
|
"github.com/bytedance/sonic/internal/encoder/vars"
|
|
"github.com/bytedance/sonic/internal/rt"
|
|
"github.com/bytedance/sonic/internal/base64"
|
|
)
|
|
|
|
const (
|
|
_S_cond = iota
|
|
_S_init
|
|
)
|
|
|
|
var (
|
|
_T_json_Marshaler = rt.UnpackType(vars.JsonMarshalerType)
|
|
_T_encoding_TextMarshaler = rt.UnpackType(vars.EncodingTextMarshalerType)
|
|
)
|
|
|
|
func print_instr(buf []byte, pc int, op ir.Op, ins *ir.Instr, p unsafe.Pointer) {
|
|
if len(buf) > 20 {
|
|
fmt.Println(string(buf[len(buf)-20:]))
|
|
} else {
|
|
fmt.Println(string(buf))
|
|
}
|
|
fmt.Printf("pc %04d, op %v, ins %#v, ptr: %x\n", pc, op, ins.Disassemble(), p)
|
|
}
|
|
|
|
func Execute(b *[]byte, p unsafe.Pointer, s *vars.Stack, flags uint64, prog *ir.Program) (error) {
|
|
pl := len(*prog)
|
|
if pl <= 0 {
|
|
return nil
|
|
}
|
|
|
|
var buf = *b
|
|
var x int
|
|
var q unsafe.Pointer
|
|
var f uint64
|
|
|
|
var pro = &(*prog)[0]
|
|
for pc := 0; pc < pl; {
|
|
ins := (*ir.Instr)(rt.Add(unsafe.Pointer(pro), ir.OpSize*uintptr(pc)))
|
|
pc++
|
|
op := ins.Op()
|
|
|
|
switch op {
|
|
case ir.OP_goto:
|
|
pc = ins.Vi()
|
|
continue
|
|
case ir.OP_byte:
|
|
v := ins.Byte()
|
|
buf = append(buf, v)
|
|
case ir.OP_text:
|
|
v := ins.Vs()
|
|
buf = append(buf, v...)
|
|
case ir.OP_deref:
|
|
p = *(*unsafe.Pointer)(p)
|
|
case ir.OP_index:
|
|
p = rt.Add(p, uintptr(ins.I64()))
|
|
case ir.OP_load:
|
|
// NOTICE: load CANNOT change f!
|
|
x, _, p, q = s.Load()
|
|
case ir.OP_save:
|
|
if !s.Save(x, f, p, q) {
|
|
return vars.ERR_too_deep
|
|
}
|
|
case ir.OP_drop:
|
|
x, f, p, q = s.Drop()
|
|
case ir.OP_drop_2:
|
|
s.Drop()
|
|
x, f, p, q = s.Drop()
|
|
case ir.OP_recurse:
|
|
vt, pv := ins.Vp2()
|
|
f := flags
|
|
if pv {
|
|
f |= (1 << alg.BitPointerValue)
|
|
}
|
|
*b = buf
|
|
if vt.Indirect() {
|
|
if err := EncodeTypedPointer(b, vt, (*unsafe.Pointer)(rt.NoEscape(unsafe.Pointer(&p))), s, f); err != nil {
|
|
return err
|
|
}
|
|
} else {
|
|
vp := (*unsafe.Pointer)(p)
|
|
if err := EncodeTypedPointer(b, vt, vp, s, f); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
buf = *b
|
|
case ir.OP_is_nil:
|
|
if is_nil(p) {
|
|
pc = ins.Vi()
|
|
continue
|
|
}
|
|
case ir.OP_is_nil_p1:
|
|
if (*rt.GoEface)(p).Value == nil {
|
|
pc = ins.Vi()
|
|
continue
|
|
}
|
|
case ir.OP_null:
|
|
buf = append(buf, 'n', 'u', 'l', 'l')
|
|
case ir.OP_str:
|
|
v := *(*string)(p)
|
|
buf = alg.Quote(buf, v, false)
|
|
case ir.OP_bool:
|
|
if *(*bool)(p) {
|
|
buf = append(buf, 't', 'r', 'u', 'e')
|
|
} else {
|
|
buf = append(buf, 'f', 'a', 'l', 's', 'e')
|
|
}
|
|
case ir.OP_i8:
|
|
v := *(*int8)(p)
|
|
buf = alg.I64toa(buf, int64(v))
|
|
case ir.OP_i16:
|
|
v := *(*int16)(p)
|
|
buf = alg.I64toa(buf, int64(v))
|
|
case ir.OP_i32:
|
|
v := *(*int32)(p)
|
|
buf = alg.I64toa(buf, int64(v))
|
|
case ir.OP_i64:
|
|
v := *(*int64)(p)
|
|
buf = alg.I64toa(buf, int64(v))
|
|
case ir.OP_u8:
|
|
v := *(*uint8)(p)
|
|
buf = alg.U64toa(buf, uint64(v))
|
|
case ir.OP_u16:
|
|
v := *(*uint16)(p)
|
|
buf = alg.U64toa(buf, uint64(v))
|
|
case ir.OP_u32:
|
|
v := *(*uint32)(p)
|
|
buf = alg.U64toa(buf, uint64(v))
|
|
case ir.OP_u64:
|
|
v := *(*uint64)(p)
|
|
buf = alg.U64toa(buf, uint64(v))
|
|
case ir.OP_f32:
|
|
v := *(*float32)(p)
|
|
if math.IsNaN(float64(v)) || math.IsInf(float64(v), 0) {
|
|
if flags&(1<<alg.BitEncodeNullForInfOrNan) != 0 {
|
|
buf = append(buf, 'n', 'u', 'l', 'l')
|
|
continue
|
|
}
|
|
return vars.ERR_nan_or_infinite
|
|
}
|
|
buf = alg.F32toa(buf, v)
|
|
case ir.OP_f64:
|
|
v := *(*float64)(p)
|
|
if math.IsNaN(v) || math.IsInf(v, 0) {
|
|
if flags&(1<<alg.BitEncodeNullForInfOrNan) != 0 {
|
|
buf = append(buf, 'n', 'u', 'l', 'l')
|
|
continue
|
|
}
|
|
return vars.ERR_nan_or_infinite
|
|
}
|
|
buf = alg.F64toa(buf, v)
|
|
case ir.OP_bin:
|
|
v := *(*[]byte)(p)
|
|
buf = base64.EncodeBase64(buf, v)
|
|
case ir.OP_quote:
|
|
v := *(*string)(p)
|
|
buf = alg.Quote(buf, v, true)
|
|
case ir.OP_number:
|
|
v := *(*json.Number)(p)
|
|
if v == "" {
|
|
buf = append(buf, '0')
|
|
} else if !rt.IsValidNumber(string(v)) {
|
|
return vars.Error_number(v)
|
|
} else {
|
|
buf = append(buf, v...)
|
|
}
|
|
case ir.OP_eface:
|
|
*b = buf
|
|
if err := EncodeTypedPointer(b, *(**rt.GoType)(p), (*unsafe.Pointer)(rt.Add(p, 8)), s, flags); err != nil {
|
|
return err
|
|
}
|
|
buf = *b
|
|
case ir.OP_iface:
|
|
*b = buf
|
|
if err := EncodeTypedPointer(b, (*(**rt.GoItab)(p)).Vt, (*unsafe.Pointer)(rt.Add(p, 8)), s, flags); err != nil {
|
|
return err
|
|
}
|
|
buf = *b
|
|
case ir.OP_is_zero_map:
|
|
v := *(**rt.GoMap)(p)
|
|
if v == nil || v.Count == 0 {
|
|
pc = ins.Vi()
|
|
continue
|
|
}
|
|
case ir.OP_map_iter:
|
|
v := *(**rt.GoMap)(p)
|
|
vt := ins.Vr()
|
|
it, err := alg.IteratorStart(rt.MapType(vt), v, flags)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
q = unsafe.Pointer(it)
|
|
case ir.OP_map_stop:
|
|
it := (*alg.MapIterator)(q)
|
|
alg.IteratorStop(it)
|
|
q = nil
|
|
case ir.OP_map_value_next:
|
|
it := (*alg.MapIterator)(q)
|
|
p = it.It.V
|
|
alg.IteratorNext(it)
|
|
case ir.OP_map_check_key:
|
|
it := (*alg.MapIterator)(q)
|
|
if it.It.K == nil {
|
|
pc = ins.Vi()
|
|
continue
|
|
}
|
|
p = it.It.K
|
|
case ir.OP_marshal_text:
|
|
vt, itab := ins.Vtab()
|
|
var it rt.GoIface
|
|
switch vt.Kind() {
|
|
case reflect.Interface :
|
|
if is_nil(p) {
|
|
buf = append(buf, 'n', 'u', 'l', 'l')
|
|
continue
|
|
}
|
|
it = rt.AssertI2I(_T_encoding_TextMarshaler, *(*rt.GoIface)(p))
|
|
case reflect.Ptr, reflect.Map : it = convT2I(p, true, itab)
|
|
default : it = convT2I(p, !vt.Indirect(), itab)
|
|
}
|
|
if err := alg.EncodeTextMarshaler(&buf, *(*encoding.TextMarshaler)(unsafe.Pointer(&it)), (flags)); err != nil {
|
|
return err
|
|
}
|
|
case ir.OP_marshal_text_p:
|
|
_, itab := ins.Vtab()
|
|
it := convT2I(p, false, itab)
|
|
if err := alg.EncodeTextMarshaler(&buf, *(*encoding.TextMarshaler)(unsafe.Pointer(&it)), (flags)); err != nil {
|
|
return err
|
|
}
|
|
case ir.OP_map_write_key:
|
|
if has_opts(flags, alg.BitSortMapKeys) {
|
|
v := *(*string)(p)
|
|
buf = alg.Quote(buf, v, false)
|
|
pc = ins.Vi()
|
|
continue
|
|
}
|
|
case ir.OP_slice_len:
|
|
v := (*rt.GoSlice)(p)
|
|
x = v.Len
|
|
p = v.Ptr
|
|
//TODO: why?
|
|
f |= 1<<_S_init
|
|
case ir.OP_slice_next:
|
|
if x == 0 {
|
|
pc = ins.Vi()
|
|
continue
|
|
}
|
|
x--
|
|
if has_opts(f, _S_init) {
|
|
f &= ^uint64(1 << _S_init)
|
|
} else {
|
|
p = rt.Add(p, uintptr(ins.Vlen()))
|
|
}
|
|
case ir.OP_cond_set:
|
|
f |= 1<<_S_cond
|
|
case ir.OP_cond_testc:
|
|
if has_opts(f, _S_cond) {
|
|
f &= ^uint64(1 << _S_cond)
|
|
pc = ins.Vi()
|
|
continue
|
|
}
|
|
case ir.OP_is_zero_1:
|
|
if *(*uint8)(p) == 0 {
|
|
pc = ins.Vi()
|
|
continue
|
|
}
|
|
case ir.OP_is_zero_2:
|
|
if *(*uint16)(p) == 0 {
|
|
pc = ins.Vi()
|
|
continue
|
|
}
|
|
case ir.OP_is_zero_4:
|
|
if *(*uint32)(p) == 0 {
|
|
pc = ins.Vi()
|
|
continue
|
|
}
|
|
case ir.OP_is_zero_8:
|
|
if *(*uint64)(p) == 0 {
|
|
pc = ins.Vi()
|
|
continue
|
|
}
|
|
case ir.OP_empty_arr:
|
|
if has_opts(flags, alg.BitNoNullSliceOrMap) {
|
|
buf = append(buf, '[', ']')
|
|
} else {
|
|
buf = append(buf, 'n', 'u', 'l', 'l')
|
|
}
|
|
case ir.OP_empty_obj:
|
|
if has_opts(flags, alg.BitNoNullSliceOrMap) {
|
|
buf = append(buf, '{', '}')
|
|
} else {
|
|
buf = append(buf, 'n', 'u', 'l', 'l')
|
|
}
|
|
case ir.OP_marshal:
|
|
vt, itab := ins.Vtab()
|
|
var it rt.GoIface
|
|
switch vt.Kind() {
|
|
case reflect.Interface :
|
|
if is_nil(p) {
|
|
buf = append(buf, 'n', 'u', 'l', 'l')
|
|
continue
|
|
}
|
|
it = rt.AssertI2I(_T_json_Marshaler, *(*rt.GoIface)(p))
|
|
case reflect.Ptr, reflect.Map : it = convT2I(p, true, itab)
|
|
default : it = convT2I(p, !vt.Indirect(), itab)
|
|
}
|
|
if err := alg.EncodeJsonMarshaler(&buf, *(*json.Marshaler)(unsafe.Pointer(&it)), (flags)); err != nil {
|
|
return err
|
|
}
|
|
case ir.OP_marshal_p:
|
|
_, itab := ins.Vtab()
|
|
it := convT2I(p, false, itab)
|
|
if err := alg.EncodeJsonMarshaler(&buf, *(*json.Marshaler)(unsafe.Pointer(&it)), (flags)); err != nil {
|
|
return err
|
|
}
|
|
default:
|
|
panic(fmt.Sprintf("not implement %s at %d", ins.Op().String(), pc))
|
|
}
|
|
}
|
|
|
|
*b = buf
|
|
return nil
|
|
}
|
|
|
|
// func to_buf(w unsafe.Pointer, l int, c int) []byte {
|
|
// return rt.BytesFrom(unsafe.Pointer(uintptr(w)-uintptr(l)), l, c)
|
|
// }
|
|
|
|
// func from_buf(buf []byte) (unsafe.Pointer, int, int) {
|
|
// return rt.IndexByte(buf, len(buf)), len(buf), cap(buf)
|
|
// }
|
|
|
|
func has_opts(opts uint64, bit int) bool {
|
|
return opts & (1<<bit) != 0
|
|
}
|
|
|
|
func is_nil(p unsafe.Pointer) bool {
|
|
return *(*unsafe.Pointer)(p) == nil
|
|
}
|
|
|
|
func convT2I(ptr unsafe.Pointer, deref bool, itab *rt.GoItab) (rt.GoIface) {
|
|
if deref {
|
|
ptr = *(*unsafe.Pointer)(ptr)
|
|
}
|
|
return rt.GoIface{
|
|
Itab: itab,
|
|
Value: ptr,
|
|
}
|
|
}
|