diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/AsmUtil.java b/compiler/backend/src/org/jetbrains/jet/codegen/AsmUtil.java index 387cdc6d025..019893f6ccd 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/AsmUtil.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/AsmUtil.java @@ -202,15 +202,6 @@ public class AsmUtil { return NO_FLAG_PACKAGE_PRIVATE; } - public static int getModalityAccessFlag(@NotNull MemberDescriptor descriptor) { - switch (descriptor.getModality()) { - case ABSTRACT: return ACC_ABSTRACT; - case FINAL: return ACC_FINAL; - case OPEN: return 0; - default: throw new UnsupportedOperationException("Unknown modality: " + descriptor.getModality()); - } - } - public static int getDeprecatedAccessFlag(@NotNull MemberDescriptor descriptor) { if (descriptor instanceof PropertyAccessorDescriptor) { return KotlinBuiltIns.getInstance().isDeprecated(descriptor) @@ -325,6 +316,7 @@ public class AsmUtil { } public static void genInitSingletonField(FieldInfo info, InstructionAdapter iv) { + assert info.isStatic(); genInitSingletonField(info.getOwnerType(), info.getFieldName(), info.getFieldType(), iv); } @@ -335,6 +327,16 @@ public class AsmUtil { iv.putstatic(fieldOwnerType.getInternalName(), fieldName, fieldAsmType.getDescriptor()); } + public static int genAssignInstanceFieldFromParam(FieldInfo info, int index, InstructionAdapter iv) { + assert !info.isStatic(); + Type fieldType = info.getFieldType(); + iv.load(0, info.getOwnerType());//this + iv.load(index, fieldType); //param + iv.visitFieldInsn(PUTFIELD, info.getOwnerInternalName(), info.getFieldName(), fieldType.getDescriptor()); + index += fieldType.getSize(); + return index; + } + public static void genStringBuilderConstructor(InstructionAdapter v) { v.visitTypeInsn(NEW, "java/lang/StringBuilder"); v.dup(); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java index 28f715bd0a4..e90fa53de7c 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java @@ -16,8 +16,9 @@ package org.jetbrains.jet.codegen; -import com.intellij.openapi.util.Pair; +import com.google.common.collect.Lists; import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; import org.jetbrains.asm4.MethodVisitor; import org.jetbrains.asm4.Type; import org.jetbrains.asm4.commons.InstructionAdapter; @@ -29,6 +30,7 @@ import org.jetbrains.jet.codegen.context.CodegenContext; import org.jetbrains.jet.codegen.signature.JvmMethodSignature; import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.codegen.state.GenerationStateAware; +import org.jetbrains.jet.codegen.state.JetTypeMapper; import org.jetbrains.jet.codegen.state.JetTypeMapperMode; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.JetDeclarationWithBody; @@ -40,7 +42,6 @@ import org.jetbrains.jet.lang.resolve.java.JvmAbi; import org.jetbrains.jet.lang.resolve.java.JvmClassName; import org.jetbrains.jet.lang.types.JetType; -import java.util.ArrayList; import java.util.List; import static org.jetbrains.asm4.Opcodes.*; @@ -197,10 +198,11 @@ public class ClosureCodegen extends GenerationStateAware { ClassBuilder cv, CalculatedClosure closure ) { - ArrayList> args = new ArrayList>(); - calculateConstructorParameters(args, state, closure); - Type[] argTypes = nameAnTypeListToTypeArray(args); + List args = calculateConstructorParameters(typeMapper, bindingContext, state, closure, + Type.getObjectType(name.getInternalName())); + + Type[] argTypes = fieldListToTypeArray(args); Method constructor = new Method("", Type.VOID_TYPE, argTypes); MethodVisitor mv = cv.newMethod(fun, ACC_PUBLIC, "", constructor.getDescriptor(), null, new String[0]); @@ -215,13 +217,8 @@ public class ClosureCodegen extends GenerationStateAware { iv.invokespecial(funClass.getInternalName(), "", "()V"); int k = 1; - for (int i = 0; i != argTypes.length; ++i) { - StackValue.local(0, OBJECT_TYPE).put(OBJECT_TYPE, iv); - Pair nameAndType = args.get(i); - Type type = nameAndType.second; - StackValue.local(k, type).put(type, iv); - k += type.getSize(); - StackValue.field(type, name, nameAndType.first, false).store(type, iv); + for (FieldInfo fieldInfo : args) { + k = AsmUtil.genAssignInstanceFieldFromParam(fieldInfo, k, iv); } iv.visitInsn(RETURN); @@ -231,19 +228,24 @@ public class ClosureCodegen extends GenerationStateAware { return constructor; } - private void calculateConstructorParameters( - List> args, + @NotNull + public static List calculateConstructorParameters( + @NotNull JetTypeMapper typeMapper, + @NotNull BindingContext bindingContext, GenerationState state, - CalculatedClosure closure + CalculatedClosure closure, + Type ownerType ) { + + List args = Lists.newArrayList(); ClassDescriptor captureThis = closure.getCaptureThis(); if (captureThis != null) { Type type = typeMapper.mapType(captureThis); - args.add(new Pair(CAPTURED_THIS_FIELD, type)); + args.add(FieldInfo.createForHiddenField(ownerType, type, CAPTURED_THIS_FIELD)); } ClassifierDescriptor captureReceiver = closure.getCaptureReceiver(); if (captureReceiver != null) { - args.add(new Pair(CAPTURED_RECEIVER_FIELD, typeMapper.mapType(captureReceiver))); + args.add(FieldInfo.createForHiddenField(ownerType, typeMapper.mapType(captureReceiver), CAPTURED_RECEIVER_FIELD)); } for (DeclarationDescriptor descriptor : closure.getCaptureVariables().keySet()) { @@ -253,7 +255,7 @@ public class ClosureCodegen extends GenerationStateAware { Type type = sharedVarType != null ? sharedVarType : typeMapper.mapType((VariableDescriptor) descriptor); - args.add(new Pair("$" + descriptor.getName().getName(), type)); + args.add(FieldInfo.createForHiddenField(ownerType, type, "$" + descriptor.getName().getName())); } else if (isLocalNamedFun(state.getBindingContext(), descriptor)) { Type type = @@ -261,18 +263,19 @@ public class ClosureCodegen extends GenerationStateAware { (JetElement) BindingContextUtils.descriptorToDeclaration(bindingContext, descriptor)) .getAsmType(); - args.add(new Pair("$" + descriptor.getName().getName(), type)); + args.add(FieldInfo.createForHiddenField(ownerType, type, "$" + descriptor.getName().getName())); } else if (descriptor instanceof FunctionDescriptor) { assert captureReceiver != null; } } + return args; } - private static Type[] nameAnTypeListToTypeArray(List> args) { + private static Type[] fieldListToTypeArray(List args) { Type[] argTypes = new Type[args.size()]; for (int i = 0; i != argTypes.length; ++i) { - argTypes[i] = args.get(i).second; + argTypes[i] = args.get(i).getFieldType(); } return argTypes; } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FieldInfo.java b/compiler/backend/src/org/jetbrains/jet/codegen/FieldInfo.java index 7119f2b19e6..47371252938 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/FieldInfo.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FieldInfo.java @@ -26,16 +26,44 @@ import org.jetbrains.jet.lang.resolve.java.JvmAbi; public class FieldInfo { + @NotNull + public static FieldInfo createForSingleton(@NotNull ClassDescriptor fieldClassDescriptor, @NotNull JetTypeMapper typeMapper) { + ClassKind kind = fieldClassDescriptor.getKind(); + if (kind != ClassKind.OBJECT && kind != ClassKind.CLASS_OBJECT && kind != ClassKind.ENUM_ENTRY) { + throw new UnsupportedOperationException(); + } + + Type fieldType = typeMapper.mapType(fieldClassDescriptor.getDefaultType()); + + ClassDescriptor ownerDescriptor = kind == ClassKind.OBJECT + ? fieldClassDescriptor: DescriptorUtils.getParentOfType(fieldClassDescriptor, ClassDescriptor.class); + assert ownerDescriptor != null; + Type ownerType = typeMapper.mapType(ownerDescriptor.getDefaultType()); + + String fieldName = kind == ClassKind.ENUM_ENTRY + ? fieldClassDescriptor.getName().getName() + : fieldClassDescriptor.getKind() == ClassKind.CLASS_OBJECT ? JvmAbi.CLASS_OBJECT_FIELD : JvmAbi.INSTANCE_FIELD; + return new FieldInfo(ownerType, fieldType, fieldName, true); + } + + + public static FieldInfo createForHiddenField(@NotNull Type owner, Type fieldType, String fieldName) { + return new FieldInfo(owner, fieldType, fieldName, false); + } + private final Type fieldType; private final Type ownerType; private final String fieldName; - private FieldInfo(@NotNull Type ownerType, @NotNull Type fieldType, @NotNull String fieldName) { + private final boolean isStatic; + + private FieldInfo(@NotNull Type ownerType, @NotNull Type fieldType, @NotNull String fieldName, @NotNull boolean isStatic) { this.ownerType = ownerType; this.fieldType = fieldType; this.fieldName = fieldName; + this.isStatic = isStatic; } @NotNull @@ -59,23 +87,7 @@ public class FieldInfo { } @NotNull - public static FieldInfo createForSingleton(@NotNull ClassDescriptor fieldClassDescriptor, @NotNull JetTypeMapper typeMapper) { - ClassKind kind = fieldClassDescriptor.getKind(); - if (kind != ClassKind.OBJECT && kind != ClassKind.CLASS_OBJECT && kind != ClassKind.ENUM_ENTRY) { - throw new UnsupportedOperationException(); - } - - Type fieldType = typeMapper.mapType(fieldClassDescriptor.getDefaultType()); - - ClassDescriptor ownerDescriptor = kind == ClassKind.OBJECT - ? fieldClassDescriptor: DescriptorUtils.getParentOfType(fieldClassDescriptor, ClassDescriptor.class); - assert ownerDescriptor != null; - Type ownerType = typeMapper.mapType(ownerDescriptor.getDefaultType()); - - String fieldName = kind == ClassKind.ENUM_ENTRY - ? fieldClassDescriptor.getName().getName() - : fieldClassDescriptor.getKind() == ClassKind.CLASS_OBJECT ? JvmAbi.CLASS_OBJECT_FIELD : JvmAbi.INSTANCE_FIELD; - return new FieldInfo(ownerType, fieldType, fieldName); + public boolean isStatic() { + return isStatic; } - } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index c86cc031825..8a829b98d59 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -955,7 +955,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { ClassDescriptor fieldTypeDescriptor = hasClassObject ? descriptor.getClassObjectDescriptor() : descriptor; assert fieldTypeDescriptor != null; final FieldInfo info = FieldInfo.createForSingleton(fieldTypeDescriptor, typeMapper); - JetClassOrObject original = hasClassObject ? ((JetClass)myClass).getClassObject().getObjectDeclaration() : myClass; + JetClassOrObject original = hasClassObject ? ((JetClass) myClass).getClassObject().getObjectDeclaration() : myClass; v.newField(original, ACC_PUBLIC | ACC_STATIC | ACC_FINAL, info.getFieldName(), info.getFieldType().getDescriptor(), null, null); @@ -1012,8 +1012,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { return; } - generatePrimaryConstructorImpl(constructorDescriptor, constructorContext, constructorMethod, callableMethod, hasCapturedThis, - closure, mv); + generatePrimaryConstructorImpl(constructorDescriptor, constructorContext, constructorMethod, callableMethod, closure, mv); } FunctionCodegen.generateConstructorWithoutParametersIfNeeded(state, callableMethod, constructorDescriptor, v); @@ -1024,7 +1023,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { ConstructorContext constructorContext, JvmMethodSignature constructorMethod, CallableMethod callableMethod, - boolean hasCapturedThis, MutableClosure closure, MethodVisitor mv ) { @@ -1051,39 +1049,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { generateDelegatorToConstructorCall(iv, codegen, constructorDescriptor, frameMap); } - if (hasCapturedThis) { - Type type = typeMapper - .mapType(enclosingClassDescriptor(bindingContext, descriptor)); - String interfaceDesc = type.getDescriptor(); - iv.load(0, classAsmType); - iv.load(frameMap.getOuterThisIndex(), type); - iv.putfield(classname.getInternalName(), CAPTURED_THIS_FIELD, interfaceDesc); - } - if (closure != null) { - int k = hasCapturedThis ? 2 : 1; - String internalName = typeMapper.mapType(descriptor).getInternalName(); - ClassifierDescriptor captureReceiver = closure.getCaptureReceiver(); - if (captureReceiver != null) { - iv.load(0, OBJECT_TYPE); - Type asmType = typeMapper.mapType(captureReceiver.getDefaultType(), JetTypeMapperMode.IMPL); - iv.load(k, asmType); - iv.putfield(internalName, CAPTURED_RECEIVER_FIELD, asmType.getDescriptor()); - k += asmType.getSize(); - } - - for (DeclarationDescriptor varDescr : closure.getCaptureVariables().keySet()) { - if (varDescr instanceof VariableDescriptor && !(varDescr instanceof PropertyDescriptor)) { - Type sharedVarType = typeMapper.getSharedVarType(varDescr); - if (sharedVarType == null) { - sharedVarType = typeMapper.mapType((VariableDescriptor) varDescr); - } - iv.load(0, OBJECT_TYPE); - iv.load(k, StackValue.refType(sharedVarType)); - k += StackValue.refType(sharedVarType).getSize(); - iv.putfield(internalName, - "$" + varDescr.getName(), sharedVarType.getDescriptor()); - } + List argsFromClosure = ClosureCodegen.calculateConstructorParameters(typeMapper, bindingContext, state, closure, classAsmType); + int k = 1; + for (FieldInfo info : argsFromClosure) { + k = AsmUtil.genAssignInstanceFieldFromParam(info, k, iv); } }