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
|
/*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
// Blocks
class HeapBlock VALUE_OBJ_CLASS_SPEC {
friend class VMStructs;
public:
struct Header {
size_t _length; // the length in segments
bool _used; // Used bit
};
protected:
union {
Header _header;
int64_t _padding[ (sizeof(Header) + sizeof(int64_t)-1) / sizeof(int64_t) ];
// pad to 0 mod 8
};
public:
// Initialization
void initialize(size_t length) { _header._length = length; set_used(); }
// Accessors
void* allocated_space() const { return (void*)(this + 1); }
size_t length() const { return _header._length; }
// Used/free
void set_used() { _header._used = true; }
void set_free() { _header._used = false; }
bool free() { return !_header._used; }
};
class FreeBlock: public HeapBlock {
friend class VMStructs;
protected:
FreeBlock* _link;
public:
// Initialization
void initialize(size_t length) { HeapBlock::initialize(length); _link= NULL; }
// Merging
void set_length(size_t l) { _header._length = l; }
// Accessors
FreeBlock* link() const { return _link; }
void set_link(FreeBlock* link) { _link = link; }
};
class CodeHeap : public CHeapObj {
friend class VMStructs;
private:
VirtualSpace _memory; // the memory holding the blocks
VirtualSpace _segmap; // the memory holding the segment map
size_t _number_of_committed_segments;
size_t _number_of_reserved_segments;
size_t _segment_size;
int _log2_segment_size;
size_t _next_segment;
FreeBlock* _freelist;
size_t _free_segments; // No. of segments in freelist
// Helper functions
size_t number_of_segments(size_t size) const { return (size + _segment_size - 1) >> _log2_segment_size; }
size_t size(size_t number_of_segments) const { return number_of_segments << _log2_segment_size; }
size_t segment_for(void* p) const { return ((char*)p - _memory.low()) >> _log2_segment_size; }
HeapBlock* block_at(size_t i) const { return (HeapBlock*)(_memory.low() + (i << _log2_segment_size)); }
void mark_segmap_as_free(size_t beg, size_t end);
void mark_segmap_as_used(size_t beg, size_t end);
// Freelist management helpers
FreeBlock* following_block(FreeBlock *b);
void insert_after(FreeBlock* a, FreeBlock* b);
void merge_right (FreeBlock* a);
// Toplevel freelist management
void add_to_freelist(HeapBlock *b);
FreeBlock* search_freelist(size_t length);
// Iteration helpers
void* next_free(HeapBlock* b) const;
HeapBlock* first_block() const;
HeapBlock* next_block(HeapBlock* b) const;
HeapBlock* block_start(void* p) const;
// to perform additional actions on creation of executable code
void on_code_mapping(char* base, size_t size);
public:
CodeHeap();
// Heap extents
bool reserve(size_t reserved_size, size_t committed_size, size_t segment_size);
void release(); // releases all allocated memory
bool expand_by(size_t size); // expands commited memory by size
void shrink_by(size_t size); // shrinks commited memory by size
void clear(); // clears all heap contents
// Memory allocation
void* allocate (size_t size); // allocates a block of size or returns NULL
void deallocate(void* p); // deallocates a block
// Attributes
void* begin() const { return _memory.low (); }
void* end() const { return _memory.high(); }
bool contains(void* p) const { return begin() <= p && p < end(); }
void* find_start(void* p) const; // returns the block containing p or NULL
size_t alignment_unit() const; // alignment of any block
size_t alignment_offset() const; // offset of first byte of any block, within the enclosing alignment unit
static size_t header_size(); // returns the header size for each heap block
// Returns reserved area high and low addresses
char *low_boundary() const { return _memory.low_boundary (); }
char *high() const { return _memory.high(); }
char *high_boundary() const { return _memory.high_boundary(); }
// Iteration
// returns the first block or NULL
void* first() const { return next_free(first_block()); }
// returns the next block given a block p or NULL
void* next(void* p) const { return next_free(next_block(block_start(p))); }
// Statistics
size_t capacity() const;
size_t max_capacity() const;
size_t allocated_capacity() const;
size_t unallocated_capacity() const { return max_capacity() - allocated_capacity(); }
// Debugging
void verify();
void print() PRODUCT_RETURN;
};
|