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 * ***************************************************************************/
15 // Enables instruction counting and displaying stats at process exit.
19 using System.Collections.Generic;
20 using System.Diagnostics;
21 using System.Reflection;
22 using System.Runtime.CompilerServices;
23 using System.Security;
24 using Microsoft.Scripting.Runtime;
25 using Microsoft.Scripting.Utils;
27 namespace Microsoft.Scripting.Interpreter {
28 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes")]
29 [DebuggerTypeProxy(typeof(InstructionArray.DebugView))]
30 public struct InstructionArray {
31 internal readonly int MaxStackDepth;
32 internal readonly int MaxContinuationDepth;
33 internal readonly Instruction[] Instructions;
34 internal readonly object[] Objects;
35 internal readonly RuntimeLabel[] Labels;
37 // list of (instruction index, cookie) sorted by instruction index:
38 internal readonly List<KeyValuePair<int, object>> DebugCookies;
40 internal InstructionArray(int maxStackDepth, int maxContinuationDepth, Instruction[] instructions,
41 object[] objects, RuntimeLabel[] labels, List<KeyValuePair<int, object>> debugCookies) {
43 MaxStackDepth = maxStackDepth;
44 MaxContinuationDepth = maxContinuationDepth;
45 Instructions = instructions;
46 DebugCookies = debugCookies;
52 get { return Instructions.Length; }
57 internal sealed class DebugView {
58 private readonly InstructionArray _array;
60 public DebugView(InstructionArray array) {
65 [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
66 public InstructionList.DebugView.InstructionView[]/*!*/ A0 {
68 return InstructionList.DebugView.GetInstructionViews(
71 (index) => _array.Labels[index].Index,
81 [DebuggerTypeProxy(typeof(InstructionList.DebugView))]
82 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling")]
83 public sealed class InstructionList {
84 private readonly List<Instruction> _instructions = new List<Instruction>();
85 private List<object> _objects;
87 private int _currentStackDepth;
88 private int _maxStackDepth;
89 private int _currentContinuationsDepth;
90 private int _maxContinuationDepth;
91 private int _runtimeLabelCount;
92 private List<BranchLabel> _labels;
94 // list of (instruction index, cookie) sorted by instruction index:
95 private List<KeyValuePair<int, object>> _debugCookies = null;
99 internal sealed class DebugView {
100 private readonly InstructionList _list;
102 public DebugView(InstructionList list) {
106 [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
107 public InstructionView[]/*!*/ A0 {
109 return GetInstructionViews(
112 (index) => _list._labels[index].TargetIndex,
118 internal static InstructionView[] GetInstructionViews(IList<Instruction> instructions, IList<object> objects,
119 Func<int, int> labelIndexer, IList<KeyValuePair<int, object>> debugCookies) {
121 var result = new List<InstructionView>();
124 int continuationsDepth = 0;
126 var cookieEnumerator = (debugCookies != null ? debugCookies : new KeyValuePair<int, object>[0]).GetEnumerator();
127 var hasCookie = cookieEnumerator.MoveNext();
129 for (int i = 0; i < instructions.Count; i++) {
130 object cookie = null;
131 while (hasCookie && cookieEnumerator.Current.Key == i) {
132 cookie = cookieEnumerator.Current.Value;
133 hasCookie = cookieEnumerator.MoveNext();
136 int stackDiff = instructions[i].StackBalance;
137 int contDiff = instructions[i].ContinuationsBalance;
138 string name = instructions[i].ToDebugString(i, cookie, labelIndexer, objects);
139 result.Add(new InstructionView(instructions[i], name, i, stackDepth, continuationsDepth));
142 stackDepth += stackDiff;
143 continuationsDepth += contDiff;
145 return result.ToArray();
148 [DebuggerDisplay("{GetValue(),nq}", Name = "{GetName(),nq}", Type = "{GetDisplayType(), nq}")]
149 internal struct InstructionView {
150 private readonly int _index;
151 private readonly int _stackDepth;
152 private readonly int _continuationsDepth;
153 private readonly string _name;
154 private readonly Instruction _instruction;
156 internal string GetName() {
157 return _index.ToString() +
158 (_continuationsDepth == 0 ? "" : " C(" + _continuationsDepth.ToString() + ")") +
159 (_stackDepth == 0 ? "" : " S(" + _stackDepth.ToString() + ")");
162 internal string GetValue() {
166 internal string GetDisplayType() {
167 return _instruction.ContinuationsBalance.ToString() + "/" + _instruction.StackBalance.ToString();
170 public InstructionView(Instruction instruction, string name, int index, int stackDepth, int continuationsDepth) {
171 _instruction = instruction;
174 _stackDepth = stackDepth;
175 _continuationsDepth = continuationsDepth;
182 #region Core Emit Ops
184 public void Emit(Instruction instruction) {
185 _instructions.Add(instruction);
186 UpdateStackDepth(instruction);
189 private void UpdateStackDepth(Instruction instruction) {
190 Debug.Assert(instruction.ConsumedStack >= 0 && instruction.ProducedStack >= 0 &&
191 instruction.ConsumedContinuations >= 0 && instruction.ProducedContinuations >= 0);
193 _currentStackDepth -= instruction.ConsumedStack;
194 Debug.Assert(_currentStackDepth >= 0);
195 _currentStackDepth += instruction.ProducedStack;
196 if (_currentStackDepth > _maxStackDepth) {
197 _maxStackDepth = _currentStackDepth;
200 _currentContinuationsDepth -= instruction.ConsumedContinuations;
201 Debug.Assert(_currentContinuationsDepth >= 0);
202 _currentContinuationsDepth += instruction.ProducedContinuations;
203 if (_currentContinuationsDepth > _maxContinuationDepth) {
204 _maxContinuationDepth = _currentContinuationsDepth;
209 /// Attaches a cookie to the last emitted instruction.
211 [Conditional("DEBUG")]
212 public void SetDebugCookie(object cookie) {
214 if (_debugCookies == null) {
215 _debugCookies = new List<KeyValuePair<int, object>>();
218 Debug.Assert(Count > 0);
219 _debugCookies.Add(new KeyValuePair<int, object>(Count - 1, cookie));
224 get { return _instructions.Count; }
227 public int CurrentStackDepth {
228 get { return _currentStackDepth; }
231 public int CurrentContinuationsDepth {
232 get { return _currentContinuationsDepth; }
235 public int MaxStackDepth {
236 get { return _maxStackDepth; }
239 internal Instruction GetInstruction(int index) {
240 return _instructions[index];
244 private static Dictionary<string, int> _executedInstructions = new Dictionary<string, int>();
245 private static Dictionary<string, Dictionary<object, bool>> _instances = new Dictionary<string, Dictionary<object, bool>>();
247 static InstructionList() {
248 AppDomain.CurrentDomain.ProcessExit += new EventHandler((_, __) => {
249 PerfTrack.DumpHistogram(_executedInstructions);
250 Console.WriteLine("-- Total executed: {0}", _executedInstructions.Values.Aggregate(0, (sum, value) => sum + value));
251 Console.WriteLine("-----");
253 var referenced = new Dictionary<string, int>();
255 foreach (var entry in _instances) {
256 referenced[entry.Key] = entry.Value.Count;
257 total += entry.Value.Count;
260 PerfTrack.DumpHistogram(referenced);
261 Console.WriteLine("-- Total referenced: {0}", total);
262 Console.WriteLine("-----");
266 public InstructionArray ToArray() {
268 lock (_executedInstructions) {
269 _instructions.ForEach((instr) => {
271 var name = instr.GetType().Name;
272 _executedInstructions.TryGetValue(name, out value);
273 _executedInstructions[name] = value + 1;
275 Dictionary<object, bool> dict;
276 if (!_instances.TryGetValue(name, out dict)) {
277 _instances[name] = dict = new Dictionary<object, bool>();
283 return new InstructionArray(
285 _maxContinuationDepth,
286 _instructions.ToArray(),
287 (_objects != null) ? _objects.ToArray() : null,
288 BuildRuntimeLabels(),
295 #region Stack Operations
297 private const int PushIntMinCachedValue = -100;
298 private const int PushIntMaxCachedValue = 100;
299 private const int CachedObjectCount = 256;
301 private static Instruction _null;
302 private static Instruction _true;
303 private static Instruction _false;
304 private static Instruction[] _ints;
305 private static Instruction[] _loadObjectCached;
307 public void EmitLoad(object value) {
308 EmitLoad(value, null);
311 public void EmitLoad(bool value) {
313 Emit(_true ?? (_true = new LoadObjectInstruction(value)));
315 Emit(_false ?? (_false = new LoadObjectInstruction(value)));
319 public void EmitLoad(object value, Type type) {
321 Emit(_null ?? (_null = new LoadObjectInstruction(null)));
325 if (type == null || type.IsValueType()) {
327 EmitLoad((bool)value);
333 if (i >= PushIntMinCachedValue && i <= PushIntMaxCachedValue) {
335 _ints = new Instruction[PushIntMaxCachedValue - PushIntMinCachedValue + 1];
337 i -= PushIntMinCachedValue;
338 Emit(_ints[i] ?? (_ints[i] = new LoadObjectInstruction(value)));
344 if (_objects == null) {
345 _objects = new List<object>();
346 if (_loadObjectCached == null) {
347 _loadObjectCached = new Instruction[CachedObjectCount];
351 if (_objects.Count < _loadObjectCached.Length) {
352 uint index = (uint)_objects.Count;
354 Emit(_loadObjectCached[index] ?? (_loadObjectCached[index] = new LoadCachedObjectInstruction(index)));
356 Emit(new LoadObjectInstruction(value));
360 public void EmitDup() {
361 Emit(DupInstruction.Instance);
364 public void EmitPop() {
365 Emit(PopInstruction.Instance);
372 internal void SwitchToBoxed(int index, int instructionIndex) {
373 var instruction = _instructions[instructionIndex] as IBoxableInstruction;
375 if (instruction != null) {
376 var newInstruction = instruction.BoxIfIndexMatches(index);
377 if (newInstruction != null) {
378 _instructions[instructionIndex] = newInstruction;
383 private const int LocalInstrCacheSize = 64;
385 private static Instruction[] _loadLocal;
386 private static Instruction[] _loadLocalBoxed;
387 private static Instruction[] _loadLocalFromClosure;
388 private static Instruction[] _loadLocalFromClosureBoxed;
389 private static Instruction[] _assignLocal;
390 private static Instruction[] _storeLocal;
391 private static Instruction[] _assignLocalBoxed;
392 private static Instruction[] _storeLocalBoxed;
393 private static Instruction[] _assignLocalToClosure;
394 private static Instruction[] _initReference;
395 private static Instruction[] _initImmutableRefBox;
396 private static Instruction[] _parameterBox;
397 private static Instruction[] _parameter;
399 public void EmitLoadLocal(int index) {
400 if (_loadLocal == null) {
401 _loadLocal = new Instruction[LocalInstrCacheSize];
404 if (index < _loadLocal.Length) {
405 Emit(_loadLocal[index] ?? (_loadLocal[index] = new LoadLocalInstruction(index)));
407 Emit(new LoadLocalInstruction(index));
411 public void EmitLoadLocalBoxed(int index) {
412 Emit(LoadLocalBoxed(index));
415 internal static Instruction LoadLocalBoxed(int index) {
416 if (_loadLocalBoxed == null) {
417 _loadLocalBoxed = new Instruction[LocalInstrCacheSize];
420 if (index < _loadLocalBoxed.Length) {
421 return _loadLocalBoxed[index] ?? (_loadLocalBoxed[index] = new LoadLocalBoxedInstruction(index));
423 return new LoadLocalBoxedInstruction(index);
427 public void EmitLoadLocalFromClosure(int index) {
428 if (_loadLocalFromClosure == null) {
429 _loadLocalFromClosure = new Instruction[LocalInstrCacheSize];
432 if (index < _loadLocalFromClosure.Length) {
433 Emit(_loadLocalFromClosure[index] ?? (_loadLocalFromClosure[index] = new LoadLocalFromClosureInstruction(index)));
435 Emit(new LoadLocalFromClosureInstruction(index));
439 public void EmitLoadLocalFromClosureBoxed(int index) {
440 if (_loadLocalFromClosureBoxed == null) {
441 _loadLocalFromClosureBoxed = new Instruction[LocalInstrCacheSize];
444 if (index < _loadLocalFromClosureBoxed.Length) {
445 Emit(_loadLocalFromClosureBoxed[index] ?? (_loadLocalFromClosureBoxed[index] = new LoadLocalFromClosureBoxedInstruction(index)));
447 Emit(new LoadLocalFromClosureBoxedInstruction(index));
451 public void EmitAssignLocal(int index) {
452 if (_assignLocal == null) {
453 _assignLocal = new Instruction[LocalInstrCacheSize];
456 if (index < _assignLocal.Length) {
457 Emit(_assignLocal[index] ?? (_assignLocal[index] = new AssignLocalInstruction(index)));
459 Emit(new AssignLocalInstruction(index));
463 public void EmitStoreLocal(int index) {
464 if (_storeLocal == null) {
465 _storeLocal = new Instruction[LocalInstrCacheSize];
468 if (index < _storeLocal.Length) {
469 Emit(_storeLocal[index] ?? (_storeLocal[index] = new StoreLocalInstruction(index)));
471 Emit(new StoreLocalInstruction(index));
475 public void EmitAssignLocalBoxed(int index) {
476 Emit(AssignLocalBoxed(index));
479 internal static Instruction AssignLocalBoxed(int index) {
480 if (_assignLocalBoxed == null) {
481 _assignLocalBoxed = new Instruction[LocalInstrCacheSize];
484 if (index < _assignLocalBoxed.Length) {
485 return _assignLocalBoxed[index] ?? (_assignLocalBoxed[index] = new AssignLocalBoxedInstruction(index));
487 return new AssignLocalBoxedInstruction(index);
491 public void EmitStoreLocalBoxed(int index) {
492 Emit(StoreLocalBoxed(index));
495 internal static Instruction StoreLocalBoxed(int index) {
496 if (_storeLocalBoxed == null) {
497 _storeLocalBoxed = new Instruction[LocalInstrCacheSize];
500 if (index < _storeLocalBoxed.Length) {
501 return _storeLocalBoxed[index] ?? (_storeLocalBoxed[index] = new StoreLocalBoxedInstruction(index));
503 return new StoreLocalBoxedInstruction(index);
507 public void EmitAssignLocalToClosure(int index) {
508 if (_assignLocalToClosure == null) {
509 _assignLocalToClosure = new Instruction[LocalInstrCacheSize];
512 if (index < _assignLocalToClosure.Length) {
513 Emit(_assignLocalToClosure[index] ?? (_assignLocalToClosure[index] = new AssignLocalToClosureInstruction(index)));
515 Emit(new AssignLocalToClosureInstruction(index));
519 public void EmitStoreLocalToClosure(int index) {
520 EmitAssignLocalToClosure(index);
524 public void EmitInitializeLocal(int index, Type type) {
525 object value = ScriptingRuntimeHelpers.GetPrimitiveDefaultValue(type);
527 Emit(new InitializeLocalInstruction.ImmutableValue(index, value));
528 } else if (type.IsValueType()) {
529 Emit(new InitializeLocalInstruction.MutableValue(index, type));
531 Emit(InitReference(index));
535 internal void EmitInitializeParameter(int index) {
536 Emit(Parameter(index));
539 internal static Instruction Parameter(int index) {
540 if (_parameter == null) {
541 _parameter = new Instruction[LocalInstrCacheSize];
544 if (index < _parameter.Length) {
545 return _parameter[index] ?? (_parameter[index] = new InitializeLocalInstruction.Parameter(index));
548 return new InitializeLocalInstruction.Parameter(index);
551 internal static Instruction ParameterBox(int index) {
552 if (_parameterBox == null) {
553 _parameterBox = new Instruction[LocalInstrCacheSize];
556 if (index < _parameterBox.Length) {
557 return _parameterBox[index] ?? (_parameterBox[index] = new InitializeLocalInstruction.ParameterBox(index));
560 return new InitializeLocalInstruction.ParameterBox(index);
563 internal static Instruction InitReference(int index) {
564 if (_initReference == null) {
565 _initReference = new Instruction[LocalInstrCacheSize];
568 if (index < _initReference.Length) {
569 return _initReference[index] ?? (_initReference[index] = new InitializeLocalInstruction.Reference(index));
572 return new InitializeLocalInstruction.Reference(index);
575 internal static Instruction InitImmutableRefBox(int index) {
576 if (_initImmutableRefBox == null) {
577 _initImmutableRefBox = new Instruction[LocalInstrCacheSize];
580 if (index < _initImmutableRefBox.Length) {
581 return _initImmutableRefBox[index] ?? (_initImmutableRefBox[index] = new InitializeLocalInstruction.ImmutableBox(index, null));
584 return new InitializeLocalInstruction.ImmutableBox(index, null);
587 public void EmitNewRuntimeVariables(int count) {
588 Emit(new RuntimeVariablesInstruction(count));
593 #region Array Operations
595 public void EmitGetArrayItem(Type arrayType) {
596 Type elementType = arrayType.GetElementType();
597 if (elementType.IsClass() || elementType.IsInterface()) {
598 Emit(InstructionFactory<object>.Factory.GetArrayItem());
600 Emit(InstructionFactory.GetFactory(elementType).GetArrayItem());
604 public void EmitGetArrayLength(Type arrayType) {
605 Emit(GetArrayLengthInstruction.Create());
608 public void EmitSetArrayItem(Type arrayType) {
609 Type elementType = arrayType.GetElementType();
610 if (elementType.IsClass() || elementType.IsInterface()) {
611 Emit(InstructionFactory<object>.Factory.SetArrayItem());
613 Emit(InstructionFactory.GetFactory(elementType).SetArrayItem());
617 public void EmitNewArray(Type elementType) {
618 Emit(InstructionFactory.GetFactory(elementType).NewArray());
621 public void EmitNewArrayBounds(Type elementType, int rank) {
622 Emit(new NewArrayBoundsInstruction(elementType, rank));
625 public void EmitNewArrayInit(Type elementType, int elementCount) {
626 Emit(InstructionFactory.GetFactory(elementType).NewArrayInit(elementCount));
631 #region Arithmetic Operations
633 public void EmitAdd(Type type, bool @checked) {
635 Emit(AddOvfInstruction.Create(type));
637 Emit(AddInstruction.Create(type));
641 public void EmitSub(Type type, bool @checked) {
643 Emit(SubOvfInstruction.Create(type));
645 Emit(SubInstruction.Create(type));
649 public void EmitMul(Type type, bool @checked) {
651 Emit(MulOvfInstruction.Create(type));
653 Emit(MulInstruction.Create(type));
657 public void EmitDiv(Type type) {
658 Emit(DivInstruction.Create(type));
661 public void EmitMod(Type type) {
662 Emit(ModInstruction.Create(type));
667 public void EmitShl(Type type) {
668 Emit(ShlInstruction.Create(type));
671 public void EmitShr(Type type) {
672 Emit(ShrInstruction.Create(type));
675 public void EmitOr(Type type) {
676 Emit(OrInstruction.Create(type));
679 public void EmitAnd(Type type) {
680 Emit(AndInstruction.Create(type));
683 public void EmitExclusiveOr(Type type) {
684 Emit(XorInstruction.Create(type));
689 public void EmitEqual(Type type) {
690 Emit(EqualInstruction.Create(type));
693 public void EmitNotEqual(Type type) {
694 Emit(NotEqualInstruction.Create(type));
697 public void EmitLessThan(Type type) {
698 Emit(LessThanInstruction.Create(type));
701 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters")]
702 public void EmitLessThanOrEqual(Type type) {
703 throw new NotSupportedException();
706 public void EmitGreaterThan(Type type) {
707 Emit(GreaterThanInstruction.Create(type));
710 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters")]
711 public void EmitGreaterThanOrEqual(Type type) {
712 throw new NotSupportedException();
719 public void EmitNumericConvertChecked(TypeCode from, TypeCode to) {
720 Emit(new NumericConvertInstruction.Checked(from, to));
723 public void EmitNumericConvertUnchecked(TypeCode from, TypeCode to) {
724 Emit(new NumericConvertInstruction.Unchecked(from, to));
729 #region Unary Operators
731 public void EmitNegate(Type type, bool @checked) {
733 Emit(NegateOvfInstruction.Create(type));
735 Emit(NegateInstruction.Create(type));
738 public void EmitNot(Type type) {
739 Emit(NotInstruction.Create(type));
746 public void EmitDefaultValue(Type type) {
747 Emit(InstructionFactory.GetFactory(type).DefaultValue());
750 public void EmitNew(ConstructorInfo constructorInfo) {
751 Emit(new NewInstruction(constructorInfo));
754 internal void EmitCreateDelegate(LightDelegateCreator creator) {
755 Emit(new CreateDelegateInstruction(creator));
758 public void EmitTypeEquals() {
759 Emit(TypeEqualsInstruction.Instance);
762 public void EmitTypeIs(Type type) {
763 Emit(InstructionFactory.GetFactory(type).TypeIs());
766 public void EmitTypeAs(Type type) {
767 Emit(InstructionFactory.GetFactory(type).TypeAs());
772 #region Fields and Methods
774 private static readonly Dictionary<FieldInfo, Instruction> _loadFields = new Dictionary<FieldInfo, Instruction>();
776 public void EmitLoadField(FieldInfo field) {
777 Emit(GetLoadField(field));
780 private Instruction GetLoadField(FieldInfo field) {
782 Instruction instruction;
783 if (!_loadFields.TryGetValue(field, out instruction)) {
784 if (field.IsStatic) {
785 instruction = new LoadStaticFieldInstruction(field);
787 instruction = new LoadFieldInstruction(field);
789 _loadFields.Add(field, instruction);
795 public void EmitStoreField(FieldInfo field) {
796 if (field.IsStatic) {
797 Emit(new StoreStaticFieldInstruction(field));
799 Emit(new StoreFieldInstruction(field));
807 public void EmitDynamic(Type type, CallSiteBinder binder) {
808 Emit(CreateDynamicInstruction(type, binder));
811 #region Generated Dynamic InstructionList Factory
813 // *** BEGIN GENERATED CODE ***
814 // generated by function: gen_instructionlist_factory from: generate_dynamic_instructions.py
816 public void EmitDynamic<T0, TRet>(CallSiteBinder binder) {
817 Emit(DynamicInstruction<T0, TRet>.Factory(binder));
820 public void EmitDynamic<T0, T1, TRet>(CallSiteBinder binder) {
821 Emit(DynamicInstruction<T0, T1, TRet>.Factory(binder));
824 public void EmitDynamic<T0, T1, T2, TRet>(CallSiteBinder binder) {
825 Emit(DynamicInstruction<T0, T1, T2, TRet>.Factory(binder));
828 public void EmitDynamic<T0, T1, T2, T3, TRet>(CallSiteBinder binder) {
829 Emit(DynamicInstruction<T0, T1, T2, T3, TRet>.Factory(binder));
832 public void EmitDynamic<T0, T1, T2, T3, T4, TRet>(CallSiteBinder binder) {
833 Emit(DynamicInstruction<T0, T1, T2, T3, T4, TRet>.Factory(binder));
836 public void EmitDynamic<T0, T1, T2, T3, T4, T5, TRet>(CallSiteBinder binder) {
837 Emit(DynamicInstruction<T0, T1, T2, T3, T4, T5, TRet>.Factory(binder));
840 public void EmitDynamic<T0, T1, T2, T3, T4, T5, T6, TRet>(CallSiteBinder binder) {
841 Emit(DynamicInstruction<T0, T1, T2, T3, T4, T5, T6, TRet>.Factory(binder));
844 public void EmitDynamic<T0, T1, T2, T3, T4, T5, T6, T7, TRet>(CallSiteBinder binder) {
845 Emit(DynamicInstruction<T0, T1, T2, T3, T4, T5, T6, T7, TRet>.Factory(binder));
848 public void EmitDynamic<T0, T1, T2, T3, T4, T5, T6, T7, T8, TRet>(CallSiteBinder binder) {
849 Emit(DynamicInstruction<T0, T1, T2, T3, T4, T5, T6, T7, T8, TRet>.Factory(binder));
852 public void EmitDynamic<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, TRet>(CallSiteBinder binder) {
853 Emit(DynamicInstruction<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, TRet>.Factory(binder));
856 public void EmitDynamic<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TRet>(CallSiteBinder binder) {
857 Emit(DynamicInstruction<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TRet>.Factory(binder));
860 public void EmitDynamic<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TRet>(CallSiteBinder binder) {
861 Emit(DynamicInstruction<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TRet>.Factory(binder));
864 public void EmitDynamic<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TRet>(CallSiteBinder binder) {
865 Emit(DynamicInstruction<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TRet>.Factory(binder));
868 public void EmitDynamic<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TRet>(CallSiteBinder binder) {
869 Emit(DynamicInstruction<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TRet>.Factory(binder));
872 public void EmitDynamic<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TRet>(CallSiteBinder binder) {
873 Emit(DynamicInstruction<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TRet>.Factory(binder));
877 // *** END GENERATED CODE ***
881 private static Dictionary<Type, Func<CallSiteBinder, Instruction>> _factories =
882 new Dictionary<Type, Func<CallSiteBinder, Instruction>>();
884 /// <exception cref="SecurityException">Instruction can't be created due to insufficient privileges.</exception>
885 internal static Instruction CreateDynamicInstruction(Type delegateType, CallSiteBinder binder) {
886 Func<CallSiteBinder, Instruction> factory;
888 if (!_factories.TryGetValue(delegateType, out factory)) {
889 if (delegateType.GetMethod("Invoke").ReturnType == typeof(void)) {
890 // TODO: We should generally support void returning binders but the only
891 // ones that exist are delete index/member who's perf isn't that critical.
892 return new DynamicInstructionN(delegateType, CallSite.Create(delegateType, binder), true);
895 Type instructionType = DynamicInstructionN.GetDynamicInstructionType(delegateType);
896 if (instructionType == null) {
897 return new DynamicInstructionN(delegateType, CallSite.Create(delegateType, binder));
900 factory = (Func<CallSiteBinder, Instruction>)instructionType.GetMethod("Factory").CreateDelegate(typeof(Func<CallSiteBinder, Instruction>));
901 _factories[delegateType] = factory;
904 return factory(binder);
911 private static readonly RuntimeLabel[] EmptyRuntimeLabels = new RuntimeLabel[] { new RuntimeLabel(Interpreter.RethrowOnReturn, 0, 0) };
913 private RuntimeLabel[] BuildRuntimeLabels() {
914 if (_runtimeLabelCount == 0) {
915 return EmptyRuntimeLabels;
918 var result = new RuntimeLabel[_runtimeLabelCount + 1];
919 foreach (BranchLabel label in _labels) {
920 if (label.HasRuntimeLabel) {
921 result[label.LabelIndex] = label.ToRuntimeLabel();
924 // "return and rethrow" label:
925 result[result.Length - 1] = new RuntimeLabel(Interpreter.RethrowOnReturn, 0, 0);
929 public BranchLabel MakeLabel() {
930 if (_labels == null) {
931 _labels = new List<BranchLabel>();
934 var label = new BranchLabel();
939 internal void FixupBranch(int branchIndex, int offset) {
940 _instructions[branchIndex] = ((OffsetInstruction)_instructions[branchIndex]).Fixup(offset);
943 private int EnsureLabelIndex(BranchLabel label) {
944 if (label.HasRuntimeLabel) {
945 return label.LabelIndex;
948 label.LabelIndex = _runtimeLabelCount;
949 _runtimeLabelCount++;
950 return label.LabelIndex;
953 public int MarkRuntimeLabel() {
954 BranchLabel handlerLabel = MakeLabel();
955 MarkLabel(handlerLabel);
956 return EnsureLabelIndex(handlerLabel);
959 public void MarkLabel(BranchLabel label) {
963 public void EmitGoto(BranchLabel label, bool hasResult, bool hasValue) {
964 Emit(GotoInstruction.Create(EnsureLabelIndex(label), hasResult, hasValue));
967 private void EmitBranch(OffsetInstruction instruction, BranchLabel label) {
969 label.AddBranch(this, Count - 1);
972 public void EmitBranch(BranchLabel label) {
973 EmitBranch(new BranchInstruction(), label);
976 public void EmitBranch(BranchLabel label, bool hasResult, bool hasValue) {
977 EmitBranch(new BranchInstruction(hasResult, hasValue), label);
980 public void EmitCoalescingBranch(BranchLabel leftNotNull) {
981 EmitBranch(new CoalescingBranchInstruction(), leftNotNull);
984 public void EmitBranchTrue(BranchLabel elseLabel) {
985 EmitBranch(new BranchTrueInstruction(), elseLabel);
988 public void EmitBranchFalse(BranchLabel elseLabel) {
989 EmitBranch(new BranchFalseInstruction(), elseLabel);
992 public void EmitThrow() {
993 Emit(ThrowInstruction.Throw);
996 public void EmitThrowVoid() {
997 Emit(ThrowInstruction.VoidThrow);
1000 public void EmitRethrow() {
1001 Emit(ThrowInstruction.Rethrow);
1004 public void EmitRethrowVoid() {
1005 Emit(ThrowInstruction.VoidRethrow);
1008 public void EmitEnterTryFinally(BranchLabel finallyStartLabel) {
1009 Emit(EnterTryFinallyInstruction.Create(EnsureLabelIndex(finallyStartLabel)));
1012 public void EmitEnterFinally() {
1013 Emit(EnterFinallyInstruction.Instance);
1016 public void EmitLeaveFinally() {
1017 Emit(LeaveFinallyInstruction.Instance);
1020 public void EmitLeaveFault(bool hasValue) {
1021 Emit(hasValue ? LeaveFaultInstruction.NonVoid : LeaveFaultInstruction.Void);
1024 public void EmitEnterExceptionHandlerNonVoid() {
1025 Emit(EnterExceptionHandlerInstruction.NonVoid);
1028 public void EmitEnterExceptionHandlerVoid() {
1029 Emit(EnterExceptionHandlerInstruction.Void);
1032 public void EmitLeaveExceptionHandler(bool hasValue, BranchLabel tryExpressionEndLabel) {
1033 Emit(LeaveExceptionHandlerInstruction.Create(EnsureLabelIndex(tryExpressionEndLabel), hasValue));
1036 public void EmitSwitch(Dictionary<int, int> cases) {
1037 Emit(new SwitchInstruction(cases));