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.Name;
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.org.objectweb.asm.Type;
@@ -108,6 +109,7 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
@NotNull
private ClassDescriptor recordClassForFunction(
@NotNull JetElement element,
@NotNull FunctionDescriptor funDescriptor,
@NotNull Collection<JetType> supertypes,
@NotNull String name
@@ -115,7 +117,7 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
String simpleName = name.substring(name.lastIndexOf('/') + 1);
ClassDescriptorImpl classDescriptor = new ClassDescriptorImpl(
funDescriptor.getContainingDeclaration(), Name.special("<closure-" + simpleName + ">"), Modality.FINAL, supertypes,
SourceElement.NO_SOURCE
SourcePackage.toSourceElement(element)
);
classDescriptor.initialize(JetScope.EMPTY, Collections.<ConstructorDescriptor>emptySet(), null);
@@ -194,7 +196,7 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
JetPsiUtil.getElementTextWithContext(classObject));
String name = peekFromStack(nameStack) + JvmAbi.CLASS_OBJECT_SUFFIX;
recordClosure(classObject, classDescriptor, name);
recordClosure(classDescriptor, name);
pushClassDescriptor(classDescriptor);
nameStack.push(name);
@@ -216,7 +218,7 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
if (classDescriptor == null) return;
String name = getName(classDescriptor);
recordClosure(declaration, classDescriptor, name);
recordClosure(classDescriptor, name);
pushClassDescriptor(classDescriptor);
nameStack.push(name);
@@ -235,7 +237,7 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
if (classDescriptor == null) return;
String name = getName(classDescriptor);
recordClosure(klass, classDescriptor, name);
recordClosure(classDescriptor, name);
pushClassDescriptor(classDescriptor);
nameStack.push(name);
@@ -261,7 +263,7 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
}
String name = inventAnonymousClassName(expression.getObjectDeclaration());
recordClosure(expression.getObjectDeclaration(), classDescriptor, name);
recordClosure(classDescriptor, name);
pushClassDescriptor(classDescriptor);
nameStack.push(CodegenBinding.getAsmType(bindingContext, classDescriptor).getInternalName());
@@ -280,8 +282,8 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
String name = inventAnonymousClassName(expression);
Collection<JetType> supertypes = runtimeTypes.getSupertypesForClosure(functionDescriptor);
ClassDescriptor classDescriptor = recordClassForFunction(functionDescriptor, supertypes, name);
recordClosure(functionLiteral, classDescriptor, name);
ClassDescriptor classDescriptor = recordClassForFunction(functionLiteral, functionDescriptor, supertypes, name);
recordClosure(classDescriptor, name);
pushClassDescriptor(classDescriptor);
nameStack.push(name);
@@ -331,8 +333,8 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
runtimeTypes.getSupertypesForFunctionReference((FunctionDescriptor) referencedFunction.getResultingDescriptor());
String name = inventAnonymousClassName(expression);
ClassDescriptor classDescriptor = recordClassForFunction(functionDescriptor, supertypes, name);
recordClosure(expression, classDescriptor, name);
ClassDescriptor classDescriptor = recordClassForFunction(expression, functionDescriptor, supertypes, name);
recordClosure(classDescriptor, name);
pushClassDescriptor(classDescriptor);
nameStack.push(name);
@@ -342,12 +344,8 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
}
private void recordClosure(
@NotNull JetElement element,
@NotNull ClassDescriptor classDescriptor,
@NotNull String name
) {
CodegenBinding.recordClosure(bindingTrace, element, classDescriptor, getOuterClassDescriptor(), Type.getObjectType(name));
private void recordClosure(@NotNull ClassDescriptor classDescriptor, @NotNull String name) {
CodegenBinding.recordClosure(bindingTrace, classDescriptor, getOuterClassDescriptor(), Type.getObjectType(name));
}
@Override
@@ -382,8 +380,8 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
else {
String name = inventAnonymousClassName(function);
Collection<JetType> supertypes = runtimeTypes.getSupertypesForClosure(functionDescriptor);
ClassDescriptor classDescriptor = recordClassForFunction(functionDescriptor, supertypes, name);
recordClosure(function, classDescriptor, name);
ClassDescriptor classDescriptor = recordClassForFunction(function, functionDescriptor, supertypes, name);
recordClosure(classDescriptor, name);
pushClassDescriptor(classDescriptor);
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.Name;
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.util.slicedmap.BasicWritableSlice;
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.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.source.SourcePackage.toSourceElement;
@@ -151,40 +151,28 @@ public class CodegenBinding {
}
static void recordClosure(
@NotNull BindingTrace bindingTrace,
@NotNull JetElement element,
@NotNull BindingTrace trace,
@NotNull ClassDescriptor classDescriptor,
@Nullable ClassDescriptor enclosing,
@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;
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);
MutableClosure closure = new MutableClosure(classDescriptor, findSuperCall(trace.getBindingContext(), element), enclosing);
if (classDescriptor.isInner()) {
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
//TODO: we should understand that lambda/closure would be inlined and don't generate inner class record
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));
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);
}
@@ -285,28 +273,20 @@ public class CodegenBinding {
@NotNull BindingContext bindingContext,
@NotNull JetElement classOrObject
) {
if (!(classOrObject instanceof JetClassOrObject)) {
return null;
}
if (!(classOrObject instanceof JetClassOrObject)) return null;
if (classOrObject instanceof JetClass && ((JetClass) classOrObject).isTrait()) {
return null;
}
if (classOrObject instanceof JetClass && ((JetClass) classOrObject).isTrait()) return null;
for (JetDelegationSpecifier specifier : ((JetClassOrObject) classOrObject).getDelegationSpecifiers()) {
if (specifier instanceof JetDelegatorToSuperCall) {
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));
if (!(specifier instanceof JetDelegatorToSuperCall)) continue;
ClassifierDescriptor superClass = supertype.getConstructor().getDeclarationDescriptor();
if (superClass != null && !isInterface(superClass)) {
ResolvedCall<?> resolvedCall = getResolvedCall(specifier, bindingContext);
if (resolvedCall != null && resolvedCall.getResultingDescriptor() instanceof ConstructorDescriptor) {
//noinspection unchecked
return (ResolvedCall<ConstructorDescriptor>) resolvedCall;
}
}
ResolvedCall<?> resolvedCall = getResolvedCall(specifier, bindingContext);
if (resolvedCall == null) continue;
CallableDescriptor constructor = resolvedCall.getResultingDescriptor();
if (constructor instanceof ConstructorDescriptor && !isInterface(constructor.getContainingDeclaration())) {
//noinspection unchecked
return (ResolvedCall<ConstructorDescriptor>) resolvedCall;
}
}
@@ -27,6 +27,8 @@ import org.jetbrains.org.objectweb.asm.Type;
import java.util.*;
import static org.jetbrains.jet.codegen.JvmCodegenUtil.getDirectMember;
public final class MutableClosure implements CalculatedClosure {
private final ResolvedCall<ConstructorDescriptor> superCall;
@@ -40,13 +42,25 @@ public final class MutableClosure implements CalculatedClosure {
private List<Pair<String, Type>> recordedFields;
MutableClosure(
@NotNull ClassDescriptor classDescriptor,
@Nullable ResolvedCall<ConstructorDescriptor> superCall,
@Nullable ClassDescriptor enclosingClass,
@Nullable CallableDescriptor enclosingReceiverDescriptor
@Nullable ClassDescriptor enclosingClass
) {
this.superCall = superCall;
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
@@ -169,8 +169,9 @@ public class KotlinJavaFileStubProvider<T extends WithFileStubAndExtraDiagnostic
Map<JetClassOrObject, InnerKotlinClassLightClassData> innerClassesMap = ContainerUtil.newHashMap();
for (ClassDescriptor innerClassDescriptor : allInnerClasses) {
JetClassOrObject innerClass = (JetClassOrObject) descriptorToDeclaration(innerClassDescriptor);
if (innerClass == null) continue;
PsiElement declaration = descriptorToDeclaration(innerClassDescriptor);
if (!(declaration instanceof JetClassOrObject)) continue;
JetClassOrObject innerClass = (JetClassOrObject) declaration;
InnerKotlinClassLightClassData innerLightClassData = new InnerKotlinClassLightClassData(
predictClassFqName(bindingContext, innerClassDescriptor),