From 1543accf40bec92b84509888c25d681191dc5cb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steven=20Sch=C3=A4fer?= Date: Tue, 6 Aug 2019 11:38:46 +0200 Subject: [PATCH] JVM IR: Remove vararg handling from ExpressionCodegen --- .../backend/jvm/codegen/ExpressionCodegen.kt | 143 ++---------------- .../kotlin/backend/jvm/intrinsics/ArrayOf.kt | 29 ---- .../jvm/intrinsics/IrIntrinsicMethods.kt | 2 - .../kotlin/backend/jvm/intrinsics/NewArray.kt | 17 ++- 4 files changed, 28 insertions(+), 163 deletions(-) delete mode 100644 compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArrayOf.kt diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt index 06d1a02d302..bd57694c758 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt @@ -352,27 +352,27 @@ class ExpressionCodegen( } expression.descriptor is ConstructorDescriptor -> throw AssertionError("IrCall with ConstructorDescriptor: ${expression.javaClass.simpleName}") - callee.isSuspend && !irFunction.isInvokeSuspendInContinuation() -> addInlineMarker(mv, isStartNotEnd = true) + callee.isSuspend && !irFunction.isInvokeSuspendInContinuation() -> + addInlineMarker(mv, isStartNotEnd = true) } - val receiver = expression.dispatchReceiver - receiver?.apply { + expression.dispatchReceiver?.let { receiver -> callGenerator.genValueAndPut( callee.dispatchReceiverParameter!!, - this, + receiver, if (isSuperCall) receiver.asmType else callable.dispatchReceiverType ?: throw AssertionError("No dispatch receiver type: ${expression.render()}"), - this@ExpressionCodegen, + this, data ) } - expression.extensionReceiver?.apply { + expression.extensionReceiver?.let { receiver -> callGenerator.genValueAndPut( callee.extensionReceiverParameter!!, - this, + receiver, callable.extensionReceiverType!!, - this@ExpressionCodegen, + this, data ) } @@ -381,25 +381,8 @@ class ExpressionCodegen( expression.symbol.owner.valueParameters.forEachIndexed { i, irParameter -> val arg = expression.getValueArgument(i) val parameterType = callable.valueParameterTypes[i] - when { - arg != null -> { - callGenerator.genValueAndPut(irParameter, arg, parameterType, this@ExpressionCodegen, data) - } - else -> { - assert(irParameter.varargElementType != null) - val type = typeMapper.mapType( - irParameter.type.substitute(typeSubstitutionMap) - ) - callGenerator.putValueIfNeeded( - parameterType, - StackValue.operation(type) { - it.aconst(0) - it.newarray(correctElementType(type)) - }, - ValueKind.GENERAL_VARARG, i, this@ExpressionCodegen - ) - } - } + require(arg != null) { "Null argument in ExpressionCodegen for parameter ${irParameter.render()}" } + callGenerator.genValueAndPut(irParameter, arg, parameterType, this, data) } expression.markLineNumber(true) @@ -409,19 +392,14 @@ class ExpressionCodegen( addSuspendMarker(mv, isStartNotEnd = true) } - callGenerator.genCall( - callable, - this, - expression - ) - - val returnType = callee.returnType + callGenerator.genCall(callable, this, expression) if (callee.isSuspend && !irFunction.isInvokeSuspendInContinuation()) { addSuspendMarker(mv, isStartNotEnd = false) addInlineMarker(mv, isStartNotEnd = false) } + val returnType = callee.returnType return when { returnType.substitute(expression.typeSubstitutionMap).isNothing() -> { mv.aconst(null) @@ -581,101 +559,6 @@ class ExpressionCodegen( return immaterialUnitValue } - override fun visitVararg(expression: IrVararg, data: BlockInfo): PromisedValue { - expression.markLineNumber(startOffset = true) - val outType = expression.type - val type = expression.asmType - assert(type.sort == Type.ARRAY) - val elementType = correctElementType(type) - val arguments = expression.elements - val size = arguments.size - - val hasSpread = arguments.firstIsInstanceOrNull() != null - - if (hasSpread) { - val arrayOfReferences = outType.makeNotNull().isArray() - if (size == 1) { - // Arrays.copyOf(receiverValue, newLength) - val argument = (arguments[0] as IrSpreadElement).expression - val arrayType = if (arrayOfReferences) - Type.getType("[Ljava/lang/Object;") - else - Type.getType("[" + elementType.descriptor) - argument.accept(this, data).coerce(type, argument.type).materialize() - mv.dup() - mv.arraylength() - mv.invokestatic("java/util/Arrays", "copyOf", Type.getMethodDescriptor(arrayType, arrayType, Type.INT_TYPE), false) - if (arrayOfReferences) { - mv.checkcast(type) - } - } else { - val owner: String - val addDescriptor: String - val toArrayDescriptor: String - if (arrayOfReferences) { - owner = "kotlin/jvm/internal/SpreadBuilder" - addDescriptor = "(Ljava/lang/Object;)V" - toArrayDescriptor = "([Ljava/lang/Object;)[Ljava/lang/Object;" - } else { - val spreadBuilderClassName = - asmPrimitiveTypeToLangPrimitiveType(elementType)!!.typeName.identifier + "SpreadBuilder" - owner = "kotlin/jvm/internal/$spreadBuilderClassName" - addDescriptor = "(" + elementType.descriptor + ")V" - toArrayDescriptor = "()" + type.descriptor - } - mv.anew(Type.getObjectType(owner)) - mv.dup() - mv.iconst(size) - mv.invokespecial(owner, "", "(I)V", false) - for (i in 0 until size) { - mv.dup() - val argument = arguments[i] - if (argument is IrSpreadElement) { - argument.expression.accept(this, data).coerce(OBJECT_TYPE, argument.expression.type).materialize() - mv.invokevirtual(owner, "addSpread", "(Ljava/lang/Object;)V", false) - } else { - argument.accept(this, data).coerce(elementType, expression.varargElementType).materialize() - mv.invokevirtual(owner, "add", addDescriptor, false) - } - } - if (arrayOfReferences) { - mv.dup() - mv.invokevirtual(owner, "size", "()I", false) - newArrayInstruction(outType) - mv.invokevirtual(owner, "toArray", toArrayDescriptor, false) - mv.checkcast(type) - } else { - mv.invokevirtual(owner, "toArray", toArrayDescriptor, false) - } - } - } else { - mv.iconst(size) - newArrayInstruction(expression.type) - for ((i, element) in expression.elements.withIndex()) { - mv.dup() - mv.iconst(i) - element.accept(this, data).coerce(elementType, expression.varargElementType).materialize() - mv.astore(elementType) - } - } - return expression.onStack - } - - fun newArrayInstruction(arrayType: IrType) { - if (arrayType.isArray()) { - val elementIrType = arrayType.safeAs()!!.arguments[0].safeAs()!!.type - putReifiedOperationMarkerIfTypeIsReifiedParameter( - elementIrType, - ReifiedTypeInliner.OperationKind.NEW_ARRAY, - mv, - this - ) - mv.newarray(typeMapper.boxType(elementIrType)) - } else { - mv.newarray(correctElementType(arrayType.asmType)) - } - } - override fun visitReturn(expression: IrReturn, data: BlockInfo): PromisedValue { val returnTarget = expression.returnTargetSymbol.owner val owner = @@ -1224,7 +1107,7 @@ class ExpressionCodegen( } /* From ExpressionCodegen.java */ - private fun putReifiedOperationMarkerIfTypeIsReifiedParameter( + fun putReifiedOperationMarkerIfTypeIsReifiedParameter( type: IrType, operationKind: ReifiedTypeInliner.OperationKind, v: InstructionAdapter, codegen: ExpressionCodegen? ) { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArrayOf.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArrayOf.kt deleted file mode 100644 index 4f5578e607a..00000000000 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArrayOf.kt +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2010-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.backend.jvm.intrinsics - -import org.jetbrains.kotlin.backend.jvm.JvmBackendContext -import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression -import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature - -object ArrayOf : IntrinsicMethod() { - override fun toCallable(expression: IrFunctionAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction { - return IrIntrinsicFunction.create(expression, signature, context, signature.returnType) { - //do nothing all generated as vararg - } - } -} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrIntrinsicMethods.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrIntrinsicMethods.kt index 2c3e835db23..bf427b737b0 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrIntrinsicMethods.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrIntrinsicMethods.kt @@ -70,7 +70,6 @@ class IrIntrinsicMethods(val irBuiltIns: IrBuiltIns, val symbols: JvmSymbols) { "isArrayOf", emptyList() ) to IsArrayOf, - symbols.arrayOf.toKey() to ArrayOf, Key( KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME, KotlinBuiltIns.FQ_NAMES.any.toSafe(), @@ -113,7 +112,6 @@ class IrIntrinsicMethods(val irBuiltIns: IrBuiltIns, val symbols: JvmSymbols) { unaryFunForPrimitives("hashCode", HashCode) + unaryFunForPrimitives("toString", ToString) + binaryFunForPrimitives("equals", EQUALS, irBuiltIns.anyClass) + - symbols.primitiveArrayOfByType.values.map { it.toKey() to ArrayOf } + binaryFunForPrimitivesAcrossPrimitives("rangeTo", RangeTo) + binaryOp("plus", IADD) + binaryOp("minus", ISUB) + diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/NewArray.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/NewArray.kt index 3706c8c1dd0..ab3b2005263 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/NewArray.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/NewArray.kt @@ -8,13 +8,26 @@ package org.jetbrains.kotlin.backend.jvm.intrinsics import org.jetbrains.kotlin.backend.jvm.codegen.BlockInfo import org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen import org.jetbrains.kotlin.backend.jvm.codegen.PromisedValue +import org.jetbrains.kotlin.backend.jvm.ir.getArrayElementType +import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression +import org.jetbrains.kotlin.ir.types.isArray import org.jetbrains.org.objectweb.asm.Type object NewArray : IntrinsicMethod() { override fun invoke(expression: IrFunctionAccessExpression, codegen: ExpressionCodegen, data: BlockInfo): PromisedValue? { codegen.gen(expression.getValueArgument(0)!!, Type.INT_TYPE, codegen.context.irBuiltIns.intType, data) - codegen.newArrayInstruction(expression.type) - return with(codegen) { expression.onStack } + return with(codegen) { + val elementIrType = expression.type.getArrayElementType(context.irBuiltIns) + if (expression.type.isArray()) { + putReifiedOperationMarkerIfTypeIsReifiedParameter( + elementIrType, ReifiedTypeInliner.OperationKind.NEW_ARRAY, mv, this + ) + mv.newarray(typeMapper.boxType(elementIrType)) + } else { + mv.newarray(typeMapper.mapType(elementIrType)) + } + expression.onStack + } } }