Call generator refactoring
This commit is contained in:
@@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2013 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.asm4.Type;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
||||||
|
|
||||||
|
public interface CallGenerator {
|
||||||
|
|
||||||
|
public class DefaultCallGenerator implements CallGenerator {
|
||||||
|
|
||||||
|
private ExpressionCodegen codegen;
|
||||||
|
|
||||||
|
public DefaultCallGenerator(ExpressionCodegen codegen) {
|
||||||
|
this.codegen = codegen;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void genCall(
|
||||||
|
CallableMethod callableMethod,
|
||||||
|
ResolvedCall<?> resolvedCall, int mask,
|
||||||
|
ExpressionCodegen codegen
|
||||||
|
) {
|
||||||
|
if (mask == 0) {
|
||||||
|
callableMethod.invokeWithNotNullAssertion(codegen.v, codegen.getState(), resolvedCall);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
callableMethod.invokeDefaultWithNotNullAssertion(codegen.v, codegen.getState(), resolvedCall, mask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterParameterPut(Type type, StackValue stackValue, ValueParameterDescriptor valueParameterDescriptor) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void putHiddenParams() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void genValueAndPut(
|
||||||
|
@NotNull ValueParameterDescriptor valueParameterDescriptor,
|
||||||
|
@NotNull JetExpression argumentExpression,
|
||||||
|
@NotNull Type parameterType
|
||||||
|
) {
|
||||||
|
StackValue value = codegen.gen(argumentExpression);
|
||||||
|
value.put(parameterType, codegen.v);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void putCapturedValueOnStack(
|
||||||
|
@NotNull StackValue stackValue, @NotNull Type valueType, int paramIndex
|
||||||
|
) {
|
||||||
|
stackValue.put(stackValue.type, codegen.v);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void genCall(CallableMethod callableMethod, ResolvedCall<?> resolvedCall, int mask, ExpressionCodegen codegen);
|
||||||
|
|
||||||
|
void afterParameterPut(Type type, StackValue stackValue, ValueParameterDescriptor valueParameterDescriptor);
|
||||||
|
|
||||||
|
void genValueAndPut(
|
||||||
|
@NotNull ValueParameterDescriptor valueParameterDescriptor,
|
||||||
|
@NotNull JetExpression argumentExpression,
|
||||||
|
@NotNull Type parameterType
|
||||||
|
);
|
||||||
|
|
||||||
|
void putCapturedValueOnStack(
|
||||||
|
@NotNull StackValue stackValue,
|
||||||
|
@NotNull Type valueType, int paramIndex
|
||||||
|
);
|
||||||
|
|
||||||
|
void putHiddenParams();
|
||||||
|
}
|
||||||
@@ -25,7 +25,6 @@ import org.jetbrains.asm4.MethodVisitor;
|
|||||||
import org.jetbrains.asm4.Type;
|
import org.jetbrains.asm4.Type;
|
||||||
import org.jetbrains.asm4.commons.InstructionAdapter;
|
import org.jetbrains.asm4.commons.InstructionAdapter;
|
||||||
import org.jetbrains.asm4.commons.Method;
|
import org.jetbrains.asm4.commons.Method;
|
||||||
import org.jetbrains.jet.codegen.inline.CallGenerator;
|
|
||||||
import org.jetbrains.jet.codegen.binding.CalculatedClosure;
|
import org.jetbrains.jet.codegen.binding.CalculatedClosure;
|
||||||
import org.jetbrains.jet.codegen.context.CodegenContext;
|
import org.jetbrains.jet.codegen.context.CodegenContext;
|
||||||
import org.jetbrains.jet.codegen.context.LocalLookup;
|
import org.jetbrains.jet.codegen.context.LocalLookup;
|
||||||
@@ -154,7 +153,7 @@ public class ClosureCodegen extends ParentCodegenAwareImpl {
|
|||||||
v.anew(asmType);
|
v.anew(asmType);
|
||||||
v.dup();
|
v.dup();
|
||||||
|
|
||||||
codegen.pushClosureOnStack(closure, false, CallGenerator.NOT_INLINE);
|
codegen.pushClosureOnStack(closure, false, codegen.defaulCallGenerator);
|
||||||
v.invokespecial(asmType.getInternalName(), "<init>", constructor.getDescriptor());
|
v.invokespecial(asmType.getInternalName(), "<init>", constructor.getDescriptor());
|
||||||
}
|
}
|
||||||
return StackValue.onStack(asmType);
|
return StackValue.onStack(asmType);
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ import org.jetbrains.asm4.Type;
|
|||||||
import org.jetbrains.asm4.commons.InstructionAdapter;
|
import org.jetbrains.asm4.commons.InstructionAdapter;
|
||||||
import org.jetbrains.asm4.commons.Method;
|
import org.jetbrains.asm4.commons.Method;
|
||||||
import org.jetbrains.jet.codegen.inline.InlineCodegen;
|
import org.jetbrains.jet.codegen.inline.InlineCodegen;
|
||||||
import org.jetbrains.jet.codegen.inline.CallGenerator;
|
|
||||||
import org.jetbrains.jet.codegen.inline.NameGenerator;
|
import org.jetbrains.jet.codegen.inline.NameGenerator;
|
||||||
import org.jetbrains.jet.codegen.binding.CalculatedClosure;
|
import org.jetbrains.jet.codegen.binding.CalculatedClosure;
|
||||||
import org.jetbrains.jet.codegen.binding.CodegenBinding;
|
import org.jetbrains.jet.codegen.binding.CodegenBinding;
|
||||||
@@ -84,7 +83,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
|
|
||||||
private int myLastLineNumber = -1;
|
private int myLastLineNumber = -1;
|
||||||
|
|
||||||
InstructionAdapter v;
|
public final InstructionAdapter v;
|
||||||
final MethodVisitor methodVisitor;
|
final MethodVisitor methodVisitor;
|
||||||
final FrameMap myFrameMap;
|
final FrameMap myFrameMap;
|
||||||
final JetTypeMapper typeMapper;
|
final JetTypeMapper typeMapper;
|
||||||
@@ -109,6 +108,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
@NotNull
|
@NotNull
|
||||||
private final TailRecursionCodegen tailRecursionCodegen;
|
private final TailRecursionCodegen tailRecursionCodegen;
|
||||||
|
|
||||||
|
public final CallGenerator defaulCallGenerator;
|
||||||
|
|
||||||
public CalculatedClosure generateObjectLiteral(GenerationState state, JetObjectLiteralExpression literal) {
|
public CalculatedClosure generateObjectLiteral(GenerationState state, JetObjectLiteralExpression literal) {
|
||||||
JetObjectDeclaration objectDeclaration = literal.getObjectDeclaration();
|
JetObjectDeclaration objectDeclaration = literal.getObjectDeclaration();
|
||||||
|
|
||||||
@@ -178,6 +179,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
this.context = context;
|
this.context = context;
|
||||||
this.statementVisitor = new CodegenStatementVisitor(this);
|
this.statementVisitor = new CodegenStatementVisitor(this);
|
||||||
this.tailRecursionCodegen = new TailRecursionCodegen(context, this, this.v, state);
|
this.tailRecursionCodegen = new TailRecursionCodegen(context, this, this.v, state);
|
||||||
|
this.defaulCallGenerator = new CallGenerator.DefaultCallGenerator(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public GenerationState getState() {
|
public GenerationState getState() {
|
||||||
@@ -1334,7 +1336,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
v.anew(type);
|
v.anew(type);
|
||||||
v.dup();
|
v.dup();
|
||||||
|
|
||||||
pushClosureOnStack(closure, false, CallGenerator.NOT_INLINE);
|
pushClosureOnStack(closure, false, defaulCallGenerator);
|
||||||
|
|
||||||
JetDelegatorToSuperCall superCall = closure.getSuperCall();
|
JetDelegatorToSuperCall superCall = closure.getSuperCall();
|
||||||
if (superCall != null) {
|
if (superCall != null) {
|
||||||
@@ -1355,7 +1357,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
return StackValue.onStack(type);
|
return StackValue.onStack(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void pushClosureOnStack(CalculatedClosure closure, boolean ignoreThisAndReceiver, CallGenerator callGenerator) {
|
public void pushClosureOnStack(@Nullable CalculatedClosure closure, boolean ignoreThisAndReceiver, @NotNull CallGenerator callGenerator) {
|
||||||
if (closure != null) {
|
if (closure != null) {
|
||||||
int paramIndex = 0;
|
int paramIndex = 0;
|
||||||
if (!ignoreThisAndReceiver) {
|
if (!ignoreThisAndReceiver) {
|
||||||
@@ -1364,20 +1366,14 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
StackValue thisOrOuter = generateThisOrOuter(captureThis, false);
|
StackValue thisOrOuter = generateThisOrOuter(captureThis, false);
|
||||||
|
|
||||||
assert !isPrimitive(thisOrOuter.type) : "This or outer should be non primitive: " + thisOrOuter.type;
|
assert !isPrimitive(thisOrOuter.type) : "This or outer should be non primitive: " + thisOrOuter.type;
|
||||||
if (callGenerator.shouldPutValue(thisOrOuter.type, thisOrOuter, null)) {
|
callGenerator.putCapturedValueOnStack(thisOrOuter, thisOrOuter.type, paramIndex++);
|
||||||
thisOrOuter.put(thisOrOuter.type, v);
|
|
||||||
}
|
|
||||||
callGenerator.putCapturedInLocal(thisOrOuter.type, thisOrOuter, null, paramIndex++);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JetType captureReceiver = closure.getCaptureReceiverType();
|
JetType captureReceiver = closure.getCaptureReceiverType();
|
||||||
if (captureReceiver != null) {
|
if (captureReceiver != null) {
|
||||||
Type asmType = typeMapper.mapType(captureReceiver);
|
Type asmType = typeMapper.mapType(captureReceiver);
|
||||||
StackValue.Local capturedReceiver = StackValue.local(context.isStatic() ? 0 : 1, asmType);
|
StackValue.Local capturedReceiver = StackValue.local(context.isStatic() ? 0 : 1, asmType);
|
||||||
if (callGenerator.shouldPutValue(asmType, capturedReceiver, null)) {
|
callGenerator.putCapturedValueOnStack(capturedReceiver, capturedReceiver.type, paramIndex++);
|
||||||
capturedReceiver.put(asmType, v);
|
|
||||||
}
|
|
||||||
callGenerator.putCapturedInLocal(asmType, capturedReceiver, null, paramIndex++);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1387,10 +1383,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
sharedVarType = typeMapper.mapType((VariableDescriptor) entry.getKey());
|
sharedVarType = typeMapper.mapType((VariableDescriptor) entry.getKey());
|
||||||
}
|
}
|
||||||
StackValue capturedVar = entry.getValue().getOuterValue(this);
|
StackValue capturedVar = entry.getValue().getOuterValue(this);
|
||||||
if (callGenerator.shouldPutValue(sharedVarType, capturedVar, null)) {
|
callGenerator.putCapturedValueOnStack(capturedVar, sharedVarType, paramIndex++);
|
||||||
capturedVar.put(sharedVarType, v);
|
|
||||||
}
|
|
||||||
callGenerator.putCapturedInLocal(sharedVarType, capturedVar, null, paramIndex++);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2123,7 +2116,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
descriptor instanceof SimpleFunctionDescriptor &&
|
descriptor instanceof SimpleFunctionDescriptor &&
|
||||||
((SimpleFunctionDescriptor) descriptor).getInlineStrategy().isInline();
|
((SimpleFunctionDescriptor) descriptor).getInlineStrategy().isInline();
|
||||||
|
|
||||||
CallGenerator callGenerator = !isInline ? CallGenerator.NOT_INLINE :
|
CallGenerator callGenerator = !isInline ? defaulCallGenerator :
|
||||||
new InlineCodegen(this, state, (SimpleFunctionDescriptor) unwrapFakeOverride(
|
new InlineCodegen(this, state, (SimpleFunctionDescriptor) unwrapFakeOverride(
|
||||||
(CallableMemberDescriptor) descriptor.getOriginal()), call);
|
(CallableMemberDescriptor) descriptor.getOriginal()), call);
|
||||||
|
|
||||||
@@ -2136,7 +2129,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
receiver.put(receiver.type, v);
|
receiver.put(receiver.type, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert callGenerator == CallGenerator.NOT_INLINE || !hasDefaultArguments(resolvedCall) && !tailRecursionCodegen.isTailRecursion(resolvedCall) :
|
assert callGenerator == defaulCallGenerator || !hasDefaultArguments(resolvedCall) && !tailRecursionCodegen.isTailRecursion(resolvedCall) :
|
||||||
"Method with defaults or tail recursive couldn't be inlined " + descriptor;
|
"Method with defaults or tail recursive couldn't be inlined " + descriptor;
|
||||||
|
|
||||||
pushArgumentsAndInvoke(resolvedCall, callableMethod, callGenerator);
|
pushArgumentsAndInvoke(resolvedCall, callableMethod, callGenerator);
|
||||||
@@ -2152,18 +2145,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mask == 0) {
|
callGenerator.genCall(callable, resolvedCall, mask, this);
|
||||||
if (callGenerator != CallGenerator.NOT_INLINE) {
|
|
||||||
callGenerator.inlineCall(callable, getParentCodegen().getBuilder().getVisitor());
|
|
||||||
} else {
|
|
||||||
callable.invokeWithNotNullAssertion(v, state, resolvedCall);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
callable.invokeDefaultWithNotNullAssertion(v, state, resolvedCall, mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
callGenerator.leaveTemps();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void genThisAndReceiverFromResolvedCall(
|
private void genThisAndReceiverFromResolvedCall(
|
||||||
@@ -2339,7 +2321,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
|
|
||||||
callGenerator = callGenerator != null ? callGenerator : CallGenerator.NOT_INLINE;
|
callGenerator = callGenerator != null ? callGenerator : defaulCallGenerator;
|
||||||
int mask = 0;
|
int mask = 0;
|
||||||
|
|
||||||
for (Iterator<ValueParameterDescriptor> iterator = valueParameters.iterator(); iterator.hasNext(); ) {
|
for (Iterator<ValueParameterDescriptor> iterator = valueParameters.iterator(); iterator.hasNext(); ) {
|
||||||
@@ -2356,25 +2338,16 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
JetExpression argumentExpression = valueArgument.getArgumentExpression();
|
JetExpression argumentExpression = valueArgument.getArgumentExpression();
|
||||||
assert argumentExpression != null : valueArgument.asElement().getText();
|
assert argumentExpression != null : valueArgument.asElement().getText();
|
||||||
|
|
||||||
//TODO deparenthisise
|
callGenerator.genValueAndPut(valueParameter, argumentExpression, parameterType);
|
||||||
if (callGenerator.isInliningClosure(argumentExpression, valueParameter)) {
|
|
||||||
callGenerator.rememberClosure((JetFunctionLiteralExpression) argumentExpression, parameterType);
|
|
||||||
} else {
|
|
||||||
StackValue value = gen(argumentExpression);
|
|
||||||
if (callGenerator.shouldPutValue(parameterType, value, valueParameter)) {
|
|
||||||
value.put(parameterType, v);
|
|
||||||
}
|
|
||||||
callGenerator.putInLocal(parameterType, value, valueParameter);
|
|
||||||
}
|
|
||||||
} else if (resolvedValueArgument instanceof DefaultValueArgument) {
|
} else if (resolvedValueArgument instanceof DefaultValueArgument) {
|
||||||
pushDefaultValueOnStack(parameterType, v);
|
pushDefaultValueOnStack(parameterType, v);
|
||||||
mask |= (1 << valueParameter.getIndex());
|
mask |= (1 << valueParameter.getIndex());
|
||||||
callGenerator.putInLocal(parameterType, null, valueParameter);
|
callGenerator.afterParameterPut(parameterType, null, valueParameter);
|
||||||
}
|
}
|
||||||
else if (resolvedValueArgument instanceof VarargValueArgument) {
|
else if (resolvedValueArgument instanceof VarargValueArgument) {
|
||||||
VarargValueArgument valueArgument = (VarargValueArgument) resolvedValueArgument;
|
VarargValueArgument valueArgument = (VarargValueArgument) resolvedValueArgument;
|
||||||
genVarargs(valueParameter, valueArgument);
|
genVarargs(valueParameter, valueArgument);
|
||||||
callGenerator.putInLocal(parameterType, null, valueParameter);
|
callGenerator.afterParameterPut(parameterType, null, valueParameter);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
@@ -3319,7 +3292,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
//Resolved call to local class constructor doesn't have resolvedCall.getThisObject() and resolvedCall.getReceiverArgument()
|
//Resolved call to local class constructor doesn't have resolvedCall.getThisObject() and resolvedCall.getReceiverArgument()
|
||||||
//so we need generate closure on stack
|
//so we need generate closure on stack
|
||||||
//See StackValue.receiver for more info
|
//See StackValue.receiver for more info
|
||||||
pushClosureOnStack(closure, resolvedCall.getThisObject().exists() || resolvedCall.getReceiverArgument().exists(), CallGenerator.NOT_INLINE);
|
pushClosureOnStack(closure, resolvedCall.getThisObject().exists() || resolvedCall.getReceiverArgument().exists(), defaulCallGenerator);
|
||||||
|
|
||||||
ConstructorDescriptor originalOfSamAdapter = (ConstructorDescriptor) SamCodegenUtil.getOriginalIfSamAdapter(constructorDescriptor);
|
ConstructorDescriptor originalOfSamAdapter = (ConstructorDescriptor) SamCodegenUtil.getOriginalIfSamAdapter(constructorDescriptor);
|
||||||
CallableMethod method = typeMapper.mapToCallableMethod(originalOfSamAdapter == null ? constructorDescriptor : originalOfSamAdapter);
|
CallableMethod method = typeMapper.mapToCallableMethod(originalOfSamAdapter == null ? constructorDescriptor : originalOfSamAdapter);
|
||||||
@@ -3874,11 +3847,6 @@ 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");
|
throw new IllegalStateException("Script codegen should be present in codegen tree");
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public InstructionAdapter getInstructionAdapter() {
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public FrameMap getFrameMap() {
|
public FrameMap getFrameMap() {
|
||||||
return myFrameMap;
|
return myFrameMap;
|
||||||
|
|||||||
@@ -1,93 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2013 JetBrains s.r.o.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.jet.codegen.inline;
|
|
||||||
|
|
||||||
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.lang.descriptors.ValueParameterDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
|
||||||
import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression;
|
|
||||||
|
|
||||||
public interface CallGenerator {
|
|
||||||
|
|
||||||
CallGenerator NOT_INLINE = new CallGenerator() {
|
|
||||||
@Override
|
|
||||||
public void inlineCall(
|
|
||||||
CallableMethod callableMethod, ClassVisitor visitor
|
|
||||||
) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void putInLocal(Type type, StackValue stackValue, ValueParameterDescriptor valueParameterDescriptor) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void putCapturedInLocal(
|
|
||||||
Type type, StackValue stackValue, ValueParameterDescriptor valueParameterDescriptor, int index
|
|
||||||
) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void leaveTemps() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isInliningClosure(JetExpression expression, ValueParameterDescriptor valueParameterDescriptora) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void rememberClosure(JetFunctionLiteralExpression expression, Type type) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void putHiddenParams() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean shouldPutValue(
|
|
||||||
Type type, StackValue stackValue,
|
|
||||||
ValueParameterDescriptor descriptor
|
|
||||||
) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void inlineCall(CallableMethod callableMethod, ClassVisitor visitor);
|
|
||||||
|
|
||||||
void putInLocal(Type type, StackValue stackValue, ValueParameterDescriptor valueParameterDescriptor);
|
|
||||||
|
|
||||||
void putCapturedInLocal(Type type, StackValue stackValue, ValueParameterDescriptor valueParameterDescriptor, int index);
|
|
||||||
|
|
||||||
boolean shouldPutValue(Type type, StackValue stackValue, ValueParameterDescriptor descriptor);
|
|
||||||
|
|
||||||
void putHiddenParams();
|
|
||||||
|
|
||||||
void leaveTemps();
|
|
||||||
|
|
||||||
boolean isInliningClosure(JetExpression expression, ValueParameterDescriptor valueParameterDescriptora);
|
|
||||||
|
|
||||||
void rememberClosure(JetFunctionLiteralExpression expression, Type type);
|
|
||||||
}
|
|
||||||
@@ -20,7 +20,6 @@ import com.intellij.openapi.vfs.VirtualFile;
|
|||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.asm4.ClassVisitor;
|
|
||||||
import org.jetbrains.asm4.MethodVisitor;
|
import org.jetbrains.asm4.MethodVisitor;
|
||||||
import org.jetbrains.asm4.Opcodes;
|
import org.jetbrains.asm4.Opcodes;
|
||||||
import org.jetbrains.asm4.Type;
|
import org.jetbrains.asm4.Type;
|
||||||
@@ -43,6 +42,7 @@ import org.jetbrains.jet.lang.descriptors.impl.AnonymousFunctionDescriptor;
|
|||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
||||||
import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
|
import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
|
||||||
import org.jetbrains.jet.lang.types.lang.InlineStrategy;
|
import org.jetbrains.jet.lang.types.lang.InlineStrategy;
|
||||||
import org.jetbrains.jet.lang.types.lang.InlineUtil;
|
import org.jetbrains.jet.lang.types.lang.InlineUtil;
|
||||||
@@ -119,7 +119,9 @@ public class InlineCodegen implements ParentCodegenAware, CallGenerator {
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void inlineCall(CallableMethod callableMethod, ClassVisitor visitor) {
|
public void genCall(CallableMethod callableMethod, ResolvedCall<?> resolvedCall, int mask, ExpressionCodegen codegen) {
|
||||||
|
assert mask == 0 : "Default method invocation couldn't be inlined " + resolvedCall;
|
||||||
|
|
||||||
MethodNode node = null;
|
MethodNode node = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -131,13 +133,15 @@ public class InlineCodegen implements ParentCodegenAware, CallGenerator {
|
|||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
String text = getNodeText(node);
|
String text = getNodeText(node);
|
||||||
PsiElement element = BindingContextUtils.descriptorToDeclaration(bindingContext, codegen.getContext().getContextDescriptor());
|
PsiElement element = BindingContextUtils.descriptorToDeclaration(bindingContext, this.codegen.getContext().getContextDescriptor());
|
||||||
throw new CompilationException("Couldn't inline method call '" +
|
throw new CompilationException("Couldn't inline method call '" +
|
||||||
functionDescriptor.getName() +
|
functionDescriptor.getName() +
|
||||||
"' into \n" + (element != null ? element.getText() : "null psi element " + codegen.getContext().getContextDescriptor()) +
|
"' into \n" + (element != null ? element.getText() : "null psi element " + this.codegen.getContext().getContextDescriptor()) +
|
||||||
"\ncause: " +
|
"\ncause: " +
|
||||||
text, e, call.getCallElement());
|
text, e, call.getCallElement());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
leaveTemps();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -203,7 +207,7 @@ public class InlineCodegen implements ParentCodegenAware, CallGenerator {
|
|||||||
|
|
||||||
VarRemapper.ParamRemapper remapper = new VarRemapper.ParamRemapper(parameters, initialFrameSize);
|
VarRemapper.ParamRemapper remapper = new VarRemapper.ParamRemapper(parameters, initialFrameSize);
|
||||||
|
|
||||||
inliner.doTransformAndMerge(codegen.getInstructionAdapter(), remapper);
|
inliner.doTransformAndMerge(codegen.v, remapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -242,13 +246,12 @@ public class InlineCodegen implements ParentCodegenAware, CallGenerator {
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void putInLocal(@NotNull Type type, @Nullable StackValue stackValue, ValueParameterDescriptor valueParameterDescriptor) {
|
public void afterParameterPut(@NotNull Type type, @Nullable StackValue stackValue, ValueParameterDescriptor valueParameterDescriptor) {
|
||||||
putCapturedInLocal(type, stackValue, valueParameterDescriptor, -1);
|
putCapturedInLocal(type, stackValue, valueParameterDescriptor, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void putCapturedInLocal(
|
public void putCapturedInLocal(
|
||||||
@NotNull Type type, @Nullable StackValue stackValue, @Nullable ValueParameterDescriptor valueParameterDescriptor, int index
|
@NotNull Type type, @Nullable StackValue stackValue, @Nullable ValueParameterDescriptor valueParameterDescriptor, int capturedParamIndex
|
||||||
) {
|
) {
|
||||||
if (!asFunctionInline && Type.VOID_TYPE != type) {
|
if (!asFunctionInline && Type.VOID_TYPE != type) {
|
||||||
//TODO remap only inlinable closure => otherwise we could get a lot of problem
|
//TODO remap only inlinable closure => otherwise we could get a lot of problem
|
||||||
@@ -257,8 +260,8 @@ public class InlineCodegen implements ParentCodegenAware, CallGenerator {
|
|||||||
|
|
||||||
ParameterInfo info = new ParameterInfo(type, false, couldBeRemapped ? -1 : codegen.getFrameMap().enterTemp(type), remappedIndex);
|
ParameterInfo info = new ParameterInfo(type, false, couldBeRemapped ? -1 : codegen.getFrameMap().enterTemp(type), remappedIndex);
|
||||||
|
|
||||||
if (index >= 0 && couldBeRemapped) {
|
if (capturedParamIndex >= 0 && couldBeRemapped) {
|
||||||
CapturedParamInfo capturedParamInfo = activeLambda.getCapturedVars().get(index);
|
CapturedParamInfo capturedParamInfo = activeLambda.getCapturedVars().get(capturedParamIndex);
|
||||||
capturedParamInfo.setRemapValue(remappedIndex != null ? remappedIndex : StackValue.local(info.getIndex(), info.getType()));
|
capturedParamInfo.setRemapValue(remappedIndex != null ? remappedIndex : StackValue.local(info.getIndex(), info.getType()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -266,9 +269,7 @@ public class InlineCodegen implements ParentCodegenAware, CallGenerator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*descriptor is null for captured vars*/
|
/*descriptor is null for captured vars*/
|
||||||
@Override
|
|
||||||
public boolean shouldPutValue(
|
public boolean shouldPutValue(
|
||||||
@NotNull Type type,
|
@NotNull Type type,
|
||||||
@Nullable StackValue stackValue,
|
@Nullable StackValue stackValue,
|
||||||
@@ -324,7 +325,7 @@ public class InlineCodegen implements ParentCodegenAware, CallGenerator {
|
|||||||
if (!info.isSkippedOrRemapped()) {
|
if (!info.isSkippedOrRemapped()) {
|
||||||
int index = info.getIndex();
|
int index = info.getIndex();
|
||||||
Type type = info.type;
|
Type type = info.type;
|
||||||
StackValue.local(index, type).store(type, codegen.getInstructionAdapter());
|
StackValue.local(index, type).store(type, codegen.v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -353,7 +354,6 @@ public class InlineCodegen implements ParentCodegenAware, CallGenerator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void leaveTemps() {
|
public void leaveTemps() {
|
||||||
FrameMap frameMap = codegen.getFrameMap();
|
FrameMap frameMap = codegen.getFrameMap();
|
||||||
for (ListIterator<? extends ParameterInfo> iterator = actualParameters.listIterator(actualParameters.size()); iterator.hasPrevious(); ) {
|
for (ListIterator<? extends ParameterInfo> iterator = actualParameters.listIterator(actualParameters.size()); iterator.hasPrevious(); ) {
|
||||||
@@ -364,14 +364,12 @@ public class InlineCodegen implements ParentCodegenAware, CallGenerator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public static boolean isInliningClosure(JetExpression expression, ValueParameterDescriptor valueParameterDescriptora) {
|
||||||
public boolean isInliningClosure(JetExpression expression, ValueParameterDescriptor valueParameterDescriptora) {
|
|
||||||
//TODO deparenthisise
|
//TODO deparenthisise
|
||||||
return expression instanceof JetFunctionLiteralExpression &&
|
return expression instanceof JetFunctionLiteralExpression &&
|
||||||
!InlineUtil.hasNoinlineAnnotation(valueParameterDescriptora);
|
!InlineUtil.hasNoinlineAnnotation(valueParameterDescriptora);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void rememberClosure(JetFunctionLiteralExpression expression, Type type) {
|
public void rememberClosure(JetFunctionLiteralExpression expression, Type type) {
|
||||||
ParameterInfo closureInfo = new ParameterInfo(type, true, -1, -1);
|
ParameterInfo closureInfo = new ParameterInfo(type, true, -1, -1);
|
||||||
int index = recordParamInfo(closureInfo, true);
|
int index = recordParamInfo(closureInfo, true);
|
||||||
@@ -450,4 +448,32 @@ public class InlineCodegen implements ParentCodegenAware, CallGenerator {
|
|||||||
private static String descriptorName(DeclarationDescriptor descriptor) {
|
private static String descriptorName(DeclarationDescriptor descriptor) {
|
||||||
return DescriptorRenderer.SHORT_NAMES_IN_TYPES.render(descriptor);
|
return DescriptorRenderer.SHORT_NAMES_IN_TYPES.render(descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void genValueAndPut(
|
||||||
|
@NotNull ValueParameterDescriptor valueParameterDescriptor,
|
||||||
|
@NotNull JetExpression argumentExpression,
|
||||||
|
@NotNull Type parameterType
|
||||||
|
) {
|
||||||
|
//TODO deparenthisise
|
||||||
|
if (isInliningClosure(argumentExpression, valueParameterDescriptor)) {
|
||||||
|
rememberClosure((JetFunctionLiteralExpression) argumentExpression, parameterType);
|
||||||
|
} else {
|
||||||
|
StackValue value = codegen.gen(argumentExpression);
|
||||||
|
if (shouldPutValue(parameterType, value, valueParameterDescriptor)) {
|
||||||
|
value.put(parameterType, codegen.v);
|
||||||
|
}
|
||||||
|
afterParameterPut(parameterType, value, valueParameterDescriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void putCapturedValueOnStack(
|
||||||
|
@NotNull StackValue stackValue, @NotNull Type valueType, int paramIndex
|
||||||
|
) {
|
||||||
|
if (shouldPutValue(stackValue.type, stackValue, null)) {
|
||||||
|
stackValue.put(stackValue.type, codegen.v);
|
||||||
|
}
|
||||||
|
putCapturedInLocal(stackValue.type, stackValue, null, paramIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user