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"); |
121 while (iterator.has_next()) { |
158 while (iterator.has_next()) { |
122 callback.process(iterator.next()); |
159 callback.process(iterator.next()); |
123 } |
160 } |
124 } |
161 } |
125 |
162 |
|
163 template <typename Mspace, typename Callback> |
|
164 static inline Mspace* create_mspace(size_t buffer_size, size_t limit, size_t cache_count, Callback* cb) { |
|
165 Mspace* const mspace = new Mspace(buffer_size, limit, cache_count, cb); |
|
166 if (mspace != NULL) { |
|
167 mspace->initialize(); |
|
168 } |
|
169 return mspace; |
|
170 } |
|
171 |
126 template <typename Mspace> |
172 template <typename Mspace> |
127 inline size_t size_adjustment(size_t size, Mspace* mspace) { |
173 inline size_t size_adjustment(size_t size, Mspace* mspace) { |
128 assert(mspace != NULL, "invariant"); |
174 assert(mspace != NULL, "invariant"); |
129 static const size_t min_elem_size = mspace->min_elem_size(); |
175 static const size_t min_elem_size = mspace->min_elem_size(); |
130 if (size < min_elem_size) { |
176 if (size < min_elem_size) { |
171 typename Mspace::Type* const t = mspace_allocate_acquired(size, mspace, thread); |
217 typename Mspace::Type* const t = mspace_allocate_acquired(size, mspace, thread); |
172 if (t == NULL) return NULL; |
218 if (t == NULL) return NULL; |
173 mspace->insert_full_head(t); |
219 mspace->insert_full_head(t); |
174 return t; |
220 return t; |
175 } |
221 } |
|
222 |
|
223 template <typename Mspace> |
|
224 class MspaceLock { |
|
225 private: |
|
226 Mspace* _mspace; |
|
227 public: |
|
228 MspaceLock(Mspace* mspace) : _mspace(mspace) { _mspace->lock(); } |
|
229 ~MspaceLock() { _mspace->unlock(); } |
|
230 }; |
176 |
231 |
177 template <typename Mspace> |
232 template <typename Mspace> |
178 inline typename Mspace::Type* mspace_allocate_transient_to_full(size_t size, Mspace* mspace, Thread* thread) { |
233 inline typename Mspace::Type* mspace_allocate_transient_to_full(size_t size, Mspace* mspace, Thread* thread) { |
179 typename Mspace::Type* const t = mspace_allocate_transient(size, mspace, thread); |
234 typename Mspace::Type* const t = mspace_allocate_transient(size, mspace, thread); |
180 if (t == NULL) return NULL; |
235 if (t == NULL) return NULL; |
341 inline void process_free_list(Processor& processor, Mspace* mspace, jfr_iter_direction direction = forward) { |
396 inline void process_free_list(Processor& processor, Mspace* mspace, jfr_iter_direction direction = forward) { |
342 assert(mspace != NULL, "invariant"); |
397 assert(mspace != NULL, "invariant"); |
343 assert(mspace->has_free(), "invariant"); |
398 assert(mspace->has_free(), "invariant"); |
344 process_free_list_iterator_control<Processor, Mspace, typename Mspace::Iterator>(processor, mspace, direction); |
399 process_free_list_iterator_control<Processor, Mspace, typename Mspace::Iterator>(processor, mspace, direction); |
345 } |
400 } |
|
401 |
|
402 template <typename Mspace> |
|
403 class ReleaseOp : public StackObj { |
|
404 private: |
|
405 Mspace* _mspace; |
|
406 Thread* _thread; |
|
407 bool _release_full; |
|
408 public: |
|
409 typedef typename Mspace::Type Type; |
|
410 ReleaseOp(Mspace* mspace, Thread* thread, bool release_full = true) : |
|
411 _mspace(mspace), _thread(thread), _release_full(release_full) {} |
|
412 bool process(Type* t); |
|
413 size_t processed() const { return 0; } |
|
414 }; |
346 |
415 |
347 template <typename Mspace> |
416 template <typename Mspace> |
348 inline bool ReleaseOp<Mspace>::process(typename Mspace::Type* t) { |
417 inline bool ReleaseOp<Mspace>::process(typename Mspace::Type* t) { |
349 assert(t != NULL, "invariant"); |
418 assert(t != NULL, "invariant"); |
350 // assumes some means of exclusive access to t |
419 // assumes some means of exclusive access to t |