@@ -41,8 +41,16 @@ import (
41
41
// not escape, then new(T) can be rewritten into a stack allocation.
42
42
// The same is true of slice literals.
43
43
44
+ // If newescape is true, then escape.go drives escape analysis instead
45
+ // of esc.go.
46
+ var newescape bool
47
+
44
48
func escapes (all []* Node ) {
45
- visitBottomUp (all , escAnalyze )
49
+ esc := escAnalyze
50
+ if newescape {
51
+ esc = escapeFuncs
52
+ }
53
+ visitBottomUp (all , esc )
46
54
}
47
55
48
56
const (
@@ -393,7 +401,7 @@ func escAnalyze(all []*Node, recursive bool) {
393
401
// for all top level functions, tag the typenodes corresponding to the param nodes
394
402
for _ , n := range all {
395
403
if n .Op == ODCLFUNC {
396
- e . esctag (n )
404
+ esctag (n )
397
405
}
398
406
}
399
407
@@ -516,7 +524,7 @@ func (e *EscState) esclist(l Nodes, parent *Node) {
516
524
}
517
525
}
518
526
519
- func ( e * EscState ) isSliceSelfAssign (dst , src * Node ) bool {
527
+ func isSliceSelfAssign (dst , src * Node ) bool {
520
528
// Detect the following special case.
521
529
//
522
530
// func (b *Buffer) Foo() {
@@ -566,8 +574,8 @@ func (e *EscState) isSliceSelfAssign(dst, src *Node) bool {
566
574
567
575
// isSelfAssign reports whether assignment from src to dst can
568
576
// be ignored by the escape analysis as it's effectively a self-assignment.
569
- func ( e * EscState ) isSelfAssign (dst , src * Node ) bool {
570
- if e . isSliceSelfAssign (dst , src ) {
577
+ func isSelfAssign (dst , src * Node ) bool {
578
+ if isSliceSelfAssign (dst , src ) {
571
579
return true
572
580
}
573
581
@@ -589,7 +597,7 @@ func (e *EscState) isSelfAssign(dst, src *Node) bool {
589
597
case ODOT , ODOTPTR :
590
598
// Safe trailing accessors that are permitted to differ.
591
599
case OINDEX :
592
- if e . mayAffectMemory (dst .Right ) || e . mayAffectMemory (src .Right ) {
600
+ if mayAffectMemory (dst .Right ) || mayAffectMemory (src .Right ) {
593
601
return false
594
602
}
595
603
default :
@@ -602,7 +610,7 @@ func (e *EscState) isSelfAssign(dst, src *Node) bool {
602
610
603
611
// mayAffectMemory reports whether n evaluation may affect program memory state.
604
612
// If expression can't affect it, then it can be safely ignored by the escape analysis.
605
- func ( e * EscState ) mayAffectMemory (n * Node ) bool {
613
+ func mayAffectMemory (n * Node ) bool {
606
614
// We may want to use "memory safe" black list instead of general
607
615
// "side-effect free", which can include all calls and other ops
608
616
// that can affect allocate or change global state.
@@ -616,18 +624,26 @@ func (e *EscState) mayAffectMemory(n *Node) bool {
616
624
617
625
// Left+Right group.
618
626
case OINDEX , OADD , OSUB , OOR , OXOR , OMUL , OLSH , ORSH , OAND , OANDNOT , ODIV , OMOD :
619
- return e . mayAffectMemory (n .Left ) || e . mayAffectMemory (n .Right )
627
+ return mayAffectMemory (n .Left ) || mayAffectMemory (n .Right )
620
628
621
629
// Left group.
622
630
case ODOT , ODOTPTR , ODEREF , OCONVNOP , OCONV , OLEN , OCAP ,
623
631
ONOT , OBITNOT , OPLUS , ONEG , OALIGNOF , OOFFSETOF , OSIZEOF :
624
- return e . mayAffectMemory (n .Left )
632
+ return mayAffectMemory (n .Left )
625
633
626
634
default :
627
635
return true
628
636
}
629
637
}
630
638
639
+ func mustHeapAlloc (n * Node ) bool {
640
+ // TODO(mdempsky): Cleanup this mess.
641
+ return n .Type != nil &&
642
+ (n .Type .Width > maxStackVarSize ||
643
+ (n .Op == ONEW || n .Op == OPTRLIT ) && n .Type .Elem ().Width >= maxImplicitStackVarSize ||
644
+ n .Op == OMAKESLICE && ! isSmallMakeSlice (n ))
645
+ }
646
+
631
647
func (e * EscState ) esc (n * Node , parent * Node ) {
632
648
if n == nil {
633
649
return
@@ -658,10 +674,7 @@ func (e *EscState) esc(n *Node, parent *Node) {
658
674
// Big stuff and non-constant-sized stuff escapes unconditionally.
659
675
// "Big" conditions that were scattered around in walk have been
660
676
// gathered here.
661
- if n .Esc != EscHeap && n .Type != nil &&
662
- (n .Type .Width > maxStackVarSize ||
663
- (n .Op == ONEW || n .Op == OPTRLIT ) && n .Type .Elem ().Width >= maxImplicitStackVarSize ||
664
- n .Op == OMAKESLICE && ! isSmallMakeSlice (n )) {
677
+ if n .Esc != EscHeap && mustHeapAlloc (n ) {
665
678
// isSmallMakeSlice returns false for non-constant len/cap.
666
679
// If that's the case, print a more accurate escape reason.
667
680
var msgVerb , escapeMsg string
@@ -756,7 +769,7 @@ opSwitch:
756
769
757
770
case OAS , OASOP :
758
771
// Filter out some no-op assignments for escape analysis.
759
- if e . isSelfAssign (n .Left , n .Right ) {
772
+ if isSelfAssign (n .Left , n .Right ) {
760
773
if Debug ['m' ] != 0 {
761
774
Warnl (n .Pos , "%v ignoring self-assignment in %S" , e .curfnSym (n ), n )
762
775
}
@@ -2182,7 +2195,7 @@ const unsafeUintptrTag = "unsafe-uintptr"
2182
2195
// marked go:uintptrescapes.
2183
2196
const uintptrEscapesTag = "uintptr-escapes"
2184
2197
2185
- func ( e * EscState ) esctag (fn * Node ) {
2198
+ func esctag (fn * Node ) {
2186
2199
fn .Esc = EscFuncTagged
2187
2200
2188
2201
name := func (s * types.Sym , narg int ) string {
0 commit comments