From ea34e10b67ee3538924bb8f32ea80d460c2847a7 Mon Sep 17 00:00:00 2001 From: Alexander Korepanov Date: Thu, 25 Aug 2022 17:06:28 +0200 Subject: [PATCH] [JS IR] Optimize JS AST scopes memory consumption --- .../backend/js/utils/JsGenerationContext.kt | 13 ++++++++----- .../kotlin/js/backend/ast/JsScope.java | 6 ++++-- .../kotlin/js/backend/ast/jsScopes.kt | 19 ++++++++++++------- 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/JsGenerationContext.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/JsGenerationContext.kt index ca8d95431be..9e5e54986da 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/JsGenerationContext.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/JsGenerationContext.kt @@ -14,13 +14,16 @@ import org.jetbrains.kotlin.js.backend.ast.JsLocation import org.jetbrains.kotlin.js.backend.ast.JsName import org.jetbrains.kotlin.js.backend.ast.JsScope -val emptyScope: JsScope - get() = object : JsScope("nil") { - override fun doCreateName(ident: String): JsName { - error("Trying to create name in empty scope") - } +val emptyScope: JsScope = object : JsScope("nil") { + override fun doCreateName(ident: String): JsName { + error("Trying to create name in empty scope") } + override fun copyOwnNames(other: JsScope?) { + error("Trying to copy names to empty scope") + } +} + class JsGenerationContext( val currentFile: IrFile, val currentFunction: IrFunction?, diff --git a/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsScope.java b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsScope.java index b909eef7eca..fb6ea35c3bc 100644 --- a/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsScope.java +++ b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsScope.java @@ -154,8 +154,10 @@ public abstract class JsScope { } public void copyOwnNames(JsScope other) { - names = new HashMap<>(names); - names.putAll(other.names); + if (!other.names.isEmpty()) { + names = new HashMap<>(names); + names.putAll(other.names); + } } @NotNull diff --git a/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/jsScopes.kt b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/jsScopes.kt index 30fcc37a777..70972936715 100644 --- a/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/jsScopes.kt +++ b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/jsScopes.kt @@ -17,7 +17,7 @@ package org.jetbrains.kotlin.js.backend.ast import org.jetbrains.kotlin.js.common.RESERVED_KEYWORDS -import java.util.* +import kotlin.collections.ArrayList class JsObjectScope(parent: JsScope, description: String) : JsScope(parent, description) @@ -32,21 +32,26 @@ open class JsFunctionScope(parent: JsScope, description: String) : JsDeclaration } open class JsDeclarationScope(parent: JsScope, description: String, useParentScopeStack: Boolean = false) : JsScope(parent, description) { - private val labelScopes: Stack = - if (parent is JsDeclarationScope && useParentScopeStack) parent.labelScopes else Stack() + private var labelScopesImpl: ArrayList? = + if (parent is JsDeclarationScope && useParentScopeStack) parent.labelScopesImpl else null private val topLabelScope - get() = if (labelScopes.isNotEmpty()) labelScopes.peek() else null + get() = labelScopesImpl?.let { if (it.isNotEmpty()) it.last() else null } + + private val labelScopes: ArrayList + get() = labelScopesImpl ?: ArrayList().also { labelScopesImpl = it } open fun enterLabel(label: String, outputName: String): JsName { val scope = LabelScope(topLabelScope, label, outputName) - labelScopes.push(scope) + labelScopes.add(scope) return scope.labelName } open fun exitLabel() { - assert(labelScopes.isNotEmpty()) { "No scope to exit from" } - labelScopes.pop() + labelScopes.let { + assert(it.isNotEmpty()) { "No scope to exit from" } + it.removeLast() + } } open fun findLabel(label: String): JsName? =