summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/symtab/classfile
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2013-12-10 11:04:26 +0100
committerJason Zaugg <jzaugg@gmail.com>2013-12-10 11:11:57 +0100
commitf0d913b51dbe1a098e813aa08197eef9c6cbf737 (patch)
tree59e8343f0411b9c676f0a94d1174f5132e71f092 /src/compiler/scala/tools/nsc/symtab/classfile
parent7e996c1b05902df0144709a37d9149252885495c (diff)
downloadscala-f0d913b51dbe1a098e813aa08197eef9c6cbf737.tar.gz
scala-f0d913b51dbe1a098e813aa08197eef9c6cbf737.tar.bz2
scala-f0d913b51dbe1a098e813aa08197eef9c6cbf737.zip
SI-8062 Fix inliner cycle with recursion, separate compilation
ICodeReaders, which decompiles JVM bytecode to ICode, was not setting the `recursive` attribute of `IMethod`. This meant that the inliner got into a cycle, repeatedly inlining the recursive call. The method name `filter` was needed to trigger this as the inliner heuristically treats that as a more attractive inlining candidate, based on `isMonadicMethod`. This commit: - refactors the checking / setting of `virtual` - adds this to ICodeReaders - tests the case involving `invokevirtual` I'm not sure how to setup a test that fails without the other changes to `ICodeReader` (for invokestatic and invokespecial).
Diffstat (limited to 'src/compiler/scala/tools/nsc/symtab/classfile')
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala7
1 files changed, 6 insertions, 1 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
index c304c18c4f..d0c540a2c6 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
@@ -489,23 +489,28 @@ abstract class ICodeReader extends ClassfileParser {
case JVM.invokevirtual =>
val m = pool.getMemberSymbol(in.nextChar, false); size += 2
code.emit(CALL_METHOD(m, Dynamic))
+ method.updateRecursive(m)
case JVM.invokeinterface =>
val m = pool.getMemberSymbol(in.nextChar, false); size += 4
in.skip(2)
code.emit(CALL_METHOD(m, Dynamic))
+ // invokeinterface can't be recursive
case JVM.invokespecial =>
val m = pool.getMemberSymbol(in.nextChar, false); size += 2
val style = if (m.name == nme.CONSTRUCTOR || m.isPrivate) Static(true)
else SuperCall(m.owner.name);
code.emit(CALL_METHOD(m, style))
+ method.updateRecursive(m)
case JVM.invokestatic =>
val m = pool.getMemberSymbol(in.nextChar, true); size += 2
if (isBox(m))
code.emit(BOX(toTypeKind(m.info.paramTypes.head)))
else if (isUnbox(m))
code.emit(UNBOX(toTypeKind(m.info.resultType)))
- else
+ else {
code.emit(CALL_METHOD(m, Static(false)))
+ method.updateRecursive(m)
+ }
case JVM.invokedynamic =>
// TODO, this is just a place holder. A real implementation must parse the class constant entry
debuglog("Found JVM invokedynamic instructionm, inserting place holder ICode INVOKE_DYNAMIC.")