24 |
24 |
25 #ifndef SHARE_JFR_RECORDER_STORAGE_JFRMEMORYSPACE_INLINE_HPP |
25 #ifndef SHARE_JFR_RECORDER_STORAGE_JFRMEMORYSPACE_INLINE_HPP |
26 #define SHARE_JFR_RECORDER_STORAGE_JFRMEMORYSPACE_INLINE_HPP |
26 #define SHARE_JFR_RECORDER_STORAGE_JFRMEMORYSPACE_INLINE_HPP |
27 |
27 |
28 #include "jfr/recorder/storage/jfrMemorySpace.hpp" |
28 #include "jfr/recorder/storage/jfrMemorySpace.hpp" |
|
29 #include "runtime/os.hpp" |
29 |
30 |
30 template <typename T, template <typename> class RetrievalType, typename Callback> |
31 template <typename T, template <typename> class RetrievalType, typename Callback> |
31 JfrMemorySpace<T, RetrievalType, Callback>:: |
32 JfrMemorySpace<T, RetrievalType, Callback>:: |
32 JfrMemorySpace(size_t min_elem_size, size_t limit_size, size_t cache_count, Callback* callback) : |
33 JfrMemorySpace(size_t min_elem_size, size_t limit_size, size_t cache_count, Callback* callback) : |
33 _free(), |
34 _free(), |
67 } |
68 } |
68 assert(_free.count() == _cache_count, "invariant"); |
69 assert(_free.count() == _cache_count, "invariant"); |
69 return true; |
70 return true; |
70 } |
71 } |
71 |
72 |
|
73 // allocations are even multiples of the mspace min size |
|
74 static inline size_t align_allocation_size(size_t requested_size, size_t min_elem_size) { |
|
75 assert((int)min_elem_size % os::vm_page_size() == 0, "invariant"); |
|
76 u8 alloc_size_bytes = min_elem_size; |
|
77 while (requested_size > alloc_size_bytes) { |
|
78 alloc_size_bytes <<= 1; |
|
79 } |
|
80 assert((int)alloc_size_bytes % os::vm_page_size() == 0, "invariant"); |
|
81 return (size_t)alloc_size_bytes; |
|
82 } |
|
83 |
|
84 template <typename T, template <typename> class RetrievalType, typename Callback> |
|
85 inline T* JfrMemorySpace<T, RetrievalType, Callback>::allocate(size_t size) { |
|
86 const size_t aligned_size_bytes = align_allocation_size(size, _min_elem_size); |
|
87 void* const allocation = JfrCHeapObj::new_array<u1>(aligned_size_bytes + sizeof(T)); |
|
88 if (allocation == NULL) { |
|
89 return NULL; |
|
90 } |
|
91 T* const t = new (allocation) T; |
|
92 assert(t != NULL, "invariant"); |
|
93 if (!t->initialize(sizeof(T), aligned_size_bytes)) { |
|
94 JfrCHeapObj::free(t, aligned_size_bytes + sizeof(T)); |
|
95 return NULL; |
|
96 } |
|
97 return t; |
|
98 } |
|
99 |
|
100 template <typename T, template <typename> class RetrievalType, typename Callback> |
|
101 inline void JfrMemorySpace<T, RetrievalType, Callback>::deallocate(T* t) { |
|
102 assert(t != NULL, "invariant"); |
|
103 assert(!_free.in_list(t), "invariant"); |
|
104 assert(!_full.in_list(t), "invariant"); |
|
105 assert(t != NULL, "invariant"); |
|
106 JfrCHeapObj::free(t, t->total_size()); |
|
107 } |
|
108 |
72 template <typename T, template <typename> class RetrievalType, typename Callback> |
109 template <typename T, template <typename> class RetrievalType, typename Callback> |
73 inline void JfrMemorySpace<T, RetrievalType, Callback>::release_full(T* t) { |
110 inline void JfrMemorySpace<T, RetrievalType, Callback>::release_full(T* t) { |
74 assert(is_locked(), "invariant"); |
111 assert(is_locked(), "invariant"); |
75 assert(t != NULL, "invariant"); |
112 assert(t != NULL, "invariant"); |
76 assert(_full.in_list(t), "invariant"); |
113 assert(_full.in_list(t), "invariant"); |
120 while (iterator.has_next()) { |
157 while (iterator.has_next()) { |
121 callback.process(iterator.next()); |
158 callback.process(iterator.next()); |
122 } |
159 } |
123 } |
160 } |
124 |
161 |
|
162 template <typename Mspace, typename Callback> |
|
163 static inline Mspace* create_mspace(size_t buffer_size, size_t limit, size_t cache_count, Callback* cb) { |
|
164 Mspace* const mspace = new Mspace(buffer_size, limit, cache_count, cb); |
|
165 if (mspace != NULL) { |
|
166 mspace->initialize(); |
|
167 } |
|
168 return mspace; |
|
169 } |
|
170 |
125 template <typename Mspace> |
171 template <typename Mspace> |
126 inline size_t size_adjustment(size_t size, Mspace* mspace) { |
172 inline size_t size_adjustment(size_t size, Mspace* mspace) { |
127 assert(mspace != NULL, "invariant"); |
173 assert(mspace != NULL, "invariant"); |
128 static const size_t min_elem_size = mspace->min_elem_size(); |
174 static const size_t min_elem_size = mspace->min_elem_size(); |
129 if (size < min_elem_size) { |
175 if (size < min_elem_size) { |
170 typename Mspace::Type* const t = mspace_allocate_acquired(size, mspace, thread); |
216 typename Mspace::Type* const t = mspace_allocate_acquired(size, mspace, thread); |
171 if (t == NULL) return NULL; |
217 if (t == NULL) return NULL; |
172 mspace->insert_full_head(t); |
218 mspace->insert_full_head(t); |
173 return t; |
219 return t; |
174 } |
220 } |
|
221 |
|
222 template <typename Mspace> |
|
223 class MspaceLock { |
|
224 private: |
|
225 Mspace* _mspace; |
|
226 public: |
|
227 MspaceLock(Mspace* mspace) : _mspace(mspace) { _mspace->lock(); } |
|
228 ~MspaceLock() { _mspace->unlock(); } |
|
229 }; |
175 |
230 |
176 template <typename Mspace> |
231 template <typename Mspace> |
177 inline typename Mspace::Type* mspace_allocate_transient_to_full(size_t size, Mspace* mspace, Thread* thread) { |
232 inline typename Mspace::Type* mspace_allocate_transient_to_full(size_t size, Mspace* mspace, Thread* thread) { |
178 typename Mspace::Type* const t = mspace_allocate_transient(size, mspace, thread); |
233 typename Mspace::Type* const t = mspace_allocate_transient(size, mspace, thread); |
179 if (t == NULL) return NULL; |
234 if (t == NULL) return NULL; |
340 inline void process_free_list(Processor& processor, Mspace* mspace, jfr_iter_direction direction = forward) { |
395 inline void process_free_list(Processor& processor, Mspace* mspace, jfr_iter_direction direction = forward) { |
341 assert(mspace != NULL, "invariant"); |
396 assert(mspace != NULL, "invariant"); |
342 assert(mspace->has_free(), "invariant"); |
397 assert(mspace->has_free(), "invariant"); |
343 process_free_list_iterator_control<Processor, Mspace, typename Mspace::Iterator>(processor, mspace, direction); |
398 process_free_list_iterator_control<Processor, Mspace, typename Mspace::Iterator>(processor, mspace, direction); |
344 } |
399 } |
|
400 |
|
401 template <typename Mspace> |
|
402 class ReleaseOp : public StackObj { |
|
403 private: |
|
404 Mspace* _mspace; |
|
405 Thread* _thread; |
|
406 bool _release_full; |
|
407 public: |
|
408 typedef typename Mspace::Type Type; |
|
409 ReleaseOp(Mspace* mspace, Thread* thread, bool release_full = true) : |
|
410 _mspace(mspace), _thread(thread), _release_full(release_full) {} |
|
411 bool process(Type* t); |
|
412 size_t processed() const { return 0; } |
|
413 }; |
345 |
414 |
346 template <typename Mspace> |
415 template <typename Mspace> |
347 inline bool ReleaseOp<Mspace>::process(typename Mspace::Type* t) { |
416 inline bool ReleaseOp<Mspace>::process(typename Mspace::Type* t) { |
348 assert(t != NULL, "invariant"); |
417 assert(t != NULL, "invariant"); |
349 // assumes some means of exclusive access to t |
418 // assumes some means of exclusive access to t |