Support of for local fun inside lambdas
This commit is contained in:
@@ -20,6 +20,7 @@ import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
|
|||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
import static org.jetbrains.jet.codegen.asm.InlineCodegenUtil.isLambdaClass;
|
||||||
import static org.jetbrains.jet.codegen.asm.InlineCodegenUtil.isLambdaConstructorCall;
|
import static org.jetbrains.jet.codegen.asm.InlineCodegenUtil.isLambdaConstructorCall;
|
||||||
import static org.jetbrains.jet.codegen.asm.InlineCodegenUtil.isInvokeOnInlinable;
|
import static org.jetbrains.jet.codegen.asm.InlineCodegenUtil.isInvokeOnInlinable;
|
||||||
|
|
||||||
@@ -40,7 +41,10 @@ public class MethodInliner {
|
|||||||
|
|
||||||
private final List<InlinableAccess> inlinableInvocation = new ArrayList<InlinableAccess>();
|
private final List<InlinableAccess> inlinableInvocation = new ArrayList<InlinableAccess>();
|
||||||
|
|
||||||
private final List<ConstructorInvocation> constructorInvocation = new ArrayList<ConstructorInvocation>();
|
//keeps order
|
||||||
|
private final List<ConstructorInvocation> constructorInvocationList = new ArrayList<ConstructorInvocation>();
|
||||||
|
//current state
|
||||||
|
private final Map<String, ConstructorInvocation> constructorInvocation = new LinkedHashMap<String, ConstructorInvocation>();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
@@ -100,18 +104,22 @@ public class MethodInliner {
|
|||||||
|
|
||||||
MethodNode resultNode = new MethodNode(node.access, node.name, node.desc, node.signature, null);
|
MethodNode resultNode = new MethodNode(node.access, node.name, node.desc, node.signature, null);
|
||||||
|
|
||||||
|
final Iterator<ConstructorInvocation> iterator = constructorInvocationList.iterator();
|
||||||
|
|
||||||
//TODO add reset to counter
|
//TODO add reset to counter
|
||||||
InlineAdapter inliner = new InlineAdapter(resultNode, parameters.totalSize()) {
|
InlineAdapter inliner = new InlineAdapter(resultNode, parameters.totalSize()) {
|
||||||
|
|
||||||
|
private ConstructorInvocation invocation;
|
||||||
@Override
|
@Override
|
||||||
public void anew(Type type) {
|
public void anew(Type type) {
|
||||||
if (isLambdaConstructorCall(type.getInternalName(), "<init>")) {
|
if (isLambdaConstructorCall(type.getInternalName(), "<init>")) {
|
||||||
ConstructorInvocation invocation = constructorInvocation.get(0);
|
invocation = iterator.next();
|
||||||
|
|
||||||
if (invocation.isInlinable()) {
|
if (invocation.isInlinable()) {
|
||||||
LambdaTransformer transformer = new LambdaTransformer(invocation.getOwnerInternalName(), parent.subInline(parent.nameGenerator));
|
LambdaTransformer transformer = new LambdaTransformer(invocation.getOwnerInternalName(), parent.subInline(parent.nameGenerator));
|
||||||
transformer.doTransform(invocation);
|
transformer.doTransform(invocation);
|
||||||
|
|
||||||
super.anew(transformer.getNewLambdaType());
|
super.anew(transformer.getNewLambdaType());
|
||||||
|
constructorInvocation.put(invocation.getOwnerInternalName(), invocation);
|
||||||
} else {
|
} else {
|
||||||
super.anew(type);
|
super.anew(type);
|
||||||
}
|
}
|
||||||
@@ -120,6 +128,12 @@ public class MethodInliner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//for local function support
|
||||||
|
@Override
|
||||||
|
public void checkcast(Type type) {
|
||||||
|
super.checkcast(changeOwnerIfLocalFun(type));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitMethodInsn(int opcode, String owner, String name, String desc) {
|
public void visitMethodInsn(int opcode, String owner, String name, String desc) {
|
||||||
if (/*INLINE_RUNTIME.equals(owner) &&*/ isInvokeOnInlinable(owner, name)) { //TODO add method
|
if (/*INLINE_RUNTIME.equals(owner) &&*/ isInvokeOnInlinable(owner, name)) { //TODO add method
|
||||||
@@ -152,7 +166,7 @@ public class MethodInliner {
|
|||||||
StackValue.onStack(delegate.getReturnType()).put(bridge.getReturnType(), this);
|
StackValue.onStack(delegate.getReturnType()).put(bridge.getReturnType(), this);
|
||||||
}
|
}
|
||||||
else if (isLambdaConstructorCall(owner, name)) { //TODO add method
|
else if (isLambdaConstructorCall(owner, name)) { //TODO add method
|
||||||
ConstructorInvocation invocation = constructorInvocation.remove(0);
|
assert invocation != null : "<init> call not corresponds to new call" + owner + " " + name;
|
||||||
if (invocation.isInlinable()) {
|
if (invocation.isInlinable()) {
|
||||||
//put additional captured parameters on stack
|
//put additional captured parameters on stack
|
||||||
List<CapturedParamInfo> recaptured = invocation.getRecaptured();
|
List<CapturedParamInfo> recaptured = invocation.getRecaptured();
|
||||||
@@ -169,12 +183,13 @@ public class MethodInliner {
|
|||||||
super.visitVarInsn(type.getOpcode(Opcodes.ILOAD), result.getIndex());
|
super.visitVarInsn(type.getOpcode(Opcodes.ILOAD), result.getIndex());
|
||||||
}
|
}
|
||||||
super.visitMethodInsn(opcode, invocation.getNewLambdaType().getInternalName(), name, invocation.getNewConstructorDescriptor());
|
super.visitMethodInsn(opcode, invocation.getNewLambdaType().getInternalName(), name, invocation.getNewConstructorDescriptor());
|
||||||
|
invocation = null;
|
||||||
} else {
|
} else {
|
||||||
super.visitMethodInsn(opcode, owner, name, desc);
|
super.visitMethodInsn(opcode, owner, name, desc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
super.visitMethodInsn(opcode, owner, name, desc);
|
super.visitMethodInsn(opcode, changeOwnerIfLocalFun(owner), name, desc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -302,7 +317,7 @@ public class MethodInliner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ConstructorInvocation invocation = new ConstructorInvocation(owner, infos);
|
ConstructorInvocation invocation = new ConstructorInvocation(owner, infos);
|
||||||
constructorInvocation.add(invocation);
|
constructorInvocationList.add(invocation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cur = cur.getNext();
|
cur = cur.getNext();
|
||||||
@@ -468,4 +483,26 @@ public class MethodInliner {
|
|||||||
mv.visitVarInsn(next.getOpcode(Opcodes.ISTORE), shift);
|
mv.visitVarInsn(next.getOpcode(Opcodes.ISTORE), shift);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Type changeOwnerIfLocalFun(Type oldType) {
|
||||||
|
if (isLambdaClass(oldType.getInternalName())) {
|
||||||
|
ConstructorInvocation invocation1 = constructorInvocation.get(oldType.getInternalName());
|
||||||
|
if (invocation1 != null && invocation1.isInlinable()) {
|
||||||
|
return invocation1.getNewLambdaType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return oldType;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String changeOwnerIfLocalFun(String oldType) {
|
||||||
|
if (isLambdaClass(oldType)) {
|
||||||
|
ConstructorInvocation invocation1 = constructorInvocation.get(oldType);
|
||||||
|
if (invocation1 != null && invocation1.isInlinable()) {
|
||||||
|
return invocation1.getNewLambdaType().getInternalName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return oldType;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user