Skip to content

Commit 1c2bdfb

Browse files
committed
cmd/compile: add Key, FieldSlice, and SetFields helpers
Allows safely eliminating more direct uses of Type's Type and Down fields. Passes toolstash -cmp. Change-Id: I5c17fe541a0473c3cd2978d8314c4ab759079a61 Reviewed-on: https://go-review.googlesource.com/20541 Run-TryBot: Matthew Dempsky <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Brad Fitzpatrick <[email protected]>
1 parent 0b28187 commit 1c2bdfb

File tree

12 files changed

+106
-106
lines changed

12 files changed

+106
-106
lines changed

src/cmd/compile/internal/gc/align.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ func dowidth(t *Type) {
223223
w = int64(Widthptr)
224224

225225
checkwidth(t.Type)
226-
checkwidth(t.Down)
226+
checkwidth(t.Key())
227227

228228
case TFORW: // should have been filled in
229229
if !t.Broke {

src/cmd/compile/internal/gc/bexport.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -534,8 +534,8 @@ func (p *exporter) typ(t *Type) {
534534

535535
case TMAP:
536536
p.tag(mapTag)
537-
p.typ(t.Down) // key
538-
p.typ(t.Type) // val
537+
p.typ(t.Key()) // key
538+
p.typ(t.Type) // val
539539

540540
case TCHAN:
541541
p.tag(chanTag)

src/cmd/compile/internal/gc/dcl.go

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -827,12 +827,11 @@ func tostruct0(t *Type, l []*Node) {
827827
Fatalf("struct expected")
828828
}
829829

830-
tp := &t.Type
830+
var fields []*Type
831831
for _, n := range l {
832-
f := structfield(n)
833-
*tp = f
834-
tp = &f.Down
832+
fields = append(fields, structfield(n))
835833
}
834+
t.SetFields(fields)
836835

837836
for f, it := IterFields(t); f != nil && !t.Broke; f = it.Next() {
838837
if f.Broke {
@@ -849,24 +848,22 @@ func tostruct0(t *Type, l []*Node) {
849848
}
850849

851850
func tofunargs(l []*Node) *Type {
852-
var f *Type
853-
854851
t := typ(TSTRUCT)
855852
t.Funarg = true
856853

857-
tp := &t.Type
854+
var fields []*Type
858855
for _, n := range l {
859-
f = structfield(n)
856+
f := structfield(n)
860857
f.Funarg = true
861858

862859
// esc.go needs to find f given a PPARAM to add the tag.
863860
if n.Left != nil && n.Left.Class == PPARAM {
864861
n.Left.Name.Param.Field = f
865862
}
866863

867-
*tp = f
868-
tp = &f.Down
864+
fields = append(fields, f)
869865
}
866+
t.SetFields(fields)
870867

871868
for f, it := IterFields(t); f != nil && !t.Broke; f = it.Next() {
872869
if f.Broke {
@@ -955,7 +952,7 @@ func tointerface0(t *Type, l []*Node) *Type {
955952
Fatalf("interface expected")
956953
}
957954

958-
tp := &t.Type
955+
var fields []*Type
959956
for _, n := range l {
960957
f := interfacefield(n)
961958

@@ -969,14 +966,13 @@ func tointerface0(t *Type, l []*Node) *Type {
969966
if f.Sym != nil {
970967
f.Nname = newname(f.Sym)
971968
}
972-
*tp = f
973-
tp = &f.Down
969+
fields = append(fields, f)
974970
}
975971
} else {
976-
*tp = f
977-
tp = &f.Down
972+
fields = append(fields, f)
978973
}
979974
}
975+
t.SetFields(fields)
980976

981977
for f, it := IterFields(t); f != nil && !t.Broke; f = it.Next() {
982978
if f.Broke {

src/cmd/compile/internal/gc/fmt.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -580,7 +580,7 @@ func typefmt(t *Type, flag int) string {
580580
return fmt.Sprintf("chan %v", t.Type)
581581

582582
case TMAP:
583-
return fmt.Sprintf("map[%v]%v", t.Down, t.Type)
583+
return fmt.Sprintf("map[%v]%v", t.Key(), t.Type)
584584

585585
case TINTER:
586586
var buf bytes.Buffer
@@ -645,15 +645,15 @@ func typefmt(t *Type, flag int) string {
645645
// Format the bucket struct for map[x]y as map.bucket[x]y.
646646
// This avoids a recursive print that generates very long names.
647647
if t.Map.Bucket == t {
648-
return fmt.Sprintf("map.bucket[%v]%v", t.Map.Down, t.Map.Type)
648+
return fmt.Sprintf("map.bucket[%v]%v", t.Map.Key(), t.Map.Type)
649649
}
650650

651651
if t.Map.Hmap == t {
652-
return fmt.Sprintf("map.hdr[%v]%v", t.Map.Down, t.Map.Type)
652+
return fmt.Sprintf("map.hdr[%v]%v", t.Map.Key(), t.Map.Type)
653653
}
654654

655655
if t.Map.Hiter == t {
656-
return fmt.Sprintf("map.iter[%v]%v", t.Map.Down, t.Map.Type)
656+
return fmt.Sprintf("map.iter[%v]%v", t.Map.Key(), t.Map.Type)
657657
}
658658

659659
Yyerror("unknown internal map type")

src/cmd/compile/internal/gc/range.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ func typecheckrange(n *Node) {
5656
t2 = t.Type
5757

5858
case TMAP:
59-
t1 = t.Down
59+
t1 = t.Key()
6060
t2 = t.Type
6161

6262
case TCHAN:
@@ -228,12 +228,12 @@ func walkrange(n *Node) {
228228
hit := prealloc[n]
229229
hit.Type = th
230230
n.Left = nil
231-
keyname := newname(th.Type.Sym) // depends on layout of iterator struct. See reflect.go:hiter
232-
valname := newname(th.Type.Down.Sym) // ditto
231+
keyname := newname(th.Field(0).Sym) // depends on layout of iterator struct. See reflect.go:hiter
232+
valname := newname(th.Field(1).Sym) // ditto
233233

234234
fn := syslook("mapiterinit")
235235

236-
substArgTypes(&fn, t.Down, t.Type, th)
236+
substArgTypes(&fn, t.Key(), t.Type, th)
237237
init = append(init, mkcall1(fn, nil, nil, typename(t), ha, Nod(OADDR, hit, nil)))
238238
n.Left = Nod(ONE, Nod(ODOT, hit, keyname), nodnil())
239239

src/cmd/compile/internal/gc/reflect.go

Lines changed: 12 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ func mapbucket(t *Type) *Type {
7575
}
7676

7777
bucket := typ(TSTRUCT)
78-
keytype := t.Down
78+
keytype := t.Key()
7979
valtype := t.Type
8080
dowidth(keytype)
8181
dowidth(valtype)
@@ -119,7 +119,7 @@ func mapbucket(t *Type) *Type {
119119
// so if the struct needs 64-bit padding (because a key or value does)
120120
// then it would end with an extra 32-bit padding field.
121121
// Preempt that by emitting the padding here.
122-
if int(t.Type.Align) > Widthptr || int(t.Down.Align) > Widthptr {
122+
if int(t.Type.Align) > Widthptr || int(t.Key().Align) > Widthptr {
123123
field = append(field, makefield("pad", Types[TUINTPTR]))
124124
}
125125

@@ -130,7 +130,7 @@ func mapbucket(t *Type) *Type {
130130
// the type of the overflow field to uintptr in this case.
131131
// See comment on hmap.overflow in ../../../../runtime/hashmap.go.
132132
otyp := Ptrto(bucket)
133-
if !haspointers(t.Type) && !haspointers(t.Down) && t.Type.Width <= MAXKEYSIZE && t.Down.Width <= MAXVALSIZE {
133+
if !haspointers(t.Type) && !haspointers(t.Key()) && t.Type.Width <= MAXVALSIZE && t.Key().Width <= MAXKEYSIZE {
134134
otyp = Types[TUINTPTR]
135135
}
136136
ovf := makefield("overflow", otyp)
@@ -139,11 +139,7 @@ func mapbucket(t *Type) *Type {
139139
// link up fields
140140
bucket.Noalg = true
141141
bucket.Local = t.Local
142-
bucket.Type = field[0]
143-
for n := int32(0); n < int32(len(field)-1); n++ {
144-
field[n].Down = field[n+1]
145-
}
146-
field[len(field)-1].Down = nil
142+
bucket.SetFields(field[:])
147143
dowidth(bucket)
148144

149145
// Double-check that overflow field is final memory in struct,
@@ -179,11 +175,7 @@ func hmap(t *Type) *Type {
179175
h := typ(TSTRUCT)
180176
h.Noalg = true
181177
h.Local = t.Local
182-
h.Type = field[0]
183-
for n := int32(0); n < int32(len(field)-1); n++ {
184-
field[n].Down = field[n+1]
185-
}
186-
field[len(field)-1].Down = nil
178+
h.SetFields(field[:])
187179
dowidth(h)
188180
t.Hmap = h
189181
h.Map = t
@@ -212,8 +204,7 @@ func hiter(t *Type) *Type {
212204
// }
213205
// must match ../../../../runtime/hashmap.go:hiter.
214206
var field [12]*Type
215-
field[0] = makefield("key", Ptrto(t.Down))
216-
207+
field[0] = makefield("key", Ptrto(t.Key()))
217208
field[1] = makefield("val", Ptrto(t.Type))
218209
field[2] = makefield("t", Ptrto(Types[TUINT8]))
219210
field[3] = makefield("h", Ptrto(hmap(t)))
@@ -228,13 +219,8 @@ func hiter(t *Type) *Type {
228219

229220
// build iterator struct holding the above fields
230221
i := typ(TSTRUCT)
231-
232222
i.Noalg = true
233-
i.Type = field[0]
234-
for n := int32(0); n < int32(len(field)-1); n++ {
235-
field[n].Down = field[n+1]
236-
}
237-
field[len(field)-1].Down = nil
223+
i.SetFields(field[:])
238224
dowidth(i)
239225
if i.Width != int64(12*Widthptr) {
240226
Yyerror("hash_iter size not correct %d %d", i.Width, 12*Widthptr)
@@ -1124,8 +1110,7 @@ ok:
11241110

11251111
// ../../../../runtime/type.go:/mapType
11261112
case TMAP:
1127-
s1 := dtypesym(t.Down)
1128-
1113+
s1 := dtypesym(t.Key())
11291114
s2 := dtypesym(t.Type)
11301115
s3 := dtypesym(mapbucket(t))
11311116
s4 := dtypesym(hmap(t))
@@ -1134,11 +1119,11 @@ ok:
11341119
ot = dsymptr(s, ot, s2, 0)
11351120
ot = dsymptr(s, ot, s3, 0)
11361121
ot = dsymptr(s, ot, s4, 0)
1137-
if t.Down.Width > MAXKEYSIZE {
1122+
if t.Key().Width > MAXKEYSIZE {
11381123
ot = duint8(s, ot, uint8(Widthptr))
11391124
ot = duint8(s, ot, 1) // indirect
11401125
} else {
1141-
ot = duint8(s, ot, uint8(t.Down.Width))
1126+
ot = duint8(s, ot, uint8(t.Key().Width))
11421127
ot = duint8(s, ot, 0) // not indirect
11431128
}
11441129

@@ -1151,8 +1136,8 @@ ok:
11511136
}
11521137

11531138
ot = duint16(s, ot, uint16(mapbucket(t).Width))
1154-
ot = duint8(s, ot, uint8(obj.Bool2int(isreflexive(t.Down))))
1155-
ot = duint8(s, ot, uint8(obj.Bool2int(needkeyupdate(t.Down))))
1139+
ot = duint8(s, ot, uint8(obj.Bool2int(isreflexive(t.Key()))))
1140+
ot = duint8(s, ot, uint8(obj.Bool2int(needkeyupdate(t.Key()))))
11561141
ot = dextratype(s, ot, t, 0)
11571142

11581143
case TPTR32, TPTR64:

src/cmd/compile/internal/gc/sinit.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -979,7 +979,7 @@ func maplit(ctxt int, n *Node, var_ *Node, init *Nodes) {
979979
// build list of var[c] = expr.
980980
// use temporary so that mapassign1 can have addressable key, val.
981981
if key == nil {
982-
key = temp(var_.Type.Down)
982+
key = temp(var_.Type.Key())
983983
val = temp(var_.Type.Type)
984984
}
985985

src/cmd/compile/internal/gc/subr.go

Lines changed: 19 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -417,23 +417,9 @@ func (x methcmp) Less(i, j int) bool {
417417
}
418418

419419
func sortinter(t *Type) *Type {
420-
if t.Type == nil || t.Type.Down == nil {
421-
return t
422-
}
423-
424-
var a []*Type
425-
for f, it := IterFields(t); f != nil; f = it.Next() {
426-
a = append(a, f)
427-
}
428-
sort.Sort(methcmp(a))
429-
430-
n := len(a) // n > 0 due to initial conditions.
431-
for i := 0; i < n-1; i++ {
432-
a[i].Down = a[i+1]
433-
}
434-
a[n-1].Down = nil
435-
436-
t.Type = a[0]
420+
s := t.FieldSlice()
421+
sort.Sort(methcmp(s))
422+
t.SetFields(s)
437423
return t
438424
}
439425

@@ -740,12 +726,9 @@ func eqtype1(t1, t2 *Type, assumedEqual map[typePair]struct{}) bool {
740726

741727
switch t1.Etype {
742728
case TINTER, TSTRUCT:
743-
t1 = t1.Type
744-
t2 = t2.Type
745-
for ; t1 != nil && t2 != nil; t1, t2 = t1.Down, t2.Down {
746-
if t1.Etype != TFIELD || t2.Etype != TFIELD {
747-
Fatalf("struct/interface missing field: %v %v", t1, t2)
748-
}
729+
t1, i1 := IterFields(t1)
730+
t2, i2 := IterFields(t2)
731+
for ; t1 != nil && t2 != nil; t1, t2 = i1.Next(), i2.Next() {
749732
if t1.Sym != t2.Sym || t1.Embedded != t2.Embedded || !eqtype1(t1.Type, t2.Type, assumedEqual) || !eqnote(t1.Note, t2.Note) {
750733
return false
751734
}
@@ -782,9 +765,14 @@ func eqtype1(t1, t2 *Type, assumedEqual map[typePair]struct{}) bool {
782765
if t1.Chan != t2.Chan {
783766
return false
784767
}
768+
769+
case TMAP:
770+
if !eqtype1(t1.Key(), t2.Key(), assumedEqual) {
771+
return false
772+
}
785773
}
786774

787-
return eqtype1(t1.Down, t2.Down, assumedEqual) && eqtype1(t1.Type, t2.Type, assumedEqual)
775+
return eqtype1(t1.Type, t2.Type, assumedEqual)
788776
}
789777

790778
// Are t1 and t2 equal struct types when field names are ignored?
@@ -795,17 +783,17 @@ func eqtypenoname(t1 *Type, t2 *Type) bool {
795783
return false
796784
}
797785

798-
t1 = t1.Type
799-
t2 = t2.Type
786+
t1, i1 := IterFields(t1)
787+
t2, i2 := IterFields(t2)
800788
for {
801789
if !Eqtype(t1, t2) {
802790
return false
803791
}
804792
if t1 == nil {
805793
return true
806794
}
807-
t1 = t1.Down
808-
t2 = t2.Down
795+
t1 = i1.Next()
796+
t2 = i2.Next()
809797
}
810798
}
811799

@@ -2635,13 +2623,13 @@ func isdirectiface(t *Type) bool {
26352623
TUNSAFEPTR:
26362624
return true
26372625

2638-
// Array of 1 direct iface type can be direct.
26392626
case TARRAY:
2627+
// Array of 1 direct iface type can be direct.
26402628
return t.Bound == 1 && isdirectiface(t.Type)
26412629

2642-
// Struct with 1 field of direct iface type can be direct.
26432630
case TSTRUCT:
2644-
return t.Type != nil && t.Type.Down == nil && isdirectiface(t.Type.Type)
2631+
// Struct with 1 field of direct iface type can be direct.
2632+
return countfield(t) == 1 && isdirectiface(t.Field(0).Type)
26452633
}
26462634

26472635
return false

0 commit comments

Comments
 (0)