JVM_IR. Support anonymous object/lambda reification
This commit is contained in:
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.codegen
|
||||
import org.jetbrains.kotlin.codegen.inline.NameGenerator
|
||||
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeParametersUsages
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
|
||||
interface BaseExpressionCodegen {
|
||||
@@ -32,8 +31,6 @@ interface BaseExpressionCodegen {
|
||||
|
||||
val lastLineNumber: Int
|
||||
|
||||
fun consumeReifiedOperationMarker(typeParameterDescriptor: TypeParameterDescriptor)
|
||||
|
||||
fun propagateChildReifiedTypeParametersUsages(reifiedTypeParametersUsages: ReifiedTypeParametersUsages)
|
||||
|
||||
fun pushClosureOnStack(
|
||||
|
||||
@@ -92,6 +92,7 @@ import org.jetbrains.org.objectweb.asm.commons.Method;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isInt;
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.*;
|
||||
@@ -1031,7 +1032,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public StackValue putClosureInstanceOnStack(
|
||||
private StackValue putClosureInstanceOnStack(
|
||||
@NotNull ClosureCodegen closureCodegen,
|
||||
@Nullable StackValue functionReferenceReceiver
|
||||
) {
|
||||
@@ -4839,16 +4840,16 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
putReifiedOperationMarkerIfTypeIsReifiedParameterImpl(type, operationKind, v, null);
|
||||
}
|
||||
|
||||
public static void putReifiedOperationMarkerIfTypeIsReifiedParameter(
|
||||
private static void putReifiedOperationMarkerIfTypeIsReifiedParameter(
|
||||
@NotNull KotlinType type, @NotNull ReifiedTypeInliner.OperationKind operationKind, @NotNull InstructionAdapter v,
|
||||
@NotNull BaseExpressionCodegen codegen
|
||||
@NotNull ExpressionCodegen codegen
|
||||
) {
|
||||
putReifiedOperationMarkerIfTypeIsReifiedParameterImpl(type, operationKind, v, codegen);
|
||||
}
|
||||
|
||||
private static void putReifiedOperationMarkerIfTypeIsReifiedParameterImpl(
|
||||
@NotNull KotlinType type, @NotNull ReifiedTypeInliner.OperationKind operationKind, @NotNull InstructionAdapter v,
|
||||
@Nullable BaseExpressionCodegen codegen
|
||||
@Nullable ExpressionCodegen codegen
|
||||
) {
|
||||
Pair<TypeParameterDescriptor, ReificationArgument> typeParameterAndReificationArgument = extractReificationArgument(type);
|
||||
if (typeParameterAndReificationArgument != null && typeParameterAndReificationArgument.getFirst().isReified()) {
|
||||
@@ -4862,7 +4863,11 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
|
||||
@Override
|
||||
public void propagateChildReifiedTypeParametersUsages(@NotNull ReifiedTypeParametersUsages usages) {
|
||||
parentCodegen.getReifiedTypeParametersUsages().propagateChildUsagesWithinContext(usages, context);
|
||||
parentCodegen.getReifiedTypeParametersUsages().propagateChildUsagesWithinContext(
|
||||
usages,
|
||||
() -> context.getContextDescriptor().getTypeParameters().stream().filter(TypeParameterDescriptor::isReified).map(
|
||||
it -> it.getName().asString()).collect(Collectors.toSet())
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -5079,8 +5084,7 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void consumeReifiedOperationMarker(@NotNull TypeParameterDescriptor typeParameterDescriptor) {
|
||||
private void consumeReifiedOperationMarker(@NotNull TypeParameterDescriptor typeParameterDescriptor) {
|
||||
if (typeParameterDescriptor.getContainingDeclaration() != context.getContextDescriptor()) {
|
||||
parentCodegen.getReifiedTypeParametersUsages().
|
||||
addUsedReifiedParameter(typeParameterDescriptor.getName().asString());
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.inline
|
||||
|
||||
import org.jetbrains.kotlin.codegen.context.MethodContext
|
||||
import org.jetbrains.kotlin.codegen.generateAsCast
|
||||
import org.jetbrains.kotlin.codegen.generateIsCheck
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods
|
||||
@@ -349,18 +348,14 @@ class ReifiedTypeParametersUsages {
|
||||
usedTypeParameters.add(name)
|
||||
}
|
||||
|
||||
fun propagateChildUsagesWithinContext(child: ReifiedTypeParametersUsages, context: MethodContext) {
|
||||
fun propagateChildUsagesWithinContext(child: ReifiedTypeParametersUsages, reifiedTypeParameterNamesInContext: () -> Set<String>) {
|
||||
if (!child.wereUsedReifiedParameters()) return
|
||||
// used for propagating reified TP usages from children member codegen to parent's
|
||||
// mark enclosing object-literal/lambda as needed reification iff
|
||||
// 1. at least one of it's method contains operations to reify
|
||||
// 2. reified type parameter of these operations is not from current method signature
|
||||
// i.e. from outer scope
|
||||
child.usedTypeParameters.filterNot { name ->
|
||||
context.contextDescriptor.typeParameters.any { typeParameter ->
|
||||
typeParameter.isReified && typeParameter.name.asString() == name
|
||||
}
|
||||
}.forEach { usedTypeParameters.add(it) }
|
||||
usedTypeParameters.addAll(child.usedTypeParameters - reifiedTypeParameterNamesInContext())
|
||||
}
|
||||
|
||||
fun mergeAll(other: ReifiedTypeParametersUsages) {
|
||||
|
||||
+7
-3
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.backend.jvm.lower.constantValue
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
||||
import org.jetbrains.kotlin.codegen.inline.DefaultSourceMapper
|
||||
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeParametersUsages
|
||||
import org.jetbrains.kotlin.codegen.inline.SourceMapper
|
||||
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings
|
||||
import org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension
|
||||
@@ -54,6 +55,8 @@ open class ClassCodegen protected constructor(
|
||||
|
||||
val visitor: ClassBuilder = createClassBuilder()
|
||||
|
||||
val reifiedTypeParametersUsages = ReifiedTypeParametersUsages()
|
||||
|
||||
open fun createClassBuilder() = state.factory.newVisitor(
|
||||
OtherOrigin(descriptor.psiElement, descriptor),
|
||||
type,
|
||||
@@ -70,7 +73,7 @@ open class ClassCodegen protected constructor(
|
||||
else -> null
|
||||
}
|
||||
|
||||
fun generate() {
|
||||
fun generate(): ReifiedTypeParametersUsages {
|
||||
val superClassInfo = irClass.getSuperClassInfo(typeMapper)
|
||||
val signature = getSignature(irClass, type, superClassInfo, typeMapper)
|
||||
|
||||
@@ -121,6 +124,7 @@ open class ClassCodegen protected constructor(
|
||||
} else {
|
||||
done()
|
||||
}
|
||||
return reifiedTypeParametersUsages
|
||||
}
|
||||
|
||||
private fun generateKotlinMetadataAnnotation() {
|
||||
@@ -228,8 +232,8 @@ open class ClassCodegen protected constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun generateLocalClass(klass: IrClass) {
|
||||
ClassCodegen(klass, context, this).generate()
|
||||
fun generateLocalClass(klass: IrClass): ReifiedTypeParametersUsages {
|
||||
return ClassCodegen(klass, context, this).generate()
|
||||
}
|
||||
|
||||
private fun generateField(field: IrField) {
|
||||
|
||||
+22
-7
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil.*
|
||||
import org.jetbrains.kotlin.codegen.coroutines.INVOKE_SUSPEND_METHOD_NAME
|
||||
import org.jetbrains.kotlin.codegen.inline.*
|
||||
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner.Companion.putNeedClassReificationMarker
|
||||
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner.OperationKind.AS
|
||||
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner.OperationKind.SAFE_AS
|
||||
import org.jetbrains.kotlin.codegen.pseudoInsns.fakeAlwaysFalseIfeq
|
||||
@@ -26,7 +27,6 @@ import org.jetbrains.kotlin.config.isReleaseCoroutines
|
||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
@@ -120,6 +120,8 @@ class ExpressionCodegen(
|
||||
|
||||
override var lastLineNumber: Int = -1
|
||||
|
||||
private val closureReifiedMarkers = hashMapOf<IrClass, ReifiedTypeParametersUsages>()
|
||||
|
||||
private val IrType.asmType: Type
|
||||
get() = typeMapper.mapType(this)
|
||||
|
||||
@@ -322,6 +324,13 @@ class ExpressionCodegen(
|
||||
|
||||
when {
|
||||
expression is IrConstructorCall -> {
|
||||
closureReifiedMarkers[expression.symbol.owner.parentAsClass]?.let {
|
||||
if (it.wereUsedReifiedParameters()) {
|
||||
putNeedClassReificationMarker(v)
|
||||
propagateChildReifiedTypeParametersUsages(it)
|
||||
}
|
||||
}
|
||||
|
||||
// IR constructors have no receiver and return the new instance, but on JVM they are void-returning
|
||||
// instance methods named <init>.
|
||||
mv.anew(asmType)
|
||||
@@ -562,7 +571,9 @@ class ExpressionCodegen(
|
||||
|
||||
// TODO maybe remove?
|
||||
override fun visitClass(declaration: IrClass, data: BlockInfo): PromisedValue {
|
||||
classCodegen.generateLocalClass(declaration)
|
||||
classCodegen.generateLocalClass(declaration).also {
|
||||
closureReifiedMarkers[declaration] = it
|
||||
}
|
||||
return immaterialUnitValue
|
||||
}
|
||||
|
||||
@@ -1128,12 +1139,16 @@ class ExpressionCodegen(
|
||||
return IrInlineCodegen(this, state, original.descriptor, mappings, IrSourceCompilerForInline(state, element, this, data))
|
||||
}
|
||||
|
||||
override fun consumeReifiedOperationMarker(typeParameterDescriptor: TypeParameterDescriptor) {
|
||||
//TODO
|
||||
private fun consumeReifiedOperationMarker(typeParameter: IrTypeParameter) {
|
||||
if (typeParameter.parent != irFunction) {
|
||||
classCodegen.reifiedTypeParametersUsages.addUsedReifiedParameter(typeParameter.name.asString())
|
||||
}
|
||||
}
|
||||
|
||||
override fun propagateChildReifiedTypeParametersUsages(reifiedTypeParametersUsages: ReifiedTypeParametersUsages) {
|
||||
//TODO
|
||||
classCodegen.reifiedTypeParametersUsages.propagateChildUsagesWithinContext(reifiedTypeParametersUsages) {
|
||||
irFunction.typeParameters.filter { it.isReified }.map { it.name.asString() }.toSet()
|
||||
}
|
||||
}
|
||||
|
||||
override fun pushClosureOnStack(
|
||||
@@ -1208,12 +1223,12 @@ class ExpressionCodegen(
|
||||
/* From ExpressionCodegen.java */
|
||||
private fun putReifiedOperationMarkerIfTypeIsReifiedParameter(
|
||||
type: IrType, operationKind: ReifiedTypeInliner.OperationKind, v: InstructionAdapter,
|
||||
codegen: BaseExpressionCodegen?
|
||||
codegen: ExpressionCodegen?
|
||||
) {
|
||||
val typeParameterAndReificationArgument = extractReificationArgumentWithParameter(type)
|
||||
if (typeParameterAndReificationArgument != null && typeParameterAndReificationArgument.first.isReified) {
|
||||
val irTypeParameter = typeParameterAndReificationArgument.first
|
||||
codegen?.consumeReifiedOperationMarker(irTypeParameter.descriptor)
|
||||
codegen?.consumeReifiedOperationMarker(irTypeParameter)
|
||||
ReifiedTypeInliner.putReifiedOperationMarker(
|
||||
operationKind, typeParameterAndReificationArgument.second.toReificationArgument(), v
|
||||
)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
fun box(): String {
|
||||
defineFunc<String>()
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// WITH_RUNTIME
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// WITH_RUNTIME
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// WITH_RUNTIME
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// WITH_RUNTIME
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// WITH_RUNTIME
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// FILE: 1.kt
|
||||
// WITH_RUNTIME
|
||||
package test
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// FILE: 1.kt
|
||||
// WITH_RUNTIME
|
||||
package test
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// FILE: 1.kt
|
||||
// WITH_RUNTIME
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// FILE: 1.kt
|
||||
// WITH_RUNTIME
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// FILE: 1.kt
|
||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// FILE: 1.kt
|
||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// FILE: 1.kt
|
||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// FILE: 1.kt
|
||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// FILE: 1.kt
|
||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// FILE: 1.kt
|
||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// FILE: 1.kt
|
||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// FILE: 1.kt
|
||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// FILE: 1.kt
|
||||
// WITH_REFLECT
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// FILE: 1.kt
|
||||
// WITH_REFLECT
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// FILE: 1.kt
|
||||
// WITH_REFLECT
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// FILE: 1.kt
|
||||
|
||||
package test
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// FILE: 1.kt
|
||||
// WITH_REFLECT
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// FILE: 1.kt
|
||||
|
||||
package test
|
||||
|
||||
Reference in New Issue
Block a user