1 /* 2 * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #ifndef SHARE_RUNTIME_FRAME_INLINE_HPP 26 #define SHARE_RUNTIME_FRAME_INLINE_HPP 27 28 #include "runtime/frame.hpp" 29 30 #include "c1/c1_Runtime1.hpp" 31 #include "code/codeBlob.inline.hpp" 32 #include "code/nmethod.inline.hpp" 33 #include "interpreter/interpreter.hpp" 34 #include "oops/stackChunkOop.inline.hpp" 35 #include "oops/method.hpp" 36 #include "runtime/continuation.hpp" 37 #include "runtime/registerMap.hpp" 38 #include "runtime/stubRoutines.hpp" 39 #include "utilities/macros.hpp" 40 #ifdef ZERO 41 # include "entryFrame_zero.hpp" 42 # include "fakeStubFrame_zero.hpp" 43 # include "interpreterFrame_zero.hpp" 44 #endif 45 46 #include CPU_HEADER_INLINE(frame) 47 48 inline bool frame::is_entry_frame() const { 49 return StubRoutines::returns_to_call_stub(pc()); 50 } 51 52 inline bool frame::is_stub_frame() const { 53 return StubRoutines::is_stub_code(pc()) || (_cb != nullptr && _cb->is_adapter_blob()); 54 } 55 56 inline bool frame::is_first_frame() const { 57 return (is_entry_frame() && entry_frame_is_first()) 58 // Upcall stub frames entry frames are only present on certain platforms 59 || (is_upcall_stub_frame() && upcall_stub_frame_is_first()); 60 } 61 62 inline bool frame::is_upcall_stub_frame() const { 63 return _cb != nullptr && _cb->is_upcall_stub(); 64 } 65 66 inline bool frame::is_compiled_frame() const { 67 if (_cb != nullptr && 68 _cb->is_nmethod() && 69 _cb->as_nmethod()->is_java_method()) { 70 return true; 71 } 72 return false; 73 } 74 75 inline address frame::get_deopt_original_pc() const { 76 if (_cb == nullptr) return nullptr; 77 78 nmethod* nm = _cb->as_nmethod_or_null(); 79 if (nm != nullptr && nm->is_deopt_pc(_pc)) { 80 return nm->get_original_pc(this); 81 } 82 return nullptr; 83 } 84 85 #ifdef ASSERT 86 static address get_register_address_in_stub(const frame& stub_fr, VMReg reg) { 87 RegisterMap map(nullptr, 88 RegisterMap::UpdateMap::include, 89 RegisterMap::ProcessFrames::skip, 90 RegisterMap::WalkContinuation::skip); 91 stub_fr.oop_map()->update_register_map(&stub_fr, &map); 92 return map.location(reg, stub_fr.sp()); 93 } 94 #endif 95 96 inline JavaThread** frame::saved_thread_address(const frame& f) { 97 CodeBlob* cb = f.cb(); 98 assert(cb != nullptr && cb->is_runtime_stub(), "invalid frame"); 99 100 JavaThread** thread_addr; 101 if (cb == Runtime1::blob_for(Runtime1::monitorenter_id) || 102 cb == Runtime1::blob_for(Runtime1::monitorenter_nofpu_id)) { 103 thread_addr = (JavaThread**)(f.sp() + Runtime1::runtime_blob_current_thread_offset(f)); 104 } else { 105 // c2 only saves rbp in the stub frame so nothing to do. 106 thread_addr = nullptr; 107 } 108 assert(get_register_address_in_stub(f, SharedRuntime::thread_register()) == (address)thread_addr, "wrong thread address"); 109 return thread_addr; 110 } 111 112 template <typename RegisterMapT> 113 inline address frame::oopmapreg_to_location(VMReg reg, const RegisterMapT* reg_map) const { 114 if (reg->is_reg()) { 115 // If it is passed in a register, it got spilled in the stub frame. 116 return reg_map->location(reg, sp()); 117 } else { 118 int sp_offset_in_bytes = reg->reg2stack() * VMRegImpl::stack_slot_size; 119 if (reg_map->in_cont()) { 120 return (address)((intptr_t)reg_map->as_RegisterMap()->stack_chunk()->relativize_usp_offset(*this, sp_offset_in_bytes)); 121 } 122 address usp = (address)unextended_sp(); 123 assert(reg_map->thread() == nullptr || reg_map->thread()->is_in_usable_stack(usp), INTPTR_FORMAT, p2i(usp)); 124 return (usp + sp_offset_in_bytes); 125 } 126 } 127 128 template <typename RegisterMapT> 129 inline oop* frame::oopmapreg_to_oop_location(VMReg reg, const RegisterMapT* reg_map) const { 130 return (oop*)oopmapreg_to_location(reg, reg_map); 131 } 132 133 inline CodeBlob* frame::get_cb() const { 134 // if (_cb == nullptr) _cb = CodeCache::find_blob(_pc); 135 if (_cb == nullptr) { 136 int slot; 137 _cb = CodeCache::find_blob_and_oopmap(_pc, slot); 138 if (_oop_map == nullptr && slot >= 0) { 139 _oop_map = _cb->oop_map_for_slot(slot, _pc); 140 } 141 } 142 return _cb; 143 } 144 145 inline const ImmutableOopMap* frame::get_oop_map() const { 146 if (_cb == nullptr || _cb->oop_maps() == nullptr) return nullptr; 147 148 NativePostCallNop* nop = nativePostCallNop_at(_pc); 149 int oopmap_slot; 150 int cb_offset; 151 if (nop != nullptr && nop->decode(oopmap_slot, cb_offset)) { 152 return _cb->oop_map_for_slot(oopmap_slot, _pc); 153 } 154 const ImmutableOopMap* oop_map = OopMapSet::find_map(this); 155 return oop_map; 156 } 157 158 inline int frame::interpreter_frame_monitor_size_in_bytes() { 159 // Number of bytes for a monitor. 160 return frame::interpreter_frame_monitor_size() * wordSize; 161 } 162 163 #endif // SHARE_RUNTIME_FRAME_INLINE_HPP