src/cpu/x86/vm/templateInterpreter_x86_32.cpp

changeset 1161
be93aad57795
parent 1145
e5b0439ef4ae
child 1474
987e948ebbc8
equal deleted inserted replaced
1160:928912ce8438 1161:be93aad57795
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) {

mercurial