This commit is contained in:
Mikhael Bogdanov
2014-02-20 19:20:09 +04:00
parent ee136d6594
commit 3bf952b49c
7 changed files with 66 additions and 75 deletions
@@ -25,6 +25,7 @@ import org.jetbrains.asm4.MethodVisitor;
import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.asm4.commons.Method;
import org.jetbrains.jet.codegen.asm.Inliner;
import org.jetbrains.jet.codegen.binding.CalculatedClosure;
import org.jetbrains.jet.codegen.context.CodegenContext;
import org.jetbrains.jet.codegen.context.LocalLookup;
@@ -153,7 +154,7 @@ public class ClosureCodegen extends ParentCodegenAwareImpl {
v.anew(asmType);
v.dup();
codegen.pushClosureOnStack(closure, false);
codegen.pushClosureOnStack(closure, false, Inliner.NOT_INLINE);
v.invokespecial(asmType.getInternalName(), "<init>", constructor.getDescriptor());
}
return StackValue.onStack(asmType);
@@ -1334,7 +1334,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
v.anew(type);
v.dup();
pushClosureOnStack(closure, false);
pushClosureOnStack(closure, false, Inliner.NOT_INLINE);
JetDelegatorToSuperCall superCall = closure.getSuperCall();
if (superCall != null) {
@@ -1348,17 +1348,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
Type[] argumentTypes = superCallable.getAsmMethod().getArgumentTypes();
ResolvedCall resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, superCall.getCalleeExpression());
assert resolvedCall != null;
pushMethodArguments(resolvedCall, Arrays.asList(argumentTypes));
pushMethodArguments(resolvedCall, Arrays.asList(argumentTypes), null);
}
v.invokespecial(type.getInternalName(), "<init>", constructor.getAsmMethod().getDescriptor());
return StackValue.onStack(type);
}
protected void pushClosureOnStack(CalculatedClosure closure, boolean ignoreThisAndReceiver) {
pushClosureOnStack(closure, ignoreThisAndReceiver, Inliner.NOT_INLINE);
}
public void pushClosureOnStack(CalculatedClosure closure, boolean ignoreThisAndReceiver, Inliner inliner) {
if (closure != null) {
int paramIndex = 0;
@@ -1368,7 +1364,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
StackValue thisOrOuter = generateThisOrOuter(captureThis, false);
assert !isPrimitive(thisOrOuter.type) : "This or outer should be non primitive: " + thisOrOuter.type;
if (inliner.shouldPutValue(thisOrOuter.type, thisOrOuter, context, null)) {
if (inliner.shouldPutValue(thisOrOuter.type, thisOrOuter, null)) {
thisOrOuter.put(thisOrOuter.type, v);
}
inliner.putCapturedInLocal(thisOrOuter.type, thisOrOuter, null, paramIndex++);
@@ -1378,7 +1374,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
if (captureReceiver != null) {
Type asmType = typeMapper.mapType(captureReceiver);
StackValue.Local capturedReceiver = StackValue.local(context.isStatic() ? 0 : 1, asmType);
if (inliner.shouldPutValue(asmType, capturedReceiver, context, null)) {
if (inliner.shouldPutValue(asmType, capturedReceiver, null)) {
capturedReceiver.put(asmType, v);
}
inliner.putCapturedInLocal(asmType, capturedReceiver, null, paramIndex++);
@@ -1391,7 +1387,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
sharedVarType = typeMapper.mapType((VariableDescriptor) entry.getKey());
}
StackValue capturedVar = entry.getValue().getOuterValue(this);
if (inliner.shouldPutValue(sharedVarType, capturedVar, context, null)) {
if (inliner.shouldPutValue(sharedVarType, capturedVar, null)) {
capturedVar.put(sharedVarType, v);
}
inliner.putCapturedInLocal(sharedVarType, capturedVar, null, paramIndex++);
@@ -2329,14 +2325,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
return false;
}
private int pushMethodArguments(@NotNull ResolvedCall resolvedCall, List<Type> valueParameterTypes) {
return pushMethodArguments(resolvedCall, valueParameterTypes, null);
}
private int pushMethodArguments(@NotNull ResolvedCall resolvedCall, List<Type> valueParameterTypes, boolean skipLast) {
return pushMethodArguments(resolvedCall, valueParameterTypes, skipLast, null);
}
private int pushMethodArguments(@NotNull ResolvedCall resolvedCall, List<Type> valueParameterTypes, Inliner inliner) {
return pushMethodArguments(resolvedCall, valueParameterTypes, false, inliner);
}
@@ -2371,12 +2359,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
JetExpression argumentExpression = valueArgument.getArgumentExpression();
assert argumentExpression != null : valueArgument.asElement().getText();
//TODO deparenthisise
if (inliner.isInliningClosure(argumentExpression, valueParameter)) {
inliner.rememberClosure((JetFunctionLiteralExpression) argumentExpression, parameterType);
putInLocal = false;
} else {
StackValue value = gen(argumentExpression);
if (inliner.shouldPutValue(parameterType, value, context, valueParameter)) {
if (inliner.shouldPutValue(parameterType, value, valueParameter)) {
value.put(parameterType, v);
}
valueIfPresent = value;
@@ -2400,13 +2389,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
return mask;
}
private boolean hasDefaults(@NotNull ResolvedCall resolvedCall) {
@SuppressWarnings("unchecked")
private static boolean hasDefaults(@NotNull ResolvedCall<?> resolvedCall) {
List<ResolvedValueArgument> valueArguments = resolvedCall.getValueArgumentsByIndex();
CallableDescriptor fd = resolvedCall.getResultingDescriptor();
for (ValueParameterDescriptor valueParameter : fd.getValueParameters()) {
StackValue valueIfPresent = null;
ResolvedValueArgument resolvedValueArgument = valueArguments.get(valueParameter.getIndex());
if (resolvedValueArgument instanceof DefaultValueArgument) {
return true;
@@ -2477,7 +2464,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
ResolvedCall<? extends CallableDescriptor> resolvedCall =
bindingContext.get(BindingContext.RESOLVED_CALL, expression.getCalleeExpression());
if (resolvedCall != null) {
return pushMethodArguments(resolvedCall, valueParameterTypes);
return pushMethodArguments(resolvedCall, valueParameterTypes, null);
}
else {
List<? extends ValueArgument> args = expression.getValueArguments();
@@ -3355,7 +3342,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
//Resolved call to local class constructor doesn't have resolvedCall.getThisObject() and resolvedCall.getReceiverArgument()
//so we need generate closure on stack
//See StackValue.receiver for more info
pushClosureOnStack(closure, resolvedCall.getThisObject().exists() || resolvedCall.getReceiverArgument().exists());
pushClosureOnStack(closure, resolvedCall.getThisObject().exists() || resolvedCall.getReceiverArgument().exists(), Inliner.NOT_INLINE);
ConstructorDescriptor originalOfSamAdapter = (ConstructorDescriptor) SamCodegenUtil.getOriginalIfSamAdapter(constructorDescriptor);
CallableMethod method = typeMapper.mapToCallableMethod(originalOfSamAdapter == null ? constructorDescriptor : originalOfSamAdapter);
@@ -3471,7 +3458,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
if (callable instanceof CallableMethod) {
genThisAndReceiverFromResolvedCall(receiver, resolvedCall, (CallableMethod) callable);
pushMethodArguments(resolvedCall, ((CallableMethod) callable).getValueParameterTypes(), !isGetter);
boolean skipLast = !isGetter;
pushMethodArguments(resolvedCall, ((CallableMethod) callable).getValueParameterTypes(), skipLast, null);
}
else {
gen(array, arrayType); // intrinsic method
@@ -3909,18 +3897,11 @@ The "returned" value of try expression with no finally is either the last expres
throw new IllegalStateException("Script codegen should be present in codegen tree");
}
@NotNull
public InstructionAdapter getInstructionAdapter() {
return v;
}
public JetTypeMapper getTypeMapper() {
return typeMapper;
}
public MethodVisitor getMethodVisitor() {
return methodVisitor;
}
@NotNull
public FrameMap getFrameMap() {
return myFrameMap;
@@ -3931,6 +3912,7 @@ The "returned" value of try expression with no finally is either the last expres
return context;
}
@NotNull
public NameGenerator getInlineNameGenerator() {
NameGenerator nameGenerator = getParentCodegen().getInlineNameGenerator();
Name name = context.getContextDescriptor().getName();
@@ -388,10 +388,6 @@ public abstract class StackValue {
coerceFrom(topOfStackType, v);
v.store(index, this.type);
}
public int getIndex() {
return index;
}
}
public static class OnStack extends StackValue {
@@ -85,9 +85,10 @@ public class InlineCodegen implements ParentCodegenAware, Inliner {
private LambdaInfo activeLambda;
protected final List<ParameterInfo> tempTypes = new ArrayList<ParameterInfo>();
protected final List<ParameterInfo> actualParameters = new ArrayList<ParameterInfo>();
protected final Map<Integer, LambdaInfo> expressionMap = new HashMap<Integer, LambdaInfo>();
private SimpleFunctionDescriptor inlineFunctionDescriptor;
public InlineCodegen(
@@ -188,7 +189,7 @@ public class InlineCodegen implements ParentCodegenAware, Inliner {
private void inlineCall(MethodNode node) {
generateClosuresBodies();
List<ParameterInfo> realParams = new ArrayList<ParameterInfo>(tempTypes);
List<ParameterInfo> realParams = new ArrayList<ParameterInfo>(actualParameters);
putClosureParametersOnStack();
@@ -254,7 +255,7 @@ public class InlineCodegen implements ParentCodegenAware, Inliner {
) {
if (!asFunctionInline && Type.VOID_TYPE != type) {
//TODO remap only inlinable closure => otherwise we could get a lot of problem
boolean couldBeRemapped = !shouldPutValue(type, stackValue, codegen.getContext(), valueParameterDescriptor);
boolean couldBeRemapped = !shouldPutValue(type, stackValue, valueParameterDescriptor);
StackValue remappedIndex = couldBeRemapped ? stackValue : null;
ParameterInfo info = new ParameterInfo(type, false, couldBeRemapped ? -1 : codegen.getFrameMap().enterTemp(type), remappedIndex);
@@ -269,7 +270,11 @@ public class InlineCodegen implements ParentCodegenAware, Inliner {
}
@Override
public boolean shouldPutValue(@NotNull Type type, @Nullable StackValue stackValue, MethodContext context, ValueParameterDescriptor descriptor) {
public boolean shouldPutValue(
@NotNull Type type,
@Nullable StackValue stackValue,
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))) {
@@ -278,37 +283,41 @@ public class InlineCodegen implements ParentCodegenAware, Inliner {
// }
//}
if (stackValue == null) {
//default or vararg
return true;
}
//remap only inline functions (and maybe non primitives)
//TODO - clean asserion and remapping logic
if (stackValue == null || isPrimitive(type) ^ isPrimitive(stackValue.type)) {
if (isPrimitive(type) != isPrimitive(stackValue.type)) {
//don't remap boxing/unboxing primitives - lost identity and perfomance
return true;
}
boolean shouldPut = !(stackValue != null && stackValue instanceof StackValue.Local);
if (shouldPut) {
//we could recapture field of anonymous objects cause they couldn't change
boolean isInlineClosure = codegen.getContext().isInlineClosure();
if (isInlineClosure && codegen.getContext().getContextDescriptor() instanceof AnonymousFunctionDescriptor) {
Type internalName = asmTypeForAnonymousClass(bindingContext, (FunctionDescriptor) codegen.getContext().getContextDescriptor());
if (stackValue instanceof StackValue.Local) {
return false;
}
String owner = null;
if (stackValue instanceof StackValue.Field) {
owner = ((StackValue.Field) stackValue).owner.getInternalName();
}
if (codegen.getContext().isInlineClosure() && codegen.getContext().getContextDescriptor() instanceof AnonymousFunctionDescriptor) {
Type internalName = asmTypeForAnonymousClass(bindingContext, (FunctionDescriptor) codegen.getContext().getContextDescriptor());
if (stackValue instanceof StackValue.Composed) {
//go through aload 0
owner = internalName.getInternalName();
}
String owner = null;
if (stackValue instanceof StackValue.Field) {
owner = ((StackValue.Field) stackValue).owner.getInternalName();
}
if (descriptor != null && !InlineUtil.hasNoinlineAnnotation(descriptor) && internalName.getInternalName().equals(owner)) {
//check type of context
return false;
}
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;
}
}
return shouldPut;
return true;
}
private void doWithParameter(ParameterInfo info) {
@@ -318,9 +327,9 @@ public class InlineCodegen implements ParentCodegenAware, Inliner {
private int recordParamInfo(ParameterInfo info, boolean addToFrame) {
Type type = info.type;
tempTypes.add(info);
actualParameters.add(info);
if (info.getType().getSize() == 2) {
tempTypes.add(ParameterInfo.STUB);
actualParameters.add(ParameterInfo.STUB);
}
if (addToFrame) {
return originalFunctionFrame.enterTemp(type);
@@ -355,7 +364,7 @@ public class InlineCodegen implements ParentCodegenAware, Inliner {
recordParamInfo(info, false);
}
for (ListIterator<? extends ParameterInfo> iterator = tempTypes.listIterator(tempTypes.size()); iterator.hasPrevious(); ) {
for (ListIterator<? extends ParameterInfo> iterator = actualParameters.listIterator(actualParameters.size()); iterator.hasPrevious(); ) {
ParameterInfo param = iterator.previous();
putParameterOnStack(param);
}
@@ -364,7 +373,7 @@ public class InlineCodegen implements ParentCodegenAware, Inliner {
@Override
public void leaveTemps() {
FrameMap frameMap = codegen.getFrameMap();
for (ListIterator<? extends ParameterInfo> iterator = tempTypes.listIterator(tempTypes.size()); iterator.hasPrevious(); ) {
for (ListIterator<? extends ParameterInfo> iterator = actualParameters.listIterator(actualParameters.size()); iterator.hasPrevious(); ) {
ParameterInfo param = iterator.previous();
if (!param.isSkippedOrRemapped()) {
frameMap.leaveTemp(param.type);
@@ -374,6 +383,7 @@ public class InlineCodegen implements ParentCodegenAware, Inliner {
@Override
public boolean isInliningClosure(JetExpression expression, ValueParameterDescriptor valueParameterDescriptora) {
//TODO deparenthisise
return expression instanceof JetFunctionLiteralExpression &&
!InlineUtil.hasNoinlineAnnotation(valueParameterDescriptora);
}
@@ -391,7 +401,7 @@ public class InlineCodegen implements ParentCodegenAware, Inliner {
private void putClosureParametersOnStack() {
//TODO: SORT
int currentSize = tempTypes.size();
int currentSize = actualParameters.size();
for (LambdaInfo next : expressionMap.values()) {
if (next.closure != null) {
activeLambda = next;
@@ -20,7 +20,6 @@ import org.jetbrains.asm4.ClassVisitor;
import org.jetbrains.asm4.Type;
import org.jetbrains.jet.codegen.CallableMethod;
import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.codegen.context.MethodContext;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression;
@@ -69,7 +68,7 @@ public interface Inliner {
@Override
public boolean shouldPutValue(
Type type, StackValue stackValue, MethodContext context,
Type type, StackValue stackValue,
ValueParameterDescriptor descriptor
) {
return true;
@@ -82,7 +81,7 @@ public interface Inliner {
void putCapturedInLocal(Type type, StackValue stackValue, ValueParameterDescriptor valueParameterDescriptor, int index);
boolean shouldPutValue(Type type, StackValue stackValue, MethodContext context, ValueParameterDescriptor descriptor);
boolean shouldPutValue(Type type, StackValue stackValue, ValueParameterDescriptor descriptor);
void putHiddenParams();
@@ -36,6 +36,7 @@ public class MethodInliner {
private final Type lambdaInfo;
private final LambdaFieldRemapper lambdaFieldRemapper;
private boolean isSameModule;
private final JetTypeMapper typeMapper;
@@ -177,7 +178,7 @@ public class MethodInliner {
List<CapturedParamInfo> contextCaptured = MethodInliner.this.parameters.getCaptured();
CapturedParamInfo result = null;
for (CapturedParamInfo info : contextCaptured) {
//TODO more sofisticated check
//TODO more sophisticated check
if (info.getFieldName().equals(capturedParamInfo.getFieldName())) {
result = info;
}
@@ -16,6 +16,8 @@
package org.jetbrains.jet.codegen.asm;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.asm4.Type;
import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
@@ -28,8 +30,10 @@ class ParameterInfo {
public final Type type;
//for skipped parameter: e.g. inlined lambda
public final boolean isSkipped;
//in case when parameter could be extracted from outer context (e.g. from local var)
private StackValue remapIndex;
public LambdaInfo lambda;
@@ -53,6 +57,7 @@ class ParameterInfo {
return remapIndex != null;
}
@Nullable
public StackValue getRemapIndex() {
return remapIndex;
}
@@ -65,11 +70,12 @@ class ParameterInfo {
return isSkipped;
}
@NotNull
public Type getType() {
return type;
}
@Nullable
public LambdaInfo getLambda() {
return lambda;
}
@@ -78,10 +84,6 @@ class ParameterInfo {
this.lambda = lambda;
}
public void setRemapIndex(int remapIndex) {
this.remapIndex = StackValue.local(remapIndex, type);
}
public void setRemapIndex(StackValue remapIndex) {
this.remapIndex = remapIndex;
}