504 __ jump(RuntimeAddress(SharedRuntime::deopt_blob()->unpack())); |
504 __ jump(RuntimeAddress(SharedRuntime::deopt_blob()->unpack())); |
505 guarantee(code_offset() - offset <= deopt_handler_size, "overflow"); |
505 guarantee(code_offset() - offset <= deopt_handler_size, "overflow"); |
506 __ end_a_stub(); |
506 __ end_a_stub(); |
507 |
507 |
508 return offset; |
508 return offset; |
509 } |
|
510 |
|
511 |
|
512 // This is the fast version of java.lang.String.compare; it has not |
|
513 // OSR-entry and therefore, we generate a slow version for OSR's |
|
514 void LIR_Assembler::emit_string_compare(LIR_Opr arg0, LIR_Opr arg1, LIR_Opr dst, CodeEmitInfo* info) { |
|
515 __ movptr (rbx, rcx); // receiver is in rcx |
|
516 __ movptr (rax, arg1->as_register()); |
|
517 |
|
518 // Get addresses of first characters from both Strings |
|
519 __ load_heap_oop(rsi, Address(rax, java_lang_String::value_offset_in_bytes())); |
|
520 if (java_lang_String::has_offset_field()) { |
|
521 __ movptr (rcx, Address(rax, java_lang_String::offset_offset_in_bytes())); |
|
522 __ movl (rax, Address(rax, java_lang_String::count_offset_in_bytes())); |
|
523 __ lea (rsi, Address(rsi, rcx, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR))); |
|
524 } else { |
|
525 __ movl (rax, Address(rsi, arrayOopDesc::length_offset_in_bytes())); |
|
526 __ lea (rsi, Address(rsi, arrayOopDesc::base_offset_in_bytes(T_CHAR))); |
|
527 } |
|
528 |
|
529 // rbx, may be NULL |
|
530 add_debug_info_for_null_check_here(info); |
|
531 __ load_heap_oop(rdi, Address(rbx, java_lang_String::value_offset_in_bytes())); |
|
532 if (java_lang_String::has_offset_field()) { |
|
533 __ movptr (rcx, Address(rbx, java_lang_String::offset_offset_in_bytes())); |
|
534 __ movl (rbx, Address(rbx, java_lang_String::count_offset_in_bytes())); |
|
535 __ lea (rdi, Address(rdi, rcx, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR))); |
|
536 } else { |
|
537 __ movl (rbx, Address(rdi, arrayOopDesc::length_offset_in_bytes())); |
|
538 __ lea (rdi, Address(rdi, arrayOopDesc::base_offset_in_bytes(T_CHAR))); |
|
539 } |
|
540 |
|
541 // compute minimum length (in rax) and difference of lengths (on top of stack) |
|
542 __ mov (rcx, rbx); |
|
543 __ subptr(rbx, rax); // subtract lengths |
|
544 __ push (rbx); // result |
|
545 __ cmov (Assembler::lessEqual, rax, rcx); |
|
546 |
|
547 // is minimum length 0? |
|
548 Label noLoop, haveResult; |
|
549 __ testptr (rax, rax); |
|
550 __ jcc (Assembler::zero, noLoop); |
|
551 |
|
552 // compare first characters |
|
553 __ load_unsigned_short(rcx, Address(rdi, 0)); |
|
554 __ load_unsigned_short(rbx, Address(rsi, 0)); |
|
555 __ subl(rcx, rbx); |
|
556 __ jcc(Assembler::notZero, haveResult); |
|
557 // starting loop |
|
558 __ decrement(rax); // we already tested index: skip one |
|
559 __ jcc(Assembler::zero, noLoop); |
|
560 |
|
561 // set rsi.edi to the end of the arrays (arrays have same length) |
|
562 // negate the index |
|
563 |
|
564 __ lea(rsi, Address(rsi, rax, Address::times_2, type2aelembytes(T_CHAR))); |
|
565 __ lea(rdi, Address(rdi, rax, Address::times_2, type2aelembytes(T_CHAR))); |
|
566 __ negptr(rax); |
|
567 |
|
568 // compare the strings in a loop |
|
569 |
|
570 Label loop; |
|
571 __ align(wordSize); |
|
572 __ bind(loop); |
|
573 __ load_unsigned_short(rcx, Address(rdi, rax, Address::times_2, 0)); |
|
574 __ load_unsigned_short(rbx, Address(rsi, rax, Address::times_2, 0)); |
|
575 __ subl(rcx, rbx); |
|
576 __ jcc(Assembler::notZero, haveResult); |
|
577 __ increment(rax); |
|
578 __ jcc(Assembler::notZero, loop); |
|
579 |
|
580 // strings are equal up to min length |
|
581 |
|
582 __ bind(noLoop); |
|
583 __ pop(rax); |
|
584 return_op(LIR_OprFact::illegalOpr); |
|
585 |
|
586 __ bind(haveResult); |
|
587 // leave instruction is going to discard the TOS value |
|
588 __ mov (rax, rcx); // result of call is in rax, |
|
589 } |
509 } |
590 |
510 |
591 |
511 |
592 void LIR_Assembler::return_op(LIR_Opr result) { |
512 void LIR_Assembler::return_op(LIR_Opr result) { |
593 assert(result->is_illegal() || !result->is_single_cpu() || result->as_register() == rax, "word returns are in rax,"); |
513 assert(result->is_illegal() || !result->is_single_cpu() || result->as_register() == rax, "word returns are in rax,"); |