Merge pull request #4155 from BrzVlad/fix-tls-lmf-addr
[mono-project.git] / mcs / class / dlr / Runtime / Microsoft.Dynamic / Interpreter / Instructions / LocalAccess.cs
blobbc0709553d1438c2ed074b496971383b753ae422
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 * ***************************************************************************/
16 #if FEATURE_CORE_DLR
17 using System.Linq.Expressions;
18 #else
19 using Microsoft.Scripting.Ast;
20 #endif
22 using System;
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) {
38 _index = 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 + ")";
48 #region Load
50 internal sealed class LoadLocalInstruction : LocalAccessInstruction, IBoxableInstruction {
51 internal LoadLocalInstruction(int index)
52 : base(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]);
60 return +1;
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)
70 : base(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;
78 return +1;
82 internal sealed class LoadLocalFromClosureInstruction : LocalAccessInstruction {
83 internal LoadLocalFromClosureInstruction(int index)
84 : base(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;
92 return +1;
96 internal sealed class LoadLocalFromClosureBoxedInstruction : LocalAccessInstruction {
97 internal LoadLocalFromClosureBoxedInstruction(int index)
98 : base(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;
106 return +1;
110 #endregion
112 #region Store, Assign
114 internal sealed class AssignLocalInstruction : LocalAccessInstruction, IBoxableInstruction {
115 internal AssignLocalInstruction(int index)
116 : base(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();
124 return +1;
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)
134 : base(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();
141 return +1;
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)
151 : base(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();
160 return +1;
164 internal sealed class StoreLocalBoxedInstruction : LocalAccessInstruction {
165 internal StoreLocalBoxedInstruction(int index)
166 : base(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];
175 return +1;
179 internal sealed class AssignLocalToClosureInstruction : LocalAccessInstruction {
180 internal AssignLocalToClosureInstruction(int index)
181 : base(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();
190 return +1;
194 #endregion
196 #region Initialize
198 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1012:AbstractTypesShouldNotHaveConstructors")]
199 internal abstract class InitializeLocalInstruction : LocalAccessInstruction {
200 internal InitializeLocalInstruction(int index)
201 : base(index) {
204 internal sealed class Reference : InitializeLocalInstruction, IBoxableInstruction {
205 internal Reference(int index)
206 : base(index) {
209 public override int Run(InterpretedFrame frame) {
210 frame.Data[_index] = null;
211 return 1;
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)
227 : base(index) {
228 _defaultValue = defaultValue;
231 public override int Run(InterpretedFrame frame) {
232 frame.Data[_index] = _defaultValue;
233 return 1;
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 {
246 // immutable value:
247 private readonly object _defaultValue;
249 internal ImmutableBox(int index, object defaultValue)
250 : base(index) {
251 _defaultValue = defaultValue;
254 public override int Run(InterpretedFrame frame) {
255 frame.Data[_index] = new StrongBox<object>(_defaultValue);
256 return 1;
259 public override string InstructionName {
260 get { return "InitImmutableBox"; }
264 internal sealed class ParameterBox : InitializeLocalInstruction {
265 public ParameterBox(int index)
266 : base(index) {
269 public override int Run(InterpretedFrame frame) {
270 frame.Data[_index] = new StrongBox<object>(frame.Data[_index]);
271 return 1;
276 internal sealed class Parameter : InitializeLocalInstruction, IBoxableInstruction {
277 internal Parameter(int index)
278 : base(index) {
281 public override int Run(InterpretedFrame frame) {
282 // nop
283 return 1;
286 public Instruction BoxIfIndexMatches(int index) {
287 if (index == _index) {
288 return InstructionList.ParameterBox(index);
290 return null;
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)
302 : base(index) {
303 _type = type;
306 public override int Run(InterpretedFrame frame) {
307 try {
308 frame.Data[_index] = Activator.CreateInstance(_type);
309 } catch (TargetInvocationException e) {
310 ExceptionHelpers.UpdateForRethrow(e.InnerException);
311 throw e.InnerException;
314 return 1;
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)
330 : base(index) {
331 _type = type;
334 public override int Run(InterpretedFrame frame) {
335 frame.Data[_index] = new StrongBox<object>(Activator.CreateInstance(_type));
336 return 1;
339 public override string InstructionName {
340 get { return "InitMutableBox"; }
345 #endregion
347 #region RuntimeVariables
349 internal sealed class RuntimeVariablesInstruction : Instruction {
350 private readonly int _count;
352 public RuntimeVariablesInstruction(int count) {
353 _count = 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));
365 return +1;
368 public override string ToString() {
369 return "GetRuntimeVariables()";
373 #endregion