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);
                }
            }
Exemple #2
0
 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");
 }
Exemple #3
0
            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)
                        )
                    );
            }
Exemple #4
0
        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));
        }
Exemple #5
0
 public void Execute(JSFunctionMetadata funcMetadata)
 {
     _currFuncMetadata = funcMetadata;
     _currFuncCode     = null;
     _ilGen            = null;
     Execute();
 }
Exemple #6
0
 public void Execute(JSFunctionMetadata func)
 {
     output.WriteStartElement("Program");
     Dump(func, 0, 0);
     output.WriteEndElement();
     output.Flush();
 }
Exemple #7
0
 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");
 }
Exemple #8
0
 public void Execute(JSFunctionMetadata funcMetadata) 
 {
   _currFuncMetadata = funcMetadata;
   _currFuncCode = null;
   _ilGen = null;
   Execute();
 }
Exemple #9
0
 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);
     }
 }
Exemple #10
0
 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);
    }
Exemple #12
0
 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));
 }
Exemple #13
0
        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);
        }
Exemple #17
0
            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);
        }
Exemple #20
0
      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)
            )
        );
      }
Exemple #22
0
        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);
            }
        }
Exemple #23
0
      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;
      }
Exemple #24
0
            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;
            }
Exemple #25
0
 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;
 }
Exemple #26
0
 public static void Execute(JSFunctionMetadata funcMetada)
 {
     _pool.Execute(funcMetada);
 }
Exemple #27
0
 public Profiler(JSFunctionMetadata funcMetadata)
 {
     _currFuncMetadata = funcMetadata;
 }
Exemple #28
0
    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;
    }
Exemple #29
0
 internal CodeGenerationInfo(JSFunctionMetadata funcMetadata, JSFunctionCode funcCode, ILGen.BaseILGenerator ilGen)
 {
   FuncMetadata = funcMetadata;
   FuncCode = funcCode;
   IlGen = ilGen;
 }
Exemple #30
0
    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();
 }
Exemple #32
0
 public void Execute(JSFunctionMetadata funcMetadata) { throw new NotImplementedException(); }
Exemple #33
0
 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);
 }
Exemple #34
0
      /// <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;
      }
Exemple #35
0
      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();
      }
Exemple #36
0
    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); }
Exemple #38
0
        public static void Run(string filename, JSFunctionMetadata func)
        {
            var dumper = new XmlDumper(new System.IO.StreamWriter(filename));

            dumper.Execute(func);
        }
Exemple #39
0
        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);
        }
Exemple #40
0
 internal CodeGenerationInfo(JSFunctionMetadata funcMetadata, JSFunctionCode funcCode, ILGen.BaseILGenerator ilGen)
 {
     FuncMetadata = funcMetadata;
     FuncCode     = funcCode;
     IlGen        = ilGen;
 }