put receiver information into CallableMethod

This commit is contained in:
Dmitry Jemerov
2011-07-06 16:14:31 +02:00
parent d824997dcf
commit 9497b41664
4 changed files with 46 additions and 22 deletions
@@ -1,5 +1,7 @@
package org.jetbrains.jet.codegen;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
import org.objectweb.asm.commons.Method;
@@ -15,6 +17,8 @@ public class CallableMethod {
private final int invokeOpcode;
private final List<Type> valueParameterTypes;
private boolean acceptsTypeArguments = false;
private boolean needsReceiverOnStack = false;
private ClassDescriptor receiverClass = null;
public CallableMethod(String owner, Method signature, int invokeOpcode, List<Type> valueParameterTypes) {
this.owner = owner;
@@ -51,6 +55,19 @@ public class CallableMethod {
this.acceptsTypeArguments = acceptsTypeArguments;
}
public void setNeedsReceiver(@Nullable ClassDescriptor receiverClass) {
needsReceiverOnStack = true;
this.receiverClass = receiverClass;
}
public boolean needsReceiverOnStack() {
return needsReceiverOnStack;
}
public ClassDescriptor getReceiverClass() {
return receiverClass;
}
void invoke(InstructionAdapter v) {
v.visitMethodInsn(getInvokeOpcode(), getOwner(), getSignature().getName(), getSignature().getDescriptor());
}
@@ -245,6 +245,10 @@ public class ClosureCodegen {
public static CallableMethod asCallableMethod(FunctionDescriptor fd) {
Method descriptor = erasedInvokeSignature(fd);
String owner = getInternalClassName(fd);
return new CallableMethod(owner, descriptor, Opcodes.INVOKEVIRTUAL, Arrays.asList(descriptor.getArgumentTypes()));
final CallableMethod result = new CallableMethod(owner, descriptor, Opcodes.INVOKEVIRTUAL, Arrays.asList(descriptor.getArgumentTypes()));
if (fd.getReceiverType() != null) {
result.setNeedsReceiver(null);
}
return result;
}
}
@@ -768,31 +768,15 @@ public class ExpressionCodegen extends JetVisitor {
final PsiMethod psiMethod = (PsiMethod) declarationPsiElement;
callableMethod = JetTypeMapper.mapToCallableMethod(psiMethod);
if (!psiMethod.hasModifierProperty(PsiModifier.STATIC)) {
ensureReceiverOnStack(expression, null);
setOwnerFromCall(callableMethod, expression);
}
}
else if (declarationPsiElement instanceof JetNamedFunction) {
final JetNamedFunction jetFunction = (JetNamedFunction) declarationPsiElement;
callableMethod = typeMapper.mapToCallableMethod(jetFunction);
if (functionParent instanceof NamespaceDescriptorImpl) {
if (jetFunction.getReceiverTypeRef() != null) {
ensureReceiverOnStack(expression, null);
}
}
else if (functionParent instanceof ClassDescriptor) {
ensureReceiverOnStack(expression, (ClassDescriptor) functionParent);
}
}
else {
gen(callee, Type.getObjectType(ClosureCodegen.getInternalClassName(fd)));
boolean isExtensionFunction = fd.getReceiverType() != null;
if (isExtensionFunction) {
ensureReceiverOnStack(expression, null);
}
callableMethod = ClosureCodegen.asCallableMethod(fd);
}
@@ -843,6 +827,9 @@ public class ExpressionCodegen extends JetVisitor {
}
private void invokeMethodWithArguments(CallableMethod callableMethod, JetCallExpression expression) {
if (callableMethod.needsReceiverOnStack()) {
ensureReceiverOnStack(expression, callableMethod.getReceiverClass());
}
pushMethodArguments(expression, callableMethod.getValueParameterTypes());
if (callableMethod.acceptsTypeArguments()) {
pushTypeArguments(expression);
@@ -109,19 +109,27 @@ public class JetTypeMapper {
List<Type> valueParameterTypes = new ArrayList<Type>();
Collections.addAll(valueParameterTypes, signature.getArgumentTypes());
int opcode;
boolean needsReceiver = false;
if (method.isConstructor()) {
opcode = Opcodes.INVOKESPECIAL;
}
else if (method.hasModifierProperty(PsiModifier.STATIC)) {
opcode = Opcodes.INVOKESTATIC;
}
else if (containingClass.isInterface()) {
opcode = Opcodes.INVOKEINTERFACE;
}
else {
opcode = Opcodes.INVOKEVIRTUAL;
needsReceiver = true;
if (containingClass.isInterface()) {
opcode = Opcodes.INVOKEINTERFACE;
}
else {
opcode = Opcodes.INVOKEVIRTUAL;
}
}
return new CallableMethod(owner, signature, opcode, valueParameterTypes);
final CallableMethod result = new CallableMethod(owner, signature, opcode, valueParameterTypes);
if (needsReceiver) {
result.setNeedsReceiver(null);
}
return result;
}
public String jvmName(ClassDescriptor jetClass, OwnerKind kind) {
@@ -382,9 +390,12 @@ public class JetTypeMapper {
Method descriptor = mapSignature(f, valueParameterTypes);
String owner;
int invokeOpcode;
boolean needsReceiver;
ClassDescriptor receiverClass = null;
if (functionParent instanceof NamespaceDescriptor) {
owner = NamespaceCodegen.getJVMClassName(DescriptorRenderer.getFQName(functionParent));
invokeOpcode = Opcodes.INVOKESTATIC;
needsReceiver = f.getReceiverTypeRef() != null;
}
else if (functionParent instanceof ClassDescriptor) {
ClassDescriptor containingClass = (ClassDescriptor) functionParent;
@@ -392,6 +403,8 @@ public class JetTypeMapper {
invokeOpcode = isInterface(containingClass, OwnerKind.INTERFACE)
? Opcodes.INVOKEINTERFACE
: Opcodes.INVOKEVIRTUAL;
needsReceiver = true;
receiverClass = containingClass;
}
else {
throw new UnsupportedOperationException("unknown function parent");
@@ -399,6 +412,9 @@ public class JetTypeMapper {
final CallableMethod result = new CallableMethod(owner, descriptor, invokeOpcode, valueParameterTypes);
result.setAcceptsTypeArguments(true);
if (needsReceiver) {
result.setNeedsReceiver(receiverClass);
}
return result;
}