| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| 11 // with the distribution. | 11 // with the distribution. |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 101 // |done| label if a property with the given name is found leaving the | 101 // |done| label if a property with the given name is found leaving the |
| 102 // index into the dictionary in |r1|. Jump to the |miss| label | 102 // index into the dictionary in |r1|. Jump to the |miss| label |
| 103 // otherwise. | 103 // otherwise. |
| 104 static void GenerateStringDictionaryProbes(MacroAssembler* masm, | 104 static void GenerateStringDictionaryProbes(MacroAssembler* masm, |
| 105 Label* miss, | 105 Label* miss, |
| 106 Label* done, | 106 Label* done, |
| 107 Register elements, | 107 Register elements, |
| 108 Register name, | 108 Register name, |
| 109 Register r0, | 109 Register r0, |
| 110 Register r1) { | 110 Register r1) { |
| 111 // Assert that name contains a string. |
| 112 if (FLAG_debug_code) __ AbortIfNotString(name); |
| 113 |
| 111 // Compute the capacity mask. | 114 // Compute the capacity mask. |
| 112 const int kCapacityOffset = | 115 const int kCapacityOffset = |
| 113 StringDictionary::kHeaderSize + | 116 StringDictionary::kHeaderSize + |
| 114 StringDictionary::kCapacityIndex * kPointerSize; | 117 StringDictionary::kCapacityIndex * kPointerSize; |
| 115 __ SmiToInteger32(r0, FieldOperand(elements, kCapacityOffset)); | 118 __ SmiToInteger32(r0, FieldOperand(elements, kCapacityOffset)); |
| 116 __ decl(r0); | 119 __ decl(r0); |
| 117 | 120 |
| 118 // Generate an unrolled loop that performs a few probes before | 121 // Generate an unrolled loop that performs a few probes before |
| 119 // giving up. Measurements done on Gmail indicate that 2 probes | 122 // giving up. Measurements done on Gmail indicate that 2 probes |
| 120 // cover ~93% of loads from dictionaries. | 123 // cover ~93% of loads from dictionaries. |
| (...skipping 635 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 756 | 759 |
| 757 // Perform tail call to the entry. | 760 // Perform tail call to the entry. |
| 758 __ TailCallExternalReference(ExternalReference( | 761 __ TailCallExternalReference(ExternalReference( |
| 759 IC_Utility(kKeyedLoadPropertyWithInterceptor)), 2, 1); | 762 IC_Utility(kKeyedLoadPropertyWithInterceptor)), 2, 1); |
| 760 | 763 |
| 761 __ bind(&slow); | 764 __ bind(&slow); |
| 762 GenerateMiss(masm); | 765 GenerateMiss(masm); |
| 763 } | 766 } |
| 764 | 767 |
| 765 | 768 |
| 766 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { | 769 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, |
| 770 StrictModeFlag strict_mode) { |
| 767 // ----------- S t a t e ------------- | 771 // ----------- S t a t e ------------- |
| 768 // -- rax : value | 772 // -- rax : value |
| 769 // -- rcx : key | 773 // -- rcx : key |
| 770 // -- rdx : receiver | 774 // -- rdx : receiver |
| 771 // -- rsp[0] : return address | 775 // -- rsp[0] : return address |
| 772 // ----------------------------------- | 776 // ----------------------------------- |
| 773 Label slow, slow_with_tagged_index, fast, array, extra, check_pixel_array; | 777 Label slow, slow_with_tagged_index, fast, array, extra, check_pixel_array; |
| 774 | 778 |
| 775 // Check that the object isn't a smi. | 779 // Check that the object isn't a smi. |
| 776 __ JumpIfSmi(rdx, &slow_with_tagged_index); | 780 __ JumpIfSmi(rdx, &slow_with_tagged_index); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 803 __ SmiCompareInteger32(FieldOperand(rbx, FixedArray::kLengthOffset), rcx); | 807 __ SmiCompareInteger32(FieldOperand(rbx, FixedArray::kLengthOffset), rcx); |
| 804 // rax: value | 808 // rax: value |
| 805 // rbx: FixedArray | 809 // rbx: FixedArray |
| 806 // rcx: index | 810 // rcx: index |
| 807 __ j(above, &fast); | 811 __ j(above, &fast); |
| 808 | 812 |
| 809 // Slow case: call runtime. | 813 // Slow case: call runtime. |
| 810 __ bind(&slow); | 814 __ bind(&slow); |
| 811 __ Integer32ToSmi(rcx, rcx); | 815 __ Integer32ToSmi(rcx, rcx); |
| 812 __ bind(&slow_with_tagged_index); | 816 __ bind(&slow_with_tagged_index); |
| 813 GenerateRuntimeSetProperty(masm); | 817 GenerateRuntimeSetProperty(masm, strict_mode); |
| 814 // Never returns to here. | 818 // Never returns to here. |
| 815 | 819 |
| 816 // Check whether the elements is a pixel array. | 820 // Check whether the elements is a pixel array. |
| 817 // rax: value | 821 // rax: value |
| 818 // rdx: receiver | 822 // rdx: receiver |
| 819 // rbx: receiver's elements array | 823 // rbx: receiver's elements array |
| 820 // rcx: index, zero-extended. | 824 // rcx: index, zero-extended. |
| 821 __ bind(&check_pixel_array); | 825 __ bind(&check_pixel_array); |
| 822 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), | 826 GenerateFastPixelArrayStore(masm, |
| 823 Heap::kPixelArrayMapRootIndex); | 827 rdx, |
| 824 __ j(not_equal, &slow); | 828 rcx, |
| 825 // Check that the value is a smi. If a conversion is needed call into the | 829 rax, |
| 826 // runtime to convert and clamp. | 830 rbx, |
| 827 __ JumpIfNotSmi(rax, &slow); | 831 rdi, |
| 828 __ cmpl(rcx, FieldOperand(rbx, PixelArray::kLengthOffset)); | 832 false, |
| 829 __ j(above_equal, &slow); | 833 true, |
| 830 // No more bailouts to slow case on this path, so key not needed. | 834 NULL, |
| 831 __ SmiToInteger32(rdi, rax); | 835 &slow, |
| 832 { // Clamp the value to [0..255]. | 836 &slow, |
| 833 NearLabel done; | 837 &slow); |
| 834 __ testl(rdi, Immediate(0xFFFFFF00)); | |
| 835 __ j(zero, &done); | |
| 836 __ setcc(negative, rdi); // 1 if negative, 0 if positive. | |
| 837 __ decb(rdi); // 0 if negative, 255 if positive. | |
| 838 __ bind(&done); | |
| 839 } | |
| 840 __ movq(rbx, FieldOperand(rbx, PixelArray::kExternalPointerOffset)); | |
| 841 __ movb(Operand(rbx, rcx, times_1, 0), rdi); | |
| 842 __ ret(0); | |
| 843 | 838 |
| 844 // Extra capacity case: Check if there is extra capacity to | 839 // Extra capacity case: Check if there is extra capacity to |
| 845 // perform the store and update the length. Used for adding one | 840 // perform the store and update the length. Used for adding one |
| 846 // element to the array by writing to array[array.length]. | 841 // element to the array by writing to array[array.length]. |
| 847 __ bind(&extra); | 842 __ bind(&extra); |
| 848 // rax: value | 843 // rax: value |
| 849 // rdx: receiver (a JSArray) | 844 // rdx: receiver (a JSArray) |
| 850 // rbx: receiver's elements array (a FixedArray) | 845 // rbx: receiver's elements array (a FixedArray) |
| 851 // rcx: index | 846 // rcx: index |
| 852 // flags: smicompare (rdx.length(), rbx) | 847 // flags: smicompare (rdx.length(), rbx) |
| (...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1228 // ----------- S t a t e ------------- | 1223 // ----------- S t a t e ------------- |
| 1229 // rcx : function name | 1224 // rcx : function name |
| 1230 // rsp[0] : return address | 1225 // rsp[0] : return address |
| 1231 // rsp[8] : argument argc | 1226 // rsp[8] : argument argc |
| 1232 // rsp[16] : argument argc - 1 | 1227 // rsp[16] : argument argc - 1 |
| 1233 // ... | 1228 // ... |
| 1234 // rsp[argc * 8] : argument 1 | 1229 // rsp[argc * 8] : argument 1 |
| 1235 // rsp[(argc + 1) * 8] : argument 0 = receiver | 1230 // rsp[(argc + 1) * 8] : argument 0 = receiver |
| 1236 // ----------------------------------- | 1231 // ----------------------------------- |
| 1237 | 1232 |
| 1233 // Check if the name is a string. |
| 1234 Label miss; |
| 1235 __ JumpIfSmi(rcx, &miss); |
| 1236 Condition cond = masm->IsObjectStringType(rcx, rax, rax); |
| 1237 __ j(NegateCondition(cond), &miss); |
| 1238 GenerateCallNormal(masm, argc); | 1238 GenerateCallNormal(masm, argc); |
| 1239 __ bind(&miss); |
| 1239 GenerateMiss(masm, argc); | 1240 GenerateMiss(masm, argc); |
| 1240 } | 1241 } |
| 1241 | 1242 |
| 1242 | 1243 |
| 1243 void KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) { | 1244 void KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) { |
| 1244 // ----------- S t a t e ------------- | 1245 // ----------- S t a t e ------------- |
| 1245 // rcx : function name | 1246 // rcx : function name |
| 1246 // rsp[0] : return address | 1247 // rsp[0] : return address |
| 1247 // rsp[8] : argument argc | 1248 // rsp[8] : argument argc |
| 1248 // rsp[16] : argument argc - 1 | 1249 // rsp[16] : argument argc - 1 |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1469 __ pop(rbx); | 1470 __ pop(rbx); |
| 1470 __ push(rdx); // receiver | 1471 __ push(rdx); // receiver |
| 1471 __ push(rax); // name | 1472 __ push(rax); // name |
| 1472 __ push(rbx); // return address | 1473 __ push(rbx); // return address |
| 1473 | 1474 |
| 1474 // Perform tail call to the entry. | 1475 // Perform tail call to the entry. |
| 1475 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); | 1476 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); |
| 1476 } | 1477 } |
| 1477 | 1478 |
| 1478 | 1479 |
| 1479 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { | 1480 void StoreIC::GenerateMegamorphic(MacroAssembler* masm, |
| 1481 StrictModeFlag strict_mode) { |
| 1480 // ----------- S t a t e ------------- | 1482 // ----------- S t a t e ------------- |
| 1481 // -- rax : value | 1483 // -- rax : value |
| 1482 // -- rcx : name | 1484 // -- rcx : name |
| 1483 // -- rdx : receiver | 1485 // -- rdx : receiver |
| 1484 // -- rsp[0] : return address | 1486 // -- rsp[0] : return address |
| 1485 // ----------------------------------- | 1487 // ----------------------------------- |
| 1486 | 1488 |
| 1487 // Get the receiver from the stack and probe the stub cache. | 1489 // Get the receiver from the stack and probe the stub cache. |
| 1488 Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, | 1490 Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, |
| 1489 NOT_IN_LOOP, | 1491 NOT_IN_LOOP, |
| 1490 MONOMORPHIC); | 1492 MONOMORPHIC, |
| 1493 strict_mode); |
| 1491 Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, rdx, rcx, rbx, | 1494 Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, rdx, rcx, rbx, |
| 1492 no_reg); | 1495 no_reg); |
| 1493 | 1496 |
| 1494 // Cache miss: Jump to runtime. | 1497 // Cache miss: Jump to runtime. |
| 1495 GenerateMiss(masm); | 1498 GenerateMiss(masm); |
| 1496 } | 1499 } |
| 1497 | 1500 |
| 1498 | 1501 |
| 1499 void StoreIC::GenerateMiss(MacroAssembler* masm) { | 1502 void StoreIC::GenerateMiss(MacroAssembler* masm) { |
| 1500 // ----------- S t a t e ------------- | 1503 // ----------- S t a t e ------------- |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1588 GenerateDictionaryStore(masm, &miss, rbx, rcx, rax, r8, r9); | 1591 GenerateDictionaryStore(masm, &miss, rbx, rcx, rax, r8, r9); |
| 1589 __ IncrementCounter(COUNTERS->store_normal_hit(), 1); | 1592 __ IncrementCounter(COUNTERS->store_normal_hit(), 1); |
| 1590 __ ret(0); | 1593 __ ret(0); |
| 1591 | 1594 |
| 1592 __ bind(&miss); | 1595 __ bind(&miss); |
| 1593 __ IncrementCounter(COUNTERS->store_normal_miss(), 1); | 1596 __ IncrementCounter(COUNTERS->store_normal_miss(), 1); |
| 1594 GenerateMiss(masm); | 1597 GenerateMiss(masm); |
| 1595 } | 1598 } |
| 1596 | 1599 |
| 1597 | 1600 |
| 1598 void StoreIC::GenerateGlobalProxy(MacroAssembler* masm) { | 1601 void StoreIC::GenerateGlobalProxy(MacroAssembler* masm, |
| 1602 StrictModeFlag strict_mode) { |
| 1599 // ----------- S t a t e ------------- | 1603 // ----------- S t a t e ------------- |
| 1600 // -- rax : value | 1604 // -- rax : value |
| 1601 // -- rcx : name | 1605 // -- rcx : name |
| 1602 // -- rdx : receiver | 1606 // -- rdx : receiver |
| 1603 // -- rsp[0] : return address | 1607 // -- rsp[0] : return address |
| 1604 // ----------------------------------- | 1608 // ----------------------------------- |
| 1605 __ pop(rbx); | 1609 __ pop(rbx); |
| 1606 __ push(rdx); | 1610 __ push(rdx); |
| 1607 __ push(rcx); | 1611 __ push(rcx); |
| 1608 __ push(rax); | 1612 __ push(rax); |
| 1609 __ push(rbx); | 1613 __ Push(Smi::FromInt(NONE)); // PropertyAttributes |
| 1614 __ Push(Smi::FromInt(strict_mode)); |
| 1615 __ push(rbx); // return address |
| 1610 | 1616 |
| 1611 // Do tail-call to runtime routine. | 1617 // Do tail-call to runtime routine. |
| 1612 __ TailCallRuntime(Runtime::kSetProperty, 3, 1); | 1618 __ TailCallRuntime(Runtime::kSetProperty, 5, 1); |
| 1613 } | 1619 } |
| 1614 | 1620 |
| 1615 | 1621 |
| 1616 void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm) { | 1622 void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm, |
| 1623 StrictModeFlag strict_mode) { |
| 1617 // ----------- S t a t e ------------- | 1624 // ----------- S t a t e ------------- |
| 1618 // -- rax : value | 1625 // -- rax : value |
| 1619 // -- rcx : key | 1626 // -- rcx : key |
| 1620 // -- rdx : receiver | 1627 // -- rdx : receiver |
| 1621 // -- rsp[0] : return address | 1628 // -- rsp[0] : return address |
| 1622 // ----------------------------------- | 1629 // ----------------------------------- |
| 1623 | 1630 |
| 1624 __ pop(rbx); | 1631 __ pop(rbx); |
| 1625 __ push(rdx); // receiver | 1632 __ push(rdx); // receiver |
| 1626 __ push(rcx); // key | 1633 __ push(rcx); // key |
| 1627 __ push(rax); // value | 1634 __ push(rax); // value |
| 1635 __ Push(Smi::FromInt(NONE)); // PropertyAttributes |
| 1636 __ Push(Smi::FromInt(strict_mode)); // Strict mode. |
| 1628 __ push(rbx); // return address | 1637 __ push(rbx); // return address |
| 1629 | 1638 |
| 1630 // Do tail-call to runtime routine. | 1639 // Do tail-call to runtime routine. |
| 1631 __ TailCallRuntime(Runtime::kSetProperty, 3, 1); | 1640 __ TailCallRuntime(Runtime::kSetProperty, 5, 1); |
| 1632 } | 1641 } |
| 1633 | 1642 |
| 1634 | 1643 |
| 1635 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { | 1644 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { |
| 1636 // ----------- S t a t e ------------- | 1645 // ----------- S t a t e ------------- |
| 1637 // -- rax : value | 1646 // -- rax : value |
| 1638 // -- rcx : key | 1647 // -- rcx : key |
| 1639 // -- rdx : receiver | 1648 // -- rdx : receiver |
| 1640 // -- rsp[0] : return address | 1649 // -- rsp[0] : return address |
| 1641 // ----------------------------------- | 1650 // ----------------------------------- |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1704 set_target(*rewritten); | 1713 set_target(*rewritten); |
| 1705 | 1714 |
| 1706 #ifdef DEBUG | 1715 #ifdef DEBUG |
| 1707 if (FLAG_trace_ic) { | 1716 if (FLAG_trace_ic) { |
| 1708 PrintF("[CompareIC (%s->%s)#%s]\n", | 1717 PrintF("[CompareIC (%s->%s)#%s]\n", |
| 1709 GetStateName(previous_state), | 1718 GetStateName(previous_state), |
| 1710 GetStateName(state), | 1719 GetStateName(state), |
| 1711 Token::Name(op_)); | 1720 Token::Name(op_)); |
| 1712 } | 1721 } |
| 1713 #endif | 1722 #endif |
| 1723 |
| 1724 // Activate inlined smi code. |
| 1725 if (previous_state == UNINITIALIZED) { |
| 1726 PatchInlinedSmiCode(address()); |
| 1727 } |
| 1714 } | 1728 } |
| 1715 | 1729 |
| 1716 void PatchInlinedSmiCode(Address address) { | 1730 void PatchInlinedSmiCode(Address address) { |
| 1717 // Disabled, then patched inline smi code is not implemented on X64. | 1731 // The address of the instruction following the call. |
| 1718 // So we do nothing in this case. | 1732 Address test_instruction_address = |
| 1733 address + Assembler::kCallTargetAddressOffset; |
| 1734 |
| 1735 // If the instruction following the call is not a test al, nothing |
| 1736 // was inlined. |
| 1737 if (*test_instruction_address != Assembler::kTestAlByte) { |
| 1738 ASSERT(*test_instruction_address == Assembler::kNopByte); |
| 1739 return; |
| 1740 } |
| 1741 |
| 1742 Address delta_address = test_instruction_address + 1; |
| 1743 // The delta to the start of the map check instruction and the |
| 1744 // condition code uses at the patched jump. |
| 1745 int8_t delta = *reinterpret_cast<int8_t*>(delta_address); |
| 1746 if (FLAG_trace_ic) { |
| 1747 PrintF("[ patching ic at %p, test=%p, delta=%d\n", |
| 1748 address, test_instruction_address, delta); |
| 1749 } |
| 1750 |
| 1751 // Patch with a short conditional jump. There must be a |
| 1752 // short jump-if-carry/not-carry at this position. |
| 1753 Address jmp_address = test_instruction_address - delta; |
| 1754 ASSERT(*jmp_address == Assembler::kJncShortOpcode || |
| 1755 *jmp_address == Assembler::kJcShortOpcode); |
| 1756 Condition cc = *jmp_address == Assembler::kJncShortOpcode |
| 1757 ? not_zero |
| 1758 : zero; |
| 1759 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); |
| 1719 } | 1760 } |
| 1720 | 1761 |
| 1721 | 1762 |
| 1722 } } // namespace v8::internal | 1763 } } // namespace v8::internal |
| 1723 | 1764 |
| 1724 #endif // V8_TARGET_ARCH_X64 | 1765 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |