/* * Copyright (c) 2021, 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. *
*/
int index = f.frame_index(); // we need to capture the index before calling derelativize, which destroys it
StackChunkFrameStream<ChunkFrames::Mixed> fs(this, derelativize(f));
fs.next(map);
if (!fs.is_done()) {
frame sender = fs.to_frame();
assert(is_usable_in_chunk(sender.unextended_sp()), "");
relativize_frame(sender);
sender.set_frame_index(index+1); return sender;
}
if (parent() != nullptr) {
assert(!parent()->is_empty(), ""); return parent()->top_frame(map);
}
int stackChunkOopDesc::num_java_frames() const { int n = 0; for (StackChunkFrameStream<ChunkFrames::Mixed> f(const_cast<stackChunkOopDesc*>(this)); !f.is_done();
f.next(SmallRegisterMap::instance)) { if (!f.is_stub()) {
n += ::num_java_frames(f);
}
} return n;
}
template <stackChunkOopDesc::BarrierType barrier> class DoBarriersStackClosure { const stackChunkOop _chunk;
class DerivedPointersSupport { public: staticvoid relativize(oop* base_loc, derived_pointer* derived_loc) {
oop base = *base_loc; if (base == nullptr) { return;
}
assert(!UseCompressedOops || !CompressedOops::is_base(base), "");
// This is always a full derived pointer
uintptr_t derived_int_val = *(uintptr_t*)derived_loc;
// Make the pointer an offset (relativize) and store it at the same location
uintptr_t offset = derived_int_val - cast_from_oop<uintptr_t>(base);
*(uintptr_t*)derived_loc = offset;
}
bool stackChunkOopDesc::try_acquire_relativization() { for (;;) { // We use an acquiring load when reading the flags to ensure that if we leave this // function thinking that relativization is finished, we know that if another thread // did the relativization, we will still be able to observe the relativized derived // pointers, which is important as subsequent modifications of derived pointers must // happen after relativization.
uint8_t flags_before = flags_acquire(); if ((flags_before & FLAG_GC_MODE) != 0) { // Terminal state - relativization is ensured returnfalse;
}
if ((flags_before & FLAG_CLAIM_RELATIVIZE) != 0) { // Someone else has claimed relativization - wait for completion
MonitorLocker ml(ContinuationRelativize_lock, Mutex::_no_safepoint_check_flag);
uint8_t flags_under_lock = flags_acquire(); if ((flags_under_lock & FLAG_GC_MODE) != 0) { // Terminal state - relativization is ensured returnfalse;
}
if ((flags_under_lock & FLAG_NOTIFY_RELATIVIZE) != 0) { // Relativization is claimed by another thread, and it knows it needs to notify
ml.wait();
} elseif (try_set_flags(flags_under_lock, flags_under_lock | FLAG_NOTIFY_RELATIVIZE)) { // Relativization is claimed by another thread, and it knows it needs to notify
ml.wait();
} // Retry - rerun the loop continue;
}
if (try_set_flags(flags_before, flags_before | FLAG_CLAIM_RELATIVIZE)) { // Claimed relativization - let's do it returntrue;
}
}
}
void stackChunkOopDesc::release_relativization() { for (;;) {
uint8_t flags_before = flags(); if ((flags_before & FLAG_NOTIFY_RELATIVIZE) != 0) {
MonitorLocker ml(ContinuationRelativize_lock, Mutex::_no_safepoint_check_flag); // No need to CAS the terminal state; nobody else can be racingly mutating here // as both claim and notify flags are already set (and monotonic) // We do however need to use a releasing store on the flags, to ensure that // the reader of that value (using load_acquire) will be able to observe // the relativization of the derived pointers
uint8_t flags_under_lock = flags();
release_set_flags(flags_under_lock | FLAG_GC_MODE);
ml.notify_all(); return;
}
if (try_set_flags(flags_before, flags_before | FLAG_GC_MODE)) { // Successfully set the terminal state; we are done return;
}
}
}
template <stackChunkOopDesc::BarrierType barrier, ChunkFrames frame_kind, typename RegisterMapT> void stackChunkOopDesc::do_barriers0(const StackChunkFrameStream<frame_kind>& f, const RegisterMapT* map) { // We need to invoke the write barriers so as not to miss oops in old chunks that haven't yet been concurrently scanned
assert (!f.is_done(), "");
if (f.is_interpreted()) {
Method* m = f.to_frame().interpreter_frame_method(); // Class redefinition support
m->record_gc_epoch();
} elseif (f.is_compiled()) {
nmethod* nm = f.cb()->as_nmethod(); // The entry barrier takes care of having the right synchronization // when keeping the nmethod alive during concurrent execution.
nm->run_nmethod_entry_barrier(); // There is no need to mark the Method, as class redefinition will walk the // CodeCache, noting their Methods
}
template <typename T> inlinevoid do_oop_work(T* p) {
_count++;
oop obj = _chunk->load_oop(p);
assert(obj == nullptr || dbg_is_good_oop(obj), "p: " PTR_FORMAT " obj: " PTR_FORMAT, p2i(p), p2i(obj)); if (_chunk->has_bitmap()) {
BitMap::idx_t index = _chunk->bit_index_for(p);
assert(_chunk->bitmap().at(index), "Bit not set at index " SIZE_FORMAT " corresponding to " PTR_FORMAT, index, p2i(p));
}
}
int count() const { return _count; }
};
class VerifyStackChunkFrameClosure {
stackChunkOop _chunk;
public:
intptr_t* _sp;
CodeBlob* _cb; bool _callee_interpreted; int _size; int _argsize; int _num_oops; int _num_frames; int _num_interpreted_frames; int _num_i2c;
VerifyStackChunkFrameClosure(stackChunkOop chunk, int num_frames, int size)
: _chunk(chunk), _sp(nullptr), _cb(nullptr), _callee_interpreted(false),
_size(size), _argsize(0), _num_oops(0), _num_frames(num_frames), _num_interpreted_frames(0), _num_i2c(0) {}
// If argsize == 0 and the chunk isn't mixed, the chunk contains the metadata (pc, fp -- frame::sender_sp_offset) // for the top frame (below sp), and *not* for the bottom frame. int size = stack_size() - argsize() - sp();
assert(size >= 0, "");
assert((size == 0) == is_empty(), "");
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.