1 /*
   2  * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #include "precompiled.hpp"
  26 #include "jfr/leakprofiler/chains/edgeStore.hpp"
  27 #include "jfr/leakprofiler/chains/edgeUtils.hpp"
  28 #include "jfr/leakprofiler/utilities/unifiedOopRef.inline.hpp"
  29 #include "oops/oop.inline.hpp"
  30 
  31 StoredEdge::StoredEdge(const Edge* parent, UnifiedOopRef reference) : Edge(parent, reference), _gc_root_id(0), _skip_length(0) {}
  32 
  33 StoredEdge::StoredEdge(const Edge& edge) : Edge(edge), _gc_root_id(0), _skip_length(0) {}
  34 
  35 StoredEdge::StoredEdge(const StoredEdge& edge) : Edge(edge), _gc_root_id(edge._gc_root_id), _skip_length(edge._skip_length) {}
  36 
  37 traceid EdgeStore::_edge_id_counter = 0;
  38 
  39 EdgeStore::EdgeStore() : _edges(NULL) {
  40   _edges = new EdgeHashTable(this);
  41 }
  42 
  43 EdgeStore::~EdgeStore() {
  44   assert(_edges != NULL, "invariant");
  45   delete _edges;
  46 }
  47 
  48 bool EdgeStore::is_empty() const {
  49   return !_edges->has_entries();
  50 }
  51 
  52 void EdgeStore::on_link(EdgeEntry* entry) {
  53   assert(entry != NULL, "invariant");
  54   assert(entry->id() == 0, "invariant");
  55   entry->set_id(++_edge_id_counter);
  56 }
  57 
  58 bool EdgeStore::on_equals(uintptr_t hash, const EdgeEntry* entry) {
  59   assert(entry != NULL, "invariant");
  60   assert(entry->hash() == hash, "invariant");
  61   return true;
  62 }
  63 
  64 void EdgeStore::on_unlink(EdgeEntry* entry) {
  65   assert(entry != NULL, "invariant");
  66   // nothing
  67 }
  68 
  69 #ifdef ASSERT
  70 bool EdgeStore::contains(UnifiedOopRef reference) const {
  71   return get(reference) != NULL;
  72 }
  73 #endif
  74 
  75 StoredEdge* EdgeStore::get(UnifiedOopRef reference) const {
  76   assert(!reference.is_null(), "invariant");
  77   EdgeEntry* const entry = _edges->lookup_only(reference.addr<uintptr_t>());
  78   return entry != NULL ? entry->literal_addr() : NULL;
  79 }
  80 
  81 StoredEdge* EdgeStore::put(UnifiedOopRef reference) {
  82   assert(!reference.is_null(), "invariant");
  83   const StoredEdge e(NULL, reference);
  84   assert(NULL == _edges->lookup_only(reference.addr<uintptr_t>()), "invariant");
  85   EdgeEntry& entry = _edges->put(reference.addr<uintptr_t>(), e);
  86   return entry.literal_addr();
  87 }
  88 
  89 traceid EdgeStore::get_id(const Edge* edge) const {
  90   assert(edge != NULL, "invariant");
  91   EdgeEntry* const entry = _edges->lookup_only(edge->reference().addr<uintptr_t>());
  92   assert(entry != NULL, "invariant");
  93   return entry->id();
  94 }
  95 
  96 traceid EdgeStore::gc_root_id(const Edge* edge) const {
  97   assert(edge != NULL, "invariant");
  98   const traceid gc_root_id = static_cast<const StoredEdge*>(edge)->gc_root_id();
  99   if (gc_root_id != 0) {
 100     return gc_root_id;
 101   }
 102   // not cached
 103   assert(edge != NULL, "invariant");
 104   const Edge* const root = EdgeUtils::root(*edge);
 105   assert(root != NULL, "invariant");
 106   assert(root->parent() == NULL, "invariant");
 107   return get_id(root);
 108 }
 109 
 110 static const Edge* get_skip_ancestor(const Edge** current, size_t distance_to_root, size_t* skip_length) {
 111   assert(distance_to_root >= EdgeUtils::root_context, "invariant");
 112   assert(*skip_length == 0, "invariant");
 113   *skip_length = distance_to_root - (EdgeUtils::root_context - 1);
 114   const Edge* const target = EdgeUtils::ancestor(**current, *skip_length);
 115   assert(target != NULL, "invariant");
 116   assert(target->distance_to_root() + 1 == EdgeUtils::root_context, "invariant");
 117   return target;
 118 }
 119 
 120 bool EdgeStore::put_skip_edge(StoredEdge** previous, const Edge** current, size_t distance_to_root) {
 121   assert(*previous != NULL, "invariant");
 122   assert((*previous)->parent() == NULL, "invariant");
 123   assert(*current != NULL, "invariant");
 124   assert((*current)->distance_to_root() == distance_to_root, "invariant");
 125 
 126   if (distance_to_root < EdgeUtils::root_context) {
 127     // nothing to skip
 128     return false;
 129   }
 130 
 131   size_t skip_length = 0;
 132   const Edge* const skip_ancestor = get_skip_ancestor(current, distance_to_root, &skip_length);
 133   assert(skip_ancestor != NULL, "invariant");
 134   (*previous)->set_skip_length(skip_length);
 135 
 136   // lookup target
 137   StoredEdge* stored_target = get(skip_ancestor->reference());
 138   if (stored_target != NULL) {
 139     (*previous)->set_parent(stored_target);
 140     // linked to existing, complete
 141     return true;
 142   }
 143 
 144   assert(stored_target == NULL, "invariant");
 145   stored_target = put(skip_ancestor->reference());
 146   assert(stored_target != NULL, "invariant");
 147   (*previous)->set_parent(stored_target);
 148   *previous = stored_target;
 149   *current = skip_ancestor->parent();
 150   return false;
 151 }
 152 
 153 static void link_edge(const StoredEdge* current_stored, StoredEdge** previous) {
 154   assert(current_stored != NULL, "invariant");
 155   assert(*previous != NULL, "invariant");
 156   assert((*previous)->parent() == NULL, "invariant");
 157   (*previous)->set_parent(current_stored);
 158 }
 159 
 160 static const StoredEdge* find_closest_skip_edge(const StoredEdge* edge, size_t* distance) {
 161   assert(edge != NULL, "invariant");
 162   assert(distance != NULL, "invariant");
 163   const StoredEdge* current = edge;
 164   *distance = 1;
 165   while (current != NULL && !current->is_skip_edge()) {
 166     ++(*distance);
 167     current = current->parent();
 168   }
 169   return current;
 170 }
 171 
 172 void EdgeStore::link_with_existing_chain(const StoredEdge* current_stored, StoredEdge** previous, size_t previous_length) {
 173   assert(current_stored != NULL, "invariant");
 174   assert((*previous)->parent() == NULL, "invariant");
 175   size_t distance_to_skip_edge; // including the skip edge itself
 176   const StoredEdge* const closest_skip_edge = find_closest_skip_edge(current_stored, &distance_to_skip_edge);
 177   if (closest_skip_edge == NULL) {
 178     // no found skip edge implies root
 179     if (distance_to_skip_edge + previous_length <= EdgeUtils::max_ref_chain_depth) {
 180       link_edge(current_stored, previous);
 181       return;
 182     }
 183     assert(current_stored->distance_to_root() == distance_to_skip_edge - 2, "invariant");
 184     put_skip_edge(previous, reinterpret_cast<const Edge**>(&current_stored), distance_to_skip_edge - 2);
 185     return;
 186   }
 187   assert(closest_skip_edge->is_skip_edge(), "invariant");
 188   if (distance_to_skip_edge + previous_length <= EdgeUtils::leak_context) {
 189     link_edge(current_stored, previous);
 190     return;
 191   }
 192   // create a new skip edge with derived information from closest skip edge
 193   (*previous)->set_skip_length(distance_to_skip_edge + closest_skip_edge->skip_length());
 194   (*previous)->set_parent(closest_skip_edge->parent());
 195 }
 196 
 197 StoredEdge* EdgeStore::link_new_edge(StoredEdge** previous, const Edge** current) {
 198   assert(*previous != NULL, "invariant");
 199   assert((*previous)->parent() == NULL, "invariant");
 200   assert(*current != NULL, "invariant");
 201   assert(!contains((*current)->reference()), "invariant");
 202   StoredEdge* const stored_edge = put((*current)->reference());
 203   assert(stored_edge != NULL, "invariant");
 204   link_edge(stored_edge, previous);
 205   return stored_edge;
 206 }
 207 
 208 bool EdgeStore::put_edges(StoredEdge** previous, const Edge** current, size_t limit) {
 209   assert(*previous != NULL, "invariant");
 210   assert(*current != NULL, "invariant");
 211   size_t depth = 1;
 212   while (*current != NULL && depth < limit) {
 213     StoredEdge* stored_edge = get((*current)->reference());
 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 
 255   if (1 == length) {
 256     store_gc_root_id_in_leak_context_edge(leak_context_edge, leak_context_edge);
 257     return;
 258   }
 259 
 260   const Edge* current = chain->parent();
 261   assert(current != NULL, "invariant");
 262   StoredEdge* previous = leak_context_edge;
 263 
 264   // a leak context is the sequence of (limited) edges reachable from the leak candidate
 265   if (put_edges(&previous, &current, EdgeUtils::leak_context)) {
 266     // complete
 267     assert(previous != NULL, "invariant");
 268     put_chain_epilogue(leak_context_edge, EdgeUtils::root(*previous));
 269     return;
 270   }
 271 
 272   const size_t distance_to_root = length > EdgeUtils::leak_context ? length - 1 - EdgeUtils::leak_context : length - 1;
 273   assert(current->distance_to_root() == distance_to_root, "invariant");
 274 
 275   // a skip edge is the logical link
 276   // connecting the leak context sequence with the root context sequence
 277   if (put_skip_edge(&previous, &current, distance_to_root)) {
 278     // complete
 279     assert(previous != NULL, "invariant");
 280     assert(previous->is_skip_edge(), "invariant");
 281     assert(previous->parent() != NULL, "invariant");
 282     put_chain_epilogue(leak_context_edge, EdgeUtils::root(*previous->parent()));
 283     return;
 284   }
 285 
 286   assert(current->distance_to_root() < EdgeUtils::root_context, "invariant");
 287 
 288   // a root context is the sequence of (limited) edges reachable from the root
 289   put_edges(&previous, &current, EdgeUtils::root_context);
 290   assert(previous != NULL, "invariant");
 291   put_chain_epilogue(leak_context_edge, EdgeUtils::root(*previous));
 292 }
 293 
 294 void EdgeStore::put_chain_epilogue(StoredEdge* leak_context_edge, const Edge* root) const {
 295   assert(leak_context_edge != NULL, "invariant");
 296   assert(root != NULL, "invariant");
 297   store_gc_root_id_in_leak_context_edge(leak_context_edge, root);
 298   assert(leak_context_edge->distance_to_root() + 1 <= EdgeUtils::max_ref_chain_depth, "invariant");
 299 }
 300 
 301 // To avoid another traversal to resolve the root edge id later,
 302 // cache it in the immediate leak context edge for fast retrieval.
 303 void EdgeStore::store_gc_root_id_in_leak_context_edge(StoredEdge* leak_context_edge, const Edge* root) const {
 304   assert(leak_context_edge != NULL, "invariant");
 305   assert(leak_context_edge->gc_root_id() == 0, "invariant");
 306   assert(root != NULL, "invariant");
 307   assert(root->parent() == NULL, "invariant");
 308   assert(root->distance_to_root() == 0, "invariant");
 309   const StoredEdge* const stored_root = static_cast<const StoredEdge*>(root);
 310   traceid root_id = stored_root->gc_root_id();
 311   if (root_id == 0) {
 312     root_id = get_id(root);
 313     stored_root->set_gc_root_id(root_id);
 314   }
 315   assert(root_id != 0, "invariant");
 316   leak_context_edge->set_gc_root_id(root_id);
 317   assert(leak_context_edge->gc_root_id() == stored_root->gc_root_id(), "invariant");
 318 }