JS: inline stdlib functions

This commit is contained in:
Alexey Tsvetkov
2015-03-06 15:49:51 +03:00
parent 47064ce03c
commit 38efec6886
5 changed files with 37 additions and 10 deletions
@@ -92,6 +92,19 @@ public class FunctionReader(private val context: TranslationContext) {
}
}
private val functionCache = object : SLRUCache<CallableDescriptor, JsFunction>(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
@@ -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<JsInliningContext> inliningContexts = new Stack<JsInliningContext>();
private final Set<JsFunction> processedFunctions = IdentitySet();
private final Set<JsFunction> 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<JsName, JsFunction> 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<JsName, JsFunction> functions) {
private JsInliner(
@NotNull IdentityHashMap<JsName, JsFunction> 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) {
@@ -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()
@@ -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);
}
}
@@ -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<JetFile> 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<JetFile> files,
private static TranslationContext doGenerateAst(@NotNull BindingTrace bindingTrace, @NotNull Collection<JetFile> 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<JsStatement> statements, @NotNull String moduleId) {