public ScopeDictionaryStorage(TotemContext/*!*/ context, Scope/*!*/ scope)
        {
            Assert.NotNull(context, scope);

            _scope = scope;
            _context = context;
        }
示例#2
0
        public ModuleContext(TotemModule module, TotemContext creatingContext)
        {
            ContractUtils.RequiresNotNull(module, "module");
            ContractUtils.RequiresNotNull(creatingContext, "creatingContext");

            _globals = module.Dictionary;
        }
示例#3
0
        public TotemArgs(TotemContext context, string[] names, IList<object> args, Dictionary<string, object> kwargs)
            : base(context.GetType<Types.Arguments>())
        {
            _names = new ReadOnlyCollectionBuilder<string>(names).ToReadOnlyCollection();
            var vb = new ReadOnlyCollectionBuilder<object>();
            var nvb = new Dictionary<string, object>();
            var snb = new ReadOnlyCollectionBuilder<string>();

            for (var i = 0; i < args.Count; i++)
            {
                vb.Add(args[i]);
                if (i < names.Length)
                    nvb.Add(names[i], args[i]);
            }

            foreach (var arg in kwargs)
            {
                nvb.Add(arg.Key, arg.Value);
                snb.Add(arg.Key);
            }

            _values = vb.ToReadOnlyCollection();
            _namedValues = new ReadOnlyDictionary<string, object>(nvb);
            _named = snb.ToReadOnlyCollection();
        }
示例#4
0
 public TotemScopeExtension(TotemContext context, Scope scope)
     : base(scope)
 {
     _codeContext = new CodeContext(new TotemDictionary(
         new ScopeDictionaryStorage(context, scope)
     ), null, context);
 }
示例#5
0
        /// <summary>
        /// Creates a new CodeContext which is backed by the specified Python dictionary.
        /// </summary>
        public CodeContext(TotemDictionary/*!*/ dict, CodeContext globalContext, TotemContext/*!*/ context)
        {
            ContractUtils.RequiresNotNull(dict, "dict");
            ContractUtils.RequiresNotNull(context, "context");

            _context = context;
            _dict = dict;
            _globalContext = globalContext;
        }
示例#6
0
        public TotemMethod(TotemContext/*!*/ context, string name, ITotemCallable wrapped, object instance)
            : base(context.GetType<Types.Method>())
        {
            ContractUtils.RequiresNotNull(wrapped, "wrapped");
            ContractUtils.RequiresNotNull(instance, "instance");

            _wrapped = wrapped;
            _name = name;
            _instance = instance;
        }
示例#7
0
        public ModuleContext(TotemDictionary globals, TotemContext creatingContext)
        {
            ContractUtils.RequiresNotNull(globals, "globals");
            ContractUtils.RequiresNotNull(creatingContext, "creatingContext");

            _globals = globals;
            _totemContext = creatingContext;
            _globalContext = new CodeContext(globals, this);
            _module = new TotemModule(globals);
            _module.Scope.SetExtension(_totemContext.ContextId, new TotemScopeExtension(_totemContext, _module, this));
        }
示例#8
0
 internal static TotemNull Get(TotemContext context)
 {
     lock (nullValues)
     {
         TotemNull val;
         if (!nullValues.TryGetValue(context, out val))
         {
             val = new TotemNull(context);
             nullValues.Add(context, val);
         }
         return val;
     }
 }
示例#9
0
        private LambdaExpression _tracingLambda; // the transformed lambda used for tracing/debugging

        #endregion Fields

        #region Constructors

        /// <summary>
        /// Constructor used to create a FunctionCode for code that's been serialized to disk.  
        /// 
        /// Code constructed this way cannot be interpreted or debugged using sys.settrace/sys.setprofile.
        /// 
        /// Function codes created this way do support recursion enforcement and are therefore registered in the global function code registry.
        /// </summary>
        internal FunctionCode(TotemContext context, Delegate code, Parsing.Ast.ScopeStatement scope, int localCount)
        {
            _normalDelegate = code;
            _lambda = scope;
            _argCount = CalculateArgumentCount();

            // need to take this lock to ensure sys.settrace/sys.setprofile is not actively changing
            lock (_CodeCreateAndUpdateDelegateLock)
            {
                SetTarget(AddRecursionCheck(context, code));
            }

            RegisterFunctionCode(context);
        }
示例#10
0
        /// <summary>
        /// Constructor to create a FunctionCode at runtime.
        /// 
        /// Code constructed this way supports both being interpreted and debugged.  When necessary the code will
        /// be re-compiled or re-interpreted for that specific purpose.
        /// 
        /// Function codes created this way do support recursion enforcement and are therefore registered in the global function code registry.
        /// 
        /// the initial delegate provided here should NOT be the actual code.  It should always be a delegate which updates our Target lazily.
        /// </summary>
        internal FunctionCode(TotemContext context, Delegate initialDelegate, CompilableStmt code, bool? tracing, bool register)
        {
            _lambda = code;
            Target = LightThrowTarget = initialDelegate;
            _localCount = code._scopeVars == null ? 0 : code._scopeVars.Count;
            _argCount = CalculateArgumentCount();
            if (tracing.HasValue)
            {
                if (tracing.Value)
                {
                    _tracingDelegate = initialDelegate;
                }
                else
                {
                    _normalDelegate = initialDelegate;
                }
            }

            if (register)
            {
                RegisterFunctionCode(context);
            }
        }
示例#11
0
 private static CodeList GetRootCodeNoUpdating(TotemContext context)
 {
     CodeList cur = context._allCodes;
     if (cur == _CodeCreateAndUpdateDelegateLock)
     {
         lock (_CodeCreateAndUpdateDelegateLock)
         {
             // wait until enumerating thread is done, but it's alright
             // if we got cur and then an enumeration started (because we'll
             // just clear entries out)
             cur = context._allCodes;
             Debug.Assert(cur != _CodeCreateAndUpdateDelegateLock);
         }
     }
     return cur;
 }
示例#12
0
        /// <summary>
        /// Enumerates all function codes for updating the current type of targets we generate.
        /// 
        /// While enumerating we hold a lock so that users cannot change sys.settrace/sys.setprofile
        /// until the lock is released.
        /// </summary>
        private static IEnumerable<FunctionCode> GetAllCode(TotemContext context)
        {
            // only a single thread can enumerate the current FunctionCodes at a time.
            lock (_CodeCreateAndUpdateDelegateLock)
            {
                CodeList curCodeList = Interlocked.Exchange(ref context._allCodes, _CodeCreateAndUpdateDelegateLock);
                Debug.Assert(curCodeList != _CodeCreateAndUpdateDelegateLock);

                CodeList initialCode = curCodeList;

                try
                {
                    while (curCodeList != null)
                    {
                        WeakReference codeRef = curCodeList.Code;
                        FunctionCode target = (FunctionCode)codeRef.Target;

                        if (target != null)
                        {
                            yield return target;
                        }

                        curCodeList = curCodeList.Next;
                    }
                }
                finally
                {
                    Interlocked.Exchange(ref context._allCodes, initialCode);
                }
            }
        }
示例#13
0
        /// <summary>
        /// Updates the delegate based upon current Totem context settings for recursion enforcement
        /// and for tracing.
        /// </summary>
        internal void UpdateDelegate(TotemContext context, bool forceCreation)
        {
            Delegate finalTarget;

            if (context.EnableTracing && _lambda != null)
            {
                if (_tracingLambda == null)
                {
                    if (!forceCreation)
                    {
                        // the user just called sys.settrace(), don't force re-compilation of every method in the system.  Instead
                        // we'll just re-compile them as they're invoked.
                        Target = (Func<TotemFunction, TotemArgs, object>)IronTotem.Parsing.Ast.FunctionDefinition.FunctionDelegate;
                        LightThrowTarget = Target;
                        return;
                    }
                    throw new NotImplementedException();
                    //_tracingLambda = GetGeneratorOrNormalLambdaTracing(context);
                }

                if (_tracingDelegate == null)
                {
                    throw new NotImplementedException();
                    //_tracingDelegate = CompileLambda(_tracingLambda, new TargetUpdaterForCompilation(context, this).SetCompiledTargetTracing);
                }

                finalTarget = _tracingDelegate;
            }
            else
            {
                if (_normalDelegate == null)
                {
                    if (!forceCreation)
                    {
                        // we cannot create the delegate when forceCreation is false because we hold the
                        // _CodeCreateAndUpdateDelegateLock and compiling the delegate may create a FunctionCode
                        // object which requires the lock.
                        Target = (Func<TotemFunction, TotemArgs, object>)IronTotem.Parsing.Ast.FunctionDefinition.FunctionDelegate;
                        LightThrowTarget = Target;
                        return;
                    }
                    _normalDelegate = CompileLambda(GetGeneratorOrNormalLambda(), new TargetUpdaterForCompilation(context, this).SetCompiledTarget);
                }

                finalTarget = _normalDelegate;
            }

            finalTarget = AddRecursionCheck(context, finalTarget);

            SetTarget(finalTarget);
        }
示例#14
0
        /// <summary>
        /// Called to set the initial target delegate when the user has passed -X:Debug to enable
        /// .NET style debugging.
        /// </summary>
        internal void SetDebugTarget(TotemContext context, Delegate target)
        {
            _normalDelegate = target;

            SetTarget(AddRecursionCheck(context, target));
        }
示例#15
0
        internal Delegate AddRecursionCheck(TotemContext context, Delegate finalTarget)
        {
            //if (context.RecursionLimit != Int32.MaxValue)
            //{
            //    if (finalTarget is Func<CodeContext, CodeContext> ||
            //        finalTarget is Func<CodeContext, object> ||
            //        finalTarget is LookupComiplationDelegate)
            //    {
            //        return finalTarget;
            //    }

            //    switch (_lambda.ParameterNames.Length)
            //    {
            //        default:
            //            finalTarget = new Func<TotemFunction, object[], object>(new TotemFunctionRecursionCheckN((Func<TotemFunction, object[], object>)finalTarget).CallTarget);
            //            break;
            //    }
            //}
            return finalTarget;
        }
 public TotemScopeExtension(TotemContext context, TotemModule module, ModuleContext moduleContext)
     : base(module.Scope)
 {
     _module = module;
     _moduleContext = moduleContext;
 }
示例#17
0
 public TargetUpdaterForCompilation(TotemContext context, FunctionCode code)
 {
     _code = code;
     _context = context;
 }
示例#18
0
 public static void FunctionPushFrame(TotemContext context)
 {
     if (TotemFunction.AddRecursionDepth(1) > context.RecursionLimit)
     {
         throw TotemOps.RuntimeError("maximum recursion depth exceeded");
     }
 }
示例#19
0
 private bool ShouldInterpret(TotemContext tc)
 {
     return tc.ShouldInterpret((TotemCompilerOptions)Ast.CompilerContext.Options, Ast.CompilerContext.SourceUnit);
 }
示例#20
0
 private TotemNull(TotemContext context)
     : base(context.GetType<Null>())
 {
 }
 public TotemScopeExtension(TotemContext context, Scope scope)
     : base(scope)
 {
     _module = new TotemModule(context, scope);
     _moduleContext = new ModuleContext(_module, context);
 }
示例#22
0
        internal TotemOverload(TotemContext context, TotemType type, string name, Tuple<MethodInfo, TotemType.DynamicFlags>/*!*/[]/*!*/ methodInfos)
            : base(context.GetType<Overloaded>())
        {
            ContractUtils.RequiresNotNull(methodInfos, "methodInfos");
            ContractUtils.RequiresNotNull(name, "name");
            ContractUtils.RequiresNotNull(type, "type");

            _methodInfos = methodInfos;
            _name = name;
            _typeDefinition = type;
        }
示例#23
0
 internal static TotemMethod Create(TotemContext/*!*/ context, string name, ITotemCallable wrapped, object/*!*/ instance)
 {
     return new TotemMethod(context, name, wrapped, instance);
 }
示例#24
0
        /// <summary>
        /// Registers the current function code in our global weak list of all function codes.
        /// 
        /// The weak list can be enumerated with GetAllCode().
        /// 
        /// Ultimately there are 3 types of threads we care about races with:
        ///     1. Other threads which are registering function codes
        ///     2. Threads calling sys.settrace which require the world to stop and get updated
        ///     3. Threads running cleanup (thread pool thread, or call to gc.collect).
        ///     
        /// The 1st two must have perfect synchronization.  We cannot have a thread registering
        /// a new function which another thread is trying to update all of the functions in the world.  Doing
        /// so would mean we could miss adding tracing to a thread.   
        /// 
        /// But the cleanup thread can run in parallel to either registrying or sys.settrace.  The only
        /// thing it needs to take a lock for is updating our accounting information about the
        /// number of code objects are alive.
        /// </summary>
        private void RegisterFunctionCode(TotemContext context)
        {
            if (_lambda == null)
            {
                return;
            }

            WeakReference codeRef = new WeakReference(this);
            CodeList prevCode;
            lock (_CodeCreateAndUpdateDelegateLock)
            {
                Debug.Assert(context._allCodes != _CodeCreateAndUpdateDelegateLock);
                // we do an interlocked operation here because this can run in parallel w/ the CodeCleanup thread.  The
                // lock only prevents us from running in parallel w/ an update to all of the functions in the world which
                // needs to be synchronized.
                do
                {
                    prevCode = context._allCodes;
                } while (Interlocked.CompareExchange(ref context._allCodes, new CodeList(codeRef, prevCode), prevCode) != prevCode);

                if (context._codeCount++ == context._nextCodeCleanup)
                {
                    // run cleanup of codes on another thread
                    CleanFunctionCodes(context, false);
                }
            }
        }
示例#25
0
 internal static void CleanFunctionCodes(TotemContext context, bool synchronous)
 {
     if (synchronous)
     {
         CodeCleanup(context);
     }
     else
     {
         ThreadPool.QueueUserWorkItem(CodeCleanup, context);
     }
 }
示例#26
0
 internal static void UpdateAllCode(TotemContext context)
 {
     foreach (FunctionCode fc in GetAllCode(context))
     {
         fc.UpdateDelegate(context, false);
     }
 }
示例#27
0
        /// <summary>
        /// Constructor to create a FunctionCode at runtime.
        /// 
        /// Code constructed this way supports both being interpreted and debugged.  When necessary the code will
        /// be re-compiled or re-interpreted for that specific purpose.
        /// 
        /// Function codes created this way do support recursion enforcement and are therefore registered in the global function code registry.
        /// 
        /// the initial delegate provided here should NOT be the actual code.  It should always be a delegate which updates our Target lazily.
        /// </summary>
        internal FunctionCode(TotemContext context, Delegate initialDelegate, Parsing.Ast.ScopeStatement scope, bool? tracing, bool register)
        {
            _lambda = scope;
            Target = LightThrowTarget = initialDelegate;
            _localCount = scope.Variables == null ? 0 : scope.Variables.Count;
            _argCount = CalculateArgumentCount();
            if (tracing.HasValue)
            {
                if (tracing.Value)
                {
                    _tracingDelegate = initialDelegate;
                }
                else
                {
                    _normalDelegate = initialDelegate;
                }
            }

            if (register)
            {
                RegisterFunctionCode(context);
            }
        }
示例#28
0
 internal static TotemOverload Create(TotemContext/*!*/ context, TotemType/*!*/ type, string name, Tuple<MethodInfo, TotemType.DynamicFlags>/*!*/[]/*!*/ methodInfos)
 {
     return new TotemOverload(context, type, name, methodInfos);
 }
示例#29
0
 internal TotemModule(TotemContext context, Scope scope)
 {
     _dict = new TotemDictionary(new ScopeDictionaryStorage(context, scope));
     _scope = scope;
 }
示例#30
0
        private Delegate AddRecursionCheck(TotemContext context, Delegate finalTarget)
        {
            if (context.RecursionLimit != Int32.MaxValue)
            {
                if (finalTarget is Func<CodeContext, CodeContext> ||
                    finalTarget is Func<FunctionCode, object> ||
                    finalTarget is LookupCompilationDelegate)
                {
                    // no recursion enforcement on classes or modules
                    return finalTarget;
                }

                finalTarget = TotemCallTargets.AddRecursionCheck(_lambda.ParameterNames.Length > TotemCallTargets.MAX_ARGS, _lambda.ParameterNames.Length, finalTarget);
            }
            return finalTarget;
        }