Skip to content

Commit

Permalink
refactor: less in-use objects
Browse files Browse the repository at this point in the history
  • Loading branch information
xiaost committed Jul 15, 2024
1 parent 528b641 commit 563a721
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 37 deletions.
7 changes: 5 additions & 2 deletions internal/binary/defs/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ func ResolveFields(vt reflect.Type) ([]Field, error) {
}

/* still not found, do the actual resolving */
if fv, ex = doResolveFields(vt); ex != nil {
if fv, ex = DoResolveFields(vt); ex != nil {
return nil, ex
}

Expand All @@ -118,7 +118,10 @@ func ResolveFields(vt reflect.Type) ([]Field, error) {
return fv, nil
}

func doResolveFields(vt reflect.Type) ([]Field, error) {
// DoResolveFields ... no cache, use ResolveFields instead.
// it's only used by reflect pkg for less objects,
// coz reflect pkg has its own cache.
func DoResolveFields(vt reflect.Type) ([]Field, error) {
var err error
var ret []Field
var mem reflect.Value
Expand Down
12 changes: 6 additions & 6 deletions internal/reflect/decoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,11 @@ func (d *tDecoder) Decode(b []byte, base unsafe.Pointer, sd *structDesc, maxdept
return 0, errDepthLimitExceeded
}
var bs *bitset
if len(sd.requiredFields) > 0 {
if len(sd.requiredFieldIDs) > 0 {
bs = bitsetPool.Get().(*bitset)
defer bitsetPool.Put(bs)
for _, f := range sd.requiredFields {
bs.unset(f.ID)
for _, f := range sd.requiredFieldIDs {
bs.unset(f)
}
}

Expand Down Expand Up @@ -123,9 +123,9 @@ func (d *tDecoder) Decode(b []byte, base unsafe.Pointer, sd *structDesc, maxdept
bs.set(f.ID)
}
}
for _, f := range sd.requiredFields {
if !bs.test(f.ID) {
return i, newRequiredFieldNotSetException(lookupFieldName(sd.rt, f.Offset))
for _, fid := range sd.requiredFieldIDs {
if !bs.test(fid) {
return i, newRequiredFieldNotSetException(lookupFieldName(sd.rt, sd.GetField(fid).Offset))
}
}
if ufs != nil && ufs.Size() > 0 {
Expand Down
28 changes: 15 additions & 13 deletions internal/reflect/desc.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,8 @@ func createStructDesc(rv reflect.Value) (*structDesc, error) {
if rt.Kind() != reflect.Struct {
return nil, errType
}
// XXX: only for rvTypePtr
// make sure rvTypePtr returns reflect.Struct abiType
rv = reflect.New(rt).Elem()
}
abiType := rvTypePtr(rv)
abiType := rtTypePtr(rt)
mapStructDescWriteMu.Lock()
defer mapStructDescWriteMu.Unlock()
if sd := sds.Get(abiType); sd != nil {
Expand All @@ -67,6 +64,9 @@ func createStructDesc(rv reflect.Value) (*structDesc, error) {
return nil, err
}
sds.Set(abiType, sd)
if rv.Kind() == reflect.Ptr {
sds.Set(rvTypePtr(rv), sd) // *struct and struct share the same structDesc
}
return sd, nil
}

Expand Down Expand Up @@ -130,9 +130,9 @@ type structDesc struct {
hasUnknownFields bool // for the _unknownFields feature
unknownFieldsOffset uintptr

fixedLenFieldSize int // sum of f.EncodedSize() > 0
varLenFields []*tField // list of fields that f.EncodedSize() <= 0
requiredFields []*tField
fixedLenFieldSize int // sum of f.EncodedSize() > 0
varLenFields []int // maps to fields. list of fields that f.EncodedSize() <= 0
requiredFieldIDs []uint16
}

func newStructDesc(t reflect.Type) (*structDesc, error) {
Expand All @@ -142,7 +142,7 @@ func newStructDesc(t reflect.Type) (*structDesc, error) {
if t.Kind() != reflect.Struct {
return nil, errType
}
ff, err := defs.ResolveFields(t)
ff, err := defs.DoResolveFields(t)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -189,21 +189,23 @@ func (d *structDesc) fromDefsFields(ff []defs.Field) {
for i := range d.fieldIdx {
d.fieldIdx[i] = -1
}
fields := make([]tField, len(ff))
d.fields = make([]*tField, len(ff))
for i, f := range ff {
d.fields[i] = &tField{}
d.fields[i] = &fields[i]
d.fields[i].fromDefsField(f)
d.fieldIdx[f.ID] = i
}
d.varLenFields = make([]*tField, 0, len(ff))
for _, f := range d.fields {
d.varLenFields = make([]int, 0, len(ff))
d.requiredFieldIDs = make([]uint16, 0, len(ff))
for i, f := range d.fields {
if n := f.EncodedSize(); n > 0 {
d.fixedLenFieldSize += n
} else {
d.varLenFields = append(d.varLenFields, f)
d.varLenFields = append(d.varLenFields, i)
}
if f.Spec == defs.Required {
d.requiredFields = append(d.requiredFields, f)
d.requiredFieldIDs = append(d.requiredFieldIDs, f.ID)
}
}
}
Expand Down
3 changes: 1 addition & 2 deletions internal/reflect/encoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,7 @@ func (e *tEncoder) encodeContainerType(t *tType, b []byte, p unsafe.Pointer) (in
}
binary.BigEndian.PutUint32(b[2:], uint32(maplen(*(*unsafe.Pointer)(p))))
i := mapHeaderLen
mv := rvWithPtr(t.RV, p)
it := newMapIter(mv)
it := newMapIter(rvWithPtr(t.RV, p))
for kp, vp := it.Next(); kp != nil; kp, vp = it.Next() {
// Key
// SimpleType or tSTRUCT
Expand Down
24 changes: 19 additions & 5 deletions internal/reflect/hack.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ func testhack() {
panic("compatibility issue found: rvTypePtr")
}

if rtTypePtr(reflect.TypeOf(m1)) != rvTypePtr(reflect.ValueOf(m1)) ||
rtTypePtr(reflect.New(rv.Type()).Elem().Type()) != rvTypePtr(rv) {
panic("compatibility issue found: rtTypePtr")
}

var f iFoo = &dog{"test"} // update itab
if f.Foo() != "test" {
panic("never goes here ...")
Expand Down Expand Up @@ -152,14 +157,13 @@ func rvPtr(rv reflect.Value) unsafe.Pointer {
return (*rvtype)(unsafe.Pointer(&rv)).ptr
}

type iface struct {
tab uintptr
data unsafe.Pointer
}

// updateIface updates the underlying data ptr of a iface.
// PLEASE MAKE SURE the iface.tab matches the data pointer
func updateIface(p, data unsafe.Pointer) {
type iface struct {
tab uintptr
data unsafe.Pointer
}
(*iface)(p).data = data
}

Expand All @@ -170,6 +174,16 @@ func rvTypePtr(rv reflect.Value) uintptr {
return (*rvtype)(unsafe.Pointer(&rv)).abiType
}

// rtTypePtr returns the abi.Type pointer of the given reflect.Type.
// *rtype of reflect pkg shares the same data struct with *abi.Type
func rtTypePtr(rt reflect.Type) uintptr {
type iface struct {
tab uintptr
data uintptr
}
return (*iface)(unsafe.Pointer(&rt)).data
}

// same as reflect.StringHeader with Data type is unsafe.Pointer
type stringHeader struct {
Data unsafe.Pointer
Expand Down
22 changes: 13 additions & 9 deletions internal/reflect/ttype.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ type tType struct {
MallocAbiType uintptr // 0 if a type contains no pointer

// tmp var for reflect.Type, use `rvWithPtr` to copy-on-write
// only used for newMapIter
RV reflect.Value

IsPointer bool // true if t.Tag == defs.T_pointer
Expand Down Expand Up @@ -127,6 +128,11 @@ func newTType(x *defs.Type) *tType {
return t
}
t := &tType{}

// newTType is always succuess, update cache as soon as it's created
// this func is called with lock, no need to add a additional one.
ttypes[k] = t

t.T = ttype(x.Tag())
t.WT = t.T
t.Tag = x.T
Expand All @@ -137,14 +143,14 @@ func newTType(x *defs.Type) *tType {
t.Size = int(x.S.Size())
t.Align = x.S.Align()

t.RV = reflect.New(t.RT) // alloc on heap, make it addressable
t.RV = t.RV.Elem()
switch t.RV.Kind() {
switch t.RT.Kind() {
case reflect.Array, reflect.Map, reflect.Ptr, reflect.Slice, reflect.String, reflect.Struct:
t.MallocAbiType = rvTypePtr(t.RV) // pass to mallocgc
t.MallocAbiType = rtTypePtr(t.RT) // pass to mallocgc
}

if t.T == tMAP {
t.RV = reflect.New(t.RT) // alloc on heap, make it addressable
t.RV = t.RV.Elem()
t.MapTmpVarsPool = initOrGetMapTmpVarsPool(t)
}
t.IsPointer = t.Tag == defs.T_pointer
Expand All @@ -158,7 +164,6 @@ func newTType(x *defs.Type) *tType {
case tSTRUCT:
t.EncodedSizeFunc = t.EncodedSize
}
ttypes[k] = t
if x.K != nil {
t.K = newTType(x.K)
}
Expand Down Expand Up @@ -198,7 +203,8 @@ func (t *tType) EncodedSize(base unsafe.Pointer) (int, error) {
return 1, nil // tSTOP
}
ret := sd.fixedLenFieldSize
for _, f := range sd.varLenFields {
for _, i := range sd.varLenFields {
f := sd.fields[i]
p := unsafe.Add(base, f.Offset)
if f.CanSkipEncodeIfNil && *(*unsafe.Pointer)(p) == nil {
continue
Expand Down Expand Up @@ -258,11 +264,9 @@ func (t *tType) encodedMapSize(p unsafe.Pointer) (int, error) {
return ret, nil // fast path
}

mv := rvWithPtr(t.RV, p)

// we already skipped primitive types.
// need to handle tSTRING, tMAP, tLIST, tSET or tSTRUCT
it := newMapIter(mv)
it := newMapIter(rvWithPtr(t.RV, p))
for kp, vp := it.Next(); kp != nil; kp, vp = it.Next() {
// Key
// tSTRING, tSTRUCT
Expand Down

0 comments on commit 563a721

Please sign in to comment.