Chromium Code Reviews| Index: src/x64/code-stubs-x64.cc |
| diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc |
| index 59522d22f9f5f85e5d57a8254b603c150b073d1e..f54fdfc7f7ecc30856d43f7e9de92ff0dedae47b 100644 |
| --- a/src/x64/code-stubs-x64.cc |
| +++ b/src/x64/code-stubs-x64.cc |
| @@ -3248,6 +3248,12 @@ void InstanceofStub::Generate(MacroAssembler* masm) { |
| } |
| +Register InstanceofStub::left() { return rax; } |
| + |
| + |
| +Register InstanceofStub::right() { return rdx; } |
| + |
| + |
| int CompareStub::MinorKey() { |
| // Encode the three parameters in a unique 16 bit value. To avoid duplicate |
| // stubs the never NaN NaN condition is only taken into account if the |
| @@ -4272,22 +4278,119 @@ void StringCompareStub::Generate(MacroAssembler* masm) { |
| } |
| void ICCompareStub::GenerateSmis(MacroAssembler* masm) { |
| - UNIMPLEMENTED(); |
| + ASSERT(state_ == CompareIC::SMIS); |
| + NearLabel miss; |
| + __ JumpIfNotBothSmi(rdx, rax, &miss); |
| + |
| + if (GetCondition() == equal) { |
| + // For equality we do not care about the sign of the result. |
| + __ SmiSub(rax, rax, rdx); |
| + } else { |
| + NearLabel done; |
| + __ SmiSub(rdx, rdx, rax); |
| + __ j(no_overflow, &done); |
| + // Correct sign of result in case of overflow. |
| + __ SmiNot(rdx, rdx); |
| + __ bind(&done); |
| + __ movq(rax, rdx); |
| + } |
| + __ ret(0); |
| + |
| + __ bind(&miss); |
| + GenerateMiss(masm); |
| } |
| void ICCompareStub::GenerateHeapNumbers(MacroAssembler* masm) { |
| - UNIMPLEMENTED(); |
| + ASSERT(state_ == CompareIC::HEAP_NUMBERS); |
| + |
| + NearLabel generic_stub; |
| + NearLabel unordered; |
| + NearLabel miss; |
| + Condition either_smi = masm->CheckEitherSmi(rax, rdx); |
| + __ j(either_smi, &generic_stub); |
| + |
| + __ CmpObjectType(rax, HEAP_NUMBER_TYPE, rcx); |
| + __ j(not_equal, &miss); |
| + __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rcx); |
| + __ j(not_equal, &miss); |
| + |
| + // Load left and right operand |
| + __ movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset)); |
| + __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset)); |
| + |
| + // Compare operands |
| + __ ucomisd(xmm0, xmm1); |
| + |
| + // Don't base result on EFLAGS when a NaN is involved. |
| + __ j(parity_even, &unordered); |
| + |
| + // Return a result of -1, 0, or 1, based on EFLAGS. |
| + // Performing mov, because xor would destroy the flag register. |
| + __ movl(rax, Immediate(0)); |
| + __ movl(rcx, Immediate(0)); |
| + __ setcc(above, rax); // Add one to zero if carry clear and not equal. |
| + __ sbbl(rax, rcx); // Subtract one if below (aka. carry set). |
|
William Hesse
2011/01/18 14:01:50
Should be a 64-bit subtraction, to return a 64-bit
Lasse Reichstein
2011/01/19 09:20:35
Done. Well spotted.
|
| + __ ret(0); |
| + |
| + __ bind(&unordered); |
| + |
| + CompareStub stub(GetCondition(), strict(), NO_COMPARE_FLAGS); |
| + __ bind(&generic_stub); |
| + __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); |
| + |
| + __ bind(&miss); |
| + GenerateMiss(masm); |
| } |
| void ICCompareStub::GenerateObjects(MacroAssembler* masm) { |
| - UNIMPLEMENTED(); |
| + ASSERT(state_ == CompareIC::OBJECTS); |
| + NearLabel miss; |
| + Condition either_smi = masm->CheckEitherSmi(rdx, rax); |
| + __ j(either_smi, &miss); |
| + |
| + __ CmpObjectType(rax, JS_OBJECT_TYPE, rcx); |
| + __ j(not_equal, &miss, not_taken); |
| + __ CmpObjectType(rdx, JS_OBJECT_TYPE, rcx); |
| + __ j(not_equal, &miss, not_taken); |
| + |
| + ASSERT(GetCondition() == equal); |
| + __ subq(rax, rdx); |
| + __ ret(0); |
| + |
| + __ bind(&miss); |
| + GenerateMiss(masm); |
| } |
| void ICCompareStub::GenerateMiss(MacroAssembler* masm) { |
| - UNIMPLEMENTED(); |
| + // Save the registers. |
| + __ pop(rcx); |
| + __ push(rdx); |
| + __ push(rax); |
| + __ push(rcx); |
| + |
| + // Call the runtime system in a fresh internal frame. |
| + ExternalReference miss = ExternalReference(IC_Utility(IC::kCompareIC_Miss)); |
| + __ EnterInternalFrame(); |
| + __ push(rdx); |
| + __ push(rax); |
| + __ Push(Smi::FromInt(op_)); |
| + __ CallExternalReference(miss, 3); |
| + __ LeaveInternalFrame(); |
| + |
| + // Compute the entry point of the rewritten stub. |
| + __ lea(rdi, FieldOperand(rax, Code::kHeaderSize)); |
| + |
| + // Restore registers. |
| + __ pop(rcx); |
| + __ pop(rax); |
| + __ pop(rdx); |
| + __ push(rcx); |
| + |
| + // Do a tail call to the rewritten stub. |
| + __ jmp(rdi); |
| } |
| #undef __ |