Use local aliases for Kotlin runtime functions in JS BE

This commit is contained in:
Alexey Andreev
2017-07-17 15:04:48 +03:00
parent 8c256b24dc
commit 7646c2fc72
21 changed files with 539 additions and 70 deletions
@@ -359,6 +359,7 @@ class Analyzer(private val context: Context) : JsVisitor() {
private fun enterFunction(function: JsFunction, arguments: List<JsExpression>) {
functionsToEnter += function
context.addNodesForLocalVars(function.collectLocalVariables())
context.markSpecialFunctions(function.body)
for ((param, arg) in function.parameters.zip(arguments)) {
if (arg is JsFunction && arg.name == null && isProperFunctionalParameter(arg.body, param)) {
@@ -377,6 +378,7 @@ class Analyzer(private val context: Context) : JsVisitor() {
private fun enterFunctionWithGivenNodes(function: JsFunction, arguments: List<Node>) {
functionsToEnter += function
context.addNodesForLocalVars(function.collectLocalVariables())
context.markSpecialFunctions(function.body)
for ((param, arg) in function.parameters.zip(arguments)) {
val paramNode = context.nodes[param.name]!!
@@ -17,6 +17,9 @@
package org.jetbrains.kotlin.js.dce
import org.jetbrains.kotlin.js.backend.ast.*
import org.jetbrains.kotlin.js.backend.ast.metadata.SpecialFunction
import org.jetbrains.kotlin.js.backend.ast.metadata.specialFunction
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
import org.jetbrains.kotlin.js.translate.utils.jsAstUtils.array
import org.jetbrains.kotlin.js.translate.utils.jsAstUtils.index
@@ -32,6 +35,45 @@ class Context {
nodes += names.filter { it !in nodes }.associate { it to Node(it) }
}
fun markSpecialFunctions(root: JsNode) {
val candidates = mutableMapOf<JsName, SpecialFunction>()
val unsuitableNames = mutableSetOf<JsName>()
val assignedNames = mutableSetOf<JsName>()
root.accept(object : RecursiveJsVisitor() {
override fun visit(x: JsVars.JsVar) {
val name = x.name
if (!assignedNames.add(name)) {
unsuitableNames += name
}
val initializer = x.initExpression
if (initializer != null) {
val specialName = when {
isDefineInlineFunction(initializer) -> SpecialFunction.DEFINE_INLINE_FUNCTION
isWrapFunction(initializer) -> SpecialFunction.WRAP_FUNCTION
else -> null
}
specialName?.let { candidates[name] = specialName }
}
super.visit(x)
}
override fun visitBinaryExpression(x: JsBinaryOperation) {
JsAstUtils.decomposeAssignmentToVariable(x)?.let { (left, _) -> unsuitableNames += left }
}
override fun visitFunction(x: JsFunction) {
x.name?.let { unsuitableNames += it }
}
})
for ((name, function) in candidates) {
if (name !in unsuitableNames) {
name.specialFunction = function
}
}
}
fun extractNode(expression: JsExpression): Node? {
val node = extractNodeImpl(expression)?.original
return if (node != null && moduleExportsNode in generateSequence(node) { it.qualifier?.parent }) {
@@ -18,10 +18,7 @@ package org.jetbrains.kotlin.js.dce
import com.google.gwt.dev.js.rhino.CodePosition
import com.google.gwt.dev.js.rhino.ErrorReporter
import org.jetbrains.kotlin.js.backend.ast.JsBlock
import org.jetbrains.kotlin.js.backend.ast.JsGlobalBlock
import org.jetbrains.kotlin.js.backend.ast.JsNode
import org.jetbrains.kotlin.js.backend.ast.JsProgram
import org.jetbrains.kotlin.js.backend.ast.*
import org.jetbrains.kotlin.js.dce.Context.Node
import org.jetbrains.kotlin.js.inline.util.collectDefinedNames
import org.jetbrains.kotlin.js.inline.util.fixForwardNameReferences
@@ -17,6 +17,8 @@
package org.jetbrains.kotlin.js.dce
import org.jetbrains.kotlin.js.backend.ast.*
import org.jetbrains.kotlin.js.backend.ast.metadata.SpecialFunction
import org.jetbrains.kotlin.js.backend.ast.metadata.specialFunction
import org.jetbrains.kotlin.js.dce.Context.Node
fun Context.isObjectDefineProperty(function: JsExpression) = isObjectFunction(function, "defineProperty")
@@ -25,9 +27,11 @@ fun Context.isObjectGetOwnPropertyDescriptor(function: JsExpression) = isObjectF
fun Context.isDefineModule(function: JsExpression): Boolean = isKotlinFunction(function, "defineModule")
fun Context.isDefineInlineFunction(function: JsExpression): Boolean = isKotlinFunction(function, "defineInlineFunction")
fun Context.isDefineInlineFunction(function: JsExpression): Boolean =
isKotlinFunction(function, "defineInlineFunction") || isSpecialFunction(function, SpecialFunction.DEFINE_INLINE_FUNCTION)
fun Context.isWrapFunction(function: JsExpression): Boolean = isKotlinFunction(function, "wrapFunction")
fun Context.isWrapFunction(function: JsExpression): Boolean =
isKotlinFunction(function, "wrapFunction") || isSpecialFunction(function, SpecialFunction.WRAP_FUNCTION)
fun Context.isObjectFunction(function: JsExpression, functionName: String): Boolean {
if (function !is JsNameRef) return false
@@ -45,6 +49,9 @@ fun Context.isKotlinFunction(function: JsExpression, name: String): Boolean {
return receiver in nodes && receiver.ident.toLowerCase() == "kotlin"
}
fun isSpecialFunction(expr: JsExpression, specialFunction: SpecialFunction): Boolean =
expr is JsNameRef && expr.qualifier == null && expr.name?.specialFunction == specialFunction
fun Context.isAmdDefine(function: JsExpression): Boolean = isTopLevelFunction(function, "define")
fun Context.isTopLevelFunction(function: JsExpression, name: String): Boolean {