internal/runtime: check abi.TFlagRegularMemory
This commit is contained in:
@@ -134,21 +134,8 @@ func nilinterhash(p unsafe.Pointer, h uintptr) uintptr {
|
|||||||
// Note: this function must match the compiler generated
|
// Note: this function must match the compiler generated
|
||||||
// functions exactly. See issue 37716.
|
// functions exactly. See issue 37716.
|
||||||
func typehash(t *_type, p unsafe.Pointer, h uintptr) uintptr {
|
func typehash(t *_type, p unsafe.Pointer, h uintptr) uintptr {
|
||||||
// if t.TFlag&abi.TFlagRegularMemory != 0 {
|
if t.TFlag&abi.TFlagRegularMemory != 0 {
|
||||||
// // Handle ptr sizes specially, see issue 37086.
|
// Handle ptr sizes specially, see issue 37086.
|
||||||
// switch t.Size_ {
|
|
||||||
// case 4:
|
|
||||||
// return memhash32(p, h)
|
|
||||||
// case 8:
|
|
||||||
// return memhash64(p, h)
|
|
||||||
// default:
|
|
||||||
// return memhash(p, h, t.Size_)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
switch t.Kind() {
|
|
||||||
case abi.Bool, abi.Int, abi.Int8, abi.Int16, abi.Int32, abi.Int64,
|
|
||||||
abi.Uint, abi.Uint8, abi.Uint16, abi.Uint32, abi.Uint64,
|
|
||||||
abi.Uintptr, abi.UnsafePointer, abi.Pointer:
|
|
||||||
switch t.Size_ {
|
switch t.Size_ {
|
||||||
case 4:
|
case 4:
|
||||||
return memhash32(p, h)
|
return memhash32(p, h)
|
||||||
@@ -157,6 +144,8 @@ func typehash(t *_type, p unsafe.Pointer, h uintptr) uintptr {
|
|||||||
default:
|
default:
|
||||||
return memhash(p, h, t.Size_)
|
return memhash(p, h, t.Size_)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
switch t.Kind() {
|
||||||
case abi.Float32:
|
case abi.Float32:
|
||||||
return f32hash(p, h)
|
return f32hash(p, h)
|
||||||
case abi.Float64:
|
case abi.Float64:
|
||||||
@@ -179,8 +168,6 @@ func typehash(t *_type, p unsafe.Pointer, h uintptr) uintptr {
|
|||||||
h = typehash(a.Elem, add(p, i*a.Elem.Size_), h)
|
h = typehash(a.Elem, add(p, i*a.Elem.Size_), h)
|
||||||
}
|
}
|
||||||
return h
|
return h
|
||||||
case abi.Chan:
|
|
||||||
return typehash(t.Elem(), p, h)
|
|
||||||
case abi.Struct:
|
case abi.Struct:
|
||||||
s := (*structtype)(unsafe.Pointer(t))
|
s := (*structtype)(unsafe.Pointer(t))
|
||||||
for _, f := range s.Fields {
|
for _, f := range s.Fields {
|
||||||
|
|||||||
@@ -60,6 +60,14 @@ func basicEqual(kind Kind, size uintptr) func(a, b unsafe.Pointer) bool {
|
|||||||
panic("unreachable")
|
panic("unreachable")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func basicFlags(kind Kind) abi.TFlag {
|
||||||
|
switch kind {
|
||||||
|
case abi.Float32, abi.Float64, abi.Complex64, abi.Complex128, abi.String:
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return abi.TFlagRegularMemory
|
||||||
|
}
|
||||||
|
|
||||||
func Basic(kind Kind) *Type {
|
func Basic(kind Kind) *Type {
|
||||||
if tyBasic[kind] == nil {
|
if tyBasic[kind] == nil {
|
||||||
name, size, align := basicTypeInfo(kind)
|
name, size, align := basicTypeInfo(kind)
|
||||||
@@ -70,6 +78,7 @@ func Basic(kind Kind) *Type {
|
|||||||
FieldAlign_: uint8(align),
|
FieldAlign_: uint8(align),
|
||||||
Kind_: uint8(kind),
|
Kind_: uint8(kind),
|
||||||
Equal: basicEqual(kind, size),
|
Equal: basicEqual(kind, size),
|
||||||
|
TFlag: basicFlags(kind),
|
||||||
Str_: name,
|
Str_: name,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -170,6 +179,9 @@ func Struct(pkgPath string, size uintptr, fields ...abi.StructField) *Type {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if isRegularMemory(&ret.Type) {
|
||||||
|
ret.TFlag = abi.TFlagRegularMemory
|
||||||
|
}
|
||||||
return &ret.Type
|
return &ret.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,13 +208,14 @@ func newPointer(elem *Type) *Type {
|
|||||||
FieldAlign_: pointerAlign,
|
FieldAlign_: pointerAlign,
|
||||||
Kind_: uint8(abi.Pointer),
|
Kind_: uint8(abi.Pointer),
|
||||||
Equal: memequalptr,
|
Equal: memequalptr,
|
||||||
|
TFlag: abi.TFlagRegularMemory,
|
||||||
},
|
},
|
||||||
Elem: elem,
|
Elem: elem,
|
||||||
}
|
}
|
||||||
if (elem.TFlag & abi.TFlagExtraStar) != 0 {
|
if (elem.TFlag & abi.TFlagExtraStar) != 0 {
|
||||||
ptr.Str_ = "**" + elem.Str_
|
ptr.Str_ = "**" + elem.Str_
|
||||||
} else {
|
} else {
|
||||||
ptr.TFlag = abi.TFlagExtraStar
|
ptr.TFlag |= abi.TFlagExtraStar
|
||||||
ptr.Str_ = elem.Str_
|
ptr.Str_ = elem.Str_
|
||||||
}
|
}
|
||||||
return &ptr.Type
|
return &ptr.Type
|
||||||
@@ -255,6 +268,9 @@ func ArrayOf(length uintptr, elem *Type) *Type {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ret.Len == 0 || ret.Elem.TFlag&abi.TFlagRegularMemory != 0 {
|
||||||
|
ret.TFlag = abi.TFlagRegularMemory
|
||||||
|
}
|
||||||
return &ret.Type
|
return &ret.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -264,6 +280,7 @@ func ChanOf(dir int, strChan string, elem *Type) *Type {
|
|||||||
Size_: 8,
|
Size_: 8,
|
||||||
Hash: uint32(abi.Chan),
|
Hash: uint32(abi.Chan),
|
||||||
Align_: pointerAlign,
|
Align_: pointerAlign,
|
||||||
|
TFlag: abi.TFlagRegularMemory,
|
||||||
FieldAlign_: pointerAlign,
|
FieldAlign_: pointerAlign,
|
||||||
Kind_: uint8(abi.Chan),
|
Kind_: uint8(abi.Chan),
|
||||||
Equal: memequalptr,
|
Equal: memequalptr,
|
||||||
@@ -272,7 +289,6 @@ func ChanOf(dir int, strChan string, elem *Type) *Type {
|
|||||||
Elem: elem,
|
Elem: elem,
|
||||||
Dir: abi.ChanDir(dir),
|
Dir: abi.ChanDir(dir),
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ret.Type
|
return &ret.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -300,4 +316,55 @@ func MapOf(key, elem *Type, bucket *Type, flags int) *Type {
|
|||||||
return &ret.Type
|
return &ret.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isRegularMemory(t *_type) bool {
|
||||||
|
switch t.Kind() {
|
||||||
|
case abi.Func, abi.Map, abi.Slice, abi.String, abi.Interface:
|
||||||
|
return false
|
||||||
|
case abi.Float32, abi.Float64, abi.Complex64, abi.Complex128:
|
||||||
|
return false
|
||||||
|
case abi.Array:
|
||||||
|
at := t.ArrayType()
|
||||||
|
b := isRegularMemory(at.Elem)
|
||||||
|
if b {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if at.Len == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
case abi.Struct:
|
||||||
|
st := t.StructType()
|
||||||
|
n := len(st.Fields)
|
||||||
|
switch n {
|
||||||
|
case 0:
|
||||||
|
return true
|
||||||
|
case 1:
|
||||||
|
f := st.Fields[0]
|
||||||
|
if f.Name_ == "_" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return isRegularMemory(f.Typ)
|
||||||
|
default:
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
f := st.Fields[i]
|
||||||
|
if f.Name_ == "_" || !isRegularMemory(f.Typ) || ispaddedfield(st, i) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// ispaddedfield reports whether the i'th field of struct type t is followed
|
||||||
|
// by padding.
|
||||||
|
func ispaddedfield(st *structtype, i int) bool {
|
||||||
|
end := st.Size()
|
||||||
|
if i+1 < len(st.Fields) {
|
||||||
|
end = st.Fields[i+1].Offset
|
||||||
|
}
|
||||||
|
fd := st.Fields[i]
|
||||||
|
return fd.Offset+fd.Typ.Size_ != end
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user