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()";