1 /* 2 * Copyright (c) 2022, 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_VM_RUNTIME_CONTINUATIONHELPER_INLINE_HPP 26 #define SHARE_VM_RUNTIME_CONTINUATIONHELPER_INLINE_HPP 27 28 #include "runtime/continuationHelper.hpp" 29 30 #include "code/scopeDesc.hpp" 31 #include "compiler/oopMap.hpp" 32 #include "compiler/oopMap.inline.hpp" 33 #include "interpreter/oopMapCache.hpp" 34 #include "runtime/frame.inline.hpp" 35 #include "runtime/stackValue.hpp" 36 #include "utilities/macros.hpp" 37 38 #include CPU_HEADER_INLINE(continuationHelper) 39 40 #ifndef CPU_OVERRIDES_RETURN_ADDRESS_ACCESSORS 41 inline address ContinuationHelper::return_address_at(intptr_t* sp) { 42 return *(address*)sp; 43 } 44 45 inline void ContinuationHelper::patch_return_address_at(intptr_t* sp, 46 address pc) { 47 *(address*)sp = pc; 48 } 49 #endif // !CPU_OVERRIDES_RETURN_ADDRESS_ACCESSORS 50 51 inline bool ContinuationHelper::NonInterpretedUnknownFrame::is_instance(const frame& f) { 52 return !f.is_interpreted_frame(); 53 } 54 55 inline bool ContinuationHelper::Frame::is_stub(CodeBlob* cb) { 56 return cb != nullptr && (cb->is_safepoint_stub() || cb->is_runtime_stub()); 57 } 58 59 inline Method* ContinuationHelper::Frame::frame_method(const frame& f) { 60 return f.is_interpreted_frame() ? f.interpreter_frame_method() : f.cb()->as_nmethod()->method(); 61 } 62 63 inline address ContinuationHelper::Frame::return_pc(const frame& f) { 64 return return_address_at((intptr_t *)return_pc_address(f)); 65 } 66 67 #ifdef ASSERT 68 inline intptr_t* ContinuationHelper::Frame::frame_top(const frame &f) { 69 if (f.is_interpreted_frame()) { 70 ResourceMark rm; 71 InterpreterOopMap mask; 72 f.interpreted_frame_oop_map(&mask); 73 return InterpretedFrame::frame_top(f, &mask); 74 } else { 75 return CompiledFrame::frame_top(f); 76 } 77 } 78 79 inline bool ContinuationHelper::Frame::is_deopt_return(address pc, const frame& sender) { 80 if (sender.is_interpreted_frame()) return false; 81 82 nmethod* nm = sender.cb()->as_nmethod(); 83 return nm->is_deopt_pc(pc); 84 } 85 86 #endif 87 88 inline bool ContinuationHelper::InterpretedFrame::is_instance(const frame& f) { 89 return f.is_interpreted_frame(); 90 } 91 92 inline address ContinuationHelper::InterpretedFrame::return_pc(const frame& f) { 93 return return_address_at((intptr_t *)return_pc_address(f)); 94 } 95 96 inline int ContinuationHelper::InterpretedFrame::size(const frame&f) { 97 return pointer_delta_as_int(InterpretedFrame::frame_bottom(f), InterpretedFrame::frame_top(f)); 98 } 99 100 inline int ContinuationHelper::InterpretedFrame::stack_argsize(const frame& f) { 101 return f.interpreter_frame_method()->size_of_parameters(); 102 } 103 104 inline int ContinuationHelper::InterpretedFrame::expression_stack_size(const frame &f, InterpreterOopMap* mask) { 105 int size = mask->expression_stack_size(); 106 assert(size <= f.interpreter_frame_expression_stack_size(), "size1: %d size2: %d", size, f.interpreter_frame_expression_stack_size()); 107 return size; 108 } 109 110 #ifdef ASSERT 111 inline bool ContinuationHelper::InterpretedFrame::is_owning_locks(const frame& f) { 112 assert(f.interpreter_frame_monitor_end() <= f.interpreter_frame_monitor_begin(), "must be"); 113 if (f.interpreter_frame_monitor_end() == f.interpreter_frame_monitor_begin()) { 114 return false; 115 } 116 117 for (BasicObjectLock* current = f.previous_monitor_in_interpreter_frame(f.interpreter_frame_monitor_begin()); 118 current >= f.interpreter_frame_monitor_end(); 119 current = f.previous_monitor_in_interpreter_frame(current)) { 120 121 oop obj = current->obj(); 122 if (obj != nullptr) { 123 return true; 124 } 125 } 126 return false; 127 } 128 #endif 129 130 inline intptr_t* ContinuationHelper::InterpretedFrame::frame_top(const frame& f) { // inclusive; this will be copied with the frame 131 return f.unextended_sp(); 132 } 133 134 inline intptr_t* ContinuationHelper::NonInterpretedFrame::frame_top(const frame& f, int callee_argsize, bool callee_interpreted) { 135 return f.unextended_sp() + (callee_interpreted ? 0 : callee_argsize); 136 } 137 138 inline intptr_t* ContinuationHelper::NonInterpretedFrame::frame_top(const frame& f) { // inclusive; this will be copied with the frame 139 return f.unextended_sp(); 140 } 141 142 inline intptr_t* ContinuationHelper::NonInterpretedFrame::frame_bottom(const frame& f) { // exclusive; this will not be copied with the frame 143 return f.unextended_sp() + f.cb()->frame_size(); 144 } 145 146 inline int ContinuationHelper::NonInterpretedFrame::size(const frame& f) { 147 assert(!f.is_interpreted_frame(), ""); 148 return f.cb()->frame_size(); 149 } 150 151 inline int ContinuationHelper::NonInterpretedFrame::stack_argsize(const frame& f) { 152 return f.compiled_frame_stack_argsize(); 153 } 154 155 inline bool ContinuationHelper::CompiledFrame::is_instance(const frame& f) { 156 return f.is_compiled_frame(); 157 } 158 159 #ifdef ASSERT 160 template<typename RegisterMapT> 161 bool ContinuationHelper::CompiledFrame::is_owning_locks(JavaThread* thread, RegisterMapT* map, const frame& f) { 162 assert(!f.is_interpreted_frame(), ""); 163 assert(CompiledFrame::is_instance(f), ""); 164 165 nmethod* nm = f.cb()->as_nmethod(); 166 assert(!nm->is_native_method(), ""); // See compiledVFrame::compiledVFrame(...) in vframe_hp.cpp 167 168 if (!nm->has_monitors()) { 169 return false; 170 } 171 172 frame::update_map_with_saved_link(map, Frame::callee_link_address(f)); // the monitor object could be stored in the link register 173 ResourceMark rm; 174 for (ScopeDesc* scope = nm->scope_desc_at(f.pc()); scope != nullptr; scope = scope->sender()) { 175 GrowableArray<MonitorValue*>* mons = scope->monitors(); 176 if (mons == nullptr || mons->is_empty()) { 177 continue; 178 } 179 180 for (int index = (mons->length()-1); index >= 0; index--) { // see compiledVFrame::monitors() 181 MonitorValue* mon = mons->at(index); 182 if (mon->eliminated()) { 183 continue; // we ignore scalar-replaced monitors 184 } 185 ScopeValue* ov = mon->owner(); 186 StackValue* owner_sv = StackValue::create_stack_value(&f, map, ov); // it is an oop 187 oop owner = owner_sv->get_obj()(); 188 if (owner != nullptr) { 189 //assert(nm->has_monitors(), ""); 190 return true; 191 } 192 } 193 } 194 return false; 195 } 196 #endif 197 198 inline bool ContinuationHelper::StubFrame::is_instance(const frame& f) { 199 return !f.is_interpreted_frame() && is_stub(f.cb()); 200 } 201 202 #endif // SHARE_VM_RUNTIME_CONTINUATIONHELPER_INLINE_HPP