Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 1517 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1528 __ cmp(r2, Operand(ODDBALL_TYPE)); | 1528 __ cmp(r2, Operand(ODDBALL_TYPE)); |
| 1529 __ b(eq, &return_not_equal); | 1529 __ b(eq, &return_not_equal); |
| 1530 | 1530 |
| 1531 __ CompareObjectType(lhs, r3, r3, FIRST_SPEC_OBJECT_TYPE); | 1531 __ CompareObjectType(lhs, r3, r3, FIRST_SPEC_OBJECT_TYPE); |
| 1532 __ b(ge, &return_not_equal); | 1532 __ b(ge, &return_not_equal); |
| 1533 | 1533 |
| 1534 // Check for oddballs: true, false, null, undefined. | 1534 // Check for oddballs: true, false, null, undefined. |
| 1535 __ cmp(r3, Operand(ODDBALL_TYPE)); | 1535 __ cmp(r3, Operand(ODDBALL_TYPE)); |
| 1536 __ b(eq, &return_not_equal); | 1536 __ b(eq, &return_not_equal); |
| 1537 | 1537 |
| 1538 // Now that we have the types we might as well check for symbol-symbol. | 1538 // Now that we have the types we might as well check for |
| 1539 // Ensure that no non-strings have the symbol bit set. | 1539 // internalized-internalized. |
| 1540 STATIC_ASSERT(LAST_TYPE < kNotStringTag + kIsSymbolMask); | 1540 // Ensure that no non-strings have the internalized bit set. |
| 1541 STATIC_ASSERT(kSymbolTag != 0); | 1541 STATIC_ASSERT(LAST_TYPE < kNotStringTag + kIsInternalizedMask); |
| 1542 STATIC_ASSERT(kInternalizedTag != 0); | |
| 1542 __ and_(r2, r2, Operand(r3)); | 1543 __ and_(r2, r2, Operand(r3)); |
| 1543 __ tst(r2, Operand(kIsSymbolMask)); | 1544 __ tst(r2, Operand(kIsInternalizedMask)); |
| 1544 __ b(ne, &return_not_equal); | 1545 __ b(ne, &return_not_equal); |
| 1545 } | 1546 } |
| 1546 | 1547 |
| 1547 | 1548 |
| 1548 // See comment at call site. | 1549 // See comment at call site. |
| 1549 static void EmitCheckForTwoHeapNumbers(MacroAssembler* masm, | 1550 static void EmitCheckForTwoHeapNumbers(MacroAssembler* masm, |
| 1550 Register lhs, | 1551 Register lhs, |
| 1551 Register rhs, | 1552 Register rhs, |
| 1552 Label* both_loaded_as_doubles, | 1553 Label* both_loaded_as_doubles, |
| 1553 Label* not_heap_numbers, | 1554 Label* not_heap_numbers, |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 1570 __ sub(r7, lhs, Operand(kHeapObjectTag)); | 1571 __ sub(r7, lhs, Operand(kHeapObjectTag)); |
| 1571 __ vldr(d7, r7, HeapNumber::kValueOffset); | 1572 __ vldr(d7, r7, HeapNumber::kValueOffset); |
| 1572 } else { | 1573 } else { |
| 1573 __ Ldrd(r2, r3, FieldMemOperand(lhs, HeapNumber::kValueOffset)); | 1574 __ Ldrd(r2, r3, FieldMemOperand(lhs, HeapNumber::kValueOffset)); |
| 1574 __ Ldrd(r0, r1, FieldMemOperand(rhs, HeapNumber::kValueOffset)); | 1575 __ Ldrd(r0, r1, FieldMemOperand(rhs, HeapNumber::kValueOffset)); |
| 1575 } | 1576 } |
| 1576 __ jmp(both_loaded_as_doubles); | 1577 __ jmp(both_loaded_as_doubles); |
| 1577 } | 1578 } |
| 1578 | 1579 |
| 1579 | 1580 |
| 1580 // Fast negative check for symbol-to-symbol equality. | 1581 // Fast negative check for internalized-to-internalized equality. |
| 1581 static void EmitCheckForSymbolsOrObjects(MacroAssembler* masm, | 1582 static void EmitCheckForInternalizedStringsOrObjects(MacroAssembler* masm, |
| 1582 Register lhs, | 1583 Register lhs, |
| 1583 Register rhs, | 1584 Register rhs, |
| 1584 Label* possible_strings, | 1585 Label* possible_strings, |
| 1585 Label* not_both_strings) { | 1586 Label* not_both_strings) { |
| 1586 ASSERT((lhs.is(r0) && rhs.is(r1)) || | 1587 ASSERT((lhs.is(r0) && rhs.is(r1)) || |
| 1587 (lhs.is(r1) && rhs.is(r0))); | 1588 (lhs.is(r1) && rhs.is(r0))); |
| 1588 | 1589 |
| 1589 // r2 is object type of rhs. | 1590 // r2 is object type of rhs. |
| 1590 // Ensure that no non-strings have the symbol bit set. | 1591 // Ensure that no non-strings have the internalized bit set. |
| 1591 Label object_test; | 1592 Label object_test; |
| 1592 STATIC_ASSERT(kSymbolTag != 0); | 1593 STATIC_ASSERT(kInternalizedTag != 0); |
| 1593 __ tst(r2, Operand(kIsNotStringMask)); | 1594 __ tst(r2, Operand(kIsNotStringMask)); |
| 1594 __ b(ne, &object_test); | 1595 __ b(ne, &object_test); |
| 1595 __ tst(r2, Operand(kIsSymbolMask)); | 1596 __ tst(r2, Operand(kIsInternalizedMask)); |
| 1596 __ b(eq, possible_strings); | 1597 __ b(eq, possible_strings); |
| 1597 __ CompareObjectType(lhs, r3, r3, FIRST_NONSTRING_TYPE); | 1598 __ CompareObjectType(lhs, r3, r3, FIRST_NONSTRING_TYPE); |
| 1598 __ b(ge, not_both_strings); | 1599 __ b(ge, not_both_strings); |
| 1599 __ tst(r3, Operand(kIsSymbolMask)); | 1600 __ tst(r3, Operand(kIsInternalizedMask)); |
| 1600 __ b(eq, possible_strings); | 1601 __ b(eq, possible_strings); |
| 1601 | 1602 |
| 1602 // Both are symbols. We already checked they weren't the same pointer | 1603 // Both are internalized. We already checked they weren't the same pointer |
| 1603 // so they are not equal. | 1604 // so they are not equal. |
| 1604 __ mov(r0, Operand(NOT_EQUAL)); | 1605 __ mov(r0, Operand(NOT_EQUAL)); |
| 1605 __ Ret(); | 1606 __ Ret(); |
| 1606 | 1607 |
| 1607 __ bind(&object_test); | 1608 __ bind(&object_test); |
| 1608 __ cmp(r2, Operand(FIRST_SPEC_OBJECT_TYPE)); | 1609 __ cmp(r2, Operand(FIRST_SPEC_OBJECT_TYPE)); |
| 1609 __ b(lt, not_both_strings); | 1610 __ b(lt, not_both_strings); |
| 1610 __ CompareObjectType(lhs, r2, r3, FIRST_SPEC_OBJECT_TYPE); | 1611 __ CompareObjectType(lhs, r2, r3, FIRST_SPEC_OBJECT_TYPE); |
| 1611 __ b(lt, not_both_strings); | 1612 __ b(lt, not_both_strings); |
| 1612 // If both objects are undetectable, they are equal. Otherwise, they | 1613 // If both objects are undetectable, they are equal. Otherwise, they |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1739 CompareIC::State expected, | 1740 CompareIC::State expected, |
| 1740 Label* fail) { | 1741 Label* fail) { |
| 1741 Label ok; | 1742 Label ok; |
| 1742 if (expected == CompareIC::SMI) { | 1743 if (expected == CompareIC::SMI) { |
| 1743 __ JumpIfNotSmi(input, fail); | 1744 __ JumpIfNotSmi(input, fail); |
| 1744 } else if (expected == CompareIC::HEAP_NUMBER) { | 1745 } else if (expected == CompareIC::HEAP_NUMBER) { |
| 1745 __ JumpIfSmi(input, &ok); | 1746 __ JumpIfSmi(input, &ok); |
| 1746 __ CheckMap(input, scratch, Heap::kHeapNumberMapRootIndex, fail, | 1747 __ CheckMap(input, scratch, Heap::kHeapNumberMapRootIndex, fail, |
| 1747 DONT_DO_SMI_CHECK); | 1748 DONT_DO_SMI_CHECK); |
| 1748 } | 1749 } |
| 1749 // We could be strict about symbol/string here, but as long as | 1750 // We could be strict about internalized/string here, but as long as |
|
Yang
2013/02/11 12:26:36
suggest to change to "... about internatilized/non
rossberg
2013/02/11 13:30:16
Done.
| |
| 1750 // hydrogen doesn't care, the stub doesn't have to care either. | 1751 // hydrogen doesn't care, the stub doesn't have to care either. |
| 1751 __ bind(&ok); | 1752 __ bind(&ok); |
| 1752 } | 1753 } |
| 1753 | 1754 |
| 1754 | 1755 |
| 1755 // On entry r1 and r2 are the values to be compared. | 1756 // On entry r1 and r2 are the values to be compared. |
| 1756 // On exit r0 is 0, positive or negative to indicate the result of | 1757 // On exit r0 is 0, positive or negative to indicate the result of |
| 1757 // the comparison. | 1758 // the comparison. |
| 1758 void ICCompareStub::GenerateGeneric(MacroAssembler* masm) { | 1759 void ICCompareStub::GenerateGeneric(MacroAssembler* masm) { |
| 1759 Register lhs = r1; | 1760 Register lhs = r1; |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1837 | 1838 |
| 1838 __ bind(¬_smis); | 1839 __ bind(¬_smis); |
| 1839 // At this point we know we are dealing with two different objects, | 1840 // At this point we know we are dealing with two different objects, |
| 1840 // and neither of them is a Smi. The objects are in rhs_ and lhs_. | 1841 // and neither of them is a Smi. The objects are in rhs_ and lhs_. |
| 1841 if (strict()) { | 1842 if (strict()) { |
| 1842 // This returns non-equal for some object types, or falls through if it | 1843 // This returns non-equal for some object types, or falls through if it |
| 1843 // was not lucky. | 1844 // was not lucky. |
| 1844 EmitStrictTwoHeapObjectCompare(masm, lhs, rhs); | 1845 EmitStrictTwoHeapObjectCompare(masm, lhs, rhs); |
| 1845 } | 1846 } |
| 1846 | 1847 |
| 1847 Label check_for_symbols; | 1848 Label check_for_internalized_strings; |
| 1848 Label flat_string_check; | 1849 Label flat_string_check; |
| 1849 // Check for heap-number-heap-number comparison. Can jump to slow case, | 1850 // Check for heap-number-heap-number comparison. Can jump to slow case, |
| 1850 // or load both doubles into r0, r1, r2, r3 and jump to the code that handles | 1851 // or load both doubles into r0, r1, r2, r3 and jump to the code that handles |
| 1851 // that case. If the inputs are not doubles then jumps to check_for_symbols. | 1852 // that case. If the inputs are not doubles then jumps to |
| 1853 // check_for_internalized_strings. | |
| 1852 // In this case r2 will contain the type of rhs_. Never falls through. | 1854 // In this case r2 will contain the type of rhs_. Never falls through. |
| 1853 EmitCheckForTwoHeapNumbers(masm, | 1855 EmitCheckForTwoHeapNumbers(masm, |
| 1854 lhs, | 1856 lhs, |
| 1855 rhs, | 1857 rhs, |
| 1856 &both_loaded_as_doubles, | 1858 &both_loaded_as_doubles, |
| 1857 &check_for_symbols, | 1859 &check_for_internalized_strings, |
| 1858 &flat_string_check); | 1860 &flat_string_check); |
| 1859 | 1861 |
| 1860 __ bind(&check_for_symbols); | 1862 __ bind(&check_for_internalized_strings); |
| 1861 // In the strict case the EmitStrictTwoHeapObjectCompare already took care of | 1863 // In the strict case the EmitStrictTwoHeapObjectCompare already took care of |
| 1862 // symbols. | 1864 // internalized strings. |
| 1863 if (cc == eq && !strict()) { | 1865 if (cc == eq && !strict()) { |
| 1864 // Returns an answer for two symbols or two detectable objects. | 1866 // Returns an answer for two internalized strings or two detectable objects. |
| 1865 // Otherwise jumps to string case or not both strings case. | 1867 // Otherwise jumps to string case or not both strings case. |
| 1866 // Assumes that r2 is the type of rhs_ on entry. | 1868 // Assumes that r2 is the type of rhs_ on entry. |
| 1867 EmitCheckForSymbolsOrObjects(masm, lhs, rhs, &flat_string_check, &slow); | 1869 EmitCheckForInternalizedStringsOrObjects( |
| 1870 masm, lhs, rhs, &flat_string_check, &slow); | |
| 1868 } | 1871 } |
| 1869 | 1872 |
| 1870 // Check for both being sequential ASCII strings, and inline if that is the | 1873 // Check for both being sequential ASCII strings, and inline if that is the |
| 1871 // case. | 1874 // case. |
| 1872 __ bind(&flat_string_check); | 1875 __ bind(&flat_string_check); |
| 1873 | 1876 |
| 1874 __ JumpIfNonSmisNotBothSequentialAsciiStrings(lhs, rhs, r2, r3, &slow); | 1877 __ JumpIfNonSmisNotBothSequentialAsciiStrings(lhs, rhs, r2, r3, &slow); |
| 1875 | 1878 |
| 1876 __ IncrementCounter(isolate->counters()->string_compare_native(), 1, r2, r3); | 1879 __ IncrementCounter(isolate->counters()->string_compare_native(), 1, r2, r3); |
| 1877 if (cc == eq) { | 1880 if (cc == eq) { |
| (...skipping 2648 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4526 | 4529 |
| 4527 void ArrayLengthStub::Generate(MacroAssembler* masm) { | 4530 void ArrayLengthStub::Generate(MacroAssembler* masm) { |
| 4528 Label miss; | 4531 Label miss; |
| 4529 Register receiver; | 4532 Register receiver; |
| 4530 if (kind() == Code::KEYED_LOAD_IC) { | 4533 if (kind() == Code::KEYED_LOAD_IC) { |
| 4531 // ----------- S t a t e ------------- | 4534 // ----------- S t a t e ------------- |
| 4532 // -- lr : return address | 4535 // -- lr : return address |
| 4533 // -- r0 : key | 4536 // -- r0 : key |
| 4534 // -- r1 : receiver | 4537 // -- r1 : receiver |
| 4535 // ----------------------------------- | 4538 // ----------------------------------- |
| 4536 __ cmp(r0, Operand(masm->isolate()->factory()->length_symbol())); | 4539 __ cmp(r0, Operand(masm->isolate()->factory()->length_string())); |
| 4537 __ b(ne, &miss); | 4540 __ b(ne, &miss); |
| 4538 receiver = r1; | 4541 receiver = r1; |
| 4539 } else { | 4542 } else { |
| 4540 ASSERT(kind() == Code::LOAD_IC); | 4543 ASSERT(kind() == Code::LOAD_IC); |
| 4541 // ----------- S t a t e ------------- | 4544 // ----------- S t a t e ------------- |
| 4542 // -- r2 : name | 4545 // -- r2 : name |
| 4543 // -- lr : return address | 4546 // -- lr : return address |
| 4544 // -- r0 : receiver | 4547 // -- r0 : receiver |
| 4545 // -- sp[0] : receiver | 4548 // -- sp[0] : receiver |
| 4546 // ----------------------------------- | 4549 // ----------------------------------- |
| 4547 receiver = r0; | 4550 receiver = r0; |
| 4548 } | 4551 } |
| 4549 | 4552 |
| 4550 StubCompiler::GenerateLoadArrayLength(masm, receiver, r3, &miss); | 4553 StubCompiler::GenerateLoadArrayLength(masm, receiver, r3, &miss); |
| 4551 __ bind(&miss); | 4554 __ bind(&miss); |
| 4552 StubCompiler::GenerateLoadMiss(masm, kind()); | 4555 StubCompiler::GenerateLoadMiss(masm, kind()); |
| 4553 } | 4556 } |
| 4554 | 4557 |
| 4555 | 4558 |
| 4556 void FunctionPrototypeStub::Generate(MacroAssembler* masm) { | 4559 void FunctionPrototypeStub::Generate(MacroAssembler* masm) { |
| 4557 Label miss; | 4560 Label miss; |
| 4558 Register receiver; | 4561 Register receiver; |
| 4559 if (kind() == Code::KEYED_LOAD_IC) { | 4562 if (kind() == Code::KEYED_LOAD_IC) { |
| 4560 // ----------- S t a t e ------------- | 4563 // ----------- S t a t e ------------- |
| 4561 // -- lr : return address | 4564 // -- lr : return address |
| 4562 // -- r0 : key | 4565 // -- r0 : key |
| 4563 // -- r1 : receiver | 4566 // -- r1 : receiver |
| 4564 // ----------------------------------- | 4567 // ----------------------------------- |
| 4565 __ cmp(r0, Operand(masm->isolate()->factory()->prototype_symbol())); | 4568 __ cmp(r0, Operand(masm->isolate()->factory()->prototype_string())); |
| 4566 __ b(ne, &miss); | 4569 __ b(ne, &miss); |
| 4567 receiver = r1; | 4570 receiver = r1; |
| 4568 } else { | 4571 } else { |
| 4569 ASSERT(kind() == Code::LOAD_IC); | 4572 ASSERT(kind() == Code::LOAD_IC); |
| 4570 // ----------- S t a t e ------------- | 4573 // ----------- S t a t e ------------- |
| 4571 // -- r2 : name | 4574 // -- r2 : name |
| 4572 // -- lr : return address | 4575 // -- lr : return address |
| 4573 // -- r0 : receiver | 4576 // -- r0 : receiver |
| 4574 // -- sp[0] : receiver | 4577 // -- sp[0] : receiver |
| 4575 // ----------------------------------- | 4578 // ----------------------------------- |
| 4576 receiver = r0; | 4579 receiver = r0; |
| 4577 } | 4580 } |
| 4578 | 4581 |
| 4579 StubCompiler::GenerateLoadFunctionPrototype(masm, receiver, r3, r4, &miss); | 4582 StubCompiler::GenerateLoadFunctionPrototype(masm, receiver, r3, r4, &miss); |
| 4580 __ bind(&miss); | 4583 __ bind(&miss); |
| 4581 StubCompiler::GenerateLoadMiss(masm, kind()); | 4584 StubCompiler::GenerateLoadMiss(masm, kind()); |
| 4582 } | 4585 } |
| 4583 | 4586 |
| 4584 | 4587 |
| 4585 void StringLengthStub::Generate(MacroAssembler* masm) { | 4588 void StringLengthStub::Generate(MacroAssembler* masm) { |
| 4586 Label miss; | 4589 Label miss; |
| 4587 Register receiver; | 4590 Register receiver; |
| 4588 if (kind() == Code::KEYED_LOAD_IC) { | 4591 if (kind() == Code::KEYED_LOAD_IC) { |
| 4589 // ----------- S t a t e ------------- | 4592 // ----------- S t a t e ------------- |
| 4590 // -- lr : return address | 4593 // -- lr : return address |
| 4591 // -- r0 : key | 4594 // -- r0 : key |
| 4592 // -- r1 : receiver | 4595 // -- r1 : receiver |
| 4593 // ----------------------------------- | 4596 // ----------------------------------- |
| 4594 __ cmp(r0, Operand(masm->isolate()->factory()->length_symbol())); | 4597 __ cmp(r0, Operand(masm->isolate()->factory()->length_string())); |
| 4595 __ b(ne, &miss); | 4598 __ b(ne, &miss); |
| 4596 receiver = r1; | 4599 receiver = r1; |
| 4597 } else { | 4600 } else { |
| 4598 ASSERT(kind() == Code::LOAD_IC); | 4601 ASSERT(kind() == Code::LOAD_IC); |
| 4599 // ----------- S t a t e ------------- | 4602 // ----------- S t a t e ------------- |
| 4600 // -- r2 : name | 4603 // -- r2 : name |
| 4601 // -- lr : return address | 4604 // -- lr : return address |
| 4602 // -- r0 : receiver | 4605 // -- r0 : receiver |
| 4603 // -- sp[0] : receiver | 4606 // -- sp[0] : receiver |
| 4604 // ----------------------------------- | 4607 // ----------------------------------- |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 4622 | 4625 |
| 4623 Register receiver; | 4626 Register receiver; |
| 4624 Register value; | 4627 Register value; |
| 4625 if (kind() == Code::KEYED_STORE_IC) { | 4628 if (kind() == Code::KEYED_STORE_IC) { |
| 4626 // ----------- S t a t e ------------- | 4629 // ----------- S t a t e ------------- |
| 4627 // -- lr : return address | 4630 // -- lr : return address |
| 4628 // -- r0 : value | 4631 // -- r0 : value |
| 4629 // -- r1 : key | 4632 // -- r1 : key |
| 4630 // -- r2 : receiver | 4633 // -- r2 : receiver |
| 4631 // ----------------------------------- | 4634 // ----------------------------------- |
| 4632 __ cmp(r1, Operand(masm->isolate()->factory()->length_symbol())); | 4635 __ cmp(r1, Operand(masm->isolate()->factory()->length_string())); |
| 4633 __ b(ne, &miss); | 4636 __ b(ne, &miss); |
| 4634 receiver = r2; | 4637 receiver = r2; |
| 4635 value = r0; | 4638 value = r0; |
| 4636 } else { | 4639 } else { |
| 4637 ASSERT(kind() == Code::STORE_IC); | 4640 ASSERT(kind() == Code::STORE_IC); |
| 4638 // ----------- S t a t e ------------- | 4641 // ----------- S t a t e ------------- |
| 4639 // -- lr : return address | 4642 // -- lr : return address |
| 4640 // -- r0 : value | 4643 // -- r0 : value |
| 4641 // -- r1 : receiver | 4644 // -- r1 : receiver |
| 4642 // -- r2 : key | 4645 // -- r2 : key |
| (...skipping 583 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5226 | 5229 |
| 5227 // String is sliced. | 5230 // String is sliced. |
| 5228 __ ldr(r9, FieldMemOperand(subject, SlicedString::kOffsetOffset)); | 5231 __ ldr(r9, FieldMemOperand(subject, SlicedString::kOffsetOffset)); |
| 5229 __ mov(r9, Operand(r9, ASR, kSmiTagSize)); | 5232 __ mov(r9, Operand(r9, ASR, kSmiTagSize)); |
| 5230 __ ldr(subject, FieldMemOperand(subject, SlicedString::kParentOffset)); | 5233 __ ldr(subject, FieldMemOperand(subject, SlicedString::kParentOffset)); |
| 5231 // r9: offset of sliced string, smi-tagged. | 5234 // r9: offset of sliced string, smi-tagged. |
| 5232 __ jmp(&check_encoding); | 5235 __ jmp(&check_encoding); |
| 5233 // String is a cons string, check whether it is flat. | 5236 // String is a cons string, check whether it is flat. |
| 5234 __ bind(&cons_string); | 5237 __ bind(&cons_string); |
| 5235 __ ldr(r0, FieldMemOperand(subject, ConsString::kSecondOffset)); | 5238 __ ldr(r0, FieldMemOperand(subject, ConsString::kSecondOffset)); |
| 5236 __ CompareRoot(r0, Heap::kEmptyStringRootIndex); | 5239 __ CompareRoot(r0, Heap::kempty_stringRootIndex); |
| 5237 __ b(ne, &runtime); | 5240 __ b(ne, &runtime); |
| 5238 __ ldr(subject, FieldMemOperand(subject, ConsString::kFirstOffset)); | 5241 __ ldr(subject, FieldMemOperand(subject, ConsString::kFirstOffset)); |
| 5239 // Is first part of cons or parent of slice a flat string? | 5242 // Is first part of cons or parent of slice a flat string? |
| 5240 __ bind(&check_encoding); | 5243 __ bind(&check_encoding); |
| 5241 __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset)); | 5244 __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset)); |
| 5242 __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset)); | 5245 __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset)); |
| 5243 STATIC_ASSERT(kSeqStringTag == 0); | 5246 STATIC_ASSERT(kSeqStringTag == 0); |
| 5244 __ tst(r0, Operand(kStringRepresentationMask)); | 5247 __ tst(r0, Operand(kStringRepresentationMask)); |
| 5245 __ b(ne, &external_string); | 5248 __ b(ne, &external_string); |
| 5246 | 5249 |
| (...skipping 824 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6071 __ cmp(dest, Operand(limit)); | 6074 __ cmp(dest, Operand(limit)); |
| 6072 __ ldrb(scratch1, MemOperand(src, 1, PostIndex), lt); | 6075 __ ldrb(scratch1, MemOperand(src, 1, PostIndex), lt); |
| 6073 __ b(ge, &done); | 6076 __ b(ge, &done); |
| 6074 __ strb(scratch1, MemOperand(dest, 1, PostIndex)); | 6077 __ strb(scratch1, MemOperand(dest, 1, PostIndex)); |
| 6075 __ b(&byte_loop); | 6078 __ b(&byte_loop); |
| 6076 | 6079 |
| 6077 __ bind(&done); | 6080 __ bind(&done); |
| 6078 } | 6081 } |
| 6079 | 6082 |
| 6080 | 6083 |
| 6081 void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm, | 6084 void StringHelper::GenerateTwoCharacterStringTableProbe(MacroAssembler* masm, |
| 6082 Register c1, | 6085 Register c1, |
| 6083 Register c2, | 6086 Register c2, |
| 6084 Register scratch1, | 6087 Register scratch1, |
| 6085 Register scratch2, | 6088 Register scratch2, |
| 6086 Register scratch3, | 6089 Register scratch3, |
| 6087 Register scratch4, | 6090 Register scratch4, |
| 6088 Register scratch5, | 6091 Register scratch5, |
| 6089 Label* not_found) { | 6092 Label* not_found) { |
| 6090 // Register scratch3 is the general scratch register in this function. | 6093 // Register scratch3 is the general scratch register in this function. |
| 6091 Register scratch = scratch3; | 6094 Register scratch = scratch3; |
| 6092 | 6095 |
| 6093 // Make sure that both characters are not digits as such strings has a | 6096 // Make sure that both characters are not digits as such strings has a |
| 6094 // different hash algorithm. Don't try to look for these in the symbol table. | 6097 // different hash algorithm. Don't try to look for these in the string table. |
| 6095 Label not_array_index; | 6098 Label not_array_index; |
| 6096 __ sub(scratch, c1, Operand(static_cast<int>('0'))); | 6099 __ sub(scratch, c1, Operand(static_cast<int>('0'))); |
| 6097 __ cmp(scratch, Operand(static_cast<int>('9' - '0'))); | 6100 __ cmp(scratch, Operand(static_cast<int>('9' - '0'))); |
| 6098 __ b(hi, ¬_array_index); | 6101 __ b(hi, ¬_array_index); |
| 6099 __ sub(scratch, c2, Operand(static_cast<int>('0'))); | 6102 __ sub(scratch, c2, Operand(static_cast<int>('0'))); |
| 6100 __ cmp(scratch, Operand(static_cast<int>('9' - '0'))); | 6103 __ cmp(scratch, Operand(static_cast<int>('9' - '0'))); |
| 6101 | 6104 |
| 6102 // If check failed combine both characters into single halfword. | 6105 // If check failed combine both characters into single halfword. |
| 6103 // This is required by the contract of the method: code at the | 6106 // This is required by the contract of the method: code at the |
| 6104 // not_found branch expects this combination in c1 register | 6107 // not_found branch expects this combination in c1 register |
| 6105 __ orr(c1, c1, Operand(c2, LSL, kBitsPerByte), LeaveCC, ls); | 6108 __ orr(c1, c1, Operand(c2, LSL, kBitsPerByte), LeaveCC, ls); |
| 6106 __ b(ls, not_found); | 6109 __ b(ls, not_found); |
| 6107 | 6110 |
| 6108 __ bind(¬_array_index); | 6111 __ bind(¬_array_index); |
| 6109 // Calculate the two character string hash. | 6112 // Calculate the two character string hash. |
| 6110 Register hash = scratch1; | 6113 Register hash = scratch1; |
| 6111 StringHelper::GenerateHashInit(masm, hash, c1); | 6114 StringHelper::GenerateHashInit(masm, hash, c1); |
| 6112 StringHelper::GenerateHashAddCharacter(masm, hash, c2); | 6115 StringHelper::GenerateHashAddCharacter(masm, hash, c2); |
| 6113 StringHelper::GenerateHashGetHash(masm, hash); | 6116 StringHelper::GenerateHashGetHash(masm, hash); |
| 6114 | 6117 |
| 6115 // Collect the two characters in a register. | 6118 // Collect the two characters in a register. |
| 6116 Register chars = c1; | 6119 Register chars = c1; |
| 6117 __ orr(chars, chars, Operand(c2, LSL, kBitsPerByte)); | 6120 __ orr(chars, chars, Operand(c2, LSL, kBitsPerByte)); |
| 6118 | 6121 |
| 6119 // chars: two character string, char 1 in byte 0 and char 2 in byte 1. | 6122 // chars: two character string, char 1 in byte 0 and char 2 in byte 1. |
| 6120 // hash: hash of two character string. | 6123 // hash: hash of two character string. |
| 6121 | 6124 |
| 6122 // Load symbol table | 6125 // Load string table |
| 6123 // Load address of first element of the symbol table. | 6126 // Load address of first element of the string table. |
| 6124 Register symbol_table = c2; | 6127 Register string_table = c2; |
| 6125 __ LoadRoot(symbol_table, Heap::kSymbolTableRootIndex); | 6128 __ LoadRoot(string_table, Heap::kStringTableRootIndex); |
| 6126 | 6129 |
| 6127 Register undefined = scratch4; | 6130 Register undefined = scratch4; |
| 6128 __ LoadRoot(undefined, Heap::kUndefinedValueRootIndex); | 6131 __ LoadRoot(undefined, Heap::kUndefinedValueRootIndex); |
| 6129 | 6132 |
| 6130 // Calculate capacity mask from the symbol table capacity. | 6133 // Calculate capacity mask from the string table capacity. |
| 6131 Register mask = scratch2; | 6134 Register mask = scratch2; |
| 6132 __ ldr(mask, FieldMemOperand(symbol_table, SymbolTable::kCapacityOffset)); | 6135 __ ldr(mask, FieldMemOperand(string_table, StringTable::kCapacityOffset)); |
| 6133 __ mov(mask, Operand(mask, ASR, 1)); | 6136 __ mov(mask, Operand(mask, ASR, 1)); |
| 6134 __ sub(mask, mask, Operand(1)); | 6137 __ sub(mask, mask, Operand(1)); |
| 6135 | 6138 |
| 6136 // Calculate untagged address of the first element of the symbol table. | 6139 // Calculate untagged address of the first element of the string table. |
| 6137 Register first_symbol_table_element = symbol_table; | 6140 Register first_string_table_element = string_table; |
| 6138 __ add(first_symbol_table_element, symbol_table, | 6141 __ add(first_string_table_element, string_table, |
| 6139 Operand(SymbolTable::kElementsStartOffset - kHeapObjectTag)); | 6142 Operand(StringTable::kElementsStartOffset - kHeapObjectTag)); |
| 6140 | 6143 |
| 6141 // Registers | 6144 // Registers |
| 6142 // chars: two character string, char 1 in byte 0 and char 2 in byte 1. | 6145 // chars: two character string, char 1 in byte 0 and char 2 in byte 1. |
| 6143 // hash: hash of two character string | 6146 // hash: hash of two character string |
| 6144 // mask: capacity mask | 6147 // mask: capacity mask |
| 6145 // first_symbol_table_element: address of the first element of | 6148 // first_string_table_element: address of the first element of |
| 6146 // the symbol table | 6149 // the string table |
| 6147 // undefined: the undefined object | 6150 // undefined: the undefined object |
| 6148 // scratch: - | 6151 // scratch: - |
| 6149 | 6152 |
| 6150 // Perform a number of probes in the symbol table. | 6153 // Perform a number of probes in the string table. |
| 6151 const int kProbes = 4; | 6154 const int kProbes = 4; |
| 6152 Label found_in_symbol_table; | 6155 Label found_in_string_table; |
| 6153 Label next_probe[kProbes]; | 6156 Label next_probe[kProbes]; |
| 6154 Register candidate = scratch5; // Scratch register contains candidate. | 6157 Register candidate = scratch5; // Scratch register contains candidate. |
| 6155 for (int i = 0; i < kProbes; i++) { | 6158 for (int i = 0; i < kProbes; i++) { |
| 6156 // Calculate entry in symbol table. | 6159 // Calculate entry in string table. |
| 6157 if (i > 0) { | 6160 if (i > 0) { |
| 6158 __ add(candidate, hash, Operand(SymbolTable::GetProbeOffset(i))); | 6161 __ add(candidate, hash, Operand(StringTable::GetProbeOffset(i))); |
| 6159 } else { | 6162 } else { |
| 6160 __ mov(candidate, hash); | 6163 __ mov(candidate, hash); |
| 6161 } | 6164 } |
| 6162 | 6165 |
| 6163 __ and_(candidate, candidate, Operand(mask)); | 6166 __ and_(candidate, candidate, Operand(mask)); |
| 6164 | 6167 |
| 6165 // Load the entry from the symble table. | 6168 // Load the entry from the symble table. |
| 6166 STATIC_ASSERT(SymbolTable::kEntrySize == 1); | 6169 STATIC_ASSERT(StringTable::kEntrySize == 1); |
| 6167 __ ldr(candidate, | 6170 __ ldr(candidate, |
| 6168 MemOperand(first_symbol_table_element, | 6171 MemOperand(first_string_table_element, |
| 6169 candidate, | 6172 candidate, |
| 6170 LSL, | 6173 LSL, |
| 6171 kPointerSizeLog2)); | 6174 kPointerSizeLog2)); |
| 6172 | 6175 |
| 6173 // If entry is undefined no string with this hash can be found. | 6176 // If entry is undefined no string with this hash can be found. |
| 6174 Label is_string; | 6177 Label is_string; |
| 6175 __ CompareObjectType(candidate, scratch, scratch, ODDBALL_TYPE); | 6178 __ CompareObjectType(candidate, scratch, scratch, ODDBALL_TYPE); |
| 6176 __ b(ne, &is_string); | 6179 __ b(ne, &is_string); |
| 6177 | 6180 |
| 6178 __ cmp(undefined, candidate); | 6181 __ cmp(undefined, candidate); |
| 6179 __ b(eq, not_found); | 6182 __ b(eq, not_found); |
| 6180 // Must be the hole (deleted entry). | 6183 // Must be the hole (deleted entry). |
| 6181 if (FLAG_debug_code) { | 6184 if (FLAG_debug_code) { |
| 6182 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 6185 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
| 6183 __ cmp(ip, candidate); | 6186 __ cmp(ip, candidate); |
| 6184 __ Assert(eq, "oddball in symbol table is not undefined or the hole"); | 6187 __ Assert(eq, "oddball in string table is not undefined or the hole"); |
| 6185 } | 6188 } |
| 6186 __ jmp(&next_probe[i]); | 6189 __ jmp(&next_probe[i]); |
| 6187 | 6190 |
| 6188 __ bind(&is_string); | 6191 __ bind(&is_string); |
| 6189 | 6192 |
| 6190 // Check that the candidate is a non-external ASCII string. The instance | 6193 // Check that the candidate is a non-external ASCII string. The instance |
| 6191 // type is still in the scratch register from the CompareObjectType | 6194 // type is still in the scratch register from the CompareObjectType |
| 6192 // operation. | 6195 // operation. |
| 6193 __ JumpIfInstanceTypeIsNotSequentialAscii(scratch, scratch, &next_probe[i]); | 6196 __ JumpIfInstanceTypeIsNotSequentialAscii(scratch, scratch, &next_probe[i]); |
| 6194 | 6197 |
| 6195 // If length is not 2 the string is not a candidate. | 6198 // If length is not 2 the string is not a candidate. |
| 6196 __ ldr(scratch, FieldMemOperand(candidate, String::kLengthOffset)); | 6199 __ ldr(scratch, FieldMemOperand(candidate, String::kLengthOffset)); |
| 6197 __ cmp(scratch, Operand(Smi::FromInt(2))); | 6200 __ cmp(scratch, Operand(Smi::FromInt(2))); |
| 6198 __ b(ne, &next_probe[i]); | 6201 __ b(ne, &next_probe[i]); |
| 6199 | 6202 |
| 6200 // Check if the two characters match. | 6203 // Check if the two characters match. |
| 6201 // Assumes that word load is little endian. | 6204 // Assumes that word load is little endian. |
| 6202 __ ldrh(scratch, FieldMemOperand(candidate, SeqOneByteString::kHeaderSize)); | 6205 __ ldrh(scratch, FieldMemOperand(candidate, SeqOneByteString::kHeaderSize)); |
| 6203 __ cmp(chars, scratch); | 6206 __ cmp(chars, scratch); |
| 6204 __ b(eq, &found_in_symbol_table); | 6207 __ b(eq, &found_in_string_table); |
| 6205 __ bind(&next_probe[i]); | 6208 __ bind(&next_probe[i]); |
| 6206 } | 6209 } |
| 6207 | 6210 |
| 6208 // No matching 2 character string found by probing. | 6211 // No matching 2 character string found by probing. |
| 6209 __ jmp(not_found); | 6212 __ jmp(not_found); |
| 6210 | 6213 |
| 6211 // Scratch register contains result when we fall through to here. | 6214 // Scratch register contains result when we fall through to here. |
| 6212 Register result = candidate; | 6215 Register result = candidate; |
| 6213 __ bind(&found_in_symbol_table); | 6216 __ bind(&found_in_string_table); |
| 6214 __ Move(r0, result); | 6217 __ Move(r0, result); |
| 6215 } | 6218 } |
| 6216 | 6219 |
| 6217 | 6220 |
| 6218 void StringHelper::GenerateHashInit(MacroAssembler* masm, | 6221 void StringHelper::GenerateHashInit(MacroAssembler* masm, |
| 6219 Register hash, | 6222 Register hash, |
| 6220 Register character) { | 6223 Register character) { |
| 6221 // hash = character + (character << 10); | 6224 // hash = character + (character << 10); |
| 6222 __ LoadRoot(hash, Heap::kHashSeedRootIndex); | 6225 __ LoadRoot(hash, Heap::kHashSeedRootIndex); |
| 6223 // Untag smi seed and add the character. | 6226 // Untag smi seed and add the character. |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6328 // If the string is not indirect, it can only be sequential or external. | 6331 // If the string is not indirect, it can only be sequential or external. |
| 6329 STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag)); | 6332 STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag)); |
| 6330 STATIC_ASSERT(kIsIndirectStringMask != 0); | 6333 STATIC_ASSERT(kIsIndirectStringMask != 0); |
| 6331 __ tst(r1, Operand(kIsIndirectStringMask)); | 6334 __ tst(r1, Operand(kIsIndirectStringMask)); |
| 6332 __ b(eq, &seq_or_external_string); | 6335 __ b(eq, &seq_or_external_string); |
| 6333 | 6336 |
| 6334 __ tst(r1, Operand(kSlicedNotConsMask)); | 6337 __ tst(r1, Operand(kSlicedNotConsMask)); |
| 6335 __ b(ne, &sliced_string); | 6338 __ b(ne, &sliced_string); |
| 6336 // Cons string. Check whether it is flat, then fetch first part. | 6339 // Cons string. Check whether it is flat, then fetch first part. |
| 6337 __ ldr(r5, FieldMemOperand(r0, ConsString::kSecondOffset)); | 6340 __ ldr(r5, FieldMemOperand(r0, ConsString::kSecondOffset)); |
| 6338 __ CompareRoot(r5, Heap::kEmptyStringRootIndex); | 6341 __ CompareRoot(r5, Heap::kempty_stringRootIndex); |
| 6339 __ b(ne, &runtime); | 6342 __ b(ne, &runtime); |
| 6340 __ ldr(r5, FieldMemOperand(r0, ConsString::kFirstOffset)); | 6343 __ ldr(r5, FieldMemOperand(r0, ConsString::kFirstOffset)); |
| 6341 // Update instance type. | 6344 // Update instance type. |
| 6342 __ ldr(r1, FieldMemOperand(r5, HeapObject::kMapOffset)); | 6345 __ ldr(r1, FieldMemOperand(r5, HeapObject::kMapOffset)); |
| 6343 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset)); | 6346 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset)); |
| 6344 __ jmp(&underlying_unpacked); | 6347 __ jmp(&underlying_unpacked); |
| 6345 | 6348 |
| 6346 __ bind(&sliced_string); | 6349 __ bind(&sliced_string); |
| 6347 // Sliced string. Fetch parent and correct start index by offset. | 6350 // Sliced string. Fetch parent and correct start index by offset. |
| 6348 __ ldr(r5, FieldMemOperand(r0, SlicedString::kParentOffset)); | 6351 __ ldr(r5, FieldMemOperand(r0, SlicedString::kParentOffset)); |
| (...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6688 // r1: second string | 6691 // r1: second string |
| 6689 // r2: length of first string | 6692 // r2: length of first string |
| 6690 // r3: length of second string | 6693 // r3: length of second string |
| 6691 // r4: first string instance type (if flags_ == NO_STRING_ADD_FLAGS) | 6694 // r4: first string instance type (if flags_ == NO_STRING_ADD_FLAGS) |
| 6692 // r5: second string instance type (if flags_ == NO_STRING_ADD_FLAGS) | 6695 // r5: second string instance type (if flags_ == NO_STRING_ADD_FLAGS) |
| 6693 // Look at the length of the result of adding the two strings. | 6696 // Look at the length of the result of adding the two strings. |
| 6694 Label string_add_flat_result, longer_than_two; | 6697 Label string_add_flat_result, longer_than_two; |
| 6695 // Adding two lengths can't overflow. | 6698 // Adding two lengths can't overflow. |
| 6696 STATIC_ASSERT(String::kMaxLength < String::kMaxLength * 2); | 6699 STATIC_ASSERT(String::kMaxLength < String::kMaxLength * 2); |
| 6697 __ add(r6, r2, Operand(r3)); | 6700 __ add(r6, r2, Operand(r3)); |
| 6698 // Use the symbol table when adding two one character strings, as it | 6701 // Use the string table when adding two one character strings, as it |
| 6699 // helps later optimizations to return a symbol here. | 6702 // helps later optimizations to return a string here. |
| 6700 __ cmp(r6, Operand(2)); | 6703 __ cmp(r6, Operand(2)); |
| 6701 __ b(ne, &longer_than_two); | 6704 __ b(ne, &longer_than_two); |
| 6702 | 6705 |
| 6703 // Check that both strings are non-external ASCII strings. | 6706 // Check that both strings are non-external ASCII strings. |
| 6704 if (flags_ != NO_STRING_ADD_FLAGS) { | 6707 if (flags_ != NO_STRING_ADD_FLAGS) { |
| 6705 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); | 6708 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); |
| 6706 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); | 6709 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); |
| 6707 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); | 6710 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); |
| 6708 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); | 6711 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); |
| 6709 } | 6712 } |
| 6710 __ JumpIfBothInstanceTypesAreNotSequentialAscii(r4, r5, r6, r7, | 6713 __ JumpIfBothInstanceTypesAreNotSequentialAscii(r4, r5, r6, r7, |
| 6711 &call_runtime); | 6714 &call_runtime); |
| 6712 | 6715 |
| 6713 // Get the two characters forming the sub string. | 6716 // Get the two characters forming the sub string. |
| 6714 __ ldrb(r2, FieldMemOperand(r0, SeqOneByteString::kHeaderSize)); | 6717 __ ldrb(r2, FieldMemOperand(r0, SeqOneByteString::kHeaderSize)); |
| 6715 __ ldrb(r3, FieldMemOperand(r1, SeqOneByteString::kHeaderSize)); | 6718 __ ldrb(r3, FieldMemOperand(r1, SeqOneByteString::kHeaderSize)); |
| 6716 | 6719 |
| 6717 // Try to lookup two character string in symbol table. If it is not found | 6720 // Try to lookup two character string in string table. If it is not found |
| 6718 // just allocate a new one. | 6721 // just allocate a new one. |
| 6719 Label make_two_character_string; | 6722 Label make_two_character_string; |
| 6720 StringHelper::GenerateTwoCharacterSymbolTableProbe( | 6723 StringHelper::GenerateTwoCharacterStringTableProbe( |
| 6721 masm, r2, r3, r6, r7, r4, r5, r9, &make_two_character_string); | 6724 masm, r2, r3, r6, r7, r4, r5, r9, &make_two_character_string); |
| 6722 __ IncrementCounter(counters->string_add_native(), 1, r2, r3); | 6725 __ IncrementCounter(counters->string_add_native(), 1, r2, r3); |
| 6723 __ add(sp, sp, Operand(2 * kPointerSize)); | 6726 __ add(sp, sp, Operand(2 * kPointerSize)); |
| 6724 __ Ret(); | 6727 __ Ret(); |
| 6725 | 6728 |
| 6726 __ bind(&make_two_character_string); | 6729 __ bind(&make_two_character_string); |
| 6727 // Resulting string has length 2 and first chars of two strings | 6730 // Resulting string has length 2 and first chars of two strings |
| 6728 // are combined into single halfword in r2 register. | 6731 // are combined into single halfword in r2 register. |
| 6729 // So we can fill resulting string without two loops by a single | 6732 // So we can fill resulting string without two loops by a single |
| 6730 // halfword store instruction (which assumes that processor is | 6733 // halfword store instruction (which assumes that processor is |
| (...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7051 if (Token::IsOrderedRelationalCompareOp(op_)) { | 7054 if (Token::IsOrderedRelationalCompareOp(op_)) { |
| 7052 __ CompareRoot(r1, Heap::kUndefinedValueRootIndex); | 7055 __ CompareRoot(r1, Heap::kUndefinedValueRootIndex); |
| 7053 __ b(eq, &unordered); | 7056 __ b(eq, &unordered); |
| 7054 } | 7057 } |
| 7055 | 7058 |
| 7056 __ bind(&miss); | 7059 __ bind(&miss); |
| 7057 GenerateMiss(masm); | 7060 GenerateMiss(masm); |
| 7058 } | 7061 } |
| 7059 | 7062 |
| 7060 | 7063 |
| 7061 void ICCompareStub::GenerateSymbols(MacroAssembler* masm) { | 7064 void ICCompareStub::GenerateInternalizedStrings(MacroAssembler* masm) { |
| 7062 ASSERT(state_ == CompareIC::SYMBOL); | 7065 ASSERT(state_ == CompareIC::INTERNALIZED_STRING); |
| 7063 Label miss; | 7066 Label miss; |
| 7064 | 7067 |
| 7065 // Registers containing left and right operands respectively. | 7068 // Registers containing left and right operands respectively. |
| 7066 Register left = r1; | 7069 Register left = r1; |
| 7067 Register right = r0; | 7070 Register right = r0; |
| 7068 Register tmp1 = r2; | 7071 Register tmp1 = r2; |
| 7069 Register tmp2 = r3; | 7072 Register tmp2 = r3; |
| 7070 | 7073 |
| 7071 // Check that both operands are heap objects. | 7074 // Check that both operands are heap objects. |
| 7072 __ JumpIfEitherSmi(left, right, &miss); | 7075 __ JumpIfEitherSmi(left, right, &miss); |
| 7073 | 7076 |
| 7074 // Check that both operands are symbols. | 7077 // Check that both operands are internalized strings. |
| 7075 __ ldr(tmp1, FieldMemOperand(left, HeapObject::kMapOffset)); | 7078 __ ldr(tmp1, FieldMemOperand(left, HeapObject::kMapOffset)); |
| 7076 __ ldr(tmp2, FieldMemOperand(right, HeapObject::kMapOffset)); | 7079 __ ldr(tmp2, FieldMemOperand(right, HeapObject::kMapOffset)); |
| 7077 __ ldrb(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset)); | 7080 __ ldrb(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset)); |
| 7078 __ ldrb(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset)); | 7081 __ ldrb(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset)); |
| 7079 STATIC_ASSERT(kSymbolTag != 0); | 7082 STATIC_ASSERT(kInternalizedTag != 0); |
| 7080 __ and_(tmp1, tmp1, Operand(tmp2)); | 7083 __ and_(tmp1, tmp1, Operand(tmp2)); |
| 7081 __ tst(tmp1, Operand(kIsSymbolMask)); | 7084 __ tst(tmp1, Operand(kIsInternalizedMask)); |
| 7082 __ b(eq, &miss); | 7085 __ b(eq, &miss); |
| 7083 | 7086 |
| 7084 // Symbols are compared by identity. | 7087 // Internalized strings are compared by identity. |
| 7085 __ cmp(left, right); | 7088 __ cmp(left, right); |
| 7086 // Make sure r0 is non-zero. At this point input operands are | 7089 // Make sure r0 is non-zero. At this point input operands are |
| 7087 // guaranteed to be non-zero. | 7090 // guaranteed to be non-zero. |
| 7088 ASSERT(right.is(r0)); | 7091 ASSERT(right.is(r0)); |
| 7089 STATIC_ASSERT(EQUAL == 0); | 7092 STATIC_ASSERT(EQUAL == 0); |
| 7090 STATIC_ASSERT(kSmiTag == 0); | 7093 STATIC_ASSERT(kSmiTag == 0); |
| 7091 __ mov(r0, Operand(Smi::FromInt(EQUAL)), LeaveCC, eq); | 7094 __ mov(r0, Operand(Smi::FromInt(EQUAL)), LeaveCC, eq); |
| 7092 __ Ret(); | 7095 __ Ret(); |
| 7093 | 7096 |
| 7094 __ bind(&miss); | 7097 __ bind(&miss); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7126 | 7129 |
| 7127 // Fast check for identical strings. | 7130 // Fast check for identical strings. |
| 7128 __ cmp(left, right); | 7131 __ cmp(left, right); |
| 7129 STATIC_ASSERT(EQUAL == 0); | 7132 STATIC_ASSERT(EQUAL == 0); |
| 7130 STATIC_ASSERT(kSmiTag == 0); | 7133 STATIC_ASSERT(kSmiTag == 0); |
| 7131 __ mov(r0, Operand(Smi::FromInt(EQUAL)), LeaveCC, eq); | 7134 __ mov(r0, Operand(Smi::FromInt(EQUAL)), LeaveCC, eq); |
| 7132 __ Ret(eq); | 7135 __ Ret(eq); |
| 7133 | 7136 |
| 7134 // Handle not identical strings. | 7137 // Handle not identical strings. |
| 7135 | 7138 |
| 7136 // Check that both strings are symbols. If they are, we're done | 7139 // Check that both strings are internalized strings. If they are, we're done |
| 7137 // because we already know they are not identical. | 7140 // because we already know they are not identical. |
| 7138 if (equality) { | 7141 if (equality) { |
| 7139 ASSERT(GetCondition() == eq); | 7142 ASSERT(GetCondition() == eq); |
| 7140 STATIC_ASSERT(kSymbolTag != 0); | 7143 STATIC_ASSERT(kInternalizedTag != 0); |
| 7141 __ and_(tmp3, tmp1, Operand(tmp2)); | 7144 __ and_(tmp3, tmp1, Operand(tmp2)); |
| 7142 __ tst(tmp3, Operand(kIsSymbolMask)); | 7145 __ tst(tmp3, Operand(kIsInternalizedMask)); |
| 7143 // Make sure r0 is non-zero. At this point input operands are | 7146 // Make sure r0 is non-zero. At this point input operands are |
| 7144 // guaranteed to be non-zero. | 7147 // guaranteed to be non-zero. |
| 7145 ASSERT(right.is(r0)); | 7148 ASSERT(right.is(r0)); |
| 7146 __ Ret(ne); | 7149 __ Ret(ne); |
| 7147 } | 7150 } |
| 7148 | 7151 |
| 7149 // Check that both strings are sequential ASCII. | 7152 // Check that both strings are sequential ASCII. |
| 7150 Label runtime; | 7153 Label runtime; |
| 7151 __ JumpIfBothInstanceTypesAreNotSequentialAscii( | 7154 __ JumpIfBothInstanceTypesAreNotSequentialAscii( |
| 7152 tmp1, tmp2, tmp3, tmp4, &runtime); | 7155 tmp1, tmp2, tmp3, tmp4, &runtime); |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7314 __ LoadRoot(tmp, Heap::kTheHoleValueRootIndex); | 7317 __ LoadRoot(tmp, Heap::kTheHoleValueRootIndex); |
| 7315 | 7318 |
| 7316 // Stop if found the property. | 7319 // Stop if found the property. |
| 7317 __ cmp(entity_name, Operand(Handle<String>(name))); | 7320 __ cmp(entity_name, Operand(Handle<String>(name))); |
| 7318 __ b(eq, miss); | 7321 __ b(eq, miss); |
| 7319 | 7322 |
| 7320 Label the_hole; | 7323 Label the_hole; |
| 7321 __ cmp(entity_name, tmp); | 7324 __ cmp(entity_name, tmp); |
| 7322 __ b(eq, &the_hole); | 7325 __ b(eq, &the_hole); |
| 7323 | 7326 |
| 7324 // Check if the entry name is not a symbol. | 7327 // Check if the entry name is not an internalized string. |
| 7325 __ ldr(entity_name, FieldMemOperand(entity_name, HeapObject::kMapOffset)); | 7328 __ ldr(entity_name, FieldMemOperand(entity_name, HeapObject::kMapOffset)); |
| 7326 __ ldrb(entity_name, | 7329 __ ldrb(entity_name, |
| 7327 FieldMemOperand(entity_name, Map::kInstanceTypeOffset)); | 7330 FieldMemOperand(entity_name, Map::kInstanceTypeOffset)); |
| 7328 __ tst(entity_name, Operand(kIsSymbolMask)); | 7331 __ tst(entity_name, Operand(kIsInternalizedMask)); |
| 7329 __ b(eq, miss); | 7332 __ b(eq, miss); |
| 7330 | 7333 |
| 7331 __ bind(&the_hole); | 7334 __ bind(&the_hole); |
| 7332 | 7335 |
| 7333 // Restore the properties. | 7336 // Restore the properties. |
| 7334 __ ldr(properties, | 7337 __ ldr(properties, |
| 7335 FieldMemOperand(receiver, JSObject::kPropertiesOffset)); | 7338 FieldMemOperand(receiver, JSObject::kPropertiesOffset)); |
| 7336 } | 7339 } |
| 7337 } | 7340 } |
| 7338 | 7341 |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7487 | 7490 |
| 7488 // Having undefined at this place means the name is not contained. | 7491 // Having undefined at this place means the name is not contained. |
| 7489 __ cmp(entry_key, Operand(undefined)); | 7492 __ cmp(entry_key, Operand(undefined)); |
| 7490 __ b(eq, ¬_in_dictionary); | 7493 __ b(eq, ¬_in_dictionary); |
| 7491 | 7494 |
| 7492 // Stop if found the property. | 7495 // Stop if found the property. |
| 7493 __ cmp(entry_key, Operand(key)); | 7496 __ cmp(entry_key, Operand(key)); |
| 7494 __ b(eq, &in_dictionary); | 7497 __ b(eq, &in_dictionary); |
| 7495 | 7498 |
| 7496 if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) { | 7499 if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) { |
| 7497 // Check if the entry name is not a symbol. | 7500 // Check if the entry name is not an internalized string. |
| 7498 __ ldr(entry_key, FieldMemOperand(entry_key, HeapObject::kMapOffset)); | 7501 __ ldr(entry_key, FieldMemOperand(entry_key, HeapObject::kMapOffset)); |
| 7499 __ ldrb(entry_key, | 7502 __ ldrb(entry_key, |
| 7500 FieldMemOperand(entry_key, Map::kInstanceTypeOffset)); | 7503 FieldMemOperand(entry_key, Map::kInstanceTypeOffset)); |
| 7501 __ tst(entry_key, Operand(kIsSymbolMask)); | 7504 __ tst(entry_key, Operand(kIsInternalizedMask)); |
| 7502 __ b(eq, &maybe_in_dictionary); | 7505 __ b(eq, &maybe_in_dictionary); |
| 7503 } | 7506 } |
| 7504 } | 7507 } |
| 7505 | 7508 |
| 7506 __ bind(&maybe_in_dictionary); | 7509 __ bind(&maybe_in_dictionary); |
| 7507 // If we are doing negative lookup then probing failure should be | 7510 // If we are doing negative lookup then probing failure should be |
| 7508 // treated as a lookup success. For positive lookup probing failure | 7511 // treated as a lookup success. For positive lookup probing failure |
| 7509 // should be treated as lookup failure. | 7512 // should be treated as lookup failure. |
| 7510 if (mode_ == POSITIVE_LOOKUP) { | 7513 if (mode_ == POSITIVE_LOOKUP) { |
| 7511 __ mov(result, Operand::Zero()); | 7514 __ mov(result, Operand::Zero()); |
| (...skipping 434 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7946 | 7949 |
| 7947 __ Pop(lr, r5, r1); | 7950 __ Pop(lr, r5, r1); |
| 7948 __ Ret(); | 7951 __ Ret(); |
| 7949 } | 7952 } |
| 7950 | 7953 |
| 7951 #undef __ | 7954 #undef __ |
| 7952 | 7955 |
| 7953 } } // namespace v8::internal | 7956 } } // namespace v8::internal |
| 7954 | 7957 |
| 7955 #endif // V8_TARGET_ARCH_ARM | 7958 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |