Add proper DefaultLambda initialization,
patch lambda related instructions in default method Remove default lambda linked instructions from default method
This commit is contained in:
@@ -316,7 +316,7 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
ClassId classId = IntrinsicArrayConstructorsKt.getClassId();
|
ClassId classId = IntrinsicArrayConstructorsKt.getClassId();
|
||||||
byte[] bytes =
|
byte[] bytes =
|
||||||
InlineCacheKt.getOrPut(state.getInlineCache().getClassBytes(), classId, IntrinsicArrayConstructorsKt::getBytecode);
|
InlineCacheKt.getOrPut(state.getInlineCache().getClassBytes(), classId, IntrinsicArrayConstructorsKt::getBytecode);
|
||||||
return InlineCodegenUtil.getMethodNode(bytes, asmMethod.getName(), asmMethod.getDescriptor(), classId);
|
return InlineCodegenUtil.getMethodNode(bytes, asmMethod.getName(), asmMethod.getDescriptor(), classId.asString());
|
||||||
}
|
}
|
||||||
|
|
||||||
assert callableDescriptor instanceof DeserializedCallableMemberDescriptor : "Not a deserialized function or proper: " + callableDescriptor;
|
assert callableDescriptor instanceof DeserializedCallableMemberDescriptor : "Not a deserialized function or proper: " + callableDescriptor;
|
||||||
@@ -339,7 +339,7 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return InlineCodegenUtil.getMethodNode(bytes, asmMethod.getName(), asmMethod.getDescriptor(), containerId);
|
return InlineCodegenUtil.getMethodNode(bytes, asmMethod.getName(), asmMethod.getDescriptor(), containerId.asString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
@@ -88,12 +88,14 @@ public class InlineCodegenUtil {
|
|||||||
public static final String INLINE_FUN_THIS_0_SUFFIX = "$inline_fun";
|
public static final String INLINE_FUN_THIS_0_SUFFIX = "$inline_fun";
|
||||||
public static final String INLINE_FUN_VAR_SUFFIX = "$iv";
|
public static final String INLINE_FUN_VAR_SUFFIX = "$iv";
|
||||||
|
|
||||||
|
public static final String DEFAULT_LAMBDA_FAKE_CALL = "$$$DEFAULT_LAMBDA_FAKE_CALL$$$";
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static SMAPAndMethodNode getMethodNode(
|
public static SMAPAndMethodNode getMethodNode(
|
||||||
byte[] classData,
|
byte[] classData,
|
||||||
String methodName,
|
@NotNull String methodName,
|
||||||
String methodDescriptor,
|
@NotNull String methodDescriptor,
|
||||||
ClassId classId
|
@NotNull String classInternalName
|
||||||
) {
|
) {
|
||||||
ClassReader cr = new ClassReader(classData);
|
ClassReader cr = new ClassReader(classData);
|
||||||
MethodNode[] node = new MethodNode[1];
|
MethodNode[] node = new MethodNode[1];
|
||||||
@@ -138,12 +140,12 @@ public class InlineCodegenUtil {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (classId.equals(IntrinsicArrayConstructorsKt.getClassId())) {
|
if (IntrinsicArrayConstructorsKt.getClassId().asString().equals(classInternalName)) {
|
||||||
// Don't load source map for intrinsic array constructors
|
// Don't load source map for intrinsic array constructors
|
||||||
debugInfo[0] = null;
|
debugInfo[0] = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
SMAP smap = SMAPParser.parseOrCreateDefault(debugInfo[1], debugInfo[0], classId.asString(), lines[0], lines[1]);
|
SMAP smap = SMAPParser.parseOrCreateDefault(debugInfo[1], debugInfo[0], classInternalName, lines[0], lines[1]);
|
||||||
return new SMAPAndMethodNode(node[0], smap);
|
return new SMAPAndMethodNode(node[0], smap);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,7 +171,7 @@ public class InlineCodegenUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private static VirtualFile findVirtualFileImprecise(@NotNull GenerationState state, @NotNull String internalClassName) {
|
public static VirtualFile findVirtualFileImprecise(@NotNull GenerationState state, @NotNull String internalClassName) {
|
||||||
FqName packageFqName = JvmClassName.byInternalName(internalClassName).getPackageFqName();
|
FqName packageFqName = JvmClassName.byInternalName(internalClassName).getPackageFqName();
|
||||||
String classNameWithDollars = StringsKt.substringAfterLast(internalClassName, "/", internalClassName);
|
String classNameWithDollars = StringsKt.substringAfterLast(internalClassName, "/", internalClassName);
|
||||||
//TODO: we cannot construct proper classId at this point, we need to read InnerClasses info from class file
|
//TODO: we cannot construct proper classId at this point, we need to read InnerClasses info from class file
|
||||||
@@ -444,7 +446,6 @@ public class InlineCodegenUtil {
|
|||||||
|
|
||||||
public static int getConstant(@NotNull AbstractInsnNode ins) {
|
public static int getConstant(@NotNull AbstractInsnNode ins) {
|
||||||
int opcode = ins.getOpcode();
|
int opcode = ins.getOpcode();
|
||||||
Integer value;
|
|
||||||
if (opcode >= Opcodes.ICONST_0 && opcode <= Opcodes.ICONST_5) {
|
if (opcode >= Opcodes.ICONST_0 && opcode <= Opcodes.ICONST_5) {
|
||||||
return opcode - Opcodes.ICONST_0;
|
return opcode - Opcodes.ICONST_0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,15 +25,16 @@ import org.jetbrains.kotlin.codegen.binding.MutableClosure
|
|||||||
import org.jetbrains.kotlin.codegen.context.EnclosedValueDescriptor
|
import org.jetbrains.kotlin.codegen.context.EnclosedValueDescriptor
|
||||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||||
import org.jetbrains.kotlin.psi.KtCallableReferenceExpression
|
import org.jetbrains.kotlin.psi.KtCallableReferenceExpression
|
||||||
import org.jetbrains.kotlin.psi.KtExpression
|
import org.jetbrains.kotlin.psi.KtExpression
|
||||||
import org.jetbrains.kotlin.psi.KtLambdaExpression
|
import org.jetbrains.kotlin.psi.KtLambdaExpression
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCallWithAssert
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCallWithAssert
|
||||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||||
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
import org.jetbrains.org.objectweb.asm.commons.Method
|
import org.jetbrains.org.objectweb.asm.commons.Method
|
||||||
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
|
|
||||||
import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode
|
import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode
|
||||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||||
|
|
||||||
@@ -66,7 +67,11 @@ abstract class LambdaInfo(@JvmField val isCrossInline: Boolean, @JvmField val is
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun LambdaInfo.getCapturedParamInfo(descriptor: EnclosedValueDescriptor): CapturedParamDesc {
|
fun LambdaInfo.getCapturedParamInfo(descriptor: EnclosedValueDescriptor): CapturedParamDesc {
|
||||||
return CapturedParamDesc(lambdaClassType, descriptor.fieldName, descriptor.type)
|
return capturedParamDesc(descriptor.fieldName, descriptor.type)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun LambdaInfo.capturedParamDesc(fieldName: String, fieldType: Type): CapturedParamDesc {
|
||||||
|
return CapturedParamDesc(lambdaClassType, fieldName, fieldType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -76,22 +81,52 @@ class DefaultLambda(
|
|||||||
override val lambdaClassType: Type,
|
override val lambdaClassType: Type,
|
||||||
val capturedArgs: Array<Type>,
|
val capturedArgs: Array<Type>,
|
||||||
val parameterDescriptor: ValueParameterDescriptor,
|
val parameterDescriptor: ValueParameterDescriptor,
|
||||||
val initInstuctions: List<AbstractInsnNode>,
|
|
||||||
val offset: Int
|
val offset: Int
|
||||||
) : LambdaInfo(false, false) {
|
) : LambdaInfo(parameterDescriptor.isCrossinline, false) {
|
||||||
override val invokeMethod: Method
|
|
||||||
get() = TODO("not implemented")
|
|
||||||
|
|
||||||
override val invokeMethodDescriptor: FunctionDescriptor
|
override lateinit var invokeMethod: Method
|
||||||
get() = TODO("not implemented")
|
private set
|
||||||
|
|
||||||
override val capturedVars: List<CapturedParamDesc>
|
|
||||||
get() = TODO("not implemented")
|
override val invokeMethodDescriptor: FunctionDescriptor =
|
||||||
|
parameterDescriptor.type.memberScope.getContributedFunctions(OperatorNameConventions.INVOKE, NoLookupLocation.FROM_BACKEND).single()
|
||||||
|
|
||||||
|
|
||||||
|
override lateinit var capturedVars: List<CapturedParamDesc>
|
||||||
|
private set
|
||||||
|
|
||||||
override fun isMyLabel(name: String): Boolean = false
|
override fun isMyLabel(name: String): Boolean = false
|
||||||
|
|
||||||
override fun generateLambdaBody(codegen: ExpressionCodegen) {
|
override fun generateLambdaBody(codegen: ExpressionCodegen) {
|
||||||
TODO("not implemented")
|
val classReader = InlineCodegenUtil.buildClassReaderByInternalName(codegen.state, lambdaClassType.internalName)
|
||||||
|
|
||||||
|
val descriptor = Type.getMethodDescriptor(Type.VOID_TYPE, *capturedArgs)
|
||||||
|
val constructor = InlineCodegenUtil.getMethodNode(
|
||||||
|
classReader.b,
|
||||||
|
"<init>",
|
||||||
|
descriptor,
|
||||||
|
lambdaClassType.internalName)?.node
|
||||||
|
|
||||||
|
assert(constructor != null || capturedArgs.isEmpty()) {
|
||||||
|
"Can't find non-default constructor <init>$descriptor for default lambda $lambdaClassType"
|
||||||
|
}
|
||||||
|
|
||||||
|
capturedVars = constructor?.findCapturedFieldAssignmentInstructions()?.map {
|
||||||
|
fieldNode ->
|
||||||
|
capturedParamDesc(fieldNode.name, Type.getType(fieldNode.desc))
|
||||||
|
}?.toList() ?: emptyList()
|
||||||
|
|
||||||
|
|
||||||
|
invokeMethod = Method(
|
||||||
|
OperatorNameConventions.INVOKE.asString(),
|
||||||
|
codegen.state.typeMapper.mapSignatureSkipGeneric(invokeMethodDescriptor).asmMethod.descriptor
|
||||||
|
)
|
||||||
|
|
||||||
|
node = InlineCodegenUtil.getMethodNode(
|
||||||
|
classReader.b,
|
||||||
|
invokeMethod.name,
|
||||||
|
invokeMethod.descriptor,
|
||||||
|
lambdaClassType.internalName)!!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -189,8 +189,7 @@ class MethodInliner(
|
|||||||
val valueParamShift = Math.max(nextLocalIndex, markerShift)//NB: don't inline cause it changes
|
val valueParamShift = Math.max(nextLocalIndex, markerShift)//NB: don't inline cause it changes
|
||||||
putStackValuesIntoLocals(listOf(*info.invokeMethod.argumentTypes), valueParamShift, this, desc)
|
putStackValuesIntoLocals(listOf(*info.invokeMethod.argumentTypes), valueParamShift, this, desc)
|
||||||
|
|
||||||
|
if (invokeCall.lambdaInfo.invokeMethodDescriptor.valueParameters.isEmpty()) {
|
||||||
if (invokeCall.lambdaInfo.invokeMethodDescriptor.getValueParameters().isEmpty()) {
|
|
||||||
// There won't be no parameters processing and line call can be left without actual instructions.
|
// There won't be no parameters processing and line call can be left without actual instructions.
|
||||||
// Note: if function is called on the line with other instructions like 1 + foo(), 'nop' will still be generated.
|
// Note: if function is called on the line with other instructions like 1 + foo(), 'nop' will still be generated.
|
||||||
visitInsn(Opcodes.NOP)
|
visitInsn(Opcodes.NOP)
|
||||||
|
|||||||
@@ -90,14 +90,11 @@ private fun MethodInliner.getLambdaIfExistsAndMarkInstructions(
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun parameterOffsets(valueParameters: List<JvmMethodParameterSignature>): Array<Int> {
|
fun parameterOffsets(isStatic: Boolean, valueParameters: List<JvmMethodParameterSignature>): Array<Int> {
|
||||||
var offset = 0
|
var nextOffset = if (isStatic) 0 else 1
|
||||||
return Array(valueParameters.size) { index ->
|
return Array(valueParameters.size) { index ->
|
||||||
if (index == 0) {
|
nextOffset.also {
|
||||||
0
|
nextOffset += valueParameters[index].asmType.size
|
||||||
}
|
|
||||||
else offset.apply {
|
|
||||||
offset += valueParameters[index - 1].asmType.size
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,10 +16,17 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.codegen.inline
|
package org.jetbrains.kotlin.codegen.inline
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.codegen.getMemberOwnerKind
|
||||||
|
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.optimization.common.InsnSequence
|
import org.jetbrains.kotlin.codegen.optimization.common.InsnSequence
|
||||||
import org.jetbrains.kotlin.codegen.optimization.common.asSequence
|
import org.jetbrains.kotlin.codegen.optimization.common.asSequence
|
||||||
|
import org.jetbrains.kotlin.codegen.optimization.common.insnText
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||||
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||||
@@ -39,7 +46,14 @@ private data class Condition(
|
|||||||
|
|
||||||
fun extractDefaultLambdaOffsetAndDescriptor(jvmSignature: JvmMethodSignature, functionDescriptor: FunctionDescriptor): Map<Int, ValueParameterDescriptor> {
|
fun extractDefaultLambdaOffsetAndDescriptor(jvmSignature: JvmMethodSignature, functionDescriptor: FunctionDescriptor): Map<Int, ValueParameterDescriptor> {
|
||||||
val valueParameters = jvmSignature.valueParameters
|
val valueParameters = jvmSignature.valueParameters
|
||||||
val parameterOffsets = parameterOffsets(valueParameters)
|
val containingDeclaration = functionDescriptor.containingDeclaration
|
||||||
|
val kind = containingDeclaration.getMemberOwnerKind().let {
|
||||||
|
if (DescriptorUtils.isInterface(containingDeclaration)) {
|
||||||
|
OwnerKind.DEFAULT_IMPLS
|
||||||
|
}
|
||||||
|
else it
|
||||||
|
}
|
||||||
|
val parameterOffsets = parameterOffsets(AsmUtil.isStaticMethod(kind, functionDescriptor), valueParameters)
|
||||||
val valueParameterOffset = valueParameters.takeWhile { it.kind != JvmMethodParameterKind.VALUE }.size
|
val valueParameterOffset = valueParameters.takeWhile { it.kind != JvmMethodParameterKind.VALUE }.size
|
||||||
|
|
||||||
return functionDescriptor.valueParameters.filter {
|
return functionDescriptor.valueParameters.filter {
|
||||||
@@ -81,7 +95,7 @@ fun expandMaskConditionsAndUpdateVariableNodes(
|
|||||||
val jumpInstruction = it.next?.next?.next as JumpInsnNode
|
val jumpInstruction = it.next?.next?.next as JumpInsnNode
|
||||||
Condition(
|
Condition(
|
||||||
masks[it.`var` - maskStartIndex],
|
masks[it.`var` - maskStartIndex],
|
||||||
InlineCodegenUtil.getConstant(it.next),
|
getConstant(it.next),
|
||||||
it,
|
it,
|
||||||
jumpInstruction,
|
jumpInstruction,
|
||||||
jumpInstruction.label.previous as VarInsnNode
|
jumpInstruction.label.previous as VarInsnNode
|
||||||
@@ -97,10 +111,12 @@ fun expandMaskConditionsAndUpdateVariableNodes(
|
|||||||
else null
|
else null
|
||||||
}.toList()
|
}.toList()
|
||||||
|
|
||||||
val defaultLambdasInfo = extractDefaultLambdasInfo(conditions, defaultLambdas)
|
val toDelete = arrayListOf<AbstractInsnNode>()
|
||||||
|
val toInsert = arrayListOf<Pair<AbstractInsnNode, AbstractInsnNode>>()
|
||||||
|
|
||||||
|
val defaultLambdasInfo = extractDefaultLambdasInfo(conditions, defaultLambdas, toDelete, toInsert)
|
||||||
|
|
||||||
val indexToVarNode = node.localVariables?.filter { it.index < maskStartIndex }?.associateBy { it.index } ?: emptyMap()
|
val indexToVarNode = node.localVariables?.filter { it.index < maskStartIndex }?.associateBy { it.index } ?: emptyMap()
|
||||||
val toDelete = arrayListOf<AbstractInsnNode>()
|
|
||||||
conditions.forEach {
|
conditions.forEach {
|
||||||
val jumpInstruction = it.jumpInstruction
|
val jumpInstruction = it.jumpInstruction
|
||||||
InsnSequence(it.maskInstruction, (if (it.expandNotDelete) jumpInstruction.next else jumpInstruction.label)).forEach {
|
InsnSequence(it.maskInstruction, (if (it.expandNotDelete) jumpInstruction.next else jumpInstruction.label)).forEach {
|
||||||
@@ -113,51 +129,72 @@ fun expandMaskConditionsAndUpdateVariableNodes(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
toDelete.forEach {
|
toInsert.forEach { (position, newInsn) ->
|
||||||
node.instructions.remove(it)
|
node.instructions.insert(position, newInsn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
node.remove(toDelete)
|
||||||
|
|
||||||
return defaultLambdasInfo
|
return defaultLambdasInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun extractDefaultLambdasInfo(conditions: List<Condition>, defaultLambdas: Map<Int, ValueParameterDescriptor>): List<DefaultLambda> {
|
private fun extractDefaultLambdasInfo(
|
||||||
|
conditions: List<Condition>,
|
||||||
|
defaultLambdas: Map<Int, ValueParameterDescriptor>,
|
||||||
|
toDelete: MutableList<AbstractInsnNode>,
|
||||||
|
toInsert: MutableList<Pair<AbstractInsnNode, AbstractInsnNode>>
|
||||||
|
): List<DefaultLambda> {
|
||||||
val defaultLambdaConditions = conditions.filter { it.expandNotDelete && defaultLambdas.contains(it.varIndex) }
|
val defaultLambdaConditions = conditions.filter { it.expandNotDelete && defaultLambdas.contains(it.varIndex) }
|
||||||
|
|
||||||
return defaultLambdaConditions.map {
|
return defaultLambdaConditions.map {
|
||||||
val varAssignmentInstruction = it.varInsNode!!
|
val varAssignmentInstruction = it.varInsNode!!
|
||||||
var instanceInstuction = varAssignmentInstruction.previous
|
var instanceInstuction = varAssignmentInstruction.previous
|
||||||
if (instanceInstuction is TypeInsnNode && instanceInstuction.opcode == Opcodes.CHECKCAST) {
|
if (instanceInstuction is TypeInsnNode && instanceInstuction.opcode == Opcodes.CHECKCAST) {
|
||||||
instanceInstuction = instanceInstuction.previous
|
instanceInstuction = instanceInstuction.previous
|
||||||
}
|
}
|
||||||
when (instanceInstuction) {
|
|
||||||
|
val (owner, argTypes) = when (instanceInstuction) {
|
||||||
is MethodInsnNode -> {
|
is MethodInsnNode -> {
|
||||||
assert(instanceInstuction.name == "<init>") { "Expected constructor call for default lambda, but $instanceInstuction" }
|
assert(instanceInstuction.name == "<init>") { "Expected constructor call for default lambda, but $instanceInstuction" }
|
||||||
val ownerInternalName = instanceInstuction.owner
|
val ownerInternalName = instanceInstuction.owner
|
||||||
val instanceCreation = InsnSequence(it.jumpInstruction, it.jumpInstruction.label).filter {
|
val instanceCreation = InsnSequence(it.jumpInstruction, it.jumpInstruction.label).filter {
|
||||||
it.opcode == Opcodes.NEW && (it as TypeInsnNode).desc == ownerInternalName
|
it.opcode == Opcodes.NEW && (it as TypeInsnNode).desc == ownerInternalName
|
||||||
}.single()
|
}.single()
|
||||||
|
|
||||||
assert(instanceCreation.next?.opcode == Opcodes.DUP) {
|
assert(instanceCreation.next?.opcode == Opcodes.DUP) {
|
||||||
"Dup should follow default lambda instanceInstuction creation but ${instanceCreation.next}"
|
"Dup should follow default lambda instanceInstruction creation but ${instanceCreation.next}"
|
||||||
}
|
}
|
||||||
|
|
||||||
DefaultLambda(
|
toDelete.apply {
|
||||||
Type.getObjectType(instanceInstuction.owner),
|
addAll(listOf(instanceCreation, instanceCreation.next))
|
||||||
Type.getArgumentTypes(instanceInstuction.desc),
|
addAll(InsnSequence(instanceInstuction, varAssignmentInstruction.next).toList())
|
||||||
defaultLambdas[it.varIndex]!!,
|
}
|
||||||
listOf(instanceCreation, instanceCreation.next) + InsnSequence(instanceInstuction, varAssignmentInstruction).toList(),
|
|
||||||
it.varIndex
|
Type.getObjectType(instanceInstuction.owner) to Type.getArgumentTypes(instanceInstuction.desc)
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
is FieldInsnNode -> DefaultLambda(
|
is FieldInsnNode -> {
|
||||||
Type.getObjectType(instanceInstuction.owner),
|
toDelete.addAll(InsnSequence(instanceInstuction, varAssignmentInstruction.next).toList())
|
||||||
emptyArray<Type>(),
|
|
||||||
defaultLambdas[it.varIndex]!!,
|
Type.getObjectType(instanceInstuction.owner) to emptyArray<Type>()
|
||||||
InsnSequence(instanceInstuction, varAssignmentInstruction).toList(),
|
}
|
||||||
it.varIndex
|
else -> throw RuntimeException("Can't extract default lambda info $it.\n Unknown instruction: ${instanceInstuction.insnText}")
|
||||||
)
|
|
||||||
else -> throw RuntimeException("Can't extract default lambda info $it.\n Unknown instruction: $instanceInstuction")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toInsert.add(varAssignmentInstruction to defaultLambdaFakeCallStub(argTypes, it.varIndex))
|
||||||
|
|
||||||
|
DefaultLambda(owner, argTypes, defaultLambdas[it.varIndex]!!, it.varIndex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//marker that removes captured parameters from stack
|
||||||
|
//at inlining it would be substituted with parameters store
|
||||||
|
private fun defaultLambdaFakeCallStub(args: Array<Type>, lambdaOffset: Int): MethodInsnNode {
|
||||||
|
return MethodInsnNode(
|
||||||
|
Opcodes.INVOKESTATIC,
|
||||||
|
DEFAULT_LAMBDA_FAKE_CALL,
|
||||||
|
DEFAULT_LAMBDA_FAKE_CALL + lambdaOffset,
|
||||||
|
Type.getMethodDescriptor(Type.VOID_TYPE, *args),
|
||||||
|
false
|
||||||
|
)
|
||||||
|
}
|
||||||
+2
-2
@@ -270,9 +270,9 @@ val IrFunction.OtherOrigin: JvmDeclarationOrigin
|
|||||||
get() = OtherOrigin(descriptor.psiElement, this.descriptor)
|
get() = OtherOrigin(descriptor.psiElement, this.descriptor)
|
||||||
|
|
||||||
fun DeclarationDescriptor.getMemberOwnerKind(): OwnerKind = when (this) {
|
fun DeclarationDescriptor.getMemberOwnerKind(): OwnerKind = when (this) {
|
||||||
is FileClassDescriptor ->
|
is FileClassDescriptor,
|
||||||
|
is PackageFragmentDescriptor ->
|
||||||
OwnerKind.PACKAGE
|
OwnerKind.PACKAGE
|
||||||
is PackageFragmentDescriptor,
|
|
||||||
is ClassDescriptor ->
|
is ClassDescriptor ->
|
||||||
OwnerKind.IMPLEMENTATION
|
OwnerKind.IMPLEMENTATION
|
||||||
else ->
|
else ->
|
||||||
|
|||||||
Reference in New Issue
Block a user