From 30ddbb06829e75a3f4a3d252985c878f417bc448 Mon Sep 17 00:00:00 2001 From: Mikhael Bogdanov Date: Tue, 3 Jun 2014 14:08:57 +0400 Subject: [PATCH] Parameter processing rewrote with parameter builder Split capture parameter descriptor and it representation --- .../inline/AnonymousObjectTransformer.java | 13 ++- .../jet/codegen/inline/CapturedParamDesc.java | 5 + .../jet/codegen/inline/CapturedParamInfo.java | 11 -- .../codegen/inline/ConstructorInvocation.java | 6 +- .../jet/codegen/inline/InlineCodegen.java | 102 +++++++----------- .../jet/codegen/inline/LambdaInfo.java | 45 +++----- .../jet/codegen/inline/MethodInliner.java | 7 +- .../jet/codegen/inline/ParameterInfo.java | 4 +- .../jet/codegen/inline/ParametersBuilder.java | 28 ++++- 9 files changed, 99 insertions(+), 122 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/inline/AnonymousObjectTransformer.java b/compiler/backend/src/org/jetbrains/jet/codegen/inline/AnonymousObjectTransformer.java index 30d82f4abc8..271517485b6 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/inline/AnonymousObjectTransformer.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/inline/AnonymousObjectTransformer.java @@ -384,20 +384,19 @@ public class AnonymousObjectTransformer { //For all inlined lambdas add their captured parameters //TODO: some of such parameters could be skipped - we should perform additional analysis Map capturedLambdasToInline = new HashMap(); //captured var of inlined parameter - List allRecapturedParameters = new ArrayList(); + List allRecapturedParameters = new ArrayList(); for (LambdaInfo info : capturedLambdas) { - for (CapturedParamInfo var : info.getCapturedVars()) { - CapturedParamInfo recapturedParamInfo = capturedParamBuilder.addCapturedParam(var, - getNewFieldName(var.getOriginalFieldName())); + for (CapturedParamDesc desc : info.getCapturedVars()) { + CapturedParamInfo recapturedParamInfo = capturedParamBuilder.addCapturedParam(desc, getNewFieldName(desc.getFieldName())); StackValue composed = StackValue.composed(StackValue.local(0, oldObjectType), - StackValue.field(var.getType(), + StackValue.field(desc.getType(), oldObjectType, /*TODO owner type*/ recapturedParamInfo.getNewFieldName(), false) ); recapturedParamInfo.setRemapValue(composed); - allRecapturedParameters.add(var); + allRecapturedParameters.add(desc); - constructorParamBuilder.addCapturedParam(var, recapturedParamInfo.getNewFieldName()).setRemapValue(composed); + constructorParamBuilder.addCapturedParam(recapturedParamInfo, recapturedParamInfo.getNewFieldName()).setRemapValue(composed); } capturedLambdasToInline.put(info.getLambdaClassType().getInternalName(), info); } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/inline/CapturedParamDesc.java b/compiler/backend/src/org/jetbrains/jet/codegen/inline/CapturedParamDesc.java index 7778490d250..e05d1bc8490 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/inline/CapturedParamDesc.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/inline/CapturedParamDesc.java @@ -56,4 +56,9 @@ public class CapturedParamDesc { public static CapturedParamDesc createDesc(@NotNull CapturedParamOwner containingLambdaInfo, @NotNull String fieldName, @NotNull Type type) { return new CapturedParamDesc(containingLambdaInfo, fieldName, type); } + + @NotNull + public String getContainingLambdaName() { + return containingLambda.getType().getInternalName(); + } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/inline/CapturedParamInfo.java b/compiler/backend/src/org/jetbrains/jet/codegen/inline/CapturedParamInfo.java index 73ad023b429..8b62ae1686e 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/inline/CapturedParamInfo.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/inline/CapturedParamInfo.java @@ -31,8 +31,6 @@ public class CapturedParamInfo extends ParameterInfo { public final CapturedParamDesc desc; - private int shift = 0; - private final String newFieldName; public CapturedParamInfo(@NotNull CapturedParamDesc desc, boolean skipped, int index, int remapIndex) { @@ -61,15 +59,6 @@ public class CapturedParamInfo extends ParameterInfo { return desc.getFieldName(); } - @Override - public int getIndex() { - return shift + super.getIndex(); - } - - public void setShift(int shift) { - this.shift = shift; - } - @NotNull public CapturedParamInfo newIndex(int newIndex) { return clone(newIndex, getRemapValue()); 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 5ae70f17642..71fb72cbd85 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/inline/ConstructorInvocation.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/inline/ConstructorInvocation.java @@ -36,7 +36,7 @@ public class ConstructorInvocation { private String newConstructorDescriptor; - private List allRecapturedParameters; + private List allRecapturedParameters; private Map capturedLambdasToInline; @@ -84,11 +84,11 @@ public class ConstructorInvocation { this.newConstructorDescriptor = newConstructorDescriptor; } - public List getAllRecapturedParameters() { + public List getAllRecapturedParameters() { return allRecapturedParameters; } - public void setAllRecapturedParameters(List allRecapturedParameters) { + public void setAllRecapturedParameters(List allRecapturedParameters) { this.allRecapturedParameters = allRecapturedParameters; } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/inline/InlineCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/inline/InlineCodegen.java index d28ba901068..d9d85c89d83 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/inline/InlineCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/inline/InlineCodegen.java @@ -68,12 +68,12 @@ public class InlineCodegen implements CallGenerator { private final JetElement callElement; private final MethodContext context; private final ExpressionCodegen codegen; - private final FrameMap originalFunctionFrame; + private final boolean asFunctionInline; private final int initialFrameSize; private final boolean isSameModule; - protected final List actualParameters = new ArrayList(); + protected final ParametersBuilder invocationParamBuilder = ParametersBuilder.newBuilder(); protected final Map expressionMap = new HashMap(); private LambdaInfo activeLambda; @@ -95,7 +95,6 @@ public class InlineCodegen implements CallGenerator { initialFrameSize = codegen.getFrameMap().getCurrentSize(); context = (MethodContext) getContext(functionDescriptor, state); - originalFunctionFrame = context.prepareFrame(typeMapper); jvmSignature = typeMapper.mapSignature(functionDescriptor, context.getContextKind()); InlineStrategy inlineStrategy = @@ -205,13 +204,10 @@ public class InlineCodegen implements CallGenerator { private InlineResult inlineCall(MethodNode node) { generateClosuresBodies(); - List realParams = new ArrayList(actualParameters); - + //through generation captured parameters will be added to invocationParamBuilder putClosureParametersOnStack(); - List captured = getAllCaptured(); - - Parameters parameters = new Parameters(realParams, Parameters.shiftAndAddStubs(captured, realParams.size())); + Parameters parameters = invocationParamBuilder.buildParameters(); InliningContext info = new RootInliningContext(expressionMap, state, @@ -269,14 +265,16 @@ public class InlineCodegen implements CallGenerator { boolean couldBeRemapped = !shouldPutValue(type, stackValue, valueParameterDescriptor); StackValue remappedIndex = couldBeRemapped ? stackValue : null; - ParameterInfo info = new ParameterInfo(type, false, couldBeRemapped ? -1 : codegen.getFrameMap().enterTemp(type), remappedIndex); - - if (capturedParamIndex >= 0 && couldBeRemapped) { - CapturedParamInfo capturedParamInfo = activeLambda.getCapturedVars().get(capturedParamIndex); - capturedParamInfo.setRemapValue(remappedIndex != null ? remappedIndex : StackValue.local(info.getIndex(), info.getType())); + ParameterInfo info; + if (capturedParamIndex >= 0) { + CapturedParamDesc capturedParamInfoInLambda = activeLambda.getCapturedVars().get(capturedParamIndex); + info = invocationParamBuilder.addCapturedParam(capturedParamInfoInLambda, capturedParamInfoInLambda.getFieldName()); + info.setRemapValue(remappedIndex); + } else { + info = invocationParamBuilder.addNextParameter(type, false, remappedIndex); } - doWithParameter(info); + putParameterOnStack(info); } } @@ -315,59 +313,49 @@ public class InlineCodegen implements CallGenerator { return true; } - private void doWithParameter(ParameterInfo info) { - recordParamInfo(info, true); - putParameterOnStack(info); - } - - private int recordParamInfo(ParameterInfo info, boolean addToFrame) { - Type type = info.type; - actualParameters.add(info); - if (info.getType().getSize() == 2) { - actualParameters.add(ParameterInfo.STUB); + private void putParameterOnStack(ParameterInfo ... infos) { + int [] index = new int[infos.length]; + for (int i = 0; i < infos.length; i++) { + ParameterInfo info = infos[i]; + if (!info.isSkippedOrRemapped()) { + index[i] = codegen.getFrameMap().enterTemp(info.getType()); + } else { + index[i] = -1; + } } - if (addToFrame) { - return originalFunctionFrame.enterTemp(type); - } - return -1; - } - private void putParameterOnStack(ParameterInfo info) { - if (!info.isSkippedOrRemapped()) { - int index = info.getIndex(); - Type type = info.type; - StackValue.local(index, type).store(type, codegen.v); + for (int i = infos.length - 1; i >= 0; i--) { + ParameterInfo info = infos[i]; + if (!info.isSkippedOrRemapped()) { + Type type = info.type; + StackValue.local(index[i], type).store(type, codegen.v); + } } } @Override public void putHiddenParams() { - List types = jvmSignature.getValueParameters(); + List valueParameters = jvmSignature.getValueParameters(); if (!isStaticMethod(functionDescriptor, context)) { - Type type = AsmTypeConstants.OBJECT_TYPE; - ParameterInfo info = new ParameterInfo(type, false, codegen.getFrameMap().enterTemp(type), -1); - recordParamInfo(info, false); + invocationParamBuilder.addNextParameter(AsmTypeConstants.OBJECT_TYPE, false, null); } - for (JvmMethodParameterSignature param : types) { + for (JvmMethodParameterSignature param : valueParameters) { if (param.getKind() == JvmMethodParameterKind.VALUE) { break; } - Type type = param.getAsmType(); - ParameterInfo info = new ParameterInfo(type, false, codegen.getFrameMap().enterTemp(type), -1); - recordParamInfo(info, false); + invocationParamBuilder.addNextParameter(param.getAsmType(), false, null); } - for (ListIterator iterator = actualParameters.listIterator(actualParameters.size()); iterator.hasPrevious(); ) { - ParameterInfo param = iterator.previous(); - putParameterOnStack(param); - } + List infos = invocationParamBuilder.listNotCaptured(); + putParameterOnStack(infos.toArray(new ParameterInfo[infos.size()])); } public void leaveTemps() { FrameMap frameMap = codegen.getFrameMap(); - for (ListIterator iterator = actualParameters.listIterator(actualParameters.size()); iterator.hasPrevious(); ) { + List infos = invocationParamBuilder.listAllParams(); + for (ListIterator iterator = infos.listIterator(infos.size()); iterator.hasPrevious(); ) { ParameterInfo param = iterator.previous(); if (!param.isSkippedOrRemapped()) { frameMap.leaveTemp(param.type); @@ -382,40 +370,24 @@ public class InlineCodegen implements CallGenerator { } public void rememberClosure(JetFunctionLiteralExpression expression, Type type) { - ParameterInfo closureInfo = new ParameterInfo(type, true, -1, -1); - int index = recordParamInfo(closureInfo, true); + ParameterInfo closureInfo = invocationParamBuilder.addNextParameter(type, true, null); LambdaInfo info = new LambdaInfo(expression, typeMapper); - expressionMap.put(index, info); + expressionMap.put(closureInfo.getIndex(), info); closureInfo.setLambda(info); } private void putClosureParametersOnStack() { - //TODO: SORT - int currentSize = actualParameters.size(); for (LambdaInfo next : expressionMap.values()) { if (next.closure != null) { activeLambda = next; - next.setParamOffset(currentSize); codegen.pushClosureOnStack(next.closure, false, this); - currentSize += next.getCapturedVarsSize(); } } activeLambda = null; } - private List getAllCaptured() { - //TODO: SORT - List result = new ArrayList(); - for (LambdaInfo next : expressionMap.values()) { - if (next.closure != null) { - result.addAll(next.getCapturedVars()); - } - } - return result; - } - public static CodegenContext getContext(DeclarationDescriptor descriptor, GenerationState state) { if (descriptor instanceof PackageFragmentDescriptor) { return new PackageContext((PackageFragmentDescriptor) descriptor, null, null); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/inline/LambdaInfo.java b/compiler/backend/src/org/jetbrains/jet/codegen/inline/LambdaInfo.java index cb7a398756f..a9c73f6187b 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/inline/LambdaInfo.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/inline/LambdaInfo.java @@ -18,6 +18,7 @@ package org.jetbrains.jet.codegen.inline; import org.jetbrains.annotations.NotNull; import org.jetbrains.org.objectweb.asm.Type; +import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode; import org.jetbrains.org.objectweb.asm.tree.MethodNode; import org.jetbrains.jet.codegen.AsmUtil; import org.jetbrains.jet.codegen.binding.CalculatedClosure; @@ -48,7 +49,7 @@ public class LambdaInfo implements CapturedParamOwner { private MethodNode node; - private List capturedVars; + private List capturedVars; private final FunctionDescriptor functionDescriptor; @@ -67,7 +68,6 @@ public class LambdaInfo implements CapturedParamOwner { closureClassType = asmTypeForAnonymousClass(bindingContext, functionDescriptor); closure = bindingContext.get(CLOSURE, classDescriptor); - } public MethodNode getNode() { @@ -94,11 +94,12 @@ public class LambdaInfo implements CapturedParamOwner { return closureClassType; } - public List getCapturedVars() { + public List getCapturedVars() { //lazy initialization cause it would be calculated after object creation int index = 0; if (capturedVars == null) { - capturedVars = new ArrayList(); + capturedVars = new ArrayList(); + assert closure != null : "Closure for lambda should be not null " + expression.getText(); if (closure.getCaptureThis() != null) { EnclosedValueDescriptor descriptor = new EnclosedValueDescriptor(AsmUtil.CAPTURED_THIS_FIELD, null, null, typeMapper.mapType(closure.getCaptureThis())); @@ -112,33 +113,28 @@ public class LambdaInfo implements CapturedParamOwner { index += descriptor.getType().getSize(); } - if (closure != null) { - for (EnclosedValueDescriptor descriptor : closure.getCaptureVariables().values()) { - capturedVars.add(getCapturedParamInfo(descriptor, index)); - index += descriptor.getType().getSize(); - } + for (EnclosedValueDescriptor descriptor : closure.getCaptureVariables().values()) { + capturedVars.add(getCapturedParamInfo(descriptor, index)); + index += descriptor.getType().getSize(); } } return capturedVars; } @NotNull - public CapturedParamInfo getCapturedParamInfo(@NotNull EnclosedValueDescriptor descriptor, int index) { - return new CapturedParamInfo(CapturedParamDesc.createDesc(this, descriptor.getFieldName(), descriptor.getType()), false, index, -1); - } - - public void setParamOffset(int paramOffset) { - for (CapturedParamInfo var : getCapturedVars()) { - var.setShift(paramOffset); - } + private CapturedParamDesc getCapturedParamInfo(@NotNull EnclosedValueDescriptor descriptor, int index) { + //return new CapturedParamInfo(CapturedParamDesc.createDesc(this, descriptor.getFieldName(), descriptor.getType()), false, index, -1); + return CapturedParamDesc.createDesc(this, descriptor.getFieldName(), descriptor.getType()); } + @NotNull public List getParamsWithoutCapturedValOrVar() { Type[] types = typeMapper.mapSignature(functionDescriptor).getAsmMethod().getArgumentTypes(); return Arrays.asList(types); } - public Parameters addAllParameters() { + @NotNull + public Parameters addAllParameters(FieldRemapper remapper) { ParametersBuilder builder = ParametersBuilder.newBuilder(); //add skipped this cause inlined lambda doesn't have it builder.addThis(AsmTypeConstants.OBJECT_TYPE, true).setLambda(this); @@ -149,21 +145,14 @@ public class LambdaInfo implements CapturedParamOwner { builder.addNextParameter(type, false, null); } - for (CapturedParamInfo info : getCapturedVars()) { - builder.addCapturedParam(info, info.getOriginalFieldName()); + for (CapturedParamDesc info : getCapturedVars()) { + CapturedParamInfo field = remapper.findField(new FieldInsnNode(0, info.getContainingLambdaName(), info.getFieldName(), "")); + builder.addCapturedParam(field, info.getFieldName()); } return builder.buildParameters(); } - public int getCapturedVarsSize() { - int size = 0; - for (CapturedParamInfo next : getCapturedVars()) { - size += next.getType().getSize(); - } - return size; - } - @Override public Type getType() { return closureClassType; 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 cc64c90d51e..31ee090ed99 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/inline/MethodInliner.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/inline/MethodInliner.java @@ -181,7 +181,7 @@ public class MethodInliner { int valueParamShift = getNextLocalIndex();//NB: don't inline cause it changes putStackValuesIntoLocals(info.getParamsWithoutCapturedValOrVar(), valueParamShift, this, desc); - Parameters lambdaParameters = info.addAllParameters(); + Parameters lambdaParameters = info.addAllParameters(nodeRemapper); InlinedLambdaRemapper newCapturedRemapper = new InlinedLambdaRemapper(info.getLambdaClassType().getInternalName(), nodeRemapper, lambdaParameters); @@ -207,8 +207,9 @@ public class MethodInliner { assert invocation != null : " call not corresponds to new call" + owner + " " + name; if (invocation.shouldRegenerate()) { //put additional captured parameters on stack - for (CapturedParamInfo capturedParamInfo : invocation.getAllRecapturedParameters()) { - visitFieldInsn(Opcodes.GETSTATIC, capturedParamInfo.getContainingLambdaName(), "$$$" + capturedParamInfo.getOriginalFieldName(), capturedParamInfo.getType().getDescriptor()); + for (CapturedParamDesc capturedParamDesc : invocation.getAllRecapturedParameters()) { + visitFieldInsn(Opcodes.GETSTATIC, capturedParamDesc.getContainingLambdaName(), + "$$$" + capturedParamDesc.getFieldName(), capturedParamDesc.getType().getDescriptor()); } super.visitMethodInsn(opcode, invocation.getNewLambdaType().getInternalName(), name, invocation.getNewConstructorDescriptor(), itf); invocation = null; diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/inline/ParameterInfo.java b/compiler/backend/src/org/jetbrains/jet/codegen/inline/ParameterInfo.java index 159f7b89d49..c6dbe80e407 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/inline/ParameterInfo.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/inline/ParameterInfo.java @@ -44,10 +44,10 @@ class ParameterInfo { this(type, skipped, index, remapValue == -1 ? null : StackValue.local(remapValue, type)); } - ParameterInfo(Type type, boolean skipped, int index, StackValue stackValue) { + ParameterInfo(@NotNull Type type, boolean skipped, int index, @Nullable StackValue remapValue) { this.type = type; this.isSkipped = skipped; - this.remapValue = stackValue; + this.remapValue = remapValue; this.index = index; } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/inline/ParametersBuilder.java b/compiler/backend/src/org/jetbrains/jet/codegen/inline/ParametersBuilder.java index 954c9641c00..68543c8d092 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/inline/ParametersBuilder.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/inline/ParametersBuilder.java @@ -18,6 +18,8 @@ package org.jetbrains.jet.codegen.inline; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.codegen.FrameMap; +import org.jetbrains.jet.codegen.StackValue; import org.jetbrains.org.objectweb.asm.Type; import java.util.ArrayList; @@ -32,19 +34,21 @@ public class ParametersBuilder { private int nextIndex = 0; private int nextCaptured = 0; + @NotNull public static ParametersBuilder newBuilder() { return new ParametersBuilder(); } - public ParameterInfo addThis(Type type, boolean skipped) { + @NotNull + public ParameterInfo addThis(@NotNull Type type, boolean skipped) { ParameterInfo info = new ParameterInfo(type, skipped, nextIndex, -1); addParameter(info); return info; } @NotNull - public ParameterInfo addNextParameter(@NotNull Type type, boolean skipped, @Nullable ParameterInfo original) { - return addParameter(new ParameterInfo(type, skipped, nextIndex, original != null ? original.getIndex() : -1)); + public ParameterInfo addNextParameter(@NotNull Type type, boolean skipped, @Nullable StackValue remapValue) { + return addParameter(new ParameterInfo(type, skipped, nextIndex, remapValue)); } @NotNull @@ -57,6 +61,15 @@ public class ParametersBuilder { return addCapturedParameter(info); } + @NotNull + public CapturedParamInfo addCapturedParam( + @NotNull CapturedParamDesc desc, + @NotNull String newFieldName + ) { + CapturedParamInfo info = new CapturedParamInfo(desc, newFieldName, false, nextCaptured, null); + return addCapturedParameter(info); + } + @NotNull public CapturedParamInfo addCapturedParamCopy( @NotNull CapturedParamInfo copyFrom @@ -82,12 +95,14 @@ public class ParametersBuilder { return addCapturedParameter(info); } + @NotNull private ParameterInfo addParameter(ParameterInfo info) { params.add(info); nextIndex += info.getType().getSize(); return info; } + @NotNull private CapturedParamInfo addCapturedParameter(CapturedParamInfo info) { capturedParams.add(info); nextCaptured += info.getType().getSize(); @@ -104,6 +119,13 @@ public class ParametersBuilder { return Collections.unmodifiableList(capturedParams); } + @NotNull + public List listAllParams() { + List list = new ArrayList(params); + list.addAll(capturedParams); + return list; + } + @NotNull private List buildWithStubs() { return Parameters.addStubs(listNotCaptured());