diff options
Diffstat (limited to 'vendor/github.com/goccy/go-json/internal/encoder/compiler_race.go')
-rw-r--r-- | vendor/github.com/goccy/go-json/internal/encoder/compiler_race.go | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/vendor/github.com/goccy/go-json/internal/encoder/compiler_race.go b/vendor/github.com/goccy/go-json/internal/encoder/compiler_race.go new file mode 100644 index 000000000..63b7733e0 --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/encoder/compiler_race.go @@ -0,0 +1,47 @@ +// +build race + +package encoder + +import ( + "sync" + "unsafe" + + "github.com/goccy/go-json/internal/runtime" +) + +var setsMu sync.RWMutex + +func CompileToGetCodeSet(typeptr uintptr) (*OpcodeSet, error) { + if typeptr > typeAddr.MaxTypeAddr { + return compileToGetCodeSetSlowPath(typeptr) + } + index := (typeptr - typeAddr.BaseTypeAddr) >> typeAddr.AddrShift + setsMu.RLock() + if codeSet := cachedOpcodeSets[index]; codeSet != nil { + setsMu.RUnlock() + return codeSet, nil + } + setsMu.RUnlock() + + // noescape trick for header.typ ( reflect.*rtype ) + copiedType := *(**runtime.Type)(unsafe.Pointer(&typeptr)) + + code, err := compileHead(&compileContext{ + typ: copiedType, + structTypeToCompiledCode: map[uintptr]*CompiledCode{}, + }) + if err != nil { + return nil, err + } + code = copyOpcode(code) + codeLength := code.TotalLength() + codeSet := &OpcodeSet{ + Type: copiedType, + Code: code, + CodeLength: codeLength, + } + setsMu.Lock() + cachedOpcodeSets[index] = codeSet + setsMu.Unlock() + return codeSet, nil +} |