Introduce new naming convention for captured receiver backing fields

'receiver$0' -> '$this_<label>'
This commit is contained in:
Yan Zhulanow
2018-08-28 15:34:16 +05:00
parent 11d4a6bf5c
commit d16b55033e
53 changed files with 942 additions and 69 deletions
@@ -16,28 +16,32 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.builtins.PrimitiveType;
import org.jetbrains.kotlin.codegen.binding.CalculatedClosure;
import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
import org.jetbrains.kotlin.codegen.context.CodegenContext;
import org.jetbrains.kotlin.codegen.intrinsics.HashCode;
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
import org.jetbrains.kotlin.config.JvmTarget;
import org.jetbrains.kotlin.config.LanguageFeature;
import org.jetbrains.kotlin.config.LanguageVersionSettings;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.lexer.KtTokens;
import org.jetbrains.kotlin.load.java.JavaVisibilities;
import org.jetbrains.kotlin.load.java.JvmAnnotationNames;
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil;
import org.jetbrains.kotlin.metadata.jvm.serialization.JvmStringTable;
import org.jetbrains.kotlin.name.ClassId;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.name.*;
import org.jetbrains.kotlin.protobuf.MessageLite;
import org.jetbrains.kotlin.renderer.DescriptorRenderer;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.InlineClassDescriptorResolver;
import org.jetbrains.kotlin.resolve.InlineClassesUtilsKt;
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker;
import org.jetbrains.kotlin.resolve.inline.InlineUtil;
import org.jetbrains.kotlin.resolve.jvm.*;
import org.jetbrains.kotlin.resolve.jvm.checkers.DalvikIdentifierUtils;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
import org.jetbrains.kotlin.serialization.DescriptorSerializer;
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor;
@@ -88,11 +92,24 @@ public class AsmUtil {
.put(JavaVisibilities.PACKAGE_VISIBILITY, NO_FLAG_PACKAGE_PRIVATE)
.build();
public static final String BOUND_REFERENCE_RECEIVER = "receiver";
public static final String RECEIVER_NAME = "$receiver";
public static final String CAPTURED_RECEIVER_FIELD = "receiver$0";
public static final String THIS = "this";
private static final String LABELED_THIS_FIELD = THIS + "_";
public static final String CAPTURED_THIS_FIELD = "this$0";
public static final String RECEIVER_PARAMETER_NAME = "$receiver";
/*
This is basically an old convention. Starting from Kotlin 1.3, it was replaced with `$this_<label>`.
Note that it is still used for inlined callable references and anonymous callable extension receivers
even in 1.3.
*/
public static final String CAPTURED_RECEIVER_FIELD = "receiver$0";
// For non-inlined callable references ('kotlin.jvm.internal.CallableReference' has a 'receiver' field)
public static final String BOUND_REFERENCE_RECEIVER = "receiver";
private static final ImmutableMap<Integer, JvmPrimitiveType> primitiveTypeByAsmSort;
private static final ImmutableMap<Type, Type> primitiveTypeByBoxedType;
@@ -111,6 +128,74 @@ public class AsmUtil {
private AsmUtil() {
}
@NotNull
public static String getCapturedFieldName(@NotNull String originalName) {
return "$" + originalName;
}
@NotNull
public static String getLabeledThisNameForReceiver(
@NotNull CallableDescriptor descriptor,
@NotNull BindingContext bindingContext,
@NotNull LanguageVersionSettings languageVersionSettings
) {
if (!languageVersionSettings.supportsFeature(LanguageFeature.NewCapturedReceiverFieldNamingConvention)) {
return CAPTURED_RECEIVER_FIELD;
}
Name callableName = null;
if (descriptor instanceof FunctionDescriptor) {
String labelName = bindingContext.get(CodegenBinding.CALL_LABEL_FOR_LAMBDA_ARGUMENT, (FunctionDescriptor) descriptor);
if (labelName != null) {
return getLabeledThisName(labelName, CAPTURED_RECEIVER_FIELD);
}
if (descriptor instanceof VariableAccessorDescriptor) {
VariableAccessorDescriptor accessor = (VariableAccessorDescriptor) descriptor;
callableName = accessor.getCorrespondingVariable().getName();
}
}
if (callableName == null) {
callableName = descriptor.getName();
}
if (callableName.isSpecial()) {
return CAPTURED_RECEIVER_FIELD;
}
return getLabeledThisName(callableName.asString(), CAPTURED_RECEIVER_FIELD);
}
@NotNull
private static String getLabeledThisName(@NotNull String callableName, @NotNull String defaultName) {
if (!Name.isValidIdentifier(callableName)) {
return defaultName;
}
if (!DalvikIdentifierUtils.isValidDalvikIdentifier(callableName)) {
return LABELED_THIS_FIELD + mangleLabel(callableName);
}
return LABELED_THIS_FIELD + callableName;
}
private static String mangleLabel(String label) {
StringBuilder sb = new StringBuilder();
for (char c : label.toCharArray()) {
if (DalvikIdentifierUtils.isValidDalvikCharacter(c)) {
sb.append(c);
continue;
}
sb.append("_u").append(Integer.toHexString(c));
}
return sb.toString();
}
@NotNull
public static Type boxType(@NotNull Type type) {
Type boxedType = boxPrimitiveType(type);
@@ -510,7 +595,12 @@ public class AsmUtil {
v.athrow();
}
public static void genClosureFields(@NotNull CalculatedClosure closure, ClassBuilder v, KotlinTypeMapper typeMapper) {
public static void genClosureFields(
@NotNull CalculatedClosure closure,
ClassBuilder v,
KotlinTypeMapper typeMapper,
@NotNull LanguageVersionSettings languageVersionSettings
) {
List<Pair<String, Type>> allFields = new ArrayList<>();
ClassifierDescriptor captureThis = closure.getCapturedOuterClassDescriptor();
@@ -520,7 +610,8 @@ public class AsmUtil {
KotlinType captureReceiverType = closure.getCapturedReceiverFromOuterContext();
if (captureReceiverType != null && !CallableReferenceUtilKt.isForCallableReference(closure)) {
allFields.add(Pair.create(CAPTURED_RECEIVER_FIELD, typeMapper.mapType(captureReceiverType)));
String fieldName = closure.getCapturedReceiverFieldName(typeMapper.getBindingContext(), languageVersionSettings);
allFields.add(Pair.create(fieldName, typeMapper.mapType(captureReceiverType)));
}
allFields.addAll(closure.getRecordedFields());
@@ -736,7 +827,7 @@ public class AsmUtil {
}
}
public static void genNotNullAssertionsForParameters(
static void genNotNullAssertionsForParameters(
@NotNull InstructionAdapter v,
@NotNull GenerationState state,
@NotNull FunctionDescriptor descriptor,
@@ -758,7 +849,7 @@ public class AsmUtil {
if (descriptor.isOperator()) {
ReceiverParameterDescriptor receiverParameter = descriptor.getExtensionReceiverParameter();
if (receiverParameter != null) {
genParamAssertion(v, state.getTypeMapper(), frameMap, receiverParameter, "$receiver", descriptor);
genParamAssertion(v, state.getTypeMapper(), frameMap, receiverParameter, CAPTURED_RECEIVER_FIELD, descriptor);
}
}
return;
@@ -766,7 +857,7 @@ public class AsmUtil {
ReceiverParameterDescriptor receiverParameter = descriptor.getExtensionReceiverParameter();
if (receiverParameter != null) {
genParamAssertion(v, state.getTypeMapper(), frameMap, receiverParameter, "$receiver", descriptor);
genParamAssertion(v, state.getTypeMapper(), frameMap, receiverParameter, CAPTURED_RECEIVER_FIELD, descriptor);
}
for (ValueParameterDescriptor parameter : descriptor.getValueParameters()) {
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter;
import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
import org.jetbrains.kotlin.config.LanguageVersionSettings;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor;
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl;
@@ -171,7 +172,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
generateConstInstance(asmType, asmType);
}
genClosureFields(closure, v, typeMapper);
genClosureFields(closure, v, typeMapper, state.getLanguageVersionSettings());
}
protected void generateClosureBody() {
@@ -425,7 +426,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
@NotNull
protected Method generateConstructor() {
List<FieldInfo> args = calculateConstructorParameters(typeMapper, closure, asmType);
List<FieldInfo> args = calculateConstructorParameters(typeMapper, state.getLanguageVersionSettings(), closure, asmType);
Type[] argTypes = fieldListToTypeArray(args);
@@ -482,6 +483,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
@NotNull
public static List<FieldInfo> calculateConstructorParameters(
@NotNull KotlinTypeMapper typeMapper,
@NotNull LanguageVersionSettings languageVersionSettings,
@NotNull CalculatedClosure closure,
@NotNull Type ownerType
) {
@@ -493,7 +495,8 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
}
KotlinType captureReceiverType = closure.getCapturedReceiverFromOuterContext();
if (captureReceiverType != null) {
args.add(FieldInfo.createForHiddenField(ownerType, typeMapper.mapType(captureReceiverType), CAPTURED_RECEIVER_FIELD));
String fieldName = closure.getCapturedReceiverFieldName(typeMapper.getBindingContext(), languageVersionSettings);
args.add(FieldInfo.createForHiddenField(ownerType, typeMapper.mapType(captureReceiverType), fieldName));
}
for (EnclosedValueDescriptor enclosedValueDescriptor : closure.getCaptureVariables().values()) {
@@ -18,16 +18,19 @@ package org.jetbrains.kotlin.codegen
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.psi.KtDeclarationWithBody
import org.jetbrains.kotlin.psi.KtFunctionLiteral
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
class ClosureGenerationStrategy(
state: GenerationState,
declaration: KtDeclarationWithBody
val declaration: KtDeclarationWithBody
) : FunctionGenerationStrategy.FunctionDefault(state, declaration) {
override fun doGenerateBody(codegen: ExpressionCodegen, signature: JvmMethodSignature) {
initializeVariablesForDestructuredLambdaParameters(codegen, codegen.context.functionDescriptor.valueParameters)
if (declaration is KtFunctionLiteral) {
recordCallLabelForLambdaArgument(declaration, state.bindingTrace)
}
super.doGenerateBody(codegen, signature)
}
}
@@ -286,7 +286,9 @@ public class ConstructorCodegen {
private void generateClosureInitialization(@NotNull InstructionAdapter iv) {
MutableClosure closure = context.closure;
if (closure != null) {
List<FieldInfo> argsFromClosure = ClosureCodegen.calculateConstructorParameters(typeMapper, closure, classAsmType);
List<FieldInfo> argsFromClosure = ClosureCodegen.calculateConstructorParameters(
typeMapper, state.getLanguageVersionSettings(), closure, classAsmType);
int k = 1;
for (FieldInfo info : argsFromClosure) {
k = AsmUtil.genAssignInstanceFieldFromParam(info, k, iv);
@@ -431,7 +431,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
if (context.closure != null)
genClosureFields(context.closure, v, typeMapper);
genClosureFields(context.closure, v, typeMapper, state.getLanguageVersionSettings());
for (ExpressionCodegenExtension extension : ExpressionCodegenExtension.Companion.getInstances(state.getProject())) {
if (state.getClassBuilderMode() != ClassBuilderMode.LIGHT_CLASSES
@@ -679,7 +679,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
if (captureReceiver != null) {
iv.load(0, classAsmType);
Type type = typeMapper.mapType(captureReceiver);
iv.getfield(classAsmType.getInternalName(), CAPTURED_RECEIVER_FIELD, type.getDescriptor());
String fieldName = closure.getCapturedReceiverFieldName(bindingContext, state.getLanguageVersionSettings());
iv.getfield(classAsmType.getInternalName(), fieldName, type.getDescriptor());
}
for (Map.Entry<DeclarationDescriptor, EnclosedValueDescriptor> entry : closure.getCaptureVariables().entrySet()) {
@@ -78,9 +78,11 @@ class PropertyReferenceCodegen(
}
}
private val constructorArgs = ClosureCodegen.calculateConstructorParameters(typeMapper, closure, asmType).apply {
assert(size <= 1) { "Bound property reference should capture only one value: $this" }
}
private val constructorArgs =
ClosureCodegen.calculateConstructorParameters(typeMapper, state.languageVersionSettings, closure, asmType).apply {
assert(size <= 1) { "Bound property reference should capture only one value: $this" }
}
private val constructor = method("<init>", Type.VOID_TYPE, *constructorArgs.map { it.fieldType }.toTypedArray())
override fun generateDeclaration() {
@@ -102,7 +104,7 @@ class PropertyReferenceCodegen(
if (JvmCodegenUtil.isConst(closure)) {
generateConstInstance(asmType, wrapperMethod.returnType)
} else {
AsmUtil.genClosureFields(closure, v, typeMapper)
AsmUtil.genClosureFields(closure, v, typeMapper, state.languageVersionSettings)
}
generateConstructor()
@@ -20,6 +20,7 @@ import com.intellij.openapi.util.Pair;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.context.EnclosedValueDescriptor;
import org.jetbrains.kotlin.config.LanguageVersionSettings;
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
import org.jetbrains.kotlin.resolve.BindingContext;
@@ -40,7 +41,7 @@ public interface CalculatedClosure {
KotlinType getCapturedReceiverFromOuterContext();
@NotNull
String getCapturedReceiverLabel(BindingContext bindingContext);
String getCapturedReceiverFieldName(BindingContext bindingContext, LanguageVersionSettings languageVersionSettings);
@NotNull
Map<DeclarationDescriptor, EnclosedValueDescriptor> getCaptureVariables();
@@ -68,6 +68,8 @@ public class CodegenBinding {
public static final WritableSlice<VariableDescriptor, VariableDescriptor> LOCAL_VARIABLE_PROPERTY_METADATA =
Slices.createSimpleSlice();
public static final WritableSlice<FunctionDescriptor, String> CALL_LABEL_FOR_LAMBDA_ARGUMENT = Slices.createSimpleSlice();
static {
BasicWritableSlice.initSliceDebugNames(CodegenBinding.class);
}
@@ -21,8 +21,9 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.AsmUtil;
import org.jetbrains.kotlin.codegen.context.EnclosedValueDescriptor;
import org.jetbrains.kotlin.config.LanguageFeature;
import org.jetbrains.kotlin.config.LanguageVersionSettings;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.name.NameUtils;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.org.objectweb.asm.Type;
@@ -101,12 +102,19 @@ public final class MutableClosure implements CalculatedClosure {
@NotNull
@Override
public String getCapturedReceiverLabel(BindingContext bindingContext) {
public String getCapturedReceiverFieldName(BindingContext bindingContext, LanguageVersionSettings languageVersionSettings) {
if (captureReceiverType != null) {
// Should effectively be returned only for callable references
return AsmUtil.CAPTURED_RECEIVER_FIELD;
} else if (enclosingFunWithReceiverDescriptor != null) {
return AsmUtil.CAPTURED_RECEIVER_FIELD;
if (!languageVersionSettings.supportsFeature(LanguageFeature.NewCapturedReceiverFieldNamingConvention)) {
return AsmUtil.CAPTURED_RECEIVER_FIELD;
}
String labeledThis = AsmUtil.getLabeledThisNameForReceiver(
enclosingFunWithReceiverDescriptor, bindingContext, languageVersionSettings);
return AsmUtil.getCapturedFieldName(labeledThis);
} else {
throw new IllegalStateException("Closure does not capture an outer receiver");
}
@@ -31,10 +31,10 @@ fun capturedBoundReferenceReceiver(ownerType: Type, expectedReceiverType: Type,
StackValue.operation(expectedReceiverType) { iv ->
iv.load(0, ownerType)
iv.getfield(
ownerType.internalName,
ownerType.internalName,
//HACK for inliner - it should recognize field as captured receiver
if (isInliningStrategy) AsmUtil.CAPTURED_RECEIVER_FIELD else AsmUtil.BOUND_REFERENCE_RECEIVER,
AsmTypes.OBJECT_TYPE.descriptor
if (isInliningStrategy) AsmUtil.CAPTURED_RECEIVER_FIELD else AsmUtil.BOUND_REFERENCE_RECEIVER,
AsmTypes.OBJECT_TYPE.descriptor
)
StackValue.coerce(AsmTypes.OBJECT_TYPE, expectedReceiverType, iv)
}
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.codegen
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
import org.jetbrains.kotlin.builtins.UnsignedTypes
import org.jetbrains.kotlin.codegen.context.CodegenContext
import org.jetbrains.kotlin.codegen.context.FieldOwnerContext
@@ -30,11 +31,13 @@ import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.renderer.DescriptorRenderer
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils.isSubclass
import org.jetbrains.kotlin.resolve.annotations.hasJvmStaticAnnotation
import org.jetbrains.kotlin.resolve.calls.callUtil.getFirstArgumentExpression
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.isInlineClassType
@@ -439,3 +442,26 @@ fun KotlinType.isInlineClassTypeWithPrimitiveEquality(): Boolean {
fun CallableDescriptor.needsExperimentalCoroutinesWrapper() =
(this as? DeserializedMemberDescriptor)?.coroutinesExperimentalCompatibilityMode == CoroutinesCompatibilityMode.NEEDS_WRAPPER
fun recordCallLabelForLambdaArgument(declaration: KtFunctionLiteral, bindingTrace: BindingTrace) {
fun storeLabelName(labelName: String) {
val functionDescriptor = bindingTrace[BindingContext.FUNCTION, declaration] ?: return
bindingTrace.record(CodegenBinding.CALL_LABEL_FOR_LAMBDA_ARGUMENT, functionDescriptor, labelName)
}
val lambdaExpression = declaration.parent as? KtLambdaExpression ?: return
val lambdaExpressionParent = lambdaExpression.parent
if (lambdaExpressionParent is KtLabeledExpression) {
lambdaExpressionParent.name?.let { labelName ->
storeLabelName(labelName)
return
}
}
val lambdaArgument = lambdaExpression.parent as? KtLambdaArgument ?: return
val callExpression = lambdaArgument.parent as? KtCallExpression ?: return
val call = callExpression.getResolvedCall(bindingTrace.bindingContext) ?: return
storeLabelName(call.resultingDescriptor.name.asString())
}
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.codegen.context;
import kotlin.text.StringsKt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.codegen.AsmUtil;
import org.jetbrains.kotlin.codegen.ExpressionCodegen;
import org.jetbrains.kotlin.codegen.JvmCodegenUtil;
import org.jetbrains.kotlin.codegen.StackValue;
@@ -18,7 +19,6 @@ import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.org.objectweb.asm.Type;
import static org.jetbrains.kotlin.codegen.AsmUtil.CAPTURED_RECEIVER_FIELD;
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.*;
import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isLocalFunction;
@@ -147,8 +147,9 @@ public interface LocalLookup {
KotlinType receiverType = enclosingReceiverDescriptor.getType();
Type type = state.getTypeMapper().mapType(receiverType);
String fieldName = closure.getCapturedReceiverFieldName(state.getBindingContext(), state.getLanguageVersionSettings());
StackValue.StackValueWithSimpleReceiver innerValue = StackValue.field(
type, receiverType, classType, CAPTURED_RECEIVER_FIELD, false, StackValue.LOCAL_0, d
type, receiverType, classType, fieldName, false, StackValue.LOCAL_0, d
);
closure.setNeedsCaptureReceiverFromOuterContext();
@@ -102,7 +102,7 @@ abstract class AbstractCoroutineCodegen(
)
override fun generateConstructor(): Method {
val args = calculateConstructorParameters(typeMapper, closure, asmType)
val args = calculateConstructorParameters(typeMapper, languageVersionSettings, closure, asmType)
val argTypes = args.map { it.fieldType }.plus(languageVersionSettings.continuationAsmType()).toTypedArray()
val constructor = Method("<init>", Type.VOID_TYPE, argTypes)
@@ -345,7 +345,7 @@ class CoroutineCodegenForLambda private constructor(
dup()
// pass captured closure to constructor
val constructorParameters = calculateConstructorParameters(typeMapper, closure, owner)
val constructorParameters = calculateConstructorParameters(typeMapper, languageVersionSettings, closure, owner)
for (parameter in constructorParameters) {
StackValue.field(parameter, thisInstance).put(parameter.fieldType, this)
}
@@ -46,7 +46,7 @@ internal fun generateParameterNames(
isEnumName = !isEnumName
if (!isEnumName) "\$enum\$name" else "\$enum\$ordinal"
}
JvmMethodParameterKind.RECEIVER -> AsmUtil.RECEIVER_NAME
JvmMethodParameterKind.RECEIVER -> AsmUtil.RECEIVER_PARAMETER_NAME
JvmMethodParameterKind.OUTER -> AsmUtil.CAPTURED_THIS_FIELD
JvmMethodParameterKind.VALUE -> iterator.next().name.asString()
@@ -588,8 +588,8 @@ class AnonymousObjectTransformer(
val parent = parentFieldRemapper.parent as? RegeneratedLambdaFieldRemapper ?:
throw AssertionError("Expecting RegeneratedLambdaFieldRemapper, but ${parentFieldRemapper.parent}")
val ownerType = Type.getObjectType(parent.originalLambdaInternalName)
val desc = CapturedParamDesc(ownerType, THIS, ownerType)
val recapturedParamInfo = capturedParamBuilder.addCapturedParam(desc, THIS_0/*outer lambda/object*/, false)
val desc = CapturedParamDesc(ownerType, AsmUtil.THIS, ownerType)
val recapturedParamInfo = capturedParamBuilder.addCapturedParam(desc, AsmUtil.CAPTURED_THIS_FIELD/*outer lambda/object*/, false)
val composed = StackValue.LOCAL_0
recapturedParamInfo.remapValue = composed
allRecapturedParameters.add(desc)
@@ -611,7 +611,7 @@ class AnonymousObjectTransformer(
}
private fun getNewFieldName(oldName: String, originalField: Boolean): String {
if (THIS_0 == oldName) {
if (AsmUtil.CAPTURED_THIS_FIELD == oldName) {
return if (!originalField) {
oldName
}
@@ -25,9 +25,7 @@ import org.jetbrains.kotlin.config.isReleaseCoroutines
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.isInlineOnly
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtCallableReferenceExpression
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtPsiUtil
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.renderer.DescriptorRenderer
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils
@@ -769,7 +767,8 @@ class PsiInlineCodegen(
assert(isInlinableParameterExpression(ktLambda)) { "Couldn't find inline expression in ${expression.text}" }
return PsiExpressionLambda(
ktLambda!!, typeMapper, parameter.isCrossinline, getBoundCallableReferenceReceiver(expression) != null
ktLambda!!, typeMapper, state.languageVersionSettings,
parameter.isCrossinline, getBoundCallableReferenceReceiver(expression) != null
).also { lambda ->
val closureInfo = invocationParamBuilder.addNextValueParameter(type, true, null, parameter.index)
closureInfo.lambda = lambda
@@ -34,7 +34,7 @@ class InlinedLambdaRemapper(
isDefaultBoundCallableReference && fieldName == AsmUtil.BOUND_REFERENCE_RECEIVER && fieldOwner == originalLambdaInternalName
override fun getFieldNameForFolding(insnNode: FieldInsnNode): String =
if (isMyBoundReceiverForDefaultLambda(insnNode.owner, insnNode.name)) AsmUtil.RECEIVER_NAME else insnNode.name
if (isMyBoundReceiverForDefaultLambda(insnNode.owner, insnNode.name)) AsmUtil.RECEIVER_PARAMETER_NAME else insnNode.name
override fun findField(fieldInsnNode: FieldInsnNode, captured: Collection<CapturedParamInfo>) =
parent!!.findField(fieldInsnNode, captured)
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.codegen.binding.CodegenBinding.*
import org.jetbrains.kotlin.codegen.binding.MutableClosure
import org.jetbrains.kotlin.codegen.context.EnclosedValueDescriptor
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.psi.KtCallableReferenceExpression
@@ -144,7 +145,7 @@ class DefaultLambda(
if (isFunctionReference || isPropertyReference)
constructor?.desc?.let { Type.getArgumentTypes(it) }?.singleOrNull()?.let {
originalBoundReceiverType = it
listOf(capturedParamDesc(AsmUtil.RECEIVER_NAME, it.boxReceiverForBoundReference()))
listOf(capturedParamDesc(AsmUtil.RECEIVER_PARAMETER_NAME, it.boxReceiverForBoundReference()))
} ?: emptyList()
else
constructor?.findCapturedFieldAssignmentInstructions()?.map { fieldNode ->
@@ -197,6 +198,7 @@ abstract class ExpressionLambda(protected val typeMapper: KotlinTypeMapper, isCr
class PsiExpressionLambda(
expression: KtExpression,
typeMapper: KotlinTypeMapper,
languageVersionSettings: LanguageVersionSettings,
isCrossInline: Boolean,
override val isBoundCallableReference: Boolean
) : ExpressionLambda(typeMapper, isCrossInline) {
@@ -266,9 +268,11 @@ class PsiExpressionLambda(
val type = typeMapper.mapType(closure.capturedReceiverFromOuterContext!!).let {
if (isBoundCallableReference) it.boxReceiverForBoundReference() else it
}
val fieldName = closure.getCapturedReceiverFieldName(typeMapper.bindingContext, languageVersionSettings)
val descriptor = EnclosedValueDescriptor(
AsmUtil.CAPTURED_RECEIVER_FIELD, null,
StackValue.field(type, lambdaClassType, AsmUtil.CAPTURED_RECEIVER_FIELD, false, StackValue.LOCAL_0),
fieldName, null,
StackValue.field(type, lambdaClassType, fieldName, false, StackValue.LOCAL_0),
type
)
add(getCapturedParamInfo(descriptor))
@@ -328,7 +328,7 @@ class MethodInliner(
resultNode.desc.endsWith(")" + languageVersionSettings.continuationAsmType().descriptor)
for (capturedParamDesc in info.allRecapturedParameters) {
if (capturedParamDesc.fieldName == THIS && isContinuationCreate) {
if (capturedParamDesc.fieldName == AsmUtil.THIS && isContinuationCreate) {
// Common inliner logic doesn't support cases when transforming anonymous object can
// be instantiated by itself.
// To support such cases workaround with 'oldInfo' is used.
@@ -336,7 +336,7 @@ class MethodInliner(
// 'This' in outer context corresponds to outer instance in current
visitFieldInsn(
Opcodes.GETSTATIC, owner,
CAPTURED_FIELD_FOLD_PREFIX + THIS_0, capturedParamDesc.type.descriptor
CAPTURED_FIELD_FOLD_PREFIX + AsmUtil.CAPTURED_THIS_FIELD, capturedParamDesc.type.descriptor
)
} else {
visitFieldInsn(
@@ -948,6 +948,7 @@ class MethodInliner(
private fun analyzeMethodNodeBeforeInline(node: MethodNode): Array<Frame<SourceValue>?> {
val analyzer = object : Analyzer<SourceValue>(SourceInterpreter()) {
override fun newFrame(nLocals: Int, nStack: Int): Frame<SourceValue> {
return object : Frame<SourceValue>(nLocals, nStack) {
@Throws(AnalyzerException::class)
override fun execute(insn: AbstractInsnNode, interpreter: Interpreter<SourceValue>) {
@@ -16,6 +16,8 @@
package org.jetbrains.kotlin.codegen.inline
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.AsmUtil.THIS
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
@@ -65,7 +67,7 @@ class RegeneratedLambdaFieldRemapper(
val field = findFieldInSuper(fin) ?:
//search in parent
findFieldInSuper(FieldInsnNode(
Opcodes.GETSTATIC, originalLambdaInternalName, THIS_0,
Opcodes.GETSTATIC, originalLambdaInternalName, AsmUtil.CAPTURED_THIS_FIELD,
Type.getObjectType(parent!!.originalLambdaInternalName!!).descriptor
))?.also { fromParent = true } ?:
throw AssertionError("Couldn't find captured this $originalLambdaInternalName for $fieldName")
@@ -60,8 +60,6 @@ const val API = Opcodes.ASM5
const val NUMBERED_FUNCTION_PREFIX = "kotlin/jvm/functions/Function"
const val INLINE_FUN_VAR_SUFFIX = "\$iv"
internal const val THIS = "this"
internal const val THIS_0 = "this$0"
internal const val FIRST_FUN_LABEL = "$$$$\$ROOT$$$$$"
internal const val SPECIAL_TRANSFORMATION_NAME = "\$special"
const val INLINE_TRANSFORMATION_SUFFIX = "\$inlined"
@@ -70,7 +68,6 @@ internal const val INLINE_FUN_THIS_0_SUFFIX = "\$inline_fun"
internal const val DEFAULT_LAMBDA_FAKE_CALL = "$$\$DEFAULT_LAMBDA_FAKE_CALL$$$"
internal const val CAPTURED_FIELD_FOLD_PREFIX = "$$$"
private const val RECEIVER_0 = "receiver$0"
private const val NON_LOCAL_RETURN = "$$$$\$NON_LOCAL_RETURN$$$$$"
private const val CAPTURED_FIELD_PREFIX = "$"
private const val NON_CAPTURED_FIELD_PREFIX = "$$"
@@ -249,9 +246,9 @@ private fun String.isInteger(radix: Int = 10) = toIntOrNull(radix) != null
internal fun isCapturedFieldName(fieldName: String): Boolean {
// TODO: improve this heuristic
return fieldName.startsWith(CAPTURED_FIELD_PREFIX) && !fieldName.startsWith(NON_CAPTURED_FIELD_PREFIX) ||
THIS_0 == fieldName ||
RECEIVER_0 == fieldName
return fieldName.startsWith(CAPTURED_FIELD_PREFIX) && !fieldName.startsWith(NON_CAPTURED_FIELD_PREFIX)
|| AsmUtil.CAPTURED_THIS_FIELD == fieldName
|| AsmUtil.CAPTURED_RECEIVER_FIELD == fieldName
}
internal fun isReturnOpcode(opcode: Int) = opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN
@@ -521,7 +518,7 @@ fun isFakeLocalVariableForInline(name: String): Boolean {
return name.startsWith(JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_FUNCTION) || name.startsWith(JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_ARGUMENT)
}
internal fun isThis0(name: String): Boolean = THIS_0 == name
internal fun isThis0(name: String): Boolean = AsmUtil.CAPTURED_THIS_FIELD == name
internal fun isSpecialEnumMethod(functionDescriptor: FunctionDescriptor): Boolean {
val containingDeclaration = functionDescriptor.containingDeclaration as? PackageFragmentDescriptor ?: return false
@@ -9,7 +9,7 @@ package org.jetbrains.kotlin.resolve.jvm.checkers
fun isValidDalvikIdentifier(identifier: String) = identifier.all { isValidDalvikCharacter(it) }
// https://source.android.com/devices/tech/dalvik/dex-format.html#string-syntax
private fun isValidDalvikCharacter(c: Char) = when (c) {
fun isValidDalvikCharacter(c: Char) = when (c) {
in 'A'..'Z' -> true
in 'a'..'z' -> true
in '0'..'9' -> true
@@ -0,0 +1,17 @@
// LOCAL_VARIABLE_TABLE
fun String.foo(count: Int) {
val x = false
block {
val y = false
block {
val z = true
block {
this@foo + this@block.toString() + x + y + z + count
}
}
}
}
inline fun block(block: Long.() -> Unit) = 5L.block()
@@ -0,0 +1,25 @@
public final class DeepInlineKt : java/lang/Object {
public final static void block(kotlin.jvm.functions.Function1 block) {
Local variables:
0 block: Lkotlin/jvm/functions/Function1;
1 $i$f$block: I
}
public final static void foo(java.lang.String $receiver, int $i$a$1$block) {
Local variables:
9 $receiver: J
11 $i$a$1$block: I
12 $i$f$block: I
8 z: Z
6 $receiver: J
13 $i$a$1$block: I
14 $i$f$block: I
5 y: Z
3 $receiver: J
15 $i$a$1$block: I
16 $i$f$block: I
2 x: Z
0 $receiver: Ljava/lang/String;
1 count: I
}
}
@@ -0,0 +1,17 @@
// LOCAL_VARIABLE_TABLE
fun String.foo(count: Int) {
val x = false
block b1@ {
val y = false
block b2@ {
val z = true
block b3@ {
this@foo + this@b1 + this@b2 + this@b3 + x + y + z + count
}
}
}
}
inline fun block(block: Long.() -> Unit) = 5L.block()
@@ -0,0 +1,25 @@
public final class DeepInlineWithLabelsKt : java/lang/Object {
public final static void block(kotlin.jvm.functions.Function1 block) {
Local variables:
0 block: Lkotlin/jvm/functions/Function1;
1 $i$f$block: I
}
public final static void foo(java.lang.String $receiver, int $i$a$1$block) {
Local variables:
9 $receiver: J
11 $i$a$1$block: I
12 $i$f$block: I
8 z: Z
6 $receiver: J
13 $i$a$1$block: I
14 $i$f$block: I
5 y: Z
3 $receiver: J
15 $i$a$1$block: I
16 $i$f$block: I
2 x: Z
0 $receiver: Ljava/lang/String;
1 count: I
}
}
@@ -0,0 +1,18 @@
// LOCAL_VARIABLE_TABLE
// LANGUAGE_VERSION: 1.3
fun String.foo(count: Int) {
val x = false
block b1@ {
val y = false
block b2@ {
val z = true
block b3@ {
this@foo + this@b1 + this@b2 + this@b3 + x + y + z + count
}
}
}
}
fun block(block: Long.() -> Unit) = 5L.block()
@@ -0,0 +1,69 @@
final class DeepNoinlineWithLabels_afterKt$foo$1$1$1 : kotlin/jvm/internal/Lambda, kotlin/jvm/functions/Function1 {
final long $this_b2
final boolean $z
final DeepNoinlineWithLabels_afterKt$foo$1$1 this$0
void <init>(DeepNoinlineWithLabels_afterKt$foo$1$1 p0, long p1, boolean p2)
public java.lang.Object invoke(java.lang.Object p0)
public final void invoke(long $receiver) {
Local variables:
0 this: LDeepNoinlineWithLabels_afterKt$foo$1$1$1;
1 $receiver: J
}
}
final class DeepNoinlineWithLabels_afterKt$foo$1$1 : kotlin/jvm/internal/Lambda, kotlin/jvm/functions/Function1 {
final long $this_b1
final boolean $y
final DeepNoinlineWithLabels_afterKt$foo$1 this$0
void <init>(DeepNoinlineWithLabels_afterKt$foo$1 p0, long p1, boolean p2)
public java.lang.Object invoke(java.lang.Object p0)
public final void invoke(long this) {
Local variables:
3 z: Z
0 this: LDeepNoinlineWithLabels_afterKt$foo$1$1;
1 $receiver: J
}
}
final class DeepNoinlineWithLabels_afterKt$foo$1 : kotlin/jvm/internal/Lambda, kotlin/jvm/functions/Function1 {
final int $count
final java.lang.String $this_foo
final boolean $x
void <init>(java.lang.String p0, boolean p1, int p2)
public java.lang.Object invoke(java.lang.Object p0)
public final void invoke(long this) {
Local variables:
3 y: Z
0 this: LDeepNoinlineWithLabels_afterKt$foo$1;
1 $receiver: J
}
}
public final class DeepNoinlineWithLabels_afterKt : java/lang/Object {
public final static void block(kotlin.jvm.functions.Function1 block) {
Local variables:
0 block: Lkotlin/jvm/functions/Function1;
}
public final static void foo(java.lang.String x, int $receiver) {
Local variables:
2 x: Z
0 $receiver: Ljava/lang/String;
1 count: I
}
}
@@ -0,0 +1,18 @@
// !LANGUAGE: -NewCapturedReceiverFieldNamingConvention
// LOCAL_VARIABLE_TABLE
fun String.foo(count: Int) {
val x = false
block b1@ {
val y = false
block b2@ {
val z = true
block b3@ {
this@foo + this@b1 + this@b2 + this@b3 + x + y + z + count
}
}
}
}
fun block(block: Long.() -> Unit) = 5L.block()
@@ -0,0 +1,69 @@
final class DeepNoinlineWithLabels_beforeKt$foo$1$1$1 : kotlin/jvm/internal/Lambda, kotlin/jvm/functions/Function1 {
final boolean $z
final long receiver$0
final DeepNoinlineWithLabels_beforeKt$foo$1$1 this$0
void <init>(DeepNoinlineWithLabels_beforeKt$foo$1$1 p0, long p1, boolean p2)
public java.lang.Object invoke(java.lang.Object p0)
public final void invoke(long $receiver) {
Local variables:
0 this: LDeepNoinlineWithLabels_beforeKt$foo$1$1$1;
1 $receiver: J
}
}
final class DeepNoinlineWithLabels_beforeKt$foo$1$1 : kotlin/jvm/internal/Lambda, kotlin/jvm/functions/Function1 {
final boolean $y
final long receiver$0
final DeepNoinlineWithLabels_beforeKt$foo$1 this$0
void <init>(DeepNoinlineWithLabels_beforeKt$foo$1 p0, long p1, boolean p2)
public java.lang.Object invoke(java.lang.Object p0)
public final void invoke(long this) {
Local variables:
3 z: Z
0 this: LDeepNoinlineWithLabels_beforeKt$foo$1$1;
1 $receiver: J
}
}
final class DeepNoinlineWithLabels_beforeKt$foo$1 : kotlin/jvm/internal/Lambda, kotlin/jvm/functions/Function1 {
final int $count
final boolean $x
final java.lang.String receiver$0
void <init>(java.lang.String p0, boolean p1, int p2)
public java.lang.Object invoke(java.lang.Object p0)
public final void invoke(long this) {
Local variables:
3 y: Z
0 this: LDeepNoinlineWithLabels_beforeKt$foo$1;
1 $receiver: J
}
}
public final class DeepNoinlineWithLabels_beforeKt : java/lang/Object {
public final static void block(kotlin.jvm.functions.Function1 block) {
Local variables:
0 block: Lkotlin/jvm/functions/Function1;
}
public final static void foo(java.lang.String x, int $receiver) {
Local variables:
2 x: Z
0 $receiver: Ljava/lang/String;
1 count: I
}
}
@@ -0,0 +1,18 @@
// LOCAL_VARIABLE_TABLE
// LANGUAGE_VERSION: 1.3
fun String.foo(count: Int) {
val x = false
block {
val y = false
block {
val z = true
block {
this@foo + this@block.toString() + x + y + z + count
}
}
}
}
fun block(block: Long.() -> Unit) = 5L.block()
@@ -0,0 +1,65 @@
final class DeepNoinline_afterKt$foo$1$1$1 : kotlin/jvm/internal/Lambda, kotlin/jvm/functions/Function1 {
final boolean $z
final DeepNoinline_afterKt$foo$1$1 this$0
void <init>(DeepNoinline_afterKt$foo$1$1 p0, boolean p1)
public java.lang.Object invoke(java.lang.Object p0)
public final void invoke(long $receiver) {
Local variables:
0 this: LDeepNoinline_afterKt$foo$1$1$1;
1 $receiver: J
}
}
final class DeepNoinline_afterKt$foo$1$1 : kotlin/jvm/internal/Lambda, kotlin/jvm/functions/Function1 {
final boolean $y
final DeepNoinline_afterKt$foo$1 this$0
void <init>(DeepNoinline_afterKt$foo$1 p0, boolean p1)
public java.lang.Object invoke(java.lang.Object p0)
public final void invoke(long this) {
Local variables:
3 z: Z
0 this: LDeepNoinline_afterKt$foo$1$1;
1 $receiver: J
}
}
final class DeepNoinline_afterKt$foo$1 : kotlin/jvm/internal/Lambda, kotlin/jvm/functions/Function1 {
final int $count
final java.lang.String $this_foo
final boolean $x
void <init>(java.lang.String p0, boolean p1, int p2)
public java.lang.Object invoke(java.lang.Object p0)
public final void invoke(long this) {
Local variables:
3 y: Z
0 this: LDeepNoinline_afterKt$foo$1;
1 $receiver: J
}
}
public final class DeepNoinline_afterKt : java/lang/Object {
public final static void block(kotlin.jvm.functions.Function1 block) {
Local variables:
0 block: Lkotlin/jvm/functions/Function1;
}
public final static void foo(java.lang.String x, int $receiver) {
Local variables:
2 x: Z
0 $receiver: Ljava/lang/String;
1 count: I
}
}
@@ -0,0 +1,18 @@
// !LANGUAGE: -NewCapturedReceiverFieldNamingConvention
// LOCAL_VARIABLE_TABLE
fun String.foo(count: Int) {
val x = false
block {
val y = false
block {
val z = true
block {
this@foo + this@block.toString() + x + y + z + count
}
}
}
}
fun block(block: Long.() -> Unit) = 5L.block()
@@ -0,0 +1,65 @@
final class DeepNoinline_beforeKt$foo$1$1$1 : kotlin/jvm/internal/Lambda, kotlin/jvm/functions/Function1 {
final boolean $z
final DeepNoinline_beforeKt$foo$1$1 this$0
void <init>(DeepNoinline_beforeKt$foo$1$1 p0, boolean p1)
public java.lang.Object invoke(java.lang.Object p0)
public final void invoke(long $receiver) {
Local variables:
0 this: LDeepNoinline_beforeKt$foo$1$1$1;
1 $receiver: J
}
}
final class DeepNoinline_beforeKt$foo$1$1 : kotlin/jvm/internal/Lambda, kotlin/jvm/functions/Function1 {
final boolean $y
final DeepNoinline_beforeKt$foo$1 this$0
void <init>(DeepNoinline_beforeKt$foo$1 p0, boolean p1)
public java.lang.Object invoke(java.lang.Object p0)
public final void invoke(long this) {
Local variables:
3 z: Z
0 this: LDeepNoinline_beforeKt$foo$1$1;
1 $receiver: J
}
}
final class DeepNoinline_beforeKt$foo$1 : kotlin/jvm/internal/Lambda, kotlin/jvm/functions/Function1 {
final int $count
final boolean $x
final java.lang.String receiver$0
void <init>(java.lang.String p0, boolean p1, int p2)
public java.lang.Object invoke(java.lang.Object p0)
public final void invoke(long this) {
Local variables:
3 y: Z
0 this: LDeepNoinline_beforeKt$foo$1;
1 $receiver: J
}
}
public final class DeepNoinline_beforeKt : java/lang/Object {
public final static void block(kotlin.jvm.functions.Function1 block) {
Local variables:
0 block: Lkotlin/jvm/functions/Function1;
}
public final static void foo(java.lang.String x, int $receiver) {
Local variables:
2 x: Z
0 $receiver: Ljava/lang/String;
1 count: I
}
}
@@ -0,0 +1,25 @@
// LOCAL_VARIABLE_TABLE
class Foo {
fun foo() {
block {
this@Foo
}
}
inner class Bar {
fun bar() {
block {
this@Foo
this@Bar
block {
this@Foo
this@Bar
}
}
}
}
}
inline fun block(block: () -> Unit) = block()
@@ -0,0 +1,40 @@
public final class Foo$Bar : java/lang/Object {
final Foo this$0
public void <init>(Foo $outer) {
Local variables:
0 this: LFoo$Bar;
1 $outer: LFoo;
}
public final void bar() {
Local variables:
1 $i$a$1$block: I
2 $i$f$block: I
3 $i$a$1$block: I
4 $i$f$block: I
0 this: LFoo$Bar;
}
}
public final class Foo : java/lang/Object {
public void <init>() {
Local variables:
0 this: LFoo;
}
public final void foo() {
Local variables:
1 $i$a$1$block: I
2 $i$f$block: I
0 this: LFoo;
}
}
public final class InlineClassCaptureKt : java/lang/Object {
public final static void block(kotlin.jvm.functions.Function0 block) {
Local variables:
0 block: Lkotlin/jvm/functions/Function0;
1 $i$f$block: I
}
}
@@ -0,0 +1,11 @@
// LOCAL_VARIABLE_TABLE
fun String.foo(count: Int) {
val x: Boolean = false
block {
this@foo + this@block.toString() + x.toString() + count.toString()
}
}
inline fun block(block: Long.() -> Unit) = 5L.block()
@@ -0,0 +1,17 @@
public final class InlineReceiversKt : java/lang/Object {
public final static void block(kotlin.jvm.functions.Function1 block) {
Local variables:
0 block: Lkotlin/jvm/functions/Function1;
1 $i$f$block: I
}
public final static void foo(java.lang.String $receiver, int $i$a$1$block) {
Local variables:
3 $receiver: J
5 $i$a$1$block: I
6 $i$f$block: I
2 x: Z
0 $receiver: Ljava/lang/String;
1 count: I
}
}
@@ -0,0 +1,3 @@
class Foo {
inner class Bar
}
@@ -0,0 +1,9 @@
public final class Foo$Bar : java/lang/Object {
final Foo this$0
public void <init>(Foo $outer)
}
public final class Foo : java/lang/Object {
public void <init>()
}
@@ -0,0 +1,11 @@
// LOCAL_VARIABLE_TABLE
fun String.foo(count: Int) {
val x = false
block {
this@foo + this@block.toString() + x.toString() + count.toString()
}
}
fun block(block: Long.() -> Unit) = 5L.block()
@@ -0,0 +1,31 @@
final class NonInlineReceivers_afterKt$foo$1 : kotlin/jvm/internal/Lambda, kotlin/jvm/functions/Function1 {
final int $count
final java.lang.String $this_foo
final boolean $x
void <init>(java.lang.String p0, boolean p1, int p2)
public java.lang.Object invoke(java.lang.Object p0)
public final void invoke(long $receiver) {
Local variables:
0 this: LNonInlineReceivers_afterKt$foo$1;
1 $receiver: J
}
}
public final class NonInlineReceivers_afterKt : java/lang/Object {
public final static void block(kotlin.jvm.functions.Function1 block) {
Local variables:
0 block: Lkotlin/jvm/functions/Function1;
}
public final static void foo(java.lang.String x, int $receiver) {
Local variables:
2 x: Z
0 $receiver: Ljava/lang/String;
1 count: I
}
}
@@ -0,0 +1,12 @@
// !LANGUAGE: -NewCapturedReceiverFieldNamingConvention
// LOCAL_VARIABLE_TABLE
fun String.foo(count: Int) {
val x = false
block {
this@foo + this@block.toString() + x.toString() + count.toString()
}
}
fun block(block: Long.() -> Unit) = 5L.block()
@@ -0,0 +1,31 @@
final class NonInlineReceivers_beforeKt$foo$1 : kotlin/jvm/internal/Lambda, kotlin/jvm/functions/Function1 {
final int $count
final boolean $x
final java.lang.String receiver$0
void <init>(java.lang.String p0, boolean p1, int p2)
public java.lang.Object invoke(java.lang.Object p0)
public final void invoke(long $receiver) {
Local variables:
0 this: LNonInlineReceivers_beforeKt$foo$1;
1 $receiver: J
}
}
public final class NonInlineReceivers_beforeKt : java/lang/Object {
public final static void block(kotlin.jvm.functions.Function1 block) {
Local variables:
0 block: Lkotlin/jvm/functions/Function1;
}
public final static void foo(java.lang.String x, int $receiver) {
Local variables:
2 x: Z
0 $receiver: Ljava/lang/String;
1 count: I
}
}
@@ -0,0 +1 @@
fun String.foo(a: Int) {}
@@ -0,0 +1,3 @@
public final class SimpleKt : java/lang/Object {
public final static void foo(java.lang.String $receiver, int a)
}
@@ -34,7 +34,7 @@ public final class CrossinlineKt$box$1$filter$$inlined$source$1$lambda$1$1 {
@kotlin.Metadata
public final class CrossinlineKt$box$1$filter$$inlined$source$1$lambda$1 {
synthetic final field receiver$0$inlined: Sink
synthetic final field $this_source$inlined: Sink
synthetic final field this$0: CrossinlineKt$box$1$filter$$inlined$source$1
inner class CrossinlineKt$box$1$filter$$inlined$source$1$lambda$1
inner class CrossinlineKt$box$1$filter$$inlined$source$1$lambda$1$1
@@ -46,7 +46,7 @@ public final class CrossinlineKt$box$1$filter$$inlined$source$1$lambda$1 {
@kotlin.Metadata
public final class CrossinlineKt$box$1$filter$$inlined$source$1 {
synthetic final field $predicate$inlined: kotlin.jvm.functions.Function1
synthetic final field receiver$0$inlined: SourceCrossinline
synthetic final field $this_filter$inlined: SourceCrossinline
inner class CrossinlineKt$box$1$filter$$inlined$source$1
inner class CrossinlineKt$box$1$filter$$inlined$source$1$1
public method <init>(p0: SourceCrossinline, p1: kotlin.jvm.functions.Function1): void
@@ -111,7 +111,7 @@ public final class CrossinlineKt$box$1$invokeSuspend$$inlined$filter$1$2$1 {
@kotlin.Metadata
public final class CrossinlineKt$box$1$invokeSuspend$$inlined$filter$1$2 {
synthetic final field receiver$0$inlined: Sink
synthetic final field $this_source$inlined: Sink
synthetic final field this$0: CrossinlineKt$box$1$invokeSuspend$$inlined$filter$1
inner class CrossinlineKt$box$1$invokeSuspend$$inlined$filter$1$2
inner class CrossinlineKt$box$1$invokeSuspend$$inlined$filter$1$2$1
@@ -122,7 +122,7 @@ public final class CrossinlineKt$box$1$invokeSuspend$$inlined$filter$1$2 {
@kotlin.Metadata
public final class CrossinlineKt$box$1$invokeSuspend$$inlined$filter$1 {
synthetic final field receiver$0$inlined: SourceCrossinline
synthetic final field $this_filter$inlined: SourceCrossinline
inner class CrossinlineKt$box$1$invokeSuspend$$inlined$filter$1
inner class CrossinlineKt$box$1$invokeSuspend$$inlined$filter$1$1
public method <init>(p0: SourceCrossinline): void
@@ -213,7 +213,7 @@ public final class CrossinlineKt$filter$$inlined$source$1$lambda$1$1 {
@kotlin.Metadata
public final class CrossinlineKt$filter$$inlined$source$1$lambda$1 {
synthetic final field receiver$0$inlined: Sink
synthetic final field $this_source$inlined: Sink
synthetic final field this$0: CrossinlineKt$filter$$inlined$source$1
inner class CrossinlineKt$filter$$inlined$source$1$lambda$1
inner class CrossinlineKt$filter$$inlined$source$1$lambda$1$1
@@ -225,7 +225,7 @@ public final class CrossinlineKt$filter$$inlined$source$1$lambda$1 {
@kotlin.Metadata
public final class CrossinlineKt$filter$$inlined$source$1 {
synthetic final field $predicate$inlined: kotlin.jvm.functions.Function1
synthetic final field receiver$0$inlined: SourceCrossinline
synthetic final field $this_filter$inlined: SourceCrossinline
inner class CrossinlineKt$filter$$inlined$source$1
inner class CrossinlineKt$filter$$inlined$source$1$1
public method <init>(p0: SourceCrossinline, p1: kotlin.jvm.functions.Function1): void
@@ -34,7 +34,7 @@ public final class CrossinlineKt$box$1$filter$$inlined$source$1$lambda$1$1 {
@kotlin.Metadata
public final class CrossinlineKt$box$1$filter$$inlined$source$1$lambda$1 {
synthetic final field receiver$0$inlined: Sink
synthetic final field $this_source$inlined: Sink
synthetic final field this$0: CrossinlineKt$box$1$filter$$inlined$source$1
inner class CrossinlineKt$box$1$filter$$inlined$source$1$lambda$1
inner class CrossinlineKt$box$1$filter$$inlined$source$1$lambda$1$1
@@ -46,7 +46,7 @@ public final class CrossinlineKt$box$1$filter$$inlined$source$1$lambda$1 {
@kotlin.Metadata
public final class CrossinlineKt$box$1$filter$$inlined$source$1 {
synthetic final field $predicate$inlined: kotlin.jvm.functions.Function1
synthetic final field receiver$0$inlined: SourceCrossinline
synthetic final field $this_filter$inlined: SourceCrossinline
inner class CrossinlineKt$box$1$filter$$inlined$source$1
inner class CrossinlineKt$box$1$filter$$inlined$source$1$1
public method <init>(p0: SourceCrossinline, p1: kotlin.jvm.functions.Function1): void
@@ -111,7 +111,7 @@ public final class CrossinlineKt$box$1$invokeSuspend$$inlined$filter$1$2$1 {
@kotlin.Metadata
public final class CrossinlineKt$box$1$invokeSuspend$$inlined$filter$1$2 {
synthetic final field receiver$0$inlined: Sink
synthetic final field $this_source$inlined: Sink
synthetic final field this$0: CrossinlineKt$box$1$invokeSuspend$$inlined$filter$1
inner class CrossinlineKt$box$1$invokeSuspend$$inlined$filter$1$2
inner class CrossinlineKt$box$1$invokeSuspend$$inlined$filter$1$2$1
@@ -122,7 +122,7 @@ public final class CrossinlineKt$box$1$invokeSuspend$$inlined$filter$1$2 {
@kotlin.Metadata
public final class CrossinlineKt$box$1$invokeSuspend$$inlined$filter$1 {
synthetic final field receiver$0$inlined: SourceCrossinline
synthetic final field $this_filter$inlined: SourceCrossinline
inner class CrossinlineKt$box$1$invokeSuspend$$inlined$filter$1
inner class CrossinlineKt$box$1$invokeSuspend$$inlined$filter$1$1
public method <init>(p0: SourceCrossinline): void
@@ -213,7 +213,7 @@ public final class CrossinlineKt$filter$$inlined$source$1$lambda$1$1 {
@kotlin.Metadata
public final class CrossinlineKt$filter$$inlined$source$1$lambda$1 {
synthetic final field receiver$0$inlined: Sink
synthetic final field $this_source$inlined: Sink
synthetic final field this$0: CrossinlineKt$filter$$inlined$source$1
inner class CrossinlineKt$filter$$inlined$source$1$lambda$1
inner class CrossinlineKt$filter$$inlined$source$1$lambda$1$1
@@ -225,7 +225,7 @@ public final class CrossinlineKt$filter$$inlined$source$1$lambda$1 {
@kotlin.Metadata
public final class CrossinlineKt$filter$$inlined$source$1 {
synthetic final field $predicate$inlined: kotlin.jvm.functions.Function1
synthetic final field receiver$0$inlined: SourceCrossinline
synthetic final field $this_filter$inlined: SourceCrossinline
inner class CrossinlineKt$filter$$inlined$source$1
inner class CrossinlineKt$filter$$inlined$source$1$1
public method <init>(p0: SourceCrossinline, p1: kotlin.jvm.functions.Function1): void
@@ -6,5 +6,5 @@ public fun IntArray.asIterable(): Iterable<Int> {
return Iterable { this.iterator() }
}
/*Threre are two constuctors so we should be sure that we check required one by checking 'receiver$0$inlined' assign*/
// 1 <init>\(\[I\)V\s+L0\s+ALOAD 0\s+ALOAD 1\s+PUTFIELD InlinedConstuctorKt\$asIterable\$\$inlined\$Iterable\$1\.receiver\$0\$inlined : \[I
// 1 <init>\(\[I\)V\s+L0\s+ALOAD 0\s+ALOAD 1\s+PUTFIELD InlinedConstuctorKt\$asIterable\$\$inlined\$Iterable\$1\.\$this_asIterable\$inlined : \[I
// 1 LOCALVARIABLE this LInlinedConstuctorKt\$asIterable\$\$inlined\$Iterable\$1; L0 L2 0
@@ -0,0 +1,104 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.codegen;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.TargetBackend;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("compiler/testData/codegen/asmLike")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class AsmLikeInstructionListingTestGenerated extends AbstractAsmLikeInstructionListingTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
}
public void testAllFilesPresentInAsmLike() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/asmLike"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
}
@TestMetadata("compiler/testData/codegen/asmLike/receiverMangling")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ReceiverMangling extends AbstractAsmLikeInstructionListingTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
}
public void testAllFilesPresentInReceiverMangling() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/asmLike/receiverMangling"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
}
@TestMetadata("deepInline.kt")
public void testDeepInline() throws Exception {
runTest("compiler/testData/codegen/asmLike/receiverMangling/deepInline.kt");
}
@TestMetadata("deepInlineWithLabels.kt")
public void testDeepInlineWithLabels() throws Exception {
runTest("compiler/testData/codegen/asmLike/receiverMangling/deepInlineWithLabels.kt");
}
@TestMetadata("deepNoinlineWithLabels_after.kt")
public void testDeepNoinlineWithLabels_after() throws Exception {
runTest("compiler/testData/codegen/asmLike/receiverMangling/deepNoinlineWithLabels_after.kt");
}
@TestMetadata("deepNoinlineWithLabels_before.kt")
public void testDeepNoinlineWithLabels_before() throws Exception {
runTest("compiler/testData/codegen/asmLike/receiverMangling/deepNoinlineWithLabels_before.kt");
}
@TestMetadata("deepNoinline_after.kt")
public void testDeepNoinline_after() throws Exception {
runTest("compiler/testData/codegen/asmLike/receiverMangling/deepNoinline_after.kt");
}
@TestMetadata("deepNoinline_before.kt")
public void testDeepNoinline_before() throws Exception {
runTest("compiler/testData/codegen/asmLike/receiverMangling/deepNoinline_before.kt");
}
@TestMetadata("inlineClassCapture.kt")
public void testInlineClassCapture() throws Exception {
runTest("compiler/testData/codegen/asmLike/receiverMangling/inlineClassCapture.kt");
}
@TestMetadata("inlineReceivers.kt")
public void testInlineReceivers() throws Exception {
runTest("compiler/testData/codegen/asmLike/receiverMangling/inlineReceivers.kt");
}
@TestMetadata("innerClass.kt")
public void testInnerClass() throws Exception {
runTest("compiler/testData/codegen/asmLike/receiverMangling/innerClass.kt");
}
@TestMetadata("nonInlineReceivers_after.kt")
public void testNonInlineReceivers_after() throws Exception {
runTest("compiler/testData/codegen/asmLike/receiverMangling/nonInlineReceivers_after.kt");
}
@TestMetadata("nonInlineReceivers_before.kt")
public void testNonInlineReceivers_before() throws Exception {
runTest("compiler/testData/codegen/asmLike/receiverMangling/nonInlineReceivers_before.kt");
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("compiler/testData/codegen/asmLike/receiverMangling/simple.kt");
}
}
}
@@ -152,6 +152,10 @@ fun main(args: Array<String>) {
model("codegen/kapt", targetBackend = TargetBackend.JVM)
}
testClass<AbstractAsmLikeInstructionListingTest> {
model("codegen/asmLike", targetBackend = TargetBackend.JVM)
}
testClass<AbstractBlackBoxInlineCodegenTest> {
model("codegen/boxInline")
}
@@ -87,6 +87,7 @@ enum class LanguageFeature(
SoundSmartcastFromLoopConditionForLoopAssignedVariables(KOTLIN_1_3, kind = BUG_FIX),
DslMarkerOnFunctionTypeReceiver(KOTLIN_1_4, kind = BUG_FIX),
ProhibitErroneousExpressionsInAnnotationsWithUseSiteTargets(KOTLIN_1_3, kind = BUG_FIX),
NewCapturedReceiverFieldNamingConvention(KOTLIN_1_3, kind = BUG_FIX),
RestrictReturnStatementTarget(KOTLIN_1_4, kind = BUG_FIX),
NoConstantValueAttributeForNonConstVals(KOTLIN_1_4, kind = BUG_FIX),
@@ -50,4 +50,7 @@ object NameUtils {
@JvmStatic
fun getScriptNameForFile(filePath: String): Name =
Name.identifier(NameUtils.getPackagePartClassNamePrefix(filePath.substringAfterLast('/').substringBeforeLast('.')))
@JvmStatic
fun hasName(name: Name) = name != SpecialNames.NO_NAME_PROVIDED && name != SpecialNames.ANONYMOUS_FUNCTION
}