| 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/base/bits.h" | 9 #include "src/base/bits.h" |
| 10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
| (...skipping 1550 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1561 Register scratch) { | 1561 Register scratch) { |
| 1562 __ JumpIfSmi(object, label); | 1562 __ JumpIfSmi(object, label); |
| 1563 __ mov(scratch, FieldOperand(object, HeapObject::kMapOffset)); | 1563 __ mov(scratch, FieldOperand(object, HeapObject::kMapOffset)); |
| 1564 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); | 1564 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); |
| 1565 STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); | 1565 STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); |
| 1566 __ test(scratch, Immediate(kIsNotStringMask | kIsNotInternalizedMask)); | 1566 __ test(scratch, Immediate(kIsNotStringMask | kIsNotInternalizedMask)); |
| 1567 __ j(not_zero, label); | 1567 __ j(not_zero, label); |
| 1568 } | 1568 } |
| 1569 | 1569 |
| 1570 | 1570 |
| 1571 void ICCompareStub::GenerateGeneric(MacroAssembler* masm) { | 1571 void CompareICStub::GenerateGeneric(MacroAssembler* masm) { |
| 1572 Label check_unequal_objects; | 1572 Label check_unequal_objects; |
| 1573 Condition cc = GetCondition(); | 1573 Condition cc = GetCondition(); |
| 1574 | 1574 |
| 1575 Label miss; | 1575 Label miss; |
| 1576 CheckInputType(masm, edx, left(), &miss); | 1576 CheckInputType(masm, edx, left(), &miss); |
| 1577 CheckInputType(masm, eax, right(), &miss); | 1577 CheckInputType(masm, eax, right(), &miss); |
| 1578 | 1578 |
| 1579 // Compare two smis. | 1579 // Compare two smis. |
| 1580 Label non_smi, smi_done; | 1580 Label non_smi, smi_done; |
| 1581 __ mov(ecx, edx); | 1581 __ mov(ecx, edx); |
| (...skipping 1786 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3368 __ Assert(equal, kExpectedAllocationSite); | 3368 __ Assert(equal, kExpectedAllocationSite); |
| 3369 } | 3369 } |
| 3370 | 3370 |
| 3371 // Tail call into the stub that handles binary operations with allocation | 3371 // Tail call into the stub that handles binary operations with allocation |
| 3372 // sites. | 3372 // sites. |
| 3373 BinaryOpWithAllocationSiteStub stub(isolate(), state()); | 3373 BinaryOpWithAllocationSiteStub stub(isolate(), state()); |
| 3374 __ TailCallStub(&stub); | 3374 __ TailCallStub(&stub); |
| 3375 } | 3375 } |
| 3376 | 3376 |
| 3377 | 3377 |
| 3378 void ICCompareStub::GenerateSmis(MacroAssembler* masm) { | 3378 void CompareICStub::GenerateSmis(MacroAssembler* masm) { |
| 3379 DCHECK(state() == CompareIC::SMI); | 3379 DCHECK(state() == CompareIC::SMI); |
| 3380 Label miss; | 3380 Label miss; |
| 3381 __ mov(ecx, edx); | 3381 __ mov(ecx, edx); |
| 3382 __ or_(ecx, eax); | 3382 __ or_(ecx, eax); |
| 3383 __ JumpIfNotSmi(ecx, &miss, Label::kNear); | 3383 __ JumpIfNotSmi(ecx, &miss, Label::kNear); |
| 3384 | 3384 |
| 3385 if (GetCondition() == equal) { | 3385 if (GetCondition() == equal) { |
| 3386 // For equality we do not care about the sign of the result. | 3386 // For equality we do not care about the sign of the result. |
| 3387 __ sub(eax, edx); | 3387 __ sub(eax, edx); |
| 3388 } else { | 3388 } else { |
| 3389 Label done; | 3389 Label done; |
| 3390 __ sub(edx, eax); | 3390 __ sub(edx, eax); |
| 3391 __ j(no_overflow, &done, Label::kNear); | 3391 __ j(no_overflow, &done, Label::kNear); |
| 3392 // Correct sign of result in case of overflow. | 3392 // Correct sign of result in case of overflow. |
| 3393 __ not_(edx); | 3393 __ not_(edx); |
| 3394 __ bind(&done); | 3394 __ bind(&done); |
| 3395 __ mov(eax, edx); | 3395 __ mov(eax, edx); |
| 3396 } | 3396 } |
| 3397 __ ret(0); | 3397 __ ret(0); |
| 3398 | 3398 |
| 3399 __ bind(&miss); | 3399 __ bind(&miss); |
| 3400 GenerateMiss(masm); | 3400 GenerateMiss(masm); |
| 3401 } | 3401 } |
| 3402 | 3402 |
| 3403 | 3403 |
| 3404 void ICCompareStub::GenerateNumbers(MacroAssembler* masm) { | 3404 void CompareICStub::GenerateNumbers(MacroAssembler* masm) { |
| 3405 DCHECK(state() == CompareIC::NUMBER); | 3405 DCHECK(state() == CompareIC::NUMBER); |
| 3406 | 3406 |
| 3407 Label generic_stub; | 3407 Label generic_stub; |
| 3408 Label unordered, maybe_undefined1, maybe_undefined2; | 3408 Label unordered, maybe_undefined1, maybe_undefined2; |
| 3409 Label miss; | 3409 Label miss; |
| 3410 | 3410 |
| 3411 if (left() == CompareIC::SMI) { | 3411 if (left() == CompareIC::SMI) { |
| 3412 __ JumpIfNotSmi(edx, &miss); | 3412 __ JumpIfNotSmi(edx, &miss); |
| 3413 } | 3413 } |
| 3414 if (right() == CompareIC::SMI) { | 3414 if (right() == CompareIC::SMI) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3451 // Performing mov, because xor would destroy the flag register. | 3451 // Performing mov, because xor would destroy the flag register. |
| 3452 __ mov(eax, 0); // equal | 3452 __ mov(eax, 0); // equal |
| 3453 __ mov(ecx, Immediate(Smi::FromInt(1))); | 3453 __ mov(ecx, Immediate(Smi::FromInt(1))); |
| 3454 __ cmov(above, eax, ecx); | 3454 __ cmov(above, eax, ecx); |
| 3455 __ mov(ecx, Immediate(Smi::FromInt(-1))); | 3455 __ mov(ecx, Immediate(Smi::FromInt(-1))); |
| 3456 __ cmov(below, eax, ecx); | 3456 __ cmov(below, eax, ecx); |
| 3457 __ ret(0); | 3457 __ ret(0); |
| 3458 | 3458 |
| 3459 __ bind(&unordered); | 3459 __ bind(&unordered); |
| 3460 __ bind(&generic_stub); | 3460 __ bind(&generic_stub); |
| 3461 ICCompareStub stub(isolate(), op(), CompareIC::GENERIC, CompareIC::GENERIC, | 3461 CompareICStub stub(isolate(), op(), CompareIC::GENERIC, CompareIC::GENERIC, |
| 3462 CompareIC::GENERIC); | 3462 CompareIC::GENERIC); |
| 3463 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); | 3463 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); |
| 3464 | 3464 |
| 3465 __ bind(&maybe_undefined1); | 3465 __ bind(&maybe_undefined1); |
| 3466 if (Token::IsOrderedRelationalCompareOp(op())) { | 3466 if (Token::IsOrderedRelationalCompareOp(op())) { |
| 3467 __ cmp(eax, Immediate(isolate()->factory()->undefined_value())); | 3467 __ cmp(eax, Immediate(isolate()->factory()->undefined_value())); |
| 3468 __ j(not_equal, &miss); | 3468 __ j(not_equal, &miss); |
| 3469 __ JumpIfSmi(edx, &unordered); | 3469 __ JumpIfSmi(edx, &unordered); |
| 3470 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ecx); | 3470 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ecx); |
| 3471 __ j(not_equal, &maybe_undefined2, Label::kNear); | 3471 __ j(not_equal, &maybe_undefined2, Label::kNear); |
| 3472 __ jmp(&unordered); | 3472 __ jmp(&unordered); |
| 3473 } | 3473 } |
| 3474 | 3474 |
| 3475 __ bind(&maybe_undefined2); | 3475 __ bind(&maybe_undefined2); |
| 3476 if (Token::IsOrderedRelationalCompareOp(op())) { | 3476 if (Token::IsOrderedRelationalCompareOp(op())) { |
| 3477 __ cmp(edx, Immediate(isolate()->factory()->undefined_value())); | 3477 __ cmp(edx, Immediate(isolate()->factory()->undefined_value())); |
| 3478 __ j(equal, &unordered); | 3478 __ j(equal, &unordered); |
| 3479 } | 3479 } |
| 3480 | 3480 |
| 3481 __ bind(&miss); | 3481 __ bind(&miss); |
| 3482 GenerateMiss(masm); | 3482 GenerateMiss(masm); |
| 3483 } | 3483 } |
| 3484 | 3484 |
| 3485 | 3485 |
| 3486 void ICCompareStub::GenerateInternalizedStrings(MacroAssembler* masm) { | 3486 void CompareICStub::GenerateInternalizedStrings(MacroAssembler* masm) { |
| 3487 DCHECK(state() == CompareIC::INTERNALIZED_STRING); | 3487 DCHECK(state() == CompareIC::INTERNALIZED_STRING); |
| 3488 DCHECK(GetCondition() == equal); | 3488 DCHECK(GetCondition() == equal); |
| 3489 | 3489 |
| 3490 // Registers containing left and right operands respectively. | 3490 // Registers containing left and right operands respectively. |
| 3491 Register left = edx; | 3491 Register left = edx; |
| 3492 Register right = eax; | 3492 Register right = eax; |
| 3493 Register tmp1 = ecx; | 3493 Register tmp1 = ecx; |
| 3494 Register tmp2 = ebx; | 3494 Register tmp2 = ebx; |
| 3495 | 3495 |
| 3496 // Check that both operands are heap objects. | 3496 // Check that both operands are heap objects. |
| (...skipping 24 matching lines...) Expand all Loading... |
| 3521 STATIC_ASSERT(kSmiTag == 0); | 3521 STATIC_ASSERT(kSmiTag == 0); |
| 3522 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); | 3522 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); |
| 3523 __ bind(&done); | 3523 __ bind(&done); |
| 3524 __ ret(0); | 3524 __ ret(0); |
| 3525 | 3525 |
| 3526 __ bind(&miss); | 3526 __ bind(&miss); |
| 3527 GenerateMiss(masm); | 3527 GenerateMiss(masm); |
| 3528 } | 3528 } |
| 3529 | 3529 |
| 3530 | 3530 |
| 3531 void ICCompareStub::GenerateUniqueNames(MacroAssembler* masm) { | 3531 void CompareICStub::GenerateUniqueNames(MacroAssembler* masm) { |
| 3532 DCHECK(state() == CompareIC::UNIQUE_NAME); | 3532 DCHECK(state() == CompareIC::UNIQUE_NAME); |
| 3533 DCHECK(GetCondition() == equal); | 3533 DCHECK(GetCondition() == equal); |
| 3534 | 3534 |
| 3535 // Registers containing left and right operands respectively. | 3535 // Registers containing left and right operands respectively. |
| 3536 Register left = edx; | 3536 Register left = edx; |
| 3537 Register right = eax; | 3537 Register right = eax; |
| 3538 Register tmp1 = ecx; | 3538 Register tmp1 = ecx; |
| 3539 Register tmp2 = ebx; | 3539 Register tmp2 = ebx; |
| 3540 | 3540 |
| 3541 // Check that both operands are heap objects. | 3541 // Check that both operands are heap objects. |
| (...skipping 24 matching lines...) Expand all Loading... |
| 3566 STATIC_ASSERT(kSmiTag == 0); | 3566 STATIC_ASSERT(kSmiTag == 0); |
| 3567 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); | 3567 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); |
| 3568 __ bind(&done); | 3568 __ bind(&done); |
| 3569 __ ret(0); | 3569 __ ret(0); |
| 3570 | 3570 |
| 3571 __ bind(&miss); | 3571 __ bind(&miss); |
| 3572 GenerateMiss(masm); | 3572 GenerateMiss(masm); |
| 3573 } | 3573 } |
| 3574 | 3574 |
| 3575 | 3575 |
| 3576 void ICCompareStub::GenerateStrings(MacroAssembler* masm) { | 3576 void CompareICStub::GenerateStrings(MacroAssembler* masm) { |
| 3577 DCHECK(state() == CompareIC::STRING); | 3577 DCHECK(state() == CompareIC::STRING); |
| 3578 Label miss; | 3578 Label miss; |
| 3579 | 3579 |
| 3580 bool equality = Token::IsEqualityOp(op()); | 3580 bool equality = Token::IsEqualityOp(op()); |
| 3581 | 3581 |
| 3582 // Registers containing left and right operands respectively. | 3582 // Registers containing left and right operands respectively. |
| 3583 Register left = edx; | 3583 Register left = edx; |
| 3584 Register right = eax; | 3584 Register right = eax; |
| 3585 Register tmp1 = ecx; | 3585 Register tmp1 = ecx; |
| 3586 Register tmp2 = ebx; | 3586 Register tmp2 = ebx; |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3655 __ TailCallRuntime(Runtime::kStringEquals, 2, 1); | 3655 __ TailCallRuntime(Runtime::kStringEquals, 2, 1); |
| 3656 } else { | 3656 } else { |
| 3657 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 3657 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
| 3658 } | 3658 } |
| 3659 | 3659 |
| 3660 __ bind(&miss); | 3660 __ bind(&miss); |
| 3661 GenerateMiss(masm); | 3661 GenerateMiss(masm); |
| 3662 } | 3662 } |
| 3663 | 3663 |
| 3664 | 3664 |
| 3665 void ICCompareStub::GenerateObjects(MacroAssembler* masm) { | 3665 void CompareICStub::GenerateObjects(MacroAssembler* masm) { |
| 3666 DCHECK(state() == CompareIC::OBJECT); | 3666 DCHECK(state() == CompareIC::OBJECT); |
| 3667 Label miss; | 3667 Label miss; |
| 3668 __ mov(ecx, edx); | 3668 __ mov(ecx, edx); |
| 3669 __ and_(ecx, eax); | 3669 __ and_(ecx, eax); |
| 3670 __ JumpIfSmi(ecx, &miss, Label::kNear); | 3670 __ JumpIfSmi(ecx, &miss, Label::kNear); |
| 3671 | 3671 |
| 3672 __ CmpObjectType(eax, JS_OBJECT_TYPE, ecx); | 3672 __ CmpObjectType(eax, JS_OBJECT_TYPE, ecx); |
| 3673 __ j(not_equal, &miss, Label::kNear); | 3673 __ j(not_equal, &miss, Label::kNear); |
| 3674 __ CmpObjectType(edx, JS_OBJECT_TYPE, ecx); | 3674 __ CmpObjectType(edx, JS_OBJECT_TYPE, ecx); |
| 3675 __ j(not_equal, &miss, Label::kNear); | 3675 __ j(not_equal, &miss, Label::kNear); |
| 3676 | 3676 |
| 3677 DCHECK(GetCondition() == equal); | 3677 DCHECK(GetCondition() == equal); |
| 3678 __ sub(eax, edx); | 3678 __ sub(eax, edx); |
| 3679 __ ret(0); | 3679 __ ret(0); |
| 3680 | 3680 |
| 3681 __ bind(&miss); | 3681 __ bind(&miss); |
| 3682 GenerateMiss(masm); | 3682 GenerateMiss(masm); |
| 3683 } | 3683 } |
| 3684 | 3684 |
| 3685 | 3685 |
| 3686 void ICCompareStub::GenerateKnownObjects(MacroAssembler* masm) { | 3686 void CompareICStub::GenerateKnownObjects(MacroAssembler* masm) { |
| 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 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); | 3692 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); |
| 3693 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); | 3693 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); |
| 3694 __ cmp(ecx, known_map_); | 3694 __ cmp(ecx, known_map_); |
| 3695 __ j(not_equal, &miss, Label::kNear); | 3695 __ j(not_equal, &miss, Label::kNear); |
| 3696 __ cmp(ebx, known_map_); | 3696 __ cmp(ebx, known_map_); |
| 3697 __ j(not_equal, &miss, Label::kNear); | 3697 __ j(not_equal, &miss, Label::kNear); |
| 3698 | 3698 |
| 3699 __ sub(eax, edx); | 3699 __ sub(eax, edx); |
| 3700 __ ret(0); | 3700 __ ret(0); |
| 3701 | 3701 |
| 3702 __ bind(&miss); | 3702 __ bind(&miss); |
| 3703 GenerateMiss(masm); | 3703 GenerateMiss(masm); |
| 3704 } | 3704 } |
| 3705 | 3705 |
| 3706 | 3706 |
| 3707 void ICCompareStub::GenerateMiss(MacroAssembler* masm) { | 3707 void CompareICStub::GenerateMiss(MacroAssembler* masm) { |
| 3708 { | 3708 { |
| 3709 // Call the runtime system in a fresh internal frame. | 3709 // Call the runtime system in a fresh internal frame. |
| 3710 ExternalReference miss = ExternalReference(IC_Utility(IC::kCompareIC_Miss), | 3710 ExternalReference miss = ExternalReference(IC_Utility(IC::kCompareIC_Miss), |
| 3711 isolate()); | 3711 isolate()); |
| 3712 FrameScope scope(masm, StackFrame::INTERNAL); | 3712 FrameScope scope(masm, StackFrame::INTERNAL); |
| 3713 __ push(edx); // Preserve edx and eax. | 3713 __ push(edx); // Preserve edx and eax. |
| 3714 __ push(eax); | 3714 __ push(eax); |
| 3715 __ push(edx); // And also use them as the arguments. | 3715 __ push(edx); // And also use them as the arguments. |
| 3716 __ push(eax); | 3716 __ push(eax); |
| 3717 __ push(Immediate(Smi::FromInt(op()))); | 3717 __ push(Immediate(Smi::FromInt(op()))); |
| (...skipping 1029 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4747 Operand(ebp, 7 * kPointerSize), | 4747 Operand(ebp, 7 * kPointerSize), |
| 4748 NULL); | 4748 NULL); |
| 4749 } | 4749 } |
| 4750 | 4750 |
| 4751 | 4751 |
| 4752 #undef __ | 4752 #undef __ |
| 4753 | 4753 |
| 4754 } } // namespace v8::internal | 4754 } } // namespace v8::internal |
| 4755 | 4755 |
| 4756 #endif // V8_TARGET_ARCH_IA32 | 4756 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |