Refactoring: code duplication removed from constructor generators
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user