Mercurial > hg > graal-jvmci-8
annotate src/share/vm/runtime/vframeArray.cpp @ 2607:008adfd6d850
Fixed the stateBefore of invokes and monitorenter instructions to include the arguments of the instruction.
This is necessary to ensure correct continuation in the interpreter when the stateBefore is used as a deoptimization point.
author | Thomas Wuerthinger <thomas@wuerthinger.net> |
---|---|
date | Fri, 06 May 2011 17:47:17 +0200 |
parents | d25d4ca69222 |
children | 5ca1332171c8 |
rev | line source |
---|---|
0 | 1 /* |
2142 | 2 * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. |
0 | 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1506
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1506
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1506
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "classfile/vmSymbols.hpp" | |
27 #include "interpreter/interpreter.hpp" | |
28 #include "memory/allocation.inline.hpp" | |
29 #include "memory/resourceArea.hpp" | |
30 #include "memory/universe.inline.hpp" | |
31 #include "oops/methodDataOop.hpp" | |
32 #include "oops/oop.inline.hpp" | |
33 #include "prims/jvmtiThreadState.hpp" | |
34 #include "runtime/handles.inline.hpp" | |
35 #include "runtime/monitorChunk.hpp" | |
36 #include "runtime/sharedRuntime.hpp" | |
37 #include "runtime/vframe.hpp" | |
38 #include "runtime/vframeArray.hpp" | |
39 #include "runtime/vframe_hp.hpp" | |
40 #include "utilities/events.hpp" | |
41 #ifdef COMPILER2 | |
42 #include "opto/runtime.hpp" | |
43 #endif | |
0 | 44 |
45 | |
46 int vframeArrayElement:: bci(void) const { return (_bci == SynchronizationEntryBCI ? 0 : _bci); } | |
47 | |
48 void vframeArrayElement::free_monitors(JavaThread* jt) { | |
49 if (_monitors != NULL) { | |
50 MonitorChunk* chunk = _monitors; | |
51 _monitors = NULL; | |
52 jt->remove_monitor_chunk(chunk); | |
53 delete chunk; | |
54 } | |
55 } | |
56 | |
57 void vframeArrayElement::fill_in(compiledVFrame* vf) { | |
58 | |
59 // Copy the information from the compiled vframe to the | |
60 // interpreter frame we will be creating to replace vf | |
61 | |
62 _method = vf->method(); | |
63 _bci = vf->raw_bci(); | |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
818
diff
changeset
|
64 _reexecute = vf->should_reexecute(); |
0 | 65 |
66 int index; | |
67 | |
68 // Get the monitors off-stack | |
69 | |
70 GrowableArray<MonitorInfo*>* list = vf->monitors(); | |
71 if (list->is_empty()) { | |
72 _monitors = NULL; | |
73 } else { | |
74 | |
75 // Allocate monitor chunk | |
76 _monitors = new MonitorChunk(list->length()); | |
77 vf->thread()->add_monitor_chunk(_monitors); | |
78 | |
79 // Migrate the BasicLocks from the stack to the monitor chunk | |
80 for (index = 0; index < list->length(); index++) { | |
81 MonitorInfo* monitor = list->at(index); | |
818
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
0
diff
changeset
|
82 assert(!monitor->owner_is_scalar_replaced(), "object should be reallocated already"); |
0 | 83 assert(monitor->owner() == NULL || (!monitor->owner()->is_unlocked() && !monitor->owner()->has_bias_pattern()), "object must be null or locked, and unbiased"); |
84 BasicObjectLock* dest = _monitors->at(index); | |
85 dest->set_obj(monitor->owner()); | |
86 monitor->lock()->move_to(monitor->owner(), dest->lock()); | |
87 } | |
88 } | |
89 | |
90 // Convert the vframe locals and expressions to off stack | |
91 // values. Because we will not gc all oops can be converted to | |
92 // intptr_t (i.e. a stack slot) and we are fine. This is | |
93 // good since we are inside a HandleMark and the oops in our | |
94 // collection would go away between packing them here and | |
95 // unpacking them in unpack_on_stack. | |
96 | |
97 // First the locals go off-stack | |
98 | |
99 // FIXME this seems silly it creates a StackValueCollection | |
100 // in order to get the size to then copy them and | |
101 // convert the types to intptr_t size slots. Seems like it | |
102 // could do it in place... Still uses less memory than the | |
103 // old way though | |
104 | |
105 StackValueCollection *locs = vf->locals(); | |
106 _locals = new StackValueCollection(locs->size()); | |
107 for(index = 0; index < locs->size(); index++) { | |
108 StackValue* value = locs->at(index); | |
109 switch(value->type()) { | |
110 case T_OBJECT: | |
818
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
0
diff
changeset
|
111 assert(!value->obj_is_scalar_replaced(), "object should be reallocated already"); |
0 | 112 // preserve object type |
113 _locals->add( new StackValue((intptr_t) (value->get_obj()()), T_OBJECT )); | |
114 break; | |
115 case T_CONFLICT: | |
116 // A dead local. Will be initialized to null/zero. | |
117 _locals->add( new StackValue()); | |
118 break; | |
119 case T_INT: | |
120 _locals->add( new StackValue(value->get_int())); | |
121 break; | |
122 default: | |
123 ShouldNotReachHere(); | |
124 } | |
125 } | |
126 | |
127 // Now the expressions off-stack | |
128 // Same silliness as above | |
129 | |
130 StackValueCollection *exprs = vf->expressions(); | |
131 _expressions = new StackValueCollection(exprs->size()); | |
132 for(index = 0; index < exprs->size(); index++) { | |
133 StackValue* value = exprs->at(index); | |
134 switch(value->type()) { | |
135 case T_OBJECT: | |
818
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
0
diff
changeset
|
136 assert(!value->obj_is_scalar_replaced(), "object should be reallocated already"); |
0 | 137 // preserve object type |
138 _expressions->add( new StackValue((intptr_t) (value->get_obj()()), T_OBJECT )); | |
139 break; | |
140 case T_CONFLICT: | |
141 // A dead stack element. Will be initialized to null/zero. | |
142 // This can occur when the compiler emits a state in which stack | |
143 // elements are known to be dead (because of an imminent exception). | |
144 _expressions->add( new StackValue()); | |
145 break; | |
146 case T_INT: | |
147 _expressions->add( new StackValue(value->get_int())); | |
148 break; | |
149 default: | |
150 ShouldNotReachHere(); | |
151 } | |
152 } | |
153 } | |
154 | |
155 int unpack_counter = 0; | |
156 | |
157 void vframeArrayElement::unpack_on_stack(int callee_parameters, | |
158 int callee_locals, | |
159 frame* caller, | |
160 bool is_top_frame, | |
161 int exec_mode) { | |
162 JavaThread* thread = (JavaThread*) Thread::current(); | |
163 | |
164 // Look at bci and decide on bcp and continuation pc | |
165 address bcp; | |
166 // C++ interpreter doesn't need a pc since it will figure out what to do when it | |
167 // begins execution | |
168 address pc; | |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
818
diff
changeset
|
169 bool use_next_mdp = false; // true if we should use the mdp associated with the next bci |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
818
diff
changeset
|
170 // rather than the one associated with bcp |
0 | 171 if (raw_bci() == SynchronizationEntryBCI) { |
172 // We are deoptimizing while hanging in prologue code for synchronized method | |
173 bcp = method()->bcp_from(0); // first byte code | |
174 pc = Interpreter::deopt_entry(vtos, 0); // step = 0 since we don't skip current bytecode | |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
818
diff
changeset
|
175 } else if (should_reexecute()) { //reexecute this bytecode |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
818
diff
changeset
|
176 assert(is_top_frame, "reexecute allowed only for the top frame"); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
818
diff
changeset
|
177 bcp = method()->bcp_from(bci()); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
818
diff
changeset
|
178 pc = Interpreter::deopt_reexecute_entry(method(), bcp); |
0 | 179 } else { |
180 bcp = method()->bcp_from(bci()); | |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
818
diff
changeset
|
181 pc = Interpreter::deopt_continue_after_entry(method(), bcp, callee_parameters, is_top_frame); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
818
diff
changeset
|
182 use_next_mdp = true; |
0 | 183 } |
184 assert(Bytecodes::is_defined(*bcp), "must be a valid bytecode"); | |
185 | |
186 // Monitorenter and pending exceptions: | |
187 // | |
188 // For Compiler2, there should be no pending exception when deoptimizing at monitorenter | |
189 // because there is no safepoint at the null pointer check (it is either handled explicitly | |
190 // or prior to the monitorenter) and asynchronous exceptions are not made "pending" by the | |
191 // runtime interface for the slow case (see JRT_ENTRY_FOR_MONITORENTER). If an asynchronous | |
192 // exception was processed, the bytecode pointer would have to be extended one bytecode beyond | |
193 // the monitorenter to place it in the proper exception range. | |
194 // | |
195 // For Compiler1, deoptimization can occur while throwing a NullPointerException at monitorenter, | |
196 // in which case bcp should point to the monitorenter since it is within the exception's range. | |
197 | |
198 assert(*bcp != Bytecodes::_monitorenter || is_top_frame, "a _monitorenter must be a top frame"); | |
1814
fd5d4527cdf5
6986270: guarantee(*bcp != Bytecodes::_monitorenter || exec_mode != Deoptimization::Unpack_exception) fails
iveresov
parents:
1603
diff
changeset
|
199 assert(thread->deopt_nmethod() != NULL, "nmethod should be known"); |
fd5d4527cdf5
6986270: guarantee(*bcp != Bytecodes::_monitorenter || exec_mode != Deoptimization::Unpack_exception) fails
iveresov
parents:
1603
diff
changeset
|
200 guarantee(!(thread->deopt_nmethod()->is_compiled_by_c2() && |
fd5d4527cdf5
6986270: guarantee(*bcp != Bytecodes::_monitorenter || exec_mode != Deoptimization::Unpack_exception) fails
iveresov
parents:
1603
diff
changeset
|
201 *bcp == Bytecodes::_monitorenter && |
fd5d4527cdf5
6986270: guarantee(*bcp != Bytecodes::_monitorenter || exec_mode != Deoptimization::Unpack_exception) fails
iveresov
parents:
1603
diff
changeset
|
202 exec_mode == Deoptimization::Unpack_exception), |
fd5d4527cdf5
6986270: guarantee(*bcp != Bytecodes::_monitorenter || exec_mode != Deoptimization::Unpack_exception) fails
iveresov
parents:
1603
diff
changeset
|
203 "shouldn't get exception during monitorenter"); |
0 | 204 |
205 int popframe_preserved_args_size_in_bytes = 0; | |
206 int popframe_preserved_args_size_in_words = 0; | |
207 if (is_top_frame) { | |
1255
e3a4305c6bc3
6925249: assert(last_sp < (intptr_t*) interpreter_frame_monitor_begin(),"bad tos")
kvn
parents:
903
diff
changeset
|
208 JvmtiThreadState *state = thread->jvmti_thread_state(); |
0 | 209 if (JvmtiExport::can_pop_frame() && |
210 (thread->has_pending_popframe() || thread->popframe_forcing_deopt_reexecution())) { | |
211 if (thread->has_pending_popframe()) { | |
212 // Pop top frame after deoptimization | |
213 #ifndef CC_INTERP | |
214 pc = Interpreter::remove_activation_preserving_args_entry(); | |
215 #else | |
216 // Do an uncommon trap type entry. c++ interpreter will know | |
217 // to pop frame and preserve the args | |
218 pc = Interpreter::deopt_entry(vtos, 0); | |
219 use_next_mdp = false; | |
220 #endif | |
221 } else { | |
222 // Reexecute invoke in top frame | |
223 pc = Interpreter::deopt_entry(vtos, 0); | |
224 use_next_mdp = false; | |
225 popframe_preserved_args_size_in_bytes = in_bytes(thread->popframe_preserved_args_size()); | |
226 // Note: the PopFrame-related extension of the expression stack size is done in | |
227 // Deoptimization::fetch_unroll_info_helper | |
228 popframe_preserved_args_size_in_words = in_words(thread->popframe_preserved_args_size_in_words()); | |
229 } | |
230 } else if (JvmtiExport::can_force_early_return() && state != NULL && state->is_earlyret_pending()) { | |
231 // Force early return from top frame after deoptimization | |
232 #ifndef CC_INTERP | |
233 pc = Interpreter::remove_activation_early_entry(state->earlyret_tos()); | |
234 #else | |
235 // TBD: Need to implement ForceEarlyReturn for CC_INTERP (ia64) | |
236 #endif | |
237 } else { | |
238 // Possibly override the previous pc computation of the top (youngest) frame | |
239 switch (exec_mode) { | |
240 case Deoptimization::Unpack_deopt: | |
241 // use what we've got | |
242 break; | |
243 case Deoptimization::Unpack_exception: | |
244 // exception is pending | |
1295 | 245 pc = SharedRuntime::raw_exception_handler_for_return_address(thread, pc); |
0 | 246 // [phh] We're going to end up in some handler or other, so it doesn't |
247 // matter what mdp we point to. See exception_handler_for_exception() | |
248 // in interpreterRuntime.cpp. | |
249 break; | |
250 case Deoptimization::Unpack_uncommon_trap: | |
251 case Deoptimization::Unpack_reexecute: | |
252 // redo last byte code | |
253 pc = Interpreter::deopt_entry(vtos, 0); | |
254 use_next_mdp = false; | |
255 break; | |
256 default: | |
257 ShouldNotReachHere(); | |
258 } | |
259 } | |
260 } | |
261 | |
262 // Setup the interpreter frame | |
263 | |
264 assert(method() != NULL, "method must exist"); | |
265 int temps = expressions()->size(); | |
266 | |
267 int locks = monitors() == NULL ? 0 : monitors()->number_of_monitors(); | |
268 | |
269 Interpreter::layout_activation(method(), | |
270 temps + callee_parameters, | |
271 popframe_preserved_args_size_in_words, | |
272 locks, | |
273 callee_parameters, | |
274 callee_locals, | |
275 caller, | |
276 iframe(), | |
277 is_top_frame); | |
278 | |
279 // Update the pc in the frame object and overwrite the temporary pc | |
280 // we placed in the skeletal frame now that we finally know the | |
281 // exact interpreter address we should use. | |
282 | |
283 _frame.patch_pc(thread, pc); | |
284 | |
285 assert (!method()->is_synchronized() || locks > 0, "synchronized methods must have monitors"); | |
286 | |
287 BasicObjectLock* top = iframe()->interpreter_frame_monitor_begin(); | |
288 for (int index = 0; index < locks; index++) { | |
289 top = iframe()->previous_monitor_in_interpreter_frame(top); | |
290 BasicObjectLock* src = _monitors->at(index); | |
291 top->set_obj(src->obj()); | |
292 src->lock()->move_to(src->obj(), top->lock()); | |
293 } | |
294 if (ProfileInterpreter) { | |
295 iframe()->interpreter_frame_set_mdx(0); // clear out the mdp. | |
296 } | |
297 iframe()->interpreter_frame_set_bcx((intptr_t)bcp); // cannot use bcp because frame is not initialized yet | |
298 if (ProfileInterpreter) { | |
299 methodDataOop mdo = method()->method_data(); | |
300 if (mdo != NULL) { | |
301 int bci = iframe()->interpreter_frame_bci(); | |
302 if (use_next_mdp) ++bci; | |
303 address mdp = mdo->bci_to_dp(bci); | |
304 iframe()->interpreter_frame_set_mdp(mdp); | |
305 } | |
306 } | |
2607
008adfd6d850
Fixed the stateBefore of invokes and monitorenter instructions to include the arguments of the instruction.
Thomas Wuerthinger <thomas@wuerthinger.net>
parents:
2181
diff
changeset
|
307 |
008adfd6d850
Fixed the stateBefore of invokes and monitorenter instructions to include the arguments of the instruction.
Thomas Wuerthinger <thomas@wuerthinger.net>
parents:
2181
diff
changeset
|
308 if (TraceDeoptimization) { |
008adfd6d850
Fixed the stateBefore of invokes and monitorenter instructions to include the arguments of the instruction.
Thomas Wuerthinger <thomas@wuerthinger.net>
parents:
2181
diff
changeset
|
309 tty->print_cr("Expressions size: %d", expressions()->size()); |
008adfd6d850
Fixed the stateBefore of invokes and monitorenter instructions to include the arguments of the instruction.
Thomas Wuerthinger <thomas@wuerthinger.net>
parents:
2181
diff
changeset
|
310 } |
0 | 311 |
312 // Unpack expression stack | |
313 // If this is an intermediate frame (i.e. not top frame) then this | |
314 // only unpacks the part of the expression stack not used by callee | |
315 // as parameters. The callee parameters are unpacked as part of the | |
316 // callee locals. | |
317 int i; | |
318 for(i = 0; i < expressions()->size(); i++) { | |
319 StackValue *value = expressions()->at(i); | |
320 intptr_t* addr = iframe()->interpreter_frame_expression_stack_at(i); | |
321 switch(value->type()) { | |
322 case T_INT: | |
323 *addr = value->get_int(); | |
1936
8d88c9ac9247
Correct deopt handler entry. New flag -XX:+TraceSignals. More detailed deopt printing.
Thomas Wuerthinger <wuerthinger@ssw.jku.at>
parents:
1814
diff
changeset
|
324 #ifndef PRODUCT |
8d88c9ac9247
Correct deopt handler entry. New flag -XX:+TraceSignals. More detailed deopt printing.
Thomas Wuerthinger <wuerthinger@ssw.jku.at>
parents:
1814
diff
changeset
|
325 if (TraceDeoptimization) { |
8d88c9ac9247
Correct deopt handler entry. New flag -XX:+TraceSignals. More detailed deopt printing.
Thomas Wuerthinger <wuerthinger@ssw.jku.at>
parents:
1814
diff
changeset
|
326 tty->print_cr("Reconstructed expression %d (INT): %d", i, (int)(*addr)); |
8d88c9ac9247
Correct deopt handler entry. New flag -XX:+TraceSignals. More detailed deopt printing.
Thomas Wuerthinger <wuerthinger@ssw.jku.at>
parents:
1814
diff
changeset
|
327 } |
8d88c9ac9247
Correct deopt handler entry. New flag -XX:+TraceSignals. More detailed deopt printing.
Thomas Wuerthinger <wuerthinger@ssw.jku.at>
parents:
1814
diff
changeset
|
328 #endif |
0 | 329 break; |
330 case T_OBJECT: | |
331 *addr = value->get_int(T_OBJECT); | |
1936
8d88c9ac9247
Correct deopt handler entry. New flag -XX:+TraceSignals. More detailed deopt printing.
Thomas Wuerthinger <wuerthinger@ssw.jku.at>
parents:
1814
diff
changeset
|
332 #ifndef PRODUCT |
8d88c9ac9247
Correct deopt handler entry. New flag -XX:+TraceSignals. More detailed deopt printing.
Thomas Wuerthinger <wuerthinger@ssw.jku.at>
parents:
1814
diff
changeset
|
333 if (TraceDeoptimization) { |
8d88c9ac9247
Correct deopt handler entry. New flag -XX:+TraceSignals. More detailed deopt printing.
Thomas Wuerthinger <wuerthinger@ssw.jku.at>
parents:
1814
diff
changeset
|
334 tty->print("Reconstructed expression %d (OBJECT): ", i); |
8d88c9ac9247
Correct deopt handler entry. New flag -XX:+TraceSignals. More detailed deopt printing.
Thomas Wuerthinger <wuerthinger@ssw.jku.at>
parents:
1814
diff
changeset
|
335 oop o = (oop)(*addr); |
8d88c9ac9247
Correct deopt handler entry. New flag -XX:+TraceSignals. More detailed deopt printing.
Thomas Wuerthinger <wuerthinger@ssw.jku.at>
parents:
1814
diff
changeset
|
336 if (o == NULL) { |
8d88c9ac9247
Correct deopt handler entry. New flag -XX:+TraceSignals. More detailed deopt printing.
Thomas Wuerthinger <wuerthinger@ssw.jku.at>
parents:
1814
diff
changeset
|
337 tty->print_cr("NULL"); |
8d88c9ac9247
Correct deopt handler entry. New flag -XX:+TraceSignals. More detailed deopt printing.
Thomas Wuerthinger <wuerthinger@ssw.jku.at>
parents:
1814
diff
changeset
|
338 } else { |
8d88c9ac9247
Correct deopt handler entry. New flag -XX:+TraceSignals. More detailed deopt printing.
Thomas Wuerthinger <wuerthinger@ssw.jku.at>
parents:
1814
diff
changeset
|
339 tty->print_cr(err_msg("%s", o->blueprint()->name()->as_C_string())); |
8d88c9ac9247
Correct deopt handler entry. New flag -XX:+TraceSignals. More detailed deopt printing.
Thomas Wuerthinger <wuerthinger@ssw.jku.at>
parents:
1814
diff
changeset
|
340 } |
8d88c9ac9247
Correct deopt handler entry. New flag -XX:+TraceSignals. More detailed deopt printing.
Thomas Wuerthinger <wuerthinger@ssw.jku.at>
parents:
1814
diff
changeset
|
341 } |
8d88c9ac9247
Correct deopt handler entry. New flag -XX:+TraceSignals. More detailed deopt printing.
Thomas Wuerthinger <wuerthinger@ssw.jku.at>
parents:
1814
diff
changeset
|
342 #endif |
0 | 343 break; |
344 case T_CONFLICT: | |
345 // A dead stack slot. Initialize to null in case it is an oop. | |
346 *addr = NULL_WORD; | |
347 break; | |
348 default: | |
349 ShouldNotReachHere(); | |
350 } | |
351 } | |
352 | |
353 | |
354 // Unpack the locals | |
355 for(i = 0; i < locals()->size(); i++) { | |
356 StackValue *value = locals()->at(i); | |
357 intptr_t* addr = iframe()->interpreter_frame_local_at(i); | |
358 switch(value->type()) { | |
359 case T_INT: | |
360 *addr = value->get_int(); | |
1936
8d88c9ac9247
Correct deopt handler entry. New flag -XX:+TraceSignals. More detailed deopt printing.
Thomas Wuerthinger <wuerthinger@ssw.jku.at>
parents:
1814
diff
changeset
|
361 #ifndef PRODUCT |
8d88c9ac9247
Correct deopt handler entry. New flag -XX:+TraceSignals. More detailed deopt printing.
Thomas Wuerthinger <wuerthinger@ssw.jku.at>
parents:
1814
diff
changeset
|
362 if (TraceDeoptimization) { |
8d88c9ac9247
Correct deopt handler entry. New flag -XX:+TraceSignals. More detailed deopt printing.
Thomas Wuerthinger <wuerthinger@ssw.jku.at>
parents:
1814
diff
changeset
|
363 tty->print_cr("Reconstructed local %d (INT): %d", i, (int)(*addr)); |
8d88c9ac9247
Correct deopt handler entry. New flag -XX:+TraceSignals. More detailed deopt printing.
Thomas Wuerthinger <wuerthinger@ssw.jku.at>
parents:
1814
diff
changeset
|
364 } |
8d88c9ac9247
Correct deopt handler entry. New flag -XX:+TraceSignals. More detailed deopt printing.
Thomas Wuerthinger <wuerthinger@ssw.jku.at>
parents:
1814
diff
changeset
|
365 #endif |
0 | 366 break; |
367 case T_OBJECT: | |
368 *addr = value->get_int(T_OBJECT); | |
1936
8d88c9ac9247
Correct deopt handler entry. New flag -XX:+TraceSignals. More detailed deopt printing.
Thomas Wuerthinger <wuerthinger@ssw.jku.at>
parents:
1814
diff
changeset
|
369 #ifndef PRODUCT |
8d88c9ac9247
Correct deopt handler entry. New flag -XX:+TraceSignals. More detailed deopt printing.
Thomas Wuerthinger <wuerthinger@ssw.jku.at>
parents:
1814
diff
changeset
|
370 if (TraceDeoptimization) { |
8d88c9ac9247
Correct deopt handler entry. New flag -XX:+TraceSignals. More detailed deopt printing.
Thomas Wuerthinger <wuerthinger@ssw.jku.at>
parents:
1814
diff
changeset
|
371 tty->print("Reconstructed local %d (OBJECT): ", i); |
8d88c9ac9247
Correct deopt handler entry. New flag -XX:+TraceSignals. More detailed deopt printing.
Thomas Wuerthinger <wuerthinger@ssw.jku.at>
parents:
1814
diff
changeset
|
372 oop o = (oop)(*addr); |
8d88c9ac9247
Correct deopt handler entry. New flag -XX:+TraceSignals. More detailed deopt printing.
Thomas Wuerthinger <wuerthinger@ssw.jku.at>
parents:
1814
diff
changeset
|
373 if (o == NULL) { |
8d88c9ac9247
Correct deopt handler entry. New flag -XX:+TraceSignals. More detailed deopt printing.
Thomas Wuerthinger <wuerthinger@ssw.jku.at>
parents:
1814
diff
changeset
|
374 tty->print_cr("NULL"); |
8d88c9ac9247
Correct deopt handler entry. New flag -XX:+TraceSignals. More detailed deopt printing.
Thomas Wuerthinger <wuerthinger@ssw.jku.at>
parents:
1814
diff
changeset
|
375 } else { |
8d88c9ac9247
Correct deopt handler entry. New flag -XX:+TraceSignals. More detailed deopt printing.
Thomas Wuerthinger <wuerthinger@ssw.jku.at>
parents:
1814
diff
changeset
|
376 tty->print_cr(err_msg("%s", o->blueprint()->name()->as_C_string())); |
8d88c9ac9247
Correct deopt handler entry. New flag -XX:+TraceSignals. More detailed deopt printing.
Thomas Wuerthinger <wuerthinger@ssw.jku.at>
parents:
1814
diff
changeset
|
377 } |
8d88c9ac9247
Correct deopt handler entry. New flag -XX:+TraceSignals. More detailed deopt printing.
Thomas Wuerthinger <wuerthinger@ssw.jku.at>
parents:
1814
diff
changeset
|
378 } |
8d88c9ac9247
Correct deopt handler entry. New flag -XX:+TraceSignals. More detailed deopt printing.
Thomas Wuerthinger <wuerthinger@ssw.jku.at>
parents:
1814
diff
changeset
|
379 #endif |
0 | 380 break; |
381 case T_CONFLICT: | |
382 // A dead location. If it is an oop then we need a NULL to prevent GC from following it | |
383 *addr = NULL_WORD; | |
384 break; | |
385 default: | |
386 ShouldNotReachHere(); | |
387 } | |
388 } | |
389 | |
390 if (is_top_frame && JvmtiExport::can_pop_frame() && thread->popframe_forcing_deopt_reexecution()) { | |
391 // An interpreted frame was popped but it returns to a deoptimized | |
392 // frame. The incoming arguments to the interpreted activation | |
393 // were preserved in thread-local storage by the | |
394 // remove_activation_preserving_args_entry in the interpreter; now | |
395 // we put them back into the just-unpacked interpreter frame. | |
396 // Note that this assumes that the locals arena grows toward lower | |
397 // addresses. | |
398 if (popframe_preserved_args_size_in_words != 0) { | |
399 void* saved_args = thread->popframe_preserved_args(); | |
400 assert(saved_args != NULL, "must have been saved by interpreter"); | |
401 #ifdef ASSERT | |
402 assert(popframe_preserved_args_size_in_words <= | |
1506 | 403 iframe()->interpreter_frame_expression_stack_size()*Interpreter::stackElementWords, |
0 | 404 "expression stack size should have been extended"); |
405 #endif // ASSERT | |
406 int top_element = iframe()->interpreter_frame_expression_stack_size()-1; | |
407 intptr_t* base; | |
408 if (frame::interpreter_frame_expression_stack_direction() < 0) { | |
409 base = iframe()->interpreter_frame_expression_stack_at(top_element); | |
410 } else { | |
411 base = iframe()->interpreter_frame_expression_stack(); | |
412 } | |
1603
d93949c5bdcc
6730276: JDI_REGRESSION tests fail with "Error: count must be non-zero" error on x86
kvn
parents:
1552
diff
changeset
|
413 Copy::conjoint_jbytes(saved_args, |
d93949c5bdcc
6730276: JDI_REGRESSION tests fail with "Error: count must be non-zero" error on x86
kvn
parents:
1552
diff
changeset
|
414 base, |
d93949c5bdcc
6730276: JDI_REGRESSION tests fail with "Error: count must be non-zero" error on x86
kvn
parents:
1552
diff
changeset
|
415 popframe_preserved_args_size_in_bytes); |
0 | 416 thread->popframe_free_preserved_args(); |
417 } | |
418 } | |
419 | |
420 #ifndef PRODUCT | |
421 if (TraceDeoptimization && Verbose) { | |
422 ttyLocker ttyl; | |
423 tty->print_cr("[%d Interpreted Frame]", ++unpack_counter); | |
424 iframe()->print_on(tty); | |
425 RegisterMap map(thread); | |
426 vframe* f = vframe::new_vframe(iframe(), &map, thread); | |
427 f->print(); | |
428 | |
429 tty->print_cr("locals size %d", locals()->size()); | |
430 tty->print_cr("expression size %d", expressions()->size()); | |
431 | |
432 method()->print_value(); | |
433 tty->cr(); | |
434 // method()->print_codes(); | |
435 } else if (TraceDeoptimization) { | |
436 tty->print(" "); | |
437 method()->print_value(); | |
2142 | 438 Bytecodes::Code code = Bytecodes::java_code_at(method(), bcp); |
0 | 439 int bci = method()->bci_from(bcp); |
440 tty->print(" - %s", Bytecodes::name(code)); | |
441 tty->print(" @ bci %d ", bci); | |
442 tty->print_cr("sp = " PTR_FORMAT, iframe()->sp()); | |
443 } | |
444 #endif // PRODUCT | |
445 | |
446 // The expression stack and locals are in the resource area don't leave | |
447 // a dangling pointer in the vframeArray we leave around for debug | |
448 // purposes | |
449 | |
450 _locals = _expressions = NULL; | |
451 | |
452 } | |
453 | |
454 int vframeArrayElement::on_stack_size(int callee_parameters, | |
455 int callee_locals, | |
456 bool is_top_frame, | |
457 int popframe_extra_stack_expression_els) const { | |
458 assert(method()->max_locals() == locals()->size(), "just checking"); | |
459 int locks = monitors() == NULL ? 0 : monitors()->number_of_monitors(); | |
460 int temps = expressions()->size(); | |
461 return Interpreter::size_activation(method(), | |
462 temps + callee_parameters, | |
463 popframe_extra_stack_expression_els, | |
464 locks, | |
465 callee_parameters, | |
466 callee_locals, | |
467 is_top_frame); | |
468 } | |
469 | |
470 | |
471 | |
472 vframeArray* vframeArray::allocate(JavaThread* thread, int frame_size, GrowableArray<compiledVFrame*>* chunk, | |
473 RegisterMap *reg_map, frame sender, frame caller, frame self) { | |
474 | |
475 // Allocate the vframeArray | |
476 vframeArray * result = (vframeArray*) AllocateHeap(sizeof(vframeArray) + // fixed part | |
477 sizeof(vframeArrayElement) * (chunk->length() - 1), // variable part | |
478 "vframeArray::allocate"); | |
479 result->_frames = chunk->length(); | |
480 result->_owner_thread = thread; | |
481 result->_sender = sender; | |
482 result->_caller = caller; | |
483 result->_original = self; | |
484 result->set_unroll_block(NULL); // initialize it | |
485 result->fill_in(thread, frame_size, chunk, reg_map); | |
486 return result; | |
487 } | |
488 | |
489 void vframeArray::fill_in(JavaThread* thread, | |
490 int frame_size, | |
491 GrowableArray<compiledVFrame*>* chunk, | |
492 const RegisterMap *reg_map) { | |
493 // Set owner first, it is used when adding monitor chunks | |
494 | |
495 _frame_size = frame_size; | |
496 for(int i = 0; i < chunk->length(); i++) { | |
497 element(i)->fill_in(chunk->at(i)); | |
498 } | |
499 | |
500 // Copy registers for callee-saved registers | |
501 if (reg_map != NULL) { | |
502 for(int i = 0; i < RegisterMap::reg_count; i++) { | |
503 #ifdef AMD64 | |
504 // The register map has one entry for every int (32-bit value), so | |
505 // 64-bit physical registers have two entries in the map, one for | |
506 // each half. Ignore the high halves of 64-bit registers, just like | |
507 // frame::oopmapreg_to_location does. | |
508 // | |
509 // [phh] FIXME: this is a temporary hack! This code *should* work | |
510 // correctly w/o this hack, possibly by changing RegisterMap::pd_location | |
511 // in frame_amd64.cpp and the values of the phantom high half registers | |
512 // in amd64.ad. | |
513 // if (VMReg::Name(i) < SharedInfo::stack0 && is_even(i)) { | |
514 intptr_t* src = (intptr_t*) reg_map->location(VMRegImpl::as_VMReg(i)); | |
515 _callee_registers[i] = src != NULL ? *src : NULL_WORD; | |
516 // } else { | |
517 // jint* src = (jint*) reg_map->location(VMReg::Name(i)); | |
518 // _callee_registers[i] = src != NULL ? *src : NULL_WORD; | |
519 // } | |
520 #else | |
521 jint* src = (jint*) reg_map->location(VMRegImpl::as_VMReg(i)); | |
522 _callee_registers[i] = src != NULL ? *src : NULL_WORD; | |
523 #endif | |
524 if (src == NULL) { | |
525 set_location_valid(i, false); | |
526 } else { | |
527 set_location_valid(i, true); | |
528 jint* dst = (jint*) register_location(i); | |
529 *dst = *src; | |
530 } | |
531 } | |
532 } | |
533 } | |
534 | |
535 void vframeArray::unpack_to_stack(frame &unpack_frame, int exec_mode) { | |
536 // stack picture | |
537 // unpack_frame | |
538 // [new interpreter frames ] (frames are skeletal but walkable) | |
539 // caller_frame | |
540 // | |
541 // This routine fills in the missing data for the skeletal interpreter frames | |
542 // in the above picture. | |
543 | |
544 // Find the skeletal interpreter frames to unpack into | |
545 RegisterMap map(JavaThread::current(), false); | |
546 // Get the youngest frame we will unpack (last to be unpacked) | |
547 frame me = unpack_frame.sender(&map); | |
548 int index; | |
549 for (index = 0; index < frames(); index++ ) { | |
550 *element(index)->iframe() = me; | |
551 // Get the caller frame (possibly skeletal) | |
552 me = me.sender(&map); | |
553 } | |
554 | |
555 frame caller_frame = me; | |
556 | |
557 // Do the unpacking of interpreter frames; the frame at index 0 represents the top activation, so it has no callee | |
558 | |
559 // Unpack the frames from the oldest (frames() -1) to the youngest (0) | |
560 | |
561 for (index = frames() - 1; index >= 0 ; index--) { | |
562 int callee_parameters = index == 0 ? 0 : element(index-1)->method()->size_of_parameters(); | |
563 int callee_locals = index == 0 ? 0 : element(index-1)->method()->max_locals(); | |
564 element(index)->unpack_on_stack(callee_parameters, | |
565 callee_locals, | |
566 &caller_frame, | |
567 index == 0, | |
568 exec_mode); | |
569 if (index == frames() - 1) { | |
570 Deoptimization::unwind_callee_save_values(element(index)->iframe(), this); | |
571 } | |
572 caller_frame = *element(index)->iframe(); | |
573 } | |
574 | |
575 | |
576 deallocate_monitor_chunks(); | |
577 } | |
578 | |
579 void vframeArray::deallocate_monitor_chunks() { | |
580 JavaThread* jt = JavaThread::current(); | |
581 for (int index = 0; index < frames(); index++ ) { | |
582 element(index)->free_monitors(jt); | |
583 } | |
584 } | |
585 | |
586 #ifndef PRODUCT | |
587 | |
588 bool vframeArray::structural_compare(JavaThread* thread, GrowableArray<compiledVFrame*>* chunk) { | |
589 if (owner_thread() != thread) return false; | |
590 int index = 0; | |
591 #if 0 // FIXME can't do this comparison | |
592 | |
593 // Compare only within vframe array. | |
594 for (deoptimizedVFrame* vf = deoptimizedVFrame::cast(vframe_at(first_index())); vf; vf = vf->deoptimized_sender_or_null()) { | |
595 if (index >= chunk->length() || !vf->structural_compare(chunk->at(index))) return false; | |
596 index++; | |
597 } | |
598 if (index != chunk->length()) return false; | |
599 #endif | |
600 | |
601 return true; | |
602 } | |
603 | |
604 #endif | |
605 | |
606 address vframeArray::register_location(int i) const { | |
607 assert(0 <= i && i < RegisterMap::reg_count, "index out of bounds"); | |
608 return (address) & _callee_registers[i]; | |
609 } | |
610 | |
611 | |
612 #ifndef PRODUCT | |
613 | |
614 // Printing | |
615 | |
616 // Note: we cannot have print_on as const, as we allocate inside the method | |
617 void vframeArray::print_on_2(outputStream* st) { | |
618 st->print_cr(" - sp: " INTPTR_FORMAT, sp()); | |
619 st->print(" - thread: "); | |
620 Thread::current()->print(); | |
621 st->print_cr(" - frame size: %d", frame_size()); | |
622 for (int index = 0; index < frames() ; index++ ) { | |
623 element(index)->print(st); | |
624 } | |
625 } | |
626 | |
627 void vframeArrayElement::print(outputStream* st) { | |
1255
e3a4305c6bc3
6925249: assert(last_sp < (intptr_t*) interpreter_frame_monitor_begin(),"bad tos")
kvn
parents:
903
diff
changeset
|
628 st->print_cr(" - interpreter_frame -> sp: " INTPTR_FORMAT, iframe()->sp()); |
0 | 629 } |
630 | |
631 void vframeArray::print_value_on(outputStream* st) const { | |
632 st->print_cr("vframeArray [%d] ", frames()); | |
633 } | |
634 | |
635 | |
636 #endif |