diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java
index 6650d907bfb..a125ab0f0f2 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java
@@ -72,8 +72,7 @@ import static org.jetbrains.jet.codegen.binding.CodegenBinding.*;
import static org.jetbrains.jet.descriptors.serialization.NameSerializationUtil.createNameResolver;
import static org.jetbrains.jet.lang.resolve.BindingContextUtils.descriptorToDeclaration;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*;
-import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.JAVA_STRING_TYPE;
-import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE;
+import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.*;
import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.KotlinSyntheticClass;
import static org.jetbrains.jet.lang.resolve.java.diagnostics.DiagnosticsPackage.DelegationToTraitImpl;
import static org.jetbrains.jet.lang.resolve.java.diagnostics.DiagnosticsPackage.OtherOrigin;
@@ -429,7 +428,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
@Override
protected void generateSyntheticParts() {
- generateDelegatedPropertyMetadataArray();
+ generateStaticSyntheticFields();
generateFieldForSingleton();
@@ -463,10 +462,20 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
generateToArray();
- genClosureFields(context.closure, v, state.getTypeMapper());
+ genClosureFields(context.closure, v, typeMapper);
}
- private void generateDelegatedPropertyMetadataArray() {
+ private void generateStaticSyntheticFields() {
+ if (isAnnotationClass(descriptor)) {
+ // There's a bug in JDK 6 and 7 that prevents us from generating a static field in an annotation class:
+ // http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6857918
+ // TODO: make reflection work on annotation classes somehow
+ return;
+ }
+
+ generateReflectionObjectField(state, classAsmType, v, K_CLASS_IMPL_TYPE, JvmAbi.KOTLIN_CLASS_FIELD_NAME,
+ createOrGetClInitCodegen().v);
+
generatePropertyMetadataArrayFieldIfNeeded(classAsmType);
}
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/MemberCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/MemberCodegen.java
index b491052aabb..622b710fe57 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/MemberCodegen.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/MemberCodegen.java
@@ -50,12 +50,12 @@ import java.util.List;
import static org.jetbrains.jet.codegen.AsmUtil.boxType;
import static org.jetbrains.jet.codegen.AsmUtil.isPrimitive;
-import static org.jetbrains.jet.lang.resolve.java.diagnostics.DiagnosticsPackage.OtherOrigin;
-import static org.jetbrains.jet.lang.resolve.java.diagnostics.DiagnosticsPackage.TraitImpl;
-import static org.jetbrains.jet.lang.resolve.java.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
import static org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED;
import static org.jetbrains.jet.lang.resolve.BindingContext.VARIABLE;
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.*;
+import static org.jetbrains.jet.lang.resolve.java.diagnostics.DiagnosticsPackage.OtherOrigin;
+import static org.jetbrains.jet.lang.resolve.java.diagnostics.DiagnosticsPackage.TraitImpl;
+import static org.jetbrains.jet.lang.resolve.java.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
public abstract class MemberCodegen extends ParentCodegenAware {
@@ -316,6 +316,27 @@ public abstract class MemberCodegen", "(Ljava/lang/Class;)V", false);
+ v.putstatic(thisAsmType.getInternalName(), fieldName, kImplType.getDescriptor());
+ }
+
protected void generatePropertyMetadataArrayFieldIfNeeded(@NotNull Type thisAsmType) {
List delegatedProperties = new ArrayList();
for (JetDeclaration declaration : ((JetDeclarationContainer) element).getDeclarations()) {
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/PackageCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/PackageCodegen.java
index c46ae090f6b..24a8e07baf2 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/PackageCodegen.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/PackageCodegen.java
@@ -56,27 +56,32 @@ import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.org.objectweb.asm.AnnotationVisitor;
import org.jetbrains.org.objectweb.asm.MethodVisitor;
import org.jetbrains.org.objectweb.asm.Type;
+import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
import java.util.*;
import static org.jetbrains.jet.codegen.AsmUtil.asmDescByFqNameWithoutInnerClasses;
import static org.jetbrains.jet.descriptors.serialization.NameSerializationUtil.createNameResolver;
+import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.K_PACKAGE_IMPL_TYPE;
import static org.jetbrains.jet.lang.resolve.java.PackageClassUtils.getPackageClassFqName;
import static org.jetbrains.jet.lang.resolve.java.diagnostics.DiagnosticsPackage.*;
+import static org.jetbrains.jet.lang.resolve.java.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
public class PackageCodegen {
- private final GenerationState state;
private final ClassBuilderOnDemand v;
+ private final GenerationState state;
private final Collection files;
+ private final Type packageClassType;
private final PackageFragmentDescriptor packageFragment;
private final PackageFragmentDescriptor compiledPackageFragment;
private final List previouslyCompiledCallables;
- public PackageCodegen(@NotNull GenerationState state, @NotNull Collection files, @NotNull final FqName fqName) {
+ public PackageCodegen(@NotNull GenerationState state, @NotNull Collection files, @NotNull FqName fqName) {
this.state = state;
this.files = files;
this.packageFragment = getOnlyPackageFragment(fqName);
+ this.packageClassType = AsmUtil.asmTypeByFqNameWithoutInnerClasses(getPackageClassFqName(fqName));
this.compiledPackageFragment = getCompiledPackageFragment(fqName);
this.previouslyCompiledCallables = filterDeserializedCallables(compiledPackageFragment);
@@ -88,14 +93,13 @@ public class PackageCodegen {
Collection files = PackageCodegen.this.files;
JetFile sourceFile = getRepresentativePackageFile(files);
- String className = AsmUtil.internalNameByFqNameWithoutInnerClasses(getPackageClassFqName(fqName));
- ClassBuilder v = PackageCodegen.this.state.getFactory()
- .newVisitor(
- PackageFacade(packageFragment == null ? compiledPackageFragment : packageFragment),
- Type.getObjectType(className), PackagePartClassUtils.getPackageFilesWithCallables(files));
+ ClassBuilder v = PackageCodegen.this.state.getFactory().newVisitor(
+ PackageFacade(packageFragment == null ? compiledPackageFragment : packageFragment),
+ packageClassType, PackagePartClassUtils.getPackageFilesWithCallables(files)
+ );
v.defineClass(sourceFile, V1_6,
ACC_PUBLIC | ACC_FINAL,
- className,
+ packageClassType.getInternalName(),
null,
"java/lang/Object",
ArrayUtil.EMPTY_STRING_ARRAY
@@ -216,18 +220,35 @@ public class PackageCodegen {
}
}
- generateDelegationsToPreviouslyCompiled(generateCallableMemberTasks);
+ if (!generateCallableMemberTasks.isEmpty()) {
+ generatePackageFacadeClass(generateCallableMemberTasks, bindings);
+ }
+ }
- if (generateCallableMemberTasks.isEmpty()) return;
+ private void generatePackageFacadeClass(
+ @NotNull Map tasks,
+ @NotNull List bindings
+ ) {
+ generateKotlinPackageReflectionField();
- for (CallableMemberDescriptor member : Ordering.from(MemberComparator.INSTANCE).sortedCopy(generateCallableMemberTasks.keySet())) {
- generateCallableMemberTasks.get(member).run();
+ generateDelegationsToPreviouslyCompiled(tasks);
+
+ for (CallableMemberDescriptor member : Ordering.from(MemberComparator.INSTANCE).sortedCopy(tasks.keySet())) {
+ tasks.get(member).run();
}
bindings.add(v.getSerializationBindings());
writeKotlinPackageAnnotationIfNeeded(JvmSerializationBindings.union(bindings));
}
+ private void generateKotlinPackageReflectionField() {
+ MethodVisitor mv = v.newMethod(NO_ORIGIN, ACC_STATIC, "", "()V", null, null);
+ MemberCodegen.generateReflectionObjectField(state, packageClassType, v, K_PACKAGE_IMPL_TYPE, JvmAbi.KOTLIN_PACKAGE_FIELD_NAME,
+ new InstructionAdapter(mv));
+ mv.visitInsn(RETURN);
+ FunctionCodegen.endVisit(mv, "static initializer", null);
+ }
+
private void writeKotlinPackageAnnotationIfNeeded(@NotNull JvmSerializationBindings bindings) {
if (state.getClassBuilderMode() != ClassBuilderMode.FULL) {
return;
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/inline/InlineCodegenUtil.java b/compiler/backend/src/org/jetbrains/jet/codegen/inline/InlineCodegenUtil.java
index 4cbaceed56b..c1871be9e64 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/inline/InlineCodegenUtil.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/inline/InlineCodegenUtil.java
@@ -266,6 +266,9 @@ public class InlineCodegenUtil {
}
public static boolean isCapturedFieldName(@NotNull String fieldName) {
- return fieldName.startsWith(CAPTURED_FIELD_PREFIX) || THIS$0.equals(fieldName) || RECEIVER$0.equals(fieldName);
+ // TODO: improve this heuristic
+ return (fieldName.startsWith(CAPTURED_FIELD_PREFIX) && !fieldName.equals(JvmAbi.KOTLIN_CLASS_FIELD_NAME)) ||
+ THIS$0.equals(fieldName) ||
+ RECEIVER$0.equals(fieldName);
}
}
diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/AsmTypeConstants.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/AsmTypeConstants.java
index 873dff87312..d9a1f950fcc 100644
--- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/AsmTypeConstants.java
+++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/AsmTypeConstants.java
@@ -38,6 +38,9 @@ public class AsmTypeConstants {
public static final Type PROPERTY_METADATA_TYPE = Type.getObjectType(BUILT_INS_PACKAGE_FQ_NAME + "/PropertyMetadata");
public static final Type PROPERTY_METADATA_IMPL_TYPE = Type.getObjectType(BUILT_INS_PACKAGE_FQ_NAME + "/PropertyMetadataImpl");
+ public static final Type K_CLASS_IMPL_TYPE = Type.getObjectType("kotlin/reflect/jvm/internal/KClassImpl");
+ public static final Type K_PACKAGE_IMPL_TYPE = Type.getObjectType("kotlin/reflect/jvm/internal/KPackageImpl");
+
public static final Type OBJECT_REF_TYPE = Type.getObjectType("kotlin/jvm/internal/Ref$ObjectRef");
public static Type getType(@NotNull Class> javaClass) {
diff --git a/compiler/integration-tests/src/org/jetbrains/kotlin/CompilerSmokeTest.java b/compiler/integration-tests/src/org/jetbrains/kotlin/CompilerSmokeTest.java
index f9c87e96f20..6b544d4500e 100644
--- a/compiler/integration-tests/src/org/jetbrains/kotlin/CompilerSmokeTest.java
+++ b/compiler/integration-tests/src/org/jetbrains/kotlin/CompilerSmokeTest.java
@@ -20,15 +20,14 @@ import org.junit.Test;
import java.io.File;
-import static junit.framework.Assert.*;
+import static org.junit.Assert.assertEquals;
public class CompilerSmokeTest extends KotlinIntegrationTestBase {
-
@Test
public void compileAndRunHelloApp() throws Exception {
String jar = tmpdir.getTmpDir().getAbsolutePath() + File.separator + "hello.jar";
- assertEquals("compilation failed", 0, runCompiler("hello.compile", "-src", "hello.kt", "-jar", jar));
+ assertEquals("compilation failed", 0, runCompiler("hello.compile", "-includeRuntime", "hello.kt", "-jar", jar));
runJava("hello.run", "-cp", jar, "Hello.HelloPackage");
}
@@ -36,7 +35,7 @@ public class CompilerSmokeTest extends KotlinIntegrationTestBase {
public void compileAndRunHelloAppFQMain() throws Exception {
String jar = tmpdir.getTmpDir().getAbsolutePath() + File.separator + "hello.jar";
- assertEquals("compilation failed", 0, runCompiler("hello.compile", "-src", "hello.kt", "-jar", jar));
+ assertEquals("compilation failed", 0, runCompiler("hello.compile", "-includeRuntime", "hello.kt", "-jar", jar));
runJava("hello.run", "-cp", jar, "Hello.HelloPackage");
}
@@ -44,7 +43,7 @@ public class CompilerSmokeTest extends KotlinIntegrationTestBase {
public void compileAndRunHelloAppVarargMain() throws Exception {
String jar = tmpdir.getTmpDir().getAbsolutePath() + File.separator + "hello.jar";
- assertEquals("compilation failed", 0, runCompiler("hello.compile", "-src", "hello.kt", "-jar", jar));
+ assertEquals("compilation failed", 0, runCompiler("hello.compile", "-includeRuntime", "hello.kt", "-jar", jar));
runJava("hello.run", "-cp", jar, "Hello.HelloPackage");
}
diff --git a/compiler/testData/codegen/bytecodeText/kt2202.kt b/compiler/testData/codegen/bytecodeText/kt2202.kt
index 2d62a6e896b..e2bc119b688 100644
--- a/compiler/testData/codegen/bytecodeText/kt2202.kt
+++ b/compiler/testData/codegen/bytecodeText/kt2202.kt
@@ -18,4 +18,4 @@ class B {
}
// 0 INVOKEVIRTUAL
-// 4 INVOKESPECIAL
+// 2 INVOKESPECIAL [AB]\.
diff --git a/compiler/testData/codegen/bytecodeText/privateDefaultArgs.kt b/compiler/testData/codegen/bytecodeText/privateDefaultArgs.kt
index 699df18dff9..633b067a1be 100644
--- a/compiler/testData/codegen/bytecodeText/privateDefaultArgs.kt
+++ b/compiler/testData/codegen/bytecodeText/privateDefaultArgs.kt
@@ -13,4 +13,4 @@ fun box(): String {
}
// 0 INVOKEVIRTUAL
-// 3 INVOKESPECIAL
+// 2 INVOKESPECIAL B\.foo
diff --git a/compiler/tests/org/jetbrains/jet/codegen/PropertyGenTest.java b/compiler/tests/org/jetbrains/jet/codegen/PropertyGenTest.java
index a03cf5e89e4..242c52c6794 100644
--- a/compiler/tests/org/jetbrains/jet/codegen/PropertyGenTest.java
+++ b/compiler/tests/org/jetbrains/jet/codegen/PropertyGenTest.java
@@ -40,11 +40,7 @@ public class PropertyGenTest extends CodegenTestCase {
public void testPrivateVal() throws Exception {
loadFile();
- Class> aClass = generateClass("PrivateVal");
- Field[] fields = aClass.getDeclaredFields();
- assertEquals(1, fields.length); // prop
- Field field = fields[0];
- assertEquals("prop", field.getName());
+ generateClass("PrivateVal").getDeclaredField("prop");
}
public void testPrivateVar() throws Exception {
diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/JvmAbi.java b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/JvmAbi.java
index 49e8d8f3874..4cb17862e6c 100644
--- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/JvmAbi.java
+++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/JvmAbi.java
@@ -45,6 +45,8 @@ public final class JvmAbi {
public static final String CLASS_OBJECT_FIELD = "object$";
public static final FqName K_OBJECT = new FqName("kotlin.jvm.internal.KObject");
+ public static final String KOTLIN_CLASS_FIELD_NAME = "$kotlinClass";
+ public static final String KOTLIN_PACKAGE_FIELD_NAME = "$kotlinPackage";
public static boolean isClassObjectFqName(@NotNull FqName fqName) {
return fqName.lastSegmentIs(Name.identifier(CLASS_OBJECT_CLASS_NAME));
diff --git a/idea/testData/debugger/tinyApp/outs/memberFunFromTopLevel.out b/idea/testData/debugger/tinyApp/outs/memberFunFromTopLevel.out
index c2e52ded0b3..4f55a285f35 100644
--- a/idea/testData/debugger/tinyApp/outs/memberFunFromTopLevel.out
+++ b/idea/testData/debugger/tinyApp/outs/memberFunFromTopLevel.out
@@ -1,7 +1,7 @@
-LineBreakpoint created at memberFunFromTopLevel.kt:11
+LineBreakpoint created at memberFunFromTopLevel.kt:13
!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! memberFunFromTopLevel.MemberFunFromTopLevelPackage
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
-memberFunFromTopLevel.kt:10
+memberFunFromTopLevel.kt:12
memberFunFromTopLevel.kt:4
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
diff --git a/idea/testData/debugger/tinyApp/outs/memberGetterFromTopLevel.out b/idea/testData/debugger/tinyApp/outs/memberGetterFromTopLevel.out
index 72ee47c8875..7699e7232f3 100644
--- a/idea/testData/debugger/tinyApp/outs/memberGetterFromTopLevel.out
+++ b/idea/testData/debugger/tinyApp/outs/memberGetterFromTopLevel.out
@@ -1,7 +1,7 @@
-LineBreakpoint created at memberGetterFromTopLevel.kt:13
+LineBreakpoint created at memberGetterFromTopLevel.kt:15
!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! memberGetterFromTopLevel.MemberGetterFromTopLevelPackage
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
-memberGetterFromTopLevel.kt:12
+memberGetterFromTopLevel.kt:14
memberGetterFromTopLevel.kt:5
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
diff --git a/idea/testData/debugger/tinyApp/src/stepInto/memberFunFromTopLevel.kt b/idea/testData/debugger/tinyApp/src/stepInto/memberFunFromTopLevel.kt
index 0ab3d10e410..6dfc6d4cb91 100644
--- a/idea/testData/debugger/tinyApp/src/stepInto/memberFunFromTopLevel.kt
+++ b/idea/testData/debugger/tinyApp/src/stepInto/memberFunFromTopLevel.kt
@@ -7,6 +7,8 @@ class A {
}
fun main(args: Array) {
+ A()
+
//Breakpoint!
A().bar()
}
diff --git a/idea/testData/debugger/tinyApp/src/stepInto/memberGetterFromTopLevel.kt b/idea/testData/debugger/tinyApp/src/stepInto/memberGetterFromTopLevel.kt
index 328316b07ef..13f8d06f27a 100644
--- a/idea/testData/debugger/tinyApp/src/stepInto/memberGetterFromTopLevel.kt
+++ b/idea/testData/debugger/tinyApp/src/stepInto/memberGetterFromTopLevel.kt
@@ -9,6 +9,8 @@ class A {
}
fun main(args: Array) {
+ A()
+
//Breakpoint!
A().bar
}
diff --git a/jps-plugin/test/org/jetbrains/jet/jps/build/KotlinJpsBuildTest.java b/jps-plugin/test/org/jetbrains/jet/jps/build/KotlinJpsBuildTest.java
index 92ed4cf7664..695ef09e8c5 100644
--- a/jps-plugin/test/org/jetbrains/jet/jps/build/KotlinJpsBuildTest.java
+++ b/jps-plugin/test/org/jetbrains/jet/jps/build/KotlinJpsBuildTest.java
@@ -220,8 +220,8 @@ public class KotlinJpsBuildTest extends AbstractKotlinJpsBuildTestCase {
// Check that outputs are located properly
File facadeWithA = findFileInOutputDir(findModule("module1"), "test/TestPackage.class");
File facadeWithB = findFileInOutputDir(findModule("module2"), "test/TestPackage.class");
- assertSameElements(getMethodsOfClass(facadeWithA), "a", "getA");
- assertSameElements(getMethodsOfClass(facadeWithB), "b", "getB", "setB");
+ assertSameElements(getMethodsOfClass(facadeWithA), "", "a", "getA");
+ assertSameElements(getMethodsOfClass(facadeWithB), "", "b", "getB", "setB");
checkPackageDeletedFromOutputWhen(Operation.CHANGE, "module1", "module1/src/a.kt", "test.TestPackage");
checkPackageDeletedFromOutputWhen(Operation.CHANGE, "module2", "module2/src/b.kt", "test.TestPackage");
diff --git a/jps-plugin/testData/general/CircularDependenciesSamePackage/module1/src/a.kt b/jps-plugin/testData/general/CircularDependenciesSamePackage/module1/src/a.kt
index 4987d3f36ec..8311da66012 100644
--- a/jps-plugin/testData/general/CircularDependenciesSamePackage/module1/src/a.kt
+++ b/jps-plugin/testData/general/CircularDependenciesSamePackage/module1/src/a.kt
@@ -4,4 +4,4 @@ fun a() {
}
-val a = ""
\ No newline at end of file
+val a = ""
diff --git a/jps-plugin/testData/general/CircularDependenciesSamePackage/module2/src/b.kt b/jps-plugin/testData/general/CircularDependenciesSamePackage/module2/src/b.kt
index 1dcef1df913..b04c387135d 100644
--- a/jps-plugin/testData/general/CircularDependenciesSamePackage/module2/src/b.kt
+++ b/jps-plugin/testData/general/CircularDependenciesSamePackage/module2/src/b.kt
@@ -4,4 +4,4 @@ fun b() {
}
-var b = ""
\ No newline at end of file
+var b = b()