Mercurial > hg > truffle
comparison src/cpu/sparc/vm/methodHandles_sparc.cpp @ 4137:04b9a2566eec
Merge with hsx23/hotspot.
author | Thomas Wuerthinger <thomas.wuerthinger@oracle.com> |
---|---|
date | Sat, 17 Dec 2011 21:40:27 +0100 |
parents | 6729bbc1fcd6 |
children | 33df1aeaebbf |
comparison
equal
deleted
inserted
replaced
3737:9dc19b7d89a3 | 4137:04b9a2566eec |
---|---|
285 | 285 |
286 Label L_ok_1, L_ok_2, L_ok_3, L_ok_4; | 286 Label L_ok_1, L_ok_2, L_ok_3, L_ok_4; |
287 BLOCK_COMMENT("verify_clean {"); | 287 BLOCK_COMMENT("verify_clean {"); |
288 // Magic numbers must check out: | 288 // Magic numbers must check out: |
289 __ set((int32_t) MAGIC_NUMBER_1, O7_temp); | 289 __ set((int32_t) MAGIC_NUMBER_1, O7_temp); |
290 __ cmp(O7_temp, L0_magic_number_1); | 290 __ cmp_and_br_short(O7_temp, L0_magic_number_1, Assembler::equal, Assembler::pt, L_ok_1); |
291 __ br(Assembler::equal, false, Assembler::pt, L_ok_1); | |
292 __ delayed()->nop(); | |
293 __ stop("damaged ricochet frame: MAGIC_NUMBER_1 not found"); | 291 __ stop("damaged ricochet frame: MAGIC_NUMBER_1 not found"); |
294 | 292 |
295 __ BIND(L_ok_1); | 293 __ BIND(L_ok_1); |
296 | 294 |
297 // Arguments pointer must look reasonable: | 295 // Arguments pointer must look reasonable: |
299 Register FP_temp = O5_temp; | 297 Register FP_temp = O5_temp; |
300 __ add(FP, STACK_BIAS, FP_temp); | 298 __ add(FP, STACK_BIAS, FP_temp); |
301 #else | 299 #else |
302 Register FP_temp = FP; | 300 Register FP_temp = FP; |
303 #endif | 301 #endif |
304 __ cmp(L4_saved_args_base, FP_temp); | 302 __ cmp_and_brx_short(L4_saved_args_base, FP_temp, Assembler::greaterEqualUnsigned, Assembler::pt, L_ok_2); |
305 __ br(Assembler::greaterEqualUnsigned, false, Assembler::pt, L_ok_2); | |
306 __ delayed()->nop(); | |
307 __ stop("damaged ricochet frame: L4 < FP"); | 303 __ stop("damaged ricochet frame: L4 < FP"); |
308 | 304 |
309 __ BIND(L_ok_2); | 305 __ BIND(L_ok_2); |
310 // Disable until we decide on it's fate | 306 // Disable until we decide on it's fate |
311 // __ sub(L4_saved_args_base, UNREASONABLE_STACK_MOVE * Interpreter::stackElementSize, O7_temp); | 307 // __ sub(L4_saved_args_base, UNREASONABLE_STACK_MOVE * Interpreter::stackElementSize, O7_temp); |
314 // __ delayed()->nop(); | 310 // __ delayed()->nop(); |
315 // __ stop("damaged ricochet frame: (L4 - UNREASONABLE_STACK_MOVE) > FP"); | 311 // __ stop("damaged ricochet frame: (L4 - UNREASONABLE_STACK_MOVE) > FP"); |
316 | 312 |
317 __ BIND(L_ok_3); | 313 __ BIND(L_ok_3); |
318 extract_conversion_dest_type(_masm, L5_conversion, O7_temp); | 314 extract_conversion_dest_type(_masm, L5_conversion, O7_temp); |
319 __ cmp(O7_temp, T_VOID); | 315 __ cmp_and_br_short(O7_temp, T_VOID, Assembler::equal, Assembler::pt, L_ok_4); |
320 __ br(Assembler::equal, false, Assembler::pt, L_ok_4); | |
321 __ delayed()->nop(); | |
322 extract_conversion_vminfo(_masm, L5_conversion, O5_temp); | 316 extract_conversion_vminfo(_masm, L5_conversion, O5_temp); |
323 __ ld_ptr(L4_saved_args_base, __ argument_offset(O5_temp, O5_temp), O7_temp); | 317 __ ld_ptr(L4_saved_args_base, __ argument_offset(O5_temp, O5_temp), O7_temp); |
324 assert(__ is_simm13(RETURN_VALUE_PLACEHOLDER), "must be simm13"); | 318 assert(Assembler::is_simm13(RETURN_VALUE_PLACEHOLDER), "must be simm13"); |
325 __ cmp(O7_temp, (int32_t) RETURN_VALUE_PLACEHOLDER); | 319 __ cmp_and_brx_short(O7_temp, (int32_t) RETURN_VALUE_PLACEHOLDER, Assembler::equal, Assembler::pt, L_ok_4); |
326 __ brx(Assembler::equal, false, Assembler::pt, L_ok_4); | |
327 __ delayed()->nop(); | |
328 __ stop("damaged ricochet frame: RETURN_VALUE_PLACEHOLDER not found"); | 320 __ stop("damaged ricochet frame: RETURN_VALUE_PLACEHOLDER not found"); |
329 __ BIND(L_ok_4); | 321 __ BIND(L_ok_4); |
330 BLOCK_COMMENT("} verify_clean"); | 322 BLOCK_COMMENT("} verify_clean"); |
331 } | 323 } |
332 #endif //ASSERT | 324 #endif //ASSERT |
358 Address G3_amh_conversion, | 350 Address G3_amh_conversion, |
359 Register stack_move_reg) { | 351 Register stack_move_reg) { |
360 BLOCK_COMMENT("load_stack_move {"); | 352 BLOCK_COMMENT("load_stack_move {"); |
361 __ ldsw(G3_amh_conversion, stack_move_reg); | 353 __ ldsw(G3_amh_conversion, stack_move_reg); |
362 __ sra(stack_move_reg, CONV_STACK_MOVE_SHIFT, stack_move_reg); | 354 __ sra(stack_move_reg, CONV_STACK_MOVE_SHIFT, stack_move_reg); |
355 #ifdef ASSERT | |
363 if (VerifyMethodHandles) { | 356 if (VerifyMethodHandles) { |
364 Label L_ok, L_bad; | 357 Label L_ok, L_bad; |
365 int32_t stack_move_limit = 0x0800; // extra-large | 358 int32_t stack_move_limit = 0x0800; // extra-large |
366 __ cmp(stack_move_reg, stack_move_limit); | 359 __ cmp_and_br_short(stack_move_reg, stack_move_limit, Assembler::greaterEqual, Assembler::pn, L_bad); |
367 __ br(Assembler::greaterEqual, false, Assembler::pn, L_bad); | |
368 __ delayed()->nop(); | |
369 __ cmp(stack_move_reg, -stack_move_limit); | 360 __ cmp(stack_move_reg, -stack_move_limit); |
370 __ br(Assembler::greater, false, Assembler::pt, L_ok); | 361 __ br(Assembler::greater, false, Assembler::pt, L_ok); |
371 __ delayed()->nop(); | 362 __ delayed()->nop(); |
372 __ BIND(L_bad); | 363 __ BIND(L_bad); |
373 __ stop("load_stack_move of garbage value"); | 364 __ stop("load_stack_move of garbage value"); |
374 __ BIND(L_ok); | 365 __ BIND(L_ok); |
375 } | 366 } |
367 #endif | |
376 BLOCK_COMMENT("} load_stack_move"); | 368 BLOCK_COMMENT("} load_stack_move"); |
377 } | 369 } |
378 | 370 |
379 #ifdef ASSERT | 371 #ifdef ASSERT |
380 void MethodHandles::RicochetFrame::verify() const { | 372 void MethodHandles::RicochetFrame::verify() const { |
399 | 391 |
400 void MethodHandles::verify_argslot(MacroAssembler* _masm, Register argslot_reg, Register temp_reg, const char* error_message) { | 392 void MethodHandles::verify_argslot(MacroAssembler* _masm, Register argslot_reg, Register temp_reg, const char* error_message) { |
401 // Verify that argslot lies within (Gargs, FP]. | 393 // Verify that argslot lies within (Gargs, FP]. |
402 Label L_ok, L_bad; | 394 Label L_ok, L_bad; |
403 BLOCK_COMMENT("verify_argslot {"); | 395 BLOCK_COMMENT("verify_argslot {"); |
396 __ cmp_and_brx_short(Gargs, argslot_reg, Assembler::greaterUnsigned, Assembler::pn, L_bad); | |
404 __ add(FP, STACK_BIAS, temp_reg); // STACK_BIAS is zero on !_LP64 | 397 __ add(FP, STACK_BIAS, temp_reg); // STACK_BIAS is zero on !_LP64 |
405 __ cmp(argslot_reg, temp_reg); | 398 __ cmp_and_brx_short(argslot_reg, temp_reg, Assembler::lessEqualUnsigned, Assembler::pt, L_ok); |
406 __ brx(Assembler::greaterUnsigned, false, Assembler::pn, L_bad); | |
407 __ delayed()->nop(); | |
408 __ cmp(Gargs, argslot_reg); | |
409 __ brx(Assembler::lessEqualUnsigned, false, Assembler::pt, L_ok); | |
410 __ delayed()->nop(); | |
411 __ BIND(L_bad); | 399 __ BIND(L_bad); |
412 __ stop(error_message); | 400 __ stop(error_message); |
413 __ BIND(L_ok); | 401 __ BIND(L_ok); |
414 BLOCK_COMMENT("} verify_argslot"); | 402 BLOCK_COMMENT("} verify_argslot"); |
415 } | 403 } |
432 arg_slots = temp_reg; | 420 arg_slots = temp_reg; |
433 } | 421 } |
434 } | 422 } |
435 __ add(arg_slot_base_reg, __ argument_offset(arg_slots, temp_reg), temp_reg); | 423 __ add(arg_slot_base_reg, __ argument_offset(arg_slots, temp_reg), temp_reg); |
436 __ add(FP, STACK_BIAS, temp2_reg); // STACK_BIAS is zero on !_LP64 | 424 __ add(FP, STACK_BIAS, temp2_reg); // STACK_BIAS is zero on !_LP64 |
437 __ cmp(temp_reg, temp2_reg); | 425 __ cmp_and_brx_short(temp_reg, temp2_reg, Assembler::greaterUnsigned, Assembler::pn, L_bad); |
438 __ brx(Assembler::greaterUnsigned, false, Assembler::pn, L_bad); | |
439 __ delayed()->nop(); | |
440 // Gargs points to the first word so adjust by BytesPerWord | 426 // Gargs points to the first word so adjust by BytesPerWord |
441 __ add(arg_slot_base_reg, BytesPerWord, temp_reg); | 427 __ add(arg_slot_base_reg, BytesPerWord, temp_reg); |
442 __ cmp(Gargs, temp_reg); | 428 __ cmp_and_brx_short(Gargs, temp_reg, Assembler::lessEqualUnsigned, Assembler::pt, L_ok); |
443 __ brx(Assembler::lessEqualUnsigned, false, Assembler::pt, L_ok); | |
444 __ delayed()->nop(); | |
445 __ BIND(L_bad); | 429 __ BIND(L_bad); |
446 __ stop(error_message); | 430 __ stop(error_message); |
447 __ BIND(L_ok); | 431 __ BIND(L_ok); |
448 BLOCK_COMMENT("} verify_argslots"); | 432 BLOCK_COMMENT("} verify_argslots"); |
449 } | 433 } |
500 klass_addr <= SystemDictionaryHandles::Long_klass().raw_value(), | 484 klass_addr <= SystemDictionaryHandles::Long_klass().raw_value(), |
501 "must be one of the SystemDictionaryHandles"); | 485 "must be one of the SystemDictionaryHandles"); |
502 Label L_ok, L_bad; | 486 Label L_ok, L_bad; |
503 BLOCK_COMMENT("verify_klass {"); | 487 BLOCK_COMMENT("verify_klass {"); |
504 __ verify_oop(obj_reg); | 488 __ verify_oop(obj_reg); |
505 __ br_null(obj_reg, false, Assembler::pn, L_bad); | 489 __ br_null_short(obj_reg, Assembler::pn, L_bad); |
506 __ delayed()->nop(); | |
507 __ load_klass(obj_reg, temp_reg); | 490 __ load_klass(obj_reg, temp_reg); |
508 __ set(ExternalAddress(klass_addr), temp2_reg); | 491 __ set(ExternalAddress(klass_addr), temp2_reg); |
509 __ ld_ptr(Address(temp2_reg, 0), temp2_reg); | 492 __ ld_ptr(Address(temp2_reg, 0), temp2_reg); |
510 __ cmp(temp_reg, temp2_reg); | 493 __ cmp_and_brx_short(temp_reg, temp2_reg, Assembler::equal, Assembler::pt, L_ok); |
511 __ brx(Assembler::equal, false, Assembler::pt, L_ok); | |
512 __ delayed()->nop(); | |
513 intptr_t super_check_offset = klass->super_check_offset(); | 494 intptr_t super_check_offset = klass->super_check_offset(); |
514 __ ld_ptr(Address(temp_reg, super_check_offset), temp_reg); | 495 __ ld_ptr(Address(temp_reg, super_check_offset), temp_reg); |
515 __ set(ExternalAddress(klass_addr), temp2_reg); | 496 __ set(ExternalAddress(klass_addr), temp2_reg); |
516 __ ld_ptr(Address(temp2_reg, 0), temp2_reg); | 497 __ ld_ptr(Address(temp2_reg, 0), temp2_reg); |
517 __ cmp(temp_reg, temp2_reg); | 498 __ cmp_and_brx_short(temp_reg, temp2_reg, Assembler::equal, Assembler::pt, L_ok); |
518 __ brx(Assembler::equal, false, Assembler::pt, L_ok); | |
519 __ delayed()->nop(); | |
520 __ BIND(L_bad); | 499 __ BIND(L_bad); |
521 __ stop(error_message); | 500 __ stop(error_message); |
522 __ BIND(L_ok); | 501 __ BIND(L_ok); |
523 BLOCK_COMMENT("} verify_klass"); | 502 BLOCK_COMMENT("} verify_klass"); |
524 } | 503 } |
525 #endif // ASSERT | 504 #endif // ASSERT |
505 | |
506 | |
507 void MethodHandles::jump_from_method_handle(MacroAssembler* _masm, Register method, Register target, Register temp) { | |
508 assert(method == G5_method, "interpreter calling convention"); | |
509 __ verify_oop(method); | |
510 __ ld_ptr(G5_method, in_bytes(methodOopDesc::from_interpreted_offset()), target); | |
511 if (JvmtiExport::can_post_interpreter_events()) { | |
512 // JVMTI events, such as single-stepping, are implemented partly by avoiding running | |
513 // compiled code in threads for which the event is enabled. Check here for | |
514 // interp_only_mode if these events CAN be enabled. | |
515 __ verify_thread(); | |
516 Label skip_compiled_code; | |
517 | |
518 const Address interp_only(G2_thread, JavaThread::interp_only_mode_offset()); | |
519 __ ld(interp_only, temp); | |
520 __ tst(temp); | |
521 __ br(Assembler::notZero, true, Assembler::pn, skip_compiled_code); | |
522 __ delayed()->ld_ptr(G5_method, in_bytes(methodOopDesc::interpreter_entry_offset()), target); | |
523 __ bind(skip_compiled_code); | |
524 } | |
525 __ jmp(target, 0); | |
526 __ delayed()->nop(); | |
527 } | |
528 | |
526 | 529 |
527 // Code generation | 530 // Code generation |
528 address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* _masm) { | 531 address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* _masm) { |
529 // I5_savedSP/O5_savedSP: sender SP (must preserve) | 532 // I5_savedSP/O5_savedSP: sender SP (must preserve) |
530 // G4 (Gargs): incoming argument list (must preserve) | 533 // G4 (Gargs): incoming argument list (must preserve) |
645 return offset; | 648 return offset; |
646 } else { | 649 } else { |
647 #ifdef ASSERT | 650 #ifdef ASSERT |
648 { | 651 { |
649 Label L_ok; | 652 Label L_ok; |
650 __ cmp(arg_slots.as_register(), 0); | 653 __ cmp_and_br_short(arg_slots.as_register(), 0, Assembler::greaterEqual, Assembler::pt, L_ok); |
651 __ br(Assembler::greaterEqual, false, Assembler::pt, L_ok); | |
652 __ delayed()->nop(); | |
653 __ stop("negative arg_slots"); | 654 __ stop("negative arg_slots"); |
654 __ bind(L_ok); | 655 __ bind(L_ok); |
655 } | 656 } |
656 #endif | 657 #endif |
657 __ sll_ptr(arg_slots.as_register(), LogBytesPerWord, temp_reg); | 658 __ sll_ptr(arg_slots.as_register(), LogBytesPerWord, temp_reg); |
722 __ BIND(loop); | 723 __ BIND(loop); |
723 // pull one word down each time through the loop | 724 // pull one word down each time through the loop |
724 __ ld_ptr( Address(temp_reg, 0 ), temp2_reg); | 725 __ ld_ptr( Address(temp_reg, 0 ), temp2_reg); |
725 __ st_ptr(temp2_reg, Address(temp_reg, offset) ); | 726 __ st_ptr(temp2_reg, Address(temp_reg, offset) ); |
726 __ add(temp_reg, wordSize, temp_reg); | 727 __ add(temp_reg, wordSize, temp_reg); |
727 __ cmp(temp_reg, argslot_reg); | 728 __ cmp_and_brx_short(temp_reg, argslot_reg, Assembler::lessUnsigned, Assembler::pt, loop); |
728 __ brx(Assembler::lessUnsigned, false, Assembler::pt, loop); | |
729 __ delayed()->nop(); // FILLME | |
730 } | 729 } |
731 | 730 |
732 // Now move the argslot down, to point to the opened-up space. | 731 // Now move the argslot down, to point to the opened-up space. |
733 __ add(argslot_reg, offset, argslot_reg); | 732 __ add(argslot_reg, offset, argslot_reg); |
734 BLOCK_COMMENT("} insert_arg_slots"); | 733 BLOCK_COMMENT("} insert_arg_slots"); |
771 __ BIND(L_loop); | 770 __ BIND(L_loop); |
772 // pull one word up each time through the loop | 771 // pull one word up each time through the loop |
773 __ ld_ptr( Address(temp_reg, 0 ), temp2_reg); | 772 __ ld_ptr( Address(temp_reg, 0 ), temp2_reg); |
774 __ st_ptr(temp2_reg, Address(temp_reg, offset) ); | 773 __ st_ptr(temp2_reg, Address(temp_reg, offset) ); |
775 __ sub(temp_reg, wordSize, temp_reg); | 774 __ sub(temp_reg, wordSize, temp_reg); |
776 __ cmp(temp_reg, Gargs); | 775 __ cmp_and_brx_short(temp_reg, Gargs, Assembler::greaterEqualUnsigned, Assembler::pt, L_loop); |
777 __ brx(Assembler::greaterEqualUnsigned, false, Assembler::pt, L_loop); | |
778 __ delayed()->nop(); // FILLME | |
779 } | 776 } |
780 | 777 |
781 // And adjust the argslot address to point at the deletion point. | 778 // And adjust the argslot address to point at the deletion point. |
782 __ add(argslot_reg, offset, argslot_reg); | 779 __ add(argslot_reg, offset, argslot_reg); |
783 | 780 |
822 __ delayed()->nop(); | 819 __ delayed()->nop(); |
823 __ br(Assembler::less, false, Assembler::pn, L_break); | 820 __ br(Assembler::less, false, Assembler::pn, L_break); |
824 __ delayed()->nop(); | 821 __ delayed()->nop(); |
825 __ ld_ptr( Address(argslot_reg, 0), temp_reg); | 822 __ ld_ptr( Address(argslot_reg, 0), temp_reg); |
826 __ st_ptr(temp_reg, Address(Gargs, 0)); | 823 __ st_ptr(temp_reg, Address(Gargs, 0)); |
827 __ ba(false, L_break); | 824 __ ba_short(L_break); |
828 __ delayed()->nop(); // FILLME | |
829 __ BIND(L_plural); | 825 __ BIND(L_plural); |
830 | 826 |
831 // Loop for 2 or more: | 827 // Loop for 2 or more: |
832 // top = &argslot[slot_count] | 828 // top = &argslot[slot_count] |
833 // while (top > argslot) *(--Gargs) = *(--top) | 829 // while (top > argslot) *(--Gargs) = *(--top) |
837 __ BIND(L_loop); | 833 __ BIND(L_loop); |
838 __ sub(top_reg, wordSize, top_reg); | 834 __ sub(top_reg, wordSize, top_reg); |
839 __ sub(Gargs, wordSize, Gargs ); | 835 __ sub(Gargs, wordSize, Gargs ); |
840 __ ld_ptr( Address(top_reg, 0), temp2_reg); | 836 __ ld_ptr( Address(top_reg, 0), temp2_reg); |
841 __ st_ptr(temp2_reg, Address(Gargs, 0)); | 837 __ st_ptr(temp2_reg, Address(Gargs, 0)); |
842 __ cmp(top_reg, argslot_reg); | 838 __ cmp_and_brx_short(top_reg, argslot_reg, Assembler::greaterUnsigned, Assembler::pt, L_loop); |
843 __ brx(Assembler::greaterUnsigned, false, Assembler::pt, L_loop); | |
844 __ delayed()->nop(); // FILLME | |
845 __ BIND(L_break); | 839 __ BIND(L_break); |
846 } | 840 } |
847 BLOCK_COMMENT("} push_arg_slots"); | 841 BLOCK_COMMENT("} push_arg_slots"); |
848 } | 842 } |
849 | 843 |
871 if (positive_distance_in_slots.is_register()) { | 865 if (positive_distance_in_slots.is_register()) { |
872 __ cmp(positive_distance_in_slots.as_register(), (int32_t) 0); | 866 __ cmp(positive_distance_in_slots.as_register(), (int32_t) 0); |
873 __ br(Assembler::lessEqual, false, Assembler::pn, L_bad); | 867 __ br(Assembler::lessEqual, false, Assembler::pn, L_bad); |
874 __ delayed()->nop(); | 868 __ delayed()->nop(); |
875 } | 869 } |
876 __ cmp(bottom_reg, top_reg); | 870 __ cmp_and_brx_short(bottom_reg, top_reg, Assembler::lessUnsigned, Assembler::pt, L_ok); |
877 __ brx(Assembler::lessUnsigned, false, Assembler::pt, L_ok); | |
878 __ delayed()->nop(); | |
879 __ BIND(L_bad); | 871 __ BIND(L_bad); |
880 __ stop("valid bounds (copy up)"); | 872 __ stop("valid bounds (copy up)"); |
881 __ BIND(L_ok); | 873 __ BIND(L_ok); |
882 } | 874 } |
883 #endif | 875 #endif |
884 __ cmp(bottom_reg, top_reg); | 876 __ cmp_and_brx_short(bottom_reg, top_reg, Assembler::greaterEqualUnsigned, Assembler::pn, L_break); |
885 __ brx(Assembler::greaterEqualUnsigned, false, Assembler::pn, L_break); | 877 >> |
886 __ delayed()->nop(); | 878 __ cmp_and_brx_short(top_reg, bottom_reg, Assembler::greaterUnsigned, Assembler::pt, L_loop); |
887 // work top down to bottom, copying contiguous data upwards | |
888 // In pseudo-code: | |
889 // while (--top >= bottom) *(top + distance) = *(top + 0); | |
890 RegisterOrConstant offset = __ argument_offset(positive_distance_in_slots, positive_distance_in_slots.register_or_noreg()); | |
891 __ BIND(L_loop); | |
892 __ sub(top_reg, wordSize, top_reg); | |
893 __ ld_ptr( Address(top_reg, 0 ), temp2_reg); | |
894 __ st_ptr(temp2_reg, Address(top_reg, offset) ); | |
895 __ cmp(top_reg, bottom_reg); | |
896 __ brx(Assembler::greaterUnsigned, false, Assembler::pt, L_loop); | |
897 __ delayed()->nop(); // FILLME | |
898 assert(Interpreter::stackElementSize == wordSize, "else change loop"); | 879 assert(Interpreter::stackElementSize == wordSize, "else change loop"); |
899 __ BIND(L_break); | 880 __ BIND(L_break); |
900 BLOCK_COMMENT("} move_arg_slots_up"); | 881 BLOCK_COMMENT("} move_arg_slots_up"); |
901 } | 882 } |
902 | 883 |
925 if (negative_distance_in_slots.is_register()) { | 906 if (negative_distance_in_slots.is_register()) { |
926 __ cmp(negative_distance_in_slots.as_register(), (int32_t) 0); | 907 __ cmp(negative_distance_in_slots.as_register(), (int32_t) 0); |
927 __ br(Assembler::greaterEqual, false, Assembler::pn, L_bad); | 908 __ br(Assembler::greaterEqual, false, Assembler::pn, L_bad); |
928 __ delayed()->nop(); | 909 __ delayed()->nop(); |
929 } | 910 } |
930 __ cmp(bottom_reg, top_reg); | 911 __ cmp_and_brx_short(bottom_reg, top_reg, Assembler::lessUnsigned, Assembler::pt, L_ok); |
931 __ brx(Assembler::lessUnsigned, false, Assembler::pt, L_ok); | |
932 __ delayed()->nop(); | |
933 __ BIND(L_bad); | 912 __ BIND(L_bad); |
934 __ stop("valid bounds (copy down)"); | 913 __ stop("valid bounds (copy down)"); |
935 __ BIND(L_ok); | 914 __ BIND(L_ok); |
936 } | 915 } |
937 #endif | 916 #endif |
938 __ cmp(bottom_reg, top_reg); | 917 __ cmp_and_brx_short(bottom_reg, top_reg, Assembler::greaterEqualUnsigned, Assembler::pn, L_break); |
939 __ brx(Assembler::greaterEqualUnsigned, false, Assembler::pn, L_break); | |
940 __ delayed()->nop(); | |
941 // work bottom up to top, copying contiguous data downwards | 918 // work bottom up to top, copying contiguous data downwards |
942 // In pseudo-code: | 919 // In pseudo-code: |
943 // while (bottom < top) *(bottom - distance) = *(bottom + 0), bottom++; | 920 // while (bottom < top) *(bottom - distance) = *(bottom + 0), bottom++; |
944 RegisterOrConstant offset = __ argument_offset(negative_distance_in_slots, negative_distance_in_slots.register_or_noreg()); | 921 RegisterOrConstant offset = __ argument_offset(negative_distance_in_slots, negative_distance_in_slots.register_or_noreg()); |
945 __ BIND(L_loop); | 922 __ BIND(L_loop); |
946 __ ld_ptr( Address(bottom_reg, 0 ), temp2_reg); | 923 __ ld_ptr( Address(bottom_reg, 0 ), temp2_reg); |
947 __ st_ptr(temp2_reg, Address(bottom_reg, offset) ); | 924 __ st_ptr(temp2_reg, Address(bottom_reg, offset) ); |
948 __ add(bottom_reg, wordSize, bottom_reg); | 925 __ add(bottom_reg, wordSize, bottom_reg); |
949 __ cmp(bottom_reg, top_reg); | 926 __ cmp_and_brx_short(bottom_reg, top_reg, Assembler::lessUnsigned, Assembler::pt, L_loop); |
950 __ brx(Assembler::lessUnsigned, false, Assembler::pt, L_loop); | |
951 __ delayed()->nop(); // FILLME | |
952 assert(Interpreter::stackElementSize == wordSize, "else change loop"); | 927 assert(Interpreter::stackElementSize == wordSize, "else change loop"); |
953 __ BIND(L_break); | 928 __ BIND(L_break); |
954 BLOCK_COMMENT("} move_arg_slots_down"); | 929 BLOCK_COMMENT("} move_arg_slots_down"); |
955 } | 930 } |
956 | 931 |
1103 const Register O2_required = O2; | 1078 const Register O2_required = O2; |
1104 | 1079 |
1105 guarantee(java_lang_invoke_MethodHandle::vmentry_offset_in_bytes() != 0, "must have offsets"); | 1080 guarantee(java_lang_invoke_MethodHandle::vmentry_offset_in_bytes() != 0, "must have offsets"); |
1106 | 1081 |
1107 // Some handy addresses: | 1082 // Some handy addresses: |
1108 Address G5_method_fie( G5_method, in_bytes(methodOopDesc::from_interpreted_offset())); | |
1109 Address G5_method_fce( G5_method, in_bytes(methodOopDesc::from_compiled_offset())); | |
1110 | |
1111 Address G3_mh_vmtarget( G3_method_handle, java_lang_invoke_MethodHandle::vmtarget_offset_in_bytes()); | 1083 Address G3_mh_vmtarget( G3_method_handle, java_lang_invoke_MethodHandle::vmtarget_offset_in_bytes()); |
1112 | 1084 |
1113 Address G3_dmh_vmindex( G3_method_handle, java_lang_invoke_DirectMethodHandle::vmindex_offset_in_bytes()); | 1085 Address G3_dmh_vmindex( G3_method_handle, java_lang_invoke_DirectMethodHandle::vmindex_offset_in_bytes()); |
1114 | 1086 |
1115 Address G3_bmh_vmargslot( G3_method_handle, java_lang_invoke_BoundMethodHandle::vmargslot_offset_in_bytes()); | 1087 Address G3_bmh_vmargslot( G3_method_handle, java_lang_invoke_BoundMethodHandle::vmargslot_offset_in_bytes()); |
1134 | 1106 |
1135 switch ((int) ek) { | 1107 switch ((int) ek) { |
1136 case _raise_exception: | 1108 case _raise_exception: |
1137 { | 1109 { |
1138 // Not a real MH entry, but rather shared code for raising an | 1110 // Not a real MH entry, but rather shared code for raising an |
1139 // exception. Since we use the compiled entry, arguments are | 1111 // exception. For sharing purposes the arguments are passed into registers |
1140 // expected in compiler argument registers. | 1112 // and then placed in the intepreter calling convention here. |
1141 assert(raise_exception_method(), "must be set"); | 1113 assert(raise_exception_method(), "must be set"); |
1142 assert(raise_exception_method()->from_compiled_entry(), "method must be linked"); | 1114 assert(raise_exception_method()->from_compiled_entry(), "method must be linked"); |
1143 | 1115 |
1144 __ mov(O5_savedSP, SP); // Cut the stack back to where the caller started. | |
1145 | |
1146 Label L_no_method; | |
1147 // FIXME: fill in _raise_exception_method with a suitable java.lang.invoke method | |
1148 __ set(AddressLiteral((address) &_raise_exception_method), G5_method); | 1116 __ set(AddressLiteral((address) &_raise_exception_method), G5_method); |
1149 __ ld_ptr(Address(G5_method, 0), G5_method); | 1117 __ ld_ptr(Address(G5_method, 0), G5_method); |
1150 | 1118 |
1151 const int jobject_oop_offset = 0; | 1119 const int jobject_oop_offset = 0; |
1152 __ ld_ptr(Address(G5_method, jobject_oop_offset), G5_method); | 1120 __ ld_ptr(Address(G5_method, jobject_oop_offset), G5_method); |
1153 | 1121 |
1154 __ verify_oop(G5_method); | 1122 adjust_SP_and_Gargs_down_by_slots(_masm, 3, noreg, noreg); |
1155 __ jump_indirect_to(G5_method_fce, O3_scratch); // jump to compiled entry | 1123 |
1156 __ delayed()->nop(); | 1124 __ st (O0_code, __ argument_address(constant(2), noreg, 0)); |
1125 __ st_ptr(O1_actual, __ argument_address(constant(1), noreg, 0)); | |
1126 __ st_ptr(O2_required, __ argument_address(constant(0), noreg, 0)); | |
1127 jump_from_method_handle(_masm, G5_method, O1_scratch, O2_scratch); | |
1157 } | 1128 } |
1158 break; | 1129 break; |
1159 | 1130 |
1160 case _invokestatic_mh: | 1131 case _invokestatic_mh: |
1161 case _invokespecial_mh: | 1132 case _invokespecial_mh: |
1162 { | 1133 { |
1163 __ load_heap_oop(G3_mh_vmtarget, G5_method); // target is a methodOop | 1134 __ load_heap_oop(G3_mh_vmtarget, G5_method); // target is a methodOop |
1164 __ verify_oop(G5_method); | |
1165 // Same as TemplateTable::invokestatic or invokespecial, | 1135 // Same as TemplateTable::invokestatic or invokespecial, |
1166 // minus the CP setup and profiling: | 1136 // minus the CP setup and profiling: |
1167 if (ek == _invokespecial_mh) { | 1137 if (ek == _invokespecial_mh) { |
1168 // Must load & check the first argument before entering the target method. | 1138 // Must load & check the first argument before entering the target method. |
1169 __ load_method_handle_vmslots(O0_argslot, G3_method_handle, O1_scratch); | 1139 __ load_method_handle_vmslots(O0_argslot, G3_method_handle, O1_scratch); |
1170 __ ld_ptr(__ argument_address(O0_argslot, O0_argslot, -1), G3_method_handle); | 1140 __ ld_ptr(__ argument_address(O0_argslot, O0_argslot, -1), G3_method_handle); |
1171 __ null_check(G3_method_handle); | 1141 __ null_check(G3_method_handle); |
1172 __ verify_oop(G3_method_handle); | 1142 __ verify_oop(G3_method_handle); |
1173 } | 1143 } |
1174 __ jump_indirect_to(G5_method_fie, O1_scratch); | 1144 jump_from_method_handle(_masm, G5_method, O1_scratch, O2_scratch); |
1175 __ delayed()->nop(); | |
1176 } | 1145 } |
1177 break; | 1146 break; |
1178 | 1147 |
1179 case _invokevirtual_mh: | 1148 case _invokevirtual_mh: |
1180 { | 1149 { |
1202 __ sll_ptr(O2_index, LogBytesPerWord, O2_index); | 1171 __ sll_ptr(O2_index, LogBytesPerWord, O2_index); |
1203 __ add(O0_klass, O2_index, O0_klass); | 1172 __ add(O0_klass, O2_index, O0_klass); |
1204 Address vtable_entry_addr(O0_klass, base + vtableEntry::method_offset_in_bytes()); | 1173 Address vtable_entry_addr(O0_klass, base + vtableEntry::method_offset_in_bytes()); |
1205 __ ld_ptr(vtable_entry_addr, G5_method); | 1174 __ ld_ptr(vtable_entry_addr, G5_method); |
1206 | 1175 |
1207 __ verify_oop(G5_method); | 1176 jump_from_method_handle(_masm, G5_method, O1_scratch, O2_scratch); |
1208 __ jump_indirect_to(G5_method_fie, O1_scratch); | |
1209 __ delayed()->nop(); | |
1210 } | 1177 } |
1211 break; | 1178 break; |
1212 | 1179 |
1213 case _invokeinterface_mh: | 1180 case _invokeinterface_mh: |
1214 { | 1181 { |
1235 G5_index, G5_method, | 1202 G5_index, G5_method, |
1236 O2_scratch, | 1203 O2_scratch, |
1237 O3_scratch, | 1204 O3_scratch, |
1238 no_such_interface); | 1205 no_such_interface); |
1239 | 1206 |
1240 __ verify_oop(G5_method); | 1207 jump_from_method_handle(_masm, G5_method, O1_scratch, O2_scratch); |
1241 __ jump_indirect_to(G5_method_fie, O1_scratch); | |
1242 __ delayed()->nop(); | |
1243 | 1208 |
1244 __ bind(no_such_interface); | 1209 __ bind(no_such_interface); |
1245 // Throw an exception. | 1210 // Throw an exception. |
1246 // For historical reasons, it will be IncompatibleClassChangeError. | 1211 // For historical reasons, it will be IncompatibleClassChangeError. |
1247 __ unimplemented("not tested yet"); | 1212 __ unimplemented("not tested yet"); |
1281 O2_scratch); // must be an even register for !_LP64 long moves (uses O2/O3) | 1246 O2_scratch); // must be an even register for !_LP64 long moves (uses O2/O3) |
1282 } | 1247 } |
1283 | 1248 |
1284 if (direct_to_method) { | 1249 if (direct_to_method) { |
1285 __ load_heap_oop(G3_mh_vmtarget, G5_method); // target is a methodOop | 1250 __ load_heap_oop(G3_mh_vmtarget, G5_method); // target is a methodOop |
1286 __ verify_oop(G5_method); | 1251 jump_from_method_handle(_masm, G5_method, O1_scratch, O2_scratch); |
1287 __ jump_indirect_to(G5_method_fie, O1_scratch); | |
1288 __ delayed()->nop(); | |
1289 } else { | 1252 } else { |
1290 __ load_heap_oop(G3_mh_vmtarget, G3_method_handle); // target is a methodOop | 1253 __ load_heap_oop(G3_mh_vmtarget, G3_method_handle); // target is a methodOop |
1291 __ verify_oop(G3_method_handle); | 1254 __ verify_oop(G3_method_handle); |
1292 __ jump_to_method_handle_entry(G3_method_handle, O1_scratch); | 1255 __ jump_to_method_handle_entry(G3_method_handle, O1_scratch); |
1293 } | 1256 } |
1294 } | 1257 } |
1295 break; | 1258 break; |
1259 | |
1260 case _adapter_opt_profiling: | |
1261 if (java_lang_invoke_CountingMethodHandle::vmcount_offset_in_bytes() != 0) { | |
1262 Address G3_mh_vmcount(G3_method_handle, java_lang_invoke_CountingMethodHandle::vmcount_offset_in_bytes()); | |
1263 __ ld(G3_mh_vmcount, O1_scratch); | |
1264 __ add(O1_scratch, 1, O1_scratch); | |
1265 __ st(O1_scratch, G3_mh_vmcount); | |
1266 } | |
1267 // fall through | |
1296 | 1268 |
1297 case _adapter_retype_only: | 1269 case _adapter_retype_only: |
1298 case _adapter_retype_raw: | 1270 case _adapter_retype_raw: |
1299 // Immediately jump to the next MH layer: | 1271 // Immediately jump to the next MH layer: |
1300 __ load_heap_oop(G3_mh_vmtarget, G3_method_handle); | 1272 __ load_heap_oop(G3_mh_vmtarget, G3_method_handle); |
1315 __ load_heap_oop(G3_amh_argument, O1_klass); // This is a Class object! | 1287 __ load_heap_oop(G3_amh_argument, O1_klass); // This is a Class object! |
1316 load_klass_from_Class(_masm, O1_klass, O2_scratch, O3_scratch); | 1288 load_klass_from_Class(_masm, O1_klass, O2_scratch, O3_scratch); |
1317 | 1289 |
1318 Label L_done; | 1290 Label L_done; |
1319 __ ld_ptr(vmarg, O2_scratch); | 1291 __ ld_ptr(vmarg, O2_scratch); |
1320 __ tst(O2_scratch); | 1292 __ br_null_short(O2_scratch, Assembler::pn, L_done); // No cast if null. |
1321 __ brx(Assembler::zero, false, Assembler::pn, L_done); // No cast if null. | |
1322 __ delayed()->nop(); | |
1323 __ load_klass(O2_scratch, O2_scratch); | 1293 __ load_klass(O2_scratch, O2_scratch); |
1324 | 1294 |
1325 // Live at this point: | 1295 // Live at this point: |
1326 // - O0_argslot : argslot index in vmarg; may be required in the failing path | 1296 // - O0_argslot : argslot index in vmarg; may be required in the failing path |
1327 // - O1_klass : klass required by the target method | 1297 // - O1_klass : klass required by the target method |
1422 __ br(Assembler::zero, false, Assembler::pn, zero_extend); | 1392 __ br(Assembler::zero, false, Assembler::pn, zero_extend); |
1423 __ delayed()->nop(); | 1393 __ delayed()->nop(); |
1424 | 1394 |
1425 // this path is taken for int->byte, int->short | 1395 // this path is taken for int->byte, int->short |
1426 __ sra(O1_scratch, G5_vminfo, O1_scratch); | 1396 __ sra(O1_scratch, G5_vminfo, O1_scratch); |
1427 __ ba(false, done); | 1397 __ ba_short(done); |
1428 __ delayed()->nop(); | |
1429 | 1398 |
1430 __ bind(zero_extend); | 1399 __ bind(zero_extend); |
1431 // this is taken for int->char | 1400 // this is taken for int->char |
1432 __ srl(O1_scratch, G5_vminfo, O1_scratch); | 1401 __ srl(O1_scratch, G5_vminfo, O1_scratch); |
1433 | 1402 |
1846 #ifdef ASSERT | 1815 #ifdef ASSERT |
1847 if (VerifyMethodHandles) { | 1816 if (VerifyMethodHandles) { |
1848 BLOCK_COMMENT("verify collect_count_constant {"); | 1817 BLOCK_COMMENT("verify collect_count_constant {"); |
1849 __ load_method_handle_vmslots(O3_scratch, G3_method_handle, O2_scratch); | 1818 __ load_method_handle_vmslots(O3_scratch, G3_method_handle, O2_scratch); |
1850 Label L_count_ok; | 1819 Label L_count_ok; |
1851 __ cmp(O3_scratch, collect_count_constant); | 1820 __ cmp_and_br_short(O3_scratch, collect_count_constant, Assembler::equal, Assembler::pt, L_count_ok); |
1852 __ br(Assembler::equal, false, Assembler::pt, L_count_ok); | |
1853 __ delayed()->nop(); | |
1854 __ stop("bad vminfo in AMH.conv"); | 1821 __ stop("bad vminfo in AMH.conv"); |
1855 __ BIND(L_count_ok); | 1822 __ BIND(L_count_ok); |
1856 BLOCK_COMMENT("} verify collect_count_constant"); | 1823 BLOCK_COMMENT("} verify collect_count_constant"); |
1857 } | 1824 } |
1858 #endif //ASSERT | 1825 #endif //ASSERT |
1895 #ifdef ASSERT | 1862 #ifdef ASSERT |
1896 if (VerifyMethodHandles && dest_slot_constant < 0) { | 1863 if (VerifyMethodHandles && dest_slot_constant < 0) { |
1897 BLOCK_COMMENT("verify dest_slot_constant {"); | 1864 BLOCK_COMMENT("verify dest_slot_constant {"); |
1898 extract_conversion_vminfo(_masm, RicochetFrame::L5_conversion, O3_scratch); | 1865 extract_conversion_vminfo(_masm, RicochetFrame::L5_conversion, O3_scratch); |
1899 Label L_vminfo_ok; | 1866 Label L_vminfo_ok; |
1900 __ cmp(O3_scratch, dest_slot_constant); | 1867 __ cmp_and_br_short(O3_scratch, dest_slot_constant, Assembler::equal, Assembler::pt, L_vminfo_ok); |
1901 __ br(Assembler::equal, false, Assembler::pt, L_vminfo_ok); | |
1902 __ delayed()->nop(); | |
1903 __ stop("bad vminfo in AMH.conv"); | 1868 __ stop("bad vminfo in AMH.conv"); |
1904 __ BIND(L_vminfo_ok); | 1869 __ BIND(L_vminfo_ok); |
1905 BLOCK_COMMENT("} verify dest_slot_constant"); | 1870 BLOCK_COMMENT("} verify dest_slot_constant"); |
1906 } | 1871 } |
1907 #endif //ASSERT | 1872 #endif //ASSERT |
1937 // (As it happens, all movements involve an argument list size change.) | 1902 // (As it happens, all movements involve an argument list size change.) |
1938 | 1903 |
1939 // If there are variable parameters, use dynamic checks to skip around the whole mess. | 1904 // If there are variable parameters, use dynamic checks to skip around the whole mess. |
1940 Label L_done; | 1905 Label L_done; |
1941 if (keep3_count.is_register()) { | 1906 if (keep3_count.is_register()) { |
1942 __ tst(keep3_count.as_register()); | 1907 __ cmp_and_br_short(keep3_count.as_register(), 0, Assembler::equal, Assembler::pn, L_done); |
1943 __ br(Assembler::zero, false, Assembler::pn, L_done); | |
1944 __ delayed()->nop(); | |
1945 } | 1908 } |
1946 if (close_count.is_register()) { | 1909 if (close_count.is_register()) { |
1947 __ cmp(close_count.as_register(), open_count); | 1910 __ cmp_and_br_short(close_count.as_register(), open_count, Assembler::equal, Assembler::pn, L_done); |
1948 __ br(Assembler::equal, false, Assembler::pn, L_done); | |
1949 __ delayed()->nop(); | |
1950 } | 1911 } |
1951 | 1912 |
1952 if (move_keep3 && fix_arg_base) { | 1913 if (move_keep3 && fix_arg_base) { |
1953 bool emit_move_down = false, emit_move_up = false, emit_guard = false; | 1914 bool emit_move_down = false, emit_move_up = false, emit_guard = false; |
1954 if (!close_count.is_constant()) { | 1915 if (!close_count.is_constant()) { |
1985 O4_scratch, G5_scratch); | 1946 O4_scratch, G5_scratch); |
1986 } | 1947 } |
1987 } | 1948 } |
1988 | 1949 |
1989 if (emit_guard) { | 1950 if (emit_guard) { |
1990 __ ba(false, L_done); // assumes emit_move_up is true also | 1951 __ ba_short(L_done); // assumes emit_move_up is true also |
1991 __ delayed()->nop(); | |
1992 __ BIND(L_move_up); | 1952 __ BIND(L_move_up); |
1993 } | 1953 } |
1994 | 1954 |
1995 if (emit_move_up) { | 1955 if (emit_move_up) { |
1996 // Move arguments up if |+dest+| < |-collect-| | 1956 // Move arguments up if |+dest+| < |-collect-| |
2119 __ sll_ptr(O5_dest_type, LogBytesPerWord, O5_dest_type); | 2079 __ sll_ptr(O5_dest_type, LogBytesPerWord, O5_dest_type); |
2120 __ ld_ptr(O7_temp, O5_dest_type, O7_temp); | 2080 __ ld_ptr(O7_temp, O5_dest_type, O7_temp); |
2121 | 2081 |
2122 #ifdef ASSERT | 2082 #ifdef ASSERT |
2123 { Label L_ok; | 2083 { Label L_ok; |
2124 __ br_notnull(O7_temp, false, Assembler::pt, L_ok); | 2084 __ br_notnull_short(O7_temp, Assembler::pt, L_ok); |
2125 __ delayed()->nop(); | |
2126 __ stop("bad method handle return"); | 2085 __ stop("bad method handle return"); |
2127 __ BIND(L_ok); | 2086 __ BIND(L_ok); |
2128 } | 2087 } |
2129 #endif //ASSERT | 2088 #endif //ASSERT |
2130 __ JMP(O7_temp, 0); | 2089 __ JMP(O7_temp, 0); |
2178 if (length_can_be_zero) { | 2137 if (length_can_be_zero) { |
2179 // handle the null pointer case, if zero is allowed | 2138 // handle the null pointer case, if zero is allowed |
2180 Label L_skip; | 2139 Label L_skip; |
2181 if (length_constant < 0) { | 2140 if (length_constant < 0) { |
2182 load_conversion_vminfo(_masm, G3_amh_conversion, O3_scratch); | 2141 load_conversion_vminfo(_masm, G3_amh_conversion, O3_scratch); |
2183 __ br_zero(Assembler::notZero, false, Assembler::pn, O3_scratch, L_skip); | 2142 __ cmp_zero_and_br(Assembler::notZero, O3_scratch, L_skip); |
2184 __ delayed()->nop(); | 2143 __ delayed()->nop(); // to avoid back-to-back cbcond instructions |
2185 } | 2144 } |
2186 __ br_null(O1_array, false, Assembler::pn, L_array_is_empty); | 2145 __ br_null_short(O1_array, Assembler::pn, L_array_is_empty); |
2187 __ delayed()->nop(); | |
2188 __ BIND(L_skip); | 2146 __ BIND(L_skip); |
2189 } | 2147 } |
2190 __ null_check(O1_array, oopDesc::klass_offset_in_bytes()); | 2148 __ null_check(O1_array, oopDesc::klass_offset_in_bytes()); |
2191 __ load_klass(O1_array, O2_array_klass); | 2149 __ load_klass(O1_array, O2_array_klass); |
2192 | 2150 |
2196 load_klass_from_Class(_masm, O3_klass, O4_scratch, G5_scratch); | 2154 load_klass_from_Class(_masm, O3_klass, O4_scratch, G5_scratch); |
2197 | 2155 |
2198 Label L_ok_array_klass, L_bad_array_klass, L_bad_array_length; | 2156 Label L_ok_array_klass, L_bad_array_klass, L_bad_array_length; |
2199 __ check_klass_subtype(O2_array_klass, O3_klass, O4_scratch, G5_scratch, L_ok_array_klass); | 2157 __ check_klass_subtype(O2_array_klass, O3_klass, O4_scratch, G5_scratch, L_ok_array_klass); |
2200 // If we get here, the type check failed! | 2158 // If we get here, the type check failed! |
2201 __ ba(false, L_bad_array_klass); | 2159 __ ba_short(L_bad_array_klass); |
2202 __ delayed()->nop(); | |
2203 __ BIND(L_ok_array_klass); | 2160 __ BIND(L_ok_array_klass); |
2204 | 2161 |
2205 // Check length. | 2162 // Check length. |
2206 if (length_constant >= 0) { | 2163 if (length_constant >= 0) { |
2207 __ ldsw(Address(O1_array, length_offset), O4_scratch); | 2164 __ ldsw(Address(O1_array, length_offset), O4_scratch); |
2233 __ delayed()->nop(); | 2190 __ delayed()->nop(); |
2234 // single argument case, with no array movement | 2191 // single argument case, with no array movement |
2235 __ BIND(L_array_is_empty); | 2192 __ BIND(L_array_is_empty); |
2236 remove_arg_slots(_masm, -stack_move_unit() * array_slots, | 2193 remove_arg_slots(_masm, -stack_move_unit() * array_slots, |
2237 O0_argslot, O1_scratch, O2_scratch, O3_scratch); | 2194 O0_argslot, O1_scratch, O2_scratch, O3_scratch); |
2238 __ ba(false, L_args_done); // no spreading to do | 2195 __ ba_short(L_args_done); // no spreading to do |
2239 __ delayed()->nop(); | |
2240 __ BIND(L_insert_arg_space); | 2196 __ BIND(L_insert_arg_space); |
2241 // come here in the usual case, stack_move < 0 (2 or more spread arguments) | 2197 // come here in the usual case, stack_move < 0 (2 or more spread arguments) |
2242 // Live: O1_array, O2_argslot_limit, O3_stack_move | 2198 // Live: O1_array, O2_argslot_limit, O3_stack_move |
2243 insert_arg_slots(_masm, O3_stack_move, | 2199 insert_arg_slots(_masm, O3_stack_move, |
2244 O0_argslot, O4_scratch, G5_scratch, O1_scratch); | 2200 O0_argslot, O4_scratch, G5_scratch, O1_scratch); |
2275 __ add(O4_fill_ptr, -Interpreter::stackElementSize * elem_slots, O4_fill_ptr); | 2231 __ add(O4_fill_ptr, -Interpreter::stackElementSize * elem_slots, O4_fill_ptr); |
2276 move_typed_arg(_masm, elem_type, true, | 2232 move_typed_arg(_masm, elem_type, true, |
2277 Address(O1_source, 0), Address(O4_fill_ptr, 0), | 2233 Address(O1_source, 0), Address(O4_fill_ptr, 0), |
2278 O2_scratch); // must be an even register for !_LP64 long moves (uses O2/O3) | 2234 O2_scratch); // must be an even register for !_LP64 long moves (uses O2/O3) |
2279 __ add(O1_source, type2aelembytes(elem_type), O1_source); | 2235 __ add(O1_source, type2aelembytes(elem_type), O1_source); |
2280 __ cmp(O4_fill_ptr, O0_argslot); | 2236 __ cmp_and_brx_short(O4_fill_ptr, O0_argslot, Assembler::greaterUnsigned, Assembler::pt, L_loop); |
2281 __ brx(Assembler::greaterUnsigned, false, Assembler::pt, L_loop); | |
2282 __ delayed()->nop(); // FILLME | |
2283 } else if (length_constant == 0) { | 2237 } else if (length_constant == 0) { |
2284 // nothing to copy | 2238 // nothing to copy |
2285 } else { | 2239 } else { |
2286 int elem_offset = elem0_offset; | 2240 int elem_offset = elem0_offset; |
2287 int slot_offset = length_constant * Interpreter::stackElementSize; | 2241 int slot_offset = length_constant * Interpreter::stackElementSize; |