mirror of https://github.com/goccy/go-json.git
Fix error by race detector
This commit is contained in:
parent
0297427ef5
commit
b431a095d6
|
@ -22,11 +22,12 @@ type opcodeSet struct {
|
|||
}
|
||||
|
||||
var (
|
||||
marshalJSONType = reflect.TypeOf((*Marshaler)(nil)).Elem()
|
||||
marshalTextType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
|
||||
cachedOpcode unsafe.Pointer // map[uintptr]*opcodeSet
|
||||
baseTypeAddr uintptr
|
||||
cachedOpcodeSets []*opcodeSet
|
||||
marshalJSONType = reflect.TypeOf((*Marshaler)(nil)).Elem()
|
||||
marshalTextType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
|
||||
cachedOpcode unsafe.Pointer // map[uintptr]*opcodeSet
|
||||
baseTypeAddr uintptr
|
||||
cachedOpcodeSets []*opcodeSet
|
||||
existsCachedOpcodeSets bool
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -80,6 +81,7 @@ func setupOpcodeSets() error {
|
|||
return fmt.Errorf("too big address range %d", addrRange)
|
||||
}
|
||||
cachedOpcodeSets = make([]*opcodeSet, addrRange)
|
||||
existsCachedOpcodeSets = true
|
||||
baseTypeAddr = min
|
||||
return nil
|
||||
}
|
||||
|
@ -90,35 +92,6 @@ func init() {
|
|||
}
|
||||
}
|
||||
|
||||
func encodeCompileToGetCodeSet(typeptr uintptr) (*opcodeSet, error) {
|
||||
if cachedOpcodeSets == nil {
|
||||
return encodeCompileToGetCodeSetSlowPath(typeptr)
|
||||
}
|
||||
if codeSet := cachedOpcodeSets[typeptr-baseTypeAddr]; codeSet != nil {
|
||||
return codeSet, nil
|
||||
}
|
||||
|
||||
// noescape trick for header.typ ( reflect.*rtype )
|
||||
copiedType := *(**rtype)(unsafe.Pointer(&typeptr))
|
||||
|
||||
code, err := encodeCompileHead(&encodeCompileContext{
|
||||
typ: copiedType,
|
||||
root: true,
|
||||
structTypeToCompiledCode: map[uintptr]*compiledCode{},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
code = copyOpcode(code)
|
||||
codeLength := code.totalLength()
|
||||
codeSet := &opcodeSet{
|
||||
code: code,
|
||||
codeLength: codeLength,
|
||||
}
|
||||
cachedOpcodeSets[int(typeptr-baseTypeAddr)] = codeSet
|
||||
return codeSet, nil
|
||||
}
|
||||
|
||||
func encodeCompileToGetCodeSetSlowPath(typeptr uintptr) (*opcodeSet, error) {
|
||||
opcodeMap := loadOpcodeMap()
|
||||
if codeSet, exists := opcodeMap[typeptr]; exists {
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
// +build !race
|
||||
|
||||
package json
|
||||
|
||||
import "unsafe"
|
||||
|
||||
func encodeCompileToGetCodeSet(typeptr uintptr) (*opcodeSet, error) {
|
||||
if !existsCachedOpcodeSets {
|
||||
return encodeCompileToGetCodeSetSlowPath(typeptr)
|
||||
}
|
||||
if codeSet := cachedOpcodeSets[typeptr-baseTypeAddr]; codeSet != nil {
|
||||
return codeSet, nil
|
||||
}
|
||||
|
||||
// noescape trick for header.typ ( reflect.*rtype )
|
||||
copiedType := *(**rtype)(unsafe.Pointer(&typeptr))
|
||||
|
||||
code, err := encodeCompileHead(&encodeCompileContext{
|
||||
typ: copiedType,
|
||||
root: true,
|
||||
structTypeToCompiledCode: map[uintptr]*compiledCode{},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
code = copyOpcode(code)
|
||||
codeLength := code.totalLength()
|
||||
codeSet := &opcodeSet{
|
||||
code: code,
|
||||
codeLength: codeLength,
|
||||
}
|
||||
cachedOpcodeSets[int(typeptr-baseTypeAddr)] = codeSet
|
||||
return codeSet, nil
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
// +build race
|
||||
|
||||
package json
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var setsMu sync.RWMutex
|
||||
|
||||
func encodeCompileToGetCodeSet(typeptr uintptr) (*opcodeSet, error) {
|
||||
if !existsCachedOpcodeSets {
|
||||
return encodeCompileToGetCodeSetSlowPath(typeptr)
|
||||
}
|
||||
setsMu.RLock()
|
||||
if codeSet := cachedOpcodeSets[typeptr-baseTypeAddr]; codeSet != nil {
|
||||
setsMu.RUnlock()
|
||||
return codeSet, nil
|
||||
}
|
||||
setsMu.RUnlock()
|
||||
|
||||
// noescape trick for header.typ ( reflect.*rtype )
|
||||
copiedType := *(**rtype)(unsafe.Pointer(&typeptr))
|
||||
|
||||
code, err := encodeCompileHead(&encodeCompileContext{
|
||||
typ: copiedType,
|
||||
root: true,
|
||||
structTypeToCompiledCode: map[uintptr]*compiledCode{},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
code = copyOpcode(code)
|
||||
codeLength := code.totalLength()
|
||||
codeSet := &opcodeSet{
|
||||
code: code,
|
||||
codeLength: codeLength,
|
||||
}
|
||||
setsMu.Lock()
|
||||
cachedOpcodeSets[int(typeptr-baseTypeAddr)] = codeSet
|
||||
setsMu.Unlock()
|
||||
return codeSet, nil
|
||||
}
|
Loading…
Reference in New Issue