From 38efec6886f629a8f0913d081e49be4cd0ebeecd Mon Sep 17 00:00:00 2001 From: Alexey Tsvetkov Date: Fri, 6 Mar 2015 15:49:51 +0300 Subject: [PATCH] JS: inline stdlib functions --- .../jetbrains/kotlin/js/inline/FunctionReader.kt | 13 +++++++++++++ .../org/jetbrains/kotlin/js/inline/JsInliner.java | 15 +++++++++++---- .../kotlin/js/inline/context/FunctionContext.kt | 8 +++++++- .../kotlin/js/facade/K2JSTranslator.java | 5 +++-- .../kotlin/js/translate/general/Translation.java | 6 +++--- 5 files changed, 37 insertions(+), 10 deletions(-) diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/FunctionReader.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/FunctionReader.kt index f9f888e333d..1846c0e58f4 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/FunctionReader.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/FunctionReader.kt @@ -92,6 +92,19 @@ public class FunctionReader(private val context: TranslationContext) { } } + private val functionCache = object : SLRUCache(50, 50) { + override fun createValue(descriptor: CallableDescriptor): JsFunction = + requireNotNull(readFunction(descriptor), "Could not read function: $descriptor") + } + + public fun contains(descriptor: CallableDescriptor): Boolean { + val moduleName = getExternalModuleName(descriptor) + val currentModuleName = context.getConfig().getModuleId() + return currentModuleName != moduleName && moduleName in moduleJsDefinition + } + + public fun get(descriptor: CallableDescriptor): JsFunction = functionCache.get(descriptor) + private fun readFunction(descriptor: CallableDescriptor): JsFunction? { if (descriptor !in this) return null diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/JsInliner.java b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/JsInliner.java index 0ca50df2f9f..0d7717b47a7 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/JsInliner.java +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/JsInliner.java @@ -23,6 +23,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.builtins.InlineStrategy; import org.jetbrains.kotlin.js.inline.context.*; import org.jetbrains.kotlin.js.inline.exception.InlineRecursionException; +import org.jetbrains.kotlin.js.translate.context.TranslationContext; import java.util.IdentityHashMap; import java.util.Set; @@ -40,6 +41,7 @@ public class JsInliner extends JsVisitorWithContextImpl { private final Stack inliningContexts = new Stack(); private final Set processedFunctions = IdentitySet(); private final Set inProcessFunctions = IdentitySet(); + private final FunctionReader functionReader; /** * A statement can contain more, than one inlineable sub-expressions. @@ -71,16 +73,21 @@ public class JsInliner extends JsVisitorWithContextImpl { */ private boolean lastStatementWasShifted = false; - public static JsProgram process(JsProgram program) { + public static JsProgram process(@NotNull TranslationContext context) { + JsProgram program = context.program(); IdentityHashMap functions = collectNamedFunctions(program); - JsInliner inliner = new JsInliner(functions); + JsInliner inliner = new JsInliner(functions, new FunctionReader(context)); inliner.accept(program); removeUnusedFunctionDefinitions(program, functions); return program; } - JsInliner(IdentityHashMap functions) { + private JsInliner( + @NotNull IdentityHashMap functions, + @NotNull FunctionReader functionReader + ) { this.functions = functions; + this.functionReader = functionReader; } @Override @@ -191,7 +198,7 @@ public class JsInliner extends JsVisitorWithContextImpl { private final FunctionContext functionContext; JsInliningContext(JsFunction function) { - functionContext = new FunctionContext(function, this) { + functionContext = new FunctionContext(function, this, functionReader) { @Nullable @Override protected JsFunction lookUpStaticFunction(@Nullable JsName functionName) { diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/context/FunctionContext.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/context/FunctionContext.kt index a7e27488bcb..288ea6a0b3e 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/context/FunctionContext.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/context/FunctionContext.kt @@ -27,10 +27,13 @@ import org.jetbrains.kotlin.js.inline.util.isFunctionCreator import com.intellij.util.containers.ContainerUtil import java.util.IdentityHashMap +import org.jetbrains.kotlin.js.inline.FunctionReader +import com.google.dart.compiler.backend.js.ast.metadata.descriptor abstract class FunctionContext( private val function: JsFunction, - private val inliningContext: InliningContext + private val inliningContext: InliningContext, + private val functionReader: FunctionReader ) { /** * Caches function with captured arguments applied. @@ -109,6 +112,9 @@ abstract class FunctionContext( * in case of local function with closure. */ private fun getFunctionDefinitionImpl(call: JsInvocation): JsFunction? { + val descriptor = call.descriptor + if (descriptor != null && descriptor in functionReader) return functionReader[descriptor] + /** remove ending `()` */ var callQualifier = call.getQualifier() diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/facade/K2JSTranslator.java b/js/js.translator/src/org/jetbrains/kotlin/js/facade/K2JSTranslator.java index 7765f035a65..92e997a73fa 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/facade/K2JSTranslator.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/facade/K2JSTranslator.java @@ -43,6 +43,7 @@ import org.jetbrains.kotlin.js.inline.JsInliner; import org.jetbrains.kotlin.js.sourceMap.JsSourceGenerationVisitor; import org.jetbrains.kotlin.js.sourceMap.SourceMap3Builder; import org.jetbrains.kotlin.js.sourceMap.SourceMapBuilder; +import org.jetbrains.kotlin.js.translate.context.TranslationContext; import org.jetbrains.kotlin.js.translate.general.Translation; import org.jetbrains.kotlin.psi.JetFile; import org.jetbrains.kotlin.resolve.BindingTrace; @@ -82,12 +83,12 @@ public final class K2JSTranslator { BindingTrace bindingTrace = analysisResult.getBindingTrace(); TopDownAnalyzerFacadeForJS.checkForErrors(Config.withJsLibAdded(files, config), bindingTrace.getBindingContext()); ModuleDescriptor moduleDescriptor = analysisResult.getModuleDescriptor(); - JsProgram program = Translation.generateAst(bindingTrace, files, mainCallParameters, moduleDescriptor, config); + TranslationContext context = Translation.generateAst(bindingTrace, files, mainCallParameters, moduleDescriptor, config); Diagnostics diagnostics = bindingTrace.getBindingContext().getDiagnostics(); if (hasError(diagnostics)) return new TranslationResult.Fail(diagnostics); - program = JsInliner.process(program); + JsProgram program = JsInliner.process(context); return new TranslationResult.Success(config, files, program, diagnostics); } } diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/general/Translation.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/general/Translation.java index 5e301c67424..6eb83dd06f3 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/general/Translation.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/general/Translation.java @@ -162,7 +162,7 @@ public final class Translation { } @NotNull - public static JsProgram generateAst(@NotNull BindingTrace bindingTrace, + public static TranslationContext generateAst(@NotNull BindingTrace bindingTrace, @NotNull Collection files, @NotNull MainCallParameters mainCallParameters, @NotNull ModuleDescriptor moduleDescriptor, @NotNull Config config) @@ -179,7 +179,7 @@ public final class Translation { } @NotNull - private static JsProgram doGenerateAst(@NotNull BindingTrace bindingTrace, @NotNull Collection files, + private static TranslationContext doGenerateAst(@NotNull BindingTrace bindingTrace, @NotNull Collection files, @NotNull MainCallParameters mainCallParameters, @NotNull ModuleDescriptor moduleDescriptor, @NotNull Config config) throws MainFunctionNotFoundException { @@ -203,7 +203,7 @@ public final class Translation { } } mayBeGenerateTests(files, config, rootBlock, context); - return context.program(); + return context; } private static void defineModule(@NotNull TranslationContext context, @NotNull List statements, @NotNull String moduleId) {