214 if (stored_edge != NULL) {
215 link_with_existing_chain(stored_edge, previous, depth);
216 return true;
217 }
218 stored_edge = link_new_edge(previous, current);
219 assert((*previous)->parent() != NULL, "invariant");
220 *previous = stored_edge;
221 *current = (*current)->parent();
222 ++depth;
223 }
224 return NULL == *current;
225 }
226
227 // Install the immediate edge into the mark word of the leak candidate object
228 StoredEdge* EdgeStore::associate_leak_context_with_candidate(const Edge* edge) {
229 assert(edge != NULL, "invariant");
230 assert(!contains(edge->reference()), "invariant");
231 StoredEdge* const leak_context_edge = put(edge->reference());
232 oop sample_object = edge->pointee();
233 assert(sample_object != NULL, "invariant");
234 assert(NULL == sample_object->mark().to_pointer(), "invariant");
235 sample_object->set_mark(markWord::from_pointer(leak_context_edge));
236 return leak_context_edge;
237 }
238
239 /*
240 * The purpose of put_chain() is to reify the edge sequence
241 * discovered during heap traversal with a normalized logical copy.
242 * This copy consist of two sub-sequences and a connecting link (skip edge).
243 *
244 * "current" can be thought of as the cursor (search) edge, it is not in the edge store.
245 * "previous" is always an edge in the edge store.
246 * The leak context edge is the edge adjacent to the leak candidate object, always an edge in the edge store.
247 */
248 void EdgeStore::put_chain(const Edge* chain, size_t length) {
249 assert(chain != NULL, "invariant");
250 assert(chain->distance_to_root() + 1 == length, "invariant");
251 StoredEdge* const leak_context_edge = associate_leak_context_with_candidate(chain);
252 assert(leak_context_edge != NULL, "invariant");
253 assert(leak_context_edge->parent() == NULL, "invariant");
254
|
214 if (stored_edge != NULL) {
215 link_with_existing_chain(stored_edge, previous, depth);
216 return true;
217 }
218 stored_edge = link_new_edge(previous, current);
219 assert((*previous)->parent() != NULL, "invariant");
220 *previous = stored_edge;
221 *current = (*current)->parent();
222 ++depth;
223 }
224 return NULL == *current;
225 }
226
227 // Install the immediate edge into the mark word of the leak candidate object
228 StoredEdge* EdgeStore::associate_leak_context_with_candidate(const Edge* edge) {
229 assert(edge != NULL, "invariant");
230 assert(!contains(edge->reference()), "invariant");
231 StoredEdge* const leak_context_edge = put(edge->reference());
232 oop sample_object = edge->pointee();
233 assert(sample_object != NULL, "invariant");
234 assert(sample_object->mark().is_marked(), "invariant");
235 sample_object->set_mark(markWord::from_pointer(leak_context_edge));
236 return leak_context_edge;
237 }
238
239 /*
240 * The purpose of put_chain() is to reify the edge sequence
241 * discovered during heap traversal with a normalized logical copy.
242 * This copy consist of two sub-sequences and a connecting link (skip edge).
243 *
244 * "current" can be thought of as the cursor (search) edge, it is not in the edge store.
245 * "previous" is always an edge in the edge store.
246 * The leak context edge is the edge adjacent to the leak candidate object, always an edge in the edge store.
247 */
248 void EdgeStore::put_chain(const Edge* chain, size_t length) {
249 assert(chain != NULL, "invariant");
250 assert(chain->distance_to_root() + 1 == length, "invariant");
251 StoredEdge* const leak_context_edge = associate_leak_context_with_candidate(chain);
252 assert(leak_context_edge != NULL, "invariant");
253 assert(leak_context_edge->parent() == NULL, "invariant");
254
|