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 }
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
|
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 "utilities/macros.hpp"
38
39 #include CPU_HEADER_INLINE(continuationHelper)
40
41 #ifndef CPU_OVERRIDES_RETURN_ADDRESS_ACCESSORS
42 inline address ContinuationHelper::return_address_at(intptr_t* sp) {
43 return *(address*)sp;
44 }
45
46 inline void ContinuationHelper::patch_return_address_at(intptr_t* sp,
47 address pc) {
48 *(address*)sp = pc;
49 }
50 #endif // !CPU_OVERRIDES_RETURN_ADDRESS_ACCESSORS
51
52 inline bool ContinuationHelper::NonInterpretedUnknownFrame::is_instance(const frame& f) {
53 return !f.is_interpreted_frame();
54 }
55
56 inline bool ContinuationHelper::Frame::is_stub(CodeBlob* cb) {
57 return cb != nullptr && cb->is_runtime_stub();
58 }
59
60 inline Method* ContinuationHelper::Frame::frame_method(const frame& f) {
61 return f.is_interpreted_frame() ? f.interpreter_frame_method() : f.cb()->as_nmethod()->method();
62 }
63
64 inline address ContinuationHelper::Frame::return_pc(const frame& f) {
65 return return_address_at((intptr_t *)return_pc_address(f));
66 }
67
68 #ifdef ASSERT
69 inline intptr_t* ContinuationHelper::Frame::frame_top(const frame &f) {
70 if (f.is_interpreted_frame()) {
71 ResourceMark rm;
72 InterpreterOopMap mask;
73 f.interpreted_frame_oop_map(&mask);
74 return InterpretedFrame::frame_top(f, &mask);
75 } else {
76 return CompiledFrame::frame_top(f);
77 }
92
93 inline address ContinuationHelper::InterpretedFrame::return_pc(const frame& f) {
94 return return_address_at((intptr_t *)return_pc_address(f));
95 }
96
97 inline int ContinuationHelper::InterpretedFrame::size(const frame&f) {
98 return pointer_delta_as_int(InterpretedFrame::frame_bottom(f), InterpretedFrame::frame_top(f));
99 }
100
101 inline int ContinuationHelper::InterpretedFrame::stack_argsize(const frame& f) {
102 return f.interpreter_frame_method()->size_of_parameters();
103 }
104
105 inline int ContinuationHelper::InterpretedFrame::expression_stack_size(const frame &f, InterpreterOopMap* mask) {
106 int size = mask->expression_stack_size();
107 assert(size <= f.interpreter_frame_expression_stack_size(), "size1: %d size2: %d", size, f.interpreter_frame_expression_stack_size());
108 return size;
109 }
110
111 #ifdef ASSERT
112 inline int ContinuationHelper::InterpretedFrame::monitors_to_fix(JavaThread* thread, const frame& f, ResourceHashtable<oopDesc*, bool> &table, stackChunkOop chunk) {
113 BasicObjectLock* first_mon = f.interpreter_frame_monitor_begin();
114 BasicObjectLock* last_mon = f.interpreter_frame_monitor_end();
115 assert(last_mon <= first_mon, "must be");
116
117 if (first_mon == last_mon) {
118 // No monitors in this frame
119 return 0;
120 }
121
122 int monitor_count = 0;
123 oop monitorenter_oop = thread->is_on_monitorenter() ? thread->current_pending_monitor()->object() : nullptr;
124
125 for (BasicObjectLock* current = f.previous_monitor_in_interpreter_frame(first_mon);
126 current >= last_mon; current = f.previous_monitor_in_interpreter_frame(current)) {
127 oop* obj_adr = current->obj_adr();
128
129 oop obj;
130 if (f.is_heap_frame()) {
131 assert(chunk != nullptr, "null stackChunk");
132 obj = chunk->has_bitmap() && UseCompressedOops ? chunk->load_oop((narrowOop*)obj_adr) : chunk->load_oop(obj_adr);
133 } else {
134 // We have already processed oops when getting this frame.
135 obj = *obj_adr;
136 }
137 assert(obj == nullptr || dbg_is_good_oop(obj), "obj_adr: " PTR_FORMAT " obj: " PTR_FORMAT, p2i(obj_adr), p2i(obj));
138
139 if (obj != nullptr && obj != monitorenter_oop) {
140 markWord mark = obj->mark();
141 if (mark.has_monitor() && !mark.monitor()->is_owner_anonymous()) {
142 // Nothing to do
143 assert(mark.monitor()->is_owner(thread), "invariant");
144 continue;
145 }
146 assert(!f.is_heap_frame() || LockingMode == LM_LIGHTWEIGHT,
147 "monitors found on heap frame that need to be fixed should only be those saved in the LockStack");
148 bool created;
149 table.put_if_absent(obj, true, &created);
150 if (created) {
151 monitor_count++;
152 }
153 }
154 }
155 return monitor_count;
156 }
157 #endif
158
159 inline intptr_t* ContinuationHelper::InterpretedFrame::frame_top(const frame& f) { // inclusive; this will be copied with the frame
160 return f.unextended_sp();
161 }
162
163 inline intptr_t* ContinuationHelper::NonInterpretedFrame::frame_top(const frame& f, int callee_argsize, bool callee_interpreted) {
164 return f.unextended_sp() + (callee_interpreted ? 0 : callee_argsize);
165 }
166
167 inline intptr_t* ContinuationHelper::NonInterpretedFrame::frame_top(const frame& f) { // inclusive; this will be copied with the frame
168 return f.unextended_sp();
169 }
170
171 inline intptr_t* ContinuationHelper::NonInterpretedFrame::frame_bottom(const frame& f) { // exclusive; this will not be copied with the frame
172 return f.unextended_sp() + f.cb()->frame_size();
173 }
174
175 inline int ContinuationHelper::NonInterpretedFrame::size(const frame& f) {
176 assert(!f.is_interpreted_frame(), "");
177 return f.cb()->frame_size();
178 }
179
180 inline int ContinuationHelper::NonInterpretedFrame::stack_argsize(const frame& f) {
181 return f.compiled_frame_stack_argsize();
182 }
183
184 inline bool ContinuationHelper::CompiledFrame::is_instance(const frame& f) {
185 return f.is_compiled_frame();
186 }
187
188 inline bool ContinuationHelper::NativeFrame::is_instance(const frame& f) {
189 return f.is_native_frame();
190 }
191
192 #ifdef ASSERT
193 template<typename RegisterMapT>
194 int ContinuationHelper::CompiledFrame::monitors_to_fix(JavaThread* thread, RegisterMapT* map, const frame& f, ResourceHashtable<oopDesc*, bool> &table) {
195 assert(!f.is_interpreted_frame(), "");
196 assert(CompiledFrame::is_instance(f), "");
197
198 nmethod* nm = f.cb()->as_nmethod();
199 assert(!nm->is_nmethod() || !nm->as_nmethod()->is_native_method(), ""); // See compiledVFrame::compiledVFrame(...) in vframe_hp.cpp
200
201 if (!nm->has_monitors()) {
202 // No monitors in this frame
203 return 0;
204 }
205
206 int monitor_count = 0;
207 oop monitorenter_oop = thread->is_on_monitorenter() ? thread->current_pending_monitor()->object() : nullptr;
208
209 for (ScopeDesc* scope = nm->scope_desc_at(f.pc()); scope != nullptr; scope = scope->sender()) {
210 GrowableArray<MonitorValue*>* mons = scope->monitors();
211 if (mons == nullptr || mons->is_empty()) {
212 continue;
213 }
214
215 for (int index = (mons->length()-1); index >= 0; index--) { // see compiledVFrame::monitors()
216 MonitorValue* mon = mons->at(index);
217 if (mon->eliminated()) {
218 continue; // we ignore eliminated monitors
219 }
220
221 ScopeValue* ov = mon->owner();
222 StackValue* owner_sv = StackValue::create_stack_value(&f, map, ov); // it is an oop
223 oop owner = owner_sv->get_obj()();
224 if (owner != nullptr && owner != monitorenter_oop) {
225 markWord mark = owner->mark();
226 if (mark.has_monitor() && !mark.monitor()->is_owner_anonymous()) {
227 // Nothing to do
228 assert(mark.monitor()->is_owner(thread), "invariant");
229 continue;
230 }
231 assert(!f.is_heap_frame() || LockingMode == LM_LIGHTWEIGHT,
232 "monitors found on heap frame that need to be fixed should only be those saved in the LockStack");
233 bool created;
234 table.put_if_absent(owner, true, &created);
235 if (created) {
236 monitor_count++;
237 }
238 }
239 }
240 }
241 return monitor_count;
242 }
243
244 inline int ContinuationHelper::NativeFrame::monitors_to_fix(JavaThread* thread, const frame& f, ResourceHashtable<oopDesc*, bool> &table) {
245 assert(NativeFrame::is_instance(f), "");
246
247 Method* method = f.cb()->as_nmethod()->method();
248 if (!method->is_synchronized()) {
249 return 0;
250 }
251
252 oop synced_obj = f.get_native_receiver();
253 oop monitorenter_oop = thread->is_on_monitorenter() ? thread->current_pending_monitor()->object() : nullptr;
254
255 bool is_first_frame = f.sp() == thread->last_Java_sp();
256 if (!is_first_frame) {
257 assert(ObjectSynchronizer::current_thread_holds_lock(thread, Handle(thread, synced_obj)), "must be owner");
258 assert(monitorenter_oop == nullptr || monitorenter_oop != synced_obj, "owner already, should not be contended");
259
260 markWord mark = synced_obj->mark();
261 if (mark.has_monitor() && !mark.monitor()->is_owner_anonymous()) {
262 // Nothing to do
263 assert(mark.monitor()->is_owner(thread), "invariant");
264 return 0;
265 }
266 assert(!f.is_heap_frame(), "native frame on the heap???");
267 bool created;
268 table.put_if_absent(synced_obj, true, &created);
269 if (created) {
270 return 1;
271 }
272 } else {
273 assert(thread->is_on_monitorenter() && monitorenter_oop != nullptr && monitorenter_oop == synced_obj,
274 "should be freeze case due to preempt on monitorenter contention");
275 assert(!ObjectSynchronizer::current_thread_holds_lock(thread, Handle(thread, synced_obj)), "should not be owner");
276 }
277 return 0;
278 }
279 #endif
280
281 inline bool ContinuationHelper::StubFrame::is_instance(const frame& f) {
282 return !f.is_interpreted_frame() && is_stub(f.cb());
283 }
284
285 #endif // SHARE_VM_RUNTIME_CONTINUATIONHELPER_INLINE_HPP
|