Introduce local variable type checker.
CheckLocalVariablesTableTests will now check the validity of the locals table against types of locals computed based on the bytecode. These checks and the new destructuringInFor test act as a regression test for the changes in https://github.com/JetBrains/kotlin/pull/2613 These checks also caught a similar issue for destructuring lambda parameters, where the local is introduced before the value has been written to the local slot. This change also fixes that. Finally, this change fixes the asmLike tests to correctly look up the name of parameters in the locals table.
This commit is contained in:
@@ -27,7 +27,8 @@ class ClosureGenerationStrategy(
|
||||
) : FunctionGenerationStrategy.FunctionDefault(state, declaration) {
|
||||
|
||||
override fun doGenerateBody(codegen: ExpressionCodegen, signature: JvmMethodSignature) {
|
||||
initializeVariablesForDestructuredLambdaParameters(codegen, codegen.context.functionDescriptor.valueParameters)
|
||||
initializeVariablesForDestructuredLambdaParameters(
|
||||
codegen, codegen.context.functionDescriptor.valueParameters, codegen.context.methodEndLabel)
|
||||
if (declaration is KtFunctionLiteral) {
|
||||
recordCallLabelForLambdaArgument(declaration, state.bindingTrace)
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotated;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl;
|
||||
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature;
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||
import org.jetbrains.kotlin.load.java.SpecialBuiltinMembers;
|
||||
@@ -767,7 +766,7 @@ public class FunctionCodegen {
|
||||
generateLocalVariablesForParameters(mv,
|
||||
jvmMethodSignature, functionDescriptor,
|
||||
thisType, methodBegin, methodEnd, functionDescriptor.getValueParameters(),
|
||||
AsmUtil.isStaticMethod(ownerKind, functionDescriptor), state, shiftForDestructuringVariables
|
||||
AsmUtil.isStaticMethod(ownerKind, functionDescriptor), state
|
||||
);
|
||||
}
|
||||
|
||||
@@ -781,24 +780,6 @@ public class FunctionCodegen {
|
||||
Collection<ValueParameterDescriptor> valueParameters,
|
||||
boolean isStatic,
|
||||
@NotNull GenerationState state
|
||||
) {
|
||||
generateLocalVariablesForParameters(
|
||||
mv, jvmMethodSignature, functionDescriptor,
|
||||
thisType, methodBegin, methodEnd, valueParameters, isStatic, state,
|
||||
0);
|
||||
}
|
||||
|
||||
private static void generateLocalVariablesForParameters(
|
||||
@NotNull MethodVisitor mv,
|
||||
@NotNull JvmMethodSignature jvmMethodSignature,
|
||||
@NotNull FunctionDescriptor functionDescriptor,
|
||||
@Nullable Type thisType,
|
||||
@NotNull Label methodBegin,
|
||||
@NotNull Label methodEnd,
|
||||
Collection<ValueParameterDescriptor> valueParameters,
|
||||
boolean isStatic,
|
||||
@NotNull GenerationState state,
|
||||
int shiftForDestructuringVariables
|
||||
) {
|
||||
Iterator<ValueParameterDescriptor> valueParameterIterator = valueParameters.iterator();
|
||||
List<JvmMethodParameterSignature> params = jvmMethodSignature.getValueParameters();
|
||||
@@ -845,30 +826,6 @@ public class FunctionCodegen {
|
||||
mv.visitLocalVariable(parameterName, type.getDescriptor(), null, methodBegin, methodEnd, shift);
|
||||
shift += type.getSize();
|
||||
}
|
||||
|
||||
shift += shiftForDestructuringVariables;
|
||||
generateDestructuredParameterEntries(mv, methodBegin, methodEnd, valueParameters, typeMapper, shift);
|
||||
}
|
||||
|
||||
private static int generateDestructuredParameterEntries(
|
||||
@NotNull MethodVisitor mv,
|
||||
@NotNull Label methodBegin,
|
||||
@NotNull Label methodEnd,
|
||||
Collection<ValueParameterDescriptor> valueParameters,
|
||||
KotlinTypeMapper typeMapper,
|
||||
int shift
|
||||
) {
|
||||
for (ValueParameterDescriptor parameter : valueParameters) {
|
||||
List<VariableDescriptor> destructuringVariables = ValueParameterDescriptorImpl.getDestructuringVariablesOrNull(parameter);
|
||||
if (destructuringVariables == null) continue;
|
||||
|
||||
for (VariableDescriptor entry : CodegenUtilKt.filterOutDescriptorsWithSpecialNames(destructuringVariables)) {
|
||||
Type type = typeMapper.mapType(entry.getType());
|
||||
mv.visitLocalVariable(entry.getName().asString(), type.getDescriptor(), null, methodBegin, methodEnd, shift);
|
||||
shift += type.getSize();
|
||||
}
|
||||
}
|
||||
return shift;
|
||||
}
|
||||
|
||||
private static String computeParameterName(int i, ValueParameterDescriptor parameter) {
|
||||
|
||||
@@ -323,7 +323,7 @@ fun MemberDescriptor.isToArrayFromCollection(): Boolean {
|
||||
fun FqName.topLevelClassInternalName() = JvmClassName.byClassId(ClassId(parent(), shortName())).internalName
|
||||
fun FqName.topLevelClassAsmType(): Type = Type.getObjectType(topLevelClassInternalName())
|
||||
|
||||
fun initializeVariablesForDestructuredLambdaParameters(codegen: ExpressionCodegen, valueParameters: List<ValueParameterDescriptor>, endLabel: Label? = null) {
|
||||
fun initializeVariablesForDestructuredLambdaParameters(codegen: ExpressionCodegen, valueParameters: List<ValueParameterDescriptor>, endLabel: Label?) {
|
||||
// Do not write line numbers until destructuring happens
|
||||
// (otherwise destructuring variables will be uninitialized in the beginning of lambda)
|
||||
codegen.runWithShouldMarkLineNumbers(false) {
|
||||
|
||||
Reference in New Issue
Block a user