OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 1592 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1603 __ mov(r0, Operand(Smi::FromInt(ncr))); | 1603 __ mov(r0, Operand(Smi::FromInt(ncr))); |
1604 __ push(r0); | 1604 __ push(r0); |
1605 } | 1605 } |
1606 | 1606 |
1607 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) | 1607 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) |
1608 // tagged as a small integer. | 1608 // tagged as a small integer. |
1609 __ InvokeBuiltin(native, JUMP_FUNCTION); | 1609 __ InvokeBuiltin(native, JUMP_FUNCTION); |
1610 } | 1610 } |
1611 | 1611 |
1612 | 1612 |
1613 // This stub does not handle the inlined cases (Smis, Booleans, undefined). | |
1614 // The stub returns zero for false, and a non-zero value for true. | 1613 // The stub returns zero for false, and a non-zero value for true. |
1615 void ToBooleanStub::Generate(MacroAssembler* masm) { | 1614 void ToBooleanStub::Generate(MacroAssembler* masm) { |
1616 // This stub uses VFP3 instructions. | 1615 // This stub uses VFP3 instructions. |
1617 CpuFeatures::Scope scope(VFP3); | 1616 CpuFeatures::Scope scope(VFP3); |
1618 | 1617 |
1619 Label false_result; | 1618 Label false_result, true_result, not_string; |
1620 Label not_heap_number; | 1619 const Register map = r9.is(tos_) ? r7 : r9; |
1621 Register scratch = r9.is(tos_) ? r7 : r9; | |
1622 | 1620 |
1623 // undefined -> false | 1621 // undefined -> false |
1624 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 1622 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
1625 __ cmp(tos_, ip); | 1623 __ cmp(tos_, ip); |
1626 __ b(eq, &false_result); | 1624 __ b(eq, &false_result); |
1627 | 1625 |
1628 // Boolean -> its value | 1626 // Boolean -> its value |
1629 __ LoadRoot(ip, Heap::kFalseValueRootIndex); | 1627 __ LoadRoot(ip, Heap::kFalseValueRootIndex); |
1630 __ cmp(tos_, ip); | 1628 __ cmp(tos_, ip); |
1631 __ b(eq, &false_result); | 1629 __ b(eq, &false_result); |
1632 __ LoadRoot(ip, Heap::kTrueValueRootIndex); | 1630 __ LoadRoot(ip, Heap::kTrueValueRootIndex); |
1633 __ cmp(tos_, ip); | 1631 __ cmp(tos_, ip); |
1634 // "tos_" is a register and contains a non-zero value. Hence we implicitly | 1632 // "tos_" is a register and contains a non-zero value. Hence we implicitly |
1635 // return true if the equal condition is satisfied. | 1633 // return true if the equal condition is satisfied. |
1636 __ Ret(eq); | 1634 __ Ret(eq); |
1637 | 1635 |
1638 // Smis: 0 -> false, all other -> true | 1636 // Smis: 0 -> false, all other -> true |
1639 __ tst(tos_, tos_); | 1637 __ tst(tos_, tos_); |
1640 __ b(eq, &false_result); | 1638 __ b(eq, &false_result); |
1641 __ tst(tos_, Operand(kSmiTagMask)); | 1639 __ tst(tos_, Operand(kSmiTagMask)); |
1642 // "tos_" is a register and contains a non-zero value. Hence we implicitly | 1640 // "tos_" is a register and contains a non-zero value. Hence we implicitly |
1643 // return true if the not equal condition is satisfied. | 1641 // return true if the not equal condition is satisfied. |
1644 __ Ret(eq); | 1642 __ Ret(eq); |
1645 | 1643 |
1646 // 'null' -> false | 1644 // 'null' -> false |
1647 __ LoadRoot(ip, Heap::kNullValueRootIndex); | 1645 __ LoadRoot(ip, Heap::kNullValueRootIndex); |
1648 __ cmp(tos_, ip); | 1646 __ cmp(tos_, ip); |
1649 __ b(eq, &false_result); | 1647 __ b(eq, &false_result); |
1650 | 1648 |
1651 // HeapNumber => false iff +0, -0, or NaN. | 1649 // Get the map of the heap object. |
1652 __ ldr(scratch, FieldMemOperand(tos_, HeapObject::kMapOffset)); | 1650 __ ldr(map, FieldMemOperand(tos_, HeapObject::kMapOffset)); |
1653 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); | 1651 |
1654 __ cmp(scratch, ip); | 1652 // Undetectable -> false. |
1655 __ b(¬_heap_number, ne); | 1653 __ ldrb(ip, FieldMemOperand(map, Map::kBitFieldOffset)); |
| 1654 __ tst(ip, Operand(1 << Map::kIsUndetectable)); |
| 1655 __ b(&false_result, ne); |
| 1656 |
| 1657 // JavaScript object -> true. |
| 1658 __ CompareInstanceType(map, ip, FIRST_SPEC_OBJECT_TYPE); |
| 1659 // "tos_" is a register and contains a non-zero value. Hence we implicitly |
| 1660 // return true if the greater than condition is satisfied. |
| 1661 __ Ret(ge); |
| 1662 |
| 1663 // String value -> false iff empty. |
| 1664 __ CompareInstanceType(map, ip, FIRST_NONSTRING_TYPE); |
| 1665 __ b(¬_string, ge); |
| 1666 __ ldr(tos_, FieldMemOperand(tos_, String::kLengthOffset)); |
| 1667 // Return string length as boolean value, i.e. return false iff length is 0. |
| 1668 __ Ret(); |
| 1669 |
| 1670 __ bind(¬_string); |
| 1671 // HeapNumber -> false iff +0, -0, or NaN. |
| 1672 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); |
| 1673 __ b(&true_result, ne); |
1656 __ vldr(d1, FieldMemOperand(tos_, HeapNumber::kValueOffset)); | 1674 __ vldr(d1, FieldMemOperand(tos_, HeapNumber::kValueOffset)); |
1657 __ VFPCompareAndSetFlags(d1, 0.0); | 1675 __ VFPCompareAndSetFlags(d1, 0.0); |
1658 // "tos_" is a register, and contains a non zero value by default. | 1676 // "tos_" is a register, and contains a non zero value by default. |
1659 // Hence we only need to overwrite "tos_" with zero to return false for | 1677 // Hence we only need to overwrite "tos_" with zero to return false for |
1660 // FP_ZERO or FP_NAN cases. Otherwise, by default it returns true. | 1678 // FP_ZERO or FP_NAN cases. Otherwise, by default it returns true. |
1661 __ mov(tos_, Operand(0, RelocInfo::NONE), LeaveCC, eq); // for FP_ZERO | 1679 __ mov(tos_, Operand(0, RelocInfo::NONE), LeaveCC, eq); // for FP_ZERO |
1662 __ mov(tos_, Operand(0, RelocInfo::NONE), LeaveCC, vs); // for FP_NAN | 1680 __ mov(tos_, Operand(0, RelocInfo::NONE), LeaveCC, vs); // for FP_NAN |
1663 __ Ret(); | 1681 __ Ret(); |
1664 | 1682 |
1665 __ bind(¬_heap_number); | 1683 // Return 1/0 for true/false in tos_. |
1666 | 1684 __ bind(&true_result); |
1667 // It can be an undetectable object. | 1685 __ mov(tos_, Operand(1, RelocInfo::NONE)); |
1668 // Undetectable => false. | |
1669 __ ldr(ip, FieldMemOperand(tos_, HeapObject::kMapOffset)); | |
1670 __ ldrb(scratch, FieldMemOperand(ip, Map::kBitFieldOffset)); | |
1671 __ and_(scratch, scratch, Operand(1 << Map::kIsUndetectable)); | |
1672 __ cmp(scratch, Operand(1 << Map::kIsUndetectable)); | |
1673 __ b(&false_result, eq); | |
1674 | |
1675 // JavaScript object => true. | |
1676 __ ldr(scratch, FieldMemOperand(tos_, HeapObject::kMapOffset)); | |
1677 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); | |
1678 __ cmp(scratch, Operand(FIRST_SPEC_OBJECT_TYPE)); | |
1679 // "tos_" is a register and contains a non-zero value. | |
1680 // Hence we implicitly return true if the greater than | |
1681 // condition is satisfied. | |
1682 __ Ret(gt); | |
1683 | |
1684 // Check for string | |
1685 __ ldr(scratch, FieldMemOperand(tos_, HeapObject::kMapOffset)); | |
1686 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); | |
1687 __ cmp(scratch, Operand(FIRST_NONSTRING_TYPE)); | |
1688 // "tos_" is a register and contains a non-zero value. | |
1689 // Hence we implicitly return true if the greater than | |
1690 // condition is satisfied. | |
1691 __ Ret(gt); | |
1692 | |
1693 // String value => false iff empty, i.e., length is zero | |
1694 __ ldr(tos_, FieldMemOperand(tos_, String::kLengthOffset)); | |
1695 // If length is zero, "tos_" contains zero ==> false. | |
1696 // If length is not zero, "tos_" contains a non-zero value ==> true. | |
1697 __ Ret(); | 1686 __ Ret(); |
1698 | |
1699 // Return 0 in "tos_" for false . | |
1700 __ bind(&false_result); | 1687 __ bind(&false_result); |
1701 __ mov(tos_, Operand(0, RelocInfo::NONE)); | 1688 __ mov(tos_, Operand(0, RelocInfo::NONE)); |
1702 __ Ret(); | 1689 __ Ret(); |
1703 } | 1690 } |
1704 | 1691 |
1705 | 1692 |
1706 const char* UnaryOpStub::GetName() { | 1693 const char* UnaryOpStub::GetName() { |
1707 if (name_ != NULL) return name_; | 1694 if (name_ != NULL) return name_; |
1708 const int kMaxNameLength = 100; | 1695 const int kMaxNameLength = 100; |
1709 name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray( | 1696 name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray( |
(...skipping 1833 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3543 // r3: argc | 3530 // r3: argc |
3544 // [sp+0]: argv | 3531 // [sp+0]: argv |
3545 | 3532 |
3546 Label invoke, exit; | 3533 Label invoke, exit; |
3547 | 3534 |
3548 // Called from C, so do not pop argc and args on exit (preserve sp) | 3535 // Called from C, so do not pop argc and args on exit (preserve sp) |
3549 // No need to save register-passed args | 3536 // No need to save register-passed args |
3550 // Save callee-saved registers (incl. cp and fp), sp, and lr | 3537 // Save callee-saved registers (incl. cp and fp), sp, and lr |
3551 __ stm(db_w, sp, kCalleeSaved | lr.bit()); | 3538 __ stm(db_w, sp, kCalleeSaved | lr.bit()); |
3552 | 3539 |
| 3540 if (CpuFeatures::IsSupported(VFP3)) { |
| 3541 CpuFeatures::Scope scope(VFP3); |
| 3542 // Save callee-saved vfp registers. |
| 3543 __ vstm(db_w, sp, kFirstCalleeSavedDoubleReg, kLastCalleeSavedDoubleReg); |
| 3544 } |
| 3545 |
3553 // Get address of argv, see stm above. | 3546 // Get address of argv, see stm above. |
3554 // r0: code entry | 3547 // r0: code entry |
3555 // r1: function | 3548 // r1: function |
3556 // r2: receiver | 3549 // r2: receiver |
3557 // r3: argc | 3550 // r3: argc |
3558 __ ldr(r4, MemOperand(sp, (kNumCalleeSaved + 1) * kPointerSize)); // argv | 3551 |
| 3552 // Setup argv in r4. |
| 3553 int offset_to_argv = (kNumCalleeSaved + 1) * kPointerSize; |
| 3554 if (CpuFeatures::IsSupported(VFP3)) { |
| 3555 offset_to_argv += kNumDoubleCalleeSaved * kDoubleSize; |
| 3556 } |
| 3557 __ ldr(r4, MemOperand(sp, offset_to_argv)); |
3559 | 3558 |
3560 // Push a frame with special values setup to mark it as an entry frame. | 3559 // Push a frame with special values setup to mark it as an entry frame. |
3561 // r0: code entry | 3560 // r0: code entry |
3562 // r1: function | 3561 // r1: function |
3563 // r2: receiver | 3562 // r2: receiver |
3564 // r3: argc | 3563 // r3: argc |
3565 // r4: argv | 3564 // r4: argv |
3566 Isolate* isolate = masm->isolate(); | 3565 Isolate* isolate = masm->isolate(); |
3567 __ mov(r8, Operand(-1)); // Push a bad frame pointer to fail if it is used. | 3566 __ mov(r8, Operand(-1)); // Push a bad frame pointer to fail if it is used. |
3568 int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY; | 3567 int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY; |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3673 | 3672 |
3674 // Reset the stack to the callee saved registers. | 3673 // Reset the stack to the callee saved registers. |
3675 __ add(sp, sp, Operand(-EntryFrameConstants::kCallerFPOffset)); | 3674 __ add(sp, sp, Operand(-EntryFrameConstants::kCallerFPOffset)); |
3676 | 3675 |
3677 // Restore callee-saved registers and return. | 3676 // Restore callee-saved registers and return. |
3678 #ifdef DEBUG | 3677 #ifdef DEBUG |
3679 if (FLAG_debug_code) { | 3678 if (FLAG_debug_code) { |
3680 __ mov(lr, Operand(pc)); | 3679 __ mov(lr, Operand(pc)); |
3681 } | 3680 } |
3682 #endif | 3681 #endif |
| 3682 |
| 3683 if (CpuFeatures::IsSupported(VFP3)) { |
| 3684 CpuFeatures::Scope scope(VFP3); |
| 3685 // Restore callee-saved vfp registers. |
| 3686 __ vldm(ia_w, sp, kFirstCalleeSavedDoubleReg, kLastCalleeSavedDoubleReg); |
| 3687 } |
| 3688 |
3683 __ ldm(ia_w, sp, kCalleeSaved | pc.bit()); | 3689 __ ldm(ia_w, sp, kCalleeSaved | pc.bit()); |
3684 } | 3690 } |
3685 | 3691 |
3686 | 3692 |
3687 // Uses registers r0 to r4. | 3693 // Uses registers r0 to r4. |
3688 // Expected input (depending on whether args are in registers or on the stack): | 3694 // Expected input (depending on whether args are in registers or on the stack): |
3689 // * object: r0 or at sp + 1 * kPointerSize. | 3695 // * object: r0 or at sp + 1 * kPointerSize. |
3690 // * function: r1 or at sp. | 3696 // * function: r1 or at sp. |
3691 // | 3697 // |
3692 // An inlined call site may have been generated before calling this stub. | 3698 // An inlined call site may have been generated before calling this stub. |
(...skipping 2902 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6595 __ mov(result, Operand(0)); | 6601 __ mov(result, Operand(0)); |
6596 __ Ret(); | 6602 __ Ret(); |
6597 } | 6603 } |
6598 | 6604 |
6599 | 6605 |
6600 #undef __ | 6606 #undef __ |
6601 | 6607 |
6602 } } // namespace v8::internal | 6608 } } // namespace v8::internal |
6603 | 6609 |
6604 #endif // V8_TARGET_ARCH_ARM | 6610 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |