Refactoring: code duplication removed from constructor generators

This commit is contained in:
Mikhael Bogdanov
2013-03-13 12:05:07 +04:00
parent c8f3ecdce7
commit 001a27f802
4 changed files with 72 additions and 85 deletions
@@ -202,15 +202,6 @@ public class AsmUtil {
return NO_FLAG_PACKAGE_PRIVATE;
}
public static int getModalityAccessFlag(@NotNull MemberDescriptor descriptor) {
switch (descriptor.getModality()) {
case ABSTRACT: return ACC_ABSTRACT;
case FINAL: return ACC_FINAL;
case OPEN: return 0;
default: throw new UnsupportedOperationException("Unknown modality: " + descriptor.getModality());
}
}
public static int getDeprecatedAccessFlag(@NotNull MemberDescriptor descriptor) {
if (descriptor instanceof PropertyAccessorDescriptor) {
return KotlinBuiltIns.getInstance().isDeprecated(descriptor)
@@ -325,6 +316,7 @@ public class AsmUtil {
}
public static void genInitSingletonField(FieldInfo info, InstructionAdapter iv) {
assert info.isStatic();
genInitSingletonField(info.getOwnerType(), info.getFieldName(), info.getFieldType(), iv);
}
@@ -335,6 +327,16 @@ public class AsmUtil {
iv.putstatic(fieldOwnerType.getInternalName(), fieldName, fieldAsmType.getDescriptor());
}
public static int genAssignInstanceFieldFromParam(FieldInfo info, int index, InstructionAdapter iv) {
assert !info.isStatic();
Type fieldType = info.getFieldType();
iv.load(0, info.getOwnerType());//this
iv.load(index, fieldType); //param
iv.visitFieldInsn(PUTFIELD, info.getOwnerInternalName(), info.getFieldName(), fieldType.getDescriptor());
index += fieldType.getSize();
return index;
}
public static void genStringBuilderConstructor(InstructionAdapter v) {
v.visitTypeInsn(NEW, "java/lang/StringBuilder");
v.dup();
@@ -16,8 +16,9 @@
package org.jetbrains.jet.codegen;
import com.intellij.openapi.util.Pair;
import com.google.common.collect.Lists;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.asm4.MethodVisitor;
import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter;
@@ -29,6 +30,7 @@ import org.jetbrains.jet.codegen.context.CodegenContext;
import org.jetbrains.jet.codegen.signature.JvmMethodSignature;
import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.codegen.state.GenerationStateAware;
import org.jetbrains.jet.codegen.state.JetTypeMapper;
import org.jetbrains.jet.codegen.state.JetTypeMapperMode;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.JetDeclarationWithBody;
@@ -40,7 +42,6 @@ import org.jetbrains.jet.lang.resolve.java.JvmAbi;
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
import org.jetbrains.jet.lang.types.JetType;
import java.util.ArrayList;
import java.util.List;
import static org.jetbrains.asm4.Opcodes.*;
@@ -197,10 +198,11 @@ public class ClosureCodegen extends GenerationStateAware {
ClassBuilder cv,
CalculatedClosure closure
) {
ArrayList<Pair<String, Type>> args = new ArrayList<Pair<String, Type>>();
calculateConstructorParameters(args, state, closure);
Type[] argTypes = nameAnTypeListToTypeArray(args);
List<FieldInfo> args = calculateConstructorParameters(typeMapper, bindingContext, state, closure,
Type.getObjectType(name.getInternalName()));
Type[] argTypes = fieldListToTypeArray(args);
Method constructor = new Method("<init>", Type.VOID_TYPE, argTypes);
MethodVisitor mv = cv.newMethod(fun, ACC_PUBLIC, "<init>", constructor.getDescriptor(), null, new String[0]);
@@ -215,13 +217,8 @@ public class ClosureCodegen extends GenerationStateAware {
iv.invokespecial(funClass.getInternalName(), "<init>", "()V");
int k = 1;
for (int i = 0; i != argTypes.length; ++i) {
StackValue.local(0, OBJECT_TYPE).put(OBJECT_TYPE, iv);
Pair<String, Type> nameAndType = args.get(i);
Type type = nameAndType.second;
StackValue.local(k, type).put(type, iv);
k += type.getSize();
StackValue.field(type, name, nameAndType.first, false).store(type, iv);
for (FieldInfo fieldInfo : args) {
k = AsmUtil.genAssignInstanceFieldFromParam(fieldInfo, k, iv);
}
iv.visitInsn(RETURN);
@@ -231,19 +228,24 @@ public class ClosureCodegen extends GenerationStateAware {
return constructor;
}
private void calculateConstructorParameters(
List<Pair<String, Type>> args,
@NotNull
public static List<FieldInfo> calculateConstructorParameters(
@NotNull JetTypeMapper typeMapper,
@NotNull BindingContext bindingContext,
GenerationState state,
CalculatedClosure closure
CalculatedClosure closure,
Type ownerType
) {
List<FieldInfo> args = Lists.newArrayList();
ClassDescriptor captureThis = closure.getCaptureThis();
if (captureThis != null) {
Type type = typeMapper.mapType(captureThis);
args.add(new Pair<String, Type>(CAPTURED_THIS_FIELD, type));
args.add(FieldInfo.createForHiddenField(ownerType, type, CAPTURED_THIS_FIELD));
}
ClassifierDescriptor captureReceiver = closure.getCaptureReceiver();
if (captureReceiver != null) {
args.add(new Pair<String, Type>(CAPTURED_RECEIVER_FIELD, typeMapper.mapType(captureReceiver)));
args.add(FieldInfo.createForHiddenField(ownerType, typeMapper.mapType(captureReceiver), CAPTURED_RECEIVER_FIELD));
}
for (DeclarationDescriptor descriptor : closure.getCaptureVariables().keySet()) {
@@ -253,7 +255,7 @@ public class ClosureCodegen extends GenerationStateAware {
Type type = sharedVarType != null
? sharedVarType
: typeMapper.mapType((VariableDescriptor) descriptor);
args.add(new Pair<String, Type>("$" + descriptor.getName().getName(), type));
args.add(FieldInfo.createForHiddenField(ownerType, type, "$" + descriptor.getName().getName()));
}
else if (isLocalNamedFun(state.getBindingContext(), descriptor)) {
Type type =
@@ -261,18 +263,19 @@ public class ClosureCodegen extends GenerationStateAware {
(JetElement) BindingContextUtils.descriptorToDeclaration(bindingContext, descriptor))
.getAsmType();
args.add(new Pair<String, Type>("$" + descriptor.getName().getName(), type));
args.add(FieldInfo.createForHiddenField(ownerType, type, "$" + descriptor.getName().getName()));
}
else if (descriptor instanceof FunctionDescriptor) {
assert captureReceiver != null;
}
}
return args;
}
private static Type[] nameAnTypeListToTypeArray(List<Pair<String, Type>> args) {
private static Type[] fieldListToTypeArray(List<FieldInfo> args) {
Type[] argTypes = new Type[args.size()];
for (int i = 0; i != argTypes.length; ++i) {
argTypes[i] = args.get(i).second;
argTypes[i] = args.get(i).getFieldType();
}
return argTypes;
}
@@ -26,16 +26,44 @@ import org.jetbrains.jet.lang.resolve.java.JvmAbi;
public class FieldInfo {
@NotNull
public static FieldInfo createForSingleton(@NotNull ClassDescriptor fieldClassDescriptor, @NotNull JetTypeMapper typeMapper) {
ClassKind kind = fieldClassDescriptor.getKind();
if (kind != ClassKind.OBJECT && kind != ClassKind.CLASS_OBJECT && kind != ClassKind.ENUM_ENTRY) {
throw new UnsupportedOperationException();
}
Type fieldType = typeMapper.mapType(fieldClassDescriptor.getDefaultType());
ClassDescriptor ownerDescriptor = kind == ClassKind.OBJECT
? fieldClassDescriptor: DescriptorUtils.getParentOfType(fieldClassDescriptor, ClassDescriptor.class);
assert ownerDescriptor != null;
Type ownerType = typeMapper.mapType(ownerDescriptor.getDefaultType());
String fieldName = kind == ClassKind.ENUM_ENTRY
? fieldClassDescriptor.getName().getName()
: fieldClassDescriptor.getKind() == ClassKind.CLASS_OBJECT ? JvmAbi.CLASS_OBJECT_FIELD : JvmAbi.INSTANCE_FIELD;
return new FieldInfo(ownerType, fieldType, fieldName, true);
}
public static FieldInfo createForHiddenField(@NotNull Type owner, Type fieldType, String fieldName) {
return new FieldInfo(owner, fieldType, fieldName, false);
}
private final Type fieldType;
private final Type ownerType;
private final String fieldName;
private FieldInfo(@NotNull Type ownerType, @NotNull Type fieldType, @NotNull String fieldName) {
private final boolean isStatic;
private FieldInfo(@NotNull Type ownerType, @NotNull Type fieldType, @NotNull String fieldName, @NotNull boolean isStatic) {
this.ownerType = ownerType;
this.fieldType = fieldType;
this.fieldName = fieldName;
this.isStatic = isStatic;
}
@NotNull
@@ -59,23 +87,7 @@ public class FieldInfo {
}
@NotNull
public static FieldInfo createForSingleton(@NotNull ClassDescriptor fieldClassDescriptor, @NotNull JetTypeMapper typeMapper) {
ClassKind kind = fieldClassDescriptor.getKind();
if (kind != ClassKind.OBJECT && kind != ClassKind.CLASS_OBJECT && kind != ClassKind.ENUM_ENTRY) {
throw new UnsupportedOperationException();
}
Type fieldType = typeMapper.mapType(fieldClassDescriptor.getDefaultType());
ClassDescriptor ownerDescriptor = kind == ClassKind.OBJECT
? fieldClassDescriptor: DescriptorUtils.getParentOfType(fieldClassDescriptor, ClassDescriptor.class);
assert ownerDescriptor != null;
Type ownerType = typeMapper.mapType(ownerDescriptor.getDefaultType());
String fieldName = kind == ClassKind.ENUM_ENTRY
? fieldClassDescriptor.getName().getName()
: fieldClassDescriptor.getKind() == ClassKind.CLASS_OBJECT ? JvmAbi.CLASS_OBJECT_FIELD : JvmAbi.INSTANCE_FIELD;
return new FieldInfo(ownerType, fieldType, fieldName);
public boolean isStatic() {
return isStatic;
}
}
@@ -955,7 +955,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
ClassDescriptor fieldTypeDescriptor = hasClassObject ? descriptor.getClassObjectDescriptor() : descriptor;
assert fieldTypeDescriptor != null;
final FieldInfo info = FieldInfo.createForSingleton(fieldTypeDescriptor, typeMapper);
JetClassOrObject original = hasClassObject ? ((JetClass)myClass).getClassObject().getObjectDeclaration() : myClass;
JetClassOrObject original = hasClassObject ? ((JetClass) myClass).getClassObject().getObjectDeclaration() : myClass;
v.newField(original, ACC_PUBLIC | ACC_STATIC | ACC_FINAL, info.getFieldName(), info.getFieldType().getDescriptor(), null, null);
@@ -1012,8 +1012,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
return;
}
generatePrimaryConstructorImpl(constructorDescriptor, constructorContext, constructorMethod, callableMethod, hasCapturedThis,
closure, mv);
generatePrimaryConstructorImpl(constructorDescriptor, constructorContext, constructorMethod, callableMethod, closure, mv);
}
FunctionCodegen.generateConstructorWithoutParametersIfNeeded(state, callableMethod, constructorDescriptor, v);
@@ -1024,7 +1023,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
ConstructorContext constructorContext,
JvmMethodSignature constructorMethod,
CallableMethod callableMethod,
boolean hasCapturedThis,
MutableClosure closure,
MethodVisitor mv
) {
@@ -1051,39 +1049,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
generateDelegatorToConstructorCall(iv, codegen, constructorDescriptor, frameMap);
}
if (hasCapturedThis) {
Type type = typeMapper
.mapType(enclosingClassDescriptor(bindingContext, descriptor));
String interfaceDesc = type.getDescriptor();
iv.load(0, classAsmType);
iv.load(frameMap.getOuterThisIndex(), type);
iv.putfield(classname.getInternalName(), CAPTURED_THIS_FIELD, interfaceDesc);
}
if (closure != null) {
int k = hasCapturedThis ? 2 : 1;
String internalName = typeMapper.mapType(descriptor).getInternalName();
ClassifierDescriptor captureReceiver = closure.getCaptureReceiver();
if (captureReceiver != null) {
iv.load(0, OBJECT_TYPE);
Type asmType = typeMapper.mapType(captureReceiver.getDefaultType(), JetTypeMapperMode.IMPL);
iv.load(k, asmType);
iv.putfield(internalName, CAPTURED_RECEIVER_FIELD, asmType.getDescriptor());
k += asmType.getSize();
}
for (DeclarationDescriptor varDescr : closure.getCaptureVariables().keySet()) {
if (varDescr instanceof VariableDescriptor && !(varDescr instanceof PropertyDescriptor)) {
Type sharedVarType = typeMapper.getSharedVarType(varDescr);
if (sharedVarType == null) {
sharedVarType = typeMapper.mapType((VariableDescriptor) varDescr);
}
iv.load(0, OBJECT_TYPE);
iv.load(k, StackValue.refType(sharedVarType));
k += StackValue.refType(sharedVarType).getSize();
iv.putfield(internalName,
"$" + varDescr.getName(), sharedVarType.getDescriptor());
}
List<FieldInfo> argsFromClosure = ClosureCodegen.calculateConstructorParameters(typeMapper, bindingContext, state, closure, classAsmType);
int k = 1;
for (FieldInfo info : argsFromClosure) {
k = AsmUtil.genAssignInstanceFieldFromParam(info, k, iv);
}
}