Default function generation refactoring

This commit is contained in:
Mikhael Bogdanov
2013-05-08 11:32:09 +04:00
parent 702dadccf4
commit 6da8ba3fec
2 changed files with 62 additions and 130 deletions
@@ -137,11 +137,11 @@ public class AsmUtil {
}
public static boolean isStaticMethod(OwnerKind kind, FunctionDescriptor functionDescriptor) {
return isStatic(kind) || kind == OwnerKind.TRAIT_IMPL || JetTypeMapper.isAccessor(functionDescriptor);
return isStatic(kind) || JetTypeMapper.isAccessor(functionDescriptor);
}
public static boolean isStatic(OwnerKind kind) {
return kind == OwnerKind.NAMESPACE || kind instanceof OwnerKind.StaticDelegateKind;
return kind == OwnerKind.NAMESPACE || kind instanceof OwnerKind.StaticDelegateKind || kind == OwnerKind.TRAIT_IMPL;
}
public static int getMethodAsmFlags(FunctionDescriptor functionDescriptor, OwnerKind kind) {
@@ -41,7 +41,6 @@ import org.jetbrains.jet.codegen.state.JetTypeMapperMode;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.JetNamedFunction;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames;
@@ -519,12 +518,12 @@ public class FunctionCodegen extends GenerationStateAware {
static void generateDefaultIfNeeded(
@NotNull MethodContext owner,
GenerationState state,
ClassBuilder v,
JvmMethodSignature signature,
@NotNull GenerationState state,
@NotNull ClassBuilder v,
@NotNull JvmMethodSignature signature,
@NotNull FunctionDescriptor functionDescriptor,
OwnerKind kind,
DefaultParameterValueLoader loadStrategy
@NotNull OwnerKind kind,
@NotNull DefaultParameterValueLoader loadStrategy
) {
DeclarationDescriptor contextClass = owner.getContextDescriptor().getContainingDeclaration();
@@ -538,21 +537,10 @@ public class FunctionCodegen extends GenerationStateAware {
return;
}
ReceiverParameterDescriptor receiverParameter = functionDescriptor.getReceiverParameter();
boolean hasReceiver = receiverParameter != null;
// Has outer in local variables (constructor for inner class)
boolean hasOuter = functionDescriptor instanceof ConstructorDescriptor &&
CodegenBinding.canHaveOuter(state.getBindingContext(), ((ConstructorDescriptor) functionDescriptor).getContainingDeclaration());
boolean isStatic = isStatic(kind);
Method jvmSignature = signature.getAsmMethod();
if (kind == OwnerKind.TRAIT_IMPL) {
String correctedDescr = "(" + jvmSignature.getDescriptor().substring(jvmSignature.getDescriptor().indexOf(";") + 1);
jvmSignature = new Method(jvmSignature.getName(), correctedDescr);
}
int flags = ACC_PUBLIC | ACC_SYNTHETIC; // TODO.
JvmClassName ownerInternalName;
@@ -573,86 +561,63 @@ public class FunctionCodegen extends GenerationStateAware {
MethodVisitor mv = v.newMethod(null, flags | (isConstructor ? 0 : ACC_STATIC),
isConstructor ? "<init>" : jvmSignature.getName() + JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX,
descriptor, null, null);
InstructionAdapter iv = new InstructionAdapter(mv);
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
genStubCode(mv);
}
else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
generateDefaultImpl(owner, state, jvmSignature, functionDescriptor, kind, receiverParameter, hasReceiver, hasOuter, isStatic,
ownerInternalName,
isConstructor, mv, iv, loadStrategy);
generateDefaultImpl(owner, state, signature, functionDescriptor, kind, isStatic, mv, loadStrategy);
}
}
private static void generateDefaultImpl(
MethodContext owner,
GenerationState state,
Method jvmSignature,
FunctionDescriptor functionDescriptor,
OwnerKind kind,
ReceiverParameterDescriptor receiverParameter,
boolean hasReceiver, boolean hasOuter,
@NotNull MethodContext methodContext,
@NotNull GenerationState state,
@NotNull JvmMethodSignature signature,
@NotNull FunctionDescriptor functionDescriptor,
@NotNull OwnerKind kind,
boolean aStatic,
JvmClassName ownerInternalName,
boolean constructor,
MethodVisitor mv,
InstructionAdapter iv,
DefaultParameterValueLoader loadStrategy
@NotNull MethodVisitor mv,
@NotNull DefaultParameterValueLoader loadStrategy
) {
mv.visitCode();
boolean isEnumConstructor = functionDescriptor instanceof ConstructorDescriptor &&
DescriptorUtils.isEnumClass(functionDescriptor.getContainingDeclaration());
FrameMap frameMap = new FrameMap();
FrameMap frameMap = owner.prepareFrame(state.getTypeMapper());
if (kind instanceof OwnerKind.StaticDelegateKind) {
frameMap.leaveTemp(OBJECT_TYPE);
}
if (hasOuter) {
if (!aStatic) {
frameMap.enterTemp(OBJECT_TYPE);
}
if (isEnumConstructor) {
frameMap.enterTemp(OBJECT_TYPE);
frameMap.enterTemp(Type.INT_TYPE);
}
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, jvmSignature.getReturnType(), owner, state);
Type receiverType = null;
if (hasReceiver) {
receiverType = state.getTypeMapper().mapType(receiverParameter.getType());
}
int extraInLocalVariablesTable = getSizeOfExplicitArgumentsInLocalVariablesTable(aStatic, hasOuter, isEnumConstructor, receiverType);
int countOfExtraVarsInMethodArgs = getCountOfExplicitArgumentsInMethodArguments(hasOuter, hasReceiver, isEnumConstructor);
Method jvmSignature = signature.getAsmMethod();
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, jvmSignature.getReturnType(), methodContext, state);
Type[] argTypes = jvmSignature.getArgumentTypes();
List<ValueParameterDescriptor> paramDescrs = functionDescriptor.getValueParameters();
int paramSizeInLocalVariablesTable = 0;
for (int i = 0; i < paramDescrs.size(); i++) {
Type argType = argTypes[i + countOfExtraVarsInMethodArgs];
int size = argType.getSize();
frameMap.enter(paramDescrs.get(i), argType);
paramSizeInLocalVariablesTable += size;
Iterator<ValueParameterDescriptor> iterator = paramDescrs.iterator();
int countOfExtraVarsInMethodArgs = 0;
List<JvmMethodParameterSignature> params = signature.getKotlinParameterTypes();
for (int i = 0; i < params.size(); i++) {
JvmMethodParameterSignature parameterSignature = params.get(i);
if (parameterSignature.getKind() != JvmMethodParameterKind.VALUE) {
countOfExtraVarsInMethodArgs++;
frameMap.enterTemp(parameterSignature.getAsmType());
} else {
frameMap.enter(iterator.next(), parameterSignature.getAsmType());
}
}
int maskIndex = extraInLocalVariablesTable + paramSizeInLocalVariablesTable;
int maskIndex = frameMap.enterTemp(Type.INT_TYPE);
loadExplicitArgumentsOnStack(iv, OBJECT_TYPE, receiverType, ownerInternalName.getAsmType(), aStatic, hasOuter, isEnumConstructor);
InstructionAdapter iv = new InstructionAdapter(mv);
loadExplicitArgumentsOnStack(iv, OBJECT_TYPE, aStatic, signature);
int indexInLocalVariablesTable = extraInLocalVariablesTable;
for (int index = 0; index < paramDescrs.size(); index++) {
ValueParameterDescriptor parameterDescriptor = paramDescrs.get(index);
Type t = argTypes[countOfExtraVarsInMethodArgs + index];
if (frameMap.getIndex(parameterDescriptor) < 0) {
frameMap.enter(parameterDescriptor, t);
}
if (parameterDescriptor.declaresDefaultValue()) {
iv.load(maskIndex, Type.INT_TYPE);
iv.iconst(1 << index);
@@ -668,81 +633,48 @@ public class FunctionCodegen extends GenerationStateAware {
iv.mark(loadArg);
}
iv.load(indexInLocalVariablesTable, t);
indexInLocalVariablesTable += t.getSize();
iv.load(frameMap.getIndex(parameterDescriptor), t);
}
String internalName = ownerInternalName.getInternalName();
String jvmSignatureName = jvmSignature.getName();
String jvmSignatureDescriptor = jvmSignature.getDescriptor();
if (!aStatic) {
if (kind == OwnerKind.TRAIT_IMPL) {
iv.invokeinterface(internalName, jvmSignatureName, jvmSignatureDescriptor);
}
else {
if (!constructor && functionDescriptor.getVisibility() != Visibilities.PRIVATE) {
iv.invokevirtual(internalName, jvmSignatureName, jvmSignatureDescriptor);
}
else {
iv.invokespecial(internalName, jvmSignatureName, jvmSignatureDescriptor);
}
}
}
else {
iv.invokestatic(internalName, jvmSignatureName, jvmSignatureDescriptor);
CallableMethod method = null;
if (functionDescriptor instanceof ConstructorDescriptor) {
method = state.getTypeMapper().mapToCallableMethod((ConstructorDescriptor) functionDescriptor);
} else {
method = state.getTypeMapper()
.mapToCallableMethod(functionDescriptor, false, isCallInsideSameClassAsDeclared(functionDescriptor, methodContext),
isCallInsideSameModuleAsDeclared(functionDescriptor, methodContext), OwnerKind.IMPLEMENTATION);
}
iv.visitMethodInsn(method.getInvokeOpcode(), method.getOwner().getInternalName(), method.getSignature().getAsmMethod().getName(),
method.getSignature().getAsmMethod().getDescriptor());
iv.areturn(jvmSignature.getReturnType());
endVisit(mv, "default method", callableDescriptorToDeclaration(state.getBindingContext(), functionDescriptor));
mv.visitEnd();
}
private static int getSizeOfExplicitArgumentsInLocalVariablesTable(
private static void loadExplicitArgumentsOnStack(
@NotNull InstructionAdapter iv,
@NotNull Type ownerType,
boolean isStatic,
boolean hasOuter,
boolean isEnumConstructor,
@Nullable Type receiverType
@NotNull JvmMethodSignature signature
) {
int result = 0;
if (!isStatic) result++;
if (receiverType != null) result += receiverType.getSize();
if (hasOuter) result++;
if (isEnumConstructor) result += 2;
return result;
}
private static int getCountOfExplicitArgumentsInMethodArguments(
boolean hasOuter,
boolean hasReceiver,
boolean isEnumConstructor
) {
int result = 0;
if (hasReceiver) result++;
if (hasOuter) result++;
if (isEnumConstructor) result += 2;
return result;
}
private static void loadExplicitArgumentsOnStack(@NotNull InstructionAdapter iv,
@NotNull Type ownerType, @Nullable Type receiverType, @NotNull Type outerType,
boolean isStatic, boolean hasOuter, boolean isEnumConstructor) {
int var = 0;
if (!isStatic) {
iv.load(var++, ownerType);
iv.load(var, ownerType);
var += ownerType.getSize();
}
if (hasOuter) {
iv.load(var++, outerType);
}
if (isEnumConstructor) {
iv.load(var++, OBJECT_TYPE);
iv.load(var++, Type.INT_TYPE);
}
if (receiverType != null) {
iv.load(var, receiverType);
List<JvmMethodParameterSignature> params = signature.getKotlinParameterTypes();
for (int i = 0; i < params.size(); i++) {
JvmMethodParameterSignature parameterSignature = params.get(i);
if (parameterSignature.getKind() != JvmMethodParameterKind.VALUE) {
Type type = parameterSignature.getAsmType();
iv.load(var, type);
var += type.getSize();
}
}
}