Parameter processing rewrote with parameter builder

Split capture parameter descriptor and it representation
This commit is contained in:
Mikhael Bogdanov
2014-06-03 14:08:57 +04:00
committed by Michael Bogdanov
parent 98e87f2f95
commit 30ddbb0682
9 changed files with 99 additions and 122 deletions
@@ -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<String, LambdaInfo> capturedLambdasToInline = new HashMap<String, LambdaInfo>(); //captured var of inlined parameter
List<CapturedParamInfo> allRecapturedParameters = new ArrayList<CapturedParamInfo>();
List<CapturedParamDesc> allRecapturedParameters = new ArrayList<CapturedParamDesc>();
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);
}
@@ -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();
}
}
@@ -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());
@@ -36,7 +36,7 @@ public class ConstructorInvocation {
private String newConstructorDescriptor;
private List<CapturedParamInfo> allRecapturedParameters;
private List<CapturedParamDesc> allRecapturedParameters;
private Map<String, LambdaInfo> capturedLambdasToInline;
@@ -84,11 +84,11 @@ public class ConstructorInvocation {
this.newConstructorDescriptor = newConstructorDescriptor;
}
public List<CapturedParamInfo> getAllRecapturedParameters() {
public List<CapturedParamDesc> getAllRecapturedParameters() {
return allRecapturedParameters;
}
public void setAllRecapturedParameters(List<CapturedParamInfo> allRecapturedParameters) {
public void setAllRecapturedParameters(List<CapturedParamDesc> allRecapturedParameters) {
this.allRecapturedParameters = allRecapturedParameters;
}
@@ -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<ParameterInfo> actualParameters = new ArrayList<ParameterInfo>();
protected final ParametersBuilder invocationParamBuilder = ParametersBuilder.newBuilder();
protected final Map<Integer, LambdaInfo> expressionMap = new HashMap<Integer, LambdaInfo>();
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<ParameterInfo> realParams = new ArrayList<ParameterInfo>(actualParameters);
//through generation captured parameters will be added to invocationParamBuilder
putClosureParametersOnStack();
List<CapturedParamInfo> 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<JvmMethodParameterSignature> types = jvmSignature.getValueParameters();
List<JvmMethodParameterSignature> 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<? extends ParameterInfo> iterator = actualParameters.listIterator(actualParameters.size()); iterator.hasPrevious(); ) {
ParameterInfo param = iterator.previous();
putParameterOnStack(param);
}
List<ParameterInfo> infos = invocationParamBuilder.listNotCaptured();
putParameterOnStack(infos.toArray(new ParameterInfo[infos.size()]));
}
public void leaveTemps() {
FrameMap frameMap = codegen.getFrameMap();
for (ListIterator<? extends ParameterInfo> iterator = actualParameters.listIterator(actualParameters.size()); iterator.hasPrevious(); ) {
List<ParameterInfo> infos = invocationParamBuilder.listAllParams();
for (ListIterator<? extends ParameterInfo> 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<CapturedParamInfo> getAllCaptured() {
//TODO: SORT
List<CapturedParamInfo> result = new ArrayList<CapturedParamInfo>();
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);
@@ -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<CapturedParamInfo> capturedVars;
private List<CapturedParamDesc> 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<CapturedParamInfo> getCapturedVars() {
public List<CapturedParamDesc> getCapturedVars() {
//lazy initialization cause it would be calculated after object creation
int index = 0;
if (capturedVars == null) {
capturedVars = new ArrayList<CapturedParamInfo>();
capturedVars = new ArrayList<CapturedParamDesc>();
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<Type> 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;
@@ -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 : "<init> 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;
@@ -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;
}
@@ -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<ParameterInfo> listAllParams() {
List<ParameterInfo> list = new ArrayList<ParameterInfo>(params);
list.addAll(capturedParams);
return list;
}
@NotNull
private List<ParameterInfo> buildWithStubs() {
return Parameters.addStubs(listNotCaptured());