2
0
Fork 0
mirror of https://github.com/ii64/sonic.git synced 2026-06-20 16:45:22 +08:00

fix: use stackmap of shadow func as jit func's (#127)

* fix: use stackmap of shadow func as jit func's

* fix: use LoadWithFaker in decoder

* fix: LoadWithFaker support go115

* add 'runtime.' prefix on jit funcname to prevent preempt

* add parallel GC tests

* remove no_stack_pointer()

Co-authored-by: duanyi.aster <duanyi.aster@bytedance.com>
Co-authored-by: liuqiang <liuqiang.06@bytedance.com>
This commit is contained in:
Yi Duan 2021-11-09 11:50:40 +08:00 committed by GitHub
parent 3a25fcac4f
commit 442ce696fb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 7204 additions and 5553 deletions

View file

@ -19,5 +19,6 @@ header:
- 'internal/native/avx2/native_subr_amd64.go' # auto-generated by asm2asm - 'internal/native/avx2/native_subr_amd64.go' # auto-generated by asm2asm
- 'internal/resolver/asm.s' # empty file - 'internal/resolver/asm.s' # empty file
- 'internal/rt/asm.s' # empty file - 'internal/rt/asm.s' # empty file
- 'internal/loader/asm.s' # empty file
comment: on-failure comment: on-failure

View file

@ -17,12 +17,47 @@
package ast package ast
import ( import (
`encoding/json` `encoding/json`
`testing` `testing`
`runtime`
`runtime/debug`
`sync`
`github.com/bytedance/sonic/internal/native/types` `github.com/bytedance/sonic/internal/native/types`
) )
func TestGC_Encode(t *testing.T) {
root, err := NewSearcher(_TwitterJson).GetByPath()
if err != nil {
t.Fatal(err)
}
root.LoadAll()
_, err = root.MarshalJSON()
if err != nil {
t.Fatal(err)
}
wg := &sync.WaitGroup{}
N := 10000
for i:=0; i<N; i++ {
wg.Add(1)
go func (wg *sync.WaitGroup) {
defer wg.Done()
root, err := NewSearcher(_TwitterJson).GetByPath()
if err != nil {
t.Fatal(err)
}
root.Load()
_, err = root.MarshalJSON()
if err != nil {
t.Fatal(err)
}
runtime.GC()
debug.FreeOSMemory()
}(wg)
}
wg.Wait()
}
func TestEncodeValue(t *testing.T) { func TestEncodeValue(t *testing.T) {
type Case struct { type Case struct {
node Node node Node

View file

@ -19,12 +19,49 @@ package ast
import ( import (
`encoding/json` `encoding/json`
`testing` `testing`
`runtime`
`runtime/debug`
`sync`
jsoniter `github.com/json-iterator/go` jsoniter `github.com/json-iterator/go`
`github.com/stretchr/testify/assert` `github.com/stretchr/testify/assert`
`github.com/tidwall/gjson` `github.com/tidwall/gjson`
) )
func TestMain(m *testing.M) {
go func () {
println("Begin GC looping...")
for {
runtime.GC()
debug.FreeOSMemory()
}
println("stop GC looping!")
}()
m.Run()
}
func TestGC_Parse(t *testing.T) {
_, _, err := Loads(_TwitterJson)
if err != nil {
t.Fatal(err)
}
wg := &sync.WaitGroup{}
N := 1000
for i:=0; i<N; i++ {
wg.Add(1)
go func (wg *sync.WaitGroup) {
defer wg.Done()
_, _, err := Loads(_TwitterJson)
if err != nil {
t.Fatal(err)
}
runtime.GC()
debug.FreeOSMemory()
}(wg)
}
wg.Wait()
}
func runDecoderTest(t *testing.T, src string, expect interface{}) { func runDecoderTest(t *testing.T, src string, expect interface{}) {
vv, err := NewParser(src).Parse() vv, err := NewParser(src).Parse()
if err != 0 { panic(err) } if err != 0 { panic(err) }

View file

@ -18,12 +18,38 @@ package ast
import ( import (
`testing` `testing`
`runtime`
`runtime/debug`
`sync`
jsoniter `github.com/json-iterator/go` jsoniter `github.com/json-iterator/go`
`github.com/stretchr/testify/assert` `github.com/stretchr/testify/assert`
`github.com/tidwall/gjson` `github.com/tidwall/gjson`
) )
func TestGC_Search(t *testing.T) {
_, err := NewSearcher(_TwitterJson).GetByPath("statuses", 0, "id")
if err != nil {
t.Fatal(err)
}
wg := &sync.WaitGroup{}
N := 10000
for i:=0; i<N; i++ {
wg.Add(1)
go func (wg *sync.WaitGroup) {
defer wg.Done()
_, err := NewSearcher(_TwitterJson).GetByPath("statuses", 0, "id")
if err != nil {
t.Fatal(err)
}
runtime.GC()
debug.FreeOSMemory()
}(wg)
}
wg.Wait()
}
func TestExportError(t *testing.T) { func TestExportError(t *testing.T) {
data := `{"a":]` data := `{"a":]`
p := NewSearcher(data) p := NewSearcher(data)

View file

@ -192,7 +192,7 @@ func newAssembler(p _Program) *_Assembler {
/** Assembler Interface **/ /** Assembler Interface **/
func (self *_Assembler) Load() _Decoder { func (self *_Assembler) Load() _Decoder {
return ptodec(self.BaseAssembler.Load("json_decoder", _FP_size, _FP_args)) return ptodec(self.BaseAssembler.LoadWithFaker("json_decoder", _FP_size, _FP_args, _Decoder_Shadow))
} }
func (self *_Assembler) Init(p _Program) *_Assembler { func (self *_Assembler) Init(p _Program) *_Assembler {
@ -289,6 +289,7 @@ func (self *_Assembler) instrs() {
for i, v := range self.p { for i, v := range self.p {
self.Mark(i) self.Mark(i)
self.instr(&v) self.instr(&v)
self.debug_instr(i, &v)
} }
} }

68
decoder/debug.go Normal file
View file

@ -0,0 +1,68 @@
/*
* Copyright 2021 ByteDance Inc.
*
* 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 decoder
import (
`strings`
`runtime`
`runtime/debug`
`github.com/bytedance/sonic/internal/jit`
)
//WARN: MUST set false after release
var debugGC = false
var (
_Instr_End _Instr = newInsOp(_OP_nil_1)
_F_gc = jit.Func(runtime.GC)
_F_force_gc = jit.Func(debug.FreeOSMemory)
_F_println = jit.Func(println_wrapper)
)
func println_wrapper(i int, op1 int, op2 int){
println(i, " Intrs ", op1, _OpNames[op1], "next: ", op2, _OpNames[op2])
}
func (self *_Assembler) print_gc(i int, p1 *_Instr, p2 *_Instr) {
self.Emit("MOVQ", jit.Imm(int64(p2.op())), jit.Ptr(_SP, 16))// MOVQ $(p2.op()), 16(SP)
self.Emit("MOVQ", jit.Imm(int64(p1.op())), jit.Ptr(_SP, 8)) // MOVQ $(p1.op()), 8(SP)
self.Emit("MOVQ", jit.Imm(int64(i)), jit.Ptr(_SP, 0)) // MOVQ $(i), (SP)
self.call_go(_F_println)
}
func (self *_Assembler) force_gc() {
self.call_go(_F_gc)
self.call_go(_F_force_gc)
}
func (self *_Assembler) debug_instr(i int, v *_Instr) {
if debugGC {
if (i+1 == len(self.p)) {
self.print_gc(i, v, &_Instr_End)
} else {
next := &(self.p[i+1])
self.print_gc(i, v, next)
name := _OpNames[next.op()]
if strings.Contains(name, "save") {
return
}
}
self.force_gc()
}
}

View file

@ -19,6 +19,9 @@ package decoder
import ( import (
`encoding/json` `encoding/json`
`testing` `testing`
`runtime`
`runtime/debug`
`sync`
`github.com/davecgh/go-spew/spew` `github.com/davecgh/go-spew/spew`
gojson `github.com/goccy/go-json` gojson `github.com/goccy/go-json`
@ -27,6 +30,48 @@ import (
`github.com/stretchr/testify/require` `github.com/stretchr/testify/require`
) )
func TestMain(m *testing.M) {
go func () {
println("Begin GC looping...")
for {
runtime.GC()
debug.FreeOSMemory()
}
println("stop GC looping!")
}()
m.Run()
}
func TestGC(t *testing.T) {
var w interface{}
out, err := decode(TwitterJson, &w)
if err != nil {
t.Fatal(err)
}
if out != len(TwitterJson) {
t.Fatal(out)
}
wg := &sync.WaitGroup{}
N := 10000
for i:=0; i<N; i++ {
wg.Add(1)
go func (wg *sync.WaitGroup) {
defer wg.Done()
var w interface{}
out, err := decode(TwitterJson, &w)
if err != nil {
t.Fatal(err)
}
if out != len(TwitterJson) {
t.Fatal(out)
}
runtime.GC()
debug.FreeOSMemory()
}(wg)
}
wg.Wait()
}
var _BindingValue TwitterStruct var _BindingValue TwitterStruct
func init() { func init() {

View file

@ -17,6 +17,8 @@
package decoder package decoder
import ( import (
`errors`
`runtime`
`sync` `sync`
`unsafe` `unsafe`
@ -58,6 +60,23 @@ type _Decoder func(
fv uint64, fv uint64,
) (int, error) ) (int, error)
var errCallShadow = errors.New("DON'T CALL THIS!")
//go:nosplit
// Faker func of _Decoder, used to export its stackmap as _Decoder's
func _Decoder_Shadow(rb *[]byte, vp unsafe.Pointer, sb *_Stack, fv uint64) error {
// align to assembler_amd64.go: _FP_offs
var stacks [_FP_offs]byte
runtime.KeepAlive(stacks)
// must keep rb, vp and sb noticeable to GC
runtime.KeepAlive(sb)
runtime.KeepAlive(rb)
runtime.KeepAlive(vp)
return errCallShadow
}
func newStack() *_Stack { func newStack() *_Stack {
if ret := stackPool.Get(); ret == nil { if ret := stackPool.Get(); ret == nil {
return new(_Stack) return new(_Stack)
@ -102,4 +121,4 @@ func findOrCompile(vt *rt.GoType) (_Decoder, error) {
} else { } else {
return nil, err return nil, err
} }
} }

View file

@ -25,6 +25,8 @@ import (
`math` `math`
`reflect` `reflect`
`regexp` `regexp`
`runtime`
`runtime/debug`
`strconv` `strconv`
`testing` `testing`
`unsafe` `unsafe`
@ -32,6 +34,18 @@ import (
`github.com/bytedance/sonic/encoder` `github.com/bytedance/sonic/encoder`
) )
func TestMain(m *testing.M) {
go func () {
println("Begin GC looping...")
for {
runtime.GC()
debug.FreeOSMemory()
}
println("stop GC looping!")
}()
m.Run()
}
type Optionals struct { type Optionals struct {
Sr string `json:"sr"` Sr string `json:"sr"`
So string `json:"so,omitempty"` So string `json:"so,omitempty"`

View file

@ -123,16 +123,16 @@ var (
) )
var ( var (
_ST = jit.Reg("BX") _ST = jit.Reg("BX")
_RP = jit.Reg("DI") _RP = jit.Reg("DI")
_RL = jit.Reg("SI") _RL = jit.Reg("SI")
_RC = jit.Reg("DX") _RC = jit.Reg("DX")
) )
var ( var (
_LR = jit.Reg("R9") _LR = jit.Reg("R9")
_ET = jit.Reg("R10") _ET = jit.Reg("R10")
_EP = jit.Reg("R11") _EP = jit.Reg("R11")
) )
var ( var (
@ -179,7 +179,7 @@ func newAssembler(p _Program) *_Assembler {
/** Assembler Interface **/ /** Assembler Interface **/
func (self *_Assembler) Load() _Encoder { func (self *_Assembler) Load() _Encoder {
return ptoenc(self.BaseAssembler.Load("json_encoder", _FP_size, _FP_args)) return ptoenc(self.BaseAssembler.LoadWithFaker("json_encoder", _FP_size, _FP_args, _Encoder_Shadow))
} }
func (self *_Assembler) Init(p _Program) *_Assembler { func (self *_Assembler) Init(p _Program) *_Assembler {
@ -260,6 +260,7 @@ func (self *_Assembler) instrs() {
for i, v := range self.p { for i, v := range self.p {
self.Mark(i) self.Mark(i)
self.instr(&v) self.instr(&v)
self.debug_instr(i, &v)
} }
} }

68
encoder/debug.go Normal file
View file

@ -0,0 +1,68 @@
/*
* Copyright 2021 ByteDance Inc.
*
* 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 encoder
import (
`strings`
`runtime`
`runtime/debug`
`github.com/bytedance/sonic/internal/jit`
)
//WARN: MUST set false after release
var debugGC = false
var (
_Instr_End _Instr = newInsOp(_OP_null)
_F_gc = jit.Func(runtime.GC)
_F_force_gc = jit.Func(debug.FreeOSMemory)
_F_println = jit.Func(println_wrapper)
)
func println_wrapper(i int, op1 int, op2 int){
println(i, " Intrs ", op1, _OpNames[op1], "next: ", op2, _OpNames[op2])
}
func (self *_Assembler) print_gc(i int, p1 *_Instr, p2 *_Instr) {
self.Emit("MOVQ", jit.Imm(int64(p2.op())), jit.Ptr(_SP, 16))// MOVQ $(p2.op()), 16(SP)
self.Emit("MOVQ", jit.Imm(int64(p1.op())), jit.Ptr(_SP, 8)) // MOVQ $(p1.op()), 8(SP)
self.Emit("MOVQ", jit.Imm(int64(i)), jit.Ptr(_SP, 0)) // MOVQ $(i), (SP)
self.call_go(_F_println)
}
func (self *_Assembler) force_gc() {
self.call_go(_F_gc)
self.call_go(_F_force_gc)
}
func (self *_Assembler) debug_instr(i int, v *_Instr) {
if debugGC {
if (i+1 == len(self.p)) {
self.print_gc(i, v, &_Instr_End)
} else {
next := &(self.p[i+1])
self.print_gc(i, v, next)
name := _OpNames[next.op()]
if strings.Contains(name, "save") {
return
}
}
self.force_gc()
}
}

View file

@ -18,7 +18,10 @@ package encoder
import ( import (
`encoding/json` `encoding/json`
`runtime`
`runtime/debug`
`strconv` `strconv`
`sync`
`testing` `testing`
gojson `github.com/goccy/go-json` gojson `github.com/goccy/go-json`
@ -26,6 +29,44 @@ import (
`github.com/stretchr/testify/require` `github.com/stretchr/testify/require`
) )
func TestMain(m *testing.M) {
go func () {
println("Begin GC looping...")
for {
runtime.GC()
debug.FreeOSMemory()
}
println("stop GC looping!")
}()
m.Run()
}
func TestGC(t *testing.T) {
out, err := Encode(_GenericValue, 0)
if err != nil {
t.Fatal(err)
}
n := len(out)
wg := &sync.WaitGroup{}
N := 10000
for i:=0; i<N; i++ {
wg.Add(1)
go func (wg *sync.WaitGroup, size int) {
defer wg.Done()
out, err := Encode(_GenericValue, 0)
if err != nil {
t.Fatal(err)
}
if len(out) != size {
t.Fatal(len(out), size)
}
runtime.GC()
debug.FreeOSMemory()
}(wg, n)
}
wg.Wait()
}
func runEncoderTest(t *testing.T, fn func(string)string, exp string, arg string) { func runEncoderTest(t *testing.T, fn func(string)string, exp string, arg string) {
require.Equal(t, exp, fn(arg)) require.Equal(t, exp, fn(arg))
} }

View file

@ -18,6 +18,8 @@ package encoder
import ( import (
`bytes` `bytes`
`errors`
`runtime`
`sync` `sync`
`unsafe` `unsafe`
@ -56,6 +58,24 @@ type _Encoder func(
fv uint64, fv uint64,
) error ) error
var errCallShadow = errors.New("DON'T CALL THIS!")
// Faker func of _Encoder, used to export its stackmap as _Encoder's
//go:nosplit
func _Encoder_Shadow(rb *[]byte, vp unsafe.Pointer, sb *_Stack, fv uint64) error {
// align to assembler_amd64.go: _FP_offs
var frames [_FP_offs]byte
runtime.KeepAlive(frames)
// must keep sb noticeable to GC
runtime.KeepAlive(sb)
runtime.KeepAlive(rb)
runtime.KeepAlive(vp)
return errCallShadow
}
func newBytes() []byte { func newBytes() []byte {
if ret := bytesPool.Get(); ret != nil { if ret := bytesPool.Get(); ret != nil {
return ret.([]byte) return ret.([]byte)

View file

@ -207,6 +207,11 @@ func (self *BaseAssembler) Load(fn string, fp int, args int) loader.Function {
return loader.Loader(self.c).Load(fn, fp, args) return loader.Loader(self.c).Load(fn, fp, args)
} }
func (self *BaseAssembler) LoadWithFaker(fn string, fp int, args int, faker interface{}) loader.Function {
self.build()
return loader.Loader(self.c).LoadWithFaker(fn, fp, args, faker)
}
/** Assembler Stages **/ /** Assembler Stages **/
func (self *BaseAssembler) init() { func (self *BaseAssembler) init() {

0
internal/loader/asm.s Normal file
View file

View file

@ -18,7 +18,8 @@ package loader
import ( import (
`sync` `sync`
_ `unsafe` `unsafe`
`reflect`
) )
//go:linkname lastmoduledatap runtime.lastmoduledatap //go:linkname lastmoduledatap runtime.lastmoduledatap
@ -28,8 +29,24 @@ var lastmoduledatap *_ModuleData
//go:linkname moduledataverify1 runtime.moduledataverify1 //go:linkname moduledataverify1 runtime.moduledataverify1
func moduledataverify1(_ *_ModuleData) func moduledataverify1(_ *_ModuleData)
//go:nosplit // PCDATA and FUNCDATA table indexes.
func no_pointers_stackmap() uintptr //
// See funcdata.h and $GROOT/src/cmd/internal/objabi/funcdata.go.
const (
_FUNCDATA_ArgsPointerMaps = 0
_FUNCDATA_LocalsPointerMaps = 1
)
type funcInfo struct {
*_Func
datap *_ModuleData
}
//go:linkname findfunc runtime.findfunc
func findfunc(pc uintptr) funcInfo
//go:linkname funcdata runtime.funcdata
func funcdata(f funcInfo, i uint8) unsafe.Pointer
var ( var (
modLock sync.Mutex modLock sync.Mutex
@ -64,3 +81,12 @@ func registerModule(mod *_ModuleData) {
lastmoduledatap = mod lastmoduledatap = mod
modLock.Unlock() modLock.Unlock()
} }
func stackMap(f interface{}) (args uintptr, locals uintptr) {
fv := reflect.ValueOf(f)
if fv.Kind() != reflect.Func {
panic("f must be reflect.Func kind!")
}
fi := findfunc(fv.Pointer())
return uintptr(funcdata(fi, uint8(_FUNCDATA_ArgsPointerMaps))), uintptr(funcdata(fi, uint8(_FUNCDATA_LocalsPointerMaps)))
}

View file

@ -98,7 +98,7 @@ var findFuncTab = &_FindFuncBucket {
idx: 1, idx: 1,
} }
func registerFunction(name string, pc uintptr, fp int, args int, size uintptr) { func registerFunction(name string, pc uintptr, fp int, args int, size uintptr, argptrs uintptr, localptrs uintptr) {
minpc := pc minpc := pc
maxpc := pc + size maxpc := pc + size
@ -127,8 +127,8 @@ func registerFunction(name string, pc uintptr, fp int, args int, size uintptr) {
args : int32(args), args : int32(args),
pcsp : int32(pcsp), pcsp : int32(pcsp),
nfuncdata : 2, nfuncdata : 2,
argptrs : no_pointers_stackmap(), argptrs : argptrs,
localptrs : no_pointers_stackmap(), localptrs : localptrs,
} }
/* align the func to 8 bytes */ /* align the func to 8 bytes */

View file

@ -126,7 +126,7 @@ func makePCtab(fp int) []byte {
return append([]byte{0}, encodeVariant((fp + 1) << 1)...) return append([]byte{0}, encodeVariant((fp + 1) << 1)...)
} }
func registerFunction(name string, pc uintptr, fp int, args int, size uintptr) { func registerFunction(name string, pc uintptr, fp int, args int, size uintptr, argptrs uintptr, localptrs uintptr) {
minpc := pc minpc := pc
maxpc := pc + size maxpc := pc + size
@ -137,8 +137,8 @@ func registerFunction(name string, pc uintptr, fp int, args int, size uintptr) {
args : int32(args), args : int32(args),
pcsp : 1, pcsp : 1,
nfuncdata : 2, nfuncdata : 2,
argptrs : no_pointers_stackmap(), argptrs : argptrs,
localptrs : no_pointers_stackmap(), localptrs : localptrs,
}} }}
/* function table */ /* function table */
@ -164,4 +164,4 @@ func registerFunction(name string, pc uintptr, fp int, args int, size uintptr) {
/* verify and register the new module */ /* verify and register the new module */
moduledataverify1(mod) moduledataverify1(mod)
registerModule(mod) registerModule(mod)
} }

View file

@ -33,14 +33,15 @@ const (
type Loader []byte type Loader []byte
type Function unsafe.Pointer type Function unsafe.Pointer
func (self Loader) Load(fn string, fp int, args int) (f Function) { func (self Loader) LoadWithFaker(fn string, fp int, args int, faker interface{}) (f Function) {
p := os.Getpagesize() p := os.Getpagesize()
n := (((len(self) - 1) / p) + 1) * p n := (((len(self) - 1) / p) + 1) * p
/* register the function */ /* register the function */
m := mmap(n) m := mmap(n)
v := fmt.Sprintf("__%s_%x", fn, m) v := fmt.Sprintf("runtime.__%s_%x", fn, m)
registerFunction(v, m, fp, args, uintptr(len(self))) argsptr, localsptr := stackMap(faker)
registerFunction(v, m, fp, args, uintptr(len(self)), argsptr, localsptr)
/* reference as a slice */ /* reference as a slice */
s := *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader { s := *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader {
@ -55,6 +56,10 @@ func (self Loader) Load(fn string, fp int, args int) (f Function) {
return Function(&m) return Function(&m)
} }
func (self Loader) Load(fn string, fp int, args int) (f Function) {
return self.LoadWithFaker(fn, fp, args, func(){})
}
func mmap(nb int) uintptr { func mmap(nb int) uintptr {
if m, _, e := syscall.RawSyscall6(syscall.SYS_MMAP, 0, uintptr(nb), _RW, _AP, 0, 0); e != 0 { if m, _, e := syscall.RawSyscall6(syscall.SYS_MMAP, 0, uintptr(nb), _RW, _AP, 0, 0); e != 0 {
panic(e) panic(e)

View file

@ -17,7 +17,11 @@
package loader package loader
import ( import (
`errors`
`fmt`
`reflect`
`runtime` `runtime`
`runtime/debug`
`testing` `testing`
`unsafe` `unsafe`
@ -36,3 +40,73 @@ func TestLoader_Load(t *testing.T) {
assert.Equal(t, 1234, v0) assert.Equal(t, 1234, v0)
println(runtime.FuncForPC(*(*uintptr)(fn)).Name()) println(runtime.FuncForPC(*(*uintptr)(fn)).Name())
} }
func faker1(in string) error {
runtime.KeepAlive(in)
return errors.New("1")
}
func faker2(in string) error {
runtime.KeepAlive(in)
return errors.New("2")
}
func faker4(in string) error {
return nil
}
func TestStackMap(t *testing.T) {
args1, locals1 := stackMap(faker1)
fi1 := findfunc(reflect.ValueOf(faker1).Pointer())
fmt.Printf("func1: %#v, args: %x, locals: %x\n", fi1, args1, locals1)
args2, locals2 := stackMap(faker2)
fi2 := findfunc(reflect.ValueOf(faker2).Pointer())
fmt.Printf("func2: %#v, args: %x, locals: %x\n", fi2, args2, locals2)
args4, locals4 := stackMap(faker4)
fi4 := findfunc(reflect.ValueOf(faker4).Pointer())
fmt.Printf("func4: %#v, args: %x, locals: %x\n", fi4, args4, locals4)
if reflect.DeepEqual(fi1, fi2) || reflect.DeepEqual(fi1, fi2) {
t.Fatal()
}
if args1 != args2 || locals1 != locals2 {
t.Fatal()
}
if args1 == args4 || locals1 == locals4 || args2 == args4 || locals2 == locals4 {
t.Fatal()
}
}
func funcWrap(f func(i *int)) int {
var ret int
var x int = 0
runtime.SetFinalizer(&x, func(xp *int){
fmt.Printf("x got dropped: %x\n", unsafe.Pointer(xp))
})
f(&x)
ret = x
return ret
}
func TestLoadWithStackMap(t *testing.T) {
var f = func(i *int) {
*i = 1234
}
v1 := funcWrap(f)
bc := []byte {
0x48, 0x8b, 0x44, 0x24, 0x08, // MOVQ 8(%rsp), %rax
0x48, 0xc7, 0x00, 0xd2, 0x04, 0x00, 0x00, // MOVQ $1234, (%rax)
0xc3, // RET
}
fn := Loader(bc).LoadWithFaker("test", 0, 8, f)
f2 := (*(*func(*int))(unsafe.Pointer(&fn)))
v2 := funcWrap(f2)
runtime.GC()
debug.FreeOSMemory()
println(v1, v2)
assert.Equal(t, v1, v2)
}

View file

@ -1,25 +0,0 @@
//
// Copyright 2021 ByteDance Inc.
//
// 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.
//
#include "go_asm.h"
#include "funcdata.h"
#include "textflag.h"
TEXT ·no_pointers_stackmap(SB), NOSPLIT, $0 - 8
NO_LOCAL_POINTERS
LEAQ runtime·no_pointers_stackmap(SB), AX
MOVQ AX, ret+0(FP)
RET

File diff suppressed because it is too large Load diff

View file

@ -3,32 +3,27 @@
package avx package avx
import (
`unsafe`
)
//go:nosplit //go:nosplit
//go:noescape //go:noescape
//goland:noinspection ALL //goland:noinspection ALL
func ___asm2asm_compiled_code__DO_NOT_CALL_THIS_SYMBOL___() func __native_entry__() uintptr
var ( var (
_func__base = ___asm2asm_compiled_code__DO_NOT_CALL_THIS_SYMBOL___ _subr__f64toa = __native_entry__() + 630
_subr__f64toa = **(**uintptr)(unsafe.Pointer(&_func__base)) + 542 _subr__i64toa = __native_entry__() + 3642
_subr__i64toa = **(**uintptr)(unsafe.Pointer(&_func__base)) + 3551 _subr__lspace = __native_entry__() + 301
_subr__lspace = **(**uintptr)(unsafe.Pointer(&_func__base)) + 238 _subr__lzero = __native_entry__() + 13
_subr__lzero = **(**uintptr)(unsafe.Pointer(&_func__base)) + 0 _subr__quote = __native_entry__() + 4955
_subr__quote = **(**uintptr)(unsafe.Pointer(&_func__base)) + 4864 _subr__skip_array = __native_entry__() + 17298
_subr__skip_array = **(**uintptr)(unsafe.Pointer(&_func__base)) + 16010 _subr__skip_object = __native_entry__() + 17333
_subr__skip_object = **(**uintptr)(unsafe.Pointer(&_func__base)) + 16045 _subr__skip_one = __native_entry__() + 15505
_subr__skip_one = **(**uintptr)(unsafe.Pointer(&_func__base)) + 14217 _subr__u64toa = __native_entry__() + 3735
_subr__u64toa = **(**uintptr)(unsafe.Pointer(&_func__base)) + 3644 _subr__unquote = __native_entry__() + 5888
_subr__unquote = **(**uintptr)(unsafe.Pointer(&_func__base)) + 5885 _subr__value = __native_entry__() + 10928
_subr__value = **(**uintptr)(unsafe.Pointer(&_func__base)) + 9700 _subr__vnumber = __native_entry__() + 13704
_subr__vnumber = **(**uintptr)(unsafe.Pointer(&_func__base)) + 12411 _subr__vsigned = __native_entry__() + 14977
_subr__vsigned = **(**uintptr)(unsafe.Pointer(&_func__base)) + 13667 _subr__vstring = __native_entry__() + 12691
_subr__vstring = **(**uintptr)(unsafe.Pointer(&_func__base)) + 11458 _subr__vunsigned = __native_entry__() + 15236
_subr__vunsigned = **(**uintptr)(unsafe.Pointer(&_func__base)) + 13944
) )
var ( var (

File diff suppressed because it is too large Load diff

View file

@ -3,32 +3,27 @@
package avx2 package avx2
import (
`unsafe`
)
//go:nosplit //go:nosplit
//go:noescape //go:noescape
//goland:noinspection ALL //goland:noinspection ALL
func ___asm2asm_compiled_code__DO_NOT_CALL_THIS_SYMBOL___() func __native_entry__() uintptr
var ( var (
_func__base = ___asm2asm_compiled_code__DO_NOT_CALL_THIS_SYMBOL___ _subr__f64toa = __native_entry__() + 903
_subr__f64toa = **(**uintptr)(unsafe.Pointer(&_func__base)) + 790 _subr__i64toa = __native_entry__() + 3915
_subr__i64toa = **(**uintptr)(unsafe.Pointer(&_func__base)) + 3799 _subr__lspace = __native_entry__() + 429
_subr__lspace = **(**uintptr)(unsafe.Pointer(&_func__base)) + 366 _subr__lzero = __native_entry__() + 13
_subr__lzero = **(**uintptr)(unsafe.Pointer(&_func__base)) + 0 _subr__quote = __native_entry__() + 5328
_subr__quote = **(**uintptr)(unsafe.Pointer(&_func__base)) + 5212 _subr__skip_array = __native_entry__() + 20361
_subr__skip_array = **(**uintptr)(unsafe.Pointer(&_func__base)) + 17881 _subr__skip_object = __native_entry__() + 20396
_subr__skip_object = **(**uintptr)(unsafe.Pointer(&_func__base)) + 17916 _subr__skip_one = __native_entry__() + 17472
_subr__skip_one = **(**uintptr)(unsafe.Pointer(&_func__base)) + 16135 _subr__u64toa = __native_entry__() + 4008
_subr__u64toa = **(**uintptr)(unsafe.Pointer(&_func__base)) + 3892 _subr__unquote = __native_entry__() + 7125
_subr__unquote = **(**uintptr)(unsafe.Pointer(&_func__base)) + 7049 _subr__value = __native_entry__() + 13020
_subr__value = **(**uintptr)(unsafe.Pointer(&_func__base)) + 11489 _subr__vnumber = __native_entry__() + 15671
_subr__vnumber = **(**uintptr)(unsafe.Pointer(&_func__base)) + 14329 _subr__vsigned = __native_entry__() + 16944
_subr__vsigned = **(**uintptr)(unsafe.Pointer(&_func__base)) + 15585 _subr__vstring = __native_entry__() + 14794
_subr__vstring = **(**uintptr)(unsafe.Pointer(&_func__base)) + 13492 _subr__vunsigned = __native_entry__() + 17203
_subr__vunsigned = **(**uintptr)(unsafe.Pointer(&_func__base)) + 15862
) )
var ( var (

@ -1 +1 @@
Subproject commit daab6520b48bc30586f7468676c990b5c1f781bd Subproject commit a9988b2b8191ac9b8bc879ff8db18c650753a067