protected virtual LocalBuilder CreateCallFrame(Invocation node) { var callFrame = _localVars.PushTemporary(Types.CallFrame.TypeOf); _ilGen.Ldloca(callFrame); _ilGen.Initobj(Types.CallFrame.TypeOf); _ilGen.Ldloca(callFrame); VisitNode(node.Function); Debug.Assert(_result.ValueType == mdr.ValueTypes.Function, "Invalid situation, {0} is not a function value type", node.Function); _ilGen.Stfld(Types.CallFrame.Function); _ilGen.Ldloca(callFrame); _ilGen.Ldflda(Types.CallFrame.Signature); _ilGen.Ldc_U8(0); _ilGen.Stfld(Types.DFunctionSignature.Value); _ilGen.Ldloca(callFrame); _ilGen.Ldc_I4(node.Arguments.Count); _ilGen.Stfld(Types.CallFrame.PassedArgsCount); var argsArraySize = node.Arguments.Count - mdr.CallFrame.InlineArgsCount; if (argsArraySize > 0) { _ilGen.Ldloca(callFrame); _ilGen.Ldc_I4(argsArraySize); _ilGen.NewArr(Types.DValue.TypeOf); _ilGen.Stfld(Types.CallFrame.Arguments); } if (JSRuntime.Instance.Configuration.ProfileStats) GenCounterIncrement("Args_" + node.Arguments.Count.ToString(), null, 1); return callFrame; }
mdr.DFunctionCode LoadArguments(Invocation node, LocalBuilder callFrame) { var knownStaticSignature = mdr.DFunctionSignature.EmptySignature; var staticallyTypedArgsCount = 0; for (var argIndex = 0; argIndex < node.Arguments.Count; ++argIndex) { var passedArg = node.Arguments[argIndex]; _ilGen.Ldloca(callFrame); Ldarg_Parameter(argIndex, true); VisitNode(passedArg); var argType = _result.ValueType; _ilGen.Call(Types.DValue.Set.Get(argType)); if (argType < mdr.ValueTypes.DValue) { knownStaticSignature.InitArgType(argIndex, argType); ++staticallyTypedArgsCount; } else { _ilGen.Ldloca(callFrame); _ilGen.Ldflda(Types.CallFrame.Signature); _ilGen.Ldc_I4(argIndex); _ilGen.Ldloca(callFrame); Ldarg_Parameter(argIndex, true); _ilGen.Call(Types.DValue.GetValueType); _ilGen.Call(Types.DFunctionSignature.InitArgType); } } if (staticallyTypedArgsCount > 0) { //Merge static signature with dynamically calculated one. _ilGen.Ldloca(callFrame); _ilGen.Ldflda(Types.CallFrame.Signature); #if DEBUG //This is to prevent error in our source code generators _ilGen.Ldloca(callFrame); _ilGen.Ldflda(Types.CallFrame.Signature); #else _ilGen.Dup(); #endif _ilGen.Ldfld(Types.DFunctionSignature.Value); _ilGen.Ldc_U8(knownStaticSignature.Value); _ilGen.Or(); _ilGen.Stfld(Types.DFunctionSignature.Value); } ///If parallel jit is enabled, we try to launch jitting for possible callee functions //if (JSRuntime.Instance.Configuration.EnableParallelJit) //{ // string lookupKey = null; // var id = function as Identifier; // if (id != null) // lookupKey = id.Text; // else // { // var indexer = function as Indexer; // if (indexer != null && indexer.FieldId != mdr.Runtime.InvalidFieldId) // lookupKey = mdr.Runtime.Instance.GetFieldName(indexer.FieldId); // } // if (lookupKey != null) // { // var funcs = JSRuntime.Instance.Speculator.Get(lookupKey); // if (funcs != null) // foreach (var f in funcs) // { // bool dummy; // f.Jit(ref knownStaticSignature, out dummy); // } // } // else // { // var funcExp = function as FunctionExpression; // if (funcExp != null) // { // bool dummy; // funcExp.Metadata.Jit(ref knownStaticSignature, out dummy); // } // } //} var targetFuncMetadata = node.TargetFunctionMetadata; bool canEmitDirectCalls = targetFuncMetadata != null && JSRuntime.Instance.Configuration.EnableDirectCalls && staticallyTypedArgsCount == node.Arguments.Count; if ( canEmitDirectCalls && targetFuncMetadata.CurrentStatus != JSFunctionMetadata.Status.Jitting //FIXME: for now we disable recursive direct calls because CreateDelegate may throw if current method calls unfinised methods ) { StopJitTimer(); //knownStaticSignature.Value |= unknownStaticSignature.Value; //We now can messup with this signature. Debug.WriteLine("Looking for {0} with sig=0x{1:X}", targetFuncMetadata.Declaration, knownStaticSignature.Value); var targetCode = targetFuncMetadata.JitSpeculatively(ref knownStaticSignature); StartJitTimer(); if (targetCode != null) { //We have everythihng ready on the stack and all params are statically typed //So we can directly call the target function //TODO: we can even use this situation for return type calculation. if (targetCode.Method == null) { //TODO: add targetcode to list to wait for it! } //var targetCode = targetFuncMetadata.UniqueInstance; //if (targetCode == null) //{ // targetCode = targetFuncMetadata.Cache.Get(staticSignature.Value); // if (targetCode == null) // targetCode = expression.TargetFunctionMetadata.Jit(ref staticSignature); //} } return targetCode; } return null; }
protected override void Visit(Invocation node) { Visit((Expression)node); }
protected override void Visit(Invocation node) { VisitNode(node.Function); VisitNodes(node.Arguments); Visit((Expression)node); }
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; }
protected override LocalBuilder CreateCallFrame(Invocation node) { var callFrame = base.CreateCallFrame(node); int profIndex = _currFuncMetadata.GetProfileIndex(node); _ilGen.Ldloc(_profiler); _ilGen.Ldc_I4(profIndex); _ilGen.Ldloca(callFrame); _ilGen.Ldfld(Types.CallFrame.Function); _ilGen.Call(Types.Operations.Internals.UpdateCallProfile); return callFrame; }
protected virtual void Visit(Invocation node) { }
internal void PopLocation(Invocation node, mdr.DFunction callTarget) { if (_currProfiler != null) { _currProfiler.GetOrAddNodeProfile(node).UpdateNodeProfile(callTarget); //NodeProfile nProfile = _currProfiler.GetNodeProfile(functionExpr); //if (nProfile != null) //{ // (nProfile as CallNodeProfile).UpdateNodeProfile(callTarget); //} //else //{ // _currProfiler.CreateNewProfile(functionExpr, callTarget); //} } }
public int GetProfileIndex(Invocation node) { return (node.ProfileIndex == -1) ? (node.ProfileIndex = InvocationNodeCount++) : node.ProfileIndex; }