JVM IR: decouple JvmBackendContext from intrinsic implementation

This commit is contained in:
Alexander Udalov
2021-09-15 01:39:45 +02:00
parent 3582188faa
commit 616cec8527
8 changed files with 33 additions and 17 deletions
@@ -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()
@@ -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}"))
@@ -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
@@ -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
}
@@ -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
@@ -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<IrAttributeContainer, Type>()
@@ -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)
@@ -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,