Path: blob/master/src/hotspot/share/compiler/oopMap.cpp
40930 views
/*1* Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 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 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include "precompiled.hpp"25#include "code/codeBlob.hpp"26#include "code/codeCache.hpp"27#include "code/nmethod.hpp"28#include "code/scopeDesc.hpp"29#include "compiler/oopMap.hpp"30#include "gc/shared/collectedHeap.hpp"31#include "memory/allocation.inline.hpp"32#include "memory/iterator.hpp"33#include "memory/resourceArea.hpp"34#include "memory/universe.hpp"35#include "oops/compressedOops.hpp"36#include "runtime/frame.inline.hpp"37#include "runtime/handles.inline.hpp"38#include "runtime/signature.hpp"39#include "runtime/stackWatermarkSet.inline.hpp"40#include "utilities/align.hpp"41#include "utilities/lockFreeStack.hpp"42#ifdef COMPILER143#include "c1/c1_Defs.hpp"44#endif45#ifdef COMPILER246#include "opto/optoreg.hpp"47#endif48#if INCLUDE_JVMCI49#include "jvmci/jvmci_globals.hpp"50#endif5152static_assert(sizeof(oop) == sizeof(intptr_t), "Derived pointer sanity check");5354static inline intptr_t derived_pointer_value(derived_pointer p) {55return static_cast<intptr_t>(p);56}5758static inline derived_pointer to_derived_pointer(oop obj) {59return static_cast<derived_pointer>(cast_from_oop<intptr_t>(obj));60}6162static inline intptr_t operator-(derived_pointer p, derived_pointer p1) {63return derived_pointer_value(p) - derived_pointer_value(p1);64}6566static inline derived_pointer operator+(derived_pointer p, intptr_t offset) {67return static_cast<derived_pointer>(derived_pointer_value(p) + offset);68}6970// OopMapStream7172OopMapStream::OopMapStream(OopMap* oop_map) {73_stream = new CompressedReadStream(oop_map->write_stream()->buffer());74_size = oop_map->omv_count();75_position = 0;76_valid_omv = false;77}7879OopMapStream::OopMapStream(const ImmutableOopMap* oop_map) {80_stream = new CompressedReadStream(oop_map->data_addr());81_size = oop_map->count();82_position = 0;83_valid_omv = false;84}8586void OopMapStream::find_next() {87if (_position++ < _size) {88_omv.read_from(_stream);89_valid_omv = true;90return;91}92_valid_omv = false;93}949596// OopMap9798// frame_size units are stack-slots (4 bytes) NOT intptr_t; we can name odd99// slots to hold 4-byte values like ints and floats in the LP64 build.100OopMap::OopMap(int frame_size, int arg_count) {101// OopMaps are usually quite so small, so pick a small initial size102set_write_stream(new CompressedWriteStream(32));103set_omv_count(0);104105#ifdef ASSERT106_locs_length = VMRegImpl::stack2reg(0)->value() + frame_size + arg_count;107_locs_used = NEW_RESOURCE_ARRAY(OopMapValue::oop_types, _locs_length);108for(int i = 0; i < _locs_length; i++) _locs_used[i] = OopMapValue::unused_value;109#endif110}111112113OopMap::OopMap(OopMap::DeepCopyToken, OopMap* source) {114// This constructor does a deep copy115// of the source OopMap.116set_write_stream(new CompressedWriteStream(source->omv_count() * 2));117set_omv_count(0);118set_offset(source->offset());119120#ifdef ASSERT121_locs_length = source->_locs_length;122_locs_used = NEW_RESOURCE_ARRAY(OopMapValue::oop_types, _locs_length);123for(int i = 0; i < _locs_length; i++) _locs_used[i] = OopMapValue::unused_value;124#endif125126// We need to copy the entries too.127for (OopMapStream oms(source); !oms.is_done(); oms.next()) {128OopMapValue omv = oms.current();129omv.write_on(write_stream());130increment_count();131}132}133134135OopMap* OopMap::deep_copy() {136return new OopMap(_deep_copy_token, this);137}138139void OopMap::copy_data_to(address addr) const {140memcpy(addr, write_stream()->buffer(), write_stream()->position());141}142143int OopMap::heap_size() const {144int size = sizeof(OopMap);145int align = sizeof(void *) - 1;146size += write_stream()->position();147// Align to a reasonable ending point148size = ((size+align) & ~align);149return size;150}151152// frame_size units are stack-slots (4 bytes) NOT intptr_t; we can name odd153// slots to hold 4-byte values like ints and floats in the LP64 build.154void OopMap::set_xxx(VMReg reg, OopMapValue::oop_types x, VMReg optional) {155156assert(reg->value() < _locs_length, "too big reg value for stack size");157assert( _locs_used[reg->value()] == OopMapValue::unused_value, "cannot insert twice" );158debug_only( _locs_used[reg->value()] = x; )159160OopMapValue o(reg, x, optional);161o.write_on(write_stream());162increment_count();163}164165166void OopMap::set_oop(VMReg reg) {167set_xxx(reg, OopMapValue::oop_value, VMRegImpl::Bad());168}169170171void OopMap::set_narrowoop(VMReg reg) {172set_xxx(reg, OopMapValue::narrowoop_value, VMRegImpl::Bad());173}174175176void OopMap::set_callee_saved(VMReg reg, VMReg caller_machine_register ) {177set_xxx(reg, OopMapValue::callee_saved_value, caller_machine_register);178}179180181void OopMap::set_derived_oop(VMReg reg, VMReg derived_from_local_register ) {182if( reg == derived_from_local_register ) {183// Actually an oop, derived shares storage with base,184set_oop(reg);185} else {186set_xxx(reg, OopMapValue::derived_oop_value, derived_from_local_register);187}188}189190// OopMapSet191192OopMapSet::OopMapSet() : _list(MinOopMapAllocation) {}193194void OopMapSet::add_gc_map(int pc_offset, OopMap *map ) {195map->set_offset(pc_offset);196197#ifdef ASSERT198if(_list.length() > 0) {199OopMap* last = _list.last();200if (last->offset() == map->offset() ) {201fatal("OopMap inserted twice");202}203if (last->offset() > map->offset()) {204tty->print_cr( "WARNING, maps not sorted: pc[%d]=%d, pc[%d]=%d",205_list.length(),last->offset(),_list.length()+1,map->offset());206}207}208#endif // ASSERT209210add(map);211}212213static void add_derived_oop(oop* base, derived_pointer* derived, OopClosure* oop_fn) {214#if COMPILER2_OR_JVMCI215DerivedPointerTable::add(derived, base);216#endif // COMPILER2_OR_JVMCI217}218219static void ignore_derived_oop(oop* base, derived_pointer* derived, OopClosure* oop_fn) {220}221222static void process_derived_oop(oop* base, derived_pointer* derived, OopClosure* oop_fn) {223// All derived pointers must be processed before the base pointer of any derived pointer is processed.224// Otherwise, if two derived pointers use the same base, the second derived pointer will get an obscured225// offset, if the base pointer is processed in the first derived pointer.226derived_pointer derived_base = to_derived_pointer(*base);227intptr_t offset = *derived - derived_base;228*derived = derived_base;229oop_fn->do_oop((oop*)derived);230*derived = *derived + offset;231}232233234#ifndef PRODUCT235static void trace_codeblob_maps(const frame *fr, const RegisterMap *reg_map) {236// Print oopmap and regmap237tty->print_cr("------ ");238CodeBlob* cb = fr->cb();239const ImmutableOopMapSet* maps = cb->oop_maps();240const ImmutableOopMap* map = cb->oop_map_for_return_address(fr->pc());241map->print();242if( cb->is_nmethod() ) {243nmethod* nm = (nmethod*)cb;244// native wrappers have no scope data, it is implied245if (nm->is_native_method()) {246tty->print("bci: 0 (native)");247} else {248ScopeDesc* scope = nm->scope_desc_at(fr->pc());249tty->print("bci: %d ",scope->bci());250}251}252tty->cr();253fr->print_on(tty);254tty->print(" ");255cb->print_value_on(tty); tty->cr();256reg_map->print();257tty->print_cr("------ ");258259}260#endif // PRODUCT261262void OopMapSet::oops_do(const frame *fr, const RegisterMap* reg_map, OopClosure* f, DerivedPointerIterationMode mode) {263switch (mode) {264case DerivedPointerIterationMode::_directly:265all_do(fr, reg_map, f, process_derived_oop);266break;267case DerivedPointerIterationMode::_with_table:268all_do(fr, reg_map, f, add_derived_oop);269break;270case DerivedPointerIterationMode::_ignore:271all_do(fr, reg_map, f, ignore_derived_oop);272break;273}274}275276277void OopMapSet::all_do(const frame *fr, const RegisterMap *reg_map,278OopClosure* oop_fn, void derived_oop_fn(oop*, derived_pointer*, OopClosure*)) {279CodeBlob* cb = fr->cb();280assert(cb != NULL, "no codeblob");281282NOT_PRODUCT(if (TraceCodeBlobStacks) trace_codeblob_maps(fr, reg_map);)283284const ImmutableOopMap* map = cb->oop_map_for_return_address(fr->pc());285assert(map != NULL, "no ptr map found");286287// handle derived pointers first (otherwise base pointer may be288// changed before derived pointer offset has been collected)289{290for (OopMapStream oms(map); !oms.is_done(); oms.next()) {291OopMapValue omv = oms.current();292if (omv.type() != OopMapValue::derived_oop_value) {293continue;294}295296#ifndef COMPILER2297COMPILER1_PRESENT(ShouldNotReachHere();)298#if INCLUDE_JVMCI299if (UseJVMCICompiler) {300ShouldNotReachHere();301}302#endif303#endif // !COMPILER2304derived_pointer* derived_loc = (derived_pointer*)fr->oopmapreg_to_location(omv.reg(),reg_map);305guarantee(derived_loc != NULL, "missing saved register");306oop* base_loc = fr->oopmapreg_to_oop_location(omv.content_reg(), reg_map);307// Ignore NULL oops and decoded NULL narrow oops which308// equal to CompressedOops::base() when a narrow oop309// implicit null check is used in compiled code.310// The narrow_oop_base could be NULL or be the address311// of the page below heap depending on compressed oops mode.312if (base_loc != NULL && *base_loc != NULL && !CompressedOops::is_base(*base_loc)) {313derived_oop_fn(base_loc, derived_loc, oop_fn);314}315}316}317318{319// We want coop and oop oop_types320for (OopMapStream oms(map); !oms.is_done(); oms.next()) {321OopMapValue omv = oms.current();322oop* loc = fr->oopmapreg_to_oop_location(omv.reg(),reg_map);323// It should be an error if no location can be found for a324// register mentioned as contained an oop of some kind. Maybe325// this was allowed previously because value_value items might326// be missing?327guarantee(loc != NULL, "missing saved register");328if ( omv.type() == OopMapValue::oop_value ) {329oop val = *loc;330if (val == NULL || CompressedOops::is_base(val)) {331// Ignore NULL oops and decoded NULL narrow oops which332// equal to CompressedOops::base() when a narrow oop333// implicit null check is used in compiled code.334// The narrow_oop_base could be NULL or be the address335// of the page below heap depending on compressed oops mode.336continue;337}338oop_fn->do_oop(loc);339} else if ( omv.type() == OopMapValue::narrowoop_value ) {340narrowOop *nl = (narrowOop*)loc;341#ifndef VM_LITTLE_ENDIAN342VMReg vmReg = omv.reg();343if (!vmReg->is_stack()) {344// compressed oops in registers only take up 4 bytes of an345// 8 byte register but they are in the wrong part of the346// word so adjust loc to point at the right place.347nl = (narrowOop*)((address)nl + 4);348}349#endif350oop_fn->do_oop(nl);351}352}353}354}355356357// Update callee-saved register info for the following frame358void OopMapSet::update_register_map(const frame *fr, RegisterMap *reg_map) {359ResourceMark rm;360CodeBlob* cb = fr->cb();361assert(cb != NULL, "no codeblob");362363// Any reg might be saved by a safepoint handler (see generate_handler_blob).364assert( reg_map->_update_for_id == NULL || fr->is_older(reg_map->_update_for_id),365"already updated this map; do not 'update' it twice!" );366debug_only(reg_map->_update_for_id = fr->id());367368// Check if caller must update oop argument369assert((reg_map->include_argument_oops() ||370!cb->caller_must_gc_arguments(reg_map->thread())),371"include_argument_oops should already be set");372373// Scan through oopmap and find location of all callee-saved registers374// (we do not do update in place, since info could be overwritten)375376address pc = fr->pc();377const ImmutableOopMap* map = cb->oop_map_for_return_address(pc);378assert(map != NULL, "no ptr map found");379DEBUG_ONLY(int nof_callee = 0;)380381for (OopMapStream oms(map); !oms.is_done(); oms.next()) {382OopMapValue omv = oms.current();383if (omv.type() == OopMapValue::callee_saved_value) {384VMReg reg = omv.content_reg();385oop* loc = fr->oopmapreg_to_oop_location(omv.reg(), reg_map);386reg_map->set_location(reg, (address) loc);387DEBUG_ONLY(nof_callee++;)388}389}390391// Check that runtime stubs save all callee-saved registers392#ifdef COMPILER2393assert(cb->is_compiled_by_c1() || cb->is_compiled_by_jvmci() || !cb->is_runtime_stub() ||394(nof_callee >= SAVED_ON_ENTRY_REG_COUNT || nof_callee >= C_SAVED_ON_ENTRY_REG_COUNT),395"must save all");396#endif // COMPILER2397}398399// Printing code is present in product build for -XX:+PrintAssembly.400401static402void print_register_type(OopMapValue::oop_types x, VMReg optional,403outputStream* st) {404switch( x ) {405case OopMapValue::oop_value:406st->print("Oop");407break;408case OopMapValue::narrowoop_value:409st->print("NarrowOop");410break;411case OopMapValue::callee_saved_value:412st->print("Callers_");413optional->print_on(st);414break;415case OopMapValue::derived_oop_value:416st->print("Derived_oop_");417optional->print_on(st);418break;419default:420ShouldNotReachHere();421}422}423424void OopMapValue::print_on(outputStream* st) const {425reg()->print_on(st);426st->print("=");427print_register_type(type(),content_reg(),st);428st->print(" ");429}430431void OopMapValue::print() const { print_on(tty); }432433void ImmutableOopMap::print_on(outputStream* st) const {434OopMapValue omv;435st->print("ImmutableOopMap {");436for(OopMapStream oms(this); !oms.is_done(); oms.next()) {437omv = oms.current();438omv.print_on(st);439}440st->print("}");441}442443void ImmutableOopMap::print() const { print_on(tty); }444445void OopMap::print_on(outputStream* st) const {446OopMapValue omv;447st->print("OopMap {");448for(OopMapStream oms((OopMap*)this); !oms.is_done(); oms.next()) {449omv = oms.current();450omv.print_on(st);451}452// Print hex offset in addition.453st->print("off=%d/0x%x}", (int) offset(), (int) offset());454}455456void OopMap::print() const { print_on(tty); }457458void ImmutableOopMapSet::print_on(outputStream* st) const {459const ImmutableOopMap* last = NULL;460const int len = count();461462st->print_cr("ImmutableOopMapSet contains %d OopMaps", len);463464for (int i = 0; i < len; i++) {465const ImmutableOopMapPair* pair = pair_at(i);466const ImmutableOopMap* map = pair->get_from(this);467if (map != last) {468st->cr();469map->print_on(st);470st->print(" pc offsets: ");471}472last = map;473st->print("%d ", pair->pc_offset());474}475st->cr();476}477478void ImmutableOopMapSet::print() const { print_on(tty); }479480void OopMapSet::print_on(outputStream* st) const {481const int len = _list.length();482483st->print_cr("OopMapSet contains %d OopMaps", len);484485for( int i = 0; i < len; i++) {486OopMap* m = at(i);487st->print_cr("#%d ",i);488m->print_on(st);489st->cr();490}491st->cr();492}493494void OopMapSet::print() const { print_on(tty); }495496bool OopMap::equals(const OopMap* other) const {497if (other->_omv_count != _omv_count) {498return false;499}500if (other->write_stream()->position() != write_stream()->position()) {501return false;502}503if (memcmp(other->write_stream()->buffer(), write_stream()->buffer(), write_stream()->position()) != 0) {504return false;505}506return true;507}508509const ImmutableOopMap* ImmutableOopMapSet::find_map_at_offset(int pc_offset) const {510ImmutableOopMapPair* pairs = get_pairs();511ImmutableOopMapPair* last = NULL;512513for (int i = 0; i < _count; ++i) {514if (pairs[i].pc_offset() >= pc_offset) {515last = &pairs[i];516break;517}518}519520// Heal Coverity issue: potential index out of bounds access.521guarantee(last != NULL, "last may not be null");522assert(last->pc_offset() == pc_offset, "oopmap not found");523return last->get_from(this);524}525526const ImmutableOopMap* ImmutableOopMapPair::get_from(const ImmutableOopMapSet* set) const {527return set->oopmap_at_offset(_oopmap_offset);528}529530ImmutableOopMap::ImmutableOopMap(const OopMap* oopmap) : _count(oopmap->count()) {531address addr = data_addr();532oopmap->copy_data_to(addr);533}534535#ifdef ASSERT536int ImmutableOopMap::nr_of_bytes() const {537OopMapStream oms(this);538539while (!oms.is_done()) {540oms.next();541}542return sizeof(ImmutableOopMap) + oms.stream_position();543}544#endif545546ImmutableOopMapBuilder::ImmutableOopMapBuilder(const OopMapSet* set) : _set(set), _empty(NULL), _last(NULL), _empty_offset(-1), _last_offset(-1), _offset(0), _required(-1), _new_set(NULL) {547_mapping = NEW_RESOURCE_ARRAY(Mapping, _set->size());548}549550int ImmutableOopMapBuilder::size_for(const OopMap* map) const {551return align_up((int)sizeof(ImmutableOopMap) + map->data_size(), 8);552}553554int ImmutableOopMapBuilder::heap_size() {555int base = sizeof(ImmutableOopMapSet);556base = align_up(base, 8);557558// all of ours pc / offset pairs559int pairs = _set->size() * sizeof(ImmutableOopMapPair);560pairs = align_up(pairs, 8);561562for (int i = 0; i < _set->size(); ++i) {563int size = 0;564OopMap* map = _set->at(i);565566if (is_empty(map)) {567/* only keep a single empty map in the set */568if (has_empty()) {569_mapping[i].set(Mapping::OOPMAP_EMPTY, _empty_offset, 0, map, _empty);570} else {571_empty_offset = _offset;572_empty = map;573size = size_for(map);574_mapping[i].set(Mapping::OOPMAP_NEW, _offset, size, map);575}576} else if (is_last_duplicate(map)) {577/* if this entry is identical to the previous one, just point it there */578_mapping[i].set(Mapping::OOPMAP_DUPLICATE, _last_offset, 0, map, _last);579} else {580/* not empty, not an identical copy of the previous entry */581size = size_for(map);582_mapping[i].set(Mapping::OOPMAP_NEW, _offset, size, map);583_last_offset = _offset;584_last = map;585}586587assert(_mapping[i]._map == map, "check");588_offset += size;589}590591int total = base + pairs + _offset;592DEBUG_ONLY(total += 8);593_required = total;594return total;595}596597void ImmutableOopMapBuilder::fill_pair(ImmutableOopMapPair* pair, const OopMap* map, int offset, const ImmutableOopMapSet* set) {598assert(offset < set->nr_of_bytes(), "check");599new ((address) pair) ImmutableOopMapPair(map->offset(), offset);600}601602int ImmutableOopMapBuilder::fill_map(ImmutableOopMapPair* pair, const OopMap* map, int offset, const ImmutableOopMapSet* set) {603fill_pair(pair, map, offset, set);604address addr = (address) pair->get_from(_new_set); // location of the ImmutableOopMap605606new (addr) ImmutableOopMap(map);607return size_for(map);608}609610void ImmutableOopMapBuilder::fill(ImmutableOopMapSet* set, int sz) {611ImmutableOopMapPair* pairs = set->get_pairs();612613for (int i = 0; i < set->count(); ++i) {614const OopMap* map = _mapping[i]._map;615ImmutableOopMapPair* pair = NULL;616int size = 0;617618if (_mapping[i]._kind == Mapping::OOPMAP_NEW) {619size = fill_map(&pairs[i], map, _mapping[i]._offset, set);620} else if (_mapping[i]._kind == Mapping::OOPMAP_DUPLICATE || _mapping[i]._kind == Mapping::OOPMAP_EMPTY) {621fill_pair(&pairs[i], map, _mapping[i]._offset, set);622}623624const ImmutableOopMap* nv = set->find_map_at_offset(map->offset());625assert(memcmp(map->data(), nv->data_addr(), map->data_size()) == 0, "check identity");626}627}628629#ifdef ASSERT630void ImmutableOopMapBuilder::verify(address buffer, int size, const ImmutableOopMapSet* set) {631for (int i = 0; i < 8; ++i) {632assert(buffer[size - 8 + i] == (unsigned char) 0xff, "overwritten memory check");633}634635for (int i = 0; i < set->count(); ++i) {636const ImmutableOopMapPair* pair = set->pair_at(i);637assert(pair->oopmap_offset() < set->nr_of_bytes(), "check size");638const ImmutableOopMap* map = pair->get_from(set);639int nr_of_bytes = map->nr_of_bytes();640assert(pair->oopmap_offset() + nr_of_bytes <= set->nr_of_bytes(), "check size + size");641}642}643#endif644645ImmutableOopMapSet* ImmutableOopMapBuilder::generate_into(address buffer) {646DEBUG_ONLY(memset(&buffer[_required-8], 0xff, 8));647648_new_set = new (buffer) ImmutableOopMapSet(_set, _required);649fill(_new_set, _required);650651DEBUG_ONLY(verify(buffer, _required, _new_set));652653return _new_set;654}655656ImmutableOopMapSet* ImmutableOopMapBuilder::build() {657_required = heap_size();658659// We need to allocate a chunk big enough to hold the ImmutableOopMapSet and all of its ImmutableOopMaps660address buffer = NEW_C_HEAP_ARRAY(unsigned char, _required, mtCode);661return generate_into(buffer);662}663664ImmutableOopMapSet* ImmutableOopMapSet::build_from(const OopMapSet* oopmap_set) {665ResourceMark mark;666ImmutableOopMapBuilder builder(oopmap_set);667return builder.build();668}669670671//------------------------------DerivedPointerTable---------------------------672673#if COMPILER2_OR_JVMCI674675class DerivedPointerTable::Entry : public CHeapObj<mtCompiler> {676derived_pointer* _location; // Location of derived pointer, also pointing to base677intptr_t _offset; // Offset from base pointer678Entry* volatile _next;679680static Entry* volatile* next_ptr(Entry& entry) { return &entry._next; }681682public:683Entry(derived_pointer* location, intptr_t offset) :684_location(location), _offset(offset), _next(NULL) {}685686derived_pointer* location() const { return _location; }687intptr_t offset() const { return _offset; }688Entry* next() const { return _next; }689690typedef LockFreeStack<Entry, &next_ptr> List;691static List* _list;692};693694DerivedPointerTable::Entry::List* DerivedPointerTable::Entry::_list = NULL;695bool DerivedPointerTable::_active = false;696697bool DerivedPointerTable::is_empty() {698return Entry::_list == NULL || Entry::_list->empty();699}700701void DerivedPointerTable::clear() {702// The first time, we create the list. Otherwise it should be703// empty. If not, then we have probably forgotton to call704// update_pointers after last GC/Scavenge.705assert (!_active, "should not be active");706assert(is_empty(), "table not empty");707if (Entry::_list == NULL) {708void* mem = NEW_C_HEAP_OBJ(Entry::List, mtCompiler);709Entry::_list = ::new (mem) Entry::List();710}711_active = true;712}713714void DerivedPointerTable::add(derived_pointer* derived_loc, oop *base_loc) {715assert(Universe::heap()->is_in_or_null(*base_loc), "not an oop");716assert(derived_loc != (void*)base_loc, "Base and derived in same location");717derived_pointer base_loc_as_derived_pointer =718static_cast<derived_pointer>(reinterpret_cast<intptr_t>(base_loc));719assert(*derived_loc != base_loc_as_derived_pointer, "location already added");720assert(Entry::_list != NULL, "list must exist");721assert(is_active(), "table must be active here");722intptr_t offset = *derived_loc - to_derived_pointer(*base_loc);723// This assert is invalid because derived pointers can be724// arbitrarily far away from their base.725// assert(offset >= -1000000, "wrong derived pointer info");726727if (TraceDerivedPointers) {728tty->print_cr(729"Add derived pointer@" INTPTR_FORMAT730" - Derived: " INTPTR_FORMAT731" Base: " INTPTR_FORMAT " (@" INTPTR_FORMAT ") (Offset: " INTX_FORMAT ")",732p2i(derived_loc), derived_pointer_value(*derived_loc), p2i(*base_loc), p2i(base_loc), offset733);734}735// Set derived oop location to point to base.736*derived_loc = base_loc_as_derived_pointer;737Entry* entry = new Entry(derived_loc, offset);738Entry::_list->push(*entry);739}740741void DerivedPointerTable::update_pointers() {742assert(Entry::_list != NULL, "list must exist");743Entry* entries = Entry::_list->pop_all();744while (entries != NULL) {745Entry* entry = entries;746entries = entry->next();747derived_pointer* derived_loc = entry->location();748intptr_t offset = entry->offset();749// The derived oop was setup to point to location of base750oop base = **reinterpret_cast<oop**>(derived_loc);751assert(Universe::heap()->is_in_or_null(base), "must be an oop");752753derived_pointer derived_base = to_derived_pointer(base);754*derived_loc = derived_base + offset;755assert(*derived_loc - derived_base == offset, "sanity check");756757if (TraceDerivedPointers) {758tty->print_cr("Updating derived pointer@" INTPTR_FORMAT759" - Derived: " INTPTR_FORMAT " Base: " INTPTR_FORMAT " (Offset: " INTX_FORMAT ")",760p2i(derived_loc), derived_pointer_value(*derived_loc), p2i(base), offset);761}762763// Delete entry764delete entry;765}766assert(Entry::_list->empty(), "invariant");767_active = false;768}769770#endif // COMPILER2_OR_JVMCI771772773