OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_IA32 | 7 #if V8_TARGET_ARCH_IA32 |
8 | 8 |
9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
(...skipping 1558 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1569 __ test(scratch, Immediate(kIsNotStringMask | kIsNotInternalizedMask)); | 1569 __ test(scratch, Immediate(kIsNotStringMask | kIsNotInternalizedMask)); |
1570 __ j(not_zero, label); | 1570 __ j(not_zero, label); |
1571 } | 1571 } |
1572 | 1572 |
1573 | 1573 |
1574 void ICCompareStub::GenerateGeneric(MacroAssembler* masm) { | 1574 void ICCompareStub::GenerateGeneric(MacroAssembler* masm) { |
1575 Label check_unequal_objects; | 1575 Label check_unequal_objects; |
1576 Condition cc = GetCondition(); | 1576 Condition cc = GetCondition(); |
1577 | 1577 |
1578 Label miss; | 1578 Label miss; |
1579 CheckInputType(masm, edx, left_, &miss); | 1579 CheckInputType(masm, edx, left(), &miss); |
1580 CheckInputType(masm, eax, right_, &miss); | 1580 CheckInputType(masm, eax, right(), &miss); |
1581 | 1581 |
1582 // Compare two smis. | 1582 // Compare two smis. |
1583 Label non_smi, smi_done; | 1583 Label non_smi, smi_done; |
1584 __ mov(ecx, edx); | 1584 __ mov(ecx, edx); |
1585 __ or_(ecx, eax); | 1585 __ or_(ecx, eax); |
1586 __ JumpIfNotSmi(ecx, &non_smi, Label::kNear); | 1586 __ JumpIfNotSmi(ecx, &non_smi, Label::kNear); |
1587 __ sub(edx, eax); // Return on the result of the subtraction. | 1587 __ sub(edx, eax); // Return on the result of the subtraction. |
1588 __ j(no_overflow, &smi_done, Label::kNear); | 1588 __ j(no_overflow, &smi_done, Label::kNear); |
1589 __ not_(edx); // Correct sign in case of overflow. edx is never 0 here. | 1589 __ not_(edx); // Correct sign in case of overflow. edx is never 0 here. |
1590 __ bind(&smi_done); | 1590 __ bind(&smi_done); |
(...skipping 1797 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3388 } | 3388 } |
3389 | 3389 |
3390 // Tail call into the stub that handles binary operations with allocation | 3390 // Tail call into the stub that handles binary operations with allocation |
3391 // sites. | 3391 // sites. |
3392 BinaryOpWithAllocationSiteStub stub(isolate(), state()); | 3392 BinaryOpWithAllocationSiteStub stub(isolate(), state()); |
3393 __ TailCallStub(&stub); | 3393 __ TailCallStub(&stub); |
3394 } | 3394 } |
3395 | 3395 |
3396 | 3396 |
3397 void ICCompareStub::GenerateSmis(MacroAssembler* masm) { | 3397 void ICCompareStub::GenerateSmis(MacroAssembler* masm) { |
3398 DCHECK(state_ == CompareIC::SMI); | 3398 DCHECK(state() == CompareIC::SMI); |
3399 Label miss; | 3399 Label miss; |
3400 __ mov(ecx, edx); | 3400 __ mov(ecx, edx); |
3401 __ or_(ecx, eax); | 3401 __ or_(ecx, eax); |
3402 __ JumpIfNotSmi(ecx, &miss, Label::kNear); | 3402 __ JumpIfNotSmi(ecx, &miss, Label::kNear); |
3403 | 3403 |
3404 if (GetCondition() == equal) { | 3404 if (GetCondition() == equal) { |
3405 // For equality we do not care about the sign of the result. | 3405 // For equality we do not care about the sign of the result. |
3406 __ sub(eax, edx); | 3406 __ sub(eax, edx); |
3407 } else { | 3407 } else { |
3408 Label done; | 3408 Label done; |
3409 __ sub(edx, eax); | 3409 __ sub(edx, eax); |
3410 __ j(no_overflow, &done, Label::kNear); | 3410 __ j(no_overflow, &done, Label::kNear); |
3411 // Correct sign of result in case of overflow. | 3411 // Correct sign of result in case of overflow. |
3412 __ not_(edx); | 3412 __ not_(edx); |
3413 __ bind(&done); | 3413 __ bind(&done); |
3414 __ mov(eax, edx); | 3414 __ mov(eax, edx); |
3415 } | 3415 } |
3416 __ ret(0); | 3416 __ ret(0); |
3417 | 3417 |
3418 __ bind(&miss); | 3418 __ bind(&miss); |
3419 GenerateMiss(masm); | 3419 GenerateMiss(masm); |
3420 } | 3420 } |
3421 | 3421 |
3422 | 3422 |
3423 void ICCompareStub::GenerateNumbers(MacroAssembler* masm) { | 3423 void ICCompareStub::GenerateNumbers(MacroAssembler* masm) { |
3424 DCHECK(state_ == CompareIC::NUMBER); | 3424 DCHECK(state() == CompareIC::NUMBER); |
3425 | 3425 |
3426 Label generic_stub; | 3426 Label generic_stub; |
3427 Label unordered, maybe_undefined1, maybe_undefined2; | 3427 Label unordered, maybe_undefined1, maybe_undefined2; |
3428 Label miss; | 3428 Label miss; |
3429 | 3429 |
3430 if (left_ == CompareIC::SMI) { | 3430 if (left() == CompareIC::SMI) { |
3431 __ JumpIfNotSmi(edx, &miss); | 3431 __ JumpIfNotSmi(edx, &miss); |
3432 } | 3432 } |
3433 if (right_ == CompareIC::SMI) { | 3433 if (right() == CompareIC::SMI) { |
3434 __ JumpIfNotSmi(eax, &miss); | 3434 __ JumpIfNotSmi(eax, &miss); |
3435 } | 3435 } |
3436 | 3436 |
3437 // Load left and right operand. | 3437 // Load left and right operand. |
3438 Label done, left, left_smi, right_smi; | 3438 Label done, left, left_smi, right_smi; |
3439 __ JumpIfSmi(eax, &right_smi, Label::kNear); | 3439 __ JumpIfSmi(eax, &right_smi, Label::kNear); |
3440 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), | 3440 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), |
3441 isolate()->factory()->heap_number_map()); | 3441 isolate()->factory()->heap_number_map()); |
3442 __ j(not_equal, &maybe_undefined1, Label::kNear); | 3442 __ j(not_equal, &maybe_undefined1, Label::kNear); |
3443 __ movsd(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); | 3443 __ movsd(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); |
(...skipping 26 matching lines...) Expand all Loading... |
3470 // Performing mov, because xor would destroy the flag register. | 3470 // Performing mov, because xor would destroy the flag register. |
3471 __ mov(eax, 0); // equal | 3471 __ mov(eax, 0); // equal |
3472 __ mov(ecx, Immediate(Smi::FromInt(1))); | 3472 __ mov(ecx, Immediate(Smi::FromInt(1))); |
3473 __ cmov(above, eax, ecx); | 3473 __ cmov(above, eax, ecx); |
3474 __ mov(ecx, Immediate(Smi::FromInt(-1))); | 3474 __ mov(ecx, Immediate(Smi::FromInt(-1))); |
3475 __ cmov(below, eax, ecx); | 3475 __ cmov(below, eax, ecx); |
3476 __ ret(0); | 3476 __ ret(0); |
3477 | 3477 |
3478 __ bind(&unordered); | 3478 __ bind(&unordered); |
3479 __ bind(&generic_stub); | 3479 __ bind(&generic_stub); |
3480 ICCompareStub stub(isolate(), op_, CompareIC::GENERIC, CompareIC::GENERIC, | 3480 ICCompareStub stub(isolate(), op(), CompareIC::GENERIC, CompareIC::GENERIC, |
3481 CompareIC::GENERIC); | 3481 CompareIC::GENERIC); |
3482 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); | 3482 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); |
3483 | 3483 |
3484 __ bind(&maybe_undefined1); | 3484 __ bind(&maybe_undefined1); |
3485 if (Token::IsOrderedRelationalCompareOp(op_)) { | 3485 if (Token::IsOrderedRelationalCompareOp(op())) { |
3486 __ cmp(eax, Immediate(isolate()->factory()->undefined_value())); | 3486 __ cmp(eax, Immediate(isolate()->factory()->undefined_value())); |
3487 __ j(not_equal, &miss); | 3487 __ j(not_equal, &miss); |
3488 __ JumpIfSmi(edx, &unordered); | 3488 __ JumpIfSmi(edx, &unordered); |
3489 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ecx); | 3489 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ecx); |
3490 __ j(not_equal, &maybe_undefined2, Label::kNear); | 3490 __ j(not_equal, &maybe_undefined2, Label::kNear); |
3491 __ jmp(&unordered); | 3491 __ jmp(&unordered); |
3492 } | 3492 } |
3493 | 3493 |
3494 __ bind(&maybe_undefined2); | 3494 __ bind(&maybe_undefined2); |
3495 if (Token::IsOrderedRelationalCompareOp(op_)) { | 3495 if (Token::IsOrderedRelationalCompareOp(op())) { |
3496 __ cmp(edx, Immediate(isolate()->factory()->undefined_value())); | 3496 __ cmp(edx, Immediate(isolate()->factory()->undefined_value())); |
3497 __ j(equal, &unordered); | 3497 __ j(equal, &unordered); |
3498 } | 3498 } |
3499 | 3499 |
3500 __ bind(&miss); | 3500 __ bind(&miss); |
3501 GenerateMiss(masm); | 3501 GenerateMiss(masm); |
3502 } | 3502 } |
3503 | 3503 |
3504 | 3504 |
3505 void ICCompareStub::GenerateInternalizedStrings(MacroAssembler* masm) { | 3505 void ICCompareStub::GenerateInternalizedStrings(MacroAssembler* masm) { |
3506 DCHECK(state_ == CompareIC::INTERNALIZED_STRING); | 3506 DCHECK(state() == CompareIC::INTERNALIZED_STRING); |
3507 DCHECK(GetCondition() == equal); | 3507 DCHECK(GetCondition() == equal); |
3508 | 3508 |
3509 // Registers containing left and right operands respectively. | 3509 // Registers containing left and right operands respectively. |
3510 Register left = edx; | 3510 Register left = edx; |
3511 Register right = eax; | 3511 Register right = eax; |
3512 Register tmp1 = ecx; | 3512 Register tmp1 = ecx; |
3513 Register tmp2 = ebx; | 3513 Register tmp2 = ebx; |
3514 | 3514 |
3515 // Check that both operands are heap objects. | 3515 // Check that both operands are heap objects. |
3516 Label miss; | 3516 Label miss; |
(...skipping 24 matching lines...) Expand all Loading... |
3541 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); | 3541 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); |
3542 __ bind(&done); | 3542 __ bind(&done); |
3543 __ ret(0); | 3543 __ ret(0); |
3544 | 3544 |
3545 __ bind(&miss); | 3545 __ bind(&miss); |
3546 GenerateMiss(masm); | 3546 GenerateMiss(masm); |
3547 } | 3547 } |
3548 | 3548 |
3549 | 3549 |
3550 void ICCompareStub::GenerateUniqueNames(MacroAssembler* masm) { | 3550 void ICCompareStub::GenerateUniqueNames(MacroAssembler* masm) { |
3551 DCHECK(state_ == CompareIC::UNIQUE_NAME); | 3551 DCHECK(state() == CompareIC::UNIQUE_NAME); |
3552 DCHECK(GetCondition() == equal); | 3552 DCHECK(GetCondition() == equal); |
3553 | 3553 |
3554 // Registers containing left and right operands respectively. | 3554 // Registers containing left and right operands respectively. |
3555 Register left = edx; | 3555 Register left = edx; |
3556 Register right = eax; | 3556 Register right = eax; |
3557 Register tmp1 = ecx; | 3557 Register tmp1 = ecx; |
3558 Register tmp2 = ebx; | 3558 Register tmp2 = ebx; |
3559 | 3559 |
3560 // Check that both operands are heap objects. | 3560 // Check that both operands are heap objects. |
3561 Label miss; | 3561 Label miss; |
(...skipping 24 matching lines...) Expand all Loading... |
3586 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); | 3586 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); |
3587 __ bind(&done); | 3587 __ bind(&done); |
3588 __ ret(0); | 3588 __ ret(0); |
3589 | 3589 |
3590 __ bind(&miss); | 3590 __ bind(&miss); |
3591 GenerateMiss(masm); | 3591 GenerateMiss(masm); |
3592 } | 3592 } |
3593 | 3593 |
3594 | 3594 |
3595 void ICCompareStub::GenerateStrings(MacroAssembler* masm) { | 3595 void ICCompareStub::GenerateStrings(MacroAssembler* masm) { |
3596 DCHECK(state_ == CompareIC::STRING); | 3596 DCHECK(state() == CompareIC::STRING); |
3597 Label miss; | 3597 Label miss; |
3598 | 3598 |
3599 bool equality = Token::IsEqualityOp(op_); | 3599 bool equality = Token::IsEqualityOp(op()); |
3600 | 3600 |
3601 // Registers containing left and right operands respectively. | 3601 // Registers containing left and right operands respectively. |
3602 Register left = edx; | 3602 Register left = edx; |
3603 Register right = eax; | 3603 Register right = eax; |
3604 Register tmp1 = ecx; | 3604 Register tmp1 = ecx; |
3605 Register tmp2 = ebx; | 3605 Register tmp2 = ebx; |
3606 Register tmp3 = edi; | 3606 Register tmp3 = edi; |
3607 | 3607 |
3608 // Check that both operands are heap objects. | 3608 // Check that both operands are heap objects. |
3609 __ mov(tmp1, left); | 3609 __ mov(tmp1, left); |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3676 } else { | 3676 } else { |
3677 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 3677 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
3678 } | 3678 } |
3679 | 3679 |
3680 __ bind(&miss); | 3680 __ bind(&miss); |
3681 GenerateMiss(masm); | 3681 GenerateMiss(masm); |
3682 } | 3682 } |
3683 | 3683 |
3684 | 3684 |
3685 void ICCompareStub::GenerateObjects(MacroAssembler* masm) { | 3685 void ICCompareStub::GenerateObjects(MacroAssembler* masm) { |
3686 DCHECK(state_ == CompareIC::OBJECT); | 3686 DCHECK(state() == CompareIC::OBJECT); |
3687 Label miss; | 3687 Label miss; |
3688 __ mov(ecx, edx); | 3688 __ mov(ecx, edx); |
3689 __ and_(ecx, eax); | 3689 __ and_(ecx, eax); |
3690 __ JumpIfSmi(ecx, &miss, Label::kNear); | 3690 __ JumpIfSmi(ecx, &miss, Label::kNear); |
3691 | 3691 |
3692 __ CmpObjectType(eax, JS_OBJECT_TYPE, ecx); | 3692 __ CmpObjectType(eax, JS_OBJECT_TYPE, ecx); |
3693 __ j(not_equal, &miss, Label::kNear); | 3693 __ j(not_equal, &miss, Label::kNear); |
3694 __ CmpObjectType(edx, JS_OBJECT_TYPE, ecx); | 3694 __ CmpObjectType(edx, JS_OBJECT_TYPE, ecx); |
3695 __ j(not_equal, &miss, Label::kNear); | 3695 __ j(not_equal, &miss, Label::kNear); |
3696 | 3696 |
(...skipping 30 matching lines...) Expand all Loading... |
3727 void ICCompareStub::GenerateMiss(MacroAssembler* masm) { | 3727 void ICCompareStub::GenerateMiss(MacroAssembler* masm) { |
3728 { | 3728 { |
3729 // Call the runtime system in a fresh internal frame. | 3729 // Call the runtime system in a fresh internal frame. |
3730 ExternalReference miss = ExternalReference(IC_Utility(IC::kCompareIC_Miss), | 3730 ExternalReference miss = ExternalReference(IC_Utility(IC::kCompareIC_Miss), |
3731 isolate()); | 3731 isolate()); |
3732 FrameScope scope(masm, StackFrame::INTERNAL); | 3732 FrameScope scope(masm, StackFrame::INTERNAL); |
3733 __ push(edx); // Preserve edx and eax. | 3733 __ push(edx); // Preserve edx and eax. |
3734 __ push(eax); | 3734 __ push(eax); |
3735 __ push(edx); // And also use them as the arguments. | 3735 __ push(edx); // And also use them as the arguments. |
3736 __ push(eax); | 3736 __ push(eax); |
3737 __ push(Immediate(Smi::FromInt(op_))); | 3737 __ push(Immediate(Smi::FromInt(op()))); |
3738 __ CallExternalReference(miss, 3); | 3738 __ CallExternalReference(miss, 3); |
3739 // Compute the entry point of the rewritten stub. | 3739 // Compute the entry point of the rewritten stub. |
3740 __ lea(edi, FieldOperand(eax, Code::kHeaderSize)); | 3740 __ lea(edi, FieldOperand(eax, Code::kHeaderSize)); |
3741 __ pop(eax); | 3741 __ pop(eax); |
3742 __ pop(edx); | 3742 __ pop(edx); |
3743 } | 3743 } |
3744 | 3744 |
3745 // Do a tail call to the rewritten stub. | 3745 // Do a tail call to the rewritten stub. |
3746 __ jmp(edi); | 3746 __ jmp(edi); |
3747 } | 3747 } |
(...skipping 1033 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4781 Operand(ebp, 7 * kPointerSize), | 4781 Operand(ebp, 7 * kPointerSize), |
4782 NULL); | 4782 NULL); |
4783 } | 4783 } |
4784 | 4784 |
4785 | 4785 |
4786 #undef __ | 4786 #undef __ |
4787 | 4787 |
4788 } } // namespace v8::internal | 4788 } } // namespace v8::internal |
4789 | 4789 |
4790 #endif // V8_TARGET_ARCH_IA32 | 4790 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |