private ScriptInfo InternalAdd(string scriptString, string scriptKey, JSRuntime runtime) { Debug.Assert(scriptKey != null, "Invalid scriptKey, should be string"); ScriptInfo script = null; if (!Scripts.TryGetValue(scriptKey, out script)) { script = Scripts.GetOrAdd(scriptKey, key => { Debug.WriteLine("Script precompilation cache {0} [miss]", key); JSRuntime.Instance = runtime; var scriptInfo = new ScriptInfo(key, scriptString); scriptInfo.LexTask = System.Threading.Tasks.Task.Factory.StartNew(state => { var taskState = state as JSTaskState <ScriptInfo>; var info = taskState.GetState(); var timer = JSRuntime.StartTimer(true, "JS/PreLoad/" + key); info.Metadata = taskState.RuntimeInstance.LoadScriptStringMetadata(info.Text); if (Instance.Configuration.EnableParallelJit) { info.Metadata.JitSpeculatively(ref mdr.DFunctionSignature.EmptySignature); } else if (Instance.Configuration.EnableParallelAnalyze) { info.Metadata.Analyze(); //Will launch the rest itself. } JSRuntime.StopTimer(timer); }, new JSTaskState <ScriptInfo>(scriptInfo)); return(scriptInfo); }); } else { Debug.WriteLine("Script precompilation cache {0} [hit]", scriptKey); } return(script); }
/// <summary> /// Prepare() is called once before the first execution of function. /// </summary> void Prepare() { if (CurrentStatus < Status.Preparing) { Analyze(); var configuration = JSRuntime.Instance.Configuration; CurrentStatus = Status.Preparing; ParametersMask.Value = mdr.DFunctionSignature.GetMask(ParametersCount); //TODO: heuristic to disable TypeInference, we can also see if the func does not have any argument AND the "arguments" variable is not referenced in the functiob body EnableTypeInference = configuration.EnableTypeInference && configuration.EnableJIT && (ParametersCount <= mdr.DFunctionSignature.TypesPerElement) && (Scope.HasLoop || Scope.Symbols.Count > 0) ; //if (ParametersCount <= mdr.DFunctionSignature.TypesPerElement) if (EnableTypeInference) { SignatureMask.Value = ParametersMask.Value; } else { SignatureMask.Value = mdr.DFunctionSignature.EmptySignature.Value; } //TODO: make this a configuration parameter. EnableProfiling = configuration.EnableProfiling && !IsBlackListed; FunctionDeclarationHoister.Execute(this); if (configuration.EnableMethodCallResolution) { MethodResolver.Execute(this); } EnableInlineCache = configuration.EnableInlineCache; var timer = configuration.ProfileFunctionTime ? JSRuntime.StartTimer(configuration.ProfileJitTime, "JS/SymInit/" + Declaration) : JSRuntime.StartTimer(configuration.ProfileJitTime, "JS/SymInit"); try { var symbols = Scope.Symbols; for (var i = symbols.Count - 1; i >= 0; --i) { var symbol = symbols[i]; if (symbol.SymbolType == JSSymbol.SymbolTypes.ClosedOnLocal || symbol.SymbolType == JSSymbol.SymbolTypes.ParentLocal || symbol.SymbolType == JSSymbol.SymbolTypes.Global || symbol.SymbolType == JSSymbol.SymbolTypes.Unknown ) { symbol.AssignFieldId(); } Debug.Assert( !symbol.IsParameter || (symbol.Index == i && ( (symbol.ParameterIndex == i && (Scope.IsFunctionDeclaration || FunctionIR.Name == null)) || (symbol.ParameterIndex == (i - 1) && !Scope.IsFunctionDeclaration && FunctionIR.Name != null) ) ) , "Invalid situation!, symbol {0} should be paramter with parameter index {1} instead of {2}", symbol.Name, i, symbol.ParameterIndex); } } finally { JSRuntime.StopTimer(timer); } CurrentStatus = Status.Prepared; } }