[JS IR BE] Use static fields instead of variables in enum lowering

This commit is contained in:
Svyatoslav Kuzmich
2019-05-22 12:57:11 +03:00
parent 30ada0ccbb
commit cd55e6b1e5
3 changed files with 29 additions and 23 deletions
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.builders.declarations.buildField
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
@@ -36,6 +37,7 @@ import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.Name
import java.util.* import java.util.*
class EnumUsageLowering(val context: JsIrBackendContext) : FileLoweringPass { class EnumUsageLowering(val context: JsIrBackendContext) : FileLoweringPass {
@@ -412,17 +414,20 @@ class EnumClassTransformer(val context: JsIrBackendContext, private val irClass:
} }
private fun createEnumEntryInstanceVariables() = enumEntries.map { enumEntry -> private fun createEnumEntryInstanceVariables() = enumEntries.map { enumEntry ->
val type = enumEntry.getType(irClass).makeNullable() val result = buildField {
val name = "${enumName}_${enumEntry.name.identifier}_instance" name = Name.identifier("${enumName}_${enumEntry.name.identifier}_instance")
val result = builder.run { type = enumEntry.getType(irClass).makeNullable()
scope.createTmpVariable(irImplicitCast(irNull(), type), name) isStatic = true
}.apply {
parent = irClass
initializer = builder.run { irExprBody(irImplicitCast(irNull(), type)) }
} }
enumEntry.correspondingClass?.constructors?.forEach { enumEntry.correspondingClass?.constructors?.forEach {
// Initialize entry instance at the beginning of constructor so it can be used inside constructor body // Initialize entry instance at the beginning of constructor so it can be used inside constructor body
(it.body as? IrBlockBody)?.apply { (it.body as? IrBlockBody)?.apply {
statements.add(0, context.createIrBuilder(it.symbol).run { statements.add(0, context.createIrBuilder(it.symbol).run {
irSetVar(result.symbol, irGet(enumEntry.correspondingClass!!.thisReceiver!!)) irSetField(null, result, irGet(enumEntry.correspondingClass!!.thisReceiver!!))
}) })
} }
} }
@@ -449,37 +454,39 @@ class EnumClassTransformer(val context: JsIrBackendContext, private val irClass:
private fun createGetEntryInstanceFuns( private fun createGetEntryInstanceFuns(
initEntryInstancesFun: IrSimpleFunction, initEntryInstancesFun: IrSimpleFunction,
entryInstances: List<IrVariable> entryInstances: List<IrField>
) = enumEntries.mapIndexed { index, enumEntry -> ) = enumEntries.mapIndexed { index, enumEntry ->
context.enumEntryToGetInstanceFunction.getOrPut(enumEntry.symbol) { context.enumEntryToGetInstanceFunction.getOrPut(enumEntry.symbol) {
buildFunction(createEntryAccessorName(enumName, enumEntry), enumEntry.getType(irClass)) buildFunction(createEntryAccessorName(enumName, enumEntry), enumEntry.getType(irClass))
}.apply { }.apply {
body = context.createIrBuilder(symbol).irBlockBody(this) { body = context.createIrBuilder(symbol).irBlockBody(this) {
+irCall(initEntryInstancesFun) +irCall(initEntryInstancesFun)
+irReturn(irGet(entryInstances[index])) +irReturn(irGetField(null, entryInstances[index]))
} }
} }
} }
private fun createInitEntryInstancesFun( private fun createInitEntryInstancesFun(
entryInstancesInitializedVar: IrVariable, entryInstancesInitializedField: IrField,
entryInstances: List<IrVariable> entryInstances: List<IrField>
) = buildFunction("${enumName}_initEntries") { ) = buildFunction("${enumName}_initEntries") {
+irIfThen(irGet(entryInstancesInitializedVar), irReturnUnit()) +irIfThen(irGetField(null, entryInstancesInitializedField), irReturnUnit())
+irSetVar(entryInstancesInitializedVar.symbol, irBoolean(true)) +irSetField(null, entryInstancesInitializedField, irBoolean(true))
for ((entry, instanceVar) in enumEntries.zip(entryInstances)) { for ((entry, instanceField) in enumEntries.zip(entryInstances)) {
+irSetVar(instanceVar.symbol, entry.initializerExpression!!) +irSetField(null, instanceField, entry.initializerExpression!!)
} }
}.also { }.also {
// entry.initializerExpression can have local declarations // entry.initializerExpression can have local declarations
it.acceptVoid(PatchDeclarationParentsVisitor(irClass)) it.acceptVoid(PatchDeclarationParentsVisitor(irClass))
} }
private fun createEntryInstancesInitializedVar(): IrVariable { private fun createEntryInstancesInitializedVar(): IrField = buildField {
return builder.scope.createTemporaryVariable( name = Name.identifier("${enumName}_entriesInitialized")
builder.irBoolean(false), type = context.irBuiltIns.booleanType
"${enumName}_entriesInitialized" isStatic = true
) }.apply {
parent = irClass
initializer = builder.run { irExprBody(irBoolean(false)) }
} }
@@ -38,11 +38,10 @@ class StaticMembersLowering(val context: JsIrBackendContext) : FileLoweringPass
super.visitSimpleFunction(declaration) super.visitSimpleFunction(declaration)
} }
override fun visitVariable(declaration: IrVariable) { override fun visitField(declaration: IrField) {
// TODO: Don't generate variables inside classes if (declaration.parent is IrClass && declaration.isStatic)
if (declaration.parent is IrClass)
staticDeclarationsInClasses.add(declaration) staticDeclarationsInClasses.add(declaration)
super.visitVariable(declaration) super.visitField(declaration)
} }
}) })
@@ -170,7 +170,7 @@ fun IrBuilderWithScope.irGetField(receiver: IrExpression?, field: IrField) =
IrGetFieldImpl(startOffset, endOffset, field.symbol, field.type, receiver) IrGetFieldImpl(startOffset, endOffset, field.symbol, field.type, receiver)
fun IrBuilderWithScope.irSetField(receiver: IrExpression?, field: IrField, value: IrExpression) = fun IrBuilderWithScope.irSetField(receiver: IrExpression?, field: IrField, value: IrExpression) =
IrSetFieldImpl(startOffset, endOffset, field.symbol, receiver, value, field.type) IrSetFieldImpl(startOffset, endOffset, field.symbol, receiver, value, context.irBuiltIns.unitType)
fun IrBuilderWithScope.irGetObjectValue(type: IrType, classSymbol: IrClassSymbol) = fun IrBuilderWithScope.irGetObjectValue(type: IrType, classSymbol: IrClassSymbol) =
IrGetObjectValueImpl(startOffset, endOffset, type, classSymbol) IrGetObjectValueImpl(startOffset, endOffset, type, classSymbol)