diff --git a/idea/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java b/idea/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java index a9b64bd2306..ed0735204e8 100644 --- a/idea/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java @@ -20,12 +20,14 @@ public abstract class ClassBodyCodegen { protected final OwnerKind kind; protected final ClassDescriptor descriptor; protected final ClassVisitor v; + protected final ClassContext context; - public ClassBodyCodegen(JetClassOrObject aClass, OwnerKind kind, ClassVisitor v, GenerationState state) { + public ClassBodyCodegen(JetClassOrObject aClass, ClassContext context, ClassVisitor v, GenerationState state) { this.state = state; descriptor = state.getBindingContext().getClassDescriptor(aClass); myClass = aClass; - this.kind = kind; + this.context = context; + this.kind = context.getContextKind(); this.v = v; } @@ -45,8 +47,8 @@ public abstract class ClassBodyCodegen { } private void generateClassBody() { - final FunctionCodegen functionCodegen = new FunctionCodegen((JetDeclaration) myClass, v, state); - final PropertyCodegen propertyCodegen = new PropertyCodegen(v, functionCodegen, state); + final FunctionCodegen functionCodegen = new FunctionCodegen(context, v, state); + final PropertyCodegen propertyCodegen = new PropertyCodegen(context, v, functionCodegen, state); for (JetDeclaration declaration : myClass.getDeclarations()) { generateDeclaration(propertyCodegen, declaration, functionCodegen); @@ -57,25 +59,26 @@ public abstract class ClassBodyCodegen { protected void generateDeclaration(PropertyCodegen propertyCodegen, JetDeclaration declaration, FunctionCodegen functionCodegen) { if (declaration instanceof JetProperty) { - propertyCodegen.gen((JetProperty) declaration, kind); + propertyCodegen.gen((JetProperty) declaration); } else if (declaration instanceof JetNamedFunction) { try { - functionCodegen.gen((JetNamedFunction) declaration, kind); + functionCodegen.gen((JetNamedFunction) declaration); } catch (RuntimeException e) { - throw new RuntimeException("Error generating method " + myClass.getName() + "." + declaration.getName() + " in " + kind, e); + throw new RuntimeException("Error generating method " + myClass.getName() + "." + declaration.getName() + " in " + context, e); } } } private void generatePrimaryConstructorProperties(PropertyCodegen propertyCodegen) { + OwnerKind kind = context.getContextKind(); for (JetParameter p : getPrimaryConstructorParameters()) { if (p.getValOrVarNode() != null) { PropertyDescriptor propertyDescriptor = state.getBindingContext().getPropertyDescriptor(p); if (propertyDescriptor != null) { - propertyCodegen.generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC, kind); + propertyCodegen.generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC); if (propertyDescriptor.isVar()) { - propertyCodegen.generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC, kind); + propertyCodegen.generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC); } if (!(kind instanceof OwnerKind.DelegateKind) && kind != OwnerKind.INTERFACE && state.getBindingContext().hasBackingField(propertyDescriptor)) { diff --git a/idea/src/org/jetbrains/jet/codegen/ClassCodegen.java b/idea/src/org/jetbrains/jet/codegen/ClassCodegen.java index bc7e5b0a041..2ba069000ab 100644 --- a/idea/src/org/jetbrains/jet/codegen/ClassCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ClassCodegen.java @@ -16,36 +16,39 @@ public class ClassCodegen { this.state = state; } - public void generate(JetClassOrObject aClass) { + public void generate(ClassContext parentContext, JetClassOrObject aClass) { state.prepareAnonymousClasses((JetElement) aClass); if (aClass instanceof JetObjectDeclaration) { - generateImplementation(aClass, OwnerKind.IMPLEMENTATION); + generateImplementation(parentContext, aClass, OwnerKind.IMPLEMENTATION); } else { - generateInterface(aClass); - generateImplementation(aClass, OwnerKind.IMPLEMENTATION); - generateImplementation(aClass, OwnerKind.DELEGATING_IMPLEMENTATION); + generateInterface(parentContext, aClass); + generateImplementation(parentContext, aClass, OwnerKind.IMPLEMENTATION); + generateImplementation(parentContext, aClass, OwnerKind.DELEGATING_IMPLEMENTATION); } + ClassDescriptor descriptor = state.getBindingContext().getClassDescriptor(aClass); + final ClassContext contextForInners = parentContext.intoClass(descriptor, OwnerKind.IMPLEMENTATION); for (JetDeclaration declaration : aClass.getDeclarations()) { if (declaration instanceof JetClass) { - generate((JetClass) declaration); + generate(contextForInners, (JetClass) declaration); } } } - private void generateInterface(JetClassOrObject aClass) { - final ClassVisitor visitor = state.forClassInterface(state.getBindingContext().getClassDescriptor(aClass)); - new InterfaceBodyCodegen(aClass, visitor, state).generate(); + private void generateInterface(ClassContext parentContext, JetClassOrObject aClass) { + ClassDescriptor descriptor = state.getBindingContext().getClassDescriptor(aClass); + final ClassVisitor visitor = state.forClassInterface(descriptor); + new InterfaceBodyCodegen(aClass, parentContext.intoClass(descriptor, OwnerKind.INTERFACE), visitor, state).generate(); } - private void generateImplementation(JetClassOrObject aClass, OwnerKind kind) { + private void generateImplementation(ClassContext parentContext, JetClassOrObject aClass, OwnerKind kind) { ClassDescriptor descriptor = state.getBindingContext().getClassDescriptor(aClass); ClassVisitor v = kind == OwnerKind.IMPLEMENTATION ? state.forClassImplementation(descriptor) : state.forClassDelegatingImplementation(descriptor); - new ImplementationBodyCodegen(aClass, kind, v, state).generate(); + new ImplementationBodyCodegen(aClass, parentContext.intoClass(descriptor, kind), v, state).generate(); } diff --git a/idea/src/org/jetbrains/jet/codegen/ClassContext.java b/idea/src/org/jetbrains/jet/codegen/ClassContext.java index 66321d31122..ca188b2ad12 100644 --- a/idea/src/org/jetbrains/jet/codegen/ClassContext.java +++ b/idea/src/org/jetbrains/jet/codegen/ClassContext.java @@ -3,18 +3,23 @@ */ package org.jetbrains.jet.codegen; +import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; +import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; +import org.jetbrains.jet.lang.types.JetType; +import org.objectweb.asm.Type; public class ClassContext { - public static final ClassContext STATIC = new ClassContext(null, OwnerKind.NAMESPACE, null); + public static final ClassContext STATIC = new ClassContext(null, OwnerKind.NAMESPACE, null, null); private final DeclarationDescriptor contextType; private final OwnerKind contextKind; - private final StackValue thisExpression; + private final ClassContext parentContext; - public ClassContext(DeclarationDescriptor contextType, OwnerKind contextKind, StackValue thisExpression) { + public ClassContext(DeclarationDescriptor contextType, OwnerKind contextKind, StackValue thisExpression, ClassContext parentContext) { this.contextType = contextType; this.contextKind = contextKind; - this.thisExpression = thisExpression; + this.parentContext = parentContext; } public DeclarationDescriptor getContextType() { @@ -26,6 +31,82 @@ public class ClassContext { } public StackValue getThisExpression() { - return thisExpression; + int thisIdx = -1; + if (getContextKind() != OwnerKind.NAMESPACE) { + thisIdx++; + } + + if (hasReceiver()) { + thisIdx++; + } + + if (thisIdx == -1) { + throw new RuntimeException("Has no this!" + contextType); + } + + return StackValue.local(thisIdx, JetTypeMapper.TYPE_OBJECT); + } + + public ClassContext intoNamespace(NamespaceDescriptor descriptor) { + return new ClassContext(descriptor, OwnerKind.NAMESPACE, null, this); + } + + public ClassContext intoClass(ClassDescriptor descriptor, OwnerKind kind) { + final StackValue thisValue; + if (kind == OwnerKind.DELEGATING_IMPLEMENTATION) { + thisValue = StackValue.instanceField(JetTypeMapper.jetInterfaceType(descriptor), + JetTypeMapper.jetDelegatingImplementationType(descriptor).getInternalName(), + "$this"); + } + else { + thisValue = StackValue.local(0, JetTypeMapper.TYPE_OBJECT); + } + return new ClassContext(descriptor, kind, thisValue, this); + } + + public ClassContext intoFunction(FunctionDescriptor descriptor) { + return new ClassContext(descriptor, getContextKind(), StackValue.local(0, JetTypeMapper.TYPE_OBJECT), this); + } + + public ClassContext intoClosure() { + return new ClassContext(null, OwnerKind.IMPLEMENTATION, StackValue.local(0, JetTypeMapper.TYPE_OBJECT), this); // TODO! + } + + public FrameMap prepareFrame() { + FrameMap frameMap = new FrameMap(); + + if (getContextKind() != OwnerKind.NAMESPACE) { + frameMap.enterTemp(); // 0 slot for this + } + + if (hasReceiver()) { + frameMap.enterTemp(); // Next slot for fake this + } + + return frameMap; + } + + private JetType receiverType() { + return contextType instanceof FunctionDescriptor ? ((FunctionDescriptor) contextType).getReceiverType() : null; + } + + private boolean hasReceiver() { + return receiverType() != null; + } + + public ClassContext getParentContext() { + return parentContext; + } + + public Type jvmType(JetTypeMapper mapper) { + if (contextType instanceof ClassDescriptor) { + if (contextKind == OwnerKind.INTERFACE) { + System.out.println("OOps?!"); + } + return mapper.jvmType((ClassDescriptor) contextType, contextKind); + } + else { + return JetTypeMapper.TYPE_OBJECT; // TODO? + } } } diff --git a/idea/src/org/jetbrains/jet/codegen/ClosureCodegen.java b/idea/src/org/jetbrains/jet/codegen/ClosureCodegen.java index f3d2983f81d..3525ac50d78 100644 --- a/idea/src/org/jetbrains/jet/codegen/ClosureCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ClosureCodegen.java @@ -8,7 +8,8 @@ import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.descriptors.VariableDescriptor; -import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.psi.JetFunctionLiteral; +import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression; import org.jetbrains.jet.lang.types.JetType; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.MethodVisitor; @@ -25,15 +26,17 @@ import java.util.Map; public class ClosureCodegen { private final GenerationState state; - private final ExpressionCodegen context; + private final ExpressionCodegen exprContext; + private final ClassContext context; private ClassVisitor cv = null; private String name = null; private Map closure = new LinkedHashMap(); - public ClosureCodegen(GenerationState state, ExpressionCodegen context) { + public ClosureCodegen(GenerationState state, ExpressionCodegen exprContext, ClassContext context) { this.state = state; - this.context = context; + this.exprContext = exprContext; + this.context = context.intoClosure(); } public static Method erasedInvokeSignature(FunctionDescriptor fd) { @@ -59,7 +62,7 @@ public class ClosureCodegen { EnclosedValueDescriptor answer = closure.get(vd); if (answer != null) return answer.getInnerValue(); - final int idx = context.lookupLocal(vd); + final int idx = exprContext.lookupLocal(vd); if (idx < 0) return null; final Type type = state.getTypeMapper().mapType(vd.getOutType()); @@ -107,7 +110,7 @@ public class ClosureCodegen { generateBridge(name, funDescriptor, cv); - generateBody(funDescriptor, cv, fun.getFunctionLiteral().getBodyExpression().getStatements()); + generateBody(funDescriptor, cv, fun.getFunctionLiteral()); final Method constructor = generateConstructor(funClass); @@ -121,10 +124,9 @@ public class ClosureCodegen { return answer; } - private void generateBody(FunctionDescriptor funDescriptor, ClassVisitor cv, List body) { - FunctionCodegen fc = new FunctionCodegen(null, cv, state); - fc.generatedMethod(body, OwnerKind.IMPLEMENTATION, invokeSignature(funDescriptor), funDescriptor.getReceiverType(), - funDescriptor.getValueParameters(), funDescriptor.getTypeParameters(), null); + private void generateBody(FunctionDescriptor funDescriptor, ClassVisitor cv, JetFunctionLiteral body) { + FunctionCodegen fc = new FunctionCodegen(context, cv, state); + fc.generateMethod(body, invokeSignature(funDescriptor), funDescriptor); } private void generateBridge(String className, FunctionDescriptor funDescriptor, ClassVisitor cv) { diff --git a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 72a99ac834a..248dce3b3e4 100644 --- a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -5,6 +5,7 @@ import com.intellij.psi.*; import com.intellij.psi.search.ProjectScope; import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiTreeUtil; +import gnu.trove.THashSet; import jet.IntRange; import jet.JetObject; import jet.Range; @@ -79,7 +80,6 @@ public class ExpressionCodegen extends JetVisitor { private final GenerationState state; private final Type returnType; private final BindingContext bindingContext; - private final Map outerThisExpressions = new HashMap(); private final Map typeParameterExpressions = new HashMap(); private final ClassContext context; @@ -97,10 +97,6 @@ public class ExpressionCodegen extends JetVisitor { this.context = context; } - public void addOuterThis(ClassDescriptor outer, StackValue expression) { - outerThisExpressions.put(outer, expression); - } - public void addTypeParameter(TypeParameterDescriptor typeParameter, StackValue expression) { typeParameterExpressions.put(typeParameter, expression); } @@ -315,7 +311,12 @@ public class ExpressionCodegen extends JetVisitor { } private DeclarationDescriptor contextType() { - return context.getContextType(); + DeclarationDescriptor descriptor = context.getContextType(); + while (descriptor != null) { + if (descriptor instanceof ClassDescriptor || descriptor instanceof NamespaceDescriptor) return descriptor; + descriptor = descriptor.getContainingDeclaration(); + } + return descriptor; } private OwnerKind contextKind() { @@ -505,7 +506,7 @@ public class ExpressionCodegen extends JetVisitor { generateBlock(expression.getFunctionLiteral().getBodyExpression().getStatements()); } else { - final GeneratedAnonymousClassDescriptor closure = state.generateClosure(expression, this); + final GeneratedAnonymousClassDescriptor closure = state.generateClosure(expression, this, context); v.anew(Type.getObjectType(closure.getClassname())); v.dup(); @@ -523,7 +524,7 @@ public class ExpressionCodegen extends JetVisitor { @Override public void visitObjectLiteralExpression(JetObjectLiteralExpression expression) { - GeneratedAnonymousClassDescriptor descriptor = state.generateObjectLiteral(expression, this); + GeneratedAnonymousClassDescriptor descriptor = state.generateObjectLiteral(expression, this, context); v.anew(Type.getObjectType(descriptor.getClassname())); v.dup(); v.invokespecial(descriptor.getClassname(), "", descriptor.getConstructor().getDescriptor()); @@ -885,30 +886,69 @@ public class ExpressionCodegen extends JetVisitor { } } else if (!(expression.getParent() instanceof JetSafeQualifiedExpression)) { - final StackValue value = generateThisOrOuter(calleeContainingClass); - value.put(value.type, v); + generateThisOrOuter(calleeContainingClass); } } - public StackValue generateThisOrOuter(ClassDescriptor calleeContainingClass) { - final StackValue value = outerThisExpressions.get(calleeContainingClass); - if (value != null) { - return value; + private static boolean isSubclass(ClassDescriptor subClass, ClassDescriptor superClass) { + Set allSuperTypes = new THashSet(); + + addSuperTypes(subClass.getDefaultType(), allSuperTypes); + + final DeclarationDescriptor superOriginal = superClass.getOriginal(); + + for (JetType superType : allSuperTypes) { + final DeclarationDescriptor descriptor = superType.getConstructor().getDeclarationDescriptor(); + if (descriptor != null && superOriginal == descriptor.getOriginal()) { + return true; + } } - else { - // TODO hope it works; really need more checks here :) - if (calleeContainingClass != null && contextType() instanceof ClassDescriptor && - calleeContainingClass == contextType().getContainingDeclaration()) { - v.load(0, JetTypeMapper.TYPE_OBJECT); - return StackValue.field(typeMapper.jvmType(calleeContainingClass, OwnerKind.IMPLEMENTATION), - typeMapper.jvmName((ClassDescriptor) contextType(), OwnerKind.IMPLEMENTATION), - "this$0", - false); - // TODO handle more levels of class nestng - } - else { - return thisExpression() != null ? thisExpression() : StackValue.local(0, JetTypeMapper.TYPE_OBJECT); + + return false; + } + + private static void addSuperTypes(JetType type, Set set) { + set.add(type); + + for (JetType jetType : type.getConstructor().getSupertypes()) { + addSuperTypes(jetType, set); + } + } + + public void generateThisOrOuter(ClassDescriptor calleeContainingClass) { + boolean thisDone = false; + + ClassContext cur = context; + while (true) { + ClassContext parentContext = cur.getParentContext(); + if (parentContext == null) break; + + final DeclarationDescriptor curContextType = cur.getContextType(); + if (curContextType instanceof ClassDescriptor) { + if (isSubclass((ClassDescriptor) curContextType, calleeContainingClass)) break; + + final StackValue outer; + if (!thisDone && myMap instanceof ConstructorFrameMap) { + outer = StackValue.local(((ConstructorFrameMap) myMap).getOuterThisIndex(), JetTypeMapper.TYPE_OBJECT); + } + else { + thisToStack(); + outer = StackValue.field(parentContext.jvmType(typeMapper), + cur.jvmType(typeMapper).getInternalName(), + "this$0", + false); + } + + thisDone = true; + outer.put(outer.type, v); + } + + cur = parentContext; + } + + if (!thisDone) { + thisToStack(); } } @@ -1492,7 +1532,8 @@ public class ExpressionCodegen extends JetVisitor { public void visitThisExpression(JetThisExpression expression) { final DeclarationDescriptor descriptor = bindingContext.resolveReferenceExpression(expression.getThisReference()); if (descriptor instanceof ClassDescriptor) { - myStack.push(generateThisOrOuter((ClassDescriptor) descriptor)); + generateThisOrOuter((ClassDescriptor) descriptor); + myStack.push(StackValue.onStack(JetTypeMapper.TYPE_OBJECT)); } else { generateThis(); @@ -1505,27 +1546,7 @@ public class ExpressionCodegen extends JetVisitor { } private void generateThis() { - if (thisExpression() != null) { - myStack.push(thisExpression()); - return; - } - if (contextKind() != OwnerKind.NAMESPACE) { - ClassDescriptor contextClass = (ClassDescriptor) contextType(); - final Type thisType = typeMapper.jvmType(contextClass, contextKind()); - if (contextKind() == OwnerKind.IMPLEMENTATION) { - myStack.push(StackValue.local(0, thisType)); - return; - } - else if (contextKind() == OwnerKind.DELEGATING_IMPLEMENTATION) { - v.load(0, thisType); - myStack.push(StackValue.field(JetTypeMapper.jetInterfaceType(contextClass), - thisType.getInternalName(), - "$this", - false)); - return; - } - } - throw new UnsupportedOperationException("'this' expression is not defined in the context"); + myStack.push(thisExpression()); } @Override diff --git a/idea/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/idea/src/org/jetbrains/jet/codegen/FunctionCodegen.java index 835065387a7..a7f11a8de4b 100644 --- a/idea/src/org/jetbrains/jet/codegen/FunctionCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/FunctionCodegen.java @@ -1,12 +1,9 @@ package org.jetbrains.jet.codegen; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.psi.*; -import org.jetbrains.jet.lang.types.JetType; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; @@ -22,49 +19,40 @@ import java.util.List; * @author yole */ public class FunctionCodegen { - private final JetDeclaration owner; + private final ClassContext owner; private final ClassVisitor v; private final GenerationState state; - public FunctionCodegen(JetDeclaration owner, ClassVisitor v, GenerationState state) { + public FunctionCodegen(ClassContext owner, ClassVisitor v, GenerationState state) { this.owner = owner; this.v = v; this.state = state; } - public void gen(JetNamedFunction f, OwnerKind kind) { - final JetTypeReference receiverTypeRef = f.getReceiverTypeRef(); - final JetType receiverType = receiverTypeRef == null ? null : state.getBindingContext().resolveTypeReference(receiverTypeRef); + public void gen(JetNamedFunction f) { Method method = state.getTypeMapper().mapToCallableMethod(f).getSignature(); final FunctionDescriptor functionDescriptor = state.getBindingContext().getFunctionDescriptor(f); - generateMethod(f, kind, method, receiverType, functionDescriptor.getValueParameters(), - functionDescriptor.getTypeParameters()); + generateMethod(f, method, functionDescriptor); } - public void generateMethod(JetDeclarationWithBody f, - OwnerKind kind, - Method jvmSignature, - @Nullable JetType receiverType, - List paramDescrs, - List typeParameters) { - final DeclarationDescriptor contextDesc = owner instanceof JetClassOrObject - ? state.getBindingContext().getClassDescriptor((JetClassOrObject) owner) - : state.getBindingContext().getNamespaceDescriptor((JetNamespace) owner); + public void generateMethod(JetDeclarationWithBody f, Method jvmMethod, FunctionDescriptor functionDescriptor) { + ClassContext funContext = owner.intoFunction(functionDescriptor); + final JetExpression bodyExpression = f.getBodyExpression(); final List bodyExpressions = bodyExpression != null ? Collections.singletonList(bodyExpression) : null; - generatedMethod(bodyExpressions, kind, jvmSignature, receiverType, paramDescrs, typeParameters, contextDesc); + generatedMethod(bodyExpressions, jvmMethod, funContext, functionDescriptor.getValueParameters(), functionDescriptor.getTypeParameters()); } - public void generatedMethod(List bodyExpressions, - OwnerKind kind, - Method jvmSignature, - JetType receiverType, - List paramDescrs, - List typeParameters, - DeclarationDescriptor contextDesc) + private void generatedMethod(List bodyExpressions, + Method jvmSignature, + ClassContext context, + List paramDescrs, + List typeParameters) { int flags = Opcodes.ACC_PUBLIC; // TODO. + OwnerKind kind = context.getContextKind(); + boolean isStatic = kind == OwnerKind.NAMESPACE; if (isStatic) flags |= Opcodes.ACC_STATIC; @@ -78,34 +66,19 @@ public class FunctionCodegen { final MethodVisitor mv = v.visitMethod(flags, jvmSignature.getName(), jvmSignature.getDescriptor(), null, null); if (kind != OwnerKind.INTERFACE) { mv.visitCode(); - FrameMap frameMap = new FrameMap(); + FrameMap frameMap = context.prepareFrame(); - int thisIdx = -1; - if (kind != OwnerKind.NAMESPACE) { - frameMap.enterTemp(); // 0 slot for this - thisIdx++; - } - - if (receiverType != null) { - thisIdx++; - frameMap.enterTemp(); // Next slot for fake this - } - - StackValue thisExpression = receiverType == null ? null : StackValue.local(thisIdx, state.getTypeMapper().mapType(receiverType)); - ClassContext context = new ClassContext(contextDesc, kind, thisExpression); ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, jvmSignature.getReturnType(), context, state); - int firstArg = thisIdx+1; Type[] argTypes = jvmSignature.getArgumentTypes(); for (int i = 0; i < paramDescrs.size(); i++) { ValueParameterDescriptor parameter = paramDescrs.get(i); frameMap.enter(parameter, argTypes[i].getSize()); } - for (int i = 0; i < typeParameters.size(); i++) { - final TypeParameterDescriptor typeParameterDescriptor = typeParameters.get(i); - codegen.addTypeParameter(typeParameterDescriptor, - StackValue.local(firstArg + paramDescrs.size() + i, JetTypeMapper.TYPE_TYPEINFO)); - frameMap.enterTemp(); + + for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) { + int slot = frameMap.enterTemp(); + codegen.addTypeParameter(typeParameterDescriptor, StackValue.local(slot, JetTypeMapper.TYPE_TYPEINFO)); } if (kind instanceof OwnerKind.DelegateKind) { diff --git a/idea/src/org/jetbrains/jet/codegen/GenerationState.java b/idea/src/org/jetbrains/jet/codegen/GenerationState.java index c825b2a8fc8..3c2308ef79c 100644 --- a/idea/src/org/jetbrains/jet/codegen/GenerationState.java +++ b/idea/src/org/jetbrains/jet/codegen/GenerationState.java @@ -94,8 +94,8 @@ public class GenerationState { } } - public GeneratedAnonymousClassDescriptor generateClosure(JetFunctionLiteralExpression literal, ExpressionCodegen context) { - final ClosureCodegen codegen = new ClosureCodegen(this, context); + public GeneratedAnonymousClassDescriptor generateClosure(JetFunctionLiteralExpression literal, ExpressionCodegen context, ClassContext classContext) { + final ClosureCodegen codegen = new ClosureCodegen(this, context, classContext); closureContexts.push(codegen); try { return codegen.gen(literal); @@ -106,9 +106,12 @@ public class GenerationState { } } - public GeneratedAnonymousClassDescriptor generateObjectLiteral(JetObjectLiteralExpression literal, ExpressionCodegen context) { + public GeneratedAnonymousClassDescriptor generateObjectLiteral(JetObjectLiteralExpression literal, ExpressionCodegen context, ClassContext classContext) { Pair nameAndVisitor = forAnonymousSubclass(literal.getObjectDeclaration()); - new ImplementationBodyCodegen(literal.getObjectDeclaration(), OwnerKind.IMPLEMENTATION, nameAndVisitor.getSecond(), this).generate(); + + final ClassContext objectContext = classContext.intoClass(getBindingContext().getClassDescriptor(literal.getObjectDeclaration()), OwnerKind.IMPLEMENTATION); + + new ImplementationBodyCodegen(literal.getObjectDeclaration(), objectContext, nameAndVisitor.getSecond(), this).generate(); return new GeneratedAnonymousClassDescriptor(nameAndVisitor.first, new Method("", "()V")); } diff --git a/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index a31a7418e62..df41ee20250 100644 --- a/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -20,8 +20,8 @@ import java.util.*; * @author yole */ public class ImplementationBodyCodegen extends ClassBodyCodegen { - public ImplementationBodyCodegen(JetClassOrObject aClass, OwnerKind kind, ClassVisitor v, GenerationState state) { - super(aClass, kind, v, state); + public ImplementationBodyCodegen(JetClassOrObject aClass, ClassContext context, ClassVisitor v, GenerationState state) { + super(aClass, context, v, state); } @Override @@ -112,7 +112,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { ConstructorFrameMap frameMap = new ConstructorFrameMap(callableMethod, constructorDescriptor, kind); final InstructionAdapter iv = new InstructionAdapter(mv); - ClassContext context = new ClassContext(descriptor, kind, StackValue.local(0, state.getTypeMapper().jvmType(descriptor, kind))); ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, context, state); String classname = state.getTypeMapper().jvmName(descriptor, kind); @@ -138,7 +137,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { if (outerDescriptor instanceof ClassDescriptor) { final ClassDescriptor outerClassDescriptor = (ClassDescriptor) outerDescriptor; final Type type = JetTypeMapper.jetImplementationType(outerClassDescriptor); - codegen.addOuterThis(outerClassDescriptor, StackValue.local(frameMap.getOuterThisIndex(), type)); String interfaceDesc = type.getDescriptor(); final String fieldName = "this$0"; v.visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL, fieldName, interfaceDesc, null, null); @@ -189,9 +187,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { iv.putfield(classname, delegateField, fieldDesc); JetClass superClass = (JetClass) state.getBindingContext().getDeclarationPsiElement(superClassDescriptor); - generateDelegates(myClass, superClass, + final ClassContext delegateContext = context.intoClass(superClassDescriptor, new OwnerKind.DelegateKind(StackValue.field(fieldType, classname, delegateField, false), - JetTypeMapper.jvmNameForInterface(superClassDescriptor)), overridden); + JetTypeMapper.jvmNameForInterface(superClassDescriptor))); + generateDelegates(superClass, delegateContext, overridden); } n++; @@ -291,7 +290,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { ConstructorFrameMap frameMap = new ConstructorFrameMap(method, constructorDescriptor, kind); final InstructionAdapter iv = new InstructionAdapter(mv); - ClassContext context = new ClassContext(descriptor, kind, StackValue.local(0, state.getTypeMapper().jvmType(descriptor, kind))); ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, context, state); for (JetDelegationSpecifier initializer : constructor.getInitializers()) { @@ -358,17 +356,17 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } } - protected void generateDelegates(JetClassOrObject inClass, JetClass toClass, OwnerKind kind, Set overriden) { - final FunctionCodegen functionCodegen = new FunctionCodegen(toClass, v, state); - final PropertyCodegen propertyCodegen = new PropertyCodegen(v, functionCodegen, state); + protected void generateDelegates(JetClass toClass, ClassContext delegateContext, Set overriden) { + final FunctionCodegen functionCodegen = new FunctionCodegen(delegateContext, v, state); + final PropertyCodegen propertyCodegen = new PropertyCodegen(delegateContext, v, functionCodegen, state); for (JetDeclaration declaration : toClass.getDeclarations()) { if (declaration instanceof JetProperty) { - propertyCodegen.gen((JetProperty) declaration, kind); + propertyCodegen.gen((JetProperty) declaration); } else if (declaration instanceof JetFunction) { if (!overriden.contains(state.getBindingContext().getFunctionDescriptor((JetNamedFunction) declaration))) { - functionCodegen.gen((JetNamedFunction) declaration, kind); + functionCodegen.gen((JetNamedFunction) declaration); } } } @@ -377,9 +375,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { if (p.getValOrVarNode() != null) { PropertyDescriptor propertyDescriptor = state.getBindingContext().getPropertyDescriptor(p); if (propertyDescriptor != null) { - propertyCodegen.generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC, kind); + propertyCodegen.generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC); if (propertyDescriptor.isVar()) { - propertyCodegen.generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC, kind); + propertyCodegen.generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC); } } } diff --git a/idea/src/org/jetbrains/jet/codegen/InterfaceBodyCodegen.java b/idea/src/org/jetbrains/jet/codegen/InterfaceBodyCodegen.java index 3cecc1df70c..e14303bcf89 100644 --- a/idea/src/org/jetbrains/jet/codegen/InterfaceBodyCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/InterfaceBodyCodegen.java @@ -17,8 +17,9 @@ import java.util.Set; * @author yole */ public class InterfaceBodyCodegen extends ClassBodyCodegen { - public InterfaceBodyCodegen(JetClassOrObject aClass, ClassVisitor v, GenerationState state) { - super(aClass, OwnerKind.INTERFACE, v, state); + public InterfaceBodyCodegen(JetClassOrObject aClass, ClassContext context, ClassVisitor v, GenerationState state) { + super(aClass, context, v, state); + assert context.getContextKind() == OwnerKind.INTERFACE; } protected void generateDeclaration() { diff --git a/idea/src/org/jetbrains/jet/codegen/NamespaceCodegen.java b/idea/src/org/jetbrains/jet/codegen/NamespaceCodegen.java index 4f802805dc3..25fdb173174 100644 --- a/idea/src/org/jetbrains/jet/codegen/NamespaceCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/NamespaceCodegen.java @@ -33,8 +33,10 @@ public class NamespaceCodegen { } public void generate(JetNamespace namespace) { - final FunctionCodegen functionCodegen = new FunctionCodegen(namespace, v, state); - final PropertyCodegen propertyCodegen = new PropertyCodegen(v, functionCodegen, state); + final ClassContext context = ClassContext.STATIC.intoNamespace(state.getBindingContext().getNamespaceDescriptor(namespace)); + + final FunctionCodegen functionCodegen = new FunctionCodegen(context, v, state); + final PropertyCodegen propertyCodegen = new PropertyCodegen(context, v, functionCodegen, state); final ClassCodegen classCodegen = state.forClass(); state.prepareAnonymousClasses(namespace); @@ -45,17 +47,17 @@ public class NamespaceCodegen { for (JetDeclaration declaration : namespace.getDeclarations()) { if (declaration instanceof JetProperty) { - propertyCodegen.gen((JetProperty) declaration, OwnerKind.NAMESPACE); + propertyCodegen.gen((JetProperty) declaration); } else if (declaration instanceof JetNamedFunction) { try { - functionCodegen.gen((JetNamedFunction) declaration, OwnerKind.NAMESPACE); + functionCodegen.gen((JetNamedFunction) declaration); } catch (Exception e) { throw new RuntimeException("Failed to generate function " + declaration.getName(), e); } } else if (declaration instanceof JetClassOrObject) { - classCodegen.generate((JetClassOrObject) declaration); + classCodegen.generate(context, (JetClassOrObject) declaration); } else if (declaration instanceof JetNamespace) { JetNamespace childNamespace = (JetNamespace) declaration; diff --git a/idea/src/org/jetbrains/jet/codegen/PropertyCodegen.java b/idea/src/org/jetbrains/jet/codegen/PropertyCodegen.java index cd1a8cbb512..a6e8df86a6f 100644 --- a/idea/src/org/jetbrains/jet/codegen/PropertyCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/PropertyCodegen.java @@ -1,9 +1,10 @@ package org.jetbrains.jet.codegen; import com.intellij.openapi.util.text.StringUtil; -import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; +import org.jetbrains.jet.lang.descriptors.PropertySetterDescriptor; +import org.jetbrains.jet.lang.descriptors.VariableDescriptor; import org.jetbrains.jet.lang.psi.*; -import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lexer.JetTokens; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.MethodVisitor; @@ -11,36 +12,32 @@ import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; import org.objectweb.asm.commons.InstructionAdapter; -import java.util.Collections; - /** * @author max */ public class PropertyCodegen { private final GenerationState state; - private final BindingContext context; private final FunctionCodegen functionCodegen; private final ClassVisitor v; - private final JetTypeMapper mapper; + private final OwnerKind kind; - public PropertyCodegen(ClassVisitor v, FunctionCodegen functionCodegen, GenerationState state) { + public PropertyCodegen(ClassContext context, ClassVisitor v, FunctionCodegen functionCodegen, GenerationState state) { this.v = v; this.functionCodegen = functionCodegen; this.state = state; - mapper = state.getTypeMapper(); - context = state.getBindingContext(); + this.kind = context.getContextKind(); } - public void gen(JetProperty p, OwnerKind kind) { - final VariableDescriptor descriptor = context.getVariableDescriptor(p); + public void gen(JetProperty p) { + final VariableDescriptor descriptor = state.getBindingContext().getVariableDescriptor(p); if (!(descriptor instanceof PropertyDescriptor)) { throw new UnsupportedOperationException("expect a property to have a property descriptor"); } final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor; if (kind == OwnerKind.NAMESPACE || kind == OwnerKind.IMPLEMENTATION || kind == OwnerKind.DELEGATING_IMPLEMENTATION) { - generateBackingField(p, kind, propertyDescriptor); - generateGetter(p, kind, propertyDescriptor); - generateSetter(p, kind, propertyDescriptor); + generateBackingField(p, propertyDescriptor); + generateGetter(p, propertyDescriptor); + generateSetter(p, propertyDescriptor); } else if (kind == OwnerKind.INTERFACE) { final JetPropertyAccessor getter = p.getGetter(); @@ -48,7 +45,7 @@ public class PropertyCodegen { (getter == null && isExternallyAccessible(p)))) { v.visitMethod(Opcodes.ACC_ABSTRACT | Opcodes.ACC_PUBLIC, getterName(p.getName()), - mapper.mapGetterSignature(propertyDescriptor).getDescriptor(), + state.getTypeMapper().mapGetterSignature(propertyDescriptor).getDescriptor(), null, null); } final JetPropertyAccessor setter = p.getSetter(); @@ -56,20 +53,20 @@ public class PropertyCodegen { (setter == null && isExternallyAccessible(p) && p.isVar()))) { v.visitMethod(Opcodes.ACC_ABSTRACT | Opcodes.ACC_PUBLIC, setterName(p.getName()), - mapper.mapSetterSignature(propertyDescriptor).getDescriptor(), + state.getTypeMapper().mapSetterSignature(propertyDescriptor).getDescriptor(), null, null); } } else if (kind instanceof OwnerKind.DelegateKind) { - generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC, kind); + generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC); if (propertyDescriptor.isVar()) { - generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC, kind); + generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC); } } } - private void generateBackingField(JetProperty p, OwnerKind kind, PropertyDescriptor propertyDescriptor) { - if (context.hasBackingField(propertyDescriptor)) { + private void generateBackingField(JetProperty p, PropertyDescriptor propertyDescriptor) { + if (state.getBindingContext().hasBackingField(propertyDescriptor)) { Object value = null; final JetExpression initializer = p.getInitializer(); if (initializer != null) { @@ -85,25 +82,22 @@ public class PropertyCodegen { else { modifiers = Opcodes.ACC_PRIVATE; } - v.visitField(modifiers, p.getName(), mapper.mapType(propertyDescriptor.getOutType()).getDescriptor(), null, value); + v.visitField(modifiers, p.getName(), state.getTypeMapper().mapType(propertyDescriptor.getOutType()).getDescriptor(), null, value); } } - private void generateGetter(JetProperty p, OwnerKind kind, PropertyDescriptor propertyDescriptor) { + private void generateGetter(JetProperty p, PropertyDescriptor propertyDescriptor) { final JetPropertyAccessor getter = p.getGetter(); if (getter != null) { if (getter.getBodyExpression() != null) { - functionCodegen.generateMethod(getter, kind, mapper.mapGetterSignature(propertyDescriptor), - null, - Collections.emptyList(), - Collections.emptyList()); + functionCodegen.generateMethod(getter, state.getTypeMapper().mapGetterSignature(propertyDescriptor), propertyDescriptor.getGetter()); } else if (!getter.hasModifier(JetTokens.PRIVATE_KEYWORD)) { - generateDefaultGetter(p, getter, kind); + generateDefaultGetter(p, getter); } } else if (isExternallyAccessible(p)) { - generateDefaultGetter(p, p, kind); + generateDefaultGetter(p, p); } } @@ -111,33 +105,30 @@ public class PropertyCodegen { return !p.hasModifier(JetTokens.PRIVATE_KEYWORD); } - private void generateSetter(JetProperty p, OwnerKind kind, PropertyDescriptor propertyDescriptor) { + private void generateSetter(JetProperty p, PropertyDescriptor propertyDescriptor) { final JetPropertyAccessor setter = p.getSetter(); if (setter != null) { if (setter.getBodyExpression() != null) { final PropertySetterDescriptor setterDescriptor = propertyDescriptor.getSetter(); assert setterDescriptor != null; - functionCodegen.generateMethod(setter, kind, mapper.mapSetterSignature(propertyDescriptor), - null, - setterDescriptor.getValueParameters(), - Collections.emptyList()); + functionCodegen.generateMethod(setter, state.getTypeMapper().mapSetterSignature(propertyDescriptor), setterDescriptor); } else if (!p.hasModifier(JetTokens.PRIVATE_KEYWORD)) { - generateDefaultSetter(p, setter, kind); + generateDefaultSetter(p, setter); } } else if (isExternallyAccessible(p) && p.isVar()) { - generateDefaultSetter(p, p, kind); + generateDefaultSetter(p, p); } } - private void generateDefaultGetter(JetProperty p, JetDeclaration declaration, OwnerKind kind) { - final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) context.getVariableDescriptor(p); + private void generateDefaultGetter(JetProperty p, JetDeclaration declaration) { + final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) state.getBindingContext().getVariableDescriptor(p); int flags = JetTypeMapper.getAccessModifiers(declaration, Opcodes.ACC_PUBLIC); - generateDefaultGetter(propertyDescriptor, flags, kind); + generateDefaultGetter(propertyDescriptor, flags); } - public void generateDefaultGetter(PropertyDescriptor propertyDescriptor, int flags, OwnerKind kind) { + public void generateDefaultGetter(PropertyDescriptor propertyDescriptor, int flags) { if (kind == OwnerKind.NAMESPACE) { flags |= Opcodes.ACC_STATIC; } @@ -145,7 +136,7 @@ public class PropertyCodegen { flags |= Opcodes.ACC_ABSTRACT; } - final String signature = mapper.mapGetterSignature(propertyDescriptor).getDescriptor(); + final String signature = state.getTypeMapper().mapGetterSignature(propertyDescriptor).getDescriptor(); String getterName = getterName(propertyDescriptor.getName()); MethodVisitor mv = v.visitMethod(flags, getterName, signature, null, null); if (kind != OwnerKind.INTERFACE) { @@ -154,7 +145,7 @@ public class PropertyCodegen { if (kind != OwnerKind.NAMESPACE) { iv.load(0, JetTypeMapper.TYPE_OBJECT); } - final Type type = mapper.mapType(propertyDescriptor.getOutType()); + final Type type = state.getTypeMapper().mapType(propertyDescriptor.getOutType()); if (kind instanceof OwnerKind.DelegateKind) { OwnerKind.DelegateKind dk = (OwnerKind.DelegateKind) kind; dk.getDelegate().put(JetTypeMapper.TYPE_OBJECT, iv); @@ -162,7 +153,7 @@ public class PropertyCodegen { } else { iv.visitFieldInsn(kind == OwnerKind.NAMESPACE ? Opcodes.GETSTATIC : Opcodes.GETFIELD, - mapper.getOwner(propertyDescriptor, kind), propertyDescriptor.getName(), + state.getTypeMapper().getOwner(propertyDescriptor, kind), propertyDescriptor.getName(), type.getDescriptor()); } iv.areturn(type); @@ -171,13 +162,13 @@ public class PropertyCodegen { } } - private void generateDefaultSetter(JetProperty p, JetDeclaration declaration, OwnerKind kind) { - final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) context.getVariableDescriptor(p); + private void generateDefaultSetter(JetProperty p, JetDeclaration declaration) { + final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) state.getBindingContext().getVariableDescriptor(p); int flags = JetTypeMapper.getAccessModifiers(declaration, Opcodes.ACC_PUBLIC); - generateDefaultSetter(propertyDescriptor, flags, kind); + generateDefaultSetter(propertyDescriptor, flags); } - public void generateDefaultSetter(PropertyDescriptor propertyDescriptor, int flags, OwnerKind kind) { + public void generateDefaultSetter(PropertyDescriptor propertyDescriptor, int flags) { if (kind == OwnerKind.NAMESPACE) { flags |= Opcodes.ACC_STATIC; } @@ -185,12 +176,12 @@ public class PropertyCodegen { flags |= Opcodes.ACC_ABSTRACT; } - final String signature = mapper.mapSetterSignature(propertyDescriptor).getDescriptor(); + final String signature = state.getTypeMapper().mapSetterSignature(propertyDescriptor).getDescriptor(); MethodVisitor mv = v.visitMethod(flags, setterName(propertyDescriptor.getName()), signature, null, null); if (kind != OwnerKind.INTERFACE) { mv.visitCode(); InstructionAdapter iv = new InstructionAdapter(mv); - final Type type = mapper.mapType(propertyDescriptor.getOutType()); + final Type type = state.getTypeMapper().mapType(propertyDescriptor.getOutType()); int paramCode = 0; if (kind != OwnerKind.NAMESPACE) { iv.load(0, JetTypeMapper.TYPE_OBJECT); @@ -208,7 +199,7 @@ public class PropertyCodegen { else { iv.load(paramCode, type); iv.visitFieldInsn(kind == OwnerKind.NAMESPACE ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD, - mapper.getOwner(propertyDescriptor, kind), propertyDescriptor.getName(), + state.getTypeMapper().getOwner(propertyDescriptor, kind), propertyDescriptor.getName(), type.getDescriptor()); } diff --git a/idea/src/org/jetbrains/jet/codegen/StackValue.java b/idea/src/org/jetbrains/jet/codegen/StackValue.java index 1cab78d0637..cbeb23af8b4 100644 --- a/idea/src/org/jetbrains/jet/codegen/StackValue.java +++ b/idea/src/org/jetbrains/jet/codegen/StackValue.java @@ -71,6 +71,10 @@ public abstract class StackValue { return new Field(type, owner, name, isStatic); } + public static StackValue instanceField(Type type, String owner, String name) { + return new InstanceField(type, owner, name); + } + public static StackValue property(String name, String owner, Type type, boolean isStatic, boolean isInterface, Method getter, Method setter) { return new Property(name, owner, getter, setter, isStatic, isInterface, type); } @@ -379,6 +383,7 @@ public abstract class StackValue { } } + private static class Field extends StackValue { private final String owner; private final String name; @@ -414,6 +419,33 @@ public abstract class StackValue { } } + private static class InstanceField extends StackValue { + private final String owner; + private final String name; + + public InstanceField(Type type, String owner, String name) { + super(type); + this.owner = owner; + this.name = name; + } + + @Override + public void put(Type type, InstructionAdapter v) { + v.load(0, JetTypeMapper.TYPE_OBJECT); + v.getfield(owner, name, this.type.getDescriptor()); + } + + @Override + public void dupReceiver(InstructionAdapter v, int below) { + } + + @Override + public void store(InstructionAdapter v) { + v.load(0, JetTypeMapper.TYPE_OBJECT); + v.putfield(owner, name, this.type.getDescriptor()); + } + } + private static class Property extends StackValue { private final String name; private final Method getter;