PageRenderTime 31ms CodeModel.GetById 18ms app.highlight 10ms RepoModel.GetById 1ms app.codeStats 1ms

/Mono.Cecil.Cil/MethodBody.cs

http://github.com/jbevain/cecil
C# | 263 lines | 194 code | 60 blank | 9 comment | 37 complexity | 14cc1463a84ed50cbd0de20590085069 MD5 | raw file
  1//
  2// Author:
  3//   Jb Evain (jbevain@gmail.com)
  4//
  5// Copyright (c) 2008 - 2015 Jb Evain
  6// Copyright (c) 2008 - 2011 Novell, Inc.
  7//
  8// Licensed under the MIT/X11 license.
  9//
 10
 11using System;
 12using System.Threading;
 13
 14using Mono.Collections.Generic;
 15
 16namespace Mono.Cecil.Cil {
 17
 18	public sealed class MethodBody {
 19
 20		readonly internal MethodDefinition method;
 21
 22		internal ParameterDefinition this_parameter;
 23		internal int max_stack_size;
 24		internal int code_size;
 25		internal bool init_locals;
 26		internal MetadataToken local_var_token;
 27
 28		internal Collection<Instruction> instructions;
 29		internal Collection<ExceptionHandler> exceptions;
 30		internal Collection<VariableDefinition> variables;
 31
 32		public MethodDefinition Method {
 33			get { return method; }
 34		}
 35
 36		public int MaxStackSize {
 37			get { return max_stack_size; }
 38			set { max_stack_size = value; }
 39		}
 40
 41		public int CodeSize {
 42			get { return code_size; }
 43		}
 44
 45		public bool InitLocals {
 46			get { return init_locals; }
 47			set { init_locals = value; }
 48		}
 49
 50		public MetadataToken LocalVarToken {
 51			get { return local_var_token; }
 52			set { local_var_token = value; }
 53		}
 54
 55		public Collection<Instruction> Instructions {
 56			get {
 57				if (instructions == null)
 58					Interlocked.CompareExchange (ref instructions, new InstructionCollection (method), null);
 59
 60				return instructions;
 61			}
 62		}
 63
 64		public bool HasExceptionHandlers {
 65			get { return !exceptions.IsNullOrEmpty (); }
 66		}
 67
 68		public Collection<ExceptionHandler> ExceptionHandlers {
 69			get {
 70				if (exceptions == null)
 71					Interlocked.CompareExchange (ref exceptions, new Collection<ExceptionHandler> (), null);
 72
 73				return exceptions;
 74			}
 75		}
 76
 77		public bool HasVariables {
 78			get { return !variables.IsNullOrEmpty (); }
 79		}
 80
 81		public Collection<VariableDefinition> Variables {
 82			get {
 83				if (variables == null)
 84					Interlocked.CompareExchange (ref variables, new VariableDefinitionCollection (), null);
 85
 86				return variables;
 87			}
 88		}
 89
 90		public ParameterDefinition ThisParameter {
 91			get {
 92				if (method == null || method.DeclaringType == null)
 93					throw new NotSupportedException ();
 94
 95				if (!method.HasThis)
 96					return null;
 97
 98				if (this_parameter == null)
 99					Interlocked.CompareExchange (ref this_parameter, CreateThisParameter (method), null);
100
101				return this_parameter;
102			}
103		}
104
105		static ParameterDefinition CreateThisParameter (MethodDefinition method)
106		{
107			var parameter_type = method.DeclaringType as TypeReference;
108
109			if (parameter_type.HasGenericParameters) {
110				var instance = new GenericInstanceType (parameter_type, parameter_type.GenericParameters.Count);
111				for (int i = 0; i < parameter_type.GenericParameters.Count; i++)
112					instance.GenericArguments.Add (parameter_type.GenericParameters [i]);
113
114				parameter_type = instance;
115
116			}
117
118			if (parameter_type.IsValueType || parameter_type.IsPrimitive)
119				parameter_type = new ByReferenceType (parameter_type);
120
121			return new ParameterDefinition (parameter_type, method);
122		}
123
124		public MethodBody (MethodDefinition method)
125		{
126			this.method = method;
127		}
128
129		public ILProcessor GetILProcessor ()
130		{
131			return new ILProcessor (this);
132		}
133	}
134
135	sealed class VariableDefinitionCollection : Collection<VariableDefinition> {
136
137		internal VariableDefinitionCollection ()
138		{
139		}
140
141		internal VariableDefinitionCollection (int capacity)
142			: base (capacity)
143		{
144		}
145
146		protected override void OnAdd (VariableDefinition item, int index)
147		{
148			item.index = index;
149		}
150
151		protected override void OnInsert (VariableDefinition item, int index)
152		{
153			item.index = index;
154
155			for (int i = index; i < size; i++)
156				items [i].index = i + 1;
157		}
158
159		protected override void OnSet (VariableDefinition item, int index)
160		{
161			item.index = index;
162		}
163
164		protected override void OnRemove (VariableDefinition item, int index)
165		{
166			item.index = -1;
167
168			for (int i = index + 1; i < size; i++)
169				items [i].index = i - 1;
170		}
171	}
172
173	class InstructionCollection : Collection<Instruction> {
174
175		readonly MethodDefinition method;
176
177		internal InstructionCollection (MethodDefinition method)
178		{
179			this.method = method;
180		}
181
182		internal InstructionCollection (MethodDefinition method, int capacity)
183			: base (capacity)
184		{
185			this.method = method;
186		}
187
188		protected override void OnAdd (Instruction item, int index)
189		{
190			if (index == 0)
191				return;
192
193			var previous = items [index - 1];
194			previous.next = item;
195			item.previous = previous;
196		}
197
198		protected override void OnInsert (Instruction item, int index)
199		{
200			if (size == 0)
201				return;
202
203			var current = items [index];
204			if (current == null) {
205				var last = items [index - 1];
206				last.next = item;
207				item.previous = last;
208				return;
209			}
210
211			var previous = current.previous;
212			if (previous != null) {
213				previous.next = item;
214				item.previous = previous;
215			}
216
217			current.previous = item;
218			item.next = current;
219		}
220
221		protected override void OnSet (Instruction item, int index)
222		{
223			var current = items [index];
224
225			item.previous = current.previous;
226			item.next = current.next;
227
228			current.previous = null;
229			current.next = null;
230		}
231
232		protected override void OnRemove (Instruction item, int index)
233		{
234			var previous = item.previous;
235			if (previous != null)
236				previous.next = item.next;
237
238			var next = item.next;
239			if (next != null)
240				next.previous = item.previous;
241
242			RemoveSequencePoint (item);
243
244			item.previous = null;
245			item.next = null;
246		}
247
248		void RemoveSequencePoint (Instruction instruction)
249		{
250			var debug_info = method.debug_info;
251			if (debug_info == null || !debug_info.HasSequencePoints)
252				return;
253
254			var sequence_points = debug_info.sequence_points;
255			for (int i = 0; i < sequence_points.Count; i++) {
256				if (sequence_points [i].Offset == instruction.offset) {
257					sequence_points.RemoveAt (i);
258					return;
259				}
260			}
261		}
262	}
263}