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 |
22 | { |
23 | private: |
24 | #if defined(BIT64) |
25 | uint32_t ; |
26 | #endif // BIT64 |
27 | uint32_t ; |
28 | |
29 | public: |
30 | uint32_t () { return m_uSyncBlockValue; } |
31 | void (uint32_t uBit) { Interlocked::Or(&m_uSyncBlockValue, uBit); } |
32 | void (uint32_t uBit) { Interlocked::And(&m_uSyncBlockValue, ~uBit); } |
33 | void () { m_uSyncBlockValue |= BIT_SBLK_GC_RESERVE; } |
34 | void () { 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 | |
127 | class Object |
128 | { |
129 | MethodTable * m_pMethTab; |
130 | |
131 | public: |
132 | ObjHeader * () |
133 | { |
134 | return ((ObjHeader *)this) - 1; |
135 | } |
136 | |
137 | MethodTable * RawGetMethodTable() const |
138 | { |
139 | return m_pMethTab; |
140 | } |
141 | |
142 | MethodTable * GetGCSafeMethodTable() const |
143 | { |
144 | return (MethodTable *)((uintptr_t)m_pMethTab & ~3); |
145 | } |
146 | |
147 | void RawSetMethodTable(MethodTable * pMT) |
148 | { |
149 | m_pMethTab = pMT; |
150 | } |
151 | }; |
152 | #define MIN_OBJECT_SIZE (2*sizeof(uint8_t*) + sizeof(ObjHeader)) |
153 | |
154 | class ArrayBase : public Object |
155 | { |
156 | uint32_t m_dwLength; |
157 | |
158 | public: |
159 | uint32_t GetNumComponents() |
160 | { |
161 | return m_dwLength; |
162 | } |
163 | |
164 | static size_t GetOffsetOfNumComponents() |
165 | { |
166 | return offsetof(ArrayBase, m_dwLength); |
167 | } |
168 | }; |
169 | |
170 | #endif // __GCENV_OBJECT_H__ |
171 | |