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 2875233df2b..164ef409f12 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 @@ -143,7 +143,7 @@ class ExpressionCodegen( // Assume this expression's result has already been materialized on the stack // with the correct type. val IrExpression.onStack: MaterialValue - get() = MaterialValue(this@ExpressionCodegen, asmType) + get() = MaterialValue(mv, asmType) private fun markNewLabel() = Label().apply { mv.visitLabel(this) } @@ -392,9 +392,9 @@ class ExpressionCodegen( return voidValue } else if (expression.type.isUnit()) { // NewInference allows casting `() -> T` to `() -> Unit`. A CHECKCAST here will fail. - return MaterialValue(this, callable.returnType).discard().coerce(expression.asmType) + return MaterialValue(mv, callable.returnType).discard().coerce(expression.asmType) } - return MaterialValue(this, callable.returnType).coerce(expression.asmType) + return MaterialValue(mv, callable.returnType).coerce(expression.asmType) } override fun visitVariable(declaration: IrVariable, data: BlockInfo): PromisedValue { @@ -442,7 +442,7 @@ class ExpressionCodegen( isStatic -> mv.getstatic(ownerType, fieldName, fieldType.descriptor) else -> mv.getfield(ownerType, fieldName, fieldType.descriptor) } - MaterialValue(this, fieldType).coerce(expression.asmType) + MaterialValue(mv, fieldType).coerce(expression.asmType) } } @@ -495,10 +495,10 @@ class ExpressionCodegen( override fun visitConst(expression: IrConst, data: BlockInfo): PromisedValue { expression.markLineNumber(startOffset = true) when (val value = expression.value) { - is Boolean -> return object : BooleanValue(this) { - override fun jumpIfFalse(target: Label) = if (value) Unit else codegen.mv.goTo(target) - override fun jumpIfTrue(target: Label) = if (value) codegen.mv.goTo(target) else Unit - override fun materialize() = codegen.mv.iconst(if (value) 1 else 0) + is Boolean -> return object : BooleanValue(mv) { + override fun jumpIfFalse(target: Label) = if (value) Unit else mv.goTo(target) + override fun jumpIfTrue(target: Label) = if (value) mv.goTo(target) else Unit + override fun materialize() = mv.iconst(if (value) 1 else 0) } is Char -> mv.iconst(value.toInt()) is Long -> mv.lconst(value) @@ -715,7 +715,7 @@ class ExpressionCodegen( state.languageVersionSettings.isReleaseCoroutines() ) } - MaterialValue(this, boxedType).coerce(expression.asmType) + MaterialValue(mv, boxedType).coerce(expression.asmType) } IrTypeOperator.INSTANCEOF, IrTypeOperator.NOT_INSTANCEOF -> { 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 index bc5741f6466..8d748b9eb89 100644 --- 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 @@ -9,23 +9,24 @@ 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 +import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter // 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) { +abstract class PromisedValue(val mv: InstructionAdapter, 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) { +class MaterialValue(mv: InstructionAdapter, type: Type) : PromisedValue(mv, 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 class BooleanValue(mv: InstructionAdapter) : PromisedValue(mv, Type.BOOLEAN_TYPE) { abstract fun jumpIfFalse(target: Label) abstract fun jumpIfTrue(target: Label) @@ -33,11 +34,11 @@ abstract class BooleanValue(codegen: ExpressionCodegen) : PromisedValue(codegen, 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) + mv.iconst(1) + mv.goTo(end) + mv.mark(const0) + mv.iconst(0) + mv.mark(end) } } @@ -45,7 +46,7 @@ abstract class BooleanValue(codegen: ExpressionCodegen) : PromisedValue(codegen, val PromisedValue.materialized: MaterialValue get() { materialize() - return MaterialValue(codegen, type) + return MaterialValue(mv, type) } // Materialize and disregard this value. Materialization is forced because, presumably, @@ -53,28 +54,28 @@ val PromisedValue.materialized: MaterialValue fun PromisedValue.discard(): MaterialValue { materialize() if (type !== Type.VOID_TYPE) - AsmUtil.pop(codegen.mv, type) - return MaterialValue(codegen, Type.VOID_TYPE) + AsmUtil.pop(mv, type) + return MaterialValue(mv, 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) { + else -> object : PromisedValue(mv, target) { // TODO remove dependency - override fun materialize() = StackValue.coerce(this@coerce.materialized.type, type, codegen.mv) + override fun materialize() = StackValue.coerce(this@coerce.materialized.type, type, 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) } + else -> object : BooleanValue(mv) { + override fun jumpIfFalse(target: Label) = coerced.materialize().also { mv.ifeq(target) } + override fun jumpIfTrue(target: Label) = coerced.materialize().also { mv.ifne(target) } override fun materialize() = coerced.materialize() } } val ExpressionCodegen.voidValue: MaterialValue - get() = MaterialValue(this, Type.VOID_TYPE) + get() = MaterialValue(mv, Type.VOID_TYPE) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/CompareTo.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/CompareTo.kt index 745533a88ac..15ffb6d5f41 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/CompareTo.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/CompareTo.kt @@ -65,22 +65,22 @@ class CompareTo : IntrinsicMethod() { } } -class BooleanComparison(val op: IElementType, val a: MaterialValue, val b: MaterialValue) : BooleanValue(a.codegen) { +class BooleanComparison(val op: IElementType, val a: MaterialValue, val b: MaterialValue) : BooleanValue(a.mv) { override fun jumpIfFalse(target: Label) { // TODO 1. get rid of the dependency; 2. take `b.type` into account. val opcode = if (a.type.sort == Type.OBJECT) ObjectCompare.getObjectCompareOpcode(op) else - NumberCompare.patchOpcode(NumberCompare.getNumberCompareOpcode(op), codegen.mv, op, a.type) - codegen.mv.visitJumpInsn(opcode, target) + NumberCompare.patchOpcode(NumberCompare.getNumberCompareOpcode(op), mv, op, a.type) + mv.visitJumpInsn(opcode, target) } override fun jumpIfTrue(target: Label) { val opcode = if (a.type.sort == Type.OBJECT) BranchedValue.negatedOperations[ObjectCompare.getObjectCompareOpcode(op)]!! else - NumberCompare.patchOpcode(BranchedValue.negatedOperations[NumberCompare.getNumberCompareOpcode(op)]!!, codegen.mv, op, a.type) - codegen.mv.visitJumpInsn(opcode, target) + NumberCompare.patchOpcode(BranchedValue.negatedOperations[NumberCompare.getNumberCompareOpcode(op)]!!, mv, op, a.type) + mv.visitJumpInsn(opcode, target) } } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Equals.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Equals.kt index 4e56dd2348c..3ede0e49551 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Equals.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Equals.kt @@ -27,9 +27,9 @@ import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter class Equals(val operator: IElementType) : IntrinsicMethod() { - private class BooleanNullCheck(val value: PromisedValue) : BooleanValue(value.codegen) { - override fun jumpIfFalse(target: Label) = value.materialize().also { codegen.mv.ifnonnull(target) } - override fun jumpIfTrue(target: Label) = value.materialize().also { codegen.mv.ifnull(target) } + private class BooleanNullCheck(val value: PromisedValue) : BooleanValue(value.mv) { + override fun jumpIfFalse(target: Label) = value.materialize().also { mv.ifnonnull(target) } + override fun jumpIfTrue(target: Label) = value.materialize().also { mv.ifnull(target) } } override fun invoke(expression: IrFunctionAccessExpression, codegen: ExpressionCodegen, data: BlockInfo): PromisedValue? { @@ -50,7 +50,7 @@ class Equals(val operator: IElementType) : IntrinsicMethod() { val bValue = b.accept(codegen, data).coerce(operandType).materialized if (useEquals) { AsmUtil.genAreEqualCall(codegen.mv) - return MaterialValue(codegen, Type.BOOLEAN_TYPE) + return MaterialValue(codegen.mv, Type.BOOLEAN_TYPE) } return BooleanComparison(operator, aValue, bValue) } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IntrinsicMethod.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IntrinsicMethod.kt index b142d2223a9..eeca23c7269 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IntrinsicMethod.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IntrinsicMethod.kt @@ -28,8 +28,8 @@ abstract class IntrinsicMethod { with(codegen) { val descriptor = typeMapper.mapSignatureSkipGeneric(expression.descriptor) val stackValue = toCallable(expression, descriptor, context).invoke(mv, codegen, data) - return object : PromisedValue(codegen, stackValue.type) { - override fun materialize() = stackValue.put(codegen.mv) + return object : PromisedValue(mv, stackValue.type) { + override fun materialize() = stackValue.put(mv) } } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/JavaClassProperty.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/JavaClassProperty.kt index efb3ff7719b..1445b2b6f14 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/JavaClassProperty.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/JavaClassProperty.kt @@ -30,10 +30,10 @@ object JavaClassProperty : IntrinsicMethod() { } if (isPrimitive(value.type)) { value.discard() - value.codegen.mv.getstatic(boxType(value.type).internalName, "TYPE", "Ljava/lang/Class;") + value.mv.getstatic(boxType(value.type).internalName, "TYPE", "Ljava/lang/Class;") } else { value.materialize() - value.codegen.mv.invokevirtual("java/lang/Object", "getClass", "()Ljava/lang/Class;", false) + value.mv.invokevirtual("java/lang/Object", "getClass", "()Ljava/lang/Class;", false) } } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Not.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Not.kt index 6037a32e56b..a1e567c4746 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Not.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Not.kt @@ -24,7 +24,7 @@ import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression import org.jetbrains.org.objectweb.asm.Label class Not : IntrinsicMethod() { - class BooleanNegation(val value: BooleanValue) : BooleanValue(value.codegen) { + class BooleanNegation(val value: BooleanValue) : BooleanValue(value.mv) { override fun jumpIfFalse(target: Label) = value.jumpIfTrue(target) override fun jumpIfTrue(target: Label) = value.jumpIfFalse(target) }