< prev index next >

src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp

Print this page
rev 55404 : 8226197: Reducing G1?s CPU cost with simplified write post-barrier and disabling concurrent refinement
Summary: A prototype to add a mode for G1 to use a simplified write post-barrier. Guarded by new flag G1FastWriteBarrier.


 401   }
 402 
 403   if (use_ReduceInitialCardMarks()
 404       && g1_can_remove_post_barrier(kit, &kit->gvn(), oop_store, adr)) {
 405     return;
 406   }
 407 
 408   if (!use_precise) {
 409     // All card marks for a (non-array) instance are in one place:
 410     adr = obj;
 411   }
 412   // (Else it's an array (or unknown), and we want more precise card marks.)
 413   assert(adr != NULL, "");
 414 
 415   IdealKit ideal(kit, true);
 416 
 417   Node* tls = __ thread(); // ThreadLocalStorage
 418 
 419   Node* no_base = __ top();
 420   float unlikely  = PROB_UNLIKELY(0.999);
 421   Node* young_card = __ ConI((jint)G1CardTable::g1_young_card_val());
 422   Node* dirty_card = __ ConI((jint)G1CardTable::dirty_card_val());
 423   Node* zeroX = __ ConX(0);
 424 
 425   const TypeFunc *tf = write_ref_field_post_entry_Type();
 426 
 427   // Offsets into the thread
 428   const int index_offset  = in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset());
 429   const int buffer_offset = in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset());
 430 
 431   // Pointers into the thread
 432 
 433   Node* buffer_adr = __ AddP(no_base, tls, __ ConX(buffer_offset));
 434   Node* index_adr =  __ AddP(no_base, tls, __ ConX(index_offset));
 435 
 436   // Now some values
 437   // Use ctrl to avoid hoisting these values past a safepoint, which could
 438   // potentially reset these fields in the JavaThread.
 439   Node* index  = __ load(__ ctrl(), index_adr, TypeX_X, TypeX_X->basic_type(), Compile::AliasIdxRaw);
 440   Node* buffer = __ load(__ ctrl(), buffer_adr, TypeRawPtr::NOTNULL, T_ADDRESS, Compile::AliasIdxRaw);
 441 


 448 
 449   // Combine card table base and card offset
 450   Node* card_adr = __ AddP(no_base, byte_map_base_node(kit), card_offset );
 451 
 452   // If we know the value being stored does it cross regions?
 453 
 454   if (val != NULL) {
 455     // Does the store cause us to cross regions?
 456 
 457     // Should be able to do an unsigned compare of region_size instead of
 458     // and extra shift. Do we have an unsigned compare??
 459     // Node* region_size = __ ConI(1 << HeapRegion::LogOfHRGrainBytes);
 460     Node* xor_res =  __ URShiftX ( __ XorX( cast,  __ CastPX(__ ctrl(), val)), __ ConI(HeapRegion::LogOfHRGrainBytes));
 461 
 462     // if (xor_res == 0) same region so skip
 463     __ if_then(xor_res, BoolTest::ne, zeroX); {
 464 
 465       // No barrier if we are storing a NULL
 466       __ if_then(val, BoolTest::ne, kit->null(), unlikely); {
 467 




 468         // Ok must mark the card if not already dirty
 469 
 470         // load the original value of the card
 471         Node* card_val = __ load(__ ctrl(), card_adr, TypeInt::INT, T_BYTE, Compile::AliasIdxRaw);
 472 
 473         __ if_then(card_val, BoolTest::ne, young_card); {
 474           kit->sync_kit(ideal);
 475           kit->insert_store_load_for_barrier();
 476           __ sync_kit(kit);
 477 
 478           Node* card_val_reload = __ load(__ ctrl(), card_adr, TypeInt::INT, T_BYTE, Compile::AliasIdxRaw);
 479           __ if_then(card_val_reload, BoolTest::ne, dirty_card); {
 480             g1_mark_card(kit, ideal, card_adr, oop_store, alias_idx, index, index_adr, buffer, tf);
 481           } __ end_if();
 482         } __ end_if();

 483       } __ end_if();
 484     } __ end_if();
 485   } else {
 486     // The Object.clone() intrinsic uses this path if !ReduceInitialCardMarks.
 487     // We don't need a barrier here if the destination is a newly allocated object
 488     // in Eden. Otherwise, GC verification breaks because we assume that cards in Eden
 489     // are set to 'g1_young_gen' (see G1CardTable::verify_g1_young_region()).
 490     assert(!use_ReduceInitialCardMarks(), "can only happen with card marking");
 491     Node* card_val = __ load(__ ctrl(), card_adr, TypeInt::INT, T_BYTE, Compile::AliasIdxRaw);
 492     __ if_then(card_val, BoolTest::ne, young_card); {
 493       g1_mark_card(kit, ideal, card_adr, oop_store, alias_idx, index, index_adr, buffer, tf);
 494     } __ end_if();
 495   }
 496 
 497   // Final sync IdealKit and GraphKit.
 498   kit->final_sync(ideal);
 499 }
 500 
 501 // Helper that guards and inserts a pre-barrier.
 502 void G1BarrierSetC2::insert_pre_barrier(GraphKit* kit, Node* base_oop, Node* offset,




 401   }
 402 
 403   if (use_ReduceInitialCardMarks()
 404       && g1_can_remove_post_barrier(kit, &kit->gvn(), oop_store, adr)) {
 405     return;
 406   }
 407 
 408   if (!use_precise) {
 409     // All card marks for a (non-array) instance are in one place:
 410     adr = obj;
 411   }
 412   // (Else it's an array (or unknown), and we want more precise card marks.)
 413   assert(adr != NULL, "");
 414 
 415   IdealKit ideal(kit, true);
 416 
 417   Node* tls = __ thread(); // ThreadLocalStorage
 418 
 419   Node* no_base = __ top();
 420   float unlikely  = PROB_UNLIKELY(0.999);
 421   Node* young_card = G1FastWriteBarrier ? NULL : __ ConI((jint)G1CardTable::g1_young_card_val());
 422   Node* dirty_card = __ ConI((jint)G1CardTable::dirty_card_val());
 423   Node* zeroX = __ ConX(0);
 424 
 425   const TypeFunc *tf = write_ref_field_post_entry_Type();
 426 
 427   // Offsets into the thread
 428   const int index_offset  = in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset());
 429   const int buffer_offset = in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset());
 430 
 431   // Pointers into the thread
 432 
 433   Node* buffer_adr = __ AddP(no_base, tls, __ ConX(buffer_offset));
 434   Node* index_adr =  __ AddP(no_base, tls, __ ConX(index_offset));
 435 
 436   // Now some values
 437   // Use ctrl to avoid hoisting these values past a safepoint, which could
 438   // potentially reset these fields in the JavaThread.
 439   Node* index  = __ load(__ ctrl(), index_adr, TypeX_X, TypeX_X->basic_type(), Compile::AliasIdxRaw);
 440   Node* buffer = __ load(__ ctrl(), buffer_adr, TypeRawPtr::NOTNULL, T_ADDRESS, Compile::AliasIdxRaw);
 441 


 448 
 449   // Combine card table base and card offset
 450   Node* card_adr = __ AddP(no_base, byte_map_base_node(kit), card_offset );
 451 
 452   // If we know the value being stored does it cross regions?
 453 
 454   if (val != NULL) {
 455     // Does the store cause us to cross regions?
 456 
 457     // Should be able to do an unsigned compare of region_size instead of
 458     // and extra shift. Do we have an unsigned compare??
 459     // Node* region_size = __ ConI(1 << HeapRegion::LogOfHRGrainBytes);
 460     Node* xor_res =  __ URShiftX ( __ XorX( cast,  __ CastPX(__ ctrl(), val)), __ ConI(HeapRegion::LogOfHRGrainBytes));
 461 
 462     // if (xor_res == 0) same region so skip
 463     __ if_then(xor_res, BoolTest::ne, zeroX); {
 464 
 465       // No barrier if we are storing a NULL
 466       __ if_then(val, BoolTest::ne, kit->null(), unlikely); {
 467 
 468         if (G1FastWriteBarrier) {
 469           __ storeCM(__ ctrl(), card_adr, __ ConI(0), oop_store, alias_idx, T_BYTE, Compile::AliasIdxRaw);
 470         } else {
 471 
 472           // Ok must mark the card if not already dirty
 473 
 474           // load the original value of the card
 475           Node* card_val = __ load(__ ctrl(), card_adr, TypeInt::INT, T_BYTE, Compile::AliasIdxRaw);
 476 
 477           __ if_then(card_val, BoolTest::ne, young_card); {
 478             kit->sync_kit(ideal);
 479             kit->insert_store_load_for_barrier();
 480             __ sync_kit(kit);
 481 
 482             Node* card_val_reload = __ load(__ ctrl(), card_adr, TypeInt::INT, T_BYTE, Compile::AliasIdxRaw);
 483             __ if_then(card_val_reload, BoolTest::ne, dirty_card); {
 484               g1_mark_card(kit, ideal, card_adr, oop_store, alias_idx, index, index_adr, buffer, tf);
 485             } __ end_if();
 486           } __ end_if();
 487         }
 488       } __ end_if();
 489     } __ end_if();
 490   } else {
 491     // The Object.clone() intrinsic uses this path if !ReduceInitialCardMarks.
 492     // We don't need a barrier here if the destination is a newly allocated object
 493     // in Eden. Otherwise, GC verification breaks because we assume that cards in Eden
 494     // are set to 'g1_young_gen' (see G1CardTable::verify_g1_young_region()).
 495     assert(!use_ReduceInitialCardMarks(), "can only happen with card marking");
 496     Node* card_val = __ load(__ ctrl(), card_adr, TypeInt::INT, T_BYTE, Compile::AliasIdxRaw);
 497     __ if_then(card_val, BoolTest::ne, young_card); {
 498       g1_mark_card(kit, ideal, card_adr, oop_store, alias_idx, index, index_adr, buffer, tf);
 499     } __ end_if();
 500   }
 501 
 502   // Final sync IdealKit and GraphKit.
 503   kit->final_sync(ideal);
 504 }
 505 
 506 // Helper that guards and inserts a pre-barrier.
 507 void G1BarrierSetC2::insert_pre_barrier(GraphKit* kit, Node* base_oop, Node* offset,


< prev index next >