summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorLukas Rytz <lukas.rytz@gmail.com>2015-10-27 10:39:54 +0100
committerLukas Rytz <lukas.rytz@gmail.com>2015-10-27 10:45:23 +0100
commit4e994933c4b40a90555fe8acbe630f1c2fd03f55 (patch)
treee659744f926ab3dbb3a61e25b47be0a21be4d99d /src/compiler
parent3a9581d32f9d3adb1dcb0b9c4bfeb9c86f0addcf (diff)
downloadscala-4e994933c4b40a90555fe8acbe630f1c2fd03f55.tar.gz
scala-4e994933c4b40a90555fe8acbe630f1c2fd03f55.tar.bz2
scala-4e994933c4b40a90555fe8acbe630f1c2fd03f55.zip
Support JSR / RET in computeMaxLocalsMaxStack
Even though the two bytecodes are not allowed in classfiles of version 51+ (see [1]), we could encounter them when inlining from a JAR file containing classfiles of older version. [1] https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.9.1
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala21
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/opt/InstructionResultSize.scala8
2 files changed, 20 insertions, 9 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala b/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala
index aeb0f41237..efeaa54a7b 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala
@@ -303,6 +303,8 @@ class BackendUtils[BT <: BTypes](val btypes: BT) {
r
}
+ val subroutineRetTargets = new mutable.Stack[AbstractInsnNode]
+
// for each instruction in the queue, contains the stack height at this instruction.
// once an instruction has been treated, contains -1 to prevent re-enqueuing
val stackHeights = new Array[Int](size)
@@ -353,21 +355,34 @@ class BackendUtils[BT <: BTypes](val btypes: BT) {
insn match {
case j: JumpInsnNode =>
- enqInsn(j.label, heightAfter)
- val opc = j.getOpcode
- if (opc != GOTO) enqInsnIndex(insnIndex + 1, heightAfter) // jump is conditional, so the successor is also a possible control flow target
+ if (j.getOpcode == JSR) {
+ val jsrTargetHeight = heightAfter + 1
+ if (jsrTargetHeight > maxStack) maxStack = jsrTargetHeight
+ subroutineRetTargets.push(j.getNext)
+ enqInsn(j.label, jsrTargetHeight)
+ } else {
+ enqInsn(j.label, heightAfter)
+ val opc = j.getOpcode
+ if (opc != GOTO) enqInsnIndex(insnIndex + 1, heightAfter) // jump is conditional, so the successor is also a possible control flow target
+ }
+
case l: LookupSwitchInsnNode =>
var j = 0
while (j < l.labels.size) {
enqInsn(l.labels.get(j), heightAfter); j += 1
}
enqInsn(l.dflt, heightAfter)
+
case t: TableSwitchInsnNode =>
var j = 0
while (j < t.labels.size) {
enqInsn(t.labels.get(j), heightAfter); j += 1
}
enqInsn(t.dflt, heightAfter)
+
+ case r: VarInsnNode if r.getOpcode == RET =>
+ enqInsn(subroutineRetTargets.pop(), heightAfter)
+
case _ =>
val opc = insn.getOpcode
if (opc != ATHROW && !isReturn(insn))
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/InstructionResultSize.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/InstructionResultSize.scala
index 8d744f6d13..79e44a8503 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/opt/InstructionResultSize.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/InstructionResultSize.scala
@@ -33,14 +33,10 @@ object InstructionResultSize {
case LDC =>
instruction.asInstanceOf[LdcInsnNode].cst match {
- case _: java.lang.Integer |
- _: java.lang.Float |
- _: String |
- _: Type |
- _: Handle => 1
-
case _: java.lang.Long |
_: java.lang.Double => 2
+
+ case _ => 1
}
case ILOAD |