JS/Inlining: change sideEffects metadata to take three values: producing side effect, dependding on side effect and purity
This commit is contained in:
+7
-1
@@ -55,7 +55,7 @@ var JsReturn.returnTarget: FunctionDescriptor? by MetadataProperty(default = nul
|
|||||||
|
|
||||||
var HasMetadata.synthetic: Boolean by MetadataProperty(default = false)
|
var HasMetadata.synthetic: Boolean by MetadataProperty(default = false)
|
||||||
|
|
||||||
var HasMetadata.sideEffects: Boolean by MetadataProperty(default = true)
|
var HasMetadata.sideEffects: SideEffectKind by MetadataProperty(default = SideEffectKind.AFFECTS_STATE)
|
||||||
|
|
||||||
enum class TypeCheck {
|
enum class TypeCheck {
|
||||||
TYPEOF,
|
TYPEOF,
|
||||||
@@ -64,3 +64,9 @@ enum class TypeCheck {
|
|||||||
IS_ANY,
|
IS_ANY,
|
||||||
AND_PREDICATE
|
AND_PREDICATE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class SideEffectKind {
|
||||||
|
AFFECTS_STATE,
|
||||||
|
DEPENDS_ON_STATE,
|
||||||
|
PURE
|
||||||
|
}
|
||||||
@@ -17,10 +17,7 @@
|
|||||||
package org.jetbrains.kotlin.js.inline
|
package org.jetbrains.kotlin.js.inline
|
||||||
|
|
||||||
import com.google.dart.compiler.backend.js.ast.*
|
import com.google.dart.compiler.backend.js.ast.*
|
||||||
import com.google.dart.compiler.backend.js.ast.metadata.HasMetadata
|
import com.google.dart.compiler.backend.js.ast.metadata.*
|
||||||
import com.google.dart.compiler.backend.js.ast.metadata.sideEffects
|
|
||||||
import com.google.dart.compiler.backend.js.ast.metadata.staticRef
|
|
||||||
import com.google.dart.compiler.backend.js.ast.metadata.synthetic
|
|
||||||
import com.intellij.util.SmartList
|
import com.intellij.util.SmartList
|
||||||
import org.jetbrains.kotlin.js.inline.util.IdentitySet
|
import org.jetbrains.kotlin.js.inline.util.IdentitySet
|
||||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.*
|
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.*
|
||||||
@@ -270,7 +267,7 @@ internal class ExpressionDecomposer private constructor(
|
|||||||
// Qualifier might be a reference to lambda property. See KT-7674
|
// Qualifier might be a reference to lambda property. See KT-7674
|
||||||
// An exception here is `fn.call()`, which are marked as side effect free. Further recognition of such
|
// An exception here is `fn.call()`, which are marked as side effect free. Further recognition of such
|
||||||
// case in inliner might be quite difficult, so never extract such call (and other calls marked this way).
|
// case in inliner might be quite difficult, so never extract such call (and other calls marked this way).
|
||||||
if (qualifier in containsNodeWithSideEffect && (qualifier as? HasMetadata)?.sideEffects ?: true) {
|
if (qualifier in containsNodeWithSideEffect && (qualifier as? HasMetadata)?.sideEffects != SideEffectKind.PURE) {
|
||||||
qualifier = qualifier.extractToTemporary()
|
qualifier = qualifier.extractToTemporary()
|
||||||
}
|
}
|
||||||
else if (callee != null && receiver != null && receiver in containsNodeWithSideEffect) {
|
else if (callee != null && receiver != null && receiver in containsNodeWithSideEffect) {
|
||||||
|
|||||||
+6
-5
@@ -17,6 +17,7 @@
|
|||||||
package org.jetbrains.kotlin.js.inline.clean
|
package org.jetbrains.kotlin.js.inline.clean
|
||||||
|
|
||||||
import com.google.dart.compiler.backend.js.ast.*
|
import com.google.dart.compiler.backend.js.ast.*
|
||||||
|
import com.google.dart.compiler.backend.js.ast.metadata.SideEffectKind
|
||||||
import com.google.dart.compiler.backend.js.ast.metadata.sideEffects
|
import com.google.dart.compiler.backend.js.ast.metadata.sideEffects
|
||||||
import com.google.dart.compiler.backend.js.ast.metadata.synthetic
|
import com.google.dart.compiler.backend.js.ast.metadata.synthetic
|
||||||
import org.jetbrains.kotlin.js.inline.util.collectLocalVariables
|
import org.jetbrains.kotlin.js.inline.util.collectLocalVariables
|
||||||
@@ -53,7 +54,7 @@ class IneffectiveStatementElimination(private val root: JsFunction) {
|
|||||||
if (expression.name in localVars) {
|
if (expression.name in localVars) {
|
||||||
listOf()
|
listOf()
|
||||||
}
|
}
|
||||||
else if (!expression.sideEffects) {
|
else if (expression.sideEffects != SideEffectKind.AFFECTS_STATE) {
|
||||||
val qualifier = expression.qualifier
|
val qualifier = expression.qualifier
|
||||||
if (qualifier != null) replace(qualifier) else listOf()
|
if (qualifier != null) replace(qualifier) else listOf()
|
||||||
}
|
}
|
||||||
@@ -78,7 +79,7 @@ class IneffectiveStatementElimination(private val root: JsFunction) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
is JsBinaryOperation -> {
|
is JsBinaryOperation -> {
|
||||||
if (expression.sideEffects) {
|
if (expression.sideEffects == SideEffectKind.AFFECTS_STATE) {
|
||||||
when (expression.operator) {
|
when (expression.operator) {
|
||||||
JsBinaryOperator.BIT_AND,
|
JsBinaryOperator.BIT_AND,
|
||||||
JsBinaryOperator.BIT_OR,
|
JsBinaryOperator.BIT_OR,
|
||||||
@@ -130,7 +131,7 @@ class IneffectiveStatementElimination(private val root: JsFunction) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
is JsInvocation -> {
|
is JsInvocation -> {
|
||||||
if (!expression.sideEffects) {
|
if (expression.sideEffects != SideEffectKind.AFFECTS_STATE) {
|
||||||
replace(expression.qualifier) + replaceMany(expression.arguments)
|
replace(expression.qualifier) + replaceMany(expression.arguments)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -139,7 +140,7 @@ class IneffectiveStatementElimination(private val root: JsFunction) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
is JsNew -> {
|
is JsNew -> {
|
||||||
if (!expression.sideEffects) {
|
if (expression.sideEffects != SideEffectKind.AFFECTS_STATE) {
|
||||||
replace(expression.constructorExpression) + replaceMany(expression.arguments)
|
replace(expression.constructorExpression) + replaceMany(expression.arguments)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -166,7 +167,7 @@ class IneffectiveStatementElimination(private val root: JsFunction) {
|
|||||||
// Then, inlined body of `bar` never uses `$tmp`, therefore we can eliminate it, so `Kotlin.modules['foo']` remains.
|
// Then, inlined body of `bar` never uses `$tmp`, therefore we can eliminate it, so `Kotlin.modules['foo']` remains.
|
||||||
// It's good to eliminate such useless expression.
|
// It's good to eliminate such useless expression.
|
||||||
is JsArrayAccess -> {
|
is JsArrayAccess -> {
|
||||||
if (!expression.sideEffects) {
|
if (expression.sideEffects != SideEffectKind.AFFECTS_STATE) {
|
||||||
replace(expression.arrayExpression) + replace(expression.indexExpression)
|
replace(expression.arrayExpression) + replace(expression.indexExpression)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
+16
-9
@@ -17,6 +17,7 @@
|
|||||||
package org.jetbrains.kotlin.js.inline.clean
|
package org.jetbrains.kotlin.js.inline.clean
|
||||||
|
|
||||||
import com.google.dart.compiler.backend.js.ast.*
|
import com.google.dart.compiler.backend.js.ast.*
|
||||||
|
import com.google.dart.compiler.backend.js.ast.metadata.SideEffectKind
|
||||||
import com.google.dart.compiler.backend.js.ast.metadata.sideEffects
|
import com.google.dart.compiler.backend.js.ast.metadata.sideEffects
|
||||||
import com.google.dart.compiler.backend.js.ast.metadata.synthetic
|
import com.google.dart.compiler.backend.js.ast.metadata.synthetic
|
||||||
import org.jetbrains.kotlin.js.inline.util.collectFreeVariables
|
import org.jetbrains.kotlin.js.inline.util.collectFreeVariables
|
||||||
@@ -180,14 +181,14 @@ internal class TemporaryVariableElimination(function: JsFunction) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
super.visitNameRef(nameRef)
|
super.visitNameRef(nameRef)
|
||||||
if (nameRef.qualifier != null && nameRef.sideEffects) {
|
if (nameRef.qualifier != null && nameRef.sideEffects == SideEffectKind.AFFECTS_STATE) {
|
||||||
sideEffectOccurred = true
|
sideEffectOccurred = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitInvocation(invocation: JsInvocation) {
|
override fun visitInvocation(invocation: JsInvocation) {
|
||||||
super.visitInvocation(invocation)
|
super.visitInvocation(invocation)
|
||||||
if (invocation.sideEffects) {
|
if (invocation.sideEffects == SideEffectKind.AFFECTS_STATE) {
|
||||||
sideEffectOccurred = true
|
sideEffectOccurred = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -242,7 +243,7 @@ internal class TemporaryVariableElimination(function: JsFunction) {
|
|||||||
|
|
||||||
override fun visitArrayAccess(x: JsArrayAccess) {
|
override fun visitArrayAccess(x: JsArrayAccess) {
|
||||||
super.visitArrayAccess(x)
|
super.visitArrayAccess(x)
|
||||||
if (x.sideEffects) {
|
if (x.sideEffects == SideEffectKind.AFFECTS_STATE) {
|
||||||
sideEffectOccurred = true
|
sideEffectOccurred = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -533,15 +534,21 @@ internal class TemporaryVariableElimination(function: JsFunction) {
|
|||||||
|
|
||||||
private fun isTrivial(expr: JsExpression): Boolean = when (expr) {
|
private fun isTrivial(expr: JsExpression): Boolean = when (expr) {
|
||||||
is JsNameRef -> {
|
is JsNameRef -> {
|
||||||
val name = expr.name
|
val qualifier = expr.qualifier
|
||||||
name in namesToProcess && when (definitions[name]) {
|
if (expr.sideEffects == SideEffectKind.PURE && (qualifier == null || isTrivial(qualifier))) {
|
||||||
null, 0 -> true
|
true
|
||||||
1 -> name !in namesToSubstitute || definedValues[name]?.let { isTrivial(it) } ?: false
|
}
|
||||||
else -> false
|
else {
|
||||||
|
val name = expr.name
|
||||||
|
name in namesToProcess && when (definitions[name]) {
|
||||||
|
null, 0 -> true
|
||||||
|
1 -> name !in namesToSubstitute || definedValues[name]?.let { isTrivial(it) } ?: false
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is JsLiteral.JsValueLiteral -> true
|
is JsLiteral.JsValueLiteral -> true
|
||||||
is JsInvocation -> !expr.sideEffects && isTrivial(expr.qualifier) && expr.arguments.all { isTrivial(it) }
|
is JsInvocation -> expr.sideEffects == SideEffectKind.PURE && isTrivial(expr.qualifier) && expr.arguments.all { isTrivial(it) }
|
||||||
is JsArrayAccess -> isTrivial(expr.arrayExpression) && isTrivial(expr.indexExpression)
|
is JsArrayAccess -> isTrivial(expr.arrayExpression) && isTrivial(expr.indexExpression)
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.js.inline.util
|
|||||||
|
|
||||||
import com.google.dart.compiler.backend.js.ast.*
|
import com.google.dart.compiler.backend.js.ast.*
|
||||||
import com.google.dart.compiler.backend.js.ast.metadata.HasMetadata
|
import com.google.dart.compiler.backend.js.ast.metadata.HasMetadata
|
||||||
|
import com.google.dart.compiler.backend.js.ast.metadata.SideEffectKind
|
||||||
import com.google.dart.compiler.backend.js.ast.metadata.sideEffects
|
import com.google.dart.compiler.backend.js.ast.metadata.sideEffects
|
||||||
import org.jetbrains.kotlin.js.translate.utils.jsAstUtils.any
|
import org.jetbrains.kotlin.js.translate.utils.jsAstUtils.any
|
||||||
|
|
||||||
@@ -28,7 +29,7 @@ fun JsExpression.canHaveOwnSideEffect(vars: Set<JsName>) = when (this) {
|
|||||||
is JsConditional,
|
is JsConditional,
|
||||||
is JsLiteral -> false
|
is JsLiteral -> false
|
||||||
is JsBinaryOperation -> operator.isAssignment
|
is JsBinaryOperation -> operator.isAssignment
|
||||||
is JsNameRef -> name !in vars && sideEffects
|
is JsNameRef -> name !in vars && sideEffects != SideEffectKind.PURE
|
||||||
is HasMetadata -> sideEffects
|
is HasMetadata -> sideEffects != SideEffectKind.PURE
|
||||||
else -> true
|
else -> true
|
||||||
}
|
}
|
||||||
|
|||||||
+12
@@ -257,6 +257,18 @@ public class InlineEvaluationOrderTestGenerated extends AbstractInlineEvaluation
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("propertyAccessAfterModification.kt")
|
||||||
|
public void testPropertyAccessAfterModification() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/inlineEvaluationOrder/cases/propertyAccessAfterModification.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("propertyAccessAndInitializer.kt")
|
||||||
|
public void testPropertyAccessAndInitializer() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/inlineEvaluationOrder/cases/propertyAccessAndInitializer.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("propertyAccessWithSideEffect.kt")
|
@TestMetadata("propertyAccessWithSideEffect.kt")
|
||||||
public void testPropertyAccessWithSideEffect() throws Exception {
|
public void testPropertyAccessWithSideEffect() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/inlineEvaluationOrder/cases/propertyAccessWithSideEffect.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/inlineEvaluationOrder/cases/propertyAccessWithSideEffect.kt");
|
||||||
|
|||||||
+2
-1
@@ -20,6 +20,7 @@ import com.google.dart.compiler.backend.js.ast.JsEmptyExpression
|
|||||||
import com.google.dart.compiler.backend.js.ast.JsExpression
|
import com.google.dart.compiler.backend.js.ast.JsExpression
|
||||||
import com.google.dart.compiler.backend.js.ast.JsName
|
import com.google.dart.compiler.backend.js.ast.JsName
|
||||||
import com.google.dart.compiler.backend.js.ast.metadata.HasMetadata
|
import com.google.dart.compiler.backend.js.ast.metadata.HasMetadata
|
||||||
|
import com.google.dart.compiler.backend.js.ast.metadata.SideEffectKind
|
||||||
import com.google.dart.compiler.backend.js.ast.metadata.sideEffects
|
import com.google.dart.compiler.backend.js.ast.metadata.sideEffects
|
||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
@@ -76,7 +77,7 @@ fun VariableAccessInfo.constructAccessExpression(ref: JsExpression): JsExpressio
|
|||||||
return ref
|
return ref
|
||||||
} else {
|
} else {
|
||||||
return if (value !is JsEmptyExpression) {
|
return if (value !is JsEmptyExpression) {
|
||||||
(ref as? HasMetadata)?.let { it.sideEffects = false }
|
(ref as? HasMetadata)?.let { it.sideEffects = SideEffectKind.PURE }
|
||||||
JsAstUtils.assignment(ref, value!!)
|
JsAstUtils.assignment(ref, value!!)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
+5
-5
@@ -25,7 +25,7 @@ import org.jetbrains.kotlin.js.translate.operation.OperatorTable
|
|||||||
import org.jetbrains.kotlin.js.translate.reference.CallArgumentTranslator
|
import org.jetbrains.kotlin.js.translate.reference.CallArgumentTranslator
|
||||||
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
|
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
|
||||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.fqnWithoutSideEffects
|
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.pureFqn
|
||||||
import org.jetbrains.kotlin.js.translate.utils.PsiUtils
|
import org.jetbrains.kotlin.js.translate.utils.PsiUtils
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
@@ -59,7 +59,7 @@ object DefaultFunctionCallCase : FunctionCallCase() {
|
|||||||
if (isNative && hasSpreadOperator) {
|
if (isNative && hasSpreadOperator) {
|
||||||
return nativeSpreadFunWithDispatchOrExtensionReceiver(argumentsInfo, functionName)
|
return nativeSpreadFunWithDispatchOrExtensionReceiver(argumentsInfo, functionName)
|
||||||
}
|
}
|
||||||
return JsInvocation(fqnWithoutSideEffects(functionName, dispatchReceiver), argumentsInfo.translateArguments)
|
return JsInvocation(pureFqn(functionName, dispatchReceiver), argumentsInfo.translateArguments)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun buildDefaultCallWithoutReceiver(context: TranslationContext,
|
fun buildDefaultCallWithoutReceiver(context: TranslationContext,
|
||||||
@@ -78,7 +78,7 @@ object DefaultFunctionCallCase : FunctionCallCase() {
|
|||||||
|
|
||||||
val functionRef = context.aliasOrValue(callableDescriptor) {
|
val functionRef = context.aliasOrValue(callableDescriptor) {
|
||||||
val qualifierForFunction = context.getQualifierForDescriptor(it)
|
val qualifierForFunction = context.getQualifierForDescriptor(it)
|
||||||
fqnWithoutSideEffects(functionName, qualifierForFunction)
|
pureFqn(functionName, qualifierForFunction)
|
||||||
}
|
}
|
||||||
return JsInvocation(functionRef, argumentsInfo.translateArguments)
|
return JsInvocation(functionRef, argumentsInfo.translateArguments)
|
||||||
}
|
}
|
||||||
@@ -101,7 +101,7 @@ object DefaultFunctionCallCase : FunctionCallCase() {
|
|||||||
|
|
||||||
val functionRef = context.aliasOrValue(callableDescriptor) {
|
val functionRef = context.aliasOrValue(callableDescriptor) {
|
||||||
val qualifierForFunction = context.getQualifierForDescriptor(it)
|
val qualifierForFunction = context.getQualifierForDescriptor(it)
|
||||||
fqnWithoutSideEffects(functionName, qualifierForFunction) // TODO: remake to call
|
pureFqn(functionName, qualifierForFunction) // TODO: remake to call
|
||||||
}
|
}
|
||||||
|
|
||||||
val referenceToCall =
|
val referenceToCall =
|
||||||
@@ -238,7 +238,7 @@ object SuperCallCase : FunctionCallCase() {
|
|||||||
|
|
||||||
override fun FunctionCallInfo.dispatchReceiver(): JsExpression {
|
override fun FunctionCallInfo.dispatchReceiver(): JsExpression {
|
||||||
// TODO: spread operator
|
// TODO: spread operator
|
||||||
val prototypeClass = fqnWithoutSideEffects(Namer.getPrototypeName(), calleeOwner)
|
val prototypeClass = pureFqn(Namer.getPrototypeName(), calleeOwner)
|
||||||
val functionRef = Namer.getFunctionCallRef(JsNameRef(functionName, prototypeClass))
|
val functionRef = Namer.getFunctionCallRef(JsNameRef(functionName, prototypeClass))
|
||||||
return JsInvocation(functionRef, argumentsInfo.argsWithReceiver(dispatchReceiver!!))
|
return JsInvocation(functionRef, argumentsInfo.argsWithReceiver(dispatchReceiver!!))
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.js.translate.callTranslator
|
|||||||
import com.google.dart.compiler.backend.js.ast.JsExpression
|
import com.google.dart.compiler.backend.js.ast.JsExpression
|
||||||
import com.google.dart.compiler.backend.js.ast.JsInvocation
|
import com.google.dart.compiler.backend.js.ast.JsInvocation
|
||||||
import com.google.dart.compiler.backend.js.ast.JsNameRef
|
import com.google.dart.compiler.backend.js.ast.JsNameRef
|
||||||
|
import com.google.dart.compiler.backend.js.ast.metadata.SideEffectKind
|
||||||
import com.google.dart.compiler.backend.js.ast.metadata.sideEffects
|
import com.google.dart.compiler.backend.js.ast.metadata.sideEffects
|
||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
@@ -74,8 +75,8 @@ object DefaultVariableAccessCase : VariableAccessCase() {
|
|||||||
override fun VariableAccessInfo.dispatchReceiver(): JsExpression {
|
override fun VariableAccessInfo.dispatchReceiver(): JsExpression {
|
||||||
val accessor = JsNameRef(variableName, dispatchReceiver!!)
|
val accessor = JsNameRef(variableName, dispatchReceiver!!)
|
||||||
val descriptor = callableDescriptor
|
val descriptor = callableDescriptor
|
||||||
if (descriptor is PropertyDescriptor && JsDescriptorUtils.sideEffectsPossible(descriptor)) {
|
if (descriptor is PropertyDescriptor && !JsDescriptorUtils.sideEffectsPossible(descriptor)) {
|
||||||
accessor.sideEffects = false
|
accessor.sideEffects = SideEffectKind.DEPENDS_ON_STATE
|
||||||
}
|
}
|
||||||
return constructAccessExpression(accessor)
|
return constructAccessExpression(accessor)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,13 +17,12 @@
|
|||||||
package org.jetbrains.kotlin.js.translate.context;
|
package org.jetbrains.kotlin.js.translate.context;
|
||||||
|
|
||||||
import com.google.dart.compiler.backend.js.ast.*;
|
import com.google.dart.compiler.backend.js.ast.*;
|
||||||
import com.google.dart.compiler.backend.js.ast.metadata.HasMetadata;
|
|
||||||
import com.google.dart.compiler.backend.js.ast.metadata.MetadataProperties;
|
import com.google.dart.compiler.backend.js.ast.metadata.MetadataProperties;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.metadata.SideEffectKind;
|
||||||
import com.google.dart.compiler.backend.js.ast.metadata.TypeCheck;
|
import com.google.dart.compiler.backend.js.ast.metadata.TypeCheck;
|
||||||
import com.intellij.openapi.util.text.StringUtil;
|
import com.intellij.openapi.util.text.StringUtil;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
|
||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor;
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor;
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
||||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
|
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
|
||||||
@@ -38,7 +37,7 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static com.google.dart.compiler.backend.js.ast.JsScopesKt.JsObjectScope;
|
import static com.google.dart.compiler.backend.js.ast.JsScopesKt.JsObjectScope;
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.fqnWithoutSideEffects;
|
import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.pureFqn;
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.getModuleName;
|
import static org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.getModuleName;
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.ManglingUtils.getStableMangledNameForDescriptor;
|
import static org.jetbrains.kotlin.js.translate.utils.ManglingUtils.getStableMangledNameForDescriptor;
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.ManglingUtils.getSuggestedName;
|
import static org.jetbrains.kotlin.js.translate.utils.ManglingUtils.getSuggestedName;
|
||||||
@@ -143,7 +142,7 @@ public final class Namer {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static JsNameRef superMethodNameRef(@NotNull JsName superClassJsName) {
|
public static JsNameRef superMethodNameRef(@NotNull JsName superClassJsName) {
|
||||||
return fqnWithoutSideEffects(SUPER_METHOD_NAME, superClassJsName.makeRef());
|
return pureFqn(SUPER_METHOD_NAME, superClassJsName.makeRef());
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -182,7 +181,7 @@ public final class Namer {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static JsNameRef getRefToPrototype(@NotNull JsExpression classOrTraitExpression) {
|
public static JsNameRef getRefToPrototype(@NotNull JsExpression classOrTraitExpression) {
|
||||||
return fqnWithoutSideEffects(getPrototypeName(), classOrTraitExpression);
|
return pureFqn(getPrototypeName(), classOrTraitExpression);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -207,12 +206,12 @@ public final class Namer {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static JsNameRef getFunctionCallRef(@NotNull JsExpression functionExpression) {
|
public static JsNameRef getFunctionCallRef(@NotNull JsExpression functionExpression) {
|
||||||
return fqnWithoutSideEffects(CALL_FUNCTION, functionExpression);
|
return pureFqn(CALL_FUNCTION, functionExpression);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static JsNameRef getFunctionApplyRef(@NotNull JsExpression functionExpression) {
|
public static JsNameRef getFunctionApplyRef(@NotNull JsExpression functionExpression) {
|
||||||
return fqnWithoutSideEffects(APPLY_FUNCTION, functionExpression);
|
return pureFqn(APPLY_FUNCTION, functionExpression);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -222,7 +221,7 @@ public final class Namer {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static JsNameRef getCapturedVarAccessor(@NotNull JsExpression ref) {
|
public static JsNameRef getCapturedVarAccessor(@NotNull JsExpression ref) {
|
||||||
return fqnWithoutSideEffects(CAPTURED_VAR_FIELD, ref);
|
return pureFqn(CAPTURED_VAR_FIELD, ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -297,7 +296,6 @@ public final class Namer {
|
|||||||
|
|
||||||
isTypeName = kotlinScope.declareName("isType");
|
isTypeName = kotlinScope.declareName("isType");
|
||||||
modulesMap = kotlin("modules");
|
modulesMap = kotlin("modules");
|
||||||
MetadataProperties.setSideEffects((HasMetadata) modulesMap, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -377,7 +375,7 @@ public final class Namer {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static JsNameRef kotlin(@NotNull JsName name) {
|
public static JsNameRef kotlin(@NotNull JsName name) {
|
||||||
return fqnWithoutSideEffects(name, kotlinObject());
|
return pureFqn(name, kotlinObject());
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -387,7 +385,7 @@ public final class Namer {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static JsNameRef kotlinObject() {
|
public static JsNameRef kotlinObject() {
|
||||||
return fqnWithoutSideEffects(KOTLIN_NAME, null);
|
return pureFqn(KOTLIN_NAME, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -444,14 +442,14 @@ public final class Namer {
|
|||||||
JsInvocation invocation = new JsInvocation(kotlin(functionName));
|
JsInvocation invocation = new JsInvocation(kotlin(functionName));
|
||||||
invocation.getArguments().addAll(arguments);
|
invocation.getArguments().addAll(arguments);
|
||||||
MetadataProperties.setTypeCheck(invocation, metadata);
|
MetadataProperties.setTypeCheck(invocation, metadata);
|
||||||
MetadataProperties.setSideEffects(invocation, false);
|
MetadataProperties.setSideEffects(invocation, SideEffectKind.PURE);
|
||||||
return invocation;
|
return invocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public JsExpression isInstanceOf(@NotNull JsExpression instance, @NotNull JsExpression type) {
|
public JsExpression isInstanceOf(@NotNull JsExpression instance, @NotNull JsExpression type) {
|
||||||
JsInvocation result = new JsInvocation(kotlin(isTypeName), instance, type);
|
JsInvocation result = new JsInvocation(kotlin(isTypeName), instance, type);
|
||||||
MetadataProperties.setSideEffects(result, false);
|
MetadataProperties.setSideEffects(result, SideEffectKind.PURE);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -501,16 +499,16 @@ public final class Namer {
|
|||||||
@NotNull
|
@NotNull
|
||||||
public JsExpression getModuleReference(@NotNull JsStringLiteral moduleName) {
|
public JsExpression getModuleReference(@NotNull JsStringLiteral moduleName) {
|
||||||
JsArrayAccess result = new JsArrayAccess(modulesMap, moduleName);
|
JsArrayAccess result = new JsArrayAccess(modulesMap, moduleName);
|
||||||
MetadataProperties.setSideEffects(result, false);
|
MetadataProperties.setSideEffects(result, SideEffectKind.PURE);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static JsNameRef kotlinLong() {
|
public static JsNameRef kotlinLong() {
|
||||||
return fqnWithoutSideEffects("Long", kotlinObject());
|
return pureFqn("Long", kotlinObject());
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static JsNameRef createInlineFunction() {
|
public static JsNameRef createInlineFunction() {
|
||||||
return fqnWithoutSideEffects(DEFINE_INLINE_FUNCTION, kotlinObject());
|
return pureFqn(DEFINE_INLINE_FUNCTION, kotlinObject());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import com.google.common.collect.Maps;
|
|||||||
import com.google.dart.compiler.backend.js.ast.*;
|
import com.google.dart.compiler.backend.js.ast.*;
|
||||||
import com.google.dart.compiler.backend.js.ast.metadata.HasMetadata;
|
import com.google.dart.compiler.backend.js.ast.metadata.HasMetadata;
|
||||||
import com.google.dart.compiler.backend.js.ast.metadata.MetadataProperties;
|
import com.google.dart.compiler.backend.js.ast.metadata.MetadataProperties;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.metadata.SideEffectKind;
|
||||||
import com.intellij.openapi.util.Factory;
|
import com.intellij.openapi.util.Factory;
|
||||||
import com.intellij.util.containers.ContainerUtil;
|
import com.intellij.util.containers.ContainerUtil;
|
||||||
import com.intellij.util.containers.HashMap;
|
import com.intellij.util.containers.HashMap;
|
||||||
@@ -45,7 +46,7 @@ import java.util.Map;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils.*;
|
import static org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils.*;
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.fqnWithoutSideEffects;
|
import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.pureFqn;
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.*;
|
import static org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.*;
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.ManglingUtils.getMangledName;
|
import static org.jetbrains.kotlin.js.translate.utils.ManglingUtils.getMangledName;
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.ManglingUtils.getSuggestedName;
|
import static org.jetbrains.kotlin.js.translate.utils.ManglingUtils.getSuggestedName;
|
||||||
@@ -196,7 +197,7 @@ public final class StaticContext {
|
|||||||
@NotNull
|
@NotNull
|
||||||
public JsNameRef getQualifiedReference(@NotNull FqName packageFqName) {
|
public JsNameRef getQualifiedReference(@NotNull FqName packageFqName) {
|
||||||
JsName packageName = getNameForPackage(packageFqName);
|
JsName packageName = getNameForPackage(packageFqName);
|
||||||
return fqnWithoutSideEffects(packageName, packageFqName.isRoot() ? null : getQualifierForParentPackage(packageFqName.parent()));
|
return pureFqn(packageName, packageFqName.isRoot() ? null : getQualifierForParentPackage(packageFqName.parent()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -225,7 +226,7 @@ public final class StaticContext {
|
|||||||
FqName fqName = packageFqName;
|
FqName fqName = packageFqName;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
JsNameRef ref = fqnWithoutSideEffects(getNameForPackage(fqName), null);
|
JsNameRef ref = pureFqn(getNameForPackage(fqName), null);
|
||||||
|
|
||||||
if (qualifier == null) {
|
if (qualifier == null) {
|
||||||
result = ref;
|
result = ref;
|
||||||
@@ -640,7 +641,7 @@ public final class StaticContext {
|
|||||||
descriptor instanceof PackageFragmentDescriptor ||
|
descriptor instanceof PackageFragmentDescriptor ||
|
||||||
descriptor instanceof ClassDescriptor
|
descriptor instanceof ClassDescriptor
|
||||||
) {
|
) {
|
||||||
MetadataProperties.setSideEffects((HasMetadata) expression, false);
|
MetadataProperties.setSideEffects((HasMetadata) expression, SideEffectKind.PURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return expression;
|
return expression;
|
||||||
|
|||||||
@@ -17,6 +17,8 @@
|
|||||||
package org.jetbrains.kotlin.js.translate.declaration
|
package org.jetbrains.kotlin.js.translate.declaration
|
||||||
|
|
||||||
import com.google.dart.compiler.backend.js.ast.*
|
import com.google.dart.compiler.backend.js.ast.*
|
||||||
|
import com.google.dart.compiler.backend.js.ast.metadata.SideEffectKind
|
||||||
|
import com.google.dart.compiler.backend.js.ast.metadata.sideEffects
|
||||||
import com.intellij.util.SmartList
|
import com.intellij.util.SmartList
|
||||||
import org.jetbrains.kotlin.backend.common.CodegenUtil
|
import org.jetbrains.kotlin.backend.common.CodegenUtil
|
||||||
import org.jetbrains.kotlin.backend.common.bridges.Bridge
|
import org.jetbrains.kotlin.backend.common.bridges.Bridge
|
||||||
|
|||||||
+2
-3
@@ -27,7 +27,7 @@ import org.jetbrains.kotlin.js.translate.context.Namer.getReceiverParameterName
|
|||||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
||||||
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator
|
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator
|
||||||
import org.jetbrains.kotlin.js.translate.general.Translation
|
import org.jetbrains.kotlin.js.translate.general.Translation
|
||||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.fqnWithoutSideEffects
|
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.pureFqn
|
||||||
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils
|
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils
|
||||||
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils.assignmentToBackingField
|
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils.assignmentToBackingField
|
||||||
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils.backingFieldReference
|
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils.backingFieldReference
|
||||||
@@ -168,8 +168,7 @@ private class PropertyTranslator(
|
|||||||
val fakeArgumentExpression =
|
val fakeArgumentExpression =
|
||||||
(delegatedCall.valueArgumentsByIndex!![1] as ExpressionValueArgument).valueArgument!!.getArgumentExpression()
|
(delegatedCall.valueArgumentsByIndex!![1] as ExpressionValueArgument).valueArgument!!.getArgumentExpression()
|
||||||
return context.innerContextWithAliasesForExpressions(mapOf(
|
return context.innerContextWithAliasesForExpressions(mapOf(
|
||||||
fakeArgumentExpression to JsNew(fqnWithoutSideEffects("PropertyMetadata", Namer.kotlinObject()),
|
fakeArgumentExpression to JsNew(pureFqn("PropertyMetadata", Namer.kotlinObject()), listOf(propertyNameLiteral))
|
||||||
listOf(propertyNameLiteral))
|
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-7
@@ -17,10 +17,7 @@
|
|||||||
package org.jetbrains.kotlin.js.translate.expression
|
package org.jetbrains.kotlin.js.translate.expression
|
||||||
|
|
||||||
import com.google.dart.compiler.backend.js.ast.*
|
import com.google.dart.compiler.backend.js.ast.*
|
||||||
import com.google.dart.compiler.backend.js.ast.metadata.functionDescriptor
|
import com.google.dart.compiler.backend.js.ast.metadata.*
|
||||||
import com.google.dart.compiler.backend.js.ast.metadata.isLocal
|
|
||||||
import com.google.dart.compiler.backend.js.ast.metadata.sideEffects
|
|
||||||
import com.google.dart.compiler.backend.js.ast.metadata.staticRef
|
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.js.inline.util.getInnerFunction
|
import org.jetbrains.kotlin.js.inline.util.getInnerFunction
|
||||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
||||||
@@ -63,13 +60,13 @@ class LiteralFunctionTranslator(context: TranslationContext) : AbstractTranslato
|
|||||||
}
|
}
|
||||||
|
|
||||||
lambda.isLocal = true
|
lambda.isLocal = true
|
||||||
return invokingContext.define(descriptor, lambda).apply { sideEffects = false }
|
return invokingContext.define(descriptor, lambda).apply { sideEffects = SideEffectKind.PURE }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun JsFunction.withCapturedParameters(context: TranslationContext, invokingContext: TranslationContext, descriptor: MemberDescriptor): JsExpression {
|
fun JsFunction.withCapturedParameters(context: TranslationContext, invokingContext: TranslationContext, descriptor: MemberDescriptor): JsExpression {
|
||||||
val ref = invokingContext.define(descriptor, this).apply { sideEffects = false }
|
val ref = invokingContext.define(descriptor, this).apply { sideEffects = SideEffectKind.PURE }
|
||||||
val invocation = JsInvocation(ref).apply { sideEffects = false }
|
val invocation = JsInvocation(ref).apply { sideEffects = SideEffectKind.PURE }
|
||||||
|
|
||||||
val invocationArguments = invocation.arguments
|
val invocationArguments = invocation.arguments
|
||||||
val functionParameters = this.parameters
|
val functionParameters = this.parameters
|
||||||
|
|||||||
+4
-4
@@ -43,7 +43,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.BindingUtils.*;
|
import static org.jetbrains.kotlin.js.translate.utils.BindingUtils.*;
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.FunctionBodyTranslator.setDefaultValueForArguments;
|
import static org.jetbrains.kotlin.js.translate.utils.FunctionBodyTranslator.setDefaultValueForArguments;
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.fqnWithoutSideEffects;
|
import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.pureFqn;
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.PsiUtils.getPrimaryConstructorParameters;
|
import static org.jetbrains.kotlin.js.translate.utils.PsiUtils.getPrimaryConstructorParameters;
|
||||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.getClassDescriptorForType;
|
import static org.jetbrains.kotlin.resolve.DescriptorUtils.getClassDescriptorForType;
|
||||||
|
|
||||||
@@ -124,8 +124,8 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
|
|||||||
|
|
||||||
initFunction.getParameters().add(0, new JsParameter(outerName));
|
initFunction.getParameters().add(0, new JsParameter(outerName));
|
||||||
|
|
||||||
JsExpression paramRef = fqnWithoutSideEffects(outerName, null);
|
JsExpression paramRef = pureFqn(outerName, null);
|
||||||
JsExpression assignment = JsAstUtils.assignment(fqnWithoutSideEffects(outerName, JsLiteral.THIS), paramRef);
|
JsExpression assignment = JsAstUtils.assignment(pureFqn(outerName, JsLiteral.THIS), paramRef);
|
||||||
initFunction.getBody().getStatements().add(new JsExpressionStatement(assignment));
|
initFunction.getBody().getStatements().add(new JsExpressionStatement(assignment));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,7 +178,7 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (superDescriptor.getContainingDeclaration().isInner() && descriptor.isInner()) {
|
if (superDescriptor.getContainingDeclaration().isInner() && descriptor.isInner()) {
|
||||||
arguments.add(fqnWithoutSideEffects(Namer.OUTER_FIELD_NAME, JsLiteral.THIS));
|
arguments.add(pureFqn(Namer.OUTER_FIELD_NAME, JsLiteral.THIS));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!DescriptorUtils.isAnonymousObject(descriptor)) {
|
if (!DescriptorUtils.isAnonymousObject(descriptor)) {
|
||||||
|
|||||||
+1
-3
@@ -25,8 +25,6 @@ import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.fqnWithoutSideEffects;
|
|
||||||
|
|
||||||
public final class BuiltInFunctionIntrinsic extends FunctionIntrinsic {
|
public final class BuiltInFunctionIntrinsic extends FunctionIntrinsic {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -44,6 +42,6 @@ public final class BuiltInFunctionIntrinsic extends FunctionIntrinsic {
|
|||||||
@NotNull TranslationContext context
|
@NotNull TranslationContext context
|
||||||
) {
|
) {
|
||||||
assert receiver != null;
|
assert receiver != null;
|
||||||
return new JsInvocation(fqnWithoutSideEffects(functionName, receiver), arguments);
|
return new JsInvocation(JsAstUtils.pureFqn(functionName, receiver), arguments);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-3
@@ -24,8 +24,6 @@ import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.fqnWithoutSideEffects;
|
|
||||||
|
|
||||||
//TODO: find should be usages
|
//TODO: find should be usages
|
||||||
public final class BuiltInPropertyIntrinsic extends FunctionIntrinsic {
|
public final class BuiltInPropertyIntrinsic extends FunctionIntrinsic {
|
||||||
|
|
||||||
@@ -42,6 +40,6 @@ public final class BuiltInPropertyIntrinsic extends FunctionIntrinsic {
|
|||||||
@NotNull TranslationContext context) {
|
@NotNull TranslationContext context) {
|
||||||
assert receiver != null;
|
assert receiver != null;
|
||||||
assert arguments.isEmpty() : "Properties can't have arguments.";
|
assert arguments.isEmpty() : "Properties can't have arguments.";
|
||||||
return fqnWithoutSideEffects(propertyName, receiver);
|
return JsAstUtils.pureFqn(propertyName, receiver);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-4
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.js.translate.intrinsic.functions.factories;
|
|||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.dart.compiler.backend.js.ast.JsArrayAccess;
|
import com.google.dart.compiler.backend.js.ast.JsArrayAccess;
|
||||||
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
||||||
import com.google.dart.compiler.backend.js.ast.metadata.MetadataProperties;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||||
@@ -97,9 +96,7 @@ public final class ArrayFIF extends CompositeFIF {
|
|||||||
assert receiver != null;
|
assert receiver != null;
|
||||||
assert arguments.size() == 1 : "Array get expression must have one argument.";
|
assert arguments.size() == 1 : "Array get expression must have one argument.";
|
||||||
JsExpression indexExpression = arguments.get(0);
|
JsExpression indexExpression = arguments.get(0);
|
||||||
JsArrayAccess result = new JsArrayAccess(receiver, indexExpression);
|
return new JsArrayAccess(receiver, indexExpression);
|
||||||
MetadataProperties.setSideEffects(result, false);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -43,7 +43,7 @@ public class KotlinFunctionIntrinsic extends FunctionIntrinsic {
|
|||||||
@NotNull List<JsExpression> arguments,
|
@NotNull List<JsExpression> arguments,
|
||||||
@NotNull TranslationContext context
|
@NotNull TranslationContext context
|
||||||
) {
|
) {
|
||||||
JsExpression function = JsAstUtils.fqnWithoutSideEffects(functionName, Namer.kotlinObject());
|
JsExpression function = JsAstUtils.pureFqn(functionName, Namer.kotlinObject());
|
||||||
return new JsInvocation(function, receiver == null ? arguments : TranslationUtils.generateInvocationArguments(receiver, arguments));
|
return new JsInvocation(function, receiver == null ? arguments : TranslationUtils.generateInvocationArguments(receiver, arguments));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -211,7 +211,7 @@ public final class TopLevelFIF extends CompositeFIF {
|
|||||||
|
|
||||||
String mangledName = getStableMangledNameForDescriptor(JsPlatform.INSTANCE.getBuiltIns().getMutableMap(), operationName());
|
String mangledName = getStableMangledNameForDescriptor(JsPlatform.INSTANCE.getBuiltIns().getMutableMap(), operationName());
|
||||||
|
|
||||||
return new JsInvocation(JsAstUtils.fqnWithoutSideEffects(mangledName, thisOrReceiver), arguments);
|
return new JsInvocation(JsAstUtils.pureFqn(mangledName, thisOrReceiver), arguments);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+6
-4
@@ -17,6 +17,8 @@
|
|||||||
package org.jetbrains.kotlin.js.translate.reference
|
package org.jetbrains.kotlin.js.translate.reference
|
||||||
|
|
||||||
import com.google.dart.compiler.backend.js.ast.*
|
import com.google.dart.compiler.backend.js.ast.*
|
||||||
|
import com.google.dart.compiler.backend.js.ast.metadata.SideEffectKind
|
||||||
|
import com.google.dart.compiler.backend.js.ast.metadata.sideEffects
|
||||||
import com.intellij.util.SmartList
|
import com.intellij.util.SmartList
|
||||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||||
import org.jetbrains.kotlin.js.translate.context.Namer
|
import org.jetbrains.kotlin.js.translate.context.Namer
|
||||||
@@ -143,7 +145,7 @@ class CallArgumentTranslator private constructor(
|
|||||||
concatArguments!!.addAll(result)
|
concatArguments!!.addAll(result)
|
||||||
|
|
||||||
if (!argsBeforeVararg!!.isEmpty()) {
|
if (!argsBeforeVararg!!.isEmpty()) {
|
||||||
concatArguments.add(0, JsArrayLiteral(argsBeforeVararg))
|
concatArguments.add(0, JsArrayLiteral(argsBeforeVararg).apply { sideEffects = SideEffectKind.DEPENDS_ON_STATE })
|
||||||
}
|
}
|
||||||
|
|
||||||
result = SmartList(concatArgumentsIfNeeded(concatArguments))
|
result = SmartList(concatArgumentsIfNeeded(concatArguments))
|
||||||
@@ -212,7 +214,7 @@ class CallArgumentTranslator private constructor(
|
|||||||
context: TranslationContext, shouldWrapVarargInArray: Boolean): ArgumentsKind {
|
context: TranslationContext, shouldWrapVarargInArray: Boolean): ArgumentsKind {
|
||||||
if (arguments.isEmpty()) {
|
if (arguments.isEmpty()) {
|
||||||
if (shouldWrapVarargInArray) {
|
if (shouldWrapVarargInArray) {
|
||||||
result.add(JsArrayLiteral(listOf<JsExpression>()))
|
result.add(JsArrayLiteral(listOf<JsExpression>()).apply { sideEffects = SideEffectKind.DEPENDS_ON_STATE })
|
||||||
}
|
}
|
||||||
return ArgumentsKind.HAS_NOT_EMPTY_EXPRESSION_ARGUMENT
|
return ArgumentsKind.HAS_NOT_EMPTY_EXPRESSION_ARGUMENT
|
||||||
}
|
}
|
||||||
@@ -289,7 +291,7 @@ class CallArgumentTranslator private constructor(
|
|||||||
|
|
||||||
if (valueArgument.getSpreadElement() != null) {
|
if (valueArgument.getSpreadElement() != null) {
|
||||||
if (lastArrayContent.size > 0) {
|
if (lastArrayContent.size > 0) {
|
||||||
concatArguments.add(JsArrayLiteral(lastArrayContent))
|
concatArguments.add(JsArrayLiteral(lastArrayContent).apply { sideEffects = SideEffectKind.DEPENDS_ON_STATE })
|
||||||
concatArguments.add(expressionArgument)
|
concatArguments.add(expressionArgument)
|
||||||
lastArrayContent = SmartList<JsExpression>()
|
lastArrayContent = SmartList<JsExpression>()
|
||||||
}
|
}
|
||||||
@@ -302,7 +304,7 @@ class CallArgumentTranslator private constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (lastArrayContent.size > 0) {
|
if (lastArrayContent.size > 0) {
|
||||||
concatArguments.add(JsArrayLiteral(lastArrayContent))
|
concatArguments.add(JsArrayLiteral(lastArrayContent).apply { sideEffects = SideEffectKind.DEPENDS_ON_STATE })
|
||||||
}
|
}
|
||||||
|
|
||||||
return concatArguments
|
return concatArguments
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.js.translate.utils;
|
|||||||
|
|
||||||
import com.google.dart.compiler.backend.js.ast.*;
|
import com.google.dart.compiler.backend.js.ast.*;
|
||||||
import com.google.dart.compiler.backend.js.ast.metadata.MetadataProperties;
|
import com.google.dart.compiler.backend.js.ast.metadata.MetadataProperties;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.metadata.SideEffectKind;
|
||||||
import com.intellij.util.SmartList;
|
import com.intellij.util.SmartList;
|
||||||
import kotlin.Pair;
|
import kotlin.Pair;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@@ -32,12 +33,12 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public final class JsAstUtils {
|
public final class JsAstUtils {
|
||||||
private static final JsNameRef DEFINE_PROPERTY = fqnWithoutSideEffects("defineProperty", null);
|
private static final JsNameRef DEFINE_PROPERTY = pureFqn("defineProperty", null);
|
||||||
public static final JsNameRef CREATE_OBJECT = fqnWithoutSideEffects("create", null);
|
public static final JsNameRef CREATE_OBJECT = pureFqn("create", null);
|
||||||
|
|
||||||
private static final JsNameRef VALUE = new JsNameRef("value");
|
private static final JsNameRef VALUE = new JsNameRef("value");
|
||||||
private static final JsPropertyInitializer WRITABLE = new JsPropertyInitializer(fqnWithoutSideEffects("writable", null), JsLiteral.TRUE);
|
private static final JsPropertyInitializer WRITABLE = new JsPropertyInitializer(pureFqn("writable", null), JsLiteral.TRUE);
|
||||||
private static final JsPropertyInitializer ENUMERABLE = new JsPropertyInitializer(fqnWithoutSideEffects("enumerable", null), JsLiteral.TRUE);
|
private static final JsPropertyInitializer ENUMERABLE = new JsPropertyInitializer(pureFqn("enumerable", null), JsLiteral.TRUE);
|
||||||
|
|
||||||
public static final String LENDS_JS_DOC_TAG = "lends";
|
public static final String LENDS_JS_DOC_TAG = "lends";
|
||||||
|
|
||||||
@@ -128,7 +129,7 @@ public final class JsAstUtils {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static JsInvocation invokeMethod(@NotNull JsExpression thisObject, @NotNull String name, @NotNull JsExpression... arguments) {
|
public static JsInvocation invokeMethod(@NotNull JsExpression thisObject, @NotNull String name, @NotNull JsExpression... arguments) {
|
||||||
return new JsInvocation(fqnWithoutSideEffects(name, thisObject), arguments);
|
return new JsInvocation(pureFqn(name, thisObject), arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -173,7 +174,7 @@ public final class JsAstUtils {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static JsExpression rangeTo(@NotNull String rangeClassName, @NotNull JsExpression rangeStart, @NotNull JsExpression rangeEnd) {
|
private static JsExpression rangeTo(@NotNull String rangeClassName, @NotNull JsExpression rangeStart, @NotNull JsExpression rangeEnd) {
|
||||||
JsNameRef expr = fqnWithoutSideEffects(rangeClassName, Namer.kotlinObject());
|
JsNameRef expr = pureFqn(rangeClassName, Namer.kotlinObject());
|
||||||
JsNew numberRangeConstructorInvocation = new JsNew(expr);
|
JsNew numberRangeConstructorInvocation = new JsNew(expr);
|
||||||
setArguments(numberRangeConstructorInvocation, rangeStart, rangeEnd);
|
setArguments(numberRangeConstructorInvocation, rangeStart, rangeEnd);
|
||||||
return numberRangeConstructorInvocation;
|
return numberRangeConstructorInvocation;
|
||||||
@@ -488,16 +489,16 @@ public final class JsAstUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static JsNameRef fqnWithoutSideEffects(@NotNull String identifier, @Nullable JsExpression qualifier) {
|
public static JsNameRef pureFqn(@NotNull String identifier, @Nullable JsExpression qualifier) {
|
||||||
JsNameRef result = new JsNameRef(identifier, qualifier);
|
JsNameRef result = new JsNameRef(identifier, qualifier);
|
||||||
MetadataProperties.setSideEffects(result, false);
|
MetadataProperties.setSideEffects(result, SideEffectKind.PURE);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static JsNameRef fqnWithoutSideEffects(@NotNull JsName identifier, @Nullable JsExpression qualifier) {
|
public static JsNameRef pureFqn(@NotNull JsName identifier, @Nullable JsExpression qualifier) {
|
||||||
JsNameRef result = new JsNameRef(identifier, qualifier);
|
JsNameRef result = new JsNameRef(identifier, qualifier);
|
||||||
MetadataProperties.setSideEffects(result, false);
|
MetadataProperties.setSideEffects(result, SideEffectKind.PURE);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -148,7 +148,13 @@ public final class JsDescriptorUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean sideEffectsPossible(@NotNull PropertyDescriptor property) {
|
public static boolean sideEffectsPossible(@NotNull PropertyDescriptor property) {
|
||||||
return isDefaultAccessor(property.getGetter()) && !ModalityKt.isOverridableOrOverrides(property);
|
return !isDefaultAccessor(property.getGetter()) || ModalityKt.isOverridableOrOverrides(property) ||
|
||||||
|
isStaticInitializationPossible(property);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isStaticInitializationPossible(PropertyDescriptor property) {
|
||||||
|
DeclarationDescriptor container = property.getContainingDeclaration();
|
||||||
|
return container instanceof PackageFragmentDescriptor || DescriptorUtils.isObject(container);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isSimpleFinalProperty(@NotNull PropertyDescriptor propertyDescriptor) {
|
public static boolean isSimpleFinalProperty(@NotNull PropertyDescriptor propertyDescriptor) {
|
||||||
|
|||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
package foo
|
||||||
|
|
||||||
|
class A {
|
||||||
|
var x = 23
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun bar(value: Int, a: A): Int {
|
||||||
|
a.x = 42
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val a = A()
|
||||||
|
assertEquals(23, bar(a.x, a))
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
package foo
|
||||||
|
|
||||||
|
object A {
|
||||||
|
init {
|
||||||
|
log("A.init")
|
||||||
|
}
|
||||||
|
|
||||||
|
val x = 23
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun bar(value: Int) {
|
||||||
|
log("bar->begin")
|
||||||
|
log("value=$value")
|
||||||
|
log("bar->end")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
bar(A.x)
|
||||||
|
assertEquals("A.init;bar->begin;value=23;bar->end;", pullLog())
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package foo
|
package foo
|
||||||
|
|
||||||
// CHECK_CONTAINS_NO_CALLS: test
|
// CHECK_CONTAINS_NO_CALLS: test
|
||||||
// CHECK_VARS_COUNT: function=test count=1
|
// CHECK_VARS_COUNT: function=test count=0
|
||||||
|
|
||||||
object SumHolder {
|
object SumHolder {
|
||||||
var sum = 0
|
var sum = 0
|
||||||
|
|||||||
Reference in New Issue
Block a user