~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/ikvm/runtime/MemberWrapper.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
  Copyright (C) 2002-2012 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
*/
 
24
using System;
 
25
using System.Collections.Generic;
 
26
#if STATIC_COMPILER || STUB_GENERATOR
 
27
using IKVM.Reflection;
 
28
using IKVM.Reflection.Emit;
 
29
using Type = IKVM.Reflection.Type;
 
30
#else
 
31
using System.Reflection;
 
32
using System.Reflection.Emit;
 
33
#endif
 
34
using System.Diagnostics;
 
35
using IKVM.Attributes;
 
36
using System.Threading;
 
37
using System.Runtime.InteropServices;
 
38
 
 
39
namespace IKVM.Internal
 
40
{
 
41
        [Flags]
 
42
        enum MemberFlags : short
 
43
        {
 
44
                None = 0,
 
45
                HideFromReflection = 1,
 
46
                ExplicitOverride = 2,
 
47
                MirandaMethod = 8,
 
48
                AccessStub = 16,
 
49
                InternalAccess = 32,  // member has "internal" access (@ikvm.lang.Internal)
 
50
                PropertyAccessor = 64,
 
51
                Intrinsic = 128,
 
52
                CallerID = 256,
 
53
                NonPublicTypeInSignature = 512, // this flag is only available after linking and is not set for access stubs
 
54
                DelegateInvokeWithByRefParameter = 1024,
 
55
                Type2FinalField = 2048,
 
56
        }
 
57
 
 
58
        abstract class MemberWrapper
 
59
        {
 
60
                private HandleWrapper handle;
 
61
                private TypeWrapper declaringType;
 
62
                private Modifiers modifiers;
 
63
                private MemberFlags flags;
 
64
                private string name;
 
65
                private string sig;
 
66
 
 
67
                private sealed class HandleWrapper
 
68
                {
 
69
                        internal readonly IntPtr Value;
 
70
 
 
71
                        [System.Security.SecurityCritical]
 
72
                        internal HandleWrapper(MemberWrapper obj)
 
73
                        {
 
74
                                Value = (IntPtr)GCHandle.Alloc(obj, GCHandleType.WeakTrackResurrection);
 
75
                        }
 
76
 
 
77
#if CLASSGC
 
78
                        [System.Security.SecuritySafeCritical]
 
79
                        ~HandleWrapper()
 
80
                        {
 
81
                                if (!Environment.HasShutdownStarted)
 
82
                                {
 
83
                                        GCHandle h = (GCHandle)Value;
 
84
                                        if (h.Target == null)
 
85
                                        {
 
86
                                                h.Free();
 
87
                                        }
 
88
                                        else
 
89
                                        {
 
90
                                                GC.ReRegisterForFinalize(this);
 
91
                                        }
 
92
                                }
 
93
                        }
 
94
#endif
 
95
                }
 
96
 
 
97
                protected MemberWrapper(TypeWrapper declaringType, string name, string sig, Modifiers modifiers, MemberFlags flags)
 
98
                {
 
99
                        Debug.Assert(declaringType != null);
 
100
                        this.declaringType = declaringType;
 
101
                        this.name = String.Intern(name);
 
102
                        this.sig = String.Intern(sig);
 
103
                        this.modifiers = modifiers;
 
104
                        this.flags = flags;
 
105
                }
 
106
 
 
107
                internal IntPtr Cookie
 
108
                {
 
109
                        [System.Security.SecurityCritical]
 
110
                        get
 
111
                        {
 
112
                                lock(this)
 
113
                                {
 
114
                                        if(handle == null)
 
115
                                        {
 
116
                                                handle = new HandleWrapper(this);
 
117
                                        }
 
118
                                }
 
119
                                return handle.Value;
 
120
                        }
 
121
                }
 
122
 
 
123
                [System.Security.SecurityCritical]
 
124
                internal static MemberWrapper FromCookieImpl(IntPtr cookie)
 
125
                {
 
126
                        return (MemberWrapper)GCHandle.FromIntPtr(cookie).Target;
 
127
                }
 
128
 
 
129
                internal TypeWrapper DeclaringType
 
130
                {
 
131
                        get
 
132
                        {
 
133
                                return declaringType;
 
134
                        }
 
135
                }
 
136
 
 
137
                internal string Name
 
138
                {
 
139
                        get
 
140
                        {
 
141
                                return name;
 
142
                        }
 
143
                }
 
144
 
 
145
                internal string Signature
 
146
                {
 
147
                        get
 
148
                        {
 
149
                                return sig;
 
150
                        }
 
151
                }
 
152
 
 
153
                internal bool IsAccessibleFrom(TypeWrapper referencedType, TypeWrapper caller, TypeWrapper instance)
 
154
                {
 
155
                        if(referencedType.IsAccessibleFrom(caller))
 
156
                        {
 
157
                                return (
 
158
                                        caller == DeclaringType ||
 
159
                                        IsPublicOrProtectedMemberAccessible(caller, instance) ||
 
160
                                        (IsInternal && DeclaringType.InternalsVisibleTo(caller)) ||
 
161
                                        (!IsPrivate && DeclaringType.IsPackageAccessibleFrom(caller)))
 
162
                                        // The JVM supports accessing members that have non-public types in their signature from another package,
 
163
                                        // but the CLI doesn't. It would be nice if we worked around that by emitting extra accessors, but for now
 
164
                                        // we'll simply disallow such access across assemblies (unless the appropriate InternalsVisibleToAttribute exists).
 
165
                                        && (!(HasNonPublicTypeInSignature || IsType2FinalField) || InPracticeInternalsVisibleTo(caller));
 
166
                        }
 
167
                        return false;
 
168
                }
 
169
 
 
170
                private bool IsPublicOrProtectedMemberAccessible(TypeWrapper caller, TypeWrapper instance)
 
171
                {
 
172
                        if (IsPublic || (IsProtected && caller.IsSubTypeOf(DeclaringType) && (IsStatic || instance.IsSubTypeOf(caller))))
 
173
                        {
 
174
                                return DeclaringType.IsPublic || InPracticeInternalsVisibleTo(caller);
 
175
                        }
 
176
                        return false;
 
177
                }
 
178
 
 
179
                private bool InPracticeInternalsVisibleTo(TypeWrapper caller)
 
180
                {
 
181
#if !STATIC_COMPILER
 
182
                        if (DeclaringType.TypeAsTBD.Assembly.Equals(caller.TypeAsTBD.Assembly))
 
183
                        {
 
184
                                // both the caller and the declaring type are in the same assembly
 
185
                                // so we know that the internals are visible
 
186
                                // (this handles the case where we're running in dynamic mode)
 
187
                                return true;
 
188
                        }
 
189
#endif
 
190
#if CLASSGC
 
191
                        if (DeclaringType is DynamicTypeWrapper)
 
192
                        {
 
193
                                // if we are dynamic, we can just become friends with the caller
 
194
                                DeclaringType.GetClassLoader().GetTypeWrapperFactory().AddInternalsVisibleTo(caller.TypeAsTBD.Assembly);
 
195
                                return true;
 
196
                        }
 
197
#endif
 
198
                        return DeclaringType.InternalsVisibleTo(caller);
 
199
                }
 
200
 
 
201
                internal bool IsHideFromReflection
 
202
                {
 
203
                        get
 
204
                        {
 
205
                                return (flags & MemberFlags.HideFromReflection) != 0;
 
206
                        }
 
207
                }
 
208
 
 
209
                internal bool IsExplicitOverride
 
210
                {
 
211
                        get
 
212
                        {
 
213
                                return (flags & MemberFlags.ExplicitOverride) != 0;
 
214
                        }
 
215
                }
 
216
 
 
217
                internal bool IsMirandaMethod
 
218
                {
 
219
                        get
 
220
                        {
 
221
                                return (flags & MemberFlags.MirandaMethod) != 0;
 
222
                        }
 
223
                }
 
224
 
 
225
                internal bool IsAccessStub
 
226
                {
 
227
                        get
 
228
                        {
 
229
                                return (flags & MemberFlags.AccessStub) != 0;
 
230
                        }
 
231
                }
 
232
 
 
233
                internal bool IsPropertyAccessor
 
234
                {
 
235
                        get
 
236
                        {
 
237
                                return (flags & MemberFlags.PropertyAccessor) != 0;
 
238
                        }
 
239
                        set
 
240
                        {
 
241
                                // this is unsynchronized, so it may only be called during the JavaTypeImpl constructor
 
242
                                if(value)
 
243
                                {
 
244
                                        flags |= MemberFlags.PropertyAccessor;
 
245
                                }
 
246
                                else
 
247
                                {
 
248
                                        flags &= ~MemberFlags.PropertyAccessor;
 
249
                                }
 
250
                        }
 
251
                }
 
252
 
 
253
                internal bool IsIntrinsic
 
254
                {
 
255
                        get
 
256
                        {
 
257
                                return (flags & MemberFlags.Intrinsic) != 0;
 
258
                        }
 
259
                }
 
260
 
 
261
                protected void SetIntrinsicFlag()
 
262
                {
 
263
                        flags |= MemberFlags.Intrinsic;
 
264
                }
 
265
 
 
266
                protected void SetNonPublicTypeInSignatureFlag()
 
267
                {
 
268
                        flags |= MemberFlags.NonPublicTypeInSignature;
 
269
                }
 
270
 
 
271
                internal bool HasNonPublicTypeInSignature
 
272
                {
 
273
                        get { return (flags & MemberFlags.NonPublicTypeInSignature) != 0; }
 
274
                }
 
275
 
 
276
                protected void SetType2FinalField()
 
277
                {
 
278
                        flags |= MemberFlags.Type2FinalField;
 
279
                }
 
280
        
 
281
                internal bool IsType2FinalField
 
282
                {
 
283
                        get { return (flags & MemberFlags.Type2FinalField) != 0; }
 
284
                }
 
285
 
 
286
                internal bool HasCallerID
 
287
                {
 
288
                        get
 
289
                        {
 
290
                                return (flags & MemberFlags.CallerID) != 0;
 
291
                        }
 
292
                }
 
293
 
 
294
                internal bool IsDelegateInvokeWithByRefParameter
 
295
                {
 
296
                        get { return (flags & MemberFlags.DelegateInvokeWithByRefParameter) != 0; }
 
297
                }
 
298
 
 
299
                internal Modifiers Modifiers
 
300
                {
 
301
                        get
 
302
                        {
 
303
                                return modifiers;
 
304
                        }
 
305
                }
 
306
 
 
307
                internal bool IsStatic
 
308
                {
 
309
                        get
 
310
                        {
 
311
                                return (modifiers & Modifiers.Static) != 0;
 
312
                        }
 
313
                }
 
314
 
 
315
                internal bool IsInternal
 
316
                {
 
317
                        get
 
318
                        {
 
319
                                return (flags & MemberFlags.InternalAccess) != 0;
 
320
                        }
 
321
                }
 
322
 
 
323
                internal bool IsPublic
 
324
                {
 
325
                        get
 
326
                        {
 
327
                                return (modifiers & Modifiers.Public) != 0;
 
328
                        }
 
329
                }
 
330
 
 
331
                internal bool IsPrivate
 
332
                {
 
333
                        get
 
334
                        {
 
335
                                return (modifiers & Modifiers.Private) != 0;
 
336
                        }
 
337
                }
 
338
 
 
339
                internal bool IsProtected
 
340
                {
 
341
                        get
 
342
                        {
 
343
                                return (modifiers & Modifiers.Protected) != 0;
 
344
                        }
 
345
                }
 
346
 
 
347
                internal bool IsFinal
 
348
                {
 
349
                        get
 
350
                        {
 
351
                                return (modifiers & Modifiers.Final) != 0;
 
352
                        }
 
353
                }
 
354
        }
 
355
 
 
356
        interface ICustomInvoke
 
357
        {
 
358
#if !STATIC_COMPILER && !FIRST_PASS && !STUB_GENERATOR
 
359
                object Invoke(object obj, object[] args, ikvm.@internal.CallerID callerID);
 
360
#endif
 
361
        }
 
362
 
 
363
        abstract class MethodWrapper : MemberWrapper
 
364
        {
 
365
#if !STATIC_COMPILER && !FIRST_PASS && !STUB_GENERATOR
 
366
                private static Dictionary<MethodWrapper, sun.reflect.MethodAccessor> invokenonvirtualCache;
 
367
                private volatile object reflectionMethod;
 
368
#endif
 
369
                internal static readonly MethodWrapper[] EmptyArray  = new MethodWrapper[0];
 
370
                private MethodBase method;
 
371
                private string[] declaredExceptions;
 
372
                private TypeWrapper returnTypeWrapper;
 
373
                private TypeWrapper[] parameterTypeWrappers;
 
374
 
 
375
#if !STUB_GENERATOR
 
376
                internal virtual void EmitCall(CodeEmitter ilgen)
 
377
                {
 
378
                        throw new InvalidOperationException();
 
379
                }
 
380
 
 
381
                internal virtual void EmitCallvirt(CodeEmitter ilgen)
 
382
                {
 
383
                        throw new InvalidOperationException();
 
384
                }
 
385
 
 
386
                internal virtual void EmitCallvirtReflect(CodeEmitter ilgen)
 
387
                {
 
388
                        EmitCallvirt(ilgen);
 
389
                }
 
390
 
 
391
                internal virtual void EmitNewobj(CodeEmitter ilgen)
 
392
                {
 
393
                        throw new InvalidOperationException();
 
394
                }
 
395
 
 
396
                internal virtual bool EmitIntrinsic(EmitIntrinsicContext context)
 
397
                {
 
398
                        return Intrinsics.Emit(context);
 
399
                }
 
400
#endif // STUB_GENERATOR
 
401
 
 
402
                internal virtual bool IsDynamicOnly
 
403
                {
 
404
                        get
 
405
                        {
 
406
                                return false;
 
407
                        }
 
408
                }
 
409
 
 
410
                internal MethodWrapper(TypeWrapper declaringType, string name, string sig, MethodBase method, TypeWrapper returnType, TypeWrapper[] parameterTypes, Modifiers modifiers, MemberFlags flags)
 
411
                        : base(declaringType, name, sig, modifiers, flags)
 
412
                {
 
413
                        Profiler.Count("MethodWrapper");
 
414
                        this.method = method;
 
415
                        Debug.Assert(((returnType == null) == (parameterTypes == null)) || (returnType == PrimitiveTypeWrapper.VOID));
 
416
                        this.returnTypeWrapper = returnType;
 
417
                        this.parameterTypeWrappers = parameterTypes;
 
418
                        if (Intrinsics.IsIntrinsic(this))
 
419
                        {
 
420
                                SetIntrinsicFlag();
 
421
                        }
 
422
                        UpdateNonPublicTypeInSignatureFlag();
 
423
                }
 
424
 
 
425
                private void UpdateNonPublicTypeInSignatureFlag()
 
426
                {
 
427
                        if ((IsPublic || IsProtected) && (returnTypeWrapper != null && parameterTypeWrappers != null) && !(this is AccessStubMethodWrapper) && !(this is AccessStubConstructorMethodWrapper))
 
428
                        {
 
429
                                if (!returnTypeWrapper.IsPublic && !returnTypeWrapper.IsUnloadable)
 
430
                                {
 
431
                                        SetNonPublicTypeInSignatureFlag();
 
432
                                }
 
433
                                else
 
434
                                {
 
435
                                        foreach (TypeWrapper tw in parameterTypeWrappers)
 
436
                                        {
 
437
                                                if (!tw.IsPublic && !tw.IsUnloadable)
 
438
                                                {
 
439
                                                        SetNonPublicTypeInSignatureFlag();
 
440
                                                        break;
 
441
                                                }
 
442
                                        }
 
443
                                }
 
444
                        }
 
445
                }
 
446
 
 
447
                internal void SetDeclaredExceptions(string[] exceptions)
 
448
                {
 
449
                        if(exceptions == null)
 
450
                        {
 
451
                                exceptions = new string[0];
 
452
                        }
 
453
                        this.declaredExceptions = (string[])exceptions.Clone();
 
454
                }
 
455
 
 
456
                internal string[] GetDeclaredExceptions()
 
457
                {
 
458
                        return declaredExceptions;
 
459
                }
 
460
 
 
461
#if !STATIC_COMPILER && !STUB_GENERATOR
 
462
                internal object ToMethodOrConstructor(bool copy)
 
463
                {
 
464
#if FIRST_PASS
 
465
                        return null;
 
466
#else
 
467
                        object method = reflectionMethod;
 
468
                        if (method == null)
 
469
                        {
 
470
                                Link();
 
471
                                ClassLoaderWrapper loader = this.DeclaringType.GetClassLoader();
 
472
                                TypeWrapper[] argTypes = GetParameters();
 
473
                                java.lang.Class[] parameterTypes = new java.lang.Class[argTypes.Length];
 
474
                                for (int i = 0; i < argTypes.Length; i++)
 
475
                                {
 
476
                                        parameterTypes[i] = argTypes[i].EnsureLoadable(loader).ClassObject;
 
477
                                }
 
478
                                java.lang.Class[] checkedExceptions = GetExceptions();
 
479
                                if (this.Name == StringConstants.INIT)
 
480
                                {
 
481
                                        method = new java.lang.reflect.Constructor(
 
482
                                                this.DeclaringType.ClassObject,
 
483
                                                parameterTypes,
 
484
                                                checkedExceptions,
 
485
                                                (int)this.Modifiers | (this.IsInternal ? 0x40000000 : 0),
 
486
                                                Array.IndexOf(this.DeclaringType.GetMethods(), this),
 
487
                                                this.DeclaringType.GetGenericMethodSignature(this),
 
488
                                                null,
 
489
                                                null
 
490
                                        );
 
491
                                }
 
492
                                else
 
493
                                {
 
494
                                        method = new java.lang.reflect.Method(
 
495
                                                this.DeclaringType.ClassObject,
 
496
                                                this.Name,
 
497
                                                parameterTypes,
 
498
                                                this.ReturnType.EnsureLoadable(loader).ClassObject,
 
499
                                                checkedExceptions,
 
500
                                                (int)this.Modifiers | (this.IsInternal ? 0x40000000 : 0),
 
501
                                                Array.IndexOf(this.DeclaringType.GetMethods(), this),
 
502
                                                this.DeclaringType.GetGenericMethodSignature(this),
 
503
                                                null,
 
504
                                                null,
 
505
                                                null
 
506
                                        );
 
507
                                }
 
508
                                lock (this)
 
509
                                {
 
510
                                        if (reflectionMethod == null)
 
511
                                        {
 
512
                                                reflectionMethod = method;
 
513
                                        }
 
514
                                        else
 
515
                                        {
 
516
                                                method = reflectionMethod;
 
517
                                        }
 
518
                                }
 
519
                        }
 
520
                        if (copy)
 
521
                        {
 
522
                                java.lang.reflect.Constructor ctor = method as java.lang.reflect.Constructor;
 
523
                                if (ctor != null)
 
524
                                {
 
525
                                        return ctor.copy();
 
526
                                }
 
527
                                return ((java.lang.reflect.Method)method).copy();
 
528
                        }
 
529
                        return method;
 
530
#endif
 
531
                }
 
532
 
 
533
#if !FIRST_PASS
 
534
                private java.lang.Class[] GetExceptions()
 
535
                {
 
536
                        string[] classes = declaredExceptions;
 
537
                        Type[] types = Type.EmptyTypes;
 
538
                        if (classes == null)
 
539
                        {
 
540
                                // NOTE if method is a MethodBuilder, GetCustomAttributes doesn't work (and if
 
541
                                // the method had any declared exceptions, the declaredExceptions field would have
 
542
                                // been set)
 
543
                                if (method != null && !(method is MethodBuilder))
 
544
                                {
 
545
                                        ThrowsAttribute attr = AttributeHelper.GetThrows(method);
 
546
                                        if (attr != null)
 
547
                                        {
 
548
                                                classes = attr.classes;
 
549
                                                types = attr.types;
 
550
                                        }
 
551
                                }
 
552
                        }
 
553
                        if (classes != null)
 
554
                        {
 
555
                                java.lang.Class[] array = new java.lang.Class[classes.Length];
 
556
                                for (int i = 0; i < classes.Length; i++)
 
557
                                {
 
558
                                        array[i] = this.DeclaringType.GetClassLoader().LoadClassByDottedName(classes[i]).ClassObject;
 
559
                                }
 
560
                                return array;
 
561
                        }
 
562
                        else
 
563
                        {
 
564
                                java.lang.Class[] array = new java.lang.Class[types.Length];
 
565
                                for (int i = 0; i < types.Length; i++)
 
566
                                {
 
567
                                        array[i] = types[i];
 
568
                                }
 
569
                                return array;
 
570
                        }
 
571
                }
 
572
#endif // !FIRST_PASS
 
573
 
 
574
                internal static MethodWrapper FromMethodOrConstructor(object methodOrConstructor)
 
575
                {
 
576
#if FIRST_PASS
 
577
                        return null;
 
578
#else
 
579
                        java.lang.reflect.Method method = methodOrConstructor as java.lang.reflect.Method;
 
580
                        if (method != null)
 
581
                        {
 
582
                                return TypeWrapper.FromClass(method.getDeclaringClass()).GetMethods()[method._slot()];
 
583
                        }
 
584
                        java.lang.reflect.Constructor constructor = (java.lang.reflect.Constructor)methodOrConstructor;
 
585
                        return TypeWrapper.FromClass(constructor.getDeclaringClass()).GetMethods()[constructor._slot()];
 
586
#endif
 
587
                }
 
588
#endif // !STATIC_COMPILER && !STUB_GENERATOR
 
589
 
 
590
                [System.Security.SecurityCritical]
 
591
                internal static MethodWrapper FromCookie(IntPtr cookie)
 
592
                {
 
593
                        return (MethodWrapper)FromCookieImpl(cookie);
 
594
                }
 
595
 
 
596
                internal bool IsLinked
 
597
                {
 
598
                        get
 
599
                        {
 
600
                                return parameterTypeWrappers != null;
 
601
                        }
 
602
                }
 
603
 
 
604
                internal void Link()
 
605
                {
 
606
                        lock(this)
 
607
                        {
 
608
                                if(parameterTypeWrappers != null)
 
609
                                {
 
610
                                        return;
 
611
                                }
 
612
                        }
 
613
                        ClassLoaderWrapper loader = this.DeclaringType.GetClassLoader();
 
614
                        TypeWrapper ret = loader.RetTypeWrapperFromSigNoThrow(Signature);
 
615
                        TypeWrapper[] parameters = loader.ArgTypeWrapperListFromSigNoThrow(Signature);
 
616
                        lock(this)
 
617
                        {
 
618
                                try
 
619
                                {
 
620
                                        // critical code in the finally block to avoid Thread.Abort interrupting the thread
 
621
                                }
 
622
                                finally
 
623
                                {
 
624
                                        if(parameterTypeWrappers == null)
 
625
                                        {
 
626
                                                Debug.Assert(returnTypeWrapper == null || returnTypeWrapper == PrimitiveTypeWrapper.VOID);
 
627
                                                returnTypeWrapper = ret;
 
628
                                                parameterTypeWrappers = parameters;
 
629
                                                UpdateNonPublicTypeInSignatureFlag();
 
630
                                                if(method == null)
 
631
                                                {
 
632
                                                        try
 
633
                                                        {
 
634
                                                                DoLinkMethod();
 
635
                                                        }
 
636
                                                        catch
 
637
                                                        {
 
638
                                                                // HACK if linking fails, we unlink to make sure
 
639
                                                                // that the next link attempt will fail again
 
640
                                                                returnTypeWrapper = null;
 
641
                                                                parameterTypeWrappers = null;
 
642
                                                                throw;
 
643
                                                        }
 
644
                                                }
 
645
                                        }
 
646
                                }
 
647
                        }
 
648
                }
 
649
 
 
650
                protected virtual void DoLinkMethod()
 
651
                {
 
652
                        method = this.DeclaringType.LinkMethod(this);
 
653
                }
 
654
 
 
655
                [Conditional("DEBUG")]
 
656
                internal void AssertLinked()
 
657
                {
 
658
                        if(!(parameterTypeWrappers != null && returnTypeWrapper != null))
 
659
                        {
 
660
                                Tracer.Error(Tracer.Runtime, "AssertLinked failed: " + this.DeclaringType.Name + "::" + this.Name + this.Signature);
 
661
                        }
 
662
                        Debug.Assert(parameterTypeWrappers != null && returnTypeWrapper != null, this.DeclaringType.Name + "::" + this.Name + this.Signature);
 
663
                }
 
664
 
 
665
                internal TypeWrapper ReturnType
 
666
                {
 
667
                        get
 
668
                        {
 
669
                                AssertLinked();
 
670
                                return returnTypeWrapper;
 
671
                        }
 
672
                }
 
673
 
 
674
                internal TypeWrapper[] GetParameters()
 
675
                {
 
676
                        AssertLinked();
 
677
                        return parameterTypeWrappers;
 
678
                }
 
679
 
 
680
#if !STUB_GENERATOR
 
681
                internal DefineMethodHelper GetDefineMethodHelper()
 
682
                {
 
683
                        return new DefineMethodHelper(this);
 
684
                }
 
685
#endif
 
686
 
 
687
                internal Type ReturnTypeForDefineMethod
 
688
                {
 
689
                        get
 
690
                        {
 
691
                                return ReturnType.TypeAsSignatureType;
 
692
                        }
 
693
                }
 
694
 
 
695
                internal Type[] GetParametersForDefineMethod()
 
696
                {
 
697
                        TypeWrapper[] wrappers = GetParameters();
 
698
                        int len = wrappers.Length;
 
699
                        if(HasCallerID)
 
700
                        {
 
701
                                len++;
 
702
                        }
 
703
                        Type[] temp = new Type[len];
 
704
                        for(int i = 0; i < wrappers.Length; i++)
 
705
                        {
 
706
                                temp[i] = wrappers[i].TypeAsSignatureType;
 
707
                        }
 
708
                        if(HasCallerID)
 
709
                        {
 
710
                                temp[len - 1] = CoreClasses.ikvm.@internal.CallerID.Wrapper.TypeAsSignatureType;
 
711
                        }
 
712
                        return temp;
 
713
                }
 
714
 
 
715
                // we expose the underlying MethodBase object,
 
716
                // for Java types, this is the method that contains the compiled Java bytecode
 
717
                // for remapped types, this is the mbCore method (not the helper)
 
718
                // Note that for some artificial methods (notably wrap() in enums), method is null
 
719
                internal MethodBase GetMethod()
 
720
                {
 
721
                        AssertLinked();
 
722
                        return method;
 
723
                }
 
724
 
 
725
                internal string RealName
 
726
                {
 
727
                        get
 
728
                        {
 
729
                                AssertLinked();
 
730
                                return method.Name;
 
731
                        }
 
732
                }
 
733
 
 
734
                // this returns the Java method's attributes in .NET terms (e.g. used to create stubs for this method)
 
735
                internal MethodAttributes GetMethodAttributes()
 
736
                {
 
737
                        MethodAttributes attribs = MethodAttributes.HideBySig;
 
738
                        if(IsStatic)
 
739
                        {
 
740
                                attribs |= MethodAttributes.Static;
 
741
                        }
 
742
                        if(IsPublic)
 
743
                        {
 
744
                                attribs |= MethodAttributes.Public;
 
745
                        }
 
746
                        else if(IsPrivate)
 
747
                        {
 
748
                                attribs |= MethodAttributes.Private;
 
749
                        }
 
750
                        else if(IsProtected)
 
751
                        {
 
752
                                attribs |= MethodAttributes.FamORAssem;
 
753
                        }
 
754
                        else
 
755
                        {
 
756
                                attribs |= MethodAttributes.Family;
 
757
                        }
 
758
                        // constructors aren't virtual
 
759
                        if(!IsStatic && !IsPrivate && Name != "<init>")
 
760
                        {
 
761
                                attribs |= MethodAttributes.Virtual;
 
762
                        }
 
763
                        if(IsFinal)
 
764
                        {
 
765
                                attribs |= MethodAttributes.Final;
 
766
                        }
 
767
                        if(IsAbstract)
 
768
                        {
 
769
                                attribs |= MethodAttributes.Abstract;
 
770
                        }
 
771
                        return attribs;
 
772
                }
 
773
 
 
774
                internal bool IsAbstract
 
775
                {
 
776
                        get
 
777
                        {
 
778
                                return (Modifiers & Modifiers.Abstract) != 0;
 
779
                        }
 
780
                }
 
781
 
 
782
#if !STATIC_COMPILER && !STUB_GENERATOR
 
783
                [HideFromJava]
 
784
                internal object InvokeJNI(object obj, object[] args, bool nonVirtual, object callerID)
 
785
                {
 
786
#if FIRST_PASS
 
787
                        return null;
 
788
#else
 
789
                        if (ReferenceEquals(Name, StringConstants.INIT))
 
790
                        {
 
791
                                java.lang.reflect.Constructor cons = (java.lang.reflect.Constructor)ToMethodOrConstructor(false);
 
792
                                if (obj == null)
 
793
                                {
 
794
                                        sun.reflect.ConstructorAccessor acc = cons.getConstructorAccessor();
 
795
                                        if (acc == null)
 
796
                                        {
 
797
                                                acc = (sun.reflect.ConstructorAccessor)IKVM.NativeCode.sun.reflect.ReflectionFactory.newConstructorAccessor0(null, cons);
 
798
                                                cons.setConstructorAccessor(acc);
 
799
                                        }
 
800
                                        return acc.newInstance(args);
 
801
                                }
 
802
                                else if (!ReflectUtil.IsConstructor(method))
 
803
                                {
 
804
                                        Debug.Assert(method.IsStatic);
 
805
                                        // we're dealing with a constructor on a remapped type, if obj is supplied, it means
 
806
                                        // that we should call the constructor on an already existing instance, but that isn't
 
807
                                        // possible with remapped types
 
808
                                        // the type of this exception is a bit random (note that this can only happen through JNI reflection)
 
809
                                        throw new java.lang.IncompatibleClassChangeError(string.Format("Remapped type {0} doesn't support constructor invocation on an existing instance", DeclaringType.Name));
 
810
                                }
 
811
                                else if (!method.DeclaringType.IsInstanceOfType(obj))
 
812
                                {
 
813
                                        // we're trying to initialize an existing instance of a remapped type
 
814
                                        throw new NotSupportedException("Unable to partially construct object of type " + obj.GetType().FullName + " to type " + method.DeclaringType.FullName);
 
815
                                }
 
816
                                else
 
817
                                {
 
818
                                        try
 
819
                                        {
 
820
                                                ResolveMethod();
 
821
                                                InvokeArgsProcessor proc = new InvokeArgsProcessor(this, method, obj, UnboxArgs(args), (ikvm.@internal.CallerID)callerID);
 
822
                                                object o = method.Invoke(proc.GetObj(), proc.GetArgs());
 
823
                                                TypeWrapper retType = this.ReturnType;
 
824
                                                if (!retType.IsUnloadable && retType.IsGhost)
 
825
                                                {
 
826
                                                        o = retType.GhostRefField.GetValue(o);
 
827
                                                }
 
828
                                                return o;
 
829
                                        }
 
830
                                        catch (ArgumentException x1)
 
831
                                        {
 
832
                                                throw new java.lang.IllegalArgumentException(x1.Message);
 
833
                                        }
 
834
                                        catch (TargetInvocationException x)
 
835
                                        {
 
836
                                                throw new java.lang.reflect.InvocationTargetException(ikvm.runtime.Util.mapException(x.InnerException));
 
837
                                        }
 
838
                                }
 
839
                        }
 
840
                        else if (nonVirtual
 
841
                                && !this.IsStatic
 
842
                                && !this.IsPrivate
 
843
                                && !this.IsAbstract
 
844
                                && !this.IsFinal
 
845
                                && !this.DeclaringType.IsFinal)
 
846
                        {
 
847
                                if (this.DeclaringType.IsRemapped && !this.DeclaringType.TypeAsBaseType.IsInstanceOfType(obj))
 
848
                                {
 
849
                                        ResolveMethod();
 
850
                                        return InvokeNonvirtualRemapped(obj, UnboxArgs(args));
 
851
                                }
 
852
                                else
 
853
                                {
 
854
                                        if (invokenonvirtualCache == null)
 
855
                                        {
 
856
                                                Interlocked.CompareExchange(ref invokenonvirtualCache, new Dictionary<MethodWrapper, sun.reflect.MethodAccessor>(), null);
 
857
                                        }
 
858
                                        sun.reflect.MethodAccessor acc;
 
859
                                        lock (invokenonvirtualCache)
 
860
                                        {
 
861
                                                if (!invokenonvirtualCache.TryGetValue(this, out acc))
 
862
                                                {
 
863
                                                        acc = new IKVM.NativeCode.sun.reflect.ReflectionFactory.FastMethodAccessorImpl((java.lang.reflect.Method)ToMethodOrConstructor(false), true);
 
864
                                                        invokenonvirtualCache.Add(this, acc);
 
865
                                                }
 
866
                                        }
 
867
                                        object val = acc.invoke(obj, args, (ikvm.@internal.CallerID)callerID);
 
868
                                        if (this.ReturnType.IsPrimitive && this.ReturnType != PrimitiveTypeWrapper.VOID)
 
869
                                        {
 
870
                                                val = JVM.Unbox(val);
 
871
                                        }
 
872
                                        return val;
 
873
                                }
 
874
                        }
 
875
                        else
 
876
                        {
 
877
                                java.lang.reflect.Method method = (java.lang.reflect.Method)ToMethodOrConstructor(false);
 
878
                                sun.reflect.MethodAccessor acc = method.getMethodAccessor();
 
879
                                if (acc == null)
 
880
                                {
 
881
                                        acc = (sun.reflect.MethodAccessor)IKVM.NativeCode.sun.reflect.ReflectionFactory.newMethodAccessor(null, method);
 
882
                                        method.setMethodAccessor(acc);
 
883
                                }
 
884
                                object val = acc.invoke(obj, args, (ikvm.@internal.CallerID)callerID);
 
885
                                if (this.ReturnType.IsPrimitive && this.ReturnType != PrimitiveTypeWrapper.VOID)
 
886
                                {
 
887
                                        val = JVM.Unbox(val);
 
888
                                }
 
889
                                return val;
 
890
                        }
 
891
#endif
 
892
                }
 
893
 
 
894
                private object[] UnboxArgs(object[] args)
 
895
                {
 
896
                        TypeWrapper[] paramTypes = GetParameters();
 
897
                        for (int i = 0; i < paramTypes.Length; i++)
 
898
                        {
 
899
                                if (paramTypes[i].IsPrimitive)
 
900
                                {
 
901
                                        args[i] = JVM.Unbox(args[i]);
 
902
                                }
 
903
                        }
 
904
                        return args;
 
905
                }
 
906
#endif // !STATIC_COMPILER && !STUB_GENERATOR
 
907
 
 
908
#if !STATIC_COMPILER && !FIRST_PASS && !STUB_GENERATOR
 
909
                internal void ResolveMethod()
 
910
                {
 
911
                        // if we've still got the builder object, we need to replace it with the real thing before we can call it
 
912
                        if(method is MethodBuilder)
 
913
                        {
 
914
                                method = method.Module.ResolveMethod(((MethodBuilder)method).GetToken().Token);
 
915
                        }
 
916
                }
 
917
 
 
918
                [HideFromJava]
 
919
                protected virtual object InvokeNonvirtualRemapped(object obj, object[] args)
 
920
                {
 
921
                        throw new InvalidOperationException();
 
922
                }
 
923
 
 
924
                private struct InvokeArgsProcessor
 
925
                {
 
926
                        private object obj;
 
927
                        private object[] args;
 
928
 
 
929
                        internal InvokeArgsProcessor(MethodWrapper mw, MethodBase method, object original_obj, object[] original_args, ikvm.@internal.CallerID callerID)
 
930
                        {
 
931
                                TypeWrapper[] argTypes = mw.GetParameters();
 
932
 
 
933
                                if(!mw.IsStatic && method.IsStatic && mw.Name != "<init>")
 
934
                                {
 
935
                                        // we've been redirected to a static method, so we have to copy the 'obj' into the args
 
936
                                        object[] nargs = new object[original_args.Length + 1];
 
937
                                        nargs[0] = original_obj;
 
938
                                        original_args.CopyTo(nargs, 1);
 
939
                                        this.obj = null;
 
940
                                        this.args = nargs;
 
941
                                        for(int i = 0; i < argTypes.Length; i++)
 
942
                                        {
 
943
                                                if(!argTypes[i].IsUnloadable && argTypes[i].IsGhost)
 
944
                                                {
 
945
                                                        object v = Activator.CreateInstance(argTypes[i].TypeAsSignatureType);
 
946
                                                        argTypes[i].GhostRefField.SetValue(v, args[i + 1]);
 
947
                                                        args[i + 1] = v;
 
948
                                                }
 
949
                                        }
 
950
                                }
 
951
                                else
 
952
                                {
 
953
                                        this.obj = original_obj;
 
954
                                        this.args = original_args;
 
955
                                        for(int i = 0; i < argTypes.Length; i++)
 
956
                                        {
 
957
                                                if(!argTypes[i].IsUnloadable && argTypes[i].IsGhost)
 
958
                                                {
 
959
                                                        if(this.args == original_args)
 
960
                                                        {
 
961
                                                                this.args = (object[])args.Clone();
 
962
                                                        }
 
963
                                                        object v = Activator.CreateInstance(argTypes[i].TypeAsSignatureType);
 
964
                                                        argTypes[i].GhostRefField.SetValue(v, args[i]);
 
965
                                                        this.args[i] = v;
 
966
                                                }
 
967
                                        }
 
968
                                }
 
969
 
 
970
                                if(mw.HasCallerID)
 
971
                                {
 
972
                                        object[] nargs = new object[args.Length + 1];
 
973
                                        Array.Copy(args, nargs, args.Length);
 
974
                                        nargs[args.Length] = callerID;
 
975
                                        args = nargs;
 
976
                                }
 
977
                        }
 
978
 
 
979
                        internal object GetObj()
 
980
                        {
 
981
                                return obj;
 
982
                        }
 
983
 
 
984
                        internal object[] GetArgs()
 
985
                        {
 
986
                                return args;
 
987
                        }
 
988
                }
 
989
#endif // !STATIC_COMPILER && !FIRST_PASS && !STUB_GENERATOR
 
990
 
 
991
                internal static OpCode SimpleOpCodeToOpCode(SimpleOpCode opc)
 
992
                {
 
993
                        switch(opc)
 
994
                        {
 
995
                                case SimpleOpCode.Call:
 
996
                                        return OpCodes.Call;
 
997
                                case SimpleOpCode.Callvirt:
 
998
                                        return OpCodes.Callvirt;
 
999
                                case SimpleOpCode.Newobj:
 
1000
                                        return OpCodes.Newobj;
 
1001
                                default:
 
1002
                                        throw new InvalidOperationException();
 
1003
                        }
 
1004
                }
 
1005
 
 
1006
                internal virtual bool IsOptionalAttributeAnnotationValue
 
1007
                {
 
1008
                        get { return false; }
 
1009
                }
 
1010
        }
 
1011
 
 
1012
        // placeholder for <clinit> method that exist in ClassFile but not in TypeWrapper
 
1013
        // (because it is optimized away)
 
1014
        sealed class DummyMethodWrapper : MethodWrapper
 
1015
        {
 
1016
                internal DummyMethodWrapper(TypeWrapper tw)
 
1017
                        : base(tw, StringConstants.CLINIT, StringConstants.SIG_VOID, null, PrimitiveTypeWrapper.VOID, TypeWrapper.EmptyArray, Modifiers.Static, MemberFlags.None)
 
1018
                {
 
1019
                }
 
1020
 
 
1021
                protected override void DoLinkMethod()
 
1022
                {
 
1023
                        // we're pre-linked (because we pass the signature types to the base constructor)
 
1024
                        throw new InvalidOperationException();
 
1025
                }
 
1026
        }
 
1027
 
 
1028
        abstract class SmartMethodWrapper : MethodWrapper
 
1029
        {
 
1030
                internal SmartMethodWrapper(TypeWrapper declaringType, string name, string sig, MethodBase method, TypeWrapper returnType, TypeWrapper[] parameterTypes, Modifiers modifiers, MemberFlags flags)
 
1031
                        : base(declaringType, name, sig, method, returnType, parameterTypes, modifiers, flags)
 
1032
                {
 
1033
                }
 
1034
 
 
1035
#if !STUB_GENERATOR
 
1036
                internal sealed override void EmitCall(CodeEmitter ilgen)
 
1037
                {
 
1038
                        AssertLinked();
 
1039
                        CallImpl(ilgen);
 
1040
                }
 
1041
 
 
1042
                protected virtual void CallImpl(CodeEmitter ilgen)
 
1043
                {
 
1044
                        throw new InvalidOperationException();
 
1045
                }
 
1046
 
 
1047
                internal sealed override void EmitCallvirt(CodeEmitter ilgen)
 
1048
                {
 
1049
                        AssertLinked();
 
1050
                        if(DeclaringType.IsNonPrimitiveValueType)
 
1051
                        {
 
1052
                                // callvirt isn't allowed on a value type
 
1053
                                // (we don't need to check for a null reference, because we're always dealing with an unboxed value)
 
1054
                                CallImpl(ilgen);
 
1055
                        }
 
1056
                        else
 
1057
                        {
 
1058
                                CallvirtImpl(ilgen);
 
1059
                        }
 
1060
                }
 
1061
 
 
1062
                protected virtual void CallvirtImpl(CodeEmitter ilgen)
 
1063
                {
 
1064
                        throw new InvalidOperationException();
 
1065
                }
 
1066
 
 
1067
                internal sealed override void EmitNewobj(CodeEmitter ilgen)
 
1068
                {
 
1069
                        AssertLinked();
 
1070
                        NewobjImpl(ilgen);
 
1071
                        if(DeclaringType.IsNonPrimitiveValueType)
 
1072
                        {
 
1073
                                DeclaringType.EmitBox(ilgen);
 
1074
                        }
 
1075
                }
 
1076
 
 
1077
                protected virtual void NewobjImpl(CodeEmitter ilgen)
 
1078
                {
 
1079
                        throw new InvalidOperationException();
 
1080
                }
 
1081
#endif // STUB_GENERATOR
 
1082
        }
 
1083
 
 
1084
        enum SimpleOpCode : byte
 
1085
        {
 
1086
                Call,
 
1087
                Callvirt,
 
1088
                Newobj
 
1089
        }
 
1090
 
 
1091
        sealed class SimpleCallMethodWrapper : MethodWrapper
 
1092
        {
 
1093
                private SimpleOpCode call;
 
1094
                private SimpleOpCode callvirt;
 
1095
 
 
1096
                internal SimpleCallMethodWrapper(TypeWrapper declaringType, string name, string sig, MethodInfo method, TypeWrapper returnType, TypeWrapper[] parameterTypes, Modifiers modifiers, MemberFlags flags, SimpleOpCode call, SimpleOpCode callvirt)
 
1097
                        : base(declaringType, name, sig, method, returnType, parameterTypes, modifiers, flags)
 
1098
                {
 
1099
                        this.call = call;
 
1100
                        this.callvirt = callvirt;
 
1101
                }
 
1102
 
 
1103
#if !STUB_GENERATOR
 
1104
                internal override void EmitCall(CodeEmitter ilgen)
 
1105
                {
 
1106
                        ilgen.Emit(SimpleOpCodeToOpCode(call), GetMethod());
 
1107
                }
 
1108
 
 
1109
                internal override void EmitCallvirt(CodeEmitter ilgen)
 
1110
                {
 
1111
                        ilgen.Emit(SimpleOpCodeToOpCode(callvirt), GetMethod());
 
1112
                }
 
1113
#endif // !STUB_GENERATOR
 
1114
        }
 
1115
 
 
1116
        sealed class TypicalMethodWrapper : SmartMethodWrapper
 
1117
        {
 
1118
                internal TypicalMethodWrapper(TypeWrapper declaringType, string name, string sig, MethodBase method, TypeWrapper returnType, TypeWrapper[] parameterTypes, Modifiers modifiers, MemberFlags flags)
 
1119
                        : base(declaringType, name, sig, method, returnType, parameterTypes, modifiers, flags)
 
1120
                {
 
1121
                }
 
1122
 
 
1123
#if !STUB_GENERATOR
 
1124
                protected override void CallImpl(CodeEmitter ilgen)
 
1125
                {
 
1126
                        ilgen.Emit(OpCodes.Call, GetMethod());
 
1127
                }
 
1128
 
 
1129
                protected override void CallvirtImpl(CodeEmitter ilgen)
 
1130
                {
 
1131
                        ilgen.Emit(OpCodes.Callvirt, GetMethod());
 
1132
                }
 
1133
 
 
1134
                protected override void NewobjImpl(CodeEmitter ilgen)
 
1135
                {
 
1136
                        ilgen.Emit(OpCodes.Newobj, GetMethod());
 
1137
                }
 
1138
#endif // !STUB_GENERATOR
 
1139
        }
 
1140
 
 
1141
        sealed class GhostMethodWrapper : SmartMethodWrapper
 
1142
        {
 
1143
                private MethodInfo ghostMethod;
 
1144
 
 
1145
                internal GhostMethodWrapper(TypeWrapper declaringType, string name, string sig, MethodBase method, MethodInfo ghostMethod, TypeWrapper returnType, TypeWrapper[] parameterTypes, Modifiers modifiers, MemberFlags flags)
 
1146
                        : base(declaringType, name, sig, method, returnType, parameterTypes, modifiers, flags)
 
1147
                {
 
1148
                        // make sure we weren't handed the ghostMethod in the wrapper value type
 
1149
                        Debug.Assert(method == null || method.DeclaringType.IsInterface);
 
1150
                        this.ghostMethod = ghostMethod;
 
1151
                }
 
1152
 
 
1153
                private void ResolveGhostMethod()
 
1154
                {
 
1155
                        if (ghostMethod == null)
 
1156
                        {
 
1157
                                ghostMethod = DeclaringType.TypeAsSignatureType.GetMethod(this.Name, this.GetParametersForDefineMethod());
 
1158
                                if (ghostMethod == null)
 
1159
                                {
 
1160
                                        throw new InvalidOperationException("Unable to resolve ghost method");
 
1161
                                }
 
1162
                        }
 
1163
                }
 
1164
 
 
1165
#if !STUB_GENERATOR
 
1166
                protected override void CallvirtImpl(CodeEmitter ilgen)
 
1167
                {
 
1168
                        ResolveGhostMethod();
 
1169
                        ilgen.Emit(OpCodes.Call, ghostMethod);
 
1170
                }
 
1171
#endif
 
1172
        }
 
1173
 
 
1174
        sealed class AccessStubMethodWrapper : SmartMethodWrapper
 
1175
        {
 
1176
                private readonly MethodInfo stubVirtual;
 
1177
                private readonly MethodInfo stubNonVirtual;
 
1178
 
 
1179
                internal AccessStubMethodWrapper(TypeWrapper declaringType, string name, string sig, MethodInfo core, MethodInfo stubVirtual, MethodInfo stubNonVirtual, TypeWrapper returnType, TypeWrapper[] parameterTypes, Modifiers modifiers, MemberFlags flags)
 
1180
                        : base(declaringType, name, sig, core, returnType, parameterTypes, modifiers, flags)
 
1181
                {
 
1182
                        this.stubVirtual = stubVirtual;
 
1183
                        this.stubNonVirtual = stubNonVirtual;
 
1184
                }
 
1185
 
 
1186
#if !STUB_GENERATOR
 
1187
                protected override void CallImpl(CodeEmitter ilgen)
 
1188
                {
 
1189
                        ilgen.Emit(OpCodes.Call, stubNonVirtual);
 
1190
                }
 
1191
 
 
1192
                protected override void CallvirtImpl(CodeEmitter ilgen)
 
1193
                {
 
1194
                        ilgen.Emit(OpCodes.Callvirt, stubVirtual);
 
1195
                }
 
1196
#endif // !STUB_GENERATOR
 
1197
        }
 
1198
 
 
1199
        sealed class AccessStubConstructorMethodWrapper : SmartMethodWrapper
 
1200
        {
 
1201
                private readonly ConstructorInfo stub;
 
1202
 
 
1203
                internal AccessStubConstructorMethodWrapper(TypeWrapper declaringType, string sig, ConstructorInfo core, ConstructorInfo stub, TypeWrapper[] parameterTypes, Modifiers modifiers, MemberFlags flags)
 
1204
                        : base(declaringType, StringConstants.INIT, sig, core, PrimitiveTypeWrapper.VOID, parameterTypes, modifiers, flags)
 
1205
                {
 
1206
                        this.stub = stub;
 
1207
                }
 
1208
 
 
1209
#if !STUB_GENERATOR
 
1210
                protected override void CallImpl(CodeEmitter ilgen)
 
1211
                {
 
1212
                        ilgen.Emit(OpCodes.Call, stub);
 
1213
                }
 
1214
 
 
1215
                protected override void NewobjImpl(CodeEmitter ilgen)
 
1216
                {
 
1217
                        ilgen.Emit(OpCodes.Newobj, stub);
 
1218
                }
 
1219
#endif // !STUB_GENERATOR
 
1220
        }
 
1221
 
 
1222
        abstract class FieldWrapper : MemberWrapper
 
1223
        {
 
1224
#if !STATIC_COMPILER && !FIRST_PASS && !STUB_GENERATOR
 
1225
                private volatile java.lang.reflect.Field reflectionField;
 
1226
                private sun.reflect.FieldAccessor jniAccessor;
 
1227
#endif
 
1228
                internal static readonly FieldWrapper[] EmptyArray  = new FieldWrapper[0];
 
1229
                private FieldInfo field;
 
1230
                private TypeWrapper fieldType;
 
1231
 
 
1232
                internal FieldWrapper(TypeWrapper declaringType, TypeWrapper fieldType, string name, string sig, Modifiers modifiers, FieldInfo field, MemberFlags flags)
 
1233
                        : base(declaringType, name, sig, modifiers, flags)
 
1234
                {
 
1235
                        Debug.Assert(name != null);
 
1236
                        Debug.Assert(sig != null);
 
1237
                        this.fieldType = fieldType;
 
1238
                        this.field = field;
 
1239
                        UpdateNonPublicTypeInSignatureFlag();
 
1240
#if STATIC_COMPILER
 
1241
                        if (IsFinal
 
1242
                                && DeclaringType.IsPublic
 
1243
                                && !DeclaringType.IsInterface
 
1244
                                && (IsPublic || (IsProtected && !DeclaringType.IsFinal))
 
1245
                                && !DeclaringType.GetClassLoader().StrictFinalFieldSemantics
 
1246
                                && DeclaringType is DynamicTypeWrapper
 
1247
                                && !(this is ConstantFieldWrapper)
 
1248
                                && !(this is DynamicPropertyFieldWrapper))
 
1249
                        {
 
1250
                                SetType2FinalField();
 
1251
                        }
 
1252
#endif
 
1253
                }
 
1254
 
 
1255
                internal FieldWrapper(TypeWrapper declaringType, TypeWrapper fieldType, string name, string sig, ExModifiers modifiers, FieldInfo field)
 
1256
                        : this(declaringType, fieldType, name, sig, modifiers.Modifiers, field,
 
1257
                                        (modifiers.IsInternal ? MemberFlags.InternalAccess : MemberFlags.None))
 
1258
                {
 
1259
                }
 
1260
 
 
1261
                private void UpdateNonPublicTypeInSignatureFlag()
 
1262
                {
 
1263
                        if ((IsPublic || IsProtected) && fieldType != null && !IsAccessStub)
 
1264
                        {
 
1265
                                if (!fieldType.IsPublic && !fieldType.IsUnloadable)
 
1266
                                {
 
1267
                                        SetNonPublicTypeInSignatureFlag();
 
1268
                                }
 
1269
                        }
 
1270
                }
 
1271
 
 
1272
                internal FieldInfo GetField()
 
1273
                {
 
1274
                        AssertLinked();
 
1275
                        return field;
 
1276
                }
 
1277
 
 
1278
                [Conditional("DEBUG")]
 
1279
                internal void AssertLinked()
 
1280
                {
 
1281
                        if(fieldType == null)
 
1282
                        {
 
1283
                                Tracer.Error(Tracer.Runtime, "AssertLinked failed: " + this.DeclaringType.Name + "::" + this.Name + " (" + this.Signature + ")");
 
1284
                        }
 
1285
                        Debug.Assert(fieldType != null, this.DeclaringType.Name + "::" + this.Name + " (" + this.Signature+ ")");
 
1286
                }
 
1287
 
 
1288
#if !STATIC_COMPILER && !STUB_GENERATOR
 
1289
                // NOTE used (thru IKVM.Runtime.Util.GetFieldConstantValue) by ikvmstub to find out if the
 
1290
                // field is a constant (and if it is, to get its value)
 
1291
                internal object GetConstant()
 
1292
                {
 
1293
                        AssertLinked();
 
1294
                        // only primitives and string can be literals in Java (because the other "primitives" (like uint),
 
1295
                        // are treated as NonPrimitiveValueTypes)
 
1296
                        if(field != null && field.IsLiteral && (fieldType.IsPrimitive || fieldType == CoreClasses.java.lang.String.Wrapper))
 
1297
                        {
 
1298
                                object val = field.GetRawConstantValue();
 
1299
                                if(field.FieldType.IsEnum)
 
1300
                                {
 
1301
                                        val = EnumHelper.GetPrimitiveValue(EnumHelper.GetUnderlyingType(field.FieldType), val);
 
1302
                                }
 
1303
                                if(fieldType.IsPrimitive)
 
1304
                                {
 
1305
                                        return JVM.Box(val);
 
1306
                                }
 
1307
                                return val;
 
1308
                        }
 
1309
                        return null;
 
1310
                }
 
1311
 
 
1312
                internal static FieldWrapper FromField(object field)
 
1313
                {
 
1314
#if FIRST_PASS
 
1315
                        return null;
 
1316
#else
 
1317
                        java.lang.reflect.Field f = (java.lang.reflect.Field)field;
 
1318
                        int slot = f._slot();
 
1319
                        if (slot == -1)
 
1320
                        {
 
1321
                                // it's a Field created by Unsafe.objectFieldOffset(Class,String) so we must resolve based on the name
 
1322
                                foreach (FieldWrapper fw in TypeWrapper.FromClass(f.getDeclaringClass()).GetFields())
 
1323
                                {
 
1324
                                        if (fw.Name == f.getName())
 
1325
                                        {
 
1326
                                                return fw;
 
1327
                                        }
 
1328
                                }
 
1329
                        }
 
1330
                        return TypeWrapper.FromClass(f.getDeclaringClass()).GetFields()[slot];
 
1331
#endif
 
1332
                }
 
1333
 
 
1334
                internal object ToField(bool copy)
 
1335
                {
 
1336
                        return ToField(copy, null);
 
1337
                }
 
1338
 
 
1339
                internal object ToField(bool copy, int? fieldIndex)
 
1340
                {
 
1341
#if FIRST_PASS
 
1342
                        return null;
 
1343
#else
 
1344
                        java.lang.reflect.Field field = reflectionField;
 
1345
                        if (field == null)
 
1346
                        {
 
1347
                                const Modifiers ReflectionFieldModifiersMask = Modifiers.Public | Modifiers.Private | Modifiers.Protected | Modifiers.Static
 
1348
                                        | Modifiers.Final | Modifiers.Volatile | Modifiers.Transient | Modifiers.Synthetic | Modifiers.Enum;
 
1349
                                Link();
 
1350
                                field = new java.lang.reflect.Field(
 
1351
                                        this.DeclaringType.ClassObject,
 
1352
                                        this.Name,
 
1353
                                        this.FieldTypeWrapper.EnsureLoadable(this.DeclaringType.GetClassLoader()).ClassObject,
 
1354
                                        (int)(this.Modifiers & ReflectionFieldModifiersMask) | (this.IsInternal ? 0x40000000 : 0),
 
1355
                                        fieldIndex ?? Array.IndexOf(this.DeclaringType.GetFields(), this),
 
1356
                                        this.DeclaringType.GetGenericFieldSignature(this),
 
1357
                                        null
 
1358
                                );
 
1359
                        }
 
1360
                        lock (this)
 
1361
                        {
 
1362
                                if (reflectionField == null)
 
1363
                                {
 
1364
                                        reflectionField = field;
 
1365
                                }
 
1366
                                else
 
1367
                                {
 
1368
                                        field = reflectionField;
 
1369
                                }
 
1370
                        }
 
1371
                        if (copy)
 
1372
                        {
 
1373
                                field = field.copy();
 
1374
                        }
 
1375
                        return field;
 
1376
#endif // FIRST_PASS
 
1377
                }
 
1378
#endif // !STATIC_COMPILER && !STUB_GENERATOR
 
1379
 
 
1380
                [System.Security.SecurityCritical]
 
1381
                internal static FieldWrapper FromCookie(IntPtr cookie)
 
1382
                {
 
1383
                        return (FieldWrapper)FromCookieImpl(cookie);
 
1384
                }
 
1385
 
 
1386
                internal TypeWrapper FieldTypeWrapper
 
1387
                {
 
1388
                        get
 
1389
                        {
 
1390
                                AssertLinked();
 
1391
                                return fieldType;
 
1392
                        }
 
1393
                }
 
1394
 
 
1395
#if !STUB_GENERATOR
 
1396
                internal void EmitGet(CodeEmitter ilgen)
 
1397
                {
 
1398
                        AssertLinked();
 
1399
                        EmitGetImpl(ilgen);
 
1400
                }
 
1401
 
 
1402
                protected abstract void EmitGetImpl(CodeEmitter ilgen);
 
1403
 
 
1404
                internal void EmitSet(CodeEmitter ilgen)
 
1405
                {
 
1406
                        AssertLinked();
 
1407
                        EmitSetImpl(ilgen);
 
1408
                }
 
1409
 
 
1410
                protected abstract void EmitSetImpl(CodeEmitter ilgen);
 
1411
#endif // !STUB_GENERATOR
 
1412
 
 
1413
 
 
1414
#if STATIC_COMPILER
 
1415
                internal bool IsLinked
 
1416
                {
 
1417
                        get { return fieldType != null; }
 
1418
                }
 
1419
#endif
 
1420
                
 
1421
                internal void Link()
 
1422
                {
 
1423
                        lock(this)
 
1424
                        {
 
1425
                                if(fieldType != null)
 
1426
                                {
 
1427
                                        return;
 
1428
                                }
 
1429
                        }
 
1430
                        TypeWrapper fld = this.DeclaringType.GetClassLoader().FieldTypeWrapperFromSigNoThrow(Signature);
 
1431
                        lock(this)
 
1432
                        {
 
1433
                                try
 
1434
                                {
 
1435
                                        // critical code in the finally block to avoid Thread.Abort interrupting the thread
 
1436
                                }
 
1437
                                finally
 
1438
                                {
 
1439
                                        if(fieldType == null)
 
1440
                                        {
 
1441
                                                fieldType = fld;
 
1442
                                                UpdateNonPublicTypeInSignatureFlag();
 
1443
                                                try
 
1444
                                                {
 
1445
                                                        field = this.DeclaringType.LinkField(this);
 
1446
                                                }
 
1447
                                                catch
 
1448
                                                {
 
1449
                                                        // HACK if linking fails, we unlink to make sure
 
1450
                                                        // that the next link attempt will fail again
 
1451
                                                        fieldType = null;
 
1452
                                                        throw;
 
1453
                                                }
 
1454
                                        }
 
1455
                                }
 
1456
                        }
 
1457
                }
 
1458
 
 
1459
                internal bool IsVolatile
 
1460
                {
 
1461
                        get
 
1462
                        {
 
1463
                                return (Modifiers & Modifiers.Volatile) != 0;
 
1464
                        }
 
1465
                }
 
1466
 
 
1467
                internal static FieldWrapper Create(TypeWrapper declaringType, TypeWrapper fieldType, FieldInfo fi, string name, string sig, ExModifiers modifiers)
 
1468
                {
 
1469
                        // volatile long & double field accesses must be made atomic
 
1470
                        if((modifiers.Modifiers & Modifiers.Volatile) != 0 && (sig == "J" || sig == "D"))
 
1471
                        {
 
1472
                                return new VolatileLongDoubleFieldWrapper(declaringType, fieldType, fi, name, sig, modifiers);
 
1473
                        }
 
1474
                        return new SimpleFieldWrapper(declaringType, fieldType, fi, name, sig, modifiers);
 
1475
                }
 
1476
 
 
1477
#if !STATIC_COMPILER && !STUB_GENERATOR
 
1478
                internal virtual void ResolveField()
 
1479
                {
 
1480
                        FieldBuilder fb = field as FieldBuilder;
 
1481
                        if(fb != null)
 
1482
                        {
 
1483
                                field = field.Module.ResolveField(fb.GetToken().Token);
 
1484
                        }
 
1485
                }
 
1486
 
 
1487
                internal object GetFieldAccessorJNI()
 
1488
                {
 
1489
#if FIRST_PASS
 
1490
                        return null;
 
1491
#else
 
1492
                        if (jniAccessor == null)
 
1493
                        {
 
1494
                                jniAccessor = IKVM.NativeCode.sun.reflect.ReflectionFactory.NewFieldAccessorJNI(this);
 
1495
                        }
 
1496
                        return jniAccessor;
 
1497
#endif
 
1498
                }
 
1499
#endif // !STATIC_COMPILER && !STUB_GENERATOR
 
1500
        }
 
1501
 
 
1502
        sealed class SimpleFieldWrapper : FieldWrapper
 
1503
        {
 
1504
                internal SimpleFieldWrapper(TypeWrapper declaringType, TypeWrapper fieldType, FieldInfo fi, string name, string sig, ExModifiers modifiers)
 
1505
                        : base(declaringType, fieldType, name, sig, modifiers, fi)
 
1506
                {
 
1507
                        Debug.Assert(!(fieldType == PrimitiveTypeWrapper.DOUBLE || fieldType == PrimitiveTypeWrapper.LONG) || !IsVolatile);
 
1508
                }
 
1509
 
 
1510
#if !STUB_GENERATOR
 
1511
                protected override void EmitGetImpl(CodeEmitter ilgen)
 
1512
                {
 
1513
                        if(!IsStatic && DeclaringType.IsNonPrimitiveValueType)
 
1514
                        {
 
1515
                                ilgen.Emit(OpCodes.Unbox, DeclaringType.TypeAsTBD);
 
1516
                        }
 
1517
                        if(IsVolatile)
 
1518
                        {
 
1519
                                ilgen.Emit(OpCodes.Volatile);
 
1520
                        }
 
1521
                        ilgen.Emit(IsStatic ? OpCodes.Ldsfld : OpCodes.Ldfld, GetField());
 
1522
                }
 
1523
 
 
1524
                protected override void EmitSetImpl(CodeEmitter ilgen)
 
1525
                {
 
1526
                        FieldInfo fi = GetField();
 
1527
                        if(!IsStatic && DeclaringType.IsNonPrimitiveValueType)
 
1528
                        {
 
1529
                                CodeEmitterLocal temp = ilgen.DeclareLocal(FieldTypeWrapper.TypeAsSignatureType);
 
1530
                                ilgen.Emit(OpCodes.Stloc, temp);
 
1531
                                ilgen.Emit(OpCodes.Unbox, DeclaringType.TypeAsTBD);
 
1532
                                ilgen.Emit(OpCodes.Ldloc, temp);
 
1533
                        }
 
1534
                        if(IsVolatile)
 
1535
                        {
 
1536
                                ilgen.Emit(OpCodes.Volatile);
 
1537
                        }
 
1538
                        ilgen.Emit(IsStatic ? OpCodes.Stsfld : OpCodes.Stfld, fi);
 
1539
                        if(IsVolatile)
 
1540
                        {
 
1541
                                ilgen.EmitMemoryBarrier();
 
1542
                        }
 
1543
                }
 
1544
#endif // !STUB_GENERATOR
 
1545
        }
 
1546
 
 
1547
        sealed class VolatileLongDoubleFieldWrapper : FieldWrapper
 
1548
        {
 
1549
                internal VolatileLongDoubleFieldWrapper(TypeWrapper declaringType, TypeWrapper fieldType, FieldInfo fi, string name, string sig, ExModifiers modifiers)
 
1550
                        : base(declaringType, fieldType, name, sig, modifiers, fi)
 
1551
                {
 
1552
                        Debug.Assert(IsVolatile);
 
1553
                        Debug.Assert(sig == "J" || sig == "D");
 
1554
                }
 
1555
 
 
1556
#if !STUB_GENERATOR
 
1557
                protected override void EmitGetImpl(CodeEmitter ilgen)
 
1558
                {
 
1559
                        FieldInfo fi = GetField();
 
1560
                        if(fi.IsStatic)
 
1561
                        {
 
1562
                                ilgen.Emit(OpCodes.Ldsflda, fi);
 
1563
                        }
 
1564
                        else
 
1565
                        {
 
1566
                                if(DeclaringType.IsNonPrimitiveValueType)
 
1567
                                {
 
1568
                                        ilgen.Emit(OpCodes.Unbox, DeclaringType.TypeAsTBD);
 
1569
                                }
 
1570
                                ilgen.Emit(OpCodes.Ldflda, fi);
 
1571
                        }
 
1572
                        if(FieldTypeWrapper == PrimitiveTypeWrapper.DOUBLE)
 
1573
                        {
 
1574
                                ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.volatileReadDouble);
 
1575
                        }
 
1576
                        else
 
1577
                        {
 
1578
                                Debug.Assert(FieldTypeWrapper == PrimitiveTypeWrapper.LONG);
 
1579
                                ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.volatileReadLong);
 
1580
                        }
 
1581
                }
 
1582
 
 
1583
                protected override void EmitSetImpl(CodeEmitter ilgen)
 
1584
                {
 
1585
                        FieldInfo fi = GetField();
 
1586
                        CodeEmitterLocal temp = ilgen.DeclareLocal(FieldTypeWrapper.TypeAsSignatureType);
 
1587
                        ilgen.Emit(OpCodes.Stloc, temp);
 
1588
                        if(fi.IsStatic)
 
1589
                        {
 
1590
                                ilgen.Emit(OpCodes.Ldsflda, fi);
 
1591
                        }
 
1592
                        else
 
1593
                        {
 
1594
                                if(DeclaringType.IsNonPrimitiveValueType)
 
1595
                                {
 
1596
                                        ilgen.Emit(OpCodes.Unbox, DeclaringType.TypeAsTBD);
 
1597
                                }
 
1598
                                ilgen.Emit(OpCodes.Ldflda, fi);
 
1599
                        }
 
1600
                        ilgen.Emit(OpCodes.Ldloc, temp);
 
1601
                        if(FieldTypeWrapper == PrimitiveTypeWrapper.DOUBLE)
 
1602
                        {
 
1603
                                ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.volatileWriteDouble);
 
1604
                        }
 
1605
                        else
 
1606
                        {
 
1607
                                Debug.Assert(FieldTypeWrapper == PrimitiveTypeWrapper.LONG);
 
1608
                                ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.volatileWriteLong);
 
1609
                        }
 
1610
                }
 
1611
#endif // !STUB_GENERATOR
 
1612
        }
 
1613
 
 
1614
#if !STUB_GENERATOR
 
1615
        // this class represents a .NET property defined in Java with the ikvm.lang.Property annotation
 
1616
        sealed class DynamicPropertyFieldWrapper : FieldWrapper
 
1617
        {
 
1618
                private readonly MethodWrapper getter;
 
1619
                private readonly MethodWrapper setter;
 
1620
                private PropertyBuilder pb;
 
1621
 
 
1622
                private MethodWrapper GetMethod(string name, string sig, bool isstatic)
 
1623
                {
 
1624
                        if(name != null)
 
1625
                        {
 
1626
                                MethodWrapper mw = this.DeclaringType.GetMethodWrapper(name, sig, false);
 
1627
                                if(mw != null && mw.IsStatic == isstatic)
 
1628
                                {
 
1629
                                        mw.IsPropertyAccessor = true;
 
1630
                                        return mw;
 
1631
                                }
 
1632
                                Tracer.Error(Tracer.Compiler, "Property '{0}' accessor '{1}' not found in class '{2}'", this.Name, name, this.DeclaringType.Name);
 
1633
                        }
 
1634
                        return null;
 
1635
                }
 
1636
 
 
1637
                internal DynamicPropertyFieldWrapper(TypeWrapper declaringType, ClassFile.Field fld)
 
1638
                        : base(declaringType, null, fld.Name, fld.Signature, new ExModifiers(fld.Modifiers, fld.IsInternal), null)
 
1639
                {
 
1640
                        getter = GetMethod(fld.PropertyGetter, "()" + fld.Signature, fld.IsStatic);
 
1641
                        setter = GetMethod(fld.PropertySetter, "(" + fld.Signature + ")V", fld.IsStatic);
 
1642
                }
 
1643
 
 
1644
#if !STATIC_COMPILER && !FIRST_PASS
 
1645
                internal override void ResolveField()
 
1646
                {
 
1647
                        if (getter != null)
 
1648
                        {
 
1649
                                getter.ResolveMethod();
 
1650
                        }
 
1651
                        if (setter != null)
 
1652
                        {
 
1653
                                setter.ResolveMethod();
 
1654
                        }
 
1655
                }
 
1656
#endif
 
1657
 
 
1658
                internal PropertyBuilder GetPropertyBuilder()
 
1659
                {
 
1660
                        AssertLinked();
 
1661
                        return pb;
 
1662
                }
 
1663
 
 
1664
                internal void DoLink(TypeBuilder tb)
 
1665
                {
 
1666
                        if(getter != null)
 
1667
                        {
 
1668
                                getter.Link();
 
1669
                        }
 
1670
                        if(setter != null)
 
1671
                        {
 
1672
                                setter.Link();
 
1673
                        }
 
1674
                        pb = tb.DefineProperty(this.Name, PropertyAttributes.None, this.FieldTypeWrapper.TypeAsSignatureType, Type.EmptyTypes);
 
1675
                        if(getter != null)
 
1676
                        {
 
1677
                                pb.SetGetMethod((MethodBuilder)getter.GetMethod());
 
1678
                        }
 
1679
                        if(setter != null)
 
1680
                        {
 
1681
                                pb.SetSetMethod((MethodBuilder)setter.GetMethod());
 
1682
                        }
 
1683
#if STATIC_COMPILER
 
1684
                        AttributeHelper.SetModifiers(pb, this.Modifiers, this.IsInternal);
 
1685
#endif
 
1686
                }
 
1687
 
 
1688
                protected override void EmitGetImpl(CodeEmitter ilgen)
 
1689
                {
 
1690
                        if(getter == null)
 
1691
                        {
 
1692
                                EmitThrowNoSuchMethodErrorForGetter(ilgen, this.FieldTypeWrapper, this.IsStatic);
 
1693
                        }
 
1694
                        else if(getter.IsStatic)
 
1695
                        {
 
1696
                                getter.EmitCall(ilgen);
 
1697
                        }
 
1698
                        else
 
1699
                        {
 
1700
                                getter.EmitCallvirt(ilgen);
 
1701
                        }
 
1702
                }
 
1703
 
 
1704
                internal static void EmitThrowNoSuchMethodErrorForGetter(CodeEmitter ilgen, TypeWrapper type, bool isStatic)
 
1705
                {
 
1706
                        // HACK the branch around the throw is to keep the verifier happy
 
1707
                        CodeEmitterLabel label = ilgen.DefineLabel();
 
1708
                        ilgen.Emit(OpCodes.Ldc_I4_0);
 
1709
                        ilgen.EmitBrtrue(label);
 
1710
                        ilgen.EmitThrow("java.lang.NoSuchMethodError");
 
1711
                        ilgen.MarkLabel(label);
 
1712
                        if (!isStatic)
 
1713
                        {
 
1714
                                ilgen.Emit(OpCodes.Pop);
 
1715
                        }
 
1716
                        ilgen.Emit(OpCodes.Ldloc, ilgen.DeclareLocal(type.TypeAsLocalOrStackType));
 
1717
                }
 
1718
 
 
1719
                protected override void EmitSetImpl(CodeEmitter ilgen)
 
1720
                {
 
1721
                        if(setter == null)
 
1722
                        {
 
1723
                                if(this.IsFinal)
 
1724
                                {
 
1725
                                        ilgen.Emit(OpCodes.Pop);
 
1726
                                        if(!this.IsStatic)
 
1727
                                        {
 
1728
                                                ilgen.Emit(OpCodes.Pop);
 
1729
                                        }
 
1730
                                }
 
1731
                                else
 
1732
                                {
 
1733
                                        EmitThrowNoSuchMethodErrorForSetter(ilgen, this.IsStatic);
 
1734
                                }
 
1735
                        }
 
1736
                        else if(setter.IsStatic)
 
1737
                        {
 
1738
                                setter.EmitCall(ilgen);
 
1739
                        }
 
1740
                        else
 
1741
                        {
 
1742
                                setter.EmitCallvirt(ilgen);
 
1743
                        }
 
1744
                }
 
1745
 
 
1746
                internal static void EmitThrowNoSuchMethodErrorForSetter(CodeEmitter ilgen, bool isStatic)
 
1747
                {
 
1748
                        // HACK the branch around the throw is to keep the verifier happy
 
1749
                        CodeEmitterLabel label = ilgen.DefineLabel();
 
1750
                        ilgen.Emit(OpCodes.Ldc_I4_0);
 
1751
                        ilgen.EmitBrtrue(label);
 
1752
                        ilgen.EmitThrow("java.lang.NoSuchMethodError");
 
1753
                        ilgen.MarkLabel(label);
 
1754
                        ilgen.Emit(OpCodes.Pop);
 
1755
                        if (!isStatic)
 
1756
                        {
 
1757
                                ilgen.Emit(OpCodes.Pop);
 
1758
                        }
 
1759
                }
 
1760
        }
 
1761
#endif // !STUB_GENERATOR
 
1762
 
 
1763
        // this class represents a .NET property defined in Java with the ikvm.lang.Property annotation
 
1764
        sealed class CompiledPropertyFieldWrapper : FieldWrapper
 
1765
        {
 
1766
                private readonly PropertyInfo property;
 
1767
 
 
1768
                internal CompiledPropertyFieldWrapper(TypeWrapper declaringType, PropertyInfo property, ExModifiers modifiers)
 
1769
                        : base(declaringType, ClassLoaderWrapper.GetWrapperFromType(property.PropertyType), property.Name, ClassLoaderWrapper.GetWrapperFromType(property.PropertyType).SigName, modifiers, null)
 
1770
                {
 
1771
                        this.property = property;
 
1772
                }
 
1773
 
 
1774
#if !STUB_GENERATOR
 
1775
                protected override void EmitGetImpl(CodeEmitter ilgen)
 
1776
                {
 
1777
                        MethodInfo getter = property.GetGetMethod(true);
 
1778
                        if(getter == null)
 
1779
                        {
 
1780
                                DynamicPropertyFieldWrapper.EmitThrowNoSuchMethodErrorForGetter(ilgen, this.FieldTypeWrapper, this.IsStatic);
 
1781
                        }
 
1782
                        else if(getter.IsStatic)
 
1783
                        {
 
1784
                                ilgen.Emit(OpCodes.Call, getter);
 
1785
                        }
 
1786
                        else
 
1787
                        {
 
1788
                                ilgen.Emit(OpCodes.Callvirt, getter);
 
1789
                        }
 
1790
                }
 
1791
 
 
1792
                protected override void EmitSetImpl(CodeEmitter ilgen)
 
1793
                {
 
1794
                        MethodInfo setter = property.GetSetMethod(true);
 
1795
                        if (setter == null)
 
1796
                        {
 
1797
                                if(this.IsFinal)
 
1798
                                {
 
1799
                                        ilgen.Emit(OpCodes.Pop);
 
1800
                                        if(!this.IsStatic)
 
1801
                                        {
 
1802
                                                ilgen.Emit(OpCodes.Pop);
 
1803
                                        }
 
1804
                                }
 
1805
                                else
 
1806
                                {
 
1807
                                        DynamicPropertyFieldWrapper.EmitThrowNoSuchMethodErrorForSetter(ilgen, this.IsStatic);
 
1808
                                }
 
1809
                        }
 
1810
                        else if(setter.IsStatic)
 
1811
                        {
 
1812
                                ilgen.Emit(OpCodes.Call, setter);
 
1813
                        }
 
1814
                        else
 
1815
                        {
 
1816
                                ilgen.Emit(OpCodes.Callvirt, setter);
 
1817
                        }
 
1818
                }
 
1819
#endif // !STUB_GENERATOR
 
1820
 
 
1821
                internal PropertyInfo GetProperty()
 
1822
                {
 
1823
                        return property;
 
1824
                }
 
1825
        }
 
1826
 
 
1827
        sealed class ConstantFieldWrapper : FieldWrapper
 
1828
        {
 
1829
                // NOTE this field wrapper can resprent a .NET enum, but in that case "constant" contains the raw constant value (i.e. the boxed underlying primitive value, not a boxed enum)
 
1830
                private object constant;
 
1831
 
 
1832
                internal ConstantFieldWrapper(TypeWrapper declaringType, TypeWrapper fieldType, string name, string sig, Modifiers modifiers, FieldInfo field, object constant, MemberFlags flags)
 
1833
                        : base(declaringType, fieldType, name, sig, modifiers, field, flags)
 
1834
                {
 
1835
                        Debug.Assert(IsStatic);
 
1836
            Debug.Assert(constant == null || constant.GetType().IsPrimitive || constant is string);
 
1837
                        this.constant = constant;
 
1838
                }
 
1839
 
 
1840
#if !STUB_GENERATOR
 
1841
                protected override void EmitGetImpl(CodeEmitter ilgen)
 
1842
                {
 
1843
                        // Reading a field should trigger the cctor, but since we're inlining the value
 
1844
                        // we have to trigger it explicitly
 
1845
                        DeclaringType.EmitRunClassConstructor(ilgen);
 
1846
 
 
1847
                        // NOTE even though you're not supposed to access a constant static final (the compiler is supposed
 
1848
                        // to inline them), we have to support it (because it does happen, e.g. if the field becomes final
 
1849
                        // after the referencing class was compiled, or when we're accessing an unsigned primitive .NET field)
 
1850
                        object v = GetConstantValue();
 
1851
                        if(v == null)
 
1852
                        {
 
1853
                                ilgen.Emit(OpCodes.Ldnull);
 
1854
                        }
 
1855
                        else if(constant is int || 
 
1856
                                constant is short ||
 
1857
                                constant is ushort ||
 
1858
                                constant is byte ||
 
1859
                                constant is sbyte ||
 
1860
                                constant is char ||
 
1861
                                constant is bool)
 
1862
                        {
 
1863
                                ilgen.EmitLdc_I4(((IConvertible)constant).ToInt32(null));
 
1864
                        }
 
1865
                        else if(constant is string)
 
1866
                        {
 
1867
                                ilgen.Emit(OpCodes.Ldstr, (string)constant);
 
1868
                        }
 
1869
                        else if(constant is float)
 
1870
                        {
 
1871
                                ilgen.EmitLdc_R4((float)constant);
 
1872
                        }
 
1873
                        else if(constant is double)
 
1874
                        {
 
1875
                                ilgen.EmitLdc_R8((double)constant);
 
1876
                        }
 
1877
                        else if(constant is long)
 
1878
                        {
 
1879
                                ilgen.EmitLdc_I8((long)constant);
 
1880
                        }
 
1881
                        else if(constant is uint)
 
1882
                        {
 
1883
                                ilgen.EmitLdc_I4(unchecked((int)((IConvertible)constant).ToUInt32(null)));
 
1884
                        }
 
1885
                        else if(constant is ulong)
 
1886
                        {
 
1887
                                ilgen.EmitLdc_I8(unchecked((long)(ulong)constant));
 
1888
                        }
 
1889
                        else
 
1890
                        {
 
1891
                                throw new InvalidOperationException(constant.GetType().FullName);
 
1892
                        }
 
1893
                }
 
1894
 
 
1895
                protected override void EmitSetImpl(CodeEmitter ilgen)
 
1896
                {
 
1897
                        // when constant static final fields are updated, the JIT normally doesn't see that (because the
 
1898
                        // constant value is inlined), so we emulate that behavior by emitting a Pop
 
1899
                        ilgen.Emit(OpCodes.Pop);
 
1900
                }
 
1901
#endif // !STUB_GENERATOR
 
1902
 
 
1903
                internal object GetConstantValue()
 
1904
                {
 
1905
                        if(constant == null)
 
1906
                        {
 
1907
                                FieldInfo field = GetField();
 
1908
                                constant = field.GetRawConstantValue();
 
1909
                        }
 
1910
                        return constant;
 
1911
                }
 
1912
        }
 
1913
 
 
1914
        sealed class CompiledAccessStubFieldWrapper : FieldWrapper
 
1915
        {
 
1916
                private MethodInfo getter;
 
1917
                private MethodInfo setter;
 
1918
 
 
1919
                private static Modifiers GetModifiers(PropertyInfo property)
 
1920
                {
 
1921
                        // NOTE we only support the subset of modifiers that is expected for "access stub" properties
 
1922
                        MethodInfo getter = property.GetGetMethod(true);
 
1923
                        Modifiers modifiers = getter.IsPublic ? Modifiers.Public : Modifiers.Protected;
 
1924
                        if(!property.CanWrite)
 
1925
                        {
 
1926
                                modifiers |= Modifiers.Final;
 
1927
                        }
 
1928
                        if(getter.IsStatic)
 
1929
                        {
 
1930
                                modifiers |= Modifiers.Static;
 
1931
                        }
 
1932
                        return modifiers;
 
1933
                }
 
1934
 
 
1935
                // constructor for type 1 access stubs
 
1936
                internal CompiledAccessStubFieldWrapper(TypeWrapper wrapper, PropertyInfo property, TypeWrapper propertyType)
 
1937
                        : this(wrapper, property, null, propertyType, GetModifiers(property), MemberFlags.HideFromReflection | MemberFlags.AccessStub)
 
1938
                {
 
1939
                }
 
1940
 
 
1941
                // constructor for type 2 access stubs
 
1942
                internal CompiledAccessStubFieldWrapper(TypeWrapper wrapper, PropertyInfo property, FieldInfo field, TypeWrapper propertyType)
 
1943
                        : this(wrapper, property, field, propertyType, AttributeHelper.GetModifiersAttribute(property).Modifiers, MemberFlags.AccessStub)
 
1944
                {
 
1945
                }
 
1946
 
 
1947
                private CompiledAccessStubFieldWrapper(TypeWrapper wrapper, PropertyInfo property, FieldInfo field, TypeWrapper propertyType, Modifiers modifiers, MemberFlags flags)
 
1948
                        : base(wrapper, propertyType, property.Name, propertyType.SigName, modifiers, field, flags)
 
1949
                {
 
1950
                        this.getter = property.GetGetMethod(true);
 
1951
                        this.setter = property.GetSetMethod(true);
 
1952
                }
 
1953
 
 
1954
#if !STUB_GENERATOR
 
1955
                protected override void EmitGetImpl(CodeEmitter ilgen)
 
1956
                {
 
1957
                        ilgen.Emit(OpCodes.Call, getter);
 
1958
                }
 
1959
 
 
1960
                protected override void EmitSetImpl(CodeEmitter ilgen)
 
1961
                {
 
1962
                        ilgen.Emit(OpCodes.Call, setter);
 
1963
                }
 
1964
#endif // !STUB_GENERATOR
 
1965
        }
 
1966
}