[JS IR BE] Skip external methods in js default arguments stub generators
This commit is contained in:
+21
-17
@@ -42,7 +42,8 @@ val jvmDefaultArgumentStubPhase = makeIrFilePhase(
|
|||||||
|
|
||||||
open class DefaultArgumentStubGenerator(
|
open class DefaultArgumentStubGenerator(
|
||||||
open val context: CommonBackendContext,
|
open val context: CommonBackendContext,
|
||||||
private val skipInlineMethods: Boolean = true
|
private val skipInlineMethods: Boolean = true,
|
||||||
|
private val skipExternalMethods: Boolean = false
|
||||||
) : DeclarationContainerLoweringPass {
|
) : DeclarationContainerLoweringPass {
|
||||||
|
|
||||||
override fun lower(irDeclarationContainer: IrDeclarationContainer) {
|
override fun lower(irDeclarationContainer: IrDeclarationContainer) {
|
||||||
@@ -57,7 +58,7 @@ open class DefaultArgumentStubGenerator(
|
|||||||
private val symbols get() = context.ir.symbols
|
private val symbols get() = context.ir.symbols
|
||||||
|
|
||||||
private fun lower(irFunction: IrFunction): List<IrFunction> {
|
private fun lower(irFunction: IrFunction): List<IrFunction> {
|
||||||
if (!irFunction.needsDefaultArgumentsLowering(skipInlineMethods))
|
if (!irFunction.needsDefaultArgumentsLowering(skipInlineMethods, skipExternalMethods))
|
||||||
return listOf(irFunction)
|
return listOf(irFunction)
|
||||||
|
|
||||||
val bodies = irFunction.valueParameters.mapNotNull { it.defaultValue }
|
val bodies = irFunction.valueParameters.mapNotNull { it.defaultValue }
|
||||||
@@ -67,13 +68,13 @@ open class DefaultArgumentStubGenerator(
|
|||||||
|
|
||||||
if (bodies.isEmpty()) {
|
if (bodies.isEmpty()) {
|
||||||
// Fake override
|
// Fake override
|
||||||
val newIrFunction = irFunction.generateDefaultsFunction(context, IrDeclarationOrigin.FAKE_OVERRIDE, skipInlineMethods)
|
val newIrFunction = irFunction.generateDefaultsFunction(context, IrDeclarationOrigin.FAKE_OVERRIDE, skipInlineMethods, skipExternalMethods)
|
||||||
|
|
||||||
return listOf(irFunction, newIrFunction)
|
return listOf(irFunction, newIrFunction)
|
||||||
}
|
}
|
||||||
|
|
||||||
val newIrFunction =
|
val newIrFunction =
|
||||||
irFunction.generateDefaultsFunction(context, IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER, skipInlineMethods)
|
irFunction.generateDefaultsFunction(context, IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER, skipInlineMethods, skipExternalMethods)
|
||||||
|
|
||||||
log { "$irFunction -> $newIrFunction" }
|
log { "$irFunction -> $newIrFunction" }
|
||||||
val builder = context.createIrBuilder(newIrFunction.symbol)
|
val builder = context.createIrBuilder(newIrFunction.symbol)
|
||||||
@@ -209,7 +210,8 @@ val DEFAULT_DISPATCH_CALL = object : IrStatementOriginImpl("DEFAULT_DISPATCH_CAL
|
|||||||
|
|
||||||
open class DefaultParameterInjector(
|
open class DefaultParameterInjector(
|
||||||
val context: CommonBackendContext,
|
val context: CommonBackendContext,
|
||||||
private val skipInline: Boolean = true
|
private val skipInline: Boolean = true,
|
||||||
|
private val skipExternalMethods: Boolean = false
|
||||||
) : FileLoweringPass {
|
) : FileLoweringPass {
|
||||||
|
|
||||||
override fun lower(irFile: IrFile) {
|
override fun lower(irFile: IrFile) {
|
||||||
@@ -219,7 +221,7 @@ open class DefaultParameterInjector(
|
|||||||
|
|
||||||
val declaration = expression.symbol.owner as IrFunction
|
val declaration = expression.symbol.owner as IrFunction
|
||||||
|
|
||||||
if (!declaration.needsDefaultArgumentsLowering(skipInline))
|
if (!declaration.needsDefaultArgumentsLowering(skipInline, skipExternalMethods))
|
||||||
return expression
|
return expression
|
||||||
|
|
||||||
val argumentsCount = argumentCount(expression)
|
val argumentsCount = argumentCount(expression)
|
||||||
@@ -250,7 +252,7 @@ open class DefaultParameterInjector(
|
|||||||
super.visitCall(expression)
|
super.visitCall(expression)
|
||||||
val functionDeclaration = expression.symbol.owner
|
val functionDeclaration = expression.symbol.owner
|
||||||
|
|
||||||
if (!functionDeclaration.needsDefaultArgumentsLowering(skipInline))
|
if (!functionDeclaration.needsDefaultArgumentsLowering(skipInline, skipExternalMethods))
|
||||||
return expression
|
return expression
|
||||||
|
|
||||||
val argumentsCount = argumentCount(expression)
|
val argumentsCount = argumentCount(expression)
|
||||||
@@ -293,7 +295,7 @@ open class DefaultParameterInjector(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun IrFunction.findSuperMethodWithDefaultArguments(): IrFunction? {
|
private fun IrFunction.findSuperMethodWithDefaultArguments(): IrFunction? {
|
||||||
if (!needsDefaultArgumentsLowering(skipInline)) return null
|
if (!needsDefaultArgumentsLowering(skipInline, skipExternalMethods)) return null
|
||||||
|
|
||||||
if (this !is IrSimpleFunction) return this
|
if (this !is IrSimpleFunction) return this
|
||||||
|
|
||||||
@@ -309,7 +311,7 @@ open class DefaultParameterInjector(
|
|||||||
|
|
||||||
val keyFunction = declaration.findSuperMethodWithDefaultArguments()!!
|
val keyFunction = declaration.findSuperMethodWithDefaultArguments()!!
|
||||||
val realFunction =
|
val realFunction =
|
||||||
keyFunction.generateDefaultsFunction(context, IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER, skipInline)
|
keyFunction.generateDefaultsFunction(context, IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER, skipInline, skipExternalMethods)
|
||||||
|
|
||||||
log { "$declaration -> $realFunction" }
|
log { "$declaration -> $realFunction" }
|
||||||
val maskValues = Array((declaration.valueParameters.size + 31) / 32) { 0 }
|
val maskValues = Array((declaration.valueParameters.size + 31) / 32) { 0 }
|
||||||
@@ -389,20 +391,21 @@ class DefaultParameterCleaner constructor(val context: CommonBackendContext) : F
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO this implementation is exponential
|
// TODO this implementation is exponential
|
||||||
private fun IrFunction.needsDefaultArgumentsLowering(skipInlineMethods: Boolean): Boolean {
|
private fun IrFunction.needsDefaultArgumentsLowering(skipInlineMethods: Boolean, skipExternalMethods: Boolean): Boolean {
|
||||||
if (isInline && skipInlineMethods) return false
|
if (isInline && skipInlineMethods) return false
|
||||||
if (isEffectivelyExternal()) return false
|
if (skipExternalMethods && isEffectivelyExternal()) return false
|
||||||
if (valueParameters.any { it.defaultValue != null }) return true
|
if (valueParameters.any { it.defaultValue != null }) return true
|
||||||
|
|
||||||
if (this !is IrSimpleFunction) return false
|
if (this !is IrSimpleFunction) return false
|
||||||
|
|
||||||
return overriddenSymbols.any { it.owner.needsDefaultArgumentsLowering(skipInlineMethods) }
|
return overriddenSymbols.any { it.owner.needsDefaultArgumentsLowering(skipInlineMethods, skipExternalMethods) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrFunction.generateDefaultsFunctionImpl(
|
private fun IrFunction.generateDefaultsFunctionImpl(
|
||||||
context: CommonBackendContext,
|
context: CommonBackendContext,
|
||||||
origin: IrDeclarationOrigin,
|
origin: IrDeclarationOrigin,
|
||||||
skipInlineMethods: Boolean
|
skipInlineMethods: Boolean,
|
||||||
|
skipExternalMethods: Boolean
|
||||||
): IrFunction {
|
): IrFunction {
|
||||||
val newFunction = buildFunctionDeclaration(this, origin)
|
val newFunction = buildFunctionDeclaration(this, origin)
|
||||||
|
|
||||||
@@ -440,13 +443,13 @@ private fun IrFunction.generateDefaultsFunctionImpl(
|
|||||||
if (origin == IrDeclarationOrigin.FAKE_OVERRIDE) {
|
if (origin == IrDeclarationOrigin.FAKE_OVERRIDE) {
|
||||||
for (baseFunSymbol in (this as IrSimpleFunction).overriddenSymbols) {
|
for (baseFunSymbol in (this as IrSimpleFunction).overriddenSymbols) {
|
||||||
val baseFun = baseFunSymbol.owner
|
val baseFun = baseFunSymbol.owner
|
||||||
if (baseFun.needsDefaultArgumentsLowering(skipInlineMethods)) {
|
if (baseFun.needsDefaultArgumentsLowering(skipInlineMethods, skipExternalMethods)) {
|
||||||
val baseOrigin = if (baseFun.valueParameters.any { it.defaultValue != null }) {
|
val baseOrigin = if (baseFun.valueParameters.any { it.defaultValue != null }) {
|
||||||
IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER
|
IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER
|
||||||
} else {
|
} else {
|
||||||
IrDeclarationOrigin.FAKE_OVERRIDE
|
IrDeclarationOrigin.FAKE_OVERRIDE
|
||||||
}
|
}
|
||||||
val defaultsBaseFun = baseFun.generateDefaultsFunction(context, baseOrigin, skipInlineMethods)
|
val defaultsBaseFun = baseFun.generateDefaultsFunction(context, baseOrigin, skipInlineMethods, skipExternalMethods)
|
||||||
(newFunction as IrSimpleFunction).overriddenSymbols.add((defaultsBaseFun as IrSimpleFunction).symbol)
|
(newFunction as IrSimpleFunction).overriddenSymbols.add((defaultsBaseFun as IrSimpleFunction).symbol)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -504,10 +507,11 @@ private fun buildFunctionDeclaration(irFunction: IrFunction, origin: IrDeclarati
|
|||||||
private fun IrFunction.generateDefaultsFunction(
|
private fun IrFunction.generateDefaultsFunction(
|
||||||
context: CommonBackendContext,
|
context: CommonBackendContext,
|
||||||
origin: IrDeclarationOrigin,
|
origin: IrDeclarationOrigin,
|
||||||
skipInlineMethods: Boolean
|
skipInlineMethods: Boolean,
|
||||||
|
skipExternalMethods: Boolean
|
||||||
): IrFunction =
|
): IrFunction =
|
||||||
context.ir.defaultParameterDeclarationsCache.getOrPut(this) {
|
context.ir.defaultParameterDeclarationsCache.getOrPut(this) {
|
||||||
generateDefaultsFunctionImpl(context, origin, skipInlineMethods)
|
generateDefaultsFunctionImpl(context, origin, skipInlineMethods, skipExternalMethods)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrFunction.valueParameter(index: Int, name: Name, type: IrType): IrValueParameter {
|
private fun IrFunction.valueParameter(index: Int, name: Name, type: IrType): IrValueParameter {
|
||||||
|
|||||||
@@ -225,7 +225,7 @@ private val defaultArgumentStubGeneratorPhase = makeJsModulePhase(
|
|||||||
)
|
)
|
||||||
|
|
||||||
private val defaultParameterInjectorPhase = makeJsModulePhase(
|
private val defaultParameterInjectorPhase = makeJsModulePhase(
|
||||||
::DefaultParameterInjector,
|
{ context -> DefaultParameterInjector(context, skipExternalMethods = true) },
|
||||||
name = "DefaultParameterInjector",
|
name = "DefaultParameterInjector",
|
||||||
description = "Replace callsite with default parameters with corresponding stub function",
|
description = "Replace callsite with default parameters with corresponding stub function",
|
||||||
prerequisite = setOf(callableReferenceLoweringPhase, innerClassesLoweringPhase)
|
prerequisite = setOf(callableReferenceLoweringPhase, innerClassesLoweringPhase)
|
||||||
|
|||||||
+1
-1
@@ -27,7 +27,7 @@ import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
|||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
class JsDefaultArgumentStubGenerator(override val context: JsIrBackendContext) : DefaultArgumentStubGenerator(context, true) {
|
class JsDefaultArgumentStubGenerator(override val context: JsIrBackendContext) : DefaultArgumentStubGenerator(context, true, false) {
|
||||||
|
|
||||||
override fun needSpecialDispatch(irFunction: IrSimpleFunction) = irFunction.isOverridableOrOverrides
|
override fun needSpecialDispatch(irFunction: IrSimpleFunction) = irFunction.isOverridableOrOverrides
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user