[JS IR] Introduce the GENERATE_INLINE_ANONYMOUS_FUNCTIONS feature flag

This commit is contained in:
Sergej Jaskiewicz
2022-04-20 14:00:18 +03:00
committed by Space
parent c10af22b27
commit e03747ea7d
18 changed files with 245 additions and 17 deletions
@@ -178,6 +178,12 @@ class K2JSCompilerArguments : CommonCompilerArguments() {
@Argument(value = "-Xir-new-ir2js", description = "New fragment-based ir2js")
var irNewIr2Js: Boolean by FreezableVar(true)
@Argument(
value = "-Xir-generate-inline-anonymous-functions",
description = "Lambda expressions that capture values are translated into in-line anonymous JavaScript functions"
)
var irGenerateInlineAnonymousFunctions: Boolean by FreezableVar(false)
@Argument(
value = "-Xinclude",
valueDescription = "<path>",
@@ -163,6 +163,7 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
configurationJs.put(CLIConfigurationKeys.ALLOW_KOTLIN_PACKAGE, arguments.allowKotlinPackage)
configurationJs.put(CLIConfigurationKeys.RENDER_DIAGNOSTIC_INTERNAL_NAME, arguments.renderInternalDiagnosticNames)
configurationJs.put(JSConfigurationKeys.PROPERTY_LAZY_INITIALIZATION, arguments.irPropertyLazyInitialization)
configurationJs.put(JSConfigurationKeys.GENERATE_INLINE_ANONYMOUS_FUNCTIONS, arguments.irGenerateInlineAnonymousFunctions)
if (!checkKotlinPackageUsage(environmentForJS.configuration, sourcesFiles)) return ExitCode.COMPILATION_ERROR
@@ -28,12 +28,16 @@ import org.jetbrains.kotlin.ir.types.classifierOrNull
import org.jetbrains.kotlin.ir.types.isUnit
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.*
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.addToStdlib.cast
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class InteropCallableReferenceLowering(val context: JsIrBackendContext) : BodyLoweringPass {
val generateInlineAnonymousFunctions: Boolean
get() = context.configuration.getBoolean(JSConfigurationKeys.GENERATE_INLINE_ANONYMOUS_FUNCTIONS)
/**
* A factory that creates [IrFunctionExpression] for lambdas being constructed.
*
@@ -121,7 +125,8 @@ class InteropCallableReferenceLowering(val context: JsIrBackendContext) : BodyLo
val closureUsageAnalyser = ClosureUsageAnalyser()
irFile.acceptChildrenVoid(closureUsageAnalyser) // TODO: Only do this if lambda inlining is enabled with a feature flag!
if (generateInlineAnonymousFunctions)
irFile.acceptChildrenVoid(closureUsageAnalyser)
val callableReferenceClassTransformer = CallableReferenceClassTransformer(
ctorToFactoryMap,
@@ -317,8 +322,9 @@ class InteropCallableReferenceLowering(val context: JsIrBackendContext) : BodyLo
// This allows us to avoid allocating a new object each time the lambda is created.
liftLambda(ctorToFreeFunctionMap, lambdaInfo)
} else if (
generateInlineAnonymousFunctions
// If the lambda constructor is called from more than one place, don't inline.
closureUsageAnalyser.getLambdaConstructorCalls(lambdaClass.primaryConstructor!!.symbol).size == 1
&& closureUsageAnalyser.getLambdaConstructorCalls(lambdaClass.primaryConstructor!!.symbol).size == 1
// In-line anonymous functions that capture variables declared in loops are dangerous.
// See https://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example
&& !closureUsageAnalyser.lambdaCapturesVariablesDeclaredInLoops(lambdaClass)
+2
View File
@@ -17,6 +17,8 @@ where advanced options include:
Print declarations' reachability info to stdout during performing DCE
-Xir-dce-runtime-diagnostic={log|exception}
Enable runtime diagnostics when performing DCE instead of removing declarations
-Xir-generate-inline-anonymous-functions
Lambda expressions that capture values are translated into in-line anonymous JavaScript functions
-Xir-minimized-member-names Perform minimization for names of members
-Xir-module-name=<name> Specify a compilation module name for IR backend
-Xir-new-ir2js New fragment-based ir2js
@@ -112,6 +112,11 @@ object JsEnvironmentConfigurationDirectives : SimpleDirectivesContainer() {
applicability = DirectiveApplicability.Global
)
val GENERATE_INLINE_ANONYMOUS_FUNCTIONS by directive(
description = "translate lambdas into in-line anonymous functions",
applicability = DirectiveApplicability.Global
)
val SAFE_EXTERNAL_BOOLEAN by directive(
description = "",
applicability = DirectiveApplicability.Global
@@ -120,6 +120,10 @@ fun createCompilerConfiguration(module: TestModule, configurators: List<Abstract
configuration.put(JSConfigurationKeys.PROPERTY_LAZY_INITIALIZATION, true)
}
if (JsEnvironmentConfigurationDirectives.GENERATE_INLINE_ANONYMOUS_FUNCTIONS in module.directives) {
configuration.put(JSConfigurationKeys.GENERATE_INLINE_ANONYMOUS_FUNCTIONS, true)
}
if (module.frontendKind == FrontendKinds.FIR) {
configuration[CommonConfigurationKeys.USE_FIR] = true
}