154 __ dispatch_next(state); |
154 __ dispatch_next(state); |
155 return entry; |
155 return entry; |
156 } |
156 } |
157 |
157 |
158 |
158 |
159 address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step) { |
159 address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step, bool unbox) { |
|
160 TosState incoming_state = state; |
|
161 if (EnableInvokeDynamic) { |
|
162 if (unbox) { |
|
163 incoming_state = atos; |
|
164 } |
|
165 } else { |
|
166 assert(!unbox, "old behavior"); |
|
167 } |
|
168 |
160 Label interpreter_entry; |
169 Label interpreter_entry; |
161 address compiled_entry = __ pc(); |
170 address compiled_entry = __ pc(); |
162 |
171 |
163 #ifdef COMPILER2 |
172 #ifdef COMPILER2 |
164 // The FPU stack is clean if UseSSE >= 2 but must be cleaned in other cases |
173 // The FPU stack is clean if UseSSE >= 2 but must be cleaned in other cases |
165 if ((state == ftos && UseSSE < 1) || (state == dtos && UseSSE < 2)) { |
174 if ((incoming_state == ftos && UseSSE < 1) || (incoming_state == dtos && UseSSE < 2)) { |
166 for (int i = 1; i < 8; i++) { |
175 for (int i = 1; i < 8; i++) { |
167 __ ffree(i); |
176 __ ffree(i); |
168 } |
177 } |
169 } else if (UseSSE < 2) { |
178 } else if (UseSSE < 2) { |
170 __ empty_FPU_stack(); |
179 __ empty_FPU_stack(); |
171 } |
180 } |
172 #endif |
181 #endif |
173 if ((state == ftos && UseSSE < 1) || (state == dtos && UseSSE < 2)) { |
182 if ((incoming_state == ftos && UseSSE < 1) || (incoming_state == dtos && UseSSE < 2)) { |
174 __ MacroAssembler::verify_FPU(1, "generate_return_entry_for compiled"); |
183 __ MacroAssembler::verify_FPU(1, "generate_return_entry_for compiled"); |
175 } else { |
184 } else { |
176 __ MacroAssembler::verify_FPU(0, "generate_return_entry_for compiled"); |
185 __ MacroAssembler::verify_FPU(0, "generate_return_entry_for compiled"); |
177 } |
186 } |
178 |
187 |
184 address entry = __ pc(); |
193 address entry = __ pc(); |
185 __ bind(interpreter_entry); |
194 __ bind(interpreter_entry); |
186 |
195 |
187 // In SSE mode, interpreter returns FP results in xmm0 but they need |
196 // In SSE mode, interpreter returns FP results in xmm0 but they need |
188 // to end up back on the FPU so it can operate on them. |
197 // to end up back on the FPU so it can operate on them. |
189 if (state == ftos && UseSSE >= 1) { |
198 if (incoming_state == ftos && UseSSE >= 1) { |
190 __ subptr(rsp, wordSize); |
199 __ subptr(rsp, wordSize); |
191 __ movflt(Address(rsp, 0), xmm0); |
200 __ movflt(Address(rsp, 0), xmm0); |
192 __ fld_s(Address(rsp, 0)); |
201 __ fld_s(Address(rsp, 0)); |
193 __ addptr(rsp, wordSize); |
202 __ addptr(rsp, wordSize); |
194 } else if (state == dtos && UseSSE >= 2) { |
203 } else if (incoming_state == dtos && UseSSE >= 2) { |
195 __ subptr(rsp, 2*wordSize); |
204 __ subptr(rsp, 2*wordSize); |
196 __ movdbl(Address(rsp, 0), xmm0); |
205 __ movdbl(Address(rsp, 0), xmm0); |
197 __ fld_d(Address(rsp, 0)); |
206 __ fld_d(Address(rsp, 0)); |
198 __ addptr(rsp, 2*wordSize); |
207 __ addptr(rsp, 2*wordSize); |
199 } |
208 } |
205 // and NULL it as marker that rsp is now tos until next java call |
214 // and NULL it as marker that rsp is now tos until next java call |
206 __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); |
215 __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); |
207 |
216 |
208 __ restore_bcp(); |
217 __ restore_bcp(); |
209 __ restore_locals(); |
218 __ restore_locals(); |
210 __ get_cache_and_index_at_bcp(rbx, rcx, 1); |
219 |
|
220 Label L_fail; |
|
221 |
|
222 if (unbox && state != atos) { |
|
223 // cast and unbox |
|
224 BasicType type = as_BasicType(state); |
|
225 if (type == T_BYTE) type = T_BOOLEAN; // FIXME |
|
226 KlassHandle boxk = SystemDictionaryHandles::box_klass(type); |
|
227 __ mov32(rbx, ExternalAddress((address) boxk.raw_value())); |
|
228 __ testl(rax, rax); |
|
229 Label L_got_value, L_get_value; |
|
230 // convert nulls to zeroes (avoid NPEs here) |
|
231 if (!(type == T_FLOAT || type == T_DOUBLE)) { |
|
232 // if rax already contains zero bits, forge ahead |
|
233 __ jcc(Assembler::zero, L_got_value); |
|
234 } else { |
|
235 __ jcc(Assembler::notZero, L_get_value); |
|
236 __ fldz(); |
|
237 __ jmp(L_got_value); |
|
238 } |
|
239 __ bind(L_get_value); |
|
240 __ cmp32(rbx, Address(rax, oopDesc::klass_offset_in_bytes())); |
|
241 __ jcc(Assembler::notEqual, L_fail); |
|
242 int offset = java_lang_boxing_object::value_offset_in_bytes(type); |
|
243 // Cf. TemplateTable::getfield_or_static |
|
244 switch (type) { |
|
245 case T_BYTE: // fall through: |
|
246 case T_BOOLEAN: __ load_signed_byte(rax, Address(rax, offset)); break; |
|
247 case T_CHAR: __ load_unsigned_short(rax, Address(rax, offset)); break; |
|
248 case T_SHORT: __ load_signed_short(rax, Address(rax, offset)); break; |
|
249 case T_INT: __ movl(rax, Address(rax, offset)); break; |
|
250 case T_FLOAT: __ fld_s(Address(rax, offset)); break; |
|
251 case T_DOUBLE: __ fld_d(Address(rax, offset)); break; |
|
252 // Access to java.lang.Double.value does not need to be atomic: |
|
253 case T_LONG: { __ movl(rdx, Address(rax, offset + 4)); |
|
254 __ movl(rax, Address(rax, offset + 0)); } break; |
|
255 default: ShouldNotReachHere(); |
|
256 } |
|
257 __ bind(L_got_value); |
|
258 } |
|
259 |
|
260 Label L_got_cache, L_giant_index; |
|
261 if (EnableInvokeDynamic) { |
|
262 __ cmpb(Address(rsi, 0), Bytecodes::_invokedynamic); |
|
263 __ jcc(Assembler::equal, L_giant_index); |
|
264 } |
|
265 __ get_cache_and_index_at_bcp(rbx, rcx, 1, false); |
|
266 __ bind(L_got_cache); |
|
267 if (unbox && state == atos) { |
|
268 // insert a casting conversion, to keep verifier sane |
|
269 Label L_ok, L_ok_pops; |
|
270 __ testl(rax, rax); |
|
271 __ jcc(Assembler::zero, L_ok); |
|
272 __ push(rax); // save the object to check |
|
273 __ push(rbx); // save CP cache reference |
|
274 __ movl(rdx, Address(rax, oopDesc::klass_offset_in_bytes())); |
|
275 __ movl(rbx, Address(rbx, rcx, |
|
276 Address::times_4, constantPoolCacheOopDesc::base_offset() + |
|
277 ConstantPoolCacheEntry::f1_offset())); |
|
278 __ movl(rbx, Address(rbx, __ delayed_value(sun_dyn_CallSiteImpl::type_offset_in_bytes, rcx))); |
|
279 __ movl(rbx, Address(rbx, __ delayed_value(java_dyn_MethodType::rtype_offset_in_bytes, rcx))); |
|
280 __ movl(rax, Address(rbx, __ delayed_value(java_lang_Class::klass_offset_in_bytes, rcx))); |
|
281 __ check_klass_subtype(rdx, rax, rbx, L_ok_pops); |
|
282 __ pop(rcx); // pop and discard CP cache |
|
283 __ mov(rbx, rax); // target supertype into rbx for L_fail |
|
284 __ pop(rax); // failed object into rax for L_fail |
|
285 __ jmp(L_fail); |
|
286 |
|
287 __ bind(L_ok_pops); |
|
288 // restore pushed temp regs: |
|
289 __ pop(rbx); |
|
290 __ pop(rax); |
|
291 __ bind(L_ok); |
|
292 } |
211 __ movl(rbx, Address(rbx, rcx, |
293 __ movl(rbx, Address(rbx, rcx, |
212 Address::times_ptr, constantPoolCacheOopDesc::base_offset() + |
294 Address::times_ptr, constantPoolCacheOopDesc::base_offset() + |
213 ConstantPoolCacheEntry::flags_offset())); |
295 ConstantPoolCacheEntry::flags_offset())); |
214 __ andptr(rbx, 0xFF); |
296 __ andptr(rbx, 0xFF); |
215 __ lea(rsp, Address(rsp, rbx, Interpreter::stackElementScale())); |
297 __ lea(rsp, Address(rsp, rbx, Interpreter::stackElementScale())); |
216 __ dispatch_next(state, step); |
298 __ dispatch_next(state, step); |
|
299 |
|
300 // out of the main line of code... |
|
301 if (EnableInvokeDynamic) { |
|
302 __ bind(L_giant_index); |
|
303 __ get_cache_and_index_at_bcp(rbx, rcx, 1, true); |
|
304 __ jmp(L_got_cache); |
|
305 |
|
306 if (unbox) { |
|
307 __ bind(L_fail); |
|
308 __ push(rbx); // missed klass (required) |
|
309 __ push(rax); // bad object (actual) |
|
310 __ movptr(rdx, ExternalAddress((address) &Interpreter::_throw_WrongMethodType_entry)); |
|
311 __ call(rdx); |
|
312 } |
|
313 } |
|
314 |
217 return entry; |
315 return entry; |
218 } |
316 } |
219 |
317 |
220 |
318 |
221 address TemplateInterpreterGenerator::generate_deopt_entry_for(TosState state, int step) { |
319 address TemplateInterpreterGenerator::generate_deopt_entry_for(TosState state, int step) { |