/* * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. 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. *
*/
address original_pc = CompiledMethod::get_deopt_original_pc(this); if (original_pc != NULL) {
_pc = original_pc;
_deopt_state = is_deoptimized;
assert(_cb == NULL || _cb->as_compiled_method()->insts_contains_inclusive(_pc), "original PC must be in the main code section of the compiled method (or must be immediately following it)");
} else { if (_cb == SharedRuntime::deopt_blob()) {
_deopt_state = is_deoptimized;
} else {
_deopt_state = not_deoptimized;
}
}
}
// In thaw, non-heap frames use this constructor to pass oop_map. I don't know why.
assert(_on_heap || _cb != nullptr, "these frames are always heap frames"); if (cb != NULL) {
setup(pc);
} #ifdef ASSERT // The following assertion has been disabled because it would sometime trap for Continuation.run, // which is not *in* a continuation and therefore does not clear the _cont_fastpath flag, but this // is benign even in fast mode (see Freeze::setup_jump) // We might freeze deoptimized frame in slow mode // assert(_pc == pc && _deopt_state == not_deoptimized, ""); #endif
}
// Here's a sticky one. This constructor can be called via AsyncGetCallTrace // when last_Java_sp is non-null but the pc fetched is junk. // AsyncGetCallTrace -> pd_get_top_frame_for_signal_handler // -> pd_last_frame should use a specialized version of pd_last_frame which could // call a specilaized frame constructor instead of this one. // Then we could use the assert below. However this assert is of somewhat dubious // value.
// Return unique id for this frame. The id must have a value where we can distinguish // identity and younger/older relationship. NULL represents an invalid (incomparable) // frame. inline intptr_t* frame::id(void) const { return unextended_sp(); }
// Return true if the frame is older (less recent activation) than the frame represented by id inlinebool frame::is_older(intptr_t* id) const { assert(this->id() != NULL && id != NULL, "NULL frame id"); return this->id() > id ; }
// top of expression stack inline intptr_t* frame::interpreter_frame_tos_address() const {
intptr_t* last_sp = interpreter_frame_last_sp(); if (last_sp == NULL) { return sp();
} else { // sp() may have been extended or shrunk by an adapter. At least // check that we don't fall behind the legal region. // For top deoptimized frame last_sp == interpreter_frame_monitor_end.
assert(last_sp <= (intptr_t*) interpreter_frame_monitor_end(), "bad tos"); return last_sp;
}
}
if (map->process_frames() && !map->in_cont()) {
StackWatermarkSet::on_iteration(map->thread(), result);
}
return result;
}
//------------------------------------------------------------------------------ // frame::sender_raw
frame frame::sender_raw(RegisterMap* map) const { // Default is we done have to follow them. The sender_for_xxx will // update it accordingly
assert(map != NULL, "map must be set");
map->set_include_argument_oops(false);
if (map->in_cont()) { // already in an h-stack return map->stack_chunk()->sender(*this, map);
}
if (is_entry_frame()) { return sender_for_entry_frame(map);
}
if (is_interpreted_frame()) { return sender_for_interpreter_frame(map);
}
assert(_cb == CodeCache::find_blob(pc()),"Must be the same"); if (_cb != NULL) { return sender_for_compiled_frame(map);
}
// Must be native-compiled frame, i.e. the marshaling code for native // methods that exists in the core system.
// Native code may or may not have signed the return address, we have no way to be sure // or what signing methods they used. Instead, just ensure the stripped value is used.
return frame(sender_sp(), link(), sender_pc());
}
//------------------------------------------------------------------------------ // frame::sender_for_compiled_frame
frame frame::sender_for_compiled_frame(RegisterMap* map) const { // we cannot rely upon the last fp having been saved to the thread // in C2 code but it will have been pushed onto the stack. so we // have to find it relative to the unextended sp
assert(map != NULL, "map must be set"); if (map->update_map()) { // Tell GC to use argument oopmaps for some runtime stubs that need it. // For C1, the runtime stub might not have oop maps, so set this flag // outside of update_register_map. if (!_cb->is_compiled()) { // compiled frames do not use callee-saved registers
map->set_include_argument_oops(_cb->caller_must_gc_arguments(map->thread())); if (oop_map() != NULL) {
_oop_map->update_register_map(this, map);
}
} else {
assert(!_cb->caller_must_gc_arguments(map->thread()), "");
assert(!map->include_argument_oops(), "");
assert(oop_map() == NULL || !oop_map()->has_any(OopMapValue::callee_saved_value), "callee-saved value in compiled frame");
}
// Since the prolog does the save and restore of FP there is no // oopmap for it so we must fill in its location as if there was // an oopmap entry since if our caller was compiled code there // could be live jvm state in it.
update_map_with_saved_link(map, saved_fp_addr);
}
if (Continuation::is_return_barrier_entry(sender_pc)) { if (map->walk_cont()) { // about to walk into an h-stack return Continuation::top_frame(*this, map);
} else { return Continuation::continuation_bottom_sender(map->thread(), *this, l_sender_sp);
}
}
//------------------------------------------------------------------------------ // frame::update_map_with_saved_link template <typename RegisterMapT> void frame::update_map_with_saved_link(RegisterMapT* map, intptr_t** link_addr) {
assert(map != NULL, "map must be set"); // The interpreter and compiler(s) always save FP in a known // location on entry. C2-compiled code uses FP as an allocatable // callee-saved register. We must record where that location is so // that if FP was live on callout from C2 we can find the saved copy.
map->set_location(::fp->as_VMReg(), (address) link_addr); // this is weird "H" ought to be at a higher address however the // oopMaps seems to have the "H" regs at the same address and the // vanilla register.
map->set_location(::fp->as_VMReg()->next(), (address) link_addr);
}
#endif// CPU_RISCV_FRAME_RISCV_INLINE_HPP
¤ Dauer der Verarbeitung: 0.14 Sekunden
(vorverarbeitet)
¤
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.