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 1595 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1606 // The stub expects its argument in the tos_ register and returns its result in | 1606 // The stub expects its argument in the tos_ register and returns its result in |
1607 // it, too: zero for false, and a non-zero value for true. | 1607 // it, too: zero for false, and a non-zero value for true. |
1608 void ToBooleanStub::Generate(MacroAssembler* masm) { | 1608 void ToBooleanStub::Generate(MacroAssembler* masm) { |
1609 // This stub uses VFP3 instructions. | 1609 // This stub uses VFP3 instructions. |
1610 CpuFeatures::Scope scope(VFP3); | 1610 CpuFeatures::Scope scope(VFP3); |
1611 | 1611 |
1612 Label patch; | 1612 Label patch; |
1613 const Register map = r9.is(tos_) ? r7 : r9; | 1613 const Register map = r9.is(tos_) ? r7 : r9; |
1614 | 1614 |
1615 // undefined -> false. | 1615 // undefined -> false. |
1616 CheckOddball(masm, UNDEFINED, Heap::kUndefinedValueRootIndex, false, &patch); | 1616 CheckOddball(masm, UNDEFINED, Heap::kUndefinedValueRootIndex, false); |
1617 | 1617 |
1618 // Boolean -> its value. | 1618 // Boolean -> its value. |
1619 CheckOddball(masm, BOOLEAN, Heap::kFalseValueRootIndex, false, &patch); | 1619 CheckOddball(masm, BOOLEAN, Heap::kFalseValueRootIndex, false); |
1620 CheckOddball(masm, BOOLEAN, Heap::kTrueValueRootIndex, true, &patch); | 1620 CheckOddball(masm, BOOLEAN, Heap::kTrueValueRootIndex, true); |
1621 | 1621 |
1622 // 'null' -> false. | 1622 // 'null' -> false. |
1623 CheckOddball(masm, NULL_TYPE, Heap::kNullValueRootIndex, false, &patch); | 1623 CheckOddball(masm, NULL_TYPE, Heap::kNullValueRootIndex, false); |
1624 | 1624 |
1625 if (types_.Contains(SMI)) { | 1625 if (types_.Contains(SMI)) { |
1626 // Smis: 0 -> false, all other -> true | 1626 // Smis: 0 -> false, all other -> true |
1627 __ tst(tos_, Operand(kSmiTagMask)); | 1627 __ tst(tos_, Operand(kSmiTagMask)); |
1628 // tos_ contains the correct return value already | 1628 // tos_ contains the correct return value already |
1629 __ Ret(eq); | 1629 __ Ret(eq); |
1630 } else if (types_.NeedsMap()) { | 1630 } else if (types_.NeedsMap()) { |
1631 // If we need a map later and have a Smi -> patch. | 1631 // If we need a map later and have a Smi -> patch. |
1632 __ JumpIfSmi(tos_, &patch); | 1632 __ JumpIfSmi(tos_, &patch); |
1633 } | 1633 } |
1634 | 1634 |
1635 if (types_.NeedsMap()) { | 1635 if (types_.NeedsMap()) { |
1636 __ ldr(map, FieldMemOperand(tos_, HeapObject::kMapOffset)); | 1636 __ ldr(map, FieldMemOperand(tos_, HeapObject::kMapOffset)); |
1637 | 1637 |
1638 // Everything with a map could be undetectable, so check this now. | 1638 if (types_.CanBeUndetectable()) { |
1639 __ ldrb(ip, FieldMemOperand(map, Map::kBitFieldOffset)); | 1639 __ ldrb(ip, FieldMemOperand(map, Map::kBitFieldOffset)); |
1640 __ tst(ip, Operand(1 << Map::kIsUndetectable)); | 1640 __ tst(ip, Operand(1 << Map::kIsUndetectable)); |
1641 // Undetectable -> false. | 1641 // Undetectable -> false. |
1642 __ mov(tos_, Operand(0, RelocInfo::NONE), LeaveCC, ne); | 1642 __ mov(tos_, Operand(0, RelocInfo::NONE), LeaveCC, ne); |
1643 __ Ret(ne); | 1643 __ Ret(ne); |
| 1644 } |
1644 } | 1645 } |
1645 | 1646 |
1646 if (types_.Contains(SPEC_OBJECT)) { | 1647 if (types_.Contains(SPEC_OBJECT)) { |
1647 // Spec object -> true. | 1648 // Spec object -> true. |
1648 __ CompareInstanceType(map, ip, FIRST_SPEC_OBJECT_TYPE); | 1649 __ CompareInstanceType(map, ip, FIRST_SPEC_OBJECT_TYPE); |
1649 // tos_ contains the correct non-zero return value already. | 1650 // tos_ contains the correct non-zero return value already. |
1650 __ Ret(ge); | 1651 __ Ret(ge); |
1651 } else if (types_.Contains(INTERNAL_OBJECT)) { | |
1652 // We've seen a spec object for the first time -> patch. | |
1653 __ CompareInstanceType(map, ip, FIRST_SPEC_OBJECT_TYPE); | |
1654 __ b(ge, &patch); | |
1655 } | 1652 } |
1656 | 1653 |
1657 if (types_.Contains(STRING)) { | 1654 if (types_.Contains(STRING)) { |
1658 // String value -> false iff empty. | 1655 // String value -> false iff empty. |
1659 __ CompareInstanceType(map, ip, FIRST_NONSTRING_TYPE); | 1656 __ CompareInstanceType(map, ip, FIRST_NONSTRING_TYPE); |
1660 __ ldr(tos_, FieldMemOperand(tos_, String::kLengthOffset), lt); | 1657 __ ldr(tos_, FieldMemOperand(tos_, String::kLengthOffset), lt); |
1661 __ Ret(lt); // the string length is OK as the return value | 1658 __ Ret(lt); // the string length is OK as the return value |
1662 } else if (types_.Contains(INTERNAL_OBJECT)) { | |
1663 // We've seen a string for the first time -> patch | |
1664 __ CompareInstanceType(map, ip, FIRST_NONSTRING_TYPE); | |
1665 __ b(lt, &patch); | |
1666 } | 1659 } |
1667 | 1660 |
1668 if (types_.Contains(HEAP_NUMBER)) { | 1661 if (types_.Contains(HEAP_NUMBER)) { |
1669 // Heap number -> false iff +0, -0, or NaN. | 1662 // Heap number -> false iff +0, -0, or NaN. |
1670 Label not_heap_number; | 1663 Label not_heap_number; |
1671 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); | 1664 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); |
1672 __ b(ne, ¬_heap_number); | 1665 __ b(ne, ¬_heap_number); |
1673 __ vldr(d1, FieldMemOperand(tos_, HeapNumber::kValueOffset)); | 1666 __ vldr(d1, FieldMemOperand(tos_, HeapNumber::kValueOffset)); |
1674 __ VFPCompareAndSetFlags(d1, 0.0); | 1667 __ VFPCompareAndSetFlags(d1, 0.0); |
1675 // "tos_" is a register, and contains a non zero value by default. | 1668 // "tos_" is a register, and contains a non zero value by default. |
1676 // Hence we only need to overwrite "tos_" with zero to return false for | 1669 // Hence we only need to overwrite "tos_" with zero to return false for |
1677 // FP_ZERO or FP_NAN cases. Otherwise, by default it returns true. | 1670 // FP_ZERO or FP_NAN cases. Otherwise, by default it returns true. |
1678 __ mov(tos_, Operand(0, RelocInfo::NONE), LeaveCC, eq); // for FP_ZERO | 1671 __ mov(tos_, Operand(0, RelocInfo::NONE), LeaveCC, eq); // for FP_ZERO |
1679 __ mov(tos_, Operand(0, RelocInfo::NONE), LeaveCC, vs); // for FP_NAN | 1672 __ mov(tos_, Operand(0, RelocInfo::NONE), LeaveCC, vs); // for FP_NAN |
1680 __ Ret(); | 1673 __ Ret(); |
1681 __ bind(¬_heap_number); | 1674 __ bind(¬_heap_number); |
1682 } else if (types_.Contains(INTERNAL_OBJECT)) { | |
1683 // We've seen a heap number for the first time -> patch | |
1684 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); | |
1685 __ b(eq, &patch); | |
1686 } | 1675 } |
1687 | 1676 |
1688 if (types_.Contains(INTERNAL_OBJECT)) { | 1677 __ bind(&patch); |
1689 // Internal objects -> true. | 1678 GenerateTypeTransition(masm); |
1690 __ mov(tos_, Operand(1, RelocInfo::NONE)); | |
1691 __ Ret(); | |
1692 } | |
1693 | |
1694 if (!types_.IsAll()) { | |
1695 __ bind(&patch); | |
1696 GenerateTypeTransition(masm); | |
1697 } | |
1698 } | 1679 } |
1699 | 1680 |
1700 | 1681 |
1701 void ToBooleanStub::CheckOddball(MacroAssembler* masm, | 1682 void ToBooleanStub::CheckOddball(MacroAssembler* masm, |
1702 Type type, | 1683 Type type, |
1703 Heap::RootListIndex value, | 1684 Heap::RootListIndex value, |
1704 bool result, | 1685 bool result) { |
1705 Label* patch) { | |
1706 if (types_.Contains(type)) { | 1686 if (types_.Contains(type)) { |
1707 // If we see an expected oddball, return its ToBoolean value tos_. | 1687 // If we see an expected oddball, return its ToBoolean value tos_. |
1708 __ LoadRoot(ip, value); | 1688 __ LoadRoot(ip, value); |
1709 __ cmp(tos_, ip); | 1689 __ cmp(tos_, ip); |
1710 // The value of a root is never NULL, so we can avoid loading a non-null | 1690 // The value of a root is never NULL, so we can avoid loading a non-null |
1711 // value into tos_ when we want to return 'true'. | 1691 // value into tos_ when we want to return 'true'. |
1712 if (!result) { | 1692 if (!result) { |
1713 __ mov(tos_, Operand(0, RelocInfo::NONE), LeaveCC, eq); | 1693 __ mov(tos_, Operand(0, RelocInfo::NONE), LeaveCC, eq); |
1714 } | 1694 } |
1715 __ Ret(eq); | 1695 __ Ret(eq); |
1716 } else if (types_.Contains(INTERNAL_OBJECT)) { | |
1717 // If we see an unexpected oddball and handle internal objects, we must | |
1718 // patch because the code for internal objects doesn't handle it explictly. | |
1719 __ LoadRoot(ip, value); | |
1720 __ cmp(tos_, ip); | |
1721 __ b(eq, patch); | |
1722 } | 1696 } |
1723 } | 1697 } |
1724 | 1698 |
1725 | 1699 |
1726 void ToBooleanStub::GenerateTypeTransition(MacroAssembler* masm) { | 1700 void ToBooleanStub::GenerateTypeTransition(MacroAssembler* masm) { |
1727 if (!tos_.is(r3)) { | 1701 if (!tos_.is(r3)) { |
1728 __ mov(r3, Operand(tos_)); | 1702 __ mov(r3, Operand(tos_)); |
1729 } | 1703 } |
1730 __ mov(r2, Operand(Smi::FromInt(tos_.code()))); | 1704 __ mov(r2, Operand(Smi::FromInt(tos_.code()))); |
1731 __ mov(r1, Operand(Smi::FromInt(types_.ToByte()))); | 1705 __ mov(r1, Operand(Smi::FromInt(types_.ToByte()))); |
(...skipping 4859 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6591 __ mov(result, Operand(0)); | 6565 __ mov(result, Operand(0)); |
6592 __ Ret(); | 6566 __ Ret(); |
6593 } | 6567 } |
6594 | 6568 |
6595 | 6569 |
6596 #undef __ | 6570 #undef __ |
6597 | 6571 |
6598 } } // namespace v8::internal | 6572 } } // namespace v8::internal |
6599 | 6573 |
6600 #endif // V8_TARGET_ARCH_ARM | 6574 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |