29 #include "memory/allocation.inline.hpp" |
29 #include "memory/allocation.inline.hpp" |
30 #include "memory/resourceArea.hpp" |
30 #include "memory/resourceArea.hpp" |
31 |
31 |
32 jint EpsilonHeap::initialize() { |
32 jint EpsilonHeap::initialize() { |
33 size_t init_byte_size = _policy->initial_heap_byte_size(); |
33 size_t init_byte_size = _policy->initial_heap_byte_size(); |
34 size_t max_byte_size = _policy->max_heap_byte_size(); |
34 size_t max_byte_size = _policy->max_heap_byte_size(); |
35 size_t align = _policy->heap_alignment(); |
35 |
36 |
36 // Initialize backing storage |
37 ReservedSpace heap_rs = Universe::reserve_heap(max_byte_size, align); |
37 ReservedSpace heap_rs = Universe::reserve_heap(max_byte_size, _policy->heap_alignment()); |
38 _virtual_space.initialize(heap_rs, init_byte_size); |
38 _virtual_space.initialize(heap_rs, init_byte_size); |
39 |
39 |
40 MemRegion committed_region((HeapWord*)_virtual_space.low(), (HeapWord*)_virtual_space.high()); |
40 MemRegion committed_region((HeapWord*)_virtual_space.low(), (HeapWord*)_virtual_space.high()); |
41 MemRegion reserved_region((HeapWord*)_virtual_space.low_boundary(), (HeapWord*)_virtual_space.high_boundary()); |
41 MemRegion reserved_region((HeapWord*)_virtual_space.low_boundary(), (HeapWord*)_virtual_space.high_boundary()); |
42 |
42 |
43 initialize_reserved_region(reserved_region.start(), reserved_region.end()); |
43 initialize_reserved_region(reserved_region.start(), reserved_region.end()); |
44 |
44 |
45 _space = new ContiguousSpace(); |
45 _space = new ContiguousSpace(); |
46 _space->initialize(committed_region, true, true); |
46 _space->initialize(committed_region, /* clear_space = */ true, /* mangle_space */ = true); |
47 |
47 |
48 BarrierSet::set_barrier_set(new EpsilonBarrierSet()); |
48 // Precompute hot fields |
49 |
|
50 _max_tlab_size = MIN2(CollectedHeap::max_tlab_size(), EpsilonMaxTLABSize / HeapWordSize); |
49 _max_tlab_size = MIN2(CollectedHeap::max_tlab_size(), EpsilonMaxTLABSize / HeapWordSize); |
51 |
50 _step_counter_update = MIN2<size_t>(max_byte_size / 16, EpsilonUpdateCountersStep); |
|
51 _step_heap_print = (EpsilonPrintHeapStep == 0) ? SIZE_MAX : (max_byte_size / EpsilonPrintHeapStep); |
|
52 _decay_time_ns = (int64_t) EpsilonTLABDecayTime * 1000 * 1000; |
|
53 |
|
54 // Enable monitoring |
52 _monitoring_support = new EpsilonMonitoringSupport(this); |
55 _monitoring_support = new EpsilonMonitoringSupport(this); |
53 _last_counter_update = 0; |
56 _last_counter_update = 0; |
54 _last_heap_print = 0; |
57 _last_heap_print = 0; |
55 |
58 |
56 _step_counter_update = MIN2<size_t>(max_byte_size / 16, EpsilonUpdateCountersStep); |
59 // Install barrier set |
57 _step_heap_print = (EpsilonPrintHeapStep == 0) ? SIZE_MAX : (max_byte_size / EpsilonPrintHeapStep); |
60 BarrierSet::set_barrier_set(new EpsilonBarrierSet()); |
58 |
61 |
59 _decay_time_ns = (int64_t) EpsilonTLABDecayTime * 1000 * 1000; |
62 // All done, print out the configuration |
60 |
|
61 if (init_byte_size != max_byte_size) { |
63 if (init_byte_size != max_byte_size) { |
62 log_info(gc)("Resizeable heap; starting at " SIZE_FORMAT "M, max: " SIZE_FORMAT "M, step: " SIZE_FORMAT "M", |
64 log_info(gc)("Resizeable heap; starting at " SIZE_FORMAT "M, max: " SIZE_FORMAT "M, step: " SIZE_FORMAT "M", |
63 init_byte_size / M, max_byte_size / M, EpsilonMinHeapExpand / M); |
65 init_byte_size / M, max_byte_size / M, EpsilonMinHeapExpand / M); |
64 } else { |
66 } else { |
65 log_info(gc)("Non-resizeable heap; start/max: " SIZE_FORMAT "M", init_byte_size / M); |
67 log_info(gc)("Non-resizeable heap; start/max: " SIZE_FORMAT "M", init_byte_size / M); |
66 } |
68 } |
|
69 |
67 if (UseTLAB) { |
70 if (UseTLAB) { |
68 log_info(gc)("Using TLAB allocation; max: " SIZE_FORMAT "K", _max_tlab_size * HeapWordSize / K); |
71 log_info(gc)("Using TLAB allocation; max: " SIZE_FORMAT "K", _max_tlab_size * HeapWordSize / K); |
69 if (EpsilonElasticTLAB) { |
72 if (EpsilonElasticTLAB) { |
70 log_info(gc)("Elastic TLABs enabled; elasticity: %.2fx", EpsilonTLABElasticity); |
73 log_info(gc)("Elastic TLABs enabled; elasticity: %.2fx", EpsilonTLABElasticity); |
71 } |
74 } |
127 // Enough space to expand in bulk: |
130 // Enough space to expand in bulk: |
128 bool expand = _virtual_space.expand_by(want_space); |
131 bool expand = _virtual_space.expand_by(want_space); |
129 assert(expand, "Should be able to expand"); |
132 assert(expand, "Should be able to expand"); |
130 } else if (size < space_left) { |
133 } else if (size < space_left) { |
131 // No space to expand in bulk, and this allocation is still possible, |
134 // No space to expand in bulk, and this allocation is still possible, |
132 // take all the space left: |
135 // take all the remaining space: |
133 bool expand = _virtual_space.expand_by(space_left); |
136 bool expand = _virtual_space.expand_by(space_left); |
134 assert(expand, "Should be able to expand"); |
137 assert(expand, "Should be able to expand"); |
135 } else { |
138 } else { |
136 // No space left: |
139 // No space left: |
137 return NULL; |
140 return NULL; |
139 |
142 |
140 _space->set_end((HeapWord *) _virtual_space.high()); |
143 _space->set_end((HeapWord *) _virtual_space.high()); |
141 res = _space->par_allocate(size); |
144 res = _space->par_allocate(size); |
142 } |
145 } |
143 |
146 |
|
147 // Allocation successful, update counters |
144 size_t used = _space->used(); |
148 size_t used = _space->used(); |
145 if (used - _last_counter_update >= _step_counter_update) { |
149 if (used - _last_counter_update >= _step_counter_update) { |
146 _last_counter_update = used; |
150 _last_counter_update = used; |
147 _monitoring_support->update_counters(); |
151 _monitoring_support->update_counters(); |
148 } |
152 } |
149 |
153 |
|
154 // ...and print the occupancy line, if needed |
150 if (used - _last_heap_print >= _step_heap_print) { |
155 if (used - _last_heap_print >= _step_heap_print) { |
151 log_info(gc)("Heap: " SIZE_FORMAT "M reserved, " SIZE_FORMAT "M committed, " SIZE_FORMAT "M used", |
156 log_info(gc)("Heap: " SIZE_FORMAT "M reserved, " SIZE_FORMAT "M committed, " SIZE_FORMAT "M used", |
152 max_capacity() / M, capacity() / M, used / M); |
157 max_capacity() / M, capacity() / M, used / M); |
153 _last_heap_print = used; |
158 _last_heap_print = used; |
154 } |
159 } |
169 |
174 |
170 if (EpsilonElasticTLAB) { |
175 if (EpsilonElasticTLAB) { |
171 ergo_tlab = EpsilonThreadLocalData::ergo_tlab_size(thread); |
176 ergo_tlab = EpsilonThreadLocalData::ergo_tlab_size(thread); |
172 |
177 |
173 if (EpsilonElasticTLABDecay) { |
178 if (EpsilonElasticTLABDecay) { |
174 int64_t last_alloc = EpsilonThreadLocalData::last_alloc_time(thread); |
179 int64_t last_time = EpsilonThreadLocalData::last_tlab_time(thread); |
175 time = (int64_t) os::javaTimeNanos(); |
180 time = (int64_t) os::javaTimeNanos(); |
176 |
181 |
177 assert(last_alloc <= time, "time should be monotonic"); |
182 assert(last_time <= time, "time should be monotonic"); |
178 |
183 |
179 // If the thread had not allocated recently, retract the ergonomic size. |
184 // If the thread had not allocated recently, retract the ergonomic size. |
180 // This conserves memory when the thread had initial burst of allocations, |
185 // This conserves memory when the thread had initial burst of allocations, |
181 // and then started allocating only sporadically. |
186 // and then started allocating only sporadically. |
182 if (last_alloc != 0 && (time - last_alloc > _decay_time_ns)) { |
187 if (last_time != 0 && (time - last_time > _decay_time_ns)) { |
183 ergo_tlab = 0; |
188 ergo_tlab = 0; |
184 EpsilonThreadLocalData::set_ergo_tlab_size(thread, 0); |
189 EpsilonThreadLocalData::set_ergo_tlab_size(thread, 0); |
185 } |
190 } |
186 } |
191 } |
187 |
192 |
206 _max_tlab_size * HeapWordSize / K, |
211 _max_tlab_size * HeapWordSize / K, |
207 ergo_tlab * HeapWordSize / K, |
212 ergo_tlab * HeapWordSize / K, |
208 size * HeapWordSize / K); |
213 size * HeapWordSize / K); |
209 } |
214 } |
210 |
215 |
|
216 // All prepared, let's do it! |
211 HeapWord* res = allocate_work(size); |
217 HeapWord* res = allocate_work(size); |
|
218 |
212 if (res != NULL) { |
219 if (res != NULL) { |
213 // Allocation successful |
220 // Allocation successful |
214 *actual_size = size; |
221 *actual_size = size; |
215 if (EpsilonElasticTLABDecay) { |
222 if (EpsilonElasticTLABDecay) { |
216 EpsilonThreadLocalData::set_last_alloc_time(thread, time); |
223 EpsilonThreadLocalData::set_last_tlab_time(thread, time); |
217 } |
224 } |
218 if (EpsilonElasticTLAB && !fits) { |
225 if (EpsilonElasticTLAB && !fits) { |
219 // If we requested expansion, this is our new ergonomic TLAB size |
226 // If we requested expansion, this is our new ergonomic TLAB size |
220 EpsilonThreadLocalData::set_ergo_tlab_size(thread, size); |
227 EpsilonThreadLocalData::set_ergo_tlab_size(thread, size); |
221 } |
228 } |