diff options
author | Lukas Rytz <lukas.rytz@typesafe.com> | 2016-03-30 11:07:37 +0200 |
---|---|---|
committer | Lukas Rytz <lukas.rytz@typesafe.com> | 2016-03-30 11:07:37 +0200 |
commit | ecc89449eebda0f6464e1dcc1e61bbdc46bdab3f (patch) | |
tree | ee0b695eac42ac90fa572e84fe36adc908bd77b1 /src/compiler/scala/tools/nsc/backend/jvm | |
parent | e5bbc98f780070326498d55bb0bdcde9bb6a746b (diff) | |
parent | e483fe26825501c175b701a662160dd0e54b035e (diff) | |
download | scala-ecc89449eebda0f6464e1dcc1e61bbdc46bdab3f.tar.gz scala-ecc89449eebda0f6464e1dcc1e61bbdc46bdab3f.tar.bz2 scala-ecc89449eebda0f6464e1dcc1e61bbdc46bdab3f.zip |
Merge pull request #5058 from lrytz/newTraitsInliner
Inline super calls, as they are statically resolved
Diffstat (limited to 'src/compiler/scala/tools/nsc/backend/jvm')
-rw-r--r-- | src/compiler/scala/tools/nsc/backend/jvm/opt/BytecodeUtils.scala | 5 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala | 7 |
2 files changed, 9 insertions, 3 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/BytecodeUtils.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/BytecodeUtils.scala index 9a90c53d3e..f48f60a438 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/BytecodeUtils.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/BytecodeUtils.scala @@ -88,6 +88,11 @@ object BytecodeUtils { def isLoadOrStore(instruction: AbstractInsnNode): Boolean = isLoad(instruction) || isStore(instruction) + def isNonVirtualCall(instruction: AbstractInsnNode): Boolean = { + val op = instruction.getOpcode + op == INVOKESPECIAL || op == INVOKESTATIC + } + def isExecutable(instruction: AbstractInsnNode): Boolean = instruction.getOpcode >= 0 def isConstructor(methodNode: MethodNode): Boolean = { diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala index 6dd74bad84..3267b9b5df 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala @@ -132,7 +132,7 @@ class CallGraph[BT <: BTypes](val btypes: BT) { (declarationClassNode, source) <- byteCodeRepository.classNodeAndSource(declarationClass): Either[OptimizerWarning, (ClassNode, Source)] } yield { val declarationClassBType = classBTypeFromClassNode(declarationClassNode) - val CallsiteInfo(safeToInline, safeToRewrite, canInlineFromSource, annotatedInline, annotatedNoInline, samParamTypes, warning) = analyzeCallsite(method, declarationClassBType, call.owner, source) + val CallsiteInfo(safeToInline, safeToRewrite, canInlineFromSource, annotatedInline, annotatedNoInline, samParamTypes, warning) = analyzeCallsite(method, declarationClassBType, call, source) Callee( callee = method, calleeDeclarationClass = declarationClassBType, @@ -264,7 +264,7 @@ class CallGraph[BT <: BTypes](val btypes: BT) { /** * Analyze a callsite and gather meta-data that can be used for inlining decisions. */ - private def analyzeCallsite(calleeMethodNode: MethodNode, calleeDeclarationClassBType: ClassBType, receiverTypeInternalName: InternalName, calleeSource: Source): CallsiteInfo = { + private def analyzeCallsite(calleeMethodNode: MethodNode, calleeDeclarationClassBType: ClassBType, call: MethodInsnNode, calleeSource: Source): CallsiteInfo = { val methodSignature = calleeMethodNode.name + calleeMethodNode.desc try { @@ -277,7 +277,7 @@ class CallGraph[BT <: BTypes](val btypes: BT) { val isAbstract = BytecodeUtils.isAbstractMethod(calleeMethodNode) - val receiverType = classBTypeFromParsedClassfile(receiverTypeInternalName) + val receiverType = classBTypeFromParsedClassfile(call.owner) // (1) A non-final method can be safe to inline if the receiver type is a final subclass. Example: // class A { @inline def f = 1 }; object B extends A; B.f // can be inlined // @@ -295,6 +295,7 @@ class CallGraph[BT <: BTypes](val btypes: BT) { // TODO: type analysis can render more calls statically resolved. Example: // new A.f // can be inlined, the receiver type is known to be exactly A. val isStaticallyResolved: Boolean = { + isNonVirtualCall(call) || // SD-86: super calls (invokespecial) can be inlined methodInlineInfo.effectivelyFinal || receiverType.info.orThrow.inlineInfo.isEffectivelyFinal // (1) } |