Callable methods to properties

This commit is contained in:
Michael Bogdanov
2015-04-04 12:19:15 +03:00
parent 45d5a86468
commit 05aa80e7f1
18 changed files with 81 additions and 110 deletions
@@ -26,26 +26,26 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
public trait Callable {
public fun getOwner(): Type
public val owner: Type
public val thisType: Type?
public val receiverType: Type?
public val generateCalleeType: Type?
public val valueParameterTypes: List<Type>
public val argumentTypes: Array<Type>
public val returnType: Type
public fun invokeWithNotNullAssertion(v: InstructionAdapter, state: GenerationState, resolvedCall: ResolvedCall<*>)
public fun invokeWithoutAssertions(v: InstructionAdapter)
public fun getGenerateCalleeType(): Type?
public fun getValueParameterTypes(): List<Type>
public fun getArgumentTypes(): Array<Type>
public fun getReturnType(): Type
public fun isStaticCall(): Boolean
public fun getThisType(): Type?
public fun getReceiverClass(): Type?
public fun beforeParameterGeneration(v: InstructionAdapter, value: StackValue?)
public fun invokeMethodWithArguments(resolvedCall: ResolvedCall<*>, receiver: StackValue, returnType: Type, codegen: ExpressionCodegen): StackValue
@@ -38,42 +38,31 @@ import org.jetbrains.org.objectweb.asm.util.Printer;
import java.util.ArrayList;
public class CallableMethod(private val owner: Type, private val defaultImplOwner: Type?, private val defaultImplParam: Type?, private val signature: JvmMethodSignature, private val invokeOpcode: Int, private val thisClass: Type?, private val receiverParameterType: Type?, private val generateCalleeType: Type?) : Callable {
public class CallableMethod(override val owner: Type, private val defaultImplOwner: Type?, private val defaultImplParam: Type?, private val signature: JvmMethodSignature, private val invokeOpcode: Int, override val thisType: Type?, override val receiverType: Type?, override val generateCalleeType: Type?) : Callable {
override fun getOwner(): Type {
return owner
}
public fun getValueParameters(): List<JvmMethodParameterSignature> {
return signature.getValueParameters()
}
override fun getValueParameterTypes(): List<Type> {
val valueParameters = signature.getValueParameters()
val result = ArrayList<Type>(valueParameters.size())
for (parameter in valueParameters) {
if (parameter.getKind() == JvmMethodParameterKind.VALUE) {
result.add(parameter.getAsmType())
override val valueParameterTypes: List<Type>
get() {
val valueParameters = signature.getValueParameters()
val result = ArrayList<Type>(valueParameters.size())
for (parameter in valueParameters) {
if (parameter.getKind() == JvmMethodParameterKind.VALUE) {
result.add(parameter.getAsmType())
}
}
return result
}
return result
}
public fun getAsmMethod(): Method {
return signature.getAsmMethod()
}
override fun getArgumentTypes(): Array<Type> {
return signature.getAsmMethod().getArgumentTypes()
}
override fun getThisType(): Type? {
return thisClass
}
override fun getReceiverClass(): Type? {
return receiverParameterType
}
override val argumentTypes: Array<Type>
get() =signature.getAsmMethod().getArgumentTypes()
private fun invoke(v: InstructionAdapter) {
v.visitMethodInsn(invokeOpcode, owner.getInternalName(), getAsmMethod().getName(), getAsmMethod().getDescriptor())
@@ -89,10 +78,6 @@ public class CallableMethod(private val owner: Type, private val defaultImplOwne
invoke(v)
}
override fun getGenerateCalleeType(): Type? {
return generateCalleeType
}
private fun invokeDefault(v: InstructionAdapter) {
if (defaultImplOwner == null || defaultImplParam == null) {
throw IllegalStateException()
@@ -100,8 +85,8 @@ public class CallableMethod(private val owner: Type, private val defaultImplOwne
val method = getAsmMethod();
val desc = JetTypeMapper.getDefaultDescriptor(method,
if (invokeOpcode == INVOKESTATIC) null else defaultImplParam.getDescriptor(),
receiverParameterType != null);
if (invokeOpcode == INVOKESTATIC) null else defaultImplParam.getDescriptor(),
receiverType != null);
if ("<init>".equals(method.getName())) {
v.aconst(null)
@@ -118,9 +103,10 @@ public class CallableMethod(private val owner: Type, private val defaultImplOwne
AsmUtil.genNotNullAssertionForMethod(v, state, resolvedCall)
}
override fun getReturnType(): Type {
return signature.getReturnType()
}
override val returnType: Type
get() {
return signature.getReturnType()
}
override fun toString(): String {
return Printer.OPCODES[invokeOpcode] + " " + owner.getInternalName() + "." + signature
@@ -130,7 +116,6 @@ public class CallableMethod(private val owner: Type, private val defaultImplOwne
return invokeOpcode == INVOKESTATIC
}
public override fun beforeParameterGeneration(v: InstructionAdapter, value: StackValue?) {
}
@@ -136,7 +136,7 @@ public class DefaultParameterValueSubstitutor(val state: GenerationState) {
val v = InstructionAdapter(mv)
mv.visitCode()
val methodOwner = typeMapper.mapToCallableMethod(delegateFunctionDescriptor, false, context).getOwner()
val methodOwner = typeMapper.mapToCallableMethod(delegateFunctionDescriptor, false, context).owner
if (!isStatic) {
val thisIndex = frameMap.enterTemp(AsmTypes.OBJECT_TYPE)
v.load(thisIndex, methodOwner) // Load this on stack
@@ -1275,7 +1275,7 @@ public abstract class StackValue {
ReceiverParameterDescriptor extensionReceiver = descriptor.getExtensionReceiverParameter();
if (extensionReceiver != null) {
return callableMethod != null ? callableMethod.getReceiverClass() : typeMapper.mapType(extensionReceiver.getType());
return callableMethod != null ? callableMethod.getReceiverType() : typeMapper.mapType(extensionReceiver.getType());
}
else if (dispatchReceiver != null) {
if (AnnotationsPackage.isPlatformStaticInObjectOrClass(descriptor)) {
@@ -74,13 +74,13 @@ public class TailRecursionCodegen {
throw new IllegalStateException("Failed to arrange value arguments by index: " + fd);
}
assignParameterValues(fd, callable, arguments);
if (callable.getReceiverClass() != null) {
if (callable.getReceiverType() != null) {
if (resolvedCall.getExtensionReceiver() != fd.getExtensionReceiverParameter().getValue()) {
StackValue expression = context.getReceiverExpression(codegen.typeMapper);
expression.store(StackValue.onStack(callable.getReceiverClass()), v, true);
expression.store(StackValue.onStack(callable.getReceiverType()), v, true);
}
else {
AsmUtil.pop(v, callable.getReceiverClass());
AsmUtil.pop(v, callable.getReceiverType());
}
}
@@ -25,8 +25,8 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
public class ArraySet : IntrinsicMethod() {
override fun toCallable(method: CallableMethod): Callable {
val type = correctElementType(method.getThisType())
return object: IntrinsicCallable(Type.VOID_TYPE, listOf(Type.INT_TYPE, type), method.getThisType(), method.getReceiverClass()) {
val type = correctElementType(method.thisType)
return object: IntrinsicCallable(Type.VOID_TYPE, listOf(Type.INT_TYPE, type), method.thisType, method.receiverType) {
override fun invokeIntrinsic(v: InstructionAdapter) {
v.astore(type)
}
@@ -31,13 +31,13 @@ public class BinaryOp(private val opcode: Int) : IntrinsicMethod() {
}
override fun toCallable(method: CallableMethod): Callable {
val returnType = method.getReturnType()
val returnType = method.returnType
assert(method.getValueParameters().size() == 1)
val operandType = numberFunctionOperandType(returnType)
val paramType = if (shift()) Type.INT_TYPE else operandType
return IntrinsicCallable.binaryIntrinsic(operandType, paramType, operandType) {
v -> v.visitInsn(getReturnType().getOpcode(opcode))
v -> v.visitInsn(returnType.getOpcode(opcode))
}
}
}
@@ -43,8 +43,8 @@ public class CompareTo : IntrinsicMethod() {
}
override fun toCallable(method: CallableMethod): Callable {
val argumentType = comparisonOperandType(method.getThisType() ?: method.getReceiverClass(), method.getArgumentTypes().first())
return IntrinsicCallable.binaryIntrinsic(method.getReturnType(), argumentType, argumentType, null) {
val argumentType = comparisonOperandType(method.thisType ?: method.receiverType, method.argumentTypes.first())
return IntrinsicCallable.binaryIntrinsic(method.returnType, argumentType, argumentType, null) {
genInvoke(argumentType, it)
}
}
@@ -24,7 +24,7 @@ import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE
public class Equals : IntrinsicMethod() {
override fun toCallable(method: CallableMethod): Callable {
return IntrinsicCallable.binaryIntrinsic(method.getReturnType(), OBJECT_TYPE, nullOrObject(method.getThisType()), nullOrObject(method.getReceiverClass())) {
return IntrinsicCallable.binaryIntrinsic(method.returnType, OBJECT_TYPE, nullOrObject(method.thisType), nullOrObject(method.receiverType)) {
AsmUtil.genAreEqualCall(it)
}
}
@@ -25,7 +25,7 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
public class HashCode : IntrinsicMethod() {
override fun toCallable(method: CallableMethod): Callable {
return object: IntrinsicCallable(Type.INT_TYPE, emptyList(), nullOrObject(method.getThisType()), nullOrObject(method.getReceiverClass())) {
return object: IntrinsicCallable(Type.INT_TYPE, emptyList(), nullOrObject(method.thisType), nullOrObject(method.receiverType)) {
override fun invokeIntrinsic(v: InstructionAdapter) {
v.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "hashCode", "()I", false)
}
@@ -30,7 +30,7 @@ public class Increment(private val myDelta: Int) : IntrinsicMethod() {
return MappedCallable(method) {
val jetExpression = resolvedCall.getCall().getCalleeExpression()
assert(jetExpression !is JetPrefixExpression) { "There should be postfix increment ${jetExpression!!.getText()}" }
genIncrement(getReturnType(), myDelta, it)
genIncrement(returnType, myDelta, it)
}
}
}
@@ -25,10 +25,10 @@ import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
public abstract class IntrinsicCallable(val returnType1: Type,
val valueParametersTypes: List<Type>,
val thisType1: Type?,
val receiverType1: Type?) : Callable {
public abstract class IntrinsicCallable(override val returnType: Type,
override val valueParameterTypes: List<Type>,
override val thisType: Type?,
override val receiverType: Type?) : Callable {
companion object {
fun create(descriptor: FunctionDescriptor, context: CodegenContext<*>, state: GenerationState, lambda: IntrinsicCallable.(i: InstructionAdapter) -> Unit): IntrinsicCallable {
@@ -36,7 +36,7 @@ public abstract class IntrinsicCallable(val returnType1: Type,
}
fun create(callableMethod: CallableMethod, lambda: IntrinsicCallable.(i: InstructionAdapter) -> Unit): IntrinsicCallable {
return object : IntrinsicCallable(callableMethod.getReturnType(), callableMethod.getValueParameterTypes(), callableMethod.getThisType(), callableMethod.getReceiverClass()) {
return object : IntrinsicCallable(callableMethod.returnType, callableMethod.valueParameterTypes, callableMethod.thisType, callableMethod.receiverType) {
override fun invokeIntrinsic(v: InstructionAdapter) {
lambda(v)
}
@@ -56,7 +56,7 @@ public abstract class IntrinsicCallable(val returnType1: Type,
fun create(descriptor: FunctionDescriptor, context: CodegenContext<*>, state: GenerationState, receiverTransformer: Type.() -> Type, lambda: IntrinsicCallable.(i: InstructionAdapter) -> Unit): IntrinsicCallable {
val callableMethod = state.getTypeMapper().mapToCallableMethod(descriptor, false, context)
return object : IntrinsicCallable(callableMethod.getReturnType(), callableMethod.getValueParameterTypes(), callableMethod.getThisType()?.receiverTransformer(), callableMethod.getReceiverClass()?.receiverTransformer()) {
return object : IntrinsicCallable(callableMethod.returnType, callableMethod.valueParameterTypes, callableMethod.thisType?.receiverTransformer(), callableMethod.receiverType?.receiverTransformer()) {
override fun invokeIntrinsic(v: InstructionAdapter) {
lambda(v)
}
@@ -64,11 +64,6 @@ public abstract class IntrinsicCallable(val returnType1: Type,
}
}
override fun getValueParameterTypes(): List<Type> {
return valueParametersTypes
}
override fun invokeWithoutAssertions(v: InstructionAdapter) {
invokeIntrinsic(v)
}
@@ -79,36 +74,27 @@ public abstract class IntrinsicCallable(val returnType1: Type,
public abstract fun invokeIntrinsic(v: InstructionAdapter);
override fun getArgumentTypes(): Array<Type> {
throw UnsupportedOperationException()
}
override val argumentTypes: Array<Type>
get() {
throw UnsupportedOperationException()
}
override fun isStaticCall(): Boolean {
return false
}
override fun getGenerateCalleeType(): Type? {
return null
}
override val generateCalleeType: Type?
get() {
return null
}
override fun getReturnType(): Type {
return returnType1
}
override fun getThisType(): Type? {
return thisType1
}
override fun getReceiverClass(): Type? {
return receiverType1
}
override fun getOwner(): Type {
throw UnsupportedOperationException()
}
override val owner: Type
get() {
throw UnsupportedOperationException()
}
public fun calcReceiverType(): Type? {
return getReceiverClass() ?: getThisType()
return receiverType ?: thisType
}
override fun beforeParameterGeneration(v: InstructionAdapter, value: StackValue?) {
@@ -124,13 +110,13 @@ public abstract class IntrinsicCallable(val returnType1: Type,
public class UnaryIntrinsic(val callable: CallableMethod, val newReturnType: Type? = null, needPrimitiveCheck: Boolean = false, val newThisType: Type? = null, val invoke: UnaryIntrinsic.(v: InstructionAdapter) -> Unit) :
IntrinsicCallable(newReturnType ?: callable.getReturnType(), callable.getValueParameterTypes(), newThisType ?: callable.getThisType(), callable.getReceiverClass()) {
IntrinsicCallable(newReturnType ?: callable.returnType, callable.valueParameterTypes, newThisType ?: callable.thisType, callable.receiverType) {
{
if (needPrimitiveCheck) {
assert(AsmUtil.isPrimitive(getReturnType())) { "Return type of UnaryPlus intrinsic should be of primitive type : " + getReturnType() }
assert(AsmUtil.isPrimitive(returnType)) { "Return type of UnaryPlus intrinsic should be of primitive type : " + returnType }
}
assert(getValueParameterTypes().size == 0, "Unary operation should not have any parameters")
assert(valueParameterTypes.size == 0, "Unary operation should not have any parameters")
}
override fun invokeIntrinsic(v: InstructionAdapter) {
@@ -140,7 +126,7 @@ public class UnaryIntrinsic(val callable: CallableMethod, val newReturnType: Typ
}
public open class MappedCallable(val callable: CallableMethod, val invoke: MappedCallable.(v: InstructionAdapter) -> Unit = {}) :
IntrinsicCallable(callable.getReturnType(), callable.getValueParameterTypes(), callable.getThisType(), callable.getReceiverClass()) {
IntrinsicCallable(callable.returnType, callable.valueParameterTypes, callable.thisType, callable.receiverType) {
override fun invokeIntrinsic(v: InstructionAdapter) {
@@ -24,15 +24,15 @@ import org.jetbrains.org.objectweb.asm.Type
public class Inv : IntrinsicMethod() {
override fun toCallable(method: CallableMethod): Callable {
val type = numberFunctionOperandType(method.getReturnType())
return UnaryIntrinsic(method, method.getReturnType(), newThisType = type) {
if (getReturnType() == Type.LONG_TYPE) {
val type = numberFunctionOperandType(method.returnType)
return UnaryIntrinsic(method, method.returnType, newThisType = type) {
if (returnType == Type.LONG_TYPE) {
it.lconst(-1)
}
else {
it.iconst(-1)
}
it.xor(getReturnType())
it.xor(returnType)
}
}
}
@@ -63,7 +63,7 @@ public class IteratorNext : IntrinsicMethod() {
val type = state.getTypeMapper().mapReturnType(fd)
return object: IntrinsicCallable(type, listOf(), AsmTypes.OBJECT_TYPE, null) {
override fun invokeIntrinsic(v: InstructionAdapter) {
val returnType = getReturnType()
val returnType = returnType
val name = getIteratorName(returnType)
v.invokevirtual(BUILT_INS_PACKAGE_FQ_NAME.toString() + "/" + name + "Iterator", "next" + name, "()" + returnType.getDescriptor(), false)
}
@@ -24,7 +24,7 @@ public class NumberCast : IntrinsicMethod() {
override fun toCallable(method: CallableMethod): Callable {
return UnaryIntrinsic(method) {
StackValue.coerce(calcReceiverType()!!, getReturnType(), it)
StackValue.coerce(calcReceiverType()!!, returnType, it)
}
}
}
@@ -42,16 +42,16 @@ public class RangeTo : IntrinsicMethod() {
override fun toCallable(fd: FunctionDescriptor, isSuper: Boolean, resolvedCall: ResolvedCall<*>, codegen: ExpressionCodegen): Callable {
val method = codegen.getState().getTypeMapper().mapToCallableMethod(fd, false, codegen.getContext())
val argType = nameToPrimitive(method.getReturnType().getInternalName().substringAfter("kotlin/").substringBefore("Range"))
return object : IntrinsicCallable(method.getReturnType(), method.getValueParameterTypes().map { argType }, nullOr(method.getThisType(), argType), nullOr(method.getReceiverClass(), argType)) {
val argType = nameToPrimitive(method.returnType.getInternalName().substringAfter("kotlin/").substringBefore("Range"))
return object : IntrinsicCallable(method.returnType, method.valueParameterTypes.map { argType }, nullOr(method.thisType, argType), nullOr(method.receiverType, argType)) {
override fun beforeParameterGeneration(v: InstructionAdapter, value: StackValue?) {
v.anew(getReturnType())
v.anew(returnType)
v.dup()
value?.moveToTopOfStack(value!!.type, v, 2)
}
override fun invokeIntrinsic(v: InstructionAdapter) {
v.invokespecial(getReturnType().getInternalName(), "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, argType, argType), false)
v.invokespecial(returnType.getInternalName(), "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, argType, argType), false)
}
}
}
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.codegen.CallableMethod
public class ToString : IntrinsicMethod() {
override fun toCallable(method: CallableMethod): Callable {
val type = AsmUtil.stringValueOfType(method.getThisType() ?: method.getReceiverClass())
val type = AsmUtil.stringValueOfType(method.thisType ?: method.receiverType)
return UnaryIntrinsic(method, newThisType = type) {
it.invokestatic("java/lang/String", "valueOf", "(" + type.getDescriptor() + ")Ljava/lang/String;", false)
}
@@ -23,8 +23,8 @@ import org.jetbrains.kotlin.codegen.CallableMethod
public class UnaryMinus : IntrinsicMethod() {
override fun toCallable(method: CallableMethod): Callable {
return UnaryIntrinsic(method, numberFunctionOperandType(method.getReturnType()), needPrimitiveCheck = true) {
it.neg(getReturnType())
return UnaryIntrinsic(method, numberFunctionOperandType(method.returnType), needPrimitiveCheck = true) {
it.neg(returnType)
}
}
}