diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2016-09-26 09:47:49 +1000 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2016-09-27 08:45:38 +1000 |
commit | e994c1c0becddc0d91fd4428f0d673bfac8941a3 (patch) | |
tree | d1d98efed86aa774a2c5349b3eca562a4ae7b9fd | |
parent | 6df14e57a4980897d5517f002c04584b82e05b15 (diff) | |
download | scala-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.scala | 4 | ||||
-rw-r--r-- | test/junit/scala/tools/nsc/backend/jvm/BytecodeTest.scala | 8 |
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) + } } |