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.
21class ObjHeader
22{
23private:
24#if defined(BIT64)
25 uint32_t m_uAlignpad;
26#endif // BIT64
27 uint32_t m_uSyncBlockValue;
28
29public:
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
37static_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
46class MethodTable
47{
48public:
49 uint16_t m_componentSize;
50 uint16_t m_flags;
51 uint32_t m_baseSize;
52
53 MethodTable * m_pRelatedType;
54
55public:
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
127class Object
128{
129 MethodTable * m_pMethTab;
130
131public:
132 ObjHeader * GetHeader()
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
154class ArrayBase : public Object
155{
156 uint32_t m_dwLength;
157
158public:
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