Refactoring: code duplication removed from constructor generators
This commit is contained in:
@@ -202,15 +202,6 @@ public class AsmUtil {
|
|||||||
return NO_FLAG_PACKAGE_PRIVATE;
|
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) {
|
public static int getDeprecatedAccessFlag(@NotNull MemberDescriptor descriptor) {
|
||||||
if (descriptor instanceof PropertyAccessorDescriptor) {
|
if (descriptor instanceof PropertyAccessorDescriptor) {
|
||||||
return KotlinBuiltIns.getInstance().isDeprecated(descriptor)
|
return KotlinBuiltIns.getInstance().isDeprecated(descriptor)
|
||||||
@@ -325,6 +316,7 @@ public class AsmUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void genInitSingletonField(FieldInfo info, InstructionAdapter iv) {
|
public static void genInitSingletonField(FieldInfo info, InstructionAdapter iv) {
|
||||||
|
assert info.isStatic();
|
||||||
genInitSingletonField(info.getOwnerType(), info.getFieldName(), info.getFieldType(), iv);
|
genInitSingletonField(info.getOwnerType(), info.getFieldName(), info.getFieldType(), iv);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -335,6 +327,16 @@ public class AsmUtil {
|
|||||||
iv.putstatic(fieldOwnerType.getInternalName(), fieldName, fieldAsmType.getDescriptor());
|
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) {
|
public static void genStringBuilderConstructor(InstructionAdapter v) {
|
||||||
v.visitTypeInsn(NEW, "java/lang/StringBuilder");
|
v.visitTypeInsn(NEW, "java/lang/StringBuilder");
|
||||||
v.dup();
|
v.dup();
|
||||||
|
|||||||
@@ -16,8 +16,9 @@
|
|||||||
|
|
||||||
package org.jetbrains.jet.codegen;
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
import com.intellij.openapi.util.Pair;
|
import com.google.common.collect.Lists;
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.asm4.MethodVisitor;
|
import org.jetbrains.asm4.MethodVisitor;
|
||||||
import org.jetbrains.asm4.Type;
|
import org.jetbrains.asm4.Type;
|
||||||
import org.jetbrains.asm4.commons.InstructionAdapter;
|
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.signature.JvmMethodSignature;
|
||||||
import org.jetbrains.jet.codegen.state.GenerationState;
|
import org.jetbrains.jet.codegen.state.GenerationState;
|
||||||
import org.jetbrains.jet.codegen.state.GenerationStateAware;
|
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.codegen.state.JetTypeMapperMode;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.psi.JetDeclarationWithBody;
|
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.resolve.java.JvmClassName;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.jetbrains.asm4.Opcodes.*;
|
import static org.jetbrains.asm4.Opcodes.*;
|
||||||
@@ -197,10 +198,11 @@ public class ClosureCodegen extends GenerationStateAware {
|
|||||||
ClassBuilder cv,
|
ClassBuilder cv,
|
||||||
CalculatedClosure closure
|
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);
|
Method constructor = new Method("<init>", Type.VOID_TYPE, argTypes);
|
||||||
MethodVisitor mv = cv.newMethod(fun, ACC_PUBLIC, "<init>", constructor.getDescriptor(), null, new String[0]);
|
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");
|
iv.invokespecial(funClass.getInternalName(), "<init>", "()V");
|
||||||
|
|
||||||
int k = 1;
|
int k = 1;
|
||||||
for (int i = 0; i != argTypes.length; ++i) {
|
for (FieldInfo fieldInfo : args) {
|
||||||
StackValue.local(0, OBJECT_TYPE).put(OBJECT_TYPE, iv);
|
k = AsmUtil.genAssignInstanceFieldFromParam(fieldInfo, k, 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
iv.visitInsn(RETURN);
|
iv.visitInsn(RETURN);
|
||||||
@@ -231,19 +228,24 @@ public class ClosureCodegen extends GenerationStateAware {
|
|||||||
return constructor;
|
return constructor;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void calculateConstructorParameters(
|
@NotNull
|
||||||
List<Pair<String, Type>> args,
|
public static List<FieldInfo> calculateConstructorParameters(
|
||||||
|
@NotNull JetTypeMapper typeMapper,
|
||||||
|
@NotNull BindingContext bindingContext,
|
||||||
GenerationState state,
|
GenerationState state,
|
||||||
CalculatedClosure closure
|
CalculatedClosure closure,
|
||||||
|
Type ownerType
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
List<FieldInfo> args = Lists.newArrayList();
|
||||||
ClassDescriptor captureThis = closure.getCaptureThis();
|
ClassDescriptor captureThis = closure.getCaptureThis();
|
||||||
if (captureThis != null) {
|
if (captureThis != null) {
|
||||||
Type type = typeMapper.mapType(captureThis);
|
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();
|
ClassifierDescriptor captureReceiver = closure.getCaptureReceiver();
|
||||||
if (captureReceiver != null) {
|
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()) {
|
for (DeclarationDescriptor descriptor : closure.getCaptureVariables().keySet()) {
|
||||||
@@ -253,7 +255,7 @@ public class ClosureCodegen extends GenerationStateAware {
|
|||||||
Type type = sharedVarType != null
|
Type type = sharedVarType != null
|
||||||
? sharedVarType
|
? sharedVarType
|
||||||
: typeMapper.mapType((VariableDescriptor) descriptor);
|
: 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)) {
|
else if (isLocalNamedFun(state.getBindingContext(), descriptor)) {
|
||||||
Type type =
|
Type type =
|
||||||
@@ -261,18 +263,19 @@ public class ClosureCodegen extends GenerationStateAware {
|
|||||||
(JetElement) BindingContextUtils.descriptorToDeclaration(bindingContext, descriptor))
|
(JetElement) BindingContextUtils.descriptorToDeclaration(bindingContext, descriptor))
|
||||||
.getAsmType();
|
.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) {
|
else if (descriptor instanceof FunctionDescriptor) {
|
||||||
assert captureReceiver != null;
|
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()];
|
Type[] argTypes = new Type[args.size()];
|
||||||
for (int i = 0; i != argTypes.length; ++i) {
|
for (int i = 0; i != argTypes.length; ++i) {
|
||||||
argTypes[i] = args.get(i).second;
|
argTypes[i] = args.get(i).getFieldType();
|
||||||
}
|
}
|
||||||
return argTypes;
|
return argTypes;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,16 +26,44 @@ import org.jetbrains.jet.lang.resolve.java.JvmAbi;
|
|||||||
|
|
||||||
public class FieldInfo {
|
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 fieldType;
|
||||||
|
|
||||||
private final Type ownerType;
|
private final Type ownerType;
|
||||||
|
|
||||||
private final String fieldName;
|
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.ownerType = ownerType;
|
||||||
this.fieldType = fieldType;
|
this.fieldType = fieldType;
|
||||||
this.fieldName = fieldName;
|
this.fieldName = fieldName;
|
||||||
|
this.isStatic = isStatic;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -59,23 +87,7 @@ public class FieldInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static FieldInfo createForSingleton(@NotNull ClassDescriptor fieldClassDescriptor, @NotNull JetTypeMapper typeMapper) {
|
public boolean isStatic() {
|
||||||
ClassKind kind = fieldClassDescriptor.getKind();
|
return isStatic;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -955,7 +955,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
ClassDescriptor fieldTypeDescriptor = hasClassObject ? descriptor.getClassObjectDescriptor() : descriptor;
|
ClassDescriptor fieldTypeDescriptor = hasClassObject ? descriptor.getClassObjectDescriptor() : descriptor;
|
||||||
assert fieldTypeDescriptor != null;
|
assert fieldTypeDescriptor != null;
|
||||||
final FieldInfo info = FieldInfo.createForSingleton(fieldTypeDescriptor, typeMapper);
|
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);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
generatePrimaryConstructorImpl(constructorDescriptor, constructorContext, constructorMethod, callableMethod, hasCapturedThis,
|
generatePrimaryConstructorImpl(constructorDescriptor, constructorContext, constructorMethod, callableMethod, closure, mv);
|
||||||
closure, mv);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FunctionCodegen.generateConstructorWithoutParametersIfNeeded(state, callableMethod, constructorDescriptor, v);
|
FunctionCodegen.generateConstructorWithoutParametersIfNeeded(state, callableMethod, constructorDescriptor, v);
|
||||||
@@ -1024,7 +1023,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
ConstructorContext constructorContext,
|
ConstructorContext constructorContext,
|
||||||
JvmMethodSignature constructorMethod,
|
JvmMethodSignature constructorMethod,
|
||||||
CallableMethod callableMethod,
|
CallableMethod callableMethod,
|
||||||
boolean hasCapturedThis,
|
|
||||||
MutableClosure closure,
|
MutableClosure closure,
|
||||||
MethodVisitor mv
|
MethodVisitor mv
|
||||||
) {
|
) {
|
||||||
@@ -1051,39 +1049,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
generateDelegatorToConstructorCall(iv, codegen, constructorDescriptor, frameMap);
|
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) {
|
if (closure != null) {
|
||||||
int k = hasCapturedThis ? 2 : 1;
|
List<FieldInfo> argsFromClosure = ClosureCodegen.calculateConstructorParameters(typeMapper, bindingContext, state, closure, classAsmType);
|
||||||
String internalName = typeMapper.mapType(descriptor).getInternalName();
|
int k = 1;
|
||||||
ClassifierDescriptor captureReceiver = closure.getCaptureReceiver();
|
for (FieldInfo info : argsFromClosure) {
|
||||||
if (captureReceiver != null) {
|
k = AsmUtil.genAssignInstanceFieldFromParam(info, k, iv);
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user