[JS IR BE] Skip external methods in js default arguments stub generators

This commit is contained in:
Svyatoslav Kuzmich
2019-02-26 17:21:33 +03:00
parent 8da076c1ed
commit e11fda1c49
3 changed files with 23 additions and 19 deletions
@@ -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)
@@ -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