Fix error by race detector

This commit is contained in:
Masaaki Goshima 2021-02-01 20:02:43 +09:00
parent 0297427ef5
commit b431a095d6
3 changed files with 85 additions and 34 deletions

View File

@ -27,6 +27,7 @@ var (
cachedOpcode unsafe.Pointer // map[uintptr]*opcodeSet cachedOpcode unsafe.Pointer // map[uintptr]*opcodeSet
baseTypeAddr uintptr baseTypeAddr uintptr
cachedOpcodeSets []*opcodeSet cachedOpcodeSets []*opcodeSet
existsCachedOpcodeSets bool
) )
const ( const (
@ -80,6 +81,7 @@ func setupOpcodeSets() error {
return fmt.Errorf("too big address range %d", addrRange) return fmt.Errorf("too big address range %d", addrRange)
} }
cachedOpcodeSets = make([]*opcodeSet, addrRange) cachedOpcodeSets = make([]*opcodeSet, addrRange)
existsCachedOpcodeSets = true
baseTypeAddr = min baseTypeAddr = min
return nil 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) { func encodeCompileToGetCodeSetSlowPath(typeptr uintptr) (*opcodeSet, error) {
opcodeMap := loadOpcodeMap() opcodeMap := loadOpcodeMap()
if codeSet, exists := opcodeMap[typeptr]; exists { if codeSet, exists := opcodeMap[typeptr]; exists {

34
encode_compile_norace.go Normal file
View File

@ -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
}

44
encode_compile_race.go Normal file
View File

@ -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
}