use CallableMethod also for Jet constructor calls

This commit is contained in:
Dmitry Jemerov
2011-06-30 20:30:35 +02:00
parent 70dfda124e
commit 4b8f40b238
6 changed files with 36 additions and 47 deletions
@@ -11,13 +11,13 @@ import java.util.List;
*/
public class CallableMethod {
private final String owner;
private final Method descriptor;
private final Method signature;
private final int invokeOpcode;
private final List<Type> valueParameterTypes;
public CallableMethod(String owner, Method descriptor, int invokeOpcode, List<Type> valueParameterTypes) {
public CallableMethod(String owner, Method signature, int invokeOpcode, List<Type> valueParameterTypes) {
this.owner = owner;
this.descriptor = descriptor;
this.signature = signature;
this.invokeOpcode = invokeOpcode;
this.valueParameterTypes = valueParameterTypes;
}
@@ -26,8 +26,8 @@ public class CallableMethod {
return owner;
}
public Method getDescriptor() {
return descriptor;
public Method getSignature() {
return signature;
}
public int getInvokeOpcode() {
@@ -39,6 +39,6 @@ public class CallableMethod {
}
void invoke(InstructionAdapter v) {
v.visitMethodInsn(getInvokeOpcode(), getOwner(), getDescriptor().getName(), getDescriptor().getDescriptor());
v.visitMethodInsn(getInvokeOpcode(), getOwner(), getSignature().getName(), getSignature().getDescriptor());
}
}
@@ -5,7 +5,6 @@ import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.Method;
import java.util.Collections;
import java.util.List;
@@ -18,45 +17,28 @@ public class ConstructorFrameMap extends FrameMap {
private int myDelegateThisIndex = -1;
private int myFirstTypeParameter = -1;
private int myTypeParameterCount = 0;
private int myFirstExplicitArgument = 0;
private Type[] myExplicitArgTypes;
public ConstructorFrameMap(JetTypeMapper typeMapper, @Nullable ConstructorDescriptor descriptor, OwnerKind kind) {
Type[] argTypes = new Type[0];
if (descriptor != null) {
Method method = typeMapper.mapConstructorSignature(descriptor, kind);
argTypes = method.getArgumentTypes();
}
public ConstructorFrameMap(CallableMethod callableMethod, @Nullable ConstructorDescriptor descriptor, OwnerKind kind) {
enterTemp(); // this
ClassDescriptor classDescriptor = null;
if (descriptor != null) {
classDescriptor = descriptor.getContainingDeclaration();
if (classDescriptor.getContainingDeclaration() instanceof ClassDescriptor) {
myOuterThisIndex = enterTemp(); // outer class instance
myFirstExplicitArgument++;
}
}
if (kind == OwnerKind.DELEGATING_IMPLEMENTATION) {
myDelegateThisIndex = enterTemp(); // $this
myFirstExplicitArgument++;
}
if (myFirstExplicitArgument > 0) {
int explicitArgCount = argTypes.length - myFirstExplicitArgument;
myExplicitArgTypes = new Type[explicitArgCount];
System.arraycopy(argTypes, myFirstExplicitArgument, myExplicitArgTypes, 0, explicitArgCount);
}
else {
myExplicitArgTypes = argTypes;
}
List<Type> explicitArgTypes = callableMethod.getValueParameterTypes();
List<ValueParameterDescriptor> paramDescrs = descriptor != null
? descriptor.getValueParameters()
: Collections.<ValueParameterDescriptor>emptyList();
for (int i = 0; i < paramDescrs.size(); i++) {
ValueParameterDescriptor parameter = paramDescrs.get(i);
enter(parameter, myExplicitArgTypes[i].getSize());
enter(parameter, explicitArgTypes.get(i).getSize());
}
@@ -88,8 +70,4 @@ public class ConstructorFrameMap extends FrameMap {
public int getTypeParameterCount() {
return myTypeParameterCount;
}
public Type[] getExplicitArgTypes() {
return myExplicitArgTypes;
}
}
@@ -798,7 +798,7 @@ public class ExpressionCodegen extends JetVisitor {
pushMethodArguments(expression, callableMethod.getValueParameterTypes());
pushTypeArguments(expression);
callableMethod.invoke(v);
methodDescriptor = callableMethod.getDescriptor();
methodDescriptor = callableMethod.getSignature();
}
else {
gen(callee, Type.getObjectType(ClosureCodegen.getInternalClassName(fd)));
@@ -1460,11 +1460,11 @@ public class ExpressionCodegen extends JetVisitor {
// TODO typechecker must verify that we're the outer class of the instance being created
pushOuterClassArguments(classDecl);
Method method = typeMapper.mapConstructorSignature((ConstructorDescriptor) constructorDescriptor, OwnerKind.IMPLEMENTATION);
pushMethodArguments(expression, method);
CallableMethod method = typeMapper.mapToCallableMethod((ConstructorDescriptor) constructorDescriptor, OwnerKind.IMPLEMENTATION);
pushMethodArguments(expression, method.getValueParameterTypes());
pushTypeArguments(expression);
v.invokespecial(JetTypeMapper.jvmNameForImplementation(classDecl), "<init>", method.getDescriptor());
method.invoke(v);
}
}
else {
@@ -35,7 +35,7 @@ public class FunctionCodegen {
public void gen(JetNamedFunction f, OwnerKind kind) {
final JetTypeReference receiverTypeRef = f.getReceiverTypeRef();
final JetType receiverType = receiverTypeRef == null ? null : state.getBindingContext().resolveTypeReference(receiverTypeRef);
Method method = state.getTypeMapper().mapToCallableMethod(f).getDescriptor();
Method method = state.getTypeMapper().mapToCallableMethod(f).getSignature();
final FunctionDescriptor functionDescriptor = state.getBindingContext().getFunctionDescriptor(f);
generateMethod(f, kind, method, receiverType, functionDescriptor.getValueParameters(),
functionDescriptor.getTypeParameters());
@@ -91,11 +91,14 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
if (constructorDescriptor == null && !(myClass instanceof JetObjectDeclaration)) return;
Method method;
CallableMethod callableMethod;
if (myClass instanceof JetObjectDeclaration) {
method = new Method("<init>", Type.VOID_TYPE, new Type[0]);
callableMethod = new CallableMethod("", method, Opcodes.INVOKESPECIAL, Collections.<Type>emptyList());
}
else {
method = state.getTypeMapper().mapConstructorSignature(constructorDescriptor, kind);
callableMethod = state.getTypeMapper().mapToCallableMethod(constructorDescriptor, kind);
method = callableMethod.getSignature();
}
int flags = Opcodes.ACC_PUBLIC; // TODO
final MethodVisitor mv = v.visitMethod(flags, "<init>", method.getDescriptor(), null, null);
@@ -106,7 +109,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
? constructorDescriptor.getValueParameters()
: Collections.<ValueParameterDescriptor>emptyList();
ConstructorFrameMap frameMap = new ConstructorFrameMap(state.getTypeMapper(), constructorDescriptor, kind);
ConstructorFrameMap frameMap = new ConstructorFrameMap(callableMethod, constructorDescriptor, kind);
final InstructionAdapter iv = new InstructionAdapter(mv);
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE,
@@ -255,15 +258,14 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
iv.load(frameMap.getOuterThisIndex(), state.getTypeMapper().jvmType((ClassDescriptor) descriptor.getContainingDeclaration(), OwnerKind.IMPLEMENTATION));
}
Method method = state.getTypeMapper().mapConstructorSignature(constructorDescriptor, kind);
List<ValueParameterDescriptor> valueParameters = constructorDescriptor.getValueParameters();
CallableMethod method = state.getTypeMapper().mapToCallableMethod(constructorDescriptor, kind);
List<JetArgument> args = constructorCall.getValueArguments();
for (int i = 0, argsSize = args.size(); i < argsSize; i++) {
JetArgument arg = args.get(i);
codegen.gen(arg.getArgumentExpression(), state.getTypeMapper().mapType(valueParameters.get(i).getOutType()));
codegen.gen(arg.getArgumentExpression(), method.getValueParameterTypes().get(i));
}
iv.invokespecial(type.getInternalName(), "<init>", method.getDescriptor());
method.invoke(iv);
}
@Override
@@ -281,12 +283,12 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
if (constructorDescriptor == null) {
throw new UnsupportedOperationException("failed to get descriptor for secondary constructor");
}
Method method = state.getTypeMapper().mapConstructorSignature(constructorDescriptor, kind);
CallableMethod method = state.getTypeMapper().mapToCallableMethod(constructorDescriptor, kind);
int flags = Opcodes.ACC_PUBLIC; // TODO
final MethodVisitor mv = v.visitMethod(flags, "<init>", method.getDescriptor(), null, null);
final MethodVisitor mv = v.visitMethod(flags, "<init>", method.getSignature().getDescriptor(), null, null);
mv.visitCode();
ConstructorFrameMap frameMap = new ConstructorFrameMap(state.getTypeMapper(), constructorDescriptor, kind);
ConstructorFrameMap frameMap = new ConstructorFrameMap(method, constructorDescriptor, kind);
final InstructionAdapter iv = new InstructionAdapter(mv);
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE,
@@ -383,7 +383,7 @@ public class JetTypeMapper {
return new Method(PropertyCodegen.setterName(descriptor.getName()), Type.VOID_TYPE, new Type[] { paramType });
}
public Method mapConstructorSignature(ConstructorDescriptor descriptor, OwnerKind kind) {
private Method mapConstructorSignature(ConstructorDescriptor descriptor, OwnerKind kind, List<Type> valueParameterTypes) {
boolean delegate = kind == OwnerKind.DELEGATING_IMPLEMENTATION;
List<ValueParameterDescriptor> parameters = descriptor.getOriginal().getValueParameters();
List<Type> parameterTypes = new ArrayList<Type>();
@@ -396,7 +396,9 @@ public class JetTypeMapper {
parameterTypes.add(jetInterfaceType(classDescriptor));
}
for (ValueParameterDescriptor parameter : parameters) {
parameterTypes.add(mapType(parameter.getOutType()));
final Type type = mapType(parameter.getOutType());
parameterTypes.add(type);
valueParameterTypes.add(type);
}
List<TypeParameterDescriptor> typeParameters = classDescriptor.getTypeConstructor().getParameters();
@@ -407,6 +409,13 @@ public class JetTypeMapper {
return new Method("<init>", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()]));
}
public CallableMethod mapToCallableMethod(ConstructorDescriptor descriptor, OwnerKind kind) {
List<Type> valueParameterTypes = new ArrayList<Type>();
final Method method = mapConstructorSignature(descriptor, kind, valueParameterTypes);
String owner = jvmName(descriptor.getContainingDeclaration(), kind);
return new CallableMethod(owner, method, Opcodes.INVOKESPECIAL, valueParameterTypes);
}
static int getAccessModifiers(JetDeclaration p, int defaultFlags) {
int flags = 0;
if (p.hasModifier(JetTokens.PUBLIC_KEYWORD)) {