diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java index 6d353c1bf46..94f066ccb20 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java @@ -40,19 +40,19 @@ public abstract class ClassBodyCodegen { this.v = v; } - public final void generate(@Nullable HashMap accessors) { + public final void generate() { generateDeclaration(); generateClassBody(); - generateSyntheticParts(accessors); + generateSyntheticParts(); generateStaticInitializer(); } protected abstract void generateDeclaration(); - protected void generateSyntheticParts(HashMap accessors) { + protected void generateSyntheticParts() { } private void generateClassBody() { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java index 50996384f19..5ecc867aa69 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java @@ -51,11 +51,12 @@ public class ClassCodegen { private void generateImplementation(CodegenContext context, JetClassOrObject aClass, OwnerKind kind, HashMap accessors, ClassBuilder classBuilder) { ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass); CodegenContext classContext = context.intoClass(descriptor, kind, state.getTypeMapper()); - new ImplementationBodyCodegen(aClass, classContext, classBuilder, state).generate(accessors); + classContext.copyAccessors(accessors); + new ImplementationBodyCodegen(aClass, classContext, classBuilder, state).generate(); if(aClass instanceof JetClass && ((JetClass)aClass).isTrait()) { ClassBuilder traitBuilder = state.forTraitImplementation(descriptor); - new TraitImplBodyCodegen(aClass, context.intoClass(descriptor, OwnerKind.TRAIT_IMPL, state.getTypeMapper()), traitBuilder, state).generate(null); + new TraitImplBodyCodegen(aClass, context.intoClass(descriptor, OwnerKind.TRAIT_IMPL, state.getTypeMapper()), traitBuilder, state).generate(); traitBuilder.done(); } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java index f83089cf5e9..a7c1b270ff2 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java @@ -264,6 +264,15 @@ public abstract class CodegenContext { public abstract boolean isStatic(); + public void copyAccessors(HashMap accessors) { + if(accessors != null) { + if(this.accessors == null) { + this.accessors = new HashMap(); + } + this.accessors.putAll(accessors); + } + } + public abstract static class ReceiverContext extends CodegenContext { final CallableDescriptor receiverDescriptor; diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java b/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java index 99539cb3875..7b97fd41f2d 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java @@ -145,7 +145,7 @@ public class GenerationState { closure.name = nameAndVisitor.getFirst(); final CodegenContext objectContext = closure.context.intoAnonymousClass(closure, getBindingContext().get(BindingContext.CLASS, objectDeclaration), OwnerKind.IMPLEMENTATION, typeMapper); - new ImplementationBodyCodegen(objectDeclaration, objectContext, nameAndVisitor.getSecond(), this).generate(null); + new ImplementationBodyCodegen(objectDeclaration, objectContext, nameAndVisitor.getSecond(), this).generate(); ConstructorDescriptor constructorDescriptor = closure.state.getBindingContext().get(BindingContext.CONSTRUCTOR, objectDeclaration); CallableMethod callableMethod = closure.state.getTypeMapper().mapToCallableMethod(constructorDescriptor, OwnerKind.IMPLEMENTATION); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index 52c23bd170e..3ed944f727f 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -206,10 +206,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } @Override - protected void generateSyntheticParts(HashMap accessors) { + protected void generateSyntheticParts() { generateFieldForObjectInstance(); generateFieldForClassObject(); - generateAccessors(accessors); try { generatePrimaryConstructor(); @@ -222,98 +221,104 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } generateGetTypeInfo(); + + generateAccessors(); } - private void generateAccessors(HashMap accessors) { - if(accessors != null) { - for (Map.Entry entry : accessors.entrySet()) { - if(entry.getValue() instanceof FunctionDescriptor) { - FunctionDescriptor bridge = (FunctionDescriptor) entry.getValue(); - FunctionDescriptor original = (FunctionDescriptor) entry.getKey(); + private void generateAccessors() { + if(context.accessors != null) { + for (Map.Entry entry : context.accessors.entrySet()) { + genAccessor(entry); + } + } + } - Method method = typeMapper.mapSignature(bridge.getName(), bridge).getAsmMethod(); - Method originalMethod = typeMapper.mapSignature(original.getName(), original).getAsmMethod(); - Type[] argTypes = method.getArgumentTypes(); + private void genAccessor(Map.Entry entry) { + if(entry.getValue() instanceof FunctionDescriptor) { + FunctionDescriptor bridge = (FunctionDescriptor) entry.getValue(); + FunctionDescriptor original = (FunctionDescriptor) entry.getKey(); - MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC|Opcodes.ACC_BRIDGE|Opcodes.ACC_FINAL, bridge.getName(), method.getDescriptor(), null, null); - if (v.generateCode()) { - mv.visitCode(); + Method method = typeMapper.mapSignature(bridge.getName(), bridge).getAsmMethod(); + Method originalMethod = typeMapper.mapSignature(original.getName(), original).getAsmMethod(); + Type[] argTypes = method.getArgumentTypes(); - InstructionAdapter iv = new InstructionAdapter(mv); + MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC|Opcodes.ACC_BRIDGE|Opcodes.ACC_FINAL, bridge.getName(), method.getDescriptor(), null, null); + if (v.generateCode()) { + mv.visitCode(); - iv.load(0, JetTypeMapper.TYPE_OBJECT); - for (int i = 0, reg = 1; i < argTypes.length; i++) { - Type argType = argTypes[i]; - iv.load(reg, argType); - //noinspection AssignmentToForLoopParameter - reg += argType.getSize(); - } + InstructionAdapter iv = new InstructionAdapter(mv); + + iv.load(0, JetTypeMapper.TYPE_OBJECT); + for (int i = 0, reg = 1; i < argTypes.length; i++) { + Type argType = argTypes[i]; + iv.load(reg, argType); + //noinspection AssignmentToForLoopParameter + reg += argType.getSize(); + } + iv.invokespecial(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor()); + + iv.areturn(method.getReturnType()); + FunctionCodegen.endVisit(iv, "accessor", null); + } + } + else if(entry.getValue() instanceof PropertyDescriptor) { + PropertyDescriptor bridge = (PropertyDescriptor) entry.getValue(); + PropertyDescriptor original = (PropertyDescriptor) entry.getKey(); + + { + Method method = typeMapper.mapGetterSignature(bridge, OwnerKind.IMPLEMENTATION).getJvmMethodSignature().getAsmMethod(); + JvmPropertyAccessorSignature originalSignature = typeMapper.mapGetterSignature(original, OwnerKind.IMPLEMENTATION); + Method originalMethod = originalSignature.getJvmMethodSignature().getAsmMethod(); + MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC | Opcodes.ACC_BRIDGE | Opcodes.ACC_FINAL, method.getName(), method.getDescriptor(), null, null); + PropertyCodegen.generateJetPropertyAnnotation(mv, originalSignature.getPropertyTypeKotlinSignature(), originalSignature.getJvmMethodSignature().getKotlinTypeParameter()); + if (v.generateCode()) { + mv.visitCode(); + + InstructionAdapter iv = new InstructionAdapter(mv); + + iv.load(0, JetTypeMapper.TYPE_OBJECT); + if(original.getVisibility() == Visibility.PRIVATE) + iv.getfield(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION), original.getName(), originalMethod.getReturnType().getDescriptor()); + else iv.invokespecial(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor()); - iv.areturn(method.getReturnType()); - FunctionCodegen.endVisit(iv, "accessor", null); - } - } - else if(entry.getValue() instanceof PropertyDescriptor) { - PropertyDescriptor bridge = (PropertyDescriptor) entry.getValue(); - PropertyDescriptor original = (PropertyDescriptor) entry.getKey(); - - { - Method method = typeMapper.mapGetterSignature(bridge, OwnerKind.IMPLEMENTATION).getJvmMethodSignature().getAsmMethod(); - JvmPropertyAccessorSignature originalSignature = typeMapper.mapGetterSignature(original, OwnerKind.IMPLEMENTATION); - Method originalMethod = originalSignature.getJvmMethodSignature().getAsmMethod(); - MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC | Opcodes.ACC_BRIDGE | Opcodes.ACC_FINAL, method.getName(), method.getDescriptor(), null, null); - PropertyCodegen.generateJetPropertyAnnotation(mv, originalSignature.getPropertyTypeKotlinSignature(), originalSignature.getJvmMethodSignature().getKotlinTypeParameter()); - if (v.generateCode()) { - mv.visitCode(); - - InstructionAdapter iv = new InstructionAdapter(mv); - - iv.load(0, JetTypeMapper.TYPE_OBJECT); - if(original.getVisibility() == Visibility.PRIVATE) - iv.getfield(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION), original.getName(), originalMethod.getReturnType().getDescriptor()); - else - iv.invokespecial(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor()); - - iv.areturn(method.getReturnType()); - FunctionCodegen.endVisit(iv, "accessor", null); - } - } - - { - - Method method = typeMapper.mapSetterSignature(bridge, OwnerKind.IMPLEMENTATION).getJvmMethodSignature().getAsmMethod(); - JvmPropertyAccessorSignature originalSignature2 = typeMapper.mapSetterSignature(original, OwnerKind.IMPLEMENTATION); - Method originalMethod = originalSignature2.getJvmMethodSignature().getAsmMethod(); - MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC | Opcodes.ACC_BRIDGE | Opcodes.ACC_FINAL, method.getName(), method.getDescriptor(), null, null); - PropertyCodegen.generateJetPropertyAnnotation(mv, originalSignature2.getPropertyTypeKotlinSignature(), originalSignature2.getJvmMethodSignature().getKotlinTypeParameter()); - if (v.generateCode()) { - mv.visitCode(); - - InstructionAdapter iv = new InstructionAdapter(mv); - - iv.load(0, JetTypeMapper.TYPE_OBJECT); - Type[] argTypes = method.getArgumentTypes(); - for (int i = 0, reg = 1; i < argTypes.length; i++) { - Type argType = argTypes[i]; - iv.load(reg, argType); - //noinspection AssignmentToForLoopParameter - reg += argType.getSize(); - } - if(original.getVisibility() == Visibility.PRIVATE) - iv.putfield(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION), original.getName(), originalMethod.getArgumentTypes()[0].getDescriptor()); - else - iv.invokespecial(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor()); - - iv.areturn(method.getReturnType()); - FunctionCodegen.endVisit(iv, "accessor", null); - } - } - } - else { - throw new UnsupportedOperationException(); + iv.areturn(method.getReturnType()); + FunctionCodegen.endVisit(iv, "accessor", null); } } + + if(bridge.isVar()) + { + Method method = typeMapper.mapSetterSignature(bridge, OwnerKind.IMPLEMENTATION).getJvmMethodSignature().getAsmMethod(); + JvmPropertyAccessorSignature originalSignature2 = typeMapper.mapSetterSignature(original, OwnerKind.IMPLEMENTATION); + Method originalMethod = originalSignature2.getJvmMethodSignature().getAsmMethod(); + MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC | Opcodes.ACC_BRIDGE | Opcodes.ACC_FINAL, method.getName(), method.getDescriptor(), null, null); + PropertyCodegen.generateJetPropertyAnnotation(mv, originalSignature2.getPropertyTypeKotlinSignature(), originalSignature2.getJvmMethodSignature().getKotlinTypeParameter()); + if (v.generateCode()) { + mv.visitCode(); + + InstructionAdapter iv = new InstructionAdapter(mv); + + iv.load(0, JetTypeMapper.TYPE_OBJECT); + Type[] argTypes = method.getArgumentTypes(); + for (int i = 0, reg = 1; i < argTypes.length; i++) { + Type argType = argTypes[i]; + iv.load(reg, argType); + //noinspection AssignmentToForLoopParameter + reg += argType.getSize(); + } + if(original.getVisibility() == Visibility.PRIVATE) + iv.putfield(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION), original.getName(), originalMethod.getArgumentTypes()[0].getDescriptor()); + else + iv.invokespecial(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor()); + + iv.areturn(method.getReturnType()); + FunctionCodegen.endVisit(iv, "accessor", null); + } + } + } + else { + throw new UnsupportedOperationException(); } } diff --git a/compiler/testData/codegen/regressions/kt1136.kt b/compiler/testData/codegen/regressions/kt1136.kt new file mode 100644 index 00000000000..4abaa6ab1c7 --- /dev/null +++ b/compiler/testData/codegen/regressions/kt1136.kt @@ -0,0 +1,35 @@ +import java.util.ArrayList + +public class SomeClass() { + class Inner { + val copy = list + } + + private val list = ArrayList() + var status : Throwable? = null + private val workerThread = object : Thread() { + public override fun run() { + try { + list.add("123") + list.add("33") + Inner().copy.add("444") + } + catch(t: Throwable) { + status = t + } + } + } + + { + workerThread.start() + workerThread.join() + } +} + +public fun box():String { + var obj = SomeClass() + return if(obj.status == null) "OK" else { + obj.status?.printStackTrace() + "failed" + } +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/codegen/ObjectGenTest.java b/compiler/tests/org/jetbrains/jet/codegen/ObjectGenTest.java index a698aab25e2..9db2d483ca3 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/ObjectGenTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/ObjectGenTest.java @@ -30,4 +30,8 @@ public class ObjectGenTest extends CodegenTestCase { public void testKt640() throws Exception { blackBoxFile("regressions/kt640.jet"); } + + public void testKt1136() throws Exception { + blackBoxFile("regressions/kt1136.kt"); + } }