diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java index b58b9fc9fde..5fe40d1b34d 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java @@ -22,7 +22,6 @@ package org.jetbrains.jet.codegen; import com.intellij.openapi.util.Pair; import com.intellij.psi.PsiElement; -import org.jetbrains.asm4.Label; import org.jetbrains.asm4.MethodVisitor; import org.jetbrains.asm4.Type; import org.jetbrains.asm4.commons.InstructionAdapter; @@ -41,6 +40,7 @@ import org.jetbrains.jet.lang.psi.JetElement; import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContextUtils; +import org.jetbrains.jet.lang.resolve.java.JvmAbi; import org.jetbrains.jet.lang.resolve.java.JvmClassName; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.JetType; @@ -49,10 +49,10 @@ import java.util.ArrayList; import java.util.List; import static org.jetbrains.asm4.Opcodes.*; -import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE; import static org.jetbrains.jet.codegen.CodegenUtil.*; import static org.jetbrains.jet.codegen.binding.CodegenBinding.classNameForAnonymousClass; import static org.jetbrains.jet.codegen.binding.CodegenBinding.isLocalNamedFun; +import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE; public class ClosureCodegen extends GenerationStateAware { @@ -116,31 +116,19 @@ public class ClosureCodegen extends GenerationStateAware { } private void generateConstInstance(PsiElement fun, ClassBuilder cv) { - String classDescr = name.getDescriptor(); - cv.newField(fun, ACC_PRIVATE | ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC, "$instance", classDescr, null, null); + MethodVisitor mv = cv.newMethod(fun, ACC_PUBLIC | ACC_STATIC | ACC_SYNTHETIC, "", "()V", null, new String[0]); + final InstructionAdapter iv = new InstructionAdapter(mv); + + cv.newField(fun, ACC_PUBLIC | ACC_STATIC | ACC_FINAL, JvmAbi.INSTANCE_FIELD, name.getDescriptor(), null, null); - MethodVisitor mv = - cv.newMethod(fun, ACC_PUBLIC | ACC_STATIC | ACC_SYNTHETIC, "$getInstance", "()" + classDescr, null, new String[0]); if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) { StubCodegen.generateStubCode(mv); } else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) { mv.visitCode(); - mv.visitFieldInsn(GETSTATIC, name.getInternalName(), "$instance", classDescr); - mv.visitInsn(DUP); - Label ret = new Label(); - mv.visitJumpInsn(IFNONNULL, ret); - - mv.visitInsn(POP); - mv.visitTypeInsn(NEW, name.getInternalName()); - mv.visitInsn(DUP); - mv.visitMethodInsn(INVOKESPECIAL, name.getInternalName(), "", "()V"); - mv.visitInsn(DUP); - mv.visitFieldInsn(PUTSTATIC, name.getInternalName(), "$instance", classDescr); - - mv.visitLabel(ret); - mv.visitInsn(ARETURN); - FunctionCodegen.endVisit(mv, "$getInstance", fun); + initSingletonField(fun, name.getAsmType(), cv, iv); + mv.visitInsn(RETURN); + FunctionCodegen.endVisit(mv, "", fun); } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java index 87443d2682d..96d9d9101d8 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java @@ -49,8 +49,8 @@ import org.jetbrains.jet.lang.types.lang.JetStandardLibrary; import java.util.*; import static org.jetbrains.asm4.Opcodes.*; -import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE; import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isClassObject; +import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE; /** * @author abreslav @@ -364,4 +364,11 @@ public class CodegenUtil { throw new IllegalStateException("code generation for synthesized members should be handled separately"); } } + + public static void initSingletonField(PsiElement element, Type classAsmType, ClassBuilder builder, InstructionAdapter iv) { + iv.anew(classAsmType); + iv.dup(); + iv.invokespecial(classAsmType.getInternalName(), "", "()V"); + iv.putstatic(classAsmType.getInternalName(), JvmAbi.INSTANCE_FIELD, classAsmType.getDescriptor()); + } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index e1c766d1df0..020a0246315 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -48,6 +48,7 @@ import org.jetbrains.jet.lang.resolve.BindingContextUtils; import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.calls.*; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; +import org.jetbrains.jet.lang.resolve.java.JvmAbi; import org.jetbrains.jet.lang.resolve.java.JvmClassName; import org.jetbrains.jet.lang.resolve.scopes.receivers.*; import org.jetbrains.jet.lang.types.JetType; @@ -1046,9 +1047,8 @@ public class ExpressionCodegen extends JetVisitor implem final JvmClassName className = closureCodegen.name; final Type asmType = className.getAsmType(); - final String internalName = className.getInternalName(); if (isConst(closure)) { - v.invokestatic(internalName, "$getInstance", "()" + className.getDescriptor()); + v.getstatic(className.getInternalName(), JvmAbi.INSTANCE_FIELD, className.getDescriptor()); } else { v.anew(asmType); @@ -1056,7 +1056,7 @@ public class ExpressionCodegen extends JetVisitor implem final Method cons = closureCodegen.constructor; pushClosureOnStack(closure, false); - v.invokespecial(internalName, "", cons.getDescriptor()); + v.invokespecial(className.getInternalName(), "", cons.getDescriptor()); } return StackValue.onStack(asmType); } @@ -1870,7 +1870,7 @@ public class ExpressionCodegen extends JetVisitor implem v.load(0, OBJECT_TYPE); } else { - v.getstatic(exprType.getInternalName(), "$instance", exprType.getDescriptor()); + v.getstatic(exprType.getInternalName(), JvmAbi.INSTANCE_FIELD, exprType.getDescriptor()); } StackValue.onStack(exprType).put(type, v); } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index b452542d049..9163f7850d6 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -200,7 +200,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { if (descriptor.getClassObjectDescriptor() != null) { int innerClassAccess = ACC_PUBLIC | ACC_FINAL | ACC_STATIC; - v.visitInnerClass(classAsmType.getInternalName() + JvmAbi.CLASS_OBJECT_SUFFIX, classAsmType.getInternalName(), JvmAbi.CLASS_OBJECT_CLASS_NAME, + v.visitInnerClass(classAsmType.getInternalName() + JvmAbi.CLASS_OBJECT_SUFFIX, classAsmType.getInternalName(), + JvmAbi.CLASS_OBJECT_CLASS_NAME, innerClassAccess); } } @@ -330,8 +331,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { @Override protected void generateSyntheticParts() { - generateFieldForObjectInstance(); - generateFieldForClassObject(); + generateFieldForSingleton(); try { generatePrimaryConstructor(); @@ -571,37 +571,15 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } } - private void generateFieldForObjectInstance() { - if (isNonLiteralObject(myClass)) { - Type type = typeMapper.mapType(descriptor); - v.newField(myClass, ACC_PUBLIC | ACC_STATIC | ACC_FINAL, "$instance", type.getDescriptor(), null, null); + private void generateFieldForSingleton() { + if (!(isNonLiteralObject(myClass) || descriptor.getKind() == ClassKind.CLASS_OBJECT)) return; - staticInitializerChunks.add(new CodeChunk() { - @Override - public void generate(InstructionAdapter v) { - String name = jvmName(); - v.anew(Type.getObjectType(name)); - v.dup(); - v.invokespecial(name, "", "()V"); - v.putstatic(name, "$instance", - typeMapper.mapType(descriptor).getDescriptor()); - } - }); - } - } - - private void generateFieldForClassObject() { - if (descriptor.getKind() != ClassKind.CLASS_OBJECT) return; - - v.newField(myClass, ACC_PUBLIC | ACC_STATIC | ACC_FINAL , "$instance", classAsmType.getDescriptor(), null, null); + v.newField(myClass, ACC_PUBLIC | ACC_STATIC | ACC_FINAL, JvmAbi.INSTANCE_FIELD, classAsmType.getDescriptor(), null, null); staticInitializerChunks.add(new CodeChunk() { @Override - public void generate(InstructionAdapter v) { - v.anew(classAsmType); - v.dup(); - v.invokespecial(classAsmType.getInternalName(), "", "()V"); - v.putstatic(typeMapper.mapType(descriptor).getInternalName(), "$instance", classAsmType.getDescriptor()); + public void generate(InstructionAdapter iv) { + initSingletonField(myClass, classAsmType, v, iv); } }); } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java index 9feb7788278..7cdfb63349c 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java @@ -30,6 +30,7 @@ import org.jetbrains.jet.codegen.state.JetTypeMapper; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.resolve.calls.ResolvedCall; +import org.jetbrains.jet.lang.resolve.java.JvmAbi; import org.jetbrains.jet.lang.resolve.java.JvmClassName; import org.jetbrains.jet.lang.resolve.java.JvmPrimitiveType; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; @@ -360,7 +361,7 @@ public abstract class StackValue { final ClassKind kind = classDescriptor.getKind(); if (kind == ClassKind.CLASS_OBJECT || kind == ClassKind.OBJECT) { - return field(type, JvmClassName.byInternalName(type.getInternalName()), "$instance", true); + return field(type, JvmClassName.byInternalName(type.getInternalName()), JvmAbi.INSTANCE_FIELD, true); } else if (kind == ClassKind.ENUM_ENTRY) { final JvmClassName owner = typeMapper.getBindingContext() diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JvmAbi.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JvmAbi.java index 9d38ccedfda..1c6fbbd9aeb 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JvmAbi.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JvmAbi.java @@ -31,6 +31,8 @@ public class JvmAbi { public static final String CLASS_OBJECT_CLASS_NAME = "ClassObject$"; public static final String CLASS_OBJECT_SUFFIX = "$" + CLASS_OBJECT_CLASS_NAME; + public static final String INSTANCE_FIELD = "$instance"; + public static final JvmClassName JETBRAINS_NOT_NULL_ANNOTATION = JvmClassName.byFqNameWithoutInnerClasses("org.jetbrains.annotations.NotNull"); diff --git a/idea/tests/org/jetbrains/jet/plugin/javaFacade/JetJavaFacadeTest.java b/idea/tests/org/jetbrains/jet/plugin/javaFacade/JetJavaFacadeTest.java index a3df896e162..c8d1a59aa89 100644 --- a/idea/tests/org/jetbrains/jet/plugin/javaFacade/JetJavaFacadeTest.java +++ b/idea/tests/org/jetbrains/jet/plugin/javaFacade/JetJavaFacadeTest.java @@ -27,6 +27,7 @@ import org.jetbrains.jet.lang.psi.JetClass; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetNamedFunction; import org.jetbrains.jet.lang.psi.JetPsiUtil; +import org.jetbrains.jet.lang.resolve.java.JvmAbi; import org.jetbrains.jet.plugin.JetLightProjectDescriptor; import org.jetbrains.jet.plugin.PluginTestCaseBase; @@ -114,7 +115,7 @@ public class JetJavaFacadeTest extends LightCodeInsightFixtureTestCase { assertEquals("foo.TheClass.ClassObject$", classObjectClass.getQualifiedName()); assertTrue(classObjectClass.hasModifierProperty(PsiModifier.STATIC)); - final PsiField instance = classObjectClass.findFieldByName("$instance", false); + final PsiField instance = classObjectClass.findFieldByName(JvmAbi.INSTANCE_FIELD, false); assertNotNull(instance); assertEquals("foo.TheClass.ClassObject$", instance.getType().getCanonicalText()); assertTrue(instance.hasModifierProperty(PsiModifier.PUBLIC));