summaryrefslogtreecommitdiff
path: root/src/gc/env/gcenv.object.h
blob: db8995a118e9f1a18cbab971e7e9cdf0d65a719e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

//-------------------------------------------------------------------------------------------------
//
// Low-level types describing GC object layouts.
//

// Bits stolen from the sync block index that the GC/HandleTable knows about (currently these are at the same
// positions as the mainline runtime but we can change this below when it becomes apparent how Redhawk will
// handle sync blocks).
#define BIT_SBLK_GC_RESERVE                 0x20000000
#define BIT_SBLK_FINALIZER_RUN              0x40000000

// The sync block index header (small structure that immediately precedes every object in the GC heap). Only
// the GC uses this so far, and only to store a couple of bits of information.
class ObjHeader
{
private:
#if defined(BIT64)
    uint32_t m_uAlignpad;
#endif // BIT64
    uint32_t m_uSyncBlockValue;

public:
    uint32_t GetBits() { return m_uSyncBlockValue; }
    void SetBit(uint32_t uBit) { Interlocked::Or(&m_uSyncBlockValue, uBit); }
    void ClrBit(uint32_t uBit) { Interlocked::And(&m_uSyncBlockValue, ~uBit); }
    void SetGCBit() { m_uSyncBlockValue |= BIT_SBLK_GC_RESERVE; }
    void ClrGCBit() { m_uSyncBlockValue &= ~BIT_SBLK_GC_RESERVE; }
};

static_assert(sizeof(ObjHeader) == sizeof(uintptr_t), "this assumption is made by the VM!");

#define MTFlag_ContainsPointers 1
#define MTFlag_HasFinalizer 2
#define MTFlag_IsArray 4

class MethodTable
{
public:
    uint16_t    m_componentSize;
    uint16_t    m_flags;
    uint32_t    m_baseSize;

    MethodTable * m_pRelatedType;

public:
    void InitializeFreeObject()
    {
        m_baseSize = 3 * sizeof(void *);
        m_componentSize = 1;
        m_flags = 0;
    }

    uint32_t GetBaseSize()
    {
        return m_baseSize;
    }

    uint16_t RawGetComponentSize()
    {
        return m_componentSize;
    }

    bool ContainsPointers()
    {
        return (m_flags & MTFlag_ContainsPointers) != 0;
    }

    bool ContainsPointersOrCollectible()
    {
        return ContainsPointers();
    }

    bool HasComponentSize()
    {
        return m_componentSize != 0;
    }

    bool HasFinalizer()
    {
        return (m_flags & MTFlag_HasFinalizer) != 0;
    }

    bool HasCriticalFinalizer()
    {
        return false;
    }

    bool IsArray()
    {
        return (m_flags & MTFlag_IsArray) != 0;
    }

    MethodTable * GetParent()
    {
        _ASSERTE(!IsArray());
        return m_pRelatedType;
    }

    bool SanityCheck()
    {
        return true;
    }
};

class Object
{
    MethodTable * m_pMethTab;

public:
    ObjHeader * GetHeader()
    { 
        return ((ObjHeader *)this) - 1;
    }

    MethodTable * RawGetMethodTable() const
    {
        return m_pMethTab;
    }

    MethodTable * GetGCSafeMethodTable() const
    {
        return (MethodTable *)((uintptr_t)m_pMethTab & ~3);
    }

    void RawSetMethodTable(MethodTable * pMT)
    {
        m_pMethTab = pMT;
    }
};
#define MIN_OBJECT_SIZE     (2*sizeof(uint8_t*) + sizeof(ObjHeader))

class ArrayBase : public Object
{
    uint32_t m_dwLength;

public:
    uint32_t GetNumComponents()
    {
        return m_dwLength;
    }

    static size_t GetOffsetOfNumComponents()
    {
        return offsetof(ArrayBase, m_dwLength);
    }
};