@@ -202,7 +202,8 @@ func isAtomicStdPkg(p *Pkg) bool {
202
202
return p .Prefix == "sync/atomic" || p .Prefix == "runtime/internal/atomic"
203
203
}
204
204
205
- // CalcSize calculates and stores the size, alignment, and eq/hash algorithm for t.
205
+ // CalcSize calculates and stores the size, alignment, eq/hash algorithm,
206
+ // and ptrBytes for t.
206
207
// If CalcSizeDisabled is set, and the size/alignment
207
208
// have not already been calculated, it calls Fatal.
208
209
// This is used to prevent data races in the back end.
@@ -247,6 +248,7 @@ func CalcSize(t *Type) {
247
248
t .width = - 2
248
249
t .align = 0 // 0 means use t.Width, below
249
250
t .alg = AMEM // default
251
+ // default t.ptrBytes is 0.
250
252
if t .Noalg () {
251
253
t .setAlg (ANOALG )
252
254
}
@@ -314,10 +316,12 @@ func CalcSize(t *Type) {
314
316
w = int64 (PtrSize )
315
317
t .intRegs = 1
316
318
CheckSize (t .Elem ())
319
+ t .ptrBytes = int64 (PtrSize ) // See PtrDataSize
317
320
318
321
case TUNSAFEPTR :
319
322
w = int64 (PtrSize )
320
323
t .intRegs = 1
324
+ t .ptrBytes = int64 (PtrSize )
321
325
322
326
case TINTER : // implemented as 2 pointers
323
327
w = 2 * int64 (PtrSize )
@@ -329,10 +333,12 @@ func CalcSize(t *Type) {
329
333
} else {
330
334
t .setAlg (AINTER )
331
335
}
336
+ t .ptrBytes = int64 (2 * PtrSize )
332
337
333
338
case TCHAN : // implemented as pointer
334
339
w = int64 (PtrSize )
335
340
t .intRegs = 1
341
+ t .ptrBytes = int64 (PtrSize )
336
342
337
343
CheckSize (t .Elem ())
338
344
@@ -360,6 +366,7 @@ func CalcSize(t *Type) {
360
366
CheckSize (t .Elem ())
361
367
CheckSize (t .Key ())
362
368
t .setAlg (ANOEQ )
369
+ t .ptrBytes = int64 (PtrSize )
363
370
364
371
case TFORW : // should have been filled in
365
372
base .Fatalf ("invalid recursive type %v" , t )
@@ -375,6 +382,7 @@ func CalcSize(t *Type) {
375
382
t .align = uint8 (PtrSize )
376
383
t .intRegs = 2
377
384
t .setAlg (ASTRING )
385
+ t .ptrBytes = int64 (PtrSize )
378
386
379
387
case TARRAY :
380
388
if t .Elem () == nil {
@@ -420,6 +428,12 @@ func CalcSize(t *Type) {
420
428
t .setAlg (ASPECIAL )
421
429
}
422
430
}
431
+ if t .NumElem () > 0 {
432
+ x := PtrDataSize (t .Elem ())
433
+ if x > 0 {
434
+ t .ptrBytes = t .Elem ().width * (t .NumElem ()- 1 ) + x
435
+ }
436
+ }
423
437
424
438
case TSLICE :
425
439
if t .Elem () == nil {
@@ -430,6 +444,9 @@ func CalcSize(t *Type) {
430
444
t .align = uint8 (PtrSize )
431
445
t .intRegs = 3
432
446
t .setAlg (ANOEQ )
447
+ if ! t .Elem ().NotInHeap () {
448
+ t .ptrBytes = int64 (PtrSize )
449
+ }
433
450
434
451
case TSTRUCT :
435
452
if t .IsFuncArgStruct () {
@@ -446,6 +463,7 @@ func CalcSize(t *Type) {
446
463
w = int64 (PtrSize ) // width of func type is pointer
447
464
t .intRegs = 1
448
465
t .setAlg (ANOEQ )
466
+ t .ptrBytes = int64 (PtrSize )
449
467
450
468
// function is 3 cated structures;
451
469
// compute their widths as side-effect.
@@ -490,8 +508,6 @@ func CalcStructSize(t *Type) {
490
508
switch {
491
509
case sym .Name == "align64" && isAtomicStdPkg (sym .Pkg ):
492
510
maxAlign = 8
493
- case sym .Pkg .Path == "runtime/internal/sys" && sym .Name == "nih" :
494
- t .SetNotInHeap (true )
495
511
}
496
512
}
497
513
@@ -560,6 +576,14 @@ func CalcStructSize(t *Type) {
560
576
t .setAlg (a )
561
577
}
562
578
}
579
+ // Compute ptrBytes.
580
+ for i := len (fields ) - 1 ; i >= 0 ; i -- {
581
+ f := fields [i ]
582
+ if size := PtrDataSize (f .Type ); size > 0 {
583
+ t .ptrBytes = f .Offset + size
584
+ break
585
+ }
586
+ }
563
587
}
564
588
565
589
func (t * Type ) widthCalculated () bool {
@@ -630,67 +654,13 @@ func ResumeCheckSize() {
630
654
// PtrDataSize is only defined for actual Go types. It's an error to
631
655
// use it on compiler-internal types (e.g., TSSA, TRESULTS).
632
656
func PtrDataSize (t * Type ) int64 {
633
- switch t .Kind () {
634
- case TBOOL , TINT8 , TUINT8 , TINT16 , TUINT16 , TINT32 ,
635
- TUINT32 , TINT64 , TUINT64 , TINT , TUINT ,
636
- TUINTPTR , TCOMPLEX64 , TCOMPLEX128 , TFLOAT32 , TFLOAT64 :
637
- return 0
638
-
639
- case TPTR :
640
- if t .Elem ().NotInHeap () {
641
- return 0
642
- }
643
- return int64 (PtrSize )
644
-
645
- case TUNSAFEPTR , TFUNC , TCHAN , TMAP :
646
- return int64 (PtrSize )
647
-
648
- case TSTRING :
649
- // struct { byte *str; intgo len; }
650
- return int64 (PtrSize )
651
-
652
- case TINTER :
653
- // struct { Itab *tab; void *data; } or
654
- // struct { Type *type; void *data; }
655
- // Note: see comment in typebits.Set
656
- return 2 * int64 (PtrSize )
657
-
658
- case TSLICE :
659
- if t .Elem ().NotInHeap () {
660
- return 0
661
- }
662
- // struct { byte *array; uintgo len; uintgo cap; }
663
- return int64 (PtrSize )
664
-
665
- case TARRAY :
666
- if t .NumElem () == 0 {
667
- return 0
668
- }
669
- // t.NumElem() > 0
670
- size := PtrDataSize (t .Elem ())
671
- if size == 0 {
672
- return 0
673
- }
674
- return (t .NumElem ()- 1 )* t .Elem ().Size () + size
675
-
676
- case TSTRUCT :
677
- // Find the last field that has pointers, if any.
678
- fs := t .Fields ()
679
- for i := len (fs ) - 1 ; i >= 0 ; i -- {
680
- if size := PtrDataSize (fs [i ].Type ); size > 0 {
681
- return fs [i ].Offset + size
682
- }
683
- }
684
- return 0
685
-
686
- case TSSA :
687
- if t != TypeInt128 {
688
- base .Fatalf ("PtrDataSize: unexpected ssa type %v" , t )
689
- }
690
- return 0
691
-
692
- default :
693
- base .Fatalf ("PtrDataSize: unexpected type, %v" , t )
694
- return 0
695
- }
657
+ CalcSize (t )
658
+ x := t .ptrBytes
659
+ if t .Kind () == TPTR && t .Elem ().NotInHeap () {
660
+ // Note: this is done here instead of when we're setting
661
+ // the ptrBytes field, because at that time (in NewPtr, usually)
662
+ // the NotInHeap bit of the element type might not be set yet.
663
+ x = 0
664
+ }
665
+ return x
696
666
}
0 commit comments