Got rid of hack with stashing wereReified

1. Made ClosureCodegen extending MemberCodegen
2. Made ClosureContext extending ClassContext
This commit is contained in:
Denis Zharkov
2014-11-24 18:16:00 +04:00
parent ca27be87cc
commit 538a2172e5
4 changed files with 86 additions and 102 deletions
@@ -17,20 +17,19 @@
package org.jetbrains.jet.codegen; package org.jetbrains.jet.codegen;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.intellij.psi.PsiElement;
import com.intellij.util.ArrayUtil; import com.intellij.util.ArrayUtil;
import kotlin.Function1; import kotlin.Function1;
import kotlin.Unit; import kotlin.Unit;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.codegen.binding.CalculatedClosure; import org.jetbrains.jet.codegen.binding.CalculatedClosure;
import org.jetbrains.jet.codegen.context.CodegenContext; import org.jetbrains.jet.codegen.context.ClassContext;
import org.jetbrains.jet.codegen.context.LocalLookup;
import org.jetbrains.jet.codegen.signature.BothSignatureWriter; import org.jetbrains.jet.codegen.signature.BothSignatureWriter;
import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.codegen.state.JetTypeMapper; import org.jetbrains.jet.codegen.state.JetTypeMapper;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl; import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl;
import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.java.JvmAbi; import org.jetbrains.jet.lang.resolve.java.JvmAbi;
@@ -54,14 +53,12 @@ import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.KotlinSynth
import static org.jetbrains.jet.lang.resolve.java.diagnostics.DiagnosticsPackage.OtherOrigin; import static org.jetbrains.jet.lang.resolve.java.diagnostics.DiagnosticsPackage.OtherOrigin;
import static org.jetbrains.org.objectweb.asm.Opcodes.*; import static org.jetbrains.org.objectweb.asm.Opcodes.*;
public class ClosureCodegen extends ParentCodegenAware { public class ClosureCodegen extends MemberCodegen<JetElement> {
private final PsiElement fun;
private final FunctionDescriptor funDescriptor; private final FunctionDescriptor funDescriptor;
private final ClassDescriptor classDescriptor; private final ClassDescriptor classDescriptor;
private final SamType samType; private final SamType samType;
private final JetType superClassType; private final JetType superClassType;
private final List<JetType> superInterfaceTypes; private final List<JetType> superInterfaceTypes;
private final CodegenContext context;
private final FunctionGenerationStrategy strategy; private final FunctionGenerationStrategy strategy;
private final CalculatedClosure closure; private final CalculatedClosure closure;
private final Type asmType; private final Type asmType;
@@ -69,28 +66,28 @@ public class ClosureCodegen extends ParentCodegenAware {
private final KotlinSyntheticClass.Kind syntheticClassKind; private final KotlinSyntheticClass.Kind syntheticClassKind;
private Method constructor; private Method constructor;
private Type superClassAsmType;
public ClosureCodegen( public ClosureCodegen(
@NotNull GenerationState state, @NotNull GenerationState state,
@NotNull PsiElement fun, @NotNull JetElement element,
@NotNull FunctionDescriptor funDescriptor, @NotNull FunctionDescriptor funDescriptor,
@Nullable SamType samType, @Nullable SamType samType,
@NotNull CodegenContext parentContext, @NotNull ClassContext context,
@NotNull KotlinSyntheticClass.Kind syntheticClassKind, @NotNull KotlinSyntheticClass.Kind syntheticClassKind,
@NotNull LocalLookup localLookup,
@NotNull FunctionGenerationStrategy strategy, @NotNull FunctionGenerationStrategy strategy,
@Nullable MemberCodegen<?> parentCodegen @Nullable MemberCodegen<?> parentCodegen,
@NotNull ClassBuilder classBuilder,
@NotNull Type asmType
) { ) {
super(state, parentCodegen); super(state, parentCodegen, context, element, classBuilder);
this.fun = fun;
this.funDescriptor = funDescriptor; this.funDescriptor = funDescriptor;
this.samType = samType; this.samType = samType;
this.context = parentContext.intoClosure(funDescriptor, localLookup, typeMapper);
this.syntheticClassKind = syntheticClassKind; this.syntheticClassKind = syntheticClassKind;
this.strategy = strategy; this.strategy = strategy;
this.classDescriptor = anonymousClassForFunction(bindingContext, funDescriptor); this.classDescriptor = context.getContextDescriptor();
if (samType == null) { if (samType == null) {
this.superInterfaceTypes = new ArrayList<JetType>(); this.superInterfaceTypes = new ArrayList<JetType>();
@@ -118,28 +115,19 @@ public class ClosureCodegen extends ParentCodegenAware {
this.closure = bindingContext.get(CLOSURE, classDescriptor); this.closure = bindingContext.get(CLOSURE, classDescriptor);
assert closure != null : "Closure must be calculated for class: " + classDescriptor; assert closure != null : "Closure must be calculated for class: " + classDescriptor;
this.asmType = asmTypeForAnonymousClass(bindingContext, funDescriptor); this.asmType = asmType;
visibilityFlag = AsmUtil.getVisibilityAccessFlagForAnonymous(classDescriptor); visibilityFlag = AsmUtil.getVisibilityAccessFlagForAnonymous(classDescriptor);
} }
public void gen() { @Override
ClassBuilder cv = state.getFactory().newVisitor(OtherOrigin(fun, funDescriptor), asmType, fun.getContainingFile()); protected void generateDeclaration() {
FunctionDescriptor erasedInterfaceFunction;
if (samType == null) {
erasedInterfaceFunction = getErasedInvokeFunction(funDescriptor);
}
else {
erasedInterfaceFunction = samType.getAbstractMethod().getOriginal();
}
BothSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.CLASS); BothSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.CLASS);
if (samType != null) { if (samType != null) {
typeMapper.writeFormalTypeParameters(samType.getType().getConstructor().getParameters(), sw); typeMapper.writeFormalTypeParameters(samType.getType().getConstructor().getParameters(), sw);
} }
sw.writeSuperclass(); sw.writeSuperclass();
Type superClassAsmType = typeMapper.mapSupertype(superClassType, sw); superClassAsmType = typeMapper.mapSupertype(superClassType, sw);
sw.writeSuperclassEnd(); sw.writeSuperclassEnd();
String[] superInterfaceAsmTypes = new String[superInterfaceTypes.size()]; String[] superInterfaceAsmTypes = new String[superInterfaceTypes.size()];
for (int i = 0; i < superInterfaceTypes.size(); i++) { for (int i = 0; i < superInterfaceTypes.size(); i++) {
@@ -149,29 +137,39 @@ public class ClosureCodegen extends ParentCodegenAware {
sw.writeInterfaceEnd(); sw.writeInterfaceEnd();
} }
cv.defineClass(fun, v.defineClass(element,
V1_6, V1_6,
ACC_FINAL | ACC_SUPER | visibilityFlag, ACC_FINAL | ACC_SUPER | visibilityFlag,
asmType.getInternalName(), asmType.getInternalName(),
sw.makeJavaGenericSignature(), sw.makeJavaGenericSignature(),
superClassAsmType.getInternalName(), superClassAsmType.getInternalName(),
superInterfaceAsmTypes superInterfaceAsmTypes
); );
cv.visitSource(fun.getContainingFile().getName(), null); v.visitSource(element.getContainingFile().getName(), null);
writeKotlinSyntheticClassAnnotation(cv, syntheticClassKind); }
@Override
protected void generateBody() {
FunctionDescriptor erasedInterfaceFunction;
if (samType == null) {
erasedInterfaceFunction = getErasedInvokeFunction(funDescriptor);
}
else {
erasedInterfaceFunction = samType.getAbstractMethod().getOriginal();
}
JvmMethodSignature jvmMethodSignature = JvmMethodSignature jvmMethodSignature =
typeMapper.mapSignature(funDescriptor).replaceName(erasedInterfaceFunction.getName().toString()); typeMapper.mapSignature(funDescriptor).replaceName(erasedInterfaceFunction.getName().toString());
generateBridge(cv, typeMapper.mapSignature(erasedInterfaceFunction).getAsmMethod(), jvmMethodSignature.getAsmMethod()); generateBridge(typeMapper.mapSignature(erasedInterfaceFunction).getAsmMethod(), jvmMethodSignature.getAsmMethod());
FunctionCodegen fc = new FunctionCodegen(context, cv, state, getParentCodegen()); functionCodegen.generateMethod(OtherOrigin(element, funDescriptor), jvmMethodSignature, funDescriptor, strategy);
fc.generateMethod(OtherOrigin(fun, funDescriptor), jvmMethodSignature, funDescriptor, strategy);
//TODO: rewrite cause ugly hack //TODO: rewrite cause ugly hack
if (samType != null) { if (samType != null) {
SimpleFunctionDescriptorImpl descriptorForBridges = SimpleFunctionDescriptorImpl SimpleFunctionDescriptorImpl descriptorForBridges = SimpleFunctionDescriptorImpl
.create(funDescriptor.getContainingDeclaration(), funDescriptor.getAnnotations(), erasedInterfaceFunction.getName(), .create(funDescriptor.getContainingDeclaration(), funDescriptor.getAnnotations(),
erasedInterfaceFunction.getName(),
CallableMemberDescriptor.Kind.DECLARATION, funDescriptor.getSource()); CallableMemberDescriptor.Kind.DECLARATION, funDescriptor.getSource());
descriptorForBridges descriptorForBridges
@@ -180,27 +178,35 @@ public class ClosureCodegen extends ParentCodegenAware {
erasedInterfaceFunction.getVisibility()); erasedInterfaceFunction.getVisibility());
descriptorForBridges.addOverriddenDescriptor(erasedInterfaceFunction); descriptorForBridges.addOverriddenDescriptor(erasedInterfaceFunction);
fc.generateBridges(descriptorForBridges); functionCodegen.generateBridges(descriptorForBridges);
} }
this.constructor = generateConstructor(cv, superClassAsmType); this.constructor = generateConstructor(superClassAsmType);
if (isConst(closure)) { if (isConst(closure)) {
generateConstInstance(cv); generateConstInstance();
} }
genClosureFields(closure, cv, typeMapper); genClosureFields(closure, v, typeMapper);
fc.generateDefaultIfNeeded(context.intoFunction(funDescriptor), functionCodegen.generateDefaultIfNeeded(context.intoFunction(funDescriptor),
typeMapper.mapSignature(funDescriptor), typeMapper.mapSignature(funDescriptor),
funDescriptor, funDescriptor,
context.getContextKind(), context.getContextKind(),
DefaultParameterValueLoader.DEFAULT, DefaultParameterValueLoader.DEFAULT,
null); null);
}
@Override
protected void generateKotlinAnnotation() {
writeKotlinSyntheticClassAnnotation(v, syntheticClassKind);
}
AsmUtil.writeOuterClassAndEnclosingMethod(classDescriptor, funDescriptor, typeMapper, cv); @Override
cv.done(); protected void done() {
AsmUtil.writeOuterClassAndEnclosingMethod(classDescriptor, funDescriptor, typeMapper, v);
v.done();
super.done();
} }
@NotNull @NotNull
@@ -224,11 +230,11 @@ public class ClosureCodegen extends ParentCodegenAware {
} }
private void generateConstInstance(@NotNull ClassBuilder cv) { private void generateConstInstance() {
MethodVisitor mv = cv.newMethod(OtherOrigin(fun, funDescriptor), ACC_STATIC | ACC_SYNTHETIC, "<clinit>", "()V", null, ArrayUtil.EMPTY_STRING_ARRAY); MethodVisitor mv = v.newMethod(OtherOrigin(element, funDescriptor), ACC_STATIC | ACC_SYNTHETIC, "<clinit>", "()V", null, ArrayUtil.EMPTY_STRING_ARRAY);
InstructionAdapter iv = new InstructionAdapter(mv); InstructionAdapter iv = new InstructionAdapter(mv);
cv.newField(OtherOrigin(fun, funDescriptor), ACC_STATIC | ACC_FINAL | ACC_PUBLIC, JvmAbi.INSTANCE_FIELD, asmType.getDescriptor(), null, null); v.newField(OtherOrigin(element, funDescriptor), ACC_STATIC | ACC_FINAL | ACC_PUBLIC, JvmAbi.INSTANCE_FIELD, asmType.getDescriptor(), null, null);
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) { if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode(); mv.visitCode();
@@ -237,15 +243,15 @@ public class ClosureCodegen extends ParentCodegenAware {
iv.invokespecial(asmType.getInternalName(), "<init>", "()V", false); iv.invokespecial(asmType.getInternalName(), "<init>", "()V", false);
iv.putstatic(asmType.getInternalName(), JvmAbi.INSTANCE_FIELD, asmType.getDescriptor()); iv.putstatic(asmType.getInternalName(), JvmAbi.INSTANCE_FIELD, asmType.getDescriptor());
mv.visitInsn(RETURN); mv.visitInsn(RETURN);
FunctionCodegen.endVisit(mv, "<clinit>", fun); FunctionCodegen.endVisit(mv, "<clinit>", element);
} }
} }
private void generateBridge(@NotNull ClassBuilder cv, @NotNull Method bridge, @NotNull Method delegate) { private void generateBridge(@NotNull Method bridge, @NotNull Method delegate) {
if (bridge.equals(delegate)) return; if (bridge.equals(delegate)) return;
MethodVisitor mv = MethodVisitor mv =
cv.newMethod(OtherOrigin(fun, funDescriptor), ACC_PUBLIC | ACC_BRIDGE, bridge.getName(), bridge.getDescriptor(), null, ArrayUtil.EMPTY_STRING_ARRAY); v.newMethod(OtherOrigin(element, funDescriptor), ACC_PUBLIC | ACC_BRIDGE, bridge.getName(), bridge.getDescriptor(), null, ArrayUtil.EMPTY_STRING_ARRAY);
if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return; if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return;
@@ -274,17 +280,17 @@ public class ClosureCodegen extends ParentCodegenAware {
iv.areturn(bridge.getReturnType()); iv.areturn(bridge.getReturnType());
FunctionCodegen.endVisit(mv, "bridge", fun); FunctionCodegen.endVisit(mv, "bridge", element);
} }
@NotNull @NotNull
private Method generateConstructor(@NotNull ClassBuilder cv, @NotNull Type superClassAsmType) { private Method generateConstructor(@NotNull Type superClassAsmType) {
List<FieldInfo> args = calculateConstructorParameters(typeMapper, closure, asmType); List<FieldInfo> args = calculateConstructorParameters(typeMapper, closure, asmType);
Type[] argTypes = fieldListToTypeArray(args); Type[] argTypes = fieldListToTypeArray(args);
Method constructor = new Method("<init>", Type.VOID_TYPE, argTypes); Method constructor = new Method("<init>", Type.VOID_TYPE, argTypes);
MethodVisitor mv = cv.newMethod(OtherOrigin(fun, funDescriptor), visibilityFlag, "<init>", constructor.getDescriptor(), null, MethodVisitor mv = v.newMethod(OtherOrigin(element, funDescriptor), visibilityFlag, "<init>", constructor.getDescriptor(), null,
ArrayUtil.EMPTY_STRING_ARRAY); ArrayUtil.EMPTY_STRING_ARRAY);
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) { if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode(); mv.visitCode();
@@ -300,7 +306,7 @@ public class ClosureCodegen extends ParentCodegenAware {
iv.visitInsn(RETURN); iv.visitInsn(RETURN);
FunctionCodegen.endVisit(iv, "constructor", fun); FunctionCodegen.endVisit(iv, "constructor", element);
} }
return constructor; return constructor;
} }
@@ -352,11 +358,11 @@ public class ClosureCodegen extends ParentCodegenAware {
} }
@NotNull @NotNull
public static FunctionDescriptor getErasedInvokeFunction(@NotNull FunctionDescriptor funDescriptor) { public static FunctionDescriptor getErasedInvokeFunction(@NotNull FunctionDescriptor elementDescriptor) {
int arity = funDescriptor.getValueParameters().size(); int arity = elementDescriptor.getValueParameters().size();
ClassDescriptor funClass = funDescriptor.getExtensionReceiverParameter() == null ClassDescriptor elementClass = elementDescriptor.getExtensionReceiverParameter() == null
? KotlinBuiltIns.getInstance().getFunction(arity) ? KotlinBuiltIns.getInstance().getFunction(arity)
: KotlinBuiltIns.getInstance().getExtensionFunction(arity); : KotlinBuiltIns.getInstance().getExtensionFunction(arity);
return funClass.getDefaultType().getMemberScope().getFunctions(Name.identifier("invoke")).iterator().next(); return elementClass.getDefaultType().getMemberScope().getFunctions(Name.identifier("invoke")).iterator().next();
} }
} }
@@ -1387,27 +1387,26 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
@NotNull @NotNull
private StackValue genClosure( private StackValue genClosure(
@NotNull PsiElement declaration, @NotNull JetElement declaration,
@NotNull FunctionDescriptor descriptor, @NotNull FunctionDescriptor descriptor,
@NotNull FunctionGenerationStrategy strategy, @NotNull FunctionGenerationStrategy strategy,
@Nullable SamType samType, @Nullable SamType samType,
@NotNull KotlinSyntheticClass.Kind kind @NotNull KotlinSyntheticClass.Kind kind
) { ) {
boolean wereReifiedMarkers = parentCodegen.wereReifierMarkers(); Type asmType = asmTypeForAnonymousClass(bindingContext, descriptor);
parentCodegen.setWereReifierMarkers(false); ClassBuilder cv = state.getFactory().newVisitor(OtherOrigin(declaration, descriptor), asmType, declaration.getContainingFile());
ClassContext closureContext = context.intoClosure(descriptor, this, typeMapper);
ClosureCodegen closureCodegen = new ClosureCodegen( ClosureCodegen closureCodegen = new ClosureCodegen(
state, declaration, descriptor, samType, context, kind, this, state, declaration, descriptor, samType, closureContext, kind,
strategy, parentCodegen strategy, parentCodegen, cv, asmType
); );
closureCodegen.gen();
if (parentCodegen.wereReifierMarkers()) { closureCodegen.generate();
if (closureCodegen.wereReifierMarkers()) {
ReifiedTypeInliner.putNeedClassReificationMarker(v); ReifiedTypeInliner.putNeedClassReificationMarker(v);
} }
if (wereReifiedMarkers) {
parentCodegen.setWereReifierMarkers(true);
}
return closureCodegen.putInstanceOnStack(this); return closureCodegen.putInstanceOnStack(this);
} }
@@ -21,42 +21,21 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.codegen.OwnerKind; import org.jetbrains.jet.codegen.OwnerKind;
import org.jetbrains.jet.codegen.state.JetTypeMapper; import org.jetbrains.jet.codegen.state.JetTypeMapper;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.CLOSURE; class ClosureContext extends ClassContext {
class ClosureContext extends CodegenContext {
private final ClassDescriptor classDescriptor;
public ClosureContext( public ClosureContext(
@NotNull JetTypeMapper typeMapper, @NotNull JetTypeMapper typeMapper,
@NotNull FunctionDescriptor contextDescriptor,
@NotNull ClassDescriptor classDescriptor, @NotNull ClassDescriptor classDescriptor,
@Nullable CodegenContext parentContext, @Nullable CodegenContext parentContext,
@Nullable LocalLookup localLookup @Nullable LocalLookup localLookup
) { ) {
//noinspection SuspiciousMethodCalls //noinspection SuspiciousMethodCalls
super(contextDescriptor, OwnerKind.IMPLEMENTATION, parentContext, super(typeMapper, classDescriptor, OwnerKind.IMPLEMENTATION, parentContext, localLookup);
typeMapper.getBindingContext().get(CLOSURE, classDescriptor), classDescriptor, localLookup);
this.classDescriptor = classDescriptor;
initOuterExpression(typeMapper, classDescriptor);
}
@NotNull
@Override
public DeclarationDescriptor getContextDescriptor() {
return classDescriptor;
}
@Override
public boolean isStatic() {
return false;
} }
@Override @Override
public String toString() { public String toString() {
return "Closure: " + classDescriptor; return "Closure: " + getContextDescriptor();
} }
} }
@@ -187,13 +187,13 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
} }
@NotNull @NotNull
public CodegenContext intoClosure( public ClassContext intoClosure(
@NotNull FunctionDescriptor funDescriptor, @NotNull FunctionDescriptor funDescriptor,
@NotNull LocalLookup localLookup, @NotNull LocalLookup localLookup,
@NotNull JetTypeMapper typeMapper @NotNull JetTypeMapper typeMapper
) { ) {
ClassDescriptor classDescriptor = anonymousClassForFunction(typeMapper.getBindingContext(), funDescriptor); ClassDescriptor classDescriptor = anonymousClassForFunction(typeMapper.getBindingContext(), funDescriptor);
return new ClosureContext(typeMapper, funDescriptor, classDescriptor, this, localLookup); return new ClosureContext(typeMapper, classDescriptor, this, localLookup);
} }
@Nullable @Nullable