comparison src/cpu/x86/vm/c1_LIRAssembler_x86.cpp @ 3739:28263a73ebfb

7047491: C1: registers saved incorrectly when calling checkcast_arraycopy stub Summary: Save and restore the argument registers around the call to checkcast_arraycopy Reviewed-by: never, roland
author iveresov
date Thu, 26 May 2011 13:15:01 -0700
parents ccf072cdba91
children c124e2e7463e
comparison
equal deleted inserted replaced
3738:c7c81f18c834 3739:28263a73ebfb
3111 // For the moment until C1 gets the new register allocator I just force all the 3111 // For the moment until C1 gets the new register allocator I just force all the
3112 // args to the right place (except the register args) and then on the back side 3112 // args to the right place (except the register args) and then on the back side
3113 // reload the register args properly if we go slow path. Yuck 3113 // reload the register args properly if we go slow path. Yuck
3114 3114
3115 // These are proper for the calling convention 3115 // These are proper for the calling convention
3116
3117 store_parameter(length, 2); 3116 store_parameter(length, 2);
3118 store_parameter(dst_pos, 1); 3117 store_parameter(dst_pos, 1);
3119 store_parameter(dst, 0); 3118 store_parameter(dst, 0);
3120 3119
3121 // these are just temporary placements until we need to reload 3120 // these are just temporary placements until we need to reload
3349 jint objArray_lh = Klass::array_layout_helper(T_OBJECT); 3348 jint objArray_lh = Klass::array_layout_helper(T_OBJECT);
3350 __ cmpl(klass_lh_addr, objArray_lh); 3349 __ cmpl(klass_lh_addr, objArray_lh);
3351 __ jcc(Assembler::notEqual, *stub->entry()); 3350 __ jcc(Assembler::notEqual, *stub->entry());
3352 } 3351 }
3353 3352
3353 // Spill because stubs can use any register they like and it's
3354 // easier to restore just those that we care about.
3355 store_parameter(dst, 0);
3356 store_parameter(dst_pos, 1);
3357 store_parameter(length, 2);
3358 store_parameter(src_pos, 3);
3359 store_parameter(src, 4);
3360
3354 #ifndef _LP64 3361 #ifndef _LP64
3355 // save caller save registers
3356 store_parameter(rax, 2);
3357 store_parameter(rcx, 1);
3358 store_parameter(rdx, 0);
3359
3360 __ movptr(tmp, dst_klass_addr); 3362 __ movptr(tmp, dst_klass_addr);
3361 __ movptr(tmp, Address(tmp, objArrayKlass::element_klass_offset_in_bytes() + sizeof(oopDesc))); 3363 __ movptr(tmp, Address(tmp, objArrayKlass::element_klass_offset_in_bytes() + sizeof(oopDesc)));
3362 __ push(tmp); 3364 __ push(tmp);
3363 __ movl(tmp, Address(tmp, Klass::super_check_offset_offset_in_bytes() + sizeof(oopDesc))); 3365 __ movl(tmp, Address(tmp, Klass::super_check_offset_offset_in_bytes() + sizeof(oopDesc)));
3364 __ push(tmp); 3366 __ push(tmp);
3369 __ push(tmp); 3371 __ push(tmp);
3370 3372
3371 __ call_VM_leaf(copyfunc_addr, 5); 3373 __ call_VM_leaf(copyfunc_addr, 5);
3372 #else 3374 #else
3373 __ movl2ptr(length, length); //higher 32bits must be null 3375 __ movl2ptr(length, length); //higher 32bits must be null
3374
3375 // save caller save registers: copy them to callee save registers
3376 __ mov(rbx, rdx);
3377 __ mov(r13, r8);
3378 __ mov(r14, r9);
3379 #ifndef _WIN64
3380 store_parameter(rsi, 1);
3381 store_parameter(rcx, 0);
3382 // on WIN64 other incoming parameters are in rdi and rsi saved
3383 // across the call
3384 #endif
3385 3376
3386 __ lea(c_rarg0, Address(src, src_pos, scale, arrayOopDesc::base_offset_in_bytes(basic_type))); 3377 __ lea(c_rarg0, Address(src, src_pos, scale, arrayOopDesc::base_offset_in_bytes(basic_type)));
3387 assert_different_registers(c_rarg0, dst, dst_pos, length); 3378 assert_different_registers(c_rarg0, dst, dst_pos, length);
3388 __ lea(c_rarg1, Address(dst, dst_pos, scale, arrayOopDesc::base_offset_in_bytes(basic_type))); 3379 __ lea(c_rarg1, Address(dst, dst_pos, scale, arrayOopDesc::base_offset_in_bytes(basic_type)));
3389 assert_different_registers(c_rarg1, dst, length); 3380 assert_different_registers(c_rarg1, dst, length);
3430 3421
3431 __ mov(tmp, rax); 3422 __ mov(tmp, rax);
3432 3423
3433 __ xorl(tmp, -1); 3424 __ xorl(tmp, -1);
3434 3425
3435 #ifndef _LP64 3426 // Restore previously spilled arguments
3436 // restore caller save registers 3427 __ movptr (dst, Address(rsp, 0*BytesPerWord));
3437 assert_different_registers(tmp, rdx, rcx, rax); // result of stub will be lost 3428 __ movptr (dst_pos, Address(rsp, 1*BytesPerWord));
3438 __ movptr(rdx, Address(rsp, 0*BytesPerWord)); 3429 __ movptr (length, Address(rsp, 2*BytesPerWord));
3439 __ movptr(rcx, Address(rsp, 1*BytesPerWord)); 3430 __ movptr (src_pos, Address(rsp, 3*BytesPerWord));
3440 __ movptr(rax, Address(rsp, 2*BytesPerWord)); 3431 __ movptr (src, Address(rsp, 4*BytesPerWord));
3441 #else 3432
3442 // restore caller save registers
3443 __ mov(rdx, rbx);
3444 __ mov(r8, r13);
3445 __ mov(r9, r14);
3446 #ifndef _WIN64
3447 assert_different_registers(tmp, rdx, r8, r9, rcx, rsi); // result of stub will be lost
3448 __ movptr(rcx, Address(rsp, 0*BytesPerWord));
3449 __ movptr(rsi, Address(rsp, 1*BytesPerWord));
3450 #else
3451 assert_different_registers(tmp, rdx, r8, r9); // result of stub will be lost
3452 #endif
3453 #endif
3454 3433
3455 __ subl(length, tmp); 3434 __ subl(length, tmp);
3456 __ addl(src_pos, tmp); 3435 __ addl(src_pos, tmp);
3457 __ addl(dst_pos, tmp); 3436 __ addl(dst_pos, tmp);
3458 } 3437 }