Added additional parameter for default methods

This commit is contained in:
Michael Bogdanov
2016-01-20 17:32:47 +03:00
parent 875287574f
commit 829978a37d
18 changed files with 47 additions and 44 deletions
@@ -31,7 +31,7 @@ abstract class ArgumentGenerator {
* *
* @see kotlin.reflect.jvm.internal.KCallableImpl.callBy * @see kotlin.reflect.jvm.internal.KCallableImpl.callBy
*/ */
open fun generate(valueArgumentsByIndex: List<ResolvedValueArgument>, actualArgs: List<ResolvedValueArgument>): DefaultCallMask { open fun generate(valueArgumentsByIndex: List<ResolvedValueArgument>, actualArgs: List<ResolvedValueArgument>): DefaultCallArgs {
assert(valueArgumentsByIndex.size == actualArgs.size) { assert(valueArgumentsByIndex.size == actualArgs.size) {
"Value arguments collection should have same size, but ${valueArgumentsByIndex.size} != ${actualArgs.size}" "Value arguments collection should have same size, but ${valueArgumentsByIndex.size} != ${actualArgs.size}"
} }
@@ -48,7 +48,7 @@ abstract class ArgumentGenerator {
} }
} }
val masks = DefaultCallMask(valueArgumentsByIndex.size) val defaultArgs = DefaultCallArgs(valueArgumentsByIndex.size)
for (argumentWithDeclIndex in actualArgsWithDeclIndex) { for (argumentWithDeclIndex in actualArgsWithDeclIndex) {
val argument = argumentWithDeclIndex.arg val argument = argumentWithDeclIndex.arg
@@ -59,7 +59,7 @@ abstract class ArgumentGenerator {
generateExpression(declIndex, argument) generateExpression(declIndex, argument)
} }
is DefaultValueArgument -> { is DefaultValueArgument -> {
masks.mark(declIndex) defaultArgs.mark(declIndex)
generateDefault(declIndex, argument) generateDefault(declIndex, argument)
} }
is VarargValueArgument -> { is VarargValueArgument -> {
@@ -73,7 +73,7 @@ abstract class ArgumentGenerator {
reorderArgumentsIfNeeded(actualArgsWithDeclIndex) reorderArgumentsIfNeeded(actualArgsWithDeclIndex)
return masks return defaultArgs
} }
protected open fun generateExpression(i: Int, argument: ExpressionValueArgument) { protected open fun generateExpression(i: Int, argument: ExpressionValueArgument) {
@@ -51,15 +51,15 @@ public class CallBasedArgumentGenerator extends ArgumentGenerator {
@NotNull @NotNull
@Override @Override
public DefaultCallMask generate( public DefaultCallArgs generate(
@NotNull List<? extends ResolvedValueArgument> valueArgumentsByIndex, @NotNull List<? extends ResolvedValueArgument> valueArgumentsByIndex,
@NotNull List<? extends ResolvedValueArgument> valueArgs @NotNull List<? extends ResolvedValueArgument> valueArgs
) { ) {
boolean shouldMarkLineNumbers = this.codegen.isShouldMarkLineNumbers(); boolean shouldMarkLineNumbers = this.codegen.isShouldMarkLineNumbers();
this.codegen.setShouldMarkLineNumbers(false); this.codegen.setShouldMarkLineNumbers(false);
DefaultCallMask masks = super.generate(valueArgumentsByIndex, valueArgs); DefaultCallArgs defaultArgs = super.generate(valueArgumentsByIndex, valueArgs);
this.codegen.setShouldMarkLineNumbers(shouldMarkLineNumbers); this.codegen.setShouldMarkLineNumbers(shouldMarkLineNumbers);
return masks; return defaultArgs;
} }
@Override @Override
@@ -62,7 +62,6 @@ class CallableMethod(
val method = getAsmMethod() val method = getAsmMethod()
if ("<init>".equals(method.name)) { if ("<init>".equals(method.name)) {
v.aconst(null)
v.visitMethodInsn(INVOKESPECIAL, defaultImplOwner.internalName, "<init>", defaultMethodDesc, false) v.visitMethodInsn(INVOKESPECIAL, defaultImplOwner.internalName, "<init>", defaultMethodDesc, false)
} }
else { else {
@@ -16,10 +16,11 @@
package org.jetbrains.kotlin.codegen package org.jetbrains.kotlin.codegen
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.Type
import java.util.* import java.util.*
class DefaultCallMask(val size: Int) { class DefaultCallArgs(val size: Int) {
val bits: BitSet = BitSet(size) val bits: BitSet = BitSet(size)
@@ -50,10 +51,15 @@ class DefaultCallMask(val size: Int) {
return masks return masks
} }
fun generateOnStackIfNeeded(callGenerator: CallGenerator): Boolean { fun generateOnStackIfNeeded(callGenerator: CallGenerator, isConstructor: Boolean): Boolean {
val toInts = toInts() val toInts = toInts()
for (mask in toInts) { if (!toInts.isEmpty()) {
callGenerator.putValueIfNeeded(Type.INT_TYPE, StackValue.constant(mask, Type.INT_TYPE)) for (mask in toInts) {
callGenerator.putValueIfNeeded(Type.INT_TYPE, StackValue.constant(mask, Type.INT_TYPE))
}
val parameterType = if (isConstructor) AsmTypes.DEFAULT_CONSTRUCTOR_MARKER else AsmTypes.OBJECT_TYPE
callGenerator.putValueIfNeeded(parameterType, StackValue.constant(null, parameterType))
} }
return toInts.isNotEmpty(); return toInts.isNotEmpty();
} }
@@ -184,14 +184,14 @@ class DefaultParameterValueSubstitutor(val state: GenerationState) {
} }
} }
masks.add(mask) masks.add(mask)
for (m in masks) { for (m in masks) {
v.iconst(m) v.iconst(m)
} }
// constructors with default arguments has last synthetic argument of specific type // for default constructors: just marks default constructor (see DEFAULT_CONSTRUCTOR_MARKER)
if (functionDescriptor is ConstructorDescriptor) { // for default methods: contains MethodHandle for super calls ('null' cause not super call)
v.aconst(null) v.aconst(null)
}
val defaultMethod = typeMapper.mapDefaultMethod(delegateFunctionDescriptor, contextKind) val defaultMethod = typeMapper.mapDefaultMethod(delegateFunctionDescriptor, contextKind)
if (functionDescriptor is ConstructorDescriptor) { if (functionDescriptor is ConstructorDescriptor) {
@@ -2378,7 +2378,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
@NotNull CallGenerator callGenerator, @NotNull CallGenerator callGenerator,
@NotNull ArgumentGenerator argumentGenerator @NotNull ArgumentGenerator argumentGenerator
) { ) {
if (!(resolvedCall.getResultingDescriptor() instanceof ConstructorDescriptor)) { // otherwise already boolean isConstructor = resolvedCall.getResultingDescriptor() instanceof ConstructorDescriptor;
if (!isConstructor) { // otherwise already
receiver = StackValue.receiver(resolvedCall, receiver, this, callableMethod); receiver = StackValue.receiver(resolvedCall, receiver, this, callableMethod);
receiver.put(receiver.type, v); receiver.put(receiver.type, v);
callableMethod.afterReceiverGeneration(v); callableMethod.afterReceiverGeneration(v);
@@ -2389,7 +2390,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
List<ResolvedValueArgument> valueArguments = resolvedCall.getValueArgumentsByIndex(); List<ResolvedValueArgument> valueArguments = resolvedCall.getValueArgumentsByIndex();
assert valueArguments != null : "Failed to arrange value arguments by index: " + resolvedCall.getResultingDescriptor(); assert valueArguments != null : "Failed to arrange value arguments by index: " + resolvedCall.getResultingDescriptor();
DefaultCallMask masks = DefaultCallArgs defaultArgs =
argumentGenerator.generate(valueArguments, new ArrayList<ResolvedValueArgument>(resolvedCall.getValueArguments().values())); argumentGenerator.generate(valueArguments, new ArrayList<ResolvedValueArgument>(resolvedCall.getValueArguments().values()));
if (tailRecursionCodegen.isTailRecursion(resolvedCall)) { if (tailRecursionCodegen.isTailRecursion(resolvedCall)) {
@@ -2397,7 +2398,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
return; return;
} }
boolean defaultMaskWasGenerated = masks.generateOnStackIfNeeded(callGenerator); boolean defaultMaskWasGenerated = defaultArgs.generateOnStackIfNeeded(callGenerator, isConstructor);
// Extra constructor marker argument // Extra constructor marker argument
if (callableMethod instanceof CallableMethod) { if (callableMethod instanceof CallableMethod) {
@@ -774,7 +774,7 @@ public abstract class StackValue {
private final StackValue receiver; private final StackValue receiver;
private final ResolvedCall<FunctionDescriptor> resolvedGetCall; private final ResolvedCall<FunctionDescriptor> resolvedGetCall;
private final ResolvedCall<FunctionDescriptor> resolvedSetCall; private final ResolvedCall<FunctionDescriptor> resolvedSetCall;
private DefaultCallMask mask; private DefaultCallArgs defaultArgs;
private CallGenerator callGenerator; private CallGenerator callGenerator;
boolean isComplexOperationWithDup; boolean isComplexOperationWithDup;
@@ -807,7 +807,7 @@ public abstract class StackValue {
newReceiver.put(newReceiver.type, v); newReceiver.put(newReceiver.type, v);
callGenerator.putHiddenParams(); callGenerator.putHiddenParams();
mask = generator.generate(valueArguments, valueArguments); defaultArgs = generator.generate(valueArguments, valueArguments);
} }
private ArgumentGenerator createArgumentGenerator() { private ArgumentGenerator createArgumentGenerator() {
@@ -955,8 +955,8 @@ public abstract class StackValue {
} }
private boolean genDefaultMaskIfPresent(CallGenerator callGenerator) { private boolean genDefaultMaskIfPresent(CallGenerator callGenerator) {
DefaultCallMask mask = ((CollectionElementReceiver) receiver).mask; DefaultCallArgs defaultArgs = ((CollectionElementReceiver) receiver).defaultArgs;
return mask.generateOnStackIfNeeded(callGenerator); return defaultArgs.generateOnStackIfNeeded(callGenerator, true);
} }
private CallGenerator getCallGenerator() { private CallGenerator getCallGenerator() {
@@ -88,6 +88,7 @@ import static org.jetbrains.kotlin.resolve.BindingContextUtils.getDelegationCons
import static org.jetbrains.kotlin.resolve.BindingContextUtils.isVarCapturedInClosure; import static org.jetbrains.kotlin.resolve.BindingContextUtils.isVarCapturedInClosure;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*; import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.DEFAULT_CONSTRUCTOR_MARKER; import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.DEFAULT_CONSTRUCTOR_MARKER;
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE;
import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.*; import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.*;
import static org.jetbrains.org.objectweb.asm.Opcodes.*; import static org.jetbrains.org.objectweb.asm.Opcodes.*;
@@ -1104,9 +1105,7 @@ public class JetTypeMapper {
} }
int maskArgumentsCount = (argumentsCount + Integer.SIZE - 1) / Integer.SIZE; int maskArgumentsCount = (argumentsCount + Integer.SIZE - 1) / Integer.SIZE;
String additionalArgs = StringUtil.repeat(Type.INT_TYPE.getDescriptor(), maskArgumentsCount); String additionalArgs = StringUtil.repeat(Type.INT_TYPE.getDescriptor(), maskArgumentsCount);
if (isConstructor(method)) { additionalArgs += (isConstructor(method) ? DEFAULT_CONSTRUCTOR_MARKER : OBJECT_TYPE).getDescriptor();
additionalArgs += DEFAULT_CONSTRUCTOR_MARKER.getDescriptor();
}
String result = descriptor.replace(")", additionalArgs + ")"); String result = descriptor.replace(")", additionalArgs + ")");
if (dispatchReceiverDescriptor != null && !isConstructor(method)) { if (dispatchReceiverDescriptor != null && !isConstructor(method)) {
return result.replace("(", "(" + dispatchReceiverDescriptor); return result.replace("(", "(" + dispatchReceiverDescriptor);
@@ -1,7 +1,7 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER // !DIAGNOSTICS: -UNUSED_PARAMETER
open class Base { open class Base {
open fun `foo$default`(d: Derived, i: Int, mask: Int) {} open fun `foo$default`(d: Derived, i: Int, mask: Int, mh: Any) {}
} }
class Derived : Base() { class Derived : Base() {
@@ -3,7 +3,7 @@ package
public open class Base { public open class Base {
public constructor Base() public constructor Base()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open fun `foo$default`(/*0*/ d: Derived, /*1*/ i: kotlin.Int, /*2*/ mask: kotlin.Int): kotlin.Unit public open fun `foo$default`(/*0*/ d: Derived, /*1*/ i: kotlin.Int, /*2*/ mask: kotlin.Int, /*3*/ mh: kotlin.Any): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
} }
@@ -12,7 +12,7 @@ public final class Derived : Base {
public constructor Derived() public constructor Derived()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final fun foo(/*0*/ i: kotlin.Int = ...): kotlin.Unit public final fun foo(/*0*/ i: kotlin.Int = ...): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun `foo$default`(/*0*/ d: Derived, /*1*/ i: kotlin.Int, /*2*/ mask: kotlin.Int): kotlin.Unit public open override /*1*/ /*fake_override*/ fun `foo$default`(/*0*/ d: Derived, /*1*/ i: kotlin.Int, /*2*/ mask: kotlin.Int, /*3*/ mh: kotlin.Any): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
} }
@@ -1,5 +1,5 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER // !DIAGNOSTICS: -UNUSED_PARAMETER
data class <!CONFLICTING_JVM_DECLARATIONS!>C(val c: Int)<!> { data class <!CONFLICTING_JVM_DECLARATIONS!>C(val c: Int)<!> {
<!CONFLICTING_JVM_DECLARATIONS!>fun `copy$default`(c: C, x: Int, m: Int)<!> = C(this.c) <!CONFLICTING_JVM_DECLARATIONS!>fun `copy$default`(c: C, x: Int, m: Int, mh: Any)<!> = C(this.c)
} }
@@ -5,7 +5,7 @@ public final data class C {
public final val c: kotlin.Int public final val c: kotlin.Int
public final operator /*synthesized*/ fun component1(): kotlin.Int public final operator /*synthesized*/ fun component1(): kotlin.Int
public final /*synthesized*/ fun copy(/*0*/ c: kotlin.Int = ...): C public final /*synthesized*/ fun copy(/*0*/ c: kotlin.Int = ...): C
public final fun `copy$default`(/*0*/ c: C, /*1*/ x: kotlin.Int, /*2*/ m: kotlin.Int): C public final fun `copy$default`(/*0*/ c: C, /*1*/ x: kotlin.Int, /*2*/ m: kotlin.Int, /*3*/ mh: kotlin.Any): C
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
@@ -1,6 +1,6 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER // !DIAGNOSTICS: -UNUSED_PARAMETER
class C { class C {
<!CONFLICTING_JVM_DECLARATIONS!>fun `a$default`(c: C, x: Int, m: Int)<!> {} <!CONFLICTING_JVM_DECLARATIONS!>fun `a$default`(c: C, x: Int, m: Int, mh: Any)<!> {}
<!CONFLICTING_JVM_DECLARATIONS!>fun a(x: Int = 1)<!> {} <!CONFLICTING_JVM_DECLARATIONS!>fun a(x: Int = 1)<!> {}
} }
@@ -3,7 +3,7 @@ package
public final class C { public final class C {
public constructor C() public constructor C()
public final fun a(/*0*/ x: kotlin.Int = ...): kotlin.Unit public final fun a(/*0*/ x: kotlin.Int = ...): kotlin.Unit
public final fun `a$default`(/*0*/ c: C, /*1*/ x: kotlin.Int, /*2*/ m: kotlin.Int): kotlin.Unit public final fun `a$default`(/*0*/ c: C, /*1*/ x: kotlin.Int, /*2*/ m: kotlin.Int, /*3*/ mh: kotlin.Any): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
@@ -2,7 +2,7 @@
import kotlin.jvm.JvmStatic import kotlin.jvm.JvmStatic
open class Base { open class Base {
fun `foo$default`(i: Int, mask: Int) {} fun `foo$default`(i: Int, mask: Int, mh: Any) {}
} }
object Derived : Base() { object Derived : Base() {
@@ -3,7 +3,7 @@ package
public open class Base { public open class Base {
public constructor Base() public constructor Base()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final fun `foo$default`(/*0*/ i: kotlin.Int, /*1*/ mask: kotlin.Int): kotlin.Unit public final fun `foo$default`(/*0*/ i: kotlin.Int, /*1*/ mask: kotlin.Int, /*2*/ mh: kotlin.Any): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
} }
@@ -12,7 +12,7 @@ public object Derived : Base {
private constructor Derived() private constructor Derived()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
@kotlin.jvm.JvmStatic() public final fun foo(/*0*/ i: kotlin.Int = ...): kotlin.Unit @kotlin.jvm.JvmStatic() public final fun foo(/*0*/ i: kotlin.Int = ...): kotlin.Unit
public final override /*1*/ /*fake_override*/ fun `foo$default`(/*0*/ i: kotlin.Int, /*1*/ mask: kotlin.Int): kotlin.Unit public final override /*1*/ /*fake_override*/ fun `foo$default`(/*0*/ i: kotlin.Int, /*1*/ mask: kotlin.Int, /*2*/ mh: kotlin.Any): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
} }
@@ -107,10 +107,8 @@ internal interface KCallableImpl<out R> : KCallable<R>, KAnnotatedElementImpl {
arguments.addAll(masks) arguments.addAll(masks)
if (caller is FunctionCaller.Constructor) { // DefaultConstructorMarker or MethodHandle
// DefaultConstructorMarker arguments.add(null)
arguments.add(null)
}
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
return reflectionCall { return reflectionCall {
@@ -170,7 +170,7 @@ internal abstract class KDeclarationContainerImpl : ClassBasedDeclarationContain
if (isMember) { if (isMember) {
parameterTypes.add(jClass) parameterTypes.add(jClass)
} }
addParametersAndMasks(parameterTypes, desc) addParametersAndMasks(parameterTypes, desc, false)
return jClass.tryGetMethod(name + JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX, parameterTypes, declared) return jClass.tryGetMethod(name + JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX, parameterTypes, declared)
} }
@@ -181,18 +181,18 @@ internal abstract class KDeclarationContainerImpl : ClassBasedDeclarationContain
fun findDefaultConstructor(desc: String, declared: Boolean): Constructor<*>? { fun findDefaultConstructor(desc: String, declared: Boolean): Constructor<*>? {
val parameterTypes = arrayListOf<Class<*>>() val parameterTypes = arrayListOf<Class<*>>()
addParametersAndMasks(parameterTypes, desc) addParametersAndMasks(parameterTypes, desc, true)
parameterTypes.add(DEFAULT_CONSTRUCTOR_MARKER)
return jClass.tryGetConstructor(parameterTypes, declared) return jClass.tryGetConstructor(parameterTypes, declared)
} }
private fun addParametersAndMasks(result: MutableList<Class<*>>, desc: String) { private fun addParametersAndMasks(result: MutableList<Class<*>>, desc: String, isConstructor: Boolean) {
val valueParameters = loadParameterTypes(desc) val valueParameters = loadParameterTypes(desc)
result.addAll(valueParameters) result.addAll(valueParameters)
repeat((valueParameters.size + Integer.SIZE - 1) / Integer.SIZE) { repeat((valueParameters.size + Integer.SIZE - 1) / Integer.SIZE) {
result.add(Integer.TYPE) result.add(Integer.TYPE)
} }
result.add(if (isConstructor) DEFAULT_CONSTRUCTOR_MARKER else Any::class.java)
} }
private fun loadParameterTypes(desc: String): List<Class<*>> { private fun loadParameterTypes(desc: String): List<Class<*>> {