comparison src/cpu/x86/vm/methodHandles_x86.cpp @ 4874:392a3f07d567

7141637: JSR 292: MH spread invoker crashes with NULL argument on x86_32 Reviewed-by: twisti Contributed-by: Volker Simonis <volker.simonis@gmail.com>
author twisti
date Thu, 02 Feb 2012 09:14:38 -0800
parents 5dbed2f542ff
children 45a1bf98f1bb
comparison
equal deleted inserted replaced
4873:0382d2b469b2 4874:392a3f07d567
2362 __ movl(rax_argslot, rcx_amh_vmargslot); 2362 __ movl(rax_argslot, rcx_amh_vmargslot);
2363 __ lea(rax_argslot, __ argument_address(rax_argslot)); 2363 __ lea(rax_argslot, __ argument_address(rax_argslot));
2364 2364
2365 // grab another temp 2365 // grab another temp
2366 Register rsi_temp = rsi; 2366 Register rsi_temp = rsi;
2367 { if (rsi_temp == saved_last_sp) __ push(saved_last_sp); }
2368 // (preceding push must be done after argslot address is taken!)
2369 #define UNPUSH_RSI \
2370 { if (rsi_temp == saved_last_sp) __ pop(saved_last_sp); }
2371 2367
2372 // arx_argslot points both to the array and to the first output arg 2368 // arx_argslot points both to the array and to the first output arg
2373 vmarg = Address(rax_argslot, 0); 2369 vmarg = Address(rax_argslot, 0);
2374 2370
2375 // Get the array value. 2371 // Get the array value.
2376 Register rsi_array = rsi_temp; 2372 Register rdi_array = rdi_temp;
2377 Register rdx_array_klass = rdx_temp; 2373 Register rdx_array_klass = rdx_temp;
2378 BasicType elem_type = ek_adapter_opt_spread_type(ek); 2374 BasicType elem_type = ek_adapter_opt_spread_type(ek);
2379 int elem_slots = type2size[elem_type]; // 1 or 2 2375 int elem_slots = type2size[elem_type]; // 1 or 2
2380 int array_slots = 1; // array is always a T_OBJECT 2376 int array_slots = 1; // array is always a T_OBJECT
2381 int length_offset = arrayOopDesc::length_offset_in_bytes(); 2377 int length_offset = arrayOopDesc::length_offset_in_bytes();
2382 int elem0_offset = arrayOopDesc::base_offset_in_bytes(elem_type); 2378 int elem0_offset = arrayOopDesc::base_offset_in_bytes(elem_type);
2383 __ movptr(rsi_array, vmarg); 2379 __ movptr(rdi_array, vmarg);
2384 2380
2385 Label L_array_is_empty, L_insert_arg_space, L_copy_args, L_args_done; 2381 Label L_array_is_empty, L_insert_arg_space, L_copy_args, L_args_done;
2386 if (length_can_be_zero) { 2382 if (length_can_be_zero) {
2387 // handle the null pointer case, if zero is allowed 2383 // handle the null pointer case, if zero is allowed
2388 Label L_skip; 2384 Label L_skip;
2389 if (length_constant < 0) { 2385 if (length_constant < 0) {
2390 load_conversion_vminfo(_masm, rbx_temp, rcx_amh_conversion); 2386 load_conversion_vminfo(_masm, rbx_temp, rcx_amh_conversion);
2391 __ testl(rbx_temp, rbx_temp); 2387 __ testl(rbx_temp, rbx_temp);
2392 __ jcc(Assembler::notZero, L_skip); 2388 __ jcc(Assembler::notZero, L_skip);
2393 } 2389 }
2394 __ testptr(rsi_array, rsi_array); 2390 __ testptr(rdi_array, rdi_array);
2395 __ jcc(Assembler::zero, L_array_is_empty); 2391 __ jcc(Assembler::notZero, L_skip);
2392
2393 // If 'rsi' contains the 'saved_last_sp' (this is only the
2394 // case in a 32-bit version of the VM) we have to save 'rsi'
2395 // on the stack because later on (at 'L_array_is_empty') 'rsi'
2396 // will be overwritten.
2397 { if (rsi_temp == saved_last_sp) __ push(saved_last_sp); }
2398 // Also prepare a handy macro which restores 'rsi' if required.
2399 #define UNPUSH_RSI \
2400 { if (rsi_temp == saved_last_sp) __ pop(saved_last_sp); }
2401
2402 __ jmp(L_array_is_empty);
2396 __ bind(L_skip); 2403 __ bind(L_skip);
2397 } 2404 }
2398 __ null_check(rsi_array, oopDesc::klass_offset_in_bytes()); 2405 __ null_check(rdi_array, oopDesc::klass_offset_in_bytes());
2399 __ load_klass(rdx_array_klass, rsi_array); 2406 __ load_klass(rdx_array_klass, rdi_array);
2407
2408 // Save 'rsi' if required (see comment above). Do this only
2409 // after the null check such that the exception handler which is
2410 // called in the case of a null pointer exception will not be
2411 // confused by the extra value on the stack (it expects the
2412 // return pointer on top of the stack)
2413 { if (rsi_temp == saved_last_sp) __ push(saved_last_sp); }
2400 2414
2401 // Check the array type. 2415 // Check the array type.
2402 Register rbx_klass = rbx_temp; 2416 Register rbx_klass = rbx_temp;
2403 __ load_heap_oop(rbx_klass, rcx_amh_argument); // this is a Class object! 2417 __ load_heap_oop(rbx_klass, rcx_amh_argument); // this is a Class object!
2404 load_klass_from_Class(_masm, rbx_klass); 2418 load_klass_from_Class(_masm, rbx_klass);
2405 2419
2406 Label ok_array_klass, bad_array_klass, bad_array_length; 2420 Label ok_array_klass, bad_array_klass, bad_array_length;
2407 __ check_klass_subtype(rdx_array_klass, rbx_klass, rdi_temp, ok_array_klass); 2421 __ check_klass_subtype(rdx_array_klass, rbx_klass, rsi_temp, ok_array_klass);
2408 // If we get here, the type check failed! 2422 // If we get here, the type check failed!
2409 __ jmp(bad_array_klass); 2423 __ jmp(bad_array_klass);
2410 __ BIND(ok_array_klass); 2424 __ BIND(ok_array_klass);
2411 2425
2412 // Check length. 2426 // Check length.
2413 if (length_constant >= 0) { 2427 if (length_constant >= 0) {
2414 __ cmpl(Address(rsi_array, length_offset), length_constant); 2428 __ cmpl(Address(rdi_array, length_offset), length_constant);
2415 } else { 2429 } else {
2416 Register rbx_vminfo = rbx_temp; 2430 Register rbx_vminfo = rbx_temp;
2417 load_conversion_vminfo(_masm, rbx_vminfo, rcx_amh_conversion); 2431 load_conversion_vminfo(_masm, rbx_vminfo, rcx_amh_conversion);
2418 __ cmpl(rbx_vminfo, Address(rsi_array, length_offset)); 2432 __ cmpl(rbx_vminfo, Address(rdi_array, length_offset));
2419 } 2433 }
2420 __ jcc(Assembler::notEqual, bad_array_length); 2434 __ jcc(Assembler::notEqual, bad_array_length);
2421 2435
2422 Register rdx_argslot_limit = rdx_temp; 2436 Register rdx_argslot_limit = rdx_temp;
2423 2437
2425 if (length_constant == -1) { 2439 if (length_constant == -1) {
2426 // Form a pointer to the end of the affected region. 2440 // Form a pointer to the end of the affected region.
2427 __ lea(rdx_argslot_limit, Address(rax_argslot, Interpreter::stackElementSize)); 2441 __ lea(rdx_argslot_limit, Address(rax_argslot, Interpreter::stackElementSize));
2428 // 'stack_move' is negative number of words to insert 2442 // 'stack_move' is negative number of words to insert
2429 // This number already accounts for elem_slots. 2443 // This number already accounts for elem_slots.
2430 Register rdi_stack_move = rdi_temp; 2444 Register rsi_stack_move = rsi_temp;
2431 load_stack_move(_masm, rdi_stack_move, rcx_recv, true); 2445 load_stack_move(_masm, rsi_stack_move, rcx_recv, true);
2432 __ cmpptr(rdi_stack_move, 0); 2446 __ cmpptr(rsi_stack_move, 0);
2433 assert(stack_move_unit() < 0, "else change this comparison"); 2447 assert(stack_move_unit() < 0, "else change this comparison");
2434 __ jcc(Assembler::less, L_insert_arg_space); 2448 __ jcc(Assembler::less, L_insert_arg_space);
2435 __ jcc(Assembler::equal, L_copy_args); 2449 __ jcc(Assembler::equal, L_copy_args);
2436 // single argument case, with no array movement 2450 // single argument case, with no array movement
2437 __ BIND(L_array_is_empty); 2451 __ BIND(L_array_is_empty);
2438 remove_arg_slots(_masm, -stack_move_unit() * array_slots, 2452 remove_arg_slots(_masm, -stack_move_unit() * array_slots,
2439 rax_argslot, rbx_temp, rdx_temp); 2453 rax_argslot, rbx_temp, rdx_temp);
2440 __ jmp(L_args_done); // no spreading to do 2454 __ jmp(L_args_done); // no spreading to do
2441 __ BIND(L_insert_arg_space); 2455 __ BIND(L_insert_arg_space);
2442 // come here in the usual case, stack_move < 0 (2 or more spread arguments) 2456 // come here in the usual case, stack_move < 0 (2 or more spread arguments)
2443 Register rsi_temp = rsi_array; // spill this 2457 Register rdi_temp = rdi_array; // spill this
2444 insert_arg_slots(_masm, rdi_stack_move, 2458 insert_arg_slots(_masm, rsi_stack_move,
2445 rax_argslot, rbx_temp, rsi_temp); 2459 rax_argslot, rbx_temp, rdi_temp);
2446 // reload the array since rsi was killed 2460 // reload the array since rsi was killed
2447 // reload from rdx_argslot_limit since rax_argslot is now decremented 2461 // reload from rdx_argslot_limit since rax_argslot is now decremented
2448 __ movptr(rsi_array, Address(rdx_argslot_limit, -Interpreter::stackElementSize)); 2462 __ movptr(rdi_array, Address(rdx_argslot_limit, -Interpreter::stackElementSize));
2449 } else if (length_constant >= 1) { 2463 } else if (length_constant >= 1) {
2450 int new_slots = (length_constant * elem_slots) - array_slots; 2464 int new_slots = (length_constant * elem_slots) - array_slots;
2451 insert_arg_slots(_masm, new_slots * stack_move_unit(), 2465 insert_arg_slots(_masm, new_slots * stack_move_unit(),
2452 rax_argslot, rbx_temp, rdx_temp); 2466 rax_argslot, rbx_temp, rdx_temp);
2453 } else if (length_constant == 0) { 2467 } else if (length_constant == 0) {
2466 // elementwise in reverse order from the source array. 2480 // elementwise in reverse order from the source array.
2467 __ BIND(L_copy_args); 2481 __ BIND(L_copy_args);
2468 if (length_constant == -1) { 2482 if (length_constant == -1) {
2469 // [rax_argslot, rdx_argslot_limit) is the area we are inserting into. 2483 // [rax_argslot, rdx_argslot_limit) is the area we are inserting into.
2470 // Array element [0] goes at rdx_argslot_limit[-wordSize]. 2484 // Array element [0] goes at rdx_argslot_limit[-wordSize].
2471 Register rsi_source = rsi_array; 2485 Register rdi_source = rdi_array;
2472 __ lea(rsi_source, Address(rsi_array, elem0_offset)); 2486 __ lea(rdi_source, Address(rdi_array, elem0_offset));
2473 Register rdx_fill_ptr = rdx_argslot_limit; 2487 Register rdx_fill_ptr = rdx_argslot_limit;
2474 Label loop; 2488 Label loop;
2475 __ BIND(loop); 2489 __ BIND(loop);
2476 __ addptr(rdx_fill_ptr, -Interpreter::stackElementSize * elem_slots); 2490 __ addptr(rdx_fill_ptr, -Interpreter::stackElementSize * elem_slots);
2477 move_typed_arg(_masm, elem_type, true, 2491 move_typed_arg(_masm, elem_type, true,
2478 Address(rdx_fill_ptr, 0), Address(rsi_source, 0), 2492 Address(rdx_fill_ptr, 0), Address(rdi_source, 0),
2479 rbx_temp, rdi_temp); 2493 rbx_temp, rsi_temp);
2480 __ addptr(rsi_source, type2aelembytes(elem_type)); 2494 __ addptr(rdi_source, type2aelembytes(elem_type));
2481 __ cmpptr(rdx_fill_ptr, rax_argslot); 2495 __ cmpptr(rdx_fill_ptr, rax_argslot);
2482 __ jcc(Assembler::above, loop); 2496 __ jcc(Assembler::above, loop);
2483 } else if (length_constant == 0) { 2497 } else if (length_constant == 0) {
2484 // nothing to copy 2498 // nothing to copy
2485 } else { 2499 } else {
2486 int elem_offset = elem0_offset; 2500 int elem_offset = elem0_offset;
2487 int slot_offset = length_constant * Interpreter::stackElementSize; 2501 int slot_offset = length_constant * Interpreter::stackElementSize;
2488 for (int index = 0; index < length_constant; index++) { 2502 for (int index = 0; index < length_constant; index++) {
2489 slot_offset -= Interpreter::stackElementSize * elem_slots; // fill backward 2503 slot_offset -= Interpreter::stackElementSize * elem_slots; // fill backward
2490 move_typed_arg(_masm, elem_type, true, 2504 move_typed_arg(_masm, elem_type, true,
2491 Address(rax_argslot, slot_offset), Address(rsi_array, elem_offset), 2505 Address(rax_argslot, slot_offset), Address(rdi_array, elem_offset),
2492 rbx_temp, rdi_temp); 2506 rbx_temp, rsi_temp);
2493 elem_offset += type2aelembytes(elem_type); 2507 elem_offset += type2aelembytes(elem_type);
2494 } 2508 }
2495 } 2509 }
2496 __ BIND(L_args_done); 2510 __ BIND(L_args_done);
2497 2511