From 50aa1b271fbf99fc3d1acc3868405262ef03c3a9 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Thu, 5 May 2016 18:14:38 +0300 Subject: [PATCH] JS/Inlining: when generating expression for default property accessor, mark this expression as side effect free, so optimizer has opportunity to move it --- .../translate/callTranslator/CallInfoExtensions.kt | 12 ++++++++++-- .../js/translate/callTranslator/VariableCallCases.kt | 11 +++++++++-- .../kotlin/js/translate/utils/JsDescriptorUtils.java | 6 +++++- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/callTranslator/CallInfoExtensions.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/callTranslator/CallInfoExtensions.kt index da5cbd0fecd..fc54d6a3387 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/callTranslator/CallInfoExtensions.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/callTranslator/CallInfoExtensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2015 JetBrains s.r.o. + * Copyright 2010-2016 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. @@ -19,6 +19,8 @@ package org.jetbrains.kotlin.js.translate.callTranslator 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.JsName +import com.google.dart.compiler.backend.js.ast.metadata.HasMetadata +import com.google.dart.compiler.backend.js.ast.metadata.sideEffects import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.VariableDescriptor @@ -73,7 +75,13 @@ fun VariableAccessInfo.constructAccessExpression(ref: JsExpression): JsExpressio if (isGetAccess()) { return ref } else { - return if (value !is JsEmptyExpression) JsAstUtils.assignment(ref, value!!) else context.emptyExpression + return if (value !is JsEmptyExpression) { + (ref as? HasMetadata)?.let { it.sideEffects = false } + JsAstUtils.assignment(ref, value!!) + } + else { + context.emptyExpression + } } } diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/callTranslator/VariableCallCases.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/callTranslator/VariableCallCases.kt index 7ae96a0e64e..414fcf982e5 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/callTranslator/VariableCallCases.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/callTranslator/VariableCallCases.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2015 JetBrains s.r.o. + * Copyright 2010-2016 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. @@ -19,10 +19,12 @@ package org.jetbrains.kotlin.js.translate.callTranslator 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.JsNameRef +import com.google.dart.compiler.backend.js.ast.metadata.sideEffects import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor import org.jetbrains.kotlin.js.translate.context.Namer.getCapturedVarAccessor +import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils import org.jetbrains.kotlin.js.translate.utils.TranslationUtils import org.jetbrains.kotlin.resolve.BindingContextUtils.isVarCapturedInClosure import java.util.* @@ -70,7 +72,12 @@ object DefaultVariableAccessCase : VariableAccessCase() { } override fun VariableAccessInfo.dispatchReceiver(): JsExpression { - return constructAccessExpression(JsNameRef(variableName, dispatchReceiver!!)) + val accessor = JsNameRef(variableName, dispatchReceiver!!) + val descriptor = callableDescriptor + if (descriptor is PropertyDescriptor && JsDescriptorUtils.sideEffectsPossible(descriptor)) { + accessor.sideEffects = false + } + return constructAccessExpression(accessor) } override fun VariableAccessInfo.extensionReceiver(): JsExpression { diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/JsDescriptorUtils.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/JsDescriptorUtils.java index 384a29ec13a..65d31a24cde 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/JsDescriptorUtils.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/JsDescriptorUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2015 JetBrains s.r.o. + * Copyright 2010-2016 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. @@ -147,6 +147,10 @@ public final class JsDescriptorUtils { return accessorDescriptor == null || accessorDescriptor.isDefault(); } + public static boolean sideEffectsPossible(@NotNull PropertyDescriptor property) { + return isDefaultAccessor(property.getGetter()) && !ModalityKt.isOverridableOrOverrides(property); + } + public static boolean isSimpleFinalProperty(@NotNull PropertyDescriptor propertyDescriptor) { return !isExtension(propertyDescriptor) && isDefaultAccessor(propertyDescriptor.getGetter()) &&