public void Dispose()
        {
            // Write the cache back out to backing storage
            foreach (var(name, local) in _cache.OrderByDescending(a => SegmentIndex(a.Key)))
            {
                if (_mutated.Contains(name))
                {
                    var skip = _emitter.DefineLabel();

                    var dirty = _cacheDirty[name];
                    _emitter.LoadLocal(dirty);
                    _emitter.BranchIfFalse(skip);

                    _emitter.LoadLocal(local.Local);
                    _emitter.EmitCoerce(local.Type, StackType.YololValue);
                    EmitStoreValue(name);

                    _emitter.MarkLabel(skip);
                }

                local.Local.Dispose();
            }

            // Dispose the locals
            foreach (var local in _cacheDirty)
            {
                local.Value.Dispose();
            }
        }
Пример #2
0
            /// <summary>
            /// Emit code to dynamically check for errors. If an error would occur clear out the stack and jump away to the given label
            /// </summary>
            /// <typeparam name="TEmit"></typeparam>
            /// <param name="emitter"></param>
            /// <param name="errorLabel"></param>
            /// <param name="parameters"></param>
            public void EmitDynamicWillThrow <TEmit>(OptimisingEmitter <TEmit> emitter, Compiler.Emitter.Instructions.ExceptionBlock errorLabel, IReadOnlyList <Local> parameters)
            {
                // Load parameters back onto stack
                for (var i = parameters.Count - 1; i >= 0; i--)
                {
                    emitter.LoadLocal(parameters[i]);
                }

                // Invoke the `will throw` method to discover if this invocation would trigger a runtime error
                emitter.Call(WillThrow);

                // Create a label to jump past the error handling for the normal case
                var noThrowLabel = emitter.DefineLabel();

                // Jump past error handling if this is ok
                emitter.BranchIfFalse(noThrowLabel);

                // If execution reaches here it means an error would occur in this operation
                emitter.Leave(errorLabel);

                emitter.MarkLabel(noThrowLabel);
            }