Mercurial > hg > truffle
annotate src/cpu/x86/vm/templateInterpreter_x86_32.cpp @ 4582:b24386206122
Made all vm builds go into subdirectories, even product builds to simplify building the various types of VMs (server, client and graal).
Made HotSpot build jobs use the number of CPUs on the host machine.
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Mon, 13 Feb 2012 23:13:37 +0100 |
parents | b20d64f83668 |
children | dca455dea3a7 069ab3f976d3 |
rev | line source |
---|---|
0 | 1 /* |
2118
dd031b2226de
4930919: race condition in MDO creation at back branch locations
iveresov
parents:
1972
diff
changeset
|
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 "asm/assembler.hpp" | |
27 #include "interpreter/bytecodeHistogram.hpp" | |
28 #include "interpreter/interpreter.hpp" | |
29 #include "interpreter/interpreterGenerator.hpp" | |
30 #include "interpreter/interpreterRuntime.hpp" | |
31 #include "interpreter/templateTable.hpp" | |
32 #include "oops/arrayOop.hpp" | |
33 #include "oops/methodDataOop.hpp" | |
34 #include "oops/methodOop.hpp" | |
35 #include "oops/oop.inline.hpp" | |
36 #include "prims/jvmtiExport.hpp" | |
37 #include "prims/jvmtiThreadState.hpp" | |
38 #include "runtime/arguments.hpp" | |
39 #include "runtime/deoptimization.hpp" | |
40 #include "runtime/frame.inline.hpp" | |
41 #include "runtime/sharedRuntime.hpp" | |
42 #include "runtime/stubRoutines.hpp" | |
43 #include "runtime/synchronizer.hpp" | |
44 #include "runtime/timer.hpp" | |
45 #include "runtime/vframeArray.hpp" | |
46 #include "utilities/debug.hpp" | |
0 | 47 |
48 #define __ _masm-> | |
49 | |
50 | |
51 #ifndef CC_INTERP | |
52 const int method_offset = frame::interpreter_frame_method_offset * wordSize; | |
53 const int bci_offset = frame::interpreter_frame_bcx_offset * wordSize; | |
54 const int locals_offset = frame::interpreter_frame_locals_offset * wordSize; | |
55 | |
56 //------------------------------------------------------------------------------------------------------------------------ | |
57 | |
58 address TemplateInterpreterGenerator::generate_StackOverflowError_handler() { | |
59 address entry = __ pc(); | |
60 | |
61 // Note: There should be a minimal interpreter frame set up when stack | |
62 // overflow occurs since we check explicitly for it now. | |
63 // | |
64 #ifdef ASSERT | |
65 { Label L; | |
304 | 66 __ lea(rax, Address(rbp, |
0 | 67 frame::interpreter_frame_monitor_block_top_offset * wordSize)); |
304 | 68 __ cmpptr(rax, rsp); // rax, = maximal rsp for current rbp, |
0 | 69 // (stack grows negative) |
70 __ jcc(Assembler::aboveEqual, L); // check if frame is complete | |
71 __ stop ("interpreter frame not set up"); | |
72 __ bind(L); | |
73 } | |
74 #endif // ASSERT | |
75 // Restore bcp under the assumption that the current frame is still | |
76 // interpreted | |
77 __ restore_bcp(); | |
78 | |
79 // expression stack must be empty before entering the VM if an exception | |
80 // happened | |
81 __ empty_expression_stack(); | |
82 __ empty_FPU_stack(); | |
83 // throw exception | |
84 __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_StackOverflowError)); | |
85 return entry; | |
86 } | |
87 | |
88 address TemplateInterpreterGenerator::generate_ArrayIndexOutOfBounds_handler(const char* name) { | |
89 address entry = __ pc(); | |
90 // expression stack must be empty before entering the VM if an exception happened | |
91 __ empty_expression_stack(); | |
92 __ empty_FPU_stack(); | |
93 // setup parameters | |
94 // ??? convention: expect aberrant index in register rbx, | |
95 __ lea(rax, ExternalAddress((address)name)); | |
96 __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_ArrayIndexOutOfBoundsException), rax, rbx); | |
97 return entry; | |
98 } | |
99 | |
100 address TemplateInterpreterGenerator::generate_ClassCastException_handler() { | |
101 address entry = __ pc(); | |
102 // object is at TOS | |
304 | 103 __ pop(rax); |
0 | 104 // expression stack must be empty before entering the VM if an exception |
105 // happened | |
106 __ empty_expression_stack(); | |
107 __ empty_FPU_stack(); | |
108 __ call_VM(noreg, | |
109 CAST_FROM_FN_PTR(address, | |
110 InterpreterRuntime::throw_ClassCastException), | |
111 rax); | |
112 return entry; | |
113 } | |
114 | |
115 address TemplateInterpreterGenerator::generate_exception_handler_common(const char* name, const char* message, bool pass_oop) { | |
116 assert(!pass_oop || message == NULL, "either oop or message but not both"); | |
117 address entry = __ pc(); | |
118 if (pass_oop) { | |
119 // object is at TOS | |
304 | 120 __ pop(rbx); |
0 | 121 } |
122 // expression stack must be empty before entering the VM if an exception happened | |
123 __ empty_expression_stack(); | |
124 __ empty_FPU_stack(); | |
125 // setup parameters | |
126 __ lea(rax, ExternalAddress((address)name)); | |
127 if (pass_oop) { | |
128 __ call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::create_klass_exception), rax, rbx); | |
129 } else { | |
130 if (message != NULL) { | |
131 __ lea(rbx, ExternalAddress((address)message)); | |
132 } else { | |
512
db4caa99ef11
6787106: Hotspot 32 bit build fails on platforms having different definitions for intptr_t & int32_t
xlu
parents:
337
diff
changeset
|
133 __ movptr(rbx, NULL_WORD); |
0 | 134 } |
135 __ call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::create_exception), rax, rbx); | |
136 } | |
137 // throw exception | |
138 __ jump(ExternalAddress(Interpreter::throw_exception_entry())); | |
139 return entry; | |
140 } | |
141 | |
142 | |
143 address TemplateInterpreterGenerator::generate_continuation_for(TosState state) { | |
144 address entry = __ pc(); | |
145 // NULL last_sp until next java call | |
512
db4caa99ef11
6787106: Hotspot 32 bit build fails on platforms having different definitions for intptr_t & int32_t
xlu
parents:
337
diff
changeset
|
146 __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); |
0 | 147 __ dispatch_next(state); |
148 return entry; | |
149 } | |
150 | |
151 | |
1059
389049f3f393
6858164: invokedynamic code needs some cleanup (post-6655638)
jrose
parents:
1039
diff
changeset
|
152 address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step) { |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
153 TosState incoming_state = state; |
2245
638119ce7cfd
7009309: JSR 292: compiler/6991596/Test6991596.java crashes on fastdebug JDK7/b122
twisti
parents:
2141
diff
changeset
|
154 address entry = __ pc(); |
0 | 155 |
156 #ifdef COMPILER2 | |
157 // The FPU stack is clean if UseSSE >= 2 but must be cleaned in other cases | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
158 if ((incoming_state == ftos && UseSSE < 1) || (incoming_state == dtos && UseSSE < 2)) { |
0 | 159 for (int i = 1; i < 8; i++) { |
160 __ ffree(i); | |
161 } | |
162 } else if (UseSSE < 2) { | |
163 __ empty_FPU_stack(); | |
164 } | |
165 #endif | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
166 if ((incoming_state == ftos && UseSSE < 1) || (incoming_state == dtos && UseSSE < 2)) { |
0 | 167 __ MacroAssembler::verify_FPU(1, "generate_return_entry_for compiled"); |
168 } else { | |
169 __ MacroAssembler::verify_FPU(0, "generate_return_entry_for compiled"); | |
170 } | |
171 | |
172 // In SSE mode, interpreter returns FP results in xmm0 but they need | |
173 // to end up back on the FPU so it can operate on them. | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
174 if (incoming_state == ftos && UseSSE >= 1) { |
304 | 175 __ subptr(rsp, wordSize); |
0 | 176 __ movflt(Address(rsp, 0), xmm0); |
177 __ fld_s(Address(rsp, 0)); | |
304 | 178 __ addptr(rsp, wordSize); |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
179 } else if (incoming_state == dtos && UseSSE >= 2) { |
304 | 180 __ subptr(rsp, 2*wordSize); |
0 | 181 __ movdbl(Address(rsp, 0), xmm0); |
182 __ fld_d(Address(rsp, 0)); | |
304 | 183 __ addptr(rsp, 2*wordSize); |
0 | 184 } |
185 | |
186 __ MacroAssembler::verify_FPU(state == ftos || state == dtos ? 1 : 0, "generate_return_entry_for in interpreter"); | |
187 | |
188 // Restore stack bottom in case i2c adjusted stack | |
304 | 189 __ movptr(rsp, Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize)); |
0 | 190 // and NULL it as marker that rsp is now tos until next java call |
512
db4caa99ef11
6787106: Hotspot 32 bit build fails on platforms having different definitions for intptr_t & int32_t
xlu
parents:
337
diff
changeset
|
191 __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); |
0 | 192 |
193 __ restore_bcp(); | |
194 __ restore_locals(); | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
195 |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
196 Label L_got_cache, L_giant_index; |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
197 if (EnableInvokeDynamic) { |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
198 __ cmpb(Address(rsi, 0), Bytecodes::_invokedynamic); |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
199 __ jcc(Assembler::equal, L_giant_index); |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
200 } |
1565 | 201 __ get_cache_and_index_at_bcp(rbx, rcx, 1, sizeof(u2)); |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
202 __ bind(L_got_cache); |
0 | 203 __ movl(rbx, Address(rbx, rcx, |
304 | 204 Address::times_ptr, constantPoolCacheOopDesc::base_offset() + |
0 | 205 ConstantPoolCacheEntry::flags_offset())); |
304 | 206 __ andptr(rbx, 0xFF); |
207 __ lea(rsp, Address(rsp, rbx, Interpreter::stackElementScale())); | |
0 | 208 __ dispatch_next(state, step); |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
209 |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
210 // out of the main line of code... |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
211 if (EnableInvokeDynamic) { |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
212 __ bind(L_giant_index); |
1565 | 213 __ get_cache_and_index_at_bcp(rbx, rcx, 1, sizeof(u4)); |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
214 __ jmp(L_got_cache); |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
215 } |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
216 |
0 | 217 return entry; |
218 } | |
219 | |
220 | |
221 address TemplateInterpreterGenerator::generate_deopt_entry_for(TosState state, int step) { | |
222 address entry = __ pc(); | |
223 | |
224 // In SSE mode, FP results are in xmm0 | |
225 if (state == ftos && UseSSE > 0) { | |
304 | 226 __ subptr(rsp, wordSize); |
0 | 227 __ movflt(Address(rsp, 0), xmm0); |
228 __ fld_s(Address(rsp, 0)); | |
304 | 229 __ addptr(rsp, wordSize); |
0 | 230 } else if (state == dtos && UseSSE >= 2) { |
304 | 231 __ subptr(rsp, 2*wordSize); |
0 | 232 __ movdbl(Address(rsp, 0), xmm0); |
233 __ fld_d(Address(rsp, 0)); | |
304 | 234 __ addptr(rsp, 2*wordSize); |
0 | 235 } |
236 | |
237 __ MacroAssembler::verify_FPU(state == ftos || state == dtos ? 1 : 0, "generate_deopt_entry_for in interpreter"); | |
238 | |
239 // The stack is not extended by deopt but we must NULL last_sp as this | |
240 // entry is like a "return". | |
512
db4caa99ef11
6787106: Hotspot 32 bit build fails on platforms having different definitions for intptr_t & int32_t
xlu
parents:
337
diff
changeset
|
241 __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); |
0 | 242 __ restore_bcp(); |
243 __ restore_locals(); | |
244 // handle exceptions | |
245 { Label L; | |
246 const Register thread = rcx; | |
247 __ get_thread(thread); | |
304 | 248 __ cmpptr(Address(thread, Thread::pending_exception_offset()), (int32_t)NULL_WORD); |
0 | 249 __ jcc(Assembler::zero, L); |
250 __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_pending_exception)); | |
251 __ should_not_reach_here(); | |
252 __ bind(L); | |
253 } | |
254 __ dispatch_next(state, step); | |
255 return entry; | |
256 } | |
257 | |
258 | |
259 int AbstractInterpreter::BasicType_as_index(BasicType type) { | |
260 int i = 0; | |
261 switch (type) { | |
262 case T_BOOLEAN: i = 0; break; | |
263 case T_CHAR : i = 1; break; | |
264 case T_BYTE : i = 2; break; | |
265 case T_SHORT : i = 3; break; | |
266 case T_INT : // fall through | |
267 case T_LONG : // fall through | |
268 case T_VOID : i = 4; break; | |
269 case T_FLOAT : i = 5; break; // have to treat float and double separately for SSE | |
270 case T_DOUBLE : i = 6; break; | |
271 case T_OBJECT : // fall through | |
272 case T_ARRAY : i = 7; break; | |
273 default : ShouldNotReachHere(); | |
274 } | |
275 assert(0 <= i && i < AbstractInterpreter::number_of_result_handlers, "index out of bounds"); | |
276 return i; | |
277 } | |
278 | |
279 | |
280 address TemplateInterpreterGenerator::generate_result_handler_for(BasicType type) { | |
281 address entry = __ pc(); | |
282 switch (type) { | |
283 case T_BOOLEAN: __ c2bool(rax); break; | |
304 | 284 case T_CHAR : __ andptr(rax, 0xFFFF); break; |
0 | 285 case T_BYTE : __ sign_extend_byte (rax); break; |
286 case T_SHORT : __ sign_extend_short(rax); break; | |
287 case T_INT : /* nothing to do */ break; | |
288 case T_DOUBLE : | |
289 case T_FLOAT : | |
290 { const Register t = InterpreterRuntime::SignatureHandlerGenerator::temp(); | |
304 | 291 __ pop(t); // remove return address first |
0 | 292 // Must return a result for interpreter or compiler. In SSE |
293 // mode, results are returned in xmm0 and the FPU stack must | |
294 // be empty. | |
295 if (type == T_FLOAT && UseSSE >= 1) { | |
296 // Load ST0 | |
297 __ fld_d(Address(rsp, 0)); | |
298 // Store as float and empty fpu stack | |
299 __ fstp_s(Address(rsp, 0)); | |
300 // and reload | |
301 __ movflt(xmm0, Address(rsp, 0)); | |
302 } else if (type == T_DOUBLE && UseSSE >= 2 ) { | |
303 __ movdbl(xmm0, Address(rsp, 0)); | |
304 } else { | |
305 // restore ST0 | |
306 __ fld_d(Address(rsp, 0)); | |
307 } | |
308 // and pop the temp | |
304 | 309 __ addptr(rsp, 2 * wordSize); |
310 __ push(t); // restore return address | |
0 | 311 } |
312 break; | |
313 case T_OBJECT : | |
314 // retrieve result from frame | |
304 | 315 __ movptr(rax, Address(rbp, frame::interpreter_frame_oop_temp_offset*wordSize)); |
0 | 316 // and verify it |
317 __ verify_oop(rax); | |
318 break; | |
319 default : ShouldNotReachHere(); | |
320 } | |
321 __ ret(0); // return from result handler | |
322 return entry; | |
323 } | |
324 | |
325 address TemplateInterpreterGenerator::generate_safept_entry_for(TosState state, address runtime_entry) { | |
326 address entry = __ pc(); | |
327 __ push(state); | |
328 __ call_VM(noreg, runtime_entry); | |
329 __ dispatch_via(vtos, Interpreter::_normal_table.table_for(vtos)); | |
330 return entry; | |
331 } | |
332 | |
333 | |
334 // Helpers for commoning out cases in the various type of method entries. | |
335 // | |
336 | |
337 // increment invocation count & check for overflow | |
338 // | |
339 // Note: checking for negative value instead of overflow | |
340 // so we have a 'sticky' overflow test | |
341 // | |
342 // rbx,: method | |
343 // rcx: invocation counter | |
344 // | |
345 void InterpreterGenerator::generate_counter_incr(Label* overflow, Label* profile_method, Label* profile_method_continue) { | |
1783 | 346 const Address invocation_counter(rbx, in_bytes(methodOopDesc::invocation_counter_offset()) + |
347 in_bytes(InvocationCounter::counter_offset())); | |
348 // Note: In tiered we increment either counters in methodOop or in MDO depending if we're profiling or not. | |
349 if (TieredCompilation) { | |
350 int increment = InvocationCounter::count_increment; | |
351 int mask = ((1 << Tier0InvokeNotifyFreqLog) - 1) << InvocationCounter::count_shift; | |
352 Label no_mdo, done; | |
353 if (ProfileInterpreter) { | |
354 // Are we profiling? | |
355 __ movptr(rax, Address(rbx, methodOopDesc::method_data_offset())); | |
356 __ testptr(rax, rax); | |
357 __ jccb(Assembler::zero, no_mdo); | |
358 // Increment counter in the MDO | |
359 const Address mdo_invocation_counter(rax, in_bytes(methodDataOopDesc::invocation_counter_offset()) + | |
360 in_bytes(InvocationCounter::counter_offset())); | |
361 __ increment_mask_and_jump(mdo_invocation_counter, increment, mask, rcx, false, Assembler::zero, overflow); | |
362 __ jmpb(done); | |
363 } | |
364 __ bind(no_mdo); | |
365 // Increment counter in methodOop (we don't need to load it, it's in rcx). | |
366 __ increment_mask_and_jump(invocation_counter, increment, mask, rcx, true, Assembler::zero, overflow); | |
367 __ bind(done); | |
368 } else { | |
369 const Address backedge_counter (rbx, methodOopDesc::backedge_counter_offset() + | |
370 InvocationCounter::counter_offset()); | |
0 | 371 |
1783 | 372 if (ProfileInterpreter) { // %%% Merge this into methodDataOop |
373 __ incrementl(Address(rbx,methodOopDesc::interpreter_invocation_counter_offset())); | |
374 } | |
375 // Update standard invocation counters | |
376 __ movl(rax, backedge_counter); // load backedge counter | |
377 | |
378 __ incrementl(rcx, InvocationCounter::count_increment); | |
379 __ andl(rax, InvocationCounter::count_mask_value); // mask out the status bits | |
380 | |
381 __ movl(invocation_counter, rcx); // save invocation count | |
382 __ addl(rcx, rax); // add both counters | |
0 | 383 |
1783 | 384 // profile_method is non-null only for interpreted method so |
385 // profile_method != NULL == !native_call | |
386 // BytecodeInterpreter only calls for native so code is elided. | |
387 | |
388 if (ProfileInterpreter && profile_method != NULL) { | |
389 // Test to see if we should create a method data oop | |
390 __ cmp32(rcx, | |
391 ExternalAddress((address)&InvocationCounter::InterpreterProfileLimit)); | |
392 __ jcc(Assembler::less, *profile_method_continue); | |
393 | |
394 // if no method data exists, go to profile_method | |
395 __ test_method_data_pointer(rax, *profile_method); | |
396 } | |
397 | |
0 | 398 __ cmp32(rcx, |
1783 | 399 ExternalAddress((address)&InvocationCounter::InterpreterInvocationLimit)); |
400 __ jcc(Assembler::aboveEqual, *overflow); | |
0 | 401 } |
402 } | |
403 | |
404 void InterpreterGenerator::generate_counter_overflow(Label* do_continue) { | |
405 | |
406 // Asm interpreter on entry | |
407 // rdi - locals | |
408 // rsi - bcp | |
409 // rbx, - method | |
410 // rdx - cpool | |
411 // rbp, - interpreter frame | |
412 | |
413 // C++ interpreter on entry | |
414 // rsi - new interpreter state pointer | |
415 // rbp - interpreter frame pointer | |
416 // rbx - method | |
417 | |
418 // On return (i.e. jump to entry_point) [ back to invocation of interpreter ] | |
419 // rbx, - method | |
420 // rcx - rcvr (assuming there is one) | |
421 // top of stack return address of interpreter caller | |
422 // rsp - sender_sp | |
423 | |
424 // C++ interpreter only | |
425 // rsi - previous interpreter state pointer | |
426 | |
427 const Address size_of_parameters(rbx, methodOopDesc::size_of_parameters_offset()); | |
428 | |
429 // InterpreterRuntime::frequency_counter_overflow takes one argument | |
430 // indicating if the counter overflow occurs at a backwards branch (non-NULL bcp). | |
431 // The call returns the address of the verified entry point for the method or NULL | |
432 // if the compilation did not complete (either went background or bailed out). | |
533
dc3ad84615cf
6795913: A few remaining wrong casts need to be fixed for building hotspot successfully on Mac OS.
xlu
parents:
512
diff
changeset
|
433 __ movptr(rax, (intptr_t)false); |
0 | 434 __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::frequency_counter_overflow), rax); |
435 | |
304 | 436 __ movptr(rbx, Address(rbp, method_offset)); // restore methodOop |
0 | 437 |
438 // Preserve invariant that rsi/rdi contain bcp/locals of sender frame | |
439 // and jump to the interpreted entry. | |
440 __ jmp(*do_continue, relocInfo::none); | |
441 | |
442 } | |
443 | |
444 void InterpreterGenerator::generate_stack_overflow_check(void) { | |
445 // see if we've got enough room on the stack for locals plus overhead. | |
446 // the expression stack grows down incrementally, so the normal guard | |
447 // page mechanism will work for that. | |
448 // | |
449 // Registers live on entry: | |
450 // | |
451 // Asm interpreter | |
452 // rdx: number of additional locals this frame needs (what we must check) | |
453 // rbx,: methodOop | |
454 | |
455 // destroyed on exit | |
456 // rax, | |
457 | |
458 // NOTE: since the additional locals are also always pushed (wasn't obvious in | |
459 // generate_method_entry) so the guard should work for them too. | |
460 // | |
461 | |
462 // monitor entry size: see picture of stack set (generate_method_entry) and frame_x86.hpp | |
463 const int entry_size = frame::interpreter_frame_monitor_size() * wordSize; | |
464 | |
465 // total overhead size: entry_size + (saved rbp, thru expr stack bottom). | |
466 // be sure to change this if you add/subtract anything to/from the overhead area | |
467 const int overhead_size = -(frame::interpreter_frame_initial_sp_offset*wordSize) + entry_size; | |
468 | |
469 const int page_size = os::vm_page_size(); | |
470 | |
471 Label after_frame_check; | |
472 | |
473 // see if the frame is greater than one page in size. If so, | |
474 // then we need to verify there is enough stack space remaining | |
475 // for the additional locals. | |
1506 | 476 __ cmpl(rdx, (page_size - overhead_size)/Interpreter::stackElementSize); |
0 | 477 __ jcc(Assembler::belowEqual, after_frame_check); |
478 | |
479 // compute rsp as if this were going to be the last frame on | |
480 // the stack before the red zone | |
481 | |
482 Label after_frame_check_pop; | |
483 | |
304 | 484 __ push(rsi); |
0 | 485 |
486 const Register thread = rsi; | |
487 | |
488 __ get_thread(thread); | |
489 | |
490 const Address stack_base(thread, Thread::stack_base_offset()); | |
491 const Address stack_size(thread, Thread::stack_size_offset()); | |
492 | |
493 // locals + overhead, in bytes | |
304 | 494 __ lea(rax, Address(noreg, rdx, Interpreter::stackElementScale(), overhead_size)); |
0 | 495 |
496 #ifdef ASSERT | |
497 Label stack_base_okay, stack_size_okay; | |
498 // verify that thread stack base is non-zero | |
304 | 499 __ cmpptr(stack_base, (int32_t)NULL_WORD); |
0 | 500 __ jcc(Assembler::notEqual, stack_base_okay); |
501 __ stop("stack base is zero"); | |
502 __ bind(stack_base_okay); | |
503 // verify that thread stack size is non-zero | |
304 | 504 __ cmpptr(stack_size, 0); |
0 | 505 __ jcc(Assembler::notEqual, stack_size_okay); |
506 __ stop("stack size is zero"); | |
507 __ bind(stack_size_okay); | |
508 #endif | |
509 | |
510 // Add stack base to locals and subtract stack size | |
304 | 511 __ addptr(rax, stack_base); |
512 __ subptr(rax, stack_size); | |
0 | 513 |
514 // Use the maximum number of pages we might bang. | |
515 const int max_pages = StackShadowPages > (StackRedPages+StackYellowPages) ? StackShadowPages : | |
516 (StackRedPages+StackYellowPages); | |
304 | 517 __ addptr(rax, max_pages * page_size); |
0 | 518 |
519 // check against the current stack bottom | |
304 | 520 __ cmpptr(rsp, rax); |
0 | 521 __ jcc(Assembler::above, after_frame_check_pop); |
522 | |
304 | 523 __ pop(rsi); // get saved bcp / (c++ prev state ). |
0 | 524 |
304 | 525 __ pop(rax); // get return address |
0 | 526 __ jump(ExternalAddress(Interpreter::throw_StackOverflowError_entry())); |
527 | |
528 // all done with frame size check | |
529 __ bind(after_frame_check_pop); | |
304 | 530 __ pop(rsi); |
0 | 531 |
532 __ bind(after_frame_check); | |
533 } | |
534 | |
535 // Allocate monitor and lock method (asm interpreter) | |
536 // rbx, - methodOop | |
537 // | |
538 void InterpreterGenerator::lock_method(void) { | |
539 // synchronize method | |
540 const Address access_flags (rbx, methodOopDesc::access_flags_offset()); | |
541 const Address monitor_block_top (rbp, frame::interpreter_frame_monitor_block_top_offset * wordSize); | |
542 const int entry_size = frame::interpreter_frame_monitor_size() * wordSize; | |
543 | |
544 #ifdef ASSERT | |
545 { Label L; | |
546 __ movl(rax, access_flags); | |
547 __ testl(rax, JVM_ACC_SYNCHRONIZED); | |
548 __ jcc(Assembler::notZero, L); | |
549 __ stop("method doesn't need synchronization"); | |
550 __ bind(L); | |
551 } | |
552 #endif // ASSERT | |
553 // get synchronization object | |
554 { Label done; | |
555 const int mirror_offset = klassOopDesc::klass_part_offset_in_bytes() + Klass::java_mirror_offset_in_bytes(); | |
556 __ movl(rax, access_flags); | |
557 __ testl(rax, JVM_ACC_STATIC); | |
304 | 558 __ movptr(rax, Address(rdi, Interpreter::local_offset_in_bytes(0))); // get receiver (assume this is frequent case) |
0 | 559 __ jcc(Assembler::zero, done); |
304 | 560 __ movptr(rax, Address(rbx, methodOopDesc::constants_offset())); |
561 __ movptr(rax, Address(rax, constantPoolOopDesc::pool_holder_offset_in_bytes())); | |
562 __ movptr(rax, Address(rax, mirror_offset)); | |
0 | 563 __ bind(done); |
564 } | |
565 // add space for monitor & lock | |
304 | 566 __ subptr(rsp, entry_size); // add space for a monitor entry |
567 __ movptr(monitor_block_top, rsp); // set new monitor block top | |
568 __ movptr(Address(rsp, BasicObjectLock::obj_offset_in_bytes()), rax); // store object | |
569 __ mov(rdx, rsp); // object address | |
0 | 570 __ lock_object(rdx); |
571 } | |
572 | |
573 // | |
574 // Generate a fixed interpreter frame. This is identical setup for interpreted methods | |
575 // and for native methods hence the shared code. | |
576 | |
577 void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) { | |
578 // initialize fixed part of activation frame | |
304 | 579 __ push(rax); // save return address |
0 | 580 __ enter(); // save old & set new rbp, |
581 | |
582 | |
304 | 583 __ push(rsi); // set sender sp |
584 __ push((int32_t)NULL_WORD); // leave last_sp as null | |
585 __ movptr(rsi, Address(rbx,methodOopDesc::const_offset())); // get constMethodOop | |
586 __ lea(rsi, Address(rsi,constMethodOopDesc::codes_offset())); // get codebase | |
587 __ push(rbx); // save methodOop | |
0 | 588 if (ProfileInterpreter) { |
589 Label method_data_continue; | |
304 | 590 __ movptr(rdx, Address(rbx, in_bytes(methodOopDesc::method_data_offset()))); |
591 __ testptr(rdx, rdx); | |
0 | 592 __ jcc(Assembler::zero, method_data_continue); |
304 | 593 __ addptr(rdx, in_bytes(methodDataOopDesc::data_offset())); |
0 | 594 __ bind(method_data_continue); |
304 | 595 __ push(rdx); // set the mdp (method data pointer) |
0 | 596 } else { |
304 | 597 __ push(0); |
0 | 598 } |
599 | |
304 | 600 __ movptr(rdx, Address(rbx, methodOopDesc::constants_offset())); |
601 __ movptr(rdx, Address(rdx, constantPoolOopDesc::cache_offset_in_bytes())); | |
602 __ push(rdx); // set constant pool cache | |
603 __ push(rdi); // set locals pointer | |
0 | 604 if (native_call) { |
304 | 605 __ push(0); // no bcp |
0 | 606 } else { |
304 | 607 __ push(rsi); // set bcp |
0 | 608 } |
304 | 609 __ push(0); // reserve word for pointer to expression stack bottom |
610 __ movptr(Address(rsp, 0), rsp); // set expression stack bottom | |
0 | 611 } |
612 | |
613 // End of helpers | |
614 | |
615 // | |
616 // Various method entries | |
617 //------------------------------------------------------------------------------------------------------------------------ | |
618 // | |
619 // | |
620 | |
621 // Call an accessor method (assuming it is resolved, otherwise drop into vanilla (slow path) entry | |
622 | |
623 address InterpreterGenerator::generate_accessor_entry(void) { | |
624 | |
625 // rbx,: methodOop | |
626 // rcx: receiver (preserve for slow entry into asm interpreter) | |
627 | |
628 // rsi: senderSP must preserved for slow path, set SP to it on fast path | |
629 | |
630 address entry_point = __ pc(); | |
631 Label xreturn_path; | |
632 | |
633 // do fastpath for resolved accessor methods | |
634 if (UseFastAccessorMethods) { | |
635 Label slow_path; | |
636 // If we need a safepoint check, generate full interpreter entry. | |
637 ExternalAddress state(SafepointSynchronize::address_of_state()); | |
638 __ cmp32(ExternalAddress(SafepointSynchronize::address_of_state()), | |
639 SafepointSynchronize::_not_synchronized); | |
640 | |
641 __ jcc(Assembler::notEqual, slow_path); | |
642 // ASM/C++ Interpreter | |
643 // Code: _aload_0, _(i|a)getfield, _(i|a)return or any rewrites thereof; parameter size = 1 | |
644 // Note: We can only use this code if the getfield has been resolved | |
645 // and if we don't have a null-pointer exception => check for | |
646 // these conditions first and use slow path if necessary. | |
647 // rbx,: method | |
648 // rcx: receiver | |
304 | 649 __ movptr(rax, Address(rsp, wordSize)); |
0 | 650 |
651 // check if local 0 != NULL and read field | |
304 | 652 __ testptr(rax, rax); |
0 | 653 __ jcc(Assembler::zero, slow_path); |
654 | |
304 | 655 __ movptr(rdi, Address(rbx, methodOopDesc::constants_offset())); |
0 | 656 // read first instruction word and extract bytecode @ 1 and index @ 2 |
304 | 657 __ movptr(rdx, Address(rbx, methodOopDesc::const_offset())); |
0 | 658 __ movl(rdx, Address(rdx, constMethodOopDesc::codes_offset())); |
659 // Shift codes right to get the index on the right. | |
660 // The bytecode fetched looks like <index><0xb4><0x2a> | |
661 __ shrl(rdx, 2*BitsPerByte); | |
662 __ shll(rdx, exact_log2(in_words(ConstantPoolCacheEntry::size()))); | |
304 | 663 __ movptr(rdi, Address(rdi, constantPoolOopDesc::cache_offset_in_bytes())); |
0 | 664 |
665 // rax,: local 0 | |
666 // rbx,: method | |
667 // rcx: receiver - do not destroy since it is needed for slow path! | |
668 // rcx: scratch | |
669 // rdx: constant pool cache index | |
670 // rdi: constant pool cache | |
671 // rsi: sender sp | |
672 | |
673 // check if getfield has been resolved and read constant pool cache entry | |
674 // check the validity of the cache entry by testing whether _indices field | |
675 // contains Bytecode::_getfield in b1 byte. | |
676 assert(in_words(ConstantPoolCacheEntry::size()) == 4, "adjust shift below"); | |
677 __ movl(rcx, | |
678 Address(rdi, | |
679 rdx, | |
304 | 680 Address::times_ptr, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::indices_offset())); |
0 | 681 __ shrl(rcx, 2*BitsPerByte); |
682 __ andl(rcx, 0xFF); | |
683 __ cmpl(rcx, Bytecodes::_getfield); | |
684 __ jcc(Assembler::notEqual, slow_path); | |
685 | |
686 // Note: constant pool entry is not valid before bytecode is resolved | |
304 | 687 __ movptr(rcx, |
688 Address(rdi, | |
689 rdx, | |
690 Address::times_ptr, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::f2_offset())); | |
0 | 691 __ movl(rdx, |
692 Address(rdi, | |
693 rdx, | |
304 | 694 Address::times_ptr, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::flags_offset())); |
0 | 695 |
696 Label notByte, notShort, notChar; | |
697 const Address field_address (rax, rcx, Address::times_1); | |
698 | |
699 // Need to differentiate between igetfield, agetfield, bgetfield etc. | |
700 // because they are different sizes. | |
701 // Use the type from the constant pool cache | |
702 __ shrl(rdx, ConstantPoolCacheEntry::tosBits); | |
703 // Make sure we don't need to mask rdx for tosBits after the above shift | |
704 ConstantPoolCacheEntry::verify_tosBits(); | |
705 __ cmpl(rdx, btos); | |
706 __ jcc(Assembler::notEqual, notByte); | |
707 __ load_signed_byte(rax, field_address); | |
708 __ jmp(xreturn_path); | |
709 | |
710 __ bind(notByte); | |
711 __ cmpl(rdx, stos); | |
712 __ jcc(Assembler::notEqual, notShort); | |
622
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
533
diff
changeset
|
713 __ load_signed_short(rax, field_address); |
0 | 714 __ jmp(xreturn_path); |
715 | |
716 __ bind(notShort); | |
717 __ cmpl(rdx, ctos); | |
718 __ jcc(Assembler::notEqual, notChar); | |
622
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
533
diff
changeset
|
719 __ load_unsigned_short(rax, field_address); |
0 | 720 __ jmp(xreturn_path); |
721 | |
722 __ bind(notChar); | |
723 #ifdef ASSERT | |
724 Label okay; | |
725 __ cmpl(rdx, atos); | |
726 __ jcc(Assembler::equal, okay); | |
727 __ cmpl(rdx, itos); | |
728 __ jcc(Assembler::equal, okay); | |
729 __ stop("what type is this?"); | |
730 __ bind(okay); | |
731 #endif // ASSERT | |
732 // All the rest are a 32 bit wordsize | |
304 | 733 // This is ok for now. Since fast accessors should be going away |
734 __ movptr(rax, field_address); | |
0 | 735 |
736 __ bind(xreturn_path); | |
737 | |
738 // _ireturn/_areturn | |
304 | 739 __ pop(rdi); // get return address |
740 __ mov(rsp, rsi); // set sp to sender sp | |
0 | 741 __ jmp(rdi); |
742 | |
743 // generate a vanilla interpreter entry as the slow path | |
744 __ bind(slow_path); | |
745 | |
746 (void) generate_normal_entry(false); | |
747 return entry_point; | |
748 } | |
749 return NULL; | |
750 | |
751 } | |
752 | |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
753 // Method entry for java.lang.ref.Reference.get. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
754 address InterpreterGenerator::generate_Reference_get_entry(void) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
755 #ifndef SERIALGC |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
756 // Code: _aload_0, _getfield, _areturn |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
757 // parameter size = 1 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
758 // |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
759 // The code that gets generated by this routine is split into 2 parts: |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
760 // 1. The "intrinsified" code for G1 (or any SATB based GC), |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
761 // 2. The slow path - which is an expansion of the regular method entry. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
762 // |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
763 // Notes:- |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
764 // * In the G1 code we do not check whether we need to block for |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
765 // a safepoint. If G1 is enabled then we must execute the specialized |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
766 // code for Reference.get (except when the Reference object is null) |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
767 // so that we can log the value in the referent field with an SATB |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
768 // update buffer. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
769 // If the code for the getfield template is modified so that the |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
770 // G1 pre-barrier code is executed when the current method is |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
771 // Reference.get() then going through the normal method entry |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
772 // will be fine. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
773 // * The G1 code below can, however, check the receiver object (the instance |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
774 // of java.lang.Reference) and jump to the slow path if null. If the |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
775 // Reference object is null then we obviously cannot fetch the referent |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
776 // and so we don't need to call the G1 pre-barrier. Thus we can use the |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
777 // regular method entry code to generate the NPE. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
778 // |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
779 // This code is based on generate_accessor_enty. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
780 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
781 // rbx,: methodOop |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
782 // rcx: receiver (preserve for slow entry into asm interpreter) |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
783 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
784 // rsi: senderSP must preserved for slow path, set SP to it on fast path |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
785 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
786 address entry = __ pc(); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
787 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
788 const int referent_offset = java_lang_ref_Reference::referent_offset; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
789 guarantee(referent_offset > 0, "referent offset not initialized"); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
790 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
791 if (UseG1GC) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
792 Label slow_path; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
793 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
794 // Check if local 0 != NULL |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
795 // If the receiver is null then it is OK to jump to the slow path. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
796 __ movptr(rax, Address(rsp, wordSize)); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
797 __ testptr(rax, rax); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
798 __ jcc(Assembler::zero, slow_path); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
799 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
800 // rax: local 0 (must be preserved across the G1 barrier call) |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
801 // |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
802 // rbx: method (at this point it's scratch) |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
803 // rcx: receiver (at this point it's scratch) |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
804 // rdx: scratch |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
805 // rdi: scratch |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
806 // |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
807 // rsi: sender sp |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
808 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
809 // Preserve the sender sp in case the pre-barrier |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
810 // calls the runtime |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
811 __ push(rsi); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
812 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
813 // Load the value of the referent field. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
814 const Address field_address(rax, referent_offset); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
815 __ movptr(rax, field_address); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
816 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
817 // Generate the G1 pre-barrier code to log the value of |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
818 // the referent field in an SATB buffer. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
819 __ get_thread(rcx); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
820 __ g1_write_barrier_pre(noreg /* obj */, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
821 rax /* pre_val */, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
822 rcx /* thread */, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
823 rbx /* tmp */, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
824 true /* tosca_save */, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
825 true /* expand_call */); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
826 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
827 // _areturn |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
828 __ pop(rsi); // get sender sp |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
829 __ pop(rdi); // get return address |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
830 __ mov(rsp, rsi); // set sp to sender sp |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
831 __ jmp(rdi); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
832 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
833 __ bind(slow_path); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
834 (void) generate_normal_entry(false); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
835 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
836 return entry; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
837 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
838 #endif // SERIALGC |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
839 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
840 // If G1 is not enabled then attempt to go through the accessor entry point |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
841 // Reference.get is an accessor |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
842 return generate_accessor_entry(); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
843 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
844 |
0 | 845 // |
846 // Interpreter stub for calling a native method. (asm interpreter) | |
847 // This sets up a somewhat different looking stack for calling the native method | |
848 // than the typical interpreter frame setup. | |
849 // | |
850 | |
851 address InterpreterGenerator::generate_native_entry(bool synchronized) { | |
852 // determine code generation flags | |
853 bool inc_counter = UseCompiler || CountCompiledCalls; | |
854 | |
855 // rbx,: methodOop | |
856 // rsi: sender sp | |
857 // rsi: previous interpreter state (C++ interpreter) must preserve | |
858 address entry_point = __ pc(); | |
859 | |
860 | |
861 const Address size_of_parameters(rbx, methodOopDesc::size_of_parameters_offset()); | |
862 const Address invocation_counter(rbx, methodOopDesc::invocation_counter_offset() + InvocationCounter::counter_offset()); | |
863 const Address access_flags (rbx, methodOopDesc::access_flags_offset()); | |
864 | |
865 // get parameter size (always needed) | |
622
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
533
diff
changeset
|
866 __ load_unsigned_short(rcx, size_of_parameters); |
0 | 867 |
868 // native calls don't need the stack size check since they have no expression stack | |
869 // and the arguments are already on the stack and we only add a handful of words | |
870 // to the stack | |
871 | |
872 // rbx,: methodOop | |
873 // rcx: size of parameters | |
874 // rsi: sender sp | |
875 | |
304 | 876 __ pop(rax); // get return address |
0 | 877 // for natives the size of locals is zero |
878 | |
879 // compute beginning of parameters (rdi) | |
304 | 880 __ lea(rdi, Address(rsp, rcx, Interpreter::stackElementScale(), -wordSize)); |
0 | 881 |
882 | |
883 // add 2 zero-initialized slots for native calls | |
884 // NULL result handler | |
304 | 885 __ push((int32_t)NULL_WORD); |
0 | 886 // NULL oop temp (mirror or jni oop result) |
304 | 887 __ push((int32_t)NULL_WORD); |
0 | 888 |
889 if (inc_counter) __ movl(rcx, invocation_counter); // (pre-)fetch invocation count | |
890 // initialize fixed part of activation frame | |
891 | |
892 generate_fixed_frame(true); | |
893 | |
894 // make sure method is native & not abstract | |
895 #ifdef ASSERT | |
896 __ movl(rax, access_flags); | |
897 { | |
898 Label L; | |
899 __ testl(rax, JVM_ACC_NATIVE); | |
900 __ jcc(Assembler::notZero, L); | |
901 __ stop("tried to execute non-native method as native"); | |
902 __ bind(L); | |
903 } | |
904 { Label L; | |
905 __ testl(rax, JVM_ACC_ABSTRACT); | |
906 __ jcc(Assembler::zero, L); | |
907 __ stop("tried to execute abstract method in interpreter"); | |
908 __ bind(L); | |
909 } | |
910 #endif | |
911 | |
912 // Since at this point in the method invocation the exception handler | |
913 // would try to exit the monitor of synchronized methods which hasn't | |
914 // been entered yet, we set the thread local variable | |
915 // _do_not_unlock_if_synchronized to true. The remove_activation will | |
916 // check this flag. | |
917 | |
918 __ get_thread(rax); | |
919 const Address do_not_unlock_if_synchronized(rax, | |
920 in_bytes(JavaThread::do_not_unlock_if_synchronized_offset())); | |
921 __ movbool(do_not_unlock_if_synchronized, true); | |
922 | |
923 // increment invocation count & check for overflow | |
924 Label invocation_counter_overflow; | |
925 if (inc_counter) { | |
926 generate_counter_incr(&invocation_counter_overflow, NULL, NULL); | |
927 } | |
928 | |
929 Label continue_after_compile; | |
930 __ bind(continue_after_compile); | |
931 | |
932 bang_stack_shadow_pages(true); | |
933 | |
934 // reset the _do_not_unlock_if_synchronized flag | |
935 __ get_thread(rax); | |
936 __ movbool(do_not_unlock_if_synchronized, false); | |
937 | |
938 // check for synchronized methods | |
939 // Must happen AFTER invocation_counter check and stack overflow check, | |
940 // so method is not locked if overflows. | |
941 // | |
942 if (synchronized) { | |
943 lock_method(); | |
944 } else { | |
945 // no synchronization necessary | |
946 #ifdef ASSERT | |
947 { Label L; | |
948 __ movl(rax, access_flags); | |
949 __ testl(rax, JVM_ACC_SYNCHRONIZED); | |
950 __ jcc(Assembler::zero, L); | |
951 __ stop("method needs synchronization"); | |
952 __ bind(L); | |
953 } | |
954 #endif | |
955 } | |
956 | |
957 // start execution | |
958 #ifdef ASSERT | |
959 { Label L; | |
960 const Address monitor_block_top (rbp, | |
961 frame::interpreter_frame_monitor_block_top_offset * wordSize); | |
304 | 962 __ movptr(rax, monitor_block_top); |
963 __ cmpptr(rax, rsp); | |
0 | 964 __ jcc(Assembler::equal, L); |
965 __ stop("broken stack frame setup in interpreter"); | |
966 __ bind(L); | |
967 } | |
968 #endif | |
969 | |
970 // jvmti/dtrace support | |
971 __ notify_method_entry(); | |
972 | |
973 // work registers | |
974 const Register method = rbx; | |
975 const Register thread = rdi; | |
976 const Register t = rcx; | |
977 | |
978 // allocate space for parameters | |
979 __ get_method(method); | |
980 __ verify_oop(method); | |
622
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
533
diff
changeset
|
981 __ load_unsigned_short(t, Address(method, methodOopDesc::size_of_parameters_offset())); |
1506 | 982 __ shlptr(t, Interpreter::logStackElementSize); |
304 | 983 __ addptr(t, 2*wordSize); // allocate two more slots for JNIEnv and possible mirror |
984 __ subptr(rsp, t); | |
985 __ andptr(rsp, -(StackAlignmentInBytes)); // gcc needs 16 byte aligned stacks to do XMM intrinsics | |
0 | 986 |
987 // get signature handler | |
988 { Label L; | |
304 | 989 __ movptr(t, Address(method, methodOopDesc::signature_handler_offset())); |
990 __ testptr(t, t); | |
0 | 991 __ jcc(Assembler::notZero, L); |
992 __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::prepare_native_call), method); | |
993 __ get_method(method); | |
304 | 994 __ movptr(t, Address(method, methodOopDesc::signature_handler_offset())); |
0 | 995 __ bind(L); |
996 } | |
997 | |
998 // call signature handler | |
999 assert(InterpreterRuntime::SignatureHandlerGenerator::from() == rdi, "adjust this code"); | |
1000 assert(InterpreterRuntime::SignatureHandlerGenerator::to () == rsp, "adjust this code"); | |
1001 assert(InterpreterRuntime::SignatureHandlerGenerator::temp() == t , "adjust this code"); | |
1002 // The generated handlers do not touch RBX (the method oop). | |
1003 // However, large signatures cannot be cached and are generated | |
1004 // each time here. The slow-path generator will blow RBX | |
1005 // sometime, so we must reload it after the call. | |
1006 __ call(t); | |
1007 __ get_method(method); // slow path call blows RBX on DevStudio 5.0 | |
1008 | |
1009 // result handler is in rax, | |
1010 // set result handler | |
304 | 1011 __ movptr(Address(rbp, frame::interpreter_frame_result_handler_offset*wordSize), rax); |
0 | 1012 |
1013 // pass mirror handle if static call | |
1014 { Label L; | |
1015 const int mirror_offset = klassOopDesc::klass_part_offset_in_bytes() + Klass::java_mirror_offset_in_bytes(); | |
1016 __ movl(t, Address(method, methodOopDesc::access_flags_offset())); | |
1017 __ testl(t, JVM_ACC_STATIC); | |
1018 __ jcc(Assembler::zero, L); | |
1019 // get mirror | |
304 | 1020 __ movptr(t, Address(method, methodOopDesc:: constants_offset())); |
1021 __ movptr(t, Address(t, constantPoolOopDesc::pool_holder_offset_in_bytes())); | |
1022 __ movptr(t, Address(t, mirror_offset)); | |
0 | 1023 // copy mirror into activation frame |
304 | 1024 __ movptr(Address(rbp, frame::interpreter_frame_oop_temp_offset * wordSize), t); |
0 | 1025 // pass handle to mirror |
304 | 1026 __ lea(t, Address(rbp, frame::interpreter_frame_oop_temp_offset * wordSize)); |
1027 __ movptr(Address(rsp, wordSize), t); | |
0 | 1028 __ bind(L); |
1029 } | |
1030 | |
1031 // get native function entry point | |
1032 { Label L; | |
304 | 1033 __ movptr(rax, Address(method, methodOopDesc::native_function_offset())); |
0 | 1034 ExternalAddress unsatisfied(SharedRuntime::native_method_throw_unsatisfied_link_error_entry()); |
304 | 1035 __ cmpptr(rax, unsatisfied.addr()); |
0 | 1036 __ jcc(Assembler::notEqual, L); |
1037 __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::prepare_native_call), method); | |
1038 __ get_method(method); | |
1039 __ verify_oop(method); | |
304 | 1040 __ movptr(rax, Address(method, methodOopDesc::native_function_offset())); |
0 | 1041 __ bind(L); |
1042 } | |
1043 | |
1044 // pass JNIEnv | |
1045 __ get_thread(thread); | |
304 | 1046 __ lea(t, Address(thread, JavaThread::jni_environment_offset())); |
1047 __ movptr(Address(rsp, 0), t); | |
0 | 1048 |
1049 // set_last_Java_frame_before_call | |
1050 // It is enough that the pc() | |
1051 // points into the right code segment. It does not have to be the correct return pc. | |
1052 __ set_last_Java_frame(thread, noreg, rbp, __ pc()); | |
1053 | |
1054 // change thread state | |
1055 #ifdef ASSERT | |
1056 { Label L; | |
1057 __ movl(t, Address(thread, JavaThread::thread_state_offset())); | |
1058 __ cmpl(t, _thread_in_Java); | |
1059 __ jcc(Assembler::equal, L); | |
1060 __ stop("Wrong thread state in native stub"); | |
1061 __ bind(L); | |
1062 } | |
1063 #endif | |
1064 | |
1065 // Change state to native | |
1066 __ movl(Address(thread, JavaThread::thread_state_offset()), _thread_in_native); | |
1067 __ call(rax); | |
1068 | |
1069 // result potentially in rdx:rax or ST0 | |
1070 | |
1071 // Either restore the MXCSR register after returning from the JNI Call | |
1072 // or verify that it wasn't changed. | |
1073 if (VM_Version::supports_sse()) { | |
1074 if (RestoreMXCSROnJNICalls) { | |
1075 __ ldmxcsr(ExternalAddress(StubRoutines::addr_mxcsr_std())); | |
1076 } | |
1077 else if (CheckJNICalls ) { | |
304 | 1078 __ call(RuntimeAddress(StubRoutines::x86::verify_mxcsr_entry())); |
0 | 1079 } |
1080 } | |
1081 | |
1082 // Either restore the x87 floating pointer control word after returning | |
1083 // from the JNI call or verify that it wasn't changed. | |
1084 if (CheckJNICalls) { | |
304 | 1085 __ call(RuntimeAddress(StubRoutines::x86::verify_fpu_cntrl_wrd_entry())); |
0 | 1086 } |
1087 | |
1088 // save potential result in ST(0) & rdx:rax | |
1089 // (if result handler is the T_FLOAT or T_DOUBLE handler, result must be in ST0 - | |
1090 // the check is necessary to avoid potential Intel FPU overflow problems by saving/restoring 'empty' FPU registers) | |
1091 // It is safe to do this push because state is _thread_in_native and return address will be found | |
1092 // via _last_native_pc and not via _last_jave_sp | |
1093 | |
1094 // NOTE: the order of theses push(es) is known to frame::interpreter_frame_result. | |
1095 // If the order changes or anything else is added to the stack the code in | |
1096 // interpreter_frame_result will have to be changed. | |
1097 | |
1098 { Label L; | |
1099 Label push_double; | |
1100 ExternalAddress float_handler(AbstractInterpreter::result_handler(T_FLOAT)); | |
1101 ExternalAddress double_handler(AbstractInterpreter::result_handler(T_DOUBLE)); | |
1102 __ cmpptr(Address(rbp, (frame::interpreter_frame_oop_temp_offset + 1)*wordSize), | |
1103 float_handler.addr()); | |
1104 __ jcc(Assembler::equal, push_double); | |
1105 __ cmpptr(Address(rbp, (frame::interpreter_frame_oop_temp_offset + 1)*wordSize), | |
1106 double_handler.addr()); | |
1107 __ jcc(Assembler::notEqual, L); | |
1108 __ bind(push_double); | |
1109 __ push(dtos); | |
1110 __ bind(L); | |
1111 } | |
1112 __ push(ltos); | |
1113 | |
1114 // change thread state | |
1115 __ get_thread(thread); | |
1116 __ movl(Address(thread, JavaThread::thread_state_offset()), _thread_in_native_trans); | |
1117 if(os::is_MP()) { | |
1118 if (UseMembar) { | |
304 | 1119 // Force this write out before the read below |
1120 __ membar(Assembler::Membar_mask_bits( | |
1121 Assembler::LoadLoad | Assembler::LoadStore | | |
1122 Assembler::StoreLoad | Assembler::StoreStore)); | |
0 | 1123 } else { |
1124 // Write serialization page so VM thread can do a pseudo remote membar. | |
1125 // We use the current thread pointer to calculate a thread specific | |
1126 // offset to write to within the page. This minimizes bus traffic | |
1127 // due to cache line collision. | |
1128 __ serialize_memory(thread, rcx); | |
1129 } | |
1130 } | |
1131 | |
1132 if (AlwaysRestoreFPU) { | |
1133 // Make sure the control word is correct. | |
1134 __ fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std())); | |
1135 } | |
1136 | |
1137 // check for safepoint operation in progress and/or pending suspend requests | |
1138 { Label Continue; | |
1139 | |
1140 __ cmp32(ExternalAddress(SafepointSynchronize::address_of_state()), | |
1141 SafepointSynchronize::_not_synchronized); | |
1142 | |
1143 Label L; | |
1144 __ jcc(Assembler::notEqual, L); | |
1145 __ cmpl(Address(thread, JavaThread::suspend_flags_offset()), 0); | |
1146 __ jcc(Assembler::equal, Continue); | |
1147 __ bind(L); | |
1148 | |
1149 // Don't use call_VM as it will see a possible pending exception and forward it | |
1150 // and never return here preventing us from clearing _last_native_pc down below. | |
1151 // Also can't use call_VM_leaf either as it will check to see if rsi & rdi are | |
1152 // preserved and correspond to the bcp/locals pointers. So we do a runtime call | |
1153 // by hand. | |
1154 // | |
304 | 1155 __ push(thread); |
0 | 1156 __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, |
1157 JavaThread::check_special_condition_for_native_trans))); | |
1158 __ increment(rsp, wordSize); | |
1159 __ get_thread(thread); | |
1160 | |
1161 __ bind(Continue); | |
1162 } | |
1163 | |
1164 // change thread state | |
1165 __ movl(Address(thread, JavaThread::thread_state_offset()), _thread_in_Java); | |
1166 | |
1167 __ reset_last_Java_frame(thread, true, true); | |
1168 | |
1169 // reset handle block | |
304 | 1170 __ movptr(t, Address(thread, JavaThread::active_handles_offset())); |
512
db4caa99ef11
6787106: Hotspot 32 bit build fails on platforms having different definitions for intptr_t & int32_t
xlu
parents:
337
diff
changeset
|
1171 __ movptr(Address(t, JNIHandleBlock::top_offset_in_bytes()), NULL_WORD); |
0 | 1172 |
1173 // If result was an oop then unbox and save it in the frame | |
1174 { Label L; | |
1175 Label no_oop, store_result; | |
1176 ExternalAddress handler(AbstractInterpreter::result_handler(T_OBJECT)); | |
1177 __ cmpptr(Address(rbp, frame::interpreter_frame_result_handler_offset*wordSize), | |
1178 handler.addr()); | |
1179 __ jcc(Assembler::notEqual, no_oop); | |
304 | 1180 __ cmpptr(Address(rsp, 0), (int32_t)NULL_WORD); |
0 | 1181 __ pop(ltos); |
304 | 1182 __ testptr(rax, rax); |
0 | 1183 __ jcc(Assembler::zero, store_result); |
1184 // unbox | |
304 | 1185 __ movptr(rax, Address(rax, 0)); |
0 | 1186 __ bind(store_result); |
304 | 1187 __ movptr(Address(rbp, (frame::interpreter_frame_oop_temp_offset)*wordSize), rax); |
0 | 1188 // keep stack depth as expected by pushing oop which will eventually be discarded |
1189 __ push(ltos); | |
1190 __ bind(no_oop); | |
1191 } | |
1192 | |
1193 { | |
1194 Label no_reguard; | |
1195 __ cmpl(Address(thread, JavaThread::stack_guard_state_offset()), JavaThread::stack_guard_yellow_disabled); | |
1196 __ jcc(Assembler::notEqual, no_reguard); | |
1197 | |
304 | 1198 __ pusha(); |
0 | 1199 __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::reguard_yellow_pages))); |
304 | 1200 __ popa(); |
0 | 1201 |
1202 __ bind(no_reguard); | |
1203 } | |
1204 | |
1205 // restore rsi to have legal interpreter frame, | |
1206 // i.e., bci == 0 <=> rsi == code_base() | |
1207 // Can't call_VM until bcp is within reasonable. | |
1208 __ get_method(method); // method is junk from thread_in_native to now. | |
1209 __ verify_oop(method); | |
304 | 1210 __ movptr(rsi, Address(method,methodOopDesc::const_offset())); // get constMethodOop |
1211 __ lea(rsi, Address(rsi,constMethodOopDesc::codes_offset())); // get codebase | |
0 | 1212 |
1213 // handle exceptions (exception handling will handle unlocking!) | |
1214 { Label L; | |
304 | 1215 __ cmpptr(Address(thread, Thread::pending_exception_offset()), (int32_t)NULL_WORD); |
0 | 1216 __ jcc(Assembler::zero, L); |
1217 // Note: At some point we may want to unify this with the code used in call_VM_base(); | |
1218 // i.e., we should use the StubRoutines::forward_exception code. For now this | |
1219 // doesn't work here because the rsp is not correctly set at this point. | |
1220 __ MacroAssembler::call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_pending_exception)); | |
1221 __ should_not_reach_here(); | |
1222 __ bind(L); | |
1223 } | |
1224 | |
1225 // do unlocking if necessary | |
1226 { Label L; | |
1227 __ movl(t, Address(method, methodOopDesc::access_flags_offset())); | |
1228 __ testl(t, JVM_ACC_SYNCHRONIZED); | |
1229 __ jcc(Assembler::zero, L); | |
1230 // the code below should be shared with interpreter macro assembler implementation | |
1231 { Label unlock; | |
1232 // BasicObjectLock will be first in list, since this is a synchronized method. However, need | |
1233 // to check that the object has not been unlocked by an explicit monitorexit bytecode. | |
1234 const Address monitor(rbp, frame::interpreter_frame_initial_sp_offset * wordSize - (int)sizeof(BasicObjectLock)); | |
1235 | |
304 | 1236 __ lea(rdx, monitor); // address of first monitor |
0 | 1237 |
304 | 1238 __ movptr(t, Address(rdx, BasicObjectLock::obj_offset_in_bytes())); |
1239 __ testptr(t, t); | |
0 | 1240 __ jcc(Assembler::notZero, unlock); |
1241 | |
1242 // Entry already unlocked, need to throw exception | |
1243 __ MacroAssembler::call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_illegal_monitor_state_exception)); | |
1244 __ should_not_reach_here(); | |
1245 | |
1246 __ bind(unlock); | |
1247 __ unlock_object(rdx); | |
1248 } | |
1249 __ bind(L); | |
1250 } | |
1251 | |
1252 // jvmti/dtrace support | |
1253 // Note: This must happen _after_ handling/throwing any exceptions since | |
1254 // the exception handler code notifies the runtime of method exits | |
1255 // too. If this happens before, method entry/exit notifications are | |
1256 // not properly paired (was bug - gri 11/22/99). | |
1257 __ notify_method_exit(vtos, InterpreterMacroAssembler::NotifyJVMTI); | |
1258 | |
1259 // restore potential result in rdx:rax, call result handler to restore potential result in ST0 & handle result | |
1260 __ pop(ltos); | |
304 | 1261 __ movptr(t, Address(rbp, frame::interpreter_frame_result_handler_offset*wordSize)); |
0 | 1262 __ call(t); |
1263 | |
1264 // remove activation | |
304 | 1265 __ movptr(t, Address(rbp, frame::interpreter_frame_sender_sp_offset * wordSize)); // get sender sp |
0 | 1266 __ leave(); // remove frame anchor |
304 | 1267 __ pop(rdi); // get return address |
1268 __ mov(rsp, t); // set sp to sender sp | |
0 | 1269 __ jmp(rdi); |
1270 | |
1271 if (inc_counter) { | |
1272 // Handle overflow of counter and compile method | |
1273 __ bind(invocation_counter_overflow); | |
1274 generate_counter_overflow(&continue_after_compile); | |
1275 } | |
1276 | |
1277 return entry_point; | |
1278 } | |
1279 | |
1280 // | |
1281 // Generic interpreted method entry to (asm) interpreter | |
1282 // | |
1283 address InterpreterGenerator::generate_normal_entry(bool synchronized) { | |
1284 // determine code generation flags | |
1285 bool inc_counter = UseCompiler || CountCompiledCalls; | |
1286 | |
1287 // rbx,: methodOop | |
1288 // rsi: sender sp | |
1289 address entry_point = __ pc(); | |
1290 | |
1291 | |
1292 const Address size_of_parameters(rbx, methodOopDesc::size_of_parameters_offset()); | |
1293 const Address size_of_locals (rbx, methodOopDesc::size_of_locals_offset()); | |
1294 const Address invocation_counter(rbx, methodOopDesc::invocation_counter_offset() + InvocationCounter::counter_offset()); | |
1295 const Address access_flags (rbx, methodOopDesc::access_flags_offset()); | |
1296 | |
1297 // get parameter size (always needed) | |
622
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
533
diff
changeset
|
1298 __ load_unsigned_short(rcx, size_of_parameters); |
0 | 1299 |
1300 // rbx,: methodOop | |
1301 // rcx: size of parameters | |
1302 | |
1303 // rsi: sender_sp (could differ from sp+wordSize if we were called via c2i ) | |
1304 | |
622
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
533
diff
changeset
|
1305 __ load_unsigned_short(rdx, size_of_locals); // get size of locals in words |
0 | 1306 __ subl(rdx, rcx); // rdx = no. of additional locals |
1307 | |
1308 // see if we've got enough room on the stack for locals plus overhead. | |
1309 generate_stack_overflow_check(); | |
1310 | |
1311 // get return address | |
304 | 1312 __ pop(rax); |
0 | 1313 |
1314 // compute beginning of parameters (rdi) | |
304 | 1315 __ lea(rdi, Address(rsp, rcx, Interpreter::stackElementScale(), -wordSize)); |
0 | 1316 |
1317 // rdx - # of additional locals | |
1318 // allocate space for locals | |
1319 // explicitly initialize locals | |
1320 { | |
1321 Label exit, loop; | |
1322 __ testl(rdx, rdx); | |
1323 __ jcc(Assembler::lessEqual, exit); // do nothing if rdx <= 0 | |
1324 __ bind(loop); | |
304 | 1325 __ push((int32_t)NULL_WORD); // initialize local variables |
0 | 1326 __ decrement(rdx); // until everything initialized |
1327 __ jcc(Assembler::greater, loop); | |
1328 __ bind(exit); | |
1329 } | |
1330 | |
1331 if (inc_counter) __ movl(rcx, invocation_counter); // (pre-)fetch invocation count | |
1332 // initialize fixed part of activation frame | |
1333 generate_fixed_frame(false); | |
1334 | |
1335 // make sure method is not native & not abstract | |
1336 #ifdef ASSERT | |
1337 __ movl(rax, access_flags); | |
1338 { | |
1339 Label L; | |
1340 __ testl(rax, JVM_ACC_NATIVE); | |
1341 __ jcc(Assembler::zero, L); | |
1342 __ stop("tried to execute native method as non-native"); | |
1343 __ bind(L); | |
1344 } | |
1345 { Label L; | |
1346 __ testl(rax, JVM_ACC_ABSTRACT); | |
1347 __ jcc(Assembler::zero, L); | |
1348 __ stop("tried to execute abstract method in interpreter"); | |
1349 __ bind(L); | |
1350 } | |
1351 #endif | |
1352 | |
1353 // Since at this point in the method invocation the exception handler | |
1354 // would try to exit the monitor of synchronized methods which hasn't | |
1355 // been entered yet, we set the thread local variable | |
1356 // _do_not_unlock_if_synchronized to true. The remove_activation will | |
1357 // check this flag. | |
1358 | |
1359 __ get_thread(rax); | |
1360 const Address do_not_unlock_if_synchronized(rax, | |
1361 in_bytes(JavaThread::do_not_unlock_if_synchronized_offset())); | |
1362 __ movbool(do_not_unlock_if_synchronized, true); | |
1363 | |
1364 // increment invocation count & check for overflow | |
1365 Label invocation_counter_overflow; | |
1366 Label profile_method; | |
1367 Label profile_method_continue; | |
1368 if (inc_counter) { | |
1369 generate_counter_incr(&invocation_counter_overflow, &profile_method, &profile_method_continue); | |
1370 if (ProfileInterpreter) { | |
1371 __ bind(profile_method_continue); | |
1372 } | |
1373 } | |
1374 Label continue_after_compile; | |
1375 __ bind(continue_after_compile); | |
1376 | |
1377 bang_stack_shadow_pages(false); | |
1378 | |
1379 // reset the _do_not_unlock_if_synchronized flag | |
1380 __ get_thread(rax); | |
1381 __ movbool(do_not_unlock_if_synchronized, false); | |
1382 | |
1383 // check for synchronized methods | |
1384 // Must happen AFTER invocation_counter check and stack overflow check, | |
1385 // so method is not locked if overflows. | |
1386 // | |
1387 if (synchronized) { | |
1388 // Allocate monitor and lock method | |
1389 lock_method(); | |
1390 } else { | |
1391 // no synchronization necessary | |
1392 #ifdef ASSERT | |
1393 { Label L; | |
1394 __ movl(rax, access_flags); | |
1395 __ testl(rax, JVM_ACC_SYNCHRONIZED); | |
1396 __ jcc(Assembler::zero, L); | |
1397 __ stop("method needs synchronization"); | |
1398 __ bind(L); | |
1399 } | |
1400 #endif | |
1401 } | |
1402 | |
1403 // start execution | |
1404 #ifdef ASSERT | |
1405 { Label L; | |
1406 const Address monitor_block_top (rbp, | |
1407 frame::interpreter_frame_monitor_block_top_offset * wordSize); | |
304 | 1408 __ movptr(rax, monitor_block_top); |
1409 __ cmpptr(rax, rsp); | |
0 | 1410 __ jcc(Assembler::equal, L); |
1411 __ stop("broken stack frame setup in interpreter"); | |
1412 __ bind(L); | |
1413 } | |
1414 #endif | |
1415 | |
1416 // jvmti support | |
1417 __ notify_method_entry(); | |
1418 | |
1419 __ dispatch_next(vtos); | |
1420 | |
1421 // invocation counter overflow | |
1422 if (inc_counter) { | |
1423 if (ProfileInterpreter) { | |
1424 // We have decided to profile this method in the interpreter | |
1425 __ bind(profile_method); | |
2118
dd031b2226de
4930919: race condition in MDO creation at back branch locations
iveresov
parents:
1972
diff
changeset
|
1426 __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method)); |
dd031b2226de
4930919: race condition in MDO creation at back branch locations
iveresov
parents:
1972
diff
changeset
|
1427 __ set_method_data_pointer_for_bcp(); |
2141
b599a4c6c2df
7012766: assert(false) failed: DEBUG MESSAGE in MacroAssembler::debug32
iveresov
parents:
2118
diff
changeset
|
1428 __ get_method(rbx); |
0 | 1429 __ jmp(profile_method_continue); |
1430 } | |
1431 // Handle overflow of counter and compile method | |
1432 __ bind(invocation_counter_overflow); | |
1433 generate_counter_overflow(&continue_after_compile); | |
1434 } | |
1435 | |
1436 return entry_point; | |
1437 } | |
1438 | |
1439 //------------------------------------------------------------------------------------------------------------------------ | |
1440 // Entry points | |
1441 // | |
1442 // Here we generate the various kind of entries into the interpreter. | |
1443 // The two main entry type are generic bytecode methods and native call method. | |
1444 // These both come in synchronized and non-synchronized versions but the | |
1445 // frame layout they create is very similar. The other method entry | |
1446 // types are really just special purpose entries that are really entry | |
1447 // and interpretation all in one. These are for trivial methods like | |
1448 // accessor, empty, or special math methods. | |
1449 // | |
1450 // When control flow reaches any of the entry types for the interpreter | |
1451 // the following holds -> | |
1452 // | |
1453 // Arguments: | |
1454 // | |
1455 // rbx,: methodOop | |
1456 // rcx: receiver | |
1457 // | |
1458 // | |
1459 // Stack layout immediately at entry | |
1460 // | |
1461 // [ return address ] <--- rsp | |
1462 // [ parameter n ] | |
1463 // ... | |
1464 // [ parameter 1 ] | |
1465 // [ expression stack ] (caller's java expression stack) | |
1466 | |
1467 // Assuming that we don't go to one of the trivial specialized | |
1468 // entries the stack will look like below when we are ready to execute | |
1469 // the first bytecode (or call the native routine). The register usage | |
1470 // will be as the template based interpreter expects (see interpreter_x86.hpp). | |
1471 // | |
1472 // local variables follow incoming parameters immediately; i.e. | |
1473 // the return address is moved to the end of the locals). | |
1474 // | |
1475 // [ monitor entry ] <--- rsp | |
1476 // ... | |
1477 // [ monitor entry ] | |
1478 // [ expr. stack bottom ] | |
1479 // [ saved rsi ] | |
1480 // [ current rdi ] | |
1481 // [ methodOop ] | |
1482 // [ saved rbp, ] <--- rbp, | |
1483 // [ return address ] | |
1484 // [ local variable m ] | |
1485 // ... | |
1486 // [ local variable 1 ] | |
1487 // [ parameter n ] | |
1488 // ... | |
1489 // [ parameter 1 ] <--- rdi | |
1490 | |
1491 address AbstractInterpreterGenerator::generate_method_entry(AbstractInterpreter::MethodKind kind) { | |
1492 // determine code generation flags | |
1493 bool synchronized = false; | |
1494 address entry_point = NULL; | |
1495 | |
1496 switch (kind) { | |
1497 case Interpreter::zerolocals : break; | |
1498 case Interpreter::zerolocals_synchronized: synchronized = true; break; | |
1499 case Interpreter::native : entry_point = ((InterpreterGenerator*)this)->generate_native_entry(false); break; | |
1500 case Interpreter::native_synchronized : entry_point = ((InterpreterGenerator*)this)->generate_native_entry(true); break; | |
1501 case Interpreter::empty : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry(); break; | |
1502 case Interpreter::accessor : entry_point = ((InterpreterGenerator*)this)->generate_accessor_entry(); break; | |
1503 case Interpreter::abstract : entry_point = ((InterpreterGenerator*)this)->generate_abstract_entry(); break; | |
710 | 1504 case Interpreter::method_handle : entry_point = ((InterpreterGenerator*)this)->generate_method_handle_entry(); break; |
0 | 1505 |
1506 case Interpreter::java_lang_math_sin : // fall thru | |
1507 case Interpreter::java_lang_math_cos : // fall thru | |
1508 case Interpreter::java_lang_math_tan : // fall thru | |
1509 case Interpreter::java_lang_math_abs : // fall thru | |
1510 case Interpreter::java_lang_math_log : // fall thru | |
1511 case Interpreter::java_lang_math_log10 : // fall thru | |
1512 case Interpreter::java_lang_math_sqrt : entry_point = ((InterpreterGenerator*)this)->generate_math_entry(kind); break; | |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
1513 case Interpreter::java_lang_ref_reference_get |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2245
diff
changeset
|
1514 : entry_point = ((InterpreterGenerator*)this)->generate_Reference_get_entry(); break; |
0 | 1515 default : ShouldNotReachHere(); break; |
1516 } | |
1517 | |
1518 if (entry_point) return entry_point; | |
1519 | |
1520 return ((InterpreterGenerator*)this)->generate_normal_entry(synchronized); | |
1521 | |
1522 } | |
1523 | |
1174
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1135
diff
changeset
|
1524 // These should never be compiled since the interpreter will prefer |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1135
diff
changeset
|
1525 // the compiled version to the intrinsic version. |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1135
diff
changeset
|
1526 bool AbstractInterpreter::can_be_compiled(methodHandle m) { |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1135
diff
changeset
|
1527 switch (method_kind(m)) { |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1135
diff
changeset
|
1528 case Interpreter::java_lang_math_sin : // fall thru |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1135
diff
changeset
|
1529 case Interpreter::java_lang_math_cos : // fall thru |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1135
diff
changeset
|
1530 case Interpreter::java_lang_math_tan : // fall thru |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1135
diff
changeset
|
1531 case Interpreter::java_lang_math_abs : // fall thru |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1135
diff
changeset
|
1532 case Interpreter::java_lang_math_log : // fall thru |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1135
diff
changeset
|
1533 case Interpreter::java_lang_math_log10 : // fall thru |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1135
diff
changeset
|
1534 case Interpreter::java_lang_math_sqrt : |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1135
diff
changeset
|
1535 return false; |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1135
diff
changeset
|
1536 default: |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1135
diff
changeset
|
1537 return true; |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1135
diff
changeset
|
1538 } |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1135
diff
changeset
|
1539 } |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1135
diff
changeset
|
1540 |
0 | 1541 // How much stack a method activation needs in words. |
1542 int AbstractInterpreter::size_top_interpreter_activation(methodOop method) { | |
1543 | |
1544 const int stub_code = 4; // see generate_call_stub | |
1545 // Save space for one monitor to get into the interpreted method in case | |
1546 // the method is synchronized | |
1547 int monitor_size = method->is_synchronized() ? | |
1548 1*frame::interpreter_frame_monitor_size() : 0; | |
1549 | |
1550 // total overhead size: entry_size + (saved rbp, thru expr stack bottom). | |
1551 // be sure to change this if you add/subtract anything to/from the overhead area | |
1552 const int overhead_size = -frame::interpreter_frame_initial_sp_offset; | |
1553 | |
710 | 1554 const int extra_stack = methodOopDesc::extra_stack_entries(); |
1555 const int method_stack = (method->max_locals() + method->max_stack() + extra_stack) * | |
1506 | 1556 Interpreter::stackElementWords; |
0 | 1557 return overhead_size + method_stack + stub_code; |
1558 } | |
1559 | |
1560 // asm based interpreter deoptimization helpers | |
1561 | |
1562 int AbstractInterpreter::layout_activation(methodOop method, | |
1563 int tempcount, | |
1564 int popframe_extra_args, | |
1565 int moncount, | |
3369
3d2ab563047a
7043461: VM crashes in void LinkResolver::runtime_resolve_virtual_method
never
parents:
3252
diff
changeset
|
1566 int caller_actual_parameters, |
0 | 1567 int callee_param_count, |
1568 int callee_locals, | |
1569 frame* caller, | |
1570 frame* interpreter_frame, | |
1571 bool is_top_frame) { | |
1572 // Note: This calculation must exactly parallel the frame setup | |
1573 // in AbstractInterpreterGenerator::generate_method_entry. | |
1574 // If interpreter_frame!=NULL, set up the method, locals, and monitors. | |
1575 // The frame interpreter_frame, if not NULL, is guaranteed to be the right size, | |
1576 // as determined by a previous call to this method. | |
1577 // It is also guaranteed to be walkable even though it is in a skeletal state | |
1578 // NOTE: return size is in words not bytes | |
1579 | |
1580 // fixed size of an interpreter frame: | |
1506 | 1581 int max_locals = method->max_locals() * Interpreter::stackElementWords; |
0 | 1582 int extra_locals = (method->max_locals() - method->size_of_parameters()) * |
1506 | 1583 Interpreter::stackElementWords; |
0 | 1584 |
1585 int overhead = frame::sender_sp_offset - frame::interpreter_frame_initial_sp_offset; | |
1586 | |
1587 // Our locals were accounted for by the caller (or last_frame_adjust on the transistion) | |
1588 // Since the callee parameters already account for the callee's params we only need to account for | |
1589 // the extra locals. | |
1590 | |
1591 | |
1592 int size = overhead + | |
1506 | 1593 ((callee_locals - callee_param_count)*Interpreter::stackElementWords) + |
0 | 1594 (moncount*frame::interpreter_frame_monitor_size()) + |
1506 | 1595 tempcount*Interpreter::stackElementWords + popframe_extra_args; |
0 | 1596 |
1597 if (interpreter_frame != NULL) { | |
1598 #ifdef ASSERT | |
2416
38fea01eb669
6817525: turn on method handle functionality by default for JSR 292
twisti
parents:
2245
diff
changeset
|
1599 if (!EnableInvokeDynamic) |
1135
e66fd840cb6b
6893081: method handle & invokedynamic code needs additional cleanup (post 6815692, 6858164)
twisti
parents:
1059
diff
changeset
|
1600 // @@@ FIXME: Should we correct interpreter_frame_sender_sp in the calling sequences? |
e66fd840cb6b
6893081: method handle & invokedynamic code needs additional cleanup (post 6815692, 6858164)
twisti
parents:
1059
diff
changeset
|
1601 // Probably, since deoptimization doesn't work yet. |
e66fd840cb6b
6893081: method handle & invokedynamic code needs additional cleanup (post 6815692, 6858164)
twisti
parents:
1059
diff
changeset
|
1602 assert(caller->unextended_sp() == interpreter_frame->interpreter_frame_sender_sp(), "Frame not properly walkable"); |
0 | 1603 assert(caller->sp() == interpreter_frame->sender_sp(), "Frame not properly walkable(2)"); |
1604 #endif | |
1605 | |
1606 interpreter_frame->interpreter_frame_set_method(method); | |
1607 // NOTE the difference in using sender_sp and interpreter_frame_sender_sp | |
1608 // interpreter_frame_sender_sp is the original sp of the caller (the unextended_sp) | |
1609 // and sender_sp is fp+8 | |
1610 intptr_t* locals = interpreter_frame->sender_sp() + max_locals - 1; | |
1611 | |
4042
b20d64f83668
7090904: JSR 292: JRuby junit test crashes in PSScavengeRootsClosure::do_oop
twisti
parents:
3781
diff
changeset
|
1612 #ifdef ASSERT |
b20d64f83668
7090904: JSR 292: JRuby junit test crashes in PSScavengeRootsClosure::do_oop
twisti
parents:
3781
diff
changeset
|
1613 if (caller->is_interpreted_frame()) { |
b20d64f83668
7090904: JSR 292: JRuby junit test crashes in PSScavengeRootsClosure::do_oop
twisti
parents:
3781
diff
changeset
|
1614 assert(locals < caller->fp() + frame::interpreter_frame_initial_sp_offset, "bad placement"); |
b20d64f83668
7090904: JSR 292: JRuby junit test crashes in PSScavengeRootsClosure::do_oop
twisti
parents:
3781
diff
changeset
|
1615 } |
b20d64f83668
7090904: JSR 292: JRuby junit test crashes in PSScavengeRootsClosure::do_oop
twisti
parents:
3781
diff
changeset
|
1616 #endif |
b20d64f83668
7090904: JSR 292: JRuby junit test crashes in PSScavengeRootsClosure::do_oop
twisti
parents:
3781
diff
changeset
|
1617 |
0 | 1618 interpreter_frame->interpreter_frame_set_locals(locals); |
1619 BasicObjectLock* montop = interpreter_frame->interpreter_frame_monitor_begin(); | |
1620 BasicObjectLock* monbot = montop - moncount; | |
1621 interpreter_frame->interpreter_frame_set_monitor_end(monbot); | |
1622 | |
1623 // Set last_sp | |
1624 intptr_t* rsp = (intptr_t*) monbot - | |
1506 | 1625 tempcount*Interpreter::stackElementWords - |
0 | 1626 popframe_extra_args; |
1627 interpreter_frame->interpreter_frame_set_last_sp(rsp); | |
1628 | |
1629 // All frames but the initial (oldest) interpreter frame we fill in have a | |
1630 // value for sender_sp that allows walking the stack but isn't | |
1631 // truly correct. Correct the value here. | |
1632 | |
1633 if (extra_locals != 0 && | |
1634 interpreter_frame->sender_sp() == interpreter_frame->interpreter_frame_sender_sp() ) { | |
1635 interpreter_frame->set_interpreter_frame_sender_sp(caller->sp() + extra_locals); | |
1636 } | |
1637 *interpreter_frame->interpreter_frame_cache_addr() = | |
1638 method->constants()->cache(); | |
1639 } | |
1640 return size; | |
1641 } | |
1642 | |
1643 | |
1644 //------------------------------------------------------------------------------------------------------------------------ | |
1645 // Exceptions | |
1646 | |
1647 void TemplateInterpreterGenerator::generate_throw_exception() { | |
1648 // Entry point in previous activation (i.e., if the caller was interpreted) | |
1649 Interpreter::_rethrow_exception_entry = __ pc(); | |
1295 | 1650 const Register thread = rcx; |
0 | 1651 |
1652 // Restore sp to interpreter_frame_last_sp even though we are going | |
1653 // to empty the expression stack for the exception processing. | |
512
db4caa99ef11
6787106: Hotspot 32 bit build fails on platforms having different definitions for intptr_t & int32_t
xlu
parents:
337
diff
changeset
|
1654 __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); |
0 | 1655 // rax,: exception |
1656 // rdx: return address/pc that threw exception | |
1657 __ restore_bcp(); // rsi points to call/send | |
1658 __ restore_locals(); | |
1659 | |
1660 // Entry point for exceptions thrown within interpreter code | |
1661 Interpreter::_throw_exception_entry = __ pc(); | |
1662 // expression stack is undefined here | |
1663 // rax,: exception | |
1664 // rsi: exception bcp | |
1665 __ verify_oop(rax); | |
1666 | |
1667 // expression stack must be empty before entering the VM in case of an exception | |
1668 __ empty_expression_stack(); | |
1669 __ empty_FPU_stack(); | |
1670 // find exception handler address and preserve exception oop | |
1671 __ call_VM(rdx, CAST_FROM_FN_PTR(address, InterpreterRuntime::exception_handler_for_exception), rax); | |
1672 // rax,: exception handler entry point | |
1673 // rdx: preserved exception oop | |
1674 // rsi: bcp for exception handler | |
1675 __ push_ptr(rdx); // push exception which is now the only value on the stack | |
1676 __ jmp(rax); // jump to exception handler (may be _remove_activation_entry!) | |
1677 | |
1678 // If the exception is not handled in the current frame the frame is removed and | |
1679 // the exception is rethrown (i.e. exception continuation is _rethrow_exception). | |
1680 // | |
1681 // Note: At this point the bci is still the bxi for the instruction which caused | |
1682 // the exception and the expression stack is empty. Thus, for any VM calls | |
1683 // at this point, GC will find a legal oop map (with empty expression stack). | |
1684 | |
1685 // In current activation | |
1686 // tos: exception | |
1687 // rsi: exception bcp | |
1688 | |
1689 // | |
1690 // JVMTI PopFrame support | |
1691 // | |
1692 | |
1693 Interpreter::_remove_activation_preserving_args_entry = __ pc(); | |
1694 __ empty_expression_stack(); | |
1695 __ empty_FPU_stack(); | |
1696 // Set the popframe_processing bit in pending_popframe_condition indicating that we are | |
1697 // currently handling popframe, so that call_VMs that may happen later do not trigger new | |
1698 // popframe handling cycles. | |
1295 | 1699 __ get_thread(thread); |
1700 __ movl(rdx, Address(thread, JavaThread::popframe_condition_offset())); | |
0 | 1701 __ orl(rdx, JavaThread::popframe_processing_bit); |
1295 | 1702 __ movl(Address(thread, JavaThread::popframe_condition_offset()), rdx); |
0 | 1703 |
1704 { | |
1705 // Check to see whether we are returning to a deoptimized frame. | |
1706 // (The PopFrame call ensures that the caller of the popped frame is | |
1707 // either interpreted or compiled and deoptimizes it if compiled.) | |
1708 // In this case, we can't call dispatch_next() after the frame is | |
1709 // popped, but instead must save the incoming arguments and restore | |
1710 // them after deoptimization has occurred. | |
1711 // | |
1712 // Note that we don't compare the return PC against the | |
1713 // deoptimization blob's unpack entry because of the presence of | |
1714 // adapter frames in C2. | |
1715 Label caller_not_deoptimized; | |
304 | 1716 __ movptr(rdx, Address(rbp, frame::return_addr_offset * wordSize)); |
0 | 1717 __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::interpreter_contains), rdx); |
1718 __ testl(rax, rax); | |
1719 __ jcc(Assembler::notZero, caller_not_deoptimized); | |
1720 | |
1721 // Compute size of arguments for saving when returning to deoptimized caller | |
1722 __ get_method(rax); | |
1723 __ verify_oop(rax); | |
622
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
533
diff
changeset
|
1724 __ load_unsigned_short(rax, Address(rax, in_bytes(methodOopDesc::size_of_parameters_offset()))); |
1506 | 1725 __ shlptr(rax, Interpreter::logStackElementSize); |
0 | 1726 __ restore_locals(); |
304 | 1727 __ subptr(rdi, rax); |
1728 __ addptr(rdi, wordSize); | |
0 | 1729 // Save these arguments |
1295 | 1730 __ get_thread(thread); |
1731 __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, Deoptimization::popframe_preserve_args), thread, rax, rdi); | |
0 | 1732 |
1733 __ remove_activation(vtos, rdx, | |
1734 /* throw_monitor_exception */ false, | |
1735 /* install_monitor_exception */ false, | |
1736 /* notify_jvmdi */ false); | |
1737 | |
1738 // Inform deoptimization that it is responsible for restoring these arguments | |
1295 | 1739 __ get_thread(thread); |
1740 __ movl(Address(thread, JavaThread::popframe_condition_offset()), JavaThread::popframe_force_deopt_reexecution_bit); | |
0 | 1741 |
1742 // Continue in deoptimization handler | |
1743 __ jmp(rdx); | |
1744 | |
1745 __ bind(caller_not_deoptimized); | |
1746 } | |
1747 | |
1748 __ remove_activation(vtos, rdx, | |
1749 /* throw_monitor_exception */ false, | |
1750 /* install_monitor_exception */ false, | |
1751 /* notify_jvmdi */ false); | |
1752 | |
1753 // Finish with popframe handling | |
1754 // A previous I2C followed by a deoptimization might have moved the | |
1755 // outgoing arguments further up the stack. PopFrame expects the | |
1756 // mutations to those outgoing arguments to be preserved and other | |
1757 // constraints basically require this frame to look exactly as | |
1758 // though it had previously invoked an interpreted activation with | |
1759 // no space between the top of the expression stack (current | |
1760 // last_sp) and the top of stack. Rather than force deopt to | |
1761 // maintain this kind of invariant all the time we call a small | |
1762 // fixup routine to move the mutated arguments onto the top of our | |
1763 // expression stack if necessary. | |
304 | 1764 __ mov(rax, rsp); |
1765 __ movptr(rbx, Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize)); | |
1295 | 1766 __ get_thread(thread); |
0 | 1767 // PC must point into interpreter here |
1295 | 1768 __ set_last_Java_frame(thread, noreg, rbp, __ pc()); |
1769 __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::popframe_move_outgoing_args), thread, rax, rbx); | |
1770 __ get_thread(thread); | |
1771 __ reset_last_Java_frame(thread, true, true); | |
0 | 1772 // Restore the last_sp and null it out |
304 | 1773 __ movptr(rsp, Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize)); |
512
db4caa99ef11
6787106: Hotspot 32 bit build fails on platforms having different definitions for intptr_t & int32_t
xlu
parents:
337
diff
changeset
|
1774 __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); |
0 | 1775 |
1776 __ restore_bcp(); | |
1777 __ restore_locals(); | |
1778 // The method data pointer was incremented already during | |
1779 // call profiling. We have to restore the mdp for the current bcp. | |
1780 if (ProfileInterpreter) { | |
1781 __ set_method_data_pointer_for_bcp(); | |
1782 } | |
1783 | |
1784 // Clear the popframe condition flag | |
1295 | 1785 __ get_thread(thread); |
1786 __ movl(Address(thread, JavaThread::popframe_condition_offset()), JavaThread::popframe_inactive); | |
0 | 1787 |
1788 __ dispatch_next(vtos); | |
1789 // end of PopFrame support | |
1790 | |
1791 Interpreter::_remove_activation_entry = __ pc(); | |
1792 | |
1793 // preserve exception over this code sequence | |
1794 __ pop_ptr(rax); | |
1295 | 1795 __ get_thread(thread); |
1796 __ movptr(Address(thread, JavaThread::vm_result_offset()), rax); | |
0 | 1797 // remove the activation (without doing throws on illegalMonitorExceptions) |
1798 __ remove_activation(vtos, rdx, false, true, false); | |
1799 // restore exception | |
1295 | 1800 __ get_thread(thread); |
1801 __ movptr(rax, Address(thread, JavaThread::vm_result_offset())); | |
1802 __ movptr(Address(thread, JavaThread::vm_result_offset()), NULL_WORD); | |
0 | 1803 __ verify_oop(rax); |
1804 | |
1805 // Inbetween activations - previous activation type unknown yet | |
1806 // compute continuation point - the continuation point expects | |
1807 // the following registers set up: | |
1808 // | |
1295 | 1809 // rax: exception |
0 | 1810 // rdx: return address/pc that threw exception |
1811 // rsp: expression stack of caller | |
1295 | 1812 // rbp: rbp, of caller |
304 | 1813 __ push(rax); // save exception |
1814 __ push(rdx); // save return address | |
1295 | 1815 __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), thread, rdx); |
304 | 1816 __ mov(rbx, rax); // save exception handler |
1817 __ pop(rdx); // restore return address | |
1818 __ pop(rax); // restore exception | |
0 | 1819 // Note that an "issuing PC" is actually the next PC after the call |
1820 __ jmp(rbx); // jump to exception handler of caller | |
1821 } | |
1822 | |
1823 | |
1824 // | |
1825 // JVMTI ForceEarlyReturn support | |
1826 // | |
1827 address TemplateInterpreterGenerator::generate_earlyret_entry_for(TosState state) { | |
1828 address entry = __ pc(); | |
1295 | 1829 const Register thread = rcx; |
0 | 1830 |
1831 __ restore_bcp(); | |
1832 __ restore_locals(); | |
1833 __ empty_expression_stack(); | |
1834 __ empty_FPU_stack(); | |
1835 __ load_earlyret_value(state); | |
1836 | |
1295 | 1837 __ get_thread(thread); |
1838 __ movptr(rcx, Address(thread, JavaThread::jvmti_thread_state_offset())); | |
0 | 1839 const Address cond_addr(rcx, JvmtiThreadState::earlyret_state_offset()); |
1840 | |
1841 // Clear the earlyret state | |
1842 __ movl(cond_addr, JvmtiThreadState::earlyret_inactive); | |
1843 | |
1844 __ remove_activation(state, rsi, | |
1845 false, /* throw_monitor_exception */ | |
1846 false, /* install_monitor_exception */ | |
1847 true); /* notify_jvmdi */ | |
1848 __ jmp(rsi); | |
1849 return entry; | |
1850 } // end of ForceEarlyReturn support | |
1851 | |
1852 | |
1853 //------------------------------------------------------------------------------------------------------------------------ | |
1854 // Helper for vtos entry point generation | |
1855 | |
1856 void TemplateInterpreterGenerator::set_vtos_entry_points (Template* t, address& bep, address& cep, address& sep, address& aep, address& iep, address& lep, address& fep, address& dep, address& vep) { | |
1857 assert(t->is_valid() && t->tos_in() == vtos, "illegal template"); | |
1858 Label L; | |
1859 fep = __ pc(); __ push(ftos); __ jmp(L); | |
1860 dep = __ pc(); __ push(dtos); __ jmp(L); | |
1861 lep = __ pc(); __ push(ltos); __ jmp(L); | |
1862 aep = __ pc(); __ push(atos); __ jmp(L); | |
1863 bep = cep = sep = // fall through | |
1864 iep = __ pc(); __ push(itos); // fall through | |
1865 vep = __ pc(); __ bind(L); // fall through | |
1866 generate_and_dispatch(t); | |
1867 } | |
1868 | |
1869 //------------------------------------------------------------------------------------------------------------------------ | |
1870 // Generation of individual instructions | |
1871 | |
1872 // helpers for generate_and_dispatch | |
1873 | |
1874 | |
1875 | |
1876 InterpreterGenerator::InterpreterGenerator(StubQueue* code) | |
1877 : TemplateInterpreterGenerator(code) { | |
1878 generate_all(); // down here so it can be "virtual" | |
1879 } | |
1880 | |
1881 //------------------------------------------------------------------------------------------------------------------------ | |
1882 | |
1883 // Non-product code | |
1884 #ifndef PRODUCT | |
1885 address TemplateInterpreterGenerator::generate_trace_code(TosState state) { | |
1886 address entry = __ pc(); | |
1887 | |
1888 // prepare expression stack | |
304 | 1889 __ pop(rcx); // pop return address so expression stack is 'pure' |
0 | 1890 __ push(state); // save tosca |
1891 | |
1892 // pass tosca registers as arguments & call tracer | |
1893 __ call_VM(noreg, CAST_FROM_FN_PTR(address, SharedRuntime::trace_bytecode), rcx, rax, rdx); | |
304 | 1894 __ mov(rcx, rax); // make sure return address is not destroyed by pop(state) |
0 | 1895 __ pop(state); // restore tosca |
1896 | |
1897 // return | |
1898 __ jmp(rcx); | |
1899 | |
1900 return entry; | |
1901 } | |
1902 | |
1903 | |
1904 void TemplateInterpreterGenerator::count_bytecode() { | |
304 | 1905 __ incrementl(ExternalAddress((address) &BytecodeCounter::_counter_value)); |
0 | 1906 } |
1907 | |
1908 | |
1909 void TemplateInterpreterGenerator::histogram_bytecode(Template* t) { | |
304 | 1910 __ incrementl(ExternalAddress((address) &BytecodeHistogram::_counters[t->bytecode()])); |
0 | 1911 } |
1912 | |
1913 | |
1914 void TemplateInterpreterGenerator::histogram_bytecode_pair(Template* t) { | |
1915 __ mov32(ExternalAddress((address) &BytecodePairHistogram::_index), rbx); | |
1916 __ shrl(rbx, BytecodePairHistogram::log2_number_of_codes); | |
1917 __ orl(rbx, ((int)t->bytecode()) << BytecodePairHistogram::log2_number_of_codes); | |
1918 ExternalAddress table((address) BytecodePairHistogram::_counters); | |
1919 Address index(noreg, rbx, Address::times_4); | |
304 | 1920 __ incrementl(ArrayAddress(table, index)); |
0 | 1921 } |
1922 | |
1923 | |
1924 void TemplateInterpreterGenerator::trace_bytecode(Template* t) { | |
1925 // Call a little run-time stub to avoid blow-up for each bytecode. | |
1926 // The run-time runtime saves the right registers, depending on | |
1927 // the tosca in-state for the given template. | |
1928 assert(Interpreter::trace_code(t->tos_in()) != NULL, | |
1929 "entry must have been generated"); | |
1930 __ call(RuntimeAddress(Interpreter::trace_code(t->tos_in()))); | |
1931 } | |
1932 | |
1933 | |
1934 void TemplateInterpreterGenerator::stop_interpreter_at() { | |
1935 Label L; | |
1936 __ cmp32(ExternalAddress((address) &BytecodeCounter::_counter_value), | |
1937 StopInterpreterAt); | |
1938 __ jcc(Assembler::notEqual, L); | |
1939 __ int3(); | |
1940 __ bind(L); | |
1941 } | |
1942 #endif // !PRODUCT | |
1943 #endif // CC_INTERP |