< prev index next >

src/share/vm/gc/shenandoah/shenandoahBarrierSet.cpp

Print this page
rev 13055 : Implement barriers for maintaining connection matrix.


   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/g1/g1SATBCardTableModRefBS.hpp"
  26 #include "gc/shenandoah/shenandoahBarrierSet.hpp"

  27 #include "gc/shenandoah/shenandoahHeap.inline.hpp"
  28 #include "runtime/interfaceSupport.hpp"
  29 
  30 class UpdateRefsForOopClosure: public ExtendedOopClosure {
  31 
  32 private:
  33   ShenandoahHeap* _heap;
  34   template <class T>
  35   inline void do_oop_work(T* p) {
  36     _heap->maybe_update_oop_ref(p);
  37   }
  38 public:
  39   UpdateRefsForOopClosure() {
  40     _heap = ShenandoahHeap::heap();
  41   }
  42 
  43   void do_oop(oop* p)       {
  44     do_oop_work(p);
  45   }
  46 
  47   void do_oop(narrowOop* p) {
  48     do_oop_work(p);
  49   }
  50 
  51 };
  52 


























  53 ShenandoahBarrierSet::ShenandoahBarrierSet(ShenandoahHeap* heap) :
  54   BarrierSet(BarrierSet::FakeRtti(BarrierSet::ShenandoahBarrierSet)),
  55   _heap(heap)
  56 {
  57 }
  58 
  59 void ShenandoahBarrierSet::print_on(outputStream* st) const {
  60   st->print("ShenandoahBarrierSet");
  61 }
  62 
  63 bool ShenandoahBarrierSet::is_a(BarrierSet::Name bsn) {
  64   return bsn == BarrierSet::ShenandoahBarrierSet;
  65 }
  66 
  67 bool ShenandoahBarrierSet::has_read_prim_array_opt() {
  68   return true;
  69 }
  70 
  71 bool ShenandoahBarrierSet::has_read_prim_barrier() {
  72   return false;


 143 }
 144 
 145 void ShenandoahBarrierSet::resize_covered_region(MemRegion mr) {
 146   Unimplemented();
 147 }
 148 
 149 void ShenandoahBarrierSet::write_prim_array(MemRegion mr) {
 150   Unimplemented();
 151 }
 152 
 153 void ShenandoahBarrierSet::write_prim_field(HeapWord* hw, size_t s , juint x, juint y) {
 154   Unimplemented();
 155 }
 156 
 157 bool ShenandoahBarrierSet::write_prim_needs_barrier(HeapWord* hw, size_t s, juint x, juint y) {
 158   Unimplemented();
 159   return false;
 160 }
 161 
 162 bool ShenandoahBarrierSet::need_update_refs_barrier() {
 163   return _heap->concurrent_mark_in_progress() && _heap->need_update_refs();
 164 }
 165 
 166 void ShenandoahBarrierSet::write_ref_array_work(MemRegion r) {
 167   ShouldNotReachHere();
 168 }
 169 
 170 void ShenandoahBarrierSet::write_ref_array(HeapWord* start, size_t count) {
 171   if (! need_update_refs_barrier()) return;



 172   if (UseCompressedOops) {
 173     narrowOop* dst = (narrowOop*) start;
 174     for (size_t i = 0; i < count; i++, dst++) {
 175       _heap->maybe_update_oop_ref(dst);



 176     }
 177   } else {
 178     oop* dst = (oop*) start;
 179     for (size_t i = 0; i < count; i++, dst++) {
 180       _heap->maybe_update_oop_ref(dst);



 181     }
 182   }
 183 }
 184 
 185 template <class T>
 186 void ShenandoahBarrierSet::write_ref_array_pre_work(T* dst, int count) {
 187 
 188 #ifdef ASSERT
 189     if (_heap->is_in(dst) &&
 190         _heap->in_collection_set(dst) &&
 191         ! _heap->cancelled_concgc()) {
 192       tty->print_cr("dst = "PTR_FORMAT, p2i(dst));
 193       _heap->heap_region_containing((HeapWord*) dst)->print();
 194       assert(false, "We should have fixed this earlier");
 195     }
 196 #endif
 197 
 198   if (! JavaThread::satb_mark_queue_set().is_active()) return;
 199   T* elem_ptr = dst;
 200   for (int i = 0; i < count; i++, elem_ptr++) {
 201     T heap_oop = oopDesc::load_heap_oop(elem_ptr);
 202     if (!oopDesc::is_null(heap_oop)) {
 203       G1SATBCardTableModRefBS::enqueue(oopDesc::decode_heap_oop_not_null(heap_oop));
 204     }
 205   }
 206 }
 207 
 208 void ShenandoahBarrierSet::write_ref_array_pre(oop* dst, int count, bool dest_uninitialized) {
 209   if (! dest_uninitialized) {
 210     write_ref_array_pre_work(dst, count);
 211   }
 212 }
 213 
 214 void ShenandoahBarrierSet::write_ref_array_pre(narrowOop* dst, int count, bool dest_uninitialized) {
 215   if (! dest_uninitialized) {
 216     write_ref_array_pre_work(dst, count);
 217   }
 218 }
 219 
 220 template <class T>
 221 void ShenandoahBarrierSet::write_ref_field_pre_static(T* field, oop newVal) {
 222   T heap_oop = oopDesc::load_heap_oop(field);
 223 
 224 #ifdef ASSERT

 225   ShenandoahHeap* heap = ShenandoahHeap::heap();
 226     if (heap->is_in(field) &&
 227         heap->in_collection_set(field) &&
 228         ! heap->cancelled_concgc()) {
 229       tty->print_cr("field = "PTR_FORMAT, p2i(field));
 230       tty->print_cr("in_cset: %s", BOOL_TO_STR(heap->in_collection_set(field)));
 231       heap->heap_region_containing((HeapWord*)field)->print();
 232       tty->print_cr("marking: %s, evacuating: %s",
 233                     BOOL_TO_STR(heap->concurrent_mark_in_progress()),
 234                     BOOL_TO_STR(heap->is_evacuation_in_progress()));
 235       assert(false, "We should have fixed this earlier");
 236     }

 237 #endif
 238 
 239   if (!oopDesc::is_null(heap_oop)) {
 240     G1SATBCardTableModRefBS::enqueue(oopDesc::decode_heap_oop(heap_oop));
 241   }





 242 }
 243 
 244 template <class T>
 245 inline void ShenandoahBarrierSet::inline_write_ref_field_pre(T* field, oop newVal) {
 246   write_ref_field_pre_static(field, newVal);
 247 }
 248 
 249 // These are the more general virtual versions.
 250 void ShenandoahBarrierSet::write_ref_field_pre_work(oop* field, oop new_val) {
 251   write_ref_field_pre_static(field, new_val);
 252 }
 253 
 254 void ShenandoahBarrierSet::write_ref_field_pre_work(narrowOop* field, oop new_val) {
 255   write_ref_field_pre_static(field, new_val);
 256 }
 257 
 258 void ShenandoahBarrierSet::write_ref_field_pre_work(void* field, oop new_val) {
 259   guarantee(false, "Not needed");
 260 }
 261 
 262 void ShenandoahBarrierSet::write_ref_field_work(void* v, oop o, bool release) {
 263 #ifdef ASSERT
 264   ShenandoahHeap* heap = ShenandoahHeap::heap();
 265   if (!(heap->cancelled_concgc() || !heap->in_collection_set(v))) {
 266     tty->print_cr("field not in collection set: "PTR_FORMAT, p2i(v));
 267     tty->print_cr("containing heap region:");
 268     ShenandoahHeap::heap()->heap_region_containing(v)->print();
 269   }
 270   assert(heap->cancelled_concgc() || !heap->in_collection_set(v), "only write to to-space");
 271   if (! need_update_refs_barrier()) return;
 272   assert(o == NULL || oopDesc::unsafe_equals(o, resolve_oop_static(o)), "only write to-space values");
 273   assert(o == NULL || !heap->in_collection_set(o), "only write to-space values");

 274 #endif





 275 }
 276 
 277 void ShenandoahBarrierSet::write_region_work(MemRegion mr) {
 278 
 279   if (! need_update_refs_barrier()) return;
 280 
 281   // This is called for cloning an object (see jvm.cpp) after the clone
 282   // has been made. We are not interested in any 'previous value' because
 283   // it would be NULL in any case. But we *are* interested in any oop*
 284   // that potentially need to be updated.
 285 
 286   oop obj = oop(mr.start());
 287   assert(obj->is_oop(), "must be an oop");




 288   UpdateRefsForOopClosure cl;
 289   obj->oop_iterate(&cl);

 290 }
 291 
 292 oop ShenandoahBarrierSet::read_barrier(oop src) {
 293   if (ShenandoahReadBarrier) {
 294     return ShenandoahBarrierSet::resolve_oop_static(src);
 295   } else {
 296     return src;
 297   }
 298 }
 299 
 300 bool ShenandoahBarrierSet::obj_equals(oop obj1, oop obj2) {
 301   bool eq = oopDesc::unsafe_equals(obj1, obj2);
 302   if (! eq && ShenandoahAcmpBarrier) {
 303     OrderAccess::loadload();
 304     obj1 = resolve_oop_static(obj1);
 305     obj2 = resolve_oop_static(obj2);
 306     eq = oopDesc::unsafe_equals(obj1, obj2);
 307   }
 308   return eq;
 309 }




   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/g1/g1SATBCardTableModRefBS.hpp"
  26 #include "gc/shenandoah/shenandoahBarrierSet.hpp"
  27 #include "gc/shenandoah/shenandoahConnectionMatrix.hpp"
  28 #include "gc/shenandoah/shenandoahHeap.inline.hpp"
  29 #include "runtime/interfaceSupport.hpp"
  30 
  31 class UpdateRefsForOopClosure: public ExtendedOopClosure {
  32 
  33 private:
  34   ShenandoahHeap* _heap;
  35   template <class T>
  36   inline void do_oop_work(T* p) {
  37     _heap->maybe_update_oop_ref(p);
  38   }
  39 public:
  40   UpdateRefsForOopClosure() {
  41     _heap = ShenandoahHeap::heap();
  42   }
  43 
  44   void do_oop(oop* p)       {
  45     do_oop_work(p);
  46   }
  47 
  48   void do_oop(narrowOop* p) {
  49     do_oop_work(p);
  50   }
  51 
  52 };
  53 
  54 class UpdateRefsForOopMatrixClosure: public ExtendedOopClosure {
  55 
  56 private:
  57   ShenandoahHeap* _heap;
  58   template <class T>
  59   inline void do_oop_work(T* p) {
  60     oop o = _heap->maybe_update_oop_ref(p);
  61     if (! oopDesc::is_null(o)) {
  62       _heap->connection_matrix()->set_connected(_heap->heap_region_index_containing(p), _heap->heap_region_index_containing(o), true);
  63     }
  64   }
  65 public:
  66   UpdateRefsForOopMatrixClosure() {
  67     _heap = ShenandoahHeap::heap();
  68   }
  69 
  70   void do_oop(oop* p)       {
  71     do_oop_work(p);
  72   }
  73 
  74   void do_oop(narrowOop* p) {
  75     do_oop_work(p);
  76   }
  77 
  78 };
  79 
  80 ShenandoahBarrierSet::ShenandoahBarrierSet(ShenandoahHeap* heap) :
  81   BarrierSet(BarrierSet::FakeRtti(BarrierSet::ShenandoahBarrierSet)),
  82   _heap(heap)
  83 {
  84 }
  85 
  86 void ShenandoahBarrierSet::print_on(outputStream* st) const {
  87   st->print("ShenandoahBarrierSet");
  88 }
  89 
  90 bool ShenandoahBarrierSet::is_a(BarrierSet::Name bsn) {
  91   return bsn == BarrierSet::ShenandoahBarrierSet;
  92 }
  93 
  94 bool ShenandoahBarrierSet::has_read_prim_array_opt() {
  95   return true;
  96 }
  97 
  98 bool ShenandoahBarrierSet::has_read_prim_barrier() {
  99   return false;


 170 }
 171 
 172 void ShenandoahBarrierSet::resize_covered_region(MemRegion mr) {
 173   Unimplemented();
 174 }
 175 
 176 void ShenandoahBarrierSet::write_prim_array(MemRegion mr) {
 177   Unimplemented();
 178 }
 179 
 180 void ShenandoahBarrierSet::write_prim_field(HeapWord* hw, size_t s , juint x, juint y) {
 181   Unimplemented();
 182 }
 183 
 184 bool ShenandoahBarrierSet::write_prim_needs_barrier(HeapWord* hw, size_t s, juint x, juint y) {
 185   Unimplemented();
 186   return false;
 187 }
 188 
 189 bool ShenandoahBarrierSet::need_update_refs_barrier() {
 190   return UseShenandoahMatrix || (_heap->concurrent_mark_in_progress() && _heap->need_update_refs());
 191 }
 192 
 193 void ShenandoahBarrierSet::write_ref_array_work(MemRegion r) {
 194   ShouldNotReachHere();
 195 }
 196 
 197 void ShenandoahBarrierSet::write_ref_array(HeapWord* start, size_t count) {
 198   if (! need_update_refs_barrier()) return;
 199   ShenandoahHeap* heap = ShenandoahHeap::heap();
 200   ShenandoahConnectionMatrix* matrix = heap->connection_matrix();
 201   // TODO: Use templated loop and split on oop/narrowOop and UseShenandoahMatrix.
 202   if (UseCompressedOops) {
 203     narrowOop* dst = (narrowOop*) start;
 204     for (size_t i = 0; i < count; i++, dst++) {
 205       oop o = _heap->maybe_update_oop_ref(dst);
 206       if (UseShenandoahMatrix && ! oopDesc::is_null(o)) {
 207         matrix->set_connected(heap->heap_region_index_containing(dst), heap->heap_region_index_containing(o), true);
 208       }
 209     }
 210   } else {
 211     oop* dst = (oop*) start;
 212     for (size_t i = 0; i < count; i++, dst++) {
 213       oop o = _heap->maybe_update_oop_ref(dst);
 214       if (UseShenandoahMatrix && ! oopDesc::is_null(o)) {
 215         matrix->set_connected(heap->heap_region_index_containing(dst), heap->heap_region_index_containing(o), true);
 216       }
 217     }
 218   }
 219 }
 220 
 221 template <class T>
 222 void ShenandoahBarrierSet::write_ref_array_pre_work(T* dst, int count) {
 223 
 224 #ifdef ASSERT
 225     if (_heap->is_in(dst) &&
 226         _heap->in_collection_set(dst) &&
 227         ! _heap->cancelled_concgc()) {
 228       tty->print_cr("dst = "PTR_FORMAT, p2i(dst));
 229       _heap->heap_region_containing((HeapWord*) dst)->print();
 230       assert(false, "We should have fixed this earlier");
 231     }
 232 #endif
 233 
 234   if (! JavaThread::satb_mark_queue_set().is_active()) return;
 235   T* elem_ptr = dst;
 236   for (int i = 0; i < count; i++, elem_ptr++) {
 237     T heap_oop = oopDesc::load_heap_oop(elem_ptr);
 238     if (!oopDesc::is_null(heap_oop)) {
 239       G1SATBCardTableModRefBS::enqueue(oopDesc::decode_heap_oop_not_null(heap_oop));
 240     }
 241   }
 242 }
 243 
 244 void ShenandoahBarrierSet::write_ref_array_pre(oop* dst, int count, bool dest_uninitialized) {
 245   if (! dest_uninitialized) {
 246     write_ref_array_pre_work(dst, count);
 247   }
 248 }
 249 
 250 void ShenandoahBarrierSet::write_ref_array_pre(narrowOop* dst, int count, bool dest_uninitialized) {
 251   if (! dest_uninitialized) {
 252     write_ref_array_pre_work(dst, count);
 253   }
 254 }
 255 
 256 template <class T>
 257 void ShenandoahBarrierSet::write_ref_field_pre_static(T* field, oop new_val) {
 258   T heap_oop = oopDesc::load_heap_oop(field);
 259 
 260 #ifdef ASSERT
 261   {
 262     ShenandoahHeap* heap = ShenandoahHeap::heap();
 263     if (heap->is_in(field) &&
 264         heap->in_collection_set(field) &&
 265         ! heap->cancelled_concgc()) {
 266       tty->print_cr("field = "PTR_FORMAT, p2i(field));
 267       tty->print_cr("in_cset: %s", BOOL_TO_STR(heap->in_collection_set(field)));
 268       heap->heap_region_containing((HeapWord*)field)->print();
 269       tty->print_cr("marking: %s, evacuating: %s",
 270                     BOOL_TO_STR(heap->concurrent_mark_in_progress()),
 271                     BOOL_TO_STR(heap->is_evacuation_in_progress()));
 272       assert(false, "We should have fixed this earlier");
 273     }
 274   }
 275 #endif
 276 
 277   if (!oopDesc::is_null(heap_oop)) {
 278     G1SATBCardTableModRefBS::enqueue(oopDesc::decode_heap_oop(heap_oop));
 279   }
 280   if (UseShenandoahMatrix && ! oopDesc::is_null(new_val)) {
 281     ShenandoahHeap* heap = ShenandoahHeap::heap();
 282     ShenandoahConnectionMatrix* matrix = heap->connection_matrix();
 283     matrix->set_connected(heap->heap_region_index_containing(field), heap->heap_region_index_containing(new_val), true);
 284   }
 285 }
 286 
 287 template <class T>
 288 inline void ShenandoahBarrierSet::inline_write_ref_field_pre(T* field, oop newVal) {
 289   write_ref_field_pre_static(field, newVal);
 290 }
 291 
 292 // These are the more general virtual versions.
 293 void ShenandoahBarrierSet::write_ref_field_pre_work(oop* field, oop new_val) {
 294   write_ref_field_pre_static(field, new_val);
 295 }
 296 
 297 void ShenandoahBarrierSet::write_ref_field_pre_work(narrowOop* field, oop new_val) {
 298   write_ref_field_pre_static(field, new_val);
 299 }
 300 
 301 void ShenandoahBarrierSet::write_ref_field_pre_work(void* field, oop new_val) {
 302   guarantee(false, "Not needed");
 303 }
 304 
 305 void ShenandoahBarrierSet::write_ref_field_work(void* v, oop o, bool release) {
 306 #ifdef ASSERT
 307   ShenandoahHeap* heap = ShenandoahHeap::heap();
 308   if (!(heap->cancelled_concgc() || !heap->in_collection_set(v))) {
 309     tty->print_cr("field not in collection set: "PTR_FORMAT, p2i(v));
 310     tty->print_cr("containing heap region:");
 311     ShenandoahHeap::heap()->heap_region_containing(v)->print();
 312   }
 313   assert(heap->cancelled_concgc() || !heap->in_collection_set(v), "only write to to-space");
 314   if (_heap->concurrent_mark_in_progress()) {
 315     assert(o == NULL || oopDesc::unsafe_equals(o, resolve_oop_static(o)), "only write to-space values");
 316     assert(o == NULL || !heap->in_collection_set(o), "only write to-space values");
 317   }
 318 #endif
 319   if (UseShenandoahMatrix && ! oopDesc::is_null(o)) {
 320     ShenandoahHeap* heap = ShenandoahHeap::heap();
 321     ShenandoahConnectionMatrix* matrix = heap->connection_matrix();
 322     matrix->set_connected(heap->heap_region_index_containing(v), heap->heap_region_index_containing(o), true);
 323   }
 324 }
 325 
 326 void ShenandoahBarrierSet::write_region_work(MemRegion mr) {
 327 
 328   if (! need_update_refs_barrier()) return;
 329 
 330   // This is called for cloning an object (see jvm.cpp) after the clone
 331   // has been made. We are not interested in any 'previous value' because
 332   // it would be NULL in any case. But we *are* interested in any oop*
 333   // that potentially need to be updated.
 334 
 335   oop obj = oop(mr.start());
 336   assert(obj->is_oop(), "must be an oop");
 337   if (UseShenandoahMatrix) {
 338     UpdateRefsForOopMatrixClosure cl;
 339     obj->oop_iterate(&cl);
 340   } else {
 341     UpdateRefsForOopClosure cl;
 342     obj->oop_iterate(&cl);
 343   }
 344 }
 345 
 346 oop ShenandoahBarrierSet::read_barrier(oop src) {
 347   if (ShenandoahReadBarrier) {
 348     return ShenandoahBarrierSet::resolve_oop_static(src);
 349   } else {
 350     return src;
 351   }
 352 }
 353 
 354 bool ShenandoahBarrierSet::obj_equals(oop obj1, oop obj2) {
 355   bool eq = oopDesc::unsafe_equals(obj1, obj2);
 356   if (! eq && ShenandoahAcmpBarrier) {
 357     OrderAccess::loadload();
 358     obj1 = resolve_oop_static(obj1);
 359     obj2 = resolve_oop_static(obj2);
 360     eq = oopDesc::unsafe_equals(obj1, obj2);
 361   }
 362   return eq;
 363 }


< prev index next >