1 /*
   2  * Copyright (c) 2017, Red Hat, Inc. and/or its affiliates.
   3  *
   4  * This code is free software; you can redistribute it and/or modify it
   5  * under the terms of the GNU General Public License version 2 only, as
   6  * published by the Free Software Foundation.
   7  *
   8  * This code is distributed in the hope that it will be useful, but WITHOUT
   9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  11  * version 2 for more details (a copy is included in the LICENSE file that
  12  * accompanied this code).
  13  *
  14  * You should have received a copy of the GNU General Public License version
  15  * 2 along with this work; if not, write to the Free Software Foundation,
  16  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  17  *
  18  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  19  * or visit www.oracle.com if you need additional information or have any
  20  * questions.
  21  *
  22  */
  23 
  24 #include "precompiled.hpp"
  25 #include "gc/shenandoah/shenandoahConnectionMatrix.hpp"
  26 #include "gc/shenandoah/shenandoahConnectionMatrix.inline.hpp"
  27 #include "gc/shenandoah/shenandoahHeap.hpp"
  28 #include "gc/shenandoah/shenandoahHeapRegion.hpp"
  29 #include "gc/shenandoah/shenandoahHeapRegionSet.hpp"
  30 #include "memory/allocation.inline.hpp"
  31 #include "utilities/copy.hpp"
  32 
  33 ShenandoahConnectionMatrix::ShenandoahConnectionMatrix(size_t max_regions) :
  34   _stride(max_regions),
  35   _region_shift(ShenandoahHeapRegion::region_size_shift()),
  36   _matrix(NEW_C_HEAP_ARRAY(char, max_regions * max_regions, mtGC)),
  37   _magic_offset( ((uintptr_t) _matrix) - ( ((uintptr_t) ShenandoahHeap::heap()->base()) >> _region_shift) * (_stride + 1))
  38 
  39 {
  40   if (UseShenandoahMatrix) {
  41     clear_all();
  42   }
  43 }
  44 
  45 ShenandoahConnectionMatrix::~ShenandoahConnectionMatrix() {
  46   FREE_C_HEAP_ARRAY(char, _matrix);
  47 }
  48 
  49 void ShenandoahConnectionMatrix::clear_connected(size_t from_idx, size_t to_idx) {
  50   assert (UseShenandoahMatrix, "call only when matrix is enabled");
  51   _matrix[index_of(from_idx, to_idx)] = 0;
  52 }
  53 
  54 void ShenandoahConnectionMatrix::clear_region(size_t idx) {
  55   assert (UseShenandoahMatrix, "call only when matrix is enabled");
  56   clear_region_inbound(idx);
  57   clear_region_outbound(idx);
  58 }
  59 
  60 void ShenandoahConnectionMatrix::clear_region_outbound(size_t idx) {
  61   assert (UseShenandoahMatrix, "call only when matrix is enabled");
  62   char* matrix = _matrix;
  63   size_t stride = _stride;
  64   size_t count = stride * stride;
  65   for (size_t i = idx; i < count; i += stride) {
  66     matrix[i] = 0;
  67   }
  68 }
  69 
  70 void ShenandoahConnectionMatrix::clear_region_inbound(size_t idx) {
  71   assert (UseShenandoahMatrix, "call only when matrix is enabled");
  72   Copy::fill_to_bytes(_matrix + idx * _stride, _stride, 0);
  73 }
  74 
  75 void ShenandoahConnectionMatrix::clear_all() {
  76   assert (UseShenandoahMatrix, "call only when matrix is enabled");
  77   size_t count = sizeof(char) * _stride * _stride;
  78   Copy::fill_to_bytes(_matrix, count, 0);
  79 }
  80 
  81 void ShenandoahConnectionMatrix::print_on(outputStream* st) const {
  82   assert (UseShenandoahMatrix, "call only when matrix is enabled");
  83   st->print_cr("Connection Matrix:");
  84   st->print_cr("%8s, %10s, %10s, %10s, %8s, %s", "Region", "Live", "Used", "Garbage", "Refcnt", "Referenced by");
  85 
  86   ShenandoahHeap* heap = ShenandoahHeap::heap();
  87   size_t num_regions = heap->num_regions();
  88   for (uint from_idx = 0; from_idx < num_regions; from_idx++) {
  89     ShenandoahHeapRegion* r = heap->regions()->get(from_idx);
  90     if (! r->is_empty()) {
  91       uint count = 0;
  92       for (uint to_idx = 0; to_idx < _stride; to_idx++) {
  93         if (is_connected(to_idx, from_idx)) {
  94           count++;
  95         }
  96       }
  97 
  98       if (count > 0) {
  99         st->print("%8u, "SIZE_FORMAT_W(10)", "SIZE_FORMAT_W(10)", "SIZE_FORMAT_W(10)", %8u, {",
 100                 from_idx, r->get_live_data_bytes(), r->used(), r->garbage(), count);
 101         for (uint to_idx = 0; to_idx < _stride; to_idx++) {
 102           if (is_connected(to_idx, from_idx)) {
 103             st->print("%u, ", to_idx);
 104           }
 105         }
 106         st->print_cr("}");
 107       }
 108     }
 109   }
 110 }