| 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 |