diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/dce/Dce.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/dce/Dce.kt index 6d1e67906cbf5..8171af3a3319d 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/dce/Dce.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/dce/Dce.kt @@ -17,6 +17,7 @@ import org.jetbrains.kotlin.ir.visitors.IrVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.js.config.JSConfigurationKeys +import org.jetbrains.kotlin.utils.indexBasedForEach fun eliminateDeadDeclarations(modules: List, context: WasmBackendContext, dceDumpNameCache: DceDumpNameCache) { val printReachabilityInfo = @@ -51,7 +52,7 @@ private fun buildRoots(modules: List, context: WasmBackendCont } modules.onAllFiles { - declarations.forEach { declaration -> + declarations.indexBasedForEach { declaration -> when (declaration) { is IrFunction -> { if (declaration.isExported()) { @@ -106,8 +107,8 @@ private fun buildRoots(modules: List, context: WasmBackendCont } private inline fun List.onAllFiles(body: IrFile.() -> Unit) { - forEach { module -> - module.files.forEach { file -> + indexBasedForEach { module -> + module.files.indexBasedForEach { file -> file.body() } } 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 a8fbf689ef645..6073dc8139a78 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 @@ -17,6 +17,7 @@ import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.erasedUpperBound import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull +import org.jetbrains.kotlin.utils.indexBasedForEach internal class WasmUsefulDeclarationProcessor( override val context: WasmBackendContext, @@ -211,7 +212,7 @@ internal class WasmUsefulDeclarationProcessor( val isIntrinsic = irFunction.hasWasmNoOpCastAnnotation() || irFunction.getWasmOpAnnotation() != null if (isIntrinsic) return - irFunction.getEffectiveValueParameters().forEach { it.enqueueValueParameterType(irFunction) } + irFunction.getEffectiveValueParameters().indexBasedForEach { it.enqueueValueParameterType(irFunction) } irFunction.returnType.enqueueType(irFunction, "function return type") kotlinClosureToJsClosureConvertFunToKotlinClosureCallFun[irFunction.fileOrNull]?.get(irFunction)?.enqueue( @@ -236,7 +237,7 @@ internal class WasmUsefulDeclarationProcessor( // Primitive constructors has no body, since that such constructors implicitly initialize all fields, so we have to preserve them if (irConstructor.hasWasmPrimitiveConstructorAnnotation()) { - constructedClass.declarations.forEach { declaration -> + constructedClass.declarations.indexBasedForEach { declaration -> if (declaration is IrField) { declaration.enqueue(constructedClass, "preserve all fields for primitive constructors") } diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/export/ExportModelGenerator.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/export/ExportModelGenerator.kt index 1fb1da4ed0497..bbea6ebed649b 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/export/ExportModelGenerator.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/export/ExportModelGenerator.kt @@ -16,7 +16,6 @@ import org.jetbrains.kotlin.ir.backend.js.utils.typeScriptInnerClassReference import org.jetbrains.kotlin.ir.backend.js.utils.getFqNameWithJsNameWhenAvailable import org.jetbrains.kotlin.ir.backend.js.utils.isJsExport import org.jetbrains.kotlin.ir.backend.js.utils.realOverrideTarget -import org.jetbrains.kotlin.ir.backend.js.utils.shouldGenerateObjectWithGetInstanceInEsModuleTypeScript import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol @@ -30,6 +29,7 @@ import org.jetbrains.kotlin.name.parentOrNull import org.jetbrains.kotlin.serialization.js.ModuleKind import org.jetbrains.kotlin.utils.addToStdlib.runIf import org.jetbrains.kotlin.utils.memoryOptimizedFilter +import org.jetbrains.kotlin.utils.indexBasedForEach import org.jetbrains.kotlin.utils.memoryOptimizedMap import org.jetbrains.kotlin.utils.memoryOptimizedMapNotNull @@ -60,8 +60,8 @@ class ExportModelGenerator(val context: WasmBackendContext) { val declarationVisitor = object : IrVisitorVoid() { override fun visitFunction(declaration: IrFunction) { visitType(declaration.returnType) - declaration.typeParameters.forEach(::visitTypeParameter) - declaration.parameters.forEach { + declaration.typeParameters.indexBasedForEach(::visitTypeParameter) + declaration.parameters.indexBasedForEach { if (it.kind != IrParameterKind.DispatchReceiver) { visitValueParameter(it) } @@ -69,9 +69,9 @@ class ExportModelGenerator(val context: WasmBackendContext) { } override fun visitClass(declaration: IrClass) { - declaration.superTypes.forEach(::visitType) - declaration.typeParameters.forEach(::visitTypeParameter) - declaration.declarations.forEach { it.acceptVoid(this) } + declaration.superTypes.indexBasedForEach(::visitType) + declaration.typeParameters.indexBasedForEach(::visitTypeParameter) + declaration.declarations.indexBasedForEach { it.acceptVoid(this) } } override fun visitProperty(declaration: IrProperty) { @@ -88,7 +88,7 @@ class ExportModelGenerator(val context: WasmBackendContext) { } override fun visitTypeParameter(declaration: IrTypeParameter) { - declaration.superTypes.forEach(::visitType) + declaration.superTypes.indexBasedForEach(::visitType) } private fun visitType(type: IrType) { @@ -98,7 +98,7 @@ class ExportModelGenerator(val context: WasmBackendContext) { if (!klass.isExternal || klass in excludedFromExport || klass in declarationsToExport) return queue.add(klass) declarationsToExport.add(klass) - type.arguments.forEach { it.typeOrNull?.let(::visitType) } + type.arguments.indexBasedForEach { it.typeOrNull?.let(::visitType) } } } 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 6251505ce2d46..dd8d8516cecf3 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 @@ -27,6 +27,8 @@ import org.jetbrains.kotlin.ir.util.isNullable import org.jetbrains.kotlin.ir.util.isSubtypeOfClass import org.jetbrains.kotlin.ir.visitors.IrVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid +import org.jetbrains.kotlin.utils.indexBasedForEach +import org.jetbrains.kotlin.utils.indexBasedForEachIndexed import org.jetbrains.kotlin.wasm.config.WasmConfigurationKeys import org.jetbrains.kotlin.wasm.ir.* import org.jetbrains.kotlin.wasm.ir.source.location.SourceLocation @@ -120,7 +122,7 @@ class BodyGenerator( } private fun tryGenerateVarargArray(irVararg: IrVararg, wasmArrayType: WasmImmediate.GcType) { - irVararg.elements.forEach { + irVararg.elements.indexBasedForEach { check(it is IrExpression) generateExpression(it) } @@ -331,7 +333,7 @@ class BodyGenerator( private fun buildFinallyBody(catchBlock: IrCatch) { val composite = catchBlock.result as IrComposite assert(composite.statements.last().isSimpleRethrowing(catchBlock)) { "Last throw is not rethrowing" } - composite.statements.dropLast(1).forEach(::generateStatement) + composite.statements.dropLast(1).indexBasedForEach(::generateStatement) } private fun buildCatchBlockBody(catchBlock: IrCatch) { @@ -686,7 +688,7 @@ class BodyGenerator( body.buildIf("this_init") generateAnyParameters(parentClass.symbol, location) val irFields: List = parentClass.allFields(backendContext.irBuiltIns) - irFields.forEachIndexed { index, field -> + irFields.indexBasedForEachIndexed { index, field -> if (index > 0) { generateDefaultInitializerForType(wasmModuleTypeTransformer.transformType(field.type), body) } @@ -1216,7 +1218,7 @@ class BodyGenerator( } override fun visitBlockBody(body: IrBlockBody) { - body.statements.forEach(::generateStatement) + body.statements.indexBasedForEach(::generateStatement) this.body.buildNop(body.getSourceEndLocation()) } @@ -1244,7 +1246,7 @@ class BodyGenerator( private fun processContainerExpression(expression: IrContainerExpression) { val statements = expression.statements - statements.forEachIndexed { i, statement -> + statements.indexBasedForEachIndexed { i, statement -> if (i != statements.lastIndex) { generateStatement(statement) } else { diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/ConstantData.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/ConstantData.kt index ed144ddc26030..2b08ccdca8271 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/ConstantData.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/ConstantData.kt @@ -5,6 +5,8 @@ package org.jetbrains.kotlin.backend.wasm.ir2wasm +import org.jetbrains.kotlin.utils.indexBasedForEach +import org.jetbrains.kotlin.utils.indexBasedForEachIndexed import org.jetbrains.kotlin.wasm.ir.WasmSymbol // Representation of constant data in Wasm memory @@ -87,7 +89,7 @@ class ConstantDataCharArray(val value: List>, val fitsLatin1: B override fun toBytes(): ByteArray { return ByteArray(value.size * bytesPerChar).apply { - value.forEachIndexed { index, symbol -> symbol.owner.toLittleEndianBytes(this, index * bytesPerChar, fitsLatin1) } + value.indexBasedForEachIndexed { index, symbol -> symbol.owner.toLittleEndianBytes(this, index * bytesPerChar, fitsLatin1) } } } @@ -105,7 +107,7 @@ class ConstantDataCharArray(val value: List>, val fitsLatin1: B class ConstantDataStruct(val elements: List) : ConstantDataElement() { override fun toBytes(): ByteArray { return buildList { - elements.forEach { + elements.indexBasedForEach { for (byte in it.toBytes()) { add(byte) } 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 5173861b96038..4e38b24d96c43 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 @@ -26,6 +26,7 @@ import org.jetbrains.kotlin.ir.util.erasedUpperBound import org.jetbrains.kotlin.ir.visitors.IrVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.name.parentOrNull +import org.jetbrains.kotlin.utils.indexBasedForEachIndexed import org.jetbrains.kotlin.wasm.ir.* import org.jetbrains.kotlin.wasm.ir.source.location.SourceLocation @@ -324,7 +325,7 @@ class DeclarationGenerator( val initVTableGlobal = buildWasmExpression { val location = SourceLocation.NoLocation("Create instance of vtable struct") buildSpecialITableInit(metadata, this, location) - metadata.virtualMethods.forEachIndexed { i, method -> + metadata.virtualMethods.indexBasedForEachIndexed { i, method -> if (method.function.modality != Modality.ABSTRACT) { buildInstr(WasmOp.REF_FUNC, location, WasmImmediate.FuncIdx(wasmFileCodegenContext.referenceFunction(method.function.symbol))) } else { diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/RecursiveTypesUtils.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/RecursiveTypesUtils.kt index 55dbb9de45e73..730f92e0da4db 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/RecursiveTypesUtils.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/RecursiveTypesUtils.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.backend.wasm.ir2wasm import org.jetbrains.kotlin.backend.common.serialization.Hash128Bits import org.jetbrains.kotlin.backend.wasm.utils.StronglyConnectedComponents +import org.jetbrains.kotlin.utils.indexBasedForEach import org.jetbrains.kotlin.utils.yieldIfNotNull import org.jetbrains.kotlin.wasm.ir.* @@ -56,11 +57,11 @@ private fun wasmTypeDeclarationOrderKey(declaration: WasmTypeDeclaration): Int { fun createRecursiveTypeGroups(types: List): List { val componentFinder = StronglyConnectedComponents(::dependencyTypes) - types.forEach(componentFinder::visit) + types.indexBasedForEach(componentFinder::visit) val components = componentFinder.findComponents() - components.forEach { component -> + components.indexBasedForEach { component -> component.sortBy(::wasmTypeDeclarationOrderKey) } 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 22420569da0fe..762608c3328b2 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 @@ -19,6 +19,7 @@ import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.util.IdSignature import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable import org.jetbrains.kotlin.ir.util.getPackageFragment +import org.jetbrains.kotlin.utils.indexBasedForEach import org.jetbrains.kotlin.wasm.ir.* import org.jetbrains.kotlin.wasm.ir.source.location.SourceLocation @@ -152,8 +153,8 @@ class WasmCompiledModuleFragment( private fun partitionDefinedAndImportedFunctions(): Pair, MutableList> { val definedFunctions = mutableListOf() val importedFunctions = mutableListOf() - wasmCompiledFileFragments.forEach { fragment -> - fragment.functions.elements.forEach { function -> + wasmCompiledFileFragments.indexBasedForEach { fragment -> + fragment.functions.elements.indexBasedForEach { function -> when (function) { is WasmFunction.Defined -> definedFunctions.add(function) is WasmFunction.Imported -> importedFunctions.add(function) @@ -260,7 +261,7 @@ class WasmCompiledModuleFragment( val (importedTags, definedTags) = tags.partition { it.importPair != null } val importsInOrder = importedFunctions + importedTags - tags.forEach { additionalTypes.add(it.type) } + tags.indexBasedForEach { additionalTypes.add(it.type) } val recursiveTypeGroups = getTypes(syntheticTypes, canonicalFunctionTypes, additionalTypes) @@ -306,13 +307,13 @@ class WasmCompiledModuleFragment( additionalTypes.add(rttiTypeDeclaration) val rttiGlobals = mutableMapOf() - wasmCompiledFileFragments.forEach { fragment -> - fragment.rttiElements?.globals?.forEach { global -> + wasmCompiledFileFragments.indexBasedForEach { fragment -> + fragment.rttiElements?.globals?.indexBasedForEach { global -> rttiGlobals[global.classSignature] = global } } - wasmCompiledFileFragments.forEach { fragment -> + wasmCompiledFileFragments.indexBasedForEach { fragment -> fragment.rttiElements?.run { globalReferences.unbound.forEach { unbound -> unbound.value.bind(rttiGlobals[unbound.key]?.global ?: error("A RttiGlobal was not found for ${unbound.key}")) @@ -354,7 +355,7 @@ class WasmCompiledModuleFragment( ) syntheticTypes.add(specialSlotITableType) - wasmCompiledFileFragments.forEach { fragment -> + wasmCompiledFileFragments.indexBasedForEach { fragment -> fragment.specialITableTypes?.let { specialITableTypes -> specialITableTypes.wasmAnyArrayType.bind(wasmAnyArrayType) specialITableTypes.specialSlotITableType.bind(specialSlotITableType) @@ -415,13 +416,13 @@ class WasmCompiledModuleFragment( } } - additionalTypes.forEach { groupsWithMixIns.add(listOf(it)) } + additionalTypes.indexBasedForEach { groupsWithMixIns.add(listOf(it)) } return groupsWithMixIns } private fun getGlobals(additionalTypes: MutableList) = mutableListOf().apply { - wasmCompiledFileFragments.forEach { fragment -> + wasmCompiledFileFragments.indexBasedForEach { fragment -> addAll(fragment.globalFields.elements) addAll(fragment.globalVTables.elements) addAll(fragment.globalClassITables.elements.distinct()) @@ -460,8 +461,8 @@ class WasmCompiledModuleFragment( buildInstr(WasmOp.CALL, serviceCodeLocation, WasmImmediate.FuncIdx(WasmSymbol(registerModuleDescriptor))) } - wasmCompiledFileFragments.forEach { fragment -> - fragment.mainFunctionWrappers.forEach { signature -> + wasmCompiledFileFragments.indexBasedForEach { fragment -> + fragment.mainFunctionWrappers.indexBasedForEach { signature -> val wrapperFunction = fragment.functions.defined[signature] ?: compilationException("Cannot find symbol for main wrapper", type = null) buildCall(WasmSymbol(wrapperFunction), serviceCodeLocation) @@ -502,17 +503,17 @@ class WasmCompiledModuleFragment( } val allDefinedFunctions = mutableMapOf() - wasmCompiledFileFragments.forEach { allDefinedFunctions.putAll(it.functions.defined) } + wasmCompiledFileFragments.indexBasedForEach { allDefinedFunctions.putAll(it.functions.defined) } associatedObjectGetter.instructions.clear() with(WasmExpressionBuilder(associatedObjectGetter.instructions)) { - wasmCompiledFileFragments.forEach { fragment -> + wasmCompiledFileFragments.indexBasedForEach { fragment -> for ((klassId, associatedObjectsInstanceGetters) in fragment.classAssociatedObjectsInstanceGetters) { buildGetLocal(WasmLocal(0, "classId", WasmI64, true), serviceCodeLocation) buildConstI64(klassId, serviceCodeLocation) buildInstr(WasmOp.I64_EQ, serviceCodeLocation) buildIf("Class matches") - associatedObjectsInstanceGetters.forEach { (keyId, getter, isExternal) -> + associatedObjectsInstanceGetters.indexBasedForEach { (keyId, getter, isExternal) -> val getterFunction = allDefinedFunctions[getter] if (getterFunction != null) { //Could be deleted with DCE buildGetLocal(WasmLocal(1, "keyId", WasmI64, true), serviceCodeLocation) @@ -540,8 +541,8 @@ class WasmCompiledModuleFragment( val runRootSuites = tryFindBuiltInFunction { it.runRootSuites } ?: return null val startUnitTestsFunction = WasmFunction.Defined("startUnitTests", WasmSymbol(parameterlessNoReturnFunctionType)) with(WasmExpressionBuilder(startUnitTestsFunction.instructions)) { - wasmCompiledFileFragments.forEach { fragment -> - fragment.testFunctionDeclarators.forEach{ declarator -> + wasmCompiledFileFragments.indexBasedForEach { fragment -> + fragment.testFunctionDeclarators.indexBasedForEach{ declarator -> val declaratorFunction = fragment.functions.defined[declarator] ?: compilationException("Cannot find symbol for test declarator", type = null) buildCall(WasmSymbol(declaratorFunction), serviceCodeLocation) @@ -574,15 +575,15 @@ class WasmCompiledModuleFragment( } ?: compilationException("stringPool initializer not found!", type = null) buildCall(stringPoolInitializer, serviceCodeLocation) - wasmCompiledFileFragments.forEach { fragment -> - fragment.objectInstanceFieldInitializers.forEach { objectInitializer -> + wasmCompiledFileFragments.indexBasedForEach { fragment -> + fragment.objectInstanceFieldInitializers.indexBasedForEach { objectInitializer -> val functionSymbol = WasmSymbol(fragment.functions.defined[objectInitializer]!!) buildCall(functionSymbol, serviceCodeLocation) } } - wasmCompiledFileFragments.forEach { fragment -> - fragment.nonConstantFieldInitializers.forEach { nonConstantInitializer -> + wasmCompiledFileFragments.indexBasedForEach { fragment -> + fragment.nonConstantFieldInitializers.indexBasedForEach { nonConstantInitializer -> val functionSymbol = WasmSymbol(fragment.functions.defined[nonConstantInitializer]!!) buildCall(functionSymbol, serviceCodeLocation) } @@ -797,7 +798,7 @@ class WasmCompiledModuleFragment( ) ) - wasmCompiledFileFragments.forEach { fragment -> + wasmCompiledFileFragments.indexBasedForEach { fragment -> if (isLatin1) { fragment.wasmStringsElements?.createStringLiteralLatin1?.bind(stringLiteralFunction) } else { @@ -827,7 +828,7 @@ class WasmCompiledModuleFragment( definedSelector: (WasmCompiledFileFragment) -> Map, ) { val allDefined = mutableMapOf() - fragments.forEach { fragment -> + fragments.indexBasedForEach { fragment -> definedSelector(fragment).forEach { defined -> check(!allDefined.containsKey(defined.key)) { "Redeclaration of symbol ${defined.key}" @@ -844,11 +845,11 @@ class WasmCompiledModuleFragment( private fun bindUnboundFunctionTypes(): Map { // Associate function types to a single canonical function type val canonicalFunctionTypes = LinkedHashMap() - wasmCompiledFileFragments.forEach { fragment -> + wasmCompiledFileFragments.indexBasedForEach { fragment -> fragment.functionTypes.elements.associateWithTo(canonicalFunctionTypes) { it } } // Rebind symbol to canonical - wasmCompiledFileFragments.forEach { fragment -> + wasmCompiledFileFragments.indexBasedForEach { fragment -> fragment.functionTypes.unbound.forEach { (_, wasmSymbol) -> wasmSymbol.bind(canonicalFunctionTypes.getValue(wasmSymbol.owner)) } @@ -861,7 +862,7 @@ class WasmCompiledModuleFragment( var stringDataSectionStart = 0 val visitedStrings = mutableMapOf() val addressesAndLengths = mutableListOf() - wasmCompiledFileFragments.forEach { fragment -> + wasmCompiledFileFragments.indexBasedForEach { fragment -> for ((string, literalIdSymbol) in fragment.stringLiteralId.unbound) { val visitedStringId = visitedStrings[string] val stringId: Int @@ -880,7 +881,7 @@ class WasmCompiledModuleFragment( } } - wasmCompiledFileFragments.forEach { fragment -> + wasmCompiledFileFragments.indexBasedForEach { fragment -> fragment.wasmStringsElements?.stringPoolSize?.bind(visitedStrings.size) } @@ -892,7 +893,7 @@ class WasmCompiledModuleFragment( } private fun bindConstantArrayDataSegmentIds(data: MutableList) { - wasmCompiledFileFragments.forEach { fragment -> + wasmCompiledFileFragments.indexBasedForEach { fragment -> fragment.constantArrayDataSegmentId.unbound.forEach { (constantArraySegment, symbol) -> symbol.bind(data.size) val integerSize = when (constantArraySegment.second) { @@ -910,7 +911,7 @@ class WasmCompiledModuleFragment( private fun bindUniqueJsFunNames() { val jsCodeCounter = mutableMapOf() - wasmCompiledFileFragments.forEach { fragment -> + wasmCompiledFileFragments.indexBasedForEach { fragment -> fragment.jsFuns.forEach { jsCodeSnippet -> val jsFunName = jsCodeSnippet.value.importName.owner val counterValue = jsCodeCounter.getOrPut(jsFunName, defaultValue = { 0 }) @@ -924,7 +925,7 @@ class WasmCompiledModuleFragment( private fun rebindEquivalentFunctions() { val equivalentFunctions = mutableMapOf() - wasmCompiledFileFragments.forEach { fragment -> + wasmCompiledFileFragments.indexBasedForEach { fragment -> for ((signatureString, idSignature) in fragment.equivalentFunctions) { val func = equivalentFunctions[signatureString] if (func == null) { diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmStringSwitchOptimizerLowering.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmStringSwitchOptimizerLowering.kt index d2dacd86affcf..1171160a9f671 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmStringSwitchOptimizerLowering.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmStringSwitchOptimizerLowering.kt @@ -10,7 +10,6 @@ import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext import org.jetbrains.kotlin.backend.common.IrWhenUtils import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.wasm.WasmBackendContext -import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.declarations.buildVariable import org.jetbrains.kotlin.ir.declarations.* @@ -22,6 +21,7 @@ import org.jetbrains.kotlin.ir.util.isElseBranch import org.jetbrains.kotlin.ir.util.isNullable import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.utils.indexBasedForEachIndexed private val OPTIMISED_WHEN_SUBJECT by IrDeclarationOriginImpl @@ -238,7 +238,7 @@ class WasmStringSwitchOptimizerLowering( var firstEqCall: IrCall? = null var isSimpleWhen = true //simple when is when without else block and commas val stringConstantToMatchedCase = mutableMapOf() - visitedWhen.branches.forEachIndexed { branchIndex, branch -> + visitedWhen.branches.indexBasedForEachIndexed { branchIndex, branch -> if (!isElseBranch(branch)) { val conditions = IrWhenUtils.matchConditions(context.irBuiltIns.ororSymbol, branch.condition) ?: return visitedWhen if (conditions.isEmpty()) return visitedWhen diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmVarargExpressionLowering.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmVarargExpressionLowering.kt index 74dc84cf61fb8..d8bb02bee9dfe 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmVarargExpressionLowering.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmVarargExpressionLowering.kt @@ -24,7 +24,7 @@ import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.getArrayElementType import org.jetbrains.kotlin.ir.util.isBoxedArray import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid -import org.jetbrains.kotlin.util.OperatorNameConventions +import org.jetbrains.kotlin.utils.indexBasedForEach internal class WasmVarargExpressionLowering( private val context: WasmBackendContext @@ -233,7 +233,7 @@ internal class WasmVarargExpressionLowering( return builder.irComposite(irVararg) { // Emit all of the variables first so that all vararg expressions // are evaluated only once and in order of their appearance. - elementVars.forEach { +it } + elementVars.indexBasedForEach { +it } val arrayLength = segments .map { irSize(it) } @@ -244,7 +244,7 @@ internal class WasmVarargExpressionLowering( nameHint = "vararg_array") val indexVar = if (segments.size >= 2) irTemporary(irInt(0), "vararg_idx") else null - segments.forEach { + segments.indexBasedForEach { irCopyInto(arrayTempVariable, indexVar, it) if (indexVar != null) diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/serialization/WasmSerializer.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/serialization/WasmSerializer.kt index 48b348e568bde..08f30acbde343 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/serialization/WasmSerializer.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/serialization/WasmSerializer.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.backend.wasm.serialization import org.jetbrains.kotlin.backend.wasm.ir2wasm.* import org.jetbrains.kotlin.ir.util.IdSignature +import org.jetbrains.kotlin.utils.indexBasedForEach import org.jetbrains.kotlin.wasm.ir.* import org.jetbrains.kotlin.wasm.ir.convertors.ByteWriter import org.jetbrains.kotlin.wasm.ir.source.location.SourceLocation @@ -133,7 +134,7 @@ class WasmSerializer(outputStream: OutputStream) { while (newReferences.isNotEmpty()) { val sorted = newReferences.sortedBy { it.id } newReferences.clear() - sorted.forEach { + sorted.indexBasedForEach { tempBuffer.reset() it.serializeFunc() tableElementsInBytes.add(tempBuffer.toByteArray()) @@ -145,7 +146,7 @@ class WasmSerializer(outputStream: OutputStream) { out.writeUInt32(size.toUInt()) // Output each element in the form: sizeInBytes data - tableElementsInBytes.forEach { + tableElementsInBytes.indexBasedForEach { val bytesCount = it.size out.writeUInt32(bytesCount.toUInt()) out.writeBytes(it) @@ -393,7 +394,7 @@ class WasmSerializer(outputStream: OutputStream) { private fun serializeList(list: List, serializeFunc: (T) -> Unit) { b.writeUInt32(list.size.toUInt()) - list.forEach { serializeFunc(it) } + list.indexBasedForEach { serializeFunc(it) } } private fun serializeSet(set: Set, serializeFunc: (T) -> Unit) { diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/wasmCompiler.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/wasmCompiler.kt index d5f4708ee86a3..6bc60dbabb271 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/wasmCompiler.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/wasmCompiler.kt @@ -34,6 +34,8 @@ import org.jetbrains.kotlin.util.PhaseType import org.jetbrains.kotlin.util.tryMeasurePhaseTime import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty import org.jetbrains.kotlin.utils.addToStdlib.runIf +import org.jetbrains.kotlin.utils.indexBasedForEach +import org.jetbrains.kotlin.utils.indexBasedForEachIndexed import org.jetbrains.kotlin.wasm.config.WasmConfigurationKeys import org.jetbrains.kotlin.wasm.ir.* import org.jetbrains.kotlin.wasm.ir.convertors.WasmIrToBinary @@ -92,7 +94,7 @@ fun compileToLoweredIr( is MainModule.Klib -> sortedModuleDependencies.all } - allModules.forEach { it.patchDeclarationParents() } + allModules.indexBasedForEach { it.patchDeclarationParents() } irLinker.postProcess(inOrAfterLinkageStep = true) irLinker.checkNoUnboundSymbols(symbolTable, "at the end of IR linkage process") @@ -134,7 +136,7 @@ fun lowerPreservingTags( val phaserState = PhaserState() val wasmLowerings = getWasmLowerings(context.configuration, isIncremental) - wasmLowerings.forEachIndexed { i, lowering -> + wasmLowerings.indexBasedForEachIndexed { i, lowering -> controller.currentStage = i + 1 modules.forEach { module -> lowering.invoke(context.phaseConfig, phaserState, context, module) @@ -209,7 +211,7 @@ fun compileWasm( val jsModuleImports = mutableSetOf() val jsFuns = mutableSetOf() val jsModuleAndQualifierReferences = mutableSetOf() - wasmCompiledFileFragments.forEach { fragment -> + wasmCompiledFileFragments.indexBasedForEach { fragment -> jsModuleImports.addAll(fragment.jsModuleImports.values) jsFuns.addAll(fragment.jsFuns.values) jsModuleAndQualifierReferences.addAll(fragment.jsModuleAndQualifierReferences) diff --git a/core/util.runtime/src/org/jetbrains/kotlin/utils/MemoryOptimizedCollectionUtil.kt b/core/util.runtime/src/org/jetbrains/kotlin/utils/MemoryOptimizedCollectionUtil.kt index b388116a0404c..9ba84eaa11468 100644 --- a/core/util.runtime/src/org/jetbrains/kotlin/utils/MemoryOptimizedCollectionUtil.kt +++ b/core/util.runtime/src/org/jetbrains/kotlin/utils/MemoryOptimizedCollectionUtil.kt @@ -6,6 +6,8 @@ package org.jetbrains.kotlin.utils import java.util.* +import kotlin.contracts.ExperimentalContracts +import kotlin.contracts.contract import kotlin.math.min /** @@ -91,6 +93,34 @@ infix fun List.memoryOptimizedPlus(element: T): List = } } +/** + * A memory-optimized version of [Iterable.forEach]. It uses indexed access to avoid iterator allocation. + * + * **Using this in a non-random access-based list will lead to performance degradation.** + * @see Iterable.forEach + */ +@OptIn(ExperimentalContracts::class) +public inline fun List.indexBasedForEach(action: (T) -> Unit): Unit { + contract { + callsInPlace(action) + } + for (index in 0..size - 1) action(this[index]) +} + +/** + * A memory-optimized version of [Iterable.forEachIndexed]. It uses indexed access to avoid iterator allocation. + * + * **Using this in a non-random access-based list will lead to performance degradation.** + * @see Iterable.forEachIndexed + */ +@OptIn(ExperimentalContracts::class) +public inline fun List.indexBasedForEachIndexed(action: (Int, T) -> Unit): Unit { + contract { + callsInPlace(action) + } + for (index in 0..size - 1) action(index, this[index]) +} + /** * A memory-optimized version of [Iterable.zip]. * @see Iterable.zip diff --git a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmIrToBinary.kt b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmIrToBinary.kt index 7df0475d41345..06f214cda838c 100644 --- a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmIrToBinary.kt +++ b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmIrToBinary.kt @@ -9,6 +9,8 @@ import org.jetbrains.kotlin.wasm.ir.* import java.io.ByteArrayOutputStream import java.io.OutputStream import kotlinx.collections.immutable.* +import org.jetbrains.kotlin.utils.indexBasedForEach +import org.jetbrains.kotlin.utils.indexBasedForEachIndexed import org.jetbrains.kotlin.wasm.ir.debug.DebugData import org.jetbrains.kotlin.wasm.ir.debug.DebugInformation import org.jetbrains.kotlin.wasm.ir.debug.DebugInformationConsumer @@ -71,7 +73,7 @@ class WasmIrToBinary( private var offsets = persistentListOf() override fun consumeDebugInformation(debugInformation: DebugInformation) { - debugInformation.forEach { + debugInformation.indexBasedForEach { appendSection(WasmBinary.Section.CUSTOM) { b.writeString(it.name) when (it.data) { @@ -83,7 +85,7 @@ class WasmIrToBinary( } private fun appendWasmTypeList(typeList: List) { - typeList.forEach { type -> + typeList.indexBasedForEach { type -> when (type) { is WasmStructDeclaration -> appendStructTypeDeclaration(type) is WasmArrayDeclaration -> appendArrayTypeDeclaration(type) @@ -100,7 +102,7 @@ class WasmIrToBinary( // type section appendSection(WasmBinary.Section.TYPE) { appendVectorSize(recGroups.size) - recGroups.forEach { recGroup -> + recGroups.indexBasedForEach { recGroup -> if (recGroup.size > 1) { b.writeVarInt7(WasmBinary.REC_GROUP) appendVectorSize(recGroup.size) @@ -114,7 +116,7 @@ class WasmIrToBinary( // import section appendSection(WasmBinary.Section.IMPORT) { appendVectorSize(importsInOrder.size) - importsInOrder.forEach { + importsInOrder.indexBasedForEach { when (it) { is WasmFunction.Imported -> appendImportedFunction(it) is WasmMemory -> appendMemory(it) @@ -129,37 +131,37 @@ class WasmIrToBinary( // function section appendSection(WasmBinary.Section.FUNCTION) { appendVectorSize(definedFunctions.size) - definedFunctions.forEach { appendDefinedFunction(it) } + definedFunctions.indexBasedForEach { appendDefinedFunction(it) } } // table section appendSection(WasmBinary.Section.TABLE) { appendVectorSize(tables.size) - tables.forEach { appendTable(it) } + tables.indexBasedForEach { appendTable(it) } } // memory section appendSection(WasmBinary.Section.MEMORY) { appendVectorSize(memories.size) - memories.forEach { appendMemory(it) } + memories.indexBasedForEach { appendMemory(it) } } // tag section if (tags.isNotEmpty()) { appendSection(WasmBinary.Section.TAG) { appendVectorSize(tags.size) - tags.forEach { appendTag(it) } + tags.indexBasedForEach { appendTag(it) } } } appendSection(WasmBinary.Section.GLOBAL) { appendVectorSize(globals.size) - globals.forEach { appendGlobal(it) } + globals.indexBasedForEach { appendGlobal(it) } } appendSection(WasmBinary.Section.EXPORT) { appendVectorSize(exports.size) - exports.forEach { appendExport(it) } + exports.indexBasedForEach { appendExport(it) } } if (startFunction != null) { @@ -171,7 +173,7 @@ class WasmIrToBinary( // element section appendSection(WasmBinary.Section.ELEMENT) { appendVectorSize(elements.size) - elements.forEach { appendElement(it) } + elements.indexBasedForEach { appendElement(it) } } if (dataCount) { @@ -183,12 +185,12 @@ class WasmIrToBinary( // code section appendSection(WasmBinary.Section.CODE, beforeContentWrite = { codeSectionOffset = b.written }) { appendVectorSize(definedFunctions.size) - definedFunctions.forEach { appendCode(it) } + definedFunctions.indexBasedForEach { appendCode(it) } } appendSection(WasmBinary.Section.DATA) { appendVectorSize(data.size) - data.forEach { appendData(it) } + data.indexBasedForEach { appendData(it) } } // text section (should be placed after data) @@ -208,17 +210,17 @@ class WasmIrToBinary( } appendSection(WasmBinary.Section.TYPE) { appendVectorSize(definedFunctions.size) - definedFunctions.forEach { + definedFunctions.indexBasedForEach { appendModuleFieldReference(it) b.writeString(it.name) } } appendSection(WasmBinary.Section.IMPORT) { appendVectorSize(definedFunctions.size) - definedFunctions.forEach { + definedFunctions.indexBasedForEach { appendModuleFieldReference(it) appendVectorSize(it.locals.size) - it.locals.forEach { local -> + it.locals.indexBasedForEach { local -> b.writeVarUInt32(local.id) b.writeString(local.name) } @@ -230,8 +232,8 @@ class WasmIrToBinary( appendSection(WasmBinary.Section.TABLE) { appendVectorSize(module.recGroups.sumOf { it.size }) - module.recGroups.forEach { recGroup -> - recGroup.forEach { + module.recGroups.indexBasedForEach { recGroup -> + recGroup.indexBasedForEach { appendModuleFieldReference(it) b.writeString(it.name) } @@ -240,7 +242,7 @@ class WasmIrToBinary( appendSection(WasmBinary.Section.EXPORT) { appendVectorSize(module.globals.size) - module.globals.forEach { global -> + module.globals.indexBasedForEach { global -> appendModuleFieldReference(global) b.writeString(global.name) } @@ -251,10 +253,10 @@ class WasmIrToBinary( appendSection(WasmBinary.Section.CODE) { val structDeclarations = module.recGroups.flatMap { it.filterIsInstance() } appendVectorSize(structDeclarations.size) - structDeclarations.forEach { + structDeclarations.indexBasedForEach { appendModuleFieldReference(it) appendVectorSize(it.fields.size) - it.fields.forEachIndexed { index, field -> + it.fields.indexBasedForEachIndexed { index, field -> b.writeVarUInt32(index) b.writeString(field.name) } @@ -280,7 +282,7 @@ class WasmIrToBinary( b.writeByte(opcode.toByte()) } - instr.immediates.forEach { + instr.immediates.indexBasedForEach { appendImmediate(it) } } @@ -331,7 +333,7 @@ class WasmIrToBinary( is WasmImmediate.Catch -> { b.writeVarUInt32(x.type.opcode) - x.immediates.forEach(this::appendImmediate) + x.immediates.indexBasedForEach(this::appendImmediate) } } } @@ -367,9 +369,9 @@ class WasmIrToBinary( private fun appendFunctionTypeDeclaration(type: WasmFunctionType) { b.writeVarInt7(WasmBinary.FUNC_TYPE) b.writeVarUInt32(type.parameterTypes.size) - type.parameterTypes.forEach { appendType(it) } + type.parameterTypes.indexBasedForEach { appendType(it) } b.writeVarUInt32(type.resultTypes.size) - type.resultTypes.forEach { appendType(it) } + type.resultTypes.indexBasedForEach { appendType(it) } } private fun appendBlockType(type: WasmImmediate.BlockType) { @@ -417,7 +419,7 @@ class WasmIrToBinary( b.writeVarInt7(WasmBinary.STRUCT_TYPE) b.writeVarUInt32(type.fields.size) - type.fields.forEach { + type.fields.indexBasedForEach { appendFiledType(it) } } @@ -528,9 +530,9 @@ class WasmIrToBinary( fun writeElements() { appendVectorSize(element.values.size) if (funcIndices != null) { - funcIndices.forEach { b.writeVarUInt32(it) } + funcIndices.indexBasedForEach { b.writeVarUInt32(it) } } else { - element.values.forEach { + element.values.indexBasedForEach { appendExpr((it as WasmTable.Value.Expression).expr) } } @@ -597,7 +599,7 @@ class WasmIrToBinary( } b.writeVarUInt32(function.locals.count { !it.isParameter }) - function.locals.forEach { local -> + function.locals.indexBasedForEach { local -> if (!local.isParameter) { b.writeVarUInt32(1u) appendType(local.type) diff --git a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmIrToText.kt b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmIrToText.kt index f28f4584f37e8..9ca46cae6bfe5 100644 --- a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmIrToText.kt +++ b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmIrToText.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.wasm.ir.convertors +import org.jetbrains.kotlin.utils.indexBasedForEach import org.jetbrains.kotlin.wasm.ir.* import org.jetbrains.kotlin.wasm.ir.debug.DebugData import org.jetbrains.kotlin.wasm.ir.debug.DebugInformation @@ -86,7 +87,7 @@ class WasmIrToText( appendInstr(instruction) } } else { - instr.forEach(::appendInstr) + instr.indexBasedForEach(::appendInstr) } } @@ -115,7 +116,7 @@ class WasmIrToText( } WasmOp.PSEUDO_COMMENT_GROUP_START -> { newLine() - commentText().lines().forEach { line -> + commentText().lines().indexBasedForEach { line -> newLine() stringBuilder.append(";; ") stringBuilder.append(line) @@ -148,12 +149,12 @@ class WasmIrToText( indent++ if (wasmInstr.operator in setOf(WasmOp.CALL_INDIRECT, WasmOp.TABLE_INIT)) { - wasmInstr.immediates.reversed().forEach { + wasmInstr.immediates.reversed().indexBasedForEach { appendImmediate(it) } return } - wasmInstr.immediates.forEach { + wasmInstr.immediates.indexBasedForEach { appendImmediate(it) } } @@ -181,11 +182,11 @@ class WasmIrToText( is WasmImmediate.LabelIdx -> appendElement(x.value.toString()) is WasmImmediate.TagIdx -> appendElement(x.value.toString()) is WasmImmediate.LabelIdxVector -> - x.value.forEach { appendElement(it.toString()) } + x.value.indexBasedForEach { appendElement(it.toString()) } is WasmImmediate.ElemIdx -> appendElement(x.value.id!!.toString()) - is WasmImmediate.ValTypeVector -> sameLineList("result") { x.value.forEach { appendType(it) } } + is WasmImmediate.ValTypeVector -> sameLineList("result") { x.value.indexBasedForEach { appendType(it) } } is WasmImmediate.GcType -> appendModuleFieldReference(x.value.owner) is WasmImmediate.StructFieldIdx -> appendElement(x.value.owner.toString()) @@ -261,10 +262,10 @@ class WasmIrToText( val parameters = type.type.owner.parameterTypes val results = type.type.owner.resultTypes if (parameters.isNotEmpty()) { - sameLineList("param") { parameters.forEach { appendType(it) } } + sameLineList("param") { parameters.indexBasedForEach { appendType(it) } } } if (results.isNotEmpty()) { - sameLineList("result") { results.forEach { appendType(it) } } + sameLineList("result") { results.indexBasedForEach { appendType(it) } } } } } @@ -278,7 +279,7 @@ class WasmIrToText( } private fun appendWasmTypeList(typeList: List) { - typeList.forEach { type -> + typeList.indexBasedForEach { type -> when (type) { is WasmStructDeclaration -> appendStructTypeDeclaration(type) @@ -293,7 +294,7 @@ class WasmIrToText( fun appendWasmModule(module: WasmModule) { with(module) { newLineList("module") { - recGroups.forEach { recGroup -> + recGroups.indexBasedForEach { recGroup -> if (recGroup.size > 1) { newLineList("rec") { appendWasmTypeList(recGroup) } } else { @@ -301,7 +302,7 @@ class WasmIrToText( } } - importsInOrder.forEach { + importsInOrder.indexBasedForEach { when (it) { is WasmFunction.Imported -> appendImportedFunction(it) is WasmMemory -> appendMemory(it) @@ -311,15 +312,15 @@ class WasmIrToText( else -> error("Unknown import kind ${it::class}") } } - definedFunctions.forEach { appendDefinedFunction(it) } - tables.forEach { appendTable(it) } - memories.forEach { appendMemory(it) } - globals.forEach { appendGlobal(it) } - exports.forEach { appendExport(it) } - elements.forEach { appendWasmElement(it) } + definedFunctions.indexBasedForEach { appendDefinedFunction(it) } + tables.indexBasedForEach { appendTable(it) } + memories.indexBasedForEach { appendMemory(it) } + globals.indexBasedForEach { appendGlobal(it) } + exports.indexBasedForEach { appendExport(it) } + elements.indexBasedForEach { appendWasmElement(it) } startFunction?.let { appendStartFunction(it) } - data.forEach { appendData(it) } - tags.forEach { appendTag(it) } + data.indexBasedForEach { appendData(it) } + tags.indexBasedForEach { appendTag(it) } debugInformationGenerator?.let { consumeDebugInformation(it.generateDebugInformation()) } } } @@ -330,11 +331,11 @@ class WasmIrToText( appendModuleFieldReference(type) sameLineList("func") { sameLineList("param") { - type.parameterTypes.forEach { appendType(it) } + type.parameterTypes.indexBasedForEach { appendType(it) } } if (type.resultTypes.isNotEmpty()) { sameLineList("result") { - type.resultTypes.forEach { appendType(it) } + type.resultTypes.indexBasedForEach { appendType(it) } } } } @@ -358,7 +359,7 @@ class WasmIrToText( appendModuleFieldReference(type) maybeSubType(type.superType?.owner) { sameLineList("struct") { - type.fields.forEach { + type.fields.indexBasedForEach { appendStructField(it) } } @@ -395,13 +396,13 @@ class WasmIrToText( newLineList("func") { appendModuleFieldReference(function) sameLineList("type") { appendModuleFieldReference(function.type) } - function.locals.forEach { if (it.isParameter) appendLocal(it) } + function.locals.indexBasedForEach { if (it.isParameter) appendLocal(it) } if (function.type.owner.resultTypes.isNotEmpty()) { sameLineList("result") { - function.type.owner.resultTypes.forEach { appendType(it) } + function.type.owner.resultTypes.indexBasedForEach { appendType(it) } } } - function.locals.forEach { if (!it.isParameter) appendLocal(it) } + function.locals.indexBasedForEach { if (!it.isParameter) appendLocal(it) } appendInstrList(function.instructions) } } @@ -519,7 +520,7 @@ class WasmIrToText( wasmTag.importPair?.appendImportPair() sameLineList("param") { - wasmTag.type.parameterTypes.forEach { appendType(it) } + wasmTag.type.parameterTypes.indexBasedForEach { appendType(it) } } assert(wasmTag.type.resultTypes.isEmpty()) { "must be as per spec" } } @@ -597,7 +598,7 @@ class WasmIrToText( fun appendCatch(catch: WasmImmediate.Catch) { appendElement(catch.type.mnemonic) - catch.immediates.forEach(this::appendImmediate) + catch.immediates.indexBasedForEach(this::appendImmediate) } fun appendModuleFieldReference(field: WasmSymbolReadOnly) {