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