Obtain reification marker on default lambda extraction.

Add reification tests.
This commit is contained in:
Mikhael Bogdanov
2017-05-12 13:37:47 +02:00
parent 47c5e64ba5
commit 309051bd21
11 changed files with 234 additions and 9 deletions
@@ -522,7 +522,7 @@ public class InlineCodegen extends CallGenerator {
private void generateClosuresBodies() {
for (LambdaInfo info : expressionMap.values()) {
info.generateLambdaBody(codegen);
info.generateLambdaBody(codegen, reifiedTypeInliner);
}
}
@@ -50,7 +50,7 @@ abstract class LambdaInfo(@JvmField val isCrossInline: Boolean, @JvmField val is
lateinit var node: SMAPAndMethodNode
abstract fun generateLambdaBody(codegen: ExpressionCodegen)
abstract fun generateLambdaBody(codegen: ExpressionCodegen, reifiedTypeInliner: ReifiedTypeInliner)
fun addAllParameters(remapper: FieldRemapper): Parameters {
val builder = ParametersBuilder.initializeBuilderFrom(AsmTypes.OBJECT_TYPE, invokeMethod.descriptor, this)
@@ -81,7 +81,8 @@ class DefaultLambda(
override val lambdaClassType: Type,
val capturedArgs: Array<Type>,
val parameterDescriptor: ValueParameterDescriptor,
val offset: Int
val offset: Int,
val needReification: Boolean
) : LambdaInfo(parameterDescriptor.isCrossinline, false) {
val parameterOffsetsInDefault: MutableList<Int> = arrayListOf()
@@ -99,7 +100,7 @@ class DefaultLambda(
override fun isMyLabel(name: String): Boolean = false
override fun generateLambdaBody(codegen: ExpressionCodegen) {
override fun generateLambdaBody(codegen: ExpressionCodegen, reifiedTypeInliner: ReifiedTypeInliner) {
val classReader = InlineCodegenUtil.buildClassReaderByInternalName(codegen.state, lambdaClassType.internalName)
val descriptor = Type.getMethodDescriptor(Type.VOID_TYPE, *capturedArgs)
@@ -129,6 +130,11 @@ class DefaultLambda(
invokeMethod.name,
invokeMethod.descriptor,
lambdaClassType.internalName)!!
if (needReification) {
//nested classes could also require reification
reifiedTypeInliner.reifyInstructions(node.node)
}
}
}
@@ -223,7 +229,7 @@ class ExpressionLambda(
val isPropertyReference: Boolean
get() = propertyReferenceInfo != null
override fun generateLambdaBody(codegen: ExpressionCodegen) {
override fun generateLambdaBody(codegen: ExpressionCodegen, reifiedTypeInliner: ReifiedTypeInliner) {
val closureContext =
if (isPropertyReference)
codegen.getContext().intoAnonymousClass(classDescriptor, codegen, OwnerKind.IMPLEMENTATION)
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.OwnerKind
import org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.DEFAULT_LAMBDA_FAKE_CALL
import org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.getConstant
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner.Companion.isNeedClassReificationMarker
import org.jetbrains.kotlin.codegen.optimization.common.InsnSequence
import org.jetbrains.kotlin.codegen.optimization.common.asSequence
import org.jetbrains.kotlin.codegen.optimization.common.insnText
@@ -153,7 +154,7 @@ private fun extractDefaultLambdasInfo(
instanceInstuction = instanceInstuction.previous
}
val (owner, argTypes) = when (instanceInstuction) {
val (owner, argTypes, needReification) = when (instanceInstuction) {
is MethodInsnNode -> {
assert(instanceInstuction.name == "<init>") { "Expected constructor call for default lambda, but $instanceInstuction" }
val ownerInternalName = instanceInstuction.owner
@@ -170,20 +171,23 @@ private fun extractDefaultLambdasInfo(
addAll(InsnSequence(instanceInstuction, varAssignmentInstruction.next).toList())
}
Type.getObjectType(instanceInstuction.owner) to Type.getArgumentTypes(instanceInstuction.desc)
val needReification = instanceCreation.previous.takeIf { isNeedClassReificationMarker(it) }?.let { toDelete.add(it) } != null
Triple(Type.getObjectType(instanceInstuction.owner), Type.getArgumentTypes(instanceInstuction.desc), needReification)
}
is FieldInsnNode -> {
toDelete.addAll(InsnSequence(instanceInstuction, varAssignmentInstruction.next).toList())
Type.getObjectType(instanceInstuction.owner) to emptyArray<Type>()
val needReification = instanceInstuction.previous.takeIf { isNeedClassReificationMarker(it) }?.let { toDelete.add(it) } != null
Triple(Type.getObjectType(instanceInstuction.owner), emptyArray<Type>(), needReification)
}
else -> throw RuntimeException("Can't extract default lambda info $it.\n Unknown instruction: ${instanceInstuction.insnText}")
}
toInsert.add(varAssignmentInstruction to defaultLambdaFakeCallStub(argTypes, it.varIndex))
DefaultLambda(owner, argTypes, defaultLambdas[it.varIndex]!!, it.varIndex)
DefaultLambda(owner, argTypes, defaultLambdas[it.varIndex]!!, it.varIndex, needReification)
}
}