|
22 | 22 | */
|
23 | 23 |
|
24 | 24 | #include "precompiled.hpp"
|
| 25 | +#include "gc/z/zArray.inline.hpp" |
25 | 26 | #include "gc/z/zForwarding.inline.hpp"
|
26 | 27 | #include "gc/z/zForwardingAllocator.inline.hpp"
|
27 | 28 | #include "gc/z/zRelocationSet.hpp"
|
| 29 | +#include "gc/z/zRelocationSetSelector.inline.hpp" |
28 | 30 | #include "gc/z/zStat.hpp"
|
29 |
| -#include "memory/allocation.hpp" |
| 31 | +#include "gc/z/zTask.hpp" |
| 32 | +#include "gc/z/zWorkers.hpp" |
| 33 | +#include "runtime/atomic.hpp" |
30 | 34 | #include "utilities/debug.hpp"
|
31 | 35 |
|
32 |
| -ZRelocationSet::ZRelocationSet() : |
33 |
| - _allocator(), |
34 |
| - _forwardings(NULL), |
35 |
| - _nforwardings(0) {} |
| 36 | +class ZRelocationSetInstallTask : public ZTask { |
| 37 | +private: |
| 38 | + ZForwardingAllocator* const _allocator; |
| 39 | + ZForwarding** _forwardings; |
| 40 | + const size_t _nforwardings; |
| 41 | + ZArrayParallelIterator<ZPage*> _small_iter; |
| 42 | + ZArrayParallelIterator<ZPage*> _medium_iter; |
| 43 | + volatile size_t _small_next; |
| 44 | + volatile size_t _medium_next; |
| 45 | + |
| 46 | + void install(ZForwarding* forwarding, volatile size_t* next) { |
| 47 | + const size_t index = Atomic::fetch_and_add(next, 1u); |
| 48 | + assert(index < _nforwardings, "Invalid index"); |
| 49 | + _forwardings[index] = forwarding; |
| 50 | + } |
36 | 51 |
|
37 |
| -void ZRelocationSet::populate(ZPage* const* small, size_t nsmall, |
38 |
| - ZPage* const* medium, size_t nmedium, |
39 |
| - size_t forwarding_entries) { |
40 |
| - // Set relocation set length |
41 |
| - _nforwardings = nsmall + nmedium; |
| 52 | + void install_small(ZForwarding* forwarding) { |
| 53 | + install(forwarding, &_small_next); |
| 54 | + } |
42 | 55 |
|
43 |
| - // Initialize forwarding allocator to have room for the |
44 |
| - // relocation set, all forwardings, and all forwarding entries. |
45 |
| - const size_t relocation_set_size = _nforwardings * sizeof(ZForwarding*); |
46 |
| - const size_t forwardings_size = _nforwardings * sizeof(ZForwarding); |
47 |
| - const size_t forwarding_entries_size = forwarding_entries * sizeof(ZForwardingEntry); |
48 |
| - _allocator.reset(relocation_set_size + forwardings_size + forwarding_entries_size); |
| 56 | + void install_medium(ZForwarding* forwarding) { |
| 57 | + install(forwarding, &_medium_next); |
| 58 | + } |
49 | 59 |
|
50 |
| - // Allocate relocation set |
51 |
| - _forwardings = new (_allocator.alloc(relocation_set_size)) ZForwarding*[_nforwardings]; |
| 60 | +public: |
| 61 | + ZRelocationSetInstallTask(ZForwardingAllocator* allocator, const ZRelocationSetSelector* selector) : |
| 62 | + ZTask("ZRelocationSetInstallTask"), |
| 63 | + _allocator(allocator), |
| 64 | + _forwardings(NULL), |
| 65 | + _nforwardings(selector->small()->length() + selector->medium()->length()), |
| 66 | + _small_iter(selector->small()), |
| 67 | + _medium_iter(selector->medium()), |
| 68 | + _small_next(selector->medium()->length()), |
| 69 | + _medium_next(0) { |
52 | 70 |
|
53 |
| - // Populate relocation set array |
54 |
| - size_t j = 0; |
| 71 | + // Reset the allocator to have room for the relocation |
| 72 | + // set, all forwardings, and all forwarding entries. |
| 73 | + const size_t relocation_set_size = _nforwardings * sizeof(ZForwarding*); |
| 74 | + const size_t forwardings_size = _nforwardings * sizeof(ZForwarding); |
| 75 | + const size_t forwarding_entries_size = selector->forwarding_entries() * sizeof(ZForwardingEntry); |
| 76 | + _allocator->reset(relocation_set_size + forwardings_size + forwarding_entries_size); |
55 | 77 |
|
56 |
| - // Populate medium pages |
57 |
| - for (size_t i = 0; i < nmedium; i++) { |
58 |
| - _forwardings[j++] = ZForwarding::alloc(&_allocator, medium[i]); |
| 78 | + // Allocate relocation set |
| 79 | + _forwardings = new (_allocator->alloc(relocation_set_size)) ZForwarding*[_nforwardings]; |
59 | 80 | }
|
60 | 81 |
|
61 |
| - // Populate small pages |
62 |
| - for (size_t i = 0; i < nsmall; i++) { |
63 |
| - _forwardings[j++] = ZForwarding::alloc(&_allocator, small[i]); |
| 82 | + ~ZRelocationSetInstallTask() { |
| 83 | + assert(_allocator->is_full(), "Should be full"); |
| 84 | + } |
| 85 | + |
| 86 | + virtual void work() { |
| 87 | + // Allocate and install forwardings for small pages |
| 88 | + for (ZPage* page; _small_iter.next(&page);) { |
| 89 | + ZForwarding* const forwarding = ZForwarding::alloc(_allocator, page); |
| 90 | + install_small(forwarding); |
| 91 | + } |
| 92 | + |
| 93 | + // Allocate and install forwardings for medium pages |
| 94 | + for (ZPage* page; _medium_iter.next(&page);) { |
| 95 | + ZForwarding* const forwarding = ZForwarding::alloc(_allocator, page); |
| 96 | + install_medium(forwarding); |
| 97 | + } |
64 | 98 | }
|
65 | 99 |
|
66 |
| - assert(_allocator.is_full(), "Should be full"); |
| 100 | + ZForwarding** forwardings() const { |
| 101 | + return _forwardings; |
| 102 | + } |
| 103 | + |
| 104 | + size_t nforwardings() const { |
| 105 | + return _nforwardings; |
| 106 | + } |
| 107 | +}; |
| 108 | + |
| 109 | +ZRelocationSet::ZRelocationSet(ZWorkers* workers) : |
| 110 | + _workers(workers), |
| 111 | + _allocator(), |
| 112 | + _forwardings(NULL), |
| 113 | + _nforwardings(0) {} |
| 114 | + |
| 115 | +void ZRelocationSet::install(const ZRelocationSetSelector* selector) { |
| 116 | + // Install relocation set |
| 117 | + ZRelocationSetInstallTask task(&_allocator, selector); |
| 118 | + _workers->run_concurrent(&task); |
| 119 | + |
| 120 | + _forwardings = task.forwardings(); |
| 121 | + _nforwardings = task.nforwardings(); |
67 | 122 |
|
68 | 123 | // Update statistics
|
69 |
| - ZStatRelocation::set_at_populate_relocation_set(_allocator.size()); |
| 124 | + ZStatRelocation::set_at_install_relocation_set(_allocator.size()); |
70 | 125 | }
|
71 | 126 |
|
72 | 127 | void ZRelocationSet::reset() {
|
|
0 commit comments