diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt index 63286e1026f..43291f4f9e8 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt @@ -23,15 +23,13 @@ import org.jetbrains.kotlin.ir.SourceManager import org.jetbrains.kotlin.ir.SourceRangeInfo import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.backend.js.lower.CallableReferenceKey +import org.jetbrains.kotlin.ir.backend.js.lower.ConstructorPair import org.jetbrains.kotlin.ir.backend.js.lower.inline.ModuleIndex import org.jetbrains.kotlin.ir.backend.js.utils.OperatorNames import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns -import org.jetbrains.kotlin.ir.symbols.IrClassSymbol -import org.jetbrains.kotlin.ir.symbols.IrEnumEntrySymbol -import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol -import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.types.impl.IrDynamicTypeImpl import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.ir.util.getPropertyDeclaration @@ -120,6 +118,7 @@ class JsIrBackendContext( val enumEntryToGetInstanceFunction = mutableMapOf() val enumEntryExternalToInstanceField = mutableMapOf() val callableReferencesCache = mutableMapOf() + val secondaryConstructorToFactoryCache = mutableMapOf() val coroutineGetContext: IrFunctionSymbol get() { @@ -241,6 +240,13 @@ class JsIrBackendContext( val primitiveClassProperties = primitiveClassesObject.declarations.filterIsInstance() + val throwableClass = symbolTable.referenceClass( + getClass(JsIrBackendContext.KOTLIN_PACKAGE_FQN.child(Name.identifier("Throwable"))) + ).owner + val throwableConstructors = throwableClass.declarations.filterIsInstance() + + val defaultThrowableCtor = throwableConstructors.single { it.valueParameters.size == 0 } + private fun referenceOperators() = OperatorNames.ALL.map { name -> // TODO to replace KotlinType with IrType we need right equals on IrType name to irBuiltIns.primitiveTypes.fold(mutableMapOf()) { m, t -> diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt index 69f15dff8df..d2f3fe61753 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt @@ -246,15 +246,17 @@ private val TypeOperatorLoweringPhase = makeJsPhase( prerequisite = setOf(BridgesConstructionPhase, RemoveInlineFunctionsWithReifiedTypeParametersLoweringPhase) ) -private val SecondaryCtorLoweringPhase = makeJsPhase( - { context, module -> - SecondaryCtorLowering(context).run { - constructorProcessorLowering.runOnFilesPostfix(module.files + context.dependencies.flatMap { it.files }) - constructorRedirectorLowering.lower(module) - } - }, - name = "SecondaryCtorLoweringPhase", - description = "Generate static functions for each secondary constructor and replace usages", +private val SecondaryConstructorLoweringPhase = makeJsPhase( + { context, module -> SecondaryConstructorLowering(context).lower(module) }, + name = "SecondaryConstructorLoweringPhase", + description = "Generate static functions for each secondary constructor", + prerequisite = setOf(InnerClassesLoweringPhase) +) + +private val SecondaryFactoryInjectorLoweringPhase = makeJsPhase( + { context, module -> SecondaryFactoryInjectorLowering(context).lower(module) }, + name = "SecondaryFactoryInjectorLoweringPhase", + description = "Replace usage of secondary constructor with corresponding static function", prerequisite = setOf(InnerClassesLoweringPhase) ) @@ -355,7 +357,8 @@ val jsPhases = listOf( MultipleCatchesLoweringPhase, BridgesConstructionPhase, TypeOperatorLoweringPhase, - SecondaryCtorLoweringPhase, + SecondaryConstructorLoweringPhase, + SecondaryFactoryInjectorLoweringPhase, InlineClassLoweringPhase, AutoboxingTransformerPhase, BlockDecomposerLoweringPhase, diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/SecondaryCtorLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/SecondaryCtorLowering.kt index 6fbd570911c..ff6b681a4b4 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/SecondaryCtorLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/SecondaryCtorLowering.kt @@ -5,10 +5,10 @@ package org.jetbrains.kotlin.ir.backend.js.lower -import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass +import org.jetbrains.kotlin.backend.common.ClassLoweringPass +import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.ir.copyTo import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom -import org.jetbrains.kotlin.backend.common.runOnFilePostfix import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement @@ -19,101 +19,106 @@ import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl -import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol -import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.util.parentAsClass -import org.jetbrains.kotlin.ir.util.transformDeclarationsFlat +import org.jetbrains.kotlin.ir.util.transformFlat import org.jetbrains.kotlin.ir.visitors.IrElementTransformer import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid -class SecondaryCtorLowering(val context: JsIrBackendContext) { +data class ConstructorPair(val delegate: IrSimpleFunction, val stub: IrSimpleFunction) - data class ConstructorPair(val delegate: IrSimpleFunctionSymbol, val stub: IrSimpleFunctionSymbol) +class SecondaryConstructorLowering(val context: JsIrBackendContext) : ClassLoweringPass { - private val oldCtorToNewMap = mutableMapOf() + private val oldCtorToNewMap = context.secondaryConstructorToFactoryCache - val constructorProcessorLowering = object : DeclarationContainerLoweringPass { - override fun lower(irDeclarationContainer: IrDeclarationContainer) { - irDeclarationContainer.declarations.filterIsInstance().forEach { - if (!it.isInline) // Inline classes are lowered separately - lowerClass(it) - } - } - } + override fun lower(irClass: IrClass) { + if (irClass.isInline) return - val constructorRedirectorLowering = object : DeclarationContainerLoweringPass { - override fun lower(irDeclarationContainer: IrDeclarationContainer) { - if (irDeclarationContainer is IrClass) { - if (!irDeclarationContainer.isInline) // Inline classes are lowered separately - updateConstructorDeclarations(irDeclarationContainer) - } - for (it in irDeclarationContainer.declarations) { - it.accept(CallsiteRedirectionTransformer(), null) - } - } - } - - private fun updateConstructorDeclarations(irClass: IrClass) { - irClass.transformDeclarationsFlat { + irClass.declarations.transformFlat { if (it is IrConstructor) { - oldCtorToNewMap[it.symbol]?.let { (newInit, newCreate) -> - listOf(newInit.owner, newCreate.owner) - } + if (it.isPrimary) null else transformConstructor(it, irClass) } else null } } - private fun lowerClass(irClass: IrClass): List { - val className = irClass.name.asString() - val oldConstructors = mutableListOf() - val newConstructors = mutableListOf() - - for (declaration in irClass.declarations) { - if (declaration is IrConstructor && !declaration.isPrimary) { - // TODO delegate name generation - val constructorName = "${className}_init" - // We should split secondary constructor into two functions, - // * Initializer which contains constructor's body and takes just created object as implicit param `$this` - // ** This function is also delegation constructor - // * Creation function which has same signature with original constructor, - // creates new object via `Object.create` builtIn and passes it to corresponding `Init` function - // In other words: - // Foo::constructor(...) { - // body - // } - // => - // Foo_init_$Init$(..., $this) { - // body[ this = $this ] - // return $this - // } - // Foo_init_$Create$(...) { - // val t = Object.create(Foo.prototype); - // return Foo_init_$Init$(..., t) - // } - val newInitConstructor = createInitConstructor(declaration, irClass, constructorName, irClass.defaultType) - val newCreateConstructor = createCreateConstructor(declaration, newInitConstructor, constructorName, irClass.defaultType) - - oldCtorToNewMap[declaration.symbol] = ConstructorPair(newInitConstructor.symbol, newCreateConstructor.symbol) - - oldConstructors += declaration - newConstructors += newInitConstructor - newConstructors += newCreateConstructor - } + private fun transformConstructor(constructor: IrConstructor, irClass: IrClass): List { + val stubs = oldCtorToNewMap.getOrPut(constructor) { + buildConstructorStubDeclarations(constructor, irClass) } - return newConstructors + generateStubsBody(constructor, irClass, stubs) + + return listOf(stubs.delegate, stubs.stub) } + private fun generateStubsBody(constructor: IrConstructor, irClass: IrClass, stubs: ConstructorPair) { + // We should split secondary constructor into two functions, + // * Initializer which contains constructor's body and takes just created object as implicit param `$this` + // ** This function is also delegation constructor + // * Creation function which has same signature with original constructor, + // creates new object via `Object.create` builtIn and passes it to corresponding `Init` function + // In other words: + // Foo::constructor(...) { + // body + // } + // => + // Foo_init_$Init$(..., $this) { + // body[ this = $this ] + // return $this + // } + // Foo_init_$Create$(...) { + // val t = Object.create(Foo.prototype); + // return Foo_init_$Init$(..., t) + // } + generateInitBody(constructor, irClass, stubs.delegate) + generateFactoryBody(constructor, irClass, stubs.stub, stubs.delegate) + } + + private fun generateFactoryBody(constructor: IrConstructor, irClass: IrClass, stub: IrSimpleFunction, delegate: IrSimpleFunction) { + val type = irClass.defaultType + val createFunctionIntrinsic = context.intrinsics.jsObjectCreate + val irCreateCall = JsIrBuilder.buildCall(createFunctionIntrinsic.symbol, type, listOf(type)) + val irDelegateCall = JsIrBuilder.buildCall(delegate.symbol, type).also { call -> + for (i in 0 until stub.typeParameters.size) { + call.putTypeArgument(i, stub.typeParameters[i].toIrType()) + } + + for (i in 0 until stub.valueParameters.size) { + call.putValueArgument(i, JsIrBuilder.buildGetValue(stub.valueParameters[i].symbol)) + } + + call.putValueArgument(constructor.valueParameters.size, irCreateCall) + } + val irReturn = JsIrBuilder.buildReturn(stub.symbol, irDelegateCall, context.irBuiltIns.nothingType) + + + stub.body = JsIrBuilder.buildBlockBody(listOf(irReturn)) + } + + private fun generateInitBody(constructor: IrConstructor, irClass: IrClass, delegate: IrSimpleFunction) { + val thisParam = delegate.valueParameters.last() + val oldThisReceiver = irClass.thisReceiver!! + val retStmt = JsIrBuilder.buildReturn(delegate.symbol, JsIrBuilder.buildGetValue(thisParam.symbol), context.irBuiltIns.nothingType) + val statements = (constructor.body!!.deepCopyWithSymbols(delegate) as IrStatementContainer).statements + + val oldValueParameters = constructor.valueParameters + oldThisReceiver + + // TODO: replace parameters as well + delegate.body = JsIrBuilder.buildBlockBody(statements + retStmt).apply { + transformChildrenVoid(ThisUsageReplaceTransformer(delegate.symbol, oldValueParameters.zip(delegate.valueParameters).toMap())) + } + } + + private class ThisUsageReplaceTransformer( val function: IrFunctionSymbol, val symbolMapping: Map - ) : - IrElementTransformerVoid() { + ) : IrElementTransformerVoid() { val newThisSymbol = symbolMapping.values.last().symbol @@ -125,154 +130,130 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) { IrGetValueImpl(expression.startOffset, expression.endOffset, newThisSymbol.owner.type, newThisSymbol) ) - override fun visitGetValue(expression: IrGetValue): IrExpression = - if (expression.symbol.owner in symbolMapping) IrGetValueImpl( - expression.startOffset, - expression.endOffset, - expression.type, - symbolMapping[expression.symbol.owner]!!.symbol, - expression.origin - ) else { - expression - } - } - - private fun createInitConstructor( - declaration: IrConstructor, - klass: IrClass, - name: String, - type: IrType - ): IrSimpleFunction { - - val thisParam = JsIrBuilder.buildValueParameter("\$this", declaration.valueParameters.size, type) - val oldThisReceiver = klass.thisReceiver!! - val functionName = "${name}_\$Init\$" - - return JsIrBuilder.buildFunction( - functionName, - type, - declaration.parent, - declaration.visibility, - Modality.FINAL, - declaration.isInline, - declaration.isExternal - ).also { - thisParam.run { parent = it } - val retStmt = JsIrBuilder.buildReturn(it.symbol, JsIrBuilder.buildGetValue(thisParam.symbol), context.irBuiltIns.nothingType) - val statements = (declaration.body!!.deepCopyWithSymbols(it) as IrStatementContainer).statements - - it.copyTypeParametersFrom(declaration.parentAsClass) - - val newValueParameters = declaration.valueParameters.map { p -> p.copyTo(it) } - it.valueParameters += (newValueParameters + thisParam) - - val oldValueParameters = declaration.valueParameters + oldThisReceiver - - // TODO: replace parameters as well - it.body = JsIrBuilder.buildBlockBody(statements + retStmt).apply { - transformChildrenVoid(ThisUsageReplaceTransformer(it.symbol, oldValueParameters.zip(it.valueParameters).toMap())) - } - } - } - - private fun createCreateConstructor( - declaration: IrConstructor, - ctorImpl: IrSimpleFunction, - name: String, - type: IrType - ): IrSimpleFunction { - - val functionName = "${name}_\$Create\$" - - return JsIrBuilder.buildFunction( - functionName, - type, - declaration.parent, - declaration.visibility, - Modality.FINAL, - declaration.isInline, - declaration.isExternal - ).also { - it.copyTypeParametersFrom(declaration.parentAsClass) - it.valueParameters += declaration.valueParameters.map { p -> p.copyTo(it) } - - val createFunctionIntrinsic = context.intrinsics.jsObjectCreate - val irCreateCall = JsIrBuilder.buildCall(createFunctionIntrinsic.symbol, type, listOf(type)) - val irDelegateCall = JsIrBuilder.buildCall(ctorImpl.symbol, type).also { call -> - for (i in 0 until it.valueParameters.size) { - call.putValueArgument(i, JsIrBuilder.buildGetValue(it.valueParameters[i].symbol)) - } -// valueParameters.forEachIndexed { i, p -> it.putValueArgument(i, JsIrBuilder.buildGetValue(p.symbol)) } - call.putValueArgument(declaration.valueParameters.size, irCreateCall) - -// typeParameters.mapIndexed { i, t -> ctorImpl.typeParameters[i].descriptor -> } - } - val irReturn = JsIrBuilder.buildReturn(it.symbol, irDelegateCall, context.irBuiltIns.nothingType) - - - it.body = JsIrBuilder.buildBlockBody(listOf(irReturn)) - } - } - - inner class CallsiteRedirectionTransformer : IrElementTransformer { - - override fun visitFunction(declaration: IrFunction, data: IrFunction?): IrStatement = super.visitFunction(declaration, declaration) - - override fun visitCall(expression: IrCall, data: IrFunction?): IrElement { - super.visitCall(expression, data) - - val target = expression.symbol.owner - - if (target is IrConstructor) { - if (!target.isPrimary) { - val ctor = oldCtorToNewMap[target.symbol] - if (ctor != null) { - return redirectCall(expression, ctor.stub) - } - } - } - - return expression - } - - override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall, data: IrFunction?): IrElement { - super.visitDelegatingConstructorCall(expression, data) - - val target = expression.symbol - if (target.owner.isPrimary) { - // nothing to do here - return expression - } - - val fromPrimary = data!! is IrConstructor - // TODO: what is `deserialized` constructor? - val ctor = oldCtorToNewMap[target] ?: return expression - val newCall = redirectCall(expression, ctor.delegate) - - val readThis = if (fromPrimary) { - val thisKlass = expression.symbol.owner.parent as IrClass - val thisSymbol = thisKlass.thisReceiver!!.symbol - IrGetValueImpl(expression.startOffset, expression.endOffset, expression.type, thisSymbol) - } else { - IrGetValueImpl(expression.startOffset, expression.endOffset, expression.type, data.valueParameters.last().symbol) - } - - newCall.putValueArgument(expression.valueArgumentsCount, readThis) - - return newCall - } - - private fun redirectCall( - call: IrFunctionAccessExpression, - newTarget: IrSimpleFunctionSymbol - ) = IrCallImpl(call.startOffset, call.endOffset, call.type, newTarget).apply { - - // TODO: Should constructors have type arguments - // copyTypeArgumentsFrom(call) - - for (i in 0 until call.valueArgumentsCount) { - putValueArgument(i, call.getValueArgument(i)) - } - } + override fun visitGetValue(expression: IrGetValue) = symbolMapping[expression.symbol.owner]?.let { + expression.run { IrGetValueImpl(startOffset, endOffset, type, it.symbol, origin) } + } ?: expression } } + +private fun IrTypeParameter.toIrType() = IrSimpleTypeImpl(symbol, true, emptyList(), emptyList()) + +private fun buildInitDeclaration(constructor: IrConstructor, irClass: IrClass): IrSimpleFunction { + val type = irClass.defaultType + val constructorName = "${irClass.name}_init" + val functionName = "${constructorName}_\$Init\$" + + return JsIrBuilder.buildFunction( + functionName, + type, + constructor.parent, + constructor.visibility, + Modality.FINAL, + constructor.isInline, + constructor.isExternal + ).also { + it.copyTypeParametersFrom(constructor.parentAsClass) + + constructor.valueParameters.mapTo(it.valueParameters) { p -> p.copyTo(it) } + it.valueParameters += JsIrBuilder.buildValueParameter("\$this", constructor.valueParameters.size, type).apply { parent = it } + } +} + +private fun buildFactoryDeclaration(constructor: IrConstructor, irClass: IrClass): IrSimpleFunction { + val type = irClass.defaultType + val constructorName = "${irClass.name}_init" + val functionName = "${constructorName}_\$Create\$" + + return JsIrBuilder.buildFunction( + functionName, + type, + constructor.parent, + constructor.visibility, + Modality.FINAL, + constructor.isInline, + constructor.isExternal + ).also { + it.copyTypeParametersFrom(constructor.parentAsClass) + it.valueParameters += constructor.valueParameters.map { p -> p.copyTo(it) } + } +} + +private fun buildConstructorStubDeclarations(constructor: IrConstructor, klass: IrClass) = + ConstructorPair(buildInitDeclaration(constructor, klass), buildFactoryDeclaration(constructor, klass)) + +class SecondaryFactoryInjectorLowering(val context: JsIrBackendContext) : FileLoweringPass { + override fun lower(irFile: IrFile) { + irFile.accept(CallsiteRedirectionTransformer(context), null) + } +} + +private class CallsiteRedirectionTransformer(context: JsIrBackendContext) : IrElementTransformer { + + private val oldCtorToNewMap = context.secondaryConstructorToFactoryCache + private val defaultThrowableConstructor = context.defaultThrowableCtor + + private val IrFunction.isSecondaryConstructorCall + get() = + this is IrConstructor && !isPrimary && this != defaultThrowableConstructor && !isExternal && !parentAsClass.isInline + + override fun visitFunction(declaration: IrFunction, data: IrFunction?): IrStatement = super.visitFunction(declaration, declaration) + + override fun visitCall(expression: IrCall, data: IrFunction?): IrElement { + super.visitCall(expression, data) + + val target = expression.symbol.owner + return if (target.isSecondaryConstructorCall) { + val constructor = target as IrConstructor + val ctor = oldCtorToNewMap.getOrPut(constructor) { + buildConstructorStubDeclarations(constructor, constructor.parentAsClass) + } + replaceSecondaryConstructorWithFactoryFunction(expression, ctor.stub.symbol, data) + } else expression + } + + override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall, data: IrFunction?): IrElement { + super.visitDelegatingConstructorCall(expression, data) + + val target = expression.symbol.owner + + return if (target.isSecondaryConstructorCall) { + val klass = target.parentAsClass + val ctor = oldCtorToNewMap.getOrPut(target) { buildConstructorStubDeclarations(target, klass) } + val newCall = replaceSecondaryConstructorWithFactoryFunction(expression, ctor.delegate.symbol, data) + + val readThis = expression.run { + if (data!! is IrConstructor) { + IrGetValueImpl(startOffset, endOffset, type, klass.thisReceiver!!.symbol) + } else { + IrGetValueImpl(startOffset, endOffset, type, data.valueParameters.last().symbol) + } + } + + newCall.apply { putValueArgument(expression.valueArgumentsCount, readThis) } + } else expression + } + + private fun replaceSecondaryConstructorWithFactoryFunction( + call: IrFunctionAccessExpression, + newTarget: IrSimpleFunctionSymbol, + enclosing: IrFunction? + ) = IrCallImpl(call.startOffset, call.endOffset, call.type, newTarget).apply { + + // There are 3 possible cases how Type Parameters should be passed + if (call is IrCall) { + // if it was just a normal constructor cal via `IrCall` just copy arguments as is + copyTypeArgumentsFrom(call) + } else { + // if it is `IrDelegatingConstructorCall` figure out from constructor is called and extract parameters from here + // Since `IrConstructor` doesn't have TypeParameters we take them from its class + val typeParameters = enclosing?.let { if (it is IrConstructor) it.parentAsClass.typeParameters else it.typeParameters }!! + for (i in 0 until typeParameters.size) { + putTypeArgument(i, typeParameters[i].toIrType()) + } + } + + for (i in 0 until call.valueArgumentsCount) { + putValueArgument(i, call.getValueArgument(i)) + } + } +} \ No newline at end of file diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/ThrowableSuccessorsLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/ThrowableSuccessorsLowering.kt index 77998bec10c..87adffd9f93 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/ThrowableSuccessorsLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/ThrowableSuccessorsLowering.kt @@ -44,12 +44,10 @@ class ThrowableSuccessorsLowering(context: JsIrBackendContext) : FileLoweringPas private val causeName get() = JsIrBuilder.buildString(stringType, "cause") private val nameName get() = JsIrBuilder.buildString(stringType, "name") - private val throwableClass = context.symbolTable.referenceClass( - context.getClass(JsIrBackendContext.KOTLIN_PACKAGE_FQN.child(Name.identifier("Throwable"))) - ).owner - private val throwableConstructors = throwableClass.declarations.filterIsInstance() + private val throwableClass = context.throwableClass + private val throwableConstructors = context.throwableConstructors - private val defaultCtor = throwableConstructors.single { it.valueParameters.size == 0 } + private val defaultCtor = context.defaultThrowableCtor private val toString = throwableClass.declarations.filterIsInstance().single { it.name == Name.identifier("toString") }