[K/JS] Add VOID optimization on object properties + align with the optimization the JS Plain Object plugin
This commit is contained in:
@@ -77,6 +77,7 @@ var JsFunction.functionDescriptor: FunctionDescriptor? by MetadataProperty(defau
|
||||
*/
|
||||
var JsReturn.returnTarget: FunctionDescriptor? by MetadataProperty(default = null)
|
||||
|
||||
var HasMetadata.constant: Boolean by MetadataProperty(default = false)
|
||||
var HasMetadata.synthetic: Boolean by MetadataProperty(default = false)
|
||||
|
||||
var HasMetadata.isInlineClassBoxing: Boolean by MetadataProperty(default = false)
|
||||
|
||||
@@ -17,8 +17,9 @@
|
||||
package org.jetbrains.kotlin.js.inline.clean
|
||||
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsFunction
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsName
|
||||
|
||||
class FunctionPostProcessor(val root: JsFunction) {
|
||||
class FunctionPostProcessor(val root: JsFunction, private val voidName: JsName? = null) {
|
||||
val optimizations = listOf(
|
||||
{ RedundantLabelRemoval(root.body).apply() },
|
||||
{ EmptyStatementElimination(root.body).apply() },
|
||||
@@ -32,7 +33,8 @@ class FunctionPostProcessor(val root: JsFunction) {
|
||||
{ RedundantStatementElimination(root).apply() },
|
||||
{ CoroutineStateElimination(root.body).apply() },
|
||||
{ BoxingUnboxingElimination(root.body).apply() },
|
||||
{ MoveTemporaryVariableDeclarationToAssignment(root.body).apply() }
|
||||
{ MoveTemporaryVariableDeclarationToAssignment(root.body).apply() },
|
||||
{ voidName?.let { VoidPropertiesElimination(root.body, voidName).apply() } ?: false }
|
||||
)
|
||||
// TODO: reduce to A || B, A && B if possible
|
||||
|
||||
|
||||
+15
-16
@@ -17,10 +17,7 @@
|
||||
package org.jetbrains.kotlin.js.inline.clean
|
||||
|
||||
import org.jetbrains.kotlin.js.backend.ast.*
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.SideEffectKind
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.imported
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.sideEffects
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.synthetic
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.*
|
||||
import org.jetbrains.kotlin.js.inline.util.collectFreeVariables
|
||||
import org.jetbrains.kotlin.js.inline.util.collectLocalVariables
|
||||
import org.jetbrains.kotlin.js.translate.context.Namer
|
||||
@@ -481,8 +478,8 @@ internal class TemporaryVariableElimination(private val function: JsFunction) {
|
||||
|
||||
override fun visitNameRef(nameRef: JsNameRef) {
|
||||
val name = nameRef.name
|
||||
if (name != null && name in localVariables) {
|
||||
if (name !in namesToSubstitute && shouldConsiderTemporary(name)) {
|
||||
if (name != null && (name in localVariables || name.constant)) {
|
||||
if (name.constant || (name !in namesToSubstitute && shouldConsiderTemporary(name))) {
|
||||
if (!sideEffectOccurred) {
|
||||
substitutableVariableReferences += name
|
||||
}
|
||||
@@ -637,16 +634,18 @@ internal class TemporaryVariableElimination(private val function: JsFunction) {
|
||||
private fun isTrivial(expr: JsExpression): Boolean = when (expr) {
|
||||
is JsNameRef -> {
|
||||
val qualifier = expr.qualifier
|
||||
if (expr.sideEffects == SideEffectKind.PURE && (qualifier == null || isTrivial(qualifier))) {
|
||||
expr.name !in temporary
|
||||
}
|
||||
else {
|
||||
val name = expr.name
|
||||
name in localVariables && when (definitions[name]) {
|
||||
// Local variables with zero definitions are function parameters. We can relocate and copy them.
|
||||
null, 0 -> true
|
||||
1 -> name !in namesToSubstitute || definedValues[name]?.let { isTrivial(it) } ?: false
|
||||
else -> false
|
||||
when {
|
||||
expr.name?.constant == true -> true
|
||||
expr.sideEffects == SideEffectKind.PURE && (qualifier == null || isTrivial(qualifier)) ->
|
||||
expr.name !in temporary
|
||||
else -> {
|
||||
val name = expr.name
|
||||
name in localVariables && when (definitions[name]) {
|
||||
// Local variables with zero definitions are function parameters. We can relocate and copy them.
|
||||
null, 0 -> true
|
||||
1 -> name !in namesToSubstitute || definedValues[name]?.let { isTrivial(it) } ?: false
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.js.inline.clean
|
||||
|
||||
import org.jetbrains.kotlin.js.backend.ast.*
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.isInlineClassBoxing
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.isInlineClassUnboxing
|
||||
|
||||
// Replaces { a: 2, b: VOID, c: VOID } with { a: 2 }
|
||||
class VoidPropertiesElimination(private val root: JsBlock, private val voidName: JsName) {
|
||||
private var changed = false
|
||||
|
||||
fun apply(): Boolean {
|
||||
val visitor = object : JsVisitorWithContextImpl() {
|
||||
override fun endVisit(x: JsPropertyInitializer, ctx: JsContext<JsNode>) {
|
||||
super.endVisit(x, ctx)
|
||||
if ((x.valueExpr as? JsNameRef)?.name === voidName) {
|
||||
ctx.removeMe()
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
visitor.accept(root)
|
||||
|
||||
return changed
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user