From 15c1d7bda74bd2434355fea512740965cae53037 Mon Sep 17 00:00:00 2001 From: Alex Tkachman Date: Tue, 28 Aug 2012 09:31:19 +0300 Subject: [PATCH] most of data previously kept in CodegenAnnotator now lives in binding context (CodegenBinding utility class) injectors regenerated in order to have BindingTrace around --- .../jetbrains/jet/codegen/ClassCodegen.java | 7 +- .../jetbrains/jet/codegen/ClosureCodegen.java | 13 +- .../jet/codegen/ExpressionCodegen.java | 21 +- .../jet/codegen/GenerationState.java | 18 +- .../codegen/ImplementationBodyCodegen.java | 14 +- .../jetbrains/jet/codegen/JetTypeMapper.java | 22 +- .../jetbrains/jet/codegen/ScriptCodegen.java | 15 +- .../jet/codegen/context/CodegenAnnotator.java | 236 ++++-------------- .../jet/codegen/context/CodegenBinding.java | 180 +++++++++++++ .../jet/codegen/context/CodegenContext.java | 3 +- .../jet/codegen/context/LocalLookup.java | 4 +- .../jet/di/InjectorForJetTypeMapper.java | 15 +- .../jet/di/InjectorForJvmCodegen.java | 15 +- .../plugin/debugger/JetPositionManager.java | 15 +- .../debugger/JetPositionManagerTest.java | 3 +- .../jet/di/AllInjectorsGenerator.java | 8 +- 16 files changed, 335 insertions(+), 254 deletions(-) create mode 100644 compiler/backend/src/org/jetbrains/jet/codegen/context/CodegenBinding.java diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java index 7c147f4dfe3..628c36ec099 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java @@ -16,6 +16,7 @@ package org.jetbrains.jet.codegen; +import org.jetbrains.jet.codegen.context.CodegenBinding; import org.jetbrains.jet.codegen.context.CodegenContext; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; @@ -25,6 +26,8 @@ import org.jetbrains.jet.lang.resolve.BindingContext; import javax.inject.Inject; import java.util.Map; +import static org.jetbrains.jet.codegen.context.CodegenBinding.*; + /** * @author max * @author alex.tkachman @@ -60,8 +63,8 @@ public class ClassCodegen { for (JetDeclaration declaration : aClass.getDeclarations()) { if (declaration instanceof JetClass) { - if (declaration instanceof JetEnumEntry && !state.getInjector().getCodegenAnnotator().enumEntryNeedSubclass( - (JetEnumEntry) declaration)) { + if (declaration instanceof JetEnumEntry && !enumEntryNeedSubclass( + state.getBindingContext(), (JetEnumEntry) declaration)) { continue; } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java index 62f421f1b2b..e23220a3c66 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java @@ -28,10 +28,7 @@ import org.jetbrains.asm4.Type; import org.jetbrains.asm4.commons.InstructionAdapter; import org.jetbrains.asm4.commons.Method; import org.jetbrains.asm4.signature.SignatureWriter; -import org.jetbrains.jet.codegen.context.CalculatedClosure; -import org.jetbrains.jet.codegen.context.CodegenAnnotator; -import org.jetbrains.jet.codegen.context.CodegenContext; -import org.jetbrains.jet.codegen.context.MutableClosure; +import org.jetbrains.jet.codegen.context.*; import org.jetbrains.jet.codegen.signature.JvmMethodSignature; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.JetDeclarationWithBody; @@ -47,11 +44,11 @@ import java.util.ArrayList; import java.util.List; import static org.jetbrains.asm4.Opcodes.*; +import static org.jetbrains.jet.codegen.context.CodegenBinding.*; public class ClosureCodegen { private final BindingContext bindingContext; - private final CodegenAnnotator codegenAnnotator; private final JetTypeMapper typeMapper; Method constructor; @@ -65,7 +62,6 @@ public class ClosureCodegen { this.closure = closure; bindingContext = state.getBindingContext(); typeMapper = state.getInjector().getJetTypeMapper(); - codegenAnnotator = typeMapper.getCodegenAnnotator(); } public ClosureCodegen gen(JetExpression fun, CodegenContext context, ExpressionCodegen expressionCodegen) { @@ -282,8 +278,9 @@ public class ClosureCodegen { } else if (CodegenUtil.isNamedFun(descriptor, state.getBindingContext()) && descriptor.getContainingDeclaration() instanceof FunctionDescriptor) { - final Type type = codegenAnnotator - .classNameForAnonymousClass((JetElement) BindingContextUtils.descriptorToDeclaration(bindingContext, descriptor)) + final Type type = + classNameForAnonymousClass(bindingContext, + (JetElement) BindingContextUtils.descriptorToDeclaration(bindingContext, descriptor)) .getAsmType(); args.add(new Pair("$" + descriptor.getName().getName(), type)); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 841902f0fce..fa3a38cf8d1 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -56,6 +56,7 @@ import org.jetbrains.jet.lexer.JetTokens; import java.util.*; import static org.jetbrains.jet.codegen.JetTypeMapper.*; +import static org.jetbrains.jet.codegen.context.CodegenBinding.*; import static org.jetbrains.jet.lang.resolve.BindingContext.*; import static org.jetbrains.jet.lang.resolve.BindingContextUtils.getNotNull; @@ -467,6 +468,7 @@ public class ExpressionCodegen extends JetVisitor implem ResolvedCall nextCall = getNotNull(bindingContext, LOOP_RANGE_NEXT_RESOLVED_CALL, loopRange, "No next() function " + DiagnosticUtils.atLocation(loopRange)); + //noinspection ConstantConditions return nextCall.getResultingDescriptor().getReturnType(); } @@ -1008,8 +1010,10 @@ public class ExpressionCodegen extends JetVisitor implem private StackValue genClosure(JetExpression expression) { final FunctionDescriptor descriptor = bindingContext.get(BindingContext.FUNCTION, expression); final CodegenAnnotator codegenAnnotator = state.getInjector().getCodegenAnnotator(); - final ClassDescriptor classDescriptor = codegenAnnotator.classDescriptorForFunctionDescriptor(descriptor); - final CalculatedClosure closure = codegenAnnotator.getCalculatedClosure(classDescriptor); + final ClassDescriptor classDescriptor = + bindingContext.get(CLASS_FOR_FUNCTION, descriptor); + //noinspection SuspiciousMethodCalls + final CalculatedClosure closure = bindingContext.get(CLOSURE, classDescriptor); ClosureCodegen closureCodegen = new ClosureCodegen(state, (MutableClosure) closure).gen(expression, context, this); @@ -1411,11 +1415,10 @@ public class ExpressionCodegen extends JetVisitor implem if (descriptor instanceof ValueParameterDescriptor && descriptor.getContainingDeclaration() instanceof ScriptDescriptor) { ScriptDescriptor scriptDescriptor = (ScriptDescriptor) descriptor.getContainingDeclaration(); - final CodegenAnnotator codegenAnnotator = state.getInjector().getCodegenAnnotator(); assert scriptDescriptor != null; - JvmClassName scriptClassName = codegenAnnotator.classNameForScriptDescriptor(scriptDescriptor); + JvmClassName scriptClassName = classNameForScriptDescriptor(bindingContext, scriptDescriptor); ValueParameterDescriptor valueParameterDescriptor = (ValueParameterDescriptor) descriptor; - final ClassDescriptor scriptClass = codegenAnnotator.classDescriptorForScriptDescriptor(scriptDescriptor); + final ClassDescriptor scriptClass = bindingContext.get(CLASS_FOR_FUNCTION, scriptDescriptor); final StackValue script = StackValue.thisOrOuter(this, scriptClass); script.put(script.type, v); Type fieldType = typeMapper.mapType(valueParameterDescriptor.getType(), MapTypeMode.VALUE); @@ -1901,13 +1904,15 @@ public class ExpressionCodegen extends JetVisitor implem CodegenContext.ScriptContext scriptContext = (CodegenContext.ScriptContext) cur; JvmClassName currentScriptClassName = - state.getInjector().getCodegenAnnotator().classNameForScriptDescriptor(scriptContext.getScriptDescriptor()); + classNameForScriptDescriptor(state.getBindingContext(), + scriptContext.getScriptDescriptor()); if (scriptContext.getScriptDescriptor() == receiver.getDeclarationDescriptor()) { result.put(currentScriptClassName.getAsmType(), v); } else { JvmClassName className = - state.getInjector().getCodegenAnnotator().classNameForScriptDescriptor(receiver.getDeclarationDescriptor()); + classNameForScriptDescriptor(state.getBindingContext(), + receiver.getDeclarationDescriptor()); String fieldName = state.getInjector().getScriptCodegen().getScriptFieldName(receiver.getDeclarationDescriptor()); result.put(currentScriptClassName.getAsmType(), v); StackValue.field(className.getAsmType(), currentScriptClassName, fieldName, false).put(className.getAsmType(), v); @@ -2837,7 +2842,7 @@ public class ExpressionCodegen extends JetVisitor implem generateInitializer.fun(variableDescriptor); JetScript scriptPsi = JetPsiUtil.getScript(variableDeclaration); assert scriptPsi != null; - JvmClassName scriptClassName = state.getInjector().getCodegenAnnotator().classNameForScriptPsi(scriptPsi); + JvmClassName scriptClassName = classNameForScriptPsi(state.getBindingContext(), scriptPsi); v.putfield(scriptClassName.getInternalName(), variableDeclaration.getName(), varType.getDescriptor()); } else if (sharedVarType == null) { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java b/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java index 0f417beb5b3..e8277227bd6 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java @@ -32,6 +32,7 @@ import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ScriptDescriptor; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.DelegatingBindingTrace; import org.jetbrains.jet.lang.resolve.ScriptNameUtil; import org.jetbrains.jet.lang.resolve.java.JvmClassName; import org.jetbrains.jet.lang.resolve.name.FqName; @@ -42,6 +43,8 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import static org.jetbrains.jet.codegen.context.CodegenBinding.*; + public class GenerationState { private final Progress progress; @NotNull @@ -71,9 +74,10 @@ public class GenerationState { this.progress = progress; this.files = files; this.classBuilderMode = builderFactory.getClassBuilderMode(); - bindingContext = exhaust.getBindingContext(); + final DelegatingBindingTrace trace = new DelegatingBindingTrace(exhaust.getBindingContext()); + bindingContext = trace.getBindingContext(); this.injector = new InjectorForJvmCodegen( - bindingContext, + trace, this.files, builtinToJavaTypesMapping, builderFactory.getClassBuilderMode(), this, builderFactory, project); } @@ -131,7 +135,8 @@ public class GenerationState { } public Pair forAnonymousSubclass(JetElement expression) { - JvmClassName className = getInjector().getJetTypeMapper().getCodegenAnnotator().classNameForAnonymousClass(expression); + JvmClassName className = + classNameForAnonymousClass(bindingContext, expression); return Pair.create(className, getFactory().forAnonymousSubclass(className)); } @@ -151,7 +156,7 @@ public class GenerationState { String name = ScriptNameUtil.classNameForScript(file); JetScript script = file.getScript(); assert script != null; - injector.getCodegenAnnotator().registerClassNameForScript(script, JvmClassName.byInternalName(name)); + registerClassNameForScript(injector.getBindingTrace(), script, JvmClassName.byInternalName(name)); } } @@ -178,7 +183,7 @@ public class GenerationState { ) { injector.getScriptCodegen().registerEarlierScripts(earlierScripts); - injector.getCodegenAnnotator().registerClassNameForScript(script, className); + registerClassNameForScript(injector.getBindingTrace(), script, className); beforeCompile(); @@ -201,7 +206,8 @@ public class GenerationState { final ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, objectDeclaration); assert classDescriptor != null; - final CalculatedClosure closure = getInjector().getCodegenAnnotator().getCalculatedClosure(classDescriptor); + //noinspection SuspiciousMethodCalls + final CalculatedClosure closure = bindingContext.get(CLOSURE, classDescriptor); final CodegenContext objectContext = expressionCodegen.context.intoAnonymousClass(classDescriptor, expressionCodegen); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index 08863f67142..04b1597a362 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -26,9 +26,7 @@ import org.jetbrains.asm4.MethodVisitor; import org.jetbrains.asm4.Type; import org.jetbrains.asm4.commons.InstructionAdapter; import org.jetbrains.asm4.commons.Method; -import org.jetbrains.jet.codegen.context.CalculatedClosure; -import org.jetbrains.jet.codegen.context.CodegenContext; -import org.jetbrains.jet.codegen.context.MutableClosure; +import org.jetbrains.jet.codegen.context.*; import org.jetbrains.jet.codegen.signature.*; import org.jetbrains.jet.codegen.signature.kotlin.JetMethodAnnotationWriter; import org.jetbrains.jet.codegen.signature.kotlin.JetValueParameterAnnotationWriter; @@ -51,6 +49,7 @@ import java.util.*; import static org.jetbrains.asm4.Opcodes.*; import static org.jetbrains.jet.codegen.JetTypeMapper.OBJECT_TYPE; +import static org.jetbrains.jet.codegen.context.CodegenBinding.*; /** * @author max @@ -135,7 +134,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { if (isEnum) { for (JetDeclaration declaration : myClass.getDeclarations()) { if (declaration instanceof JetEnumEntry) { - if (state.getInjector().getCodegenAnnotator().enumEntryNeedSubclass((JetEnumEntry) declaration)) { + if (enumEntryNeedSubclass(state.getBindingContext(), (JetEnumEntry) declaration)) { access &= ~ACC_FINAL; } } @@ -626,7 +625,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { if (hasThis0) { final Type type = typeMapper - .mapType(typeMapper.getCodegenAnnotator().getEclosingClassDescriptor(descriptor).getDefaultType(), MapTypeMode.VALUE); + .mapType(eclosingClassDescriptor(typeMapper.bindingContext, descriptor).getDefaultType(), MapTypeMode.VALUE); String interfaceDesc = type.getDescriptor(); iv.load(0, classType); iv.load(frameMap.getOuterThisIndex(), type); @@ -703,7 +702,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { if (typeMapper.hasThis0(superClassDescriptor)) { iv.load(1, JetTypeMapper.OBJECT_TYPE); parameterTypes.add(typeMapper.mapType( - typeMapper.getCodegenAnnotator().getEclosingClassDescriptor(descriptor).getDefaultType(), MapTypeMode.VALUE)); + eclosingClassDescriptor(typeMapper.bindingContext, descriptor).getDefaultType(), MapTypeMode.VALUE)); } Method superCallMethod = new Method("", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()])); //noinspection ConstantConditions @@ -1141,7 +1140,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { iv.aconst(enumConstant.getName()); iv.iconst(ordinal); - if (delegationSpecifiers.size() == 1 && !state.getInjector().getCodegenAnnotator().enumEntryNeedSubclass(enumConstant)) { + if (delegationSpecifiers.size() == 1 && ! + enumEntryNeedSubclass(state.getBindingContext(), enumConstant)) { final JetDelegationSpecifier specifier = delegationSpecifiers.get(0); if (specifier instanceof JetDelegatorToSuperCall) { final JetDelegatorToSuperCall superCall = (JetDelegatorToSuperCall) specifier; diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java index 436d66c26ae..55b8af82a10 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -44,6 +44,7 @@ import javax.inject.Inject; import java.util.*; import static org.jetbrains.asm4.Opcodes.*; +import static org.jetbrains.jet.codegen.context.CodegenBinding.*; /** * @author yole @@ -101,12 +102,14 @@ public class JetTypeMapper { } public boolean hasThis0(ClassDescriptor classDescriptor) { - final CalculatedClosure closure = codegenAnnotator.getCalculatedClosure(classDescriptor); + //noinspection SuspiciousMethodCalls + final CalculatedClosure closure = bindingContext.get(CLOSURE, classDescriptor); return closure != null && closure.getCaptureThis() != null; } public CalculatedClosure getCalculatedClosure(ClassDescriptor classDescriptor) { - return codegenAnnotator.getCalculatedClosure(classDescriptor); + //noinspection SuspiciousMethodCalls + return bindingContext.get(CLOSURE, classDescriptor); } public CodegenAnnotator getCodegenAnnotator() { @@ -152,7 +155,7 @@ public class JetTypeMapper { return JvmClassName.byType(asmType); } else if (containingDeclaration instanceof ScriptDescriptor) { - return codegenAnnotator.classNameForScriptDescriptor((ScriptDescriptor) containingDeclaration); + return classNameForScriptDescriptor(bindingContext, (ScriptDescriptor) containingDeclaration); } else { throw new UnsupportedOperationException("don't know how to generate owner for parent " + containingDeclaration); @@ -299,7 +302,7 @@ public class JetTypeMapper { } } else if (klass.getKind() == ClassKind.ENUM_ENTRY) { - if (codegenAnnotator.enumEntryNeedSubclass(klass)) { + if (enumEntryNeedSubclass(bindingContext, klass)) { return getJvmInternalFQName(klass.getContainingDeclaration()) + "$" + klass.getName().getName(); } else { @@ -307,7 +310,7 @@ public class JetTypeMapper { } } - JvmClassName name = codegenAnnotator.classNameForClassDescriptor((ClassDescriptor) descriptor); + JvmClassName name = classNameForClassDescriptor(bindingContext, (ClassDescriptor) descriptor); if (name != null) { return name.getInternalName(); } @@ -533,7 +536,7 @@ public class JetTypeMapper { } else if (functionParent instanceof ScriptDescriptor) { thisClass = owner = - ownerForDefaultParam = ownerForDefaultImpl = codegenAnnotator.classNameForScriptDescriptor((ScriptDescriptor) functionParent); + ownerForDefaultParam = ownerForDefaultImpl = classNameForScriptDescriptor(bindingContext, (ScriptDescriptor) functionParent); invokeOpcode = INVOKEVIRTUAL; } else if (functionParent instanceof ClassDescriptor) { @@ -954,8 +957,9 @@ public class JetTypeMapper { for (ScriptDescriptor importedScript : importedScripts) { signatureWriter.writeParameterType(JvmMethodParameterKind.VALUE); - mapType(codegenAnnotator.classDescriptorForScriptDescriptor(importedScript).getDefaultType(), signatureWriter, - MapTypeMode.VALUE); + final ClassDescriptor descriptor = bindingContext.get(CLASS_FOR_FUNCTION, importedScript); + assert descriptor != null; + mapType(descriptor.getDefaultType(), signatureWriter, MapTypeMode.VALUE); signatureWriter.writeParameterTypeEnd(); } @@ -1027,7 +1031,7 @@ public class JetTypeMapper { } else if (descriptor instanceof SimpleFunctionDescriptor && descriptor.getContainingDeclaration() instanceof FunctionDescriptor) { PsiElement psiElement = BindingContextUtils.descriptorToDeclaration(bindingContext, descriptor); - return codegenAnnotator.classNameForAnonymousClass((JetElement) psiElement).getAsmType(); + return classNameForAnonymousClass(bindingContext, (JetElement) psiElement).getAsmType(); } else if (descriptor instanceof FunctionDescriptor) { return StackValue diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ScriptCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ScriptCodegen.java index 5fecfad0608..1cf91dc6a2a 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ScriptCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ScriptCodegen.java @@ -40,6 +40,7 @@ import javax.inject.Inject; import java.util.List; import static org.jetbrains.jet.codegen.JetTypeMapper.OBJECT_TYPE; +import static org.jetbrains.jet.codegen.context.CodegenBinding.*; /** * @author Stepan Koltsov @@ -98,13 +99,14 @@ public class ScriptCodegen { ScriptDescriptor scriptDescriptor = state.getBindingContext().get(BindingContext.SCRIPT, scriptDeclaration); assert scriptDescriptor != null; - ClassDescriptor classDescriptorForScript = codegenAnnotator.classDescriptorForScriptDescriptor(scriptDescriptor); + ClassDescriptor classDescriptorForScript = bindingContext.get(CLASS_FOR_FUNCTION, scriptDescriptor); + assert classDescriptorForScript != null; CodegenContext.ScriptContext context = (CodegenContext.ScriptContext) CodegenContext.STATIC .intoScript(scriptDescriptor, classDescriptorForScript); - JvmClassName className = codegenAnnotator.classNameForClassDescriptor(classDescriptorForScript); + JvmClassName className = classNameForClassDescriptor(bindingContext, classDescriptorForScript); ClassBuilder classBuilder = classFileFactory.newVisitor(className.getInternalName() + ".class"); classBuilder.defineClass(scriptDeclaration, @@ -150,7 +152,7 @@ public class ScriptCodegen { InstructionAdapter instructionAdapter = new InstructionAdapter(mv); - JvmClassName className = codegenAnnotator.classNameForClassDescriptor(classDescriptorForScript); + JvmClassName className = classNameForClassDescriptor(bindingContext, classDescriptorForScript); instructionAdapter.load(0, className.getAsmType()); instructionAdapter.invokespecial("java/lang/Object", "", "()V"); @@ -181,7 +183,7 @@ public class ScriptCodegen { int offset = 1; for (ScriptDescriptor earlierScript : importedScripts) { - JvmClassName earlierClassName = codegenAnnotator.classNameForScriptDescriptor(earlierScript); + JvmClassName earlierClassName = classNameForScriptDescriptor(bindingContext, earlierScript); instructionAdapter.load(0, className.getAsmType()); instructionAdapter.load(offset, earlierClassName.getAsmType()); offset += earlierClassName.getAsmType().getSize(); @@ -212,7 +214,8 @@ public class ScriptCodegen { private void genFieldsForParameters(@NotNull ScriptDescriptor script, @NotNull ClassBuilder classBuilder) { for (ScriptDescriptor earlierScript : earlierScripts) { - JvmClassName earlierClassName = codegenAnnotator.classNameForScriptDescriptor(earlierScript); + JvmClassName earlierClassName; + earlierClassName = classNameForScriptDescriptor(bindingContext, earlierScript); int access = Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL; classBuilder.newField(null, access, getScriptFieldName(earlierScript), earlierClassName.getDescriptor(), null, null); } @@ -235,7 +238,7 @@ public class ScriptCodegen { ScriptDescriptor earlierDescriptor = t.first; JvmClassName earlierClassName = t.second; - codegenAnnotator.registerClassNameForScript(earlierDescriptor, earlierClassName); + registerClassNameForScript(codegenAnnotator.getBindingTrace(), earlierDescriptor, earlierClassName); } List earlierScriptDescriptors = Lists.newArrayList(); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/context/CodegenAnnotator.java b/compiler/backend/src/org/jetbrains/jet/codegen/context/CodegenAnnotator.java index aa98624f811..d1f34b7f209 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/context/CodegenAnnotator.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/context/CodegenAnnotator.java @@ -18,13 +18,11 @@ package org.jetbrains.jet.codegen.context; import com.intellij.util.containers.MultiMap; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.codegen.CodegenUtil; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; -import org.jetbrains.jet.lang.resolve.DescriptorUtils; +import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.java.JvmAbi; import org.jetbrains.jet.lang.resolve.java.JvmClassName; import org.jetbrains.jet.lang.resolve.name.FqName; @@ -35,26 +33,28 @@ import org.jetbrains.jet.lang.types.lang.JetStandardClasses; import javax.inject.Inject; import java.util.*; +import static org.jetbrains.jet.codegen.context.CodegenBinding.*; +import static org.jetbrains.jet.lang.resolve.BindingContext.*; + /** * @author alex.tkachman */ public class CodegenAnnotator { - private final Map closuresForClassDescriptor = new HashMap(); - private final Map classNameForScript = new HashMap(); - private final Set scriptClassNames = new HashSet(); - private final Map classesForFunctions = - new HashMap(); - private final MultiMap namespaceName2MultiNamespaceFiles = MultiMap.create(); private final MultiMap namespaceName2Files = MultiMap.create(); + private BindingTrace bindingTrace; private BindingContext bindingContext; private List files; - private final Map enumEntryNeedSubclass = new HashMap(); + + public BindingTrace getBindingTrace() { + return bindingTrace; + } @Inject - public void setBindingContext(BindingContext bindingContext) { - this.bindingContext = bindingContext; + public void setBindingTrace(BindingTrace bindingTrace) { + this.bindingTrace = bindingTrace; + bindingContext = bindingTrace.getBindingContext(); } @Inject @@ -68,92 +68,27 @@ public class CodegenAnnotator { } - @NotNull - public ClassDescriptor classDescriptorForFunctionDescriptor(FunctionDescriptor funDescriptor) { - ClassDescriptorImpl classDescriptor = classesForFunctions.get(funDescriptor); - if (classDescriptor == null) { - int arity = funDescriptor.getValueParameters().size(); + private ClassDescriptor recordClassForFunction(FunctionDescriptor funDescriptor) { + ClassDescriptor classDescriptor; + int arity = funDescriptor.getValueParameters().size(); - classDescriptor = new ClassDescriptorImpl( - funDescriptor.getContainingDeclaration(), - Collections.emptyList(), - Modality.FINAL, - Name.special("")); - classDescriptor.initialize( - false, - Collections.emptyList(), - Collections.singleton((funDescriptor.getReceiverParameter().exists() - ? JetStandardClasses.getReceiverFunction(arity) - : JetStandardClasses.getFunction(arity)).getDefaultType()), JetScope.EMPTY, - Collections.emptySet(), null); - classesForFunctions.put(funDescriptor, classDescriptor); - } - return classDescriptor; - } - - public void registerClassNameForScript(@NotNull ScriptDescriptor scriptDescriptor, @NotNull JvmClassName className) { - JvmClassName oldName = classNameForScript.put(scriptDescriptor, className); - if (oldName != null) { - throw new IllegalStateException("Rewrite at key " + scriptDescriptor + " for name"); - } - - if (!scriptClassNames.add(className)) { - throw new IllegalStateException("More than one script has class name " + className); - } - - ClassDescriptorImpl classDescriptor = new ClassDescriptorImpl( - scriptDescriptor, + classDescriptor = new ClassDescriptorImpl( + funDescriptor.getContainingDeclaration(), Collections.emptyList(), Modality.FINAL, - Name.special("")); - classDescriptor.initialize( + Name.special("")); + ((ClassDescriptorImpl)classDescriptor).initialize( false, Collections.emptyList(), - Collections.singletonList(JetStandardClasses.getAnyType()), - JetScope.EMPTY, - Collections.emptySet(), - null); + Collections.singleton((funDescriptor.getReceiverParameter().exists() + ? JetStandardClasses.getReceiverFunction(arity) + : JetStandardClasses.getFunction(arity)).getDefaultType()), JetScope.EMPTY, + Collections.emptySet(), null); - recordClosure(null, classDescriptor, null, className, false); - - ClassDescriptorImpl oldDescriptor = classesForFunctions.put(scriptDescriptor, classDescriptor); - if (oldDescriptor != null) { - throw new IllegalStateException("Rewrite at key " + scriptDescriptor + " for class"); - } - } - - public void registerClassNameForScript(@NotNull JetScript jetScript, @NotNull JvmClassName className) { - ScriptDescriptor descriptor = bindingContext.get(BindingContext.SCRIPT, jetScript); - if (descriptor == null) { - throw new IllegalStateException("Descriptor is not found for PSI " + jetScript); - } - registerClassNameForScript(descriptor, className); - } - - @NotNull - public ClassDescriptor classDescriptorForScriptDescriptor(@NotNull ScriptDescriptor scriptDescriptor) { - ClassDescriptorImpl classDescriptor = classesForFunctions.get(scriptDescriptor); - if (classDescriptor == null) { - throw new IllegalStateException("Class for script is not registered: " + scriptDescriptor); - } + bindingTrace.record(CLASS_FOR_FUNCTION, funDescriptor, classDescriptor); return classDescriptor; } - @NotNull - public JvmClassName classNameForScriptPsi(@NotNull JetScript script) { - ScriptDescriptor scriptDescriptor = bindingContext.get(BindingContext.SCRIPT, script); - if (scriptDescriptor == null) { - throw new IllegalStateException("Script descriptor not found by PSI " + script); - } - return classNameForScriptDescriptor(scriptDescriptor); - } - - @NotNull - public JvmClassName classNameForScriptDescriptor(@NotNull ScriptDescriptor scriptDescriptor) { - final ClassDescriptor classDescriptor = classDescriptorForScriptDescriptor(scriptDescriptor); - return closuresForClassDescriptor.get(classDescriptor).getClassName(); - } - private void mapFilesToNamespaces(Collection files) { for (JetFile file : files) { if (file.isScript()) { @@ -199,87 +134,6 @@ public class CodegenAnnotator { return namespaceName2MultiNamespaceFiles.get(fqName).size() > 0; } - public JvmClassName classNameForAnonymousClass(JetElement expression) { - if (expression instanceof JetObjectLiteralExpression) { - JetObjectLiteralExpression jetObjectLiteralExpression = (JetObjectLiteralExpression) expression; - expression = jetObjectLiteralExpression.getObjectDeclaration(); - } - - ClassDescriptor descriptor = bindingContext.get(BindingContext.CLASS, expression); - if (descriptor == null) { - SimpleFunctionDescriptor functionDescriptor = bindingContext.get(BindingContext.FUNCTION, expression); - assert functionDescriptor != null; - descriptor = classDescriptorForFunctionDescriptor(functionDescriptor); - } - return classNameForClassDescriptor(descriptor); - } - - public JvmClassName classNameForClassDescriptor(ClassDescriptor descriptor) { - final CalculatedClosure closure = closuresForClassDescriptor.get(descriptor); - return closure == null ? null : closure.getClassName(); - } - - public ClassDescriptor getEclosingClassDescriptor(ClassDescriptor descriptor) { - final CalculatedClosure closure = closuresForClassDescriptor.get(descriptor); - return closure == null ? null : closure.getEnclosingClass(); - } - - public boolean canHaveOuter(ClassDescriptor classDescriptor) { - if (DescriptorUtils.isClassObject(classDescriptor)) { - return false; - } - if (classDescriptor.getKind() == ClassKind.ENUM_CLASS || classDescriptor.getKind() == ClassKind.ENUM_ENTRY) { - return false; - } - - return getEclosingClassDescriptor(classDescriptor) != null; - } - - public boolean enumEntryNeedSubclass(JetEnumEntry enumEntry) { - return Boolean.TRUE.equals(enumEntryNeedSubclass.get(bindingContext.get(BindingContext.CLASS, enumEntry))); - } - - public boolean enumEntryNeedSubclass(ClassDescriptor enumEntry) { - return Boolean.TRUE.equals(enumEntryNeedSubclass.get(enumEntry)); - } - - public CalculatedClosure getCalculatedClosure(@NotNull ClassDescriptor descriptor) { - //noinspection SuspiciousMethodCalls - return closuresForClassDescriptor.get(descriptor.getOriginal()); - } - - private void recordClosure( - @Nullable JetElement element, - ClassDescriptor classDescriptor, - @Nullable ClassDescriptor enclosing, - JvmClassName name, - boolean functionLiteral - ) { - final JetDelegatorToSuperCall superCall = CodegenUtil.findSuperCall(element, bindingContext); - - CallableDescriptor enclosingReceiver = null; - if (classDescriptor.getContainingDeclaration() instanceof CallableDescriptor) { - enclosingReceiver = (CallableDescriptor) classDescriptor.getContainingDeclaration(); - enclosingReceiver = enclosingReceiver instanceof PropertyAccessorDescriptor - ? ((PropertyAccessorDescriptor) enclosingReceiver).getCorrespondingProperty() - : enclosingReceiver; - - if (!enclosingReceiver.getReceiverParameter().exists()) { - enclosingReceiver = null; - } - } - - final MutableClosure closure = new MutableClosure(superCall, enclosing, name, enclosingReceiver); - - final CalculatedClosure old = closuresForClassDescriptor.put(classDescriptor, closure); - assert old == null; - - // TODO: this is temporary before we have proper inner classes - if (canHaveOuter(classDescriptor) && !functionLiteral) { - closure.setCaptureThis(); - } - } - private class MyJetVisitorVoid extends JetVisitorVoid { private final Map anonymousSubclassesCount = new HashMap(); @@ -293,7 +147,7 @@ public class CodegenAnnotator { cnt = 0; } String name = top + "$" + (cnt + 1); - ClassDescriptor descriptor = bindingContext.get(BindingContext.CLASS, declaration); + ClassDescriptor descriptor = bindingContext.get(CLASS, declaration); if (descriptor == null) { if (declaration instanceof JetFunctionLiteralExpression || declaration instanceof JetNamedFunction || @@ -320,9 +174,11 @@ public class CodegenAnnotator { public void visitJetFile(JetFile file) { if (file.isScript()) { //noinspection ConstantConditions - classStack.push(classDescriptorForScriptDescriptor(bindingContext.get(BindingContext.SCRIPT, file.getScript()))); + final ClassDescriptor classDescriptor = + bindingContext.get(CLASS_FOR_FUNCTION, bindingContext.get(SCRIPT, file.getScript())); + classStack.push(classDescriptor); //noinspection ConstantConditions - nameStack.push(classNameForScriptPsi(file.getScript()).getInternalName()); + nameStack.push(classNameForScriptPsi(bindingContext, file.getScript()).getInternalName()); } else { nameStack.push(JetPsiUtil.getFQName(file).getFqName().replace('.', '/')); @@ -336,12 +192,12 @@ public class CodegenAnnotator { @Override public void visitEnumEntry(JetEnumEntry enumEntry) { - ClassDescriptor descriptor = bindingContext.get(BindingContext.CLASS, enumEntry); + ClassDescriptor descriptor = bindingContext.get(CLASS, enumEntry); assert descriptor != null; final boolean trivial = enumEntry.getDeclarations().isEmpty(); if (!trivial) { - enumEntryNeedSubclass.put(descriptor, Boolean.TRUE); + bindingTrace.record(ENUM_ENTRY_CLASS_NEED_SUBCLASS, descriptor); classStack.push(descriptor); nameStack.push(nameStack.peek() + "$" + descriptor.getName().getName()); @@ -356,11 +212,11 @@ public class CodegenAnnotator { @Override public void visitClassObject(JetClassObject classObject) { - ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, classObject.getObjectDeclaration()); + ClassDescriptor classDescriptor = bindingContext.get(CLASS, classObject.getObjectDeclaration()); assert classDescriptor != null; JvmClassName name = JvmClassName.byInternalName(nameStack.peek() + JvmAbi.CLASS_OBJECT_SUFFIX); - recordClosure(classObject, classDescriptor, classStack.peek(), name, false); + recordClosure(bindingTrace, classObject, classDescriptor, classStack.peek(), name, false); classStack.push(classDescriptor); nameStack.push(name.getInternalName()); @@ -375,12 +231,12 @@ public class CodegenAnnotator { super.visitObjectDeclaration(declaration); } else { - ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, declaration); + ClassDescriptor classDescriptor = bindingContext.get(CLASS, declaration); // working around a problem with shallow analysis if (classDescriptor == null) return; String name = getName(classDescriptor); - recordClosure(declaration, classDescriptor, classStack.peek(), JvmClassName.byInternalName(name), false); + recordClosure(bindingTrace, declaration, classDescriptor, classStack.peek(), JvmClassName.byInternalName(name), false); classStack.push(classDescriptor); nameStack.push(name); @@ -392,12 +248,12 @@ public class CodegenAnnotator { @Override public void visitClass(JetClass klass) { - ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, klass); + ClassDescriptor classDescriptor = bindingContext.get(CLASS, klass); // working around a problem with shallow analysis if (classDescriptor == null) return; String name = getName(classDescriptor); - recordClosure(klass, classDescriptor, classStack.peek(), JvmClassName.byInternalName(name), false); + recordClosure(bindingTrace, klass, classDescriptor, classStack.peek(), JvmClassName.byInternalName(name), false); classStack.push(classDescriptor); nameStack.push(name); @@ -414,7 +270,7 @@ public class CodegenAnnotator { @Override public void visitObjectLiteralExpression(JetObjectLiteralExpression expression) { - ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, expression.getObjectDeclaration()); + ClassDescriptor classDescriptor = bindingContext.get(CLASS, expression.getObjectDeclaration()); if (classDescriptor == null) { // working around a problem with shallow analysis super.visitObjectLiteralExpression(expression); @@ -422,10 +278,10 @@ public class CodegenAnnotator { } final String name = inventAnonymousClassName(expression.getObjectDeclaration()); - recordClosure(expression.getObjectDeclaration(), classDescriptor, classStack.peek(), JvmClassName.byInternalName(name), false); + recordClosure(bindingTrace, expression.getObjectDeclaration(), classDescriptor, classStack.peek(), JvmClassName.byInternalName(name), false); classStack.push(classDescriptor); - nameStack.push(classNameForClassDescriptor(classDescriptor).getInternalName()); + nameStack.push(classNameForClassDescriptor(bindingContext, classDescriptor).getInternalName()); super.visitObjectLiteralExpression(expression); nameStack.pop(); classStack.pop(); @@ -434,13 +290,13 @@ public class CodegenAnnotator { @Override public void visitFunctionLiteralExpression(JetFunctionLiteralExpression expression) { FunctionDescriptor functionDescriptor = - (FunctionDescriptor) bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, expression); + (FunctionDescriptor) bindingContext.get(DECLARATION_TO_DESCRIPTOR, expression); // working around a problem with shallow analysis if (functionDescriptor == null) return; String name = inventAnonymousClassName(expression); - ClassDescriptor classDescriptor = classDescriptorForFunctionDescriptor(functionDescriptor); - recordClosure(expression, classDescriptor, classStack.peek(), JvmClassName.byInternalName(name), true); + ClassDescriptor classDescriptor = recordClassForFunction(functionDescriptor); + recordClosure(bindingTrace, expression, classDescriptor, classStack.peek(), JvmClassName.byInternalName(name), true); classStack.push(classDescriptor); nameStack.push(name); @@ -459,7 +315,7 @@ public class CodegenAnnotator { @Override public void visitNamedFunction(JetNamedFunction function) { FunctionDescriptor functionDescriptor = - (FunctionDescriptor) bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, function); + (FunctionDescriptor) bindingContext.get(DECLARATION_TO_DESCRIPTOR, function); // working around a problem with shallow analysis if (functionDescriptor == null) return; DeclarationDescriptor containingDeclaration = functionDescriptor.getContainingDeclaration(); @@ -482,8 +338,8 @@ public class CodegenAnnotator { } else { String name = inventAnonymousClassName(function); - ClassDescriptor classDescriptor = classDescriptorForFunctionDescriptor(functionDescriptor); - recordClosure(function, classDescriptor, classStack.peek(), JvmClassName.byInternalName(name), true); + ClassDescriptor classDescriptor = recordClassForFunction(functionDescriptor); + recordClosure(bindingTrace, function, classDescriptor, classStack.peek(), JvmClassName.byInternalName(name), true); classStack.push(classDescriptor); nameStack.push(name); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/context/CodegenBinding.java b/compiler/backend/src/org/jetbrains/jet/codegen/context/CodegenBinding.java new file mode 100644 index 00000000000..0f63d95ce62 --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/context/CodegenBinding.java @@ -0,0 +1,180 @@ +/* + * Copyright 2010-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.codegen.context; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.codegen.CodegenUtil; +import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; +import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.BindingTrace; +import org.jetbrains.jet.lang.resolve.DescriptorUtils; +import org.jetbrains.jet.lang.resolve.java.JvmClassName; +import org.jetbrains.jet.lang.resolve.name.Name; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; +import org.jetbrains.jet.lang.types.lang.JetStandardClasses; +import org.jetbrains.jet.util.slicedmap.*; + +import java.util.Collections; + +import static org.jetbrains.jet.lang.resolve.BindingContext.CLASS; +import static org.jetbrains.jet.lang.resolve.BindingContext.FUNCTION; +import static org.jetbrains.jet.lang.resolve.BindingContext.SCRIPT; + +/** + * @author alex.tkachman + */ +public class CodegenBinding { + public static final WritableSlice CLOSURE = Slices.createSimpleSlice(); + + public static final WritableSlice CLASS_FOR_FUNCTION = Slices.createSimpleSlice(); + + public static final WritableSlice SCRIPT_NAMES = Slices.createSimpleSetSlice(); + + public static final WritableSlice ENUM_ENTRY_CLASS_NEED_SUBCLASS = Slices.createSimpleSetSlice(); + + private CodegenBinding() { + } + + public static boolean enumEntryNeedSubclass(BindingContext bindingContext, JetEnumEntry enumEntry) { + return enumEntryNeedSubclass(bindingContext, bindingContext.get(CLASS, enumEntry)); + } + + public static boolean enumEntryNeedSubclass(BindingContext bindingContext, ClassDescriptor classDescriptor) { + return Boolean.TRUE.equals(bindingContext.get(ENUM_ENTRY_CLASS_NEED_SUBCLASS, classDescriptor)); + } + + @NotNull + public static JvmClassName classNameForScriptDescriptor(BindingContext bindingContext, @NotNull ScriptDescriptor scriptDescriptor) { + final ClassDescriptor classDescriptor = bindingContext.get(CLASS_FOR_FUNCTION, scriptDescriptor); + final CalculatedClosure closure = bindingContext.get(CLOSURE, classDescriptor); + assert closure != null; + return closure.getClassName(); + } + + @NotNull + public static JvmClassName classNameForScriptPsi(BindingContext bindingContext, @NotNull JetScript script) { + ScriptDescriptor scriptDescriptor = bindingContext.get(SCRIPT, script); + if (scriptDescriptor == null) { + throw new IllegalStateException("Script descriptor not found by PSI " + script); + } + return classNameForScriptDescriptor(bindingContext, scriptDescriptor); + } + + public static ClassDescriptor eclosingClassDescriptor(BindingContext bindingContext, ClassDescriptor descriptor) { + final CalculatedClosure closure = bindingContext.get(CLOSURE, descriptor); + return closure == null ? null : closure.getEnclosingClass(); + } + + public static JvmClassName classNameForClassDescriptor(BindingContext bindingContext, ClassDescriptor descriptor) { + final CalculatedClosure closure = bindingContext.get(CLOSURE, descriptor); + return closure == null ? null : closure.getClassName(); + } + + public static JvmClassName classNameForAnonymousClass(BindingContext bindingContext, JetElement expression) { + if (expression instanceof JetObjectLiteralExpression) { + JetObjectLiteralExpression jetObjectLiteralExpression = (JetObjectLiteralExpression) expression; + expression = jetObjectLiteralExpression.getObjectDeclaration(); + } + + ClassDescriptor descriptor = bindingContext.get(CLASS, expression); + if (descriptor == null) { + SimpleFunctionDescriptor functionDescriptor = bindingContext.get(FUNCTION, expression); + assert functionDescriptor != null; + descriptor = bindingContext.get(CLASS_FOR_FUNCTION, functionDescriptor); + } + return classNameForClassDescriptor(bindingContext, descriptor); + } + + public static void registerClassNameForScript( + BindingTrace bindingTrace, + @NotNull ScriptDescriptor scriptDescriptor, + @NotNull JvmClassName className + ) { + bindingTrace.record(SCRIPT_NAMES, className); + + ClassDescriptorImpl classDescriptor = new ClassDescriptorImpl( + scriptDescriptor, + Collections.emptyList(), + Modality.FINAL, + Name.special("")); + classDescriptor.initialize( + false, + Collections.emptyList(), + Collections.singletonList(JetStandardClasses.getAnyType()), + JetScope.EMPTY, + Collections.emptySet(), + null); + + recordClosure(bindingTrace, null, classDescriptor, null, className, false); + + bindingTrace.record(CLASS_FOR_FUNCTION, scriptDescriptor, classDescriptor); + } + + private static boolean canHaveOuter(BindingContext bindingContext, ClassDescriptor classDescriptor) { + if (DescriptorUtils.isClassObject(classDescriptor)) { + return false; + } + if (classDescriptor.getKind() == ClassKind.ENUM_CLASS || classDescriptor.getKind() == ClassKind.ENUM_ENTRY) { + return false; + } + + return eclosingClassDescriptor(bindingContext, classDescriptor) != null; + } + + static void recordClosure( + BindingTrace bindingTrace, + @Nullable JetElement element, + ClassDescriptor classDescriptor, + @Nullable ClassDescriptor enclosing, + JvmClassName name, + boolean functionLiteral + ) { + final JetDelegatorToSuperCall superCall = CodegenUtil.findSuperCall(element, bindingTrace.getBindingContext()); + + CallableDescriptor enclosingReceiver = null; + if (classDescriptor.getContainingDeclaration() instanceof CallableDescriptor) { + enclosingReceiver = (CallableDescriptor) classDescriptor.getContainingDeclaration(); + enclosingReceiver = enclosingReceiver instanceof PropertyAccessorDescriptor + ? ((PropertyAccessorDescriptor) enclosingReceiver).getCorrespondingProperty() + : enclosingReceiver; + + if (!enclosingReceiver.getReceiverParameter().exists()) { + enclosingReceiver = null; + } + } + + final MutableClosure closure = new MutableClosure(superCall, enclosing, name, enclosingReceiver); + + bindingTrace.record(CLOSURE, classDescriptor, closure); + + // TODO: this is temporary before we have proper inner classes + if (canHaveOuter(bindingTrace.getBindingContext(), classDescriptor) && !functionLiteral) { + closure.setCaptureThis(); + } + } + + public static void registerClassNameForScript(BindingTrace bindingTrace, @NotNull JetScript jetScript, @NotNull JvmClassName className) { + ScriptDescriptor descriptor = bindingTrace.getBindingContext().get(SCRIPT, jetScript); + if (descriptor == null) { + throw new IllegalStateException("Descriptor is not found for PSI " + jetScript); + } + registerClassNameForScript(bindingTrace, descriptor, className); + } +} 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 64789c0e6ce..c036947c01f 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/context/CodegenContext.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/context/CodegenContext.java @@ -31,6 +31,7 @@ import java.util.List; import java.util.Map; import static org.jetbrains.jet.codegen.JetTypeMapper.OBJECT_TYPE; +import static org.jetbrains.jet.codegen.context.CodegenBinding.*; /* * @author max @@ -179,7 +180,7 @@ public abstract class CodegenContext { ) { final JetTypeMapper typeMapper = expressionCodegen.getState().getInjector().getJetTypeMapper(); return new ClosureContext(typeMapper, funDescriptor, - typeMapper.getCodegenAnnotator().classDescriptorForFunctionDescriptor(funDescriptor), + typeMapper.bindingContext.get(CLASS_FOR_FUNCTION, funDescriptor), this, expressionCodegen); } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/context/LocalLookup.java b/compiler/backend/src/org/jetbrains/jet/codegen/context/LocalLookup.java index 10603ac3681..9c61a95052a 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/context/LocalLookup.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/context/LocalLookup.java @@ -24,6 +24,8 @@ import org.jetbrains.jet.lang.resolve.BindingContextUtils; import org.jetbrains.jet.lang.resolve.java.JvmClassName; import org.jetbrains.jet.lang.types.JetType; +import static org.jetbrains.jet.codegen.context.CodegenBinding.*; + /** * @author alex.tkachman */ @@ -74,7 +76,7 @@ public interface LocalLookup { if (!idx) return null; JetElement expression = (JetElement) BindingContextUtils.callableDescriptorToDeclaration(state.getBindingContext(), vd); - JvmClassName cn = state.getInjector().getJetTypeMapper().getCodegenAnnotator().classNameForAnonymousClass(expression); + JvmClassName cn = classNameForAnonymousClass(state.getBindingContext(), expression); Type localType = cn.getAsmType(); final String fieldName = "$" + vd.getName(); diff --git a/compiler/backend/src/org/jetbrains/jet/di/InjectorForJetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/di/InjectorForJetTypeMapper.java index fdc0ba5200d..8b3628ab413 100644 --- a/compiler/backend/src/org/jetbrains/jet/di/InjectorForJetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/di/InjectorForJetTypeMapper.java @@ -17,6 +17,7 @@ package org.jetbrains.jet.di; +import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.BindingContext; import java.util.List; import org.jetbrains.jet.lang.psi.JetFile; @@ -30,7 +31,8 @@ import javax.annotation.PreDestroy; /* This file is generated by org.jetbrains.jet.di.AllInjectorsGenerator. DO NOT EDIT! */ public class InjectorForJetTypeMapper { - private final BindingContext bindingContext; + private final BindingTrace bindingTrace; + private BindingContext bindingContext; private final List listOfJetFile; private JetTypeMapper jetTypeMapper; private BuiltinToJavaTypesMapping builtinToJavaTypesMapping; @@ -38,10 +40,11 @@ public class InjectorForJetTypeMapper { private CodegenAnnotator codegenAnnotator; public InjectorForJetTypeMapper( - @NotNull BindingContext bindingContext, + @NotNull BindingTrace bindingTrace, @NotNull List listOfJetFile ) { - this.bindingContext = bindingContext; + this.bindingTrace = bindingTrace; + this.bindingContext = bindingTrace.getBindingContext(); this.listOfJetFile = listOfJetFile; this.jetTypeMapper = new JetTypeMapper(); this.builtinToJavaTypesMapping = BuiltinToJavaTypesMapping.ENABLED; @@ -53,7 +56,7 @@ public class InjectorForJetTypeMapper { this.jetTypeMapper.setClassBuilderMode(classBuilderMode); this.jetTypeMapper.setCodegenAnnotator(codegenAnnotator); - codegenAnnotator.setBindingContext(bindingContext); + codegenAnnotator.setBindingTrace(bindingTrace); codegenAnnotator.setFiles(listOfJetFile); } @@ -62,6 +65,10 @@ public class InjectorForJetTypeMapper { public void destroy() { } + public BindingTrace getBindingTrace() { + return this.bindingTrace; + } + public JetTypeMapper getJetTypeMapper() { return this.jetTypeMapper; } diff --git a/compiler/backend/src/org/jetbrains/jet/di/InjectorForJvmCodegen.java b/compiler/backend/src/org/jetbrains/jet/di/InjectorForJvmCodegen.java index ea8838334c6..49d016a8e4c 100644 --- a/compiler/backend/src/org/jetbrains/jet/di/InjectorForJvmCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/di/InjectorForJvmCodegen.java @@ -17,6 +17,7 @@ package org.jetbrains.jet.di; +import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.BindingContext; import java.util.List; import org.jetbrains.jet.lang.psi.JetFile; @@ -38,7 +39,8 @@ import javax.annotation.PreDestroy; /* This file is generated by org.jetbrains.jet.di.AllInjectorsGenerator. DO NOT EDIT! */ public class InjectorForJvmCodegen { - private final BindingContext bindingContext; + private final BindingTrace bindingTrace; + private BindingContext bindingContext; private final List listOfJetFile; private final BuiltinToJavaTypesMapping builtinToJavaTypesMapping; private final ClassBuilderMode classBuilderMode; @@ -54,7 +56,7 @@ public class InjectorForJvmCodegen { private CodegenAnnotator codegenAnnotator; public InjectorForJvmCodegen( - @NotNull BindingContext bindingContext, + @NotNull BindingTrace bindingTrace, @NotNull List listOfJetFile, @NotNull BuiltinToJavaTypesMapping builtinToJavaTypesMapping, @NotNull ClassBuilderMode classBuilderMode, @@ -62,7 +64,8 @@ public class InjectorForJvmCodegen { @NotNull ClassBuilderFactory classBuilderFactory, @NotNull Project project ) { - this.bindingContext = bindingContext; + this.bindingTrace = bindingTrace; + this.bindingContext = bindingTrace.getBindingContext(); this.listOfJetFile = listOfJetFile; this.builtinToJavaTypesMapping = builtinToJavaTypesMapping; this.classBuilderMode = classBuilderMode; @@ -97,7 +100,7 @@ public class InjectorForJvmCodegen { this.memberCodegen.setState(generationState); - this.codegenAnnotator.setBindingContext(bindingContext); + this.codegenAnnotator.setBindingTrace(bindingTrace); this.codegenAnnotator.setFiles(listOfJetFile); intrinsics.init(); @@ -108,6 +111,10 @@ public class InjectorForJvmCodegen { public void destroy() { } + public BindingTrace getBindingTrace() { + return this.bindingTrace; + } + public GenerationState getGenerationState() { return this.generationState; } diff --git a/idea/src/org/jetbrains/jet/plugin/debugger/JetPositionManager.java b/idea/src/org/jetbrains/jet/plugin/debugger/JetPositionManager.java index 6e0a0a2dd5d..be52e686f4b 100644 --- a/idea/src/org/jetbrains/jet/plugin/debugger/JetPositionManager.java +++ b/idea/src/org/jetbrains/jet/plugin/debugger/JetPositionManager.java @@ -44,19 +44,22 @@ import org.jetbrains.jet.di.InjectorForJetTypeMapper; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.DelegatingBindingTrace; import org.jetbrains.jet.lang.resolve.java.JetFilesProvider; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.plugin.project.WholeProjectAnalyzerFacade; import java.util.*; +import static org.jetbrains.jet.codegen.context.CodegenBinding.*; + /** * @author yole * @author alex.tkachman */ public class JetPositionManager implements PositionManager { private final DebugProcess myDebugProcess; - private WeakHashMap> myTypeMappers = new WeakHashMap>(); + private final WeakHashMap> myTypeMappers = new WeakHashMap>(); public JetPositionManager(DebugProcess debugProcess) { myDebugProcess = debugProcess; @@ -142,7 +145,8 @@ public class JetPositionManager implements PositionManager { result.set(getJvmInternalNameForImpl(typeMapper, (JetClassOrObject) element)); } else if (element instanceof JetFunctionLiteralExpression) { - result.set(typeMapper.getCodegenAnnotator().classNameForAnonymousClass((JetFunctionLiteralExpression) element).getInternalName()); + result.set(classNameForAnonymousClass(typeMapper.bindingContext, + (JetFunctionLiteralExpression) element).getInternalName()); } else if (element instanceof JetNamedFunction) { PsiElement parent = PsiTreeUtil.getParentOfType(element, JetClassOrObject.class, JetFunctionLiteralExpression.class, JetNamedFunction.class); @@ -150,7 +154,8 @@ public class JetPositionManager implements PositionManager { result.set(getJvmInternalNameForImpl(typeMapper, (JetClassOrObject) parent)); } else if (parent instanceof JetFunctionLiteralExpression || parent instanceof JetNamedFunction) { - result.set(typeMapper.getCodegenAnnotator().classNameForAnonymousClass((JetElement) element).getInternalName()); + result.set(classNameForAnonymousClass(typeMapper.bindingContext, + (JetElement) element).getInternalName()); } } @@ -172,7 +177,7 @@ public class JetPositionManager implements PositionManager { } @Nullable - private String getJvmInternalNameForImpl(JetTypeMapper typeMapper, JetClassOrObject jetClass) { + private static String getJvmInternalNameForImpl(JetTypeMapper typeMapper, JetClassOrObject jetClass) { final ClassDescriptor classDescriptor = typeMapper.bindingContext.get(BindingContext.CLASS, jetClass); if (classDescriptor == null) { return null; @@ -199,7 +204,7 @@ public class JetPositionManager implements PositionManager { List namespaceFiles = JetFilesProvider.getInstance(file.getProject()).allNamespaceFiles().fun(file); - JetTypeMapper typeMapper = new InjectorForJetTypeMapper(analyzeExhaust.getBindingContext(), namespaceFiles).getJetTypeMapper(); + JetTypeMapper typeMapper = new InjectorForJetTypeMapper(new DelegatingBindingTrace(analyzeExhaust.getBindingContext()), namespaceFiles).getJetTypeMapper(); typeMapper.getCodegenAnnotator().init(); return new Result(typeMapper, PsiModificationTracker.MODIFICATION_COUNT); } diff --git a/idea/tests/org/jetbrains/jet/plugin/debugger/JetPositionManagerTest.java b/idea/tests/org/jetbrains/jet/plugin/debugger/JetPositionManagerTest.java index 61b32ce4d6f..70c93c35bd5 100644 --- a/idea/tests/org/jetbrains/jet/plugin/debugger/JetPositionManagerTest.java +++ b/idea/tests/org/jetbrains/jet/plugin/debugger/JetPositionManagerTest.java @@ -22,6 +22,7 @@ import org.jetbrains.jet.codegen.GenerationState; import org.jetbrains.jet.codegen.JetTypeMapper; import org.jetbrains.jet.di.InjectorForJetTypeMapper; import org.jetbrains.jet.lang.psi.JetFile; +import org.jetbrains.jet.lang.resolve.DelegatingBindingTrace; import org.jetbrains.jet.plugin.PluginTestCaseBase; import java.util.List; @@ -44,7 +45,7 @@ public class JetPositionManagerTest extends PositionManagerTestCase { JetPositionManager positionManager = (JetPositionManager) jetPositionManagerFactory.createPositionManager(process); assertNotNull(positionManager); - JetTypeMapper typeMapper = new InjectorForJetTypeMapper(state.getBindingContext(), files).getJetTypeMapper(); + JetTypeMapper typeMapper = new InjectorForJetTypeMapper(new DelegatingBindingTrace(state.getBindingContext()), files).getJetTypeMapper(); typeMapper.getCodegenAnnotator().init(); for (JetFile file : files) { positionManager.addTypeMapper(file, typeMapper); diff --git a/injector-generator/src/org/jetbrains/jet/di/AllInjectorsGenerator.java b/injector-generator/src/org/jetbrains/jet/di/AllInjectorsGenerator.java index e630747126d..96dd0d603b1 100644 --- a/injector-generator/src/org/jetbrains/jet/di/AllInjectorsGenerator.java +++ b/injector-generator/src/org/jetbrains/jet/di/AllInjectorsGenerator.java @@ -191,7 +191,9 @@ public class AllInjectorsGenerator { private static void generateInjectorForJvmCodegen() throws IOException { DependencyInjectorGenerator generator = new DependencyInjectorGenerator(false); - generator.addParameter(BindingContext.class); + generator.addPublicParameter(BindingTrace.class); + generator.addField(false, BindingContext.class, "bindingContext", + new GivenExpression("bindingTrace.getBindingContext()")); generator.addParameter(DiType.listOf(JetFile.class)); generator.addParameter(BuiltinToJavaTypesMapping.class); generator.addParameter(ClassBuilderMode.class); @@ -210,7 +212,9 @@ public class AllInjectorsGenerator { private static void generateInjectorForJetTypeMapper() throws IOException { DependencyInjectorGenerator generator = new DependencyInjectorGenerator(false); - generator.addParameter(BindingContext.class); + generator.addPublicParameter(BindingTrace.class); + generator.addField(false, BindingContext.class, "bindingContext", + new GivenExpression("bindingTrace.getBindingContext()")); generator.addParameter(DiType.listOf(JetFile.class)); generator.addPublicField(JetTypeMapper.class); generator.addField(BuiltinToJavaTypesMapping.ENABLED);