Refactor CodegenBinding

- store source element in synthetic descriptor for easier debugging and lesser
  amount of needed method parameters everywhere
- simplify methods which calculate necessary information for MutableClosure
This commit is contained in:
Alexander Udalov
2014-09-19 16:26:28 +04:00
parent 7d6da551d1
commit 7b374b9509
4 changed files with 57 additions and 64 deletions
@@ -50,6 +50,7 @@ import org.jetbrains.jet.lang.resolve.kotlin.PackagePartClassUtils;
import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.source.SourcePackage;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.org.objectweb.asm.Type; import org.jetbrains.org.objectweb.asm.Type;
@@ -108,6 +109,7 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
@NotNull @NotNull
private ClassDescriptor recordClassForFunction( private ClassDescriptor recordClassForFunction(
@NotNull JetElement element,
@NotNull FunctionDescriptor funDescriptor, @NotNull FunctionDescriptor funDescriptor,
@NotNull Collection<JetType> supertypes, @NotNull Collection<JetType> supertypes,
@NotNull String name @NotNull String name
@@ -115,7 +117,7 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
String simpleName = name.substring(name.lastIndexOf('/') + 1); String simpleName = name.substring(name.lastIndexOf('/') + 1);
ClassDescriptorImpl classDescriptor = new ClassDescriptorImpl( ClassDescriptorImpl classDescriptor = new ClassDescriptorImpl(
funDescriptor.getContainingDeclaration(), Name.special("<closure-" + simpleName + ">"), Modality.FINAL, supertypes, funDescriptor.getContainingDeclaration(), Name.special("<closure-" + simpleName + ">"), Modality.FINAL, supertypes,
SourceElement.NO_SOURCE SourcePackage.toSourceElement(element)
); );
classDescriptor.initialize(JetScope.EMPTY, Collections.<ConstructorDescriptor>emptySet(), null); classDescriptor.initialize(JetScope.EMPTY, Collections.<ConstructorDescriptor>emptySet(), null);
@@ -194,7 +196,7 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
JetPsiUtil.getElementTextWithContext(classObject)); JetPsiUtil.getElementTextWithContext(classObject));
String name = peekFromStack(nameStack) + JvmAbi.CLASS_OBJECT_SUFFIX; String name = peekFromStack(nameStack) + JvmAbi.CLASS_OBJECT_SUFFIX;
recordClosure(classObject, classDescriptor, name); recordClosure(classDescriptor, name);
pushClassDescriptor(classDescriptor); pushClassDescriptor(classDescriptor);
nameStack.push(name); nameStack.push(name);
@@ -216,7 +218,7 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
if (classDescriptor == null) return; if (classDescriptor == null) return;
String name = getName(classDescriptor); String name = getName(classDescriptor);
recordClosure(declaration, classDescriptor, name); recordClosure(classDescriptor, name);
pushClassDescriptor(classDescriptor); pushClassDescriptor(classDescriptor);
nameStack.push(name); nameStack.push(name);
@@ -235,7 +237,7 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
if (classDescriptor == null) return; if (classDescriptor == null) return;
String name = getName(classDescriptor); String name = getName(classDescriptor);
recordClosure(klass, classDescriptor, name); recordClosure(classDescriptor, name);
pushClassDescriptor(classDescriptor); pushClassDescriptor(classDescriptor);
nameStack.push(name); nameStack.push(name);
@@ -261,7 +263,7 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
} }
String name = inventAnonymousClassName(expression.getObjectDeclaration()); String name = inventAnonymousClassName(expression.getObjectDeclaration());
recordClosure(expression.getObjectDeclaration(), classDescriptor, name); recordClosure(classDescriptor, name);
pushClassDescriptor(classDescriptor); pushClassDescriptor(classDescriptor);
nameStack.push(CodegenBinding.getAsmType(bindingContext, classDescriptor).getInternalName()); nameStack.push(CodegenBinding.getAsmType(bindingContext, classDescriptor).getInternalName());
@@ -280,8 +282,8 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
String name = inventAnonymousClassName(expression); String name = inventAnonymousClassName(expression);
Collection<JetType> supertypes = runtimeTypes.getSupertypesForClosure(functionDescriptor); Collection<JetType> supertypes = runtimeTypes.getSupertypesForClosure(functionDescriptor);
ClassDescriptor classDescriptor = recordClassForFunction(functionDescriptor, supertypes, name); ClassDescriptor classDescriptor = recordClassForFunction(functionLiteral, functionDescriptor, supertypes, name);
recordClosure(functionLiteral, classDescriptor, name); recordClosure(classDescriptor, name);
pushClassDescriptor(classDescriptor); pushClassDescriptor(classDescriptor);
nameStack.push(name); nameStack.push(name);
@@ -331,8 +333,8 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
runtimeTypes.getSupertypesForFunctionReference((FunctionDescriptor) referencedFunction.getResultingDescriptor()); runtimeTypes.getSupertypesForFunctionReference((FunctionDescriptor) referencedFunction.getResultingDescriptor());
String name = inventAnonymousClassName(expression); String name = inventAnonymousClassName(expression);
ClassDescriptor classDescriptor = recordClassForFunction(functionDescriptor, supertypes, name); ClassDescriptor classDescriptor = recordClassForFunction(expression, functionDescriptor, supertypes, name);
recordClosure(expression, classDescriptor, name); recordClosure(classDescriptor, name);
pushClassDescriptor(classDescriptor); pushClassDescriptor(classDescriptor);
nameStack.push(name); nameStack.push(name);
@@ -342,12 +344,8 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
} }
private void recordClosure( private void recordClosure(@NotNull ClassDescriptor classDescriptor, @NotNull String name) {
@NotNull JetElement element, CodegenBinding.recordClosure(bindingTrace, classDescriptor, getOuterClassDescriptor(), Type.getObjectType(name));
@NotNull ClassDescriptor classDescriptor,
@NotNull String name
) {
CodegenBinding.recordClosure(bindingTrace, element, classDescriptor, getOuterClassDescriptor(), Type.getObjectType(name));
} }
@Override @Override
@@ -382,8 +380,8 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
else { else {
String name = inventAnonymousClassName(function); String name = inventAnonymousClassName(function);
Collection<JetType> supertypes = runtimeTypes.getSupertypesForClosure(functionDescriptor); Collection<JetType> supertypes = runtimeTypes.getSupertypesForClosure(functionDescriptor);
ClassDescriptor classDescriptor = recordClassForFunction(functionDescriptor, supertypes, name); ClassDescriptor classDescriptor = recordClassForFunction(function, functionDescriptor, supertypes, name);
recordClosure(function, classDescriptor, name); recordClosure(classDescriptor, name);
pushClassDescriptor(classDescriptor); pushClassDescriptor(classDescriptor);
nameStack.push(name); nameStack.push(name);
@@ -31,7 +31,6 @@ import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import org.jetbrains.jet.util.slicedmap.BasicWritableSlice; import org.jetbrains.jet.util.slicedmap.BasicWritableSlice;
import org.jetbrains.jet.util.slicedmap.Slices; import org.jetbrains.jet.util.slicedmap.Slices;
@@ -42,6 +41,7 @@ import java.util.*;
import static org.jetbrains.jet.codegen.JvmCodegenUtil.isInterface; import static org.jetbrains.jet.codegen.JvmCodegenUtil.isInterface;
import static org.jetbrains.jet.lang.resolve.BindingContext.*; import static org.jetbrains.jet.lang.resolve.BindingContext.*;
import static org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils.descriptorToDeclaration;
import static org.jetbrains.jet.lang.resolve.calls.callUtil.CallUtilPackage.getResolvedCall; import static org.jetbrains.jet.lang.resolve.calls.callUtil.CallUtilPackage.getResolvedCall;
import static org.jetbrains.jet.lang.resolve.source.SourcePackage.toSourceElement; import static org.jetbrains.jet.lang.resolve.source.SourcePackage.toSourceElement;
@@ -151,40 +151,28 @@ public class CodegenBinding {
} }
static void recordClosure( static void recordClosure(
@NotNull BindingTrace bindingTrace, @NotNull BindingTrace trace,
@NotNull JetElement element,
@NotNull ClassDescriptor classDescriptor, @NotNull ClassDescriptor classDescriptor,
@Nullable ClassDescriptor enclosing, @Nullable ClassDescriptor enclosing,
@NotNull Type asmType @NotNull Type asmType
) { ) {
ResolvedCall<ConstructorDescriptor> superCall = findSuperCall(bindingTrace.getBindingContext(), element); JetElement element = (JetElement) descriptorToDeclaration(classDescriptor);
assert element != null : "No source element for " + classDescriptor;
CallableDescriptor enclosingReceiver = null; MutableClosure closure = new MutableClosure(classDescriptor, findSuperCall(trace.getBindingContext(), element), enclosing);
if (classDescriptor.getContainingDeclaration() instanceof CallableDescriptor) {
enclosingReceiver = (CallableDescriptor) classDescriptor.getContainingDeclaration();
enclosingReceiver = enclosingReceiver instanceof PropertyAccessorDescriptor
? ((PropertyAccessorDescriptor) enclosingReceiver).getCorrespondingProperty()
: enclosingReceiver;
if (enclosingReceiver.getReceiverParameter() == null) {
enclosingReceiver = null;
}
}
MutableClosure closure = new MutableClosure(superCall, enclosing, enclosingReceiver);
assert PsiCodegenPredictor.checkPredictedNameFromPsi(classDescriptor, asmType);
bindingTrace.record(ASM_TYPE, classDescriptor, asmType);
bindingTrace.record(CLOSURE, classDescriptor, closure);
if (classDescriptor.isInner()) { if (classDescriptor.isInner()) {
closure.setCaptureThis(); closure.setCaptureThis();
} }
assert PsiCodegenPredictor.checkPredictedNameFromPsi(classDescriptor, asmType);
trace.record(ASM_TYPE, classDescriptor, asmType);
trace.record(CLOSURE, classDescriptor, closure);
//TEMPORARY EAT INNER CLASS INFO FOR FUNCTION LITERALS //TEMPORARY EAT INNER CLASS INFO FOR FUNCTION LITERALS
//TODO: we should understand that lambda/closure would be inlined and don't generate inner class record //TODO: we should understand that lambda/closure would be inlined and don't generate inner class record
if (enclosing != null && !(element instanceof JetFunctionLiteral)) { if (enclosing != null && !(element instanceof JetFunctionLiteral)) {
recordInnerClass(bindingTrace, enclosing, classDescriptor); recordInnerClass(trace, enclosing, classDescriptor);
} }
} }
@@ -214,7 +202,7 @@ public class CodegenBinding {
Collections.singleton(KotlinBuiltIns.getInstance().getAnyType()), toSourceElement(script)); Collections.singleton(KotlinBuiltIns.getInstance().getAnyType()), toSourceElement(script));
classDescriptor.initialize(JetScope.EMPTY, Collections.<ConstructorDescriptor>emptySet(), null); classDescriptor.initialize(JetScope.EMPTY, Collections.<ConstructorDescriptor>emptySet(), null);
recordClosure(trace, script, classDescriptor, null, asmType); recordClosure(trace, classDescriptor, null, asmType);
trace.record(CLASS_FOR_SCRIPT, descriptor, classDescriptor); trace.record(CLASS_FOR_SCRIPT, descriptor, classDescriptor);
} }
@@ -285,28 +273,20 @@ public class CodegenBinding {
@NotNull BindingContext bindingContext, @NotNull BindingContext bindingContext,
@NotNull JetElement classOrObject @NotNull JetElement classOrObject
) { ) {
if (!(classOrObject instanceof JetClassOrObject)) { if (!(classOrObject instanceof JetClassOrObject)) return null;
return null;
}
if (classOrObject instanceof JetClass && ((JetClass) classOrObject).isTrait()) { if (classOrObject instanceof JetClass && ((JetClass) classOrObject).isTrait()) return null;
return null;
}
for (JetDelegationSpecifier specifier : ((JetClassOrObject) classOrObject).getDelegationSpecifiers()) { for (JetDelegationSpecifier specifier : ((JetClassOrObject) classOrObject).getDelegationSpecifiers()) {
if (specifier instanceof JetDelegatorToSuperCall) { if (!(specifier instanceof JetDelegatorToSuperCall)) continue;
JetType supertype = bindingContext.get(TYPE, specifier.getTypeReference());
assert supertype != null : String.format(
"No type in binding context for \n---\n%s\n---\n", JetPsiUtil.getElementTextWithContext(specifier));
ClassifierDescriptor superClass = supertype.getConstructor().getDeclarationDescriptor(); ResolvedCall<?> resolvedCall = getResolvedCall(specifier, bindingContext);
if (superClass != null && !isInterface(superClass)) { if (resolvedCall == null) continue;
ResolvedCall<?> resolvedCall = getResolvedCall(specifier, bindingContext);
if (resolvedCall != null && resolvedCall.getResultingDescriptor() instanceof ConstructorDescriptor) { CallableDescriptor constructor = resolvedCall.getResultingDescriptor();
//noinspection unchecked if (constructor instanceof ConstructorDescriptor && !isInterface(constructor.getContainingDeclaration())) {
return (ResolvedCall<ConstructorDescriptor>) resolvedCall; //noinspection unchecked
} return (ResolvedCall<ConstructorDescriptor>) resolvedCall;
}
} }
} }
@@ -27,6 +27,8 @@ import org.jetbrains.org.objectweb.asm.Type;
import java.util.*; import java.util.*;
import static org.jetbrains.jet.codegen.JvmCodegenUtil.getDirectMember;
public final class MutableClosure implements CalculatedClosure { public final class MutableClosure implements CalculatedClosure {
private final ResolvedCall<ConstructorDescriptor> superCall; private final ResolvedCall<ConstructorDescriptor> superCall;
@@ -40,13 +42,25 @@ public final class MutableClosure implements CalculatedClosure {
private List<Pair<String, Type>> recordedFields; private List<Pair<String, Type>> recordedFields;
MutableClosure( MutableClosure(
@NotNull ClassDescriptor classDescriptor,
@Nullable ResolvedCall<ConstructorDescriptor> superCall, @Nullable ResolvedCall<ConstructorDescriptor> superCall,
@Nullable ClassDescriptor enclosingClass, @Nullable ClassDescriptor enclosingClass
@Nullable CallableDescriptor enclosingReceiverDescriptor
) { ) {
this.superCall = superCall;
this.enclosingClass = enclosingClass; this.enclosingClass = enclosingClass;
this.enclosingReceiverDescriptor = enclosingReceiverDescriptor; this.superCall = superCall;
this.enclosingReceiverDescriptor = enclosingExtensionMemberForClass(classDescriptor);
}
@Nullable
private static CallableDescriptor enclosingExtensionMemberForClass(@NotNull ClassDescriptor classDescriptor) {
DeclarationDescriptor classContainer = classDescriptor.getContainingDeclaration();
if (classContainer instanceof CallableMemberDescriptor) {
CallableMemberDescriptor member = getDirectMember((CallableMemberDescriptor) classContainer);
if (member.getReceiverParameter() != null) {
return member;
}
}
return null;
} }
@Nullable @Nullable
@@ -169,8 +169,9 @@ public class KotlinJavaFileStubProvider<T extends WithFileStubAndExtraDiagnostic
Map<JetClassOrObject, InnerKotlinClassLightClassData> innerClassesMap = ContainerUtil.newHashMap(); Map<JetClassOrObject, InnerKotlinClassLightClassData> innerClassesMap = ContainerUtil.newHashMap();
for (ClassDescriptor innerClassDescriptor : allInnerClasses) { for (ClassDescriptor innerClassDescriptor : allInnerClasses) {
JetClassOrObject innerClass = (JetClassOrObject) descriptorToDeclaration(innerClassDescriptor); PsiElement declaration = descriptorToDeclaration(innerClassDescriptor);
if (innerClass == null) continue; if (!(declaration instanceof JetClassOrObject)) continue;
JetClassOrObject innerClass = (JetClassOrObject) declaration;
InnerKotlinClassLightClassData innerLightClassData = new InnerKotlinClassLightClassData( InnerKotlinClassLightClassData innerLightClassData = new InnerKotlinClassLightClassData(
predictClassFqName(bindingContext, innerClassDescriptor), predictClassFqName(bindingContext, innerClassDescriptor),