@@ -34,9 +34,9 @@ if ((isTopLevel)) \
34
34
byteCodeGenerator->EndStatement (pnode); \
35
35
}
36
36
37
- BOOL MayHaveSideEffectOnNode (ParseNode *pnode, ParseNode *pnodeSE)
37
+ BOOL MayHaveSideEffectOnNode (ParseNode *pnode, ParseNode *pnodeSE, ByteCodeGenerator *byteCodeGenerator )
38
38
{
39
- // Try to determine whether pnodeSE may kill the named var represented by pnode.
39
+ // Try to determine whether pnodeSE (SE = side effect) may kill the named var represented by pnode.
40
40
41
41
if (pnode->nop == knopComputedName)
42
42
{
@@ -49,54 +49,76 @@ BOOL MayHaveSideEffectOnNode(ParseNode *pnode, ParseNode *pnodeSE)
49
49
return false ;
50
50
}
51
51
52
- uint fnop = ParseNode::Grfnop (pnodeSE->nop );
53
- if (fnop & fnopLeaf)
54
- {
55
- // pnodeSE is a leaf and can't kill anything.
56
- return false ;
57
- }
52
+ ArenaAllocator *alloc = byteCodeGenerator->GetAllocator ();
53
+ SList<ParseNode*> pNodeSEStack (alloc);
58
54
59
- if (fnop & fnopAsg)
60
- {
61
- // pnodeSE is an assignment (=, ++, +=, etc.)
62
- // Trying to examine the LHS of pnodeSE caused small perf regressions,
63
- // maybe because of code layout or some other subtle effect.
64
- return true ;
65
- }
55
+ pNodeSEStack.Push (pnodeSE);
66
56
67
- if (fnop & fnopUni)
57
+ // A pnodeSE can have children that can cause a side effect on pnode. A stack is used to check
58
+ // pnodeSE and all potential pnodeSE children that could cause a side effect on pnode. When a
59
+ // child pnodeSE can cause a side effect on pnode, immediately return true. Otherwise continue
60
+ // checking children of pnodeSE until none exist
61
+ while (!pNodeSEStack.Empty ())
68
62
{
69
- // pnodeSE is a unary op, so recurse to the source (if present - e.g., [] may have no opnd).
70
- if (pnodeSE->nop == knopTempRef)
63
+ ParseNode *currPnodeSE = pNodeSEStack.Pop ();
64
+ uint fnop = ParseNode::Grfnop (currPnodeSE->nop );
65
+
66
+ if (fnop & fnopLeaf)
71
67
{
72
- return false ;
68
+ // pnodeSE is a leaf and can't kill anything.
69
+ continue ;
73
70
}
74
- else
71
+ else if (fnop & fnopAsg)
75
72
{
76
- return pnodeSE->AsParseNodeUni ()->pnode1 && MayHaveSideEffectOnNode (pnode, pnodeSE->AsParseNodeUni ()->pnode1 );
73
+ // pnodeSE is an assignment (=, ++, +=, etc.)
74
+ // Trying to examine the LHS of pnodeSE caused small perf regressions,
75
+ // maybe because of code layout or some other subtle effect.
76
+ return true ;
77
+ }
78
+ else if (fnop & fnopUni)
79
+ {
80
+ // pnodeSE is a unary op, so recurse to the source (if present - e.g., [] may have no opnd).
81
+ if (currPnodeSE->nop == knopTempRef)
82
+ {
83
+ continue ;
84
+ }
85
+ else if (currPnodeSE->AsParseNodeUni ()->pnode1 )
86
+ {
87
+ pNodeSEStack.Push (currPnodeSE->AsParseNodeUni ()->pnode1 );
88
+ }
89
+ }
90
+ else if (fnop & fnopBin)
91
+ {
92
+ // currPnodeSE is a binary (or ternary) op, so check sources (if present).
93
+
94
+ pNodeSEStack.Push (currPnodeSE->AsParseNodeBin ()->pnode1 );
95
+
96
+ if (currPnodeSE->AsParseNodeBin ()->pnode2 )
97
+ {
98
+ pNodeSEStack.Push (currPnodeSE->AsParseNodeBin ()->pnode2 );
99
+ }
100
+ }
101
+ else if (currPnodeSE->nop == knopQmark)
102
+ {
103
+ ParseNodeTri * pnodeTriSE = currPnodeSE->AsParseNodeTri ();
104
+
105
+ pNodeSEStack.Push (pnodeTriSE->pnode1 );
106
+ pNodeSEStack.Push (pnodeTriSE->pnode2 );
107
+ pNodeSEStack.Push (pnodeTriSE->pnode3 );
108
+ }
109
+ else if (currPnodeSE->nop == knopCall || currPnodeSE->nop == knopNew)
110
+ {
111
+ pNodeSEStack.Push (currPnodeSE->AsParseNodeCall ()->pnodeTarget );
112
+
113
+ if (currPnodeSE->AsParseNodeCall ()->pnodeArgs )
114
+ {
115
+ pNodeSEStack.Push (currPnodeSE->AsParseNodeCall ()->pnodeArgs );
116
+ }
117
+ }
118
+ else if (currPnodeSE->nop == knopList)
119
+ {
120
+ return true ;
77
121
}
78
- }
79
- else if (fnop & fnopBin)
80
- {
81
- // pnodeSE is a binary (or ternary) op, so recurse to the sources (if present).
82
- return MayHaveSideEffectOnNode (pnode, pnodeSE->AsParseNodeBin ()->pnode1 ) ||
83
- (pnodeSE->AsParseNodeBin ()->pnode2 && MayHaveSideEffectOnNode (pnode, pnodeSE->AsParseNodeBin ()->pnode2 ));
84
- }
85
- else if (pnodeSE->nop == knopQmark)
86
- {
87
- ParseNodeTri * pnodeTriSE = pnodeSE->AsParseNodeTri ();
88
- return MayHaveSideEffectOnNode (pnode, pnodeTriSE->pnode1 ) ||
89
- MayHaveSideEffectOnNode (pnode, pnodeTriSE->pnode2 ) ||
90
- MayHaveSideEffectOnNode (pnode, pnodeTriSE->pnode3 );
91
- }
92
- else if (pnodeSE->nop == knopCall || pnodeSE->nop == knopNew)
93
- {
94
- return MayHaveSideEffectOnNode (pnode, pnodeSE->AsParseNodeCall ()->pnodeTarget ) ||
95
- (pnodeSE->AsParseNodeCall ()->pnodeArgs && MayHaveSideEffectOnNode (pnode, pnodeSE->AsParseNodeCall ()->pnodeArgs ));
96
- }
97
- else if (pnodeSE->nop == knopList)
98
- {
99
- return true ;
100
122
}
101
123
102
124
return false ;
@@ -9718,7 +9740,7 @@ void EmitJumpCleanup(ParseNodeStmt *pnode, ParseNode *pnodeTarget, ByteCodeGener
9718
9740
void EmitBinaryOpnds (ParseNode *pnode1, ParseNode *pnode2, ByteCodeGenerator *byteCodeGenerator, FuncInfo *funcInfo)
9719
9741
{
9720
9742
// If opnd2 can overwrite opnd1, make sure the value of opnd1 is stashed away.
9721
- if (MayHaveSideEffectOnNode (pnode1, pnode2))
9743
+ if (MayHaveSideEffectOnNode (pnode1, pnode2, byteCodeGenerator ))
9722
9744
{
9723
9745
SaveOpndValue (pnode1, funcInfo);
9724
9746
}
@@ -9742,7 +9764,7 @@ void EmitBinaryReference(ParseNode *pnode1, ParseNode *pnode2, ByteCodeGenerator
9742
9764
switch (pnode1->nop )
9743
9765
{
9744
9766
case knopName:
9745
- if (fLoadLhs && MayHaveSideEffectOnNode (pnode1, pnode2))
9767
+ if (fLoadLhs && MayHaveSideEffectOnNode (pnode1, pnode2, byteCodeGenerator ))
9746
9768
{
9747
9769
// Given x op y, y may kill x, so stash x.
9748
9770
// Note that this only matters if we're loading x prior to the op.
@@ -9755,7 +9777,7 @@ void EmitBinaryReference(ParseNode *pnode1, ParseNode *pnode2, ByteCodeGenerator
9755
9777
// We're loading the value of the LHS before the RHS, so make sure the LHS gets a register first.
9756
9778
funcInfo->AcquireLoc (pnode1);
9757
9779
}
9758
- if (MayHaveSideEffectOnNode (pnode1->AsParseNodeBin ()->pnode1 , pnode2))
9780
+ if (MayHaveSideEffectOnNode (pnode1->AsParseNodeBin ()->pnode1 , pnode2, byteCodeGenerator ))
9759
9781
{
9760
9782
// Given x.y op z, z may kill x, so stash x away.
9761
9783
SaveOpndValue (pnode1->AsParseNodeBin ()->pnode1 , funcInfo);
@@ -9767,13 +9789,13 @@ void EmitBinaryReference(ParseNode *pnode1, ParseNode *pnode2, ByteCodeGenerator
9767
9789
// We're loading the value of the LHS before the RHS, so make sure the LHS gets a register first.
9768
9790
funcInfo->AcquireLoc (pnode1);
9769
9791
}
9770
- if (MayHaveSideEffectOnNode (pnode1->AsParseNodeBin ()->pnode1 , pnode2) ||
9771
- MayHaveSideEffectOnNode (pnode1->AsParseNodeBin ()->pnode1 , pnode1->AsParseNodeBin ()->pnode2 ))
9792
+ if (MayHaveSideEffectOnNode (pnode1->AsParseNodeBin ()->pnode1 , pnode2, byteCodeGenerator ) ||
9793
+ MayHaveSideEffectOnNode (pnode1->AsParseNodeBin ()->pnode1 , pnode1->AsParseNodeBin ()->pnode2 , byteCodeGenerator ))
9772
9794
{
9773
9795
// Given x[y] op z, y or z may kill x, so stash x away.
9774
9796
SaveOpndValue (pnode1->AsParseNodeBin ()->pnode1 , funcInfo);
9775
9797
}
9776
- if (MayHaveSideEffectOnNode (pnode1->AsParseNodeBin ()->pnode2 , pnode2))
9798
+ if (MayHaveSideEffectOnNode (pnode1->AsParseNodeBin ()->pnode2 , pnode2, byteCodeGenerator ))
9777
9799
{
9778
9800
// Given x[y] op z, z may kill y, so stash y away.
9779
9801
// But make sure that x gets a register before y.
@@ -9883,12 +9905,12 @@ bool CollectConcat(ParseNode *pnodeAdd, DListCounted<ParseNode *, ArenaAllocator
9883
9905
void EmitConcat3 (ParseNode *pnode, ParseNode *pnode1, ParseNode *pnode2, ParseNode *pnode3, ByteCodeGenerator *byteCodeGenerator, FuncInfo *funcInfo)
9884
9906
{
9885
9907
byteCodeGenerator->StartStatement (pnode);
9886
- if (MayHaveSideEffectOnNode (pnode1, pnode2) || MayHaveSideEffectOnNode (pnode1, pnode3))
9908
+ if (MayHaveSideEffectOnNode (pnode1, pnode2, byteCodeGenerator ) || MayHaveSideEffectOnNode (pnode1, pnode3, byteCodeGenerator ))
9887
9909
{
9888
9910
SaveOpndValue (pnode1, funcInfo);
9889
9911
}
9890
9912
9891
- if (MayHaveSideEffectOnNode (pnode2, pnode3))
9913
+ if (MayHaveSideEffectOnNode (pnode2, pnode3, byteCodeGenerator ))
9892
9914
{
9893
9915
SaveOpndValue (pnode2, funcInfo);
9894
9916
}
0 commit comments