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 |