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// OBJECT.H
6//
7// Definitions of a Com+ Object
8//
9
10// See code:EEStartup#TableOfContents for overview
11
12
13#ifndef _OBJECT_H_
14#define _OBJECT_H_
15
16#include "util.hpp"
17#include "syncblk.h"
18#include "gcdesc.h"
19#include "specialstatics.h"
20#include "sstring.h"
21#include "daccess.h"
22#include "fcall.h"
23
24extern "C" void __fastcall ZeroMemoryInGCHeap(void*, size_t);
25
26void ErectWriteBarrierForMT(MethodTable **dst, MethodTable *ref);
27
28/*
29 #ObjectModel
30 * COM+ Internal Object Model
31 *
32 *
33 * Object - This is the common base part to all COM+ objects
34 * | it contains the MethodTable pointer and the
35 * | sync block index, which is at a negative offset
36 * |
37 * +-- code:StringObject - String objects are specialized objects for string
38 * | storage/retrieval for higher performance
39 * |
40 * +-- BaseObjectWithCachedData - Object Plus one object field for caching.
41 * | |
42 * | +- ReflectClassBaseObject - The base object for the RuntimeType class
43 * | +- ReflectMethodObject - The base object for the RuntimeMethodInfo class
44 * | +- ReflectFieldObject - The base object for the RtFieldInfo class
45 * |
46 * +-- code:ArrayBase - Base portion of all arrays
47 * | |
48 * | +- I1Array - Base type arrays
49 * | | I2Array
50 * | | ...
51 * | |
52 * | +- PtrArray - Array of OBJECTREFs, different than base arrays because of pObjectClass
53 * |
54 * +-- code:AssemblyBaseObject - The base object for the class Assembly
55 *
56 *
57 * PLEASE NOTE THE FOLLOWING WHEN ADDING A NEW OBJECT TYPE:
58 *
59 * The size of the object in the heap must be able to be computed
60 * very, very quickly for GC purposes. Restrictions on the layout
61 * of the object guarantee this is possible.
62 *
63 * Any object that inherits from Object must be able to
64 * compute its complete size by using the first 4 bytes of
65 * the object following the Object part and constants
66 * reachable from the MethodTable...
67 *
68 * The formula used for this calculation is:
69 * MT->GetBaseSize() + ((OBJECTTYPEREF->GetSizeField() * MT->GetComponentSize())
70 *
71 * So for Object, since this is of fixed size, the ComponentSize is 0, which makes the right side
72 * of the equation above equal to 0 no matter what the value of GetSizeField(), so the size is just the base size.
73 *
74 */
75
76// <TODO>
77// @TODO: #define COW 0x04
78// @TODO: MOO, MOO - no, not bovine, really Copy On Write bit for StringBuffer, requires 8 byte align MT
79// @TODL: which we don't have yet</TODO>
80
81class MethodTable;
82class Thread;
83class BaseDomain;
84class Assembly;
85class DomainAssembly;
86class AssemblyNative;
87class WaitHandleNative;
88class ArgDestination;
89
90struct RCW;
91
92#ifdef _TARGET_64BIT_
93#define OBJHEADER_SIZE (sizeof(DWORD) /* m_alignpad */ + sizeof(DWORD) /* m_SyncBlockValue */)
94#else
95#define OBJHEADER_SIZE sizeof(DWORD) /* m_SyncBlockValue */
96#endif
97
98#define OBJECT_SIZE TARGET_POINTER_SIZE /* m_pMethTab */
99#define OBJECT_BASESIZE (OBJHEADER_SIZE + OBJECT_SIZE)
100
101#ifdef _TARGET_64BIT_
102#define ARRAYBASE_SIZE (OBJECT_SIZE /* m_pMethTab */ + sizeof(DWORD) /* m_NumComponents */ + sizeof(DWORD) /* pad */)
103#else
104#define ARRAYBASE_SIZE (OBJECT_SIZE /* m_pMethTab */ + sizeof(DWORD) /* m_NumComponents */)
105#endif
106
107#define ARRAYBASE_BASESIZE (OBJHEADER_SIZE + ARRAYBASE_SIZE)
108
109//
110// The generational GC requires that every object be at least 12 bytes
111// in size.
112
113#define MIN_OBJECT_SIZE (2*TARGET_POINTER_SIZE + OBJHEADER_SIZE)
114
115#define PTRALIGNCONST (DATA_ALIGNMENT-1)
116
117#ifndef PtrAlign
118#define PtrAlign(size) \
119 ((size + PTRALIGNCONST) & (~PTRALIGNCONST))
120#endif //!PtrAlign
121
122// code:Object is the respesentation of an managed object on the GC heap.
123//
124// See code:#ObjectModel for some important subclasses of code:Object
125//
126// The only fields mandated by all objects are
127//
128// * a pointer to the code:MethodTable at offset 0
129// * a poiner to a code:ObjHeader at a negative offset. This is often zero. It holds information that
130// any addition information that we might need to attach to arbitrary objects.
131//
132class Object
133{
134 protected:
135 PTR_MethodTable m_pMethTab;
136
137 protected:
138 Object() { LIMITED_METHOD_CONTRACT; };
139 ~Object() { LIMITED_METHOD_CONTRACT; };
140
141 public:
142 MethodTable *RawGetMethodTable() const
143 {
144 return m_pMethTab;
145 }
146
147#ifndef DACCESS_COMPILE
148 void RawSetMethodTable(MethodTable *pMT)
149 {
150 LIMITED_METHOD_CONTRACT;
151 m_pMethTab = pMT;
152 }
153
154 VOID SetMethodTable(MethodTable *pMT
155 DEBUG_ARG(BOOL bAllowArray = FALSE))
156 {
157 LIMITED_METHOD_CONTRACT;
158 m_pMethTab = pMT;
159
160#ifdef _DEBUG
161 if (!bAllowArray)
162 {
163 AssertNotArray();
164 }
165#endif // _DEBUG
166 }
167
168 VOID SetMethodTableForLargeObject(MethodTable *pMT
169 DEBUG_ARG(BOOL bAllowArray = FALSE))
170 {
171 // This function must be used if the allocation occurs on the large object heap, and the method table might be a collectible type
172 WRAPPER_NO_CONTRACT;
173 ErectWriteBarrierForMT(&m_pMethTab, pMT);
174
175#ifdef _DEBUG
176 if (!bAllowArray)
177 {
178 AssertNotArray();
179 }
180#endif // _DEBUG
181 }
182#endif //!DACCESS_COMPILE
183
184#define MARKED_BIT 0x1
185
186 PTR_MethodTable GetMethodTable() const
187 {
188 LIMITED_METHOD_DAC_CONTRACT;
189
190#ifndef DACCESS_COMPILE
191 // We should always use GetGCSafeMethodTable() if we're running during a GC.
192 // If the mark bit is set then we're running during a GC
193 _ASSERTE((dac_cast<TADDR>(m_pMethTab) & MARKED_BIT) == 0);
194
195 return m_pMethTab;
196#else //DACCESS_COMPILE
197
198 //@dbgtodo dharvey Make this a type which supports bitwise and operations
199 //when available
200 return PTR_MethodTable((dac_cast<TADDR>(m_pMethTab)) & (~MARKED_BIT));
201#endif //DACCESS_COMPILE
202 }
203
204 DPTR(PTR_MethodTable) GetMethodTablePtr() const
205 {
206 LIMITED_METHOD_CONTRACT;
207 return dac_cast<DPTR(PTR_MethodTable)>(PTR_HOST_MEMBER_TADDR(Object, this, m_pMethTab));
208 }
209
210 TypeHandle GetTypeHandle();
211 TypeHandle GetTrueTypeHandle();
212
213 // Methods used to determine if an object supports a given interface.
214 static BOOL SupportsInterface(OBJECTREF pObj, MethodTable *pInterfaceMT);
215
216 inline DWORD GetNumComponents();
217 inline SIZE_T GetSize();
218
219 CGCDesc* GetSlotMap()
220 {
221 WRAPPER_NO_CONTRACT;
222 return( CGCDesc::GetCGCDescFromMT(GetMethodTable()));
223 }
224
225 // Sync Block & Synchronization services
226
227 // Access the ObjHeader which is at a negative offset on the object (because of
228 // cache lines)
229 PTR_ObjHeader GetHeader()
230 {
231 LIMITED_METHOD_DAC_CONTRACT;
232 return dac_cast<PTR_ObjHeader>(this) - 1;
233 }
234
235 // Get the current address of the object (works for debug refs, too.)
236 PTR_BYTE GetAddress()
237 {
238 LIMITED_METHOD_DAC_CONTRACT;
239 return dac_cast<PTR_BYTE>(this);
240 }
241
242#ifdef _DEBUG
243 // TRUE if the header has a real SyncBlockIndex (i.e. it has an entry in the
244 // SyncTable, though it doesn't necessarily have an entry in the SyncBlockCache)
245 BOOL HasEmptySyncBlockInfo()
246 {
247 WRAPPER_NO_CONTRACT;
248 return GetHeader()->HasEmptySyncBlockInfo();
249 }
250#endif
251
252 // retrieve or allocate a sync block for this object
253 SyncBlock *GetSyncBlock()
254 {
255 WRAPPER_NO_CONTRACT;
256 return GetHeader()->GetSyncBlock();
257 }
258
259 DWORD GetSyncBlockIndex()
260 {
261 WRAPPER_NO_CONTRACT;
262 return GetHeader()->GetSyncBlockIndex();
263 }
264
265 ADIndex GetAppDomainIndex();
266
267 // Get app domain of object, or NULL if it is agile
268 AppDomain *GetAppDomain();
269
270#ifndef DACCESS_COMPILE
271 // Set app domain of object to current domain.
272 void SetAppDomain() { WRAPPER_NO_CONTRACT; SetAppDomain(::GetAppDomain()); }
273 BOOL SetAppDomainNoThrow();
274
275#endif
276
277 // Set app domain of object to given domain - it can only be set once
278 void SetAppDomain(AppDomain *pDomain);
279
280#ifdef _DEBUG
281#ifndef DACCESS_COMPILE
282 // For SO-tolerance contract violation purposes, define these DEBUG_ versions to identify
283 // the codepaths to SetAppDomain that are called only from DEBUG code.
284 void DEBUG_SetAppDomain()
285 {
286 WRAPPER_NO_CONTRACT;
287
288 DEBUG_SetAppDomain(::GetAppDomain());
289 }
290#endif //!DACCESS_COMPILE
291
292 void DEBUG_SetAppDomain(AppDomain *pDomain);
293#endif //_DEBUG
294
295 // DO NOT ADD ANY ASSERTS TO THIS METHOD.
296 // DO NOT USE THIS METHOD.
297 // Yes folks, for better or worse the debugger pokes supposed object addresses
298 // to try to see if objects are valid, possibly firing an AccessViolation or worse,
299 // and then catches the AV and reports a failure to the debug client. This makes
300 // the debugger slightly more robust should any corrupted object references appear
301 // in a session. Thus it is "correct" behaviour for this to AV when used with
302 // an invalid object pointer, and incorrect behaviour for it to
303 // assert.
304 BOOL ValidateObjectWithPossibleAV();
305
306 // Validate an object ref out of the Promote routine in the GC
307 void ValidatePromote(ScanContext *sc, DWORD flags);
308
309 // Validate an object ref out of the VerifyHeap routine in the GC
310 void ValidateHeap(Object *from, BOOL bDeep=TRUE);
311
312 PTR_SyncBlock PassiveGetSyncBlock()
313 {
314 LIMITED_METHOD_DAC_CONTRACT;
315 return GetHeader()->PassiveGetSyncBlock();
316 }
317
318 static DWORD ComputeHashCode();
319
320#ifndef DACCESS_COMPILE
321 INT32 GetHashCodeEx();
322#endif // #ifndef DACCESS_COMPILE
323
324 // Synchronization
325#ifndef DACCESS_COMPILE
326
327 void EnterObjMonitor()
328 {
329 WRAPPER_NO_CONTRACT;
330 GetHeader()->EnterObjMonitor();
331 }
332
333 BOOL TryEnterObjMonitor(INT32 timeOut = 0)
334 {
335 WRAPPER_NO_CONTRACT;
336 return GetHeader()->TryEnterObjMonitor(timeOut);
337 }
338
339 bool TryEnterObjMonitorSpinHelper();
340
341 FORCEINLINE AwareLock::EnterHelperResult EnterObjMonitorHelper(Thread* pCurThread)
342 {
343 WRAPPER_NO_CONTRACT;
344 return GetHeader()->EnterObjMonitorHelper(pCurThread);
345 }
346
347 FORCEINLINE AwareLock::EnterHelperResult EnterObjMonitorHelperSpin(Thread* pCurThread)
348 {
349 WRAPPER_NO_CONTRACT;
350 return GetHeader()->EnterObjMonitorHelperSpin(pCurThread);
351 }
352
353 BOOL LeaveObjMonitor()
354 {
355 WRAPPER_NO_CONTRACT;
356 return GetHeader()->LeaveObjMonitor();
357 }
358
359 // should be called only from unwind code; used in the
360 // case where EnterObjMonitor failed to allocate the
361 // sync-object.
362 BOOL LeaveObjMonitorAtException()
363 {
364 WRAPPER_NO_CONTRACT;
365 return GetHeader()->LeaveObjMonitorAtException();
366 }
367
368 FORCEINLINE AwareLock::LeaveHelperAction LeaveObjMonitorHelper(Thread* pCurThread)
369 {
370 WRAPPER_NO_CONTRACT;
371 return GetHeader()->LeaveObjMonitorHelper(pCurThread);
372 }
373
374 // Returns TRUE if the lock is owned and FALSE otherwise
375 // threadId is set to the ID (Thread::GetThreadId()) of the thread which owns the lock
376 // acquisitionCount is set to the number of times the lock needs to be released before
377 // it is unowned
378 BOOL GetThreadOwningMonitorLock(DWORD *pThreadId, DWORD *pAcquisitionCount)
379 {
380 WRAPPER_NO_CONTRACT;
381 SUPPORTS_DAC;
382 return GetHeader()->GetThreadOwningMonitorLock(pThreadId, pAcquisitionCount);
383 }
384
385#endif // #ifndef DACCESS_COMPILE
386
387 BOOL Wait(INT32 timeOut, BOOL exitContext)
388 {
389 WRAPPER_NO_CONTRACT;
390 return GetHeader()->Wait(timeOut, exitContext);
391 }
392
393 void Pulse()
394 {
395 WRAPPER_NO_CONTRACT;
396 GetHeader()->Pulse();
397 }
398
399 void PulseAll()
400 {
401 WRAPPER_NO_CONTRACT;
402 GetHeader()->PulseAll();
403 }
404
405 PTR_VOID UnBox(); // if it is a value class, get the pointer to the first field
406
407 PTR_BYTE GetData(void)
408 {
409 LIMITED_METHOD_CONTRACT;
410 SUPPORTS_DAC;
411 return dac_cast<PTR_BYTE>(this) + sizeof(Object);
412 }
413
414 static UINT GetOffsetOfFirstField()
415 {
416 LIMITED_METHOD_CONTRACT;
417 return sizeof(Object);
418 }
419
420 DWORD GetOffset32(DWORD dwOffset)
421 {
422 WRAPPER_NO_CONTRACT;
423 return * PTR_DWORD(GetData() + dwOffset);
424 }
425
426 USHORT GetOffset16(DWORD dwOffset)
427 {
428 WRAPPER_NO_CONTRACT;
429 return * PTR_USHORT(GetData() + dwOffset);
430 }
431
432 BYTE GetOffset8(DWORD dwOffset)
433 {
434 WRAPPER_NO_CONTRACT;
435 return * PTR_BYTE(GetData() + dwOffset);
436 }
437
438 __int64 GetOffset64(DWORD dwOffset)
439 {
440 WRAPPER_NO_CONTRACT;
441 return (__int64) * PTR_ULONG64(GetData() + dwOffset);
442 }
443
444 void *GetPtrOffset(DWORD dwOffset)
445 {
446 WRAPPER_NO_CONTRACT;
447 return (void *)(TADDR)*PTR_TADDR(GetData() + dwOffset);
448 }
449
450#ifndef DACCESS_COMPILE
451
452 void SetOffsetObjectRef(DWORD dwOffset, size_t dwValue);
453
454 void SetOffsetPtr(DWORD dwOffset, LPVOID value)
455 {
456 WRAPPER_NO_CONTRACT;
457 *(LPVOID *) &GetData()[dwOffset] = value;
458 }
459
460 void SetOffset32(DWORD dwOffset, DWORD dwValue)
461 {
462 WRAPPER_NO_CONTRACT;
463 *(DWORD *) &GetData()[dwOffset] = dwValue;
464 }
465
466 void SetOffset16(DWORD dwOffset, DWORD dwValue)
467 {
468 WRAPPER_NO_CONTRACT;
469 *(USHORT *) &GetData()[dwOffset] = (USHORT) dwValue;
470 }
471
472 void SetOffset8(DWORD dwOffset, DWORD dwValue)
473 {
474 WRAPPER_NO_CONTRACT;
475 *(BYTE *) &GetData()[dwOffset] = (BYTE) dwValue;
476 }
477
478 void SetOffset64(DWORD dwOffset, __int64 qwValue)
479 {
480 WRAPPER_NO_CONTRACT;
481 *(__int64 *) &GetData()[dwOffset] = qwValue;
482 }
483
484#endif // #ifndef DACCESS_COMPILE
485
486 VOID Validate(BOOL bDeep = TRUE, BOOL bVerifyNextHeader = TRUE, BOOL bVerifySyncBlock = TRUE);
487
488 PTR_MethodTable GetGCSafeMethodTable() const
489 {
490 LIMITED_METHOD_CONTRACT;
491 SUPPORTS_DAC;
492
493 // lose GC marking bit and the reserved bit
494 // A method table pointer should always be aligned. During GC we set the least
495 // significant bit for marked objects, and the second to least significant
496 // bit is reserved. So if we want the actual MT pointer during a GC
497 // we must zero out the lowest 2 bits.
498 return dac_cast<PTR_MethodTable>((dac_cast<TADDR>(m_pMethTab)) & ~((UINT_PTR)3));
499 }
500
501 // There are some cases where it is unsafe to get the type handle during a GC.
502 // This occurs when the type has already been unloaded as part of an in-progress appdomain shutdown.
503 TypeHandle GetGCSafeTypeHandleIfPossible() const;
504
505 inline TypeHandle GetGCSafeTypeHandle() const;
506
507#ifdef DACCESS_COMPILE
508 void EnumMemoryRegions(void);
509#endif
510
511 private:
512 VOID ValidateInner(BOOL bDeep, BOOL bVerifyNextHeader, BOOL bVerifySyncBlock);
513
514#ifdef _DEBUG
515 void AssertNotArray()
516 {
517 if (m_pMethTab->IsArray())
518 {
519 _ASSERTE(!"ArrayBase::SetArrayMethodTable/ArrayBase::SetArrayMethodTableForLargeObject should be used for arrays");
520 }
521 }
522#endif // _DEBUG
523};
524
525/*
526 * Object ref setting routines. You must use these to do
527 * proper write barrier support, as well as app domain
528 * leak checking.
529 *
530 * Note that the AppDomain parameter is the app domain affinity
531 * of the object containing the field or value class. It should
532 * be NULL if the containing object is app domain agile. Note that
533 * you typically get this value by calling obj->GetAppDomain() on
534 * the containing object.
535 */
536
537// SetObjectReference sets an OBJECTREF field
538
539void SetObjectReferenceUnchecked(OBJECTREF *dst,OBJECTREF ref);
540
541#ifdef _DEBUG
542void EnableStressHeapHelper();
543#endif
544
545//Used to clear the object reference
546inline void ClearObjectReference(OBJECTREF* dst)
547{
548 LIMITED_METHOD_CONTRACT;
549 *(void**)(dst) = NULL;
550}
551
552// CopyValueClass sets a value class field
553
554void STDCALL CopyValueClassUnchecked(void* dest, void* src, MethodTable *pMT);
555void STDCALL CopyValueClassArgUnchecked(ArgDestination *argDest, void* src, MethodTable *pMT, int destOffset);
556
557inline void InitValueClass(void *dest, MethodTable *pMT)
558{
559 WRAPPER_NO_CONTRACT;
560 ZeroMemoryInGCHeap(dest, pMT->GetNumInstanceFieldBytes());
561}
562
563// Initialize value class argument
564void InitValueClassArg(ArgDestination *argDest, MethodTable *pMT);
565
566#define SetObjectReference(_d,_r,_a) SetObjectReferenceUnchecked(_d, _r)
567#define CopyValueClass(_d,_s,_m,_a) CopyValueClassUnchecked(_d,_s,_m)
568#define CopyValueClassArg(_d,_s,_m,_a,_o) CopyValueClassArgUnchecked(_d,_s,_m,_o)
569
570#include <pshpack4.h>
571
572
573// There are two basic kinds of array layouts in COM+
574// ELEMENT_TYPE_ARRAY - a multidimensional array with lower bounds on the dims
575// ELMENNT_TYPE_SZARRAY - A zero based single dimensional array
576//
577// In addition the layout of an array in memory is also affected by
578// whether the method table is shared (eg in the case of arrays of object refs)
579// or not. In the shared case, the array has to hold the type handle of
580// the element type.
581//
582// ArrayBase encapuslates all of these details. In theory you should never
583// have to peek inside this abstraction
584//
585class ArrayBase : public Object
586{
587 friend class GCHeap;
588 friend class CObjectHeader;
589 friend class Object;
590 friend OBJECTREF AllocateArrayEx(MethodTable *pArrayMT, INT32 *pArgs, DWORD dwNumArgs, BOOL bAllocateInLargeHeap DEBUG_ARG(BOOL bDontSetAppDomain));
591 friend OBJECTREF FastAllocatePrimitiveArray(MethodTable* arrayType, DWORD cElements, BOOL bAllocateInLargeHeap);
592 friend FCDECL2(Object*, JIT_NewArr1VC_MP_FastPortable, CORINFO_CLASS_HANDLE arrayMT, INT_PTR size);
593 friend FCDECL2(Object*, JIT_NewArr1OBJ_MP_FastPortable, CORINFO_CLASS_HANDLE arrayMT, INT_PTR size);
594 friend class JIT_TrialAlloc;
595 friend class CheckAsmOffsets;
596 friend struct _DacGlobals;
597
598private:
599 // This MUST be the first field, so that it directly follows Object. This is because
600 // Object::GetSize() looks at m_NumComponents even though it may not be an array (the
601 // values is shifted out if not an array, so it's ok).
602 DWORD m_NumComponents;
603#ifdef _TARGET_64BIT_
604 DWORD pad;
605#endif // _TARGET_64BIT_
606
607 SVAL_DECL(INT32, s_arrayBoundsZero); // = 0
608
609 // What comes after this conceputally is:
610 // TypeHandle elementType; Only present if the method table is shared among many types (arrays of pointers)
611 // INT32 bounds[rank]; The bounds are only present for Multidimensional arrays
612 // INT32 lowerBounds[rank]; Valid indexes are lowerBounds[i] <= index[i] < lowerBounds[i] + bounds[i]
613
614public:
615 // Gets the unique type handle for this array object.
616 // This will call the loader in don't-load mode - the allocator
617 // always makes sure that the particular ArrayTypeDesc for this array
618 // type is available before allocating any instances of this array type.
619 inline TypeHandle GetTypeHandle() const;
620
621 inline static TypeHandle GetTypeHandle(MethodTable * pMT);
622
623 // Get the element type for the array, this works whether the the element
624 // type is stored in the array or not
625 inline TypeHandle GetArrayElementTypeHandle() const;
626
627 // Get the CorElementType for the elements in the array. Avoids creating a TypeHandle
628 inline CorElementType GetArrayElementType() const;
629
630 inline unsigned GetRank() const;
631
632 // Total element count for the array
633 inline DWORD GetNumComponents() const;
634
635#ifndef DACCESS_COMPILE
636 inline void SetArrayMethodTable(MethodTable *pArrayMT);
637 inline void SetArrayMethodTableForLargeObject(MethodTable *pArrayMT);
638#endif // !DACCESS_COMPILE
639
640 // Get pointer to elements, handles any number of dimensions
641 PTR_BYTE GetDataPtr(BOOL inGC = FALSE) const {
642 LIMITED_METHOD_CONTRACT;
643 SUPPORTS_DAC;
644#ifdef _DEBUG
645#ifndef DACCESS_COMPILE
646 EnableStressHeapHelper();
647#endif
648#endif
649 return dac_cast<PTR_BYTE>(this) +
650 GetDataPtrOffset(inGC ? GetGCSafeMethodTable() : GetMethodTable());
651 }
652
653 // The component size is actually 16-bit WORD, but this method is returning SIZE_T to ensure
654 // that SIZE_T is used everywhere for object size computation. It is necessary to support
655 // objects bigger than 2GB.
656 SIZE_T GetComponentSize() const {
657 WRAPPER_NO_CONTRACT;
658 MethodTable * pMT;
659 pMT = GetMethodTable();
660 _ASSERTE(pMT->HasComponentSize());
661 return pMT->RawGetComponentSize();
662 }
663
664 // Note that this can be a multidimensional array of rank 1
665 // (for example if we had a 1-D array with lower bounds
666 BOOL IsMultiDimArray() const {
667 WRAPPER_NO_CONTRACT;
668 SUPPORTS_DAC;
669 return(GetMethodTable()->IsMultiDimArray());
670 }
671
672 // Get pointer to the begining of the bounds (counts for each dim)
673 // Works for any array type
674 PTR_INT32 GetBoundsPtr() const {
675 WRAPPER_NO_CONTRACT;
676 MethodTable * pMT = GetMethodTable();
677 if (pMT->IsMultiDimArray())
678 {
679 return dac_cast<PTR_INT32>(
680 dac_cast<TADDR>(this) + sizeof(*this));
681 }
682 else
683 {
684 return dac_cast<PTR_INT32>(PTR_HOST_MEMBER_TADDR(ArrayBase, this,
685 m_NumComponents));
686 }
687 }
688
689 // Works for any array type
690 PTR_INT32 GetLowerBoundsPtr() const {
691 WRAPPER_NO_CONTRACT;
692 if (IsMultiDimArray())
693 {
694 // Lower bounds info is after total bounds info
695 // and total bounds info has rank elements
696 return GetBoundsPtr() + GetRank();
697 }
698 else
699 return dac_cast<PTR_INT32>(GVAL_ADDR(s_arrayBoundsZero));
700 }
701
702 static unsigned GetOffsetOfNumComponents() {
703 LIMITED_METHOD_CONTRACT;
704 return offsetof(ArrayBase, m_NumComponents);
705 }
706
707 inline static unsigned GetDataPtrOffset(MethodTable* pMT);
708
709 inline static unsigned GetBoundsOffset(MethodTable* pMT);
710 inline static unsigned GetLowerBoundsOffset(MethodTable* pMT);
711
712private:
713#ifndef DACCESS_COMPILE
714#ifdef _DEBUG
715 void AssertArrayTypeDescLoaded();
716#endif // _DEBUG
717#endif // !DACCESS_COMPILE
718};
719
720//
721// Template used to build all the non-object
722// arrays of a single dimension
723//
724
725template < class KIND >
726class Array : public ArrayBase
727{
728 public:
729
730 typedef DPTR(KIND) PTR_KIND;
731 typedef DPTR(const KIND) PTR_CKIND;
732
733 KIND m_Array[1];
734
735 PTR_KIND GetDirectPointerToNonObjectElements()
736 {
737 WRAPPER_NO_CONTRACT;
738 SUPPORTS_DAC;
739 // return m_Array;
740 return PTR_KIND(GetDataPtr()); // This also handles arrays of dim 1 with lower bounds present
741
742 }
743
744 PTR_CKIND GetDirectConstPointerToNonObjectElements() const
745 {
746 WRAPPER_NO_CONTRACT;
747 // return m_Array;
748 return PTR_CKIND(GetDataPtr()); // This also handles arrays of dim 1 with lower bounds present
749 }
750};
751
752
753// Warning: Use PtrArray only for single dimensional arrays, not multidim arrays.
754class PtrArray : public ArrayBase
755{
756 friend class GCHeap;
757 friend class ClrDataAccess;
758 friend OBJECTREF AllocateArrayEx(MethodTable *pArrayMT, INT32 *pArgs, DWORD dwNumArgs, BOOL bAllocateInLargeHeap);
759 friend class JIT_TrialAlloc;
760 friend class CheckAsmOffsets;
761
762public:
763 TypeHandle GetArrayElementTypeHandle()
764 {
765 LIMITED_METHOD_CONTRACT;
766 return GetMethodTable()->GetApproxArrayElementTypeHandle();
767 }
768
769 PTR_OBJECTREF GetDataPtr()
770 {
771 LIMITED_METHOD_CONTRACT;
772 SUPPORTS_DAC;
773 return dac_cast<PTR_OBJECTREF>(dac_cast<PTR_BYTE>(this) + GetDataOffset());
774 }
775
776 static SIZE_T GetDataOffset()
777 {
778 LIMITED_METHOD_CONTRACT;
779 return offsetof(PtrArray, m_Array);
780 }
781
782 void SetAt(SIZE_T i, OBJECTREF ref)
783 {
784 CONTRACTL
785 {
786 NOTHROW;
787 GC_NOTRIGGER;
788 SO_TOLERANT;
789 MODE_COOPERATIVE;
790 }
791 CONTRACTL_END;
792 _ASSERTE(i < GetNumComponents());
793 SetObjectReference(m_Array + i, ref, GetAppDomain());
794 }
795
796 void ClearAt(SIZE_T i)
797 {
798 WRAPPER_NO_CONTRACT;
799 _ASSERTE(i < GetNumComponents());
800 ClearObjectReference(m_Array + i);
801 }
802
803 OBJECTREF GetAt(SIZE_T i)
804 {
805 LIMITED_METHOD_CONTRACT;
806 SUPPORTS_DAC;
807 _ASSERTE(i < GetNumComponents());
808
809// DAC doesn't know the true size of this array
810// the compiler thinks it is size 1, but really it is size N hanging off the structure
811#ifndef DACCESS_COMPILE
812 return m_Array[i];
813#else
814 TADDR arrayTargetAddress = dac_cast<TADDR>(this) + offsetof(PtrArray, m_Array);
815 __ArrayDPtr<OBJECTREF> targetArray = dac_cast< __ArrayDPtr<OBJECTREF> >(arrayTargetAddress);
816 return targetArray[i];
817#endif
818 }
819
820 friend class StubLinkerCPU;
821#ifdef FEATURE_ARRAYSTUB_AS_IL
822 friend class ArrayOpLinker;
823#endif
824public:
825 OBJECTREF m_Array[1];
826};
827
828#define OFFSETOF__PtrArray__m_Array_ ARRAYBASE_SIZE
829
830/* a TypedByRef is a structure that is used to implement VB's BYREF variants.
831 it is basically a tuple of an address of some data along with a TypeHandle
832 that indicates the type of the address */
833class TypedByRef
834{
835public:
836
837 PTR_VOID data;
838 TypeHandle type;
839};
840
841typedef DPTR(TypedByRef) PTR_TypedByRef;
842
843typedef Array<I1> I1Array;
844typedef Array<I2> I2Array;
845typedef Array<I4> I4Array;
846typedef Array<I8> I8Array;
847typedef Array<R4> R4Array;
848typedef Array<R8> R8Array;
849typedef Array<U1> U1Array;
850typedef Array<U1> BOOLArray;
851typedef Array<U2> U2Array;
852typedef Array<WCHAR> CHARArray;
853typedef Array<U4> U4Array;
854typedef Array<U8> U8Array;
855typedef PtrArray PTRArray;
856
857typedef DPTR(I1Array) PTR_I1Array;
858typedef DPTR(I2Array) PTR_I2Array;
859typedef DPTR(I4Array) PTR_I4Array;
860typedef DPTR(I8Array) PTR_I8Array;
861typedef DPTR(R4Array) PTR_R4Array;
862typedef DPTR(R8Array) PTR_R8Array;
863typedef DPTR(U1Array) PTR_U1Array;
864typedef DPTR(BOOLArray) PTR_BOOLArray;
865typedef DPTR(U2Array) PTR_U2Array;
866typedef DPTR(CHARArray) PTR_CHARArray;
867typedef DPTR(U4Array) PTR_U4Array;
868typedef DPTR(U8Array) PTR_U8Array;
869typedef DPTR(PTRArray) PTR_PTRArray;
870
871class StringObject;
872
873#ifdef USE_CHECKED_OBJECTREFS
874typedef REF<ArrayBase> BASEARRAYREF;
875typedef REF<I1Array> I1ARRAYREF;
876typedef REF<I2Array> I2ARRAYREF;
877typedef REF<I4Array> I4ARRAYREF;
878typedef REF<I8Array> I8ARRAYREF;
879typedef REF<R4Array> R4ARRAYREF;
880typedef REF<R8Array> R8ARRAYREF;
881typedef REF<U1Array> U1ARRAYREF;
882typedef REF<BOOLArray> BOOLARRAYREF;
883typedef REF<U2Array> U2ARRAYREF;
884typedef REF<U4Array> U4ARRAYREF;
885typedef REF<U8Array> U8ARRAYREF;
886typedef REF<CHARArray> CHARARRAYREF;
887typedef REF<PTRArray> PTRARRAYREF; // Warning: Use PtrArray only for single dimensional arrays, not multidim arrays.
888typedef REF<StringObject> STRINGREF;
889
890#else // USE_CHECKED_OBJECTREFS
891
892typedef PTR_ArrayBase BASEARRAYREF;
893typedef PTR_I1Array I1ARRAYREF;
894typedef PTR_I2Array I2ARRAYREF;
895typedef PTR_I4Array I4ARRAYREF;
896typedef PTR_I8Array I8ARRAYREF;
897typedef PTR_R4Array R4ARRAYREF;
898typedef PTR_R8Array R8ARRAYREF;
899typedef PTR_U1Array U1ARRAYREF;
900typedef PTR_BOOLArray BOOLARRAYREF;
901typedef PTR_U2Array U2ARRAYREF;
902typedef PTR_U4Array U4ARRAYREF;
903typedef PTR_U8Array U8ARRAYREF;
904typedef PTR_CHARArray CHARARRAYREF;
905typedef PTR_PTRArray PTRARRAYREF; // Warning: Use PtrArray only for single dimensional arrays, not multidim arrays.
906typedef PTR_StringObject STRINGREF;
907
908#endif // USE_CHECKED_OBJECTREFS
909
910
911#include <poppack.h>
912
913
914/*
915 * StringObject
916 *
917 * Special String implementation for performance.
918 *
919 * m_StringLength - Length of string in number of WCHARs
920 * m_FirstChar - The string buffer
921 *
922 */
923
924
925/**
926 * The high bit state can be one of three value:
927 * STRING_STATE_HIGH_CHARS: We've examined the string and determined that it definitely has values greater than 0x80
928 * STRING_STATE_FAST_OPS: We've examined the string and determined that it definitely has no chars greater than 0x80
929 * STRING_STATE_UNDETERMINED: We've never examined this string.
930 * We've also reserved another bit for future use.
931 */
932
933#define STRING_STATE_UNDETERMINED 0x00000000
934#define STRING_STATE_HIGH_CHARS 0x40000000
935#define STRING_STATE_FAST_OPS 0x80000000
936#define STRING_STATE_SPECIAL_SORT 0xC0000000
937
938class StringObject : public Object
939{
940#ifdef DACCESS_COMPILE
941 friend class ClrDataAccess;
942#endif
943 friend class GCHeap;
944 friend class JIT_TrialAlloc;
945 friend class CheckAsmOffsets;
946 friend class COMString;
947
948 private:
949 DWORD m_StringLength;
950 WCHAR m_FirstChar;
951
952 public:
953 VOID SetStringLength(DWORD len) { LIMITED_METHOD_CONTRACT; _ASSERTE(len >= 0); m_StringLength = len; }
954
955 protected:
956 StringObject() {LIMITED_METHOD_CONTRACT; }
957 ~StringObject() {LIMITED_METHOD_CONTRACT; }
958
959 public:
960 static DWORD GetBaseSize();
961 static SIZE_T GetSize(DWORD stringLength);
962
963 DWORD GetStringLength() { LIMITED_METHOD_DAC_CONTRACT; return( m_StringLength );}
964 WCHAR* GetBuffer() { LIMITED_METHOD_CONTRACT; _ASSERTE(this != nullptr); return (WCHAR*)( dac_cast<TADDR>(this) + offsetof(StringObject, m_FirstChar) ); }
965
966 DWORD GetHighCharState() {
967 WRAPPER_NO_CONTRACT;
968 DWORD ret = GetHeader()->GetBits() & (BIT_SBLK_STRING_HIGH_CHAR_MASK);
969 return ret;
970 }
971
972 VOID SetHighCharState(DWORD value) {
973 WRAPPER_NO_CONTRACT;
974 _ASSERTE(value==STRING_STATE_HIGH_CHARS || value==STRING_STATE_FAST_OPS
975 || value==STRING_STATE_UNDETERMINED || value==STRING_STATE_SPECIAL_SORT);
976
977 // you need to clear the present state before going to a new state, but we'll allow multiple threads to set it to the same thing.
978 _ASSERTE((GetHighCharState() == STRING_STATE_UNDETERMINED) || (GetHighCharState()==value));
979
980 static_assert_no_msg(BIT_SBLK_STRING_HAS_NO_HIGH_CHARS == STRING_STATE_FAST_OPS &&
981 STRING_STATE_HIGH_CHARS == BIT_SBLK_STRING_HIGH_CHARS_KNOWN &&
982 STRING_STATE_SPECIAL_SORT == BIT_SBLK_STRING_HAS_SPECIAL_SORT);
983
984 GetHeader()->SetBit(value);
985 }
986
987 static UINT GetBufferOffset()
988 {
989 LIMITED_METHOD_DAC_CONTRACT;
990 return (UINT)(offsetof(StringObject, m_FirstChar));
991 }
992 static UINT GetStringLengthOffset()
993 {
994 LIMITED_METHOD_CONTRACT;
995 return (UINT)(offsetof(StringObject, m_StringLength));
996 }
997 VOID GetSString(SString &result)
998 {
999 WRAPPER_NO_CONTRACT;
1000 result.Set(GetBuffer(), GetStringLength());
1001 }
1002 //========================================================================
1003 // Creates a System.String object. All the functions that take a length
1004 // or a count of bytes will add the null terminator after length
1005 // characters. So this means that if you have a string that has 5
1006 // characters and the null terminator you should pass in 5 and NOT 6.
1007 //========================================================================
1008 static STRINGREF NewString(int length);
1009 static STRINGREF NewString(int length, BOOL bHasTrailByte);
1010 static STRINGREF NewString(const WCHAR *pwsz);
1011 static STRINGREF NewString(const WCHAR *pwsz, int length);
1012 static STRINGREF NewString(LPCUTF8 psz);
1013 static STRINGREF NewString(LPCUTF8 psz, int cBytes);
1014
1015 static STRINGREF GetEmptyString();
1016 static STRINGREF* GetEmptyStringRefPtr();
1017
1018 static STRINGREF* InitEmptyStringRefPtr();
1019
1020 DWORD InternalCheckHighChars();
1021
1022 BOOL HasTrailByte();
1023 BOOL GetTrailByte(BYTE *bTrailByte);
1024 BOOL SetTrailByte(BYTE bTrailByte);
1025 static BOOL CaseInsensitiveCompHelper(__in_ecount(aLength) WCHAR * strA, __in_z INT8 * strB, int aLength, int bLength, int *result);
1026
1027#ifdef VERIFY_HEAP
1028 //has to use raw object to avoid recursive validation
1029 BOOL ValidateHighChars ();
1030#endif //VERIFY_HEAP
1031
1032 /*=================RefInterpretGetStringValuesDangerousForGC======================
1033 **N.B.: This perfoms no range checking and relies on the caller to have done this.
1034 **Args: (IN)ref -- the String to be interpretted.
1035 ** (OUT)chars -- a pointer to the characters in the buffer.
1036 ** (OUT)length -- a pointer to the length of the buffer.
1037 **Returns: void.
1038 **Exceptions: None.
1039 ==============================================================================*/
1040 // !!!! If you use this function, you have to be careful because chars is a pointer
1041 // !!!! to the data buffer of ref. If GC happens after this call, you need to make
1042 // !!!! sure that you have a pin handle on ref, or use GCPROTECT_BEGINPINNING on ref.
1043 void RefInterpretGetStringValuesDangerousForGC(__deref_out_ecount(*length + 1) WCHAR **chars, int *length) {
1044 WRAPPER_NO_CONTRACT;
1045
1046 _ASSERTE(GetGCSafeMethodTable() == g_pStringClass);
1047 *length = GetStringLength();
1048 *chars = GetBuffer();
1049#ifdef _DEBUG
1050 EnableStressHeapHelper();
1051#endif
1052 }
1053
1054
1055private:
1056 static STRINGREF* EmptyStringRefPtr;
1057};
1058
1059//The first two macros are essentially the same. I just define both because
1060//having both can make the code more readable.
1061#define IS_FAST_SORT(state) (((state) == STRING_STATE_FAST_OPS))
1062#define IS_SLOW_SORT(state) (((state) != STRING_STATE_FAST_OPS))
1063
1064//This macro should be used to determine things like indexing, casing, and encoding.
1065#define IS_FAST_OPS_EXCEPT_SORT(state) (((state)==STRING_STATE_SPECIAL_SORT) || ((state)==STRING_STATE_FAST_OPS))
1066#define IS_ASCII(state) (((state)==STRING_STATE_SPECIAL_SORT) || ((state)==STRING_STATE_FAST_OPS))
1067#define IS_FAST_CASING(state) IS_ASCII(state)
1068#define IS_FAST_INDEX(state) IS_ASCII(state)
1069#define IS_STRING_STATE_UNDETERMINED(state) ((state)==STRING_STATE_UNDETERMINED)
1070#define HAS_HIGH_CHARS(state) ((state)==STRING_STATE_HIGH_CHARS)
1071
1072/*================================GetEmptyString================================
1073**Get a reference to the empty string. If we haven't already gotten one, we
1074**query the String class for a pointer to the empty string that we know was
1075**created at startup.
1076**
1077**Args: None
1078**Returns: A STRINGREF to the EmptyString
1079**Exceptions: None
1080==============================================================================*/
1081inline STRINGREF StringObject::GetEmptyString() {
1082
1083 CONTRACTL {
1084 THROWS;
1085 MODE_COOPERATIVE;
1086 GC_TRIGGERS;
1087 } CONTRACTL_END;
1088 STRINGREF* refptr = EmptyStringRefPtr;
1089
1090 //If we've never gotten a reference to the EmptyString, we need to go get one.
1091 if (refptr==NULL) {
1092 refptr = InitEmptyStringRefPtr();
1093 }
1094 //We've already have a reference to the EmptyString, so we can just return it.
1095 return *refptr;
1096}
1097
1098inline STRINGREF* StringObject::GetEmptyStringRefPtr() {
1099
1100 CONTRACTL {
1101 THROWS;
1102 MODE_ANY;
1103 GC_TRIGGERS;
1104 } CONTRACTL_END;
1105 STRINGREF* refptr = EmptyStringRefPtr;
1106
1107 //If we've never gotten a reference to the EmptyString, we need to go get one.
1108 if (refptr==NULL) {
1109 refptr = InitEmptyStringRefPtr();
1110 }
1111 //We've already have a reference to the EmptyString, so we can just return it.
1112 return refptr;
1113}
1114
1115// This is used to account for the remoting cache on RuntimeType,
1116// RuntimeMethodInfo, and RtFieldInfo.
1117class BaseObjectWithCachedData : public Object
1118{
1119};
1120
1121// This is the Class version of the Reflection object.
1122// A Class has adddition information.
1123// For a ReflectClassBaseObject the m_pData is a pointer to a FieldDesc array that
1124// contains all of the final static primitives if its defined.
1125// m_cnt = the number of elements defined in the m_pData FieldDesc array. -1 means
1126// this hasn't yet been defined.
1127class ReflectClassBaseObject : public BaseObjectWithCachedData
1128{
1129 friend class MscorlibBinder;
1130
1131protected:
1132 OBJECTREF m_keepalive;
1133 OBJECTREF m_cache;
1134 TypeHandle m_typeHandle;
1135
1136#ifdef _DEBUG
1137 void TypeCheck()
1138 {
1139 CONTRACTL
1140 {
1141 NOTHROW;
1142 MODE_COOPERATIVE;
1143 GC_NOTRIGGER;
1144 SO_TOLERANT;
1145 }
1146 CONTRACTL_END;
1147
1148 MethodTable *pMT = GetMethodTable();
1149 while (pMT != g_pRuntimeTypeClass && pMT != NULL)
1150 {
1151 pMT = pMT->GetParentMethodTable();
1152 }
1153 _ASSERTE(pMT == g_pRuntimeTypeClass);
1154 }
1155#endif // _DEBUG
1156
1157public:
1158 void SetType(TypeHandle type) {
1159 CONTRACTL
1160 {
1161 NOTHROW;
1162 MODE_COOPERATIVE;
1163 GC_NOTRIGGER;
1164 SO_TOLERANT;
1165 }
1166 CONTRACTL_END;
1167
1168 INDEBUG(TypeCheck());
1169 m_typeHandle = type;
1170 }
1171
1172 void SetKeepAlive(OBJECTREF keepalive)
1173 {
1174 CONTRACTL
1175 {
1176 NOTHROW;
1177 MODE_COOPERATIVE;
1178 GC_NOTRIGGER;
1179 SO_TOLERANT;
1180 }
1181 CONTRACTL_END;
1182
1183 INDEBUG(TypeCheck());
1184 SetObjectReference(&m_keepalive, keepalive, GetAppDomain());
1185 }
1186
1187 TypeHandle GetType() {
1188 CONTRACTL
1189 {
1190 NOTHROW;
1191 MODE_COOPERATIVE;
1192 GC_NOTRIGGER;
1193 SO_TOLERANT;
1194 }
1195 CONTRACTL_END;
1196
1197 INDEBUG(TypeCheck());
1198 return m_typeHandle;
1199 }
1200
1201};
1202
1203// This is the Method version of the Reflection object.
1204// A Method has adddition information.
1205// m_pMD - A pointer to the actual MethodDesc of the method.
1206// m_object - a field that has a reference type in it. Used only for RuntimeMethodInfoStub to keep the real type alive.
1207// This structure matches the structure up to the m_pMD for several different managed types.
1208// (RuntimeConstructorInfo, RuntimeMethodInfo, and RuntimeMethodInfoStub). These types are unrelated in the type
1209// system except that they all implement a particular interface. It is important that that interface is not attached to any
1210// type that does not sufficiently match this data structure.
1211class ReflectMethodObject : public BaseObjectWithCachedData
1212{
1213 friend class MscorlibBinder;
1214
1215protected:
1216 OBJECTREF m_object;
1217 OBJECTREF m_empty1;
1218 OBJECTREF m_empty2;
1219 OBJECTREF m_empty3;
1220 OBJECTREF m_empty4;
1221 OBJECTREF m_empty5;
1222 OBJECTREF m_empty6;
1223 OBJECTREF m_empty7;
1224 MethodDesc * m_pMD;
1225
1226public:
1227 void SetMethod(MethodDesc *pMethod) {
1228 LIMITED_METHOD_CONTRACT;
1229 m_pMD = pMethod;
1230 }
1231
1232 // This must only be called on instances of ReflectMethodObject that are actually RuntimeMethodInfoStub
1233 void SetKeepAlive(OBJECTREF keepalive)
1234 {
1235 WRAPPER_NO_CONTRACT;
1236 SetObjectReference(&m_object, keepalive, GetAppDomain());
1237 }
1238
1239 MethodDesc *GetMethod() {
1240 LIMITED_METHOD_CONTRACT;
1241 return m_pMD;
1242 }
1243
1244};
1245
1246// This is the Field version of the Reflection object.
1247// A Method has adddition information.
1248// m_pFD - A pointer to the actual MethodDesc of the method.
1249// m_object - a field that has a reference type in it. Used only for RuntimeFieldInfoStub to keep the real type alive.
1250// This structure matches the structure up to the m_pFD for several different managed types.
1251// (RtFieldInfo and RuntimeFieldInfoStub). These types are unrelated in the type
1252// system except that they all implement a particular interface. It is important that that interface is not attached to any
1253// type that does not sufficiently match this data structure.
1254class ReflectFieldObject : public BaseObjectWithCachedData
1255{
1256 friend class MscorlibBinder;
1257
1258protected:
1259 OBJECTREF m_object;
1260 OBJECTREF m_empty1;
1261 INT32 m_empty2;
1262 OBJECTREF m_empty3;
1263 OBJECTREF m_empty4;
1264 FieldDesc * m_pFD;
1265
1266public:
1267 void SetField(FieldDesc *pField) {
1268 LIMITED_METHOD_CONTRACT;
1269 m_pFD = pField;
1270 }
1271
1272 // This must only be called on instances of ReflectFieldObject that are actually RuntimeFieldInfoStub
1273 void SetKeepAlive(OBJECTREF keepalive)
1274 {
1275 WRAPPER_NO_CONTRACT;
1276 SetObjectReference(&m_object, keepalive, GetAppDomain());
1277 }
1278
1279 FieldDesc *GetField() {
1280 LIMITED_METHOD_CONTRACT;
1281 return m_pFD;
1282 }
1283};
1284
1285// ReflectModuleBaseObject
1286// This class is the base class for managed Module.
1287// This class will connect the Object back to the underlying VM representation
1288// m_ReflectClass -- This is the real Class that was used for reflection
1289// This class was used to get at this object
1290// m_pData -- this is a generic pointer which usually points CorModule
1291//
1292class ReflectModuleBaseObject : public Object
1293{
1294 friend class MscorlibBinder;
1295
1296 protected:
1297 // READ ME:
1298 // Modifying the order or fields of this object may require other changes to the
1299 // classlib class definition of this object.
1300 OBJECTREF m_runtimeType;
1301 OBJECTREF m_runtimeAssembly;
1302 void* m_ReflectClass; // Pointer to the ReflectClass structure
1303 Module* m_pData; // Pointer to the Module
1304 void* m_pGlobals; // Global values....
1305 void* m_pGlobalsFlds; // Global Fields....
1306
1307 protected:
1308 ReflectModuleBaseObject() {LIMITED_METHOD_CONTRACT;}
1309 ~ReflectModuleBaseObject() {LIMITED_METHOD_CONTRACT;}
1310
1311 public:
1312 void SetModule(Module* p) {
1313 LIMITED_METHOD_CONTRACT;
1314 m_pData = p;
1315 }
1316 Module* GetModule() {
1317 LIMITED_METHOD_CONTRACT;
1318 return m_pData;
1319 }
1320 void SetAssembly(OBJECTREF assembly)
1321 {
1322 WRAPPER_NO_CONTRACT;
1323 SetObjectReference(&m_runtimeAssembly, assembly, GetAppDomain());
1324 }
1325};
1326
1327NOINLINE ReflectModuleBaseObject* GetRuntimeModuleHelper(LPVOID __me, Module *pModule, OBJECTREF keepAlive);
1328#define FC_RETURN_MODULE_OBJECT(pModule, refKeepAlive) FC_INNER_RETURN(ReflectModuleBaseObject*, GetRuntimeModuleHelper(__me, pModule, refKeepAlive))
1329
1330class SafeHandle;
1331
1332#ifdef USE_CHECKED_OBJECTREFS
1333typedef REF<SafeHandle> SAFEHANDLE;
1334typedef REF<SafeHandle> SAFEHANDLEREF;
1335#else // USE_CHECKED_OBJECTREFS
1336typedef SafeHandle * SAFEHANDLE;
1337typedef SafeHandle * SAFEHANDLEREF;
1338#endif // USE_CHECKED_OBJECTREFS
1339
1340
1341
1342#define SYNCCTXPROPS_REQUIRESWAITNOTIFICATION 0x1 // Keep in sync with SynchronizationContext.cs SynchronizationContextFlags
1343class ThreadBaseObject;
1344class SynchronizationContextObject: public Object
1345{
1346 friend class MscorlibBinder;
1347private:
1348 // These field are also defined in the managed representation. (SecurityContext.cs)If you
1349 // add or change these field you must also change the managed code so that
1350 // it matches these. This is necessary so that the object is the proper
1351 // size.
1352 INT32 _props;
1353public:
1354 BOOL IsWaitNotificationRequired()
1355 {
1356 LIMITED_METHOD_CONTRACT;
1357 if ((_props & SYNCCTXPROPS_REQUIRESWAITNOTIFICATION) != 0)
1358 return TRUE;
1359 return FALSE;
1360 }
1361};
1362
1363
1364
1365
1366
1367typedef DPTR(class CultureInfoBaseObject) PTR_CultureInfoBaseObject;
1368
1369#ifdef USE_CHECKED_OBJECTREFS
1370typedef REF<SynchronizationContextObject> SYNCHRONIZATIONCONTEXTREF;
1371typedef REF<ExecutionContextObject> EXECUTIONCONTEXTREF;
1372typedef REF<CultureInfoBaseObject> CULTUREINFOBASEREF;
1373typedef REF<ArrayBase> ARRAYBASEREF;
1374
1375#else
1376typedef SynchronizationContextObject* SYNCHRONIZATIONCONTEXTREF;
1377typedef CultureInfoBaseObject* CULTUREINFOBASEREF;
1378typedef PTR_ArrayBase ARRAYBASEREF;
1379#endif
1380
1381// Note that the name must always be "" or "en-US". Other cases and nulls
1382// aren't allowed (we already checked.)
1383__inline bool IsCultureEnglishOrInvariant(LPCWSTR localeName)
1384{
1385 LIMITED_METHOD_CONTRACT;
1386 if (localeName != NULL &&
1387 (localeName[0] == W('\0') ||
1388 wcscmp(localeName, W("en-US")) == 0))
1389 {
1390 return true;
1391 }
1392 return false;
1393 }
1394
1395class CultureInfoBaseObject : public Object
1396{
1397 friend class MscorlibBinder;
1398
1399private:
1400 OBJECTREF _compareInfo;
1401 OBJECTREF _textInfo;
1402 OBJECTREF _numInfo;
1403 OBJECTREF _dateTimeInfo;
1404 OBJECTREF _calendar;
1405 OBJECTREF _cultureData;
1406 OBJECTREF _consoleFallbackCulture;
1407 STRINGREF _name; // "real" name - en-US, de-DE_phoneb or fj-FJ
1408 STRINGREF _nonSortName; // name w/o sort info (de-DE for de-DE_phoneb)
1409 STRINGREF _sortName; // Sort only name (de-DE_phoneb, en-us for fj-fj (w/us sort)
1410 CULTUREINFOBASEREF _parent;
1411 CLR_BOOL _isReadOnly;
1412 CLR_BOOL _isInherited;
1413
1414public:
1415 CULTUREINFOBASEREF GetParent()
1416 {
1417 LIMITED_METHOD_CONTRACT;
1418 return _parent;
1419 }// GetParent
1420
1421
1422 STRINGREF GetName()
1423 {
1424 LIMITED_METHOD_CONTRACT;
1425 return _name;
1426 }// GetName
1427
1428}; // class CultureInfoBaseObject
1429
1430typedef DPTR(class ThreadBaseObject) PTR_ThreadBaseObject;
1431class ThreadBaseObject : public Object
1432{
1433 friend class ClrDataAccess;
1434 friend class ThreadNative;
1435 friend class MscorlibBinder;
1436 friend class Object;
1437
1438private:
1439
1440 // These field are also defined in the managed representation. If you
1441 // add or change these field you must also change the managed code so that
1442 // it matches these. This is necessary so that the object is the proper
1443 // size. The order here must match that order which the loader will choose
1444 // when laying out the managed class. Note that the layouts are checked
1445 // at run time, not compile time.
1446 OBJECTREF m_ExecutionContext;
1447 OBJECTREF m_SynchronizationContext;
1448 STRINGREF m_Name;
1449 OBJECTREF m_Delegate;
1450 OBJECTREF m_ThreadStartArg;
1451
1452 // The next field (m_InternalThread) is declared as IntPtr in the managed
1453 // definition of Thread. The loader will sort it next.
1454
1455 // m_InternalThread is always valid -- unless the thread has finalized and been
1456 // resurrected. (The thread stopped running before it was finalized).
1457 Thread *m_InternalThread;
1458 INT32 m_Priority;
1459
1460 //We need to cache the thread id in managed code for perf reasons.
1461 INT32 m_ManagedThreadId;
1462
1463protected:
1464 // the ctor and dtor can do no useful work.
1465 ThreadBaseObject() {LIMITED_METHOD_CONTRACT;};
1466 ~ThreadBaseObject() {LIMITED_METHOD_CONTRACT;};
1467
1468public:
1469 Thread *GetInternal()
1470 {
1471 LIMITED_METHOD_CONTRACT;
1472 return m_InternalThread;
1473 }
1474
1475 void SetInternal(Thread *it);
1476 void ClearInternal();
1477
1478 INT32 GetManagedThreadId()
1479 {
1480 LIMITED_METHOD_CONTRACT;
1481 return m_ManagedThreadId;
1482 }
1483
1484 void SetManagedThreadId(INT32 id)
1485 {
1486 LIMITED_METHOD_CONTRACT;
1487 m_ManagedThreadId = id;
1488 }
1489
1490 OBJECTREF GetThreadStartArg() { LIMITED_METHOD_CONTRACT; return m_ThreadStartArg; }
1491 void SetThreadStartArg(OBJECTREF newThreadStartArg)
1492 {
1493 WRAPPER_NO_CONTRACT;
1494
1495 _ASSERTE(newThreadStartArg == NULL);
1496 // Note: this is an unchecked assignment. We are cleaning out the ThreadStartArg field when
1497 // a thread starts so that ADU does not cause problems
1498 SetObjectReferenceUnchecked( (OBJECTREF *)&m_ThreadStartArg, newThreadStartArg);
1499
1500 }
1501
1502 STRINGREF GetName() {
1503 LIMITED_METHOD_CONTRACT;
1504 return m_Name;
1505 }
1506 OBJECTREF GetDelegate() { LIMITED_METHOD_CONTRACT; return m_Delegate; }
1507 void SetDelegate(OBJECTREF delegate);
1508
1509 OBJECTREF GetSynchronizationContext()
1510 {
1511 LIMITED_METHOD_CONTRACT;
1512 return m_SynchronizationContext;
1513 }
1514
1515 // SetDelegate is our "constructor" for the pathway where the exposed object is
1516 // created first. InitExisting is our "constructor" for the pathway where an
1517 // existing physical thread is later exposed.
1518 void InitExisting();
1519
1520 void ResetName()
1521 {
1522 LIMITED_METHOD_CONTRACT;
1523 m_Name = NULL;
1524 }
1525
1526 void SetPriority(INT32 priority)
1527 {
1528 LIMITED_METHOD_CONTRACT;
1529 m_Priority = priority;
1530 }
1531
1532 INT32 GetPriority() const
1533 {
1534 LIMITED_METHOD_CONTRACT;
1535 return m_Priority;
1536 }
1537};
1538
1539// MarshalByRefObjectBaseObject
1540// This class is the base class for MarshalByRefObject
1541//
1542class MarshalByRefObjectBaseObject : public Object
1543{
1544};
1545
1546// AssemblyBaseObject
1547// This class is the base class for assemblies
1548//
1549class AssemblyBaseObject : public Object
1550{
1551 friend class Assembly;
1552 friend class MscorlibBinder;
1553
1554 protected:
1555 // READ ME:
1556 // Modifying the order or fields of this object may require other changes to the
1557 // classlib class definition of this object.
1558 OBJECTREF m_pModuleEventHandler; // Delegate for 'resolve module' event
1559 STRINGREF m_fullname; // Slot for storing assemblies fullname
1560 OBJECTREF m_pSyncRoot; // Pointer to loader allocator to keep collectible types alive, and to serve as the syncroot for assembly building in ref.emit
1561 DomainAssembly* m_pAssembly; // Pointer to the Assembly Structure
1562
1563 protected:
1564 AssemblyBaseObject() { LIMITED_METHOD_CONTRACT; }
1565 ~AssemblyBaseObject() { LIMITED_METHOD_CONTRACT; }
1566
1567 public:
1568
1569 void SetAssembly(DomainAssembly* p)
1570 {
1571 LIMITED_METHOD_CONTRACT;
1572 m_pAssembly = p;
1573 }
1574
1575 DomainAssembly* GetDomainAssembly()
1576 {
1577 LIMITED_METHOD_CONTRACT;
1578 return m_pAssembly;
1579 }
1580
1581 Assembly* GetAssembly();
1582
1583 void SetSyncRoot(OBJECTREF pSyncRoot)
1584 {
1585 WRAPPER_NO_CONTRACT;
1586 SetObjectReferenceUnchecked(&m_pSyncRoot, pSyncRoot);
1587 }
1588};
1589NOINLINE AssemblyBaseObject* GetRuntimeAssemblyHelper(LPVOID __me, DomainAssembly *pAssembly, OBJECTREF keepAlive);
1590#define FC_RETURN_ASSEMBLY_OBJECT(pAssembly, refKeepAlive) FC_INNER_RETURN(AssemblyBaseObject*, GetRuntimeAssemblyHelper(__me, pAssembly, refKeepAlive))
1591
1592// AssemblyNameBaseObject
1593// This class is the base class for assembly names
1594//
1595class AssemblyNameBaseObject : public Object
1596{
1597 friend class AssemblyNative;
1598 friend class AppDomainNative;
1599 friend class MscorlibBinder;
1600
1601 protected:
1602 // READ ME:
1603 // Modifying the order or fields of this object may require other changes to the
1604 // classlib class definition of this object.
1605
1606 OBJECTREF _name;
1607 U1ARRAYREF _publicKey;
1608 U1ARRAYREF _publicKeyToken;
1609 OBJECTREF _cultureInfo;
1610 OBJECTREF _codeBase;
1611 OBJECTREF _version;
1612 OBJECTREF _strongNameKeyPair;
1613 U1ARRAYREF _hashForControl;
1614 DWORD _hashAlgorithm;
1615 DWORD _hashAlgorithmForControl;
1616 DWORD _versionCompatibility;
1617 DWORD _flags;
1618
1619 protected:
1620 AssemblyNameBaseObject() { LIMITED_METHOD_CONTRACT; }
1621 ~AssemblyNameBaseObject() { LIMITED_METHOD_CONTRACT; }
1622
1623 public:
1624 OBJECTREF GetSimpleName() { LIMITED_METHOD_CONTRACT; return _name; }
1625 U1ARRAYREF GetPublicKey() { LIMITED_METHOD_CONTRACT; return _publicKey; }
1626 U1ARRAYREF GetPublicKeyToken() { LIMITED_METHOD_CONTRACT; return _publicKeyToken; }
1627 OBJECTREF GetStrongNameKeyPair() { LIMITED_METHOD_CONTRACT; return _strongNameKeyPair; }
1628 OBJECTREF GetCultureInfo() { LIMITED_METHOD_CONTRACT; return _cultureInfo; }
1629 OBJECTREF GetAssemblyCodeBase() { LIMITED_METHOD_CONTRACT; return _codeBase; }
1630 OBJECTREF GetVersion() { LIMITED_METHOD_CONTRACT; return _version; }
1631 DWORD GetAssemblyHashAlgorithm() { LIMITED_METHOD_CONTRACT; return _hashAlgorithm; }
1632 DWORD GetFlags() { LIMITED_METHOD_CONTRACT; return _flags; }
1633 U1ARRAYREF GetHashForControl() { LIMITED_METHOD_CONTRACT; return _hashForControl;}
1634 DWORD GetHashAlgorithmForControl() { LIMITED_METHOD_CONTRACT; return _hashAlgorithmForControl; }
1635};
1636
1637// VersionBaseObject
1638// This class is the base class for versions
1639//
1640class VersionBaseObject : public Object
1641{
1642 friend class MscorlibBinder;
1643
1644 protected:
1645 // READ ME:
1646 // Modifying the order or fields of this object may require other changes to the
1647 // classlib class definition of this object.
1648
1649 int m_Major;
1650 int m_Minor;
1651 int m_Build;
1652 int m_Revision;
1653
1654 VersionBaseObject() {LIMITED_METHOD_CONTRACT;}
1655 ~VersionBaseObject() {LIMITED_METHOD_CONTRACT;}
1656
1657 public:
1658 int GetMajor() { LIMITED_METHOD_CONTRACT; return m_Major; }
1659 int GetMinor() { LIMITED_METHOD_CONTRACT; return m_Minor; }
1660 int GetBuild() { LIMITED_METHOD_CONTRACT; return m_Build; }
1661 int GetRevision() { LIMITED_METHOD_CONTRACT; return m_Revision; }
1662};
1663
1664class WeakReferenceObject : public Object
1665{
1666public:
1667 Volatile<OBJECTHANDLE> m_Handle;
1668};
1669
1670#ifdef USE_CHECKED_OBJECTREFS
1671
1672typedef REF<ReflectModuleBaseObject> REFLECTMODULEBASEREF;
1673
1674typedef REF<ReflectClassBaseObject> REFLECTCLASSBASEREF;
1675
1676typedef REF<ReflectMethodObject> REFLECTMETHODREF;
1677
1678typedef REF<ReflectFieldObject> REFLECTFIELDREF;
1679
1680typedef REF<ThreadBaseObject> THREADBASEREF;
1681
1682typedef REF<AppDomainBaseObject> APPDOMAINREF;
1683
1684typedef REF<MarshalByRefObjectBaseObject> MARSHALBYREFOBJECTBASEREF;
1685
1686typedef REF<AssemblyBaseObject> ASSEMBLYREF;
1687
1688typedef REF<AssemblyNameBaseObject> ASSEMBLYNAMEREF;
1689
1690typedef REF<VersionBaseObject> VERSIONREF;
1691
1692
1693typedef REF<WeakReferenceObject> WEAKREFERENCEREF;
1694
1695inline ARG_SLOT ObjToArgSlot(OBJECTREF objRef)
1696{
1697 LIMITED_METHOD_CONTRACT;
1698 LPVOID v;
1699 v = OBJECTREFToObject(objRef);
1700 return (ARG_SLOT)(SIZE_T)v;
1701}
1702
1703inline OBJECTREF ArgSlotToObj(ARG_SLOT i)
1704{
1705 LIMITED_METHOD_CONTRACT;
1706 LPVOID v;
1707 v = (LPVOID)(SIZE_T)i;
1708 return ObjectToOBJECTREF ((Object*)v);
1709}
1710
1711inline ARG_SLOT StringToArgSlot(STRINGREF sr)
1712{
1713 LIMITED_METHOD_CONTRACT;
1714 LPVOID v;
1715 v = OBJECTREFToObject(sr);
1716 return (ARG_SLOT)(SIZE_T)v;
1717}
1718
1719inline STRINGREF ArgSlotToString(ARG_SLOT s)
1720{
1721 LIMITED_METHOD_CONTRACT;
1722 LPVOID v;
1723 v = (LPVOID)(SIZE_T)s;
1724 return ObjectToSTRINGREF ((StringObject*)v);
1725}
1726
1727#else // USE_CHECKED_OBJECTREFS
1728
1729typedef PTR_ReflectModuleBaseObject REFLECTMODULEBASEREF;
1730typedef PTR_ReflectClassBaseObject REFLECTCLASSBASEREF;
1731typedef PTR_ReflectMethodObject REFLECTMETHODREF;
1732typedef PTR_ReflectFieldObject REFLECTFIELDREF;
1733typedef PTR_ThreadBaseObject THREADBASEREF;
1734typedef PTR_AssemblyBaseObject ASSEMBLYREF;
1735typedef PTR_AssemblyNameBaseObject ASSEMBLYNAMEREF;
1736
1737#ifndef DACCESS_COMPILE
1738typedef MarshalByRefObjectBaseObject* MARSHALBYREFOBJECTBASEREF;
1739typedef VersionBaseObject* VERSIONREF;
1740typedef WeakReferenceObject* WEAKREFERENCEREF;
1741#endif // #ifndef DACCESS_COMPILE
1742
1743#define ObjToArgSlot(objref) ((ARG_SLOT)(SIZE_T)(objref))
1744#define ArgSlotToObj(s) ((OBJECTREF)(SIZE_T)(s))
1745
1746#define StringToArgSlot(objref) ((ARG_SLOT)(SIZE_T)(objref))
1747#define ArgSlotToString(s) ((STRINGREF)(SIZE_T)(s))
1748
1749#endif //USE_CHECKED_OBJECTREFS
1750
1751#define PtrToArgSlot(ptr) ((ARG_SLOT)(SIZE_T)(ptr))
1752#define ArgSlotToPtr(s) ((LPVOID)(SIZE_T)(s))
1753
1754#define BoolToArgSlot(b) ((ARG_SLOT)(CLR_BOOL)(!!(b)))
1755#define ArgSlotToBool(s) ((BOOL)(s))
1756
1757STRINGREF AllocateString(SString sstr);
1758CHARARRAYREF AllocateCharArray(DWORD dwArrayLength);
1759
1760#ifdef FEATURE_COMINTEROP
1761
1762//-------------------------------------------------------------
1763// class ComObject, Exposed class __ComObject
1764//
1765//
1766//-------------------------------------------------------------
1767class ComObject : public MarshalByRefObjectBaseObject
1768{
1769 friend class MscorlibBinder;
1770
1771protected:
1772
1773 ComObject()
1774 {LIMITED_METHOD_CONTRACT;}; // don't instantiate this class directly
1775 ~ComObject(){LIMITED_METHOD_CONTRACT;};
1776
1777public:
1778 OBJECTREF m_ObjectToDataMap;
1779
1780 //--------------------------------------------------------------------
1781 // SupportsInterface
1782 static BOOL SupportsInterface(OBJECTREF oref, MethodTable* pIntfTable);
1783
1784 //--------------------------------------------------------------------
1785 // SupportsInterface
1786 static void ThrowInvalidCastException(OBJECTREF *pObj, MethodTable* pCastToMT);
1787
1788 //-----------------------------------------------------------------
1789 // GetComIPFromRCW
1790 static IUnknown* GetComIPFromRCW(OBJECTREF *pObj, MethodTable* pIntfTable);
1791
1792 //-----------------------------------------------------------------
1793 // GetComIPFromRCWThrowing
1794 static IUnknown* GetComIPFromRCWThrowing(OBJECTREF *pObj, MethodTable* pIntfTable);
1795
1796 //-----------------------------------------------------------
1797 // create an empty ComObjectRef
1798 static OBJECTREF CreateComObjectRef(MethodTable* pMT);
1799
1800 //-----------------------------------------------------------
1801 // Release all the data associated with the __ComObject.
1802 static void ReleaseAllData(OBJECTREF oref);
1803
1804 //-----------------------------------------------------------
1805 // Redirection for ToString
1806 static FCDECL1(MethodDesc *, GetRedirectedToStringMD, Object *pThisUNSAFE);
1807 static FCDECL2(StringObject *, RedirectToString, Object *pThisUNSAFE, MethodDesc *pToStringMD);
1808
1809 //-----------------------------------------------------------
1810 // Redirection for GetHashCode
1811 static FCDECL1(MethodDesc *, GetRedirectedGetHashCodeMD, Object *pThisUNSAFE);
1812 static FCDECL2(int, RedirectGetHashCode, Object *pThisUNSAFE, MethodDesc *pGetHashCodeMD);
1813
1814 //-----------------------------------------------------------
1815 // Redirection for Equals
1816 static FCDECL1(MethodDesc *, GetRedirectedEqualsMD, Object *pThisUNSAFE);
1817 static FCDECL3(FC_BOOL_RET, RedirectEquals, Object *pThisUNSAFE, Object *pOtherUNSAFE, MethodDesc *pEqualsMD);
1818};
1819
1820#ifdef USE_CHECKED_OBJECTREFS
1821typedef REF<ComObject> COMOBJECTREF;
1822#else
1823typedef ComObject* COMOBJECTREF;
1824#endif
1825
1826
1827//-------------------------------------------------------------
1828// class UnknownWrapper, Exposed class UnknownWrapper
1829//
1830//
1831//-------------------------------------------------------------
1832class UnknownWrapper : public Object
1833{
1834protected:
1835
1836 UnknownWrapper(UnknownWrapper &wrap) {LIMITED_METHOD_CONTRACT}; // dissalow copy construction.
1837 UnknownWrapper() {LIMITED_METHOD_CONTRACT;}; // don't instantiate this class directly
1838 ~UnknownWrapper() {LIMITED_METHOD_CONTRACT;};
1839
1840 OBJECTREF m_WrappedObject;
1841
1842public:
1843 OBJECTREF GetWrappedObject()
1844 {
1845 LIMITED_METHOD_CONTRACT;
1846 return m_WrappedObject;
1847 }
1848
1849 void SetWrappedObject(OBJECTREF pWrappedObject)
1850 {
1851 LIMITED_METHOD_CONTRACT;
1852 m_WrappedObject = pWrappedObject;
1853 }
1854};
1855
1856#ifdef USE_CHECKED_OBJECTREFS
1857typedef REF<UnknownWrapper> UNKNOWNWRAPPEROBJECTREF;
1858#else
1859typedef UnknownWrapper* UNKNOWNWRAPPEROBJECTREF;
1860#endif
1861
1862
1863//-------------------------------------------------------------
1864// class DispatchWrapper, Exposed class DispatchWrapper
1865//
1866//
1867//-------------------------------------------------------------
1868class DispatchWrapper : public Object
1869{
1870protected:
1871
1872 DispatchWrapper(DispatchWrapper &wrap) {LIMITED_METHOD_CONTRACT}; // dissalow copy construction.
1873 DispatchWrapper() {LIMITED_METHOD_CONTRACT;}; // don't instantiate this class directly
1874 ~DispatchWrapper() {LIMITED_METHOD_CONTRACT;};
1875
1876 OBJECTREF m_WrappedObject;
1877
1878public:
1879 OBJECTREF GetWrappedObject()
1880 {
1881 LIMITED_METHOD_CONTRACT;
1882 return m_WrappedObject;
1883 }
1884
1885 void SetWrappedObject(OBJECTREF pWrappedObject)
1886 {
1887 LIMITED_METHOD_CONTRACT;
1888 m_WrappedObject = pWrappedObject;
1889 }
1890};
1891
1892#ifdef USE_CHECKED_OBJECTREFS
1893typedef REF<DispatchWrapper> DISPATCHWRAPPEROBJECTREF;
1894#else
1895typedef DispatchWrapper* DISPATCHWRAPPEROBJECTREF;
1896#endif
1897
1898
1899//-------------------------------------------------------------
1900// class VariantWrapper, Exposed class VARIANTWRAPPEROBJECTREF
1901//
1902//
1903//-------------------------------------------------------------
1904class VariantWrapper : public Object
1905{
1906protected:
1907
1908 VariantWrapper(VariantWrapper &wrap) {LIMITED_METHOD_CONTRACT}; // dissalow copy construction.
1909 VariantWrapper() {LIMITED_METHOD_CONTRACT}; // don't instantiate this class directly
1910 ~VariantWrapper() {LIMITED_METHOD_CONTRACT};
1911
1912 OBJECTREF m_WrappedObject;
1913
1914public:
1915 OBJECTREF GetWrappedObject()
1916 {
1917 LIMITED_METHOD_CONTRACT;
1918 return m_WrappedObject;
1919 }
1920
1921 void SetWrappedObject(OBJECTREF pWrappedObject)
1922 {
1923 LIMITED_METHOD_CONTRACT;
1924 m_WrappedObject = pWrappedObject;
1925 }
1926};
1927
1928#ifdef USE_CHECKED_OBJECTREFS
1929typedef REF<VariantWrapper> VARIANTWRAPPEROBJECTREF;
1930#else
1931typedef VariantWrapper* VARIANTWRAPPEROBJECTREF;
1932#endif
1933
1934
1935//-------------------------------------------------------------
1936// class ErrorWrapper, Exposed class ErrorWrapper
1937//
1938//
1939//-------------------------------------------------------------
1940class ErrorWrapper : public Object
1941{
1942protected:
1943
1944 ErrorWrapper(ErrorWrapper &wrap) {LIMITED_METHOD_CONTRACT}; // dissalow copy construction.
1945 ErrorWrapper() {LIMITED_METHOD_CONTRACT;}; // don't instantiate this class directly
1946 ~ErrorWrapper() {LIMITED_METHOD_CONTRACT;};
1947
1948 INT32 m_ErrorCode;
1949
1950public:
1951 INT32 GetErrorCode()
1952 {
1953 LIMITED_METHOD_CONTRACT;
1954 return m_ErrorCode;
1955 }
1956
1957 void SetErrorCode(int ErrorCode)
1958 {
1959 LIMITED_METHOD_CONTRACT;
1960 m_ErrorCode = ErrorCode;
1961 }
1962};
1963
1964#ifdef USE_CHECKED_OBJECTREFS
1965typedef REF<ErrorWrapper> ERRORWRAPPEROBJECTREF;
1966#else
1967typedef ErrorWrapper* ERRORWRAPPEROBJECTREF;
1968#endif
1969
1970
1971//-------------------------------------------------------------
1972// class CurrencyWrapper, Exposed class CurrencyWrapper
1973//
1974//
1975//-------------------------------------------------------------
1976
1977// Keep this in sync with code:MethodTableBuilder.CheckForSystemTypes where
1978// alignment requirement of the managed System.Decimal structure is computed.
1979#if !defined(ALIGN_ACCESS) && !defined(FEATURE_64BIT_ALIGNMENT)
1980#include <pshpack4.h>
1981#endif // !ALIGN_ACCESS && !FEATURE_64BIT_ALIGNMENT
1982
1983class CurrencyWrapper : public Object
1984{
1985protected:
1986
1987 CurrencyWrapper(CurrencyWrapper &wrap) {LIMITED_METHOD_CONTRACT}; // dissalow copy construction.
1988 CurrencyWrapper() {LIMITED_METHOD_CONTRACT;}; // don't instantiate this class directly
1989 ~CurrencyWrapper() {LIMITED_METHOD_CONTRACT;};
1990
1991 DECIMAL m_WrappedObject;
1992
1993public:
1994 DECIMAL GetWrappedObject()
1995 {
1996 LIMITED_METHOD_CONTRACT;
1997 return m_WrappedObject;
1998 }
1999
2000 void SetWrappedObject(DECIMAL WrappedObj)
2001 {
2002 LIMITED_METHOD_CONTRACT;
2003 m_WrappedObject = WrappedObj;
2004 }
2005};
2006
2007#if !defined(ALIGN_ACCESS) && !defined(FEATURE_64BIT_ALIGNMENT)
2008#include <poppack.h>
2009#endif // !ALIGN_ACCESS && !FEATURE_64BIT_ALIGNMENT
2010
2011#ifdef USE_CHECKED_OBJECTREFS
2012typedef REF<CurrencyWrapper> CURRENCYWRAPPEROBJECTREF;
2013#else
2014typedef CurrencyWrapper* CURRENCYWRAPPEROBJECTREF;
2015#endif
2016
2017//-------------------------------------------------------------
2018// class BStrWrapper, Exposed class BSTRWRAPPEROBJECTREF
2019//
2020//
2021//-------------------------------------------------------------
2022class BStrWrapper : public Object
2023{
2024protected:
2025
2026 BStrWrapper(BStrWrapper &wrap) {LIMITED_METHOD_CONTRACT}; // dissalow copy construction.
2027 BStrWrapper() {LIMITED_METHOD_CONTRACT}; // don't instantiate this class directly
2028 ~BStrWrapper() {LIMITED_METHOD_CONTRACT};
2029
2030 STRINGREF m_WrappedObject;
2031
2032public:
2033 STRINGREF GetWrappedObject()
2034 {
2035 LIMITED_METHOD_CONTRACT;
2036 return m_WrappedObject;
2037 }
2038
2039 void SetWrappedObject(STRINGREF pWrappedObject)
2040 {
2041 LIMITED_METHOD_CONTRACT;
2042 m_WrappedObject = pWrappedObject;
2043 }
2044};
2045
2046#ifdef USE_CHECKED_OBJECTREFS
2047typedef REF<BStrWrapper> BSTRWRAPPEROBJECTREF;
2048#else
2049typedef BStrWrapper* BSTRWRAPPEROBJECTREF;
2050#endif
2051
2052#endif // FEATURE_COMINTEROP
2053
2054class SafeHandle : public Object
2055{
2056 friend class MscorlibBinder;
2057
2058 private:
2059 // READ ME:
2060 // Modifying the order or fields of this object may require
2061 // other changes to the classlib class definition of this
2062 // object or special handling when loading this system class.
2063 Volatile<LPVOID> m_handle;
2064 Volatile<INT32> m_state; // Combined ref count and closed/disposed state (for atomicity)
2065 Volatile<CLR_BOOL> m_ownsHandle;
2066 Volatile<CLR_BOOL> m_fullyInitialized; // Did constructor finish?
2067
2068 // Describe the bits in the m_state field above.
2069 enum StateBits
2070 {
2071 SH_State_Closed = 0x00000001,
2072 SH_State_Disposed = 0x00000002,
2073 SH_State_RefCount = 0xfffffffc,
2074 SH_RefCountOne = 4, // Amount to increment state field to yield a ref count increment of 1
2075 };
2076
2077 static WORD s_IsInvalidHandleMethodSlot;
2078 static WORD s_ReleaseHandleMethodSlot;
2079
2080 static void RunReleaseMethod(SafeHandle* psh);
2081 BOOL IsFullyInitialized() const { LIMITED_METHOD_CONTRACT; return m_fullyInitialized; }
2082
2083 public:
2084 static void Init();
2085
2086 // To use the SafeHandle from native, look at the SafeHandleHolder, which
2087 // will do the AddRef & Release for you.
2088 LPVOID GetHandle() const {
2089 LIMITED_METHOD_CONTRACT;
2090 _ASSERTE(((unsigned int) m_state) >= SH_RefCountOne);
2091 return m_handle;
2092 }
2093
2094 BOOL OwnsHandle() const
2095 {
2096 LIMITED_METHOD_CONTRACT;
2097 return m_ownsHandle;
2098 }
2099
2100 static size_t GetHandleOffset() { LIMITED_METHOD_CONTRACT; return offsetof(SafeHandle, m_handle); }
2101
2102 void AddRef();
2103 void Release(bool fDispose = false);
2104 void Dispose();
2105 void SetHandle(LPVOID handle);
2106
2107 static FCDECL1(void, DisposeNative, SafeHandle* refThisUNSAFE);
2108 static FCDECL1(void, Finalize, SafeHandle* refThisUNSAFE);
2109 static FCDECL1(void, SetHandleAsInvalid, SafeHandle* refThisUNSAFE);
2110 static FCDECL2(void, DangerousAddRef, SafeHandle* refThisUNSAFE, CLR_BOOL *pfSuccess);
2111 static FCDECL1(void, DangerousRelease, SafeHandle* refThisUNSAFE);
2112};
2113
2114// SAFEHANDLEREF defined above because CompressedStackObject needs it
2115
2116void AcquireSafeHandle(SAFEHANDLEREF* s);
2117void ReleaseSafeHandle(SAFEHANDLEREF* s);
2118
2119typedef Holder<SAFEHANDLEREF*, AcquireSafeHandle, ReleaseSafeHandle> SafeHandleHolder;
2120
2121class CriticalHandle : public Object
2122{
2123 friend class MscorlibBinder;
2124
2125 private:
2126 // READ ME:
2127 // Modifying the order or fields of this object may require
2128 // other changes to the classlib class definition of this
2129 // object or special handling when loading this system class.
2130 Volatile<LPVOID> m_handle;
2131 Volatile<CLR_BOOL> m_isClosed;
2132
2133 public:
2134 LPVOID GetHandle() const { LIMITED_METHOD_CONTRACT; return m_handle; }
2135 static size_t GetHandleOffset() { LIMITED_METHOD_CONTRACT; return offsetof(CriticalHandle, m_handle); }
2136
2137 void SetHandle(LPVOID handle) { LIMITED_METHOD_CONTRACT; m_handle = handle; }
2138
2139 static FCDECL1(void, FireCustomerDebugProbe, CriticalHandle* refThisUNSAFE);
2140};
2141
2142
2143#ifdef USE_CHECKED_OBJECTREFS
2144typedef REF<CriticalHandle> CRITICALHANDLE;
2145typedef REF<CriticalHandle> CRITICALHANDLEREF;
2146#else // USE_CHECKED_OBJECTREFS
2147typedef CriticalHandle * CRITICALHANDLE;
2148typedef CriticalHandle * CRITICALHANDLEREF;
2149#endif // USE_CHECKED_OBJECTREFS
2150
2151// WaitHandleBase
2152// Base class for WaitHandle
2153class WaitHandleBase :public MarshalByRefObjectBaseObject
2154{
2155 friend class WaitHandleNative;
2156 friend class MscorlibBinder;
2157
2158public:
2159 __inline LPVOID GetWaitHandle() {LIMITED_METHOD_CONTRACT; return m_handle;}
2160 __inline SAFEHANDLEREF GetSafeHandle() {LIMITED_METHOD_CONTRACT; return m_safeHandle;}
2161
2162private:
2163 SAFEHANDLEREF m_safeHandle;
2164 LPVOID m_handle;
2165 CLR_BOOL m_hasThreadAffinity;
2166};
2167
2168#ifdef USE_CHECKED_OBJECTREFS
2169typedef REF<WaitHandleBase> WAITHANDLEREF;
2170#else // USE_CHECKED_OBJECTREFS
2171typedef WaitHandleBase* WAITHANDLEREF;
2172#endif // USE_CHECKED_OBJECTREFS
2173
2174// This class corresponds to System.MulticastDelegate on the managed side.
2175class DelegateObject : public Object
2176{
2177 friend class CheckAsmOffsets;
2178 friend class MscorlibBinder;
2179
2180public:
2181 BOOL IsWrapperDelegate() { LIMITED_METHOD_CONTRACT; return _methodPtrAux == NULL; }
2182
2183 OBJECTREF GetTarget() { LIMITED_METHOD_CONTRACT; return _target; }
2184 void SetTarget(OBJECTREF target) { WRAPPER_NO_CONTRACT; SetObjectReference(&_target, target, GetAppDomain()); }
2185 static int GetOffsetOfTarget() { LIMITED_METHOD_CONTRACT; return offsetof(DelegateObject, _target); }
2186
2187 PCODE GetMethodPtr() { LIMITED_METHOD_CONTRACT; return _methodPtr; }
2188 void SetMethodPtr(PCODE methodPtr) { LIMITED_METHOD_CONTRACT; _methodPtr = methodPtr; }
2189 static int GetOffsetOfMethodPtr() { LIMITED_METHOD_CONTRACT; return offsetof(DelegateObject, _methodPtr); }
2190
2191 PCODE GetMethodPtrAux() { LIMITED_METHOD_CONTRACT; return _methodPtrAux; }
2192 void SetMethodPtrAux(PCODE methodPtrAux) { LIMITED_METHOD_CONTRACT; _methodPtrAux = methodPtrAux; }
2193 static int GetOffsetOfMethodPtrAux() { LIMITED_METHOD_CONTRACT; return offsetof(DelegateObject, _methodPtrAux); }
2194
2195 OBJECTREF GetInvocationList() { LIMITED_METHOD_CONTRACT; return _invocationList; }
2196 void SetInvocationList(OBJECTREF invocationList) { WRAPPER_NO_CONTRACT; SetObjectReference(&_invocationList, invocationList, GetAppDomain()); }
2197 static int GetOffsetOfInvocationList() { LIMITED_METHOD_CONTRACT; return offsetof(DelegateObject, _invocationList); }
2198
2199 INT_PTR GetInvocationCount() { LIMITED_METHOD_CONTRACT; return _invocationCount; }
2200 void SetInvocationCount(INT_PTR invocationCount) { LIMITED_METHOD_CONTRACT; _invocationCount = invocationCount; }
2201 static int GetOffsetOfInvocationCount() { LIMITED_METHOD_CONTRACT; return offsetof(DelegateObject, _invocationCount); }
2202
2203 void SetMethodBase(OBJECTREF newMethodBase) { LIMITED_METHOD_CONTRACT; SetObjectReference((OBJECTREF*)&_methodBase, newMethodBase, GetAppDomain()); }
2204
2205 // README:
2206 // If you modify the order of these fields, make sure to update the definition in
2207 // BCL for this object.
2208private:
2209 // System.Delegate
2210 OBJECTREF _target;
2211 OBJECTREF _methodBase;
2212 PCODE _methodPtr;
2213 PCODE _methodPtrAux;
2214 // System.MulticastDelegate
2215 OBJECTREF _invocationList;
2216 INT_PTR _invocationCount;
2217};
2218
2219#define OFFSETOF__DelegateObject__target OBJECT_SIZE /* m_pMethTab */
2220#define OFFSETOF__DelegateObject__methodPtr (OFFSETOF__DelegateObject__target + TARGET_POINTER_SIZE /* _target */ + TARGET_POINTER_SIZE /* _methodBase */)
2221#define OFFSETOF__DelegateObject__methodPtrAux (OFFSETOF__DelegateObject__methodPtr + TARGET_POINTER_SIZE /* _methodPtr */)
2222
2223#ifdef USE_CHECKED_OBJECTREFS
2224typedef REF<DelegateObject> DELEGATEREF;
2225#else // USE_CHECKED_OBJECTREFS
2226typedef DelegateObject* DELEGATEREF;
2227#endif // USE_CHECKED_OBJECTREFS
2228
2229
2230struct StackTraceElement;
2231class ClrDataAccess;
2232
2233
2234typedef DPTR(StackTraceElement) PTR_StackTraceElement;
2235
2236class StackTraceArray
2237{
2238 struct ArrayHeader
2239 {
2240 size_t m_size;
2241 Thread * m_thread;
2242 };
2243
2244 typedef DPTR(ArrayHeader) PTR_ArrayHeader;
2245
2246public:
2247 StackTraceArray()
2248 : m_array(static_cast<I1Array *>(NULL))
2249 {
2250 WRAPPER_NO_CONTRACT;
2251 }
2252
2253 StackTraceArray(I1ARRAYREF array)
2254 : m_array(array)
2255 {
2256 LIMITED_METHOD_CONTRACT;
2257 }
2258
2259 void Swap(StackTraceArray & rhs)
2260 {
2261 CONTRACTL
2262 {
2263 NOTHROW;
2264 GC_NOTRIGGER;
2265 SO_TOLERANT;
2266 MODE_COOPERATIVE;
2267 }
2268 CONTRACTL_END;
2269 SUPPORTS_DAC;
2270 I1ARRAYREF t = m_array;
2271 m_array = rhs.m_array;
2272 rhs.m_array = t;
2273 }
2274
2275 size_t Size() const
2276 {
2277 WRAPPER_NO_CONTRACT;
2278 if (!m_array)
2279 return 0;
2280 else
2281 return GetSize();
2282 }
2283
2284 StackTraceElement const & operator[](size_t index) const;
2285 StackTraceElement & operator[](size_t index);
2286
2287 void Append(StackTraceElement const * begin, StackTraceElement const * end);
2288
2289 I1ARRAYREF Get() const
2290 {
2291 LIMITED_METHOD_DAC_CONTRACT;
2292 return m_array;
2293 }
2294
2295 // Deep copies the array
2296 void CopyFrom(StackTraceArray const & src);
2297
2298private:
2299 StackTraceArray(StackTraceArray const & rhs) = delete;
2300
2301 StackTraceArray & operator=(StackTraceArray const & rhs) = delete;
2302
2303 void Grow(size_t size);
2304 void EnsureThreadAffinity();
2305 void CheckState() const;
2306
2307 size_t Capacity() const
2308 {
2309 WRAPPER_NO_CONTRACT;
2310 assert(!!m_array);
2311
2312 return m_array->GetNumComponents();
2313 }
2314
2315 size_t GetSize() const
2316 {
2317 WRAPPER_NO_CONTRACT;
2318 return GetHeader()->m_size;
2319 }
2320
2321 void SetSize(size_t size)
2322 {
2323 WRAPPER_NO_CONTRACT;
2324 GetHeader()->m_size = size;
2325 }
2326
2327 Thread * GetObjectThread() const
2328 {
2329 WRAPPER_NO_CONTRACT;
2330 return GetHeader()->m_thread;
2331 }
2332
2333 void SetObjectThread()
2334 {
2335 WRAPPER_NO_CONTRACT;
2336 GetHeader()->m_thread = GetThread();
2337 }
2338
2339 StackTraceElement const * GetData() const
2340 {
2341 WRAPPER_NO_CONTRACT;
2342 SUPPORTS_DAC;
2343 return dac_cast<PTR_StackTraceElement>(GetRaw() + sizeof(ArrayHeader));
2344 }
2345
2346 PTR_StackTraceElement GetData()
2347 {
2348 WRAPPER_NO_CONTRACT;
2349 SUPPORTS_DAC;
2350 return dac_cast<PTR_StackTraceElement>(GetRaw() + sizeof(ArrayHeader));
2351 }
2352
2353 I1 const * GetRaw() const
2354 {
2355 WRAPPER_NO_CONTRACT;
2356 assert(!!m_array);
2357
2358 return const_cast<I1ARRAYREF &>(m_array)->GetDirectPointerToNonObjectElements();
2359 }
2360
2361 PTR_I1 GetRaw()
2362 {
2363 WRAPPER_NO_CONTRACT;
2364 SUPPORTS_DAC;
2365 assert(!!m_array);
2366
2367 return dac_cast<PTR_I1>(m_array->GetDirectPointerToNonObjectElements());
2368 }
2369
2370 ArrayHeader const * GetHeader() const
2371 {
2372 WRAPPER_NO_CONTRACT;
2373 SUPPORTS_DAC;
2374 return dac_cast<PTR_ArrayHeader>(GetRaw());
2375 }
2376
2377 PTR_ArrayHeader GetHeader()
2378 {
2379 WRAPPER_NO_CONTRACT;
2380 SUPPORTS_DAC;
2381 return dac_cast<PTR_ArrayHeader>(GetRaw());
2382 }
2383
2384 void SetArray(I1ARRAYREF const & arr)
2385 {
2386 LIMITED_METHOD_CONTRACT;
2387 m_array = arr;
2388 }
2389
2390private:
2391 // put only things here that can be protected with GCPROTECT
2392 I1ARRAYREF m_array;
2393};
2394
2395#ifdef FEATURE_COLLECTIBLE_TYPES
2396
2397class LoaderAllocatorScoutObject : public Object
2398{
2399 friend class MscorlibBinder;
2400 friend class LoaderAllocatorObject;
2401
2402protected:
2403 LoaderAllocator * m_nativeLoaderAllocator;
2404};
2405
2406#ifdef USE_CHECKED_OBJECTREFS
2407typedef REF<LoaderAllocatorScoutObject> LOADERALLOCATORSCOUTREF;
2408#else // USE_CHECKED_OBJECTREFS
2409typedef LoaderAllocatorScoutObject* LOADERALLOCATORSCOUTREF;
2410#endif // USE_CHECKED_OBJECTREFS
2411
2412class LoaderAllocatorObject : public Object
2413{
2414 friend class MscorlibBinder;
2415
2416public:
2417 PTRARRAYREF GetHandleTable()
2418 {
2419 LIMITED_METHOD_DAC_CONTRACT;
2420 return (PTRARRAYREF)m_pSlots;
2421 }
2422
2423 void SetHandleTable(PTRARRAYREF handleTable)
2424 {
2425 LIMITED_METHOD_CONTRACT;
2426 SetObjectReferenceUnchecked(&m_pSlots, (OBJECTREF)handleTable);
2427 }
2428
2429 INT32 GetSlotsUsed()
2430 {
2431 LIMITED_METHOD_CONTRACT;
2432 return m_slotsUsed;
2433 }
2434
2435 void SetSlotsUsed(INT32 newSlotsUsed)
2436 {
2437 LIMITED_METHOD_CONTRACT;
2438 m_slotsUsed = newSlotsUsed;
2439 }
2440
2441 void SetNativeLoaderAllocator(LoaderAllocator * pLoaderAllocator)
2442 {
2443 LIMITED_METHOD_CONTRACT;
2444 m_pLoaderAllocatorScout->m_nativeLoaderAllocator = pLoaderAllocator;
2445 }
2446
2447 // README:
2448 // If you modify the order of these fields, make sure to update the definition in
2449 // BCL for this object.
2450protected:
2451 LOADERALLOCATORSCOUTREF m_pLoaderAllocatorScout;
2452 OBJECTREF m_pSlots;
2453 INT32 m_slotsUsed;
2454 OBJECTREF m_methodInstantiationsTable;
2455};
2456
2457#ifdef USE_CHECKED_OBJECTREFS
2458typedef REF<LoaderAllocatorObject> LOADERALLOCATORREF;
2459#else // USE_CHECKED_OBJECTREFS
2460typedef DPTR(LoaderAllocatorObject) PTR_LoaderAllocatorObject;
2461typedef PTR_LoaderAllocatorObject LOADERALLOCATORREF;
2462#endif // USE_CHECKED_OBJECTREFS
2463
2464#endif // FEATURE_COLLECTIBLE_TYPES
2465
2466#if !defined(DACCESS_COMPILE)
2467// Define the lock used to access stacktrace from an exception object
2468EXTERN_C SpinLock g_StackTraceArrayLock;
2469#endif // !defined(DACCESS_COMPILE)
2470
2471// This class corresponds to Exception on the managed side.
2472typedef DPTR(class ExceptionObject) PTR_ExceptionObject;
2473#include "pshpack4.h"
2474class ExceptionObject : public Object
2475{
2476 friend class MscorlibBinder;
2477
2478public:
2479 void SetHResult(HRESULT hr)
2480 {
2481 LIMITED_METHOD_CONTRACT;
2482 _HResult = hr;
2483 }
2484
2485 HRESULT GetHResult()
2486 {
2487 LIMITED_METHOD_CONTRACT;
2488 return _HResult;
2489 }
2490
2491 void SetXCode(DWORD code)
2492 {
2493 LIMITED_METHOD_CONTRACT;
2494 _xcode = code;
2495 }
2496
2497 DWORD GetXCode()
2498 {
2499 LIMITED_METHOD_CONTRACT;
2500 return _xcode;
2501 }
2502
2503 void SetXPtrs(void* xptrs)
2504 {
2505 LIMITED_METHOD_CONTRACT;
2506 _xptrs = xptrs;
2507 }
2508
2509 void* GetXPtrs()
2510 {
2511 LIMITED_METHOD_CONTRACT;
2512 return _xptrs;
2513 }
2514
2515 void SetStackTrace(StackTraceArray const & stackTrace, PTRARRAYREF dynamicMethodArray);
2516 void SetNullStackTrace();
2517
2518 void GetStackTrace(StackTraceArray & stackTrace, PTRARRAYREF * outDynamicMethodArray = NULL) const;
2519
2520#ifdef DACCESS_COMPILE
2521 I1ARRAYREF GetStackTraceArrayObject() const
2522 {
2523 LIMITED_METHOD_DAC_CONTRACT;
2524 return _stackTrace;
2525 }
2526#endif // DACCESS_COMPILE
2527
2528 void SetInnerException(OBJECTREF innerException)
2529 {
2530 WRAPPER_NO_CONTRACT;
2531 SetObjectReference((OBJECTREF*)&_innerException, (OBJECTREF)innerException, GetAppDomain());
2532 }
2533
2534 OBJECTREF GetInnerException()
2535 {
2536 LIMITED_METHOD_DAC_CONTRACT;
2537 return _innerException;
2538 }
2539
2540 // Returns the innermost exception object - equivalent of the
2541 // managed System.Exception.GetBaseException method.
2542 OBJECTREF GetBaseException()
2543 {
2544 LIMITED_METHOD_CONTRACT;
2545
2546 // Loop and get the innermost exception object
2547 OBJECTREF oInnerMostException = NULL;
2548 OBJECTREF oCurrent = NULL;
2549
2550 oCurrent = _innerException;
2551 while(oCurrent != NULL)
2552 {
2553 oInnerMostException = oCurrent;
2554 oCurrent = ((ExceptionObject*)(Object *)OBJECTREFToObject(oCurrent))->GetInnerException();
2555 }
2556
2557 // return the innermost exception
2558 return oInnerMostException;
2559 }
2560
2561 void SetMessage(STRINGREF message)
2562 {
2563 WRAPPER_NO_CONTRACT;
2564 SetObjectReference((OBJECTREF*)&_message, (OBJECTREF)message, GetAppDomain());
2565 }
2566
2567 STRINGREF GetMessage()
2568 {
2569 LIMITED_METHOD_DAC_CONTRACT;
2570 return _message;
2571 }
2572
2573 void SetStackTraceString(STRINGREF stackTraceString)
2574 {
2575 WRAPPER_NO_CONTRACT;
2576 SetObjectReference((OBJECTREF*)&_stackTraceString, (OBJECTREF)stackTraceString, GetAppDomain());
2577 }
2578
2579 STRINGREF GetStackTraceString()
2580 {
2581 LIMITED_METHOD_DAC_CONTRACT;
2582 return _stackTraceString;
2583 }
2584
2585 STRINGREF GetRemoteStackTraceString()
2586 {
2587 LIMITED_METHOD_DAC_CONTRACT;
2588 return _remoteStackTraceString;
2589 }
2590
2591 void SetHelpURL(STRINGREF helpURL)
2592 {
2593 WRAPPER_NO_CONTRACT;
2594 SetObjectReference((OBJECTREF*)&_helpURL, (OBJECTREF)helpURL, GetAppDomain());
2595 }
2596
2597 void SetSource(STRINGREF source)
2598 {
2599 WRAPPER_NO_CONTRACT;
2600 SetObjectReference((OBJECTREF*)&_source, (OBJECTREF)source, GetAppDomain());
2601 }
2602
2603 void ClearStackTraceForThrow()
2604 {
2605 WRAPPER_NO_CONTRACT;
2606 SetObjectReferenceUnchecked((OBJECTREF*)&_remoteStackTraceString, NULL);
2607 SetObjectReferenceUnchecked((OBJECTREF*)&_stackTrace, NULL);
2608 SetObjectReferenceUnchecked((OBJECTREF*)&_stackTraceString, NULL);
2609 }
2610
2611 void ClearStackTracePreservingRemoteStackTrace()
2612 {
2613 WRAPPER_NO_CONTRACT;
2614 SetObjectReferenceUnchecked((OBJECTREF*)&_stackTrace, NULL);
2615 SetObjectReferenceUnchecked((OBJECTREF*)&_stackTraceString, NULL);
2616 }
2617
2618 // This method will set the reference to the array
2619 // containing the watson bucket information (in byte[] form).
2620 void SetWatsonBucketReference(OBJECTREF oWatsonBucketArray)
2621 {
2622 WRAPPER_NO_CONTRACT;
2623 SetObjectReference((OBJECTREF*)&_watsonBuckets, (OBJECTREF)oWatsonBucketArray, GetAppDomain());
2624 }
2625
2626 // This method will return the reference to the array
2627 // containing the watson buckets
2628 U1ARRAYREF GetWatsonBucketReference()
2629 {
2630 LIMITED_METHOD_CONTRACT;
2631 return _watsonBuckets;
2632 }
2633
2634 // This method will return a BOOL to indicate if the
2635 // watson buckets are present or not.
2636 BOOL AreWatsonBucketsPresent()
2637 {
2638 LIMITED_METHOD_CONTRACT;
2639 return (_watsonBuckets != NULL)?TRUE:FALSE;
2640 }
2641
2642 // This method will save the IP to be used for watson bucketing.
2643 void SetIPForWatsonBuckets(UINT_PTR ip)
2644 {
2645 LIMITED_METHOD_CONTRACT;
2646
2647 _ipForWatsonBuckets = ip;
2648 }
2649
2650 // This method will return a BOOL to indicate if Watson bucketing IP
2651 // is present (or not).
2652 BOOL IsIPForWatsonBucketsPresent()
2653 {
2654 LIMITED_METHOD_CONTRACT;
2655
2656 return (_ipForWatsonBuckets != NULL);
2657 }
2658
2659 // This method returns the IP for Watson Buckets.
2660 UINT_PTR GetIPForWatsonBuckets()
2661 {
2662 LIMITED_METHOD_CONTRACT;
2663
2664 return _ipForWatsonBuckets;
2665 }
2666
2667 // README:
2668 // If you modify the order of these fields, make sure to update the definition in
2669 // BCL for this object.
2670private:
2671 STRINGREF _className; //Needed for serialization.
2672 OBJECTREF _exceptionMethod; //Needed for serialization.
2673 STRINGREF _message;
2674 OBJECTREF _data;
2675 OBJECTREF _innerException;
2676 STRINGREF _helpURL;
2677 I1ARRAYREF _stackTrace;
2678 U1ARRAYREF _watsonBuckets;
2679 STRINGREF _stackTraceString; //Needed for serialization.
2680 STRINGREF _remoteStackTraceString;
2681 PTRARRAYREF _dynamicMethods;
2682 STRINGREF _source; // Mainly used by VB.
2683
2684 IN_WIN64(void* _xptrs;)
2685 IN_WIN64(UINT_PTR _ipForWatsonBuckets;) // Contains the IP of exception for watson bucketing
2686 INT32 _remoteStackIndex;
2687 INT32 _HResult;
2688 IN_WIN32(void* _xptrs;)
2689 INT32 _xcode;
2690 IN_WIN32(UINT_PTR _ipForWatsonBuckets;) // Contains the IP of exception for watson bucketing
2691};
2692
2693// Defined in Contracts.cs
2694enum ContractFailureKind
2695{
2696 CONTRACT_FAILURE_PRECONDITION = 0,
2697 CONTRACT_FAILURE_POSTCONDITION,
2698 CONTRACT_FAILURE_POSTCONDITION_ON_EXCEPTION,
2699 CONTRACT_FAILURE_INVARIANT,
2700 CONTRACT_FAILURE_ASSERT,
2701 CONTRACT_FAILURE_ASSUME,
2702};
2703
2704typedef DPTR(class ContractExceptionObject) PTR_ContractExceptionObject;
2705class ContractExceptionObject : public ExceptionObject
2706{
2707 friend class MscorlibBinder;
2708
2709public:
2710 ContractFailureKind GetContractFailureKind()
2711 {
2712 LIMITED_METHOD_CONTRACT;
2713
2714 return static_cast<ContractFailureKind>(_Kind);
2715 }
2716
2717private:
2718 // keep these in sync with ndp/clr/src/bcl/system/diagnostics/contracts/contractsbcl.cs
2719 IN_WIN64(INT32 _Kind;)
2720 STRINGREF _UserMessage;
2721 STRINGREF _Condition;
2722 IN_WIN32(INT32 _Kind;)
2723};
2724#include "poppack.h"
2725
2726#ifdef USE_CHECKED_OBJECTREFS
2727typedef REF<ContractExceptionObject> CONTRACTEXCEPTIONREF;
2728#else // USE_CHECKED_OBJECTREFS
2729typedef PTR_ContractExceptionObject CONTRACTEXCEPTIONREF;
2730#endif // USE_CHECKED_OBJECTREFS
2731
2732//===============================================================================
2733// #NullableFeature
2734// #NullableArchitecture
2735//
2736// In a nutshell it is counterintuitive to have a boxed Nullable<T>, since a boxed
2737// object already has a representation for null (the null pointer), and having
2738// multiple representations for the 'not present' value just causes grief. Thus the
2739// feature is build make Nullable<T> box to a boxed<T> (not boxed<Nullable<T>).
2740//
2741// We want to do this in a way that does not impact the perf of the runtime in the
2742// non-nullable case.
2743//
2744// To do this we need to
2745// * Modify the boxing helper code:JIT_Box (we don't need a special one because
2746// the JIT inlines the common case, so this only gets call in uncommon cases)
2747// * Make a new helper for the Unbox case (see code:JIT_Unbox_Nullable)
2748// * Plumb the JIT to ask for what kind of Boxing helper is needed
2749// (see code:CEEInfo.getBoxHelper, code:CEEInfo.getUnBoxHelper
2750// * change all the places in the CLR where we box or unbox by hand, and force
2751// them to use code:MethodTable.Box, and code:MethodTable.Unbox which in
2752// turn call code:Nullable.Box and code:Nullable.UnBox, most of these
2753// are in reflection, and remoting (passing and returning value types).
2754//
2755// #NullableVerification
2756//
2757// Sadly, the IL Verifier also needs to know about this change. Basically the 'box'
2758// instruction returns a boxed(T) (not a boxed(Nullable<T>)) for the purposes of
2759// verfication. The JIT finds out what box returns by calling back to the EE with
2760// the code:CEEInfo.getTypeForBox API.
2761//
2762// #NullableDebugging
2763//
2764// Sadly, because the debugger also does its own boxing 'by hand' for expression
2765// evaluation inside visual studio, it measn that debuggers also need to be aware
2766// of the fact that Nullable<T> boxes to a boxed<T>. It is the responcibility of
2767// debuggers to follow this convention (which is why this is sad).
2768//
2769
2770//===============================================================================
2771// Nullable represents the managed generic value type Nullable<T>
2772//
2773// The runtime has special logic for this value class. When it is boxed
2774// it becomes either null or a boxed T. Similarly a boxed T can be unboxed
2775// either as a T (as normal), or as a Nullable<T>
2776//
2777// See code:Nullable#NullableArchitecture for more.
2778//
2779class Nullable {
2780 Nullable(); // This is purposefully undefined. Do not make instances
2781 // of this class.
2782public:
2783 static void CheckFieldOffsets(TypeHandle nullableType);
2784 static BOOL IsNullableType(TypeHandle nullableType);
2785 static BOOL IsNullableForType(TypeHandle nullableType, MethodTable* paramMT);
2786 static BOOL IsNullableForTypeNoGC(TypeHandle nullableType, MethodTable* paramMT);
2787
2788 static OBJECTREF Box(void* src, MethodTable* nullable);
2789 static BOOL UnBox(void* dest, OBJECTREF boxedVal, MethodTable* destMT);
2790 static BOOL UnBoxNoGC(void* dest, OBJECTREF boxedVal, MethodTable* destMT);
2791 static BOOL UnBoxIntoArgNoGC(ArgDestination *argDest, OBJECTREF boxedVal, MethodTable* destMT);
2792 static void UnBoxNoCheck(void* dest, OBJECTREF boxedVal, MethodTable* destMT);
2793 static OBJECTREF BoxedNullableNull(TypeHandle nullableType) { return 0; }
2794
2795 // if 'Obj' is a true boxed nullable, return the form we want (either null or a boxed T)
2796 static OBJECTREF NormalizeBox(OBJECTREF obj);
2797
2798 static inline CLR_BOOL HasValue(void *src, MethodTable *nullableMT)
2799 {
2800 Nullable *nullable = (Nullable *)src;
2801 return *(nullable->HasValueAddr(nullableMT));
2802 }
2803
2804 static inline void *Value(void *src, MethodTable *nullableMT)
2805 {
2806 Nullable *nullable = (Nullable *)src;
2807 return nullable->ValueAddr(nullableMT);
2808 }
2809
2810private:
2811 static BOOL IsNullableForTypeHelper(MethodTable* nullableMT, MethodTable* paramMT);
2812 static BOOL IsNullableForTypeHelperNoGC(MethodTable* nullableMT, MethodTable* paramMT);
2813
2814 CLR_BOOL* HasValueAddr(MethodTable* nullableMT);
2815 void* ValueAddr(MethodTable* nullableMT);
2816};
2817
2818#ifdef USE_CHECKED_OBJECTREFS
2819typedef REF<ExceptionObject> EXCEPTIONREF;
2820#else // USE_CHECKED_OBJECTREFS
2821typedef PTR_ExceptionObject EXCEPTIONREF;
2822#endif // USE_CHECKED_OBJECTREFS
2823
2824#endif // _OBJECT_H_
2825