JVM_IR: Use direct field access instead of calling certain accessors.
Final default properties accessors that access a backing field on the same class can be replaced by direct field use. Perform the optimization late in the pipeline to allow lowerings to expose more opportunities for optimizations.
This commit is contained in:
@@ -314,10 +314,9 @@ private val jvmFilePhases =
|
|||||||
staticDefaultFunctionPhase then
|
staticDefaultFunctionPhase then
|
||||||
syntheticAccessorPhase then
|
syntheticAccessorPhase then
|
||||||
|
|
||||||
|
|
||||||
jvmArgumentNullabilityAssertions then
|
jvmArgumentNullabilityAssertions then
|
||||||
toArrayPhase then
|
toArrayPhase then
|
||||||
jvmBuiltinOptimizationLoweringPhase then
|
jvmOptimizationLoweringPhase then
|
||||||
additionalClassAnnotationPhase then
|
additionalClassAnnotationPhase then
|
||||||
typeOperatorLowering then
|
typeOperatorLowering then
|
||||||
replaceKFunctionInvokeWithFunctionInvokePhase then
|
replaceKFunctionInvokeWithFunctionInvokePhase then
|
||||||
|
|||||||
+84
-21
@@ -6,15 +6,17 @@
|
|||||||
package org.jetbrains.kotlin.backend.jvm.lower
|
package org.jetbrains.kotlin.backend.jvm.lower
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||||
|
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||||
|
import org.jetbrains.kotlin.backend.common.lower.irBlock
|
||||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||||
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.unboxInlineClass
|
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.unboxInlineClass
|
||||||
import org.jetbrains.kotlin.codegen.intrinsics.Not
|
import org.jetbrains.kotlin.codegen.intrinsics.Not
|
||||||
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
import org.jetbrains.kotlin.ir.builders.irGetField
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
import org.jetbrains.kotlin.ir.builders.irSetField
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||||
@@ -24,16 +26,15 @@ import org.jetbrains.kotlin.ir.types.isNullableAny
|
|||||||
import org.jetbrains.kotlin.ir.types.isPrimitiveType
|
import org.jetbrains.kotlin.ir.types.isPrimitiveType
|
||||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
|
||||||
|
|
||||||
internal val jvmBuiltinOptimizationLoweringPhase = makeIrFilePhase(
|
internal val jvmOptimizationLoweringPhase = makeIrFilePhase(
|
||||||
::JvmBuiltinOptimizationLowering,
|
::JvmOptimizationLowering,
|
||||||
name = "JvmBuiltinOptimizationLowering",
|
name = "JvmBuiltinOptimizationLowering",
|
||||||
description = "Optimize builtin calls for JVM code generation"
|
description = "Optimize code for JVM code generation"
|
||||||
)
|
)
|
||||||
|
|
||||||
class JvmBuiltinOptimizationLowering(val context: JvmBackendContext) : FileLoweringPass {
|
class JvmOptimizationLowering(val context: JvmBackendContext) : FileLoweringPass {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun isNegation(expression: IrExpression, context: JvmBackendContext): Boolean =
|
fun isNegation(expression: IrExpression, context: JvmBackendContext): Boolean =
|
||||||
@@ -71,9 +72,38 @@ class JvmBuiltinOptimizationLowering(val context: JvmBackendContext) : FileLower
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun lower(irFile: IrFile) {
|
override fun lower(irFile: IrFile) {
|
||||||
irFile.transformChildrenVoid(object : IrElementTransformerVoid() {
|
val transformer = object : IrElementTransformer<IrClass?> {
|
||||||
override fun visitCall(expression: IrCall): IrExpression {
|
|
||||||
expression.transformChildrenVoid(this)
|
// Thread the current class through the transformations in order to replace
|
||||||
|
// final default accessor calls with direct backing field access when
|
||||||
|
// possible.
|
||||||
|
override fun visitClass(declaration: IrClass, data: IrClass?): IrStatement {
|
||||||
|
declaration.transformChildren(this, declaration)
|
||||||
|
return declaration
|
||||||
|
}
|
||||||
|
|
||||||
|
// For some functions, we clear the current class field since the code could end up
|
||||||
|
// in another class then the one it is nested under in the IR.
|
||||||
|
// TODO: Loosen this up for local functions for lambdas passed as an inline lambda
|
||||||
|
// argument to an inline function. In that case the code does end up in the current class.
|
||||||
|
override fun visitFunction(declaration: IrFunction, currentClass: IrClass?): IrStatement {
|
||||||
|
val codeMightBeGeneratedInDifferentClass = declaration.isSuspend ||
|
||||||
|
declaration.isInline ||
|
||||||
|
declaration.origin == IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA
|
||||||
|
declaration.transformChildren(this, currentClass.takeUnless { codeMightBeGeneratedInDifferentClass })
|
||||||
|
return declaration
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitCall(expression: IrCall, currentClass: IrClass?): IrExpression {
|
||||||
|
expression.transformChildren(this, currentClass)
|
||||||
|
|
||||||
|
if (expression.symbol.owner.origin == IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR) {
|
||||||
|
if (currentClass == null) return expression
|
||||||
|
val simpleFunction = (expression.symbol.owner as? IrSimpleFunction) ?: return expression
|
||||||
|
val property = simpleFunction.correspondingPropertySymbol?.owner ?: return expression
|
||||||
|
if (property.isLateinit) return expression
|
||||||
|
return optimizePropertyAccess(expression, simpleFunction, property, currentClass)
|
||||||
|
}
|
||||||
|
|
||||||
if (isNegation(expression, context) && isNegation(expression.dispatchReceiver!!, context)) {
|
if (isNegation(expression, context) && isNegation(expression.dispatchReceiver!!, context)) {
|
||||||
return (expression.dispatchReceiver as IrCall).dispatchReceiver!!
|
return (expression.dispatchReceiver as IrCall).dispatchReceiver!!
|
||||||
@@ -115,9 +145,41 @@ class JvmBuiltinOptimizationLowering(val context: JvmBackendContext) : FileLower
|
|||||||
return expression
|
return expression
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitWhen(expression: IrWhen): IrExpression {
|
private fun optimizePropertyAccess(
|
||||||
|
expression: IrCall,
|
||||||
|
accessor: IrSimpleFunction,
|
||||||
|
property: IrProperty,
|
||||||
|
currentClass: IrClass
|
||||||
|
): IrExpression {
|
||||||
|
if (accessor.parentAsClass == currentClass &&
|
||||||
|
property.backingField?.parentAsClass == currentClass &&
|
||||||
|
accessor.modality == Modality.FINAL &&
|
||||||
|
!accessor.isExternal
|
||||||
|
) {
|
||||||
|
val backingField = property.backingField!!
|
||||||
|
val receiver = expression.dispatchReceiver
|
||||||
|
return context.createIrBuilder(expression.symbol, expression.startOffset, expression.endOffset).irBlock(expression) {
|
||||||
|
if (backingField.isStatic && receiver != null) {
|
||||||
|
// If the field is static, evaluate the receiver for potential side effects.
|
||||||
|
+receiver.coerceToUnit(context.irBuiltIns)
|
||||||
|
}
|
||||||
|
if (accessor.valueParameters.size > 0) {
|
||||||
|
+irSetField(
|
||||||
|
receiver.takeUnless { backingField.isStatic },
|
||||||
|
backingField,
|
||||||
|
expression.getValueArgument(expression.valueArgumentsCount - 1)!!
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
+irGetField(receiver.takeUnless { backingField.isStatic }, backingField)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return expression
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitWhen(expression: IrWhen, currentClass: IrClass?): IrExpression {
|
||||||
val isCompilerGenerated = expression.origin == null
|
val isCompilerGenerated = expression.origin == null
|
||||||
expression.transformChildrenVoid(this)
|
expression.transformChildren(this, currentClass)
|
||||||
// Remove all branches with constant false condition.
|
// Remove all branches with constant false condition.
|
||||||
expression.branches.removeIf {
|
expression.branches.removeIf {
|
||||||
it.condition.isFalseConst() && isCompilerGenerated
|
it.condition.isFalseConst() && isCompilerGenerated
|
||||||
@@ -259,19 +321,19 @@ class JvmBuiltinOptimizationLowering(val context: JvmBackendContext) : FileLower
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitBlockBody(body: IrBlockBody): IrBody {
|
override fun visitBlockBody(body: IrBlockBody, currentClass: IrClass?): IrBody {
|
||||||
body.transformChildrenVoid(this)
|
body.transformChildren(this, currentClass)
|
||||||
removeUnnecessaryTemporaryVariables(body.statements)
|
removeUnnecessaryTemporaryVariables(body.statements)
|
||||||
return body
|
return body
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitContainerExpression(expression: IrContainerExpression): IrExpression {
|
override fun visitContainerExpression(expression: IrContainerExpression, currentClass: IrClass?): IrExpression {
|
||||||
expression.transformChildrenVoid(this)
|
expression.transformChildren(this, currentClass)
|
||||||
removeUnnecessaryTemporaryVariables(expression.statements)
|
removeUnnecessaryTemporaryVariables(expression.statements)
|
||||||
return expression
|
return expression
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
override fun visitGetValue(expression: IrGetValue, currentClass: IrClass?): IrExpression {
|
||||||
// Replace IrGetValue of an immutable temporary variable with a constant
|
// Replace IrGetValue of an immutable temporary variable with a constant
|
||||||
// initializer with the constant initializer.
|
// initializer with the constant initializer.
|
||||||
val variable = expression.symbol.owner
|
val variable = expression.symbol.owner
|
||||||
@@ -280,6 +342,7 @@ class JvmBuiltinOptimizationLowering(val context: JvmBackendContext) : FileLower
|
|||||||
else
|
else
|
||||||
expression
|
expression
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
irFile.transformChildren(transformer, null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+2
-10
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.ir.expressions.IrFieldAccessExpression
|
|||||||
import org.jetbrains.kotlin.ir.expressions.IrTypeOperator
|
import org.jetbrains.kotlin.ir.expressions.IrTypeOperator
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
import org.jetbrains.kotlin.ir.types.makeNotNull
|
import org.jetbrains.kotlin.ir.types.makeNotNull
|
||||||
|
import org.jetbrains.kotlin.ir.util.coerceToUnit
|
||||||
import org.jetbrains.kotlin.ir.util.hasAnnotation
|
import org.jetbrains.kotlin.ir.util.hasAnnotation
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
@@ -129,16 +130,7 @@ class PropertiesToFieldsLowering(val context: CommonBackendContext) : IrElementT
|
|||||||
if (receiver != null && needBlock) {
|
if (receiver != null && needBlock) {
|
||||||
// Evaluate `dispatchReceiver` for the sake of its side effects, then return `setOrGetExpr`.
|
// Evaluate `dispatchReceiver` for the sake of its side effects, then return `setOrGetExpr`.
|
||||||
return context.createIrBuilder(setOrGetExpr.symbol, setOrGetExpr.startOffset, setOrGetExpr.endOffset).irBlock(setOrGetExpr) {
|
return context.createIrBuilder(setOrGetExpr.symbol, setOrGetExpr.startOffset, setOrGetExpr.endOffset).irBlock(setOrGetExpr) {
|
||||||
// `coerceToUnit()` is private in InsertImplicitCasts, have to reproduce it here
|
+receiver.coerceToUnit(context.irBuiltIns)
|
||||||
val receiverVoid = IrTypeOperatorCallImpl(
|
|
||||||
receiver.startOffset, receiver.endOffset,
|
|
||||||
context.irBuiltIns.unitType,
|
|
||||||
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT,
|
|
||||||
context.irBuiltIns.unitType,
|
|
||||||
receiver
|
|
||||||
)
|
|
||||||
|
|
||||||
+receiverVoid
|
|
||||||
setOrGetExpr.receiver = null
|
setOrGetExpr.receiver = null
|
||||||
+setOrGetExpr
|
+setOrGetExpr
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-15
@@ -37,7 +37,7 @@ import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
|||||||
import org.jetbrains.kotlin.ir.types.IrType
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
import org.jetbrains.kotlin.ir.types.impl.originalKotlinType
|
import org.jetbrains.kotlin.ir.types.impl.originalKotlinType
|
||||||
import org.jetbrains.kotlin.ir.util.TypeTranslator
|
import org.jetbrains.kotlin.ir.util.TypeTranslator
|
||||||
import org.jetbrains.kotlin.ir.util.coerceToUnitIfNeeded
|
import org.jetbrains.kotlin.ir.util.coerceToUnit
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.psi2ir.containsNull
|
import org.jetbrains.kotlin.psi2ir.containsNull
|
||||||
@@ -147,7 +147,7 @@ internal class InsertImplicitCasts(
|
|||||||
body.transformPostfix {
|
body.transformPostfix {
|
||||||
statements.forEachIndexed { i, irStatement ->
|
statements.forEachIndexed { i, irStatement ->
|
||||||
if (irStatement is IrExpression) {
|
if (irStatement is IrExpression) {
|
||||||
body.statements[i] = irStatement.coerceToUnit()
|
body.statements[i] = irStatement.coerceToUnit(irBuiltIns)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -163,7 +163,7 @@ internal class InsertImplicitCasts(
|
|||||||
if (i == lastIndex)
|
if (i == lastIndex)
|
||||||
irStatement.cast(type)
|
irStatement.cast(type)
|
||||||
else
|
else
|
||||||
irStatement.coerceToUnit()
|
irStatement.coerceToUnit(irBuiltIns)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -171,7 +171,7 @@ internal class InsertImplicitCasts(
|
|||||||
override fun visitReturn(expression: IrReturn): IrExpression =
|
override fun visitReturn(expression: IrReturn): IrExpression =
|
||||||
expression.transformPostfix {
|
expression.transformPostfix {
|
||||||
value = if (expression.returnTargetSymbol is IrConstructorSymbol) {
|
value = if (expression.returnTargetSymbol is IrConstructorSymbol) {
|
||||||
value.coerceToUnit()
|
value.coerceToUnit(irBuiltIns)
|
||||||
} else {
|
} else {
|
||||||
val returnTargetDescriptor = expression.returnTarget
|
val returnTargetDescriptor = expression.returnTarget
|
||||||
val isLambdaReturnValue = returnTargetDescriptor is AnonymousFunctionDescriptor
|
val isLambdaReturnValue = returnTargetDescriptor is AnonymousFunctionDescriptor
|
||||||
@@ -233,7 +233,7 @@ internal class InsertImplicitCasts(
|
|||||||
override fun visitLoop(loop: IrLoop): IrExpression =
|
override fun visitLoop(loop: IrLoop): IrExpression =
|
||||||
loop.transformPostfix {
|
loop.transformPostfix {
|
||||||
condition = condition.cast(builtIns.booleanType)
|
condition = condition.cast(builtIns.booleanType)
|
||||||
body = body?.coerceToUnit()
|
body = body?.coerceToUnit(irBuiltIns)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitThrow(expression: IrThrow): IrExpression =
|
override fun visitThrow(expression: IrThrow): IrExpression =
|
||||||
@@ -249,7 +249,7 @@ internal class InsertImplicitCasts(
|
|||||||
aCatch.result = aCatch.result.cast(type)
|
aCatch.result = aCatch.result.cast(type)
|
||||||
}
|
}
|
||||||
|
|
||||||
finallyExpression = finallyExpression?.coerceToUnit()
|
finallyExpression = finallyExpression?.coerceToUnit(irBuiltIns)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitTypeOperator(expression: IrTypeOperatorCall): IrExpression =
|
override fun visitTypeOperator(expression: IrTypeOperatorCall): IrExpression =
|
||||||
@@ -318,7 +318,7 @@ internal class InsertImplicitCasts(
|
|||||||
|
|
||||||
return when {
|
return when {
|
||||||
expectedType.isUnit() ->
|
expectedType.isUnit() ->
|
||||||
coerceToUnit()
|
coerceToUnit(irBuiltIns)
|
||||||
|
|
||||||
valueType.isDynamic() && !expectedType.isDynamic() ->
|
valueType.isDynamic() && !expectedType.isDynamic() ->
|
||||||
if (expectedType.isNullableAny())
|
if (expectedType.isNullableAny())
|
||||||
@@ -383,14 +383,6 @@ internal class InsertImplicitCasts(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrExpression.coerceToUnit(): IrExpression {
|
|
||||||
val valueType = getKotlinType(this)
|
|
||||||
return coerceToUnitIfNeeded(valueType, irBuiltIns)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getKotlinType(irExpression: IrExpression) =
|
|
||||||
irExpression.type.originalKotlinType!!
|
|
||||||
|
|
||||||
private fun KotlinType.isBuiltInIntegerType(): Boolean =
|
private fun KotlinType.isBuiltInIntegerType(): Boolean =
|
||||||
KotlinBuiltIns.isByte(this) ||
|
KotlinBuiltIns.isByte(this) ||
|
||||||
KotlinBuiltIns.isShort(this) ||
|
KotlinBuiltIns.isShort(this) ||
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
|
|||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.*
|
import org.jetbrains.kotlin.ir.symbols.*
|
||||||
import org.jetbrains.kotlin.ir.types.*
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
|
import org.jetbrains.kotlin.ir.types.impl.originalKotlinType
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.SpecialNames
|
import org.jetbrains.kotlin.name.SpecialNames
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||||
@@ -154,6 +155,14 @@ fun IrExpression.isTrueConst() = this is IrConst<*> && this.kind == IrConstKind.
|
|||||||
|
|
||||||
fun IrExpression.isFalseConst() = this is IrConst<*> && this.kind == IrConstKind.Boolean && this.value == false
|
fun IrExpression.isFalseConst() = this is IrConst<*> && this.kind == IrConstKind.Boolean && this.value == false
|
||||||
|
|
||||||
|
fun IrExpression.coerceToUnit(builtins: IrBuiltIns): IrExpression {
|
||||||
|
val valueType = getKotlinType(this)
|
||||||
|
return coerceToUnitIfNeeded(valueType, builtins)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getKotlinType(irExpression: IrExpression) =
|
||||||
|
irExpression.type.toKotlinType()
|
||||||
|
|
||||||
fun IrExpression.coerceToUnitIfNeeded(valueType: KotlinType, irBuiltIns: IrBuiltIns): IrExpression {
|
fun IrExpression.coerceToUnitIfNeeded(valueType: KotlinType, irBuiltIns: IrBuiltIns): IrExpression {
|
||||||
return if (KotlinTypeChecker.DEFAULT.isSubtypeOf(valueType, irBuiltIns.unitType.toKotlinType()))
|
return if (KotlinTypeChecker.DEFAULT.isSubtypeOf(valueType, irBuiltIns.unitType.toKotlinType()))
|
||||||
this
|
this
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
package b
|
package b
|
||||||
|
|
||||||
abstract class B {
|
abstract class B {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
val x = 1
|
val x = 1
|
||||||
|
|
||||||
class A {
|
class A {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
class Example
|
class Example
|
||||||
{
|
{
|
||||||
var a1 = 0
|
var a1 = 0
|
||||||
|
|||||||
Reference in New Issue
Block a user