233 }
234
235 bool EdgeStore::has_leak_context(const ObjectSample* sample) const {
236 const int idx = leak_context_edge_idx(sample);
237 if (idx == 0) {
238 return false;
239 }
240 assert(idx > 0, "invariant");
241 assert(_leak_context_edges != nullptr, "invariant");
242 assert(idx < _leak_context_edges->length(), "invariant");
243 assert(_leak_context_edges->at(idx) != nullptr, "invariant");
244 return true;
245 }
246
247 const StoredEdge* EdgeStore::get(const ObjectSample* sample) const {
248 assert(sample != nullptr, "invariant");
249 if (_leak_context_edges != nullptr) {
250 assert(SafepointSynchronize::is_at_safepoint(), "invariant");
251 const int idx = leak_context_edge_idx(sample);
252 if (idx > 0) {
253 assert(idx < _leak_context_edges->length(), "invariant");
254 const StoredEdge* const edge =_leak_context_edges->at(idx);
255 assert(edge != nullptr, "invariant");
256 return edge;
257 }
258 }
259 return get(UnifiedOopRef::encode_in_native(sample->object_addr()));
260 }
261
262 #ifdef ASSERT
263 // max_idx to ensure idx fit in lower 32-bits of markword together with lock bits.
264 static constexpr const int max_idx = right_n_bits(32 - markWord::lock_bits);
265
266 static void store_idx_precondition(oop sample_object, int idx) {
267 assert(sample_object != nullptr, "invariant");
268 assert(sample_object->mark().is_marked(), "invariant");
269 assert(idx > 0, "invariant");
270 assert(idx <= max_idx, "invariant");
271 }
272 #endif
273
274 static void store_idx_in_markword(oop sample_object, int idx) {
275 DEBUG_ONLY(store_idx_precondition(sample_object, idx);)
276 const markWord idx_mark_word(sample_object->mark().value() | idx << markWord::lock_bits);
277 sample_object->set_mark(idx_mark_word);
278 assert(sample_object->mark().is_marked(), "must still be marked");
279 }
280
281 static const int initial_size = 64;
282
283 static int save(const StoredEdge* edge) {
284 assert(edge != nullptr, "invariant");
285 if (_leak_context_edges == nullptr) {
286 _leak_context_edges = new (mtTracing) GrowableArray<const StoredEdge*>(initial_size, mtTracing);
287 _leak_context_edges->append(nullptr); // next idx now at 1, for disambiguation in markword.
288 }
289 return _leak_context_edges->append(edge);
290 }
|
233 }
234
235 bool EdgeStore::has_leak_context(const ObjectSample* sample) const {
236 const int idx = leak_context_edge_idx(sample);
237 if (idx == 0) {
238 return false;
239 }
240 assert(idx > 0, "invariant");
241 assert(_leak_context_edges != nullptr, "invariant");
242 assert(idx < _leak_context_edges->length(), "invariant");
243 assert(_leak_context_edges->at(idx) != nullptr, "invariant");
244 return true;
245 }
246
247 const StoredEdge* EdgeStore::get(const ObjectSample* sample) const {
248 assert(sample != nullptr, "invariant");
249 if (_leak_context_edges != nullptr) {
250 assert(SafepointSynchronize::is_at_safepoint(), "invariant");
251 const int idx = leak_context_edge_idx(sample);
252 if (idx > 0) {
253 assert(idx < _leak_context_edges->length(), "invariant idx: %d >= length: %d", idx, _leak_context_edges->length());
254 const StoredEdge* const edge =_leak_context_edges->at(idx);
255 assert(edge != nullptr, "invariant");
256 return edge;
257 }
258 }
259 return get(UnifiedOopRef::encode_in_native(sample->object_addr()));
260 }
261
262 #ifdef ASSERT
263 // max_idx to ensure idx fit in lower 32-bits of markword together with lock bits.
264 static constexpr const int max_idx = right_n_bits(32 - markWord::lock_bits);
265
266 static void store_idx_precondition(oop sample_object, int idx) {
267 assert(sample_object != nullptr, "invariant");
268 assert(sample_object->mark().is_marked(), "invariant");
269 assert(idx > 0, "invariant");
270 assert(idx <= max_idx, "invariant");
271 const int upper_bits = sample_object->mark().value() >> markWord::lock_bits;
272 assert((upper_bits | idx) == idx, "idx codec error : (%d | %d) != %d", upper_bits, idx, idx);
273 }
274 #endif
275
276 static void store_idx_in_markword(oop sample_object, int idx) {
277 DEBUG_ONLY(store_idx_precondition(sample_object, idx);)
278 const markWord idx_mark_word(sample_object->mark().value() | idx << markWord::lock_bits);
279 sample_object->set_mark(idx_mark_word);
280 assert(sample_object->mark().is_marked(), "must still be marked");
281 }
282
283 static const int initial_size = 64;
284
285 static int save(const StoredEdge* edge) {
286 assert(edge != nullptr, "invariant");
287 if (_leak_context_edges == nullptr) {
288 _leak_context_edges = new (mtTracing) GrowableArray<const StoredEdge*>(initial_size, mtTracing);
289 _leak_context_edges->append(nullptr); // next idx now at 1, for disambiguation in markword.
290 }
291 return _leak_context_edges->append(edge);
292 }
|