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;
import com.google.common.collect.Lists;
import com.intellij.psi.PsiElement;
import com.intellij.util.ArrayUtil;
import kotlin.Function1;
import kotlin.Unit;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.codegen.binding.CalculatedClosure;
import org.jetbrains.jet.codegen.context.CodegenContext;
import org.jetbrains.jet.codegen.context.LocalLookup;
import org.jetbrains.jet.codegen.context.ClassContext;
import org.jetbrains.jet.codegen.signature.BothSignatureWriter;
import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.codegen.state.JetTypeMapper;
import org.jetbrains.jet.lang.descriptors.*;
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.DescriptorUtils;
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.org.objectweb.asm.Opcodes.*;
public class ClosureCodegen extends ParentCodegenAware {
private final PsiElement fun;
public class ClosureCodegen extends MemberCodegen<JetElement> {
private final FunctionDescriptor funDescriptor;
private final ClassDescriptor classDescriptor;
private final SamType samType;
private final JetType superClassType;
private final List<JetType> superInterfaceTypes;
private final CodegenContext context;
private final FunctionGenerationStrategy strategy;
private final CalculatedClosure closure;
private final Type asmType;
@@ -69,28 +66,28 @@ public class ClosureCodegen extends ParentCodegenAware {
private final KotlinSyntheticClass.Kind syntheticClassKind;
private Method constructor;
private Type superClassAsmType;
public ClosureCodegen(
@NotNull GenerationState state,
@NotNull PsiElement fun,
@NotNull JetElement element,
@NotNull FunctionDescriptor funDescriptor,
@Nullable SamType samType,
@NotNull CodegenContext parentContext,
@NotNull ClassContext context,
@NotNull KotlinSyntheticClass.Kind syntheticClassKind,
@NotNull LocalLookup localLookup,
@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.samType = samType;
this.context = parentContext.intoClosure(funDescriptor, localLookup, typeMapper);
this.syntheticClassKind = syntheticClassKind;
this.strategy = strategy;
this.classDescriptor = anonymousClassForFunction(bindingContext, funDescriptor);
this.classDescriptor = context.getContextDescriptor();
if (samType == null) {
this.superInterfaceTypes = new ArrayList<JetType>();
@@ -118,28 +115,19 @@ public class ClosureCodegen extends ParentCodegenAware {
this.closure = bindingContext.get(CLOSURE, classDescriptor);
assert closure != null : "Closure must be calculated for class: " + classDescriptor;
this.asmType = asmTypeForAnonymousClass(bindingContext, funDescriptor);
this.asmType = asmType;
visibilityFlag = AsmUtil.getVisibilityAccessFlagForAnonymous(classDescriptor);
}
public void gen() {
ClassBuilder cv = state.getFactory().newVisitor(OtherOrigin(fun, funDescriptor), asmType, fun.getContainingFile());
FunctionDescriptor erasedInterfaceFunction;
if (samType == null) {
erasedInterfaceFunction = getErasedInvokeFunction(funDescriptor);
}
else {
erasedInterfaceFunction = samType.getAbstractMethod().getOriginal();
}
@Override
protected void generateDeclaration() {
BothSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.CLASS);
if (samType != null) {
typeMapper.writeFormalTypeParameters(samType.getType().getConstructor().getParameters(), sw);
}
sw.writeSuperclass();
Type superClassAsmType = typeMapper.mapSupertype(superClassType, sw);
superClassAsmType = typeMapper.mapSupertype(superClassType, sw);
sw.writeSuperclassEnd();
String[] superInterfaceAsmTypes = new String[superInterfaceTypes.size()];
for (int i = 0; i < superInterfaceTypes.size(); i++) {
@@ -149,29 +137,39 @@ public class ClosureCodegen extends ParentCodegenAware {
sw.writeInterfaceEnd();
}
cv.defineClass(fun,
V1_6,
ACC_FINAL | ACC_SUPER | visibilityFlag,
asmType.getInternalName(),
sw.makeJavaGenericSignature(),
superClassAsmType.getInternalName(),
superInterfaceAsmTypes
v.defineClass(element,
V1_6,
ACC_FINAL | ACC_SUPER | visibilityFlag,
asmType.getInternalName(),
sw.makeJavaGenericSignature(),
superClassAsmType.getInternalName(),
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 =
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());
fc.generateMethod(OtherOrigin(fun, funDescriptor), jvmMethodSignature, funDescriptor, strategy);
functionCodegen.generateMethod(OtherOrigin(element, funDescriptor), jvmMethodSignature, funDescriptor, strategy);
//TODO: rewrite cause ugly hack
if (samType != null) {
SimpleFunctionDescriptorImpl descriptorForBridges = SimpleFunctionDescriptorImpl
.create(funDescriptor.getContainingDeclaration(), funDescriptor.getAnnotations(), erasedInterfaceFunction.getName(),
.create(funDescriptor.getContainingDeclaration(), funDescriptor.getAnnotations(),
erasedInterfaceFunction.getName(),
CallableMemberDescriptor.Kind.DECLARATION, funDescriptor.getSource());
descriptorForBridges
@@ -180,27 +178,35 @@ public class ClosureCodegen extends ParentCodegenAware {
erasedInterfaceFunction.getVisibility());
descriptorForBridges.addOverriddenDescriptor(erasedInterfaceFunction);
fc.generateBridges(descriptorForBridges);
functionCodegen.generateBridges(descriptorForBridges);
}
this.constructor = generateConstructor(cv, superClassAsmType);
this.constructor = generateConstructor(superClassAsmType);
if (isConst(closure)) {
generateConstInstance(cv);
generateConstInstance();
}
genClosureFields(closure, cv, typeMapper);
genClosureFields(closure, v, typeMapper);
fc.generateDefaultIfNeeded(context.intoFunction(funDescriptor),
typeMapper.mapSignature(funDescriptor),
funDescriptor,
context.getContextKind(),
DefaultParameterValueLoader.DEFAULT,
null);
functionCodegen.generateDefaultIfNeeded(context.intoFunction(funDescriptor),
typeMapper.mapSignature(funDescriptor),
funDescriptor,
context.getContextKind(),
DefaultParameterValueLoader.DEFAULT,
null);
}
@Override
protected void generateKotlinAnnotation() {
writeKotlinSyntheticClassAnnotation(v, syntheticClassKind);
}
AsmUtil.writeOuterClassAndEnclosingMethod(classDescriptor, funDescriptor, typeMapper, cv);
cv.done();
@Override
protected void done() {
AsmUtil.writeOuterClassAndEnclosingMethod(classDescriptor, funDescriptor, typeMapper, v);
v.done();
super.done();
}
@NotNull
@@ -224,11 +230,11 @@ public class ClosureCodegen extends ParentCodegenAware {
}
private void generateConstInstance(@NotNull ClassBuilder cv) {
MethodVisitor mv = cv.newMethod(OtherOrigin(fun, funDescriptor), ACC_STATIC | ACC_SYNTHETIC, "<clinit>", "()V", null, ArrayUtil.EMPTY_STRING_ARRAY);
private void generateConstInstance() {
MethodVisitor mv = v.newMethod(OtherOrigin(element, funDescriptor), ACC_STATIC | ACC_SYNTHETIC, "<clinit>", "()V", null, ArrayUtil.EMPTY_STRING_ARRAY);
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) {
mv.visitCode();
@@ -237,15 +243,15 @@ public class ClosureCodegen extends ParentCodegenAware {
iv.invokespecial(asmType.getInternalName(), "<init>", "()V", false);
iv.putstatic(asmType.getInternalName(), JvmAbi.INSTANCE_FIELD, asmType.getDescriptor());
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;
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;
@@ -274,17 +280,17 @@ public class ClosureCodegen extends ParentCodegenAware {
iv.areturn(bridge.getReturnType());
FunctionCodegen.endVisit(mv, "bridge", fun);
FunctionCodegen.endVisit(mv, "bridge", element);
}
@NotNull
private Method generateConstructor(@NotNull ClassBuilder cv, @NotNull Type superClassAsmType) {
private Method generateConstructor(@NotNull Type superClassAsmType) {
List<FieldInfo> args = calculateConstructorParameters(typeMapper, closure, asmType);
Type[] argTypes = fieldListToTypeArray(args);
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);
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode();
@@ -300,7 +306,7 @@ public class ClosureCodegen extends ParentCodegenAware {
iv.visitInsn(RETURN);
FunctionCodegen.endVisit(iv, "constructor", fun);
FunctionCodegen.endVisit(iv, "constructor", element);
}
return constructor;
}
@@ -352,11 +358,11 @@ public class ClosureCodegen extends ParentCodegenAware {
}
@NotNull
public static FunctionDescriptor getErasedInvokeFunction(@NotNull FunctionDescriptor funDescriptor) {
int arity = funDescriptor.getValueParameters().size();
ClassDescriptor funClass = funDescriptor.getExtensionReceiverParameter() == null
public static FunctionDescriptor getErasedInvokeFunction(@NotNull FunctionDescriptor elementDescriptor) {
int arity = elementDescriptor.getValueParameters().size();
ClassDescriptor elementClass = elementDescriptor.getExtensionReceiverParameter() == null
? KotlinBuiltIns.getInstance().getFunction(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
private StackValue genClosure(
@NotNull PsiElement declaration,
@NotNull JetElement declaration,
@NotNull FunctionDescriptor descriptor,
@NotNull FunctionGenerationStrategy strategy,
@Nullable SamType samType,
@NotNull KotlinSyntheticClass.Kind kind
) {
boolean wereReifiedMarkers = parentCodegen.wereReifierMarkers();
parentCodegen.setWereReifierMarkers(false);
Type asmType = asmTypeForAnonymousClass(bindingContext, descriptor);
ClassBuilder cv = state.getFactory().newVisitor(OtherOrigin(declaration, descriptor), asmType, declaration.getContainingFile());
ClassContext closureContext = context.intoClosure(descriptor, this, typeMapper);
ClosureCodegen closureCodegen = new ClosureCodegen(
state, declaration, descriptor, samType, context, kind, this,
strategy, parentCodegen
state, declaration, descriptor, samType, closureContext, kind,
strategy, parentCodegen, cv, asmType
);
closureCodegen.gen();
if (parentCodegen.wereReifierMarkers()) {
closureCodegen.generate();
if (closureCodegen.wereReifierMarkers()) {
ReifiedTypeInliner.putNeedClassReificationMarker(v);
}
if (wereReifiedMarkers) {
parentCodegen.setWereReifierMarkers(true);
}
return closureCodegen.putInstanceOnStack(this);
}
@@ -21,42 +21,21 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.codegen.OwnerKind;
import org.jetbrains.jet.codegen.state.JetTypeMapper;
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 CodegenContext {
private final ClassDescriptor classDescriptor;
class ClosureContext extends ClassContext {
public ClosureContext(
@NotNull JetTypeMapper typeMapper,
@NotNull FunctionDescriptor contextDescriptor,
@NotNull ClassDescriptor classDescriptor,
@Nullable CodegenContext parentContext,
@Nullable LocalLookup localLookup
) {
//noinspection SuspiciousMethodCalls
super(contextDescriptor, OwnerKind.IMPLEMENTATION, parentContext,
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;
super(typeMapper, classDescriptor, OwnerKind.IMPLEMENTATION, parentContext, localLookup);
}
@Override
public String toString() {
return "Closure: " + classDescriptor;
return "Closure: " + getContextDescriptor();
}
}
@@ -187,13 +187,13 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
}
@NotNull
public CodegenContext intoClosure(
public ClassContext intoClosure(
@NotNull FunctionDescriptor funDescriptor,
@NotNull LocalLookup localLookup,
@NotNull JetTypeMapper typeMapper
) {
ClassDescriptor classDescriptor = anonymousClassForFunction(typeMapper.getBindingContext(), funDescriptor);
return new ClosureContext(typeMapper, funDescriptor, classDescriptor, this, localLookup);
return new ClosureContext(typeMapper, classDescriptor, this, localLookup);
}
@Nullable