compiler,reflect: make field offsets varints

Fixes #3686
This commit is contained in:
Damian Gryski
2023-04-27 09:14:08 -07:00
committed by Ron Evans
parent 02913563df
commit 07fb3a0cad
3 changed files with 36 additions and 9 deletions
+29 -5
View File
@@ -463,7 +463,6 @@ type structType struct {
type structField struct {
fieldType *rawType
offset uint32
data unsafe.Pointer // various bits of information, packed in a byte array
}
@@ -624,7 +623,7 @@ func (t *rawType) Field(i int) StructField {
}
}
func rawStructFieldFromPointer(descriptor *structType, fieldType *rawType, data unsafe.Pointer, flagsByte uint8, name string, offset uintptr) rawStructField {
func rawStructFieldFromPointer(descriptor *structType, fieldType *rawType, data unsafe.Pointer, flagsByte uint8, name string, offset uint32) rawStructField {
// Read the field tag, if there is one.
var tag string
if flagsByte&structFieldFlagHasTag != 0 {
@@ -651,7 +650,7 @@ func rawStructFieldFromPointer(descriptor *structType, fieldType *rawType, data
Type: fieldType,
Tag: StructTag(tag),
Anonymous: flagsByte&structFieldFlagAnonymous != 0,
Offset: offset,
Offset: uintptr(offset),
}
}
@@ -673,13 +672,14 @@ func (t *rawType) rawField(n int) rawStructField {
// lookup faster), but by calculating it on-the-fly a bit of storage can be
// saved.
field := (*structField)(unsafe.Add(unsafe.Pointer(&descriptor.fields[0]), uintptr(n)*unsafe.Sizeof(structField{})))
offset := uintptr(field.offset)
data := field.data
// Read some flags of this field, like whether the field is an embedded
// field. See structFieldFlagAnonymous and similar flags.
flagsByte := *(*byte)(data)
data = unsafe.Add(data, 1)
offset, lenOffs := uvarint32(unsafe.Slice((*byte)(data), maxVarintLen32))
data = unsafe.Add(data, lenOffs)
name := readStringZ(data)
data = unsafe.Add(data, len(name))
@@ -729,10 +729,12 @@ func (t *rawType) rawFieldByName(n string) (rawStructField, []int, bool) {
flagsByte := *(*byte)(data)
data = unsafe.Add(data, 1)
offset, lenOffs := uvarint32(unsafe.Slice((*byte)(data), maxVarintLen32))
data = unsafe.Add(data, lenOffs)
name := readStringZ(data)
data = unsafe.Add(data, len(name))
if name == n {
offset := uintptr(field.offset)
found = append(found, result{
rawStructFieldFromPointer(descriptor, field.fieldType, data, flagsByte, name, offset),
append(ll.index, int(i)),
@@ -1284,3 +1286,25 @@ func StructOf([]StructField) Type {
func MapOf(key, value Type) Type {
panic("unimplemented: reflect.MapOf()")
}
const maxVarintLen32 = 5
// encoding/binary.Uvarint, specialized for uint32
func uvarint32(buf []byte) (uint32, int) {
var x uint32
var s uint
for i, b := range buf {
if i == maxVarintLen32 {
return 0, -(i + 1) // overflow
}
if b < 0x80 {
if i == maxVarintLen32-1 && b > 1 {
return 0, -(i + 1) // overflow
}
return x | uint32(b)<<s, i + 1
}
x |= uint32(b&0x7f) << s
s += 7
}
return 0, 0
}
+1 -2
View File
@@ -96,8 +96,7 @@ func interfaceTypeAssert(ok bool) {
type structField struct {
typecode unsafe.Pointer // type of this struct field
offset uint32
data *uint8 // pointer to byte array containing name, tag, and 'embedded' flag
data *uint8 // pointer to byte array containing name, tag, and 'embedded' flag
}
// Pseudo function call used during a type assert. It is used during interface