IKVM11  11
Java SE 11 Virtual Machine for .NET
Loading...
Searching...
No Matches
RuntimeSimpleJavaField.cs
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2014 Jeroen Frijters
3
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any damages
6 arising from the use of this software.
7
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it
10 freely, subject to the following restrictions:
11
12 1. The origin of this software must not be misrepresented; you must not
13 claim that you wrote the original software. If you use this software
14 in a product, an acknowledgment in the product documentation would be
15 appreciated but is not required.
16 2. Altered source versions must be plainly marked as such, and must not be
17 misrepresented as being the original software.
18 3. This notice may not be removed or altered from any source distribution.
19
20 Jeroen Frijters
21 jeroen@frijters.net
22
23*/
24using System.Diagnostics;
26
27#if IMPORTER || EXPORTER
28using IKVM.Reflection;
30#else
31using System.Reflection;
32using System.Reflection.Emit;
33using System.Threading;
34#endif
35
36#if IMPORTER
38#endif
39
40namespace IKVM.Runtime
41{
42
47 {
48
58 internal RuntimeSimpleJavaField(RuntimeJavaType declaringType, RuntimeJavaType fieldType, FieldInfo fi, string name, string sig, ExModifiers modifiers) :
59 base(declaringType, fieldType, name, sig, modifiers, fi)
60 {
61 Debug.Assert(!(fieldType == declaringType.Context.PrimitiveJavaTypeFactory.DOUBLE || fieldType == declaringType.Context.PrimitiveJavaTypeFactory.LONG) || !IsVolatile);
62 }
63
64#if !IMPORTER && !EXPORTER && !FIRST_PASS
65
66 internal override object GetValue(object obj)
67 {
68 return GetField().GetValue(obj);
69 }
70
71 internal override void SetValue(object obj, object value)
72 {
73 GetField().SetValue(obj, value);
74 }
75
76#endif
77
78#if EMITTERS
79
81 protected override void EmitGetImpl(CodeEmitter il)
82 {
83 var fi = GetField();
84
85 if (IsStatic == false && DeclaringType.IsNonPrimitiveValueType)
86 il.Emit(OpCodes.Unbox, DeclaringType.TypeAsLocalOrStackType);
87
88 // conduct load operation with volatile tag if field is volatile
89 if (IsVolatile)
90 {
91 il.EmitMemoryBarrier();
92 il.Emit(OpCodes.Volatile);
93 }
94
95 if (IsStatic)
96 il.Emit(OpCodes.Ldsfld, fi);
97 else
98 il.Emit(OpCodes.Ldfld, fi);
99 }
100
102 protected override void EmitSetImpl(CodeEmitter il)
103 {
104 var fi = GetField();
105
106 if (IsStatic == false && DeclaringType.IsNonPrimitiveValueType)
107 {
108 var value = il.DeclareLocal(FieldTypeWrapper.TypeAsLocalOrStackType);
109 il.Emit(OpCodes.Stloc, value);
110 il.Emit(OpCodes.Unbox, DeclaringType.TypeAsLocalOrStackType);
111 il.Emit(OpCodes.Ldloc, value);
112 }
113
114 // conduct store operation with volatile tag if field is volatile
115 if (IsVolatile)
116 il.Emit(OpCodes.Volatile);
117
118 if (IsStatic)
119 il.Emit(OpCodes.Stsfld, fi);
120 else
121 il.Emit(OpCodes.Stfld, fi);
122
123 if (IsVolatile)
124 il.EmitMemoryBarrier();
125 }
126
128 protected override void EmitUnsafeGetImpl(CodeEmitter il)
129 {
130 var fi = GetField();
131
132 if (IsStatic)
133 {
134 if (IsFinal)
135 {
136 il.Emit(OpCodes.Ldsflda, fi);
137 il.Emit(OpCodes.Call, DeclaringType.Context.Resolver.ResolveRuntimeType(typeof(RuntimeSimpleJavaField).FullName).AsReflection().GetMethod(nameof(UnsafeGetImplByRefNoInline), BindingFlags.Static | BindingFlags.NonPublic).MakeGenericMethod(fi.FieldType));
138 }
139 else
140 {
141 il.Emit(OpCodes.Ldsfld, fi);
142 }
143 }
144 else
145 {
146 if (DeclaringType.IsNonPrimitiveValueType)
147 il.Emit(OpCodes.Unbox, DeclaringType.TypeAsLocalOrStackType);
148
149 il.Emit(OpCodes.Ldfld, fi);
150 }
151 }
152
159 [MethodImpl(MethodImplOptions.NoInlining)]
160 static T UnsafeGetImplByRefNoInline<T>(ref T r)
161 {
162 return r;
163 }
164
166 protected override void EmitUnsafeSetImpl(CodeEmitter il)
167 {
168 var fi = GetField();
169
170 if (IsStatic == false && DeclaringType.IsNonPrimitiveValueType)
171 {
172 var value = il.DeclareLocal(FieldTypeWrapper.TypeAsLocalOrStackType);
173 il.Emit(OpCodes.Stloc, value);
174 il.Emit(OpCodes.Unbox, DeclaringType.TypeAsTBD);
175 il.Emit(OpCodes.Ldloc, value);
176 }
177
178 if (IsStatic)
179 {
180 il.Emit(OpCodes.Stsfld, fi);
181 }
182 else
183 {
184 il.Emit(OpCodes.Stfld, fi);
185 }
186 }
187
189 protected override void EmitUnsafeVolatileGetImpl(CodeEmitter il)
190 {
191 var fi = GetField();
192
193 if (IsStatic)
194 {
195 il.Emit(OpCodes.Ldsflda, fi);
196 }
197 else
198 {
199 if (DeclaringType.IsNonPrimitiveValueType)
200 il.Emit(OpCodes.Unbox, DeclaringType.TypeAsLocalOrStackType);
201
202 il.Emit(OpCodes.Ldflda, fi);
203 }
204
205 if (FieldTypeWrapper == DeclaringType.Context.PrimitiveJavaTypeFactory.BOOLEAN)
206 il.Emit(OpCodes.Call, DeclaringType.Context.ByteCodeHelperMethods.VolatileReadBoolean);
207 else if (FieldTypeWrapper == DeclaringType.Context.PrimitiveJavaTypeFactory.BYTE)
208 il.Emit(OpCodes.Call, DeclaringType.Context.ByteCodeHelperMethods.VolatileReadByte);
209 else if (FieldTypeWrapper == DeclaringType.Context.PrimitiveJavaTypeFactory.CHAR)
210 il.Emit(OpCodes.Call, DeclaringType.Context.ByteCodeHelperMethods.VolatileReadChar);
211 else if (FieldTypeWrapper == DeclaringType.Context.PrimitiveJavaTypeFactory.SHORT)
212 il.Emit(OpCodes.Call, DeclaringType.Context.ByteCodeHelperMethods.VolatileReadShort);
213 else if (FieldTypeWrapper == DeclaringType.Context.PrimitiveJavaTypeFactory.INT)
214 il.Emit(OpCodes.Call, DeclaringType.Context.ByteCodeHelperMethods.VolatileReadInt);
215 else if (FieldTypeWrapper == DeclaringType.Context.PrimitiveJavaTypeFactory.LONG)
216 il.Emit(OpCodes.Call, DeclaringType.Context.ByteCodeHelperMethods.VolatileReadLong);
217 else if (FieldTypeWrapper == DeclaringType.Context.PrimitiveJavaTypeFactory.FLOAT)
218 il.Emit(OpCodes.Call, DeclaringType.Context.ByteCodeHelperMethods.VolatileReadFloat);
219 else if (FieldTypeWrapper == DeclaringType.Context.PrimitiveJavaTypeFactory.DOUBLE)
220 il.Emit(OpCodes.Call, DeclaringType.Context.ByteCodeHelperMethods.VolatileReadDouble);
221 else
222 {
223 il.EmitMemoryBarrier();
224 il.Emit(OpCodes.Volatile);
225 FieldTypeWrapper.EmitLdind(il);
226 }
227 }
228
230 protected override void EmitUnsafeVolatileSetImpl(CodeEmitter il)
231 {
232 var fi = GetField();
233
234 var value = il.DeclareLocal(FieldTypeWrapper.TypeAsLocalOrStackType);
235 il.Emit(OpCodes.Stloc, value);
236
237 if (IsStatic)
238 {
239 il.Emit(OpCodes.Ldsflda, fi);
240 }
241 else
242 {
243 if (DeclaringType.IsNonPrimitiveValueType)
244 il.Emit(OpCodes.Unbox, DeclaringType.TypeAsLocalOrStackType);
245
246 il.Emit(OpCodes.Ldflda, fi);
247 }
248
249 il.Emit(OpCodes.Ldloc, value);
250
251 if (FieldTypeWrapper == DeclaringType.Context.PrimitiveJavaTypeFactory.BOOLEAN)
252 il.Emit(OpCodes.Call, DeclaringType.Context.ByteCodeHelperMethods.VolatileWriteBoolean);
253 else if (FieldTypeWrapper == DeclaringType.Context.PrimitiveJavaTypeFactory.BYTE)
254 il.Emit(OpCodes.Call, DeclaringType.Context.ByteCodeHelperMethods.VolatileWriteByte);
255 else if (FieldTypeWrapper == DeclaringType.Context.PrimitiveJavaTypeFactory.CHAR)
256 il.Emit(OpCodes.Call, DeclaringType.Context.ByteCodeHelperMethods.VolatileWriteChar);
257 else if (FieldTypeWrapper == DeclaringType.Context.PrimitiveJavaTypeFactory.SHORT)
258 il.Emit(OpCodes.Call, DeclaringType.Context.ByteCodeHelperMethods.VolatileWriteShort);
259 else if (FieldTypeWrapper == DeclaringType.Context.PrimitiveJavaTypeFactory.INT)
260 il.Emit(OpCodes.Call, DeclaringType.Context.ByteCodeHelperMethods.VolatileWriteInt);
261 else if (FieldTypeWrapper == DeclaringType.Context.PrimitiveJavaTypeFactory.LONG)
262 il.Emit(OpCodes.Call, DeclaringType.Context.ByteCodeHelperMethods.VolatileWriteLong);
263 else if (FieldTypeWrapper == DeclaringType.Context.PrimitiveJavaTypeFactory.FLOAT)
264 il.Emit(OpCodes.Call, DeclaringType.Context.ByteCodeHelperMethods.VolatileWriteFloat);
265 else if (FieldTypeWrapper == DeclaringType.Context.PrimitiveJavaTypeFactory.DOUBLE)
266 il.Emit(OpCodes.Call, DeclaringType.Context.ByteCodeHelperMethods.VolatileWriteDouble);
267 else
268 {
269 il.Emit(OpCodes.Volatile);
270 FieldTypeWrapper.EmitStind(il);
271 il.EmitMemoryBarrier();
272 }
273 }
274
275 protected override void EmitUnsafeCompareAndSwapImpl(CodeEmitter il)
276 {
277 var fi = GetField();
278
279 var update = il.AllocTempLocal(FieldTypeWrapper.TypeAsLocalOrStackType);
280 var expect = il.AllocTempLocal(FieldTypeWrapper.TypeAsLocalOrStackType);
281
282 il.Emit(OpCodes.Stloc, update);
283 il.Emit(OpCodes.Stloc, expect);
284
285 if (IsStatic)
286 {
287 il.Emit(OpCodes.Ldsflda, fi);
288 }
289 else
290 {
291 if (DeclaringType.IsNonPrimitiveValueType)
292 il.Emit(OpCodes.Unbox, DeclaringType.TypeAsLocalOrStackType);
293
294 il.Emit(OpCodes.Ldflda, fi);
295 }
296
297 il.Emit(OpCodes.Ldloc, expect);
298 il.Emit(OpCodes.Ldloc, update);
299
300 if (FieldTypeWrapper.IsPrimitive)
301 {
302 if (FieldTypeWrapper == DeclaringType.Context.PrimitiveJavaTypeFactory.INT)
303 {
304 il.Emit(OpCodes.Call, DeclaringType.Context.ByteCodeHelperMethods.CompareAndSwapInt);
305 }
306 else if (FieldTypeWrapper == DeclaringType.Context.PrimitiveJavaTypeFactory.LONG)
307 {
308 il.Emit(OpCodes.Call, DeclaringType.Context.ByteCodeHelperMethods.CompareAndSwapLong);
309 }
310 else if (FieldTypeWrapper == DeclaringType.Context.PrimitiveJavaTypeFactory.DOUBLE)
311 {
312 il.Emit(OpCodes.Call, DeclaringType.Context.ByteCodeHelperMethods.CompareAndSwapDouble);
313 }
314 else
315 {
316 throw new InternalException();
317 }
318 }
319 else
320 {
321 il.Emit(OpCodes.Call, DeclaringType.Context.ByteCodeHelperMethods.CompareAndSwapObject);
322 }
323
324 il.ReleaseTempLocal(expect);
325 il.ReleaseTempLocal(update);
326 }
327
328#endif
329
330 }
331
332}
IKVM.Reflection.FieldInfo FieldInfo
Represents an internal error that occurred within IKVM.
ByteCodeHelperMethods ByteCodeHelperMethods
Gets the ByteCodeHelperMethods associated with this instance of the runtime.
RuntimePrimitiveJavaTypeFactory PrimitiveJavaTypeFactory
Gets the RuntimePrimitiveJavaTypeFactory associated with this instance of the runtime.
ISymbolResolver Resolver
Gets the ISymbolResolver associated with this instance of the runtime.
Field wrapper implementation for standard fields.