[WASM] Make object creation inside constructors

This commit is contained in:
Igor Yakovlev
2022-10-28 10:26:12 +02:00
committed by teamcity
parent 346b2f162c
commit 0e54e00e48
2 changed files with 27 additions and 10 deletions
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.backend.wasm.utils.*
import org.jetbrains.kotlin.backend.wasm.utils.isCanonical import org.jetbrains.kotlin.backend.wasm.utils.isCanonical
import org.jetbrains.kotlin.ir.IrBuiltIns import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.backend.js.lower.PrimaryConstructorLowering
import org.jetbrains.kotlin.ir.backend.js.utils.erasedUpperBound import org.jetbrains.kotlin.ir.backend.js.utils.erasedUpperBound
import org.jetbrains.kotlin.ir.backend.js.utils.findUnitGetInstanceFunction import org.jetbrains.kotlin.ir.backend.js.utils.findUnitGetInstanceFunction
import org.jetbrains.kotlin.ir.backend.js.utils.isDispatchReceiver import org.jetbrains.kotlin.ir.backend.js.utils.isDispatchReceiver
@@ -262,9 +263,8 @@ class BodyGenerator(
return return
} }
generateAnyParameters(klassSymbol)
if (expression.symbol.owner.hasWasmPrimitiveConstructorAnnotation()) { if (expression.symbol.owner.hasWasmPrimitiveConstructorAnnotation()) {
generateAnyParameters(klassSymbol)
for (i in 0 until expression.valueArgumentsCount) { for (i in 0 until expression.valueArgumentsCount) {
generateExpression(expression.getValueArgument(i)!!) generateExpression(expression.getValueArgument(i)!!)
} }
@@ -272,14 +272,7 @@ class BodyGenerator(
return return
} }
val irFields: List<IrField> = klass.allFields(backendContext.irBuiltIns) body.buildRefNull(WasmHeapType.Simple.NullNone) // this = null
irFields.forEachIndexed { index, field ->
if (index > 1) {
generateDefaultInitializerForType(context.transformType(field.type), body)
}
}
body.buildStructNew(wasmGcType)
generateCall(expression) generateCall(expression)
} }
@@ -296,6 +289,26 @@ class BodyGenerator(
body.buildConstI32(0) // Any::_hashCode body.buildConstI32(0) // Any::_hashCode
} }
fun generateObjectCreationPrefixIfNeeded(constructor: IrConstructor) {
val parentClass = constructor.parentAsClass
if (constructor.origin == PrimaryConstructorLowering.SYNTHETIC_PRIMARY_CONSTRUCTOR) return
if (parentClass.isAbstractOrSealed) return
val thisParameter = context.referenceLocal(parentClass.thisReceiver!!.symbol)
body.buildGetLocal(thisParameter)
body.buildInstr(WasmOp.REF_IS_NULL)
body.buildIf("this_init")
generateAnyParameters(parentClass.symbol)
val irFields: List<IrField> = parentClass.allFields(backendContext.irBuiltIns)
irFields.forEachIndexed { index, field ->
if (index > 1) {
generateDefaultInitializerForType(context.transformType(field.type), body)
}
}
body.buildStructNew(context.referenceGcType(parentClass.symbol))
body.buildSetLocal(thisParameter)
body.buildEnd()
}
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall) { override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall) {
val klass = context.irFunction.parentAsClass val klass = context.irFunction.parentAsClass
@@ -133,6 +133,10 @@ class DeclarationGenerator(
isGetUnitFunction = declaration == unitGetInstanceFunction isGetUnitFunction = declaration == unitGetInstanceFunction
) )
if (declaration is IrConstructor) {
bodyBuilder.generateObjectCreationPrefixIfNeeded(declaration)
}
require(declaration.body is IrBlockBody) { "Only IrBlockBody is supported" } require(declaration.body is IrBlockBody) { "Only IrBlockBody is supported" }
declaration.body?.acceptVoid(bodyBuilder) declaration.body?.acceptVoid(bodyBuilder)