Add basic support of VArray<Mfvc>
diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt
index 4863bd7..07da6f1 100644
--- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt
+++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt
@@ -241,6 +241,8 @@
configuration.get(JVMConfigurationKeys.STRING_CONCAT) ?: JvmStringConcat.INDY_WITH_CONSTANTS
else JvmStringConcat.INLINE
+ val mfvcVArrayFlatteningScheme = JvmMfvcVArrayFlatteningScheme.PER_SIZE // TODO init with respect to configuration
+
val samConversionsScheme = run {
val fromConfig = configuration.get(JVMConfigurationKeys.SAM_CONVERSIONS)
if (fromConfig != null && target >= fromConfig.minJvmTarget)
diff --git a/compiler/config.jvm/src/org/jetbrains/kotlin/config/JvmMfvcVArrayFlatteningScheme.kt b/compiler/config.jvm/src/org/jetbrains/kotlin/config/JvmMfvcVArrayFlatteningScheme.kt
new file mode 100644
index 0000000..24d9909
--- /dev/null
+++ b/compiler/config.jvm/src/org/jetbrains/kotlin/config/JvmMfvcVArrayFlatteningScheme.kt
@@ -0,0 +1,15 @@
+/*
+ * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * 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.config
+
+/**
+ * VArray<Mfvc> flattening scheme
+ *
+ * See [explanation](https://github.com/grechkovlad/vArrayBenchmarksReport) what do these schemes mean
+ */
+enum class JvmMfvcVArrayFlatteningScheme {
+ PER_TYPE, PER_SIZE, THREE_ARRAYS, TWO_ARRAYS
+}
\ No newline at end of file
diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/IrBuiltInsOverFir.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/IrBuiltInsOverFir.kt
index 3e9f952..12e11f1 100644
--- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/IrBuiltInsOverFir.kt
+++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/IrBuiltInsOverFir.kt
@@ -415,6 +415,14 @@
}
}
+ override val vArrayIteratorFunction: IrSimpleFunctionSymbol? by lazy {
+ findFunctions(kotlinPackage, Name.identifier("iterator")).firstOrNull {
+ it.owner.extensionReceiverParameter?.type?.classOrNull == vArrayClass
+ && it.owner.valueParameters.size == 0
+ }
+ }
+
+
override lateinit var checkNotNullSymbol: IrSimpleFunctionSymbol private set
override val arrayOfNulls: IrSimpleFunctionSymbol by lazy {
findFunctions(kotlinPackage, Name.identifier("arrayOfNulls")).first {
diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenTestGenerated.java
index 65ceff7..2d7182b 100644
--- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenTestGenerated.java
+++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenTestGenerated.java
@@ -52198,6 +52198,124 @@
public void testVarargParameterOfInlineType() throws Exception {
runTest("compiler/testData/codegen/box/vArrays/varargParameterOfInlineType.kt");
}
+
+ @Nested
+ @TestMetadata("compiler/testData/codegen/box/vArrays/mfvc")
+ @TestDataPath("$PROJECT_ROOT")
+ public class Mfvc {
+ @Test
+ public void testAllFilesPresentInMfvc() throws Exception {
+ KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/vArrays/mfvc"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
+ }
+
+ @Test
+ @TestMetadata("customIterator.kt")
+ public void testCustomIterator() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/customIterator.kt");
+ }
+
+ @Test
+ @TestMetadata("typesEncodings.kt")
+ public void testTypesEncodings() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/typesEncodings.kt");
+ }
+
+ @Test
+ @TestMetadata("vArray2D.kt")
+ public void testVArray2D() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArray2D.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayAsFunctionParameter.kt")
+ public void testVArrayAsFunctionParameter() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayAsFunctionParameter.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayAsLambdaParameter.kt")
+ public void testVArrayAsLambdaParameter() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayAsLambdaParameter.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayAsLambdaReturnType.kt")
+ public void testVArrayAsLambdaReturnType() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayAsLambdaReturnType.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayAsMfvcProperty.kt")
+ public void testVArrayAsMfvcProperty() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayAsMfvcProperty.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayAsProperty.kt")
+ public void testVArrayAsProperty() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayAsProperty.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayAsPropertyNoBackingField.kt")
+ public void testVArrayAsPropertyNoBackingField() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayAsPropertyNoBackingField.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayAsReturnType.kt")
+ public void testVArrayAsReturnType() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayAsReturnType.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayAsSfvcProperty.kt")
+ public void testVArrayAsSfvcProperty() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayAsSfvcProperty.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayChainAssignment.kt")
+ public void testVArrayChainAssignment() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayChainAssignment.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayExpression.kt")
+ public void testVArrayExpression() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayExpression.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayInIfElseBlock.kt")
+ public void testVArrayInIfElseBlock() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayInIfElseBlock.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayInTryBlock.kt")
+ public void testVArrayInTryBlock() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayInTryBlock.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayInWhenExpr.kt")
+ public void testVArrayInWhenExpr() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayInWhenExpr.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayIterator.kt")
+ public void testVArrayIterator() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayIterator.kt");
+ }
+
+ @Test
+ @TestMetadata("vArraySize.kt")
+ public void testVArraySize() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArraySize.kt");
+ }
+ }
}
@Nested
diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java
index db04d46..89e56b1 100644
--- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java
+++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java
@@ -52198,6 +52198,124 @@
public void testVarargParameterOfInlineType() throws Exception {
runTest("compiler/testData/codegen/box/vArrays/varargParameterOfInlineType.kt");
}
+
+ @Nested
+ @TestMetadata("compiler/testData/codegen/box/vArrays/mfvc")
+ @TestDataPath("$PROJECT_ROOT")
+ public class Mfvc {
+ @Test
+ public void testAllFilesPresentInMfvc() throws Exception {
+ KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/vArrays/mfvc"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
+ }
+
+ @Test
+ @TestMetadata("customIterator.kt")
+ public void testCustomIterator() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/customIterator.kt");
+ }
+
+ @Test
+ @TestMetadata("typesEncodings.kt")
+ public void testTypesEncodings() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/typesEncodings.kt");
+ }
+
+ @Test
+ @TestMetadata("vArray2D.kt")
+ public void testVArray2D() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArray2D.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayAsFunctionParameter.kt")
+ public void testVArrayAsFunctionParameter() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayAsFunctionParameter.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayAsLambdaParameter.kt")
+ public void testVArrayAsLambdaParameter() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayAsLambdaParameter.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayAsLambdaReturnType.kt")
+ public void testVArrayAsLambdaReturnType() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayAsLambdaReturnType.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayAsMfvcProperty.kt")
+ public void testVArrayAsMfvcProperty() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayAsMfvcProperty.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayAsProperty.kt")
+ public void testVArrayAsProperty() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayAsProperty.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayAsPropertyNoBackingField.kt")
+ public void testVArrayAsPropertyNoBackingField() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayAsPropertyNoBackingField.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayAsReturnType.kt")
+ public void testVArrayAsReturnType() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayAsReturnType.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayAsSfvcProperty.kt")
+ public void testVArrayAsSfvcProperty() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayAsSfvcProperty.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayChainAssignment.kt")
+ public void testVArrayChainAssignment() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayChainAssignment.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayExpression.kt")
+ public void testVArrayExpression() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayExpression.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayInIfElseBlock.kt")
+ public void testVArrayInIfElseBlock() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayInIfElseBlock.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayInTryBlock.kt")
+ public void testVArrayInTryBlock() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayInTryBlock.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayInWhenExpr.kt")
+ public void testVArrayInWhenExpr() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayInWhenExpr.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayIterator.kt")
+ public void testVArrayIterator() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayIterator.kt");
+ }
+
+ @Test
+ @TestMetadata("vArraySize.kt")
+ public void testVArraySize() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArraySize.kt");
+ }
+ }
}
@Nested
diff --git a/compiler/ir/backend.jvm/codegen/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrDataClassArrayMemberHashCode.kt b/compiler/ir/backend.jvm/codegen/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrDataClassArrayMemberHashCode.kt
index 3e969c7..3a8548f 100644
--- a/compiler/ir/backend.jvm/codegen/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrDataClassArrayMemberHashCode.kt
+++ b/compiler/ir/backend.jvm/codegen/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrDataClassArrayMemberHashCode.kt
@@ -9,16 +9,22 @@
import org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen
import org.jetbrains.kotlin.backend.jvm.codegen.PromisedValue
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
+import org.jetbrains.kotlin.ir.types.classFqName
import org.jetbrains.kotlin.ir.util.isPrimitiveArray
object IrDataClassArrayMemberHashCode : IntrinsicMethod() {
override fun invoke(expression: IrFunctionAccessExpression, codegen: ExpressionCodegen, data: BlockInfo): PromisedValue? =
with(codegen) {
val arrayType = expression.getValueArgument(0)!!.type
- val asmArrayType = codegen.typeMapper.mapType(arrayType)
- gen(expression.getValueArgument(0)!!, asmArrayType, arrayType, data)
- val hashCodeArgumentDescriptor = if (arrayType.isPrimitiveArray()) asmArrayType.descriptor else "[Ljava/lang/Object;"
- mv.invokestatic("java/util/Arrays", "hashCode", "($hashCodeArgumentDescriptor)I", false)
+ // TODO: temporary solution until implementation of VArrays.hashCode()
+ if (arrayType.classFqName!!.shortName().asString().startsWith("VArrayWrapper")) {
+ mv.aconst(0)
+ } else {
+ val asmArrayType = codegen.typeMapper.mapType(arrayType)
+ gen(expression.getValueArgument(0)!!, asmArrayType, arrayType, data)
+ val hashCodeArgumentDescriptor = if (arrayType.isPrimitiveArray()) asmArrayType.descriptor else "[Ljava/lang/Object;"
+ mv.invokestatic("java/util/Arrays", "hashCode", "($hashCodeArgumentDescriptor)I", false)
+ }
return expression.onStack
}
}
diff --git a/compiler/ir/backend.jvm/codegen/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrDataClassArrayMemberToString.kt b/compiler/ir/backend.jvm/codegen/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrDataClassArrayMemberToString.kt
index 162d58d..f29311f 100644
--- a/compiler/ir/backend.jvm/codegen/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrDataClassArrayMemberToString.kt
+++ b/compiler/ir/backend.jvm/codegen/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrDataClassArrayMemberToString.kt
@@ -9,16 +9,22 @@
import org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen
import org.jetbrains.kotlin.backend.jvm.codegen.PromisedValue
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
+import org.jetbrains.kotlin.ir.types.classFqName
import org.jetbrains.kotlin.ir.util.isPrimitiveArray
object IrDataClassArrayMemberToString : IntrinsicMethod() {
override fun invoke(expression: IrFunctionAccessExpression, codegen: ExpressionCodegen, data: BlockInfo): PromisedValue? =
with(codegen) {
val arrayType = expression.getValueArgument(0)!!.type
- val asmArrayType = codegen.typeMapper.mapType(arrayType)
- gen(expression.getValueArgument(0)!!, asmArrayType, arrayType, data)
- val toStringArgumentDescriptor = if (arrayType.isPrimitiveArray()) asmArrayType.descriptor else "[Ljava/lang/Object;"
- mv.invokestatic("java/util/Arrays", "toString", "($toStringArgumentDescriptor)Ljava/lang/String;", false)
+ // TODO: temporary solution until implementation of VArrays.toString()
+ if (arrayType.classFqName!!.shortName().asString().startsWith("VArrayWrapper")) {
+ mv.aconst("STUB")
+ } else {
+ val asmArrayType = codegen.typeMapper.mapType(arrayType)
+ gen(expression.getValueArgument(0)!!, asmArrayType, arrayType, data)
+ val toStringArgumentDescriptor = if (arrayType.isPrimitiveArray()) asmArrayType.descriptor else "[Ljava/lang/Object;"
+ mv.invokestatic("java/util/Arrays", "toString", "($toStringArgumentDescriptor)Ljava/lang/String;", false)
+ }
return expression.onStack
}
}
diff --git a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmInlineClassLowering.kt b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmInlineClassLowering.kt
index 21f1bb8..c16460b 100644
--- a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmInlineClassLowering.kt
+++ b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmInlineClassLowering.kt
@@ -14,6 +14,7 @@
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.config.ApiVersion
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
+import org.jetbrains.kotlin.descriptors.InlineClassRepresentation
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.*
@@ -101,6 +102,8 @@
}
override fun handleSpecificNewClass(declaration: IrClass) {
+ transformInlineClassRepresentationIfNeeded(declaration)
+
val irConstructor = declaration.primaryConstructor!!
// The field getter is used by reflection and cannot be removed here unless it is internal.
declaration.declarations.removeIf {
@@ -113,6 +116,16 @@
addJvmInlineAnnotation(declaration)
}
+ private fun transformInlineClassRepresentationIfNeeded(declaration: IrClass) {
+ require(declaration.inlineClassRepresentation != null)
+ val inlineClassRepresentation = declaration.inlineClassRepresentation!!
+ val transformedUnderlyingType =
+ applyVArrayWrappingTypeTransformation(inlineClassRepresentation.underlyingType, replacements.flatteningSymbolsHelper)
+ require(transformedUnderlyingType is IrSimpleType)
+ declaration.valueClassRepresentation =
+ InlineClassRepresentation(inlineClassRepresentation.underlyingPropertyName, transformedUnderlyingType)
+ }
+
private fun addJvmInlineAnnotation(valueClass: IrClass) {
if (valueClass.hasAnnotation(JVM_INLINE_ANNOTATION_FQ_NAME)) return
val constructor = context.ir.symbols.jvmInlineAnnotation.constructors.first()
diff --git a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmMultiFieldValueClassLowering.kt b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmMultiFieldValueClassLowering.kt
index 164a1e1..f657cd5 100644
--- a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmMultiFieldValueClassLowering.kt
+++ b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmMultiFieldValueClassLowering.kt
@@ -8,6 +8,7 @@
import org.jetbrains.kotlin.backend.common.ScopeWithIr
import org.jetbrains.kotlin.backend.common.ir.inline
import org.jetbrains.kotlin.backend.common.lower.irCatch
+import org.jetbrains.kotlin.backend.common.lower.irThrow
import org.jetbrains.kotlin.backend.common.pop
import org.jetbrains.kotlin.backend.common.push
import org.jetbrains.kotlin.backend.jvm.*
@@ -19,9 +20,7 @@
import org.jetbrains.kotlin.backend.jvm.lower.BlockOrBody.Block
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.Modality
-import org.jetbrains.kotlin.ir.IrElement
-import org.jetbrains.kotlin.ir.IrStatement
-import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
+import org.jetbrains.kotlin.ir.*
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
import org.jetbrains.kotlin.ir.declarations.*
@@ -30,16 +29,13 @@
import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrEnumConstructorCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl
-import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
-import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
-import org.jetbrains.kotlin.ir.symbols.IrSymbol
-import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
+import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.symbols.impl.IrAnonymousInitializerSymbolImpl
-import org.jetbrains.kotlin.ir.transformStatement
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.*
import org.jetbrains.kotlin.name.Name
+import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.utils.addIfNotNull
internal class JvmMultiFieldValueClassLowering(
@@ -196,6 +192,49 @@
return getterExpression
}
+ fun IrBlockBuilder.lowerMfvcVArrayGet(expression: IrCall): IrExpression {
+ val mfvcNode = replacements.getRootMfvcNode(expression.type.erasedUpperBound)
+ val mapper = replacements.getMfvcVArrayMapper(mfvcNode)
+ require(expression.dispatchReceiver != null)
+ val vArrayWrapperTempVariable = savableStandaloneVariableWithSetter(
+ expression = expression.dispatchReceiver!!,
+ origin = IrDeclarationOrigin.IR_TEMPORARY_VARIABLE,
+ saveVariable = ::variablesSaver
+ )
+ require(expression.valueArgumentsCount == 1)
+ val indexInVArrayExpr = expression.getValueArgument(0)!!
+ val indexInVArrayTempVariable = savableStandaloneVariableWithSetter(
+ expression = indexInVArrayExpr,
+ origin = IrDeclarationOrigin.IR_TEMPORARY_VARIABLE,
+ saveVariable = ::variablesSaver
+ )
+ val tempVariables = List(mfvcNode.leavesCount) { leafIndex ->
+ val mapping = mapper.map(indexInVArrayTempVariable, leafIndex, this, replacements.flatteningSymbolsHelper)
+ val leafValue = irCall(mapping.wrapperArrayGetFunction).apply {
+ dispatchReceiver = irGetField(
+ irGet(vArrayWrapperTempVariable),
+ mapping.wrapperField.owner
+ )
+ putValueArgument(0, mapping.indexInWrapperArray)
+ }
+ val decodedValue = mapping.decodeFunction(leafValue, this)
+ // TODO: Investigate how to get rid of temporary variables. They are presumably blame for excess bytecode.
+ savableStandaloneVariableWithSetter(
+ decodedValue,
+ name = null,
+ isMutable = false,
+ origin = JvmLoweredDeclarationOrigin.MULTI_FIELD_VALUE_CLASS_REPRESENTATION_VARIABLE,
+ saveVariable = ::variablesSaver
+ )
+ }
+ val typeArguments = makeTypeArgumentsFromType(expression.type as IrSimpleType)
+ val nodeInstance = ValueDeclarationMfvcNodeInstance(mfvcNode, typeArguments, tempVariables)
+ val resultExpr = nodeInstance.makeGetterExpression(this, irCurrentClass, ::registerPossibleExtraBoxUsage)
+ registerReplacement(resultExpr, nodeInstance)
+ +resultExpr
+ return resultExpr
+ }
+
private fun makeTypeArgumentsFromField(expression: IrFieldAccessExpression) = buildMap {
val field = expression.symbol.owner
putAll(makeTypeArgumentsFromType(field.type as IrSimpleType))
@@ -303,9 +342,15 @@
}
}
+ transformVArrayTypes(declaration)
+
return declaration
}
+ private fun transformVArrayTypes(declaration: IrClass) {
+ declaration.transformChildrenVoid(MfvcVArrayTypeWrapperVisitor(replacements.flatteningSymbolsHelper))
+ }
+
override fun visitClassNewDeclarationsWhenParallel(declaration: IrDeclaration) =
postActionAfterTransformingClassDeclaration(declaration)
@@ -963,6 +1008,24 @@
}
}
+ isCreationOfFlattenedVArray(expression, context) -> {
+ context.createJvmIrBuilder(currentScope.symbol, expression).irBlock {
+ require(expression.typeArgumentsCount == 1)
+ val rootNode = replacements.getRootMfvcNode(expression.getTypeArgument(0)!!.erasedUpperBound)
+ val flatteningScheme = replacements.getMfvcVArrayMapper(rootNode)
+ require(expression.valueArgumentsCount == 1)
+ val vArraySizeExpr = expression.getValueArgument(0)!!
+ val constructorCall =
+ flatteningScheme.getVArrayWrapperCreationCall(
+ vArraySizeExpr,
+ this,
+ replacements.flatteningSymbolsHelper,
+ ::variablesSaver
+ )
+ +constructorCall
+ }.unwrapBlock()
+ }
+
replacement != null -> context.createJvmIrBuilder(currentScope.symbol, expression).irBlock {
buildReplacement(function, expression, replacement)
}.unwrapBlock()
@@ -1069,9 +1132,177 @@
}
}.unwrapBlock()
}
+ if (isGetOnFlattenedVArray(expression, replacements.flatteningSymbolsHelper)) {
+ expression.transformChildrenVoid()
+ return context.createJvmIrBuilder(getCurrentScopeSymbol(), expression).irBlock {
+ with(valueDeclarationsRemapper) {
+ lowerMfvcVArrayGet(expression)
+ }
+ }.unwrapBlock()
+ }
+ if (isSetOnFlattenVArray(expression, replacements.flatteningSymbolsHelper)) {
+ expression.transformChildrenVoid()
+ val flattenSetBlock = context.createJvmIrBuilder(getCurrentScopeSymbol(), expression).irBlock {
+ lowerMfvcVArraySet(expression)
+ }
+ return flattenSetBlock
+ }
+ if (isGetSizeOnFlattenedVArray(expression, replacements.flatteningSymbolsHelper)) {
+ expression.transformChildrenVoid()
+ return context.createJvmIrBuilder(getCurrentScopeSymbol(), expression)
+ .irGetField(expression.dispatchReceiver!!, replacements.flatteningSymbolsHelper.wrapperSizeField.owner)
+ }
+ if (isFlattenedVArrayIteratorCreation(expression, context)) {
+ require(expression.extensionReceiver != null)
+ expression.transformChildrenVoid()
+ return with(context.createJvmIrBuilder(getCurrentScopeSymbol(), expression)) {
+ irCall(replacements.flatteningSymbolsHelper.vArrayWrapperIteratorStateHolderConstructor).apply {
+ putValueArgument(0, expression.extensionReceiver)
+ putValueArgument(1, irInt(0))
+ }
+ }
+ }
+ if (isFlattenedVArrayIteratorHasNext(expression)) {
+ expression.transformChildrenVoid()
+ return context.createJvmIrBuilder(getCurrentScopeSymbol(), expression).irBlock {
+ lowerMfvcVArrayIteratorHasNext(expression)
+ }
+ }
+ if (isFlattenedVArrayIteratorNext(expression)) {
+ val lowered = context.createJvmIrBuilder(getCurrentScopeSymbol(), expression).irBlock {
+ lowerMfvcVArrayIteratorNext(expression)
+ }
+ lowered.transformChildrenVoid()
+ return lowered
+ }
return super.visitCall(expression)
}
+ private fun IrBlockBuilder.lowerMfvcVArrayIteratorNext(expression: IrCall) {
+ require(expression.dispatchReceiver != null)
+ val symbols = replacements.flatteningSymbolsHelper
+ // Generate IR for:
+ // try { it.array[it.index++] } catch (e: ArrayIndexOutOfBoundsException) { it.index--; throw NoSuchElementException(e.message) }
+ val iteratorTempVariable = savableStandaloneVariableWithSetter(
+ expression = expression.dispatchReceiver!!,
+ origin = IrDeclarationOrigin.IR_TEMPORARY_VARIABLE,
+ saveVariable = ::variablesSaver
+ )
+ val vArrayGet = irCall(symbols.vArrayGet!!, expression.type).apply {
+ dispatchReceiver = irGetField(irGet(iteratorTempVariable), symbols.vArrayWrapperIteratorStateHolderArrayField.owner)
+ putValueArgument(0, irBlock {
+ val indexTempVariable = savableStandaloneVariableWithSetter(
+ expression = irGetField(irGet(iteratorTempVariable), symbols.vArrayWrapperIteratorStateHolderIndexField.owner),
+ origin = IrDeclarationOrigin.IR_TEMPORARY_VARIABLE,
+ saveVariable = ::variablesSaver
+ )
+ +irSetField(
+ irGet(iteratorTempVariable),
+ symbols.vArrayWrapperIteratorStateHolderIndexField.owner,
+ irCall(context.irBuiltIns.intClass.getSimpleFunction("inc")!!).apply {
+ dispatchReceiver = irGet(indexTempVariable)
+ }
+ )
+ +irGet(indexTempVariable)
+ })
+ }
+ val catchParameter = savableStandaloneVariable(
+ type = this@JvmMultiFieldValueClassLowering.context.ir.symbols.arrayIndexOutOfBoundsException.defaultType,
+ isVar = false,
+ origin = IrDeclarationOrigin.CATCH_PARAMETER,
+ saveVariable = {}
+ )
+ +irTry(
+ type = expression.type,
+ tryResult = vArrayGet,
+ catches = listOf(irCatch(
+ catchParameter = catchParameter,
+ result = irBlock {
+ +irSetField(
+ irGet(iteratorTempVariable),
+ symbols.vArrayWrapperIteratorStateHolderIndexField.owner,
+ irCall(context.irBuiltIns.intClass.getSimpleFunction("dec")!!).apply {
+ dispatchReceiver =
+ irGetField(irGet(iteratorTempVariable), symbols.vArrayWrapperIteratorStateHolderIndexField.owner)
+ })
+ +irThrow(irCall(symbols.noSuchElementExceptionConstructor).apply {
+ putValueArgument(0, irCall(symbols.throwableMessageGetter).apply {
+ dispatchReceiver = irGet(catchParameter)
+ })
+ })
+ }
+ )),
+ finallyExpression = null
+ )
+ }
+
+ private fun IrBlockBuilder.lowerMfvcVArrayIteratorHasNext(expression: IrCall) {
+ require(expression.dispatchReceiver != null)
+ val iteratorTempVariable = savableStandaloneVariableWithSetter(
+ expression = expression.dispatchReceiver!!,
+ origin = IrDeclarationOrigin.IR_TEMPORARY_VARIABLE,
+ saveVariable = ::variablesSaver
+ )
+ // IR for: iteratorStateHolder.index < iteratorStateHolder.array.size
+ +irCall(context.irBuiltIns.lessFunByOperandType[context.irBuiltIns.intType.classifierOrFail]!!).apply {
+ putValueArgument(
+ 0,
+ irGetField(
+ irGet(iteratorTempVariable),
+ replacements.flatteningSymbolsHelper.vArrayWrapperIteratorStateHolderIndexField.owner
+ )
+ )
+ putValueArgument(
+ 1,
+ irGetField(
+ irGetField(
+ irGet(iteratorTempVariable),
+ replacements.flatteningSymbolsHelper.vArrayWrapperIteratorStateHolderArrayField.owner
+ ), replacements.flatteningSymbolsHelper.wrapperSizeField.owner
+ )
+ )
+ }
+ }
+
+ private fun IrBlockBuilder.lowerMfvcVArraySet(setCall: IrCall) {
+ require(setCall.valueArgumentsCount == 2)
+ val vArrayIndexExpr = setCall.getValueArgument(0)!!
+ val vArrayIndexTempVariable = savableStandaloneVariableWithSetter(
+ expression = vArrayIndexExpr,
+ origin = IrDeclarationOrigin.IR_TEMPORARY_VARIABLE,
+ saveVariable = ::variablesSaver
+ )
+ val tempVariableForSetValue = savableStandaloneVariableWithSetter(
+ setCall.getValueArgument(1)!!,
+ origin = IrDeclarationOrigin.IR_TEMPORARY_VARIABLE,
+ saveVariable = ::variablesSaver
+ )
+ require(setCall.dispatchReceiver != null)
+ val vArrayWrapperTempVariable = savableStandaloneVariableWithSetter(
+ expression = setCall.dispatchReceiver!!,
+ origin = IrDeclarationOrigin.IR_TEMPORARY_VARIABLE,
+ saveVariable = ::variablesSaver
+ )
+ val mfvcNode = replacements.getRootMfvcNode(setCall.getValueArgument(1)!!.type.erasedUpperBound)
+ val mapper = replacements.getMfvcVArrayMapper(mfvcNode)
+ mfvcNode.leaves.forEachIndexed { leafIndex, leaf ->
+ val mapping = mapper.map(vArrayIndexTempVariable, leafIndex, this, replacements.flatteningSymbolsHelper)
+ val leafValue = irCall(leaf.unboxMethod).apply {
+ dispatchReceiver = irGet(tempVariableForSetValue)
+ }
+ val encodedValue = mapping.encodeFunction(leafValue, this)
+ val leafSetCall = irCall(mapping.wrapperArraySetFunction).apply {
+ dispatchReceiver = irGetField(
+ irGet(vArrayWrapperTempVariable),
+ mapping.wrapperField.owner
+ )
+ putValueArgument(0, mapping.indexInWrapperArray)
+ putValueArgument(1, encodedValue)
+ }
+ +leafSetCall
+ }
+ }
+
private fun IrBlockBuilder.buildReplacement(
originalFunction: IrFunction,
original: IrMemberAccessExpression<*>,
@@ -1671,3 +1902,70 @@
clear()
addAll(replacement)
}
+
+private fun isFlattenedVArrayIterator(type: IrType): Boolean {
+ if (type !is IrSimpleType) return false
+ if (type.classFqName != StandardClassIds.vArrayIterator.asSingleFqName()) return false
+ require(type.arguments.size == 1)
+ val typeArg = type.arguments[0]
+ require(typeArg is IrSimpleType)
+ return typeArg.needsMfvcFlattening()
+}
+
+private fun isFlattenedVArrayIteratorNext(expression: IrCall): Boolean {
+ if (expression.dispatchReceiver == null) return false
+ return isFlattenedVArrayIterator(expression.dispatchReceiver!!.type) && expression.symbol.owner.name == Name.identifier("next")
+}
+
+private fun isFlattenedVArrayIteratorHasNext(expression: IrCall): Boolean {
+ if (expression.dispatchReceiver == null) return false
+ return isFlattenedVArrayIterator(expression.dispatchReceiver!!.type) && expression.symbol.owner.name == Name.identifier("hasNext")
+}
+
+private fun isFlattenedVArrayIteratorCreation(expression: IrCall, context: JvmBackendContext) =
+ expression.symbol == context.irBuiltIns.vArrayIteratorFunction && expression.extensionReceiver?.type?.isFlattenedVArray() == true
+
+private fun isCreationOfFlattenedVArray(expression: IrFunctionAccessExpression, context: JvmBackendContext) =
+ expression.symbol == context.irBuiltIns.vArrayOfNulls && expression.type.isFlattenedVArray()
+
+private fun isGetSizeOnFlattenedVArray(expression: IrCall, symbols: FlatteningSymbolsHelper) =
+ expression.symbol == symbols.vArraySizeGetter && expression.dispatchReceiver?.type?.isFlattenedVArray() == true
+
+private fun isGetOnFlattenedVArray(expression: IrCall, symbols: FlatteningSymbolsHelper) =
+ expression.symbol == symbols.vArrayGet && expression.type.needsMfvcFlattening()
+
+private fun isSetOnFlattenVArray(expression: IrCall, symbols: FlatteningSymbolsHelper) =
+ expression.symbol == symbols.vArraySet && expression.getValueArgument(1)?.type?.needsMfvcFlattening() == true
+
+private class MfvcVArrayTypeWrapperVisitor(private val symbols: FlatteningSymbolsHelper) :
+ IrElementTransformerVoid() {
+
+ override fun visitCall(expression: IrCall): IrExpression {
+ return visitExpression(expression)
+ }
+
+ override fun visitExpression(expression: IrExpression): IrExpression {
+ expression.type = applyVArrayWrappingTypeTransformation(expression.type, symbols)
+ return super.visitExpression(expression)
+ }
+
+ override fun visitValueParameter(declaration: IrValueParameter): IrStatement {
+ declaration.type = applyVArrayWrappingTypeTransformation(declaration.type, symbols)
+ return super.visitValueParameter(declaration)
+ }
+
+ override fun visitField(declaration: IrField): IrStatement {
+ declaration.type = applyVArrayWrappingTypeTransformation(declaration.type, symbols)
+ return super.visitField(declaration)
+ }
+
+ override fun visitVariable(declaration: IrVariable): IrStatement {
+ declaration.type = applyVArrayWrappingTypeTransformation(declaration.type, symbols)
+ return super.visitVariable(declaration)
+ }
+
+ override fun visitFunction(declaration: IrFunction): IrStatement {
+ declaration.returnType = applyVArrayWrappingTypeTransformation(declaration.returnType, symbols)
+ return super.visitFunction(declaration)
+ }
+}
diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmSymbols.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmSymbols.kt
index 0606ee3..24286e6 100644
--- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmSymbols.kt
+++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmSymbols.kt
@@ -649,6 +649,54 @@
val arrayOfAnyType = irBuiltIns.arrayClass.typeWith(irBuiltIns.anyType)
val arrayOfAnyNType = irBuiltIns.arrayClass.typeWith(irBuiltIns.anyNType)
+ private fun IrClass.addPrimaryConstructorByFields() {
+ addConstructor { isPrimary = true }.apply {
+ fields.forEach { field -> addValueParameter(field.name, field.type) }
+ }
+ }
+
+ val vArrayWrapperPerSizeClass: IrClassSymbol = createClass(FqName("kotlin.jvm.internal.VArrayWrapperPerSize")) { klass ->
+ klass.addField("ones", irBuiltIns.byteArray.defaultType.makeNullable(), DescriptorVisibilities.PUBLIC)
+ klass.addField("twos", irBuiltIns.shortArray.defaultType.makeNullable(), DescriptorVisibilities.PUBLIC)
+ klass.addField("fours", irBuiltIns.intArray.defaultType.makeNullable(), DescriptorVisibilities.PUBLIC)
+ klass.addField("eights", irBuiltIns.longArray.defaultType.makeNullable(), DescriptorVisibilities.PUBLIC)
+ klass.addField("refs", arrayOfAnyNType.makeNullable(), DescriptorVisibilities.PUBLIC)
+ klass.addField("size", irBuiltIns.intType, DescriptorVisibilities.PUBLIC)
+
+ klass.addPrimaryConstructorByFields()
+ }
+
+ val vArrayWrapperTwoArrays: IrClassSymbol = createClass(FqName("kotlin.jvm.internal.VArrayWrapperTwoArrays")) { klass ->
+ klass.addField("longs", irBuiltIns.longArray.defaultType.makeNullable(), DescriptorVisibilities.PUBLIC)
+ klass.addField("refs", arrayOfAnyNType.makeNullable(), DescriptorVisibilities.PUBLIC)
+ klass.addField("size", irBuiltIns.intType, DescriptorVisibilities.PUBLIC)
+
+ klass.addPrimaryConstructorByFields()
+ }
+
+ val vArrayPerSizeIteratorStateHolder: IrClassSymbol =
+ createClass(FqName("kotlin.jvm.internal.VArrayPerSizeIteratorStateHolder")) { klass ->
+ klass.addField("array", vArrayWrapperPerSizeClass.owner.defaultType, DescriptorVisibilities.PUBLIC)
+ klass.addField("index", irBuiltIns.intType, DescriptorVisibilities.PUBLIC)
+
+ klass.addPrimaryConstructorByFields()
+ }
+
+ val vArrayTwoArraysIteratorStateHolder: IrClassSymbol =
+ createClass(FqName("kotlin.jvm.internal.VArrayTwoArraysIteratorStateHolder")) { klass ->
+ klass.addField("array", vArrayWrapperTwoArrays.owner.defaultType, DescriptorVisibilities.PUBLIC)
+ klass.addField("index", irBuiltIns.intType, DescriptorVisibilities.PUBLIC)
+
+ klass.addPrimaryConstructorByFields()
+ }
+
+ val arrayIndexOutOfBoundsException: IrClassSymbol = createClass(FqName("java.lang.ArrayIndexOutOfBoundsException"))
+ val noSuchElementException: IrClassSymbol = createClass(FqName("java.util.NoSuchElementException")) { klass ->
+ klass.addConstructor().apply {
+ addValueParameter("message", string.defaultType)
+ }
+ }
+
// Intrinsic to represent closure creation using INVOKEDYNAMIC with LambdaMetafactory.{metafactory, altMetafactory}
// as a bootstrap method.
// fun <SAM_TYPE> `<jvm-indy-lambda-metafactory>`(
@@ -832,6 +880,60 @@
}
}
+ val charCodeGetter: IrFunctionSymbol =
+ irFactory.buildProperty {
+ name = Name.identifier("code")
+ }.apply {
+ parent = createClass(FqName("kotlin.CharCodeKt")).owner
+ addGetter().apply {
+ isInline = true
+ addExtensionReceiver(irBuiltIns.charType)
+ returnType = irBuiltIns.intType
+ }
+ }.getter!!.symbol
+
+ val floatToRawBits: IrFunctionSymbol =
+ irFactory.buildFun {
+ name = Name.identifier("toRawBits")
+ }.apply {
+ isInline = true
+ parent = createClass(FqName("kotlin.NumbersKt__NumbersJVMKt")).owner
+ addExtensionReceiver(irBuiltIns.floatType)
+ returnType = irBuiltIns.intType
+ }.symbol
+
+ val floatFromBits: IrSimpleFunctionSymbol =
+ irFactory.buildFun {
+ name = Name.identifier("fromBits")
+ }.apply {
+ isInline = true
+ parent = createClass(FqName("kotlin.NumbersKt__NumbersJVMKt")).owner
+ addExtensionReceiver(irBuiltIns.floatClass.owner.companionObject()!!.defaultType)
+ addValueParameter("bits", irBuiltIns.intType)
+ returnType = irBuiltIns.floatType
+ }.symbol
+
+ val doubleFromBits: IrSimpleFunctionSymbol =
+ irFactory.buildFun {
+ name = Name.identifier("fromBits")
+ }.apply {
+ isInline = true
+ parent = createClass(FqName("kotlin.NumbersKt__NumbersJVMKt")).owner
+ addExtensionReceiver(irBuiltIns.doubleClass.owner.companionObject()!!.defaultType)
+ addValueParameter("bits", irBuiltIns.longType)
+ returnType = irBuiltIns.doubleType
+ }.symbol
+
+ val doubleToRawBits: IrFunctionSymbol =
+ irFactory.buildFun {
+ name = Name.identifier("toRawBits")
+ }.apply {
+ isInline = true
+ parent = createClass(FqName("kotlin.NumbersKt__NumbersJVMKt")).owner
+ addExtensionReceiver(irBuiltIns.doubleType)
+ returnType = irBuiltIns.longType
+ }.symbol
+
val kClassJava: IrPropertySymbol =
irFactory.buildProperty {
name = Name.identifier("java")
diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedMultiFieldValueClassReplacements.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedMultiFieldValueClassReplacements.kt
index 48e194d..254134f 100644
--- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedMultiFieldValueClassReplacements.kt
+++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedMultiFieldValueClassReplacements.kt
@@ -7,6 +7,7 @@
import org.jetbrains.kotlin.backend.jvm.MemoizedMultiFieldValueClassReplacements.RemappedParameter.MultiFieldValueClassMapping
import org.jetbrains.kotlin.backend.jvm.ir.*
+import org.jetbrains.kotlin.config.JvmMfvcVArrayFlatteningScheme
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
import org.jetbrains.kotlin.ir.builders.declarations.buildConstructor
@@ -15,9 +16,7 @@
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
-import org.jetbrains.kotlin.ir.types.IrSimpleType
-import org.jetbrains.kotlin.ir.types.IrType
-import org.jetbrains.kotlin.ir.types.defaultType
+import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.InlineClassDescriptorResolver
@@ -307,6 +306,15 @@
getRootNode(context, it)
}
+ val getMfvcVArrayMapper: (RootMfvcNode) -> MfvcVArrayMapper = storageManager.createMemoizedFunction {
+ when (context.state.mfvcVArrayFlatteningScheme) {
+ JvmMfvcVArrayFlatteningScheme.PER_TYPE -> TODO("Scheme is not implemented yet")
+ JvmMfvcVArrayFlatteningScheme.PER_SIZE -> PerSizeMapper(it, flatteningSymbolsHelper)
+ JvmMfvcVArrayFlatteningScheme.THREE_ARRAYS -> TODO("Scheme is not implemented yet")
+ JvmMfvcVArrayFlatteningScheme.TWO_ARRAYS -> TwoArraysMapper(it, flatteningSymbolsHelper)
+ }
+ }
+
fun getRootMfvcNodeOrNull(irClass: IrClass): RootMfvcNode? =
if (irClass.defaultType.needsMfvcFlattening()) getRootMfvcNode(irClass) else null
diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedValueClassAbstractReplacements.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedValueClassAbstractReplacements.kt
index 8304a1d..f4bda22 100644
--- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedValueClassAbstractReplacements.kt
+++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedValueClassAbstractReplacements.kt
@@ -26,6 +26,8 @@
) {
private val propertyMap = ConcurrentHashMap<IrPropertySymbol, IrProperty>()
+ val flatteningSymbolsHelper = FlatteningSymbolsHelper(context)
+
/**
* Get a replacement for a function or a constructor.
*/
diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MfvcNode.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MfvcNode.kt
index c5abecd..7e4f1cc 100644
--- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MfvcNode.kt
+++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MfvcNode.kt
@@ -24,6 +24,7 @@
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.name.Name
+import org.jetbrains.kotlin.name.StandardClassIds
typealias TypeArguments = Map<IrTypeParameterSymbol, IrType>
@@ -458,3 +459,27 @@
classifierOrNull.let { classifier ->
classifier is IrTypeParameterSymbol && classifier.owner.superTypes.any { it.needsMfvcFlattening() }
} // add not is annotated as @UseBox etc
+
+fun IrType.isFlattenedVArray() =
+ isVArray && (this as? IrSimpleType)?.arguments?.let { it.size == 1 && ((it[0] as? IrType)?.needsMfvcFlattening() == true) } == true
+
+fun applyVArrayWrappingTypeTransformation(irType: IrType, symbols: FlatteningSymbolsHelper): IrType = when {
+ // TODO Investigate if we need to transform arguments of non-reified type, i.e. X<VArray<MFVC>> -> X<VArrayWrapper>
+ irType.isFlattenedVArray() -> symbols.vArrayWrapperClass.defaultType
+ irType.isVArray -> {
+ val typeArg = (irType as IrSimpleType).arguments[0]
+ require(typeArg is IrType)
+ symbols.backendContext.irBuiltIns.vArrayClass!!.typeWith(applyVArrayWrappingTypeTransformation(typeArg, symbols))
+ }
+ irType.isBoxedArray -> irType // TODO Transform array type argument, i.e. Array<VArray<Mfvc>> -> Array<VArrayWrapper>
+ isFlattenedVArrayIterator(irType) -> symbols.vArrayWrapperIteratorStateHolderClass.defaultType
+ else -> irType
+}
+
+fun isFlattenedVArrayIterator(irType: IrType): Boolean {
+ if (irType !is IrSimpleType) return false
+ if (irType.classFqName != StandardClassIds.vArrayIterator.asSingleFqName()) return false
+ val typeArg = irType.arguments[0]
+ if (typeArg !is IrType) return false
+ return typeArg.needsMfvcFlattening()
+}
diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/mfvcVArrayMapping.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/mfvcVArrayMapping.kt
new file mode 100644
index 0000000..6d9e623
--- /dev/null
+++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/mfvcVArrayMapping.kt
@@ -0,0 +1,554 @@
+/*
+ * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * 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
+
+import org.jetbrains.kotlin.config.JvmMfvcVArrayFlatteningScheme
+import org.jetbrains.kotlin.ir.builders.*
+import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
+import org.jetbrains.kotlin.ir.declarations.IrVariable
+import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
+import org.jetbrains.kotlin.ir.expressions.IrExpression
+import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
+import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
+import org.jetbrains.kotlin.ir.types.*
+import org.jetbrains.kotlin.ir.util.*
+import org.jetbrains.kotlin.name.Name
+
+/**
+ * Mapping of [LeafMfvcNode] of VArray<Mfvc> element
+ *
+ * Contains information how [LeafMfvcNode] of VArray<Mfvc> maps onto element of flattened array representation
+ *
+ * @property wrapperField Field of wrapper of flattened representation which contains the leaf value
+ * @property indexInWrapperArray Index in array stored in [wrapperField] which contains the leaf value
+ * @property wrapperArrayGetFunction Array *get* function for array stored in [wrapperField]
+ * @property wrapperArraySetFunction Array *set* function for array stored in [wrapperField]
+ * @property encodeFunction Function that returns IR for encoded value, which actually stored in [wrapperField] by original leaf value
+ * @property decodeFunction Function that returns IR for decoded, original leaf value
+ */
+class MfvcVArrayMapping(
+ val wrapperField: IrFieldSymbol,
+ val indexInWrapperArray: IrExpression,
+ val wrapperArrayGetFunction: IrFunctionSymbol,
+ val wrapperArraySetFunction: IrFunctionSymbol,
+ val encodeFunction: (IrExpression, IrBuilderWithScope) -> IrExpression,
+ val decodeFunction: (IrExpression, IrBuilderWithScope) -> IrExpression
+)
+
+abstract class MfvcVArrayMapper(protected val mfvcNode: RootMfvcNode) {
+ internal abstract val wrapperField: Map<LeafType, IrFieldSymbol>
+ internal abstract val groupSizeForType: Map<LeafType, Int>
+ internal abstract val groupSizes: List<Int>
+ internal abstract val arrayConstructors: List<IrFunctionSymbol>
+ internal abstract val arrayGetFunctions: Map<LeafType, IrFunctionSymbol>
+ internal abstract val arraySetFunctions: Map<LeafType, IrFunctionSymbol>
+ internal abstract val encodingFunctions: Map<LeafType, (IrExpression, IrBuilderWithScope) -> IrExpression>
+ internal abstract val decodingFunctions: Map<LeafType, (IrExpression, IrBuilderWithScope) -> IrExpression>
+ abstract val indexOfLeafInGroup: IntArray
+
+ fun map(
+ indexInVArrayVariable: IrVariable,
+ leafIndex: Int,
+ builder: IrBlockBuilder,
+ symbols: FlatteningSymbolsHelper
+ ): MfvcVArrayMapping {
+ val leafType = LeafType.fromIrType(mfvcNode.leaves[leafIndex].type)
+
+ // Suppose Mfvc has group_size leafs that stored in the same array as given leaf.
+ // Suppose that given leaf is leaf_index-th in the set of leafs stored in that array.
+ // Then, leaf has index indexInVArrayVariable * group_size + leaf_index in that array.
+ val indexInWrapperArray = with(builder) {
+ irCallOp(
+ symbols.backendContext.irBuiltIns.intPlusSymbol,
+ symbols.backendContext.irBuiltIns.intType,
+ irCallOp(
+ symbols.backendContext.irBuiltIns.intTimesSymbol,
+ symbols.backendContext.irBuiltIns.intType,
+ irGet(indexInVArrayVariable),
+ irInt(groupSizeForType[leafType]!!)
+ ),
+ irInt(indexOfLeafInGroup[leafIndex])
+ )
+ }
+
+ return MfvcVArrayMapping(
+ wrapperField = wrapperField[leafType]!!,
+ indexInWrapperArray = indexInWrapperArray,
+ wrapperArrayGetFunction = arrayGetFunctions[leafType]!!,
+ wrapperArraySetFunction = arraySetFunctions[leafType]!!,
+ encodeFunction = encodingFunctions[leafType]!!,
+ decodeFunction = decodingFunctions[leafType]!!
+ )
+ }
+
+ fun getVArrayWrapperCreationCall(
+ vArraySize: IrExpression,
+ builder: IrBlockBuilder,
+ symbols: FlatteningSymbolsHelper,
+ saveVariable: (IrVariable) -> Unit
+ ): IrConstructorCall =
+
+ with(builder) {
+
+ val vArraySizeTempVariable = savableStandaloneVariableWithSetter(
+ expression = vArraySize,
+ origin = IrDeclarationOrigin.IR_TEMPORARY_VARIABLE,
+ saveVariable = saveVariable
+ )
+
+ fun getArrayArgument(leafsOfThisTypeCount: Int, arrayCreationFunction: IrFunctionSymbol): IrExpression {
+ if (leafsOfThisTypeCount == 0) return irNull()
+ val arrayType = if (arrayCreationFunction == symbols.backendContext.irBuiltIns.arrayOfNulls)
+ symbols.backendContext.irBuiltIns.arrayClass.typeWith(listOf(symbols.backendContext.irBuiltIns.anyNType))
+ else
+ arrayCreationFunction.owner.returnType
+ return irCall(arrayCreationFunction, arrayType).apply {
+ putValueArgument(
+ 0, irCallOp(
+ context.irBuiltIns.intTimesSymbol,
+ context.irBuiltIns.intType,
+ irGet(vArraySizeTempVariable),
+ irInt(leafsOfThisTypeCount)
+ )
+ )
+ if (arrayCreationFunction == symbols.backendContext.irBuiltIns.arrayOfNulls) {
+ putTypeArgument(0, symbols.backendContext.irBuiltIns.anyNType)
+ }
+ }
+ }
+
+ val wrapperConstructorArguments = buildList {
+ groupSizes.zip(arrayConstructors).map { (groupSize, arrayConstructor) ->
+ add(getArrayArgument(groupSize, arrayConstructor))
+ }
+ add(irGet(vArraySizeTempVariable))
+ }
+
+ return irCall(symbols.vArrayWrapperConstructor).apply {
+ wrapperConstructorArguments.forEachIndexed { index, argument ->
+ putValueArgument(index, argument)
+ }
+ }
+ }
+}
+
+private object Names {
+ const val GET = "get"
+ const val SET = "set"
+ const val ONES = "ones"
+ const val TWOS = "twos"
+ const val FOURS = "fours"
+ const val EIGHTS = "eights"
+ const val REFS = "refs"
+ const val LONGS = "longs"
+}
+
+class FlatteningSymbolsHelper(val backendContext: JvmBackendContext) {
+
+ val bytesGetFunction = backendContext.irBuiltIns.byteArray.functionByName(Names.GET)
+ val shortsGetFunction = backendContext.irBuiltIns.shortArray.functionByName(Names.GET)
+ val intsGetFunction = backendContext.irBuiltIns.intArray.functionByName(Names.GET)
+ val longsGetFunction = backendContext.irBuiltIns.longArray.functionByName(Names.GET)
+ val refsGetFunction = backendContext.irBuiltIns.arrayClass.functionByName(Names.GET)
+
+ val bytesSetFunction = backendContext.irBuiltIns.byteArray.functionByName(Names.SET)
+ val shortsSetFunction = backendContext.irBuiltIns.shortArray.functionByName(Names.SET)
+ val intsSetFunction = backendContext.irBuiltIns.intArray.functionByName(Names.SET)
+ val longsSetFunction = backendContext.irBuiltIns.longArray.functionByName(Names.SET)
+ val refsSetFunction = backendContext.irBuiltIns.arrayClass.functionByName(Names.SET)
+
+ val byteToLong = backendContext.irBuiltIns.byteClass.functionByName("toLong")
+ val shortToLong = backendContext.irBuiltIns.shortClass.functionByName("toLong")
+ val intToLong = backendContext.irBuiltIns.intClass.functionByName("toLong")
+
+ val intToShort = backendContext.irBuiltIns.intClass.functionByName("toShort")
+ val intToChar = backendContext.irBuiltIns.intClass.functionByName("toChar")
+ val shortToInt = backendContext.irBuiltIns.shortClass.functionByName("toInt")
+
+ val longToByte = backendContext.irBuiltIns.longClass.functionByName("toByte")
+ val longToShort = backendContext.irBuiltIns.longClass.functionByName("toShort")
+ val longToInt = backendContext.irBuiltIns.longClass.functionByName("toInt")
+
+ val floatCompanion = backendContext.irBuiltIns.floatClass.owner.companionObject()!!.symbol
+ val doubleCompanion = backendContext.irBuiltIns.doubleClass.owner.companionObject()!!.symbol
+
+ val byteArrayConstructor = backendContext.irBuiltIns.byteArray.constructors.single { it.owner.valueParameters.size == 1 }
+ val shortArrayConstructor = backendContext.irBuiltIns.shortArray.constructors.single { it.owner.valueParameters.size == 1 }
+ val intArrayConstructor = backendContext.irBuiltIns.intArray.constructors.single { it.owner.valueParameters.size == 1 }
+ val longArrayConstructor = backendContext.irBuiltIns.longArray.constructors.single { it.owner.valueParameters.size == 1 }
+
+ val vArrayWrapperClass = when (backendContext.state.mfvcVArrayFlatteningScheme) {
+ JvmMfvcVArrayFlatteningScheme.PER_TYPE -> TODO("Flattening scheme is not implemented yet")
+ JvmMfvcVArrayFlatteningScheme.PER_SIZE -> backendContext.ir.symbols.vArrayWrapperPerSizeClass
+ JvmMfvcVArrayFlatteningScheme.THREE_ARRAYS -> TODO("Flattening scheme is not implemented yet")
+ JvmMfvcVArrayFlatteningScheme.TWO_ARRAYS -> backendContext.ir.symbols.vArrayWrapperTwoArrays
+ }
+
+ val vArrayWrapperIteratorStateHolderClass = when (backendContext.state.mfvcVArrayFlatteningScheme) {
+ JvmMfvcVArrayFlatteningScheme.PER_TYPE -> TODO("Flattening scheme is not implemented yet")
+ JvmMfvcVArrayFlatteningScheme.PER_SIZE -> backendContext.ir.symbols.vArrayPerSizeIteratorStateHolder
+ JvmMfvcVArrayFlatteningScheme.THREE_ARRAYS -> TODO("Flattening scheme is not implemented yet")
+ JvmMfvcVArrayFlatteningScheme.TWO_ARRAYS -> backendContext.ir.symbols.vArrayTwoArraysIteratorStateHolder
+ }
+
+ val vArrayWrapperConstructor = vArrayWrapperClass.constructors.single { it.owner.isPrimary }
+ val vArrayWrapperIteratorStateHolderConstructor = vArrayWrapperIteratorStateHolderClass.constructors.single { it.owner.isPrimary }
+
+ val vArrayGet = backendContext.irBuiltIns.vArrayClass?.functions?.single { it.owner.name == Name.identifier("get") }
+ val vArraySet = backendContext.irBuiltIns.vArrayClass?.functions?.single { it.owner.name == Name.identifier("set") }
+ val vArraySizeGetter = backendContext.irBuiltIns.vArrayClass?.getPropertyGetter("size")
+
+ val wrapperSizeField = vArrayWrapperClass.fieldByName("size")
+ val vArrayWrapperIteratorStateHolderIndexField = vArrayWrapperIteratorStateHolderClass.fieldByName("index")
+ val vArrayWrapperIteratorStateHolderArrayField = vArrayWrapperIteratorStateHolderClass.fieldByName("array")
+
+ val noSuchElementExceptionConstructor = backendContext.ir.symbols.noSuchElementException.constructors.single()
+
+ val throwableMessageGetter = backendContext.irBuiltIns.throwableClass.getPropertyGetter("message")!!
+}
+
+internal enum class LeafType {
+ BOOL, BYTE, SHORT, CHAR, INT, FLOAT, LONG, DOUBLE, REF;
+
+ companion object {
+ fun fromIrType(type: IrType) = when {
+ type.isBoolean() -> BOOL
+ type.isByte() -> BYTE
+ type.isShort() -> SHORT
+ type.isChar() -> CHAR
+ type.isInt() -> INT
+ type.isFloat() -> FLOAT
+ type.isLong() -> LONG
+ type.isDouble() -> DOUBLE
+ else -> REF
+ }
+ }
+}
+
+fun boolToByte(boolExpr: IrExpression, irBuilder: IrBuilderWithScope, symbols: FlatteningSymbolsHelper) = with(irBuilder) {
+ irIfThenElse(
+ type = symbols.backendContext.irBuiltIns.byteType,
+ condition = boolExpr,
+ thenPart = irByte(1),
+ elsePart = irByte(0)
+ )
+}
+
+fun boolToLong(boolExpr: IrExpression, irBuilder: IrBuilderWithScope, symbols: FlatteningSymbolsHelper) = with(irBuilder) {
+ irIfThenElse(
+ type = symbols.backendContext.irBuiltIns.longType,
+ condition = boolExpr,
+ thenPart = irLong(1),
+ elsePart = irLong(0)
+ )
+}
+
+fun byteToLong(byteExpr: IrExpression, irBuilder: IrBuilderWithScope, symbols: FlatteningSymbolsHelper) = with(irBuilder) {
+ irCall(symbols.byteToLong).apply {
+ dispatchReceiver = byteExpr
+ }
+}
+
+fun shortToLong(shortExpr: IrExpression, irBuilder: IrBuilderWithScope, symbols: FlatteningSymbolsHelper) = with(irBuilder) {
+ irCall(symbols.shortToLong).apply {
+ dispatchReceiver = shortExpr
+ }
+}
+
+fun charToLong(charExpr: IrExpression, irBuilder: IrBuilderWithScope, symbols: FlatteningSymbolsHelper) =
+ shortToLong(charToShort(charExpr, irBuilder, symbols), irBuilder, symbols)
+
+fun floatToLong(floatExpr: IrExpression, irBuilder: IrBuilderWithScope, symbols: FlatteningSymbolsHelper) =
+ intToLong(floatToInt(floatExpr, irBuilder, symbols), irBuilder, symbols)
+
+fun intToLong(intExpr: IrExpression, irBuilder: IrBuilderWithScope, symbols: FlatteningSymbolsHelper) = with(irBuilder) {
+ irCall(symbols.intToLong).apply {
+ dispatchReceiver = intExpr
+ }
+}
+
+fun numericToBool(numericExpr: IrExpression, irBuilder: IrBuilderWithScope, symbols: FlatteningSymbolsHelper, zero: IrExpression) =
+ with(irBuilder) {
+ irCallOp(
+ callee = symbols.backendContext.irBuiltIns.booleanNotSymbol,
+ type = symbols.backendContext.irBuiltIns.booleanType,
+ dispatchReceiver = irCall(symbols.backendContext.irBuiltIns.eqeqSymbol).apply {
+ putValueArgument(0, numericExpr)
+ putValueArgument(1, zero)
+ }
+ )
+ }
+
+fun byteToBool(byteExpr: IrExpression, irBuilder: IrBuilderWithScope, symbols: FlatteningSymbolsHelper) =
+ numericToBool(byteExpr, irBuilder, symbols, irBuilder.irByte(0))
+
+fun longToBool(longExpr: IrExpression, irBuilder: IrBuilderWithScope, symbols: FlatteningSymbolsHelper) =
+ numericToBool(longExpr, irBuilder, symbols, irBuilder.irLong(0))
+
+fun longToByte(longExpr: IrExpression, irBuilder: IrBuilderWithScope, symbols: FlatteningSymbolsHelper) = with(irBuilder) {
+ irCall(symbols.longToByte).apply {
+ dispatchReceiver = longExpr
+ }
+}
+
+fun longToShort(longExpr: IrExpression, irBuilder: IrBuilderWithScope, symbols: FlatteningSymbolsHelper) = with(irBuilder) {
+ irCall(symbols.longToShort).apply {
+ dispatchReceiver = longExpr
+ }
+}
+
+fun longToInt(longExpr: IrExpression, irBuilder: IrBuilderWithScope, symbols: FlatteningSymbolsHelper) = with(irBuilder) {
+ irCall(symbols.longToInt).apply {
+ dispatchReceiver = longExpr
+ }
+}
+
+fun longToChar(longExpr: IrExpression, irBuilder: IrBuilderWithScope, symbols: FlatteningSymbolsHelper) = with(irBuilder) {
+ irCall(symbols.intToChar).apply {
+ dispatchReceiver = longToInt(longExpr, irBuilder, symbols)
+ }
+}
+
+fun longToFloat(longExpr: IrExpression, irBuilder: IrBuilderWithScope, symbols: FlatteningSymbolsHelper) =
+ intToFloat(longToInt(longExpr, irBuilder, symbols), irBuilder, symbols)
+
+fun charToShort(charExpr: IrExpression, irBuilder: IrBuilderWithScope, symbols: FlatteningSymbolsHelper) = with(irBuilder) {
+ irCall(symbols.intToShort).apply {
+ dispatchReceiver = irCall(symbols.backendContext.ir.symbols.charCodeGetter).apply {
+ extensionReceiver = charExpr
+ }
+ }
+}
+
+fun shortToChar(shortExpr: IrExpression, irBuilder: IrBuilderWithScope, symbols: FlatteningSymbolsHelper) = with(irBuilder) {
+ irCall(symbols.intToChar).apply {
+ dispatchReceiver = irCall(symbols.shortToInt).apply {
+ dispatchReceiver = shortExpr
+ }
+ }
+}
+
+
+private fun floatToInt(floatExpr: IrExpression, irBuilder: IrBuilderWithScope, symbols: FlatteningSymbolsHelper) = with(irBuilder) {
+ irCall(symbols.backendContext.ir.symbols.floatToRawBits).apply {
+ extensionReceiver = floatExpr
+ }
+}
+
+private fun intToFloat(intExpr: IrExpression, irBuilder: IrBuilderWithScope, symbols: FlatteningSymbolsHelper) = with(irBuilder) {
+ irCall(symbols.backendContext.ir.symbols.floatFromBits).apply {
+ extensionReceiver = irGetObject(symbols.floatCompanion)
+ putValueArgument(0, intExpr)
+ }
+}
+
+private fun longToDouble(longExpr: IrExpression, irBuilder: IrBuilderWithScope, symbols: FlatteningSymbolsHelper) = with(irBuilder) {
+ irCall(symbols.backendContext.ir.symbols.doubleFromBits).apply {
+ extensionReceiver = irGetObject(symbols.doubleCompanion)
+ putValueArgument(0, longExpr)
+ }
+}
+
+private fun doubleToLong(doubleExpr: IrExpression, irBuilder: IrBuilderWithScope, symbols: FlatteningSymbolsHelper) = with(irBuilder) {
+ irCall(symbols.backendContext.ir.symbols.doubleToRawBits).apply {
+ extensionReceiver = doubleExpr
+ }
+}
+
+class PerSizeMapper(mvfcNode: RootMfvcNode, symbols: FlatteningSymbolsHelper) : MfvcVArrayMapper(mvfcNode) {
+
+ private val onesField = symbols.backendContext.ir.symbols.vArrayWrapperPerSizeClass.fieldByName(Names.ONES)
+ private val twosField = symbols.backendContext.ir.symbols.vArrayWrapperPerSizeClass.fieldByName(Names.TWOS)
+ private val fourField = symbols.backendContext.ir.symbols.vArrayWrapperPerSizeClass.fieldByName(Names.FOURS)
+ private val eightsField = symbols.backendContext.ir.symbols.vArrayWrapperPerSizeClass.fieldByName(Names.EIGHTS)
+ private val refsField = symbols.backendContext.ir.symbols.vArrayWrapperPerSizeClass.fieldByName(Names.REFS)
+
+ override val indexOfLeafInGroup: IntArray
+ override val wrapperField: Map<LeafType, IrFieldSymbol>
+ override val groupSizeForType: Map<LeafType, Int>
+ override val groupSizes: List<Int>
+ override val arrayConstructors: List<IrFunctionSymbol>
+ override val arrayGetFunctions: Map<LeafType, IrFunctionSymbol>
+ override val arraySetFunctions: Map<LeafType, IrFunctionSymbol>
+ override val encodingFunctions: Map<LeafType, (IrExpression, IrBuilderWithScope) -> IrExpression>
+ override val decodingFunctions: Map<LeafType, (IrExpression, IrBuilderWithScope) -> IrExpression>
+
+ init {
+ var onesCount = 0;
+ var twosCount = 0;
+ var foursCount = 0;
+ var eightsCount = 0;
+ var refsCount = 0;
+ indexOfLeafInGroup = IntArray(mfvcNode.leavesCount)
+ mfvcNode.leaves.forEachIndexed { leafIndex, leaf ->
+ indexOfLeafInGroup[leafIndex] = when {
+ leaf.type.isBoolean() -> onesCount++
+ leaf.type.isByte() -> onesCount++
+ leaf.type.isChar() -> twosCount++
+ leaf.type.isShort() -> twosCount++
+ leaf.type.isInt() -> foursCount++
+ leaf.type.isFloat() -> foursCount++
+ leaf.type.isLong() -> eightsCount++
+ leaf.type.isDouble() -> eightsCount++
+ else -> refsCount++
+ }
+ }
+
+ groupSizes = listOf(onesCount, twosCount, foursCount, eightsCount, refsCount)
+
+ with(symbols) {
+ arrayConstructors = listOf(
+ byteArrayConstructor,
+ shortArrayConstructor,
+ intArrayConstructor,
+ longArrayConstructor,
+ backendContext.irBuiltIns.arrayOfNulls
+ )
+ }
+
+ wrapperField = mapOf(
+ LeafType.BOOL to onesField,
+ LeafType.BYTE to onesField,
+ LeafType.SHORT to twosField,
+ LeafType.CHAR to twosField,
+ LeafType.INT to fourField,
+ LeafType.FLOAT to fourField,
+ LeafType.LONG to eightsField,
+ LeafType.DOUBLE to eightsField,
+ LeafType.REF to refsField
+ )
+
+ groupSizeForType = mapOf(
+ LeafType.BOOL to onesCount,
+ LeafType.BYTE to onesCount,
+ LeafType.CHAR to twosCount,
+ LeafType.SHORT to twosCount,
+ LeafType.INT to foursCount,
+ LeafType.FLOAT to foursCount,
+ LeafType.LONG to eightsCount,
+ LeafType.DOUBLE to eightsCount,
+ LeafType.REF to refsCount
+ )
+
+ with(symbols) {
+ arraySetFunctions = mapOf(
+ LeafType.BOOL to bytesSetFunction,
+ LeafType.BYTE to bytesSetFunction,
+ LeafType.CHAR to shortsSetFunction,
+ LeafType.SHORT to shortsSetFunction,
+ LeafType.INT to intsSetFunction,
+ LeafType.FLOAT to intsSetFunction,
+ LeafType.LONG to longsSetFunction,
+ LeafType.DOUBLE to longsSetFunction,
+ LeafType.REF to refsSetFunction
+ )
+ }
+
+ with(symbols) {
+ arrayGetFunctions = mapOf(
+ LeafType.BOOL to bytesGetFunction,
+ LeafType.BYTE to bytesGetFunction,
+ LeafType.CHAR to shortsGetFunction,
+ LeafType.SHORT to shortsGetFunction,
+ LeafType.INT to intsGetFunction,
+ LeafType.FLOAT to intsGetFunction,
+ LeafType.LONG to longsGetFunction,
+ LeafType.DOUBLE to longsGetFunction,
+ LeafType.REF to refsGetFunction
+ )
+ }
+
+ encodingFunctions = mapOf(
+ LeafType.BOOL to { boolExpr, irBuilder -> boolToByte(boolExpr, irBuilder, symbols) },
+ LeafType.BYTE to { byteExpr, _ -> byteExpr },
+ LeafType.SHORT to { shortExpr, _ -> shortExpr },
+ LeafType.CHAR to { charExpr, irBuilder -> charToShort(charExpr, irBuilder, symbols) },
+ LeafType.INT to { intExpr, _ -> intExpr },
+ LeafType.FLOAT to { floatExpr, irBuilder -> floatToInt(floatExpr, irBuilder, symbols) },
+ LeafType.LONG to { longExpr, _ -> longExpr },
+ LeafType.DOUBLE to { doubleExpr, irBuilder -> doubleToLong(doubleExpr, irBuilder, symbols) },
+ LeafType.REF to { refExpr, _ -> refExpr }
+ )
+
+ decodingFunctions = mapOf(
+ LeafType.BOOL to { byteExpr, irBuilder -> byteToBool(byteExpr, irBuilder, symbols) },
+ LeafType.BYTE to { byteExpr, _ -> byteExpr },
+ LeafType.SHORT to { shortExpr, _ -> shortExpr },
+ LeafType.CHAR to { shortExpr, irBuilder -> shortToChar(shortExpr, irBuilder, symbols) },
+ LeafType.INT to { intExpr, _ -> intExpr },
+ LeafType.FLOAT to { intExpr, irBuilder -> intToFloat(intExpr, irBuilder, symbols) },
+ LeafType.LONG to { longExpr, _ -> longExpr },
+ LeafType.DOUBLE to { longExpr, irBuilder -> longToDouble(longExpr, irBuilder, symbols) },
+ LeafType.REF to { refExpr, _ -> refExpr }
+ )
+ }
+}
+
+class TwoArraysMapper(mvfcNode: RootMfvcNode, symbols: FlatteningSymbolsHelper) : MfvcVArrayMapper(mvfcNode) {
+
+ private val longsField = symbols.backendContext.ir.symbols.vArrayWrapperTwoArrays.fieldByName(Names.LONGS)
+ private val refsField = symbols.backendContext.ir.symbols.vArrayWrapperTwoArrays.fieldByName(Names.REFS)
+
+ override val indexOfLeafInGroup: IntArray
+ override val wrapperField: Map<LeafType, IrFieldSymbol>
+ override val groupSizeForType: Map<LeafType, Int>
+ override val groupSizes: List<Int>
+ override val arrayConstructors: List<IrFunctionSymbol>
+ override val arrayGetFunctions: Map<LeafType, IrFunctionSymbol>
+ override val arraySetFunctions: Map<LeafType, IrFunctionSymbol>
+ override val encodingFunctions: Map<LeafType, (IrExpression, IrBuilderWithScope) -> IrExpression>
+ override val decodingFunctions: Map<LeafType, (IrExpression, IrBuilderWithScope) -> IrExpression>
+
+ init {
+ var longsCount = 0;
+ var refsCount = 0;
+ indexOfLeafInGroup = IntArray(mfvcNode.leavesCount)
+ mfvcNode.leaves.forEachIndexed { leafIndex, leaf ->
+ indexOfLeafInGroup[leafIndex] = if (leaf.type.isPrimitiveType()) longsCount++ else refsCount++
+ }
+
+ groupSizes = listOf(longsCount, refsCount)
+
+ with(symbols) {
+ arrayConstructors = listOf(longArrayConstructor, backendContext.irBuiltIns.arrayOfNulls)
+ }
+
+ wrapperField = LeafType.values().associateWith { if (it == LeafType.REF) refsField else longsField }
+
+ groupSizeForType = LeafType.values().associateWith { if (it == LeafType.REF) refsCount else longsCount }
+
+ arraySetFunctions =
+ LeafType.values().associateWith { if (it == LeafType.REF) symbols.refsSetFunction else symbols.longsSetFunction }
+
+ arrayGetFunctions =
+ LeafType.values().associateWith { if (it == LeafType.REF) symbols.refsGetFunction else symbols.longsGetFunction }
+
+
+ encodingFunctions = mapOf(
+ LeafType.BOOL to { boolExpr, irBuilder -> boolToLong(boolExpr, irBuilder, symbols) },
+ LeafType.BYTE to { byteExpr, irBuilder -> byteToLong(byteExpr, irBuilder, symbols) },
+ LeafType.SHORT to { shortExpr, irBuilder -> shortToLong(shortExpr, irBuilder, symbols) },
+ LeafType.CHAR to { charExpr, irBuilder -> charToLong(charExpr, irBuilder, symbols) },
+ LeafType.INT to { intExpr, irBuilder -> intToLong(intExpr, irBuilder, symbols) },
+ LeafType.FLOAT to { floatExpr, irBuilder -> floatToLong(floatExpr, irBuilder, symbols) },
+ LeafType.LONG to { longExpr, _ -> longExpr },
+ LeafType.DOUBLE to { doubleExpr, irBuilder -> doubleToLong(doubleExpr, irBuilder, symbols) },
+ LeafType.REF to { refExpr, _ -> refExpr }
+ )
+
+ decodingFunctions = mapOf(
+ LeafType.BOOL to { longExpr, irBuilder -> longToBool(longExpr, irBuilder, symbols) },
+ LeafType.BYTE to { longExpr, irBuilder -> longToByte(longExpr, irBuilder, symbols) },
+ LeafType.SHORT to { longExpr, irBuilder -> longToShort(longExpr, irBuilder, symbols) },
+ LeafType.CHAR to { longExpr, irBuilder -> longToChar(longExpr, irBuilder, symbols) },
+ LeafType.INT to { longExpr, irBuilder -> longToInt(longExpr, irBuilder, symbols) },
+ LeafType.FLOAT to { longExpr, irBuilder -> longToFloat(longExpr, irBuilder, symbols) },
+ LeafType.LONG to { longExpr, _ -> longExpr },
+ LeafType.DOUBLE to { longExpr, irBuilder -> longToDouble(longExpr, irBuilder, symbols) },
+ LeafType.REF to { refExpr, _ -> refExpr }
+ )
+ }
+}
\ No newline at end of file
diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/descriptors/IrBuiltInsOverDescriptors.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/descriptors/IrBuiltInsOverDescriptors.kt
index f04553a..bf2b6af 100644
--- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/descriptors/IrBuiltInsOverDescriptors.kt
+++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/descriptors/IrBuiltInsOverDescriptors.kt
@@ -478,6 +478,8 @@
it.descriptor.valueParameters.size == 1 && KotlinBuiltIns.isInt(it.descriptor.valueParameters[0].type)
}
+ override val vArrayIteratorFunction: IrSimpleFunctionSymbol? = null // not implemented in old frontend
+
override val linkageErrorSymbol: IrSimpleFunctionSymbol = defineOperator("linkageError", nothingType, listOf(stringType))
override val enumClass = builtIns.enum.toIrSymbol()
diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/IrBuiltIns.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/IrBuiltIns.kt
index e75439d..dd4c447 100644
--- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/IrBuiltIns.kt
+++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/IrBuiltIns.kt
@@ -152,6 +152,7 @@
abstract val arrayOfNulls: IrSimpleFunctionSymbol
abstract val vArrayOfNulls: IrSimpleFunctionSymbol?
+ abstract val vArrayIteratorFunction: IrSimpleFunctionSymbol?
abstract val linkageErrorSymbol: IrSimpleFunctionSymbol
diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/builders/ExpressionHelpers.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/builders/ExpressionHelpers.kt
index 39febc3..5e32c79 100644
--- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/builders/ExpressionHelpers.kt
+++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/builders/ExpressionHelpers.kt
@@ -340,6 +340,9 @@
fun IrBuilderWithScope.irSamConversion(argument: IrExpression, type: IrType) =
typeOperator(type, argument, IrTypeOperator.SAM_CONVERSION, type)
+fun IrBuilderWithScope.irByte(value: Byte, type: IrType = context.irBuiltIns.byteType) =
+ IrConstImpl.byte(startOffset, endOffset, type, value)
+
fun IrBuilderWithScope.irInt(value: Int, type: IrType = context.irBuiltIns.intType) =
IrConstImpl.int(startOffset, endOffset, type, value)
diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/irTypePredicates.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/irTypePredicates.kt
index f2bb85f..4d5d039 100644
--- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/irTypePredicates.kt
+++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/irTypePredicates.kt
@@ -39,6 +39,7 @@
@JvmField val string = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "String")
@JvmField val array = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "Array")
@JvmField val vArray = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "VArray")
+ @JvmField val vArrayIterator = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "VArrayIterator")
@JvmField val collection = getPublicSignature(StandardNames.COLLECTIONS_PACKAGE_FQ_NAME, "Collection")
@JvmField val kClass = getPublicSignature(StandardNames.KOTLIN_REFLECT_FQ_NAME, "KClass")
@JvmField val comparable = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "Comparable")
diff --git a/compiler/testData/codegen/box/vArrays/mfvc/customIterator.kt b/compiler/testData/codegen/box/vArrays/mfvc/customIterator.kt
new file mode 100644
index 0000000..d53973c
--- /dev/null
+++ b/compiler/testData/codegen/box/vArrays/mfvc/customIterator.kt
@@ -0,0 +1,35 @@
+import java.lang.StringBuilder
+
+// WITH_STDLIB
+// TARGET_BACKEND: JVM_IR
+// ENABLE_JVM_IR_INLINER
+// TARGET_FRONTEND: FIR
+// LANGUAGE: +ValueClasses
+
+@JvmInline
+value class Point(val x: Int, val y: Int)
+
+class PointIterator(val array: VArray<Point>) : VArrayIterator<Point> {
+ private var index: Int = 0
+
+ override fun hasNext() = index < array.size
+
+ override fun next() = array[index++]
+}
+
+fun box(): String {
+
+ val arr = VArray(2) { Point(it, it + 1) }
+
+ val it = PointIterator(arr)
+
+ val builder = StringBuilder()
+
+ while (it.hasNext()) {
+ builder.append(it.next())
+ }
+
+ if (builder.toString() != "Point(x=0, y=1)Point(x=1, y=2)") return "Fail"
+
+ return "OK"
+}
\ No newline at end of file
diff --git a/compiler/testData/codegen/box/vArrays/mfvc/typesEncodings.kt b/compiler/testData/codegen/box/vArrays/mfvc/typesEncodings.kt
new file mode 100644
index 0000000..00bbd9a
--- /dev/null
+++ b/compiler/testData/codegen/box/vArrays/mfvc/typesEncodings.kt
@@ -0,0 +1,54 @@
+// WITH_STDLIB
+// TARGET_BACKEND: JVM_IR
+// ENABLE_JVM_IR_INLINER
+// TARGET_FRONTEND: FIR
+// LANGUAGE: +ValueClasses
+
+@JvmInline
+value class Point(
+ val bool: Boolean,
+ val byte: Byte,
+ val short: Short,
+ val char: Char,
+ val int: Int,
+ val float: Float,
+ val long: Long,
+ val double: Double,
+ val string: String
+)
+
+@JvmInline
+value class X(val z: String, val x: VArray<Point>)
+
+fun box(): String {
+
+ val vArray = VArray(9) {
+ Point(
+ it > 0,
+ it.toByte(),
+ it.toShort(),
+ '0' + it,
+ it,
+ it.toFloat(),
+ it.toLong(),
+ it.toDouble(),
+ it.toString()
+ )
+ }
+
+ val bool = vArray[0].bool
+ val byte = vArray[1].byte
+ val short = vArray[2].short
+ val char = vArray[3].char
+ val int = vArray[4].int
+ val float = vArray[5].float
+ val long = vArray[6].long
+ val double = vArray[7].double
+ val string = vArray[8].string
+
+ val str = "$bool $byte $short $char $int $float $long $double $string"
+
+ if (str != "false 1 2 3 4 5.0 6 7.0 8") return "Fail"
+
+ return "OK"
+}
\ No newline at end of file
diff --git a/compiler/testData/codegen/box/vArrays/mfvc/vArray2D.kt b/compiler/testData/codegen/box/vArrays/mfvc/vArray2D.kt
new file mode 100644
index 0000000..09a863d
--- /dev/null
+++ b/compiler/testData/codegen/box/vArrays/mfvc/vArray2D.kt
@@ -0,0 +1,17 @@
+// WITH_STDLIB
+// TARGET_BACKEND: JVM_IR
+// ENABLE_JVM_IR_INLINER
+// TARGET_FRONTEND: FIR
+// LANGUAGE: +ValueClasses
+
+@JvmInline
+value class Point(val x: Int, val y: Int)
+
+fun box(): String {
+
+ val vArray2D = VArray(2) { i -> VArray(2) { j -> Point(i + j, i + j + 1) } }
+
+ if (vArray2D[1][1].y != 3) return "Fail"
+
+ return "OK"
+}
\ No newline at end of file
diff --git a/compiler/testData/codegen/box/vArrays/mfvc/vArrayAsFunctionParameter.kt b/compiler/testData/codegen/box/vArrays/mfvc/vArrayAsFunctionParameter.kt
new file mode 100644
index 0000000..795c2c9
--- /dev/null
+++ b/compiler/testData/codegen/box/vArrays/mfvc/vArrayAsFunctionParameter.kt
@@ -0,0 +1,17 @@
+// WITH_STDLIB
+// TARGET_BACKEND: JVM_IR
+// ENABLE_JVM_IR_INLINER
+// TARGET_FRONTEND: FIR
+// LANGUAGE: +ValueClasses
+
+@JvmInline
+value class Point(val x: Int, val y: Int)
+
+fun foo(arr: VArray<Point>) = arr[1].y
+
+fun box(): String {
+
+ if (foo(VArray(2) { Point(it, it + 1) }) != 2) return "Fail"
+
+ return "OK"
+}
\ No newline at end of file
diff --git a/compiler/testData/codegen/box/vArrays/mfvc/vArrayAsLambdaParameter.kt b/compiler/testData/codegen/box/vArrays/mfvc/vArrayAsLambdaParameter.kt
new file mode 100644
index 0000000..268a984
--- /dev/null
+++ b/compiler/testData/codegen/box/vArrays/mfvc/vArrayAsLambdaParameter.kt
@@ -0,0 +1,17 @@
+// WITH_STDLIB
+// TARGET_BACKEND: JVM_IR
+// ENABLE_JVM_IR_INLINER
+// TARGET_FRONTEND: FIR
+// LANGUAGE: +ValueClasses
+
+@JvmInline
+value class Point(val x: Int, val y: Int)
+
+fun foo(arr: VArray<Point>, func: (VArray<Point>) -> Int) = func(arr)
+
+fun box(): String {
+
+ if (foo(VArray(2) { Point(it, it + 1) }) { it[1].y } != 2) return "Fail"
+
+ return "OK"
+}
\ No newline at end of file
diff --git a/compiler/testData/codegen/box/vArrays/mfvc/vArrayAsLambdaReturnType.kt b/compiler/testData/codegen/box/vArrays/mfvc/vArrayAsLambdaReturnType.kt
new file mode 100644
index 0000000..e9c7745
--- /dev/null
+++ b/compiler/testData/codegen/box/vArrays/mfvc/vArrayAsLambdaReturnType.kt
@@ -0,0 +1,17 @@
+// WITH_STDLIB
+// TARGET_BACKEND: JVM_IR
+// ENABLE_JVM_IR_INLINER
+// TARGET_FRONTEND: FIR
+// LANGUAGE: +ValueClasses
+
+@JvmInline
+value class Point(val x: Int, val y: Int)
+
+fun foo(x: Int, func: (Int) -> VArray<Point>) = func(x)[1].y
+
+fun box(): String {
+
+ if (foo(1, { x -> VArray(2) { i -> Point(i + x, i + x + 1) } }) != 3) return "Fail"
+
+ return "OK"
+}
\ No newline at end of file
diff --git a/compiler/testData/codegen/box/vArrays/mfvc/vArrayAsMfvcProperty.kt b/compiler/testData/codegen/box/vArrays/mfvc/vArrayAsMfvcProperty.kt
new file mode 100644
index 0000000..9c3981e
--- /dev/null
+++ b/compiler/testData/codegen/box/vArrays/mfvc/vArrayAsMfvcProperty.kt
@@ -0,0 +1,20 @@
+// WITH_STDLIB
+// TARGET_BACKEND: JVM_IR
+// ENABLE_JVM_IR_INLINER
+// TARGET_FRONTEND: FIR
+// LANGUAGE: +ValueClasses
+
+@JvmInline
+value class Point(val x: Int, val y: Int)
+
+@JvmInline
+value class Poly(val s: Point, val points: VArray<Point>)
+
+fun box(): String {
+
+ val poly = Poly(s = Point(1, 2), points = VArray(3) { Point(it, it + 1) })
+
+ if (poly.points[2].y != 3) return "Fail"
+
+ return "OK"
+}
\ No newline at end of file
diff --git a/compiler/testData/codegen/box/vArrays/mfvc/vArrayAsProperty.kt b/compiler/testData/codegen/box/vArrays/mfvc/vArrayAsProperty.kt
new file mode 100644
index 0000000..82e9bd1
--- /dev/null
+++ b/compiler/testData/codegen/box/vArrays/mfvc/vArrayAsProperty.kt
@@ -0,0 +1,18 @@
+// WITH_STDLIB
+// TARGET_BACKEND: JVM_IR
+// ENABLE_JVM_IR_INLINER
+// TARGET_FRONTEND: FIR
+// LANGUAGE: +ValueClasses
+
+@JvmInline
+value class Point(val x: Int, val y: Int)
+class A(val arr: VArray<Point>)
+
+fun box(): String {
+
+ val a = A(VArray(2) { Point(it, it + 1) })
+
+ if (a.arr[1].y != 2) return "Fail"
+
+ return "OK"
+}
\ No newline at end of file
diff --git a/compiler/testData/codegen/box/vArrays/mfvc/vArrayAsPropertyNoBackingField.kt b/compiler/testData/codegen/box/vArrays/mfvc/vArrayAsPropertyNoBackingField.kt
new file mode 100644
index 0000000..8618f67
--- /dev/null
+++ b/compiler/testData/codegen/box/vArrays/mfvc/vArrayAsPropertyNoBackingField.kt
@@ -0,0 +1,21 @@
+// WITH_STDLIB
+// TARGET_BACKEND: JVM_IR
+// ENABLE_JVM_IR_INLINER
+// TARGET_FRONTEND: FIR
+// LANGUAGE: +ValueClasses
+
+@JvmInline
+value class Point(val x: Int, val y: Int)
+
+class A() {
+ val arr: VArray<Point> get() = VArray(2) { Point(it, it + 1) }
+}
+
+fun box(): String {
+
+ val a = A()
+
+ if (a.arr[1].y != 2) return "Fail"
+
+ return "OK"
+}
\ No newline at end of file
diff --git a/compiler/testData/codegen/box/vArrays/mfvc/vArrayAsReturnType.kt b/compiler/testData/codegen/box/vArrays/mfvc/vArrayAsReturnType.kt
new file mode 100644
index 0000000..ddf09d4
--- /dev/null
+++ b/compiler/testData/codegen/box/vArrays/mfvc/vArrayAsReturnType.kt
@@ -0,0 +1,18 @@
+// WITH_STDLIB
+// TARGET_BACKEND: JVM_IR
+// ENABLE_JVM_IR_INLINER
+// TARGET_FRONTEND: FIR
+// LANGUAGE: +ValueClasses
+
+@JvmInline
+value class Point(val x: Int, val y: Int)
+
+fun foo() = VArray(2) { Point(it, it + 1) }
+
+
+fun box(): String {
+
+ if (foo()[1].y != 2) return "Fail"
+
+ return "OK"
+}
\ No newline at end of file
diff --git a/compiler/testData/codegen/box/vArrays/mfvc/vArrayAsSfvcProperty.kt b/compiler/testData/codegen/box/vArrays/mfvc/vArrayAsSfvcProperty.kt
new file mode 100644
index 0000000..9db316d
--- /dev/null
+++ b/compiler/testData/codegen/box/vArrays/mfvc/vArrayAsSfvcProperty.kt
@@ -0,0 +1,25 @@
+// WITH_STDLIB
+// TARGET_BACKEND: JVM_IR
+// ENABLE_JVM_IR_INLINER
+// TARGET_FRONTEND: FIR
+// LANGUAGE: +ValueClasses
+@JvmInline
+value class Point(val x: Int, val y: Int)
+
+@JvmInline
+value class Poly(val points: VArray<Point>)
+
+@JvmInline
+value class PolyWrapper(val poly: Poly)
+
+fun box(): String {
+
+ val poly = Poly(VArray(3) { Point(it, it + 1) })
+
+ if (poly.points[2].y != 3) return "Fail 1"
+
+ val polyWrapper = PolyWrapper(poly)
+ if (polyWrapper.poly.points[2].y != 3) return "Fail 2"
+
+ return "OK"
+}
\ No newline at end of file
diff --git a/compiler/testData/codegen/box/vArrays/mfvc/vArrayChainAssignment.kt b/compiler/testData/codegen/box/vArrays/mfvc/vArrayChainAssignment.kt
new file mode 100644
index 0000000..69409f7
--- /dev/null
+++ b/compiler/testData/codegen/box/vArrays/mfvc/vArrayChainAssignment.kt
@@ -0,0 +1,20 @@
+// WITH_STDLIB
+// TARGET_BACKEND: JVM_IR
+// ENABLE_JVM_IR_INLINER
+// TARGET_FRONTEND: FIR
+// LANGUAGE: +ValueClasses
+
+@JvmInline
+value class Point(val x: Int, val y: Int)
+
+
+fun box(): String {
+
+ val a = VArray(2) { Point(it, it + 1) }
+ val b = a
+ val c = b
+
+ if (c[1].y != 2) return "Fail"
+
+ return "OK"
+}
\ No newline at end of file
diff --git a/compiler/testData/codegen/box/vArrays/mfvc/vArrayExpression.kt b/compiler/testData/codegen/box/vArrays/mfvc/vArrayExpression.kt
new file mode 100644
index 0000000..f42a663
--- /dev/null
+++ b/compiler/testData/codegen/box/vArrays/mfvc/vArrayExpression.kt
@@ -0,0 +1,19 @@
+// WITH_STDLIB
+// TARGET_BACKEND: JVM_IR
+// ENABLE_JVM_IR_INLINER
+// TARGET_FRONTEND: FIR
+// LANGUAGE: +ValueClasses
+
+@JvmInline
+value class Point(val x: Int, val y: Int)
+
+fun box(): String {
+
+ VArray(2) { Point(it, it + 1) }[0] = Point(10, 20)
+
+ val a = VArray(2) { Point(it, it + 1) }[1].y
+
+ if (a != 2) return "Fail"
+
+ return "OK"
+}
\ No newline at end of file
diff --git a/compiler/testData/codegen/box/vArrays/mfvc/vArrayInIfElseBlock.kt b/compiler/testData/codegen/box/vArrays/mfvc/vArrayInIfElseBlock.kt
new file mode 100644
index 0000000..f8f7d7f
--- /dev/null
+++ b/compiler/testData/codegen/box/vArrays/mfvc/vArrayInIfElseBlock.kt
@@ -0,0 +1,27 @@
+// WITH_STDLIB
+// TARGET_BACKEND: JVM_IR
+// ENABLE_JVM_IR_INLINER
+// TARGET_FRONTEND: FIR
+// LANGUAGE: +ValueClasses
+
+@JvmInline
+value class Point(val x: Int, val y: Int)
+
+fun foo(b: Boolean, x: Int): Int {
+ val vArray = if (b) {
+ val y = x + 1;
+ VArray(2) { Point(it + y, it + y + 1) }
+ } else {
+ val z = x * 2;
+ VArray(2) { Point(it + z, it + z + 1) }
+ }
+ return vArray[1].y
+}
+
+fun box(): String {
+
+ if (foo(false, 2) != 6) return "Fail 1"
+ if (foo(true, 1) != 4) return "Fail 2"
+
+ return "OK"
+}
\ No newline at end of file
diff --git a/compiler/testData/codegen/box/vArrays/mfvc/vArrayInTryBlock.kt b/compiler/testData/codegen/box/vArrays/mfvc/vArrayInTryBlock.kt
new file mode 100644
index 0000000..4be8a76
--- /dev/null
+++ b/compiler/testData/codegen/box/vArrays/mfvc/vArrayInTryBlock.kt
@@ -0,0 +1,23 @@
+// WITH_STDLIB
+// TARGET_BACKEND: JVM_IR
+// ENABLE_JVM_IR_INLINER
+// TARGET_FRONTEND: FIR
+// LANGUAGE: +ValueClasses
+
+@JvmInline
+value class Point(val x: Int, val y: Int)
+
+fun foo(x: Int) = try {
+ 1 / x
+ VArray(2) { Point(it + x, it + x + 1) }
+} catch (t: Throwable) {
+ VArray(2) { Point(it + x + 2, it + x + 3) }
+}
+
+fun box(): String {
+
+ if (foo(0)[1].y != 4) return "Fail 1"
+ if (foo(1)[1].y != 3) return "Fail 2"
+
+ return "OK"
+}
\ No newline at end of file
diff --git a/compiler/testData/codegen/box/vArrays/mfvc/vArrayInWhenExpr.kt b/compiler/testData/codegen/box/vArrays/mfvc/vArrayInWhenExpr.kt
new file mode 100644
index 0000000..5fb60eb
--- /dev/null
+++ b/compiler/testData/codegen/box/vArrays/mfvc/vArrayInWhenExpr.kt
@@ -0,0 +1,35 @@
+// WITH_STDLIB
+// TARGET_BACKEND: JVM_IR
+// ENABLE_JVM_IR_INLINER
+// TARGET_FRONTEND: FIR
+// LANGUAGE: +ValueClasses
+
+@JvmInline
+value class Point(val x: Int, val y: Int)
+
+fun foo(c: Int, x: Int): Int {
+ val vArray = when (c) {
+ 0 -> {
+ val a = x + 1
+ VArray(2) { Point(it + a, it + a + 1) }
+ }
+ 1 -> {
+ val b = x + 2
+ VArray(2) { Point(it + b, it + b + 1) }
+ }
+ else -> {
+ val c = x + 3
+ VArray(2) { Point(it + c, it + c + 1) }
+ }
+ }
+ return vArray[1].y
+}
+
+fun box(): String {
+
+ if (foo(0, 1) != 4) return "Fail 1"
+ if (foo(1, 2) != 6) return "Fail 2"
+ if (foo(2, 3) != 8) return "Fail 3"
+
+ return "OK"
+}
\ No newline at end of file
diff --git a/compiler/testData/codegen/box/vArrays/mfvc/vArrayIterator.kt b/compiler/testData/codegen/box/vArrays/mfvc/vArrayIterator.kt
new file mode 100644
index 0000000..83d59af
--- /dev/null
+++ b/compiler/testData/codegen/box/vArrays/mfvc/vArrayIterator.kt
@@ -0,0 +1,36 @@
+// WITH_STDLIB
+// TARGET_BACKEND: JVM_IR
+// ENABLE_JVM_IR_INLINER
+// TARGET_FRONTEND: FIR
+// LANGUAGE: +ValueClasses
+
+@JvmInline
+value class Point(val x: Int, val y: Int)
+
+inline fun <reified T> throws(block: () -> Unit): Boolean {
+ try {
+ block.invoke()
+ } catch (t: Throwable) {
+ return t is T
+ }
+ return false
+}
+
+fun box(): String {
+
+ val arr = VArray(2) { Point(it, it + 1) }
+ val it = arr.iterator()
+
+ if (!it.hasNext()) return "Fail 1"
+ if (it.next().toString() != "Point(x=0, y=1)") return "Fail 2"
+ if (!it.hasNext()) return "Fail 3"
+ if (it.next().toString() != "Point(x=1, y=2)") return "Fail 4"
+ if (it.hasNext()) return "Fail 5"
+ if (!throws<NoSuchElementException> { it.next() }) return "Fail 6"
+ if (it.hasNext()) return "Fail 6"
+ if (!throws<NoSuchElementException> { it.next() }) return "Fail 7"
+
+ // TODO: fix and check exception messages
+
+ return "OK"
+}
\ No newline at end of file
diff --git a/compiler/testData/codegen/box/vArrays/mfvc/vArraySize.kt b/compiler/testData/codegen/box/vArrays/mfvc/vArraySize.kt
new file mode 100644
index 0000000..2823ad0
--- /dev/null
+++ b/compiler/testData/codegen/box/vArrays/mfvc/vArraySize.kt
@@ -0,0 +1,20 @@
+// WITH_STDLIB
+// TARGET_BACKEND: JVM_IR
+// ENABLE_JVM_IR_INLINER
+// TARGET_FRONTEND: FIR
+// LANGUAGE: +ValueClasses
+
+@JvmInline
+value class Point(val x: Int, val y: Int)
+
+fun box(): String {
+
+ if (VArray(2) { Point(-1, 1) }.size != 2) return "Fail 1"
+
+ val vArray2D = VArray(2) { VArray(3) { Point(-1, 1) } }
+
+ if (vArray2D.size != 2) return "Fail 2"
+ if (vArray2D[1].size != 3) return "Fail 3"
+
+ return "OK"
+}
\ No newline at end of file
diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java
index 836e627..022cc27 100644
--- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java
+++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java
@@ -49534,6 +49534,16 @@
public void testAllFilesPresentInVArrays() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/vArrays"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
+
+ @Nested
+ @TestMetadata("compiler/testData/codegen/box/vArrays/mfvc")
+ @TestDataPath("$PROJECT_ROOT")
+ public class Mfvc {
+ @Test
+ public void testAllFilesPresentInMfvc() throws Exception {
+ KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/vArrays/mfvc"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
+ }
+ }
}
@Nested
diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java
index 2ecea47..fc779c4 100644
--- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java
+++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java
@@ -52198,6 +52198,124 @@
public void testVarargParameterOfInlineType() throws Exception {
runTest("compiler/testData/codegen/box/vArrays/varargParameterOfInlineType.kt");
}
+
+ @Nested
+ @TestMetadata("compiler/testData/codegen/box/vArrays/mfvc")
+ @TestDataPath("$PROJECT_ROOT")
+ public class Mfvc {
+ @Test
+ public void testAllFilesPresentInMfvc() throws Exception {
+ KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/vArrays/mfvc"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
+ }
+
+ @Test
+ @TestMetadata("customIterator.kt")
+ public void testCustomIterator() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/customIterator.kt");
+ }
+
+ @Test
+ @TestMetadata("typesEncodings.kt")
+ public void testTypesEncodings() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/typesEncodings.kt");
+ }
+
+ @Test
+ @TestMetadata("vArray2D.kt")
+ public void testVArray2D() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArray2D.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayAsFunctionParameter.kt")
+ public void testVArrayAsFunctionParameter() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayAsFunctionParameter.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayAsLambdaParameter.kt")
+ public void testVArrayAsLambdaParameter() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayAsLambdaParameter.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayAsLambdaReturnType.kt")
+ public void testVArrayAsLambdaReturnType() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayAsLambdaReturnType.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayAsMfvcProperty.kt")
+ public void testVArrayAsMfvcProperty() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayAsMfvcProperty.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayAsProperty.kt")
+ public void testVArrayAsProperty() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayAsProperty.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayAsPropertyNoBackingField.kt")
+ public void testVArrayAsPropertyNoBackingField() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayAsPropertyNoBackingField.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayAsReturnType.kt")
+ public void testVArrayAsReturnType() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayAsReturnType.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayAsSfvcProperty.kt")
+ public void testVArrayAsSfvcProperty() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayAsSfvcProperty.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayChainAssignment.kt")
+ public void testVArrayChainAssignment() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayChainAssignment.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayExpression.kt")
+ public void testVArrayExpression() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayExpression.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayInIfElseBlock.kt")
+ public void testVArrayInIfElseBlock() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayInIfElseBlock.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayInTryBlock.kt")
+ public void testVArrayInTryBlock() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayInTryBlock.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayInWhenExpr.kt")
+ public void testVArrayInWhenExpr() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayInWhenExpr.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayIterator.kt")
+ public void testVArrayIterator() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayIterator.kt");
+ }
+
+ @Test
+ @TestMetadata("vArraySize.kt")
+ public void testVArraySize() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArraySize.kt");
+ }
+ }
}
@Nested
diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenWithIrInlinerTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenWithIrInlinerTestGenerated.java
index 1b85007..88d0800 100644
--- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenWithIrInlinerTestGenerated.java
+++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenWithIrInlinerTestGenerated.java
@@ -52198,6 +52198,124 @@
public void testVarargParameterOfInlineType() throws Exception {
runTest("compiler/testData/codegen/box/vArrays/varargParameterOfInlineType.kt");
}
+
+ @Nested
+ @TestMetadata("compiler/testData/codegen/box/vArrays/mfvc")
+ @TestDataPath("$PROJECT_ROOT")
+ public class Mfvc {
+ @Test
+ public void testAllFilesPresentInMfvc() throws Exception {
+ KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/vArrays/mfvc"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
+ }
+
+ @Test
+ @TestMetadata("customIterator.kt")
+ public void testCustomIterator() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/customIterator.kt");
+ }
+
+ @Test
+ @TestMetadata("typesEncodings.kt")
+ public void testTypesEncodings() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/typesEncodings.kt");
+ }
+
+ @Test
+ @TestMetadata("vArray2D.kt")
+ public void testVArray2D() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArray2D.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayAsFunctionParameter.kt")
+ public void testVArrayAsFunctionParameter() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayAsFunctionParameter.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayAsLambdaParameter.kt")
+ public void testVArrayAsLambdaParameter() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayAsLambdaParameter.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayAsLambdaReturnType.kt")
+ public void testVArrayAsLambdaReturnType() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayAsLambdaReturnType.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayAsMfvcProperty.kt")
+ public void testVArrayAsMfvcProperty() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayAsMfvcProperty.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayAsProperty.kt")
+ public void testVArrayAsProperty() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayAsProperty.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayAsPropertyNoBackingField.kt")
+ public void testVArrayAsPropertyNoBackingField() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayAsPropertyNoBackingField.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayAsReturnType.kt")
+ public void testVArrayAsReturnType() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayAsReturnType.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayAsSfvcProperty.kt")
+ public void testVArrayAsSfvcProperty() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayAsSfvcProperty.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayChainAssignment.kt")
+ public void testVArrayChainAssignment() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayChainAssignment.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayExpression.kt")
+ public void testVArrayExpression() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayExpression.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayInIfElseBlock.kt")
+ public void testVArrayInIfElseBlock() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayInIfElseBlock.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayInTryBlock.kt")
+ public void testVArrayInTryBlock() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayInTryBlock.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayInWhenExpr.kt")
+ public void testVArrayInWhenExpr() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayInWhenExpr.kt");
+ }
+
+ @Test
+ @TestMetadata("vArrayIterator.kt")
+ public void testVArrayIterator() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArrayIterator.kt");
+ }
+
+ @Test
+ @TestMetadata("vArraySize.kt")
+ public void testVArraySize() throws Exception {
+ runTest("compiler/testData/codegen/box/vArrays/mfvc/vArraySize.kt");
+ }
+ }
}
@Nested
diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java
index 830e3fa..197d866 100644
--- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java
+++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java
@@ -40321,6 +40321,19 @@
public void testAllFilesPresentInVArrays() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/vArrays"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
+
+ @TestMetadata("compiler/testData/codegen/box/vArrays/mfvc")
+ @TestDataPath("$PROJECT_ROOT")
+ @RunWith(JUnit3RunnerWithInners.class)
+ public static class Mfvc extends AbstractLightAnalysisModeTest {
+ private void runTest(String testDataFilePath) throws Exception {
+ KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
+ }
+
+ public void testAllFilesPresentInMfvc() throws Exception {
+ KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/vArrays/mfvc"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
+ }
+ }
}
@TestMetadata("compiler/testData/codegen/box/valueClasses")
diff --git a/core/builtins/native/kotlin/VArray.kt b/core/builtins/native/kotlin/VArray.kt
index ef67a65..30d6af6 100644
--- a/core/builtins/native/kotlin/VArray.kt
+++ b/core/builtins/native/kotlin/VArray.kt
@@ -5,6 +5,7 @@
package kotlin
+// TODO: add 'reified' to T
class VArray<T> {
public operator fun get(index: Int): T
public operator fun set(index: Int, value: T): Unit
diff --git a/core/builtins/src/kotlin/VArrayIterator.kt b/core/builtins/src/kotlin/VArrayIterator.kt
index d695344..6d2486e 100644
--- a/core/builtins/src/kotlin/VArrayIterator.kt
+++ b/core/builtins/src/kotlin/VArrayIterator.kt
@@ -7,4 +7,5 @@
interface VArrayIterator<T> : Iterator<T> {
override fun next(): T
+ override fun hasNext(): Boolean
}
\ No newline at end of file
diff --git a/core/compiler.common/src/org/jetbrains/kotlin/name/StandardClassIds.kt b/core/compiler.common/src/org/jetbrains/kotlin/name/StandardClassIds.kt
index 6ea3445..cbec8eb 100644
--- a/core/compiler.common/src/org/jetbrains/kotlin/name/StandardClassIds.kt
+++ b/core/compiler.common/src/org/jetbrains/kotlin/name/StandardClassIds.kt
@@ -37,6 +37,7 @@
val Annotation = "Annotation".baseId()
val Array = "Array".baseId()
val VArray = "VArray".baseId()
+ val vArrayIterator = "VArrayIterator".baseId()
val Boolean = "Boolean".baseId()
val Char = "Char".baseId()
diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/JsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/JsCodegenBoxTestGenerated.java
index a2b6193d..96a5753 100644
--- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/JsCodegenBoxTestGenerated.java
+++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/JsCodegenBoxTestGenerated.java
@@ -36906,6 +36906,16 @@
public void testAllFilesPresentInVArrays() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/vArrays"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true);
}
+
+ @Nested
+ @TestMetadata("compiler/testData/codegen/box/vArrays/mfvc")
+ @TestDataPath("$PROJECT_ROOT")
+ public class Mfvc {
+ @Test
+ public void testAllFilesPresentInMfvc() throws Exception {
+ KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/vArrays/mfvc"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true);
+ }
+ }
}
@Nested
diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirJsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirJsCodegenBoxTestGenerated.java
index 1746282..9d02b8e 100644
--- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirJsCodegenBoxTestGenerated.java
+++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirJsCodegenBoxTestGenerated.java
@@ -37248,6 +37248,16 @@
public void testAllFilesPresentInVArrays() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/vArrays"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
}
+
+ @Nested
+ @TestMetadata("compiler/testData/codegen/box/vArrays/mfvc")
+ @TestDataPath("$PROJECT_ROOT")
+ public class Mfvc {
+ @Test
+ public void testAllFilesPresentInMfvc() throws Exception {
+ KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/vArrays/mfvc"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
+ }
+ }
}
@Nested
diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsCodegenBoxTestGenerated.java
index 8d4db39..03cf91f70 100644
--- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsCodegenBoxTestGenerated.java
+++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsCodegenBoxTestGenerated.java
@@ -37248,6 +37248,16 @@
public void testAllFilesPresentInVArrays() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/vArrays"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
}
+
+ @Nested
+ @TestMetadata("compiler/testData/codegen/box/vArrays/mfvc")
+ @TestDataPath("$PROJECT_ROOT")
+ public class Mfvc {
+ @Test
+ public void testAllFilesPresentInMfvc() throws Exception {
+ KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/vArrays/mfvc"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
+ }
+ }
}
@Nested
diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsES6CodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsES6CodegenBoxTestGenerated.java
index 78975f5..02c0bba 100644
--- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsES6CodegenBoxTestGenerated.java
+++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsES6CodegenBoxTestGenerated.java
@@ -37248,6 +37248,16 @@
public void testAllFilesPresentInVArrays() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/vArrays"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR_ES6, true);
}
+
+ @Nested
+ @TestMetadata("compiler/testData/codegen/box/vArrays/mfvc")
+ @TestDataPath("$PROJECT_ROOT")
+ public class Mfvc {
+ @Test
+ public void testAllFilesPresentInMfvc() throws Exception {
+ KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/vArrays/mfvc"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR_ES6, true);
+ }
+ }
}
@Nested
diff --git a/libraries/stdlib/jvm/runtime/kotlin/jvm/internal/ArrayIterator.kt b/libraries/stdlib/jvm/runtime/kotlin/jvm/internal/ArrayIterator.kt
index 1cf47a7..4972e41 100644
--- a/libraries/stdlib/jvm/runtime/kotlin/jvm/internal/ArrayIterator.kt
+++ b/libraries/stdlib/jvm/runtime/kotlin/jvm/internal/ArrayIterator.kt
@@ -11,6 +11,7 @@
override fun next() = try { array[index++] } catch (e: ArrayIndexOutOfBoundsException) { index -= 1; throw NoSuchElementException(e.message) }
}
+// TODO: add 'reified' to T
public class VArrayIteratorImpl<T>(val array: VArray<T>) : VArrayIterator<T> {
private var index = 0
override fun hasNext() = index < array.size
diff --git a/libraries/stdlib/jvm/runtime/kotlin/jvm/internal/VArrayIteratorStateHolders.kt b/libraries/stdlib/jvm/runtime/kotlin/jvm/internal/VArrayIteratorStateHolders.kt
new file mode 100644
index 0000000..93034e0
--- /dev/null
+++ b/libraries/stdlib/jvm/runtime/kotlin/jvm/internal/VArrayIteratorStateHolders.kt
@@ -0,0 +1,10 @@
+/*
+ * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package kotlin.jvm.internal
+
+class VArrayPerSizeIteratorStateHolder(@JvmField val array: VArrayWrapperPerSize, @JvmField var index: Int)
+
+class VArrayTwoArraysIteratorStateHolder(@JvmField val array: VArrayWrapperTwoArrays, @JvmField var index: Int)
\ No newline at end of file
diff --git a/libraries/stdlib/jvm/runtime/kotlin/jvm/internal/VArrayWrappers.kt b/libraries/stdlib/jvm/runtime/kotlin/jvm/internal/VArrayWrappers.kt
new file mode 100644
index 0000000..a08c07a
--- /dev/null
+++ b/libraries/stdlib/jvm/runtime/kotlin/jvm/internal/VArrayWrappers.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package kotlin.jvm.internal
+
+import kotlin.jvm.JvmField
+
+class VArrayWrapperPerSize(
+ @JvmField val ones: ByteArray?,
+ @JvmField val twos: ShortArray?,
+ @JvmField val fours: IntArray?,
+ @JvmField val eights: LongArray?,
+ @JvmField val refs: Array<Any?>?,
+ @JvmField val size: Int
+)
+
+class VArrayWrapperTwoArrays(
+ @JvmField val longs: LongArray?,
+ @JvmField val refs: Array<Any?>?,
+ @JvmField val size: Int
+)
\ No newline at end of file
diff --git a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/FirNativeCodegenBoxTestGenerated.java b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/FirNativeCodegenBoxTestGenerated.java
index fb79699..386a8db 100644
--- a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/FirNativeCodegenBoxTestGenerated.java
+++ b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/FirNativeCodegenBoxTestGenerated.java
@@ -41446,6 +41446,20 @@
public void testAllFilesPresentInVArrays() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/vArrays"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.NATIVE, true);
}
+
+ @Nested
+ @TestMetadata("compiler/testData/codegen/box/vArrays/mfvc")
+ @TestDataPath("$PROJECT_ROOT")
+ @Tag("codegenK2")
+ @Tag("firCodegen")
+ @UseExtTestCaseGroupProvider()
+ @FirPipeline()
+ public class Mfvc {
+ @Test
+ public void testAllFilesPresentInMfvc() throws Exception {
+ KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/vArrays/mfvc"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.NATIVE, true);
+ }
+ }
}
@Nested
diff --git a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/FirNativeCodegenBoxTestNoPLGenerated.java b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/FirNativeCodegenBoxTestNoPLGenerated.java
index b48d779..6b8551f 100644
--- a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/FirNativeCodegenBoxTestNoPLGenerated.java
+++ b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/FirNativeCodegenBoxTestNoPLGenerated.java
@@ -42472,6 +42472,22 @@
public void testAllFilesPresentInVArrays() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/vArrays"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.NATIVE, true);
}
+
+ @Nested
+ @TestMetadata("compiler/testData/codegen/box/vArrays/mfvc")
+ @TestDataPath("$PROJECT_ROOT")
+ @Tag("codegenK2")
+ @Tag("firCodegen")
+ @UseExtTestCaseGroupProvider()
+ @FirPipeline()
+ @UsePartialLinkage(mode = Mode.DISABLED)
+ @Tag("no-partial-linkage-may-be-skipped")
+ public class Mfvc {
+ @Test
+ public void testAllFilesPresentInMfvc() throws Exception {
+ KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/vArrays/mfvc"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.NATIVE, true);
+ }
+ }
}
@Nested
diff --git a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeCodegenBoxTestGenerated.java b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeCodegenBoxTestGenerated.java
index feb7967..56f1f91 100644
--- a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeCodegenBoxTestGenerated.java
+++ b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeCodegenBoxTestGenerated.java
@@ -40933,6 +40933,19 @@
public void testAllFilesPresentInVArrays() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/vArrays"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.NATIVE, true);
}
+
+ @Nested
+ @TestMetadata("compiler/testData/codegen/box/vArrays/mfvc")
+ @TestDataPath("$PROJECT_ROOT")
+ @Tag("codegen")
+ @Tag("k1Codegen")
+ @UseExtTestCaseGroupProvider()
+ public class Mfvc {
+ @Test
+ public void testAllFilesPresentInMfvc() throws Exception {
+ KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/vArrays/mfvc"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.NATIVE, true);
+ }
+ }
}
@Nested
diff --git a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeCodegenBoxTestNoPLGenerated.java b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeCodegenBoxTestNoPLGenerated.java
index 4c1b9dc..8f00d69 100644
--- a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeCodegenBoxTestNoPLGenerated.java
+++ b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeCodegenBoxTestNoPLGenerated.java
@@ -41959,6 +41959,21 @@
public void testAllFilesPresentInVArrays() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/vArrays"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.NATIVE, true);
}
+
+ @Nested
+ @TestMetadata("compiler/testData/codegen/box/vArrays/mfvc")
+ @TestDataPath("$PROJECT_ROOT")
+ @Tag("codegen")
+ @Tag("k1Codegen")
+ @UseExtTestCaseGroupProvider()
+ @UsePartialLinkage(mode = Mode.DISABLED)
+ @Tag("no-partial-linkage-may-be-skipped")
+ public class Mfvc {
+ @Test
+ public void testAllFilesPresentInMfvc() throws Exception {
+ KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/vArrays/mfvc"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.NATIVE, true);
+ }
+ }
}
@Nested
diff --git a/wasm/wasm.tests/tests-gen/org/jetbrains/kotlin/wasm/test/IrCodegenBoxWasmTestGenerated.java b/wasm/wasm.tests/tests-gen/org/jetbrains/kotlin/wasm/test/IrCodegenBoxWasmTestGenerated.java
index a59da49..817f6c1 100644
--- a/wasm/wasm.tests/tests-gen/org/jetbrains/kotlin/wasm/test/IrCodegenBoxWasmTestGenerated.java
+++ b/wasm/wasm.tests/tests-gen/org/jetbrains/kotlin/wasm/test/IrCodegenBoxWasmTestGenerated.java
@@ -33271,6 +33271,19 @@
public void testAllFilesPresentInVArrays() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/vArrays"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
}
+
+ @TestMetadata("compiler/testData/codegen/box/vArrays/mfvc")
+ @TestDataPath("$PROJECT_ROOT")
+ @RunWith(JUnit3RunnerWithInners.class)
+ public static class Mfvc extends AbstractIrCodegenBoxWasmTest {
+ private void runTest(String testDataFilePath) throws Exception {
+ KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
+ }
+
+ public void testAllFilesPresentInMfvc() throws Exception {
+ KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/vArrays/mfvc"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
+ }
+ }
}
@TestMetadata("compiler/testData/codegen/box/valueClasses")