IKVM11  11
Java SE 11 Virtual Machine for .NET
Loading...
Searching...
No Matches
FieldAccessor.cs
Go to the documentation of this file.
1using System;
2using System.Linq;
3using System.Reflection;
4using System.Reflection.Emit;
5using System.Threading;
6
8{
9
10#if FIRST_PASS == false && EXPORTER == false && IMPORTER == false
11
15 internal abstract class FieldAccessor
16 {
17
18 readonly Type type;
19 readonly string name;
20 FieldInfo field;
21
28 protected FieldAccessor(Type type, string name)
29 {
30 this.type = type ?? throw new ArgumentNullException(nameof(type));
31 this.name = name ?? throw new ArgumentNullException(nameof(name));
32 }
33
37 protected Type Type => type;
38
42 protected string Name => name;
43
47 protected FieldInfo Field => AccessorUtil.LazyGet(ref field, () => type.GetField(name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)) ?? throw new InvalidOperationException();
48
49 }
50
55 internal sealed class FieldAccessor<TField> : FieldAccessor
56 {
57
65 public static FieldAccessor<TField> LazyGet(ref FieldAccessor<TField> location, Type type, string name)
66 {
67 return AccessorUtil.LazyGet(ref location, () => new FieldAccessor<TField>(type, name));
68 }
69
70 Func<TField> getter;
71 Action<TField> setter;
72
78 public FieldAccessor(Type type, string name) :
79 base(type, name)
80 {
81
82 }
83
87 Func<TField> Getter => AccessorUtil.LazyGet(ref getter, MakeGetter);
88
92 Action<TField> Setter => AccessorUtil.LazyGet(ref setter, MakeSetter);
93
99 Func<TField> MakeGetter()
100 {
101#if FIRST_PASS
102 throw new NotImplementedException();
103#else
104 var dm = DynamicMethodUtil.Create($"__<FieldAccessorGet>__{Type.Name.Replace(".", "_")}__{Field.Name}", Type, false, typeof(TField), Array.Empty<Type>());
105 var il = JVM.Context.CodeEmitterFactory.Create(dm);
106
107 il.Emit(OpCodes.Ldsfld, Field);
108 il.Emit(OpCodes.Ret);
109 il.DoEmit();
110
111 return (Func<TField>)dm.CreateDelegate(typeof(Func<TField>));
112#endif
113 }
114
120 Action<TField> MakeSetter()
121 {
122#if FIRST_PASS
123 throw new NotImplementedException();
124#else
125 var dm = DynamicMethodUtil.Create($"__<FieldAccessorSet>__{Type.Name.Replace(".", "_")}__{Field.Name}", Type, false, typeof(void), new[] { typeof(TField) });
126 var il = JVM.Context.CodeEmitterFactory.Create(dm);
127
128 il.Emit(OpCodes.Ldarg_0);
129 il.Emit(OpCodes.Stsfld, Field);
130 il.Emit(OpCodes.Ret);
131 il.DoEmit();
132
133 return (Action<TField>)dm.CreateDelegate(typeof(Action<TField>));
134#endif
135 }
136
141 public TField GetValue() => Getter();
142
147 public void SetValue(TField value) => Setter(value);
148
149 }
150
156 internal sealed class FieldAccessor<TObject, TField> : FieldAccessor
157 {
158
159 delegate TField GetterDelegate(TObject self);
160 delegate void SetterDelegate(TObject self, TField value);
161 delegate TField ExchangeDelegate(TObject self, TField value);
162 delegate TField CompareExchangeDelegate(TObject self, TField value, TField comparand);
163
164 static readonly MethodInfo ExchangeOfInt32 = typeof(Interlocked).GetMethod(nameof(Interlocked.Exchange), new[] { typeof(int).MakeByRefType(), typeof(int) });
165 static readonly MethodInfo ExchangeOfInt64 = typeof(Interlocked).GetMethod(nameof(Interlocked.Exchange), new[] { typeof(long).MakeByRefType(), typeof(long) });
166 static readonly MethodInfo ExchangeOfSingle = typeof(Interlocked).GetMethod(nameof(Interlocked.Exchange), new[] { typeof(float).MakeByRefType(), typeof(float) });
167 static readonly MethodInfo ExchangeOfDouble = typeof(Interlocked).GetMethod(nameof(Interlocked.Exchange), new[] { typeof(double).MakeByRefType(), typeof(double) });
168 static readonly MethodInfo ExchangeOfT = typeof(Interlocked).GetMethods().First(i => i.Name == nameof(Interlocked.Exchange) && i.GetGenericArguments().Length == 1);
169
170 static readonly MethodInfo CompareExchangeOfInt32 = typeof(Interlocked).GetMethod(nameof(Interlocked.CompareExchange), new[] { typeof(int).MakeByRefType(), typeof(int), typeof(int) });
171 static readonly MethodInfo CompareExchangeOfInt64 = typeof(Interlocked).GetMethod(nameof(Interlocked.CompareExchange), new[] { typeof(long).MakeByRefType(), typeof(long), typeof(long) });
172 static readonly MethodInfo CompareExchangeOfSingle = typeof(Interlocked).GetMethod(nameof(Interlocked.CompareExchange), new[] { typeof(float).MakeByRefType(), typeof(float), typeof(float) });
173 static readonly MethodInfo CompareExchangeOfDouble = typeof(Interlocked).GetMethod(nameof(Interlocked.CompareExchange), new[] { typeof(double).MakeByRefType(), typeof(double), typeof(double) });
174 static readonly MethodInfo CompareExchangeOfT = typeof(Interlocked).GetMethods().First(i => i.Name == nameof(Interlocked.CompareExchange) && i.GetGenericArguments().Length == 1);
175
183 public static FieldAccessor<TObject, TField> LazyGet(ref FieldAccessor<TObject, TField> location, Type type, string name)
184 {
185 return AccessorUtil.LazyGet(ref location, () => new FieldAccessor<TObject, TField>(type, name));
186 }
187
188 GetterDelegate getter;
189 SetterDelegate setter;
190 ExchangeDelegate exchange;
191 CompareExchangeDelegate compareExchange;
192
198 public FieldAccessor(Type type, string name) :
199 base(type, name)
200 {
201
202 }
203
207 GetterDelegate Getter => AccessorUtil.LazyGet(ref getter, MakeGetter);
208
212 SetterDelegate Setter => AccessorUtil.LazyGet(ref setter, MakeSetter);
213
217 ExchangeDelegate Exchange => AccessorUtil.LazyGet(ref exchange, MakeExchange);
218
222 CompareExchangeDelegate CompareExchange => AccessorUtil.LazyGet(ref compareExchange, MakeCompareExchange);
223
228 GetterDelegate MakeGetter()
229 {
230#if FIRST_PASS || IMPORTER || EXPORTER
231 throw new NotImplementedException();
232#else
233 var dm = DynamicMethodUtil.Create($"__<FieldAccessorGet>__{Field.DeclaringType.Name.Replace(".", "_")}__{Field.Name}", Type, false, typeof(TField), new[] { typeof(TObject) });
234 var il = JVM.Context.CodeEmitterFactory.Create(dm);
235
236 il.Emit(OpCodes.Ldarg_0);
237 il.Emit(OpCodes.Castclass, Type);
238 il.Emit(OpCodes.Ldfld, Field);
239 il.Emit(OpCodes.Ret);
240 il.DoEmit();
241
242 return (GetterDelegate)dm.CreateDelegate(typeof(GetterDelegate));
243#endif
244 }
245
250 SetterDelegate MakeSetter()
251 {
252#if FIRST_PASS || IMPORTER || EXPORTER
253 throw new NotImplementedException();
254#else
255 var dm = DynamicMethodUtil.Create($"__<FieldAccessorSet>__{Field.DeclaringType.Name.Replace(".", "_")}__{Field.Name}", Type, false, typeof(void), new[] { typeof(TObject), typeof(TField) });
256 var il = JVM.Context.CodeEmitterFactory.Create(dm);
257
258 il.Emit(OpCodes.Ldarg_0);
259 il.Emit(OpCodes.Castclass, Type);
260 il.Emit(OpCodes.Ldarg_1);
261 il.Emit(OpCodes.Stfld, Field);
262 il.Emit(OpCodes.Ret);
263 il.DoEmit();
264
265 return (SetterDelegate)dm.CreateDelegate(typeof(SetterDelegate));
266#endif
267 }
268
273 ExchangeDelegate MakeExchange()
274 {
275#if FIRST_PASS || IMPORTER || EXPORTER
276 throw new NotImplementedException();
277#else
278 var dm = DynamicMethodUtil.Create($"__<FieldAccessorExchange>__{Field.DeclaringType.Name.Replace(".", "_")}__{Field.Name}", Type, false, typeof(TField), new[] { typeof(TObject), typeof(TField) });
279 var il = JVM.Context.CodeEmitterFactory.Create(dm);
280
281 il.EmitLdarg(0);
282 il.Emit(OpCodes.Castclass, Type);
283 il.Emit(Field.IsStatic ? OpCodes.Ldsflda: OpCodes.Ldflda, Field);
284 il.EmitLdarg(1);
285
286 switch (typeof(TField))
287 {
288 case Type t when t == typeof(int):
289 il.Emit(OpCodes.Call, ExchangeOfInt32);
290 break;
291 case Type t when t == typeof(long):
292 il.Emit(OpCodes.Call, ExchangeOfInt64);
293 break;
294 case Type t when t == typeof(float):
295 il.Emit(OpCodes.Call, ExchangeOfSingle);
296 break;
297 case Type t when t == typeof(double):
298 il.Emit(OpCodes.Call, ExchangeOfDouble);
299 break;
300 case Type t when t.IsValueType == false:
301 il.Emit(OpCodes.Call, ExchangeOfT.MakeGenericMethod(Field.FieldType));
302 break;
303 default:
304 throw new InternalException("No Interlocked.Exchange implementation for type.");
305 }
306
307 il.Emit(OpCodes.Ret);
308 il.DoEmit();
309
310 return (ExchangeDelegate)dm.CreateDelegate(typeof(ExchangeDelegate));
311#endif
312 }
313
318 CompareExchangeDelegate MakeCompareExchange()
319 {
320#if FIRST_PASS || IMPORTER || EXPORTER
321 throw new NotImplementedException();
322#else
323 var dm = DynamicMethodUtil.Create($"__<FieldAccessorCompareExchange>__{Field.DeclaringType.Name.Replace(".", "_")}__{Field.Name}", Type, false, typeof(TField), new[] { typeof(TObject), typeof(TField), typeof(TField) });
324 var il = JVM.Context.CodeEmitterFactory.Create(dm);
325
326 il.EmitLdarg(0);
327 il.Emit(OpCodes.Castclass, Type);
328 il.Emit(Field.IsStatic ? OpCodes.Ldsflda : OpCodes.Ldflda, Field);
329 il.EmitLdarg(1);
330 il.EmitLdarg(2);
331
332 switch (typeof(TField))
333 {
334 case Type t when t == typeof(int):
335 il.Emit(OpCodes.Call, CompareExchangeOfInt32);
336 break;
337 case Type t when t == typeof(long):
338 il.Emit(OpCodes.Call, CompareExchangeOfInt64);
339 break;
340 case Type t when t == typeof(float):
341 il.Emit(OpCodes.Call, CompareExchangeOfSingle);
342 break;
343 case Type t when t == typeof(double):
344 il.Emit(OpCodes.Call, CompareExchangeOfDouble);
345 break;
346 case Type t when t.IsValueType == false:
347 il.Emit(OpCodes.Call, CompareExchangeOfT.MakeGenericMethod(Field.FieldType));
348 break;
349 default:
350 throw new InternalException("No Interlocked.CompareExchange implementation for type.");
351 }
352
353 il.Emit(OpCodes.Ret);
354 il.DoEmit();
355
356 return (CompareExchangeDelegate)dm.CreateDelegate(typeof(CompareExchangeDelegate));
357#endif
358 }
359
365 public TField GetValue(TObject self) => Getter(self);
366
372 public void SetValue(TObject self, TField value) => Setter(self, value);
373
380 public TField ExchangeValue(TObject self, TField value) => Exchange(self, value);
381
389 public TField CompareExchangeValue(TObject self, TField value, TField comparand) => CompareExchange(self, value, comparand);
390
391 }
392
393#endif
394
395}
System.Threading.Interlocked Interlocked
IKVM.Reflection.Type Type
IKVM.Reflection.FieldInfo FieldInfo
IKVM.Reflection.MethodInfo MethodInfo
global::java.lang.invoke.LambdaForm.Name Name