forked from PowerShell/PowerShell
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathInterpreter.cs
More file actions
175 lines (153 loc) · 6.5 KB
/
Copy pathInterpreter.cs
File metadata and controls
175 lines (153 loc) · 6.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Apache License, Version 2.0. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Apache License, Version 2.0, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Apache License, Version 2.0.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
#if !CLR2
using System.Linq.Expressions;
#else
using Microsoft.Scripting.Ast;
#endif
#if CORECLR
// Use stub for SpecialNameAttribute
using Microsoft.PowerShell.CoreClr.Stubs;
#endif
using System.Runtime.CompilerServices;
using System.Threading;
using System.Diagnostics;
using System.Collections.Generic;
namespace System.Management.Automation.Interpreter
{
/// <summary>
/// A simple forth-style stack machine for executing Expression trees
/// without the need to compile to IL and then invoke the JIT. This trades
/// off much faster compilation time for a slower execution performance.
/// For code that is only run a small number of times this can be a
/// sweet spot.
///
/// The core loop in the interpreter is the RunInstructions method.
/// </summary>
internal sealed class Interpreter
{
internal static readonly object NoValue = new object();
internal const int RethrowOnReturn = Int32.MaxValue;
// zero: sync compilation
// negative: default
internal readonly int _compilationThreshold;
internal readonly object[] _objects;
internal readonly RuntimeLabel[] _labels;
internal readonly string _name;
internal readonly DebugInfo[] _debugInfos;
internal Interpreter(string name, LocalVariables locals, HybridReferenceDictionary<LabelTarget, BranchLabel> labelMapping,
InstructionArray instructions, DebugInfo[] debugInfos, int compilationThreshold)
{
_name = name;
LocalCount = locals.LocalCount;
ClosureVariables = locals.ClosureVariables;
Instructions = instructions;
_objects = instructions.Objects;
_labels = instructions.Labels;
LabelMapping = labelMapping;
_debugInfos = debugInfos;
_compilationThreshold = compilationThreshold;
}
internal int ClosureSize
{
get
{
if (ClosureVariables == null)
{
return 0;
}
return ClosureVariables.Count;
}
}
internal int LocalCount { get; }
internal bool CompileSynchronously
{
get { return _compilationThreshold <= 1; }
}
internal InstructionArray Instructions { get; }
internal Dictionary<ParameterExpression, LocalVariable> ClosureVariables { get; }
internal HybridReferenceDictionary<LabelTarget, BranchLabel> LabelMapping { get; }
/// <summary>
/// Runs instructions within the given frame.
/// </summary>
/// <remarks>
/// Interpreted stack frames are linked via Parent reference so that each CLR frame of this method corresponds
/// to an interpreted stack frame in the chain. It is therefore possible to combine CLR stack traces with
/// interpreted stack traces by aligning interpreted frames to the frames of this method.
/// Each group of subsequent frames of Run method corresponds to a single interpreted frame.
/// </remarks>
[SpecialName, MethodImpl(MethodImplOptions.NoInlining)]
public void Run(InterpretedFrame frame)
{
var instructions = Instructions.Instructions;
int index = frame.InstructionIndex;
while (index < instructions.Length)
{
index += instructions[index].Run(frame);
frame.InstructionIndex = index;
}
}
#if !CORECLR // Thread.Abort and ThreadAbortException are not in CoreCLR.
/// <summary>
/// To get to the current AbortReason object on Thread.CurrentThread
/// we need to use ExceptionState property of any ThreadAbortException instance.
/// </summary>
[ThreadStatic]
internal static ThreadAbortException AnyAbortException = null;
/// <summary>
/// If the target that 'Goto' jumps to is inside the current catch block or the subsequent finally block,
/// we delay the call to 'Abort' method, because we want to finish the catch/finally blocks
/// </summary>
internal static void AbortThreadIfRequested(InterpretedFrame frame, int targetLabelIndex)
{
var abortHandler = frame.CurrentAbortHandler;
var targetInstrIndex = frame.Interpreter._labels[targetLabelIndex].Index;
if (abortHandler != null &&
!abortHandler.IsInsideCatchBlock(targetInstrIndex) &&
!abortHandler.IsInsideFinallyBlock(targetInstrIndex))
{
frame.CurrentAbortHandler = null;
var currentThread = Thread.CurrentThread;
if ((currentThread.ThreadState & System.Threading.ThreadState.AbortRequested) != 0)
{
Debug.Assert(AnyAbortException != null);
// The current abort reason needs to be preserved.
#if SILVERLIGHT
currentThread.Abort();
#else
currentThread.Abort(AnyAbortException.ExceptionState);
#endif
}
}
}
#else
/// <summary>
/// A thread cannot be aborted in CoreCLR, as Thread.Abort() is not available in CoreCLR (neither is ThreadAbortException).
/// So this method doesn't need to do anything when running with CoreCLR
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static void AbortThreadIfRequested(InterpretedFrame frame, int targetLabelIndex) { }
#endif
internal int ReturnAndRethrowLabelIndex
{
get
{
// the last label is "return and rethrow" label:
Debug.Assert(_labels[_labels.Length - 1].Index == RethrowOnReturn);
return _labels.Length - 1;
}
}
}
}