@@ -4,7 +4,7 @@ package jvm
4
4
5
5
import scala .language .unsafeNulls
6
6
7
- import scala .annotation .switch
7
+ import scala .annotation .{ switch , tailrec }
8
8
import scala .collection .mutable .SortedMap
9
9
10
10
import scala .tools .asm
@@ -79,9 +79,14 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
79
79
80
80
tree match {
81
81
case Assign (lhs @ DesugaredSelect (qual, _), rhs) =>
82
+ val savedStackHeight = stackHeight
82
83
val isStatic = lhs.symbol.isStaticMember
83
- if (! isStatic) { genLoadQualifier(lhs) }
84
+ if (! isStatic) {
85
+ genLoadQualifier(lhs)
86
+ stackHeight += 1
87
+ }
84
88
genLoad(rhs, symInfoTK(lhs.symbol))
89
+ stackHeight = savedStackHeight
85
90
lineNumber(tree)
86
91
// receiverClass is used in the bytecode to access the field. using sym.owner may lead to IllegalAccessError
87
92
val receiverClass = qual.tpe.typeSymbol
@@ -145,7 +150,9 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
145
150
}
146
151
147
152
genLoad(larg, resKind)
153
+ stackHeight += resKind.size
148
154
genLoad(rarg, if (isShift) INT else resKind)
155
+ stackHeight -= resKind.size
149
156
150
157
(code : @ switch) match {
151
158
case ADD => bc add resKind
@@ -182,14 +189,19 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
182
189
if (isArrayGet(code)) {
183
190
// load argument on stack
184
191
assert(args.length == 1 , s " Too many arguments for array get operation: $tree" );
192
+ stackHeight += 1
185
193
genLoad(args.head, INT )
194
+ stackHeight -= 1
186
195
generatedType = k.asArrayBType.componentType
187
196
bc.aload(elementType)
188
197
}
189
198
else if (isArraySet(code)) {
190
199
val List (a1, a2) = args
200
+ stackHeight += 1
191
201
genLoad(a1, INT )
202
+ stackHeight += 1
192
203
genLoad(a2)
204
+ stackHeight -= 2
193
205
generatedType = UNIT
194
206
bc.astore(elementType)
195
207
} else {
@@ -223,7 +235,7 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
223
235
val resKind = if (hasUnitBranch) UNIT else tpeTK(tree)
224
236
225
237
val postIf = new asm.Label
226
- genLoadTo(thenp, resKind, LoadDestination .Jump (postIf))
238
+ genLoadTo(thenp, resKind, LoadDestination .Jump (postIf, stackHeight ))
227
239
markProgramPoint(failure)
228
240
genLoadTo(elsep, resKind, LoadDestination .FallThrough )
229
241
markProgramPoint(postIf)
@@ -482,7 +494,17 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
482
494
dest match
483
495
case LoadDestination .FallThrough =>
484
496
()
485
- case LoadDestination .Jump (label) =>
497
+ case LoadDestination .Jump (label, targetStackHeight) =>
498
+ if targetStackHeight < stackHeight then
499
+ val stackDiff = stackHeight - targetStackHeight
500
+ if expectedType == UNIT then
501
+ bc dropMany stackDiff
502
+ else
503
+ val loc = locals.makeTempLocal(expectedType)
504
+ bc.store(loc.idx, expectedType)
505
+ bc dropMany stackDiff
506
+ bc.load(loc.idx, expectedType)
507
+ end if
486
508
bc goTo label
487
509
case LoadDestination .Return =>
488
510
bc emitRETURN returnType
@@ -577,7 +599,7 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
577
599
if dest == LoadDestination .FallThrough then
578
600
val resKind = tpeTK(tree)
579
601
val jumpTarget = new asm.Label
580
- registerJumpDest(labelSym, resKind, LoadDestination .Jump (jumpTarget))
602
+ registerJumpDest(labelSym, resKind, LoadDestination .Jump (jumpTarget, stackHeight ))
581
603
genLoad(expr, resKind)
582
604
markProgramPoint(jumpTarget)
583
605
resKind
@@ -635,7 +657,7 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
635
657
markProgramPoint(loop)
636
658
637
659
if isInfinite then
638
- val dest = LoadDestination .Jump (loop)
660
+ val dest = LoadDestination .Jump (loop, stackHeight )
639
661
genLoadTo(body, UNIT , dest)
640
662
dest
641
663
else
@@ -650,7 +672,7 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
650
672
val failure = new asm.Label
651
673
genCond(cond, success, failure, targetIfNoJump = success)
652
674
markProgramPoint(success)
653
- genLoadTo(body, UNIT , LoadDestination .Jump (loop))
675
+ genLoadTo(body, UNIT , LoadDestination .Jump (loop, stackHeight ))
654
676
markProgramPoint(failure)
655
677
end match
656
678
LoadDestination .FallThrough
@@ -744,7 +766,9 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
744
766
745
767
// scala/bug#10290: qual can be `this.$outer()` (not just `this`), so we call genLoad (not just ALOAD_0)
746
768
genLoad(superQual)
769
+ stackHeight += 1
747
770
genLoadArguments(args, paramTKs(app))
771
+ stackHeight -= 1
748
772
generatedType = genCallMethod(fun.symbol, InvokeStyle .Super , app.span)
749
773
750
774
// 'new' constructor call: Note: since constructors are
@@ -766,7 +790,9 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
766
790
assert(classBTypeFromSymbol(ctor.owner) == rt, s " Symbol ${ctor.owner.showFullName} is different from $rt" )
767
791
mnode.visitTypeInsn(asm.Opcodes .NEW , rt.internalName)
768
792
bc dup generatedType
793
+ stackHeight += 2
769
794
genLoadArguments(args, paramTKs(app))
795
+ stackHeight -= 2
770
796
genCallMethod(ctor, InvokeStyle .Special , app.span)
771
797
772
798
case _ =>
@@ -799,8 +825,12 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
799
825
else if (app.hasAttachment(BCodeHelpers .UseInvokeSpecial )) InvokeStyle .Special
800
826
else InvokeStyle .Virtual
801
827
802
- if (invokeStyle.hasInstance) genLoadQualifier(fun)
828
+ val savedStackHeight = stackHeight
829
+ if invokeStyle.hasInstance then
830
+ genLoadQualifier(fun)
831
+ stackHeight += 1
803
832
genLoadArguments(args, paramTKs(app))
833
+ stackHeight = savedStackHeight
804
834
805
835
val DesugaredSelect (qual, name) = fun : @ unchecked // fun is a Select, also checked in genLoadQualifier
806
836
val isArrayClone = name == nme.clone_ && qual.tpe.widen.isInstanceOf [JavaArrayType ]
@@ -858,6 +888,8 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
858
888
bc iconst elems.length
859
889
bc newarray elmKind
860
890
891
+ stackHeight += 3 // during the genLoad below, there is the result, its dup, and the index
892
+
861
893
var i = 0
862
894
var rest = elems
863
895
while (! rest.isEmpty) {
@@ -869,6 +901,8 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
869
901
i = i + 1
870
902
}
871
903
904
+ stackHeight -= 3
905
+
872
906
generatedType
873
907
}
874
908
@@ -883,7 +917,7 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
883
917
val (generatedType, postMatch, postMatchDest) =
884
918
if dest == LoadDestination .FallThrough then
885
919
val postMatch = new asm.Label
886
- (tpeTK(tree), postMatch, LoadDestination .Jump (postMatch))
920
+ (tpeTK(tree), postMatch, LoadDestination .Jump (postMatch, stackHeight ))
887
921
else
888
922
(expectedType, null , dest)
889
923
@@ -1160,14 +1194,21 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
1160
1194
}
1161
1195
1162
1196
def genLoadArguments (args : List [Tree ], btpes : List [BType ]): Unit =
1163
- args match
1164
- case arg :: args1 =>
1165
- btpes match
1166
- case btpe :: btpes1 =>
1167
- genLoad(arg, btpe)
1168
- genLoadArguments(args1, btpes1)
1169
- case _ =>
1170
- case _ =>
1197
+ @ tailrec def loop (args : List [Tree ], btpes : List [BType ]): Unit =
1198
+ args match
1199
+ case arg :: args1 =>
1200
+ btpes match
1201
+ case btpe :: btpes1 =>
1202
+ genLoad(arg, btpe)
1203
+ stackHeight += btpe.size
1204
+ loop(args1, btpes1)
1205
+ case _ =>
1206
+ case _ =>
1207
+
1208
+ val savedStackHeight = stackHeight
1209
+ loop(args, btpes)
1210
+ stackHeight = savedStackHeight
1211
+ end genLoadArguments
1171
1212
1172
1213
def genLoadModule (tree : Tree ): BType = {
1173
1214
val module = (
@@ -1266,11 +1307,14 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
1266
1307
}.sum
1267
1308
bc.genNewStringBuilder(approxBuilderSize)
1268
1309
1310
+ stackHeight += 1 // during the genLoad below, there is a reference to the StringBuilder on the stack
1269
1311
for (elem <- concatArguments) {
1270
1312
val elemType = tpeTK(elem)
1271
1313
genLoad(elem, elemType)
1272
1314
bc.genStringBuilderAppend(elemType)
1273
1315
}
1316
+ stackHeight -= 1
1317
+
1274
1318
bc.genStringBuilderEnd
1275
1319
} else {
1276
1320
@@ -1287,12 +1331,15 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
1287
1331
var totalArgSlots = 0
1288
1332
var countConcats = 1 // ie. 1 + how many times we spilled
1289
1333
1334
+ val savedStackHeight = stackHeight
1335
+
1290
1336
for (elem <- concatArguments) {
1291
1337
val tpe = tpeTK(elem)
1292
1338
val elemSlots = tpe.size
1293
1339
1294
1340
// Unlikely spill case
1295
1341
if (totalArgSlots + elemSlots >= MaxIndySlots ) {
1342
+ stackHeight = savedStackHeight + countConcats
1296
1343
bc.genIndyStringConcat(recipe.toString, argTypes.result(), constVals.result())
1297
1344
countConcats += 1
1298
1345
totalArgSlots = 0
@@ -1317,8 +1364,10 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
1317
1364
val tpe = tpeTK(elem)
1318
1365
argTypes += tpe.toASMType
1319
1366
genLoad(elem, tpe)
1367
+ stackHeight += 1
1320
1368
}
1321
1369
}
1370
+ stackHeight = savedStackHeight
1322
1371
bc.genIndyStringConcat(recipe.toString, argTypes.result(), constVals.result())
1323
1372
1324
1373
// If we spilled, generate one final concat
@@ -1513,7 +1562,9 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
1513
1562
} else {
1514
1563
val tk = tpeTK(l).maxType(tpeTK(r))
1515
1564
genLoad(l, tk)
1565
+ stackHeight += tk.size
1516
1566
genLoad(r, tk)
1567
+ stackHeight -= tk.size
1517
1568
genCJUMP(success, failure, op, tk, targetIfNoJump)
1518
1569
}
1519
1570
}
@@ -1628,7 +1679,9 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
1628
1679
}
1629
1680
1630
1681
genLoad(l, ObjectRef )
1682
+ stackHeight += 1
1631
1683
genLoad(r, ObjectRef )
1684
+ stackHeight -= 1
1632
1685
genCallMethod(equalsMethod, InvokeStyle .Static )
1633
1686
genCZJUMP(success, failure, Primitives .NE , BOOL , targetIfNoJump)
1634
1687
}
@@ -1644,7 +1697,9 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
1644
1697
} else if (isNonNullExpr(l)) {
1645
1698
// SI-7852 Avoid null check if L is statically non-null.
1646
1699
genLoad(l, ObjectRef )
1700
+ stackHeight += 1
1647
1701
genLoad(r, ObjectRef )
1702
+ stackHeight -= 1
1648
1703
genCallMethod(defn.Any_equals , InvokeStyle .Virtual )
1649
1704
genCZJUMP(success, failure, Primitives .NE , BOOL , targetIfNoJump)
1650
1705
} else {
@@ -1654,7 +1709,9 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
1654
1709
val lNonNull = new asm.Label
1655
1710
1656
1711
genLoad(l, ObjectRef )
1712
+ stackHeight += 1
1657
1713
genLoad(r, ObjectRef )
1714
+ stackHeight -= 1
1658
1715
locals.store(eqEqTempLocal)
1659
1716
bc dup ObjectRef
1660
1717
genCZJUMP(lNull, lNonNull, Primitives .EQ , ObjectRef , targetIfNoJump = lNull)
0 commit comments