MegaBites-AI/Windows-powershell
0308
1/* ****************************************************************************2 *3 * Copyright (c) Microsoft Corporation.4 *5 * This source code is subject to terms and conditions of the Apache License, Version 2.0. A6 * copy of the license can be found in the License.html file at the root of this distribution. If7 * you cannot locate the Apache License, Version 2.0, please send an email to8 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound9 * by the terms of the Apache License, Version 2.0.10 *11 * You must not remove this notice, or any other, from this software.12 *13 *14 * ***************************************************************************/15 16#if !CLR217#else18using Microsoft.Scripting.Ast;19#endif20using System.Collections.Generic;21using System.Diagnostics;22using System.Management.Automation.Language;23using System.Reflection;24using System.Runtime.CompilerServices;25 26namespace System.Management.Automation.Interpreter27{28 internal sealed class InterpretedFrame29 {30 public static readonly ThreadLocal<InterpretedFrame> CurrentFrame = new ThreadLocal<InterpretedFrame>();31 32 internal readonly Interpreter Interpreter;33 internal InterpretedFrame _parent;34 35 private readonly int[] _continuations;36 37 private int _continuationIndex;38 private int _pendingContinuation;39 private object _pendingValue;40 41 public readonly object[] Data;42 43 public readonly StrongBox<object>[] Closure;44 45 public int StackIndex;46 public int InstructionIndex;47 48 internal InterpretedFrame(Interpreter interpreter, StrongBox<object>[] closure)49 {50 Interpreter = interpreter;51 StackIndex = interpreter.LocalCount;52 Data = new object[StackIndex + interpreter.Instructions.MaxStackDepth];53 54 int c = interpreter.Instructions.MaxContinuationDepth;55 if (c > 0)56 {57 _continuations = new int[c];58 }59 60 Closure = closure;61 62 _pendingContinuation = -1;63 _pendingValue = Interpreter.NoValue;64 }65 66 public DebugInfo GetDebugInfo(int instructionIndex)67 {68 return DebugInfo.GetMatchingDebugInfo(Interpreter._debugInfos, instructionIndex);69 }70 71 public string Name72 {73 get { return Interpreter._name; }74 }75 76 #region Data Stack Operations77 78 public void Push(object value)79 {80 Data[StackIndex++] = value;81 }82 83 public void Push(bool value)84 {85 Data[StackIndex++] = value ? ScriptingRuntimeHelpers.True : ScriptingRuntimeHelpers.False;86 }87 88 public void Push(int value)89 {90 Data[StackIndex++] = ScriptingRuntimeHelpers.Int32ToObject(value);91 }92 93 public object Pop()94 {95 return Data[--StackIndex];96 }97 98 internal void SetStackDepth(int depth)99 {100 StackIndex = Interpreter.LocalCount + depth;101 }102 103 public object Peek()104 {105 return Data[StackIndex - 1];106 }107 108 public void Dup()109 {110 int i = StackIndex;111 Data[i] = Data[i - 1];112 StackIndex = i + 1;113 }114 115 public ExecutionContext ExecutionContext116 {117 get { return (ExecutionContext)Data[1]; }118 }119 120 public FunctionContext FunctionContext121 {122 get { return (FunctionContext)Data[0]; }123 }124 125 #endregion126 127 #region Stack Trace128 129 public InterpretedFrame Parent130 {131 get { return _parent; }132 }133 134 public static bool IsInterpretedFrame(MethodBase method)135 {136 // ContractUtils.RequiresNotNull(method, "method");137 return method.DeclaringType == typeof(Interpreter) && method.Name == "Run";138 }139 140 /// <summary>141 /// A single interpreted frame might be represented by multiple subsequent Interpreter.Run CLR frames.142 /// This method filters out the duplicate CLR frames.143 /// </summary>144 public static IEnumerable<StackFrame> GroupStackFrames(IEnumerable<StackFrame> stackTrace)145 {146 bool inInterpretedFrame = false;147 foreach (StackFrame frame in stackTrace)148 {149 if (InterpretedFrame.IsInterpretedFrame(frame.GetMethod()))150 {151 if (inInterpretedFrame)152 {153 continue;154 }155 156 inInterpretedFrame = true;157 }158 else159 {160 inInterpretedFrame = false;161 }162 163 yield return frame;164 }165 }166 167 public IEnumerable<InterpretedFrameInfo> GetStackTraceDebugInfo()168 {169 var frame = this;170 do171 {172 yield return new InterpretedFrameInfo(frame.Name, frame.GetDebugInfo(frame.InstructionIndex));173 frame = frame.Parent;174 } while (frame != null);175 }176 177 internal void SaveTraceToException(Exception exception)178 {179 if (exception.Data[typeof(InterpretedFrameInfo)] == null)180 {181 exception.Data[typeof(InterpretedFrameInfo)] = new List<InterpretedFrameInfo>(GetStackTraceDebugInfo()).ToArray();182 }183 }184 185 public static InterpretedFrameInfo[] GetExceptionStackTrace(Exception exception)186 {187 return exception.Data[typeof(InterpretedFrameInfo)] as InterpretedFrameInfo[];188 }189 190#if DEBUG191 internal string[] Trace192 {193 get194 {195 var trace = new List<string>();196 var frame = this;197 do198 {199 trace.Add(frame.Name);200 frame = frame.Parent;201 } while (frame != null);202 return trace.ToArray();203 }204 }205#endif206 207 internal ThreadLocal<InterpretedFrame>.StorageInfo Enter()208 {209 var currentFrame = InterpretedFrame.CurrentFrame.GetStorageInfo();210 _parent = currentFrame.Value;211 currentFrame.Value = this;212 return currentFrame;213 }214 215 internal void Leave(ThreadLocal<InterpretedFrame>.StorageInfo currentFrame)216 {217 currentFrame.Value = _parent;218 }219 220 #endregion221 222 #region Continuations223 224 internal bool IsJumpHappened()225 {226 return _pendingContinuation >= 0;227 }228 229 public void RemoveContinuation()230 {231 _continuationIndex--;232 }233 234 public void PushContinuation(int continuation)235 {236 _continuations[_continuationIndex++] = continuation;237 }238 239 public int YieldToCurrentContinuation()240 {241 var target = Interpreter._labels[_continuations[_continuationIndex - 1]];242 SetStackDepth(target.StackDepth);243 return target.Index - InstructionIndex;244 }245 246 /// <summary>247 /// Get called from the LeaveFinallyInstruction.248 /// </summary>249 public int YieldToPendingContinuation()250 {251 Debug.Assert(_pendingContinuation >= 0);252 RuntimeLabel pendingTarget = Interpreter._labels[_pendingContinuation];253 254 // the current continuation might have higher priority (continuationIndex is the depth of the current continuation):255 if (pendingTarget.ContinuationStackDepth < _continuationIndex)256 {257 RuntimeLabel currentTarget = Interpreter._labels[_continuations[_continuationIndex - 1]];258 SetStackDepth(currentTarget.StackDepth);259 return currentTarget.Index - InstructionIndex;260 }261 262 SetStackDepth(pendingTarget.StackDepth);263 if (_pendingValue != Interpreter.NoValue)264 {265 Data[StackIndex - 1] = _pendingValue;266 }267 268 // Set the _pendingContinuation and _pendingValue to the default values if we finally gets to the Goto target269 _pendingContinuation = -1;270 _pendingValue = Interpreter.NoValue;271 return pendingTarget.Index - InstructionIndex;272 }273 274 internal void PushPendingContinuation()275 {276 Push(_pendingContinuation);277 Push(_pendingValue);278 279 _pendingContinuation = -1;280 _pendingValue = Interpreter.NoValue;281 }282 283 internal void PopPendingContinuation()284 {285 _pendingValue = Pop();286 _pendingContinuation = (int)Pop();287 }288 289 private static MethodInfo s_goto;290 private static MethodInfo s_voidGoto;291 292 internal static MethodInfo GotoMethod293 {294 get { return s_goto ??= typeof(InterpretedFrame).GetMethod("Goto"); }295 }296 297 internal static MethodInfo VoidGotoMethod298 {299 get { return s_voidGoto ??= typeof(InterpretedFrame).GetMethod("VoidGoto"); }300 }301 302 public int VoidGoto(int labelIndex)303 {304 return Goto(labelIndex, Interpreter.NoValue, gotoExceptionHandler: false);305 }306 307 public int Goto(int labelIndex, object value, bool gotoExceptionHandler)308 {309 // TODO: we know this at compile time (except for compiled loop):310 RuntimeLabel target = Interpreter._labels[labelIndex];311 Debug.Assert(!gotoExceptionHandler || _continuationIndex == target.ContinuationStackDepth,312 "When it's time to jump to the exception handler, all previous finally blocks should already be processed");313 314 if (_continuationIndex == target.ContinuationStackDepth)315 {316 SetStackDepth(target.StackDepth);317 if (value != Interpreter.NoValue)318 {319 Data[StackIndex - 1] = value;320 }321 322 return target.Index - InstructionIndex;323 }324 325 // if we are in the middle of executing jump we forget the previous target and replace it by a new one:326 _pendingContinuation = labelIndex;327 _pendingValue = value;328 return YieldToCurrentContinuation();329 }330 331 #endregion332 }333}334 