From 616cec8527de9f4f8ea6c045f49fc4395e7932fc Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Wed, 15 Sep 2021 01:39:45 +0200 Subject: [PATCH] JVM IR: decouple JvmBackendContext from intrinsic implementation --- .../kotlin/backend/jvm/JvmIrCodegenFactory.kt | 9 ++++++++- .../kotlin/backend/jvm/lower/ReflectiveAccess.kt | 2 +- .../backend/jvm/lower/SyntheticAccessorLowering.kt | 5 +++-- .../jvm/lower/indy/LambdaMetafactoryArguments.kt | 2 +- .../jetbrains/kotlin/backend/jvm/IntrinsicMarker.kt | 8 ++++++++ .../kotlin/backend/jvm/JvmBackendContext.kt | 3 +-- .../kotlin/backend/jvm/codegen/ExpressionCodegen.kt | 13 +++++-------- .../backend/jvm/intrinsics/IntrinsicMethod.kt | 8 ++++++-- 8 files changed, 33 insertions(+), 17 deletions(-) create mode 100644 compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/IntrinsicMarker.kt diff --git a/compiler/ir/backend.jvm/entrypoint/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt b/compiler/ir/backend.jvm/entrypoint/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt index e47b42438bd..d396259ec48 100644 --- a/compiler/ir/backend.jvm/entrypoint/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt +++ b/compiler/ir/backend.jvm/entrypoint/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt @@ -8,7 +8,11 @@ package org.jetbrains.kotlin.backend.jvm import org.jetbrains.kotlin.analyzer.hasJdkCapability import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension import org.jetbrains.kotlin.backend.common.extensions.IrPluginContextImpl -import org.jetbrains.kotlin.backend.common.phaser.* +import org.jetbrains.kotlin.backend.common.phaser.CompilerPhase +import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig +import org.jetbrains.kotlin.backend.common.phaser.invokeToplevel +import org.jetbrains.kotlin.backend.common.phaser.then +import org.jetbrains.kotlin.backend.jvm.intrinsics.IrIntrinsicMethods import org.jetbrains.kotlin.backend.jvm.ir.getKtFile import org.jetbrains.kotlin.backend.jvm.serialization.JvmIdSignatureDescriptor import org.jetbrains.kotlin.codegen.CodegenFactory @@ -29,6 +33,7 @@ import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl import org.jetbrains.kotlin.ir.declarations.impl.IrModuleFragmentImpl import org.jetbrains.kotlin.ir.linkage.IrProvider +import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi2ir.Psi2IrConfiguration @@ -230,6 +235,8 @@ open class JvmIrCodegenFactory( val context = JvmBackendContext( state, irModuleFragment.irBuiltins, irModuleFragment, symbolTable, phaseConfig, extensions, backendExtension, irSerializer, ) + val intrinsics by lazy { IrIntrinsicMethods(irModuleFragment.irBuiltins, context.ir.symbols) } + context.getIntrinsic = { symbol: IrFunctionSymbol -> intrinsics.getIntrinsic(symbol) } /* JvmBackendContext creates new unbound symbols, have to resolve them. */ ExternalDependenciesGenerator(symbolTable, irProviders).generateUnboundSymbolsAsDependencies() diff --git a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/ReflectiveAccess.kt b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/ReflectiveAccess.kt index e1e0a3b1b64..d07549d6557 100644 --- a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/ReflectiveAccess.kt +++ b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/ReflectiveAccess.kt @@ -503,7 +503,7 @@ internal class ReflectiveAccessLowering( val builder = context.createJvmIrBuilder(expression.symbol) // invokeSpecial(owner: String, name: String, descriptor: String, isInterface: Boolean): T - return builder.irCall(context.ir.symbols.jvmDebuggerInvokeSpecialIntrinsic).apply { + return builder.irCall(symbols.jvmDebuggerInvokeSpecialIntrinsic).apply { dispatchReceiver = expression.dispatchReceiver this.type = expression.symbol.owner.returnType putValueArgument(0, builder.irString("${owner.packageFqName}/${owner.name}")) diff --git a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt index 7fe93cca1e8..a4698793e13 100644 --- a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt +++ b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt @@ -54,13 +54,14 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : FileL context: JvmBackendContext, currentScope: ScopeWithIr?, inlineScopeResolver: IrInlineScopeResolver, - withSuper: Boolean, thisObjReference: IrClassSymbol?): Boolean { + withSuper: Boolean, thisObjReference: IrClassSymbol?, + ): Boolean { /// We assume that IR code that reaches us has been checked for correctness at the frontend. /// This function needs to single out those cases where Java accessibility rules differ from Kotlin's. val declarationRaw = owner as IrDeclarationWithVisibility // If this expression won't actually result in a JVM instruction call, access modifiers don't matter. - if (declarationRaw is IrFunction && (declarationRaw.isInline || context.irIntrinsics.getIntrinsic(declarationRaw.symbol) != null)) + if (declarationRaw is IrFunction && (declarationRaw.isInline || context.getIntrinsic(declarationRaw.symbol) != null)) return true // Enum entry constructors are generated as package-private and are accessed only from corresponding enum class diff --git a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/indy/LambdaMetafactoryArguments.kt b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/indy/LambdaMetafactoryArguments.kt index 17b52e145c9..cdd24e7286d 100644 --- a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/indy/LambdaMetafactoryArguments.kt +++ b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/indy/LambdaMetafactoryArguments.kt @@ -133,7 +133,7 @@ internal class LambdaMetafactoryArgumentsBuilder( } // Don't generate references to intrinsic functions as invokedynamic (no such method exists at run-time). - if (context.irIntrinsics.getIntrinsic(implFun.symbol) != null) { + if (context.getIntrinsic(implFun.symbol) != null) { functionHazard = true } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/IntrinsicMarker.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/IntrinsicMarker.kt new file mode 100644 index 00000000000..5995d5b7f12 --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/IntrinsicMarker.kt @@ -0,0 +1,8 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.backend.jvm + +interface IntrinsicMarker diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt index d1517503eb7..1ea37715893 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt @@ -13,7 +13,6 @@ import org.jetbrains.kotlin.backend.common.ir.Ir import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig import org.jetbrains.kotlin.backend.jvm.caches.BridgeLoweringCache import org.jetbrains.kotlin.backend.jvm.caches.CollectionStubComputer -import org.jetbrains.kotlin.backend.jvm.intrinsics.IrIntrinsicMethods import org.jetbrains.kotlin.backend.jvm.mapping.IrTypeMapper import org.jetbrains.kotlin.backend.jvm.mapping.MethodSignatureMapper import org.jetbrains.kotlin.codegen.state.GenerationState @@ -75,7 +74,7 @@ class JvmBackendContext( override val sharedVariablesManager = JvmSharedVariablesManager(state.module, ir.symbols, irBuiltIns, irFactory) - val irIntrinsics by lazy { IrIntrinsicMethods(irBuiltIns, ir.symbols) } + lateinit var getIntrinsic: (IrFunctionSymbol) -> IntrinsicMarker? private val localClassType = ConcurrentHashMap() 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 90cfc0ad23b..5d879f67679 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 @@ -8,7 +8,7 @@ package org.jetbrains.kotlin.backend.jvm.codegen import org.jetbrains.kotlin.backend.common.lower.BOUND_RECEIVER_PARAMETER import org.jetbrains.kotlin.backend.common.lower.LoweredStatementOrigins import org.jetbrains.kotlin.backend.jvm.* -import org.jetbrains.kotlin.backend.jvm.intrinsics.IrIntrinsicMethods +import org.jetbrains.kotlin.backend.jvm.intrinsics.IntrinsicMethod import org.jetbrains.kotlin.backend.jvm.intrinsics.JavaClassProperty import org.jetbrains.kotlin.backend.jvm.ir.* import org.jetbrains.kotlin.backend.jvm.mapping.* @@ -455,11 +455,8 @@ class ExpressionCodegen( } override fun visitCall(expression: IrCall, data: BlockInfo): PromisedValue { - val intrinsic = classCodegen.context.irIntrinsics.getIntrinsic(expression.symbol) - if (intrinsic != null) { - intrinsic.invoke(expression, this, data) - ?.let { return it } - } + val intrinsic = classCodegen.context.getIntrinsic(expression.symbol) as IntrinsicMethod? + intrinsic?.invoke(expression, this, data)?.let { return it } val callee = expression.symbol.owner require(callee.parent is IrClass) { "Unhandled intrinsic in ExpressionCodegen: ${callee.render()}" } @@ -598,8 +595,8 @@ class ExpressionCodegen( } override fun visitConstructorCall(expression: IrConstructorCall, data: BlockInfo): PromisedValue { - classCodegen.context.irIntrinsics.getIntrinsic(expression.symbol) - ?.invoke(expression, this, data)?.let { return it } + val intrinsic = classCodegen.context.getIntrinsic(expression.symbol) as IntrinsicMethod? + intrinsic?.invoke(expression, this, data)?.let { return it } val callee = expression.symbol.owner val owner = typeMapper.mapClass(callee.constructedClass) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IntrinsicMethod.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IntrinsicMethod.kt index 53af142f651..372ed7494be 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IntrinsicMethod.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IntrinsicMethod.kt @@ -5,8 +5,12 @@ package org.jetbrains.kotlin.backend.jvm.intrinsics +import org.jetbrains.kotlin.backend.jvm.IntrinsicMarker import org.jetbrains.kotlin.backend.jvm.JvmBackendContext -import org.jetbrains.kotlin.backend.jvm.codegen.* +import org.jetbrains.kotlin.backend.jvm.codegen.BlockInfo +import org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen +import org.jetbrains.kotlin.backend.jvm.codegen.MaterialValue +import org.jetbrains.kotlin.backend.jvm.codegen.PromisedValue import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression @@ -14,7 +18,7 @@ import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.commons.Method -abstract class IntrinsicMethod { +abstract class IntrinsicMethod : IntrinsicMarker { open fun toCallable( expression: IrFunctionAccessExpression, signature: JvmMethodSignature,