diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/inline/ConstructorInvocation.java b/compiler/backend/src/org/jetbrains/jet/codegen/inline/ConstructorInvocation.java index 266c6fe95ef..5c6d035a9c3 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/inline/ConstructorInvocation.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/inline/ConstructorInvocation.java @@ -25,7 +25,7 @@ public class ConstructorInvocation { private final String ownerInternalName; - private final Map access; + private final Map lambdasToInline; private final boolean isSameModule; @@ -37,9 +37,9 @@ public class ConstructorInvocation { private Map recapturedLambdas; - ConstructorInvocation(String ownerInternalName, Map access, boolean isSameModule) { + ConstructorInvocation(String ownerInternalName, Map lambdasToInline, boolean isSameModule) { this.ownerInternalName = ownerInternalName; - this.access = access; + this.lambdasToInline = lambdasToInline; this.isSameModule = isSameModule; } @@ -47,12 +47,12 @@ public class ConstructorInvocation { return ownerInternalName; } - public boolean isInlinable() { - return !access.isEmpty() || !isSameModule; + public boolean shouldRegenerate() { + return !lambdasToInline.isEmpty() || !isSameModule; } - public Map getAccess() { - return access; + public Map getLambdasToInline() { + return lambdasToInline; } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/inline/LambdaTransformer.java b/compiler/backend/src/org/jetbrains/jet/codegen/inline/LambdaTransformer.java index f519b96cff6..adf3a5cc3f2 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/inline/LambdaTransformer.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/inline/LambdaTransformer.java @@ -189,7 +189,7 @@ public class LambdaTransformer { } private void extractParametersMapping(MethodNode constructor, ParametersBuilder builder, ConstructorInvocation invocation) { - Map indexToLambda = invocation.getAccess(); + Map indexToLambda = invocation.getLambdasToInline(); AbstractInsnNode cur = constructor.instructions.getFirst(); cur = cur.getNext(); //skip super call @@ -202,13 +202,10 @@ public class LambdaTransformer { paramMapping.put(fieldNode.name, varIndex); CapturedParamInfo info = builder.addCapturedParam(fieldNode.name, Type.getType(fieldNode.desc), false, null); - InvokeCall access = indexToLambda.get(varIndex); - if (access != null) { - LambdaInfo accessInfo = access.lambdaInfo; - if (accessInfo != null) { - info.setLambda(accessInfo); - additionalCaptured.add(accessInfo); - } + LambdaInfo LambdaInfo = indexToLambda.get(varIndex); + if (LambdaInfo != null) { + info.setLambda(LambdaInfo); + additionalCaptured.add(LambdaInfo); } } cur = cur.getNext(); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/inline/MethodInliner.java b/compiler/backend/src/org/jetbrains/jet/codegen/inline/MethodInliner.java index bc7e92afe6d..5527d588ee3 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/inline/MethodInliner.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/inline/MethodInliner.java @@ -119,19 +119,20 @@ public class MethodInliner { if (isLambdaConstructorCall(type.getInternalName(), "")) { invocation = iterator.next(); - if (invocation.isInlinable()) { + if (invocation.shouldRegenerate()) { //TODO: need poping of type but what to do with local funs??? Type newLambdaType = Type.getObjectType(parent.nameGenerator.genLambdaClassName()); currentTypeMapping.put(invocation.getOwnerInternalName(), newLambdaType.getInternalName()); - LambdaTransformer transformer = new LambdaTransformer(invocation.getOwnerInternalName(), parent.subInline(parent.nameGenerator, currentTypeMapping), + LambdaTransformer transformer = new LambdaTransformer(invocation.getOwnerInternalName(), + parent.subInline(parent.nameGenerator, currentTypeMapping), isSameModule, newLambdaType); transformer.doTransform(invocation); } - super.anew(type); - } else { - super.anew(type); } + + //in case of regenerated invocation type would be remapped to new one via remappingMethodAdapter + super.anew(type); } @Override @@ -167,12 +168,11 @@ public class MethodInliner { } else if (isLambdaConstructorCall(owner, name)) { //TODO add method assert invocation != null : " call not corresponds to new call" + owner + " " + name; - if (invocation.isInlinable()) { + if (invocation.shouldRegenerate()) { //put additional captured parameters on stack List recaptured = invocation.getRecaptured(); + List contextCaptured = MethodInliner.this.parameters.getCaptured(); for (CapturedParamInfo capturedParamInfo : recaptured) { - Type type = capturedParamInfo.getType(); - List contextCaptured = MethodInliner.this.parameters.getCaptured(); CapturedParamInfo result = null; for (CapturedParamInfo info : contextCaptured) { //TODO more sophisticated check @@ -180,7 +180,12 @@ public class MethodInliner { result = info; } } - super.visitVarInsn(type.getOpcode(Opcodes.ILOAD), result.getIndex()); + if (result == null) { + throw new UnsupportedOperationException( + "Unsupported operation: could not transform non-inline lambda inside inlined one: " + + owner + "." + name); + } + super.visitVarInsn(capturedParamInfo.getType().getOpcode(Opcodes.ILOAD), result.getIndex()); } super.visitMethodInsn(opcode, invocation.getNewLambdaType().getInternalName(), name, invocation.getNewConstructorDescriptor()); invocation = null; @@ -296,25 +301,25 @@ public class MethodInliner { invokeCalls.add(new InvokeCall(varIndex, lambdaInfo)); } else if (isLambdaConstructorCall(owner, name)) { - Map infos = new HashMap(); + Map lambdaMapping = new HashMap(); int paramStart = frame.getStackSize() - paramLength; for (int i = 0; i < paramLength; i++) { SourceValue sourceValue = frame.getStack(paramStart + i); if (sourceValue.insns.size() == 1) { AbstractInsnNode insnNode = sourceValue.insns.iterator().next(); - if (insnNode.getType() == AbstractInsnNode.VAR_INSN && insnNode.getOpcode() == Opcodes.ALOAD) { + if (insnNode.getOpcode() == Opcodes.ALOAD) { int varIndex = ((VarInsnNode) insnNode).var; LambdaInfo lambdaInfo = getLambda(varIndex); if (lambdaInfo != null) { - infos.put(i, new InvokeCall(varIndex, lambdaInfo)); + lambdaMapping.put(i, lambdaInfo); node.instructions.remove(insnNode); } } } } - constructorInvocations.add(new ConstructorInvocation(owner, infos, isSameModule)); + constructorInvocations.add(new ConstructorInvocation(owner, lambdaMapping, isSameModule)); } } } @@ -456,6 +461,9 @@ public class MethodInliner { } } + //TODO: check annotation on class - it's package part + //TODO: check it's external module + //TODO?: assert method exists in facade? public String changeOwnerForExternalPackage(String type, int opcode) { if (isSameModule || (opcode & Opcodes.INVOKESTATIC) == 0) { return type;