void ReceiverTypeData::oop_iterate_m(OopClosure* blk, MemRegion mr) { // Currently, this interface is called only during card-scanning for // a young gen gc, in which case this object cannot contribute anything, // since it does not contain any references that cross out of // the perm gen. However, for future more general use we allow // the possibility of calling for instance from more general // iterators (for example, a future regionalized perm gen for G1, // or the possibility of moving some references out of perm in // the case of other collectors). In that case, you will need // to relax or remove some of the assertions below. #ifdef ASSERT // Verify that none of the embedded oop references cross out of // this generation. for (uint row = 0; row < row_limit(); row++) { if (receiver(row) != NULL) { oop* adr = adr_receiver(row); CollectedHeap* h = Universe::heap(); assert(h->is_permanent(adr) && h->is_permanent_or_null(*adr), "Not intra-perm"); } } #endif // ASSERT assert(!blk->should_remember_mdo(), "Not expected to remember MDO"); return; // Nothing to do, see comment above #if 0 if (blk->should_remember_mdo()) { // This is a set of weak references that need // to be followed at the end of the strong marking // phase. Memoize this object so it can be visited // in the weak roots processing phase. blk->remember_mdo(data()); } else { // normal scan for (uint row = 0; row < row_limit(); row++) { if (receiver(row) != NULL) { oop* adr = adr_receiver(row); if (mr.contains(adr)) { blk->do_oop(adr); } else if ((HeapWord*)adr >= mr.end()) { // Test that the current cursor and the two ends of the range // that we may have skipped iterating over are monotonically ordered; // this is just a paranoid assertion, just in case represetations // should change in the future rendering the short-circuit return // here invalid. assert((row+1 >= row_limit() || adr_receiver(row+1) > adr) && (row+2 >= row_limit() || adr_receiver(row_limit()-1) > adr_receiver(row+1)), "Reducing?"); break; // remaining should be outside this mr too } } } } #endif }
void ReceiverTypeData::print_receiver_data_on(outputStream* st) { uint row; int entries = 0; for (row = 0; row < row_limit(); row++) { if (receiver(row) != NULL) entries++; } st->print_cr("count(%u) entries(%u)", count(), entries); for (row = 0; row < row_limit(); row++) { if (receiver(row) != NULL) { tab(st); receiver(row)->print_value_on(st); st->print_cr("(%u)", receiver_count(row)); } } }
void VirtualCallData::follow_contents() { for (uint row = 0; row < row_limit(); row++) { if (receiver(row) != NULL) { MarkSweep::mark_and_push(adr_receiver(row)); } } }
void ReceiverTypeData::adjust_pointers() { for (uint row = 0; row < row_limit(); row++) { if (receiver(row) != NULL) { MarkSweep::adjust_pointer(adr_receiver(row)); } } }
void ReceiverTypeData::update_pointers() { for (uint row = 0; row < row_limit(); row++) { if (receiver_unchecked(row) != NULL) { PSParallelCompact::adjust_pointer(adr_receiver(row)); } } }
void VirtualCallData::print_data_on(outputStream* st) { print_shared(st, "VirtualCallData"); uint row; int entries = 0; for (row = 0; row < row_limit(); row++) { if (receiver(row) != NULL) entries++; } st->print_cr("count(%u) entries(%u)", count(), entries); for (row = 0; row < row_limit(); row++) { if (receiver(row) != NULL) { tab(st); receiver(row)->print_value_on(st); st->print_cr("(%u)", receiver_count(row)); } } }
void VirtualCallData::oop_iterate(OopClosure* blk) { for (uint row = 0; row < row_limit(); row++) { if (receiver(row) != NULL) { blk->do_oop(adr_receiver(row)); } } }
void RetData::print_data_on(outputStream* st) { print_shared(st, "RetData"); uint row; int entries = 0; for (row = 0; row < row_limit(); row++) { if (bci(row) != no_bci) entries++; } st->print_cr("count(%u) entries(%u)", count(), entries); for (row = 0; row < row_limit(); row++) { if (bci(row) != no_bci) { tab(st); st->print_cr("bci(%d: count(%u) displacement(%d))", bci(row), bci_count(row), bci_displacement(row)); } } }
void ReceiverTypeData::follow_weak_refs(BoolObjectClosure* is_alive_cl) { for (uint row = 0; row < row_limit(); row++) { klassOop p = receiver(row); if (p != NULL && !is_alive_cl->do_object_b(p)) { clear_row(row); } } }
void ReceiverTypeData::clean_weak_klass_links(BoolObjectClosure* is_alive_cl) { for (uint row = 0; row < row_limit(); row++) { Klass* p = receiver(row); if (p != NULL && !p->is_loader_alive(is_alive_cl)) { clear_row(row); } } }
void ciReceiverTypeData::translate_receiver_data_from(ProfileData* data) { for (uint row = 0; row < row_limit(); row++) { klassOop k = data->as_ReceiverTypeData()->receiver(row); if (k != NULL) { ciKlass* klass = CURRENT_ENV->get_object(k)->as_klass(); set_receiver(row, klass); } } }
void ciVirtualCallData::translate_from(ProfileData* data) { for (uint row = 0; row < row_limit(); row++) { klassOop k = data->as_VirtualCallData()->receiver(row); if (k) { ciKlass* klass = CURRENT_ENV->get_object(k)->as_klass(); set_receiver(row, klass); } } };
void RetData::post_initialize(BytecodeStream* stream, methodDataOop mdo) { for (uint row = 0; row < row_limit(); row++) { set_bci_displacement(row, -1); set_bci(row, no_bci); } // release so other threads see a consistent state. bci is used as // a valid flag for bci_displacement. OrderAccess::release(); }
void VirtualCallData::oop_iterate_m(OopClosure* blk, MemRegion mr) { for (uint row = 0; row < row_limit(); row++) { if (receiver(row) != NULL) { oop* adr = adr_receiver(row); if (mr.contains(adr)) { blk->do_oop(adr); } } } }
void ReceiverTypeData::update_pointers(HeapWord* beg_addr, HeapWord* end_addr) { // The loop bounds could be computed based on beg_addr/end_addr and the // boundary test hoisted outside the loop (see klassVTable for an example); // however, row_limit() is small enough (2) to make that less efficient. for (uint row = 0; row < row_limit(); row++) { if (receiver_unchecked(row) != NULL) { PSParallelCompact::adjust_pointer(adr_receiver(row), beg_addr, end_addr); } } }
void ciReceiverTypeData::translate_receiver_data_from(const ProfileData* data) { for (uint row = 0; row < row_limit(); row++) { Klass* k = data->as_ReceiverTypeData()->receiver(row); if (k != NULL) { ciKlass* klass = CURRENT_ENV->get_klass(k); CURRENT_ENV->ensure_metadata_alive(klass); set_receiver(row, klass); } } }
void ReceiverTypeData::oop_iterate(OopClosure* blk) { if (blk->should_remember_mdo()) { // This is a set of weak references that need // to be followed at the end of the strong marking // phase. Memoize this object so it can be visited // in the weak roots processing phase. blk->remember_mdo(data()); } else { // normal scan for (uint row = 0; row < row_limit(); row++) { if (receiver(row) != NULL) { oop* adr = adr_receiver(row); blk->do_oop(adr); } } } }
// This routine needs to atomically update the RetData structure, so the // caller needs to hold the RetData_lock before it gets here. Since taking // the lock can block (and allow GC) and since RetData is a ProfileData is a // wrapper around a derived oop, taking the lock in _this_ method will // basically cause the 'this' pointer's _data field to contain junk after the // lock. We require the caller to take the lock before making the ProfileData // structure. Currently the only caller is InterpreterRuntime::update_mdp_for_ret address RetData::fixup_ret(int return_bci, methodDataHandle h_mdo) { // First find the mdp which corresponds to the return bci. address mdp = h_mdo->bci_to_dp(return_bci); // Now check to see if any of the cache slots are open. for (uint row = 0; row < row_limit(); row++) { if (bci(row) == no_bci) { set_bci_displacement(row, mdp - dp()); set_bci_count(row, DataLayout::counter_increment); // Barrier to ensure displacement is written before the bci; allows // the interpreter to read displacement without fear of race condition. release_set_bci(row, return_bci); break; } } return mdp; }
void set_receiver(uint row, ciKlass* recv) { assert((uint)row < row_limit(), "oob"); set_intptr_at(receiver0_offset + row * receiver_type_row_cell_count, (intptr_t) recv); }
ciKlass* receiver(uint row) { assert((uint)row < row_limit(), "oob"); ciObject* recv = (ciObject*)intptr_at(receiver0_offset + row * receiver_type_row_cell_count); assert(recv == NULL || recv->is_klass(), "wrong type"); return (ciKlass*)recv; }