Exemplo n.º 1
0
    public ReadIdentifierExpression(JSSymbol symbol, int offset = 0)
      :base(symbol)
    {
      SourceOffset = offset;

      symbol.Readers.Add(this);
    }
Exemplo n.º 2
0
    public VariableDeclaration(JSSymbol identifier, WriteIdentifierExpression initialization)
    {
      Symbol = identifier;
      Initialization = initialization;

      Use(Initialization);
    }
Exemplo n.º 3
0
        internal LocalBuilder Get(JSSymbol symbol)
        {
            LocalBuilder local;

            _symbolLocals.TryGetValue(symbol, out local);
            return(local);
        }
Exemplo n.º 4
0
 internal LocalBuilder Declare(LocalBuilder local, JSSymbol symbol)
 {
     //Get(symbol) is not cheap, we want to write the following ASSERT in a way that it goes away in release
     Debug.Assert(Get(symbol) == null, "Symbol {0} already has a local variable of type {1}", symbol.Name, ((Get(symbol) != null) ? Get(symbol).LocalType.ToString() : ""));
     _symbolLocals.Add(symbol, local);
     return(local);
 }
Exemplo n.º 5
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)
                        )
                    );
            }
Exemplo n.º 6
0
        public ReadIdentifierExpression(JSSymbol symbol, int offset = 0)
            : base(symbol)
        {
            SourceOffset = offset;

            symbol.Readers.Add(this);
        }
Exemplo n.º 7
0
        public VariableDeclaration(JSSymbol identifier, WriteIdentifierExpression initialization)
        {
            Symbol         = identifier;
            Initialization = initialization;

            Use(Initialization);
        }
Exemplo n.º 8
0
        private void Release(JSSymbol symbol)
        {
            //Technically we should never call this function, it will be unsafe!
            var local = Get(symbol);

            Debug.Assert(local != null, "Symbol {0} does not have a local variable assigned to", symbol.Name);
            _symbolLocals.Remove(symbol);
            Release(symbol.Name);
        }
Exemplo n.º 9
0
    public WriteIdentifierExpression(JSSymbol symbol, Expression value)
      : base(symbol)
    {
      Debug.Assert(value != null, "Value cannot be null");
      symbol.Writers.Add(this);

      Value = value;
      SourceOffset = value.SourceOffset;

      Use(Value);
    }
        public WriteIdentifierExpression(JSSymbol symbol, Expression value)
            : base(symbol)
        {
            Debug.Assert(value != null, "Value cannot be null");
            symbol.Writers.Add(this);

            Value        = value;
            SourceOffset = value.SourceOffset;

            Use(Value);
        }
 protected override void DeclareNonParamSymbol(JSSymbol symbol, mdr.ValueTypes symbolValueType, LocalBuilder contextMap)
 {
   if (symbol.SymbolType == JSSymbol.SymbolTypes.Global && _currFuncMetadata.EnableInlineCache)
   {
     if (_globalContext == null)
     {
       _globalContext = _localVars.Declare(Types.DObject.TypeOf, "__gc");
       _ilGen.LoadRuntimeInstance();
       _ilGen.Ldfld(Types.Runtime.GlobalContext);
       _ilGen.Stloc(_globalContext);
     }
   }
   else
     base.DeclareNonParamSymbol(symbol, symbolValueType, contextMap);
 }
Exemplo n.º 12
0
 /// <summary>
 /// In javascript all "var" declarations must be hoisted to the top of the function. 
 /// in other words, they are local symbols of the function scope, even if they are 
 /// defined in any inner scope. 
 /// this function will take care of that. 
 /// </summary>
 void DeclareHoistedLocal(JSSymbol symbol)
 {
   var scope = symbol.ContainerScope;
   if (scope.IsFunction)
   {
     symbol.SymbolType = JSSymbol.SymbolTypes.Local;
   }
   else
   {
     while (!scope.IsFunction)
       scope = scope.OuterScope;
     var resolvedSymbol = scope.GetOrAddSymbol(symbol.Name);
     resolvedSymbol.SymbolType = JSSymbol.SymbolTypes.Local;
     symbol.SymbolType = JSSymbol.SymbolTypes.OuterDuplicate;
     symbol.ResolvedSymbol = resolvedSymbol;
   }
 }
 protected override void DeclareNonParamSymbol(JSSymbol symbol, mdr.ValueTypes symbolValueType, LocalBuilder contextMap)
 {
     if (symbol.SymbolType == JSSymbol.SymbolTypes.Global && _currFuncMetadata.EnableInlineCache)
     {
         if (_globalContext == null)
         {
             _globalContext = _localVars.Declare(Types.DObject.TypeOf, "__gc");
             _ilGen.LoadRuntimeInstance();
             _ilGen.Ldfld(Types.Runtime.GlobalContext);
             _ilGen.Stloc(_globalContext);
         }
     }
     else
     {
         base.DeclareNonParamSymbol(symbol, symbolValueType, contextMap);
     }
 }
Exemplo n.º 14
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();
            }
Exemplo n.º 15
0
            public override void Visit(ForEachInStatement node)
            {
                JSSymbol symbol = null;
                var      vds    = node.Initialization as VariableDeclarationStatement;

                if (vds != null && vds.Declarations.Count > 0)
                {
                    symbol = vds.Declarations[0].Symbol;// _cgInfo.FuncMetadata.GetSymbol(vds.Identifier);
                }
                else
                {
                    //TODO: Make sure that other cases are covered!
                }
                if (symbol != null)
                {
                    SetType(symbol, mdr.ValueTypes.String);
                }
            }
Exemplo n.º 16
0
        /// <summary>
        /// In javascript all "var" declarations must be hoisted to the top of the function.
        /// in other words, they are local symbols of the function scope, even if they are
        /// defined in any inner scope.
        /// this function will take care of that.
        /// </summary>
        void DeclareHoistedLocal(JSSymbol symbol)
        {
            var scope = symbol.ContainerScope;

            if (scope.IsFunction)
            {
                symbol.SymbolType = JSSymbol.SymbolTypes.Local;
            }
            else
            {
                while (!scope.IsFunction)
                {
                    scope = scope.OuterScope;
                }
                var resolvedSymbol = scope.GetOrAddSymbol(symbol.Name);
                resolvedSymbol.SymbolType = JSSymbol.SymbolTypes.Local;
                symbol.SymbolType         = JSSymbol.SymbolTypes.OuterDuplicate;
                symbol.ResolvedSymbol     = resolvedSymbol;
            }
        }
Exemplo n.º 17
0
            private JSSymbol GetRenamedSymbolOf(JSSymbol s)
            {
                JSSymbol newSymbol = null;

                switch (s.SymbolType)
                {
                case JSSymbol.SymbolTypes.Local:
                    newSymbol            = _newScope.GetOrAddSymbol(RenameSymbol(s.Name));
                    newSymbol.SymbolType = JSSymbol.SymbolTypes.Local;
                    break;

                case JSSymbol.SymbolTypes.Global:
                    newSymbol            = _newScope.GetOrAddSymbol(s.Name);
                    newSymbol.SymbolType = JSSymbol.SymbolTypes.Global;
                    break;

                default:
                    Trace.Fail("Cannot support symbol type {0}", s.SymbolType);
                    break;
                }
                return(newSymbol);
            }
Exemplo n.º 18
0
            void UpdateType(JSSymbol symbol, mdr.ValueTypes type)
            {
                if (type == mdr.ValueTypes.Unknown)
                {
                    return;
                }

                var oldType = GetType(symbol);
                var newType = TypeCalculator.ResolveType(oldType, type);

                switch (newType)
                {
                case mdr.ValueTypes.Undefined:
                case mdr.ValueTypes.Null:
                case mdr.ValueTypes.Unknown:
                    newType = mdr.ValueTypes.DValueRef; //All of these cases are handled by a DValue
                    break;

                case mdr.ValueTypes.DValue:
                    if (symbol.IsParameter)
                    {
                        //We already have a DValue as argument, so just need to point to that and use its storage
                        newType = mdr.ValueTypes.DValueRef;
                    }
                    break;
                }

                if (oldType != newType)
                {
                    m.Util.Diagnose.Debug.WriteLine("---->> Type of the symbol {0} changed to {1}", symbol.Name.ToString(), newType.ToString());
                    SetType(symbol, newType);
                    //symbol.Types.Add(type);
                    foreach (var r in symbol.Readers)
                    {
                        Enqueue(r);
                    }
                }
            }
Exemplo n.º 19
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)
            )
        );
      }
Exemplo n.º 20
0
 public Identifier(JSSymbol symbol)
 {
   Debug.Assert(symbol != null, "Symbold cannot be null");
   Symbol = symbol;
 }
Exemplo n.º 21
0
 private JSSymbol GetRenamedSymbolOf(JSSymbol s)
 {
   JSSymbol newSymbol = null;
   switch (s.SymbolType)
   {
     case JSSymbol.SymbolTypes.Local:
       newSymbol = _newScope.GetOrAddSymbol(RenameSymbol(s.Name));
       newSymbol.SymbolType = JSSymbol.SymbolTypes.Local;
       break;
     case JSSymbol.SymbolTypes.Global:
       newSymbol = _newScope.GetOrAddSymbol(s.Name);
       newSymbol.SymbolType = JSSymbol.SymbolTypes.Global;
       break;
     default:
       Trace.Fail("Cannot support symbol type {0}", s.SymbolType);
       break;
   }
   return newSymbol;
 }
Exemplo n.º 22
0
 public mdr.ValueTypes GetType(JSSymbol symbol)
 {
   return symbol.ValueType;
 }
Exemplo n.º 23
0
 internal LocalBuilder Declare(LocalBuilder local, JSSymbol symbol)
 {
   //Get(symbol) is not cheap, we want to write the following ASSERT in a way that it goes away in release
   Debug.Assert(Get(symbol) == null, "Symbol {0} already has a local variable of type {1}", symbol.Name, ((Get(symbol) != null) ? Get(symbol).LocalType.ToString() : ""));
   _symbolLocals.Add(symbol, local);
   return local;
 }
Exemplo n.º 24
0
 private void Release(JSSymbol symbol)
 {
   //Technically we should never call this function, it will be unsafe!
   var local = Get(symbol);
   Debug.Assert(local != null, "Symbol {0} does not have a local variable assigned to", symbol.Name);
   _symbolLocals.Remove(symbol);
   Release(symbol.Name);
 }
Exemplo n.º 25
0
 public mdr.ValueTypes GetType(JSSymbol symbol)
 {
     return(_cgInfo.GetType(symbol));
 }
Exemplo n.º 26
0
 //###############################################################################################################################
 // Symbols' local handling
 internal LocalBuilder Declare(mdr.ValueTypes type, JSSymbol symbol) { return Declare(Types.TypeOf(type), symbol); }
Exemplo n.º 27
0
 public mdr.ValueTypes GetType(JSSymbol symbol)
 {
     return(symbol.ValueType);
 }
Exemplo n.º 28
0
      protected virtual void DeclareNonParamSymbol(JSSymbol symbol, mdr.ValueTypes symbolValueType, LocalBuilder contextMap)
      {
        Debug.Assert(!symbol.IsParameter, "This function must not be called for parameter symbols");

        var scope = symbol.ContainerScope;
        switch (symbol.SymbolType)
        {
          case JSSymbol.SymbolTypes.HiddenLocal:
          case JSSymbol.SymbolTypes.Local:
            {
              switch (symbolValueType)
              {
                case mdr.ValueTypes.Unknown:
                case mdr.ValueTypes.DValueRef:
                case mdr.ValueTypes.DValue:
                  _localVars.Declare(Types.DValue.TypeOf, symbol);
                  break;
                default:
                  _localVars.Declare(Types.TypeOf(symbolValueType), symbol);
                  break;
              }
              break;
            }
          case JSSymbol.SymbolTypes.ClosedOnLocal:
            {
              Debug.Assert(scope.IsFunction, "closed on symbols are only supported at the function level at this time");
              Debug.Assert(symbolValueType == mdr.ValueTypes.Unknown || symbolValueType == mdr.ValueTypes.DValueRef, "Invalid symbol type {0} for symbol {1}", symbolValueType, symbol.Name);
              symbol.AssignFieldId();
              ///It is guaranteed that we will have the property in the _context

              if (scope.HasEval || scope.IsEvalFunction)
              {
                ///In this case, the _context.Fields may change; so we cannot hold on to its refrences!
                _ilGen.Ldloc(contextMap);
                _ilGen.Ldc_I4(symbol.FieldId);
                _ilGen.Call(Types.PropertyMap.GetPropertyDescriptorByFieldId);
                _localVars.Declare(Types.PropertyDescriptor.TypeOf, symbol);
              }
              else
              {
                ///In this case, as an optmization, we can just store the ref to the actual field in the context
                _ilGen.Ldloc(_context);
                _ilGen.Ldfld(Types.DObject.Fields);
                _ilGen.Ldloc(contextMap);
                _ilGen.Ldc_I4(symbol.FieldId);
                _ilGen.Call(Types.PropertyMap.GetPropertyDescriptorByFieldId);
                _ilGen.Ldfld(Types.PropertyDescriptor.Index);
                _ilGen.Ldelema(Types.DValue.TypeOf);
                _localVars.Declare(Types.DValue.RefOf, symbol);
              }
              _ilGen.Stloc(_localVars.Get(symbol));

              break;
            }
          case JSSymbol.SymbolTypes.ParentLocal:
            {
              Debug.Assert(symbolValueType == mdr.ValueTypes.Unknown || symbolValueType == mdr.ValueTypes.DValueRef, "Invalid symbol type {0} for symbol {1}", symbolValueType, symbol.Name);
              symbol.AssignFieldId();
              _ilGen.Ldloc(contextMap);
              _ilGen.Ldc_I4(symbol.FieldId);
              _ilGen.Call(Types.PropertyMap.GetPropertyDescriptorByFieldId); //We know this will return an inherited PD

              var closedOnScope = symbol.ResolvedSymbol.ContainerScope.ContainerFunction.FunctionIR.Scope;
              if (true || ////TODO: this optimizations is disabled for now to find a better approach!
                closedOnScope.HasEval //eval can make any changs to the context, so no clever trick
                || closedOnScope.IsEvalFunction //eval depends on the caller function's context which is not known at compile time
              )
              {
                //In this case, the .Fields of the context may change, so we cannot rely on the references
                _localVars.Declare(Types.PropertyDescriptor.TypeOf, symbol);
                _ilGen.Stloc(_localVars.Get(symbol));
              }
              else
              {
                //In this case, we can do the lookup once, and then just use the reference to the symbol's storage
                var tmp = _localVars.PushTemporary(Types.PropertyDescriptor.TypeOf);
                _ilGen.Stloc(tmp);

                var loadContainer = _ilGen.DefineLabel();
                var loadedContainer = _ilGen.DefineLabel();

                _ilGen.Ldloc(tmp);
                _ilGen.Call(Types.PropertyDescriptor.IsInherited);
                _ilGen.Brtrue(loadContainer);

                _ilGen.Ldloc(_context);
                _ilGen.Br(loadedContainer);

                _ilGen.MarkLabel(loadContainer);
                _ilGen.Ldloc(tmp);
                _ilGen.Ldfld(Types.PropertyDescriptor.Container);

                _ilGen.MarkLabel(loadedContainer);
                _ilGen.Ldfld(Types.DObject.Fields);
                _ilGen.Ldloc(tmp);
                _ilGen.Ldfld(Types.PropertyDescriptor.Index);
                _ilGen.Ldelema(Types.DValue.TypeOf);
                _localVars.Declare(Types.DValue.RefOf, symbol);
                _localVars.PopTemporary(tmp);
                _ilGen.Stloc(_localVars.Get(symbol));
              }
              break;
            }
          case JSSymbol.SymbolTypes.Global:
            {
              ///We know it is in the global state already, but we cannot use the reference bacause:
              ///- .Fields array may change during execution
              ///- the actuall property have accessor in the global scope.
              Debug.Assert(symbolValueType == mdr.ValueTypes.Unknown || symbolValueType == mdr.ValueTypes.DValueRef, "Invalid symbol type {0} for symbol {1}", symbolValueType, symbol.Name);
              symbol.AssignFieldId();

              //The following case is ready taken care of with the OuterDuplicate case
              //var globalSymbol =
              //  (scope != _currFuncMetadata.Scope)
              //  ? _currFuncMetadata.Scope.GetSymbol(symbol.Name)
              //  : null;

              //if (globalSymbol != null)
              //{
              //  //It should be already initialized, and we don't need to do it. 
              //  var globalVar = _localVars.Get(globalSymbol);
              //  Debug.Assert(globalVar != null, "Invalid situation, global symbol {0} must already have been declared", globalSymbol.Name);
              //  _localVars.Declare(globalVar, symbol);
              //  break;
              //}
              //else
              _localVars.Declare(Types.PropertyDescriptor.TypeOf, symbol);
              _ilGen.LoadRuntimeInstance();
              _ilGen.Ldfld(Types.Runtime.GlobalContext);
              _ilGen.Ldc_I4(symbol.FieldId);
              _ilGen.Call(Types.DObject.GetPropertyDescriptorByFieldId);
              _ilGen.Stloc(_localVars.Get(symbol));
              break;
            }
          case JSSymbol.SymbolTypes.Arguments:
            {
              if (symbolValueType == mdr.ValueTypes.Array)
              {
                ///In this case, the arguments symbols must have been only read from 
                Debug.Assert(_arguments != null, "Invalid situation, the _arguments variable must be already assigned");
                var local = _localVars.Declare(Types.DArray.TypeOf, symbol);
                _ilGen.Ldloc(_arguments);
                _ilGen.Stloc(local);

              }
              else if (symbolValueType == mdr.ValueTypes.DValueRef || symbolValueType == mdr.ValueTypes.Unknown)
              {
                ///In this case, we either don't know the type, or there has been assignments to the arguments symbol
                var local = _localVars.Declare(Types.DValue.TypeOf, symbol);
                _ilGen.Ldloca(local);
                _ilGen.Ldloc(_arguments);
                _ilGen.Call(Types.DValue.Set.Get(mdr.ValueTypes.Object));
              }
              else
              {
                Debug.Fail("Invalid symbol type {0} for 'arguments'", symbolValueType);
              }
              break;
            }
          case JSSymbol.SymbolTypes.Unknown:
            {
              ///This symbol could not be resolved during analysis, and hence can be added to the context chain at runtime
              ///The context chain is: func.Context->func.Parent.Context->...GlobalContext->Object.prototype
              ///Therefore we should generate code to look it up at the access site
              Debug.Assert(symbolValueType == mdr.ValueTypes.Unknown || symbolValueType == mdr.ValueTypes.DValueRef, "Invalid symbol type");
              symbol.AssignFieldId();
              break;
            }
          case JSSymbol.SymbolTypes.OuterDuplicate:
            //we don't need to do anything since the outer symbols is going to be used. 
            break;
          default:
            Trace.Fail("cannot process symbol type {0} in {1}", symbol.SymbolType, _currFuncMetadata.FullName);
            break;
        }
      }
Exemplo n.º 29
0
 public mdr.ValueTypes GetType(JSSymbol symbol)
 {
     return(SymbolTypes[symbol]);
 }
Exemplo n.º 30
0
 public void SetType(JSSymbol symbol, mdr.ValueTypes type)
 {
     SymbolTypes[symbol] = type;
 }
Exemplo n.º 31
0
 public Identifier(JSSymbol symbol)
 {
     Debug.Assert(symbol != null, "Symbold cannot be null");
     Symbol = symbol;
 }
Exemplo n.º 32
0
 void WriteResults(JSSymbol symbol, bool pushBackResult)
 {
   switch (symbol.SymbolType)
   {
     case JSSymbol.SymbolTypes.Unknown:
     case JSSymbol.SymbolTypes.Local:
     case JSSymbol.SymbolTypes.ClosedOnLocal:
     case JSSymbol.SymbolTypes.ParentLocal:
     case JSSymbol.SymbolTypes.Global:
     case JSSymbol.SymbolTypes.Arguments:
       if (symbol.IsParameter && symbol.SymbolType != JSSymbol.SymbolTypes.ClosedOnLocal)
       {
         Ldarg_CallFrame();
         _ilGen.Ldc_I4(symbol.ParameterIndex);
         _ilGen.Ldc_I4(pushBackResult);
         Call(Types.Operations.Stack.StoreArg, 1, pushBackResult ? 1 : 0);
       }
       else
       {
         _ilGen.Ldloc(_context);
         _ilGen.Ldc_I4(symbol.FieldId);
         //_ilGen.Ldc_I4(symbol.AncestorDistance);
         _ilGen.Ldc_I4(pushBackResult);
         Call(Types.Operations.Stack.StoreVariable, 1, pushBackResult ? 1 : 0);
       }
       break;
     case JSSymbol.SymbolTypes.HiddenLocal:
       _ilGen.Ldloca(_localVars.Get(symbol));
       if (pushBackResult)
         LoadStackItem(-1);
       else
         LoadStackPop();
       _ilGen.Call(Types.DValue.Set.Get(mdr.ValueTypes.DValueRef));
       break;
     default:
       Trace.Fail("Cannot write to symbol {0}:{1}", symbol.Name, symbol.SymbolType);
       break;
   }
 }
Exemplo n.º 33
0
 public void SetType(JSSymbol symbol, mdr.ValueTypes type)
 {
     _cgInfo.SetType(symbol, type);
 }
Exemplo n.º 34
0
 public mdr.ValueTypes GetType(JSSymbol symbol)
 {
   return SymbolTypes[symbol];
 }
Exemplo n.º 35
0
 private IIdentifier MakeIdentifier(JSSymbol symbol, int offset)
 {
     return(MakeReadIdentifierExpression(symbol, offset));
 }
Exemplo n.º 36
0
 private ReadIdentifierExpression MakeReadIdentifierExpression(JSSymbol symbol, int offset)
 {
     return(new ReadIdentifierExpression(symbol, offset));
 }
Exemplo n.º 37
0
            private static void ResolveMethod(JSSymbol symbol)
            {
                var containerFunction = symbol.ContainerScope.ContainerFunction;

                bool shouldResolveAtRuntime = false;

                for (var outerScope = symbol.ContainerScope.OuterScope; outerScope != null; outerScope = outerScope.OuterScope)
                {
                    var resolvedSymbol = outerScope.GetSymbol(symbol.Name);
                    if (resolvedSymbol != null)
                    {
                        if (outerScope.ContainerFunction == containerFunction)
                        {
                            ///We just need to know everywhere instead of symbol, we should refer to resolved symbol
                            ///the rest will be taken care of as we keep analyzing the upper scopes
                            symbol.SymbolType = JSSymbol.SymbolTypes.OuterDuplicate;
                            if (resolvedSymbol.SymbolType == JSSymbol.SymbolTypes.OuterDuplicate)
                            {
                                Debug.Assert(resolvedSymbol.ResolvedSymbol != null, "symbol {0} must have already been resolved!");
                                symbol.ResolvedSymbol = resolvedSymbol.ResolvedSymbol;
                            }
                            else
                            {
                                symbol.ResolvedSymbol = resolvedSymbol;
                            }
                        }
                        else
                        {
                            //here we are sure the symbol is found in a parent function scope
                            switch (resolvedSymbol.SymbolType)
                            {
                            case JSSymbol.SymbolTypes.Local:
                            case JSSymbol.SymbolTypes.ClosedOnLocal:
                                symbol.ResolvedSymbol = resolvedSymbol;
                                if (outerScope.IsProgram)
                                {
                                    symbol.SymbolType = JSSymbol.SymbolTypes.Global;
                                }
                                else
                                {
                                    symbol.SymbolType = JSSymbol.SymbolTypes.ParentLocal;
                                }
                                symbol.ContainerScope.HasParentLocalSymbol = true; //We need this anyways since we want to know if a context is needed at runtime at all
                                lock (resolvedSymbol)                              //In case sub-functions are processed in parallel
                                {
                                    resolvedSymbol.SymbolType            = JSSymbol.SymbolTypes.ClosedOnLocal;
                                    resolvedSymbol.NonLocalWritersCount += symbol.Writers.Count;
                                    resolvedSymbol.AssignFieldId();
                                }
                                symbol.AssignFieldId();
                                break;

                            case JSSymbol.SymbolTypes.Unknown:
                                if (outerScope.HasEval)
                                {
                                    shouldResolveAtRuntime = true;
                                    outerScope             = null; //to stop the loop
                                }
                                //we will take care of this after this loop
                                break;

                            case JSSymbol.SymbolTypes.ParentLocal:
                                ///We could have made a shortcut here and setup the symbol info, but we would still need to walk up until we find the actual symbol declaration
                                ///So, the optimization here would be just not calling GetSymbol int some parent functions.
                                ///To simplify code, for now, we just ignore this until we reach the declared symbol
                                Debug.Assert(
                                    !outerScope.HasEval &&
                                    !outerScope.IsProgram &&
                                    resolvedSymbol.ResolvedSymbol != null
                                    , "symbol {0} in {1} must resolve at runtime", resolvedSymbol.Name, resolvedSymbol.ContainerScope.ContainerFunction.Declaration);
                                Debug.Assert(resolvedSymbol.ResolvedSymbol != null, "symbol {0} in {1} must have been already resolved", resolvedSymbol.Name, resolvedSymbol.ContainerScope.ContainerFunction.Declaration);
                                symbol.ResolvedSymbol = resolvedSymbol.ResolvedSymbol;
                                symbol.SymbolType     = JSSymbol.SymbolTypes.ParentLocal;
                                symbol.ContainerScope.HasParentLocalSymbol = true;
                                symbol.AssignFieldId();
                                outerScope = null; //stop the loop
                                break;

                            case JSSymbol.SymbolTypes.Global:
                                Debug.Assert(
                                    outerScope.IsProgram ||
                                    !outerScope.HasEval
                                    , "symbol {0} in {1} must resolve at runtime", resolvedSymbol.Name, resolvedSymbol.ContainerScope.ContainerFunction.Declaration);
                                //symbol is a global that ParentFunction is also using!
                                symbol.SymbolType = JSSymbol.SymbolTypes.Global;
                                if (!outerScope.IsProgram)
                                {
                                    symbol.ResolvedSymbol = resolvedSymbol.ResolvedSymbol; //may or maynot be null!
                                }
                                symbol.AssignFieldId();
                                outerScope = null; //end the loop
                                break;

                            default:
                                throw new InvalidOperationException(string.Format("{0} has unexpected symbol type {1} in {2}. This case should not have happened.", resolvedSymbol.Name, resolvedSymbol.SymbolType, resolvedSymbol.ContainerScope.ContainerFunction.Declaration));
                            }
                        }
                        break;
                    }
                    else if (outerScope.HasEval && outerScope.IsFunction)
                    {
                        ///We did not find this symbol in the parent scopes all the way to the function scope and this scope has eval, so should not search any more
                        ///note that if any of the inner scopes of a function scope has eval, then the function scope itself will also has eval
                        shouldResolveAtRuntime = true;
                        break; //The symbol may be added later by the eval!, end the loop
                    }
                }
                if (
                    symbol.SymbolType == JSSymbol.SymbolTypes.Unknown &&
                    !shouldResolveAtRuntime
                    )
                {
                    //This could be a builtin name
                    if (JSRuntime.Instance.GlobalContext.HasOwnProperty(symbol.Name))
                    {
                        symbol.SymbolType = JSSymbol.SymbolTypes.Global;
                        symbol.AssignFieldId();
                    }
                }
            }
Exemplo n.º 38
0
      public void AnalyzeSymbol(JSSymbol symbol)
      {
        ///Symbol resolution is very critical and can be complicated considering parallel analyze and inlining. 
        ///Therefore, we have to be conservative and assert every assumption we make
        ///We should consider:
        /// - In normal case, symbols of a function are resolved AFTER its sub-functions are analyzed. Therefore, some cases should not occure. However, if lazy parsing kick in
        ///     the sub-function is parsed-analyzed way after the parent function was even executed. So, this will create a new set of assumptions. 
        /// - Processing the top leve program script may have special cases which we will go through before ending the analysis of the program

        var symbolScope = symbol.ContainerScope;

        ///<Mehrdad>
        ///A function may just reference the "arguments" symbol, or even define its own. 
        ///in any case, such a symbol is first initialized with the arctual arguments value, 
        ///and may be then overwritten in the function. 
        ///In anycase, existance of such a symbol will be costly. 
        ///</Mehrdad>
        if (symbol.Name == JSFunctionArguments.Name)
        {
          var argumentsSymbol = symbol;
          var functionScope = symbolScope;

          if (!symbolScope.IsFunction)
          {
            functionScope = symbolScope.ContainerFunction.FunctionIR.Scope;
            argumentsSymbol = functionScope.GetOrAddSymbol(JSFunctionArguments.Name);
          }

          functionScope.HasArgumentsSymbol = true;
          Debug.Assert(
            argumentsSymbol.SymbolType == JSSymbol.SymbolTypes.Arguments
            || argumentsSymbol.SymbolType == JSSymbol.SymbolTypes.Local
            || argumentsSymbol.SymbolType == JSSymbol.SymbolTypes.Unknown
            , "invalide arguments type {0}", argumentsSymbol.SymbolType);

          argumentsSymbol.SymbolType = JSSymbol.SymbolTypes.Arguments;
          if (symbol != argumentsSymbol)
          {
            Debug.Assert(functionScope != symbolScope, "Invalid situation!");
            symbol.SymbolType = JSSymbol.SymbolTypes.OuterDuplicate;
            symbol.ResolvedSymbol = argumentsSymbol;
          }
        }

        switch (symbol.SymbolType)
        {
          case JSSymbol.SymbolTypes.Local:
            if (
                symbolScope.HasUnknownSubFunction
                || symbolScope.HasEval
                || symbolScope.IsEvalFunction //We don't see the full picture in eval function, the local may be defined outside as well, besides all locals are added to parent scope
                )
            {
              //In these cases we have uncertainty in access sites, so we should threat all as potential ClosedOnLocals
              symbol.SymbolType = JSSymbol.SymbolTypes.ClosedOnLocal;
              goto case JSSymbol.SymbolTypes.ClosedOnLocal;
            }
            else
            {
              symbolScope.HasLocalSymbol = true;
            }
            break;
          case JSSymbol.SymbolTypes.ClosedOnLocal:
            Trace.Assert(symbolScope.IsFunction, "At this point closure on non function level variables is not  supported");
            symbolScope.HasClosedOnSymbol = true;
            if (symbolScope.IsProgram)
            {
              ///This is in fact a global variable declataion:
              ///- We know this code is certainly executed.
              ///- We look for this symbol in the global context when analyzing subfunctions
              ///- If we add this to global context after creating subfunction objects (during execution), the heavy propagate algorithm in the Propertymap will be executed
              ///So we add the symbol to the global object to ensure it exsits there
              //symbol.SymbolType = JSSymbol.SymbolTypes.Global;
              symbol.AssignFieldId();
              var prop = mdr.Runtime.Instance.GlobalContext.Map.GetPropertyDescriptorByFieldId(symbol.FieldId);
              if (prop == null || prop.IsUndefined)
              {
                mdr.Runtime.Instance.GlobalContext.AddOwnPropertyDescriptorByFieldId(
                  symbol.FieldId
                  , mdr.PropertyDescriptor.Attributes.Data 
//                  | mdr.PropertyDescriptor.Attributes.NotConfigurable //TODO: why do we need this? 
                );
              }
            }
            break;
          case JSSymbol.SymbolTypes.HiddenLocal:
            //Nothing to do for these types
            break;
          case JSSymbol.SymbolTypes.OuterDuplicate:
            //this can happen since NodeFactory may have already hoisted some locals to outer function scop
            break;
          case JSSymbol.SymbolTypes.ParentLocal:
            Trace.Fail("Since we are resolving functions bottom-up, and scopes top-down we should not see any symbol type of {0} here", symbol.SymbolType);
            break;
          case JSSymbol.SymbolTypes.Arguments:
            Debug.Assert(symbolScope.HasArgumentsSymbol, "{0} symbol exists, but scope does have the correct attributes", JSFunctionArguments.Name);
            break;
          case JSSymbol.SymbolTypes.Global:
            Debug.Assert(
              symbolScope.IsProgram
              && mdr.Runtime.Instance.GlobalContext.HasOwnProperty(symbol.Name)
              , "we should only see this after resolving symbols and symbol {0} should be global but is not in the global context", symbol.Name);
            break;
          case JSSymbol.SymbolTypes.Unknown:
            //NOTE: we should never try to resolve "undefined" since it can be easily assigned to at runtime!!!!
            if (symbolScope.HasEval && symbolScope.IsFunction)
            {
              break; //The symbol may be added later by the eval!
            }
            ResolveMethod(symbol);
            break;
          default:
            throw new InvalidOperationException(string.Format("{0} has unexpected symbol type {1} in {2}. This case should not have happened.", symbol.Name, symbol.SymbolType, _currFuncMetadata.FullName));
        }
      }
Exemplo n.º 39
0
 private IIdentifier MakeIdentifier(JSSymbol symbol, int offset) { return MakeReadIdentifierExpression(symbol, offset); }
Exemplo n.º 40
0
 internal LocalBuilder Declare(Type type, JSSymbol symbol) { return Declare(Declare(type/*, symbol.Name*/), symbol); }
Exemplo n.º 41
0
 private ReadIdentifierExpression MakeReadIdentifierExpression(JSSymbol symbol, int offset)
 {
   return new ReadIdentifierExpression(symbol, offset);
 }
Exemplo n.º 42
0
 internal LocalBuilder Get(JSSymbol symbol)
 {
   LocalBuilder local;
   _symbolLocals.TryGetValue(symbol, out local);
   return local;
 }
Exemplo n.º 43
0
 internal void ReadSymbol(JSSymbol symbol, ref mdr.DValue result, ref mdr.CallFrame callFrame)
 {
   switch (symbol.SymbolType)
   {
     case JSSymbol.SymbolTypes.Local:
     case JSSymbol.SymbolTypes.HiddenLocal:
     case JSSymbol.SymbolTypes.Arguments:
       {
         if (symbol.IsParameter)
           if (Arguments != null)
             //result = Arguments.Elements[symbol.ParameterIndex];
             Arguments.GetField(symbol.ParameterIndex, ref result); //TODO: optimize this for faster access
           else
             result = callFrame.Arg(symbol.ParameterIndex);
         else
           result = SymbolValues[symbol.ValueIndex];
         break;
       }
     case JSSymbol.SymbolTypes.ClosedOnLocal:
     case JSSymbol.SymbolTypes.ParentLocal:
     case JSSymbol.SymbolTypes.Global:
       {
         var pd = GetPropertyDescriptor(symbol);
         pd.Get(Context, ref result);
         break;
       }
     case JSSymbol.SymbolTypes.Unknown:
       {
         var pd = Context.GetPropertyDescriptorByFieldId(symbol.FieldId);
         pd.Get(Context, ref result);
         break;
       }
     case JSSymbol.SymbolTypes.OuterDuplicate:
       ReadSymbol(symbol.ResolvedSymbol, ref result, ref callFrame);
       break;
     default:
       Trace.Fail("Could not interpret symbol {0} with type {1}", symbol.Name, symbol.SymbolType);
       break;
   }
 }
Exemplo n.º 44
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();
      }
Exemplo n.º 45
0
 private WriteIdentifierExpression MakeWriteIdentifierExpression(JSSymbol symbol, Expression value)
 {
   return new WriteIdentifierExpression(symbol, MakeGuardedCast(value));
 }
Exemplo n.º 46
0
 public void SetType(JSSymbol symbol, mdr.ValueTypes type)
 {
   symbol.ValueType = type;
 }
Exemplo n.º 47
0
 //###############################################################################################################################
 // Symbols' local handling
 internal LocalBuilder Declare(mdr.ValueTypes type, JSSymbol symbol)
 {
     return(Declare(Types.TypeOf(type), symbol));
 }
Exemplo n.º 48
0
 public void SetType(JSSymbol symbol, mdr.ValueTypes type)
 {
   SymbolTypes[symbol] = type;
 }
Exemplo n.º 49
0
 internal LocalBuilder Declare(Type type, JSSymbol symbol)
 {
     return(Declare(Declare(type /*, symbol.Name*/), symbol));
 }
Exemplo n.º 50
0
      int _symbolIndexOffset; //We may have reserved values like context, arguments ... in the CallFrame.Values

      /// <summary>
      /// Returns the index of the symbols in the CallFrame.Values
      /// </summary>
      int GetIndex(JSSymbol symbol) { return symbol.Index + _symbolIndexOffset; }
Exemplo n.º 51
0
 private mdr.PropertyDescriptor GetPropertyDescriptor(JSSymbol symbol)
 {
   mdr.PropertyDescriptor pd;
   if (SymbolValues[symbol.ValueIndex].ValueType == mdr.ValueTypes.Undefined)
   {
     //first time visit
     pd = Context.GetPropertyDescriptorByFieldId(symbol.FieldId);
     SymbolValues[symbol.ValueIndex].Set(pd);
   }
   else
     pd = (mdr.PropertyDescriptor)SymbolValues[symbol.ValueIndex].AsObject();
   return pd;
 }
Exemplo n.º 52
0
 private WriteIdentifierExpression MakeWriteIdentifierExpression(JSSymbol symbol, Expression value)
 {
     return(new WriteIdentifierExpression(symbol, MakeGuardedCast(value)));
 }
Exemplo n.º 53
0
      private static void ResolveMethod(JSSymbol symbol)
      {
        var containerFunction = symbol.ContainerScope.ContainerFunction;

        bool shouldResolveAtRuntime = false;
        for (var outerScope = symbol.ContainerScope.OuterScope; outerScope != null; outerScope = outerScope.OuterScope)
        {
          var resolvedSymbol = outerScope.GetSymbol(symbol.Name);
          if (resolvedSymbol != null)
          {
            if (outerScope.ContainerFunction == containerFunction)
            {
              ///We just need to know everywhere instead of symbol, we should refer to resolved symbol
              ///the rest will be taken care of as we keep analyzing the upper scopes
              symbol.SymbolType = JSSymbol.SymbolTypes.OuterDuplicate;
              if (resolvedSymbol.SymbolType == JSSymbol.SymbolTypes.OuterDuplicate)
              {
                Debug.Assert(resolvedSymbol.ResolvedSymbol != null, "symbol {0} must have already been resolved!");
                symbol.ResolvedSymbol = resolvedSymbol.ResolvedSymbol;
              }
              else
                symbol.ResolvedSymbol = resolvedSymbol;
            }
            else
            {
              //here we are sure the symbol is found in a parent function scope
              switch (resolvedSymbol.SymbolType)
              {
                case JSSymbol.SymbolTypes.Local:
                case JSSymbol.SymbolTypes.ClosedOnLocal:
                  symbol.ResolvedSymbol = resolvedSymbol;
                  if (outerScope.IsProgram)
                  {
                    symbol.SymbolType = JSSymbol.SymbolTypes.Global;
                  }
                  else
                  {
                    symbol.SymbolType = JSSymbol.SymbolTypes.ParentLocal;
                  }
                  symbol.ContainerScope.HasParentLocalSymbol = true; //We need this anyways since we want to know if a context is needed at runtime at all
                  lock (resolvedSymbol) //In case sub-functions are processed in parallel
                  {
                    resolvedSymbol.SymbolType = JSSymbol.SymbolTypes.ClosedOnLocal;
                    resolvedSymbol.NonLocalWritersCount += symbol.Writers.Count;
                    resolvedSymbol.AssignFieldId();
                  }
                  symbol.AssignFieldId();
                  break;
                case JSSymbol.SymbolTypes.Unknown:
                  if (outerScope.HasEval)
                  {
                    shouldResolveAtRuntime = true;
                    outerScope = null; //to stop the loop
                  }
                  //we will take care of this after this loop
                  break;
                case JSSymbol.SymbolTypes.ParentLocal:
                  ///We could have made a shortcut here and setup the symbol info, but we would still need to walk up until we find the actual symbol declaration
                  ///So, the optimization here would be just not calling GetSymbol int some parent functions. 
                  ///To simplify code, for now, we just ignore this until we reach the declared symbol 
                  Debug.Assert(
                    !outerScope.HasEval
                    && !outerScope.IsProgram
                    && resolvedSymbol.ResolvedSymbol != null
                    , "symbol {0} in {1} must resolve at runtime", resolvedSymbol.Name, resolvedSymbol.ContainerScope.ContainerFunction.Declaration);
                  Debug.Assert(resolvedSymbol.ResolvedSymbol != null, "symbol {0} in {1} must have been already resolved", resolvedSymbol.Name, resolvedSymbol.ContainerScope.ContainerFunction.Declaration);
                  symbol.ResolvedSymbol = resolvedSymbol.ResolvedSymbol;
                  symbol.SymbolType = JSSymbol.SymbolTypes.ParentLocal;
                  symbol.ContainerScope.HasParentLocalSymbol = true;
                  symbol.AssignFieldId();
                  outerScope = null; //stop the loop
                  break;
                case JSSymbol.SymbolTypes.Global:
                  Debug.Assert(
                    outerScope.IsProgram
                    || !outerScope.HasEval
                    , "symbol {0} in {1} must resolve at runtime", resolvedSymbol.Name, resolvedSymbol.ContainerScope.ContainerFunction.Declaration);
                  //symbol is a global that ParentFunction is also using!
                  symbol.SymbolType = JSSymbol.SymbolTypes.Global;
                  if (!outerScope.IsProgram)
                  {
                    symbol.ResolvedSymbol = resolvedSymbol.ResolvedSymbol; //may or maynot be null!
                  }
                  symbol.AssignFieldId();
                  outerScope = null; //end the loop
                  break;
                default:
                  throw new InvalidOperationException(string.Format("{0} has unexpected symbol type {1} in {2}. This case should not have happened.", resolvedSymbol.Name, resolvedSymbol.SymbolType, resolvedSymbol.ContainerScope.ContainerFunction.Declaration));
              }
            }
            break;
          }
          else if (outerScope.HasEval && outerScope.IsFunction)
          {
            ///We did not find this symbol in the parent scopes all the way to the function scope and this scope has eval, so should not search any more
            ///note that if any of the inner scopes of a function scope has eval, then the function scope itself will also has eval
            shouldResolveAtRuntime = true;
            break; //The symbol may be added later by the eval!, end the loop
          }
        }
        if (
            symbol.SymbolType == JSSymbol.SymbolTypes.Unknown
            && !shouldResolveAtRuntime
            )
        {
          //This could be a builtin name
          if (JSRuntime.Instance.GlobalContext.HasOwnProperty(symbol.Name))
          {
            symbol.SymbolType = JSSymbol.SymbolTypes.Global;
            symbol.AssignFieldId();
          }
        }
      }
Exemplo n.º 54
0
 public void SetType(JSSymbol symbol, mdr.ValueTypes type)
 {
     symbol.ValueType = type;
 }
Exemplo n.º 55
0
 internal void WriteSymbol(JSSymbol symbol, ref mdr.DValue result, ref mdr.CallFrame callFrame)
 {
   switch (symbol.SymbolType)
   {
     case JSSymbol.SymbolTypes.Local:
     case JSSymbol.SymbolTypes.HiddenLocal:
     case JSSymbol.SymbolTypes.Arguments:
       {
         if (symbol.IsParameter)
           if (Arguments != null)
             Arguments.Elements[symbol.ParameterIndex].Set(ref result);
           else
             callFrame.SetArg(symbol.ParameterIndex, ref result);
         else
           SymbolValues[symbol.ValueIndex] = result;
         break;
       }
     case JSSymbol.SymbolTypes.ClosedOnLocal:
     case JSSymbol.SymbolTypes.ParentLocal:
     case JSSymbol.SymbolTypes.Global:
       {
         var pd = GetPropertyDescriptor(symbol);
         pd.Set(Context, ref result);
         break;
       }
     case JSSymbol.SymbolTypes.Unknown:
       {
         var pd = Context.GetPropertyDescriptorByFieldId(symbol.FieldId);
         if (pd.IsUndefined)
           JSRuntime.Instance.GlobalContext.SetFieldByFieldId(symbol.FieldId, ref result);
         else
           pd.Set(Context, ref result);
         break;
       }
     case JSSymbol.SymbolTypes.OuterDuplicate:
       WriteSymbol(symbol.ResolvedSymbol, ref result, ref callFrame);
       break;
     default:
       Trace.Fail("Could not interpret symbol {0} with type {1}", symbol.Name, symbol.SymbolType);
       break;
   }
 }
Exemplo n.º 56
0
 mdr.ValueTypes GetType(JSSymbol symbol)
 {
   var symbolValueType = symbol.ValueType; //TODO: we actually need to read this from cgInfo
   return symbolValueType;
 }
Exemplo n.º 57
0
            public void AnalyzeSymbol(JSSymbol symbol)
            {
                ///Symbol resolution is very critical and can be complicated considering parallel analyze and inlining.
                ///Therefore, we have to be conservative and assert every assumption we make
                ///We should consider:
                /// - In normal case, symbols of a function are resolved AFTER its sub-functions are analyzed. Therefore, some cases should not occure. However, if lazy parsing kick in
                ///     the sub-function is parsed-analyzed way after the parent function was even executed. So, this will create a new set of assumptions.
                /// - Processing the top leve program script may have special cases which we will go through before ending the analysis of the program

                var symbolScope = symbol.ContainerScope;

                ///<Mehrdad>
                ///A function may just reference the "arguments" symbol, or even define its own.
                ///in any case, such a symbol is first initialized with the arctual arguments value,
                ///and may be then overwritten in the function.
                ///In anycase, existance of such a symbol will be costly.
                ///</Mehrdad>
                if (symbol.Name == JSFunctionArguments.Name)
                {
                    var argumentsSymbol = symbol;
                    var functionScope   = symbolScope;

                    if (!symbolScope.IsFunction)
                    {
                        functionScope   = symbolScope.ContainerFunction.FunctionIR.Scope;
                        argumentsSymbol = functionScope.GetOrAddSymbol(JSFunctionArguments.Name);
                    }

                    functionScope.HasArgumentsSymbol = true;
                    Debug.Assert(
                        argumentsSymbol.SymbolType == JSSymbol.SymbolTypes.Arguments ||
                        argumentsSymbol.SymbolType == JSSymbol.SymbolTypes.Local ||
                        argumentsSymbol.SymbolType == JSSymbol.SymbolTypes.Unknown
                        , "invalide arguments type {0}", argumentsSymbol.SymbolType);

                    argumentsSymbol.SymbolType = JSSymbol.SymbolTypes.Arguments;
                    if (symbol != argumentsSymbol)
                    {
                        Debug.Assert(functionScope != symbolScope, "Invalid situation!");
                        symbol.SymbolType     = JSSymbol.SymbolTypes.OuterDuplicate;
                        symbol.ResolvedSymbol = argumentsSymbol;
                    }
                }

                switch (symbol.SymbolType)
                {
                case JSSymbol.SymbolTypes.Local:
                    if (
                        symbolScope.HasUnknownSubFunction ||
                        symbolScope.HasEval ||
                        symbolScope.IsEvalFunction //We don't see the full picture in eval function, the local may be defined outside as well, besides all locals are added to parent scope
                        )
                    {
                        //In these cases we have uncertainty in access sites, so we should threat all as potential ClosedOnLocals
                        symbol.SymbolType = JSSymbol.SymbolTypes.ClosedOnLocal;
                        goto case JSSymbol.SymbolTypes.ClosedOnLocal;
                    }
                    else
                    {
                        symbolScope.HasLocalSymbol = true;
                    }
                    break;

                case JSSymbol.SymbolTypes.ClosedOnLocal:
                    Trace.Assert(symbolScope.IsFunction, "At this point closure on non function level variables is not  supported");
                    symbolScope.HasClosedOnSymbol = true;
                    if (symbolScope.IsProgram)
                    {
                        ///This is in fact a global variable declataion:
                        ///- We know this code is certainly executed.
                        ///- We look for this symbol in the global context when analyzing subfunctions
                        ///- If we add this to global context after creating subfunction objects (during execution), the heavy propagate algorithm in the Propertymap will be executed
                        ///So we add the symbol to the global object to ensure it exsits there
                        //symbol.SymbolType = JSSymbol.SymbolTypes.Global;
                        symbol.AssignFieldId();
                        var prop = mdr.Runtime.Instance.GlobalContext.Map.GetPropertyDescriptorByFieldId(symbol.FieldId);
                        if (prop == null || prop.IsUndefined)
                        {
                            mdr.Runtime.Instance.GlobalContext.AddOwnPropertyDescriptorByFieldId(
                                symbol.FieldId
                                , mdr.PropertyDescriptor.Attributes.Data
//                  | mdr.PropertyDescriptor.Attributes.NotConfigurable //TODO: why do we need this?
                                );
                        }
                    }
                    break;

                case JSSymbol.SymbolTypes.HiddenLocal:
                    //Nothing to do for these types
                    break;

                case JSSymbol.SymbolTypes.OuterDuplicate:
                    //this can happen since NodeFactory may have already hoisted some locals to outer function scop
                    break;

                case JSSymbol.SymbolTypes.ParentLocal:
                    Trace.Fail("Since we are resolving functions bottom-up, and scopes top-down we should not see any symbol type of {0} here", symbol.SymbolType);
                    break;

                case JSSymbol.SymbolTypes.Arguments:
                    Debug.Assert(symbolScope.HasArgumentsSymbol, "{0} symbol exists, but scope does have the correct attributes", JSFunctionArguments.Name);
                    break;

                case JSSymbol.SymbolTypes.Global:
                    Debug.Assert(
                        symbolScope.IsProgram &&
                        mdr.Runtime.Instance.GlobalContext.HasOwnProperty(symbol.Name)
                        , "we should only see this after resolving symbols and symbol {0} should be global but is not in the global context", symbol.Name);
                    break;

                case JSSymbol.SymbolTypes.Unknown:
                    //NOTE: we should never try to resolve "undefined" since it can be easily assigned to at runtime!!!!
                    if (symbolScope.HasEval && symbolScope.IsFunction)
                    {
                        break; //The symbol may be added later by the eval!
                    }
                    ResolveMethod(symbol);
                    break;

                default:
                    throw new InvalidOperationException(string.Format("{0} has unexpected symbol type {1} in {2}. This case should not have happened.", symbol.Name, symbol.SymbolType, _currFuncMetadata.FullName));
                }
            }