Fix crossgen with large version bubble enabled
[platform/upstream/coreclr.git] / src / vm / field.h
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4
5 //
6 // COM+ Data Field Abstraction
7 // 
8
9
10 #ifndef _FIELD_H_
11 #define _FIELD_H_
12
13 #include "excep.h"
14
15 // Temporary values stored in FieldDesc m_dwOffset during loading
16 // The high 5 bits must be zero (because in field.h we steal them for other uses), so we must choose values > 0
17 #define FIELD_OFFSET_MAX              ((1<<27)-1)
18 #define FIELD_OFFSET_UNPLACED         FIELD_OFFSET_MAX
19 #define FIELD_OFFSET_UNPLACED_GC_PTR  (FIELD_OFFSET_MAX-1)
20 #define FIELD_OFFSET_VALUE_CLASS      (FIELD_OFFSET_MAX-2)
21 #define FIELD_OFFSET_NOT_REAL_FIELD   (FIELD_OFFSET_MAX-3)
22
23 // Offset to indicate an EnC added field. They don't have offsets as aren't placed in the object.
24 #define FIELD_OFFSET_NEW_ENC          (FIELD_OFFSET_MAX-4)
25 #define FIELD_OFFSET_BIG_RVA          (FIELD_OFFSET_MAX-5)
26 #define FIELD_OFFSET_LAST_REAL_OFFSET (FIELD_OFFSET_MAX-6)    // real fields have to be smaller than this
27
28
29 //
30 // This describes a field - one of this is allocated for every field, so don't make this structure any larger.
31 //
32 // @GENERICS: 
33 // Field descriptors for fields in instantiated types may be shared between compatible instantiations
34 // Hence for reflection it's necessary to pair a field desc with the exact owning type handle
35 class FieldDesc
36 {
37     friend class MethodTableBuilder;
38 #ifdef DACCESS_COMPILE
39     friend class NativeImageDumper;
40 #endif
41
42   protected:
43     RelativePointer<PTR_MethodTable> m_pMTOfEnclosingClass;  // This is used to hold the log2 of the field size temporarily during class loading.  Yuck.
44
45     // See also: FieldDesc::InitializeFrom method
46
47 #if defined(DACCESS_COMPILE)
48     union { //create a union so I can get the correct offset for ClrDump.
49         unsigned m_dword1;
50         struct {
51 #endif
52         // Note that we may store other information in the high bits if available --
53         // see enum_packedMBLayout and m_requiresFullMbValue for details.
54         unsigned m_mb               : 24;
55
56         // 8 bits...
57         unsigned m_isStatic         : 1;
58         unsigned m_isThreadLocal    : 1;
59         unsigned m_isRVA            : 1;
60         unsigned m_prot             : 3;
61         // Does this field's mb require all 24 bits
62         unsigned m_requiresFullMbValue : 1;
63 #if defined(DACCESS_COMPILE)
64         };
65     };
66 #endif
67
68 #if defined(DACCESS_COMPILE)
69     union { //create a union so I can get the correct offset for ClrDump
70         unsigned m_dword2;
71         struct {
72 #endif
73         // Note: this has been as low as 22 bits in the past & seemed to be OK.
74         // we can steal some more bits here if we need them.
75         unsigned m_dwOffset         : 27;
76         unsigned m_type             : 5;
77 #if defined(DACCESS_COMPILE)
78         };
79     };
80 #endif
81
82 #ifdef _DEBUG
83     LPUTF8 m_debugName;
84 #endif
85
86 public:
87     // Allocated by special heap means, don't construct me
88     FieldDesc() =delete;
89
90 #ifndef DACCESS_COMPILE
91     void InitializeFrom(const FieldDesc& sourceField, MethodTable *pMT)
92     {
93         m_pMTOfEnclosingClass.SetValue(pMT);
94
95         m_mb = sourceField.m_mb;
96         m_isStatic = sourceField.m_isStatic;
97         m_isThreadLocal = sourceField.m_isThreadLocal;
98         m_isRVA = sourceField.m_isRVA;
99         m_prot = sourceField.m_prot;
100         m_requiresFullMbValue = sourceField.m_requiresFullMbValue;
101
102         m_dwOffset = sourceField.m_dwOffset;
103         m_type = sourceField.m_type;
104
105 #ifdef _DEBUG
106         m_debugName = sourceField.m_debugName;
107 #endif // _DEBUG
108     }
109 #endif // !DACCESS_COMPILE
110
111 #ifdef _DEBUG
112     inline LPUTF8 GetDebugName()
113     {
114         LIMITED_METHOD_CONTRACT;
115         return m_debugName;
116     }
117 #endif // _DEBUG
118     
119 #ifndef DACCESS_COMPILE
120     // This should be called.  It was added so that Reflection
121     // can create FieldDesc's for the static primitive fields that aren't
122     // stored with the EEClass.
123     void SetMethodTable(MethodTable* mt)
124     {
125         LIMITED_METHOD_CONTRACT;
126         m_pMTOfEnclosingClass.SetValue(mt);
127     }
128 #endif
129
130     VOID Init(mdFieldDef mb, 
131               CorElementType FieldType, 
132               DWORD dwMemberAttrs, 
133               BOOL fIsStatic, 
134               BOOL fIsRVA, 
135               BOOL fIsThreadLocal, 
136               LPCSTR pszFieldName);
137
138     enum {
139         enum_packedMbLayout_MbMask        = 0x01FFFF,
140         enum_packedMbLayout_NameHashMask  = 0xFE0000
141     };
142
143     void SetMemberDef(mdFieldDef mb)
144     {
145         WRAPPER_NO_CONTRACT;
146
147         // Check if we have to avoid using the packed mb layout
148         if (RidFromToken(mb) > enum_packedMbLayout_MbMask)
149         {
150             m_requiresFullMbValue = 1;
151         }
152
153         // Set only the portion of m_mb we are using
154         if (!m_requiresFullMbValue)
155         {
156             m_mb &= ~enum_packedMbLayout_MbMask;
157             m_mb |= RidFromToken(mb);
158         }
159         else
160         {
161             m_mb = RidFromToken(mb);
162         }
163     }
164
165     mdFieldDef GetMemberDef() const
166     {
167         LIMITED_METHOD_DAC_CONTRACT;
168
169         // Check if this FieldDesc is using the packed mb layout
170         if (!m_requiresFullMbValue)
171         {
172             return TokenFromRid(m_mb & enum_packedMbLayout_MbMask, mdtFieldDef);
173         }
174         
175         return TokenFromRid(m_mb, mdtFieldDef);
176     }
177
178     CorElementType GetFieldType()
179     {
180         LIMITED_METHOD_DAC_CONTRACT;
181
182         // Set in code:FieldDesc.Init which in turn is called from
183         // code:MethodTableBuilder.InitializeFieldDescs#InitCall which in turn calls
184         // code:MethodTableBuilder.InitializeFieldDescs#FieldDescTypeMorph
185         return (CorElementType) m_type;
186     }
187
188     DWORD GetFieldProtection()
189     {
190         LIMITED_METHOD_CONTRACT;
191
192         // Set in code:FieldDesc.Init which in turn is called from code:MethodTableBuilder::InitializeFieldDescs#InitCall
193         return m_prot;
194     }
195
196         // Please only use this in a path that you have already guarenteed
197         // the assert is true
198     DWORD GetOffsetUnsafe()
199     {
200         LIMITED_METHOD_CONTRACT;
201
202         g_IBCLogger.LogFieldDescsAccess(this);
203         _ASSERTE(m_dwOffset <= FIELD_OFFSET_LAST_REAL_OFFSET);
204         return m_dwOffset;
205     }
206
207     DWORD GetOffset()
208     {
209         LIMITED_METHOD_DAC_CONTRACT;
210         g_IBCLogger.LogFieldDescsAccess(this);
211         return GetOffset_NoLogging();
212     }
213
214     // During class load m_pMTOfEnclosingClass has the field size in it, so it has to use this version of
215     // GetOffset during that time
216     DWORD GetOffset_NoLogging()
217     {
218         LIMITED_METHOD_DAC_CONTRACT;
219
220         // Note FieldDescs are no longer on "hot" paths so the optimized code here
221         // does not look necessary.
222
223         if (m_dwOffset != FIELD_OFFSET_BIG_RVA) {
224             // Assert that the big RVA case handling doesn't get out of sync
225             // with the normal RVA case.
226 #ifdef _DEBUG
227             // The OutOfLine_BigRVAOffset() can't be correctly evaluated during the time
228             // that we repurposed m_pMTOfEnclosingClass for holding the field size
229             // I don't see any good way to determine when this is so hurray for
230             // heuristics!
231             //
232             // As of 4/11/2012 I could repro this by turning on the COMPLUS log and
233             // the LOG() at line methodtablebuilder.cpp:7845 
234             // MethodTableBuilder::PlaceRegularStaticFields() calls GetOffset_NoLogging()
235             if((DWORD)(DWORD_PTR&)m_pMTOfEnclosingClass > 16)
236             {
237                 _ASSERTE(!this->IsRVA() || (m_dwOffset == OutOfLine_BigRVAOffset()));
238             }
239 #endif
240             return m_dwOffset;
241         }
242
243         return OutOfLine_BigRVAOffset();
244     }
245
246     DWORD OutOfLine_BigRVAOffset()
247     {
248         LIMITED_METHOD_DAC_CONTRACT;
249
250         DWORD   rva;
251
252         // <NICE>I'm discarding a potential error here.  According to the code in MDInternalRO.cpp,
253         // we won't get an error if we initially found the RVA.  So I'm going to just
254         // assert it never happens.
255         //
256         // This is a small sin, but I don't see a good alternative. --cwb.</NICE>
257         HRESULT hr;
258         hr = GetMDImport()->GetFieldRVA(GetMemberDef(), &rva); 
259         _ASSERTE(SUCCEEDED(hr));
260         return rva;
261     }
262
263     HRESULT SetOffset(DWORD dwOffset)
264     {
265         LIMITED_METHOD_CONTRACT;
266
267         //
268         // value class fields must be aligned to pointer-sized boundaries
269         //
270         //
271         // This is commented out because it isn't valid in all cases.
272         // This is still here because it is useful for finding alignment
273         // problems on IA64.
274         //
275         //_ASSERTE((dwOffset > FIELD_OFFSET_LAST_REAL_OFFSET)  ||
276         //         (ELEMENT_TYPE_VALUETYPE != GetFieldType()) ||
277         //         (IS_ALIGNED(dwOffset, sizeof(void*))));
278
279         m_dwOffset = dwOffset;
280         return((dwOffset > FIELD_OFFSET_LAST_REAL_OFFSET) ? COR_E_TYPELOAD : S_OK);
281     }
282
283     // Okay, we've stolen too many bits from FieldDescs.  In the RVA case, there's no
284     // reason to believe they will be limited to 22 bits.  So use a sentinel for the
285     // huge cases, and recover them from metadata on-demand.
286     void SetOffsetRVA(DWORD dwOffset)
287     {
288         LIMITED_METHOD_CONTRACT;
289
290         m_dwOffset = (dwOffset > FIELD_OFFSET_LAST_REAL_OFFSET)
291                       ? FIELD_OFFSET_BIG_RVA
292                       : dwOffset;
293     }
294
295     DWORD   IsStatic() const
296     {
297         LIMITED_METHOD_DAC_CONTRACT;
298
299         return m_isStatic;
300     }
301
302     BOOL   IsSpecialStatic()
303     {
304         LIMITED_METHOD_CONTRACT;
305
306         return m_isStatic && (m_isRVA || m_isThreadLocal
307             );
308     }
309
310     BOOL   IsRVA() const               // Has an explicit RVA associated with it
311     { 
312         LIMITED_METHOD_DAC_CONTRACT;
313
314         return m_isRVA;
315     }
316
317     BOOL   IsThreadStatic() const      // Static relative to a thread
318     {
319         LIMITED_METHOD_DAC_CONTRACT;
320
321         return m_isThreadLocal;
322     }
323
324     // Indicate that this field was added by EnC
325     // Must only be called on instances of EnCFieldDesc
326     void SetEnCNew() 
327     {
328         WRAPPER_NO_CONTRACT;
329
330         // EnC added fields don't live in the actual object, so don't have a real offset
331         SetOffset(FIELD_OFFSET_NEW_ENC);
332     }
333
334     // Was this field added by EnC?
335     // If this is true, then this object is an instance of EnCFieldDesc
336     BOOL IsEnCNew() 
337     {
338         LIMITED_METHOD_DAC_CONTRACT;
339
340         // EnC added fields don't have a real offset
341         return m_dwOffset == FIELD_OFFSET_NEW_ENC;
342     }
343
344     BOOL IsByValue()
345     {
346         LIMITED_METHOD_DAC_CONTRACT;
347
348         return GetFieldType() == ELEMENT_TYPE_VALUETYPE;
349     }
350
351     BOOL IsPrimitive()
352     {
353         LIMITED_METHOD_DAC_CONTRACT;
354
355         return (CorIsPrimitiveType(GetFieldType()) != FALSE);
356     }
357
358     BOOL IsObjRef();
359
360 #ifdef FEATURE_PREJIT
361     void SaveContents(DataImage *image);
362     void Fixup(DataImage *image);
363 #endif // FEATURE_PREJIT
364
365     UINT LoadSize();
366
367     // Return -1 if the type isn't loaded yet (i.e. if LookupFieldTypeHandle() would return null)
368     UINT GetSize();
369
370     // These routines encapsulate the operation of getting and setting
371     // fields.
372     void    GetInstanceField(OBJECTREF o, VOID * pOutVal);
373     void    SetInstanceField(OBJECTREF o, const VOID * pInVal);
374
375     void*   GetInstanceAddress(OBJECTREF o);
376
377         // Get the address of a field within object 'o'
378     PTR_VOID   GetAddress(PTR_VOID o);
379
380     PTR_VOID GetAddressNoThrowNoGC(PTR_VOID o);
381     void*   GetAddressGuaranteedInHeap(void *o);
382
383     void*   GetValuePtr(OBJECTREF o);
384     VOID    SetValuePtr(OBJECTREF o, void* pValue);
385     DWORD   GetValue32(OBJECTREF o);
386     VOID    SetValue32(OBJECTREF o, DWORD dwValue);
387     OBJECTREF GetRefValue(OBJECTREF o);
388     VOID    SetRefValue(OBJECTREF o, OBJECTREF orValue);
389     USHORT  GetValue16(OBJECTREF o);
390     VOID    SetValue16(OBJECTREF o, DWORD dwValue);  
391     BYTE    GetValue8(OBJECTREF o);               
392     VOID    SetValue8(OBJECTREF o, DWORD dwValue);  
393     __int64 GetValue64(OBJECTREF o);               
394     VOID    SetValue64(OBJECTREF o, __int64 value);  
395
396     PTR_MethodTable GetApproxEnclosingMethodTable_NoLogging()
397     {
398         LIMITED_METHOD_DAC_CONTRACT;
399         return m_pMTOfEnclosingClass.GetValue(PTR_HOST_MEMBER_TADDR(FieldDesc, this, m_pMTOfEnclosingClass));
400     }
401
402     PTR_MethodTable GetApproxEnclosingMethodTable()
403     {
404         LIMITED_METHOD_DAC_CONTRACT;
405         g_IBCLogger.LogFieldDescsAccess(this);
406         return GetApproxEnclosingMethodTable_NoLogging();
407     }
408
409     PTR_MethodTable GetEnclosingMethodTable()
410     {
411         LIMITED_METHOD_DAC_CONTRACT;
412         _ASSERTE(!IsSharedByGenericInstantiations());
413         return GetApproxEnclosingMethodTable();
414     }
415
416     // FieldDesc can be shared between generic instantiations. So List<String>._items
417     // is really the  same as List<__Canon>._items. Hence, the FieldDesc itself
418     // cannot know the exact enclosing type. You need to provide the exact owner
419     // like List<String> or a subtype like MyInheritedList<String>.
420     MethodTable * GetExactDeclaringType(MethodTable * ownerOrSubType);
421
422     BOOL IsSharedByGenericInstantiations()
423     {
424         LIMITED_METHOD_DAC_CONTRACT;
425         return (!IsStatic()) && GetApproxEnclosingMethodTable()->IsSharedByGenericInstantiations();
426     }
427
428     BOOL IsFieldOfValueType()
429     {
430         WRAPPER_NO_CONTRACT;
431         return GetApproxEnclosingMethodTable()->IsValueType();
432     }
433
434     DWORD GetNumGenericClassArgs()
435     {
436         WRAPPER_NO_CONTRACT;
437         return GetApproxEnclosingMethodTable()->GetNumGenericArgs();
438     }
439
440    PTR_BYTE GetBaseInDomainLocalModule(DomainLocalModule * pLocalModule)
441     {
442         WRAPPER_NO_CONTRACT;
443
444         if (GetFieldType() == ELEMENT_TYPE_CLASS || GetFieldType() == ELEMENT_TYPE_VALUETYPE)
445         {
446             return pLocalModule->GetGCStaticsBasePointer(GetEnclosingMethodTable());
447         }
448         else
449         {
450             return pLocalModule->GetNonGCStaticsBasePointer(GetEnclosingMethodTable());
451         }
452     }
453
454 #ifndef DACCESS_COMPILE
455     PTR_BYTE GetBase()
456     {
457         CONTRACTL
458         {
459           THROWS;
460           GC_TRIGGERS;
461           INJECT_FAULT(COMPlusThrowOM());
462         }
463         CONTRACTL_END
464
465         MethodTable *pMT = GetEnclosingMethodTable();
466
467         return GetBaseInDomainLocalModule(pMT->GetDomainLocalModule());
468     }
469
470 #endif //!DACCESS_COMPILE
471
472     PTR_BYTE GetBaseInDomain(AppDomain * appDomain)
473     {
474         CONTRACTL
475         {
476             NOTHROW;
477             GC_NOTRIGGER;
478         }
479         CONTRACTL_END;
480
481         Module *pModule = GetEnclosingMethodTable()->GetModuleForStatics();
482         if (pModule == NULL)
483             return NULL;
484
485         DomainLocalModule *pLocalModule = pModule->GetDomainLocalModule(appDomain);
486         if (pLocalModule == NULL)
487             return NULL;
488
489         return GetBaseInDomainLocalModule(pLocalModule);
490     }
491
492     // returns the address of the field
493     void* GetStaticAddress(void *base);
494
495     // In all cases except Value classes, the AddressHandle is
496     // simply the address of the static.  For the case of value
497     // types, however, it is the address of OBJECTREF that holds
498     // the boxed value used to hold the value type.  This is needed
499     // because the OBJECTREF moves, and the JIT needs to embed something
500     // in the code that does not move.  Thus the jit has to 
501     // dereference and unbox before the access.  
502     PTR_VOID GetStaticAddressHandle(PTR_VOID base);
503
504 #ifndef DACCESS_COMPILE
505     OBJECTREF GetStaticOBJECTREF()
506     {
507         WRAPPER_NO_CONTRACT;
508         return *(OBJECTREF *)GetCurrentStaticAddress();
509     }
510
511     VOID SetStaticOBJECTREF(OBJECTREF objRef)
512     {
513         CONTRACTL
514         {
515             THROWS;
516             GC_TRIGGERS;
517             MODE_COOPERATIVE;
518             INJECT_FAULT(COMPlusThrowOM());
519         }
520         CONTRACTL_END
521
522         GCPROTECT_BEGIN(objRef);
523         OBJECTREF *pObjRef = (OBJECTREF *)GetCurrentStaticAddress();
524         SetObjectReference(pObjRef, objRef);
525         GCPROTECT_END();
526     }
527
528     void*   GetStaticValuePtr()
529     {
530         WRAPPER_NO_CONTRACT;
531         return *(void**)GetCurrentStaticAddress();
532     }
533
534     VOID    SetStaticValuePtr(void *value)
535     {
536         WRAPPER_NO_CONTRACT;
537         *(void**)GetCurrentStaticAddress() = value;
538     }
539
540     DWORD   GetStaticValue32()
541     {
542         WRAPPER_NO_CONTRACT;
543         return *(DWORD*)GetCurrentStaticAddress(); 
544     }
545
546     VOID    SetStaticValue32(DWORD dwValue)  
547     { 
548         WRAPPER_NO_CONTRACT;
549         *(DWORD*)GetCurrentStaticAddress() = dwValue; 
550     }
551
552     USHORT  GetStaticValue16()
553     {
554         WRAPPER_NO_CONTRACT;
555         return *(USHORT*)GetCurrentStaticAddress(); 
556     }
557
558     VOID    SetStaticValue16(DWORD dwValue)
559     { 
560         WRAPPER_NO_CONTRACT;
561         *(USHORT*)GetCurrentStaticAddress() = (USHORT)dwValue; 
562     }
563
564     BYTE    GetStaticValue8()
565     {
566         WRAPPER_NO_CONTRACT;
567         return *(BYTE*)GetCurrentStaticAddress(); 
568     }
569
570     VOID    SetStaticValue8(DWORD dwValue)
571     {
572         WRAPPER_NO_CONTRACT;
573         *(BYTE*)GetCurrentStaticAddress() = (BYTE)dwValue; 
574     }
575
576     __int64 GetStaticValue64()
577     { 
578         WRAPPER_NO_CONTRACT;
579         return *(__int64*)GetCurrentStaticAddress();
580     }
581
582     VOID    SetStaticValue64(__int64 qwValue)
583     {
584         WRAPPER_NO_CONTRACT;
585         *(__int64*)GetCurrentStaticAddress() = qwValue;
586     }
587
588     void* GetCurrentStaticAddress()
589     {
590         CONTRACTL
591         {
592             THROWS;
593             GC_TRIGGERS;
594             MODE_COOPERATIVE;
595             INJECT_FAULT(COMPlusThrowOM());
596         }
597         CONTRACTL_END
598
599         _ASSERTE(IsStatic());
600
601         if (IsThreadStatic()) 
602         {
603             return Thread::GetStaticFieldAddress(this);
604         }
605         else {
606             PTR_BYTE base = 0;
607             if (!IsRVA()) // for RVA the base is ignored
608                 base = GetBase();
609             return GetStaticAddress((void *)dac_cast<TADDR>(base)); 
610         }
611     }
612
613     VOID    CheckRunClassInitThrowing()
614     {
615         CONTRACTL
616         {
617             THROWS;
618             GC_TRIGGERS;
619             INJECT_FAULT(COMPlusThrowOM());
620         }
621         CONTRACTL_END;
622
623         GetEnclosingMethodTable()->CheckRunClassInitThrowing();
624     }
625 #endif //DACCESS_COMPILE
626
627     Module *GetModule()
628     {
629         LIMITED_METHOD_DAC_CONTRACT;
630
631         return GetApproxEnclosingMethodTable()->GetModule();
632     }
633
634     BOOL IsZapped()
635     {
636         WRAPPER_NO_CONTRACT;
637
638         // Field Desc's are currently always saved into the same module as their 
639         // corresponding method table.
640         return GetApproxEnclosingMethodTable()->IsZapped();
641     }
642
643     Module *GetLoaderModule()
644     {
645         WRAPPER_NO_CONTRACT;
646
647         // Field Desc's are currently always saved into the same module as their 
648         // corresponding method table.
649         return GetApproxEnclosingMethodTable()->GetLoaderModule();
650     }
651
652     void GetSig(PCCOR_SIGNATURE *ppSig, DWORD *pcSig)
653     {
654         CONTRACTL
655         {
656           NOTHROW;
657           GC_NOTRIGGER;
658           MODE_ANY;
659         }
660         CONTRACTL_END
661
662         if (FAILED(GetMDImport()->GetSigOfFieldDef(GetMemberDef(), pcSig, ppSig)))
663         {   // Class loader already asked for signature, so this should always succeed (unless there's a 
664             // bug or a new code path)
665             _ASSERTE(!"If this ever fires, then this method should return HRESULT");
666             *ppSig = NULL;
667             *pcSig = 0;
668         }
669     }
670
671     SigPointer GetSigPointer()
672     {
673         WRAPPER_NO_CONTRACT;
674
675         PCCOR_SIGNATURE pSig;
676         DWORD           cSig;
677
678         GetSig(&pSig, &cSig);
679
680         return SigPointer(pSig, cSig);
681     }
682
683     // This is slow (uses MetaData), don't use it!
684     LPCUTF8 GetName()
685     {
686         CONTRACTL
687         {
688           THROWS;
689           GC_NOTRIGGER;
690           MODE_ANY;
691         }
692         CONTRACTL_END
693         
694         LPCSTR szName;
695         IfFailThrow(GetMDImport()->GetNameOfFieldDef(GetMemberDef(), &szName));
696         _ASSERTE(szName != NULL);
697         return szName;
698     }
699     // This is slow (uses MetaData), don't use it!
700     __checkReturn 
701     HRESULT GetName_NoThrow(LPCUTF8 *pszName)
702     {
703         CONTRACTL
704         {
705           NOTHROW;
706           GC_NOTRIGGER;
707           MODE_ANY;
708         }
709         CONTRACTL_END
710         
711         return GetMDImport()->GetNameOfFieldDef(GetMemberDef(), pszName);
712     }
713     
714     void PrecomputeNameHash();
715     BOOL MightHaveName(ULONG nameHashValue);
716
717     // <TODO>@TODO: </TODO>This is slow, don't use it!
718     DWORD   GetAttributes()
719     {
720         CONTRACTL
721         {
722           NOTHROW;
723           GC_NOTRIGGER;
724           MODE_ANY;
725         }
726         CONTRACTL_END
727
728         DWORD dwAttributes;
729         if (FAILED(GetMDImport()->GetFieldDefProps(GetMemberDef(), &dwAttributes)))
730         {   // Class loader already asked for attributes, so this should always succeed (unless there's a 
731             // bug or a new code path)
732             _ASSERTE(!"If this ever fires, then this method should return HRESULT");
733             return 0;
734         }
735         return dwAttributes;
736     }
737     
738     // Mini-Helpers
739     DWORD   IsPublic()
740     {
741         WRAPPER_NO_CONTRACT;
742
743         return IsFdPublic(GetFieldProtection());
744     }
745
746     DWORD   IsProtected()
747     {
748         WRAPPER_NO_CONTRACT;
749         return IsFdFamily(GetFieldProtection());
750     }
751
752     DWORD   IsPrivate()
753     {
754         WRAPPER_NO_CONTRACT;
755
756         return IsFdPrivate(GetFieldProtection());
757     }
758
759     IMDInternalImport *GetMDImport()
760     {
761         LIMITED_METHOD_DAC_CONTRACT;
762
763         return GetModule()->GetMDImport();
764     }
765
766 #ifndef DACCESS_COMPILE
767     IMetaDataImport *GetRWImporter()
768     {
769         WRAPPER_NO_CONTRACT;
770
771         return GetModule()->GetRWImporter();
772     }
773 #endif // DACCESS_COMPILE
774
775     TypeHandle LookupFieldTypeHandle(ClassLoadLevel level = CLASS_LOADED, BOOL dropGenericArgumentLevel = FALSE);
776
777     TypeHandle LookupApproxFieldTypeHandle()
778     {
779         WRAPPER_NO_CONTRACT;
780         return LookupFieldTypeHandle(CLASS_LOAD_APPROXPARENTS, TRUE);
781     }
782
783     // Instance FieldDesc can be shared between generic instantiations. So List<String>._items
784     // is really the  same as List<__Canon>._items. Hence, the FieldDesc itself
785     // cannot know the exact field type. This function returns the approximate field type.
786     // For eg. this will return "__Canon[]" for List<String>._items.
787     TypeHandle GetFieldTypeHandleThrowing(ClassLoadLevel level = CLASS_LOADED, BOOL dropGenericArgumentLevel = FALSE);
788
789     TypeHandle GetApproxFieldTypeHandleThrowing()
790     {
791         WRAPPER_NO_CONTRACT;
792         return GetFieldTypeHandleThrowing(CLASS_LOAD_APPROXPARENTS, TRUE);
793     }
794
795     // Given a type handle of an object and a method that comes from some 
796     // superclass of the class of that object, find the instantiation of 
797     // that superclass, i.e. the class instantiation which will be relevant
798     // to interpreting the signature of the method.  The type handle of
799     // the object does not need to be given in all circumstances, in 
800     // particular it is only needed for FieldDescs pFD that
801     // return true for pFD->GetApproxEnclosingMethodTable()->IsSharedByGenericInstantiations().
802     // In other cases it is allowed to be null and will be ignored.
803     // 
804     // Will return NULL if the field is not in a generic class.
805     Instantiation GetExactClassInstantiation(TypeHandle possibleObjType);
806
807     // Instance FieldDesc can be shared between generic instantiations. So List<String>._items
808     // is really the  same as List<__Canon>._items. Hence, the FieldDesc itself
809     // cannot know the exact field type. You need to specify the owner
810     // like List<String> in order to get the exact type which would be "String[]"
811     TypeHandle GetExactFieldType(TypeHandle owner);
812
813 #ifdef DACCESS_COMPILE
814     void EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
815     {
816         SUPPORTS_DAC;
817         DAC_ENUM_DTHIS();
818     }
819 #endif
820
821 #ifndef DACCESS_COMPILE
822     REFLECTFIELDREF GetStubFieldInfo();
823 #endif
824 };
825
826 #endif // _FIELD_H_
827