From 96e2eb6fa1f36252cbf18f95c7ffd6712b57babf Mon Sep 17 00:00:00 2001 From: pyos Date: Thu, 4 Apr 2019 14:08:17 +0200 Subject: [PATCH] Move PromisedValue to a separate file --- .../backend/jvm/codegen/ExpressionCodegen.kt | 70 ---------------- .../backend/jvm/codegen/PromisedValue.kt | 80 +++++++++++++++++++ 2 files changed, 80 insertions(+), 70 deletions(-) create mode 100644 compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/PromisedValue.kt diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt index 07490a22113..2875233df2b 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt @@ -100,73 +100,6 @@ class BlockInfo private constructor(val parent: BlockInfo?) { class VariableInfo(val declaration: IrVariable, val index: Int, val type: Type, val startLabel: Label) -// A value that may not have been fully constructed yet. The ability to "roll back" code generation -// is useful for certain optimizations. -abstract class PromisedValue(val codegen: ExpressionCodegen, val type: Type) { - // If this value is immaterial, construct an object on the top of the stack. This - // must always be done before generating other values or emitting raw bytecode. - abstract fun materialize() -} - -// A value that *has* been fully constructed. -class MaterialValue(codegen: ExpressionCodegen, type: Type) : PromisedValue(codegen, type) { - override fun materialize() {} -} - -// A value that can be branched on. JVM has certain branching instructions which can be used -// to optimize these. -abstract class BooleanValue(codegen: ExpressionCodegen) : PromisedValue(codegen, Type.BOOLEAN_TYPE) { - abstract fun jumpIfFalse(target: Label) - abstract fun jumpIfTrue(target: Label) - - override fun materialize() { - val const0 = Label() - val end = Label() - jumpIfFalse(const0) - codegen.mv.iconst(1) - codegen.mv.goTo(end) - codegen.mv.mark(const0) - codegen.mv.iconst(0) - codegen.mv.mark(end) - } -} - -// Same as materialize(), but return a representation of the result. -val PromisedValue.materialized: MaterialValue - get() { - materialize() - return MaterialValue(codegen, type) - } - -// Materialize and disregard this value. Materialization is forced because, presumably, -// we only wanted the side effects anyway. -fun PromisedValue.discard(): MaterialValue { - materialize() - if (type !== Type.VOID_TYPE) - AsmUtil.pop(codegen.mv, type) - return MaterialValue(codegen, Type.VOID_TYPE) -} - -// On materialization, cast the value to a different type. -fun PromisedValue.coerce(target: Type) = when (target) { - Type.VOID_TYPE -> discard() - type -> this - else -> object : PromisedValue(codegen, target) { - // TODO remove dependency - override fun materialize() = StackValue.coerce(this@coerce.materialized.type, type, codegen.mv) - } -} - -// Same as above, but with a return type that allows conditional jumping. -fun PromisedValue.coerceToBoolean() = when (val coerced = coerce(Type.BOOLEAN_TYPE)) { - is BooleanValue -> coerced - else -> object : BooleanValue(codegen) { - override fun jumpIfFalse(target: Label) = coerced.materialize().also { codegen.mv.ifeq(target) } - override fun jumpIfTrue(target: Label) = coerced.materialize().also { codegen.mv.ifne(target) } - override fun materialize() = coerced.materialize() - } -} - class ExpressionCodegen( val irFunction: IrFunction, val frame: IrFrameMap, @@ -212,9 +145,6 @@ class ExpressionCodegen( val IrExpression.onStack: MaterialValue get() = MaterialValue(this@ExpressionCodegen, asmType) - val voidValue: MaterialValue - get() = MaterialValue(this@ExpressionCodegen, Type.VOID_TYPE) - private fun markNewLabel() = Label().apply { mv.visitLabel(this) } private fun IrElement.markLineNumber(startOffset: Boolean) { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/PromisedValue.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/PromisedValue.kt new file mode 100644 index 00000000000..bc5741f6466 --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/PromisedValue.kt @@ -0,0 +1,80 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.backend.jvm.codegen + +import org.jetbrains.kotlin.codegen.AsmUtil +import org.jetbrains.kotlin.codegen.StackValue +import org.jetbrains.org.objectweb.asm.Label +import org.jetbrains.org.objectweb.asm.Type + +// A value that may not have been fully constructed yet. The ability to "roll back" code generation +// is useful for certain optimizations. +abstract class PromisedValue(val codegen: ExpressionCodegen, val type: Type) { + // If this value is immaterial, construct an object on the top of the stack. This + // must always be done before generating other values or emitting raw bytecode. + abstract fun materialize() +} + +// A value that *has* been fully constructed. +class MaterialValue(codegen: ExpressionCodegen, type: Type) : PromisedValue(codegen, type) { + override fun materialize() {} +} + +// A value that can be branched on. JVM has certain branching instructions which can be used +// to optimize these. +abstract class BooleanValue(codegen: ExpressionCodegen) : PromisedValue(codegen, Type.BOOLEAN_TYPE) { + abstract fun jumpIfFalse(target: Label) + abstract fun jumpIfTrue(target: Label) + + override fun materialize() { + val const0 = Label() + val end = Label() + jumpIfFalse(const0) + codegen.mv.iconst(1) + codegen.mv.goTo(end) + codegen.mv.mark(const0) + codegen.mv.iconst(0) + codegen.mv.mark(end) + } +} + +// Same as materialize(), but return a representation of the result. +val PromisedValue.materialized: MaterialValue + get() { + materialize() + return MaterialValue(codegen, type) + } + +// Materialize and disregard this value. Materialization is forced because, presumably, +// we only wanted the side effects anyway. +fun PromisedValue.discard(): MaterialValue { + materialize() + if (type !== Type.VOID_TYPE) + AsmUtil.pop(codegen.mv, type) + return MaterialValue(codegen, Type.VOID_TYPE) +} + +// On materialization, cast the value to a different type. +fun PromisedValue.coerce(target: Type) = when (target) { + type -> this + else -> object : PromisedValue(codegen, target) { + // TODO remove dependency + override fun materialize() = StackValue.coerce(this@coerce.materialized.type, type, codegen.mv) + } +} + +// Same as above, but with a return type that allows conditional jumping. +fun PromisedValue.coerceToBoolean() = when (val coerced = coerce(Type.BOOLEAN_TYPE)) { + is BooleanValue -> coerced + else -> object : BooleanValue(codegen) { + override fun jumpIfFalse(target: Label) = coerced.materialize().also { codegen.mv.ifeq(target) } + override fun jumpIfTrue(target: Label) = coerced.materialize().also { codegen.mv.ifne(target) } + override fun materialize() = coerced.materialize() + } +} + +val ExpressionCodegen.voidValue: MaterialValue + get() = MaterialValue(this, Type.VOID_TYPE)