Default function generation refactoring
This commit is contained in:
@@ -137,11 +137,11 @@ public class AsmUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isStaticMethod(OwnerKind kind, FunctionDescriptor functionDescriptor) {
|
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) {
|
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) {
|
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.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.psi.JetNamedFunction;
|
import org.jetbrains.jet.lang.psi.JetNamedFunction;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
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.JvmAbi;
|
||||||
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
|
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
|
||||||
import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames;
|
import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames;
|
||||||
@@ -519,12 +518,12 @@ public class FunctionCodegen extends GenerationStateAware {
|
|||||||
|
|
||||||
static void generateDefaultIfNeeded(
|
static void generateDefaultIfNeeded(
|
||||||
@NotNull MethodContext owner,
|
@NotNull MethodContext owner,
|
||||||
GenerationState state,
|
@NotNull GenerationState state,
|
||||||
ClassBuilder v,
|
@NotNull ClassBuilder v,
|
||||||
JvmMethodSignature signature,
|
@NotNull JvmMethodSignature signature,
|
||||||
@NotNull FunctionDescriptor functionDescriptor,
|
@NotNull FunctionDescriptor functionDescriptor,
|
||||||
OwnerKind kind,
|
@NotNull OwnerKind kind,
|
||||||
DefaultParameterValueLoader loadStrategy
|
@NotNull DefaultParameterValueLoader loadStrategy
|
||||||
) {
|
) {
|
||||||
DeclarationDescriptor contextClass = owner.getContextDescriptor().getContainingDeclaration();
|
DeclarationDescriptor contextClass = owner.getContextDescriptor().getContainingDeclaration();
|
||||||
|
|
||||||
@@ -538,21 +537,10 @@ public class FunctionCodegen extends GenerationStateAware {
|
|||||||
return;
|
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);
|
boolean isStatic = isStatic(kind);
|
||||||
|
|
||||||
Method jvmSignature = signature.getAsmMethod();
|
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.
|
int flags = ACC_PUBLIC | ACC_SYNTHETIC; // TODO.
|
||||||
|
|
||||||
JvmClassName ownerInternalName;
|
JvmClassName ownerInternalName;
|
||||||
@@ -573,86 +561,63 @@ public class FunctionCodegen extends GenerationStateAware {
|
|||||||
MethodVisitor mv = v.newMethod(null, flags | (isConstructor ? 0 : ACC_STATIC),
|
MethodVisitor mv = v.newMethod(null, flags | (isConstructor ? 0 : ACC_STATIC),
|
||||||
isConstructor ? "<init>" : jvmSignature.getName() + JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX,
|
isConstructor ? "<init>" : jvmSignature.getName() + JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX,
|
||||||
descriptor, null, null);
|
descriptor, null, null);
|
||||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
|
||||||
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
|
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
|
||||||
genStubCode(mv);
|
genStubCode(mv);
|
||||||
}
|
}
|
||||||
else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
|
else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
|
||||||
generateDefaultImpl(owner, state, jvmSignature, functionDescriptor, kind, receiverParameter, hasReceiver, hasOuter, isStatic,
|
generateDefaultImpl(owner, state, signature, functionDescriptor, kind, isStatic, mv, loadStrategy);
|
||||||
ownerInternalName,
|
|
||||||
isConstructor, mv, iv, loadStrategy);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void generateDefaultImpl(
|
private static void generateDefaultImpl(
|
||||||
MethodContext owner,
|
@NotNull MethodContext methodContext,
|
||||||
GenerationState state,
|
@NotNull GenerationState state,
|
||||||
Method jvmSignature,
|
@NotNull JvmMethodSignature signature,
|
||||||
FunctionDescriptor functionDescriptor,
|
@NotNull FunctionDescriptor functionDescriptor,
|
||||||
OwnerKind kind,
|
@NotNull OwnerKind kind,
|
||||||
ReceiverParameterDescriptor receiverParameter,
|
|
||||||
boolean hasReceiver, boolean hasOuter,
|
|
||||||
boolean aStatic,
|
boolean aStatic,
|
||||||
JvmClassName ownerInternalName,
|
@NotNull MethodVisitor mv,
|
||||||
boolean constructor,
|
@NotNull DefaultParameterValueLoader loadStrategy
|
||||||
MethodVisitor mv,
|
|
||||||
InstructionAdapter iv,
|
|
||||||
DefaultParameterValueLoader loadStrategy
|
|
||||||
) {
|
) {
|
||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
|
|
||||||
boolean isEnumConstructor = functionDescriptor instanceof ConstructorDescriptor &&
|
FrameMap frameMap = new FrameMap();
|
||||||
DescriptorUtils.isEnumClass(functionDescriptor.getContainingDeclaration());
|
|
||||||
|
|
||||||
FrameMap frameMap = owner.prepareFrame(state.getTypeMapper());
|
if (!aStatic) {
|
||||||
|
|
||||||
if (kind instanceof OwnerKind.StaticDelegateKind) {
|
|
||||||
frameMap.leaveTemp(OBJECT_TYPE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasOuter) {
|
|
||||||
frameMap.enterTemp(OBJECT_TYPE);
|
frameMap.enterTemp(OBJECT_TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isEnumConstructor) {
|
Method jvmSignature = signature.getAsmMethod();
|
||||||
frameMap.enterTemp(OBJECT_TYPE);
|
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, jvmSignature.getReturnType(), methodContext, state);
|
||||||
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);
|
|
||||||
|
|
||||||
Type[] argTypes = jvmSignature.getArgumentTypes();
|
Type[] argTypes = jvmSignature.getArgumentTypes();
|
||||||
List<ValueParameterDescriptor> paramDescrs = functionDescriptor.getValueParameters();
|
List<ValueParameterDescriptor> paramDescrs = functionDescriptor.getValueParameters();
|
||||||
int paramSizeInLocalVariablesTable = 0;
|
Iterator<ValueParameterDescriptor> iterator = paramDescrs.iterator();
|
||||||
for (int i = 0; i < paramDescrs.size(); i++) {
|
|
||||||
Type argType = argTypes[i + countOfExtraVarsInMethodArgs];
|
int countOfExtraVarsInMethodArgs = 0;
|
||||||
int size = argType.getSize();
|
List<JvmMethodParameterSignature> params = signature.getKotlinParameterTypes();
|
||||||
frameMap.enter(paramDescrs.get(i), argType);
|
|
||||||
paramSizeInLocalVariablesTable += size;
|
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++) {
|
for (int index = 0; index < paramDescrs.size(); index++) {
|
||||||
ValueParameterDescriptor parameterDescriptor = paramDescrs.get(index);
|
ValueParameterDescriptor parameterDescriptor = paramDescrs.get(index);
|
||||||
|
|
||||||
Type t = argTypes[countOfExtraVarsInMethodArgs + index];
|
Type t = argTypes[countOfExtraVarsInMethodArgs + index];
|
||||||
|
|
||||||
if (frameMap.getIndex(parameterDescriptor) < 0) {
|
|
||||||
frameMap.enter(parameterDescriptor, t);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parameterDescriptor.declaresDefaultValue()) {
|
if (parameterDescriptor.declaresDefaultValue()) {
|
||||||
iv.load(maskIndex, Type.INT_TYPE);
|
iv.load(maskIndex, Type.INT_TYPE);
|
||||||
iv.iconst(1 << index);
|
iv.iconst(1 << index);
|
||||||
@@ -668,81 +633,48 @@ public class FunctionCodegen extends GenerationStateAware {
|
|||||||
iv.mark(loadArg);
|
iv.mark(loadArg);
|
||||||
}
|
}
|
||||||
|
|
||||||
iv.load(indexInLocalVariablesTable, t);
|
iv.load(frameMap.getIndex(parameterDescriptor), t);
|
||||||
indexInLocalVariablesTable += t.getSize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String internalName = ownerInternalName.getInternalName();
|
CallableMethod method = null;
|
||||||
String jvmSignatureName = jvmSignature.getName();
|
if (functionDescriptor instanceof ConstructorDescriptor) {
|
||||||
String jvmSignatureDescriptor = jvmSignature.getDescriptor();
|
method = state.getTypeMapper().mapToCallableMethod((ConstructorDescriptor) functionDescriptor);
|
||||||
if (!aStatic) {
|
} else {
|
||||||
if (kind == OwnerKind.TRAIT_IMPL) {
|
method = state.getTypeMapper()
|
||||||
iv.invokeinterface(internalName, jvmSignatureName, jvmSignatureDescriptor);
|
.mapToCallableMethod(functionDescriptor, false, isCallInsideSameClassAsDeclared(functionDescriptor, methodContext),
|
||||||
}
|
isCallInsideSameModuleAsDeclared(functionDescriptor, methodContext), OwnerKind.IMPLEMENTATION);
|
||||||
else {
|
|
||||||
if (!constructor && functionDescriptor.getVisibility() != Visibilities.PRIVATE) {
|
|
||||||
iv.invokevirtual(internalName, jvmSignatureName, jvmSignatureDescriptor);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
iv.invokespecial(internalName, jvmSignatureName, jvmSignatureDescriptor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
iv.invokestatic(internalName, jvmSignatureName, jvmSignatureDescriptor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iv.visitMethodInsn(method.getInvokeOpcode(), method.getOwner().getInternalName(), method.getSignature().getAsmMethod().getName(),
|
||||||
|
method.getSignature().getAsmMethod().getDescriptor());
|
||||||
|
|
||||||
iv.areturn(jvmSignature.getReturnType());
|
iv.areturn(jvmSignature.getReturnType());
|
||||||
|
|
||||||
endVisit(mv, "default method", callableDescriptorToDeclaration(state.getBindingContext(), functionDescriptor));
|
endVisit(mv, "default method", callableDescriptorToDeclaration(state.getBindingContext(), functionDescriptor));
|
||||||
mv.visitEnd();
|
mv.visitEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getSizeOfExplicitArgumentsInLocalVariablesTable(
|
|
||||||
|
private static void loadExplicitArgumentsOnStack(
|
||||||
|
@NotNull InstructionAdapter iv,
|
||||||
|
@NotNull Type ownerType,
|
||||||
boolean isStatic,
|
boolean isStatic,
|
||||||
boolean hasOuter,
|
@NotNull JvmMethodSignature signature
|
||||||
boolean isEnumConstructor,
|
|
||||||
@Nullable Type receiverType
|
|
||||||
) {
|
) {
|
||||||
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;
|
int var = 0;
|
||||||
if (!isStatic) {
|
if (!isStatic) {
|
||||||
iv.load(var++, ownerType);
|
iv.load(var, ownerType);
|
||||||
|
var += ownerType.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasOuter) {
|
List<JvmMethodParameterSignature> params = signature.getKotlinParameterTypes();
|
||||||
iv.load(var++, outerType);
|
for (int i = 0; i < params.size(); i++) {
|
||||||
}
|
JvmMethodParameterSignature parameterSignature = params.get(i);
|
||||||
|
if (parameterSignature.getKind() != JvmMethodParameterKind.VALUE) {
|
||||||
if (isEnumConstructor) {
|
Type type = parameterSignature.getAsmType();
|
||||||
iv.load(var++, OBJECT_TYPE);
|
iv.load(var, type);
|
||||||
iv.load(var++, Type.INT_TYPE);
|
var += type.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (receiverType != null) {
|
|
||||||
iv.load(var, receiverType);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user