1 /* ****************************************************************************
3 * Copyright (c) Microsoft Corporation.
5 * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
6 * copy of the license can be found in the License.html file at the root of this distribution. If
7 * you cannot locate the Apache License, Version 2.0, please send an email to
8 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
9 * by the terms of the Apache License, Version 2.0.
11 * You must not remove this notice, or any other, from this software.
14 * ***************************************************************************/
17 using System
.Linq
.Expressions
;
19 using Microsoft
.Scripting
.Ast
;
23 using System
.Reflection
;
24 using System
.Runtime
.CompilerServices
;
25 using Microsoft
.Scripting
.Runtime
;
26 using System
.Collections
.Generic
;
27 using Microsoft
.Scripting
.Utils
;
29 namespace Microsoft
.Scripting
.Interpreter
{
30 internal interface IBoxableInstruction
{
31 Instruction
BoxIfIndexMatches(int index
);
34 internal abstract class LocalAccessInstruction
: Instruction
{
35 internal readonly int _index
;
37 protected LocalAccessInstruction(int index
) {
41 public override string ToDebugString(int instructionIndex
, object cookie
, Func
<int, int> labelIndexer
, IList
<object> objects
) {
42 return cookie
== null ?
43 InstructionName
+ "(" + _index
+ ")" :
44 InstructionName
+ "(" + cookie
+ ": " + _index
+ ")";
50 internal sealed class LoadLocalInstruction
: LocalAccessInstruction
, IBoxableInstruction
{
51 internal LoadLocalInstruction(int index
)
55 public override int ProducedStack { get { return 1; }
}
57 public override int Run(InterpretedFrame frame
) {
58 frame
.Data
[frame
.StackIndex
++] = frame
.Data
[_index
];
59 //frame.Push(frame.Data[_index]);
63 public Instruction
BoxIfIndexMatches(int index
) {
64 return (index
== _index
) ? InstructionList
.LoadLocalBoxed(index
) : null;
68 internal sealed class LoadLocalBoxedInstruction
: LocalAccessInstruction
{
69 internal LoadLocalBoxedInstruction(int index
)
73 public override int ProducedStack { get { return 1; }
}
75 public override int Run(InterpretedFrame frame
) {
76 var box
= (StrongBox
<object>)frame
.Data
[_index
];
77 frame
.Data
[frame
.StackIndex
++] = box
.Value
;
82 internal sealed class LoadLocalFromClosureInstruction
: LocalAccessInstruction
{
83 internal LoadLocalFromClosureInstruction(int index
)
87 public override int ProducedStack { get { return 1; }
}
89 public override int Run(InterpretedFrame frame
) {
90 var box
= frame
.Closure
[_index
];
91 frame
.Data
[frame
.StackIndex
++] = box
.Value
;
96 internal sealed class LoadLocalFromClosureBoxedInstruction
: LocalAccessInstruction
{
97 internal LoadLocalFromClosureBoxedInstruction(int index
)
101 public override int ProducedStack { get { return 1; }
}
103 public override int Run(InterpretedFrame frame
) {
104 var box
= frame
.Closure
[_index
];
105 frame
.Data
[frame
.StackIndex
++] = box
;
112 #region Store, Assign
114 internal sealed class AssignLocalInstruction
: LocalAccessInstruction
, IBoxableInstruction
{
115 internal AssignLocalInstruction(int index
)
119 public override int ConsumedStack { get { return 1; }
}
120 public override int ProducedStack { get { return 1; }
}
122 public override int Run(InterpretedFrame frame
) {
123 frame
.Data
[_index
] = frame
.Peek();
127 public Instruction
BoxIfIndexMatches(int index
) {
128 return (index
== _index
) ? InstructionList
.AssignLocalBoxed(index
) : null;
132 internal sealed class StoreLocalInstruction
: LocalAccessInstruction
, IBoxableInstruction
{
133 internal StoreLocalInstruction(int index
)
137 public override int ConsumedStack { get { return 1; }
}
138 public override int Run(InterpretedFrame frame
) {
139 frame
.Data
[_index
] = frame
.Data
[--frame
.StackIndex
];
140 //frame.Data[_index] = frame.Pop();
144 public Instruction
BoxIfIndexMatches(int index
) {
145 return (index
== _index
) ? InstructionList
.StoreLocalBoxed(index
) : null;
149 internal sealed class AssignLocalBoxedInstruction
: LocalAccessInstruction
{
150 internal AssignLocalBoxedInstruction(int index
)
154 public override int ConsumedStack { get { return 1; }
}
155 public override int ProducedStack { get { return 1; }
}
157 public override int Run(InterpretedFrame frame
) {
158 var box
= (StrongBox
<object>)frame
.Data
[_index
];
159 box
.Value
= frame
.Peek();
164 internal sealed class StoreLocalBoxedInstruction
: LocalAccessInstruction
{
165 internal StoreLocalBoxedInstruction(int index
)
169 public override int ConsumedStack { get { return 1; }
}
170 public override int ProducedStack { get { return 0; }
}
172 public override int Run(InterpretedFrame frame
) {
173 var box
= (StrongBox
<object>)frame
.Data
[_index
];
174 box
.Value
= frame
.Data
[--frame
.StackIndex
];
179 internal sealed class AssignLocalToClosureInstruction
: LocalAccessInstruction
{
180 internal AssignLocalToClosureInstruction(int index
)
184 public override int ConsumedStack { get { return 1; }
}
185 public override int ProducedStack { get { return 1; }
}
187 public override int Run(InterpretedFrame frame
) {
188 var box
= frame
.Closure
[_index
];
189 box
.Value
= frame
.Peek();
198 [System
.Diagnostics
.CodeAnalysis
.SuppressMessage("Microsoft.Design", "CA1012:AbstractTypesShouldNotHaveConstructors")]
199 internal abstract class InitializeLocalInstruction
: LocalAccessInstruction
{
200 internal InitializeLocalInstruction(int index
)
204 internal sealed class Reference
: InitializeLocalInstruction
, IBoxableInstruction
{
205 internal Reference(int index
)
209 public override int Run(InterpretedFrame frame
) {
210 frame
.Data
[_index
] = null;
214 public Instruction
BoxIfIndexMatches(int index
) {
215 return (index
== _index
) ? InstructionList
.InitImmutableRefBox(index
) : null;
218 public override string InstructionName
{
219 get { return "InitRef"; }
223 internal sealed class ImmutableValue
: InitializeLocalInstruction
, IBoxableInstruction
{
224 private readonly object _defaultValue
;
226 internal ImmutableValue(int index
, object defaultValue
)
228 _defaultValue
= defaultValue
;
231 public override int Run(InterpretedFrame frame
) {
232 frame
.Data
[_index
] = _defaultValue
;
236 public Instruction
BoxIfIndexMatches(int index
) {
237 return (index
== _index
) ? new ImmutableBox(index
, _defaultValue
) : null;
240 public override string InstructionName
{
241 get { return "InitImmutableValue"; }
245 internal sealed class ImmutableBox
: InitializeLocalInstruction
{
247 private readonly object _defaultValue
;
249 internal ImmutableBox(int index
, object defaultValue
)
251 _defaultValue
= defaultValue
;
254 public override int Run(InterpretedFrame frame
) {
255 frame
.Data
[_index
] = new StrongBox
<object>(_defaultValue
);
259 public override string InstructionName
{
260 get { return "InitImmutableBox"; }
264 internal sealed class ParameterBox
: InitializeLocalInstruction
{
265 public ParameterBox(int index
)
269 public override int Run(InterpretedFrame frame
) {
270 frame
.Data
[_index
] = new StrongBox
<object>(frame
.Data
[_index
]);
276 internal sealed class Parameter
: InitializeLocalInstruction
, IBoxableInstruction
{
277 internal Parameter(int index
)
281 public override int Run(InterpretedFrame frame
) {
286 public Instruction
BoxIfIndexMatches(int index
) {
287 if (index
== _index
) {
288 return InstructionList
.ParameterBox(index
);
293 public override string InstructionName
{
294 get { return "InitParameter"; }
298 internal sealed class MutableValue
: InitializeLocalInstruction
, IBoxableInstruction
{
299 private readonly Type _type
;
301 internal MutableValue(int index
, Type type
)
306 public override int Run(InterpretedFrame frame
) {
308 frame
.Data
[_index
] = Activator
.CreateInstance(_type
);
309 } catch (TargetInvocationException e
) {
310 ExceptionHelpers
.UpdateForRethrow(e
.InnerException
);
311 throw e
.InnerException
;
317 public Instruction
BoxIfIndexMatches(int index
) {
318 return (index
== _index
) ? new MutableBox(index
, _type
) : null;
321 public override string InstructionName
{
322 get { return "InitMutableValue"; }
326 internal sealed class MutableBox
: InitializeLocalInstruction
{
327 private readonly Type _type
;
329 internal MutableBox(int index
, Type type
)
334 public override int Run(InterpretedFrame frame
) {
335 frame
.Data
[_index
] = new StrongBox
<object>(Activator
.CreateInstance(_type
));
339 public override string InstructionName
{
340 get { return "InitMutableBox"; }
347 #region RuntimeVariables
349 internal sealed class RuntimeVariablesInstruction
: Instruction
{
350 private readonly int _count
;
352 public RuntimeVariablesInstruction(int count
) {
356 public override int ProducedStack { get { return 1; }
}
357 public override int ConsumedStack { get { return _count; }
}
359 public override int Run(InterpretedFrame frame
) {
360 var ret
= new IStrongBox
[_count
];
361 for (int i
= ret
.Length
- 1; i
>= 0; i
--) {
362 ret
[i
] = (IStrongBox
)frame
.Pop();
364 frame
.Push(RuntimeVariables
.Create(ret
));
368 public override string ToString() {
369 return "GetRuntimeVariables()";