Code clean

This commit is contained in:
Mikhael Bogdanov
2014-02-26 18:39:24 +04:00
parent 8ac48b746c
commit 55fbdbd302
6 changed files with 62 additions and 54 deletions
@@ -33,9 +33,9 @@ public class ConstructorInvocation {
private String newConstructorDescriptor;
private List<CapturedParamInfo> recaptured;
private List<CapturedParamInfo> allRecapturedParameters;
private Map<String, LambdaInfo> recapturedLambdas;
private Map<String, LambdaInfo> capturedLambdasToInline;
ConstructorInvocation(String ownerInternalName, Map<Integer, LambdaInfo> lambdasToInline, boolean isSameModule) {
this.ownerInternalName = ownerInternalName;
@@ -55,7 +55,6 @@ public class ConstructorInvocation {
return lambdasToInline;
}
public Type getNewLambdaType() {
return newLambdaType;
}
@@ -72,19 +71,19 @@ public class ConstructorInvocation {
this.newConstructorDescriptor = newConstructorDescriptor;
}
public List<CapturedParamInfo> getRecaptured() {
return recaptured;
public List<CapturedParamInfo> getAllRecapturedParameters() {
return allRecapturedParameters;
}
public void setRecaptured(List<CapturedParamInfo> recaptured) {
this.recaptured = recaptured;
public void setAllRecapturedParameters(List<CapturedParamInfo> allRecapturedParameters) {
this.allRecapturedParameters = allRecapturedParameters;
}
public Map<String, LambdaInfo> getRecapturedLambdas() {
return recapturedLambdas;
public Map<String, LambdaInfo> getCapturedLambdasToInline() {
return capturedLambdasToInline;
}
public void setRecapturedLambdas(Map<String, LambdaInfo> recapturedLambdas) {
this.recapturedLambdas = recapturedLambdas;
public void setCapturedLambdasToInline(Map<String, LambdaInfo> capturedLambdasToInline) {
this.capturedLambdasToInline = capturedLambdasToInline;
}
}
@@ -207,7 +207,7 @@ public class InlineCodegen implements ParentCodegenAware, CallGenerator {
VarRemapper.ParamRemapper remapper = new VarRemapper.ParamRemapper(parameters, initialFrameSize);
inliner.doTransformAndMerge(codegen.v, remapper);
inliner.doInline(codegen.v, remapper);
}
@@ -87,7 +87,7 @@ public class InlineCodegenUtil {
FqName namespaceFqName =
PackageClassUtils.getPackageClassFqName(((PackageFragmentDescriptor) parentDeclatation).getFqName()).parent().child(
name);
file = findVirtualFile(state.getProject(), namespaceFqName, true);
file = findVirtualFileWithHeader(state.getProject(), namespaceFqName);
} else {
assert false : "Function in namespace should have implClassName property in proto: " + deserializedDescriptor;
}
@@ -103,13 +103,15 @@ public class InlineCodegenUtil {
}
@Nullable
public static VirtualFile findVirtualFile(@NotNull Project project, @NotNull FqName containerFqName, boolean onlyKotlin) {
public static VirtualFile findVirtualFileWithHeader(@NotNull Project project, @NotNull FqName containerFqName) {
VirtualFileFinder fileFinder = ServiceManager.getService(project, VirtualFileFinder.class);
if (onlyKotlin) {
return fileFinder.findVirtualFileWithHeader(containerFqName);
} else {
return fileFinder.findVirtualFile(containerFqName.asString().replace('.', '/'));
}
return fileFinder.findVirtualFileWithHeader(containerFqName);
}
@Nullable
public static VirtualFile findVirtualFile(@NotNull Project project, @NotNull String internalName) {
VirtualFileFinder fileFinder = ServiceManager.getService(project, VirtualFileFinder.class);
return fileFinder.findVirtualFile(internalName);
}
//TODO: navigate to inner classes
@@ -185,7 +187,7 @@ public class InlineCodegenUtil {
if (containerFqName == null) {
return null;
}
return findVirtualFile(project, containerFqName, true);
return findVirtualFileWithHeader(project, containerFqName);
}
@@ -27,10 +27,12 @@ import org.jetbrains.asm4.tree.FieldInsnNode;
import org.jetbrains.asm4.tree.MethodNode;
import org.jetbrains.asm4.tree.VarInsnNode;
import org.jetbrains.jet.OutputFile;
import org.jetbrains.jet.codegen.*;
import org.jetbrains.jet.codegen.AsmUtil;
import org.jetbrains.jet.codegen.ClassBuilder;
import org.jetbrains.jet.codegen.ClosureCodegen;
import org.jetbrains.jet.codegen.FieldInfo;
import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.codegen.state.JetTypeMapper;
import org.jetbrains.jet.lang.resolve.name.FqName;
import java.io.IOException;
import java.util.ArrayList;
@@ -55,8 +57,6 @@ public class LambdaTransformer {
private final InliningInfo info;
private final Map<String, Integer> paramMapping = new HashMap<String, Integer>();
private final Type oldLambdaType;
private final Type newLambdaType;
@@ -82,7 +82,7 @@ public class LambdaTransformer {
if (outputFile != null) {
reader = new ClassReader(outputFile.asByteArray());
} else {
VirtualFile file = InlineCodegenUtil.findVirtualFile(state.getProject(), new FqName(lambdaInternalName.replace('/', '.')), false);
VirtualFile file = InlineCodegenUtil.findVirtualFile(state.getProject(), lambdaInternalName);
if (file == null) {
throw new RuntimeException("Couldn't find virtual file for " + lambdaInternalName);
}
@@ -93,6 +93,7 @@ public class LambdaTransformer {
throw new RuntimeException(e);
}
//TODO rewrite to one step
constructor = getMethodNode(reader, true, false);
invoke = getMethodNode(reader, false, false);
bridge = getMethodNode(reader, false, true);
@@ -110,6 +111,7 @@ public class LambdaTransformer {
public void doTransform(ConstructorInvocation invocation) {
ClassBuilder classBuilder = createClassBuilder();
//TODO: public visibility for inline function
classBuilder.defineClass(null,
V1_6,
classAccess,
@@ -122,10 +124,10 @@ public class LambdaTransformer {
Parameters parameters = getLambdaParameters(builder, invocation);
MethodVisitor invokeVisitor = newMethod(classBuilder, invoke);
InlineFieldRemapper remapper = new InlineFieldRemapper(oldLambdaType.getInternalName(), newLambdaType.getInternalName(), parameters, invocation.getRecapturedLambdas());
InlineFieldRemapper remapper = new InlineFieldRemapper(oldLambdaType.getInternalName(), newLambdaType.getInternalName(), parameters, invocation.getCapturedLambdasToInline());
MethodInliner inliner = new MethodInliner(invoke, parameters, info.subInline(info.nameGenerator.subGenerator("lambda")), oldLambdaType,
remapper, isSameModule);
inliner.doTransformAndMerge(invokeVisitor, new VarRemapper.ParamRemapper(parameters, 0), remapper, false);
inliner.doInline(invokeVisitor, new VarRemapper.ParamRemapper(parameters, 0), remapper, false);
invokeVisitor.visitMaxs(-1, -1);
generateConstructorAndFields(classBuilder, builder, invocation);
@@ -162,6 +164,7 @@ public class LambdaTransformer {
AsmUtil.genClosureFields(newConstructorSignature, classBuilder);
//TODO for inline method make public class
Method newConstructor = ClosureCodegen.generateConstructor(classBuilder, fields, null, Type.getObjectType(superName), state, AsmUtil.NO_FLAG_PACKAGE_PRIVATE);
invocation.setNewConstructorDescriptor(newConstructor.getDescriptor());
}
@@ -173,7 +176,7 @@ public class LambdaTransformer {
}
private ClassBuilder createClassBuilder() {
return new RemappingClassBuilder(state.getFactory().forLambdaInlining(newLambdaType, info.call.getCalleeExpression().getContainingFile()),
return new RemappingClassBuilder(state.getFactory().forLambdaInlining(newLambdaType, info.call.getCallElement().getContainingFile()),
new TypeRemapper(info.typeMapping, isSameModule));
}
@@ -188,7 +191,7 @@ public class LambdaTransformer {
);
}
private void extractParametersMapping(MethodNode constructor, ParametersBuilder builder, ConstructorInvocation invocation) {
private static void extractParametersMapping(MethodNode constructor, ParametersBuilder builder, ConstructorInvocation invocation) {
Map<Integer, LambdaInfo> indexToLambda = invocation.getLambdasToInline();
AbstractInsnNode cur = constructor.instructions.getFirst();
@@ -197,34 +200,35 @@ public class LambdaTransformer {
while (cur != null) {
if (cur.getType() == AbstractInsnNode.FIELD_INSN) {
FieldInsnNode fieldNode = (FieldInsnNode) cur;
CapturedParamInfo info = builder.addCapturedParam(fieldNode.name, Type.getType(fieldNode.desc), false, null);
assert fieldNode.getPrevious() instanceof VarInsnNode : "Previous instruction should be VarInsnNode but was " + fieldNode.getPrevious();
VarInsnNode previous = (VarInsnNode) fieldNode.getPrevious();
int varIndex = previous.var;
paramMapping.put(fieldNode.name, varIndex);
CapturedParamInfo info = builder.addCapturedParam(fieldNode.name, Type.getType(fieldNode.desc), false, null);
LambdaInfo LambdaInfo = indexToLambda.get(varIndex);
if (LambdaInfo != null) {
info.setLambda(LambdaInfo);
additionalCaptured.add(LambdaInfo);
LambdaInfo lambdaInfo = indexToLambda.get(varIndex);
if (lambdaInfo != null) {
info.setLambda(lambdaInfo);
additionalCaptured.add(lambdaInfo);
}
}
cur = cur.getNext();
}
Map<String, LambdaInfo> recapturedLambdas = new HashMap<String, LambdaInfo>(); //captured var of inlined parameter
List<CapturedParamInfo> recaptured = new ArrayList<CapturedParamInfo>();
//For all inlined lambdas add their captured parameters
//TODO: some of such parameters could be skipped - we should perform additional analysis
Map<String, LambdaInfo> capturedLambdasToInline = new HashMap<String, LambdaInfo>(); //captured var of inlined parameter
List<CapturedParamInfo> allRecapturedParameters = new ArrayList<CapturedParamInfo>();
for (LambdaInfo info : additionalCaptured) {
List<CapturedParamInfo> vars = info.getCapturedVars();
for (CapturedParamInfo var : vars) {
for (CapturedParamInfo var : info.getCapturedVars()) {
CapturedParamInfo recapturedParamInfo = builder.addCapturedParam(getNewFieldName(var.getFieldName()), var.getType(), true, var);
recapturedParamInfo.setRecapturedFrom(info);
recaptured.add(var);
allRecapturedParameters.add(var);
}
recapturedLambdas.put(info.getLambdaClassType().getInternalName(), info);
capturedLambdasToInline.put(info.getLambdaClassType().getInternalName(), info);
}
invocation.setRecaptured(recaptured);
invocation.setRecapturedLambdas(recapturedLambdas);
invocation.setAllRecapturedParameters(allRecapturedParameters);
invocation.setCapturedLambdasToInline(capturedLambdasToInline);
}
@Nullable
@@ -244,7 +248,8 @@ public class LambdaTransformer {
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
boolean isConstructorMethod = "<init>".equals(name);
if (findConstructor && isConstructorMethod || (!findConstructor && !isConstructorMethod && ((access & Opcodes.ACC_BRIDGE) == (findBridge ? Opcodes.ACC_BRIDGE : 0)))) {
boolean isBridge = (access & Opcodes.ACC_BRIDGE) != 0;
if (findConstructor && isConstructorMethod || (!findConstructor && !isConstructorMethod && (isBridge == findBridge))) {
assert methodNode[0] == null : "Wrong lambda/sam structure: " + methodNode[0].name + " conflicts with " + name;
return methodNode[0] = new MethodNode(access, name, desc, signature, exceptions);
}
@@ -259,10 +264,6 @@ public class LambdaTransformer {
return methodNode[0];
}
public Type getNewLambdaType() {
return newLambdaType;
}
public static String getNewFieldName(String oldName) {
return oldName + "$inlined";
}
@@ -71,11 +71,11 @@ public class MethodInliner {
}
public void doTransformAndMerge(MethodVisitor adapter, VarRemapper.ParamRemapper remapper) {
doTransformAndMerge(adapter, remapper, new LambdaFieldRemapper(), true);
public void doInline(MethodVisitor adapter, VarRemapper.ParamRemapper remapper) {
doInline(adapter, remapper, new LambdaFieldRemapper(), true);
}
public void doTransformAndMerge(
public void doInline(
MethodVisitor adapter,
VarRemapper.ParamRemapper remapper,
LambdaFieldRemapper capturedRemapper, boolean remapReturn
@@ -158,7 +158,7 @@ public class MethodInliner {
capturedRemapper, true /*cause all calls in same module as lambda*/);
VarRemapper.ParamRemapper remapper = new VarRemapper.ParamRemapper(lambdaParameters, valueParamShift);
inliner.doTransformAndMerge(this.mv, remapper); //TODO add skipped this and receiver
inliner.doInline(this.mv, remapper); //TODO add skipped this and receiver
//return value boxing/unboxing
Method bridge = typeMapper.mapSignature(ClosureCodegen.getInvokeFunction(info.getFunctionDescriptor())).getAsmMethod();
@@ -170,7 +170,7 @@ public class MethodInliner {
assert invocation != null : "<init> call not corresponds to new call" + owner + " " + name;
if (invocation.shouldRegenerate()) {
//put additional captured parameters on stack
List<CapturedParamInfo> recaptured = invocation.getRecaptured();
List<CapturedParamInfo> recaptured = invocation.getAllRecapturedParameters();
List<CapturedParamInfo> contextCaptured = MethodInliner.this.parameters.getCaptured();
for (CapturedParamInfo capturedParamInfo : recaptured) {
CapturedParamInfo result = null;
@@ -92,4 +92,10 @@ public class RemapVisitor extends InstructionAdapter {
super.visitFieldInsn(opcode, owner, name, desc);
}
}
//TODO not skip for lambdas
@Override
public void visitLineNumber(int line, Label start) {
}
}