191c7a15835691ac0cd5c26b27d8df3dbe770b78
[platform/upstream/coreclr.git] / src / gc / env / gcenv.object.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 #ifndef __GCENV_OBJECT_H__
6 #define __GCENV_OBJECT_H__
7
8 //-------------------------------------------------------------------------------------------------
9 //
10 // Low-level types describing GC object layouts.
11 //
12
13 // Bits stolen from the sync block index that the GC/HandleTable knows about (currently these are at the same
14 // positions as the mainline runtime but we can change this below when it becomes apparent how Redhawk will
15 // handle sync blocks).
16 #define BIT_SBLK_GC_RESERVE                 0x20000000
17 #define BIT_SBLK_FINALIZER_RUN              0x40000000
18
19 // The sync block index header (small structure that immediately precedes every object in the GC heap). Only
20 // the GC uses this so far, and only to store a couple of bits of information.
21 class ObjHeader
22 {
23 private:
24 #if defined(BIT64)
25     uint32_t m_uAlignpad;
26 #endif // BIT64
27     uint32_t m_uSyncBlockValue;
28
29 public:
30     uint32_t GetBits() { return m_uSyncBlockValue; }
31     void SetBit(uint32_t uBit) { Interlocked::Or(&m_uSyncBlockValue, uBit); }
32     void ClrBit(uint32_t uBit) { Interlocked::And(&m_uSyncBlockValue, ~uBit); }
33     void SetGCBit() { m_uSyncBlockValue |= BIT_SBLK_GC_RESERVE; }
34     void ClrGCBit() { m_uSyncBlockValue &= ~BIT_SBLK_GC_RESERVE; }
35 };
36
37 static_assert(sizeof(ObjHeader) == sizeof(uintptr_t), "this assumption is made by the VM!");
38
39 #define MTFlag_ContainsPointers     0x0100
40 #define MTFlag_HasCriticalFinalizer 0x0800
41 #define MTFlag_HasFinalizer         0x0010
42 #define MTFlag_IsArray              0x0008
43 #define MTFlag_Collectible          0x1000
44 #define MTFlag_HasComponentSize     0x8000
45
46 class MethodTable
47 {
48 public:
49     uint16_t    m_componentSize;
50     uint16_t    m_flags;
51     uint32_t    m_baseSize;
52
53     MethodTable * m_pRelatedType;
54
55 public:
56     void InitializeFreeObject()
57     {
58         m_baseSize = 3 * sizeof(void *);
59         m_componentSize = 1;
60         m_flags = MTFlag_HasComponentSize | MTFlag_IsArray;
61     }
62
63     uint32_t GetBaseSize()
64     {
65         return m_baseSize;
66     }
67
68     uint16_t RawGetComponentSize()
69     {
70         return m_componentSize;
71     }
72
73     bool Collectible()
74     {
75         return (m_flags & MTFlag_Collectible) != 0;
76     }
77
78     bool ContainsPointers()
79     {
80         return (m_flags & MTFlag_ContainsPointers) != 0;
81     }
82
83     bool ContainsPointersOrCollectible()
84     {
85         return ContainsPointers() || Collectible();
86     }
87
88     bool HasComponentSize()
89     {
90         // Note that we can't just check m_componentSize != 0 here. The VM 
91         // may still construct a method table that does not have a component 
92         // size, according to this method, but still has a number in the low 
93         // 16 bits of the method table flags parameter.
94         //
95         // The solution here is to do what the VM does and check the
96         // HasComponentSize flag so that we're on the same page.
97         return (m_flags & MTFlag_HasComponentSize) != 0;
98     }
99
100     bool HasFinalizer()
101     {
102         return (m_flags & MTFlag_HasFinalizer) != 0;
103     }
104
105     bool HasCriticalFinalizer()
106     {
107         return (m_flags & MTFlag_HasCriticalFinalizer) != 0;
108     }
109
110     bool IsArray()
111     {
112         return (m_flags & MTFlag_IsArray) != 0;
113     }
114
115     MethodTable * GetParent()
116     {
117         _ASSERTE(!IsArray());
118         return m_pRelatedType;
119     }
120
121     bool SanityCheck()
122     {
123         return true;
124     }
125
126     uint8_t* GetLoaderAllocatorObjectForGC()
127     {
128         // [LOCALGC TODO] this is not correct
129         return nullptr;
130     }
131 };
132
133 class Object
134 {
135     MethodTable * m_pMethTab;
136
137 public:
138     ObjHeader * GetHeader()
139     { 
140         return ((ObjHeader *)this) - 1;
141     }
142
143     MethodTable * RawGetMethodTable() const
144     {
145         return m_pMethTab;
146     }
147
148     MethodTable * GetGCSafeMethodTable() const
149     {
150         return (MethodTable *)((uintptr_t)m_pMethTab & ~3);
151     }
152
153     void RawSetMethodTable(MethodTable * pMT)
154     {
155         m_pMethTab = pMT;
156     }
157 };
158 #define MIN_OBJECT_SIZE     (2*sizeof(uint8_t*) + sizeof(ObjHeader))
159
160 class ArrayBase : public Object
161 {
162     uint32_t m_dwLength;
163
164 public:
165     uint32_t GetNumComponents()
166     {
167         return m_dwLength;
168     }
169
170     static size_t GetOffsetOfNumComponents()
171     {
172         return offsetof(ArrayBase, m_dwLength);
173     }
174 };
175
176 #endif // __GCENV_OBJECT_H__