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 |