diff --git a/compiler/backend/backend.iml b/compiler/backend/backend.iml
index 737dd163839..6cd681955b5 100644
--- a/compiler/backend/backend.iml
+++ b/compiler/backend/backend.iml
@@ -15,7 +15,7 @@
-
+
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java
index 19463c304e0..c10ef5b387a 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java
@@ -1129,7 +1129,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
final MutableClosure closure = context.closure;
ConstructorDescriptor constructorDescriptor = bindingContext.get(BindingContext.CONSTRUCTOR, myClass);
- ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor);
+ ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor, closure);
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
lookupConstructorExpressionsInClosureIfPresent(constructorContext);
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/context/CodegenContext.java b/compiler/backend/src/org/jetbrains/jet/codegen/context/CodegenContext.java
index dbf72d35b82..64355ed58cd 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/context/CodegenContext.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/context/CodegenContext.java
@@ -16,6 +16,7 @@
package org.jetbrains.jet.codegen.context;
+import jet.Function0;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.asm4.Type;
@@ -30,6 +31,8 @@ import org.jetbrains.jet.lang.descriptors.impl.ConstructorDescriptorImpl;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.types.JetType;
+import org.jetbrains.jet.storage.LockBasedStorageManager;
+import org.jetbrains.jet.storage.NullableLazyValue;
import java.util.Collections;
import java.util.HashMap;
@@ -62,7 +65,7 @@ public abstract class CodegenContext {
private Map childContexts;
- protected StackValue outerExpression;
+ private NullableLazyValue lazyOuterExpression;
private final LocalLookup enclosingLocalLookup;
@@ -129,7 +132,7 @@ public abstract class CodegenContext {
}
private StackValue getOuterExpression(@Nullable StackValue prefix, boolean ignoreNoOuter, boolean captureThis) {
- if (outerExpression == null) {
+ if (lazyOuterExpression == null || lazyOuterExpression.invoke() == null) {
if (ignoreNoOuter) {
return null;
}
@@ -140,7 +143,7 @@ public abstract class CodegenContext {
if (captureThis) {
closure.setCaptureThis();
}
- return prefix != null ? StackValue.composed(prefix, outerExpression) : outerExpression;
+ return prefix != null ? StackValue.composed(prefix, lazyOuterExpression.invoke()) : lazyOuterExpression.invoke();
}
@NotNull
@@ -184,13 +187,13 @@ public abstract class CodegenContext {
}
@NotNull
- public ConstructorContext intoConstructor(ConstructorDescriptor descriptor) {
+ public ConstructorContext intoConstructor(@Nullable ConstructorDescriptor descriptor, @Nullable MutableClosure closure) {
if (descriptor == null) {
descriptor = new ConstructorDescriptorImpl(getThisDescriptor(), Collections.emptyList(), true)
.initialize(Collections.emptyList(), Collections.emptyList(),
Visibilities.PUBLIC);
}
- return new ConstructorContext(descriptor, getContextKind(), this);
+ return new ConstructorContext(descriptor, getContextKind(), this, closure);
}
@NotNull
@@ -294,14 +297,19 @@ public abstract class CodegenContext {
public abstract boolean isStatic();
- protected void initOuterExpression(JetTypeMapper typeMapper, ClassDescriptor classDescriptor) {
- ClassDescriptor enclosingClass = getEnclosingClass();
- outerExpression = enclosingClass != null && canHaveOuter(typeMapper.getBindingContext(), classDescriptor)
- ? StackValue.field(typeMapper.mapType(enclosingClass),
- CodegenBinding.getAsmType(typeMapper.getBindingTrace(), classDescriptor),
- CAPTURED_THIS_FIELD,
- false)
- : null;
+ protected void initOuterExpression(@NotNull final JetTypeMapper typeMapper, @NotNull final ClassDescriptor classDescriptor) {
+ lazyOuterExpression = LockBasedStorageManager.NO_LOCKS.createNullableLazyValue(new Function0() {
+ @Override
+ public StackValue invoke() {
+ ClassDescriptor enclosingClass = getEnclosingClass();
+ return enclosingClass != null && canHaveOuter(typeMapper.getBindingContext(), classDescriptor)
+ ? StackValue.field(typeMapper.mapType(enclosingClass),
+ CodegenBinding.getAsmType(typeMapper.getBindingTrace(), classDescriptor),
+ CAPTURED_THIS_FIELD,
+ false)
+ : null;
+ }
+ });
}
public StackValue lookupInContext(DeclarationDescriptor d, @Nullable StackValue result, GenerationState state, boolean ignoreNoOuter) {
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/context/ConstructorContext.java b/compiler/backend/src/org/jetbrains/jet/codegen/context/ConstructorContext.java
index 62162202bfc..fae01feb874 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/context/ConstructorContext.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/context/ConstructorContext.java
@@ -17,9 +17,10 @@
package org.jetbrains.jet.codegen.context;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.codegen.OwnerKind;
import org.jetbrains.jet.codegen.StackValue;
-import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
+import org.jetbrains.jet.codegen.binding.MutableClosure;
import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor;
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE;
@@ -30,17 +31,15 @@ public class ConstructorContext extends MethodContext {
public ConstructorContext(
@NotNull ConstructorDescriptor contextDescriptor,
@NotNull OwnerKind kind,
- @NotNull CodegenContext parent
+ @NotNull CodegenContext parent,
+ @Nullable MutableClosure closure
) {
- super(contextDescriptor, kind, parent);
-
- ClassDescriptor type = getEnclosingClass();
- outerExpression = type != null ? local1 : null;
+ super(contextDescriptor, kind, parent, closure);
}
@Override
public StackValue getOuterExpression(StackValue prefix, boolean ignoreNoOuter) {
- return outerExpression;
+ return closure != null && closure.getCaptureThis() != null ? local1 : null;
}
@Override
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/context/MethodContext.java b/compiler/backend/src/org/jetbrains/jet/codegen/context/MethodContext.java
index 6451c386573..3d65991849e 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/context/MethodContext.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/context/MethodContext.java
@@ -18,6 +18,7 @@ package org.jetbrains.jet.codegen.context;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jet.codegen.binding.MutableClosure;
import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
import org.jetbrains.jet.codegen.OwnerKind;
import org.jetbrains.jet.codegen.StackValue;
@@ -27,14 +28,24 @@ import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyAccessorDescriptor;
public class MethodContext extends CodegenContext {
+
public MethodContext(
@NotNull FunctionDescriptor contextType,
@NotNull OwnerKind contextKind,
@NotNull CodegenContext parentContext
+ ) {
+ this(contextType, contextKind, parentContext, null);
+ }
+
+ protected MethodContext(
+ @NotNull FunctionDescriptor contextType,
+ @NotNull OwnerKind contextKind,
+ @NotNull CodegenContext parentContext,
+ @Nullable MutableClosure closure
) {
super(contextType instanceof PropertyAccessorDescriptor
? ((PropertyAccessorDescriptor) contextType).getCorrespondingProperty()
- : contextType, contextKind, parentContext, null,
+ : contextType, contextKind, parentContext, closure,
parentContext.hasThisDescriptor() ? parentContext.getThisDescriptor() : null, null);
}