Code simplification and clean
~special flag
This commit is contained in:
@@ -1711,7 +1711,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
|
||||
StackValue value = context.lookupInContext(descriptor, StackValue.local(0, OBJECT_TYPE), state, false);
|
||||
if (value != null) {
|
||||
if (context.isSpecialStackValue(value) != null) {
|
||||
if (context.isSpecialStackValue(value)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -2348,9 +2348,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
continue;
|
||||
}
|
||||
|
||||
boolean putInLocal = true;
|
||||
StackValue valueIfPresent = null;
|
||||
|
||||
ResolvedValueArgument resolvedValueArgument = valueArguments.get(valueParameter.getIndex());
|
||||
Type parameterType = valueParameterTypes.get(valueParameter.getIndex());
|
||||
if (resolvedValueArgument instanceof ExpressionValueArgument) {
|
||||
@@ -2362,7 +2359,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
//TODO deparenthisise
|
||||
if (callGenerator.isInliningClosure(argumentExpression, valueParameter)) {
|
||||
callGenerator.rememberClosure((JetFunctionLiteralExpression) argumentExpression, parameterType);
|
||||
putInLocal = false;
|
||||
} else {
|
||||
StackValue value = gen(argumentExpression);
|
||||
if (callGenerator.shouldPutValue(parameterType, value, valueParameter)) {
|
||||
@@ -2373,18 +2369,16 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
} else if (resolvedValueArgument instanceof DefaultValueArgument) {
|
||||
pushDefaultValueOnStack(parameterType, v);
|
||||
mask |= (1 << valueParameter.getIndex());
|
||||
callGenerator.putInLocal(parameterType, null, valueParameter);
|
||||
}
|
||||
else if (resolvedValueArgument instanceof VarargValueArgument) {
|
||||
VarargValueArgument valueArgument = (VarargValueArgument) resolvedValueArgument;
|
||||
genVarargs(valueParameter, valueArgument);
|
||||
callGenerator.putInLocal(parameterType, null, valueParameter);
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
if (putInLocal) {
|
||||
callGenerator.putInLocal(parameterType, valueIfPresent, valueParameter);
|
||||
}
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
||||
@@ -104,17 +104,14 @@ public class MethodContext extends CodegenContext<CallableMemberDescriptor> {
|
||||
return isInlineClosure;
|
||||
}
|
||||
|
||||
public StackValue isSpecialStackValue(StackValue stackValue) {
|
||||
public boolean isSpecialStackValue(StackValue stackValue) {
|
||||
if (isInlineClosure && stackValue instanceof StackValue.Composed) {
|
||||
StackValue prefix = ((StackValue.Composed) stackValue).prefix;
|
||||
StackValue suffix = ((StackValue.Composed) stackValue).suffix;
|
||||
if (prefix instanceof StackValue.Local && ((StackValue.Local) prefix).index == 0) {
|
||||
if (suffix instanceof StackValue.Field) {
|
||||
StackValue.Field field = (StackValue.Field) suffix;
|
||||
return StackValue.field(field.type, field.owner, field.name, true);
|
||||
}
|
||||
return suffix instanceof StackValue.Field;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,20 +62,8 @@ public class CapturedParamInfo extends ParameterInfo {
|
||||
this.recapturedFrom = recapturedFrom;
|
||||
}
|
||||
|
||||
|
||||
public CapturedParamInfo newRemapIndex(int newRamapIndex) {
|
||||
return clone(index, newRamapIndex);
|
||||
}
|
||||
|
||||
public CapturedParamInfo newIndex(int newIndex) {
|
||||
return clone(newIndex, getRemapIndex());
|
||||
}
|
||||
|
||||
public CapturedParamInfo clone(int newIndex, int newRamapIndex) {
|
||||
CapturedParamInfo capturedParamInfo = new CapturedParamInfo(fieldName, type, isSkipped, newIndex, newRamapIndex);
|
||||
capturedParamInfo.setLambda(lambda);
|
||||
capturedParamInfo.setRecapturedFrom(recapturedFrom);
|
||||
return capturedParamInfo;
|
||||
return clone(newIndex, getRemapValue());
|
||||
}
|
||||
|
||||
public CapturedParamInfo clone(int newIndex, StackValue newRamapIndex) {
|
||||
|
||||
@@ -25,9 +25,9 @@ public class ConstructorInvocation {
|
||||
|
||||
private final String ownerInternalName;
|
||||
|
||||
private final Map<Integer, InlinableAccess> access;
|
||||
private final Map<Integer, InvokeCall> access;
|
||||
|
||||
private boolean isSameModule;
|
||||
private final boolean isSameModule;
|
||||
|
||||
private Type newLambdaType;
|
||||
|
||||
@@ -37,7 +37,7 @@ public class ConstructorInvocation {
|
||||
|
||||
private Map<String, LambdaInfo> recapturedLambdas;
|
||||
|
||||
ConstructorInvocation(String ownerInternalName, Map<Integer, InlinableAccess> access, boolean isSameModule) {
|
||||
ConstructorInvocation(String ownerInternalName, Map<Integer, InvokeCall> access, boolean isSameModule) {
|
||||
this.ownerInternalName = ownerInternalName;
|
||||
this.access = access;
|
||||
this.isSameModule = isSameModule;
|
||||
@@ -51,7 +51,7 @@ public class ConstructorInvocation {
|
||||
return !access.isEmpty() || !isSameModule;
|
||||
}
|
||||
|
||||
public Map<Integer, InlinableAccess> getAccess() {
|
||||
public Map<Integer, InvokeCall> getAccess() {
|
||||
return access;
|
||||
}
|
||||
|
||||
|
||||
@@ -75,19 +75,17 @@ public class InlineAdapter extends InstructionAdapter {
|
||||
public void visitTryCatchBlock(Label start,
|
||||
Label end, Label handler, String type) {
|
||||
if(!isInlining) {
|
||||
blocks.add(new CatchBlock(start, end,
|
||||
handler, type));
|
||||
} else {
|
||||
super.visitTryCatchBlock(start, end,
|
||||
handler, type);
|
||||
blocks.add(new CatchBlock(start, end, handler, type));
|
||||
}
|
||||
else {
|
||||
super.visitTryCatchBlock(start, end, handler, type);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMaxs(int stack, int locals) {
|
||||
for (CatchBlock b : blocks) {
|
||||
super.visitTryCatchBlock(b.start, b.end,
|
||||
b.handler, b.type);
|
||||
super.visitTryCatchBlock(b.start, b.end, b.handler, b.type);
|
||||
}
|
||||
super.visitMaxs(stack, locals);
|
||||
}
|
||||
|
||||
@@ -89,8 +89,6 @@ public class InlineCodegen implements ParentCodegenAware, CallGenerator {
|
||||
|
||||
protected final Map<Integer, LambdaInfo> expressionMap = new HashMap<Integer, LambdaInfo>();
|
||||
|
||||
private SimpleFunctionDescriptor inlineFunctionDescriptor;
|
||||
|
||||
public InlineCodegen(
|
||||
@NotNull ExpressionCodegen codegen,
|
||||
@NotNull GenerationState state,
|
||||
@@ -98,7 +96,6 @@ public class InlineCodegen implements ParentCodegenAware, CallGenerator {
|
||||
@NotNull Call call
|
||||
) {
|
||||
assert functionDescriptor.getInlineStrategy().isInline() : "InlineCodegen could inline only inline function but " + functionDescriptor;
|
||||
inlineFunctionDescriptor = functionDescriptor;
|
||||
|
||||
this.state = state;
|
||||
this.typeMapper = state.getTypeMapper();
|
||||
@@ -117,7 +114,7 @@ public class InlineCodegen implements ParentCodegenAware, CallGenerator {
|
||||
this.asFunctionInline = false;
|
||||
|
||||
isSameModule = !(functionDescriptor instanceof DeserializedSimpleFunctionDescriptor) /*not compiled library*/ &&
|
||||
CodegenUtil.isCallInsideSameModuleAsDeclared(inlineFunctionDescriptor, codegen.getContext());
|
||||
CodegenUtil.isCallInsideSameModuleAsDeclared(functionDescriptor, codegen.getContext());
|
||||
}
|
||||
|
||||
|
||||
@@ -262,26 +259,21 @@ public class InlineCodegen implements ParentCodegenAware, CallGenerator {
|
||||
|
||||
if (index >= 0 && couldBeRemapped) {
|
||||
CapturedParamInfo capturedParamInfo = activeLambda.getCapturedVars().get(index);
|
||||
capturedParamInfo.setRemapIndex(remappedIndex != null ? remappedIndex : StackValue.local(info.getIndex(), info.getType()));
|
||||
capturedParamInfo.setRemapValue(remappedIndex != null ? remappedIndex : StackValue.local(info.getIndex(), info.getType()));
|
||||
}
|
||||
|
||||
doWithParameter(info);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*descriptor is null for captured vars*/
|
||||
@Override
|
||||
public boolean shouldPutValue(
|
||||
@NotNull Type type,
|
||||
@Nullable StackValue stackValue,
|
||||
ValueParameterDescriptor descriptor
|
||||
@Nullable ValueParameterDescriptor descriptor
|
||||
) {
|
||||
//boolean isInline = true/*context.isInlineFunction() || context.getParentContext() instanceof ClosureContext*/;
|
||||
//if (stackValue != null && isInline && stackValue instanceof StackValue.Local) {
|
||||
// if (isInvokeOnInlinable(type.getClassName(), "invoke") && (descriptor == null || !InlineUtil.hasNoinlineAnnotation(descriptor))) {
|
||||
// //TODO remap only inlinable closure => otherwise we could get a lot of problem
|
||||
// return false;
|
||||
// }
|
||||
//}
|
||||
|
||||
if (stackValue == null) {
|
||||
//default or vararg
|
||||
@@ -299,22 +291,13 @@ public class InlineCodegen implements ParentCodegenAware, CallGenerator {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (codegen.getContext().isInlineClosure() && codegen.getContext().getContextDescriptor() instanceof AnonymousFunctionDescriptor) {
|
||||
Type internalName = asmTypeForAnonymousClass(bindingContext, (FunctionDescriptor) codegen.getContext().getContextDescriptor());
|
||||
|
||||
String owner = null;
|
||||
if (stackValue instanceof StackValue.Field) {
|
||||
owner = ((StackValue.Field) stackValue).owner.getInternalName();
|
||||
}
|
||||
|
||||
if (stackValue instanceof StackValue.Composed) {
|
||||
//go through aload 0
|
||||
owner = internalName.getInternalName();
|
||||
}
|
||||
|
||||
if (descriptor != null && !InlineUtil.hasNoinlineAnnotation(descriptor) && internalName.getInternalName().equals(owner)) {
|
||||
//check type of context
|
||||
return false;
|
||||
if (stackValue instanceof StackValue.Composed) {
|
||||
//see: Method.isSpecialStackValue: go through aload 0
|
||||
if (codegen.getContext().isInlineClosure() && codegen.getContext().getContextDescriptor() instanceof AnonymousFunctionDescriptor) {
|
||||
if (descriptor != null && !InlineUtil.hasNoinlineAnnotation(descriptor)) {
|
||||
//TODO: check type of context
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -189,7 +189,7 @@ public class InlineCodegenUtil {
|
||||
}
|
||||
|
||||
|
||||
public static boolean isInvokeOnInlinable(String owner, String name) {
|
||||
public static boolean isInvokeOnLambda(String owner, String name) {
|
||||
return INVOKE.equals(name) && /*TODO: check type*/owner.contains("Function");
|
||||
}
|
||||
|
||||
|
||||
@@ -27,8 +27,6 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.jetbrains.jet.codegen.inline.MethodInliner.getPreviousNoLabelNoLine;
|
||||
|
||||
public class InlineFieldRemapper extends LambdaFieldRemapper {
|
||||
|
||||
private final String oldOwnerType;
|
||||
@@ -50,18 +48,14 @@ public class InlineFieldRemapper extends LambdaFieldRemapper {
|
||||
public AbstractInsnNode doTransform(
|
||||
MethodNode node, FieldInsnNode fieldInsnNode, CapturedParamInfo capturedField
|
||||
) {
|
||||
boolean isRecaptured = isRecapruredLambdaType(fieldInsnNode.owner);
|
||||
boolean isRecaptured = isRecapturedLambdaType(fieldInsnNode.owner);
|
||||
|
||||
if (!isRecaptured && capturedField.getLambda() != null) {
|
||||
//strict inlining
|
||||
return super.doTransform(node, fieldInsnNode, capturedField);
|
||||
}
|
||||
|
||||
AbstractInsnNode prev = getPreviousNoLabelNoLine(fieldInsnNode);
|
||||
|
||||
assert prev.getType() == AbstractInsnNode.VAR_INSN || prev.getType() == AbstractInsnNode.FIELD_INSN;
|
||||
AbstractInsnNode loadThis = prev;
|
||||
assert /*loadThis.var == info.getCapturedVarsSize() - 1 && */loadThis.getOpcode() == Opcodes.ALOAD || loadThis.getOpcode() == Opcodes.GETSTATIC;
|
||||
AbstractInsnNode loadThis = getPreviousThis(fieldInsnNode);
|
||||
|
||||
int opcode = Opcodes.GETSTATIC;
|
||||
|
||||
@@ -95,10 +89,10 @@ public class InlineFieldRemapper extends LambdaFieldRemapper {
|
||||
|
||||
@Override
|
||||
public boolean canProcess(String owner, String currentLambdaType) {
|
||||
return super.canProcess(owner, currentLambdaType) || isRecapruredLambdaType(owner);
|
||||
return super.canProcess(owner, currentLambdaType) || isRecapturedLambdaType(owner);
|
||||
}
|
||||
|
||||
private boolean isRecapruredLambdaType(String owner) {
|
||||
private boolean isRecapturedLambdaType(String owner) {
|
||||
return recapturedLambdas.containsKey(owner);
|
||||
}
|
||||
|
||||
@@ -106,7 +100,7 @@ public class InlineFieldRemapper extends LambdaFieldRemapper {
|
||||
@Nullable
|
||||
@Override
|
||||
public CapturedParamInfo findField(FieldInsnNode fieldInsnNode, Collection<CapturedParamInfo> captured) {
|
||||
if (!isRecapruredLambdaType(fieldInsnNode.owner)) {
|
||||
if (!isRecapturedLambdaType(fieldInsnNode.owner)) {
|
||||
return super.findField(fieldInsnNode, captured);
|
||||
} else {
|
||||
LambdaInfo info = recapturedLambdas.get(fieldInsnNode.owner);
|
||||
|
||||
@@ -29,7 +29,7 @@ public class InliningInfo {
|
||||
|
||||
public final Map<Integer, LambdaInfo> expresssionMap;
|
||||
|
||||
public final List<InlinableAccess> inlinableAccesses;
|
||||
public final List<InvokeCall> invokeCalls;
|
||||
|
||||
public final List<ConstructorInvocation> constructorInvocation;
|
||||
|
||||
@@ -47,7 +47,7 @@ public class InliningInfo {
|
||||
|
||||
public InliningInfo(
|
||||
Map<Integer, LambdaInfo> map,
|
||||
List<InlinableAccess> accesses,
|
||||
List<InvokeCall> accesses,
|
||||
List<ConstructorInvocation> invocation,
|
||||
VarRemapper remapper,
|
||||
GenerationState state,
|
||||
@@ -57,7 +57,7 @@ public class InliningInfo {
|
||||
Map<String, String> typeMapping
|
||||
) {
|
||||
expresssionMap = map;
|
||||
inlinableAccesses = accesses;
|
||||
invokeCalls = accesses;
|
||||
constructorInvocation = invocation;
|
||||
this.remapper = remapper;
|
||||
this.state = state;
|
||||
@@ -74,7 +74,7 @@ public class InliningInfo {
|
||||
public InliningInfo subInline(NameGenerator generator, Map<String, String> additionalTypeMappings) {
|
||||
HashMap<String, String> newTypeMappings = new HashMap<String, String>(typeMapping);
|
||||
newTypeMappings.putAll(additionalTypeMappings);
|
||||
return new InliningInfo(expresssionMap, inlinableAccesses, constructorInvocation, remapper, state, generator, startContext, call,
|
||||
return new InliningInfo(expresssionMap, invokeCalls, constructorInvocation, remapper, state, generator, startContext, call,
|
||||
newTypeMappings);
|
||||
}
|
||||
}
|
||||
|
||||
+4
-28
@@ -18,38 +18,14 @@ package org.jetbrains.jet.codegen.inline;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
class InlinableAccess {
|
||||
class InvokeCall {
|
||||
|
||||
public final int index;
|
||||
|
||||
public final boolean inlinable;
|
||||
public final LambdaInfo lambdaInfo;
|
||||
|
||||
private final List<ParameterInfo> parameters;
|
||||
|
||||
private LambdaInfo info;
|
||||
|
||||
InlinableAccess(int index, boolean isInlinable, List<ParameterInfo> parameterInfos) {
|
||||
InvokeCall(int index, @Nullable LambdaInfo lambdaInfo) {
|
||||
this.index = index;
|
||||
inlinable = isInlinable;
|
||||
this.parameters = parameterInfos;
|
||||
}
|
||||
|
||||
public boolean isInlinable() {
|
||||
return inlinable;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public LambdaInfo getInfo() {
|
||||
return info;
|
||||
}
|
||||
|
||||
public void setInfo(LambdaInfo info) {
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
public List<ParameterInfo> getParameters() {
|
||||
return parameters;
|
||||
this.lambdaInfo = lambdaInfo;
|
||||
}
|
||||
}
|
||||
@@ -31,21 +31,26 @@ import static org.jetbrains.jet.codegen.inline.MethodInliner.getPreviousNoLabelN
|
||||
public class LambdaFieldRemapper {
|
||||
|
||||
public AbstractInsnNode doTransform(MethodNode node, FieldInsnNode fieldInsnNode, CapturedParamInfo capturedField) {
|
||||
AbstractInsnNode prev = getPreviousNoLabelNoLine(fieldInsnNode);
|
||||
|
||||
assert prev.getType() == AbstractInsnNode.VAR_INSN || prev.getType() == AbstractInsnNode.FIELD_INSN;
|
||||
AbstractInsnNode loadThis = prev;
|
||||
int opcode1 = loadThis.getOpcode();
|
||||
assert /*loadThis.var == info.getCapturedVarsSize() - 1 && */opcode1 == Opcodes.ALOAD || opcode1 == Opcodes.GETSTATIC;
|
||||
AbstractInsnNode loadThis = getPreviousThis(fieldInsnNode);
|
||||
|
||||
int opcode = fieldInsnNode.getOpcode() == Opcodes.GETFIELD ? capturedField.getType().getOpcode(Opcodes.ILOAD) : capturedField.getType().getOpcode(Opcodes.ISTORE);
|
||||
VarInsnNode insn = new VarInsnNode(opcode, capturedField.getIndex());
|
||||
VarInsnNode newInstruction = new VarInsnNode(opcode, capturedField.getIndex());
|
||||
|
||||
node.instructions.remove(prev); //remove aload this
|
||||
node.instructions.insertBefore(fieldInsnNode, insn);
|
||||
node.instructions.remove(loadThis); //remove aload this
|
||||
node.instructions.insertBefore(fieldInsnNode, newInstruction);
|
||||
node.instructions.remove(fieldInsnNode); //remove aload field
|
||||
|
||||
return insn;
|
||||
return newInstruction;
|
||||
}
|
||||
|
||||
protected static AbstractInsnNode getPreviousThis(FieldInsnNode fieldInsnNode) {
|
||||
AbstractInsnNode loadThis = getPreviousNoLabelNoLine(fieldInsnNode);
|
||||
|
||||
assert loadThis.getType() == AbstractInsnNode.VAR_INSN || loadThis.getType() == AbstractInsnNode.FIELD_INSN :
|
||||
"Field access instruction should go after load this but goes after " + loadThis;
|
||||
assert loadThis.getOpcode() == Opcodes.ALOAD || loadThis.getOpcode() == Opcodes.GETSTATIC :
|
||||
"This should be loaded by ALOAD or GETSTATIC but " + loadThis.getOpcode();
|
||||
return loadThis;
|
||||
}
|
||||
|
||||
public List<CapturedParamInfo> markRecaptured(List<CapturedParamInfo> originalCaptured, LambdaInfo lambda) {
|
||||
@@ -59,14 +64,11 @@ public class LambdaFieldRemapper {
|
||||
|
||||
@Nullable
|
||||
public CapturedParamInfo findField(FieldInsnNode fieldInsnNode, Collection<CapturedParamInfo> captured) {
|
||||
String name = fieldInsnNode.name;
|
||||
CapturedParamInfo result = null;
|
||||
for (CapturedParamInfo valueDescriptor : captured) {
|
||||
if (valueDescriptor.getFieldName().equals(name)) {
|
||||
result = valueDescriptor;
|
||||
break;
|
||||
if (valueDescriptor.getFieldName().equals(fieldInsnNode.name)) {
|
||||
return valueDescriptor;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,9 +25,11 @@ import org.jetbrains.jet.codegen.context.EnclosedValueDescriptor;
|
||||
import org.jetbrains.jet.codegen.state.JetTypeMapper;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetFunctionLiteral;
|
||||
import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -39,7 +41,8 @@ public class LambdaInfo {
|
||||
|
||||
public final JetFunctionLiteralExpression expression;
|
||||
|
||||
@NotNull private final JetTypeMapper typeMapper;
|
||||
@NotNull
|
||||
private final JetTypeMapper typeMapper;
|
||||
|
||||
public final CalculatedClosure closure;
|
||||
|
||||
@@ -53,8 +56,6 @@ public class LambdaInfo {
|
||||
|
||||
private final Type closureClassType;
|
||||
|
||||
private int paramOffset;
|
||||
|
||||
LambdaInfo(@NotNull JetFunctionLiteralExpression expression, @NotNull JetTypeMapper typeMapper) {
|
||||
this.expression = expression;
|
||||
this.typeMapper = typeMapper;
|
||||
@@ -126,19 +127,10 @@ public class LambdaInfo {
|
||||
return new CapturedParamInfo(descriptor.getFieldName(), descriptor.getType(), false, index, -1);
|
||||
}
|
||||
|
||||
private void shiftParams(int shift) {
|
||||
for (CapturedParamInfo var : getCapturedVars()) {
|
||||
var.setShift(shift);
|
||||
}
|
||||
}
|
||||
|
||||
public int getParamOffset() {
|
||||
return paramOffset;
|
||||
}
|
||||
|
||||
public void setParamOffset(int paramOffset) {
|
||||
this.paramOffset = paramOffset;
|
||||
shiftParams(paramOffset);
|
||||
for (CapturedParamInfo var : getCapturedVars()) {
|
||||
var.setShift(paramOffset);
|
||||
}
|
||||
}
|
||||
|
||||
public List<Type> getParamsWithoutCapturedValOrVar() {
|
||||
@@ -146,6 +138,25 @@ public class LambdaInfo {
|
||||
return Arrays.asList(types);
|
||||
}
|
||||
|
||||
public Parameters addAllParameters(@NotNull LambdaFieldRemapper remapper) {
|
||||
ParametersBuilder builder = ParametersBuilder.newBuilder();
|
||||
//add skipped this cause inlined lambda doesn't have it
|
||||
builder.addThis(AsmTypeConstants.OBJECT_TYPE, true).setLambda(this);
|
||||
|
||||
List<ValueParameterDescriptor> valueParameters = getFunctionDescriptor().getValueParameters();
|
||||
for (ValueParameterDescriptor parameter : valueParameters) {
|
||||
Type type = typeMapper.mapType(parameter.getType());
|
||||
builder.addNextParameter(type, false, null);
|
||||
}
|
||||
|
||||
|
||||
List<CapturedParamInfo> infos = remapper.markRecaptured(getCapturedVars(), this);
|
||||
for (CapturedParamInfo info : infos) {
|
||||
builder.addCapturedParam(info.getFieldName(), info.getType(), info.isSkipped, info);
|
||||
}
|
||||
return builder.buildParameters();
|
||||
}
|
||||
|
||||
public int getCapturedVarsSize() {
|
||||
int size = 0;
|
||||
for (CapturedParamInfo next : getCapturedVars()) {
|
||||
|
||||
@@ -65,7 +65,7 @@ public class LambdaTransformer {
|
||||
private String signature;
|
||||
private String superName;
|
||||
private String[] interfaces;
|
||||
private boolean isSameModule;
|
||||
private final boolean isSameModule;
|
||||
|
||||
public LambdaTransformer(String lambdaInternalName, InliningInfo info, boolean isSameModule, Type newLambdaType) {
|
||||
this.isSameModule = isSameModule;
|
||||
@@ -189,7 +189,7 @@ public class LambdaTransformer {
|
||||
}
|
||||
|
||||
private void extractParametersMapping(MethodNode constructor, ParametersBuilder builder, ConstructorInvocation invocation) {
|
||||
Map<Integer, InlinableAccess> indexToLambda = invocation.getAccess();
|
||||
Map<Integer, InvokeCall> indexToLambda = invocation.getAccess();
|
||||
|
||||
AbstractInsnNode cur = constructor.instructions.getFirst();
|
||||
cur = cur.getNext(); //skip super call
|
||||
@@ -202,9 +202,9 @@ public class LambdaTransformer {
|
||||
paramMapping.put(fieldNode.name, varIndex);
|
||||
|
||||
CapturedParamInfo info = builder.addCapturedParam(fieldNode.name, Type.getType(fieldNode.desc), false, null);
|
||||
InlinableAccess access = indexToLambda.get(varIndex);
|
||||
InvokeCall access = indexToLambda.get(varIndex);
|
||||
if (access != null) {
|
||||
LambdaInfo accessInfo = access.getInfo();
|
||||
LambdaInfo accessInfo = access.lambdaInfo;
|
||||
if (accessInfo != null) {
|
||||
info.setLambda(accessInfo);
|
||||
additionalCaptured.add(accessInfo);
|
||||
|
||||
@@ -16,8 +16,7 @@ import org.jetbrains.asm4.tree.analysis.*;
|
||||
import org.jetbrains.jet.codegen.ClosureCodegen;
|
||||
import org.jetbrains.jet.codegen.StackValue;
|
||||
import org.jetbrains.jet.codegen.state.JetTypeMapper;
|
||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
|
||||
import org.jetbrains.jet.utils.UtilsPackage;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -32,18 +31,18 @@ public class MethodInliner {
|
||||
private final InliningInfo parent;
|
||||
|
||||
@Nullable
|
||||
private final Type lambdaInfo;
|
||||
private final Type lambdaType;
|
||||
|
||||
private final LambdaFieldRemapper lambdaFieldRemapper;
|
||||
|
||||
private boolean isSameModule;
|
||||
private final boolean isSameModule;
|
||||
|
||||
private final JetTypeMapper typeMapper;
|
||||
|
||||
private final List<InlinableAccess> inlinableInvocation = new ArrayList<InlinableAccess>();
|
||||
private final List<InvokeCall> invokeCalls = new ArrayList<InvokeCall>();
|
||||
|
||||
//keeps order
|
||||
private final List<ConstructorInvocation> constructorInvocationList = new ArrayList<ConstructorInvocation>();
|
||||
private final List<ConstructorInvocation> constructorInvocations = new ArrayList<ConstructorInvocation>();
|
||||
//current state
|
||||
private final Map<String, String> currentTypeMapping = new HashMap<String, String>();
|
||||
|
||||
@@ -52,20 +51,20 @@ public class MethodInliner {
|
||||
* @param node
|
||||
* @param parameters
|
||||
* @param parent
|
||||
* @param lambdaInfo - in case on lambda 'invoke' inlining
|
||||
* @param lambdaType - in case on lambda 'invoke' inlining
|
||||
*/
|
||||
public MethodInliner(
|
||||
@NotNull MethodNode node,
|
||||
Parameters parameters,
|
||||
@NotNull Parameters parameters,
|
||||
@NotNull InliningInfo parent,
|
||||
@Nullable Type lambdaInfo,
|
||||
@Nullable Type lambdaType,
|
||||
LambdaFieldRemapper lambdaFieldRemapper,
|
||||
boolean isSameModule
|
||||
) {
|
||||
this.node = node;
|
||||
this.parameters = parameters;
|
||||
this.parent = parent;
|
||||
this.lambdaInfo = lambdaInfo;
|
||||
this.lambdaType = lambdaType;
|
||||
this.lambdaFieldRemapper = lambdaFieldRemapper;
|
||||
this.isSameModule = isSameModule;
|
||||
this.typeMapper = parent.state.getTypeMapper();
|
||||
@@ -87,7 +86,7 @@ public class MethodInliner {
|
||||
transformedNode = markPlacesForInlineAndRemoveInlinable(transformedNode);
|
||||
}
|
||||
catch (AnalyzerException e) {
|
||||
throw new RuntimeException(e);
|
||||
throw UtilsPackage.rethrow(e);
|
||||
}
|
||||
|
||||
transformedNode = doInline(transformedNode, capturedRemapper);
|
||||
@@ -103,11 +102,11 @@ public class MethodInliner {
|
||||
|
||||
private MethodNode doInline(MethodNode node, final LambdaFieldRemapper capturedRemapper) {
|
||||
|
||||
final Deque<InlinableAccess> infos = new LinkedList<InlinableAccess>(inlinableInvocation);
|
||||
final Deque<InvokeCall> currentInvokes = new LinkedList<InvokeCall>(invokeCalls);
|
||||
|
||||
MethodNode resultNode = new MethodNode(node.access, node.name, node.desc, node.signature, null);
|
||||
|
||||
final Iterator<ConstructorInvocation> iterator = constructorInvocationList.iterator();
|
||||
final Iterator<ConstructorInvocation> iterator = constructorInvocations.iterator();
|
||||
|
||||
RemappingMethodAdapter remappingMethodAdapter = new RemappingMethodAdapter(resultNode.access, resultNode.desc, resultNode,
|
||||
new TypeRemapper(currentTypeMapping, isSameModule));
|
||||
@@ -137,35 +136,34 @@ public class MethodInliner {
|
||||
|
||||
@Override
|
||||
public void visitMethodInsn(int opcode, String owner, String name, String desc) {
|
||||
if (/*INLINE_RUNTIME.equals(owner) &&*/ isInvokeOnInlinable(owner, name)) { //TODO add method
|
||||
assert !infos.isEmpty();
|
||||
InlinableAccess inlinableAccess = infos.remove();
|
||||
if (/*INLINE_RUNTIME.equals(owner) &&*/ isInvokeOnLambda(owner, name)) { //TODO add method
|
||||
assert !currentInvokes.isEmpty();
|
||||
InvokeCall invokeCall = currentInvokes.remove();
|
||||
LambdaInfo info = invokeCall.lambdaInfo;
|
||||
|
||||
if (!inlinableAccess.isInlinable()) {
|
||||
//noninlinable closure
|
||||
if (info == null) {
|
||||
//noninlinable lambda
|
||||
super.visitMethodInsn(opcode, owner, name, desc);
|
||||
return;
|
||||
}
|
||||
LambdaInfo info = getLambda(inlinableAccess.index);
|
||||
|
||||
int valueParamShift = getNextLocalIndex();
|
||||
|
||||
int valueParamShift = getNextLocalIndex();//NB: don't inline cause it changes
|
||||
putStackValuesIntoLocals(info.getParamsWithoutCapturedValOrVar(), valueParamShift, this, desc);
|
||||
|
||||
List<ParameterInfo> lambdaParameters = inlinableAccess.getParameters();
|
||||
Parameters lambdaParameters = info.addAllParameters(capturedRemapper);
|
||||
|
||||
Parameters params = new Parameters(lambdaParameters, Parameters.transformList(capturedRemapper.markRecaptured(info.getCapturedVars(), info), lambdaParameters.size()));
|
||||
setInlining(true);
|
||||
MethodInliner inliner = new MethodInliner(info.getNode(), lambdaParameters, parent.subInline(parent.nameGenerator.subGenerator("lambda")), info.getLambdaClassType(),
|
||||
capturedRemapper, true /*cause all calls in same module as lambda*/);
|
||||
|
||||
this.setInlining(true);
|
||||
MethodInliner inliner = new MethodInliner(info.getNode(), params, parent.subInline(parent.nameGenerator.subGenerator("lambda")), info.getLambdaClassType(),
|
||||
capturedRemapper, true /*cause all call in same module as lambda*/);
|
||||
|
||||
VarRemapper.ParamRemapper remapper = new VarRemapper.ParamRemapper(params, valueParamShift);
|
||||
VarRemapper.ParamRemapper remapper = new VarRemapper.ParamRemapper(lambdaParameters, valueParamShift);
|
||||
inliner.doTransformAndMerge(this.mv, remapper); //TODO add skipped this and receiver
|
||||
|
||||
//return value boxing/unboxing
|
||||
Method bridge = typeMapper.mapSignature(ClosureCodegen.getInvokeFunction(info.getFunctionDescriptor())).getAsmMethod();
|
||||
Method delegate = typeMapper.mapSignature(info.getFunctionDescriptor()).getAsmMethod();
|
||||
StackValue.onStack(delegate.getReturnType()).put(bridge.getReturnType(), this);
|
||||
this.setInlining(true);
|
||||
setInlining(false);
|
||||
}
|
||||
else if (isLambdaConstructorCall(owner, name)) { //TODO add method
|
||||
assert invocation != null : "<init> call not corresponds to new call" + owner + " " + name;
|
||||
@@ -248,12 +246,12 @@ public class MethodInliner {
|
||||
|
||||
node.accept(transformedNode);
|
||||
|
||||
if (lambdaInfo != null) {
|
||||
transformCaptured(transformedNode, parameters, lambdaInfo, lambdaFieldRemapper);
|
||||
}
|
||||
transformCaptured(transformedNode);
|
||||
|
||||
return transformedNode;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected MethodNode markPlacesForInlineAndRemoveInlinable(@NotNull MethodNode node) throws AnalyzerException {
|
||||
node = prepareNode(node);
|
||||
|
||||
@@ -275,10 +273,9 @@ public class MethodInliner {
|
||||
String name = methodInsnNode.name;
|
||||
//TODO check closure
|
||||
int paramLength = Type.getArgumentTypes(desc).length + 1;//non static
|
||||
if (isInvokeOnInlinable(owner, name) /*&& methodInsnNode.owner.equals(INLINE_RUNTIME)*/) {
|
||||
if (isInvokeOnLambda(owner, name) /*&& methodInsnNode.owner.equals(INLINE_RUNTIME)*/) {
|
||||
SourceValue sourceValue = frame.getStack(frame.getStackSize() - paramLength);
|
||||
|
||||
boolean isInlinable = false;
|
||||
LambdaInfo lambdaInfo = null;
|
||||
int varIndex = -1;
|
||||
|
||||
@@ -288,19 +285,18 @@ public class MethodInliner {
|
||||
assert insnNode.getOpcode() == Opcodes.ALOAD : insnNode.toString();
|
||||
varIndex = ((VarInsnNode) insnNode).var;
|
||||
lambdaInfo = getLambda(varIndex);
|
||||
isInlinable = lambdaInfo != null;
|
||||
|
||||
if (isInlinable) {
|
||||
if (lambdaInfo != null) {
|
||||
//remove inlinable access
|
||||
node.instructions.remove(insnNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inlinableInvocation.add(new InlinableAccess(varIndex, isInlinable, getParametersInfo(lambdaInfo, desc)));
|
||||
invokeCalls.add(new InvokeCall(varIndex, lambdaInfo));
|
||||
}
|
||||
else if (isLambdaConstructorCall(owner, name)) {
|
||||
Map<Integer, InlinableAccess> infos = new HashMap<Integer, InlinableAccess>();
|
||||
Map<Integer, InvokeCall> infos = new HashMap<Integer, InvokeCall>();
|
||||
int paramStart = frame.getStackSize() - paramLength;
|
||||
|
||||
for (int i = 0; i < paramLength; i++) {
|
||||
@@ -311,19 +307,14 @@ public class MethodInliner {
|
||||
int varIndex = ((VarInsnNode) insnNode).var;
|
||||
LambdaInfo lambdaInfo = getLambda(varIndex);
|
||||
if (lambdaInfo != null) {
|
||||
InlinableAccess inlinableAccess = new InlinableAccess(varIndex, true, null);
|
||||
inlinableAccess.setInfo(lambdaInfo);
|
||||
infos.put(i, inlinableAccess);
|
||||
|
||||
//remove inlinable access
|
||||
infos.put(i, new InvokeCall(varIndex, lambdaInfo));
|
||||
node.instructions.remove(insnNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ConstructorInvocation invocation = new ConstructorInvocation(owner, infos, isSameModule);
|
||||
constructorInvocationList.add(invocation);
|
||||
constructorInvocations.add(new ConstructorInvocation(owner, infos, isSameModule));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -343,7 +334,7 @@ public class MethodInliner {
|
||||
}
|
||||
}
|
||||
|
||||
//clean dead try catch blocks
|
||||
//clean dead try/catch blocks
|
||||
List<TryCatchBlockNode> blocks = node.tryCatchBlocks;
|
||||
for (Iterator<TryCatchBlockNode> iterator = blocks.iterator(); iterator.hasNext(); ) {
|
||||
TryCatchBlockNode block = iterator.next();
|
||||
@@ -355,40 +346,7 @@ public class MethodInliner {
|
||||
return node;
|
||||
}
|
||||
|
||||
public List<ParameterInfo> getParametersInfo(LambdaInfo info, String desc) {
|
||||
List<ParameterInfo> result = new ArrayList<ParameterInfo>();
|
||||
Type[] types = Type.getArgumentTypes(desc);
|
||||
|
||||
//add skipped this cause closure doesn't have it
|
||||
//result.add(ParameterInfo.STUB);
|
||||
ParameterInfo thiz = new ParameterInfo(AsmTypeConstants.OBJECT_TYPE, true, -1, -1);
|
||||
thiz.setLambda(info);
|
||||
|
||||
result.add(thiz);
|
||||
int index = 1;
|
||||
|
||||
if (info != null) {
|
||||
List<ValueParameterDescriptor> valueParameters = info.getFunctionDescriptor().getValueParameters();
|
||||
for (ValueParameterDescriptor parameter : valueParameters) {
|
||||
Type type = typeMapper.mapType(parameter.getType());
|
||||
int paramIndex = index++;
|
||||
result.add(new ParameterInfo(type, false, paramIndex, -1));
|
||||
if (type.getSize() == 2) {
|
||||
result.add(ParameterInfo.STUB);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (Type type : types) {
|
||||
int paramIndex = index++;
|
||||
result.add(new ParameterInfo(type, false, paramIndex, -1));
|
||||
if (type.getSize() == 2) {
|
||||
result.add(ParameterInfo.STUB);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public LambdaInfo getLambda(int index) {
|
||||
if (index < parameters.totalSize()) {
|
||||
return parameters.get(index).getLambda();
|
||||
@@ -433,13 +391,10 @@ public class MethodInliner {
|
||||
}
|
||||
}
|
||||
|
||||
static List<FieldAccess> transformCaptured(
|
||||
@NotNull MethodNode node,
|
||||
@NotNull Parameters paramsToSearch,
|
||||
@NotNull Type lambdaClassType,
|
||||
@NotNull LambdaFieldRemapper lambdaFieldRemapper
|
||||
) {
|
||||
List<FieldAccess> capturedFields = new ArrayList<FieldAccess>();
|
||||
private void transformCaptured(@NotNull MethodNode node) {
|
||||
if (lambdaType == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
//remove all this and shift all variables to captured ones size
|
||||
AbstractInsnNode cur = node.instructions.getFirst();
|
||||
@@ -447,53 +402,28 @@ public class MethodInliner {
|
||||
if (cur.getType() == AbstractInsnNode.FIELD_INSN) {
|
||||
FieldInsnNode fieldInsnNode = (FieldInsnNode) cur;
|
||||
//TODO check closure
|
||||
String owner = fieldInsnNode.owner;
|
||||
if (lambdaFieldRemapper.canProcess(fieldInsnNode.owner, lambdaClassType.getInternalName())) {
|
||||
String name = fieldInsnNode.name;
|
||||
String desc = fieldInsnNode.desc;
|
||||
|
||||
Collection<CapturedParamInfo> vars = paramsToSearch.getCaptured();
|
||||
CapturedParamInfo result = lambdaFieldRemapper.findField(fieldInsnNode, paramsToSearch.getCaptured());
|
||||
if (lambdaFieldRemapper.canProcess(fieldInsnNode.owner, lambdaType.getInternalName())) {
|
||||
CapturedParamInfo result = this.lambdaFieldRemapper.findField(fieldInsnNode, parameters.getCaptured());
|
||||
|
||||
if (result == null) {
|
||||
throw new UnsupportedOperationException("Coudn't find field " +
|
||||
owner +
|
||||
fieldInsnNode.owner +
|
||||
"." +
|
||||
name +
|
||||
fieldInsnNode.name +
|
||||
" (" +
|
||||
desc +
|
||||
") in captured vars of " + lambdaClassType);
|
||||
fieldInsnNode.desc +
|
||||
") in captured vars of " + lambdaType);
|
||||
}
|
||||
|
||||
if (result.isSkipped()) {
|
||||
//lambda class transformation skip this captured
|
||||
//lambda class transformation: skip captured this
|
||||
} else {
|
||||
cur = lambdaFieldRemapper.doTransform(node, fieldInsnNode, result);
|
||||
|
||||
//AbstractInsnNode prev = getPreviousNoLableNoLine(cur);
|
||||
//
|
||||
//assert prev.getType() == AbstractInsnNode.VAR_INSN;
|
||||
//VarInsnNode loadThis = (VarInsnNode) prev;
|
||||
//assert /*loadThis.var == info.getCapturedVarsSize() - 1 && */loadThis.getOpcode() == Opcodes.ALOAD;
|
||||
//
|
||||
//int opcode = fieldInsnNode.getOpcode() == Opcodes.GETFIELD ? result.getType().getOpcode(Opcodes.ILOAD) : result.getType().getOpcode(Opcodes.ISTORE);
|
||||
//VarInsnNode insn = new VarInsnNode(opcode, result.getIndex());
|
||||
//
|
||||
//node.instructions.remove(prev); //remove aload this
|
||||
//node.instructions.insertBefore(cur, insn);
|
||||
//node.instructions.remove(cur); //remove aload field
|
||||
//
|
||||
//cur = insn;
|
||||
//
|
||||
//FieldAccess fieldAccess = new FieldAccess(fieldInsnNode.name, fieldInsnNode.desc, new FieldAccess("" + loadThis.var, lambdaClassType.getInternalName()));
|
||||
//capturedFields.add(fieldAccess);
|
||||
cur = this.lambdaFieldRemapper.doTransform(node, fieldInsnNode, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
cur = cur.getNext();
|
||||
}
|
||||
|
||||
return capturedFields;
|
||||
}
|
||||
|
||||
public static AbstractInsnNode getPreviousNoLabelNoLine(AbstractInsnNode cur) {
|
||||
@@ -504,8 +434,8 @@ public class MethodInliner {
|
||||
return prev;
|
||||
}
|
||||
|
||||
public static void putStackValuesIntoLocals(List<Type> directOrder, int shift, InstructionAdapter mv, String descriptor) {
|
||||
Type[] actualParams = Type.getArgumentTypes(descriptor); //last param is closure itself
|
||||
public static void putStackValuesIntoLocals(List<Type> directOrder, int shift, InstructionAdapter iv, String descriptor) {
|
||||
Type[] actualParams = Type.getArgumentTypes(descriptor);
|
||||
assert actualParams.length == directOrder.size() : "Number of expected and actual params should be equals!";
|
||||
|
||||
int size = 0;
|
||||
@@ -520,9 +450,9 @@ public class MethodInliner {
|
||||
shift -= next.getSize();
|
||||
Type typeOnStack = actualParams[--index];
|
||||
if (!typeOnStack.equals(next)) {
|
||||
StackValue.onStack(typeOnStack).put(next, mv);
|
||||
StackValue.onStack(typeOnStack).put(next, iv);
|
||||
}
|
||||
mv.visitVarInsn(next.getOpcode(Opcodes.ISTORE), shift);
|
||||
iv.store(shift, next);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,32 +34,32 @@ class ParameterInfo {
|
||||
public final boolean isSkipped;
|
||||
|
||||
//in case when parameter could be extracted from outer context (e.g. from local var)
|
||||
private StackValue remapIndex;
|
||||
private StackValue remapValue;
|
||||
|
||||
public LambdaInfo lambda;
|
||||
|
||||
ParameterInfo(Type type, boolean skipped, int index, int remapIndex) {
|
||||
this(type, skipped, index, remapIndex == -1 ? null : StackValue.local(remapIndex, type));
|
||||
ParameterInfo(Type type, boolean skipped, int index, int remapValue) {
|
||||
this(type, skipped, index, remapValue == -1 ? null : StackValue.local(remapValue, type));
|
||||
}
|
||||
|
||||
ParameterInfo(Type type, boolean skipped, int index, StackValue stackValue) {
|
||||
this.type = type;
|
||||
this.isSkipped = skipped;
|
||||
this.remapIndex = stackValue;
|
||||
this.remapValue = stackValue;
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public boolean isSkippedOrRemapped() {
|
||||
return isSkipped || remapIndex != null;
|
||||
return isSkipped || remapValue != null;
|
||||
}
|
||||
|
||||
public boolean isRemapped() {
|
||||
return remapIndex != null;
|
||||
return remapValue != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public StackValue getRemapIndex() {
|
||||
return remapIndex;
|
||||
public StackValue getRemapValue() {
|
||||
return remapValue;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
@@ -84,7 +84,7 @@ class ParameterInfo {
|
||||
this.lambda = lambda;
|
||||
}
|
||||
|
||||
public void setRemapIndex(StackValue remapIndex) {
|
||||
this.remapIndex = remapIndex;
|
||||
public void setRemapValue(StackValue remapValue) {
|
||||
this.remapValue = remapValue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,20 +60,6 @@ public class Parameters implements Iterable<ParameterInfo> {
|
||||
return Iterables.concat(real, captured).iterator();
|
||||
}
|
||||
|
||||
public static List<CapturedParamInfo> transformList(List<CapturedParamInfo> capturedParams, int realSize) {
|
||||
List<CapturedParamInfo> result = new ArrayList<CapturedParamInfo>();
|
||||
for (CapturedParamInfo capturedParamInfo : capturedParams) {
|
||||
CapturedParamInfo newInfo = capturedParamInfo.clone(result.size() + realSize, capturedParamInfo.getIndex());
|
||||
|
||||
result.add(newInfo);
|
||||
|
||||
if (capturedParamInfo.getType().getSize() == 2) {
|
||||
result.add(CapturedParamInfo.STUB);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static List<CapturedParamInfo> addStubs(List<CapturedParamInfo> capturedParams, int realSize) {
|
||||
List<CapturedParamInfo> result = new ArrayList<CapturedParamInfo>();
|
||||
for (CapturedParamInfo capturedParamInfo : capturedParams) {
|
||||
|
||||
@@ -27,7 +27,6 @@ public class ParametersBuilder {
|
||||
|
||||
private final List<ParameterInfo> params = new ArrayList<ParameterInfo>();
|
||||
private final List<CapturedParamInfo> capturedParams = new ArrayList<CapturedParamInfo>();
|
||||
private final List<CapturedParamInfo> additionalCapturedParams = new ArrayList<CapturedParamInfo>();
|
||||
|
||||
private int nextIndex = 0;
|
||||
private int nextCaptured = 0;
|
||||
@@ -36,9 +35,10 @@ public class ParametersBuilder {
|
||||
return new ParametersBuilder();
|
||||
}
|
||||
|
||||
public ParametersBuilder addThis(Type type, boolean skipped) {
|
||||
addParameter(new ParameterInfo(type, skipped, nextIndex, -1));
|
||||
return this;
|
||||
public ParameterInfo addThis(Type type, boolean skipped) {
|
||||
ParameterInfo info = new ParameterInfo(type, skipped, nextIndex, -1);
|
||||
addParameter(info);
|
||||
return info;
|
||||
}
|
||||
|
||||
public ParametersBuilder addNextParameter(Type type, boolean skipped, @Nullable ParameterInfo original) {
|
||||
|
||||
@@ -21,7 +21,7 @@ import org.jetbrains.asm4.commons.InstructionAdapter;
|
||||
|
||||
public class ShiftAdapter extends InstructionAdapter {
|
||||
|
||||
private int shift;
|
||||
private final int shift;
|
||||
|
||||
public ShiftAdapter(MethodVisitor mv, int shift) {
|
||||
super(mv);
|
||||
|
||||
@@ -32,9 +32,9 @@ public abstract class VarRemapper {
|
||||
private final Parameters params;
|
||||
private final int actualParamsSize;
|
||||
|
||||
private final StackValue [] remapIndex;
|
||||
private final StackValue [] remapValues;
|
||||
|
||||
private int additionalShift;
|
||||
private final int additionalShift;
|
||||
|
||||
public ParamRemapper(Parameters params, int additionalShift) {
|
||||
this.additionalShift = additionalShift;
|
||||
@@ -42,15 +42,15 @@ public abstract class VarRemapper {
|
||||
this.params = params;
|
||||
|
||||
int realSize = 0;
|
||||
remapIndex = new StackValue [params.totalSize()];
|
||||
remapValues = new StackValue [params.totalSize()];
|
||||
|
||||
int index = 0;
|
||||
for (ParameterInfo info : params) {
|
||||
if (!info.isSkippedOrRemapped()) {
|
||||
remapIndex[index] = StackValue.local(realSize, AsmTypeConstants.OBJECT_TYPE);
|
||||
remapValues[index] = StackValue.local(realSize, AsmTypeConstants.OBJECT_TYPE);
|
||||
realSize += info.getType().getSize();
|
||||
} else {
|
||||
remapIndex[index] = info.isRemapped() ? info.getRemapIndex() : null;
|
||||
remapValues[index] = info.isRemapped() ? info.getRemapValue() : null;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
@@ -64,7 +64,7 @@ public abstract class VarRemapper {
|
||||
|
||||
if (index < allParamsSize) {
|
||||
ParameterInfo info = params.get(index);
|
||||
StackValue remapped = remapIndex[index];
|
||||
StackValue remapped = remapValues[index];
|
||||
if (info.isSkipped || remapped == null) {
|
||||
throw new RuntimeException("Trying to access skipped parameter: " + info.type + " at " +index);
|
||||
}
|
||||
@@ -100,9 +100,10 @@ public abstract class VarRemapper {
|
||||
}
|
||||
mv.visitVarInsn(opcode, ((StackValue.Local) value).index);
|
||||
if (remapInfo.parameterInfo != null) {
|
||||
value.coerce(value.type, remapInfo.parameterInfo.type, mv);
|
||||
StackValue.coerce(value.type, remapInfo.parameterInfo.type, mv);
|
||||
}
|
||||
} else {
|
||||
assert remapInfo.parameterInfo != null : "Non local value should have parameter info";
|
||||
value.put(remapInfo.parameterInfo.type, mv);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user