1.1 --- a/src/cpu/x86/vm/x86_64.ad Thu May 29 12:04:14 2008 -0700 1.2 +++ b/src/cpu/x86/vm/x86_64.ad Thu May 29 16:22:09 2008 -0700 1.3 @@ -3808,6 +3808,78 @@ 1.4 masm.bind(DONE_LABEL); 1.5 %} 1.6 1.7 + enc_class enc_Array_Equals(rdi_RegP ary1, rsi_RegP ary2, rax_RegI tmp1, rbx_RegI tmp2, rcx_RegI result) %{ 1.8 + Label TRUE_LABEL, FALSE_LABEL, DONE_LABEL, COMPARE_LOOP_HDR, COMPARE_LOOP; 1.9 + MacroAssembler masm(&cbuf); 1.10 + 1.11 + Register ary1Reg = as_Register($ary1$$reg); 1.12 + Register ary2Reg = as_Register($ary2$$reg); 1.13 + Register tmp1Reg = as_Register($tmp1$$reg); 1.14 + Register tmp2Reg = as_Register($tmp2$$reg); 1.15 + Register resultReg = as_Register($result$$reg); 1.16 + 1.17 + int length_offset = arrayOopDesc::length_offset_in_bytes(); 1.18 + int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); 1.19 + 1.20 + // Check the input args 1.21 + masm.cmpq(ary1Reg, ary2Reg); 1.22 + masm.jcc(Assembler::equal, TRUE_LABEL); 1.23 + masm.testq(ary1Reg, ary1Reg); 1.24 + masm.jcc(Assembler::zero, FALSE_LABEL); 1.25 + masm.testq(ary2Reg, ary2Reg); 1.26 + masm.jcc(Assembler::zero, FALSE_LABEL); 1.27 + 1.28 + // Check the lengths 1.29 + masm.movl(tmp2Reg, Address(ary1Reg, length_offset)); 1.30 + masm.movl(resultReg, Address(ary2Reg, length_offset)); 1.31 + masm.cmpl(tmp2Reg, resultReg); 1.32 + masm.jcc(Assembler::notEqual, FALSE_LABEL); 1.33 + masm.testl(resultReg, resultReg); 1.34 + masm.jcc(Assembler::zero, TRUE_LABEL); 1.35 + 1.36 + // Get the number of 4 byte vectors to compare 1.37 + masm.shrl(resultReg, 1); 1.38 + 1.39 + // Check for odd-length arrays 1.40 + masm.andl(tmp2Reg, 1); 1.41 + masm.testl(tmp2Reg, tmp2Reg); 1.42 + masm.jcc(Assembler::zero, COMPARE_LOOP_HDR); 1.43 + 1.44 + // Compare 2-byte "tail" at end of arrays 1.45 + masm.load_unsigned_word(tmp1Reg, Address(ary1Reg, resultReg, Address::times_4, base_offset)); 1.46 + masm.load_unsigned_word(tmp2Reg, Address(ary2Reg, resultReg, Address::times_4, base_offset)); 1.47 + masm.cmpl(tmp1Reg, tmp2Reg); 1.48 + masm.jcc(Assembler::notEqual, FALSE_LABEL); 1.49 + masm.testl(resultReg, resultReg); 1.50 + masm.jcc(Assembler::zero, TRUE_LABEL); 1.51 + 1.52 + // Setup compare loop 1.53 + masm.bind(COMPARE_LOOP_HDR); 1.54 + // Shift tmp1Reg and tmp2Reg to the last 4-byte boundary of the arrays 1.55 + masm.leaq(tmp1Reg, Address(ary1Reg, resultReg, Address::times_4, base_offset)); 1.56 + masm.leaq(tmp2Reg, Address(ary2Reg, resultReg, Address::times_4, base_offset)); 1.57 + masm.negq(resultReg); 1.58 + 1.59 + // 4-byte-wide compare loop 1.60 + masm.bind(COMPARE_LOOP); 1.61 + masm.movl(ary1Reg, Address(tmp1Reg, resultReg, Address::times_4, 0)); 1.62 + masm.movl(ary2Reg, Address(tmp2Reg, resultReg, Address::times_4, 0)); 1.63 + masm.cmpl(ary1Reg, ary2Reg); 1.64 + masm.jcc(Assembler::notEqual, FALSE_LABEL); 1.65 + masm.incrementq(resultReg); 1.66 + masm.jcc(Assembler::notZero, COMPARE_LOOP); 1.67 + 1.68 + masm.bind(TRUE_LABEL); 1.69 + masm.movl(resultReg, 1); // return true 1.70 + masm.jmp(DONE_LABEL); 1.71 + 1.72 + masm.bind(FALSE_LABEL); 1.73 + masm.xorl(resultReg, resultReg); // return false 1.74 + 1.75 + // That's it 1.76 + masm.bind(DONE_LABEL); 1.77 + %} 1.78 + 1.79 enc_class enc_rethrow() 1.80 %{ 1.81 cbuf.set_inst_mark(); 1.82 @@ -10876,6 +10948,18 @@ 1.83 ins_pipe( pipe_slow ); 1.84 %} 1.85 1.86 +// fast array equals 1.87 +instruct array_equals(rdi_RegP ary1, rsi_RegP ary2, rax_RegI tmp1, 1.88 + rbx_RegI tmp2, rcx_RegI result, rFlagsReg cr) %{ 1.89 + match(Set result (AryEq ary1 ary2)); 1.90 + effect(USE_KILL ary1, USE_KILL ary2, KILL tmp1, KILL tmp2, KILL cr); 1.91 + //ins_cost(300); 1.92 + 1.93 + format %{ "Array Equals $ary1,$ary2 -> $result // KILL RAX, RBX" %} 1.94 + ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, result) ); 1.95 + ins_pipe( pipe_slow ); 1.96 +%} 1.97 + 1.98 //----------Control Flow Instructions------------------------------------------ 1.99 // Signed compare Instructions 1.100