Fix reading Time zone rules using Julian days (#17672)
[platform/upstream/coreclr.git] / src / jit / alloc.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 _ALLOC_H_
6 #define _ALLOC_H_
7
8 #if !defined(_HOST_H_)
9 #include "host.h"
10 #endif // defined(_HOST_H_)
11
12 class ArenaAllocator
13 {
14 private:
15     ArenaAllocator(const ArenaAllocator& other) = delete;
16     ArenaAllocator& operator=(const ArenaAllocator& other) = delete;
17
18 protected:
19     struct PageDescriptor
20     {
21         PageDescriptor* m_next;
22         PageDescriptor* m_previous;
23
24         size_t m_pageBytes; // # of bytes allocated
25         size_t m_usedBytes; // # of bytes actually used. (This is only valid when we've allocated a new page.)
26                             // See ArenaAllocator::allocateNewPage.
27
28         BYTE m_contents[];
29     };
30
31     // Anything less than 64K leaves VM holes since the OS allocates address space in this size.
32     // Thus if we want to make this smaller, we need to do a reserve / commit scheme
33     enum
34     {
35         DEFAULT_PAGE_SIZE = 16 * OS_page_size,
36         MIN_PAGE_SIZE     = sizeof(PageDescriptor)
37     };
38
39     static size_t s_defaultPageSize;
40
41     IEEMemoryManager* m_memoryManager;
42
43     PageDescriptor* m_firstPage;
44     PageDescriptor* m_lastPage;
45
46     // These two pointers (when non-null) will always point into 'm_lastPage'.
47     BYTE* m_nextFreeByte;
48     BYTE* m_lastFreeByte;
49
50     bool isInitialized();
51
52     void* allocateNewPage(size_t size, bool canThrow);
53
54     void* allocateHostMemory(size_t size);
55     void freeHostMemory(void* block);
56
57 public:
58     ArenaAllocator();
59     ArenaAllocator(IEEMemoryManager* memoryManager);
60     ArenaAllocator& operator=(ArenaAllocator&& other);
61
62     // NOTE: it would be nice to have a destructor on this type to ensure that any value that
63     //       goes out of scope is either uninitialized or has been torn down via a call to
64     //       destroy(), but this interacts badly in methods that use SEH. #3058 tracks
65     //       revisiting EH in the JIT; such a destructor could be added if SEH is removed
66     //       as part of that work.
67
68     virtual void destroy();
69
70     inline void* allocateMemory(size_t sz);
71
72     size_t getTotalBytesAllocated();
73     size_t getTotalBytesUsed();
74
75     static bool   bypassHostAllocator();
76     static size_t getDefaultPageSize();
77
78     static void startup();
79     static void shutdown();
80
81     static ArenaAllocator* getPooledAllocator(IEEMemoryManager* memoryManager);
82 };
83
84 //------------------------------------------------------------------------
85 // ArenaAllocator::allocateMemory:
86 //    Allocates memory using an `ArenaAllocator`.
87 //
88 // Arguments:
89 //    size - The number of bytes to allocate.
90 //
91 // Return Value:
92 //    A pointer to the allocated memory.
93 //
94 // Note:
95 //    The DEBUG version of the method has some abilities that the release
96 //    version does not: it may inject faults into the allocator and
97 //    seeds all allocations with a specified pattern to help catch
98 //    use-before-init problems.
99 //
100 inline void* ArenaAllocator::allocateMemory(size_t size)
101 {
102     assert(isInitialized());
103     assert(size != 0);
104
105     // Ensure that we always allocate in pointer sized increments.
106     size = (size_t)roundUp(size, sizeof(size_t));
107
108 #if defined(DEBUG)
109     if (JitConfig.ShouldInjectFault() != 0)
110     {
111         // Force the underlying memory allocator (either the OS or the CLR hoster)
112         // to allocate the memory. Any fault injection will kick in.
113         void* p = ClrAllocInProcessHeap(0, S_SIZE_T(1));
114         if (p != nullptr)
115         {
116             ClrFreeInProcessHeap(0, p);
117         }
118         else
119         {
120             NOMEM(); // Throw!
121         }
122     }
123 #endif
124
125     void* block = m_nextFreeByte;
126     m_nextFreeByte += size;
127
128     if (m_nextFreeByte > m_lastFreeByte)
129     {
130         block = allocateNewPage(size, true);
131     }
132
133 #if defined(DEBUG)
134     memset(block, UninitializedWord<char>(nullptr), size);
135 #endif
136
137     return block;
138 }
139
140 #endif // _ALLOC_H_