92 // | | | used | |
92 // | | | used | |
93 // | | | | |
93 // | | | | |
94 // | | | | |
94 // | | | | |
95 // +--------------+ <- bottom --+ --+ |
95 // +--------------+ <- bottom --+ --+ |
96 |
96 |
|
97 // ChunkIndex defines the type of chunk. |
|
98 // Chunk types differ by size: specialized < small < medium, chunks |
|
99 // larger than medium are humongous chunks of varying size. |
|
100 enum ChunkIndex { |
|
101 ZeroIndex = 0, |
|
102 SpecializedIndex = ZeroIndex, |
|
103 SmallIndex = SpecializedIndex + 1, |
|
104 MediumIndex = SmallIndex + 1, |
|
105 HumongousIndex = MediumIndex + 1, |
|
106 NumberOfFreeLists = 3, |
|
107 NumberOfInUseLists = 4 |
|
108 }; |
|
109 |
|
110 // Utility functions. |
|
111 size_t get_size_for_nonhumongous_chunktype(ChunkIndex chunk_type, bool is_class); |
|
112 ChunkIndex get_chunk_type_by_size(size_t size, bool is_class); |
|
113 |
|
114 // Returns a descriptive name for a chunk type. |
|
115 const char* chunk_size_name(ChunkIndex index); |
|
116 |
|
117 // Verify chunk type. |
|
118 inline bool is_valid_chunktype(ChunkIndex index) { |
|
119 return index == SpecializedIndex || index == SmallIndex || |
|
120 index == MediumIndex || index == HumongousIndex; |
|
121 } |
|
122 |
|
123 inline bool is_valid_nonhumongous_chunktype(ChunkIndex index) { |
|
124 return is_valid_chunktype(index) && index != HumongousIndex; |
|
125 } |
|
126 |
|
127 enum ChunkOrigin { |
|
128 // Chunk normally born (via take_from_committed) |
|
129 origin_normal = 1, |
|
130 // Chunk was born as padding chunk |
|
131 origin_pad = 2, |
|
132 // Chunk was born as leftover chunk in VirtualSpaceNode::retire |
|
133 origin_leftover = 3, |
|
134 // Chunk was born as result of a merge of smaller chunks |
|
135 origin_merge = 4, |
|
136 // Chunk was born as result of a split of a larger chunk |
|
137 origin_split = 5, |
|
138 |
|
139 origin_minimum = origin_normal, |
|
140 origin_maximum = origin_split, |
|
141 origins_count = origin_maximum + 1 |
|
142 }; |
|
143 |
|
144 inline bool is_valid_chunkorigin(ChunkOrigin origin) { |
|
145 return origin == origin_normal || |
|
146 origin == origin_pad || |
|
147 origin == origin_leftover || |
|
148 origin == origin_merge || |
|
149 origin == origin_split; |
|
150 } |
|
151 |
97 class Metachunk : public Metabase<Metachunk> { |
152 class Metachunk : public Metabase<Metachunk> { |
98 friend class MetachunkTest; |
153 friend class MetachunkTest; |
99 // The VirtualSpaceNode containing this chunk. |
154 // The VirtualSpaceNode containing this chunk. |
100 VirtualSpaceNode* _container; |
155 VirtualSpaceNode* const _container; |
101 |
156 |
102 // Current allocation top. |
157 // Current allocation top. |
103 MetaWord* _top; |
158 MetaWord* _top; |
104 |
159 |
|
160 // A 32bit sentinel for debugging purposes. |
|
161 enum { CHUNK_SENTINEL = 0x4d4554EF, // "MET" |
|
162 CHUNK_SENTINEL_INVALID = 0xFEEEEEEF |
|
163 }; |
|
164 |
|
165 uint32_t _sentinel; |
|
166 |
|
167 const ChunkIndex _chunk_type; |
|
168 const bool _is_class; |
|
169 // Whether the chunk is free (in freelist) or in use by some class loader. |
105 bool _is_tagged_free; |
170 bool _is_tagged_free; |
|
171 |
|
172 ChunkOrigin _origin; |
|
173 int _use_count; |
106 |
174 |
107 MetaWord* initial_top() const { return (MetaWord*)this + overhead(); } |
175 MetaWord* initial_top() const { return (MetaWord*)this + overhead(); } |
108 MetaWord* top() const { return _top; } |
176 MetaWord* top() const { return _top; } |
109 |
177 |
110 public: |
178 public: |
118 static size_t object_alignment(); |
186 static size_t object_alignment(); |
119 |
187 |
120 // Size of the Metachunk header, including alignment. |
188 // Size of the Metachunk header, including alignment. |
121 static size_t overhead(); |
189 static size_t overhead(); |
122 |
190 |
123 Metachunk(size_t word_size , VirtualSpaceNode* container); |
191 Metachunk(ChunkIndex chunktype, bool is_class, size_t word_size, VirtualSpaceNode* container); |
124 |
192 |
125 MetaWord* allocate(size_t word_size); |
193 MetaWord* allocate(size_t word_size); |
126 |
194 |
127 VirtualSpaceNode* container() const { return _container; } |
195 VirtualSpaceNode* container() const { return _container; } |
128 |
196 |
141 bool is_tagged_free() { return _is_tagged_free; } |
209 bool is_tagged_free() { return _is_tagged_free; } |
142 void set_is_tagged_free(bool v) { _is_tagged_free = v; } |
210 void set_is_tagged_free(bool v) { _is_tagged_free = v; } |
143 |
211 |
144 bool contains(const void* ptr) { return bottom() <= ptr && ptr < _top; } |
212 bool contains(const void* ptr) { return bottom() <= ptr && ptr < _top; } |
145 |
213 |
146 #ifndef PRODUCT |
|
147 void mangle(juint word_value); |
|
148 #endif |
|
149 |
|
150 void print_on(outputStream* st) const; |
214 void print_on(outputStream* st) const; |
151 void verify(); |
215 |
|
216 bool is_valid_sentinel() const { return _sentinel == CHUNK_SENTINEL; } |
|
217 void remove_sentinel() { _sentinel = CHUNK_SENTINEL_INVALID; } |
|
218 |
|
219 int get_use_count() const { return _use_count; } |
|
220 void inc_use_count() { _use_count ++; } |
|
221 |
|
222 ChunkOrigin get_origin() const { return _origin; } |
|
223 void set_origin(ChunkOrigin orig) { _origin = orig; } |
|
224 |
|
225 ChunkIndex get_chunk_type() const { return _chunk_type; } |
|
226 bool is_class() const { return _is_class; } |
|
227 |
|
228 DEBUG_ONLY(void mangle(juint word_value);) |
|
229 DEBUG_ONLY(void verify();) |
|
230 |
152 }; |
231 }; |
153 |
232 |
154 // Metablock is the unit of allocation from a Chunk. |
233 // Metablock is the unit of allocation from a Chunk. |
155 // |
234 // |
156 // A Metablock may be reused by its SpaceManager but are never moved between |
235 // A Metablock may be reused by its SpaceManager but are never moved between |