Refactor copy() function generation for data classes

Use FunctionCodegen and the newly created FunctionGenerationStrategy to
generate the needed instructions. Make some methods in FunctionCodegen private
since they're not used anymore outside of the class
This commit is contained in:
Alexander Udalov
2013-04-10 15:18:04 +04:00
parent 9bb3663b54
commit 34009a2134
2 changed files with 38 additions and 54 deletions
@@ -209,7 +209,7 @@ public class FunctionCodegen extends GenerationStateAware {
} }
@NotNull @NotNull
public static List<String> getParameterNamesAsStrings(@NotNull FunctionDescriptor functionDescriptor) { private static List<String> getParameterNamesAsStrings(@NotNull FunctionDescriptor functionDescriptor) {
List<ValueParameterDescriptor> parameters = functionDescriptor.getValueParameters(); List<ValueParameterDescriptor> parameters = functionDescriptor.getValueParameters();
List<String> result = new ArrayList<String>(parameters.size()); List<String> result = new ArrayList<String>(parameters.size());
for (ValueParameterDescriptor parameter : parameters) { for (ValueParameterDescriptor parameter : parameters) {
@@ -218,7 +218,7 @@ public class FunctionCodegen extends GenerationStateAware {
return result; return result;
} }
public static void generateLocalVariableTable( private static void generateLocalVariableTable(
@NotNull JetTypeMapper typeMapper, @NotNull JetTypeMapper typeMapper,
@NotNull MethodVisitor mv, @NotNull MethodVisitor mv,
@NotNull FunctionDescriptor functionDescriptor, @NotNull FunctionDescriptor functionDescriptor,
@@ -301,7 +301,7 @@ public class FunctionCodegen extends GenerationStateAware {
return labelsForSharedVars; return labelsForSharedVars;
} }
public static void generateStaticDelegateMethodBody( private static void generateStaticDelegateMethodBody(
@NotNull MethodVisitor mv, @NotNull MethodVisitor mv,
@NotNull Method asmMethod, @NotNull Method asmMethod,
@NotNull OwnerKind.StaticDelegateKind dk @NotNull OwnerKind.StaticDelegateKind dk
@@ -697,67 +697,51 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
private void generateCopyFunction(@NotNull final FunctionDescriptor function) { private void generateCopyFunction(@NotNull final FunctionDescriptor function) {
JetType returnType = function.getReturnType();
assert returnType != null : "Return type of copy function should not be null: " + function;
JvmMethodSignature methodSignature = typeMapper.mapSignature(function.getName(), function); JvmMethodSignature methodSignature = typeMapper.mapSignature(function.getName(), function);
String methodDesc = methodSignature.getAsmMethod().getDescriptor();
MethodVisitor mv = v.newMethod(myClass, AsmUtil.getMethodAsmFlags(function, OwnerKind.IMPLEMENTATION),
function.getName().getName(), methodDesc,
null, null);
FunctionCodegen.genJetAnnotations(state, function, null, null, mv);
mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv);
ConstructorDescriptor constructor = DescriptorUtils.getConstructorOfDataClass(descriptor);
Label methodBegin = new Label();
mv.visitLabel(methodBegin);
final Type thisDescriptorType = typeMapper.mapType(descriptor.getDefaultType()); final Type thisDescriptorType = typeMapper.mapType(descriptor.getDefaultType());
iv.anew(thisDescriptorType);
iv.dup();
String thisInternalName = thisDescriptorType.getInternalName(); FunctionCodegen fc = new FunctionCodegen(context, v, state);
fc.generateMethod(myClass, methodSignature, true, null, function, new FunctionGenerationStrategy() {
@Override
public void generateBody(
@NotNull MethodVisitor mv,
@NotNull JvmMethodSignature signature,
@NotNull MethodContext context,
@NotNull Collection<String> localVariableNames,
@NotNull FrameMap frameMap
) {
InstructionAdapter iv = new InstructionAdapter(mv);
assert function.getValueParameters().size() == constructor.getValueParameters().size() : iv.anew(thisDescriptorType);
"Number of parameters of copy function and constructor are different. Copy: " + function.getValueParameters().size() + ", constructor: " + constructor.getValueParameters().size(); iv.dup();
MutableClosure closure = context.closure; ConstructorDescriptor constructor = DescriptorUtils.getConstructorOfDataClass(descriptor);
if (closure != null && closure.getCaptureThis() != null) { assert function.getValueParameters().size() == constructor.getValueParameters().size() :
Type type = typeMapper.mapType(enclosingClassDescriptor(bindingContext, descriptor)); "Number of parameters of copy function and constructor are different. " +
iv.load(0, classAsmType); "Copy: " + function.getValueParameters().size() + ", " +
iv.getfield(JvmClassName.byType(classAsmType).getInternalName(), CAPTURED_THIS_FIELD, type.getDescriptor()); "constructor: " + constructor.getValueParameters().size();
}
int parameterIndex = 1; // localVariable 0 = this MutableClosure closure = ImplementationBodyCodegen.this.context.closure;
for (ValueParameterDescriptor parameterDescriptor : function.getValueParameters()) { if (closure != null && closure.getCaptureThis() != null) {
Type type = typeMapper.mapType(parameterDescriptor.getType()); Type type = typeMapper.mapType(enclosingClassDescriptor(bindingContext, descriptor));
iv.load(parameterIndex, type); iv.load(0, classAsmType);
parameterIndex += type.getSize(); iv.getfield(JvmClassName.byType(classAsmType).getInternalName(), CAPTURED_THIS_FIELD, type.getDescriptor());
} }
String constructorJvmDescriptor = typeMapper.mapToCallableMethod(constructor).getSignature().getAsmMethod().getDescriptor(); int parameterIndex = 1; // localVariable 0 = this
iv.invokespecial(thisInternalName, "<init>", constructorJvmDescriptor); for (ValueParameterDescriptor parameterDescriptor : function.getValueParameters()) {
Type type = typeMapper.mapType(parameterDescriptor.getType());
iv.load(parameterIndex, type);
parameterIndex += type.getSize();
}
iv.areturn(thisDescriptorType); String constructorJvmDescriptor = typeMapper.mapToCallableMethod(constructor).getSignature().getAsmMethod().getDescriptor();
iv.invokespecial(thisDescriptorType.getInternalName(), "<init>", constructorJvmDescriptor);
Label methodEnd = new Label(); iv.areturn(thisDescriptorType);
mv.visitLabel(methodEnd); }
});
FunctionCodegen.MethodInfo methodInfo = new FunctionCodegen.MethodInfo(
methodBegin,
methodEnd,
FunctionCodegen.getParameterNamesAsStrings(function),
Collections.<Name, Label>emptyMap()
);
FunctionCodegen.generateLocalVariableTable(typeMapper, mv, function, thisDescriptorType, methodInfo);
FunctionCodegen.endVisit(mv, function.getName().getName(), myClass);
MethodContext functionContext = context.intoFunction(function); MethodContext functionContext = context.intoFunction(function);
FunctionCodegen.generateDefaultIfNeeded(functionContext, state, v, methodSignature.getAsmMethod(), function, OwnerKind.IMPLEMENTATION, FunctionCodegen.generateDefaultIfNeeded(functionContext, state, v, methodSignature.getAsmMethod(), function, OwnerKind.IMPLEMENTATION,