summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2016-09-26 09:47:49 +1000
committerJason Zaugg <jzaugg@gmail.com>2016-09-27 08:45:38 +1000
commite994c1c0becddc0d91fd4428f0d673bfac8941a3 (patch)
treed1d98efed86aa774a2c5349b3eca562a4ae7b9fd
parent6df14e57a4980897d5517f002c04584b82e05b15 (diff)
downloadscala-e994c1c0becddc0d91fd4428f0d673bfac8941a3.tar.gz
scala-e994c1c0becddc0d91fd4428f0d673bfac8941a3.tar.bz2
scala-e994c1c0becddc0d91fd4428f0d673bfac8941a3.zip
SD-233 synchronized blocks are JIT-friendly again
GenBCode, the new backend in Scala 2.12, subtly changed the way that synchronized blocks are emitted. It used `java/lang/Throwable` as an explicitly named exception type, rather than implying the same by omitting this in bytecode. This appears to confuse HotSpot JIT, which reports a error parsing the bytecode into its IR which leaves the enclosing method stuck in interpreted mode. This commit passes a `null` descriptor to restore the old pattern (the same one used by javac.) I've checked that the JIT warnings are gone and that the method can be compiled again.
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BCodeSyncAndTry.scala4
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/BytecodeTest.scala8
2 files changed, 11 insertions, 1 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeSyncAndTry.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeSyncAndTry.scala
index 3e53419573..466793010f 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeSyncAndTry.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeSyncAndTry.scala
@@ -73,9 +73,11 @@ abstract class BCodeSyncAndTry extends BCodeBodyBuilder {
/* ------ (4) exception-handler version of monitor-exit code.
* Reached upon abrupt termination of (2).
* Protected by whatever protects the whole synchronized expression.
+ * null => "any" exception in bytecode, like we emit for finally.
+ * Important not to use j/l/Throwable which dooms the method to a life of interpretation! (SD-233)
* ------
*/
- protect(startProtected, endProtected, currProgramPoint(), jlThrowableRef)
+ protect(startProtected, endProtected, currProgramPoint(), null)
locals.load(monitor)
emit(asm.Opcodes.MONITOREXIT)
emit(asm.Opcodes.ATHROW)
diff --git a/test/junit/scala/tools/nsc/backend/jvm/BytecodeTest.scala b/test/junit/scala/tools/nsc/backend/jvm/BytecodeTest.scala
index b09a41969e..00b6d1cc42 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/BytecodeTest.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/BytecodeTest.scala
@@ -187,4 +187,12 @@ class BytecodeTest extends BytecodeTesting {
List(Label(0), LineNumber(2, Label(0)), VarOp(ALOAD, 0), Invoke(INVOKESPECIAL, "T", "t", "()V", true), Op(RETURN), Label(4))
)
}
+
+ @Test
+ def sd233(): Unit = {
+ val code = "def f = { println(1); synchronized(println(2)) }"
+ val m = compileMethod(code)
+ val List(ExceptionHandler(_, _, _, desc)) = m.handlers
+ assert(desc == None, desc)
+ }
}