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