1 | /* |
2 | * Copyright (c) 1997, 2019, 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 CPU_X86_FRAME_X86_INLINE_HPP |
26 | #define CPU_X86_FRAME_X86_INLINE_HPP |
27 | |
28 | #include "code/codeCache.hpp" |
29 | #include "code/vmreg.inline.hpp" |
30 | |
31 | // Inline functions for Intel frames: |
32 | |
33 | // Constructors: |
34 | |
35 | inline frame::frame() { |
36 | _pc = NULL; |
37 | _sp = NULL; |
38 | _unextended_sp = NULL; |
39 | _fp = NULL; |
40 | _cb = NULL; |
41 | _deopt_state = unknown; |
42 | } |
43 | |
44 | inline void frame::init(intptr_t* sp, intptr_t* fp, address pc) { |
45 | _sp = sp; |
46 | _unextended_sp = sp; |
47 | _fp = fp; |
48 | _pc = pc; |
49 | assert(pc != NULL, "no pc?" ); |
50 | _cb = CodeCache::find_blob(pc); |
51 | adjust_unextended_sp(); |
52 | |
53 | address original_pc = CompiledMethod::get_deopt_original_pc(this); |
54 | if (original_pc != NULL) { |
55 | _pc = original_pc; |
56 | _deopt_state = is_deoptimized; |
57 | } else { |
58 | _deopt_state = not_deoptimized; |
59 | } |
60 | } |
61 | |
62 | inline frame::frame(intptr_t* sp, intptr_t* fp, address pc) { |
63 | init(sp, fp, pc); |
64 | } |
65 | |
66 | inline frame::frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address pc) { |
67 | _sp = sp; |
68 | _unextended_sp = unextended_sp; |
69 | _fp = fp; |
70 | _pc = pc; |
71 | assert(pc != NULL, "no pc?" ); |
72 | _cb = CodeCache::find_blob(pc); |
73 | adjust_unextended_sp(); |
74 | |
75 | address original_pc = CompiledMethod::get_deopt_original_pc(this); |
76 | if (original_pc != NULL) { |
77 | _pc = original_pc; |
78 | assert(_cb->as_compiled_method()->insts_contains_inclusive(_pc), |
79 | "original PC must be in the main code section of the the compiled method (or must be immediately following it)" ); |
80 | _deopt_state = is_deoptimized; |
81 | } else { |
82 | if (_cb->is_deoptimization_stub()) { |
83 | _deopt_state = is_deoptimized; |
84 | } else { |
85 | _deopt_state = not_deoptimized; |
86 | } |
87 | } |
88 | } |
89 | |
90 | inline frame::frame(intptr_t* sp, intptr_t* fp) { |
91 | _sp = sp; |
92 | _unextended_sp = sp; |
93 | _fp = fp; |
94 | _pc = (address)(sp[-1]); |
95 | |
96 | // Here's a sticky one. This constructor can be called via AsyncGetCallTrace |
97 | // when last_Java_sp is non-null but the pc fetched is junk. If we are truly |
98 | // unlucky the junk value could be to a zombied method and we'll die on the |
99 | // find_blob call. This is also why we can have no asserts on the validity |
100 | // of the pc we find here. AsyncGetCallTrace -> pd_get_top_frame_for_signal_handler |
101 | // -> pd_last_frame should use a specialized version of pd_last_frame which could |
102 | // call a specialized frame constructor instead of this one. |
103 | // Then we could use the assert below. However this assert is of somewhat dubious |
104 | // value. |
105 | // UPDATE: this constructor is only used by trace_method_handle_stub() now. |
106 | // assert(_pc != NULL, "no pc?"); |
107 | |
108 | _cb = CodeCache::find_blob(_pc); |
109 | adjust_unextended_sp(); |
110 | |
111 | address original_pc = CompiledMethod::get_deopt_original_pc(this); |
112 | if (original_pc != NULL) { |
113 | _pc = original_pc; |
114 | _deopt_state = is_deoptimized; |
115 | } else { |
116 | _deopt_state = not_deoptimized; |
117 | } |
118 | } |
119 | |
120 | // Accessors |
121 | |
122 | inline bool frame::equal(frame other) const { |
123 | bool ret = sp() == other.sp() |
124 | && unextended_sp() == other.unextended_sp() |
125 | && fp() == other.fp() |
126 | && pc() == other.pc(); |
127 | assert(!ret || ret && cb() == other.cb() && _deopt_state == other._deopt_state, "inconsistent construction" ); |
128 | return ret; |
129 | } |
130 | |
131 | // Return unique id for this frame. The id must have a value where we can distinguish |
132 | // identity and younger/older relationship. NULL represents an invalid (incomparable) |
133 | // frame. |
134 | inline intptr_t* frame::id(void) const { return unextended_sp(); } |
135 | |
136 | // Return true if the frame is older (less recent activation) than the frame represented by id |
137 | inline bool frame::is_older(intptr_t* id) const { assert(this->id() != NULL && id != NULL, "NULL frame id" ); |
138 | return this->id() > id ; } |
139 | |
140 | |
141 | |
142 | inline intptr_t* frame::link() const { return (intptr_t*) *(intptr_t **)addr_at(link_offset); } |
143 | |
144 | inline intptr_t* frame::unextended_sp() const { return _unextended_sp; } |
145 | |
146 | // Return address: |
147 | |
148 | inline address* frame::sender_pc_addr() const { return (address*) addr_at( return_addr_offset); } |
149 | inline address frame::sender_pc() const { return *sender_pc_addr(); } |
150 | |
151 | inline intptr_t* frame::sender_sp() const { return addr_at( sender_sp_offset); } |
152 | |
153 | inline intptr_t** frame::interpreter_frame_locals_addr() const { |
154 | return (intptr_t**)addr_at(interpreter_frame_locals_offset); |
155 | } |
156 | |
157 | inline intptr_t* frame::interpreter_frame_last_sp() const { |
158 | return *(intptr_t**)addr_at(interpreter_frame_last_sp_offset); |
159 | } |
160 | |
161 | inline intptr_t* frame::interpreter_frame_bcp_addr() const { |
162 | return (intptr_t*)addr_at(interpreter_frame_bcp_offset); |
163 | } |
164 | |
165 | |
166 | inline intptr_t* frame::interpreter_frame_mdp_addr() const { |
167 | return (intptr_t*)addr_at(interpreter_frame_mdp_offset); |
168 | } |
169 | |
170 | |
171 | |
172 | // Constant pool cache |
173 | |
174 | inline ConstantPoolCache** frame::interpreter_frame_cache_addr() const { |
175 | return (ConstantPoolCache**)addr_at(interpreter_frame_cache_offset); |
176 | } |
177 | |
178 | // Method |
179 | |
180 | inline Method** frame::interpreter_frame_method_addr() const { |
181 | return (Method**)addr_at(interpreter_frame_method_offset); |
182 | } |
183 | |
184 | // Mirror |
185 | |
186 | inline oop* frame::interpreter_frame_mirror_addr() const { |
187 | return (oop*)addr_at(interpreter_frame_mirror_offset); |
188 | } |
189 | |
190 | // top of expression stack |
191 | inline intptr_t* frame::interpreter_frame_tos_address() const { |
192 | intptr_t* last_sp = interpreter_frame_last_sp(); |
193 | if (last_sp == NULL) { |
194 | return sp(); |
195 | } else { |
196 | // sp() may have been extended or shrunk by an adapter. At least |
197 | // check that we don't fall behind the legal region. |
198 | // For top deoptimized frame last_sp == interpreter_frame_monitor_end. |
199 | assert(last_sp <= (intptr_t*) interpreter_frame_monitor_end(), "bad tos" ); |
200 | return last_sp; |
201 | } |
202 | } |
203 | |
204 | inline oop* frame::interpreter_frame_temp_oop_addr() const { |
205 | return (oop *)(fp() + interpreter_frame_oop_temp_offset); |
206 | } |
207 | |
208 | inline int frame::interpreter_frame_monitor_size() { |
209 | return BasicObjectLock::size(); |
210 | } |
211 | |
212 | |
213 | // expression stack |
214 | // (the max_stack arguments are used by the GC; see class FrameClosure) |
215 | |
216 | inline intptr_t* frame::interpreter_frame_expression_stack() const { |
217 | intptr_t* monitor_end = (intptr_t*) interpreter_frame_monitor_end(); |
218 | return monitor_end-1; |
219 | } |
220 | |
221 | // Entry frames |
222 | |
223 | inline JavaCallWrapper** frame::entry_frame_call_wrapper_addr() const { |
224 | return (JavaCallWrapper**)addr_at(entry_frame_call_wrapper_offset); |
225 | } |
226 | |
227 | // Compiled frames |
228 | |
229 | inline oop frame::saved_oop_result(RegisterMap* map) const { |
230 | oop* result_adr = (oop *)map->location(rax->as_VMReg()); |
231 | guarantee(result_adr != NULL, "bad register save location" ); |
232 | |
233 | return (*result_adr); |
234 | } |
235 | |
236 | inline void frame::set_saved_oop_result(RegisterMap* map, oop obj) { |
237 | oop* result_adr = (oop *)map->location(rax->as_VMReg()); |
238 | guarantee(result_adr != NULL, "bad register save location" ); |
239 | |
240 | *result_adr = obj; |
241 | } |
242 | |
243 | #endif // CPU_X86_FRAME_X86_INLINE_HPP |
244 | |