-
Notifications
You must be signed in to change notification settings - Fork 393
/
HeapRegionManager.hpp
425 lines (374 loc) · 18 KB
/
HeapRegionManager.hpp
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
/*******************************************************************************
* Copyright (c) 1991, 2015 IBM Corp. and others
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
* or the Apache License, Version 2.0 which accompanies this distribution and
* is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* This Source Code may also be made available under the following
* Secondary Licenses when the conditions for such availability set
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
* General Public License, version 2 with the GNU Classpath
* Exception [1] and GNU General Public License, version 2 with the
* OpenJDK Assembly Exception [2].
*
* [1] https://www.gnu.org/software/classpath/license.html
* [2] http://openjdk.java.net/legal/assembly-exception.html
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
*******************************************************************************/
#if !defined(HEAPREGIONMANAGER_HPP)
#define HEAPREGIONMANAGER_HPP
#include "omrcomp.h"
#include "modronbase.h"
#include "BaseVirtual.hpp"
#include "HeapRegionDescriptor.hpp"
#include "LightweightNonReentrantRWLock.hpp"
#include "ModronAssertions.h"
class MM_EnvironmentBase;
class MM_HeapRegionManager;
class MM_MemoryHandle;
class MM_MemorySubSpace;
class MM_HeapMemorySnapshot;
/**
* A function pointer used to initialize newly allocated HRDs.
*
* The function is responsible for invoking a constructor on the descriptor.
*
* @param[in] env - the current env
* @param[in] regionManager - the regionManager which owns the descriptor
* @param[in] descriptor - the uninitialized descriptor
* @param[in] lowAddress - the lowest address in the region
* @param[in] highAddress - the address of the first byte beyond the region
*
* @return true if the initialization succeeded, false otherwise
*/
typedef bool (*MM_RegionDescriptorInitializer)(MM_EnvironmentBase* env, MM_HeapRegionManager* regionManager, MM_HeapRegionDescriptor* descriptor, void* lowAddress, void* highAddress);
/**
* A function pointer used to destroy HRDs on shutdown.
*
* @param[in] env - the current env
* @param[in] regionManager - the regionManager which owns the descriptor
* @param[in] descriptor - the descriptor to be destroyed
*/
typedef void (*MM_RegionDescriptorDestructor)(MM_EnvironmentBase* env, MM_HeapRegionManager* regionManager, MM_HeapRegionDescriptor* descriptor);
class MM_HeapRegionManager : public MM_BaseVirtual {
friend class GC_HeapRegionIterator;
public:
protected:
friend class MM_InterRegionRememberedSet;
MM_LightweightNonReentrantRWLock _heapRegionListMonitor; /**< monitor that controls modification of the heap region linked list */
MM_HeapRegionDescriptor* _auxRegionDescriptorList; /**< address ordered doubly linked list for auxiliary heap regions */
uintptr_t _auxRegionCount; /**< number of heap regions on the auxiliary list */
/* Heap Region Table data */
uintptr_t _regionSize; /**< the size, in bytes, of a region in the _regionTable */
uintptr_t _regionShift; /**< the shift value to use against pointers to determine the corresponding region index */
MM_HeapRegionDescriptor* _regionTable; /**< the raw array of fixed-sized regions for representing a flat heap */
uintptr_t _tableRegionCount; /**< number of heap regions on the fixed-sized table (_regionTable) */
void* _lowTableEdge; /**< the first (lowest address) byte of heap which is addressable by the table */
void* _highTableEdge; /**< the first byte AFTER the heap range which is addressable by the table */
uintptr_t _tableDescriptorSize; /**< The size, in bytes, of the HeapRegionDescriptor subclass used by this manager */
MM_RegionDescriptorInitializer _regionDescriptorInitializer; /**< A function pointer used to initialize a newly allocated HRD */
MM_RegionDescriptorDestructor _regionDescriptorDestructor; /**< A function pointer used to destroy HRDs, or NULL */
uintptr_t _totalHeapSize; /**< The size, in bytes, of all currently active regions on the heap (that is, both table descriptors attached to subspaces and aux descriptors in the list) */
public:
void kill(MM_EnvironmentBase* env);
MM_HeapRegionManager(MM_EnvironmentBase* env, uintptr_t regionSize, uintptr_t tableDescriptorSize, MM_RegionDescriptorInitializer regionDescriptorInitializer, MM_RegionDescriptorDestructor regionDescriptorDestructor);
static MM_HeapRegionManager *newInstance(MM_EnvironmentBase *env, uintptr_t regionSize, uintptr_t tableDescriptorSize, MM_RegionDescriptorInitializer regionDescriptorInitializer, MM_RegionDescriptorDestructor regionDescriptorDestructor);
/**
* Returns the total size of the committed heap (includes both table regions with subspaces and aux regions)
* @return The total size of the committed heap, in bytes.
*/
uintptr_t getTotalHeapSize();
/**
* Register an auxiliary region with the manager and create a descriptor
* @param env MM_EnvironmentBase object
* @param subSpace the mem subspace the region belongs to
* @param lowAddress low address of the region
* @param highAddress high bound address of the region
*/
MM_HeapRegionDescriptor* createAuxiliaryRegionDescriptor(MM_EnvironmentBase* env, MM_MemorySubSpace* subSpace, void* lowAddress, void* highAddress);
/**
* Deregister an auxiliary region with the manager and destroy its descriptor
* @param env MM_EnvironmentBase object
* @param descriptor region descriptor to be removed from the manager
*/
void destroyAuxiliaryRegionDescriptor(MM_EnvironmentBase* env, MM_HeapRegionDescriptor* descriptor);
MM_HeapRegionDescriptor*
getFirstAuxiliaryRegion()
{
return _auxRegionDescriptorList;
}
MM_HeapRegionDescriptor*
getNextAuxiliaryRegion(MM_HeapRegionDescriptor* heapRegion)
{
return heapRegion->_nextRegion;
}
MM_HeapRegionDescriptor* getFirstTableRegion();
MM_HeapRegionDescriptor* getNextTableRegion(MM_HeapRegionDescriptor* heapRegion);
/**
* Lock the region manager.
* This prevents any regions from being added or removed until the manager is unlocked.
* This is a read-write lock, so multiple readers may hold the lock simultaneously.
*/
void lock();
/**
* Unlock the region manager.
* @see lock()
*/
void unlock();
/**
* Lock the region manager.
* This prevents any regions from being added or removed until the manager is unlocked.
* This is a write lock, so only one writer may hold the lock at a time.
*/
void writeLock();
/**
* Unlock the region manager from a writeLock().
*/
void writeUnlock();
/**
* Called as soon as the bounds of the contiguous heap are known (in the case of split heaps, this would also include the "gap").
* Calls to this method have the side-effect of allocating internal data structures to manage the regions backing this contiguous heap
* so a boolean return value is provided to inform the caller if these internal data structures were successfully initialized.
*
* The is expected to be called exactly once on each HRM.
*
* @param env The environment
* @param lowHeapEdge the lowest byte addressable in the contiguous heap (note that this might not be presently committed)
* @param highHeapEdge the byte after the highest byte addressable in the contiguous heap
* @return true if this manager succeeded in initializing internal data structures to manage this heap or false if an error occurred (this is
* generally fatal)
*/
virtual bool setContiguousHeapRange(MM_EnvironmentBase* env, void* lowHeapEdge, void* highHeapEdge)
{
/* TODO: Might need logic from HeapRegionManagerStandard */
return true;
}
/**
* Provide destruction of Region Table if necessary
* Use in heap shutdown (correspondent call with setContiguousHeapRange)
* @param env The environment
*/
virtual void destroyRegionTable(MM_EnvironmentBase* env)
{
Assert_MM_unreachable();
}
/**
* Retrieve current Heap snapshot
* free and total memory sizes for all memory pools
* sub class of HeapRegionManager would override this method to provide proper memory pools
*/
virtual MM_HeapMemorySnapshot* getHeapMemorySnapshot(MM_GCExtensionsBase *extensions, MM_HeapMemorySnapshot* snapshot, bool gcEnd)
{
Assert_MM_unreachable();
return NULL;
}
/**
* @return the size, in bytes, of a single region in the contiguous heap (note that AUX regions are not consulted, and spanning regions will be some multiple
* of this number)
*/
MMINLINE uintptr_t getRegionSize()
{
return _regionSize;
}
MMINLINE uintptr_t getRegionShift()
{
return _regionShift;
}
MMINLINE uintptr_t getTableRegionCount() const
{
return _tableRegionCount;
}
uintptr_t getHeapSize()
{
return (uintptr_t)_highTableEdge - (uintptr_t)_lowTableEdge;
}
uintptr_t getTotalHeapSizeInBytes()
{
return _totalHeapSize;
}
/**
* Get the physical table descriptor at the specified index.
*
* @param regionIndex - the index of the region - this is not bounds checked
* @return the region descriptor at the specified index
*/
MMINLINE MM_HeapRegionDescriptor* physicalTableDescriptorForIndex(uintptr_t regionIndex)
{
uintptr_t descriptorSize = _tableDescriptorSize;
uintptr_t regionTable = (uintptr_t)_regionTable;
return (MM_HeapRegionDescriptor*)(regionTable + (regionIndex * descriptorSize));
}
/**
* Get the index of the physical table descriptor that describes the address
*
* @param heapAddress - the address whose region we are trying to find - this is not bounds checked
* @return the index into table
*/
MMINLINE uintptr_t physicalTableDescriptorIndexForAddress(const void* heapAddress)
{
void* baseOfHeap = (_regionTable)->getLowAddress();
uintptr_t heapDelta = (uintptr_t)heapAddress - (uintptr_t)baseOfHeap;
uintptr_t index = heapDelta >> _regionShift;
return index;
}
/**
* Get the physical table descriptor that describes the address
*
* @param heapAddress - the address whose region we are trying to find - this is not bounds checked
* @return the region descriptor for the specified address
*/
MMINLINE MM_HeapRegionDescriptor* physicalTableDescriptorForAddress(const void* heapAddress)
{
uintptr_t index = physicalTableDescriptorIndexForAddress(heapAddress);
return physicalTableDescriptorForIndex(index);
}
/**
* Get the logical table descriptor at the specified index. Note that the region described
* could be part of a spanning region so return the headOfSPan
*
* @param regionIndex - the index of the region - this is not bounds checked
* @return the region descriptor at the specified index
*/
MMINLINE MM_HeapRegionDescriptor* tableDescriptorForIndex(uintptr_t regionIndex)
{
MM_HeapRegionDescriptor* tableDescriptor = physicalTableDescriptorForIndex(regionIndex);
return tableDescriptor->_headOfSpan;
}
/**
* Get the logical table descriptor that describes the address. Note that the region described
* could be part of a spanning region so return the headOfSPan
*
* @param heapAddress - the address whose region we are trying to find
* @return the region descriptor for the specified address
*/
MMINLINE MM_HeapRegionDescriptor* tableDescriptorForAddress(const void* heapAddress)
{
Assert_MM_true(heapAddress >= _lowTableEdge);
Assert_MM_true(heapAddress < _highTableEdge);
MM_HeapRegionDescriptor* tableDescriptor = physicalTableDescriptorForAddress(heapAddress);
return tableDescriptor->_headOfSpan;
}
/**
* Get the logical region descriptor that describes the address. The region may be a table
* region or an auxillar region. Note that the region described could be part of a spanning
* region so return the headOfSPan for table regions.
*
* @param heapAddress - the address whose region we are trying to find
* @return the region descriptor for the specified address
*/
MMINLINE MM_HeapRegionDescriptor* regionDescriptorForAddress(const void* heapAddress)
{
MM_HeapRegionDescriptor* result = NULL;
if ((heapAddress >= _lowTableEdge) && (heapAddress < _highTableEdge)) {
result = tableDescriptorForAddress(heapAddress);
} else {
result = auxillaryDescriptorForAddress(heapAddress);
}
return result;
}
/**
* Set the associated subspace of the given region to subSpace.
*/
void reassociateRegionWithSubSpace(MM_EnvironmentBase* env, MM_HeapRegionDescriptor* region, MM_MemorySubSpace* subSpace);
MM_HeapRegionDescriptor* auxillaryDescriptorForAddress(const void* address);
MMINLINE void resizeAuxillaryRegion(MM_EnvironmentBase* env, MM_HeapRegionDescriptor* region, void* lowAddress, void* highAddress)
{
writeLock();
_totalHeapSize -= region->getSize();
region->reinitialize(env, lowAddress, highAddress);
_totalHeapSize += region->getSize();
writeUnlock();
}
/**
* Instructs the receiver that the regions representing the heap range managed by vmem are valid for use.
*
* @param[in] env The current thread
* @param[in] handle The handle to Virtual Memory object describing the range we want to enable
*
* @return false if the table failed to be allocated or initialized (this is a fatal error in GC start-up)
*/
virtual bool enableRegionsInTable(MM_EnvironmentBase* env, MM_MemoryHandle* handle)
{
return true;
}
/**
* Given an index, return the matching region descriptor.
* @param index the 0-based index of the region to fetch
* @return the region at the specified index
*/
MM_HeapRegionDescriptor* mapRegionTableIndexToDescriptor(uintptr_t index);
/**
* Given a region, return its index in the table.
* @param region[in] the region to examine
* @return the region's 0-based index in the table
*/
uintptr_t mapDescriptorToRegionTableIndex(MM_HeapRegionDescriptor* region);
protected:
virtual bool initialize(MM_EnvironmentBase* env);
virtual void tearDown(MM_EnvironmentBase* env);
/**
* Implemented by sub-classes to allocate and initialize a single AUX region descriptor for the extent: [lowAddress, highAddress). This is required since
* the sub-class is allowed to implement descriptors as any sub-class of MM_HeapRegionDescriptor and the caller cannot assume how its storage is managed.
* The returned descriptor will later be passed to freeAuxiliaryRegionDescriptor when it is no longer needed.
*
* @param env The environment
* @param lowAddress the lowest byte addressable in the AUX region (note that this might not be presently committed)
* @param highAddress the byte after the highest byte addressable in the AUX region
* @return an instance of an implementation-defined MM_HeapRegionDescriptor sub-class on success or NULL on failure
*/
virtual MM_HeapRegionDescriptor* internalAllocateAuxiliaryRegionDescriptor(MM_EnvironmentBase* env, void* lowAddress, void* highAddress);
/**
* Implemented by sub-classes to free (and otherwise dispose of) a single AUX region descriptor (region). This is required since the sub-class is
* allowed to implement descriptors as any sub-class of MM_HeapRegionDescriptor and the caller cannot assume how its storage is managed.
*
* @param env The environment
* @param region The AUX region to be freed by the implementor (previously returned by allocateAuxiliaryRegionDescriptor)
*/
virtual void internalFreeAuxiliaryRegionDescriptor(MM_EnvironmentBase* env, MM_HeapRegionDescriptor* region);
/**
* Implemented by sub-classes to allocate and initialize the contiguous region descriptor table for contiguous heap extent [lowHeapEdge, highHeapEdge).
* This is required since the sub-class is allowed to implement the descriptor table as a contiguous array of any sub-class of MM_HeapRegionDescriptor
* and the caller cannot assume how its storage is managed. The returned descriptor will later be passed to freeRegionTable when it is no longer needed.
*
* @param env The environment
* @param lowHeapEdge the lowest byte addressable in the contiguous heap (note that this might not be presently committed)
* @param highHeapEdge the byte after the highest byte addressable in the contiguous heap
* @return an instance of an implementation-defined MM_HeapRegionDescriptor sub-class on success or NULL on failure
*/
virtual MM_HeapRegionDescriptor* internalAllocateAndInitializeRegionTable(MM_EnvironmentBase* env, void* lowHeapEdge, void* highHeapEdge);
/**
* Implemented by sub-classes to free (and otherwise dispose of) the contiguous region descriptor table starting at tableBase. This is required since the
* sub-class is allowed to implement the descriptor table as a contiguous array of any sub-class of MM_HeapRegionDescriptor and the caller cannot assume
* how its storage is managed.
*
* @param env The environment
* @param tableBase The base of the region table to be freed by the implementor (previously returned by allocateAndInitializeRegionTable)
* @param tableElementCount The number of contiguous descriptor elements in the table
*/
virtual void internalFreeRegionTable(MM_EnvironmentBase* env, MM_HeapRegionDescriptor* tableBase, uintptr_t tableElementCount);
private:
/**Insert a MM_HeapRegionDescriptor in the address ordered list
* @param env MM_EnvironmentBase object
* @param heapRegion MM_HeapRegionDescriptor to be inserted
*/
void insertHeapRegion(MM_EnvironmentBase* env, MM_HeapRegionDescriptor* heapRegion);
/**Remove a MM_HeapRegionDescriptor from the address ordered list
* @param env MM_EnvironmentBase object
* @param heapRegion MM_HeapRegionDescriptor to be removed
*/
void removeHeapRegion(MM_EnvironmentBase* env, MM_HeapRegionDescriptor* heapRegion);
/**
* The actual implementation of createAuxiliaryRegionDescriptor (called through the listener chain)
*/
MM_HeapRegionDescriptor* internalCreateAuxiliaryRegionDescriptor(MM_EnvironmentBase* env, MM_MemorySubSpace* subSpace, void* lowAddress, void* highAddress);
/**
* The actual implementation of destroyAuxiliaryRegionDescriptor (called through the listener chain)
*/
void internalDestroyAuxiliaryRegionDescriptor(MM_EnvironmentBase* env, MM_HeapRegionDescriptor* descriptor);
MM_HeapRegionDescriptor* findFirstUsedRegion(MM_HeapRegionDescriptor* start);
};
#endif /* HEAPREGIONDESCRIPTOR_HPP */