[IR] Use InlineClassesUtils in lowerings instead of IrClass.isInline
We do it because sometimes we want to treat a regular class as an inline class. For example, in the Wasm backend we treat classes with the `@WasmAutoboxed` annotation as inline classes. Also, in the JS IR backend the `Char` class is declared as a regular class for compatibility reasons, but we want it to be an inline class for performance.
This commit is contained in:
+6
-4
@@ -28,11 +28,13 @@ private const val INLINE_CLASS_IMPL_SUFFIX = "-impl"
|
||||
class InlineClassLowering(val context: CommonBackendContext) {
|
||||
private val transformedFunction = context.mapping.inlineClassMemberToStatic
|
||||
|
||||
private fun isClassInlineLike(irClass: IrClass): Boolean = context.inlineClassesUtils.isClassInlineLike(irClass)
|
||||
|
||||
val inlineClassDeclarationLowering = object : DeclarationTransformer {
|
||||
|
||||
override fun transformFlat(declaration: IrDeclaration): List<IrDeclaration>? {
|
||||
val irClass = declaration.parent as? IrClass ?: return null
|
||||
if (!irClass.isInline) return null
|
||||
if (!isClassInlineLike(irClass)) return null
|
||||
|
||||
return when (declaration) {
|
||||
is IrConstructor -> transformConstructor(declaration)
|
||||
@@ -314,7 +316,7 @@ class InlineClassLowering(val context: CommonBackendContext) {
|
||||
override fun visitConstructorCall(expression: IrConstructorCall): IrExpression {
|
||||
expression.transformChildrenVoid(this)
|
||||
val function = expression.symbol.owner
|
||||
if (!function.parentAsClass.isInline) {
|
||||
if (!isClassInlineLike(function.parentAsClass)) {
|
||||
return expression
|
||||
}
|
||||
|
||||
@@ -326,7 +328,7 @@ class InlineClassLowering(val context: CommonBackendContext) {
|
||||
val function: IrSimpleFunction = expression.symbol.owner
|
||||
if (function.parent !is IrClass ||
|
||||
function.isStaticMethodOfClass ||
|
||||
!function.parentAsClass.isInline ||
|
||||
!isClassInlineLike(function.parentAsClass) ||
|
||||
!function.isReal
|
||||
) {
|
||||
return expression
|
||||
@@ -344,7 +346,7 @@ class InlineClassLowering(val context: CommonBackendContext) {
|
||||
val function = expression.symbol.owner
|
||||
val klass = function.parentAsClass
|
||||
return when {
|
||||
!klass.isInline -> expression
|
||||
!isClassInlineLike(klass) -> expression
|
||||
else -> irCall(expression, getOrCreateStaticMethod(function))
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ open class PropertyAccessorInlineLowering(
|
||||
// TODO: temporary workarounds
|
||||
if (parent.isExpect || property.isExpect) return false
|
||||
if (parent.parent is IrExternalPackageFragment) return false
|
||||
if (parent.isInline) return false
|
||||
if (context.inlineClassesUtils.isClassInlineLike(parent)) return false
|
||||
}
|
||||
if (property.isEffectivelyExternal()) return false
|
||||
return true
|
||||
|
||||
+1
-1
@@ -211,6 +211,6 @@ class ES6AddInternalParametersToConstructorPhase(val context: JsIrBackendContext
|
||||
|
||||
private fun IrConstructor.hasStrictSignature(): Boolean {
|
||||
val primitives = with(context.irBuiltIns) { primitiveTypesToPrimitiveArrays.values + stringClass }
|
||||
return with(parentAsClass) { isExternal || isInline || symbol in primitives }
|
||||
return with(parentAsClass) { isExternal || context.inlineClassesUtils.isClassInlineLike(this) || symbol in primitives }
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -380,7 +380,7 @@ class ES6ConstructorLowering(val context: JsIrBackendContext) : BodyLoweringPass
|
||||
//util
|
||||
private fun IrConstructor.hasStrictSignature(): Boolean {
|
||||
val primitives = with(context.irBuiltIns) { primitiveTypesToPrimitiveArrays.values + stringClass }
|
||||
return with(parentAsClass) { isExternal || isInline || symbol in primitives }
|
||||
return with(parentAsClass) { isExternal || context.inlineClassesUtils.isClassInlineLike(this) || symbol in primitives }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-2
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.ir.backend.js.lower
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.eraseGenerics
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.getJsInlinedClass
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.getJsNameOrKotlinName
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.hasStableJsName
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||
@@ -19,6 +18,9 @@ import org.jetbrains.kotlin.ir.util.render
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
class JsBridgesConstruction(context: JsIrBackendContext) : BridgesConstruction<JsIrBackendContext>(context) {
|
||||
|
||||
private fun IrType.getJsInlinedClass() = context.inlineClassesUtils.getInlinedClass(this)
|
||||
|
||||
override fun getFunctionSignature(function: IrSimpleFunction): JsSignature =
|
||||
if (function.hasStableJsName(context)) {
|
||||
JsStableNameSignature(function.getJsNameOrKotlinName())
|
||||
@@ -59,4 +61,4 @@ data class JsNonStableSignature(
|
||||
|
||||
data class JsStableNameSignature(
|
||||
override val name: Name,
|
||||
) : JsSignature
|
||||
) : JsSignature
|
||||
|
||||
+2
-2
@@ -44,7 +44,7 @@ class SecondaryConstructorLowering(val context: JsIrBackendContext) : Declaratio
|
||||
if (declaration is IrConstructor && !declaration.isPrimary) {
|
||||
val irClass = declaration.parentAsClass
|
||||
|
||||
if (irClass.isInline) return null
|
||||
if (context.inlineClassesUtils.isClassInlineLike(irClass)) return null
|
||||
|
||||
return transformConstructor(declaration, irClass)
|
||||
}
|
||||
@@ -255,7 +255,7 @@ private class CallsiteRedirectionTransformer(private val context: JsIrBackendCon
|
||||
|
||||
private val IrConstructor.isSecondaryConstructorCall
|
||||
get() =
|
||||
!isPrimary && this != defaultThrowableConstructor && !isExternal && !parentAsClass.isInline
|
||||
!isPrimary && this != defaultThrowableConstructor && !isExternal && !context.inlineClassesUtils.isClassInlineLike(parentAsClass)
|
||||
|
||||
override fun visitFunction(declaration: IrFunction, data: IrFunction?): IrStatement = super.visitFunction(declaration, declaration)
|
||||
|
||||
|
||||
+7
-7
@@ -8,10 +8,7 @@ package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
|
||||
import org.jetbrains.kotlin.backend.common.compilationException
|
||||
import org.jetbrains.kotlin.backend.common.ir.isElseBranch
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.Namer
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.emptyScope
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.getJsNameOrKotlinName
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.types.isString
|
||||
@@ -25,6 +22,9 @@ import org.jetbrains.kotlin.js.backend.ast.*
|
||||
@Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE")
|
||||
class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsExpression, JsGenerationContext> {
|
||||
|
||||
private fun JsGenerationContext.isClassInlineLike(irClass: IrClass) =
|
||||
staticContext.backendContext.inlineClassesUtils.isClassInlineLike(irClass)
|
||||
|
||||
override fun visitComposite(expression: IrComposite, data: JsGenerationContext): JsExpression {
|
||||
val size = expression.statements.size
|
||||
if (size == 0) TODO("Empty IrComposite is not supported")
|
||||
@@ -114,7 +114,7 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
|
||||
.also { context.staticContext.polyfills.visitDeclaration(field) }
|
||||
}
|
||||
|
||||
if (fieldParent is IrClass && fieldParent.isInline) {
|
||||
if (fieldParent is IrClass && context.isClassInlineLike(fieldParent)) {
|
||||
return expression.receiver!!.accept(this, context).withSource(expression, context)
|
||||
}
|
||||
val fieldName = context.getNameForField(field)
|
||||
@@ -163,7 +163,7 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
|
||||
val arguments = translateCallArguments(expression, context, this)
|
||||
|
||||
val constructor = expression.symbol.owner
|
||||
if (constructor.parentAsClass.isInline) {
|
||||
if (context.isClassInlineLike(constructor.parentAsClass)) {
|
||||
assert(constructor.isPrimary) {
|
||||
"Delegation to secondary inline constructors must be lowered into simple function calls"
|
||||
}
|
||||
@@ -182,7 +182,7 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
|
||||
val arguments = translateCallArguments(expression, context, this)
|
||||
val klass = function.parentAsClass
|
||||
|
||||
require(!klass.isInline) {
|
||||
require(!context.isClassInlineLike(klass)) {
|
||||
"All inline class constructor calls must be lowered to static function calls"
|
||||
}
|
||||
|
||||
|
||||
@@ -45,32 +45,6 @@ private fun IrClassifierSymbol.asString() = when (this) {
|
||||
else -> error("Unexpected kind of IrClassifierSymbol: " + javaClass.typeName)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns inline class for given class or null of type is not inlined
|
||||
*/
|
||||
fun IrType.getJsInlinedClass(): IrClass? {
|
||||
if (this is IrSimpleType) {
|
||||
val erased = erase(this) ?: return null
|
||||
if (erased.isInline) {
|
||||
if (this.isMarkedNullable()) {
|
||||
var fieldType: IrType
|
||||
var fieldInlinedClass = erased
|
||||
while (true) {
|
||||
fieldType = getInlineClassUnderlyingType(fieldInlinedClass)
|
||||
if (fieldType.isMarkedNullable()) {
|
||||
return null
|
||||
}
|
||||
|
||||
fieldInlinedClass = fieldType.getJsInlinedClass() ?: break
|
||||
}
|
||||
}
|
||||
|
||||
return erased
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
tailrec fun erase(type: IrType): IrClass? {
|
||||
val classifier = type.classifierOrFail
|
||||
|
||||
@@ -91,4 +65,4 @@ fun IrType.getClassRef(context: JsGenerationContext): JsNameRef =
|
||||
context.getNameForClass(klass).makeRef()
|
||||
|
||||
else -> context.getNameForStaticDeclaration(klass as IrDeclarationWithName).makeRef()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ fun jsFunctionSignature(declaration: IrFunction, context: JsIrBackendContext): S
|
||||
declaration.returnType.let {
|
||||
// Return type is only used in signature for inline class and Unit types because
|
||||
// they are binary incompatible with supertypes.
|
||||
if (it.getJsInlinedClass() != null || it.isUnit()) {
|
||||
if (context.inlineClassesUtils.isTypeInlined(it) || it.isUnit()) {
|
||||
nameBuilder.append("_ret$${it.asString()}")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user