Rename this$0 on decl site

This commit is contained in:
Michael Bogdanov
2015-11-18 14:25:37 +03:00
parent d4369c1df9
commit d3f7e9f74b
3 changed files with 38 additions and 10 deletions
@@ -35,6 +35,7 @@ import org.jetbrains.org.objectweb.asm.tree.VarInsnNode;
import java.util.*; import java.util.*;
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.isThis0;
import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.NO_ORIGIN; import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
public class AnonymousObjectTransformer { public class AnonymousObjectTransformer {
@@ -399,7 +400,8 @@ public class AnonymousObjectTransformer {
while (cur != null) { while (cur != null) {
if (cur instanceof FieldInsnNode) { if (cur instanceof FieldInsnNode) {
FieldInsnNode fieldNode = (FieldInsnNode) cur; FieldInsnNode fieldNode = (FieldInsnNode) cur;
if (fieldNode.getOpcode() == Opcodes.PUTFIELD && InlineCodegenUtil.isCapturedFieldName(fieldNode.name)) { String fieldName = fieldNode.name;
if (fieldNode.getOpcode() == Opcodes.PUTFIELD && InlineCodegenUtil.isCapturedFieldName(fieldName)) {
boolean isPrevVarNode = fieldNode.getPrevious() instanceof VarInsnNode; boolean isPrevVarNode = fieldNode.getPrevious() instanceof VarInsnNode;
boolean isPrevPrevVarNode = isPrevVarNode && fieldNode.getPrevious().getPrevious() instanceof VarInsnNode; boolean isPrevPrevVarNode = isPrevVarNode && fieldNode.getPrevious().getPrevious() instanceof VarInsnNode;
@@ -410,7 +412,8 @@ public class AnonymousObjectTransformer {
VarInsnNode previous = (VarInsnNode) fieldNode.getPrevious(); VarInsnNode previous = (VarInsnNode) fieldNode.getPrevious();
int varIndex = previous.var; int varIndex = previous.var;
LambdaInfo lambdaInfo = indexToLambda.get(varIndex); LambdaInfo lambdaInfo = indexToLambda.get(varIndex);
CapturedParamInfo info = capturedParamBuilder.addCapturedParam(owner, fieldNode.name, Type.getType(fieldNode.desc), lambdaInfo != null, null); String newFieldName = isThis0(fieldName) && shouldRenameThis0(parentFieldRemapper, indexToLambda.values()) ? getNewFieldName(fieldName, true) : fieldName;
CapturedParamInfo info = capturedParamBuilder.addCapturedParam(owner, fieldName, newFieldName, Type.getType(fieldNode.desc), lambdaInfo != null, null);
if (lambdaInfo != null) { if (lambdaInfo != null) {
info.setLambda(lambdaInfo); info.setLambda(lambdaInfo);
capturedLambdas.add(lambdaInfo); capturedLambdas.add(lambdaInfo);
@@ -459,7 +462,7 @@ public class AnonymousObjectTransformer {
for (LambdaInfo info : capturedLambdas) { for (LambdaInfo info : capturedLambdas) {
if (addCapturedNotAddOuter) { if (addCapturedNotAddOuter) {
for (CapturedParamDesc desc : info.getCapturedVars()) { for (CapturedParamDesc desc : info.getCapturedVars()) {
CapturedParamInfo recapturedParamInfo = capturedParamBuilder.addCapturedParam(desc, getNewFieldName(desc.getFieldName())); CapturedParamInfo recapturedParamInfo = capturedParamBuilder.addCapturedParam(desc, getNewFieldName(desc.getFieldName(), false));
StackValue composed = StackValue.field(desc.getType(), StackValue composed = StackValue.field(desc.getType(),
oldObjectType, /*TODO owner type*/ oldObjectType, /*TODO owner type*/
recapturedParamInfo.getNewFieldName(), recapturedParamInfo.getNewFieldName(),
@@ -486,7 +489,7 @@ public class AnonymousObjectTransformer {
return ownerType; return ownerType;
} }
}, InlineCodegenUtil.THIS, ownerType); }, InlineCodegenUtil.THIS, ownerType);
CapturedParamInfo recapturedParamInfo = capturedParamBuilder.addCapturedParam(desc, InlineCodegenUtil.THIS$0); CapturedParamInfo recapturedParamInfo = capturedParamBuilder.addCapturedParam(desc, InlineCodegenUtil.THIS$0/*outer lambda/object*/);
StackValue composed = StackValue.LOCAL_0; StackValue composed = StackValue.LOCAL_0;
recapturedParamInfo.setRemapValue(composed); recapturedParamInfo.setRemapValue(composed);
allRecapturedParameters.add(desc); allRecapturedParameters.add(desc);
@@ -494,19 +497,34 @@ public class AnonymousObjectTransformer {
constructorParamBuilder.addCapturedParam(recapturedParamInfo, recapturedParamInfo.getNewFieldName()).setRemapValue(composed); constructorParamBuilder.addCapturedParam(recapturedParamInfo, recapturedParamInfo.getNewFieldName()).setRemapValue(composed);
} }
anonymousObjectGen.setAllRecapturedParameters(allRecapturedParameters); anonymousObjectGen.setAllRecapturedParameters(allRecapturedParameters);
anonymousObjectGen.setCapturedLambdasToInline(capturedLambdasToInline); anonymousObjectGen.setCapturedLambdasToInline(capturedLambdasToInline);
return constructorAdditionalFakeParams; return constructorAdditionalFakeParams;
} }
private static boolean shouldRenameThis0(@NotNull FieldRemapper parentFieldRemapper, Collection<LambdaInfo> values) {
if (isFirstDeclSiteLambdaFieldRemapper(parentFieldRemapper)) {
for (LambdaInfo value : values) {
for (CapturedParamDesc desc : value.getCapturedVars()) {
if (isThis0(desc.getFieldName())) {
return true;
}
}
}
}
return false;
}
@NotNull @NotNull
public String getNewFieldName(@NotNull String oldName) { public String getNewFieldName(@NotNull String oldName, boolean originalField) {
if (InlineCodegenUtil.THIS$0.equals(oldName)) { if (InlineCodegenUtil.THIS$0.equals(oldName)) {
//"this$0" couldn't clash and we should keep this name invariant for further transformations if (!originalField) {
return oldName; return oldName;
} else {
//rename original 'this$0' in declaration site lambda (inside inline function) to use this$0 only for outer lambda/object access on call site
return addUniqueField(oldName + InlineCodegenUtil.INLINE_FUN_THIS_0_SUFFIX);
}
} }
return addUniqueField(oldName + InlineCodegenUtil.INLINE_TRANSFORMATION_SUFFIX); return addUniqueField(oldName + InlineCodegenUtil.INLINE_TRANSFORMATION_SUFFIX);
} }
@@ -523,4 +541,8 @@ public class AnonymousObjectTransformer {
existNames.add(newName); existNames.add(newName);
return newName; return newName;
} }
private static boolean isFirstDeclSiteLambdaFieldRemapper(FieldRemapper parentRemapper) {
return !(parentRemapper instanceof RegeneratedLambdaFieldRemapper) && !(parentRemapper instanceof InlinedLambdaRemapper);
}
} }
@@ -73,6 +73,7 @@ public class InlineCodegenUtil {
public static final String INLINE_MARKER_FINALLY_START = "finallyStart"; public static final String INLINE_MARKER_FINALLY_START = "finallyStart";
public static final String INLINE_MARKER_FINALLY_END = "finallyEnd"; public static final String INLINE_MARKER_FINALLY_END = "finallyEnd";
public static final String INLINE_TRANSFORMATION_SUFFIX = "$inlined"; public static final String INLINE_TRANSFORMATION_SUFFIX = "$inlined";
public static final String INLINE_FUN_THIS_0_SUFFIX = "$inline_fun";
@Nullable @Nullable
public static SMAPAndMethodNode getMethodNode( public static SMAPAndMethodNode getMethodNode(
@@ -487,4 +488,8 @@ public class InlineCodegenUtil {
public static boolean isFakeLocalVariableForInline(@NotNull String name) { public static boolean isFakeLocalVariableForInline(@NotNull String name) {
return name.startsWith(JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_FUNCTION) || name.startsWith(JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_ARGUMENT); return name.startsWith(JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_FUNCTION) || name.startsWith(JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_ARGUMENT);
} }
public static boolean isThis0(String name) {
return THIS$0.equals(name);
}
} }
@@ -77,10 +77,11 @@ internal class ParametersBuilder private constructor(){
fun addCapturedParam( fun addCapturedParam(
containingLambda: CapturedParamOwner, containingLambda: CapturedParamOwner,
fieldName: String, fieldName: String,
newFieldName: String,
type: Type, type: Type,
skipped: Boolean, skipped: Boolean,
original: ParameterInfo?): CapturedParamInfo { original: ParameterInfo?): CapturedParamInfo {
val info = CapturedParamInfo(CapturedParamDesc.createDesc(containingLambda, fieldName, type), skipped, nextCapturedIndex(), val info = CapturedParamInfo(CapturedParamDesc.createDesc(containingLambda, fieldName, type), newFieldName, skipped, nextCapturedIndex(),
if (original != null) original.getIndex() else -1) if (original != null) original.getIndex() else -1)
if (original != null) { if (original != null) {
info.setLambda(original.getLambda()) info.setLambda(original.getLambda())