| 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..d121dfb1c493d90eafd7e737cc969ccbff0668fe 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.
|
| + __ sbbq(rax, rcx); // Subtract one if below (aka. carry set).
|
| + __ 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 __
|
|
|