Get rid of myStack holding intermediate StackValues and use functional style visitor instead.

This commit is contained in:
Maxim Shafirov
2011-08-22 18:36:41 +04:00
parent 4571d94c82
commit b3b8a23f4e
17 changed files with 259 additions and 291 deletions
@@ -37,7 +37,7 @@ public class ClassContext {
} }
public StackValue getThisExpression() { public StackValue getThisExpression() {
if (parentContext == null) return null; if (parentContext == null) return StackValue.none();
thisWasUsed = true; thisWasUsed = true;
if (thisExpression != null) return thisExpression; if (thisExpression != null) return thisExpression;
File diff suppressed because it is too large Load Diff
@@ -3,7 +3,9 @@ package org.jetbrains.jet.codegen;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.JetDeclarationWithBody;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetNamedFunction;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.MethodVisitor;
@@ -12,7 +14,6 @@ import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter; import org.objectweb.asm.commons.InstructionAdapter;
import org.objectweb.asm.commons.Method; import org.objectweb.asm.commons.Method;
import java.util.Collections;
import java.util.List; import java.util.List;
/** /**
@@ -40,11 +41,10 @@ public class FunctionCodegen {
ClassContext funContext = owner.intoFunction(functionDescriptor); ClassContext funContext = owner.intoFunction(functionDescriptor);
final JetExpression bodyExpression = f.getBodyExpression(); final JetExpression bodyExpression = f.getBodyExpression();
final List<JetElement> bodyExpressions = bodyExpression != null ? Collections.<JetElement>singletonList(bodyExpression) : null; generatedMethod(bodyExpression, jvmMethod, funContext, functionDescriptor.getValueParameters(), functionDescriptor.getTypeParameters());
generatedMethod(bodyExpressions, jvmMethod, funContext, functionDescriptor.getValueParameters(), functionDescriptor.getTypeParameters());
} }
private void generatedMethod(List<JetElement> bodyExpressions, private void generatedMethod(JetExpression bodyExpressions,
Method jvmSignature, Method jvmSignature,
ClassContext context, ClassContext context,
List<ValueParameterDescriptor> paramDescrs, List<ValueParameterDescriptor> paramDescrs,
@@ -95,35 +95,11 @@ public class FunctionCodegen {
iv.areturn(jvmSignature.getReturnType()); iv.areturn(jvmSignature.getReturnType());
} }
else if (!isAbstract) { else if (!isAbstract) {
JetElement last = null; codegen.returnExpression(bodyExpressions);
for (JetElement expression : bodyExpressions) {
expression.accept(codegen);
last = expression;
}
generateReturn(mv, last, codegen, jvmSignature);
} }
mv.visitMaxs(0, 0); mv.visitMaxs(0, 0);
mv.visitEnd(); mv.visitEnd();
} }
} }
private void generateReturn(MethodVisitor mv, JetElement bodyExpression, ExpressionCodegen codegen, Method jvmSignature) {
if (!endsWithReturn(bodyExpression)) {
if (jvmSignature.getReturnType() == Type.VOID_TYPE) {
mv.visitInsn(Opcodes.RETURN);
}
else {
codegen.returnTopOfStack();
}
}
}
private static boolean endsWithReturn(JetElement bodyExpression) {
if (bodyExpression instanceof JetBlockExpression) {
final List<JetElement> statements = ((JetBlockExpression) bodyExpression).getStatements();
return statements.size() > 0 && statements.get(statements.size()-1) instanceof JetReturnExpression;
}
return bodyExpression instanceof JetReturnExpression;
}
} }
@@ -48,8 +48,7 @@ public abstract class StackValue {
} }
public static StackValue onStack(Type type) { public static StackValue onStack(Type type) {
assert type != Type.VOID_TYPE; return type == Type.VOID_TYPE ? none() : new OnStack(type);
return new OnStack(type);
} }
public static StackValue constant(Object value, Type type) { public static StackValue constant(Object value, Type type) {
@@ -190,6 +189,21 @@ public abstract class StackValue {
v.mark(end); v.mark(end);
} }
public static StackValue none() {
return None.INSTANCE;
}
private static class None extends StackValue {
public static None INSTANCE = new None();
private None() {
super(Type.VOID_TYPE);
}
@Override
public void put(Type type, InstructionAdapter v) {
}
}
public static class Local extends StackValue { public static class Local extends StackValue {
private final int index; private final int index;
@@ -15,8 +15,8 @@ import java.util.List;
*/ */
public class ArraySize implements IntrinsicMethod { public class ArraySize implements IntrinsicMethod {
@Override @Override
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, boolean haveReceiver) { public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
codegen.ensureReceiverOnStack(element, null, JetTypeMapper.TYPE_OBJECT); receiver.put(JetTypeMapper.TYPE_OBJECT, v);
v.arraylength(); v.arraylength();
return StackValue.onStack(Type.INT_TYPE); return StackValue.onStack(Type.INT_TYPE);
} }
@@ -2,7 +2,6 @@ package org.jetbrains.jet.codegen.intrinsics;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import org.jetbrains.jet.codegen.ExpressionCodegen; import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.JetTypeMapper;
import org.jetbrains.jet.codegen.StackValue; import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetExpression;
import org.objectweb.asm.Type; import org.objectweb.asm.Type;
@@ -21,16 +20,16 @@ public class BinaryOp implements IntrinsicMethod {
} }
@Override @Override
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, boolean haveReceiver) { public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
if (arguments.size() == 1) { if (arguments.size() == 1) {
// intrinsic is called as an ordinary function // intrinsic is called as an ordinary function
codegen.ensureReceiverOnStack(element, null, expectedType); if (receiver != null) {
receiver.put(expectedType, v);
}
codegen.gen(arguments.get(0), expectedType); codegen.gen(arguments.get(0), expectedType);
} }
else { else {
if (!haveReceiver) { codegen.gen(arguments.get(0), expectedType);
codegen.gen(arguments.get(0), expectedType);
}
codegen.gen(arguments.get(1), expectedType); codegen.gen(arguments.get(1), expectedType);
} }
v.visitInsn(expectedType.getOpcode(opcode)); v.visitInsn(expectedType.getOpcode(opcode));
@@ -14,16 +14,18 @@ import java.util.List;
*/ */
public class Concat implements IntrinsicMethod { public class Concat implements IntrinsicMethod {
@Override @Override
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, boolean haveReceiver) { public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
codegen.generateStringBuilderConstructor(); codegen.generateStringBuilderConstructor();
if (haveReceiver) { if (receiver == null) { // LHS.plus(RHS)
v.swap(); v.swap(); // StringBuilder LHS
codegen.invokeAppendMethod(codegen.expressionType(arguments.get(0))); codegen.invokeAppendMethod(codegen.expressionType(arguments.get(0))); // StringBuilder(LHS)
}
else {
codegen.invokeAppend(arguments.get(0)); codegen.invokeAppend(arguments.get(0));
} }
codegen.invokeAppend(arguments.get(1)); else { // LHS + RHS
codegen.invokeAppend(arguments.get(0)); // StringBuilder(LHS)
codegen.invokeAppend(arguments.get(1));
}
v.invokevirtual(ExpressionCodegen.CLASS_STRING_BUILDER, "toString", "()Ljava/lang/String;"); v.invokevirtual(ExpressionCodegen.CLASS_STRING_BUILDER, "toString", "()Ljava/lang/String;");
return StackValue.onStack(Type.getObjectType("java/lang/String")); return StackValue.onStack(Type.getObjectType("java/lang/String"));
} }
@@ -22,7 +22,7 @@ public class Increment implements IntrinsicMethod {
} }
@Override @Override
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, boolean haveReceiver) { public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
final JetExpression operand = arguments.get(0); final JetExpression operand = arguments.get(0);
if (operand instanceof JetReferenceExpression) { if (operand instanceof JetReferenceExpression) {
final int index = codegen.indexOfLocal((JetReferenceExpression) operand); final int index = codegen.indexOfLocal((JetReferenceExpression) operand);
@@ -31,7 +31,7 @@ public class Increment implements IntrinsicMethod {
return StackValue.local(index, expectedType); return StackValue.local(index, expectedType);
} }
} }
StackValue value = codegen.generateIntermediateValue(operand); StackValue value = codegen.genQualified(receiver, operand);
value.dupReceiver(v, 0); value.dupReceiver(v, 0);
value.put(expectedType, v); value.put(expectedType, v);
if (expectedType == Type.LONG_TYPE) { if (expectedType == Type.LONG_TYPE) {
@@ -14,5 +14,5 @@ import java.util.List;
* @author yole * @author yole
*/ */
public interface IntrinsicMethod extends Callable { public interface IntrinsicMethod extends Callable {
StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, boolean haveReceiver); StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver);
} }
@@ -14,8 +14,8 @@ import java.util.List;
*/ */
public class Inv implements IntrinsicMethod { public class Inv implements IntrinsicMethod {
@Override @Override
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, boolean haveReceiver) { public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
codegen.putTopOfStack(expectedType); receiver.put(expectedType, v);
v.aconst(-1); v.aconst(-1);
v.xor(expectedType); v.xor(expectedType);
return StackValue.onStack(expectedType); return StackValue.onStack(expectedType);
@@ -14,13 +14,13 @@ import java.util.List;
*/ */
public class Not implements IntrinsicMethod { public class Not implements IntrinsicMethod {
@Override @Override
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, boolean haveReceiver) { public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
final StackValue stackValue; final StackValue stackValue;
if (arguments.size() == 1) { if (arguments.size() == 1) {
stackValue = codegen.generateIntermediateValue(arguments.get(0)); stackValue = codegen.gen(arguments.get(0));
} }
else { else {
stackValue = codegen.getReceiverAsStackValue(element, null, expectedType); stackValue = receiver;
} }
return StackValue.not(stackValue); return StackValue.not(stackValue);
} }
@@ -14,8 +14,8 @@ import java.util.List;
*/ */
public class NumberCast implements IntrinsicMethod { public class NumberCast implements IntrinsicMethod {
@Override @Override
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, boolean haveReceiver) { public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
codegen.putTopOfStack(expectedType); receiver.put(expectedType, v);
return StackValue.onStack(expectedType); return StackValue.onStack(expectedType);
} }
} }
@@ -24,9 +24,9 @@ public class PsiMethodCall implements IntrinsicMethod {
@Override @Override
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element,
List<JetExpression> arguments, boolean haveReceiver) { List<JetExpression> arguments, StackValue receiver) {
final CallableMethod callableMethod = codegen.getTypeMapper().mapToCallableMethod(myMethod); final CallableMethod callableMethod = codegen.getTypeMapper().mapToCallableMethod(myMethod);
codegen.invokeMethodWithArguments(callableMethod, (JetCallExpression) element, haveReceiver); codegen.invokeMethodWithArguments(callableMethod, (JetCallExpression) element, receiver);
return StackValue.onStack(callableMethod.getSignature().getReturnType()); return StackValue.onStack(callableMethod.getSignature().getReturnType());
} }
} }
@@ -21,7 +21,7 @@ public class RangeTo implements IntrinsicMethod {
private static final String CLASS_INT_RANGE = "jet/IntRange"; private static final String CLASS_INT_RANGE = "jet/IntRange";
@Override @Override
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, boolean haveReceiver) { public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
JetBinaryExpression expression = (JetBinaryExpression) element; JetBinaryExpression expression = (JetBinaryExpression) element;
final Type leftType = codegen.expressionType(expression.getLeft()); final Type leftType = codegen.expressionType(expression.getLeft());
if (JetTypeMapper.isIntPrimitive(leftType)) { if (JetTypeMapper.isIntPrimitive(leftType)) {
@@ -17,7 +17,7 @@ import java.util.List;
*/ */
public class TypeInfo implements IntrinsicMethod { public class TypeInfo implements IntrinsicMethod {
@Override @Override
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, boolean haveReceiver) { public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
final List<JetTypeProjection> typeArguments = ((JetCallExpression) element).getTypeArguments(); final List<JetTypeProjection> typeArguments = ((JetCallExpression) element).getTypeArguments();
if (typeArguments.size() != 1) { if (typeArguments.size() != 1) {
throw new UnsupportedOperationException("one type argument expected"); throw new UnsupportedOperationException("one type argument expected");
@@ -14,12 +14,12 @@ import java.util.List;
*/ */
public class UnaryMinus implements IntrinsicMethod { public class UnaryMinus implements IntrinsicMethod {
@Override @Override
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, boolean haveReceiver) { public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
if (arguments.size() == 1) { if (arguments.size() == 1) {
codegen.gen(arguments.get(0), expectedType); codegen.gen(arguments.get(0), expectedType);
} }
else { else {
codegen.ensureReceiverOnStack(element, null, expectedType); receiver.put(expectedType, v);
} }
v.neg(expectedType); v.neg(expectedType);
return StackValue.onStack(expectedType); return StackValue.onStack(expectedType);
@@ -15,7 +15,7 @@ import java.util.List;
*/ */
public class ValueTypeInfo implements IntrinsicMethod { public class ValueTypeInfo implements IntrinsicMethod {
@Override @Override
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, boolean haveReceiver) { public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
codegen.gen(arguments.get(0), JetTypeMapper.TYPE_JET_OBJECT); codegen.gen(arguments.get(0), JetTypeMapper.TYPE_JET_OBJECT);
v.invokeinterface("jet/JetObject", "getTypeInfo", "()Ljet/typeinfo/TypeInfo;"); v.invokeinterface("jet/JetObject", "getTypeInfo", "()Ljet/typeinfo/TypeInfo;");
return StackValue.onStack(JetTypeMapper.TYPE_TYPEINFO); return StackValue.onStack(JetTypeMapper.TYPE_TYPEINFO);