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 |