comparison src/cpu/x86/vm/stubGenerator_x86_64.cpp @ 2006:bbefa3ca1543

6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop Reviewed-by: kvn, never
author twisti
date Thu, 02 Dec 2010 01:02:55 -0800
parents f95d63e2154a
children d89a22843c62
comparison
equal deleted inserted replaced
2005:0cb042fd2d4b 2006:bbefa3ca1543
2195 StubCodeMark mark(this, "StubRoutines", name); 2195 StubCodeMark mark(this, "StubRoutines", name);
2196 address start = __ pc(); 2196 address start = __ pc();
2197 2197
2198 __ enter(); // required for proper stackwalking of RuntimeStub frame 2198 __ enter(); // required for proper stackwalking of RuntimeStub frame
2199 2199
2200 checkcast_copy_entry = __ pc();
2201 BLOCK_COMMENT("Entry:");
2202
2203 #ifdef ASSERT 2200 #ifdef ASSERT
2204 // caller guarantees that the arrays really are different 2201 // caller guarantees that the arrays really are different
2205 // otherwise, we would have to make conjoint checks 2202 // otherwise, we would have to make conjoint checks
2206 { Label L; 2203 { Label L;
2207 array_overlap_test(L, TIMES_OOP); 2204 array_overlap_test(L, TIMES_OOP);
2208 __ stop("checkcast_copy within a single array"); 2205 __ stop("checkcast_copy within a single array");
2209 __ bind(L); 2206 __ bind(L);
2210 } 2207 }
2211 #endif //ASSERT 2208 #endif //ASSERT
2212 2209
2213 // allocate spill slots for r13, r14
2214 enum {
2215 saved_r13_offset,
2216 saved_r14_offset,
2217 saved_rbp_offset,
2218 saved_rip_offset,
2219 saved_rarg0_offset
2220 };
2221 __ subptr(rsp, saved_rbp_offset * wordSize);
2222 __ movptr(Address(rsp, saved_r13_offset * wordSize), r13);
2223 __ movptr(Address(rsp, saved_r14_offset * wordSize), r14);
2224 setup_arg_regs(4); // from => rdi, to => rsi, length => rdx 2210 setup_arg_regs(4); // from => rdi, to => rsi, length => rdx
2225 // ckoff => rcx, ckval => r8 2211 // ckoff => rcx, ckval => r8
2226 // r9 and r10 may be used to save non-volatile registers 2212 // r9 and r10 may be used to save non-volatile registers
2227 #ifdef _WIN64 2213 #ifdef _WIN64
2228 // last argument (#4) is on stack on Win64 2214 // last argument (#4) is on stack on Win64
2229 const int ckval_offset = saved_rarg0_offset + 4; 2215 __ movptr(ckval, Address(rsp, 6 * wordSize));
2230 __ movptr(ckval, Address(rsp, ckval_offset * wordSize));
2231 #endif 2216 #endif
2217
2218 // Caller of this entry point must set up the argument registers.
2219 checkcast_copy_entry = __ pc();
2220 BLOCK_COMMENT("Entry:");
2221
2222 // allocate spill slots for r13, r14
2223 enum {
2224 saved_r13_offset,
2225 saved_r14_offset,
2226 saved_rbp_offset
2227 };
2228 __ subptr(rsp, saved_rbp_offset * wordSize);
2229 __ movptr(Address(rsp, saved_r13_offset * wordSize), r13);
2230 __ movptr(Address(rsp, saved_r14_offset * wordSize), r14);
2232 2231
2233 // check that int operands are properly extended to size_t 2232 // check that int operands are properly extended to size_t
2234 assert_clean_int(length, rax); 2233 assert_clean_int(length, rax);
2235 assert_clean_int(ckoff, rax); 2234 assert_clean_int(ckoff, rax);
2236 2235
2441 // Input registers 2440 // Input registers
2442 const Register src = c_rarg0; // source array oop 2441 const Register src = c_rarg0; // source array oop
2443 const Register src_pos = c_rarg1; // source position 2442 const Register src_pos = c_rarg1; // source position
2444 const Register dst = c_rarg2; // destination array oop 2443 const Register dst = c_rarg2; // destination array oop
2445 const Register dst_pos = c_rarg3; // destination position 2444 const Register dst_pos = c_rarg3; // destination position
2446 // elements count is on stack on Win64 2445 #ifndef _WIN64
2447 #ifdef _WIN64 2446 const Register length = c_rarg4;
2448 #define C_RARG4 Address(rsp, 6 * wordSize)
2449 #else 2447 #else
2450 #define C_RARG4 c_rarg4 2448 const Address length(rsp, 6 * wordSize); // elements count is on stack on Win64
2451 #endif 2449 #endif
2452 2450
2453 { int modulus = CodeEntryAlignment; 2451 { int modulus = CodeEntryAlignment;
2454 int target = modulus - 5; // 5 = sizeof jmp(L_failed) 2452 int target = modulus - 5; // 5 = sizeof jmp(L_failed)
2455 int advance = target - (__ offset() % modulus); 2453 int advance = target - (__ offset() % modulus);
2512 guarantee(((j1off ^ j4off) & ~15) != 0, "I$ line of 1st & 4th jumps"); 2510 guarantee(((j1off ^ j4off) & ~15) != 0, "I$ line of 1st & 4th jumps");
2513 2511
2514 // registers used as temp 2512 // registers used as temp
2515 const Register r11_length = r11; // elements count to copy 2513 const Register r11_length = r11; // elements count to copy
2516 const Register r10_src_klass = r10; // array klass 2514 const Register r10_src_klass = r10; // array klass
2517 const Register r9_dst_klass = r9; // dest array klass
2518 2515
2519 // if (length < 0) return -1; 2516 // if (length < 0) return -1;
2520 __ movl(r11_length, C_RARG4); // length (elements count, 32-bits value) 2517 __ movl(r11_length, length); // length (elements count, 32-bits value)
2521 __ testl(r11_length, r11_length); 2518 __ testl(r11_length, r11_length);
2522 __ jccb(Assembler::negative, L_failed_0); 2519 __ jccb(Assembler::negative, L_failed_0);
2523 2520
2524 __ load_klass(r10_src_klass, src); 2521 __ load_klass(r10_src_klass, src);
2525 #ifdef ASSERT 2522 #ifdef ASSERT
2526 // assert(src->klass() != NULL); 2523 // assert(src->klass() != NULL);
2527 BLOCK_COMMENT("assert klasses not null"); 2524 {
2528 { Label L1, L2; 2525 BLOCK_COMMENT("assert klasses not null {");
2526 Label L1, L2;
2529 __ testptr(r10_src_klass, r10_src_klass); 2527 __ testptr(r10_src_klass, r10_src_klass);
2530 __ jcc(Assembler::notZero, L2); // it is broken if klass is NULL 2528 __ jcc(Assembler::notZero, L2); // it is broken if klass is NULL
2531 __ bind(L1); 2529 __ bind(L1);
2532 __ stop("broken null klass"); 2530 __ stop("broken null klass");
2533 __ bind(L2); 2531 __ bind(L2);
2534 __ load_klass(r9_dst_klass, dst); 2532 __ load_klass(rax, dst);
2535 __ cmpq(r9_dst_klass, 0); 2533 __ cmpq(rax, 0);
2536 __ jcc(Assembler::equal, L1); // this would be broken also 2534 __ jcc(Assembler::equal, L1); // this would be broken also
2537 BLOCK_COMMENT("assert done"); 2535 BLOCK_COMMENT("} assert klasses not null done");
2538 } 2536 }
2539 #endif 2537 #endif
2540 2538
2541 // Load layout helper (32-bits) 2539 // Load layout helper (32-bits)
2542 // 2540 //
2544 // 32 30 24 16 8 2 0 2542 // 32 30 24 16 8 2 0
2545 // 2543 //
2546 // array_tag: typeArray = 0x3, objArray = 0x2, non-array = 0x0 2544 // array_tag: typeArray = 0x3, objArray = 0x2, non-array = 0x0
2547 // 2545 //
2548 2546
2549 int lh_offset = klassOopDesc::header_size() * HeapWordSize + 2547 const int lh_offset = klassOopDesc::header_size() * HeapWordSize +
2550 Klass::layout_helper_offset_in_bytes(); 2548 Klass::layout_helper_offset_in_bytes();
2549
2550 // Handle objArrays completely differently...
2551 const jint objArray_lh = Klass::array_layout_helper(T_OBJECT);
2552 __ cmpl(Address(r10_src_klass, lh_offset), objArray_lh);
2553 __ jcc(Assembler::equal, L_objArray);
2554
2555 // if (src->klass() != dst->klass()) return -1;
2556 __ load_klass(rax, dst);
2557 __ cmpq(r10_src_klass, rax);
2558 __ jcc(Assembler::notEqual, L_failed);
2551 2559
2552 const Register rax_lh = rax; // layout helper 2560 const Register rax_lh = rax; // layout helper
2553
2554 __ movl(rax_lh, Address(r10_src_klass, lh_offset)); 2561 __ movl(rax_lh, Address(r10_src_klass, lh_offset));
2555
2556 // Handle objArrays completely differently...
2557 jint objArray_lh = Klass::array_layout_helper(T_OBJECT);
2558 __ cmpl(rax_lh, objArray_lh);
2559 __ jcc(Assembler::equal, L_objArray);
2560
2561 // if (src->klass() != dst->klass()) return -1;
2562 __ load_klass(r9_dst_klass, dst);
2563 __ cmpq(r10_src_klass, r9_dst_klass);
2564 __ jcc(Assembler::notEqual, L_failed);
2565 2562
2566 // if (!src->is_Array()) return -1; 2563 // if (!src->is_Array()) return -1;
2567 __ cmpl(rax_lh, Klass::_lh_neutral_value); 2564 __ cmpl(rax_lh, Klass::_lh_neutral_value);
2568 __ jcc(Assembler::greaterEqual, L_failed); 2565 __ jcc(Assembler::greaterEqual, L_failed);
2569 2566
2570 // At this point, it is known to be a typeArray (array_tag 0x3). 2567 // At this point, it is known to be a typeArray (array_tag 0x3).
2571 #ifdef ASSERT 2568 #ifdef ASSERT
2572 { Label L; 2569 {
2570 BLOCK_COMMENT("assert primitive array {");
2571 Label L;
2573 __ cmpl(rax_lh, (Klass::_lh_array_tag_type_value << Klass::_lh_array_tag_shift)); 2572 __ cmpl(rax_lh, (Klass::_lh_array_tag_type_value << Klass::_lh_array_tag_shift));
2574 __ jcc(Assembler::greaterEqual, L); 2573 __ jcc(Assembler::greaterEqual, L);
2575 __ stop("must be a primitive array"); 2574 __ stop("must be a primitive array");
2576 __ bind(L); 2575 __ bind(L);
2576 BLOCK_COMMENT("} assert primitive array done");
2577 } 2577 }
2578 #endif 2578 #endif
2579 2579
2580 arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length, 2580 arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length,
2581 r10, L_failed); 2581 r10, L_failed);
2629 __ movl2ptr(count, r11_length); // length 2629 __ movl2ptr(count, r11_length); // length
2630 __ jump(RuntimeAddress(int_copy_entry)); 2630 __ jump(RuntimeAddress(int_copy_entry));
2631 2631
2632 __ BIND(L_copy_longs); 2632 __ BIND(L_copy_longs);
2633 #ifdef ASSERT 2633 #ifdef ASSERT
2634 { Label L; 2634 {
2635 BLOCK_COMMENT("assert long copy {");
2636 Label L;
2635 __ cmpl(rax_elsize, LogBytesPerLong); 2637 __ cmpl(rax_elsize, LogBytesPerLong);
2636 __ jcc(Assembler::equal, L); 2638 __ jcc(Assembler::equal, L);
2637 __ stop("must be long copy, but elsize is wrong"); 2639 __ stop("must be long copy, but elsize is wrong");
2638 __ bind(L); 2640 __ bind(L);
2641 BLOCK_COMMENT("} assert long copy done");
2639 } 2642 }
2640 #endif 2643 #endif
2641 __ lea(from, Address(src, src_pos, Address::times_8, 0));// src_addr 2644 __ lea(from, Address(src, src_pos, Address::times_8, 0));// src_addr
2642 __ lea(to, Address(dst, dst_pos, Address::times_8, 0));// dst_addr 2645 __ lea(to, Address(dst, dst_pos, Address::times_8, 0));// dst_addr
2643 __ movl2ptr(count, r11_length); // length 2646 __ movl2ptr(count, r11_length); // length
2644 __ jump(RuntimeAddress(long_copy_entry)); 2647 __ jump(RuntimeAddress(long_copy_entry));
2645 2648
2646 // objArrayKlass 2649 // objArrayKlass
2647 __ BIND(L_objArray); 2650 __ BIND(L_objArray);
2648 // live at this point: r10_src_klass, src[_pos], dst[_pos] 2651 // live at this point: r10_src_klass, r11_length, src[_pos], dst[_pos]
2649 2652
2650 Label L_plain_copy, L_checkcast_copy; 2653 Label L_plain_copy, L_checkcast_copy;
2651 // test array classes for subtyping 2654 // test array classes for subtyping
2652 __ load_klass(r9_dst_klass, dst); 2655 __ load_klass(rax, dst);
2653 __ cmpq(r10_src_klass, r9_dst_klass); // usual case is exact equality 2656 __ cmpq(r10_src_klass, rax); // usual case is exact equality
2654 __ jcc(Assembler::notEqual, L_checkcast_copy); 2657 __ jcc(Assembler::notEqual, L_checkcast_copy);
2655 2658
2656 // Identically typed arrays can be copied without element-wise checks. 2659 // Identically typed arrays can be copied without element-wise checks.
2657 arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length, 2660 arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length,
2658 r10, L_failed); 2661 r10, L_failed);
2664 __ movl2ptr(count, r11_length); // length 2667 __ movl2ptr(count, r11_length); // length
2665 __ BIND(L_plain_copy); 2668 __ BIND(L_plain_copy);
2666 __ jump(RuntimeAddress(oop_copy_entry)); 2669 __ jump(RuntimeAddress(oop_copy_entry));
2667 2670
2668 __ BIND(L_checkcast_copy); 2671 __ BIND(L_checkcast_copy);
2669 // live at this point: r10_src_klass, !r11_length 2672 // live at this point: r10_src_klass, r11_length, rax (dst_klass)
2670 { 2673 {
2671 // assert(r11_length == C_RARG4); // will reload from here
2672 Register r11_dst_klass = r11;
2673 __ load_klass(r11_dst_klass, dst);
2674
2675 // Before looking at dst.length, make sure dst is also an objArray. 2674 // Before looking at dst.length, make sure dst is also an objArray.
2676 __ cmpl(Address(r11_dst_klass, lh_offset), objArray_lh); 2675 __ cmpl(Address(rax, lh_offset), objArray_lh);
2677 __ jcc(Assembler::notEqual, L_failed); 2676 __ jcc(Assembler::notEqual, L_failed);
2678 2677
2679 // It is safe to examine both src.length and dst.length. 2678 // It is safe to examine both src.length and dst.length.
2680 #ifndef _WIN64
2681 arraycopy_range_checks(src, src_pos, dst, dst_pos, C_RARG4,
2682 rax, L_failed);
2683 #else
2684 __ movl(r11_length, C_RARG4); // reload
2685 arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length, 2679 arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length,
2686 rax, L_failed); 2680 rax, L_failed);
2681
2682 const Register r11_dst_klass = r11;
2687 __ load_klass(r11_dst_klass, dst); // reload 2683 __ load_klass(r11_dst_klass, dst); // reload
2688 #endif
2689 2684
2690 // Marshal the base address arguments now, freeing registers. 2685 // Marshal the base address arguments now, freeing registers.
2691 __ lea(from, Address(src, src_pos, TIMES_OOP, 2686 __ lea(from, Address(src, src_pos, TIMES_OOP,
2692 arrayOopDesc::base_offset_in_bytes(T_OBJECT))); 2687 arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
2693 __ lea(to, Address(dst, dst_pos, TIMES_OOP, 2688 __ lea(to, Address(dst, dst_pos, TIMES_OOP,
2694 arrayOopDesc::base_offset_in_bytes(T_OBJECT))); 2689 arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
2695 __ movl(count, C_RARG4); // length (reloaded) 2690 __ movl(count, length); // length (reloaded)
2696 Register sco_temp = c_rarg3; // this register is free now 2691 Register sco_temp = c_rarg3; // this register is free now
2697 assert_different_registers(from, to, count, sco_temp, 2692 assert_different_registers(from, to, count, sco_temp,
2698 r11_dst_klass, r10_src_klass); 2693 r11_dst_klass, r10_src_klass);
2699 assert_clean_int(count, sco_temp); 2694 assert_clean_int(count, sco_temp);
2700 2695
2701 // Generate the type check. 2696 // Generate the type check.
2702 int sco_offset = (klassOopDesc::header_size() * HeapWordSize + 2697 const int sco_offset = (klassOopDesc::header_size() * HeapWordSize +
2703 Klass::super_check_offset_offset_in_bytes()); 2698 Klass::super_check_offset_offset_in_bytes());
2704 __ movl(sco_temp, Address(r11_dst_klass, sco_offset)); 2699 __ movl(sco_temp, Address(r11_dst_klass, sco_offset));
2705 assert_clean_int(sco_temp, rax); 2700 assert_clean_int(sco_temp, rax);
2706 generate_type_check(r10_src_klass, sco_temp, r11_dst_klass, L_plain_copy); 2701 generate_type_check(r10_src_klass, sco_temp, r11_dst_klass, L_plain_copy);
2707 2702
2708 // Fetch destination element klass from the objArrayKlass header. 2703 // Fetch destination element klass from the objArrayKlass header.
2709 int ek_offset = (klassOopDesc::header_size() * HeapWordSize + 2704 int ek_offset = (klassOopDesc::header_size() * HeapWordSize +
2710 objArrayKlass::element_klass_offset_in_bytes()); 2705 objArrayKlass::element_klass_offset_in_bytes());
2711 __ movptr(r11_dst_klass, Address(r11_dst_klass, ek_offset)); 2706 __ movptr(r11_dst_klass, Address(r11_dst_klass, ek_offset));
2712 __ movl(sco_temp, Address(r11_dst_klass, sco_offset)); 2707 __ movl( sco_temp, Address(r11_dst_klass, sco_offset));
2713 assert_clean_int(sco_temp, rax); 2708 assert_clean_int(sco_temp, rax);
2714 2709
2715 // the checkcast_copy loop needs two extra arguments: 2710 // the checkcast_copy loop needs two extra arguments:
2716 assert(c_rarg3 == sco_temp, "#3 already in place"); 2711 assert(c_rarg3 == sco_temp, "#3 already in place");
2717 __ movptr(C_RARG4, r11_dst_klass); // dst.klass.element_klass 2712 // Set up arguments for checkcast_copy_entry.
2713 setup_arg_regs(4);
2714 __ movptr(r8, r11_dst_klass); // dst.klass.element_klass, r8 is c_rarg4 on Linux/Solaris
2718 __ jump(RuntimeAddress(checkcast_copy_entry)); 2715 __ jump(RuntimeAddress(checkcast_copy_entry));
2719 } 2716 }
2720 2717
2721 __ BIND(L_failed); 2718 __ BIND(L_failed);
2722 __ xorptr(rax, rax); 2719 __ xorptr(rax, rax);
2724 __ leave(); // required for proper stackwalking of RuntimeStub frame 2721 __ leave(); // required for proper stackwalking of RuntimeStub frame
2725 __ ret(0); 2722 __ ret(0);
2726 2723
2727 return start; 2724 return start;
2728 } 2725 }
2729
2730 #undef length_arg
2731 2726
2732 void generate_arraycopy_stubs() { 2727 void generate_arraycopy_stubs() {
2733 // Call the conjoint generation methods immediately after 2728 // Call the conjoint generation methods immediately after
2734 // the disjoint ones so that short branches from the former 2729 // the disjoint ones so that short branches from the former
2735 // to the latter can be generated. 2730 // to the latter can be generated.