From 7aaba3b78add36e0d5f1d1fbbcc58e9beaa15bed Mon Sep 17 00:00:00 2001 From: deotime <89555032+DeoTimeTheGithubUser@users.noreply.github.com> Date: Wed, 5 Apr 2023 13:18:11 -0500 Subject: [PATCH] [KT-57607] Fix performance of ArrayList.addAll methods in JS stdlib (#5116) * Fix performance of ArrayList.addAll methods in JS stdlib: extend the backing array and copy elements manually * Update expected reachable nodes after DCE in test data --------- Co-authored-by: Ilya Gorbunov --- .../multiModule/privateInterfaceNameClash.kt | 2 +- .../js/src/kotlin/collections/ArrayList.kt | 22 ++++++++++++++----- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/js/js.translator/testData/box/multiModule/privateInterfaceNameClash.kt b/js/js.translator/testData/box/multiModule/privateInterfaceNameClash.kt index dab0b9f07c6..e2d89a0cbe6 100644 --- a/js/js.translator/testData/box/multiModule/privateInterfaceNameClash.kt +++ b/js/js.translator/testData/box/multiModule/privateInterfaceNameClash.kt @@ -1,6 +1,6 @@ // IGNORE_FIR // KJS_WITH_FULL_RUNTIME -// EXPECTED_REACHABLE_NODES: 1819 +// EXPECTED_REACHABLE_NODES: 2002 // MODULE: lib1 // FILE: lib1.kt package lib1 diff --git a/libraries/stdlib/js/src/kotlin/collections/ArrayList.kt b/libraries/stdlib/js/src/kotlin/collections/ArrayList.kt index 9689eaaf13a..fddcc6dce76 100644 --- a/libraries/stdlib/js/src/kotlin/collections/ArrayList.kt +++ b/libraries/stdlib/js/src/kotlin/collections/ArrayList.kt @@ -67,11 +67,20 @@ public actual open class ArrayList internal constructor(private var array: Ar modCount++ } + private fun increaseLength(amount: Int): Int { + val previous = size + array.asDynamic().length = size + amount + return previous + } + actual override fun addAll(elements: Collection): Boolean { checkIsMutable() if (elements.isEmpty()) return false - array += elements.toTypedArray() + val offset = increaseLength(elements.size) + elements.forEachIndexed { index, element -> + array[offset + index] = element + } modCount++ return true } @@ -82,10 +91,13 @@ public actual open class ArrayList internal constructor(private var array: Ar if (index == size) return addAll(elements) if (elements.isEmpty()) return false - when (index) { - size -> return addAll(elements) - 0 -> array = elements.toTypedArray() + array - else -> array = array.copyOfRange(0, index).asDynamic().concat(elements.toTypedArray(), array.copyOfRange(index, size)) + + val tail = array.asDynamic().splice(index).unsafeCast>() + addAll(elements) + + val offset = increaseLength(tail.size) + repeat(tail.size) { tailIndex -> + array[offset + tailIndex] = tail[tailIndex] } modCount++