[K/JS] Rework IR deserialization and lowering phases to consume less memory

This commit is contained in:
Artem Kobzar
2023-04-19 13:10:19 +00:00
committed by Space Team
parent 1ee2d0814c
commit 33c5068b79
134 changed files with 964 additions and 616 deletions
@@ -0,0 +1,49 @@
/*
* 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.utils
inline fun <reified R, C : MutableCollection<in R>> Iterable<*>.filterIsInstanceAndTo(destination: C, predicate: (R) -> Boolean): C {
for (element in this) {
if (element is R && predicate(element)) {
destination.add(element)
}
}
return destination
}
inline fun <reified T, reified R, C : MutableCollection<in R>> Iterable<*>.filterIsInstanceMapTo(destination: C, transform: (T) -> R): C {
for (element in this) {
if (element is T) {
destination.add(transform(element))
}
}
return destination
}
inline fun <reified T, reified R> Collection<*>.filterIsInstanceMapNotNull(transform: (T) -> R?): Collection<R> {
if (isEmpty()) return emptyList()
return filterIsInstanceMapNotNullTo(SmartList(), transform)
}
inline fun <reified R> Collection<*>.filterIsInstanceAnd(predicate: (R) -> Boolean): List<R> {
if (isEmpty()) return emptyList()
return filterIsInstanceAndTo(SmartList(), predicate)
}
inline fun <reified T, reified R, C : MutableCollection<in R>> Iterable<*>.filterIsInstanceMapNotNullTo(
destination: C,
transform: (T) -> R?
): C {
for (element in this) {
if (element is T) {
val result = transform(element)
if (result != null) {
destination.add(result)
}
}
}
return destination
}
@@ -0,0 +1,146 @@
/*
* 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.utils
import java.util.*
import kotlin.math.min
/**
* A memory-optimized version of [Iterable.map].
* @see Iterable.map
*/
inline fun <T, R> Collection<T>.memoryOptimizedMap(transform: (T) -> R): List<R> {
return mapTo(ArrayList<R>(size), transform).compactIfPossible()
}
/**
* A memory-optimized version of [Iterable.mapIndexed].
* @see Iterable.mapIndexed
*/
inline fun <T, R> Collection<T>.memoryOptimizedMapIndexed(transform: (index: Int, T) -> R): List<R> {
return mapIndexedTo(ArrayList<R>(size), transform).compactIfPossible()
}
/**
* A memory-optimized version of [Iterable.mapNotNull].
* @see Iterable.mapNotNull
*/
inline fun <T, R : Any> Collection<T>.memoryOptimizedMapNotNull(transform: (T) -> R?): List<R> {
return mapNotNullTo(ArrayList(), transform).compactIfPossible()
}
/**
* A memory-optimized version of [Iterable.flatMap].
* @see Iterable.flatMap
*/
inline fun <T, R> Collection<T>.memoryOptimizedFlatMap(transform: (T) -> Iterable<R>): List<R> {
return flatMapTo(ArrayList<R>(), transform).compactIfPossible()
}
/**
* A memory-optimized version of [Iterable.filter].
* @see Iterable.filter
*/
inline fun <T> Collection<T>.memoryOptimizedFilter(predicate: (T) -> Boolean): List<T> {
return filterTo(ArrayList(), predicate).compactIfPossible()
}
/**
* A memory-optimized version of [Iterable.filterNot].
* @see Iterable.filterNot
*/
inline fun <T> Collection<T>.memoryOptimizedFilterNot(predicate: (T) -> Boolean): List<T> {
return filterNotTo(ArrayList(), predicate).compactIfPossible()
}
/**
* A memory-optimized version of [Iterable.filterIsInstance].
* @see Iterable.filterIsInstance
*/
inline fun <reified T> Collection<*>.memoryOptimizedFilterIsInstance(): List<T> {
return filterIsInstanceTo(ArrayList<T>()).compactIfPossible()
}
/**
* A memory-optimized version of [Iterable.plus].
* @see Iterable.plus
*/
infix fun <T> List<T>.memoryOptimizedPlus(elements: List<T>): List<T> =
when (val resultSize = size + elements.size) {
0 -> emptyList()
1 -> Collections.singletonList(if (isEmpty()) elements.first() else first())
else -> ArrayList<T>(resultSize).also {
it.addAll(this)
it.addAll(elements)
}
}
/**
* A memory-optimized version of [Iterable.plus].
* @see Iterable.plus
*/
infix fun <T> List<T>.memoryOptimizedPlus(element: T): List<T> =
when (size) {
0 -> Collections.singletonList(element)
else -> ArrayList<T>(size + 1).also {
it.addAll(this)
it.add(element)
}
}
/**
* A memory-optimized version of [Iterable.zip].
* @see Iterable.zip
*/
infix fun <T, R> Collection<T>.memoryOptimizedZip(other: Collection<R>): List<Pair<T, R>> {
return when {
isEmpty() || other.isEmpty() -> emptyList()
min(size, other.size) == 1 -> listOf(first() to other.first())
else -> zip(other) { t1, t2 -> t1 to t2 }
}
}
/**
* [Sequence] variant of [org.jetbrains.kotlin.backend.common.atMostOne]
* So, when:
* - there is no element then `null` will be returned
* - there is a single element then the element will be returned
* - there is more than one element then the error will be thrown
* @see org.jetbrains.kotlin.backend.common.atMostOne
*/
fun <T> Sequence<T>.atMostOne(): T? {
val iterator = iterator()
if (!iterator.hasNext()) return null
val single = iterator.next()
if (iterator.hasNext()) {
throw IllegalArgumentException("Sequence has more than one element.")
}
return single
}
/**
* The variant of [org.jetbrains.kotlin.util.collectionUtils.filterIsInstanceAnd] extension function but to find the first element
* which is an instance of type [T] and satisfies [predicate] condition
* @see org.jetbrains.kotlin.util.collectionUtils.filterIsInstanceAnd
*/
inline fun <reified T> Iterable<*>.findIsInstanceAnd(predicate: (T) -> Boolean): T? {
for (element in this) {
if (element is T && predicate(element)) {
return element
}
}
return null
}
/**
* The same as [Collection.toMutableList] extension function, but it returns a SmartList which is better with in sense of memory consumption
* @see Collection.toMutableList
*/
fun <T> Collection<T>.toSmartList(): List<T> = SmartList<T>(this)
@@ -86,6 +86,21 @@ fun <T> ArrayList<T>.compact(): List<T> =
else -> apply { trimToSize() }
}
/**
* The same as [org.jetbrains.kotlin.utils.compact] extension function, but it could be used with the
* immutable list type (without [java.util.ArrayList.trimToSize] for the collections with more than 1 element)
* @see org.jetbrains.kotlin.utils.compact
*/
fun <T> List<T>.compactIfPossible(): List<T> =
when (size) {
0 -> emptyList()
1 -> listOf(first())
else -> apply {
if (this is ArrayList<*>) trimToSize()
}
}
fun <T> List<T>.indexOfFirst(startFrom: Int, predicate: (T) -> Boolean): Int {
for (index in startFrom..lastIndex) {
if (predicate(this[index])) return index