diff options
| author | Michael Pratt <mpratt@google.com> | 2024-04-19 13:52:31 -0400 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2024-08-02 16:41:53 +0000 |
| commit | 4f7dc282c4bdfba4e63b39bbe9846c1469dc7ee5 (patch) | |
| tree | b4fa4f7de70120c25c408b85056ac30245cfaef9 /src/cmd/link | |
| parent | 057b703407fa833193cbdc1f37179561c6c9da90 (diff) | |
| download | go-4f7dc282c4bdfba4e63b39bbe9846c1469dc7ee5.tar.xz | |
all: split old and swiss map abi and compiler integration
The two map implementations are still identical, but now the compiler
targets the appropriate ABI depending on GOEXPERIMENT.
For #54766.
Cq-Include-Trybots: luci.golang.try:gotip-linux-amd64-longtest,gotip-linux-amd64-longtest-swissmap
Change-Id: I8438f64f044ba9de30ddbf2b8ceb9b4edd2d5614
Reviewed-on: https://go-review.googlesource.com/c/go/+/580779
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Michael Pratt <mpratt@google.com>
Diffstat (limited to 'src/cmd/link')
| -rw-r--r-- | src/cmd/link/internal/ld/deadcode.go | 8 | ||||
| -rw-r--r-- | src/cmd/link/internal/ld/dwarf.go | 132 | ||||
| -rw-r--r-- | src/cmd/link/internal/ld/dwarf_test.go | 11 |
3 files changed, 136 insertions, 15 deletions
diff --git a/src/cmd/link/internal/ld/deadcode.go b/src/cmd/link/internal/ld/deadcode.go index 20609ed7bf..3d547259a1 100644 --- a/src/cmd/link/internal/ld/deadcode.go +++ b/src/cmd/link/internal/ld/deadcode.go @@ -552,8 +552,12 @@ func (d *deadcodePass) decodetypeMethods(ldr *loader.Loader, arch *sys.Arch, sym off += 3 * arch.PtrSize case abi.Chan: // reflect.chanType off += 2 * arch.PtrSize - case abi.Map: // reflect.mapType - off += 4*arch.PtrSize + 8 + case abi.Map: + if buildcfg.Experiment.SwissMap { + off += 4*arch.PtrSize + 8 // internal/abi.SwissMapType + } else { + off += 4*arch.PtrSize + 8 // internal/abi.OldMapType + } case abi.Interface: // reflect.interfaceType off += 3 * arch.PtrSize default: diff --git a/src/cmd/link/internal/ld/dwarf.go b/src/cmd/link/internal/ld/dwarf.go index 1dc31c2565..c44a689a10 100644 --- a/src/cmd/link/internal/ld/dwarf.go +++ b/src/cmd/link/internal/ld/dwarf.go @@ -864,6 +864,110 @@ func (d *dwctxt) mkinternaltype(ctxt *Link, abbrev int, typename, keyname, valna } func (d *dwctxt) synthesizemaptypes(ctxt *Link, die *dwarf.DWDie) { + if buildcfg.Experiment.SwissMap { + d.synthesizemaptypesSwiss(ctxt, die) + } else { + d.synthesizemaptypesOld(ctxt, die) + } +} + +func (d *dwctxt) synthesizemaptypesSwiss(ctxt *Link, die *dwarf.DWDie) { + hash := walktypedef(d.findprotodie(ctxt, "type:runtime.hmap")) + bucket := walktypedef(d.findprotodie(ctxt, "type:runtime.bmap")) + + if hash == nil { + return + } + + for ; die != nil; die = die.Link { + if die.Abbrev != dwarf.DW_ABRV_MAPTYPE { + continue + } + gotype := loader.Sym(getattr(die, dwarf.DW_AT_type).Data.(dwSym)) + keytype := decodetypeMapKey(d.ldr, d.arch, gotype) + valtype := decodetypeMapValue(d.ldr, d.arch, gotype) + keydata := d.ldr.Data(keytype) + valdata := d.ldr.Data(valtype) + keysize, valsize := decodetypeSize(d.arch, keydata), decodetypeSize(d.arch, valdata) + keytype, valtype = d.walksymtypedef(d.defgotype(keytype)), d.walksymtypedef(d.defgotype(valtype)) + + // compute size info like hashmap.c does. + indirectKey, indirectVal := false, false + if keysize > abi.SwissMapMaxKeyBytes { + keysize = int64(d.arch.PtrSize) + indirectKey = true + } + if valsize > abi.SwissMapMaxElemBytes { + valsize = int64(d.arch.PtrSize) + indirectVal = true + } + + // Construct type to represent an array of BucketSize keys + keyname := d.nameFromDIESym(keytype) + dwhks := d.mkinternaltype(ctxt, dwarf.DW_ABRV_ARRAYTYPE, "[]key", keyname, "", func(dwhk *dwarf.DWDie) { + newattr(dwhk, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, abi.SwissMapBucketCount*keysize, 0) + t := keytype + if indirectKey { + t = d.defptrto(keytype) + } + d.newrefattr(dwhk, dwarf.DW_AT_type, t) + fld := d.newdie(dwhk, dwarf.DW_ABRV_ARRAYRANGE, "size") + newattr(fld, dwarf.DW_AT_count, dwarf.DW_CLS_CONSTANT, abi.SwissMapBucketCount, 0) + d.newrefattr(fld, dwarf.DW_AT_type, d.uintptrInfoSym) + }) + + // Construct type to represent an array of BucketSize values + valname := d.nameFromDIESym(valtype) + dwhvs := d.mkinternaltype(ctxt, dwarf.DW_ABRV_ARRAYTYPE, "[]val", valname, "", func(dwhv *dwarf.DWDie) { + newattr(dwhv, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, abi.SwissMapBucketCount*valsize, 0) + t := valtype + if indirectVal { + t = d.defptrto(valtype) + } + d.newrefattr(dwhv, dwarf.DW_AT_type, t) + fld := d.newdie(dwhv, dwarf.DW_ABRV_ARRAYRANGE, "size") + newattr(fld, dwarf.DW_AT_count, dwarf.DW_CLS_CONSTANT, abi.SwissMapBucketCount, 0) + d.newrefattr(fld, dwarf.DW_AT_type, d.uintptrInfoSym) + }) + + // Construct bucket<K,V> + dwhbs := d.mkinternaltype(ctxt, dwarf.DW_ABRV_STRUCTTYPE, "bucket", keyname, valname, func(dwhb *dwarf.DWDie) { + // Copy over all fields except the field "data" from the generic + // bucket. "data" will be replaced with keys/values below. + d.copychildrenexcept(ctxt, dwhb, bucket, findchild(bucket, "data")) + + fld := d.newdie(dwhb, dwarf.DW_ABRV_STRUCTFIELD, "keys") + d.newrefattr(fld, dwarf.DW_AT_type, dwhks) + newmemberoffsetattr(fld, abi.SwissMapBucketCount) + fld = d.newdie(dwhb, dwarf.DW_ABRV_STRUCTFIELD, "values") + d.newrefattr(fld, dwarf.DW_AT_type, dwhvs) + newmemberoffsetattr(fld, abi.SwissMapBucketCount+abi.SwissMapBucketCount*int32(keysize)) + fld = d.newdie(dwhb, dwarf.DW_ABRV_STRUCTFIELD, "overflow") + d.newrefattr(fld, dwarf.DW_AT_type, d.defptrto(d.dtolsym(dwhb.Sym))) + newmemberoffsetattr(fld, abi.SwissMapBucketCount+abi.SwissMapBucketCount*(int32(keysize)+int32(valsize))) + if d.arch.RegSize > d.arch.PtrSize { + fld = d.newdie(dwhb, dwarf.DW_ABRV_STRUCTFIELD, "pad") + d.newrefattr(fld, dwarf.DW_AT_type, d.uintptrInfoSym) + newmemberoffsetattr(fld, abi.SwissMapBucketCount+abi.SwissMapBucketCount*(int32(keysize)+int32(valsize))+int32(d.arch.PtrSize)) + } + + newattr(dwhb, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, abi.SwissMapBucketCount+abi.SwissMapBucketCount*keysize+abi.SwissMapBucketCount*valsize+int64(d.arch.RegSize), 0) + }) + + // Construct hash<K,V> + dwhs := d.mkinternaltype(ctxt, dwarf.DW_ABRV_STRUCTTYPE, "hash", keyname, valname, func(dwh *dwarf.DWDie) { + d.copychildren(ctxt, dwh, hash) + d.substitutetype(dwh, "buckets", d.defptrto(dwhbs)) + d.substitutetype(dwh, "oldbuckets", d.defptrto(dwhbs)) + newattr(dwh, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, getattr(hash, dwarf.DW_AT_byte_size).Value, nil) + }) + + // make map type a pointer to hash<K,V> + d.newrefattr(die, dwarf.DW_AT_type, d.defptrto(dwhs)) + } +} + +func (d *dwctxt) synthesizemaptypesOld(ctxt *Link, die *dwarf.DWDie) { hash := walktypedef(d.findprotodie(ctxt, "type:runtime.hmap")) bucket := walktypedef(d.findprotodie(ctxt, "type:runtime.bmap")) @@ -885,11 +989,11 @@ func (d *dwctxt) synthesizemaptypes(ctxt *Link, die *dwarf.DWDie) { // compute size info like hashmap.c does. indirectKey, indirectVal := false, false - if keysize > abi.MapMaxKeyBytes { + if keysize > abi.OldMapMaxKeyBytes { keysize = int64(d.arch.PtrSize) indirectKey = true } - if valsize > abi.MapMaxElemBytes { + if valsize > abi.OldMapMaxElemBytes { valsize = int64(d.arch.PtrSize) indirectVal = true } @@ -897,28 +1001,28 @@ func (d *dwctxt) synthesizemaptypes(ctxt *Link, die *dwarf.DWDie) { // Construct type to represent an array of BucketSize keys keyname := d.nameFromDIESym(keytype) dwhks := d.mkinternaltype(ctxt, dwarf.DW_ABRV_ARRAYTYPE, "[]key", keyname, "", func(dwhk *dwarf.DWDie) { - newattr(dwhk, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, abi.MapBucketCount*keysize, 0) + newattr(dwhk, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, abi.OldMapBucketCount*keysize, 0) t := keytype if indirectKey { t = d.defptrto(keytype) } d.newrefattr(dwhk, dwarf.DW_AT_type, t) fld := d.newdie(dwhk, dwarf.DW_ABRV_ARRAYRANGE, "size") - newattr(fld, dwarf.DW_AT_count, dwarf.DW_CLS_CONSTANT, abi.MapBucketCount, 0) + newattr(fld, dwarf.DW_AT_count, dwarf.DW_CLS_CONSTANT, abi.OldMapBucketCount, 0) d.newrefattr(fld, dwarf.DW_AT_type, d.uintptrInfoSym) }) // Construct type to represent an array of BucketSize values valname := d.nameFromDIESym(valtype) dwhvs := d.mkinternaltype(ctxt, dwarf.DW_ABRV_ARRAYTYPE, "[]val", valname, "", func(dwhv *dwarf.DWDie) { - newattr(dwhv, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, abi.MapBucketCount*valsize, 0) + newattr(dwhv, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, abi.OldMapBucketCount*valsize, 0) t := valtype if indirectVal { t = d.defptrto(valtype) } d.newrefattr(dwhv, dwarf.DW_AT_type, t) fld := d.newdie(dwhv, dwarf.DW_ABRV_ARRAYRANGE, "size") - newattr(fld, dwarf.DW_AT_count, dwarf.DW_CLS_CONSTANT, abi.MapBucketCount, 0) + newattr(fld, dwarf.DW_AT_count, dwarf.DW_CLS_CONSTANT, abi.OldMapBucketCount, 0) d.newrefattr(fld, dwarf.DW_AT_type, d.uintptrInfoSym) }) @@ -930,20 +1034,20 @@ func (d *dwctxt) synthesizemaptypes(ctxt *Link, die *dwarf.DWDie) { fld := d.newdie(dwhb, dwarf.DW_ABRV_STRUCTFIELD, "keys") d.newrefattr(fld, dwarf.DW_AT_type, dwhks) - newmemberoffsetattr(fld, abi.MapBucketCount) + newmemberoffsetattr(fld, abi.OldMapBucketCount) fld = d.newdie(dwhb, dwarf.DW_ABRV_STRUCTFIELD, "values") d.newrefattr(fld, dwarf.DW_AT_type, dwhvs) - newmemberoffsetattr(fld, abi.MapBucketCount+abi.MapBucketCount*int32(keysize)) + newmemberoffsetattr(fld, abi.OldMapBucketCount+abi.OldMapBucketCount*int32(keysize)) fld = d.newdie(dwhb, dwarf.DW_ABRV_STRUCTFIELD, "overflow") d.newrefattr(fld, dwarf.DW_AT_type, d.defptrto(d.dtolsym(dwhb.Sym))) - newmemberoffsetattr(fld, abi.MapBucketCount+abi.MapBucketCount*(int32(keysize)+int32(valsize))) + newmemberoffsetattr(fld, abi.OldMapBucketCount+abi.OldMapBucketCount*(int32(keysize)+int32(valsize))) if d.arch.RegSize > d.arch.PtrSize { fld = d.newdie(dwhb, dwarf.DW_ABRV_STRUCTFIELD, "pad") d.newrefattr(fld, dwarf.DW_AT_type, d.uintptrInfoSym) - newmemberoffsetattr(fld, abi.MapBucketCount+abi.MapBucketCount*(int32(keysize)+int32(valsize))+int32(d.arch.PtrSize)) + newmemberoffsetattr(fld, abi.OldMapBucketCount+abi.OldMapBucketCount*(int32(keysize)+int32(valsize))+int32(d.arch.PtrSize)) } - newattr(dwhb, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, abi.MapBucketCount+abi.MapBucketCount*keysize+abi.MapBucketCount*valsize+int64(d.arch.RegSize), 0) + newattr(dwhb, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, abi.OldMapBucketCount+abi.OldMapBucketCount*keysize+abi.OldMapBucketCount*valsize+int64(d.arch.RegSize), 0) }) // Construct hash<K,V> @@ -1782,7 +1886,6 @@ func dwarfGenerateDebugInfo(ctxt *Link) { "type:internal/abi.ArrayType", "type:internal/abi.ChanType", "type:internal/abi.FuncType", - "type:internal/abi.MapType", "type:internal/abi.PtrType", "type:internal/abi.SliceType", "type:internal/abi.StructType", @@ -1791,6 +1894,11 @@ func dwarfGenerateDebugInfo(ctxt *Link) { "type:internal/abi.Imethod"} { d.defgotype(d.lookupOrDiag(typ)) } + if buildcfg.Experiment.SwissMap { + d.defgotype(d.lookupOrDiag("type:internal/abi.SwissMapType")) + } else { + d.defgotype(d.lookupOrDiag("type:internal/abi.OldMapType")) + } // fake root DIE for compile unit DIEs var dwroot dwarf.DWDie diff --git a/src/cmd/link/internal/ld/dwarf_test.go b/src/cmd/link/internal/ld/dwarf_test.go index 8cea573999..40202bd312 100644 --- a/src/cmd/link/internal/ld/dwarf_test.go +++ b/src/cmd/link/internal/ld/dwarf_test.go @@ -60,7 +60,6 @@ func TestRuntimeTypesPresent(t *testing.T) { "internal/abi.ArrayType": true, "internal/abi.ChanType": true, "internal/abi.FuncType": true, - "internal/abi.MapType": true, "internal/abi.PtrType": true, "internal/abi.SliceType": true, "internal/abi.StructType": true, @@ -72,6 +71,16 @@ func TestRuntimeTypesPresent(t *testing.T) { if len(found) != len(want) { t.Errorf("found %v, want %v", found, want) } + + // Must have one of OldMapType or SwissMapType. + want = map[string]bool{ + "internal/abi.OldMapType": true, + "internal/abi.SwissMapType": true, + } + found = findTypes(t, dwarf, want) + if len(found) != 1 { + t.Errorf("map type want one of %v found %v", want, found) + } } func findTypes(t *testing.T, dw *dwarf.Data, want map[string]bool) (found map[string]bool) { |
