< prev index next >

src/hotspot/share/compiler/oopMap.cpp

Print this page

        

*** 26,41 **** #include "code/codeBlob.hpp" #include "code/codeCache.hpp" #include "code/nmethod.hpp" #include "code/scopeDesc.hpp" #include "compiler/oopMap.hpp" #include "gc/shared/collectedHeap.hpp" #include "memory/allocation.inline.hpp" #include "memory/iterator.hpp" #include "memory/resourceArea.hpp" - #include "memory/universe.hpp" #include "oops/compressedOops.hpp" #include "runtime/frame.inline.hpp" #include "runtime/handles.inline.hpp" #include "runtime/signature.hpp" #include "utilities/align.hpp" #include "utilities/lockFreeStack.hpp" --- 26,45 ---- #include "code/codeBlob.hpp" #include "code/codeCache.hpp" #include "code/nmethod.hpp" #include "code/scopeDesc.hpp" #include "compiler/oopMap.hpp" + #include "compiler/oopMap.inline.hpp" + #include "compiler/oopMapStubGenerator.hpp" #include "gc/shared/collectedHeap.hpp" + #include "logging/log.hpp" + #include "logging/logStream.hpp" #include "memory/allocation.inline.hpp" #include "memory/iterator.hpp" #include "memory/resourceArea.hpp" #include "oops/compressedOops.hpp" + #include "runtime/atomic.hpp" #include "runtime/frame.inline.hpp" #include "runtime/handles.inline.hpp" #include "runtime/signature.hpp" #include "utilities/align.hpp" #include "utilities/lockFreeStack.hpp"
*** 46,74 **** #include "opto/optoreg.hpp" #endif // OopMapStream ! OopMapStream::OopMapStream(OopMap* oop_map, int oop_types_mask) { ! _stream = new CompressedReadStream(oop_map->write_stream()->buffer()); _mask = oop_types_mask; _size = oop_map->omv_count(); _position = 0; _valid_omv = false; } ! OopMapStream::OopMapStream(const ImmutableOopMap* oop_map, int oop_types_mask) { ! _stream = new CompressedReadStream(oop_map->data_addr()); _mask = oop_types_mask; _size = oop_map->count(); _position = 0; _valid_omv = false; } void OopMapStream::find_next() { while(_position++ < _size) { ! _omv.read_from(_stream); if(((int)_omv.type() & _mask) > 0) { _valid_omv = true; return; } } --- 50,80 ---- #include "opto/optoreg.hpp" #endif // OopMapStream ! OopMapStream::OopMapStream(const OopMap* oop_map, int oop_types_mask) ! : _stream(oop_map->write_stream()->buffer()) { ! // _stream = new CompressedReadStream(); _mask = oop_types_mask; _size = oop_map->omv_count(); _position = 0; _valid_omv = false; } ! OopMapStream::OopMapStream(const ImmutableOopMap* oop_map, int oop_types_mask) ! : _stream(oop_map->data_addr()) { ! // _stream = new CompressedReadStream(oop_map->data_addr()); _mask = oop_types_mask; _size = oop_map->count(); _position = 0; _valid_omv = false; } void OopMapStream::find_next() { while(_position++ < _size) { ! _omv.read_from(&_stream); if(((int)_omv.type() & _mask) > 0) { _valid_omv = true; return; } }
*** 82,91 **** --- 88,99 ---- // slots to hold 4-byte values like ints and floats in the LP64 build. OopMap::OopMap(int frame_size, int arg_count) { // OopMaps are usually quite so small, so pick a small initial size set_write_stream(new CompressedWriteStream(32)); set_omv_count(0); + _num_oops = 0; + _index = -1; #ifdef ASSERT _locs_length = VMRegImpl::stack2reg(0)->value() + frame_size + arg_count; _locs_used = NEW_RESOURCE_ARRAY(OopMapValue::oop_types, _locs_length); for(int i = 0; i < _locs_length; i++) _locs_used[i] = OopMapValue::unused_value;
*** 97,106 **** --- 105,116 ---- // This constructor does a deep copy // of the source OopMap. set_write_stream(new CompressedWriteStream(source->omv_count() * 2)); set_omv_count(0); set_offset(source->offset()); + _num_oops = source->num_oops(); + _index = -1; #ifdef ASSERT _locs_length = source->_locs_length; _locs_used = NEW_RESOURCE_ARRAY(OopMapValue::oop_types, _locs_length); for(int i = 0; i < _locs_length; i++) _locs_used[i] = OopMapValue::unused_value;
*** 121,130 **** --- 131,296 ---- void OopMap::copy_data_to(address addr) const { memcpy(addr, write_stream()->buffer(), write_stream()->position()); } + class OopMapSort { + private: + const OopMap* _map; + OopMapValue* _values; + int _count; + + public: + OopMapSort(const OopMap* map) : _map(map), _count(0) { + _values = NEW_RESOURCE_ARRAY(OopMapValue, _map->omv_count()); + } + + void sort(); + + void print(); + + void write(CompressedWriteStream* stream) { + for (int i = 0; i < _count; ++i) { + _values[i].write_on(stream); + } + } + + private: + int find_derived_position(OopMapValue omv, int start) { + assert(omv.type() == OopMapValue::derived_oop_value, ""); + + VMReg base = omv.content_reg(); + int i = start; + + for (; i < _count; ++i) { + if (base == _values[i].reg()) { + + for (int n = i + 1; n < _count; ++n) { + if (_values[i].type() != OopMapValue::derived_oop_value || _values[i].content_reg() != base) { + return n; + } + + if (derived_cost(_values[i]) > derived_cost(omv)) { + return n; + } + } + return _count; + } + } + + assert(false, "failed to find base"); + return -1; + } + + int find_position(OopMapValue omv, int start) { + assert(omv.type() != OopMapValue::derived_oop_value, ""); + + int i = start; + for (; i < _count; ++i) { + if (omv_cost(_values[i]) > omv_cost(omv)) { + return i; + } + } + assert(i < _map->omv_count(), "bounds check"); + return i; + } + + void insert(OopMapValue value, int pos) { + assert(pos >= 0 && pos < _map->omv_count(), "bounds check"); + assert(pos <= _count, "sanity"); + + if (pos < _count) { + OopMapValue prev = _values[pos]; + + for (int i = pos; i < _count; ++i) { + OopMapValue tmp = _values[i+1]; + _values[i+1] = prev; + prev = tmp; + } + } + _values[pos] = value; + + ++_count; + } + + int omv_cost(OopMapValue omv) { + assert(omv.type() == OopMapValue::oop_value || omv.type() == OopMapValue::narrowoop_value, ""); + return reg_cost(omv.reg()); + } + + int reg_cost(VMReg reg) { + if (reg->is_reg()) { + return 0; + } + return reg->reg2stack() * VMRegImpl::stack_slot_size; + } + + int derived_cost(OopMapValue omv) { + return reg_cost(omv.reg()); + } + }; + + void OopMapSort::sort() { + for (OopMapStream oms(_map); !oms.is_done(); oms.next()) { + OopMapValue omv = oms.current(); + assert(omv.type() == OopMapValue::oop_value || omv.type() == OopMapValue::narrowoop_value || omv.type() == OopMapValue::derived_oop_value || omv.type() == OopMapValue::callee_saved_value, ""); + } + + for (OopMapStream oms(_map, OopMapValue::callee_saved_value); !oms.is_done(); oms.next()) { + insert(oms.current(), _count); + } + + int start = _count; + for (OopMapStream oms(_map, OopMapValue::oop_value | OopMapValue::narrowoop_value); !oms.is_done(); oms.next()) { + OopMapValue omv = oms.current(); + int pos = find_position(omv, start); + insert(omv, pos); + } + + for (OopMapStream oms(_map, OopMapValue::derived_oop_value); !oms.is_done(); oms.next()) { + OopMapValue omv = oms.current(); + int pos = find_derived_position(omv, start); + assert(pos > 0, ""); + insert(omv, pos); + } + } + + void OopMapSort::print() { + for (int i = 0; i < _count; ++i) { + OopMapValue omv = _values[i]; + if (omv.type() == OopMapValue::oop_value || omv.type() == OopMapValue::narrowoop_value) { + if (omv.reg()->is_reg()) { + tty->print_cr("[%c][%d] -> reg (%ld)", omv.type() == OopMapValue::narrowoop_value ? 'n' : 'o', i, omv.reg()->value()); + } else { + tty->print_cr("[%c][%d] -> stack (%lx)", omv.type() == OopMapValue::narrowoop_value ? 'n' : 'o', i, omv.reg()->reg2stack() * VMRegImpl::stack_slot_size); + } + } else { + if (omv.content_reg()->is_reg()) { + tty->print_cr("[d][%d] -> reg (%ld) stack (%lx)", i, omv.content_reg()->value(), omv.reg()->reg2stack() * VMRegImpl::stack_slot_size); + } else if (omv.reg()->is_reg()) { + tty->print_cr("[d][%d] -> stack (%lx) reg (%ld)", i, omv.content_reg()->reg2stack() * VMRegImpl::stack_slot_size, omv.reg()->value()); + } else { + int derived_offset = omv.reg()->reg2stack() * VMRegImpl::stack_slot_size; + int base_offset = omv.content_reg()->reg2stack() * VMRegImpl::stack_slot_size; + tty->print_cr("[d][%d] -> stack (%x) stack (%x)", i, base_offset, derived_offset); + } + } + } + } + + void OopMap::copy_and_sort_data_to(address addr) const { + OopMapSort sort(this); + sort.sort(); + CompressedWriteStream* stream = new CompressedWriteStream(_write_stream->position()); + sort.write(stream); + + assert(stream->position() == write_stream()->position(), ""); + memcpy(addr, stream->buffer(), stream->position()); + //copy_data_to(addr); + //sort.print(); + } + int OopMap::heap_size() const { int size = sizeof(OopMap); int align = sizeof(void *) - 1; size += write_stream()->position(); // Align to a reasonable ending point
*** 150,169 **** --- 316,338 ---- o.set_content_reg(optional); } o.write_on(write_stream()); increment_count(); + if (x == OopMapValue::oop_value || x == OopMapValue::narrowoop_value) + increment_num_oops(); } void OopMap::set_oop(VMReg reg) { set_xxx(reg, OopMapValue::oop_value, VMRegImpl::Bad()); } void OopMap::set_value(VMReg reg) { // At this time, we don't need value entries in our OopMap. + // set_xxx(reg, OopMapValue::live_value, VMRegImpl::Bad()); } void OopMap::set_narrowoop(VMReg reg) { set_xxx(reg, OopMapValue::narrowoop_value, VMRegImpl::Bad());
*** 200,210 **** memcpy(new_data,om_data(),om_size() * sizeof(OopMap*)); set_om_size(new_size); set_om_data(new_data); } ! void OopMapSet::add_gc_map(int pc_offset, OopMap *map ) { assert(om_size() != -1,"Cannot grow a fixed OopMapSet"); if(om_count() >= om_size()) { grow_om_data(); } --- 369,379 ---- memcpy(new_data,om_data(),om_size() * sizeof(OopMap*)); set_om_size(new_size); set_om_data(new_data); } ! int OopMapSet::add_gc_map(int pc_offset, OopMap *map ) { assert(om_size() != -1,"Cannot grow a fixed OopMapSet"); if(om_count() >= om_size()) { grow_om_data(); }
*** 221,232 **** om_count(),last->offset(),om_count()+1,map->offset()); } } #endif // ASSERT ! set(om_count(),map); increment_count(); } int OopMapSet::heap_size() const { // The space we use --- 390,404 ---- om_count(),last->offset(),om_count()+1,map->offset()); } } #endif // ASSERT ! int index = om_count(); ! set(index,map); ! map->_index = index; increment_count(); + return index; } int OopMapSet::heap_size() const { // The space we use
*** 266,459 **** OopMap* m = at(i); assert( m->offset() == pc_offset, "oopmap not found" ); return m; } ! static void add_derived_oop(oop* base, oop* derived) { #if !defined(TIERED) && !INCLUDE_JVMCI ! COMPILER1_PRESENT(ShouldNotReachHere();) #endif // !defined(TIERED) && !INCLUDE_JVMCI #if COMPILER2_OR_JVMCI ! DerivedPointerTable::add(derived, base); #endif // COMPILER2_OR_JVMCI - } - - - #ifndef PRODUCT - static void trace_codeblob_maps(const frame *fr, const RegisterMap *reg_map) { - // Print oopmap and regmap - tty->print_cr("------ "); - CodeBlob* cb = fr->cb(); - const ImmutableOopMapSet* maps = cb->oop_maps(); - const ImmutableOopMap* map = cb->oop_map_for_return_address(fr->pc()); - map->print(); - if( cb->is_nmethod() ) { - nmethod* nm = (nmethod*)cb; - // native wrappers have no scope data, it is implied - if (nm->is_native_method()) { - tty->print("bci: 0 (native)"); - } else { - ScopeDesc* scope = nm->scope_desc_at(fr->pc()); - tty->print("bci: %d ",scope->bci()); - } } ! tty->cr(); ! fr->print_on(tty); ! tty->print(" "); ! cb->print_value_on(tty); tty->cr(); ! reg_map->print(); ! tty->print_cr("------ "); } - #endif // PRODUCT ! void OopMapSet::oops_do(const frame *fr, const RegisterMap* reg_map, OopClosure* f) { ! // add derived oops to a table ! all_do(fr, reg_map, f, add_derived_oop, &do_nothing_cl); } ! void OopMapSet::all_do(const frame *fr, const RegisterMap *reg_map, ! OopClosure* oop_fn, void derived_oop_fn(oop*, oop*), ! OopClosure* value_fn) { ! CodeBlob* cb = fr->cb(); ! assert(cb != NULL, "no codeblob"); ! NOT_PRODUCT(if (TraceCodeBlobStacks) trace_codeblob_maps(fr, reg_map);) ! const ImmutableOopMapSet* maps = cb->oop_maps(); ! const ImmutableOopMap* map = cb->oop_map_for_return_address(fr->pc()); ! assert(map != NULL, "no ptr map found"); ! // handle derived pointers first (otherwise base pointer may be ! // changed before derived pointer offset has been collected) ! OopMapValue omv; ! { ! OopMapStream oms(map,OopMapValue::derived_oop_value); ! if (!oms.is_done()) { ! #ifndef TIERED ! COMPILER1_PRESENT(ShouldNotReachHere();) ! #if INCLUDE_JVMCI ! if (UseJVMCICompiler) { ! ShouldNotReachHere(); } ! #endif ! #endif // !TIERED ! do { ! omv = oms.current(); ! oop* loc = fr->oopmapreg_to_location(omv.reg(),reg_map); ! guarantee(loc != NULL, "missing saved register"); ! oop *derived_loc = loc; ! oop *base_loc = fr->oopmapreg_to_location(omv.content_reg(), reg_map); ! // Ignore NULL oops and decoded NULL narrow oops which ! // equal to CompressedOops::base() when a narrow oop ! // implicit null check is used in compiled code. ! // The narrow_oop_base could be NULL or be the address ! // of the page below heap depending on compressed oops mode. ! if (base_loc != NULL && *base_loc != NULL && !CompressedOops::is_base(*base_loc)) { ! derived_oop_fn(base_loc, derived_loc); ! } ! oms.next(); ! } while (!oms.is_done()); } } ! // We want coop and oop oop_types ! int mask = OopMapValue::oop_value | OopMapValue::narrowoop_value; ! { ! for (OopMapStream oms(map,mask); !oms.is_done(); oms.next()) { omv = oms.current(); ! oop* loc = fr->oopmapreg_to_location(omv.reg(),reg_map); ! // It should be an error if no location can be found for a ! // register mentioned as contained an oop of some kind. Maybe ! // this was allowed previously because value_value items might ! // be missing? ! guarantee(loc != NULL, "missing saved register"); ! if ( omv.type() == OopMapValue::oop_value ) { ! oop val = *loc; ! if (val == NULL || CompressedOops::is_base(val)) { ! // Ignore NULL oops and decoded NULL narrow oops which ! // equal to CompressedOops::base() when a narrow oop ! // implicit null check is used in compiled code. ! // The narrow_oop_base could be NULL or be the address ! // of the page below heap depending on compressed oops mode. ! continue; ! } ! #ifdef ASSERT ! if ((((uintptr_t)loc & (sizeof(*loc)-1)) != 0) || ! !Universe::heap()->is_in_or_null(*loc)) { ! tty->print_cr("# Found non oop pointer. Dumping state at failure"); ! // try to dump out some helpful debugging information ! trace_codeblob_maps(fr, reg_map); ! omv.print(); ! tty->print_cr("register r"); ! omv.reg()->print(); ! tty->print_cr("loc = %p *loc = %p\n", loc, (address)*loc); ! // do the real assert. ! assert(Universe::heap()->is_in_or_null(*loc), "found non oop pointer"); ! } ! #endif // ASSERT ! oop_fn->do_oop(loc); ! } else if ( omv.type() == OopMapValue::narrowoop_value ) { ! narrowOop *nl = (narrowOop*)loc; ! #ifndef VM_LITTLE_ENDIAN ! VMReg vmReg = omv.reg(); ! // Don't do this on SPARC float registers as they can be individually addressed ! if (!vmReg->is_stack() SPARC_ONLY(&& !vmReg->is_FloatRegister())) { ! // compressed oops in registers only take up 4 bytes of an ! // 8 byte register but they are in the wrong part of the ! // word so adjust loc to point at the right place. ! nl = (narrowOop*)((address)nl + 4); ! } ! #endif ! oop_fn->do_oop(nl); ! } ! } } } ! // Update callee-saved register info for the following frame ! void OopMapSet::update_register_map(const frame *fr, RegisterMap *reg_map) { ! ResourceMark rm; CodeBlob* cb = fr->cb(); assert(cb != NULL, "no codeblob"); - // Any reg might be saved by a safepoint handler (see generate_handler_blob). assert( reg_map->_update_for_id == NULL || fr->is_older(reg_map->_update_for_id), "already updated this map; do not 'update' it twice!" ); debug_only(reg_map->_update_for_id = fr->id()); // Check if caller must update oop argument assert((reg_map->include_argument_oops() || !cb->caller_must_gc_arguments(reg_map->thread())), "include_argument_oops should already be set"); // Scan through oopmap and find location of all callee-saved registers // (we do not do update in place, since info could be overwritten) - address pc = fr->pc(); - const ImmutableOopMap* map = cb->oop_map_for_return_address(pc); - assert(map != NULL, "no ptr map found"); DEBUG_ONLY(int nof_callee = 0;) ! for (OopMapStream oms(map, OopMapValue::callee_saved_value); !oms.is_done(); oms.next()) { OopMapValue omv = oms.current(); VMReg reg = omv.content_reg(); oop* loc = fr->oopmapreg_to_location(omv.reg(), reg_map); reg_map->set_location(reg, (address) loc); DEBUG_ONLY(nof_callee++;) } // Check that runtime stubs save all callee-saved registers #ifdef COMPILER2 ! assert(cb->is_compiled_by_c1() || cb->is_compiled_by_jvmci() || !cb->is_runtime_stub() || (nof_callee >= SAVED_ON_ENTRY_REG_COUNT || nof_callee >= C_SAVED_ON_ENTRY_REG_COUNT), "must save all"); #endif // COMPILER2 } //============================================================================= // Non-Product code #ifndef PRODUCT --- 438,648 ---- OopMap* m = at(i); assert( m->offset() == pc_offset, "oopmap not found" ); return m; } ! class AddDerivedOop : public DerivedOopClosure { ! public: ! enum { SkipNull = true, NeedsLock = true }; ! virtual void do_derived_oop(oop* base, oop* derived) { #if !defined(TIERED) && !INCLUDE_JVMCI ! COMPILER1_PRESENT(ShouldNotReachHere();) #endif // !defined(TIERED) && !INCLUDE_JVMCI #if COMPILER2_OR_JVMCI ! DerivedPointerTable::add(derived, base); #endif // COMPILER2_OR_JVMCI } ! }; + void OopMapSet::oops_do(const frame *fr, const RegisterMap* reg_map, OopClosure* f, DerivedOopClosure* df) { + // add_derived_oop: add derived oops to a table + find_map(fr)->oops_do(fr, reg_map, f, df); + // all_do(fr, reg_map, f, df != NULL ? df : &add_derived_oop, &do_nothing_cl); + } + + // void OopMapSet::all_do(const frame *fr, const RegisterMap *reg_map, + // OopClosure* oop_fn, DerivedOopClosure* derived_oop_fn, + // OopClosure* value_fn) { + // find_map(fr)->oops_do(fr, reg_map, oop_fn, derived_oop_fn, value_fn); + // } + + ExplodedOopMap::ExplodedOopMap(const ImmutableOopMap* oopMap) { + _oopValues = copyOopMapValues(oopMap, OopMapValue::oop_value | OopMapValue::narrowoop_value, &_nrOopValues); + _calleeSavedValues = copyOopMapValues(oopMap, OopMapValue::callee_saved_value, &_nrCalleeSavedValuesCount); + _derivedValues = copyOopMapValues(oopMap, OopMapValue::derived_oop_value, &_nrDerivedValues); + } + + OopMapValue* ExplodedOopMap::values(int mask) { + if (mask == (OopMapValue::oop_value | OopMapValue::narrowoop_value)) { + return _oopValues; + } else if (mask == OopMapValue::callee_saved_value) { + return _calleeSavedValues; + } else if (mask == OopMapValue::derived_oop_value) { + return _derivedValues; + } else { + guarantee(false, "new type?"); + return NULL; + } } ! int ExplodedOopMap::count(int mask) { ! if (mask == (OopMapValue::oop_value | OopMapValue::narrowoop_value)) { ! return _nrOopValues; ! } else if (mask == OopMapValue::callee_saved_value) { ! return _nrCalleeSavedValuesCount; ! } else if (mask == OopMapValue::derived_oop_value) { ! return _nrDerivedValues; ! } else { ! guarantee(false, "new type?"); ! return 0; ! } } + OopMapValue* ExplodedOopMap::copyOopMapValues(const ImmutableOopMap* oopMap, int mask, int* nr) { + OopMapValue omv; + int count = 0; + // We want coop and oop oop_types + for (OopMapStream oms(oopMap,mask); !oms.is_done(); oms.next()) { + ++count; + } + *nr = count; ! OopMapValue* values = (OopMapValue*) NEW_C_HEAP_ARRAY(unsigned char, sizeof(OopMapValue) * count, mtCode); ! int i = 0; ! for (OopMapStream oms(oopMap,mask); !oms.is_done(); oms.next()) { ! assert(i < count, "overflow"); ! values[i] = oms.current(); ! i++; ! } ! i = 0; ! for (OopMapStream oms(oopMap,mask); !oms.is_done(); oms.next()) { ! assert(i < count, "overflow"); ! assert(values[i].equals(oms.current()), "must"); ! i++; ! } ! return values; ! } ! ! // NULL, fail, success (address) ! void ImmutableOopMap::generate_stub(const CodeBlob* cb) const { ! /* The address of the ImmutableOopMap is put into the _freeze_stub and _thaw_stub ! * if we can't generate the stub for some reason */ ! if (_freeze_stub == NULL) { ! OopMapStubGenerator cgen(cb, *this); ! if (Atomic::cmpxchg((address) this, &_freeze_stub, (address) NULL) == NULL) { ! if (!cgen.generate()) { ! Atomic::store((address) this, &_thaw_stub); ! cgen.free(); ! return; } ! ! Atomic::store(cgen.freeze_stub(), &_freeze_stub); ! Atomic::store(cgen.thaw_stub(), &_thaw_stub); } } + } ! void ImmutableOopMap::oops_do(const frame *fr, const RegisterMap *reg_map, ! OopClosure* oop_fn, DerivedOopClosure* derived_oop_fn) const { ! AddDerivedOop add_derived_oop; ! if (derived_oop_fn == NULL) { ! derived_oop_fn = &add_derived_oop; ! } ! OopMapDo<OopClosure, DerivedOopClosure, SkipNullValue> visitor(oop_fn, derived_oop_fn); ! visitor.oops_do(fr, reg_map, this); ! } ! ! template<typename T> ! static void iterate_all_do(const frame *fr, int mask, OopMapClosure* fn, const ImmutableOopMap* oopmap) { ! OopMapValue omv; ! for (T oms(oopmap,mask); !oms.is_done(); oms.next()) { omv = oms.current(); ! fn->do_value(omv.reg(), omv.type()); } } + void ImmutableOopMap::all_do(const frame *fr, int mask, OopMapClosure* fn) const { + if (_exploded != NULL) { + iterate_all_do<ExplodedOopMapStream>(fr, mask, fn, this); + } else { + iterate_all_do<OopMapStream>(fr, mask, fn, this); + } + } ! template <typename T> ! static void update_register_map1(const ImmutableOopMap* oopmap, const frame* fr, RegisterMap* reg_map) { ! for (T oms(oopmap, OopMapValue::callee_saved_value); !oms.is_done(); oms.next()) { ! OopMapValue omv = oms.current(); ! VMReg reg = omv.content_reg(); ! oop* loc = fr->oopmapreg_to_location(omv.reg(), reg_map); ! reg_map->set_location(reg, (address) loc); ! //DEBUG_ONLY(nof_callee++;) ! } ! } ! ! void ImmutableOopMap::update_register_map(const frame *fr, RegisterMap *reg_map) const { ! // ResourceMark rm; CodeBlob* cb = fr->cb(); assert(cb != NULL, "no codeblob"); // Any reg might be saved by a safepoint handler (see generate_handler_blob). assert( reg_map->_update_for_id == NULL || fr->is_older(reg_map->_update_for_id), "already updated this map; do not 'update' it twice!" ); debug_only(reg_map->_update_for_id = fr->id()); + // Check if caller must update oop argument assert((reg_map->include_argument_oops() || !cb->caller_must_gc_arguments(reg_map->thread())), "include_argument_oops should already be set"); // Scan through oopmap and find location of all callee-saved registers // (we do not do update in place, since info could be overwritten) DEBUG_ONLY(int nof_callee = 0;) + if (_exploded != NULL) { + update_register_map1<ExplodedOopMapStream>(this, fr, reg_map); + } else { + update_register_map1<OopMapStream>(this, fr, reg_map); + } ! /* ! for (OopMapStream oms(this, OopMapValue::callee_saved_value); !oms.is_done(); oms.next()) { OopMapValue omv = oms.current(); VMReg reg = omv.content_reg(); oop* loc = fr->oopmapreg_to_location(omv.reg(), reg_map); reg_map->set_location(reg, (address) loc); DEBUG_ONLY(nof_callee++;) } + */ // Check that runtime stubs save all callee-saved registers #ifdef COMPILER2 ! assert(cb == NULL || cb->is_compiled_by_c1() || cb->is_compiled_by_jvmci() || !cb->is_runtime_stub() || (nof_callee >= SAVED_ON_ENTRY_REG_COUNT || nof_callee >= C_SAVED_ON_ENTRY_REG_COUNT), "must save all"); #endif // COMPILER2 } + const ImmutableOopMap* OopMapSet::find_map(const frame *fr) { + return find_map(fr->cb(), fr->pc()); + } + + const ImmutableOopMap* OopMapSet::find_map(const CodeBlob* cb, address pc) { + assert(cb != NULL, "no codeblob"); + const ImmutableOopMap* map = cb->oop_map_for_return_address(pc); + assert(map != NULL, "no ptr map found"); + return map; + } + + // Update callee-saved register info for the following frame + void OopMapSet::update_register_map(const frame *fr, RegisterMap *reg_map) { + find_map(fr)->update_register_map(fr, reg_map); + } + //============================================================================= // Non-Product code #ifndef PRODUCT
*** 467,476 **** --- 656,696 ---- #else return false; #endif // COMPILER2_OR_JVMCI } + #ifndef PRODUCT + void OopMapSet::trace_codeblob_maps(const frame *fr, const RegisterMap *reg_map) { + // Print oopmap and regmap + tty->print_cr("------ "); + CodeBlob* cb = fr->cb(); + const ImmutableOopMapSet* maps = cb->oop_maps(); + const ImmutableOopMap* map = cb->oop_map_for_return_address(fr->pc()); + map->print(); + if( cb->is_nmethod() ) { + nmethod* nm = (nmethod*)cb; + // native wrappers have no scope data, it is implied + if (nm->is_native_method()) { + tty->print("bci: 0 (native)"); + } else { + ScopeDesc* scope = nm->scope_desc_at(fr->pc()); + tty->print("bci: %d ",scope->bci()); + } + } + tty->cr(); + fr->print_on(tty); + tty->print(" "); + cb->print_value_on(tty); tty->cr(); + if (reg_map != NULL) { + reg_map->print(); + } + tty->print_cr("------ "); + + } + #endif // PRODUCT + + #endif //PRODUCT // Printing code is present in product build for -XX:+PrintAssembly. static
*** 579,588 **** --- 799,823 ---- return false; } return true; } + int ImmutableOopMapSet::find_slot_for_offset(int pc_offset) const { + ImmutableOopMapPair* pairs = get_pairs(); + + for (int i = 0; i < _count; ++i) { + if (pairs[i].pc_offset() >= pc_offset) { + ImmutableOopMapPair* last = &pairs[i]; + assert(last->pc_offset() == pc_offset, "oopmap not found"); + return i; + } + } + + guarantee(false, "failed to find oopmap for pc"); + return -1; + } + const ImmutableOopMap* ImmutableOopMapSet::find_map_at_offset(int pc_offset) const { ImmutableOopMapPair* pairs = get_pairs(); ImmutableOopMapPair* last = NULL; for (int i = 0; i < _count; ++i) {
*** 596,612 **** guarantee(last != NULL, "last may not be null"); assert(last->pc_offset() == pc_offset, "oopmap not found"); return last->get_from(this); } ! const ImmutableOopMap* ImmutableOopMapPair::get_from(const ImmutableOopMapSet* set) const { ! return set->oopmap_at_offset(_oopmap_offset); ! } ! ! ImmutableOopMap::ImmutableOopMap(const OopMap* oopmap) : _count(oopmap->count()) { address addr = data_addr(); ! oopmap->copy_data_to(addr); } #ifdef ASSERT int ImmutableOopMap::nr_of_bytes() const { OopMapStream oms(this); --- 831,845 ---- guarantee(last != NULL, "last may not be null"); assert(last->pc_offset() == pc_offset, "oopmap not found"); return last->get_from(this); } ! ImmutableOopMap::ImmutableOopMap(const OopMap* oopmap) : _exploded(NULL), _freeze_stub(NULL), _thaw_stub(NULL), _count(oopmap->count()), _num_oops(oopmap->num_oops()) { ! _num_oops = oopmap->num_oops(); address addr = data_addr(); ! //oopmap->copy_data_to(addr); ! oopmap->copy_and_sort_data_to(addr); } #ifdef ASSERT int ImmutableOopMap::nr_of_bytes() const { OopMapStream oms(this);
*** 695,705 **** } else if (_mapping[i]._kind == Mapping::OOPMAP_DUPLICATE || _mapping[i]._kind == Mapping::OOPMAP_EMPTY) { fill_pair(&pairs[i], map, _mapping[i]._offset, set); } const ImmutableOopMap* nv = set->find_map_at_offset(map->offset()); ! assert(memcmp(map->data(), nv->data_addr(), map->data_size()) == 0, "check identity"); } } #ifdef ASSERT void ImmutableOopMapBuilder::verify(address buffer, int size, const ImmutableOopMapSet* set) { --- 928,938 ---- } else if (_mapping[i]._kind == Mapping::OOPMAP_DUPLICATE || _mapping[i]._kind == Mapping::OOPMAP_EMPTY) { fill_pair(&pairs[i], map, _mapping[i]._offset, set); } const ImmutableOopMap* nv = set->find_map_at_offset(map->offset()); ! //assert(memcmp(map->data(), nv->data_addr(), map->data_size()) == 0, "check identity"); } } #ifdef ASSERT void ImmutableOopMapBuilder::verify(address buffer, int size, const ImmutableOopMapSet* set) {
*** 793,803 **** void DerivedPointerTable::add(oop *derived_loc, oop *base_loc) { assert(Universe::heap()->is_in_or_null(*base_loc), "not an oop"); assert(derived_loc != base_loc, "Base and derived in same location"); if (_active) { ! assert(*derived_loc != (void*)base_loc, "location already added"); assert(Entry::_list != NULL, "list must exist"); intptr_t offset = value_of_loc(derived_loc) - value_of_loc(base_loc); // This assert is invalid because derived pointers can be // arbitrarily far away from their base. // assert(offset >= -1000000, "wrong derived pointer info"); --- 1026,1036 ---- void DerivedPointerTable::add(oop *derived_loc, oop *base_loc) { assert(Universe::heap()->is_in_or_null(*base_loc), "not an oop"); assert(derived_loc != base_loc, "Base and derived in same location"); if (_active) { ! assert(*derived_loc != (oop)base_loc, "location already added"); assert(Entry::_list != NULL, "list must exist"); intptr_t offset = value_of_loc(derived_loc) - value_of_loc(base_loc); // This assert is invalid because derived pointers can be // arbitrarily far away from their base. // assert(offset >= -1000000, "wrong derived pointer info");
< prev index next >