put receiver information into CallableMethod
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user