correct generation of 'this' in DImpl classes

This commit is contained in:
Dmitry Jemerov
2011-05-30 18:14:57 +04:00
parent 02565f669c
commit 8adaf297ef
6 changed files with 62 additions and 29 deletions
@@ -1346,11 +1346,9 @@ public class ExpressionCodegen extends JetVisitor {
}
private void pushOuterClassArguments(ClassDescriptor classDecl) {
final List<ClassDescriptor> outerClassDescriptors = JetTypeMapper.getOuterClassDescriptors(classDecl);
if (outerClassDescriptors.size() > 0) {
if (classDecl.getContainingDeclaration() instanceof ClassDescriptor) {
v.load(0, JetTypeMapper.jetImplementationType(classDecl));
}
// TODO push further outer classes
}
private Type generateJavaConstructorCall(JetNewExpression expression, PsiMethod constructor) {
@@ -1426,12 +1424,14 @@ public class ExpressionCodegen extends JetVisitor {
}
else {
ClassDescriptor contextClass = (ClassDescriptor) contextType;
final Type thisType = typeMapper.jvmType(contextClass, contextKind);
if (contextKind == OwnerKind.IMPLEMENTATION) {
myStack.push(StackValue.local(0, JetTypeMapper.jetImplementationType(contextClass)));
myStack.push(StackValue.local(0, thisType));
}
else if (contextKind == OwnerKind.DELEGATING_IMPLEMENTATION) {
v.load(0, thisType);
myStack.push(StackValue.field(JetTypeMapper.jetInterfaceType(contextClass),
typeMapper.jvmName(contextClass, contextKind),
thisType.getInternalName(),
"$this",
false));
}
@@ -61,7 +61,12 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
generateStaticInitializer();
generatePrimaryConstructor();
try {
generatePrimaryConstructor();
}
catch(RuntimeException e) {
throw new RuntimeException("Error generating primary constructor of class " + myClass.getName() + " with kind " + kind, e);
}
generateGetTypeInfo();
}
@@ -103,23 +108,26 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
iv.invokespecial(superClass, "<init>", /* TODO super constructor descriptor */"()V");
}
int index = 0;
for (ClassDescriptor outerClassDescriptor : JetTypeMapper.getOuterClassDescriptors(descriptor)) {
int index = 1; // this
final DeclarationDescriptor outerDescriptor = descriptor.getContainingDeclaration();
if (outerDescriptor instanceof ClassDescriptor) {
final ClassDescriptor outerClassDescriptor = (ClassDescriptor) outerDescriptor;
final Type type = JetTypeMapper.jetInterfaceType(outerClassDescriptor);
String interfaceDesc = type.getDescriptor();
final String fieldName = "this$" + index;
final String fieldName = "this$0";
v.visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL, fieldName, interfaceDesc, null, null);
iv.load(0, classType);
iv.load(index + 1, type);
iv.load(index, type);
iv.putfield(classname, fieldName, interfaceDesc);
frameMap.enterTemp();
index++;
}
if (kind == OwnerKind.DELEGATING_IMPLEMENTATION) {
String interfaceDesc = JetTypeMapper.jetInterfaceType(descriptor).getDescriptor();
v.visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL, "$this", interfaceDesc, /*TODO*/null, null);
iv.load(0, classType);
iv.load(1, argTypes[0]);
iv.load(index, argTypes[0]);
iv.putfield(classname, "$this", interfaceDesc);
frameMap.enterTemp();
}
@@ -253,8 +253,9 @@ public class JetTypeMapper {
List<ValueParameterDescriptor> parameters = descriptor.getUnsubstitutedValueParameters();
List<Type> parameterTypes = new ArrayList<Type>();
ClassDescriptor classDescriptor = descriptor.getContainingDeclaration();
for (ClassDescriptor outerDescriptor : getOuterClassDescriptors(classDescriptor)) {
parameterTypes.add(jvmType(outerDescriptor, OwnerKind.IMPLEMENTATION));
final DeclarationDescriptor outerDescriptor = classDescriptor.getContainingDeclaration();
if (outerDescriptor instanceof ClassDescriptor) {
parameterTypes.add(jvmType((ClassDescriptor) outerDescriptor, OwnerKind.IMPLEMENTATION));
}
if (delegate) {
parameterTypes.add(jetInterfaceType(classDescriptor));
@@ -271,16 +272,6 @@ public class JetTypeMapper {
return new Method("<init>", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()]));
}
public static List<ClassDescriptor> getOuterClassDescriptors(ClassDescriptor classDescriptor) {
List<ClassDescriptor> result = new ArrayList<ClassDescriptor>();
DeclarationDescriptor outerClass = classDescriptor.getContainingDeclaration();
while (outerClass instanceof ClassDescriptor) {
result.add((ClassDescriptor) outerClass);
outerClass = outerClass.getContainingDeclaration();
}
return result;
}
static int getAccessModifiers(JetDeclaration p, int defaultFlags) {
int flags = 0;
if (p.hasModifier(JetTokens.PUBLIC_KEYWORD)) {
@@ -1,21 +1,26 @@
package org.jetbrains.jet.codegen;
import org.objectweb.asm.Type;
/**
* @author max
*/
public class OwnerKind {
public static final OwnerKind NAMESPACE = new OwnerKind();
public static final OwnerKind INTERFACE = new OwnerKind();
public static final OwnerKind IMPLEMENTATION = new OwnerKind();
public static final OwnerKind DELEGATING_IMPLEMENTATION = new OwnerKind();
private final String name;
public OwnerKind(String name) {
this.name = name;
}
public static final OwnerKind NAMESPACE = new OwnerKind("namespace");
public static final OwnerKind INTERFACE = new OwnerKind("interface");
public static final OwnerKind IMPLEMENTATION = new OwnerKind("implementation");
public static final OwnerKind DELEGATING_IMPLEMENTATION = new OwnerKind("delegating implementation");
public static class DelegateKind extends OwnerKind {
private final StackValue delegate;
private final String ownerClass;
public DelegateKind(StackValue delegate, String ownerClass) {
super("delegateKind");
this.delegate = delegate;
this.ownerClass = ownerClass;
}
@@ -28,4 +33,9 @@ public class OwnerKind {
return ownerClass;
}
}
@Override
public String toString() {
return "OwnerKind(" + name + ")";
}
}
@@ -0,0 +1,20 @@
import java.util.*
import java.io.*
class World() {
public val items: ArrayList<Item> = new ArrayList<Item>
class Item() {
{
items.add(this)
}
}
val foo = new Item()
}
fun box() {
val w = new World()
if (w.items.size() != 1) return "fail"
return "OK"
}
@@ -79,4 +79,8 @@ public class ClassGenTest extends CodegenTestCase {
public void testInheritedMethod() throws Exception {
blackBoxFile("classes/inheritedMethod.jet");
}
public void testInitializerBlockDImpl() throws Exception {
blackBoxFile("classes/initializerBlockDImpl.jet");
}
}