/* * Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. *
*/
// frame_size units are stack-slots (4 bytes) NOT intptr_t; we can name odd // 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;
_has_derived_oops = false;
_index = -1;
// We need to copy the entries too. for (OopMapStream oms(source); !oms.is_done(); oms.next()) {
OopMapValue omv = oms.current();
omv.write_on(write_stream());
increment_count();
}
}
int OopMap::heap_size() const { int size = sizeof(OopMap); int align = sizeof(void *) - 1;
size += write_stream()->position(); // Align to a reasonable ending point
size = ((size+align) & ~align); return size;
}
// frame_size units are stack-slots (4 bytes) NOT intptr_t; we can name odd // slots to hold 4-byte values like ints and floats in the LP64 build. void OopMap::set_xxx(VMReg reg, OopMapValue::oop_types x, VMReg optional) {
assert(reg->value() < _locs_length, "too big reg value for stack size");
assert( _locs_used[reg->value()] == OopMapValue::unused_value, "cannot insert twice" );
debug_only( _locs_used[reg->value()] = x; )
virtualvoid do_derived_oop(oop* base, derived_pointer* derived) { // All derived pointers must be processed before the base pointer of any derived pointer is processed. // Otherwise, if two derived pointers use the same base, the second derived pointer will get an obscured // offset, if the base pointer is processed in the first derived pointer.
derived_pointer derived_base = to_derived_pointer(*base);
intptr_t offset = *derived - derived_base;
*derived = derived_base;
_oop_cl->do_oop((oop*)derived);
*derived = *derived + offset;
}
};
class IgnoreDerivedOop : public DerivedOopClosure {
OopClosure* _oop_cl;
// Update callee-saved register info for the following frame void ImmutableOopMap::update_register_map(const frame *fr, RegisterMap *reg_map) const{
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)
// 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);
}
int ImmutableOopMapSet::find_slot_for_offset(int pc_offset) const { // we might not have an oopmap at asynchronous (non-safepoint) stackwalks
ImmutableOopMapPair* pairs = get_pairs(); for (int i = 0; i < _count; ++i) { if (pairs[i].pc_offset() >= pc_offset) {
ImmutableOopMapPair* last = &pairs[i]; return last->pc_offset() == pc_offset ? i : -1;
}
} return -1;
}
for (int i = 0; i < _count; ++i) { if (pairs[i].pc_offset() >= pc_offset) {
last = &pairs[i]; break;
}
}
// Heal Coverity issue: potential index out of bounds access.
guarantee(last != NULL, "last may not be null");
assert(last->pc_offset() == pc_offset, "oopmap not found"); return last->get_from(this);
}
int ImmutableOopMapBuilder::heap_size() { int base = sizeof(ImmutableOopMapSet);
base = align_up(base, 8);
// all of ours pc / offset pairs int pairs = _set->size() * sizeof(ImmutableOopMapPair);
pairs = align_up(pairs, 8);
for (int i = 0; i < _set->size(); ++i) { int size = 0;
OopMap* map = _set->at(i);
if (is_empty(map)) { /* only keep a single empty map in the set */ if (has_empty()) {
_mapping[i].set(Mapping::OOPMAP_EMPTY, _empty_offset, 0, map, _empty);
} else {
_empty_offset = _offset;
_empty = map;
size = size_for(map);
_mapping[i].set(Mapping::OOPMAP_NEW, _offset, size, map);
}
} elseif (is_last_duplicate(map)) { /* if this entry is identical to the previous one, just point it there */
_mapping[i].set(Mapping::OOPMAP_DUPLICATE, _last_offset, 0, map, _last);
} else { /* not empty, not an identical copy of the previous entry */
size = size_for(map);
_mapping[i].set(Mapping::OOPMAP_NEW, _offset, size, map);
_last_offset = _offset;
_last = map;
}
// We need to allocate a chunk big enough to hold the ImmutableOopMapSet and all of its ImmutableOopMaps
address buffer = NEW_C_HEAP_ARRAY(unsignedchar, _required, mtCode); return generate_into(buffer);
}
class DerivedPointerTable::Entry : public CHeapObj<mtCompiler> {
derived_pointer* _location; // Location of derived pointer, also pointing to base
intptr_t _offset; // Offset from base pointer
Entry* volatile _next;
void DerivedPointerTable::clear() { // The first time, we create the list. Otherwise it should be // empty. If not, then we have probably forgotton to call // update_pointers after last GC/Scavenge.
assert (!_active, "should not be active");
assert(is_empty(), "table not empty"); if (Entry::_list == NULL) { void* mem = NEW_C_HEAP_OBJ(Entry::List, mtCompiler);
Entry::_list = ::new (mem) Entry::List();
}
_active = true;
}
void DerivedPointerTable::add(derived_pointer* derived_loc, oop *base_loc) {
assert(Universe::heap()->is_in_or_null(*base_loc), "not an oop");
assert(derived_loc != (void*)base_loc, "Base and derived in same location");
derived_pointer base_loc_as_derived_pointer = static_cast<derived_pointer>(reinterpret_cast<intptr_t>(base_loc));
assert(*derived_loc != base_loc_as_derived_pointer, "location already added");
assert(Entry::_list != NULL, "list must exist");
assert(is_active(), "table must be active here");
intptr_t offset = *derived_loc - to_derived_pointer(*base_loc); // This assert is invalid because derived pointers can be // arbitrarily far away from their base. // assert(offset >= -1000000, "wrong derived pointer info");
if (TraceDerivedPointers) {
tty->print_cr( "Add derived pointer@" INTPTR_FORMAT " - Derived: " INTPTR_FORMAT " Base: " INTPTR_FORMAT " (@" INTPTR_FORMAT ") (Offset: " INTX_FORMAT ")",
p2i(derived_loc), derived_pointer_value(*derived_loc), p2i(*base_loc), p2i(base_loc), offset
);
} // Set derived oop location to point to base.
*derived_loc = base_loc_as_derived_pointer;
Entry* entry = new Entry(derived_loc, offset);
Entry::_list->push(*entry);
}
void DerivedPointerTable::update_pointers() {
assert(Entry::_list != NULL, "list must exist");
Entry* entries = Entry::_list->pop_all(); while (entries != NULL) {
Entry* entry = entries;
entries = entry->next();
derived_pointer* derived_loc = entry->location();
intptr_t offset = entry->offset(); // The derived oop was setup to point to location of base
oop base = **reinterpret_cast<oop**>(derived_loc);
assert(Universe::heap()->is_in_or_null(base), "must be an oop");
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.