diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmSymbols.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmSymbols.kt index 5771c90db32..d5677bb1575 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmSymbols.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmSymbols.kt @@ -63,6 +63,7 @@ class WasmSymbols( override val primitiveClassesObject = getInternalClass("PrimitiveClasses") override val kTypeClass: IrClassSymbol = getIrClass(FqName("kotlin.reflect.KClass")) + val getTypeInfoTypeDataByPtr: IrSimpleFunctionSymbol = getInternalFunction("getTypeInfoTypeDataByPtr") val wasmTypeInfoData: IrClassSymbol = getInternalClass("TypeInfoData") } @@ -208,8 +209,7 @@ class WasmSymbols( val suiteFun = maybeGetFunction("suite", kotlinTestPackage) val startUnitTests = maybeGetFunction("startUnitTests", kotlinTestPackage) - val wasmClassId = getInternalFunction("wasmClassId") - val wasmInterfaceId = getInternalFunction("wasmInterfaceId") + val wasmTypeId = getInternalFunction("wasmTypeId") val wasmIsInterface = getInternalFunction("wasmIsInterface") diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/dce/WasmUsefulDeclarationProcessor.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/dce/WasmUsefulDeclarationProcessor.kt index 5c4dc8a6870..8154e1e2a9c 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/dce/WasmUsefulDeclarationProcessor.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/dce/WasmUsefulDeclarationProcessor.kt @@ -56,8 +56,7 @@ internal class WasmUsefulDeclarationProcessor( true } - context.wasmSymbols.wasmClassId, - context.wasmSymbols.wasmInterfaceId, + context.wasmSymbols.wasmTypeId, context.wasmSymbols.refCastNull, context.wasmSymbols.refTest, context.wasmSymbols.boxIntrinsic, diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/BodyGenerator.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/BodyGenerator.kt index 3ffa6ce595d..ffe8881ffd3 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/BodyGenerator.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/BodyGenerator.kt @@ -317,7 +317,7 @@ class BodyGenerator( body.buildRefNull(WasmHeapType.Simple.Data, location) } - body.buildConstI32Symbol(context.referenceClassId(klassSymbol), location) + body.buildConstI32Symbol(context.referenceTypeId(klassSymbol), location) body.buildConstI32(0, location) // Any::_hashCode body.commentGroupEnd() } @@ -519,23 +519,15 @@ class BodyGenerator( val location = call.getSourceLocation() when (function.symbol) { - wasmSymbols.wasmClassId -> { + wasmSymbols.wasmTypeId -> { val klass = call.getTypeArgument(0)!!.getClass() - ?: error("No class given for wasmClassId intrinsic") - assert(!klass.isInterface) - body.buildConstI32Symbol(context.referenceClassId(klass.symbol), location) - } - - wasmSymbols.wasmInterfaceId -> { - val irInterface = call.getTypeArgument(0)!!.getClass() - ?: error("No interface given for wasmInterfaceId intrinsic") - assert(irInterface.isInterface) - body.buildConstI32Symbol(context.referenceInterfaceId(irInterface.symbol), location) + ?: error("No class given for wasmTypeId intrinsic") + body.buildConstI32Symbol(context.referenceTypeId(klass.symbol), location) } wasmSymbols.wasmIsInterface -> { val irInterface = call.getTypeArgument(0)!!.getClass() - ?: error("No interface given for wasmInterfaceId intrinsic") + ?: error("No interface given for wasmIsInterface intrinsic") assert(irInterface.isInterface) if (irInterface.symbol in hierarchyDisjointUnions) { val classITable = context.referenceClassITableGcType(irInterface.symbol) diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/DeclarationGenerator.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/DeclarationGenerator.kt index c79ee0c9fbf..eee8d4ab67a 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/DeclarationGenerator.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/DeclarationGenerator.kt @@ -416,7 +416,7 @@ class DeclarationGenerator( val superClass = classMetadata.klass.getSuperClass(context.backendContext.irBuiltIns) val superTypeId = superClass?.let { - ConstantDataIntField("SuperTypeId", context.referenceClassId(it.symbol)) + ConstantDataIntField("SuperTypeId", context.referenceTypeId(it.symbol)) } ?: ConstantDataIntField("SuperTypeId", -1) val typeInfoContent = mutableListOf(typeInfo, superTypeId) @@ -435,7 +435,7 @@ class DeclarationGenerator( val size = ConstantDataIntField("size", interfaces.size) val interfaceIds = ConstantDataIntArray( "interfaceIds", - interfaces.map { context.referenceInterfaceId(it.symbol) }, + interfaces.map { context.referenceTypeId(it.symbol) }, ) return ConstantDataStruct( diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmCompiledModuleFragment.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmCompiledModuleFragment.kt index ee8f8698efc..dcf600dd5ed 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmCompiledModuleFragment.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmCompiledModuleFragment.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.ir.declarations.IrExternalPackageFragment import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable import org.jetbrains.kotlin.ir.util.getPackageFragment +import org.jetbrains.kotlin.ir.util.isInterface import org.jetbrains.kotlin.wasm.ir.* import org.jetbrains.kotlin.wasm.ir.source.location.SourceLocation @@ -33,9 +34,7 @@ class WasmCompiledModuleFragment(val irBuiltIns: IrBuiltIns) { ReferencableAndDefinable() val classITableInterfaceSlot = ReferencableAndDefinable() - val classIds = - ReferencableElements() - val interfaceId = + val typeIds = ReferencableElements() val stringLiteralAddress = ReferencableElements() @@ -119,20 +118,20 @@ class WasmCompiledModuleFragment(val irBuiltIns: IrBuiltIns) { wasmSymbol.bind(canonicalFunctionTypes.getValue(functionTypes.defined.getValue(irSymbol))) } - val klassIds = mutableMapOf() var currentDataSectionAddress = 0 - for (typeInfoElement in typeInfo.elements) { - val ir = typeInfo.wasmToIr.getValue(typeInfoElement) - klassIds[ir] = currentDataSectionAddress - currentDataSectionAddress += typeInfoElement.sizeInBytes + var interfaceId = 0 + typeIds.unbound.forEach { (klassSymbol, wasmSymbol) -> + if (klassSymbol.owner.isInterface) { + interfaceId-- + wasmSymbol.bind(interfaceId) + } else { + wasmSymbol.bind(currentDataSectionAddress) + currentDataSectionAddress += typeInfo.defined.getValue(klassSymbol).sizeInBytes + } } - currentDataSectionAddress = alignUp(currentDataSectionAddress, INT_SIZE_BYTES) scratchMemAddr.bind(currentDataSectionAddress) - bind(classIds.unbound, klassIds) - interfaceId.unbound.onEachIndexed { index, entry -> entry.value.bind(index) } - val stringDataSectionBytes = mutableListOf() var stringDataSectionStart = 0 var stringLiteralCount = 0 @@ -160,9 +159,23 @@ class WasmCompiledModuleFragment(val irBuiltIns: IrBuiltIns) { val constData = ConstantDataIntegerArray("constant_array", constantArraySegment.first, integerSize) data.add(WasmData(WasmDataMode.Passive, constData.toBytes())) } - typeInfo.buildData(data, address = { klassIds.getValue(it) }) - val masterInitFunctionType = WasmFunctionType(emptyList(), emptyList()) + typeIds.unbound.forEach { (klassSymbol, typeId) -> + if (!klassSymbol.owner.isInterface) { + val instructions = mutableListOf() + WasmIrExpressionBuilder(instructions).buildConstI32( + typeId.owner, + SourceLocation.NoLocation("Compile time data per class") + ) + val typeData = WasmData( + WasmDataMode.Active(0, instructions), + typeInfo.defined.getValue(klassSymbol).toBytes() + ) + data.add(typeData) + } + } + + val masterInitFunctionType = WasmFunctionType(emptyList(), emptyList()) val masterInitFunction = WasmFunction.Defined("__init", WasmSymbol(masterInitFunctionType)) with(WasmIrExpressionBuilder(masterInitFunction.instructions)) { initFunctions.sortedBy { it.priority }.forEach { @@ -250,18 +263,6 @@ private fun irSymbolDebugDump(symbol: Any?): String = else -> symbol.toString() } -inline fun WasmCompiledModuleFragment.ReferencableAndDefinable.buildData( - into: MutableList, - address: (IrClassSymbol) -> Int -) { - elements.mapTo(into) { - val id = address(wasmToIr.getValue(it)) - val offset = mutableListOf() - WasmIrExpressionBuilder(offset).buildConstI32(id, SourceLocation.NoLocation("Compile time data per class")) - WasmData(WasmDataMode.Active(0, offset), it.toBytes()) - } -} - fun alignUp(x: Int, alignment: Int): Int { assert(alignment and (alignment - 1) == 0) { "power of 2 expected" } return (x + alignment - 1) and (alignment - 1).inv() diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmModuleCodegenContext.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmModuleCodegenContext.kt index 8bc96c804b5..7e9e84e71a2 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmModuleCodegenContext.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmModuleCodegenContext.kt @@ -177,12 +177,8 @@ class WasmModuleCodegenContext( fun referenceFunctionType(irFunction: IrFunctionSymbol): WasmSymbol = wasmFragment.functionTypes.reference(irFunction) - fun referenceClassId(irClass: IrClassSymbol): WasmSymbol = - wasmFragment.classIds.reference(irClass) - - fun referenceInterfaceId(irInterface: IrClassSymbol): WasmSymbol { - return wasmFragment.interfaceId.reference(irInterface) - } + fun referenceTypeId(irClass: IrClassSymbol): WasmSymbol = + wasmFragment.typeIds.reference(irClass) fun getStructFieldRef(field: IrField): WasmSymbol { val klass = field.parentAsClass diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/AssociatedObjectsLowering.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/AssociatedObjectsLowering.kt index 192af093928..ab360ecb353 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/AssociatedObjectsLowering.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/AssociatedObjectsLowering.kt @@ -90,19 +90,15 @@ private fun IrBuilderWithScope.createAssociatedObjectAdd( 0, irGet(wasmSymbols.initAssociatedObjects.owner.valueParameters[0]) ) - val classIdGetter = when (targetClass.owner.isInterface) { - true -> wasmSymbols.wasmInterfaceId - false -> wasmSymbols.wasmClassId - } addCall.putValueArgument( 1, - irCall(classIdGetter, irBuiltIns.intType).also { + irCall(wasmSymbols.wasmTypeId, irBuiltIns.intType).also { it.putTypeArgument(0, targetClass.defaultType) } ) addCall.putValueArgument( 2, - irCall(wasmSymbols.wasmClassId, irBuiltIns.intType).also { + irCall(wasmSymbols.wasmTypeId, irBuiltIns.intType).also { it.putTypeArgument(0, keyAnnotation.defaultType) } ) diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/BuiltInsLowering.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/BuiltInsLowering.kt index eeb82b64f4e..32a33e9ebd9 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/BuiltInsLowering.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/BuiltInsLowering.kt @@ -150,26 +150,31 @@ class BuiltInsLowering(val context: WasmBackendContext) : FileLoweringPass { return irCall(call, newSymbol, argumentsAsReceivers = true) } symbols.reflectionSymbols.getClassData -> { - val infoDataCtor = symbols.reflectionSymbols.wasmTypeInfoData.constructors.first() val type = call.getTypeArgument(0)!! - val isInterface = type.isInterface() - val fqName = type.classFqName!! - val fqnShouldBeEmitted = - context.configuration.languageVersionSettings.getFlag(AnalysisFlags.allowFullyQualifiedNameInKClass) - val packageName = if (fqnShouldBeEmitted) fqName.parentOrNull()?.asString() ?: "" else "" - val typeName = fqName.shortName().asString() + val klass = type.classOrNull?.owner ?: error("Invalid type") - return with(builder) { - val wasmIdGetter = if (type.isInterface()) symbols.wasmInterfaceId else symbols.wasmClassId - val typeId = irCall(wasmIdGetter).also { - it.putTypeArgument(0, type) - } + val typeId = builder.irCall(symbols.wasmTypeId).also { + it.putTypeArgument(0, type) + } - irCallConstructor(infoDataCtor, emptyList()).also { + if (!klass.isInterface) { + return builder.irCall(context.wasmSymbols.reflectionSymbols.getTypeInfoTypeDataByPtr).also { it.putValueArgument(0, typeId) - it.putValueArgument(1, isInterface.toIrConst(context.irBuiltIns.booleanType)) - it.putValueArgument(2, packageName.toIrConst(context.irBuiltIns.stringType)) - it.putValueArgument(3, typeName.toIrConst(context.irBuiltIns.stringType)) + } + } else { + val infoDataCtor = symbols.reflectionSymbols.wasmTypeInfoData.constructors.first() + val fqName = type.classFqName!! + val fqnShouldBeEmitted = + context.configuration.languageVersionSettings.getFlag(AnalysisFlags.allowFullyQualifiedNameInKClass) + val packageName = if (fqnShouldBeEmitted) fqName.parentOrNull()?.asString() ?: "" else "" + val typeName = fqName.shortName().asString() + + return with(builder) { + irCallConstructor(infoDataCtor, emptyList()).also { + it.putValueArgument(0, typeId) + it.putValueArgument(1, packageName.toIrConst(context.irBuiltIns.stringType)) + it.putValueArgument(2, typeName.toIrConst(context.irBuiltIns.stringType)) + } } } } diff --git a/libraries/stdlib/wasm/internal/kotlin/wasm/internal/TypeInfo.kt b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/TypeInfo.kt index 83ee0fd14f9..4396f02d79a 100644 --- a/libraries/stdlib/wasm/internal/kotlin/wasm/internal/TypeInfo.kt +++ b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/TypeInfo.kt @@ -19,7 +19,10 @@ internal const val TYPE_INFO_SUPER_TYPE_OFFSET = TYPE_INFO_TYPE_SIMPLE_NAME_PRT_ internal const val TYPE_INFO_ITABLE_SIZE_OFFSET = TYPE_INFO_SUPER_TYPE_OFFSET + TYPE_INFO_ELEMENT_SIZE internal const val TYPE_INFO_ITABLE_OFFSET = TYPE_INFO_ITABLE_SIZE_OFFSET + TYPE_INFO_ELEMENT_SIZE -internal class TypeInfoData(val typeId: Int, val isInterface: Boolean, val packageName: String, val typeName: String) +internal class TypeInfoData(val typeId: Int, val packageName: String, val typeName: String) + +internal val TypeInfoData.isInterfaceType + get() = typeId < 0 internal fun getTypeInfoTypeDataByPtr(typeInfoPtr: Int): TypeInfoData { val fqNameLength = wasm_i32_load(typeInfoPtr + TYPE_INFO_TYPE_PACKAGE_NAME_LENGTH_OFFSET) @@ -30,7 +33,7 @@ internal fun getTypeInfoTypeDataByPtr(typeInfoPtr: Int): TypeInfoData { val simpleNamePtr = wasm_i32_load(typeInfoPtr + TYPE_INFO_TYPE_SIMPLE_NAME_PRT_OFFSET) val packageName = stringLiteral(fqNameId, fqNamePtr, fqNameLength) val simpleName = stringLiteral(simpleNameId, simpleNamePtr, simpleNameLength) - return TypeInfoData(typeInfoPtr, isInterface = false, packageName, simpleName) + return TypeInfoData(typeInfoPtr, packageName, simpleName) } internal fun getSuperTypeId(typeInfoPtr: Int): Int = @@ -57,11 +60,7 @@ internal fun wasmIsInterface(obj: Any): Boolean = implementedAsIntrinsic @ExcludedFromCodegen -internal fun wasmClassId(): Int = - implementedAsIntrinsic - -@ExcludedFromCodegen -internal fun wasmInterfaceId(): Int = +internal fun wasmTypeId(): Int = implementedAsIntrinsic @ExcludedFromCodegen diff --git a/libraries/stdlib/wasm/src/kotlin/reflect/AssociatedObjects.kt b/libraries/stdlib/wasm/src/kotlin/reflect/AssociatedObjects.kt index 7a56e8c52aa..2638d0b807b 100644 --- a/libraries/stdlib/wasm/src/kotlin/reflect/AssociatedObjects.kt +++ b/libraries/stdlib/wasm/src/kotlin/reflect/AssociatedObjects.kt @@ -5,7 +5,7 @@ package kotlin.reflect -import kotlin.wasm.internal.wasmClassId +import kotlin.wasm.internal.wasmTypeId import kotlin.wasm.internal.findAssociatedObject /** @@ -40,4 +40,4 @@ public annotation class AssociatedObjectKey @ExperimentalAssociatedObjects @Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE") public inline fun KClass<*>.findAssociatedObject(): Any? = - findAssociatedObject(this, wasmClassId()) \ No newline at end of file + findAssociatedObject(this, wasmTypeId()) \ No newline at end of file diff --git a/libraries/stdlib/wasm/src/kotlin/reflect/KClassImpl.kt b/libraries/stdlib/wasm/src/kotlin/reflect/KClassImpl.kt index 5cef3f64a27..cf5a401ab38 100644 --- a/libraries/stdlib/wasm/src/kotlin/reflect/KClassImpl.kt +++ b/libraries/stdlib/wasm/src/kotlin/reflect/KClassImpl.kt @@ -8,6 +8,7 @@ import kotlin.reflect.* import kotlin.wasm.internal.TypeInfoData import kotlin.wasm.internal.getSuperTypeId import kotlin.wasm.internal.isInterfaceById +import kotlin.wasm.internal.isInterfaceType internal object NothingKClassImpl : KClass { override val simpleName: String = "Nothing" @@ -37,12 +38,16 @@ internal class KClassImpl(internal val typeData: TypeInfoData) : KClass return false } - override fun isInstance(value: Any?): Boolean = value?.let { - if (typeData.isInterface) isInterfaceById(it, typeData.typeId) else checkSuperTypeInstance(it) - } ?: false + override fun isInstance(value: Any?): Boolean { + if (value !is Any) return false + return when (typeData.isInterfaceType) { + true -> isInterfaceById(value, typeData.typeId) + false -> checkSuperTypeInstance(value) + } + } override fun equals(other: Any?): Boolean = - (this === other) || (other is KClassImpl<*> && other.typeData.isInterface == typeData.isInterface && other.typeData.typeId == typeData.typeId) + (this === other) || (other is KClassImpl<*> && other.typeData.typeId == typeData.typeId) override fun hashCode(): Int = typeData.typeId diff --git a/wasm/wasm.tests/test/org/jetbrains/kotlin/generators/tests/GenerateWasmTests.kt b/wasm/wasm.tests/test/org/jetbrains/kotlin/generators/tests/GenerateWasmTests.kt index 6c2176ff126..5a9df8c03ad 100644 --- a/wasm/wasm.tests/test/org/jetbrains/kotlin/generators/tests/GenerateWasmTests.kt +++ b/wasm/wasm.tests/test/org/jetbrains/kotlin/generators/tests/GenerateWasmTests.kt @@ -33,6 +33,7 @@ fun main(args: Array) { ) ) model("box/jsQualifier/", pattern = jsTranslatorTestPattern, targetBackend = TargetBackend.WASM) + model("box/reflection/", pattern = "^(findAssociatedObject(InSeparatedFile)?)\\.kt$", targetBackend = TargetBackend.WASM) } testClass { diff --git a/wasm/wasm.tests/tests-gen/org/jetbrains/kotlin/wasm/test/JsTranslatorWasmTestGenerated.java b/wasm/wasm.tests/tests-gen/org/jetbrains/kotlin/wasm/test/JsTranslatorWasmTestGenerated.java index eb090778be4..52394ce0217 100644 --- a/wasm/wasm.tests/tests-gen/org/jetbrains/kotlin/wasm/test/JsTranslatorWasmTestGenerated.java +++ b/wasm/wasm.tests/tests-gen/org/jetbrains/kotlin/wasm/test/JsTranslatorWasmTestGenerated.java @@ -363,4 +363,27 @@ public class JsTranslatorWasmTestGenerated extends AbstractJsTranslatorWasmTest runTest("js/js.translator/testData/box/jsQualifier/simple.kt"); } } + + @TestMetadata("js/js.translator/testData/box/reflection") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Reflection extends AbstractJsTranslatorWasmTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath); + } + + public void testAllFilesPresentInReflection() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/reflection"), Pattern.compile("^(findAssociatedObject(InSeparatedFile)?)\\.kt$"), null, TargetBackend.WASM, true); + } + + @TestMetadata("findAssociatedObject.kt") + public void testFindAssociatedObject() throws Exception { + runTest("js/js.translator/testData/box/reflection/findAssociatedObject.kt"); + } + + @TestMetadata("findAssociatedObjectInSeparatedFile.kt") + public void testFindAssociatedObjectInSeparatedFile() throws Exception { + runTest("js/js.translator/testData/box/reflection/findAssociatedObjectInSeparatedFile.kt"); + } + } }