| 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 1590 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1601 __ bind(&first_non_object); | 1601 __ bind(&first_non_object); |
| 1602 // Check for oddballs: true, false, null, undefined. | 1602 // Check for oddballs: true, false, null, undefined. |
| 1603 __ Branch(&return_not_equal, eq, a2, Operand(ODDBALL_TYPE)); | 1603 __ Branch(&return_not_equal, eq, a2, Operand(ODDBALL_TYPE)); |
| 1604 | 1604 |
| 1605 __ GetObjectType(rhs, a3, a3); | 1605 __ GetObjectType(rhs, a3, a3); |
| 1606 __ Branch(&return_not_equal, greater, a3, Operand(FIRST_SPEC_OBJECT_TYPE)); | 1606 __ Branch(&return_not_equal, greater, a3, Operand(FIRST_SPEC_OBJECT_TYPE)); |
| 1607 | 1607 |
| 1608 // Check for oddballs: true, false, null, undefined. | 1608 // Check for oddballs: true, false, null, undefined. |
| 1609 __ Branch(&return_not_equal, eq, a3, Operand(ODDBALL_TYPE)); | 1609 __ Branch(&return_not_equal, eq, a3, Operand(ODDBALL_TYPE)); |
| 1610 | 1610 |
| 1611 // Now that we have the types we might as well check for symbol-symbol. | 1611 // Now that we have the types we might as well check for |
| 1612 // Ensure that no non-strings have the symbol bit set. | 1612 // internalized-internalized. |
| 1613 STATIC_ASSERT(LAST_TYPE < kNotStringTag + kIsSymbolMask); | 1613 // Ensure that no non-strings have the internalized bit set. |
| 1614 STATIC_ASSERT(kSymbolTag != 0); | 1614 STATIC_ASSERT(LAST_TYPE < kNotStringTag + kIsInternalizedMask); |
| 1615 STATIC_ASSERT(kInternalizedTag != 0); |
| 1615 __ And(t2, a2, Operand(a3)); | 1616 __ And(t2, a2, Operand(a3)); |
| 1616 __ And(t0, t2, Operand(kIsSymbolMask)); | 1617 __ And(t0, t2, Operand(kIsInternalizedMask)); |
| 1617 __ Branch(&return_not_equal, ne, t0, Operand(zero_reg)); | 1618 __ Branch(&return_not_equal, ne, t0, Operand(zero_reg)); |
| 1618 } | 1619 } |
| 1619 | 1620 |
| 1620 | 1621 |
| 1621 static void EmitCheckForTwoHeapNumbers(MacroAssembler* masm, | 1622 static void EmitCheckForTwoHeapNumbers(MacroAssembler* masm, |
| 1622 Register lhs, | 1623 Register lhs, |
| 1623 Register rhs, | 1624 Register rhs, |
| 1624 Label* both_loaded_as_doubles, | 1625 Label* both_loaded_as_doubles, |
| 1625 Label* not_heap_numbers, | 1626 Label* not_heap_numbers, |
| 1626 Label* slow) { | 1627 Label* slow) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1644 __ lw(a0, FieldMemOperand(rhs, HeapNumber::kValueOffset)); | 1645 __ lw(a0, FieldMemOperand(rhs, HeapNumber::kValueOffset)); |
| 1645 } else { | 1646 } else { |
| 1646 __ lw(a0, FieldMemOperand(rhs, HeapNumber::kValueOffset)); | 1647 __ lw(a0, FieldMemOperand(rhs, HeapNumber::kValueOffset)); |
| 1647 __ lw(a1, FieldMemOperand(rhs, HeapNumber::kValueOffset + 4)); | 1648 __ lw(a1, FieldMemOperand(rhs, HeapNumber::kValueOffset + 4)); |
| 1648 } | 1649 } |
| 1649 } | 1650 } |
| 1650 __ jmp(both_loaded_as_doubles); | 1651 __ jmp(both_loaded_as_doubles); |
| 1651 } | 1652 } |
| 1652 | 1653 |
| 1653 | 1654 |
| 1654 // Fast negative check for symbol-to-symbol equality. | 1655 // Fast negative check for internalized-to-internalized equality. |
| 1655 static void EmitCheckForSymbolsOrObjects(MacroAssembler* masm, | 1656 static void EmitCheckForInternalizedStringsOrObjects(MacroAssembler* masm, |
| 1656 Register lhs, | 1657 Register lhs, |
| 1657 Register rhs, | 1658 Register rhs, |
| 1658 Label* possible_strings, | 1659 Label* possible_strings, |
| 1659 Label* not_both_strings) { | 1660 Label* not_both_strings) { |
| 1660 ASSERT((lhs.is(a0) && rhs.is(a1)) || | 1661 ASSERT((lhs.is(a0) && rhs.is(a1)) || |
| 1661 (lhs.is(a1) && rhs.is(a0))); | 1662 (lhs.is(a1) && rhs.is(a0))); |
| 1662 | 1663 |
| 1663 // a2 is object type of lhs. | 1664 // a2 is object type of lhs. |
| 1664 // Ensure that no non-strings have the symbol bit set. | 1665 // Ensure that no non-strings have the internalized bit set. |
| 1665 Label object_test; | 1666 Label object_test; |
| 1666 STATIC_ASSERT(kSymbolTag != 0); | 1667 STATIC_ASSERT(kInternalizedTag != 0); |
| 1667 __ And(at, a2, Operand(kIsNotStringMask)); | 1668 __ And(at, a2, Operand(kIsNotStringMask)); |
| 1668 __ Branch(&object_test, ne, at, Operand(zero_reg)); | 1669 __ Branch(&object_test, ne, at, Operand(zero_reg)); |
| 1669 __ And(at, a2, Operand(kIsSymbolMask)); | 1670 __ And(at, a2, Operand(kIsInternalizedMask)); |
| 1670 __ Branch(possible_strings, eq, at, Operand(zero_reg)); | 1671 __ Branch(possible_strings, eq, at, Operand(zero_reg)); |
| 1671 __ GetObjectType(rhs, a3, a3); | 1672 __ GetObjectType(rhs, a3, a3); |
| 1672 __ Branch(not_both_strings, ge, a3, Operand(FIRST_NONSTRING_TYPE)); | 1673 __ Branch(not_both_strings, ge, a3, Operand(FIRST_NONSTRING_TYPE)); |
| 1673 __ And(at, a3, Operand(kIsSymbolMask)); | 1674 __ And(at, a3, Operand(kIsInternalizedMask)); |
| 1674 __ Branch(possible_strings, eq, at, Operand(zero_reg)); | 1675 __ Branch(possible_strings, eq, at, Operand(zero_reg)); |
| 1675 | 1676 |
| 1676 // Both are symbols. We already checked they weren't the same pointer | 1677 // Both are internalized strings. We already checked they weren't the same |
| 1677 // so they are not equal. | 1678 // pointer so they are not equal. |
| 1678 __ Ret(USE_DELAY_SLOT); | 1679 __ Ret(USE_DELAY_SLOT); |
| 1679 __ li(v0, Operand(1)); // Non-zero indicates not equal. | 1680 __ li(v0, Operand(1)); // Non-zero indicates not equal. |
| 1680 | 1681 |
| 1681 __ bind(&object_test); | 1682 __ bind(&object_test); |
| 1682 __ Branch(not_both_strings, lt, a2, Operand(FIRST_SPEC_OBJECT_TYPE)); | 1683 __ Branch(not_both_strings, lt, a2, Operand(FIRST_SPEC_OBJECT_TYPE)); |
| 1683 __ GetObjectType(rhs, a2, a3); | 1684 __ GetObjectType(rhs, a2, a3); |
| 1684 __ Branch(not_both_strings, lt, a3, Operand(FIRST_SPEC_OBJECT_TYPE)); | 1685 __ Branch(not_both_strings, lt, a3, Operand(FIRST_SPEC_OBJECT_TYPE)); |
| 1685 | 1686 |
| 1686 // If both objects are undetectable, they are equal. Otherwise, they | 1687 // If both objects are undetectable, they are equal. Otherwise, they |
| 1687 // are not equal, since they are different objects and an object is not | 1688 // are not equal, since they are different objects and an object is not |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1813 CompareIC::State expected, | 1814 CompareIC::State expected, |
| 1814 Label* fail) { | 1815 Label* fail) { |
| 1815 Label ok; | 1816 Label ok; |
| 1816 if (expected == CompareIC::SMI) { | 1817 if (expected == CompareIC::SMI) { |
| 1817 __ JumpIfNotSmi(input, fail); | 1818 __ JumpIfNotSmi(input, fail); |
| 1818 } else if (expected == CompareIC::HEAP_NUMBER) { | 1819 } else if (expected == CompareIC::HEAP_NUMBER) { |
| 1819 __ JumpIfSmi(input, &ok); | 1820 __ JumpIfSmi(input, &ok); |
| 1820 __ CheckMap(input, scratch, Heap::kHeapNumberMapRootIndex, fail, | 1821 __ CheckMap(input, scratch, Heap::kHeapNumberMapRootIndex, fail, |
| 1821 DONT_DO_SMI_CHECK); | 1822 DONT_DO_SMI_CHECK); |
| 1822 } | 1823 } |
| 1823 // We could be strict about symbol/string here, but as long as | 1824 // We could be strict about internalized/string here, but as long as |
| 1824 // hydrogen doesn't care, the stub doesn't have to care either. | 1825 // hydrogen doesn't care, the stub doesn't have to care either. |
| 1825 __ bind(&ok); | 1826 __ bind(&ok); |
| 1826 } | 1827 } |
| 1827 | 1828 |
| 1828 | 1829 |
| 1829 // On entry a1 and a2 are the values to be compared. | 1830 // On entry a1 and a2 are the values to be compared. |
| 1830 // On exit a0 is 0, positive or negative to indicate the result of | 1831 // On exit a0 is 0, positive or negative to indicate the result of |
| 1831 // the comparison. | 1832 // the comparison. |
| 1832 void ICCompareStub::GenerateGeneric(MacroAssembler* masm) { | 1833 void ICCompareStub::GenerateGeneric(MacroAssembler* masm) { |
| 1833 Register lhs = a1; | 1834 Register lhs = a1; |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1926 | 1927 |
| 1927 __ bind(¬_smis); | 1928 __ bind(¬_smis); |
| 1928 // At this point we know we are dealing with two different objects, | 1929 // At this point we know we are dealing with two different objects, |
| 1929 // and neither of them is a Smi. The objects are in lhs_ and rhs_. | 1930 // and neither of them is a Smi. The objects are in lhs_ and rhs_. |
| 1930 if (strict()) { | 1931 if (strict()) { |
| 1931 // This returns non-equal for some object types, or falls through if it | 1932 // This returns non-equal for some object types, or falls through if it |
| 1932 // was not lucky. | 1933 // was not lucky. |
| 1933 EmitStrictTwoHeapObjectCompare(masm, lhs, rhs); | 1934 EmitStrictTwoHeapObjectCompare(masm, lhs, rhs); |
| 1934 } | 1935 } |
| 1935 | 1936 |
| 1936 Label check_for_symbols; | 1937 Label check_for_internalized_strings; |
| 1937 Label flat_string_check; | 1938 Label flat_string_check; |
| 1938 // Check for heap-number-heap-number comparison. Can jump to slow case, | 1939 // Check for heap-number-heap-number comparison. Can jump to slow case, |
| 1939 // or load both doubles and jump to the code that handles | 1940 // or load both doubles and jump to the code that handles |
| 1940 // that case. If the inputs are not doubles then jumps to check_for_symbols. | 1941 // that case. If the inputs are not doubles then jumps to |
| 1942 // check_for_internalized_strings. |
| 1941 // In this case a2 will contain the type of lhs_. | 1943 // In this case a2 will contain the type of lhs_. |
| 1942 EmitCheckForTwoHeapNumbers(masm, | 1944 EmitCheckForTwoHeapNumbers(masm, |
| 1943 lhs, | 1945 lhs, |
| 1944 rhs, | 1946 rhs, |
| 1945 &both_loaded_as_doubles, | 1947 &both_loaded_as_doubles, |
| 1946 &check_for_symbols, | 1948 &check_for_internalized_strings, |
| 1947 &flat_string_check); | 1949 &flat_string_check); |
| 1948 | 1950 |
| 1949 __ bind(&check_for_symbols); | 1951 __ bind(&check_for_internalized_strings); |
| 1950 if (cc == eq && !strict()) { | 1952 if (cc == eq && !strict()) { |
| 1951 // Returns an answer for two symbols or two detectable objects. | 1953 // Returns an answer for two internalized strings or two |
| 1954 // detectable objects. |
| 1952 // Otherwise jumps to string case or not both strings case. | 1955 // Otherwise jumps to string case or not both strings case. |
| 1953 // Assumes that a2 is the type of lhs_ on entry. | 1956 // Assumes that a2 is the type of lhs_ on entry. |
| 1954 EmitCheckForSymbolsOrObjects(masm, lhs, rhs, &flat_string_check, &slow); | 1957 EmitCheckForInternalizedStringsOrObjects( |
| 1958 masm, lhs, rhs, &flat_string_check, &slow); |
| 1955 } | 1959 } |
| 1956 | 1960 |
| 1957 // Check for both being sequential ASCII strings, and inline if that is the | 1961 // Check for both being sequential ASCII strings, and inline if that is the |
| 1958 // case. | 1962 // case. |
| 1959 __ bind(&flat_string_check); | 1963 __ bind(&flat_string_check); |
| 1960 | 1964 |
| 1961 __ JumpIfNonSmisNotBothSequentialAsciiStrings(lhs, rhs, a2, a3, &slow); | 1965 __ JumpIfNonSmisNotBothSequentialAsciiStrings(lhs, rhs, a2, a3, &slow); |
| 1962 | 1966 |
| 1963 __ IncrementCounter(isolate->counters()->string_compare_native(), 1, a2, a3); | 1967 __ IncrementCounter(isolate->counters()->string_compare_native(), 1, a2, a3); |
| 1964 if (cc == eq) { | 1968 if (cc == eq) { |
| (...skipping 2595 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4560 void ArrayLengthStub::Generate(MacroAssembler* masm) { | 4564 void ArrayLengthStub::Generate(MacroAssembler* masm) { |
| 4561 Label miss; | 4565 Label miss; |
| 4562 Register receiver; | 4566 Register receiver; |
| 4563 if (kind() == Code::KEYED_LOAD_IC) { | 4567 if (kind() == Code::KEYED_LOAD_IC) { |
| 4564 // ----------- S t a t e ------------- | 4568 // ----------- S t a t e ------------- |
| 4565 // -- ra : return address | 4569 // -- ra : return address |
| 4566 // -- a0 : key | 4570 // -- a0 : key |
| 4567 // -- a1 : receiver | 4571 // -- a1 : receiver |
| 4568 // ----------------------------------- | 4572 // ----------------------------------- |
| 4569 __ Branch(&miss, ne, a0, | 4573 __ Branch(&miss, ne, a0, |
| 4570 Operand(masm->isolate()->factory()->length_symbol())); | 4574 Operand(masm->isolate()->factory()->length_string())); |
| 4571 receiver = a1; | 4575 receiver = a1; |
| 4572 } else { | 4576 } else { |
| 4573 ASSERT(kind() == Code::LOAD_IC); | 4577 ASSERT(kind() == Code::LOAD_IC); |
| 4574 // ----------- S t a t e ------------- | 4578 // ----------- S t a t e ------------- |
| 4575 // -- a2 : name | 4579 // -- a2 : name |
| 4576 // -- ra : return address | 4580 // -- ra : return address |
| 4577 // -- a0 : receiver | 4581 // -- a0 : receiver |
| 4578 // -- sp[0] : receiver | 4582 // -- sp[0] : receiver |
| 4579 // ----------------------------------- | 4583 // ----------------------------------- |
| 4580 receiver = a0; | 4584 receiver = a0; |
| 4581 } | 4585 } |
| 4582 | 4586 |
| 4583 StubCompiler::GenerateLoadArrayLength(masm, receiver, a3, &miss); | 4587 StubCompiler::GenerateLoadArrayLength(masm, receiver, a3, &miss); |
| 4584 __ bind(&miss); | 4588 __ bind(&miss); |
| 4585 StubCompiler::GenerateLoadMiss(masm, kind()); | 4589 StubCompiler::GenerateLoadMiss(masm, kind()); |
| 4586 } | 4590 } |
| 4587 | 4591 |
| 4588 | 4592 |
| 4589 void FunctionPrototypeStub::Generate(MacroAssembler* masm) { | 4593 void FunctionPrototypeStub::Generate(MacroAssembler* masm) { |
| 4590 Label miss; | 4594 Label miss; |
| 4591 Register receiver; | 4595 Register receiver; |
| 4592 if (kind() == Code::KEYED_LOAD_IC) { | 4596 if (kind() == Code::KEYED_LOAD_IC) { |
| 4593 // ----------- S t a t e ------------- | 4597 // ----------- S t a t e ------------- |
| 4594 // -- ra : return address | 4598 // -- ra : return address |
| 4595 // -- a0 : key | 4599 // -- a0 : key |
| 4596 // -- a1 : receiver | 4600 // -- a1 : receiver |
| 4597 // ----------------------------------- | 4601 // ----------------------------------- |
| 4598 __ Branch(&miss, ne, a0, | 4602 __ Branch(&miss, ne, a0, |
| 4599 Operand(masm->isolate()->factory()->prototype_symbol())); | 4603 Operand(masm->isolate()->factory()->prototype_string())); |
| 4600 receiver = a1; | 4604 receiver = a1; |
| 4601 } else { | 4605 } else { |
| 4602 ASSERT(kind() == Code::LOAD_IC); | 4606 ASSERT(kind() == Code::LOAD_IC); |
| 4603 // ----------- S t a t e ------------- | 4607 // ----------- S t a t e ------------- |
| 4604 // -- a2 : name | 4608 // -- a2 : name |
| 4605 // -- ra : return address | 4609 // -- ra : return address |
| 4606 // -- a0 : receiver | 4610 // -- a0 : receiver |
| 4607 // -- sp[0] : receiver | 4611 // -- sp[0] : receiver |
| 4608 // ----------------------------------- | 4612 // ----------------------------------- |
| 4609 receiver = a0; | 4613 receiver = a0; |
| 4610 } | 4614 } |
| 4611 | 4615 |
| 4612 StubCompiler::GenerateLoadFunctionPrototype(masm, receiver, a3, t0, &miss); | 4616 StubCompiler::GenerateLoadFunctionPrototype(masm, receiver, a3, t0, &miss); |
| 4613 __ bind(&miss); | 4617 __ bind(&miss); |
| 4614 StubCompiler::GenerateLoadMiss(masm, kind()); | 4618 StubCompiler::GenerateLoadMiss(masm, kind()); |
| 4615 } | 4619 } |
| 4616 | 4620 |
| 4617 | 4621 |
| 4618 void StringLengthStub::Generate(MacroAssembler* masm) { | 4622 void StringLengthStub::Generate(MacroAssembler* masm) { |
| 4619 Label miss; | 4623 Label miss; |
| 4620 Register receiver; | 4624 Register receiver; |
| 4621 if (kind() == Code::KEYED_LOAD_IC) { | 4625 if (kind() == Code::KEYED_LOAD_IC) { |
| 4622 // ----------- S t a t e ------------- | 4626 // ----------- S t a t e ------------- |
| 4623 // -- ra : return address | 4627 // -- ra : return address |
| 4624 // -- a0 : key | 4628 // -- a0 : key |
| 4625 // -- a1 : receiver | 4629 // -- a1 : receiver |
| 4626 // ----------------------------------- | 4630 // ----------------------------------- |
| 4627 __ Branch(&miss, ne, a0, | 4631 __ Branch(&miss, ne, a0, |
| 4628 Operand(masm->isolate()->factory()->length_symbol())); | 4632 Operand(masm->isolate()->factory()->length_string())); |
| 4629 receiver = a1; | 4633 receiver = a1; |
| 4630 } else { | 4634 } else { |
| 4631 ASSERT(kind() == Code::LOAD_IC); | 4635 ASSERT(kind() == Code::LOAD_IC); |
| 4632 // ----------- S t a t e ------------- | 4636 // ----------- S t a t e ------------- |
| 4633 // -- a2 : name | 4637 // -- a2 : name |
| 4634 // -- ra : return address | 4638 // -- ra : return address |
| 4635 // -- a0 : receiver | 4639 // -- a0 : receiver |
| 4636 // -- sp[0] : receiver | 4640 // -- sp[0] : receiver |
| 4637 // ----------------------------------- | 4641 // ----------------------------------- |
| 4638 receiver = a0; | 4642 receiver = a0; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 4656 Register receiver; | 4660 Register receiver; |
| 4657 Register value; | 4661 Register value; |
| 4658 if (kind() == Code::KEYED_STORE_IC) { | 4662 if (kind() == Code::KEYED_STORE_IC) { |
| 4659 // ----------- S t a t e ------------- | 4663 // ----------- S t a t e ------------- |
| 4660 // -- ra : return address | 4664 // -- ra : return address |
| 4661 // -- a0 : value | 4665 // -- a0 : value |
| 4662 // -- a1 : key | 4666 // -- a1 : key |
| 4663 // -- a2 : receiver | 4667 // -- a2 : receiver |
| 4664 // ----------------------------------- | 4668 // ----------------------------------- |
| 4665 __ Branch(&miss, ne, a1, | 4669 __ Branch(&miss, ne, a1, |
| 4666 Operand(masm->isolate()->factory()->length_symbol())); | 4670 Operand(masm->isolate()->factory()->length_string())); |
| 4667 receiver = a2; | 4671 receiver = a2; |
| 4668 value = a0; | 4672 value = a0; |
| 4669 } else { | 4673 } else { |
| 4670 ASSERT(kind() == Code::STORE_IC); | 4674 ASSERT(kind() == Code::STORE_IC); |
| 4671 // ----------- S t a t e ------------- | 4675 // ----------- S t a t e ------------- |
| 4672 // -- ra : return address | 4676 // -- ra : return address |
| 4673 // -- a0 : value | 4677 // -- a0 : value |
| 4674 // -- a1 : receiver | 4678 // -- a1 : receiver |
| 4675 // -- a2 : key | 4679 // -- a2 : key |
| 4676 // ----------------------------------- | 4680 // ----------------------------------- |
| (...skipping 617 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5294 | 5298 |
| 5295 // String is sliced. | 5299 // String is sliced. |
| 5296 __ lw(t0, FieldMemOperand(subject, SlicedString::kOffsetOffset)); | 5300 __ lw(t0, FieldMemOperand(subject, SlicedString::kOffsetOffset)); |
| 5297 __ sra(t0, t0, kSmiTagSize); | 5301 __ sra(t0, t0, kSmiTagSize); |
| 5298 __ lw(subject, FieldMemOperand(subject, SlicedString::kParentOffset)); | 5302 __ lw(subject, FieldMemOperand(subject, SlicedString::kParentOffset)); |
| 5299 // t5: offset of sliced string, smi-tagged. | 5303 // t5: offset of sliced string, smi-tagged. |
| 5300 __ jmp(&check_encoding); | 5304 __ jmp(&check_encoding); |
| 5301 // String is a cons string, check whether it is flat. | 5305 // String is a cons string, check whether it is flat. |
| 5302 __ bind(&cons_string); | 5306 __ bind(&cons_string); |
| 5303 __ lw(a0, FieldMemOperand(subject, ConsString::kSecondOffset)); | 5307 __ lw(a0, FieldMemOperand(subject, ConsString::kSecondOffset)); |
| 5304 __ LoadRoot(a1, Heap::kEmptyStringRootIndex); | 5308 __ LoadRoot(a1, Heap::kempty_stringRootIndex); |
| 5305 __ Branch(&runtime, ne, a0, Operand(a1)); | 5309 __ Branch(&runtime, ne, a0, Operand(a1)); |
| 5306 __ lw(subject, FieldMemOperand(subject, ConsString::kFirstOffset)); | 5310 __ lw(subject, FieldMemOperand(subject, ConsString::kFirstOffset)); |
| 5307 // Is first part of cons or parent of slice a flat string? | 5311 // Is first part of cons or parent of slice a flat string? |
| 5308 __ bind(&check_encoding); | 5312 __ bind(&check_encoding); |
| 5309 __ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset)); | 5313 __ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset)); |
| 5310 __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset)); | 5314 __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset)); |
| 5311 STATIC_ASSERT(kSeqStringTag == 0); | 5315 STATIC_ASSERT(kSeqStringTag == 0); |
| 5312 __ And(at, a0, Operand(kStringRepresentationMask)); | 5316 __ And(at, a0, Operand(kStringRepresentationMask)); |
| 5313 __ Branch(&external_string, ne, at, Operand(zero_reg)); | 5317 __ Branch(&external_string, ne, at, Operand(zero_reg)); |
| 5314 | 5318 |
| (...skipping 816 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6131 Register scratch1, | 6135 Register scratch1, |
| 6132 Register scratch2, | 6136 Register scratch2, |
| 6133 Register scratch3, | 6137 Register scratch3, |
| 6134 Register scratch4, | 6138 Register scratch4, |
| 6135 Register scratch5, | 6139 Register scratch5, |
| 6136 Label* not_found) { | 6140 Label* not_found) { |
| 6137 // Register scratch3 is the general scratch register in this function. | 6141 // Register scratch3 is the general scratch register in this function. |
| 6138 Register scratch = scratch3; | 6142 Register scratch = scratch3; |
| 6139 | 6143 |
| 6140 // Make sure that both characters are not digits as such strings has a | 6144 // Make sure that both characters are not digits as such strings has a |
| 6141 // different hash algorithm. Don't try to look for these in the symbol table. | 6145 // different hash algorithm. Don't try to look for these in the string table. |
| 6142 Label not_array_index; | 6146 Label not_array_index; |
| 6143 __ Subu(scratch, c1, Operand(static_cast<int>('0'))); | 6147 __ Subu(scratch, c1, Operand(static_cast<int>('0'))); |
| 6144 __ Branch(¬_array_index, | 6148 __ Branch(¬_array_index, |
| 6145 Ugreater, | 6149 Ugreater, |
| 6146 scratch, | 6150 scratch, |
| 6147 Operand(static_cast<int>('9' - '0'))); | 6151 Operand(static_cast<int>('9' - '0'))); |
| 6148 __ Subu(scratch, c2, Operand(static_cast<int>('0'))); | 6152 __ Subu(scratch, c2, Operand(static_cast<int>('0'))); |
| 6149 | 6153 |
| 6150 // If check failed combine both characters into single halfword. | 6154 // If check failed combine both characters into single halfword. |
| 6151 // This is required by the contract of the method: code at the | 6155 // This is required by the contract of the method: code at the |
| (...skipping 14 matching lines...) Expand all Loading... |
| 6166 StringHelper::GenerateHashGetHash(masm, hash); | 6170 StringHelper::GenerateHashGetHash(masm, hash); |
| 6167 | 6171 |
| 6168 // Collect the two characters in a register. | 6172 // Collect the two characters in a register. |
| 6169 Register chars = c1; | 6173 Register chars = c1; |
| 6170 __ sll(scratch, c2, kBitsPerByte); | 6174 __ sll(scratch, c2, kBitsPerByte); |
| 6171 __ Or(chars, chars, scratch); | 6175 __ Or(chars, chars, scratch); |
| 6172 | 6176 |
| 6173 // chars: two character string, char 1 in byte 0 and char 2 in byte 1. | 6177 // chars: two character string, char 1 in byte 0 and char 2 in byte 1. |
| 6174 // hash: hash of two character string. | 6178 // hash: hash of two character string. |
| 6175 | 6179 |
| 6176 // Load symbol table. | 6180 // Load string table. |
| 6177 // Load address of first element of the symbol table. | 6181 // Load address of first element of the string table. |
| 6178 Register string_table = c2; | 6182 Register string_table = c2; |
| 6179 __ LoadRoot(string_table, Heap::kStringTableRootIndex); | 6183 __ LoadRoot(string_table, Heap::kStringTableRootIndex); |
| 6180 | 6184 |
| 6181 Register undefined = scratch4; | 6185 Register undefined = scratch4; |
| 6182 __ LoadRoot(undefined, Heap::kUndefinedValueRootIndex); | 6186 __ LoadRoot(undefined, Heap::kUndefinedValueRootIndex); |
| 6183 | 6187 |
| 6184 // Calculate capacity mask from the symbol table capacity. | 6188 // Calculate capacity mask from the string table capacity. |
| 6185 Register mask = scratch2; | 6189 Register mask = scratch2; |
| 6186 __ lw(mask, FieldMemOperand(string_table, StringTable::kCapacityOffset)); | 6190 __ lw(mask, FieldMemOperand(string_table, StringTable::kCapacityOffset)); |
| 6187 __ sra(mask, mask, 1); | 6191 __ sra(mask, mask, 1); |
| 6188 __ Addu(mask, mask, -1); | 6192 __ Addu(mask, mask, -1); |
| 6189 | 6193 |
| 6190 // Calculate untagged address of the first element of the symbol table. | 6194 // Calculate untagged address of the first element of the string table. |
| 6191 Register first_string_table_element = string_table; | 6195 Register first_string_table_element = string_table; |
| 6192 __ Addu(first_string_table_element, string_table, | 6196 __ Addu(first_string_table_element, string_table, |
| 6193 Operand(StringTable::kElementsStartOffset - kHeapObjectTag)); | 6197 Operand(StringTable::kElementsStartOffset - kHeapObjectTag)); |
| 6194 | 6198 |
| 6195 // Registers. | 6199 // Registers. |
| 6196 // chars: two character string, char 1 in byte 0 and char 2 in byte 1. | 6200 // chars: two character string, char 1 in byte 0 and char 2 in byte 1. |
| 6197 // hash: hash of two character string | 6201 // hash: hash of two character string |
| 6198 // mask: capacity mask | 6202 // mask: capacity mask |
| 6199 // first_string_table_element: address of the first element of | 6203 // first_string_table_element: address of the first element of |
| 6200 // the symbol table | 6204 // the string table |
| 6201 // undefined: the undefined object | 6205 // undefined: the undefined object |
| 6202 // scratch: - | 6206 // scratch: - |
| 6203 | 6207 |
| 6204 // Perform a number of probes in the symbol table. | 6208 // Perform a number of probes in the string table. |
| 6205 const int kProbes = 4; | 6209 const int kProbes = 4; |
| 6206 Label found_in_string_table; | 6210 Label found_in_string_table; |
| 6207 Label next_probe[kProbes]; | 6211 Label next_probe[kProbes]; |
| 6208 Register candidate = scratch5; // Scratch register contains candidate. | 6212 Register candidate = scratch5; // Scratch register contains candidate. |
| 6209 for (int i = 0; i < kProbes; i++) { | 6213 for (int i = 0; i < kProbes; i++) { |
| 6210 // Calculate entry in symbol table. | 6214 // Calculate entry in string table. |
| 6211 if (i > 0) { | 6215 if (i > 0) { |
| 6212 __ Addu(candidate, hash, Operand(StringTable::GetProbeOffset(i))); | 6216 __ Addu(candidate, hash, Operand(StringTable::GetProbeOffset(i))); |
| 6213 } else { | 6217 } else { |
| 6214 __ mov(candidate, hash); | 6218 __ mov(candidate, hash); |
| 6215 } | 6219 } |
| 6216 | 6220 |
| 6217 __ And(candidate, candidate, Operand(mask)); | 6221 __ And(candidate, candidate, Operand(mask)); |
| 6218 | 6222 |
| 6219 // Load the entry from the symble table. | 6223 // Load the entry from the symble table. |
| 6220 STATIC_ASSERT(StringTable::kEntrySize == 1); | 6224 STATIC_ASSERT(StringTable::kEntrySize == 1); |
| 6221 __ sll(scratch, candidate, kPointerSizeLog2); | 6225 __ sll(scratch, candidate, kPointerSizeLog2); |
| 6222 __ Addu(scratch, scratch, first_string_table_element); | 6226 __ Addu(scratch, scratch, first_string_table_element); |
| 6223 __ lw(candidate, MemOperand(scratch)); | 6227 __ lw(candidate, MemOperand(scratch)); |
| 6224 | 6228 |
| 6225 // If entry is undefined no string with this hash can be found. | 6229 // If entry is undefined no string with this hash can be found. |
| 6226 Label is_string; | 6230 Label is_string; |
| 6227 __ GetObjectType(candidate, scratch, scratch); | 6231 __ GetObjectType(candidate, scratch, scratch); |
| 6228 __ Branch(&is_string, ne, scratch, Operand(ODDBALL_TYPE)); | 6232 __ Branch(&is_string, ne, scratch, Operand(ODDBALL_TYPE)); |
| 6229 | 6233 |
| 6230 __ Branch(not_found, eq, undefined, Operand(candidate)); | 6234 __ Branch(not_found, eq, undefined, Operand(candidate)); |
| 6231 // Must be the hole (deleted entry). | 6235 // Must be the hole (deleted entry). |
| 6232 if (FLAG_debug_code) { | 6236 if (FLAG_debug_code) { |
| 6233 __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); | 6237 __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); |
| 6234 __ Assert(eq, "oddball in symbol table is not undefined or the hole", | 6238 __ Assert(eq, "oddball in string table is not undefined or the hole", |
| 6235 scratch, Operand(candidate)); | 6239 scratch, Operand(candidate)); |
| 6236 } | 6240 } |
| 6237 __ jmp(&next_probe[i]); | 6241 __ jmp(&next_probe[i]); |
| 6238 | 6242 |
| 6239 __ bind(&is_string); | 6243 __ bind(&is_string); |
| 6240 | 6244 |
| 6241 // Check that the candidate is a non-external ASCII string. The instance | 6245 // Check that the candidate is a non-external ASCII string. The instance |
| 6242 // type is still in the scratch register from the CompareObjectType | 6246 // type is still in the scratch register from the CompareObjectType |
| 6243 // operation. | 6247 // operation. |
| 6244 __ JumpIfInstanceTypeIsNotSequentialAscii(scratch, scratch, &next_probe[i]); | 6248 __ JumpIfInstanceTypeIsNotSequentialAscii(scratch, scratch, &next_probe[i]); |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6385 // If the string is not indirect, it can only be sequential or external. | 6389 // If the string is not indirect, it can only be sequential or external. |
| 6386 STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag)); | 6390 STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag)); |
| 6387 STATIC_ASSERT(kIsIndirectStringMask != 0); | 6391 STATIC_ASSERT(kIsIndirectStringMask != 0); |
| 6388 __ And(t0, a1, Operand(kIsIndirectStringMask)); | 6392 __ And(t0, a1, Operand(kIsIndirectStringMask)); |
| 6389 __ Branch(USE_DELAY_SLOT, &seq_or_external_string, eq, t0, Operand(zero_reg)); | 6393 __ Branch(USE_DELAY_SLOT, &seq_or_external_string, eq, t0, Operand(zero_reg)); |
| 6390 // t0 is used as a scratch register and can be overwritten in either case. | 6394 // t0 is used as a scratch register and can be overwritten in either case. |
| 6391 __ And(t0, a1, Operand(kSlicedNotConsMask)); | 6395 __ And(t0, a1, Operand(kSlicedNotConsMask)); |
| 6392 __ Branch(&sliced_string, ne, t0, Operand(zero_reg)); | 6396 __ Branch(&sliced_string, ne, t0, Operand(zero_reg)); |
| 6393 // Cons string. Check whether it is flat, then fetch first part. | 6397 // Cons string. Check whether it is flat, then fetch first part. |
| 6394 __ lw(t1, FieldMemOperand(v0, ConsString::kSecondOffset)); | 6398 __ lw(t1, FieldMemOperand(v0, ConsString::kSecondOffset)); |
| 6395 __ LoadRoot(t0, Heap::kEmptyStringRootIndex); | 6399 __ LoadRoot(t0, Heap::kempty_stringRootIndex); |
| 6396 __ Branch(&runtime, ne, t1, Operand(t0)); | 6400 __ Branch(&runtime, ne, t1, Operand(t0)); |
| 6397 __ lw(t1, FieldMemOperand(v0, ConsString::kFirstOffset)); | 6401 __ lw(t1, FieldMemOperand(v0, ConsString::kFirstOffset)); |
| 6398 // Update instance type. | 6402 // Update instance type. |
| 6399 __ lw(a1, FieldMemOperand(t1, HeapObject::kMapOffset)); | 6403 __ lw(a1, FieldMemOperand(t1, HeapObject::kMapOffset)); |
| 6400 __ lbu(a1, FieldMemOperand(a1, Map::kInstanceTypeOffset)); | 6404 __ lbu(a1, FieldMemOperand(a1, Map::kInstanceTypeOffset)); |
| 6401 __ jmp(&underlying_unpacked); | 6405 __ jmp(&underlying_unpacked); |
| 6402 | 6406 |
| 6403 __ bind(&sliced_string); | 6407 __ bind(&sliced_string); |
| 6404 // Sliced string. Fetch parent and correct start index by offset. | 6408 // Sliced string. Fetch parent and correct start index by offset. |
| 6405 __ lw(t1, FieldMemOperand(v0, SlicedString::kParentOffset)); | 6409 __ lw(t1, FieldMemOperand(v0, SlicedString::kParentOffset)); |
| (...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6768 // a1: second string | 6772 // a1: second string |
| 6769 // a2: length of first string | 6773 // a2: length of first string |
| 6770 // a3: length of second string | 6774 // a3: length of second string |
| 6771 // t0: first string instance type (if flags_ == NO_STRING_ADD_FLAGS) | 6775 // t0: first string instance type (if flags_ == NO_STRING_ADD_FLAGS) |
| 6772 // t1: second string instance type (if flags_ == NO_STRING_ADD_FLAGS) | 6776 // t1: second string instance type (if flags_ == NO_STRING_ADD_FLAGS) |
| 6773 // Look at the length of the result of adding the two strings. | 6777 // Look at the length of the result of adding the two strings. |
| 6774 Label string_add_flat_result, longer_than_two; | 6778 Label string_add_flat_result, longer_than_two; |
| 6775 // Adding two lengths can't overflow. | 6779 // Adding two lengths can't overflow. |
| 6776 STATIC_ASSERT(String::kMaxLength < String::kMaxLength * 2); | 6780 STATIC_ASSERT(String::kMaxLength < String::kMaxLength * 2); |
| 6777 __ Addu(t2, a2, Operand(a3)); | 6781 __ Addu(t2, a2, Operand(a3)); |
| 6778 // Use the symbol table when adding two one character strings, as it | 6782 // Use the string table when adding two one character strings, as it |
| 6779 // helps later optimizations to return a symbol here. | 6783 // helps later optimizations to return a string here. |
| 6780 __ Branch(&longer_than_two, ne, t2, Operand(2)); | 6784 __ Branch(&longer_than_two, ne, t2, Operand(2)); |
| 6781 | 6785 |
| 6782 // Check that both strings are non-external ASCII strings. | 6786 // Check that both strings are non-external ASCII strings. |
| 6783 if (flags_ != NO_STRING_ADD_FLAGS) { | 6787 if (flags_ != NO_STRING_ADD_FLAGS) { |
| 6784 __ lw(t0, FieldMemOperand(a0, HeapObject::kMapOffset)); | 6788 __ lw(t0, FieldMemOperand(a0, HeapObject::kMapOffset)); |
| 6785 __ lw(t1, FieldMemOperand(a1, HeapObject::kMapOffset)); | 6789 __ lw(t1, FieldMemOperand(a1, HeapObject::kMapOffset)); |
| 6786 __ lbu(t0, FieldMemOperand(t0, Map::kInstanceTypeOffset)); | 6790 __ lbu(t0, FieldMemOperand(t0, Map::kInstanceTypeOffset)); |
| 6787 __ lbu(t1, FieldMemOperand(t1, Map::kInstanceTypeOffset)); | 6791 __ lbu(t1, FieldMemOperand(t1, Map::kInstanceTypeOffset)); |
| 6788 } | 6792 } |
| 6789 __ JumpIfBothInstanceTypesAreNotSequentialAscii(t0, t1, t2, t3, | 6793 __ JumpIfBothInstanceTypesAreNotSequentialAscii(t0, t1, t2, t3, |
| 6790 &call_runtime); | 6794 &call_runtime); |
| 6791 | 6795 |
| 6792 // Get the two characters forming the sub string. | 6796 // Get the two characters forming the sub string. |
| 6793 __ lbu(a2, FieldMemOperand(a0, SeqOneByteString::kHeaderSize)); | 6797 __ lbu(a2, FieldMemOperand(a0, SeqOneByteString::kHeaderSize)); |
| 6794 __ lbu(a3, FieldMemOperand(a1, SeqOneByteString::kHeaderSize)); | 6798 __ lbu(a3, FieldMemOperand(a1, SeqOneByteString::kHeaderSize)); |
| 6795 | 6799 |
| 6796 // Try to lookup two character string in symbol table. If it is not found | 6800 // Try to lookup two character string in string table. If it is not found |
| 6797 // just allocate a new one. | 6801 // just allocate a new one. |
| 6798 Label make_two_character_string; | 6802 Label make_two_character_string; |
| 6799 StringHelper::GenerateTwoCharacterStringTableProbe( | 6803 StringHelper::GenerateTwoCharacterStringTableProbe( |
| 6800 masm, a2, a3, t2, t3, t0, t1, t5, &make_two_character_string); | 6804 masm, a2, a3, t2, t3, t0, t1, t5, &make_two_character_string); |
| 6801 __ IncrementCounter(counters->string_add_native(), 1, a2, a3); | 6805 __ IncrementCounter(counters->string_add_native(), 1, a2, a3); |
| 6802 __ DropAndRet(2); | 6806 __ DropAndRet(2); |
| 6803 | 6807 |
| 6804 __ bind(&make_two_character_string); | 6808 __ bind(&make_two_character_string); |
| 6805 // Resulting string has length 2 and first chars of two strings | 6809 // Resulting string has length 2 and first chars of two strings |
| 6806 // are combined into single halfword in a2 register. | 6810 // are combined into single halfword in a2 register. |
| (...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7131 if (Token::IsOrderedRelationalCompareOp(op_)) { | 7135 if (Token::IsOrderedRelationalCompareOp(op_)) { |
| 7132 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); | 7136 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); |
| 7133 __ Branch(&unordered, eq, a1, Operand(at)); | 7137 __ Branch(&unordered, eq, a1, Operand(at)); |
| 7134 } | 7138 } |
| 7135 | 7139 |
| 7136 __ bind(&miss); | 7140 __ bind(&miss); |
| 7137 GenerateMiss(masm); | 7141 GenerateMiss(masm); |
| 7138 } | 7142 } |
| 7139 | 7143 |
| 7140 | 7144 |
| 7141 void ICCompareStub::GenerateSymbols(MacroAssembler* masm) { | 7145 void ICCompareStub::GenerateInternalizedStrings(MacroAssembler* masm) { |
| 7142 ASSERT(state_ == CompareIC::SYMBOL); | 7146 ASSERT(state_ == CompareIC::SYMBOL); |
| 7143 Label miss; | 7147 Label miss; |
| 7144 | 7148 |
| 7145 // Registers containing left and right operands respectively. | 7149 // Registers containing left and right operands respectively. |
| 7146 Register left = a1; | 7150 Register left = a1; |
| 7147 Register right = a0; | 7151 Register right = a0; |
| 7148 Register tmp1 = a2; | 7152 Register tmp1 = a2; |
| 7149 Register tmp2 = a3; | 7153 Register tmp2 = a3; |
| 7150 | 7154 |
| 7151 // Check that both operands are heap objects. | 7155 // Check that both operands are heap objects. |
| 7152 __ JumpIfEitherSmi(left, right, &miss); | 7156 __ JumpIfEitherSmi(left, right, &miss); |
| 7153 | 7157 |
| 7154 // Check that both operands are symbols. | 7158 // Check that both operands are internalized strings. |
| 7155 __ lw(tmp1, FieldMemOperand(left, HeapObject::kMapOffset)); | 7159 __ lw(tmp1, FieldMemOperand(left, HeapObject::kMapOffset)); |
| 7156 __ lw(tmp2, FieldMemOperand(right, HeapObject::kMapOffset)); | 7160 __ lw(tmp2, FieldMemOperand(right, HeapObject::kMapOffset)); |
| 7157 __ lbu(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset)); | 7161 __ lbu(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset)); |
| 7158 __ lbu(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset)); | 7162 __ lbu(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset)); |
| 7159 STATIC_ASSERT(kSymbolTag != 0); | 7163 STATIC_ASSERT(kInternalizedTag != 0); |
| 7160 __ And(tmp1, tmp1, Operand(tmp2)); | 7164 __ And(tmp1, tmp1, Operand(tmp2)); |
| 7161 __ And(tmp1, tmp1, kIsSymbolMask); | 7165 __ And(tmp1, tmp1, kIsInternalizedMask); |
| 7162 __ Branch(&miss, eq, tmp1, Operand(zero_reg)); | 7166 __ Branch(&miss, eq, tmp1, Operand(zero_reg)); |
| 7163 // Make sure a0 is non-zero. At this point input operands are | 7167 // Make sure a0 is non-zero. At this point input operands are |
| 7164 // guaranteed to be non-zero. | 7168 // guaranteed to be non-zero. |
| 7165 ASSERT(right.is(a0)); | 7169 ASSERT(right.is(a0)); |
| 7166 STATIC_ASSERT(EQUAL == 0); | 7170 STATIC_ASSERT(EQUAL == 0); |
| 7167 STATIC_ASSERT(kSmiTag == 0); | 7171 STATIC_ASSERT(kSmiTag == 0); |
| 7168 __ mov(v0, right); | 7172 __ mov(v0, right); |
| 7169 // Symbols are compared by identity. | 7173 // Internalized strings are compared by identity. |
| 7170 __ Ret(ne, left, Operand(right)); | 7174 __ Ret(ne, left, Operand(right)); |
| 7171 __ li(v0, Operand(Smi::FromInt(EQUAL))); | 7175 __ li(v0, Operand(Smi::FromInt(EQUAL))); |
| 7172 __ Ret(); | 7176 __ Ret(); |
| 7173 | 7177 |
| 7174 __ bind(&miss); | 7178 __ bind(&miss); |
| 7175 GenerateMiss(masm); | 7179 GenerateMiss(masm); |
| 7176 } | 7180 } |
| 7177 | 7181 |
| 7178 | 7182 |
| 7179 void ICCompareStub::GenerateStrings(MacroAssembler* masm) { | 7183 void ICCompareStub::GenerateStrings(MacroAssembler* masm) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 7209 Label left_ne_right; | 7213 Label left_ne_right; |
| 7210 STATIC_ASSERT(EQUAL == 0); | 7214 STATIC_ASSERT(EQUAL == 0); |
| 7211 STATIC_ASSERT(kSmiTag == 0); | 7215 STATIC_ASSERT(kSmiTag == 0); |
| 7212 __ Branch(&left_ne_right, ne, left, Operand(right)); | 7216 __ Branch(&left_ne_right, ne, left, Operand(right)); |
| 7213 __ Ret(USE_DELAY_SLOT); | 7217 __ Ret(USE_DELAY_SLOT); |
| 7214 __ mov(v0, zero_reg); // In the delay slot. | 7218 __ mov(v0, zero_reg); // In the delay slot. |
| 7215 __ bind(&left_ne_right); | 7219 __ bind(&left_ne_right); |
| 7216 | 7220 |
| 7217 // Handle not identical strings. | 7221 // Handle not identical strings. |
| 7218 | 7222 |
| 7219 // Check that both strings are symbols. If they are, we're done | 7223 // Check that both strings are internalized strings. If they are, we're done |
| 7220 // because we already know they are not identical. | 7224 // because we already know they are not identical. |
| 7221 if (equality) { | 7225 if (equality) { |
| 7222 ASSERT(GetCondition() == eq); | 7226 ASSERT(GetCondition() == eq); |
| 7223 STATIC_ASSERT(kSymbolTag != 0); | 7227 STATIC_ASSERT(kInternalizedTag != 0); |
| 7224 __ And(tmp3, tmp1, Operand(tmp2)); | 7228 __ And(tmp3, tmp1, Operand(tmp2)); |
| 7225 __ And(tmp5, tmp3, Operand(kIsSymbolMask)); | 7229 __ And(tmp5, tmp3, Operand(kIsInternalizedMask)); |
| 7226 Label is_symbol; | 7230 Label is_symbol; |
| 7227 __ Branch(&is_symbol, eq, tmp5, Operand(zero_reg)); | 7231 __ Branch(&is_symbol, eq, tmp5, Operand(zero_reg)); |
| 7228 // Make sure a0 is non-zero. At this point input operands are | 7232 // Make sure a0 is non-zero. At this point input operands are |
| 7229 // guaranteed to be non-zero. | 7233 // guaranteed to be non-zero. |
| 7230 ASSERT(right.is(a0)); | 7234 ASSERT(right.is(a0)); |
| 7231 __ Ret(USE_DELAY_SLOT); | 7235 __ Ret(USE_DELAY_SLOT); |
| 7232 __ mov(v0, a0); // In the delay slot. | 7236 __ mov(v0, a0); // In the delay slot. |
| 7233 __ bind(&is_symbol); | 7237 __ bind(&is_symbol); |
| 7234 } | 7238 } |
| 7235 | 7239 |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7418 if (i != kInlinedProbes - 1) { | 7422 if (i != kInlinedProbes - 1) { |
| 7419 // Load the hole ready for use below: | 7423 // Load the hole ready for use below: |
| 7420 __ LoadRoot(tmp, Heap::kTheHoleValueRootIndex); | 7424 __ LoadRoot(tmp, Heap::kTheHoleValueRootIndex); |
| 7421 | 7425 |
| 7422 // Stop if found the property. | 7426 // Stop if found the property. |
| 7423 __ Branch(miss, eq, entity_name, Operand(Handle<String>(name))); | 7427 __ Branch(miss, eq, entity_name, Operand(Handle<String>(name))); |
| 7424 | 7428 |
| 7425 Label the_hole; | 7429 Label the_hole; |
| 7426 __ Branch(&the_hole, eq, entity_name, Operand(tmp)); | 7430 __ Branch(&the_hole, eq, entity_name, Operand(tmp)); |
| 7427 | 7431 |
| 7428 // Check if the entry name is not a symbol. | 7432 // Check if the entry name is not a internalized string. |
| 7429 __ lw(entity_name, FieldMemOperand(entity_name, HeapObject::kMapOffset)); | 7433 __ lw(entity_name, FieldMemOperand(entity_name, HeapObject::kMapOffset)); |
| 7430 __ lbu(entity_name, | 7434 __ lbu(entity_name, |
| 7431 FieldMemOperand(entity_name, Map::kInstanceTypeOffset)); | 7435 FieldMemOperand(entity_name, Map::kInstanceTypeOffset)); |
| 7432 __ And(scratch0, entity_name, Operand(kIsSymbolMask)); | 7436 __ And(scratch0, entity_name, Operand(kIsInternalizedMask)); |
| 7433 __ Branch(miss, eq, scratch0, Operand(zero_reg)); | 7437 __ Branch(miss, eq, scratch0, Operand(zero_reg)); |
| 7434 | 7438 |
| 7435 __ bind(&the_hole); | 7439 __ bind(&the_hole); |
| 7436 | 7440 |
| 7437 // Restore the properties. | 7441 // Restore the properties. |
| 7438 __ lw(properties, | 7442 __ lw(properties, |
| 7439 FieldMemOperand(receiver, JSObject::kPropertiesOffset)); | 7443 FieldMemOperand(receiver, JSObject::kPropertiesOffset)); |
| 7440 } | 7444 } |
| 7441 } | 7445 } |
| 7442 | 7446 |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7598 __ Addu(index, index, dictionary); | 7602 __ Addu(index, index, dictionary); |
| 7599 __ lw(entry_key, FieldMemOperand(index, kElementsStartOffset)); | 7603 __ lw(entry_key, FieldMemOperand(index, kElementsStartOffset)); |
| 7600 | 7604 |
| 7601 // Having undefined at this place means the name is not contained. | 7605 // Having undefined at this place means the name is not contained. |
| 7602 __ Branch(¬_in_dictionary, eq, entry_key, Operand(undefined)); | 7606 __ Branch(¬_in_dictionary, eq, entry_key, Operand(undefined)); |
| 7603 | 7607 |
| 7604 // Stop if found the property. | 7608 // Stop if found the property. |
| 7605 __ Branch(&in_dictionary, eq, entry_key, Operand(key)); | 7609 __ Branch(&in_dictionary, eq, entry_key, Operand(key)); |
| 7606 | 7610 |
| 7607 if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) { | 7611 if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) { |
| 7608 // Check if the entry name is not a symbol. | 7612 // Check if the entry name is not a internalized string. |
| 7609 __ lw(entry_key, FieldMemOperand(entry_key, HeapObject::kMapOffset)); | 7613 __ lw(entry_key, FieldMemOperand(entry_key, HeapObject::kMapOffset)); |
| 7610 __ lbu(entry_key, | 7614 __ lbu(entry_key, |
| 7611 FieldMemOperand(entry_key, Map::kInstanceTypeOffset)); | 7615 FieldMemOperand(entry_key, Map::kInstanceTypeOffset)); |
| 7612 __ And(result, entry_key, Operand(kIsSymbolMask)); | 7616 __ And(result, entry_key, Operand(kIsInternalizedMask)); |
| 7613 __ Branch(&maybe_in_dictionary, eq, result, Operand(zero_reg)); | 7617 __ Branch(&maybe_in_dictionary, eq, result, Operand(zero_reg)); |
| 7614 } | 7618 } |
| 7615 } | 7619 } |
| 7616 | 7620 |
| 7617 __ bind(&maybe_in_dictionary); | 7621 __ bind(&maybe_in_dictionary); |
| 7618 // If we are doing negative lookup then probing failure should be | 7622 // If we are doing negative lookup then probing failure should be |
| 7619 // treated as a lookup success. For positive lookup probing failure | 7623 // treated as a lookup success. For positive lookup probing failure |
| 7620 // should be treated as lookup failure. | 7624 // should be treated as lookup failure. |
| 7621 if (mode_ == POSITIVE_LOOKUP) { | 7625 if (mode_ == POSITIVE_LOOKUP) { |
| 7622 __ Ret(USE_DELAY_SLOT); | 7626 __ Ret(USE_DELAY_SLOT); |
| (...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8061 __ Pop(ra, t1, a1); | 8065 __ Pop(ra, t1, a1); |
| 8062 __ Ret(); | 8066 __ Ret(); |
| 8063 } | 8067 } |
| 8064 | 8068 |
| 8065 | 8069 |
| 8066 #undef __ | 8070 #undef __ |
| 8067 | 8071 |
| 8068 } } // namespace v8::internal | 8072 } } // namespace v8::internal |
| 8069 | 8073 |
| 8070 #endif // V8_TARGET_ARCH_MIPS | 8074 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |