char* rSet::scavenge_contents(oldSpace* sp, char* begin, char* limit) { // make sure we are staring with a dirty page assert(!*begin, "check for dirty page"); // Find object at page start oop* s = oop_for(begin); // Return if we're at the end. if (s >= sp->top()) return begin + 1; s = sp->object_start(s); char* end = begin+1; oop* object_end = NULL; while (!*end && end < limit) { while (!*end && end < limit) end++; // We now have a string of dirty pages [begin..end[ oop* e = min(oop_for(end), (oop*)sp->top()); if (e < (oop*)sp->top()) { // Find the object crossing the last dirty page object_end = sp->object_start(e); if (object_end != e) { // object starts on page boundary int size = as_memOop(object_end)->size(); object_end += size; } end = byte_for(object_end); } } // Clear the cards for (char* i = begin; i < end; i++) *i = -1; // Find the end oop* e = min(oop_for(end), (oop*)sp->top()); while (s < e) { memOop m = as_memOop(s); int size = m->scavenge_tenured_contents(); assert(size == m->size(), "just checking"); s += size; } return end; }
void survivorSpace::scavenge_contents_from(NewWaterMark* mark) { # ifdef VERBOSE_SCAVENGING lprintf("{scavenge_contents [ %#lx <= %#lx <= %#lx]}\n", bottom(), mark->_point, top()); # endif if (top() == mark->_point) return; assert(mark->_point < top(), "scavenging past top"); oop* p = mark->_point; // for performance oop* t = top(); do { memOop m = as_memOop(p); # ifdef VERBOSE_SCAVENGING lprintf("{scavenge %#lx (%#lx)} ", p, m->klass()); lprintf("%s\n", m->klass()->name()); oop *prev = p; # endif assert((*p)->is_mark(), "Header should be mark"); p += m->scavenge_contents(); # ifdef VERBOSE_SCAVENGING if (p - prev != m->size()) fatal("scavenge_contents is not returning the right size"); # endif } while (p < t); mark->_point = p; }
void space::compact(OldWaterMark* mark) { // compute the new addresses for the live objects // Used by universe::mark_sweep_phase3() // %profiling note: // the garbage collectior spends 23% of its time in this function oop* q = bottom(); oop* t = top(); oop* new_top = mark->_point; while (q < t) { memOop m = as_memOop(q); if (m->mark()->is_smi()) { // lprintf("Expanding %#lx -> %#lx\n", q, *q); q = (oop*) *q; } else { int size = m->gc_retrieve_size(); if (q != new_top) { copy_oops(q, new_top, size); // lprintf("copy %#lx -> %#lx (%d)\n", q, new_top, size); assert((*new_top)->is_mark(), "should be header"); } mark->_space->update_offsets(new_top, new_top + size); q += size; new_top += size; } } mark->_point = new_top; mark->_space->set_top(new_top); set_top(new_top); }
void space::prepare_for_compaction(OldWaterMark* mark) { // compute the new addresses for the live objects and update all // pointers to these objects. // Used by universe::mark_sweep_phase2() // %profiling note: // the garbage collectior spends 55% of its time in this function oop* q = bottom(); oop* t = top(); oop* new_top = mark->_point; memOop first_free = NULL; while (q < t) { memOop m = as_memOop(q); if (m->is_gc_marked()) { if (first_free) { first_free->set_mark(q); // lprintf("[%#lx] = %#lx, %#lx\n", first_free, first_free->mark(), q); first_free = NULL; } // Reverse the list with the mark at the end oop* root_or_mark = (oop*) m->mark(); while (is_oop_root(root_or_mark)) { oop* next = (oop*) *root_or_mark; *root_or_mark = (oop) as_memOop(new_top); root_or_mark = next; } m->set_mark(markOop(root_or_mark)); int size = m->gc_retrieve_size(); // The mark has to be restored before // the size is retrieved new_top += size; q += size; } else { if (!first_free) { first_free = m; // lprintf("First free %#lx\n", q); } q += m->size(); } } if (first_free) { first_free->set_mark(q); // lprintf("[%#lx] = %#lx, %#lx\n", first_free, first_free->mark(), q); } mark->_point = new_top; }
oop space::find_oop_backwards(void* start) { if (objs_contains(start)) { oop* p = find_this_object((oop*)start); return as_memOop(p); } ShouldNotReachHere(); // not in this space return NULL; // for C++ }
void space::canonize_map_vtbls() { for (oop* p = objs_top; p > objs_bottom; ) { p = find_this_object(p - 1); memOop obj = as_memOop(p); Map* m = as_mapOop(p)->map_addr(); if (obj->map() == Memory->map_map) m->set_vtbl_value(Vtbls->vtbl_values[m->vtblMapType()]); } }
void space::fixup_killables() { // because we can't snapshot them yet for (oop* p = objs_top; p > objs_bottom; ) { p = find_this_object(p - 1); oop obj = as_memOop(p); if (obj->is_killable()) // process, block, activation obj, foreignOop, ... obj->kill(); } }
void space::oops_do(oopsDoFn f) { oop* p = bottom(); oop* t = top(); while (p < t) { memOop m = as_memOop(p); f((oop*) &m); p += m->size(); } }
void oldSpace::verify() { lprintf("%s ", name()); oop* p = _bottom; memOop m; VerifyOldOopClosure blk; while (p < _top) { assert(oop(*p)->is_mark(), "First word must be mark"); m = as_memOop(p); int size = m->size(); assert(m == as_memOop(Universe::object_start(p + (size/2))), "check offset computation"); m->verify(); blk.the_obj = m; m->oop_iterate(&blk); p += m->size(); } assert(p == _top, "end of last object must match end of space"); }
void frame::convert_hcode_pointer() { if (!is_interpreted_frame()) return; // Adjust hcode pointer to object start u_char* h = hp(); u_char* obj = (u_char*) as_memOop(Universe::object_start((oop*) h)); set_hp(obj); // Save the offset MarkSweep::add_hcode_offset(h - obj); // if (WizardMode) lprintf("[0x%lx+%d]\n", obj, h - obj); }
void oldSpace::scavenge_contents_from(OldWaterMark* mark) { assert(this == mark->_space, "Match does not match space"); oop* p = mark->_point; while (p < _top) { assert(oop(*p)->is_mark(),"must be mark"); memOop x = as_memOop(p); p += x->scavenge_tenured_contents(); } assert(p == _top, "p should be top"); mark->_point = _top; }
oop memOopKlass::allocateObject() { klassOop k = as_klassOop(); int size = non_indexable_size(); // allocate memOop obj = as_memOop(Universe::allocate(size, (memOop*)&k)); // header obj->initialize_header(has_untagged_contents(), k); // instance variables obj->initialize_body(memOopDesc::header_size(), size); return obj; }
void space::fixup_maps() { for (oop* p = objs_top; p > objs_bottom; ) { p = find_this_object(p - 1); memOop obj = as_memOop(p); Map* m = as_mapOop(p)->map_addr(); if (obj->map() == Memory->map_map) { m->set_vtbl_value(Vtbls->translate(m->vtbl_value())); m->fixup(); } } }
oop* newSpace::object_start(oop* p) { assert (bottom() <= p && p < top(), "p must be in space"); oop* q = bottom(); oop* t = top(); while (q < t) { oop* prev = q; q += as_memOop(q)->size(); if (q > p) return prev; } fatal("should never reach this point"); return NULL; }
methodOop frame::method() const { assert(is_interpreted_frame(), "must be interpreter frame"); // First we will check the interpreter frame is valid by checking the frame size. // The interpreter guarantees hp is valid if the frame is at least 4 in size. // (return address, link, receiver, hcode pointer) if (frame_size() < minimum_size_for_deoptimized_frame) return NULL; u_char* h = hp(); if (!Universe::old_gen.contains(h)) return NULL; memOop obj = as_memOop(Universe::object_start((oop*) h)); return obj->is_method() ? methodOop(obj) : NULL; }
void oldSpace::object_iterate_from(OldWaterMark* mark, ObjectClosure* blk) { blk->begin_space(this); oop* p = mark->_point; oop* t = top(); while (p < t) { memOop m = as_memOop(p); blk->do_object(m); p += m->size(); } mark->_point = p; blk->end_space(this); }
void space::object_iterate(ObjectClosure* blk) { if (is_empty()) return; blk->begin_space(this); oop* p = bottom(); oop* t = top(); while (p < t) { memOop m = as_memOop(p); blk->do_object(m); p += m->size(); } blk->end_space(this); }
oop memOopKlass::oop_shallow_copy(oop obj, bool tenured) { // Do not copy oddballs (nil, true, false) if (obj == nilObj) return obj; if (obj == trueObj) return obj; if (obj == falseObj) return obj; int len = memOop(obj)->size(); // Important to preserve obj (in case of scavenge). oop* clone = tenured ? Universe::allocate_tenured(len) : Universe::allocate(len, (memOop*)&obj); oop* to = clone; oop* from = (oop*) memOop(obj)->addr(); oop* end = to + len; while (to < end) *to++ = *from++; if (!as_memOop(clone)->is_new()) { // Remember to update the remembered set if the clone is in old space. // Note: // should we do something special for arrays. Universe::remembered_set->record_store(clone); } return as_memOop(clone); }
void space::switch_pointers_in_region(oop from, oop to, oop* bottom, oop* top) { // don't search bytes; they contain no oop references assert(in_objs_bounds(bottom) && in_objs_bounds(top), "switching pointers outside oops part"); if (top <= bottom) return; // space could be empty oop saved_bottom = *bottom; *bottom = from; oop *p; for (p = find_prior_reference(top - 1, from); p > bottom; p = find_prior_reference(p - 1, from)) { // must undo sentinel cause switch_pointer may need to look at that spot *bottom = saved_bottom; as_memOop(find_this_object(p))->switch_pointer(p, to); *bottom = from; // redo sentinel } assert(p == bottom, "search missed sentinel"); *bottom = saved_bottom; if (saved_bottom == from) as_memOop(find_this_object(bottom))->switch_pointer(bottom, to); }
void newSpace::verify() { lprintf("%s ", name()); oop* p = bottom(); oop* t = top(); memOop m; while (p < t) { assert(oop(*p)->is_mark(), "First word must be mark"); m = as_memOop(p); m->verify(); p += m->size(); } assert(p == top(), "end of last object must match end of space"); }
oop memOopKlass::allocateObject(bool permit_scavenge, bool tenured) { klassOop k = as_klassOop(); int size = non_indexable_size(); oop* result = basicAllocate(size, &k, permit_scavenge, tenured); if (!result) return NULL; // allocate memOop obj = as_memOop(result); // header obj->initialize_header(has_untagged_contents(), k); // instance variables obj->initialize_body(memOopDesc::header_size(), size); return obj; }
oop* oldSpace::object_start(oop* p) { // Find the page start oop* q = p; int b = (int) q; clearBits(b, nthMask(card_shift)); q = (oop*) b; assert(contains(q), "q must be in this space"); int index = (q - bottom()) / card_size_in_oops; int offset = offset_array[index--]; while(offset == card_size_in_oops) { q -= card_size_in_oops; offset = offset_array[index--]; } q -= offset; oop* n = q; assert((*n)->is_mark(), "check for header"); while (n <= p) { q = n; n += as_memOop(n)->size(); } assert( as_memOop(q)->mark()->is_mark(), "Must be mark"); return q; }
bool rSet::has_page_dirty_objects(oldSpace* sp, char* page) { // Find object at page start oop* s = sp->object_start(oop_for(page)); // Find the end oop* e = min(oop_for(page+1), (oop*)sp->top()); CheckDirtyClosure blk; while (s < e) { memOop m = as_memOop(s); blk.clear(); m->oop_iterate(&blk); if (blk.is_dirty) return true; s += m->size(); } return false; }
void pp(void* p) { Command c("pp"); FlagSetting fl(PrintVMMessages, true); if (p == NULL) { lprintf("0x0"); return; } if (Universe::is_heap((oop*) p)) { memOop obj = as_memOop(Universe::object_start((oop*) p)); obj->print(); if (obj->is_method()) { int bci = methodOop(obj)->bci_from((u_char*) p); prettyPrinter::print(methodOop(obj), NULL, bci); } return; } if (oop(p)->is_smi() || oop(p)->is_mark()) { oop(p)->print(); return; } }
friend vframeOop as_vframeOop(void* p) { return vframeOop(as_memOop(p)); }
friend mixinOop as_mixinOop(void* p) { return mixinOop(as_memOop(p)); }
inline associationOop as_associationOop(void* p) { return associationOop(as_memOop(p)); }
friend weakArrayOop as_weakArrayOop(void* p) { return weakArrayOop(as_memOop(p)); }
// constructor friend objArrayOop as_objArrayOop(void* p) { return objArrayOop(as_memOop(p)); }
// constructor friend doubleValueArrayOop as_doubleValueArrayOop(void* p) { return doubleValueArrayOop(as_memOop(p)); }