Generate local variable table for inlined lambda

This commit is contained in:
Mikhael Bogdanov
2014-03-19 17:45:46 +04:00
parent 75c57f9827
commit 93367ffd3b
9 changed files with 162 additions and 31 deletions
@@ -229,28 +229,20 @@ public class MethodInliner {
node.instructions.resetLabels();
MethodNode transformedNode = new MethodNode(node.access, node.name, Type.getMethodDescriptor(returnType, allTypes), node.signature, null) {
private final boolean keepLineNumbers = nodeRemapper.isInsideInliningLambda();
private final boolean isInliningLambda = nodeRemapper.isInsideInliningLambda();
private int getNewIndex(int var) {
return var + (var < realParametersSize ? 0 : capturedParamsSize);
}
@Override
public void visitVarInsn(int opcode, int var) {
int newIndex;
if (var < realParametersSize) {
newIndex = var;
} else {
newIndex = var + capturedParamsSize;
}
super.visitVarInsn(opcode, newIndex);
super.visitVarInsn(opcode, getNewIndex(var));
}
@Override
public void visitIincInsn(int var, int increment) {
int newIndex;
if (var < realParametersSize) {
newIndex = var;
} else {
newIndex = var + capturedParamsSize;
}
super.visitIincInsn(newIndex, increment);
super.visitIincInsn(getNewIndex(var), increment);
}
@Override
@@ -260,10 +252,19 @@ public class MethodInliner {
@Override
public void visitLineNumber(int line, Label start) {
if(keepLineNumbers) {
if(isInliningLambda) {
super.visitLineNumber(line, start);
}
}
@Override
public void visitLocalVariable(
String name, String desc, String signature, Label start, Label end, int index
) {
if (isInliningLambda) {
super.visitLocalVariable(name, desc, signature, start, end, getNewIndex(index));
}
}
};
node.accept(transformedNode);
@@ -34,6 +34,8 @@ public class RemapVisitor extends InstructionAdapter {
private final FieldRemapper nodeRemapper;
private final InstructionAdapter instructionAdapter;
protected RemapVisitor(
MethodVisitor mv,
Label end,
@@ -42,6 +44,7 @@ public class RemapVisitor extends InstructionAdapter {
FieldRemapper nodeRemapper
) {
super(InlineCodegenUtil.API, mv);
this.instructionAdapter = new InstructionAdapter(mv);
this.end = end;
this.remapper = varRemapper;
this.remapReturn = remapReturn;
@@ -65,7 +68,14 @@ public class RemapVisitor extends InstructionAdapter {
@Override
public void visitVarInsn(int opcode, int var) {
remapper.visitVarInsn(opcode, var, new InstructionAdapter(mv));
remapper.visitVarInsn(opcode, var, instructionAdapter);
}
@Override
public void visitLocalVariable(
String name, String desc, String signature, Label start, Label end, int index
) {
remapper.visitLocalVariable(name, desc, signature, start, end, index, mv);
}
@Override
@@ -86,13 +96,6 @@ public class RemapVisitor extends InstructionAdapter {
}
}
@Override
public void visitLocalVariable(
String name, String desc, String signature, Label start, Label end, int index
) {
}
@Override
public AnnotationVisitor visitAnnotationDefault() {
return null;
@@ -18,12 +18,15 @@ package org.jetbrains.jet.codegen.inline;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.asm4.Label;
import org.jetbrains.asm4.MethodVisitor;
import org.jetbrains.asm4.Opcodes;
import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
import static org.jetbrains.jet.codegen.inline.VarRemapper.RemapStatus.*;
public class VarRemapper {
private final int allParamsSize;
@@ -63,10 +66,10 @@ public class VarRemapper {
ParameterInfo info = params.get(index);
StackValue remapped = remapValues[index];
if (info.isSkipped || remapped == null) {
throw new RuntimeException("Trying to access skipped parameter: " + info.type + " at " +index);
return new RemapInfo(info);
}
if (info.isRemapped()) {
return new RemapInfo(remapped, info);
return new RemapInfo(remapped, info, REMAPPED);
} else {
remappedIndex = ((StackValue.Local)remapped).index;
}
@@ -74,11 +77,16 @@ public class VarRemapper {
remappedIndex = actualParamsSize - params.totalSize() + index; //captured params not used directly in this inlined method, they used in closure
}
return new RemapInfo(StackValue.local(remappedIndex + additionalShift, AsmTypeConstants.OBJECT_TYPE), null);
return new RemapInfo(StackValue.local(remappedIndex + additionalShift, AsmTypeConstants.OBJECT_TYPE), null, SHIFT);
}
public RemapInfo remap(int index) {
return doRemap(index);
RemapInfo info = doRemap(index);
if (FAIL == info.status) {
assert info.parameterInfo != null : "Parameter info should be not null";
throw new RuntimeException("Trying to access skipped parameter: " + info.parameterInfo.type + " at " +index);
}
return info;
}
public void visitIincInsn(int var, int increment, MethodVisitor mv) {
@@ -87,6 +95,15 @@ public class VarRemapper {
mv.visitIincInsn(((StackValue.Local) remap.value).index, increment);
}
public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index, MethodVisitor mv) {
RemapInfo info = doRemap(index);
if (SHIFT == info.status) {
//add entries only for shifted vars
mv.visitLocalVariable(name, desc, signature, start, end, ((StackValue.Local) info.value).index);
}
}
public void visitVarInsn(int opcode, int var, InstructionAdapter mv) {
RemapInfo remapInfo = remap(var);
StackValue value = remapInfo.value;
@@ -104,15 +121,30 @@ public class VarRemapper {
}
}
public static class RemapInfo {
public enum RemapStatus {
SHIFT,
REMAPPED,
FAIL
}
private static class RemapInfo {
public final StackValue value;
public final ParameterInfo parameterInfo;
public RemapInfo(@NotNull StackValue value, @Nullable ParameterInfo info) {
public final RemapStatus status;
public RemapInfo(@NotNull StackValue value, @Nullable ParameterInfo info, RemapStatus remapStatus) {
this.value = value;
parameterInfo = info;
this.status = remapStatus;
}
public RemapInfo(@NotNull ParameterInfo info) {
this.value = null;
parameterInfo = info;
this.status = FAIL;
}
}
}