public void Execute(JSFunctionMetadata functionMetadata) { var subFunctions = functionMetadata.SubFunctions; var declarations = new List <Statement>(); for (var i = 0; i < subFunctions.Count; ++i) { var func = subFunctions[i]; if (func.Scope.IsFunctionDeclaration) { HoistDeclaration(functionMetadata, func, declarations); } } if (declarations.Count > 0) { var funcIR = functionMetadata.FunctionIR; var currStatements = funcIR.Statement; currStatements.RemoveUser(funcIR); var declarationBlock = new BlockStatement(declarations); var newStatements = new BlockStatement(new List <Statement>() { declarationBlock, currStatements, }); funcIR.Replace(currStatements, newStatements); } }
public override void Visit(JSFunctionMetadata funcImp) { outStream.Write("{0}(\"calling {1}\", \"{2}_func{3}\");\n", printFuncName, funcImp.FullName, JSRuntime.Instance.Configuration.InstJSPrefix, funcCounter++); outStream.Write("++__mcjs__.PrintIndent;\n"); base.Visit(funcImp); outStream.Write("--__mcjs__.PrintIndent;\n"); }
public void Execute(JSFunctionMetadata funcMetadata) { if (funcMetadata.IsAnalyzed) { return; } if (!funcMetadata.Scope.IsEvalFunction) { return; //This is not the body in an eval() } _currFuncMetadata = funcMetadata; _implicitReturn = _currFuncMetadata.Scope.GetOrAddSymbol("_implicit_eval_return"); _implicitReturn.SymbolType = JSSymbol.SymbolTypes.HiddenLocal; _currBlock = null; _currStatementIndex = -1; _currExpressionStatement = null; VisitNode(_currFuncMetadata.FunctionIR.Statement); _currFuncMetadata.FunctionIR.Statement.Statements.Add( new ReturnStatement( new ReadIdentifierExpression(_implicitReturn) ) ); }
public override mdr.DFunctionCode.JittedMethod EndJittedMethod(JSFunctionMetadata funcMetadata, mdr.DFunctionCode funcInst) { if (funcMetadata.Scope.IsEvalFunction) { _asm.Init.WriteLine("/***** eval result *****"); //We still want to see them in the output } var instMethodName = string.Format("{0}_inst", MethodName); _asm.Init.WriteLine("\t\t\t{"); _asm.Init.WriteLine("\t\t\t\tauto funcMD = {0}; //{1}", FuncDefPath(funcMetadata), funcMetadata.FullName); _asm.Init.WriteLine("\t\t\t\tauto funcSignature = mdr::DFunctionSignature(gcnew array<mdr::ValueTypes> {{ {1} }});", instMethodName, string.Join(", ", funcInst.Signature.Types.Select(t => string.Format("mdr::ValueTypes::{0}", t)).ToArray())); _asm.Init.WriteLine("\t\t\t\tauto {0} = gcnew mjr::JSFunctionCode(funcMD, funcSignature);", instMethodName); _asm.Init.WriteLine("\t\t\t\t{0}->Method = gcnew mdr::DFunctionCode::JittedMethod(&{1});", instMethodName, MethodName); //_asm.InitCache.WriteLine("\t\t\t\t{0}->SignatureMask.Value = {1};", instMethodName, funcInst.SignatureMask.Value); //_asm.InitCache.WriteLine("\t\t\t\t{0}->Signature = mdr::DFunctionSignature(gcnew array<mdr::ValueTypes> {{ {1} }});", instMethodName, string.Join(", ", funcInst.Signature.Types.Select(t => string.Format("mdr::ValueTypes::{0}", t)).ToArray())); _asm.Init.WriteLine("\t\t\t\tfuncMD->Cache->Add({0});", instMethodName); _asm.Init.WriteLine("\t\t\t\tfor (auto i = 0; i < funcMD->Scope->Symbols->Count; ++i) funcMD->Scope->Symbols[i]->AssignFieldId();"); _asm.Init.WriteLine("\t\t\t}"); if (funcMetadata.Scope.IsEvalFunction) { _asm.Init.WriteLine("***** eval result *****/"); } return(base.EndJittedMethod(funcMetadata, funcInst)); }
public void Execute(JSFunctionMetadata funcMetadata) { _currFuncMetadata = funcMetadata; _currFuncCode = null; _ilGen = null; Execute(); }
public void Execute(JSFunctionMetadata func) { output.WriteStartElement("Program"); Dump(func, 0, 0); output.WriteEndElement(); output.Flush(); }
public void Execute(JSFunctionMetadata functionMetadata) { // functions declared in the global scope can be overwritten by other functions or // other scripts in the page, so do not resolve! foreach (Invocation invocation in functionMetadata.Scope.Invocations) { DetectTargetFuncMetadata(functionMetadata, invocation, invocation.Function); } }
public InlinedInvocation( JSFunctionMetadata targetFunctionMetadata , Scope scope , BlockStatement statement , ReadIdentifierExpression returnValue) : base(returnValue) { TargetFunctionMetadata = targetFunctionMetadata; Scope = scope; Statement = statement; Use(Statement); }
string FuncDefPath(JSFunctionMetadata funcMetadata) { if (funcMetadata.ParentFunction == null) { var key = JSRuntime.Instance.Scripts.GetScriptKey(funcMetadata); if (key != null) { key = key.Replace('\\', '/'); } return(string.Format(@"runtime->Scripts->GetMetadata(L""{0}"")", key)); } return(string.Format("{0}->SubFunctions[{1}]", FuncDefPath(funcMetadata.ParentFunction), funcMetadata.FuncDefinitionIndex)); }
public FunctionExpression MakeFunctionExpression(Scope scope, IIdentifier name, IIdentifierList parameters, IStatement statement, Scope newScope) { var namedParams = parameters as List <ReadIdentifierExpression>; Debug.Assert(namedParams.Count == 0 || newScope.IsFunction, "parameters must be declared in a function scope"); for (var i = 0; i < namedParams.Count; ++i) { var symbol = namedParams[i].Symbol; Debug.Assert(newScope.GetSymbol(symbol.Name) == symbol && symbol.ContainerScope == newScope, "Invalid situation, parameter symbol is not in the newScope"); symbol.SymbolType = JSSymbol.SymbolTypes.Local; //already know symbol.ContainerScope.IsFunction, so no need for hoisting symbol.ParameterIndex = i; } var funcName = name as ReadIdentifierExpression; if (newScope.IsFunctionDeclaration) { Debug.Assert(funcName != null, "the function declaration must have a name"); Debug.Assert(scope.GetSymbol(funcName.Symbol.Name) == funcName.Symbol && funcName.Symbol.ContainerScope == scope, "Name of function declaration must exist in the outer scope"); DeclareHoistedLocal(funcName.Symbol); //This is defined now in its scope! } else if (newScope.IsProgram) { Debug.Assert(funcName == null, "program scope cannot have a name!"); } else { Debug.Assert(newScope.IsFunction == true, "The FunctionExpression scope is not properly marked"); if (funcName != null) { Debug.Assert(newScope.GetSymbol(funcName.Symbol.Name) == funcName.Symbol && funcName.Symbol.ContainerScope == newScope, "Name of function expression must exist in its own scope"); funcName.Symbol.SymbolType = JSSymbol.SymbolTypes.Local; //This is defined now in its scope, & we already know funcName.Symbol.ContainerScope.IsFunction, so no need for hoisting } } var func = new FunctionExpression(newScope, funcName, namedParams, (BlockStatement)statement); var metadata = new JSFunctionMetadata(func); func.Metadata = metadata; if (scope != null) { scope.AddSubFunction(metadata); } return(func); }
void InlineInvocation(CallExpression invocation, JSFunctionMetadata targetFuncMetadata) { _targetFuncMetadata = targetFuncMetadata; _call = invocation; Debug.WriteLine("Trying to inline function {0}", _targetFuncMetadata.Declaration); _targetFuncMetadata.Analyze(); //Just to make sure it is analyzed if (JSRuntime.Instance.Configuration.ProfileStats) { JSRuntime.Instance.Counters.GetCounter("Attempted Inline").Count++; } if (!CanInline(_targetFuncMetadata)) { return; } if (JSRuntime.Instance.Configuration.ProfileStats) { JSRuntime.Instance.Counters.GetCounter("Succeeded Inline").Count++; } _functionsBeingInlined.AddLast(_targetFuncMetadata); _round++; throw new NotImplementedException(); //TODO: we need to update this algorithm based on the recent changes to the scope _newScope = new Scope(_currentTargetScope); _returnValueSymbol = _newScope.AddSymbol(RenameSymbol("retVal")); _returnValueSymbol.SymbolType = JSSymbol.SymbolTypes.HiddenLocal; _call.InlinedIR = new InlinedInvocation( _targetFuncMetadata , _newScope , BuildInlinedBody() , new ReadIdentifierExpression(_returnValueSymbol) ); _call.InlinedIR.AddUser(_call); Debug.WriteLine("Inlined function {0}", _targetFuncMetadata.Declaration); _functionsBeingInlined.RemoveLast(); }
/// <summary> /// Checks requirements and heuristics and determines whether we should inline or not /// </summary> /// <returns></returns> private bool CanInline(JSFunctionMetadata funcMetadata) { var scope = funcMetadata.Scope; if (funcMetadata.SubFunctions.Count > 0 || //don't inline if the target has subfunctions //TODO:unless none of subfunction (tree) has ParenLocal symbols scope.AstCost > MaximumAstCostToInline || //TODO: we don't have a good cost function scope.HasClosedOnSymbol || //TODO: we can inline some functions that have closed on variables scope.HasThisSymbol || //TODO: for now we don't inline if there is "this" keyword in the function, but can be done scope.HasEval || //we don't know what direct eval can do scope.HasArgumentsSymbol || //TODO: we can actually do this as well, with some care at call site _functionsBeingInlined.Contains(funcMetadata)//recursive call ) { Debug.WriteLine("Cannot inline function {0}", funcMetadata.Declaration); return(false); } return(true); }
public mdr.DFunctionMetadata.InlineCachedMethod EndICMethod(JSFunctionMetadata funcMetadata) { var timer = JSRuntime.Instance.Configuration.ProfileFunctionTime ? JSRuntime.StartTimer(JSRuntime.Instance.Configuration.ProfileJitTime, "JS/Jit/ICClr" + funcMetadata.Declaration) : JSRuntime.StartTimer(JSRuntime.Instance.Configuration.ProfileJitTime, "JS/Jit/ICClr"); Delegate md; try { md = EndMethod(typeof(mdr.DFunctionMetadata.InlineCachedMethod)); } finally { JSRuntime.StopTimer(timer); } return((mdr.DFunctionMetadata.InlineCachedMethod)md); }
public void Execute(JSFunctionMetadata funcMetadata) { Debug.Assert(!funcMetadata.IsAnalyzed, "Function {0} is already analysed", funcMetadata.Declaration); _currFuncMetadata = funcMetadata; var scope = _currFuncMetadata.FunctionIR.Scope; Debug.Assert(scope.IsFunction, "Scope of function {0} must be a function type", funcMetadata.Declaration); if (scope.IsProgram) { ///By default, there might be multiple scripts loaded, and hence we don't have full visibility over all program. ///therefore we should be conservative and assume that there will be unknown sub-functions with all sorts of possible side effects ///unless there is a switch for a special mode in the engine that says we can be more aggressive ///and assume for example there is only going to be on top level program ///in generatl, one other option is also to assume all symbols in the main program (top level script) are marked global, however, knowing they are local may help later scope.HasUnknownSubFunction = true; //TODO: we may have to artificially add the "arguments" to the global scope, and later in the program set it to [] AnalyzeScope(scope); scope.HasLocalSymbol = false; //We just converted everything to global! } else { if (scope.IsEvalFunction) { ImplicitReturnInserter.Execute(funcMetadata); } for (var i = _currFuncMetadata.SubFunctions.Count - 1; i >= 0; --i) { var f = _currFuncMetadata.SubFunctions[i]; f.Analyze(); scope.HasUnknownSubFunction = f.Scope.HasEval || f.Scope.HasUnknownSubFunction; } ///<Mehrdad> ///NOTE: we used to inline functions here, but in the new model, we only do it when the function is hot. ///Also, we have separate scope for the inlined functions, so we will resolve them on demand later. ///</Mehrdad> AnalyzeScope(scope); } }
void HoistDeclaration(JSFunctionMetadata func, JSFunctionMetadata declaredFunc, List <Statement> declarations) { var writeId = declaredFunc.FunctionIR.User as WriteIdentifierExpression; Debug.Assert(writeId != null, "Invalid situation, user of the FunctionIR must be a WriteIdentifier"); var funcDeclStatement = writeId.User as FunctionDeclarationStatement; Debug.Assert(funcDeclStatement != null, "Invalid situation, user of the WriteIdentifier must be a FunctionDeclarationStatement"); var declarationUser = funcDeclStatement.User; Debug.Assert(declarationUser != null, "Invalid situation, user of FunctionDeclarationStatement must not be null"); var emptyStatement = new EmptyStatement(); //TODO: we can either remove the statement or use some other marker declarationUser.Replace(funcDeclStatement, emptyStatement); funcDeclStatement.RemoveUser(declarationUser); declarations.Add(funcDeclStatement); }
public virtual mdr.DFunctionCode.JittedMethod EndJittedMethod(JSFunctionMetadata funcMetadata, mdr.DFunctionCode funcInst) { var timer = JSRuntime.Instance.Configuration.ProfileFunctionTime ? JSRuntime.StartTimer(JSRuntime.Instance.Configuration.ProfileJitTime, "JS/Jit/Clr" + funcMetadata.Declaration) : JSRuntime.StartTimer(JSRuntime.Instance.Configuration.ProfileJitTime, "JS/Jit/Clr"); Delegate md; try { md = EndMethod(typeof(mdr.DFunctionCode.JittedMethod)); } finally { JSRuntime.StopTimer(timer); } return((mdr.DFunctionCode.JittedMethod)md); }
public void Execute(JSFunctionMetadata funcMetadata) { Debug.Assert(!funcMetadata.IsAnalyzed, "Function {0} is already analysed", funcMetadata.Declaration); _currFuncMetadata = funcMetadata; var scope = _currFuncMetadata.FunctionIR.Scope; Debug.Assert(scope.IsFunction, "Scope of function {0} must be a function type", funcMetadata.Declaration); if (scope.IsProgram) { ///By default, there might be multiple scripts loaded, and hence we don't have full visibility over all program. ///therefore we should be conservative and assume that there will be unknown sub-functions with all sorts of possible side effects ///unless there is a switch for a special mode in the engine that says we can be more aggressive ///and assume for example there is only going to be on top level program ///in generatl, one other option is also to assume all symbols in the main program (top level script) are marked global, however, knowing they are local may help later scope.HasUnknownSubFunction = true; //TODO: we may have to artificially add the "arguments" to the global scope, and later in the program set it to [] AnalyzeScope(scope); scope.HasLocalSymbol = false; //We just converted everything to global! } else { if (scope.IsEvalFunction) ImplicitReturnInserter.Execute(funcMetadata); for (var i = _currFuncMetadata.SubFunctions.Count - 1; i >= 0; --i) { var f = _currFuncMetadata.SubFunctions[i]; f.Analyze(); scope.HasUnknownSubFunction = f.Scope.HasEval || f.Scope.HasUnknownSubFunction; } ///<Mehrdad> ///NOTE: we used to inline functions here, but in the new model, we only do it when the function is hot. ///Also, we have separate scope for the inlined functions, so we will resolve them on demand later. ///</Mehrdad> AnalyzeScope(scope); } }
public void Execute(JSFunctionMetadata funcMetadata) { if (funcMetadata.IsAnalyzed) return; if (!funcMetadata.Scope.IsEvalFunction) return; //This is not the body in an eval() _currFuncMetadata = funcMetadata; _implicitReturn = _currFuncMetadata.Scope.GetOrAddSymbol("_implicit_eval_return"); _implicitReturn.SymbolType = JSSymbol.SymbolTypes.HiddenLocal; _currBlock = null; _currStatementIndex = -1; _currExpressionStatement = null; VisitNode(_currFuncMetadata.FunctionIR.Statement); _currFuncMetadata.FunctionIR.Statement.Statements.Add( new ReturnStatement( new ReadIdentifierExpression(_implicitReturn) ) ); }
public void Execute(JSFunctionMetadata funcMetadata) { if (JSRuntime.Instance.Configuration.ProfileStats) { JSRuntime.Instance.Counters.GetCounter(Name).Count++; } var timer = JSRuntime.Instance.Configuration.ProfileFunctionTime ? JSRuntime.StartTimer(TimerCondition(), Name + funcMetadata.Declaration) : JSRuntime.StartTimer(TimerCondition(), Name); try { var alg = Allocate(); alg.Execute(funcMetadata); Release(alg); } finally { JSRuntime.StopTimer(timer); } }
void DetectTargetFuncMetadata(JSFunctionMetadata functionMetadata, Invocation expression, Expression function) { // functions declared in the global scope can be overwritten by other functions or // other scripts in the page, so do not resolve! var parenExp = function as ParenExpression; if (parenExp != null) { DetectTargetFuncMetadata(functionMetadata, expression, parenExp.Expression); return; } var toFunction = function as ToFunction; if (toFunction != null) { DetectTargetFuncMetadata(functionMetadata, expression, toFunction.Expression); return; } var funcExp = function as FunctionExpression; if (funcExp != null) { Debug.WriteLine(new JSSourceLocation(functionMetadata, expression), " function expression detected."); expression.TargetFunctionMetadata = funcExp.Metadata; return; } else { var id = function as Identifier; if (id != null) { var symbol = id.Symbol;// _currFuncMetadata.GetSymbol(id.Text); Debug.WriteLine(new JSSourceLocation(functionMetadata, id), "Method call to {0}:", symbol.Name); Debug.Assert(symbol != null, new JSSourceLocation(functionMetadata, id), "Symbol cannot be null here!"); if (symbol.ResolvedSymbol != null) symbol = symbol.ResolvedSymbol; var jsfunc = symbol.ContainerScope.ContainerFunction; //JSFunctionMetadata jsfunc = functionMetadata; //for (int i = 0; i < symbol.AncestorDistance; i++) // jsfunc = jsfunc.ParentFunction; //if (!jsfunc.Scope.IsProgram) //do not resolve global function declaration targets if (!symbol.ContainerScope.IsProgram) { //symbol = jsfunc.Scope.GetSymbol(id.Symbol.Name); if (symbol.SubFunctionIndex != mdr.Runtime.InvalidIndex && symbol.NonLocalWritersCount == 0) { expression.TargetFunctionMetadata = jsfunc.SubFunctions[symbol.SubFunctionIndex]; // we have found the corresponding JSFunctionImp instance Debug.WriteLine(new JSSourceLocation(jsfunc, expression), string.Format("function declaration found. JSFunctionImp name: {0}", jsfunc.SubFunctions[symbol.SubFunctionIndex].FullName)); } else if (symbol.Writers.Count == 1) { // if a symbol is assigned once and the assigned expression is a function, we can find // the corresponding JSFunctionImp statically when the variable is called. For example: var x = function() {}; x(); var wfunc = symbol.Writers[0].Value as FunctionExpression; if (wfunc != null) { Debug.Write(new JSSourceLocation(functionMetadata, wfunc), " function expression detected."); expression.TargetFunctionMetadata = wfunc.Metadata; } } } else Debug.WriteLine(new JSSourceLocation(jsfunc, expression), "function {0} was not resolved because it was declared globally", jsfunc.Declaration); } } Debug.WriteLine(""); return; }
void DetectTargetFuncMetadata(JSFunctionMetadata functionMetadata, Invocation expression, Expression function) { // functions declared in the global scope can be overwritten by other functions or // other scripts in the page, so do not resolve! var parenExp = function as ParenExpression; if (parenExp != null) { DetectTargetFuncMetadata(functionMetadata, expression, parenExp.Expression); return; } var toFunction = function as ToFunction; if (toFunction != null) { DetectTargetFuncMetadata(functionMetadata, expression, toFunction.Expression); return; } var funcExp = function as FunctionExpression; if (funcExp != null) { Debug.WriteLine(new JSSourceLocation(functionMetadata, expression), " function expression detected."); expression.TargetFunctionMetadata = funcExp.Metadata; return; } else { var id = function as Identifier; if (id != null) { var symbol = id.Symbol;// _currFuncMetadata.GetSymbol(id.Text); Debug.WriteLine(new JSSourceLocation(functionMetadata, id), "Method call to {0}:", symbol.Name); Debug.Assert(symbol != null, new JSSourceLocation(functionMetadata, id), "Symbol cannot be null here!"); if (symbol.ResolvedSymbol != null) { symbol = symbol.ResolvedSymbol; } var jsfunc = symbol.ContainerScope.ContainerFunction; //JSFunctionMetadata jsfunc = functionMetadata; //for (int i = 0; i < symbol.AncestorDistance; i++) // jsfunc = jsfunc.ParentFunction; //if (!jsfunc.Scope.IsProgram) //do not resolve global function declaration targets if (!symbol.ContainerScope.IsProgram) { //symbol = jsfunc.Scope.GetSymbol(id.Symbol.Name); if (symbol.SubFunctionIndex != mdr.Runtime.InvalidIndex && symbol.NonLocalWritersCount == 0) { expression.TargetFunctionMetadata = jsfunc.SubFunctions[symbol.SubFunctionIndex]; // we have found the corresponding JSFunctionImp instance Debug.WriteLine(new JSSourceLocation(jsfunc, expression), string.Format("function declaration found. JSFunctionImp name: {0}", jsfunc.SubFunctions[symbol.SubFunctionIndex].FullName)); } else if (symbol.Writers.Count == 1) { // if a symbol is assigned once and the assigned expression is a function, we can find // the corresponding JSFunctionImp statically when the variable is called. For example: var x = function() {}; x(); var wfunc = symbol.Writers[0].Value as FunctionExpression; if (wfunc != null) { Debug.Write(new JSSourceLocation(functionMetadata, wfunc), " function expression detected."); expression.TargetFunctionMetadata = wfunc.Metadata; } } } else { Debug.WriteLine(new JSSourceLocation(jsfunc, expression), "function {0} was not resolved because it was declared globally", jsfunc.Declaration); } } } Debug.WriteLine(""); return; }
public mdr.DFunctionMetadata.InlineCachedMethod EndICMethod(JSFunctionMetadata funcMetadata) { var timer = JSRuntime.Instance.Configuration.ProfileFunctionTime ? JSRuntime.StartTimer(JSRuntime.Instance.Configuration.ProfileJitTime, "JS/Jit/ICClr" + funcMetadata.Declaration) : JSRuntime.StartTimer(JSRuntime.Instance.Configuration.ProfileJitTime, "JS/Jit/ICClr"); Delegate md; try { md = EndMethod(typeof(mdr.DFunctionMetadata.InlineCachedMethod)); } finally { JSRuntime.StopTimer(timer); } return (mdr.DFunctionMetadata.InlineCachedMethod)md; }
public static void Execute(JSFunctionMetadata funcMetada) { _pool.Execute(funcMetada); }
public Profiler(JSFunctionMetadata funcMetadata) { _currFuncMetadata = funcMetadata; }
public FunctionExpression MakeFunctionExpression(Scope scope, IIdentifier name, IIdentifierList parameters, IStatement statement, Scope newScope) { var namedParams = parameters as List<ReadIdentifierExpression>; Debug.Assert(namedParams.Count == 0 || newScope.IsFunction, "parameters must be declared in a function scope"); for (var i = 0; i < namedParams.Count; ++i) { var symbol = namedParams[i].Symbol; Debug.Assert(newScope.GetSymbol(symbol.Name) == symbol && symbol.ContainerScope == newScope, "Invalid situation, parameter symbol is not in the newScope"); symbol.SymbolType = JSSymbol.SymbolTypes.Local; //already know symbol.ContainerScope.IsFunction, so no need for hoisting symbol.ParameterIndex = i; } var funcName = name as ReadIdentifierExpression; if (newScope.IsFunctionDeclaration) { Debug.Assert(funcName != null, "the function declaration must have a name"); Debug.Assert(scope.GetSymbol(funcName.Symbol.Name) == funcName.Symbol && funcName.Symbol.ContainerScope == scope, "Name of function declaration must exist in the outer scope"); DeclareHoistedLocal(funcName.Symbol); //This is defined now in its scope! } else if (newScope.IsProgram) { Debug.Assert(funcName == null, "program scope cannot have a name!"); } else { Debug.Assert(newScope.IsFunction == true, "The FunctionExpression scope is not properly marked"); if (funcName != null) { Debug.Assert(newScope.GetSymbol(funcName.Symbol.Name) == funcName.Symbol && funcName.Symbol.ContainerScope == newScope, "Name of function expression must exist in its own scope"); funcName.Symbol.SymbolType = JSSymbol.SymbolTypes.Local; //This is defined now in its scope, & we already know funcName.Symbol.ContainerScope.IsFunction, so no need for hoisting } } var func = new FunctionExpression(newScope, funcName, namedParams, (BlockStatement)statement); var metadata = new JSFunctionMetadata(func); func.Metadata = metadata; if (scope != null) scope.AddSubFunction(metadata); return func; }
internal CodeGenerationInfo(JSFunctionMetadata funcMetadata, JSFunctionCode funcCode, ILGen.BaseILGenerator ilGen) { FuncMetadata = funcMetadata; FuncCode = funcCode; IlGen = ilGen; }
public void Execute(ref mdr.CallFrame callFrame) { _currFuncMetadata = (JSFunctionMetadata)callFrame.Function.Metadata; Timer = JSRuntime.Instance.Configuration.ProfileFunctionTime ? JSRuntime.StartTimer(JSRuntime.Instance.Configuration.ProfileExecuteTime, "JS/Interpret/" + _currFuncMetadata.Declaration) : JSRuntime.StartTimer(JSRuntime.Instance.Configuration.ProfileExecuteTime, "JS/Interpret"); try { _currScope = _currFuncMetadata.Scope; _currProfiler = ((JSFunctionCode)callFrame.Function.Code).Profiler; Debug.WriteLine("Interpretting {0} with sig=0x{1:X}-->{2} for {3}th time" , _currFuncMetadata.Declaration , callFrame.Signature.Value , string.Join(",", callFrame.Signature.Types) , (_currProfiler!=null ? _currProfiler.ExecutionCount.ToString() : "n-")); RunProlog(ref callFrame); RunBody(ref callFrame); RunEilog(ref callFrame); } finally { JSRuntime.StopTimer(Timer); } }
public void Execute(JSFunctionMetadata funcMetadata) { throw new NotImplementedException(); }
string FuncDefPath(JSFunctionMetadata funcMetadata) { if (funcMetadata.ParentFunction == null) { var key = JSRuntime.Instance.Scripts.GetScriptKey(funcMetadata); if (key != null) key = key.Replace('\\', '/'); return string.Format(@"runtime->Scripts->GetMetadata(L""{0}"")", key); } return string.Format("{0}->SubFunctions[{1}]", FuncDefPath(funcMetadata.ParentFunction), funcMetadata.FuncDefinitionIndex); }
/// <summary> /// Checks requirements and heuristics and determines whether we should inline or not /// </summary> /// <returns></returns> private bool CanInline(JSFunctionMetadata funcMetadata) { var scope = funcMetadata.Scope; if (funcMetadata.SubFunctions.Count > 0 //don't inline if the target has subfunctions //TODO:unless none of subfunction (tree) has ParenLocal symbols || scope.AstCost > MaximumAstCostToInline //TODO: we don't have a good cost function || scope.HasClosedOnSymbol //TODO: we can inline some functions that have closed on variables || scope.HasThisSymbol //TODO: for now we don't inline if there is "this" keyword in the function, but can be done || scope.HasEval //we don't know what direct eval can do || scope.HasArgumentsSymbol //TODO: we can actually do this as well, with some care at call site || _functionsBeingInlined.Contains(funcMetadata)//recursive call ) { Debug.WriteLine("Cannot inline function {0}", funcMetadata.Declaration); return false; } return true; }
void InlineInvocation(CallExpression invocation, JSFunctionMetadata targetFuncMetadata) { _targetFuncMetadata = targetFuncMetadata; _call = invocation; Debug.WriteLine("Trying to inline function {0}", _targetFuncMetadata.Declaration); _targetFuncMetadata.Analyze(); //Just to make sure it is analyzed if (JSRuntime.Instance.Configuration.ProfileStats) JSRuntime.Instance.Counters.GetCounter("Attempted Inline").Count++; if (!CanInline(_targetFuncMetadata)) return; if (JSRuntime.Instance.Configuration.ProfileStats) JSRuntime.Instance.Counters.GetCounter("Succeeded Inline").Count++; _functionsBeingInlined.AddLast(_targetFuncMetadata); _round++; throw new NotImplementedException(); //TODO: we need to update this algorithm based on the recent changes to the scope _newScope = new Scope(_currentTargetScope); _returnValueSymbol = _newScope.AddSymbol(RenameSymbol("retVal")); _returnValueSymbol.SymbolType = JSSymbol.SymbolTypes.HiddenLocal; _call.InlinedIR = new InlinedInvocation( _targetFuncMetadata , _newScope , BuildInlinedBody() , new ReadIdentifierExpression(_returnValueSymbol) ); _call.InlinedIR.AddUser(_call); Debug.WriteLine("Inlined function {0}", _targetFuncMetadata.Declaration); _functionsBeingInlined.RemoveLast(); }
public virtual mdr.DFunctionCode.JittedMethod EndJittedMethod(JSFunctionMetadata funcMetadata, mdr.DFunctionCode funcInst) { var timer = JSRuntime.Instance.Configuration.ProfileFunctionTime ? JSRuntime.StartTimer(JSRuntime.Instance.Configuration.ProfileJitTime, "JS/Jit/Clr" + funcMetadata.Declaration) : JSRuntime.StartTimer(JSRuntime.Instance.Configuration.ProfileJitTime, "JS/Jit/Clr"); Delegate md; try { md = EndMethod(typeof(mdr.DFunctionCode.JittedMethod)); } finally { JSRuntime.StopTimer(timer); } return (mdr.DFunctionCode.JittedMethod)md; }
public static void Execute(JSFunctionMetadata funcMetadata) { _pool.Execute(funcMetadata); }
public static void Run(string filename, JSFunctionMetadata func) { var dumper = new XmlDumper(new System.IO.StreamWriter(filename)); dumper.Execute(func); }
public override mdr.DFunctionCode.JittedMethod EndJittedMethod(JSFunctionMetadata funcMetadata, mdr.DFunctionCode funcInst) { if (funcMetadata.Scope.IsEvalFunction) _asm.Init.WriteLine("/***** eval result *****"); //We still want to see them in the output var instMethodName = string.Format("{0}_inst", MethodName); _asm.Init.WriteLine("\t\t\t{"); _asm.Init.WriteLine("\t\t\t\tauto funcMD = {0}; //{1}", FuncDefPath(funcMetadata), funcMetadata.FullName); _asm.Init.WriteLine("\t\t\t\tauto funcSignature = mdr::DFunctionSignature(gcnew array<mdr::ValueTypes> {{ {1} }});", instMethodName, string.Join(", ", funcInst.Signature.Types.Select(t => string.Format("mdr::ValueTypes::{0}", t)).ToArray())); _asm.Init.WriteLine("\t\t\t\tauto {0} = gcnew mjr::JSFunctionCode(funcMD, funcSignature);", instMethodName); _asm.Init.WriteLine("\t\t\t\t{0}->Method = gcnew mdr::DFunctionCode::JittedMethod(&{1});", instMethodName, MethodName); //_asm.InitCache.WriteLine("\t\t\t\t{0}->SignatureMask.Value = {1};", instMethodName, funcInst.SignatureMask.Value); //_asm.InitCache.WriteLine("\t\t\t\t{0}->Signature = mdr::DFunctionSignature(gcnew array<mdr::ValueTypes> {{ {1} }});", instMethodName, string.Join(", ", funcInst.Signature.Types.Select(t => string.Format("mdr::ValueTypes::{0}", t)).ToArray())); _asm.Init.WriteLine("\t\t\t\tfuncMD->Cache->Add({0});", instMethodName); _asm.Init.WriteLine("\t\t\t\tfor (auto i = 0; i < funcMD->Scope->Symbols->Count; ++i) funcMD->Scope->Symbols[i]->AssignFieldId();"); _asm.Init.WriteLine("\t\t\t}"); if (funcMetadata.Scope.IsEvalFunction) _asm.Init.WriteLine("***** eval result *****/"); return base.EndJittedMethod(funcMetadata, funcInst); }