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/non-internalized here, but as long as |
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 |