Simplify generated code for rangeTo/concat intrinsics

The main reason is avoiding complicated operations like
dup + dup_x2 + pop2 for instances obtained by NEW instruction.

Otherwise it leads to problems in performRefinedTypeAnalysis
because code there has a sensible assumption that NEW instances
can be only dupped or stored into a local (rare cases)

 #KT-17457 Fixed
This commit is contained in:
Denis Zharkov
2017-05-19 16:16:08 +03:00
parent 419f12f1b7
commit 52b2e632df
12 changed files with 134 additions and 25 deletions
@@ -45,7 +45,7 @@ interface Callable {
}
}
fun afterReceiverGeneration(v: InstructionAdapter) {
fun afterReceiverGeneration(v: InstructionAdapter, frameMap: FrameMap) {
}
}
@@ -2262,7 +2262,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
myFrameMap.leaveTemp(firstReceiverType);
}
callableMethod.afterReceiverGeneration(v);
callableMethod.afterReceiverGeneration(v, myFrameMap);
}
}
@@ -377,3 +377,22 @@ fun initializeVariablesForDestructuredLambdaParameters(codegen: ExpressionCodege
}
fun <D : CallableDescriptor> D.unwrapFrontendVersion() = unwrapInitialDescriptorForSuspendFunction()
inline fun FrameMap.useTmpVar(type: Type, block: (index: Int) -> Unit) {
val index = enterTemp(type)
block(index)
leaveTemp(type)
}
fun InstructionAdapter.generateNewInstanceDupAndPlaceBeforeStackTop(
frameMap: FrameMap,
topStackType: Type,
newInstanceInternalName: String
) {
frameMap.useTmpVar(topStackType) { index ->
store(index, topStackType)
anew(Type.getObjectType(newInstanceInternalName))
dup()
load(index, topStackType)
}
}
@@ -27,7 +27,6 @@ import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.JAVA_STRING_TYPE
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
@@ -83,10 +82,8 @@ class Concat : IntrinsicMethod() {
}
}
override fun afterReceiverGeneration(v: InstructionAdapter) {
v.visitTypeInsn(Opcodes.NEW, "java/lang/StringBuilder")
v.dupX1()
v.swap()
override fun afterReceiverGeneration(v: InstructionAdapter, frameMap: FrameMap) {
v.generateNewInstanceDupAndPlaceBeforeStackTop(frameMap, AsmTypes.JAVA_STRING_TYPE, "java/lang/StringBuilder")
v.invokespecial("java/lang/StringBuilder", "<init>", "(Ljava/lang/String;)V", false)
}
@@ -18,7 +18,8 @@ package org.jetbrains.kotlin.codegen.intrinsics
import org.jetbrains.kotlin.codegen.Callable
import org.jetbrains.kotlin.codegen.CallableMethod
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.FrameMap
import org.jetbrains.kotlin.codegen.generateNewInstanceDupAndPlaceBeforeStackTop
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.Type.*
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
@@ -47,19 +48,8 @@ class RangeTo : IntrinsicMethod() {
nullOr(method.dispatchReceiverType, argType),
nullOr(method.extensionReceiverType, argType)
) {
override fun afterReceiverGeneration(v: InstructionAdapter) {
v.anew(returnType)
when (argType.size) {
1 -> {
v.dupX1()
v.swap()
}
2 -> {
v.dup()
v.dup2X2()
v.pop2()
}
}
override fun afterReceiverGeneration(v: InstructionAdapter, frameMap: FrameMap) {
v.generateNewInstanceDupAndPlaceBeforeStackTop(frameMap, argType, returnType.internalName)
}
override fun invokeIntrinsic(v: InstructionAdapter) {