| OLD | NEW |
| 1 // Copyright 2011 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 |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 90 (1 << Map::kHasNamedInterceptor))); | 90 (1 << Map::kHasNamedInterceptor))); |
| 91 __ j(not_zero, miss); | 91 __ j(not_zero, miss); |
| 92 | 92 |
| 93 __ movq(r0, FieldOperand(receiver, JSObject::kPropertiesOffset)); | 93 __ movq(r0, FieldOperand(receiver, JSObject::kPropertiesOffset)); |
| 94 __ CompareRoot(FieldOperand(r0, HeapObject::kMapOffset), | 94 __ CompareRoot(FieldOperand(r0, HeapObject::kMapOffset), |
| 95 Heap::kHashTableMapRootIndex); | 95 Heap::kHashTableMapRootIndex); |
| 96 __ j(not_equal, miss); | 96 __ j(not_equal, miss); |
| 97 } | 97 } |
| 98 | 98 |
| 99 | 99 |
| 100 // Probe the string dictionary in the |elements| register. Jump to 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 | |
| 103 // otherwise. | |
| 104 static void GenerateStringDictionaryProbes(MacroAssembler* masm, | |
| 105 Label* miss, | |
| 106 Label* done, | |
| 107 Register elements, | |
| 108 Register name, | |
| 109 Register r0, | |
| 110 Register r1) { | |
| 111 // Assert that name contains a string. | |
| 112 if (FLAG_debug_code) __ AbortIfNotString(name); | |
| 113 | |
| 114 // Compute the capacity mask. | |
| 115 const int kCapacityOffset = | |
| 116 StringDictionary::kHeaderSize + | |
| 117 StringDictionary::kCapacityIndex * kPointerSize; | |
| 118 __ SmiToInteger32(r0, FieldOperand(elements, kCapacityOffset)); | |
| 119 __ decl(r0); | |
| 120 | |
| 121 // Generate an unrolled loop that performs a few probes before | |
| 122 // giving up. Measurements done on Gmail indicate that 2 probes | |
| 123 // cover ~93% of loads from dictionaries. | |
| 124 static const int kProbes = 4; | |
| 125 const int kElementsStartOffset = | |
| 126 StringDictionary::kHeaderSize + | |
| 127 StringDictionary::kElementsStartIndex * kPointerSize; | |
| 128 for (int i = 0; i < kProbes; i++) { | |
| 129 // Compute the masked index: (hash + i + i * i) & mask. | |
| 130 __ movl(r1, FieldOperand(name, String::kHashFieldOffset)); | |
| 131 __ shrl(r1, Immediate(String::kHashShift)); | |
| 132 if (i > 0) { | |
| 133 __ addl(r1, Immediate(StringDictionary::GetProbeOffset(i))); | |
| 134 } | |
| 135 __ and_(r1, r0); | |
| 136 | |
| 137 // Scale the index by multiplying by the entry size. | |
| 138 ASSERT(StringDictionary::kEntrySize == 3); | |
| 139 __ lea(r1, Operand(r1, r1, times_2, 0)); // r1 = r1 * 3 | |
| 140 | |
| 141 // Check if the key is identical to the name. | |
| 142 __ cmpq(name, Operand(elements, r1, times_pointer_size, | |
| 143 kElementsStartOffset - kHeapObjectTag)); | |
| 144 if (i != kProbes - 1) { | |
| 145 __ j(equal, done); | |
| 146 } else { | |
| 147 __ j(not_equal, miss); | |
| 148 } | |
| 149 } | |
| 150 } | |
| 151 | |
| 152 | 100 |
| 153 // Helper function used to load a property from a dictionary backing storage. | 101 // Helper function used to load a property from a dictionary backing storage. |
| 154 // This function may return false negatives, so miss_label | 102 // This function may return false negatives, so miss_label |
| 155 // must always call a backup property load that is complete. | 103 // must always call a backup property load that is complete. |
| 156 // This function is safe to call if name is not a symbol, and will jump to | 104 // This function is safe to call if name is not a symbol, and will jump to |
| 157 // the miss_label in that case. | 105 // the miss_label in that case. |
| 158 // The generated code assumes that the receiver has slow properties, | 106 // The generated code assumes that the receiver has slow properties, |
| 159 // is not a global object and does not have interceptors. | 107 // is not a global object and does not have interceptors. |
| 160 static void GenerateDictionaryLoad(MacroAssembler* masm, | 108 static void GenerateDictionaryLoad(MacroAssembler* masm, |
| 161 Label* miss_label, | 109 Label* miss_label, |
| (...skipping 10 matching lines...) Expand all Loading... |
| 172 // | 120 // |
| 173 // r0 - used to hold the capacity of the property dictionary. | 121 // r0 - used to hold the capacity of the property dictionary. |
| 174 // | 122 // |
| 175 // r1 - used to hold the index into the property dictionary. | 123 // r1 - used to hold the index into the property dictionary. |
| 176 // | 124 // |
| 177 // result - holds the result on exit if the load succeeded. | 125 // result - holds the result on exit if the load succeeded. |
| 178 | 126 |
| 179 Label done; | 127 Label done; |
| 180 | 128 |
| 181 // Probe the dictionary. | 129 // Probe the dictionary. |
| 182 GenerateStringDictionaryProbes(masm, | 130 StringDictionaryLookupStub::GeneratePositiveLookup(masm, |
| 183 miss_label, | 131 miss_label, |
| 184 &done, | 132 &done, |
| 185 elements, | 133 elements, |
| 186 name, | 134 name, |
| 187 r0, | 135 r0, |
| 188 r1); | 136 r1); |
| 189 | 137 |
| 190 // If probing finds an entry in the dictionary, r0 contains the | 138 // If probing finds an entry in the dictionary, r0 contains the |
| 191 // index into the dictionary. Check that the value is a normal | 139 // index into the dictionary. Check that the value is a normal |
| 192 // property. | 140 // property. |
| 193 __ bind(&done); | 141 __ bind(&done); |
| 194 const int kElementsStartOffset = | 142 const int kElementsStartOffset = |
| 195 StringDictionary::kHeaderSize + | 143 StringDictionary::kHeaderSize + |
| 196 StringDictionary::kElementsStartIndex * kPointerSize; | 144 StringDictionary::kElementsStartIndex * kPointerSize; |
| 197 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; | 145 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; |
| 198 __ Test(Operand(elements, r1, times_pointer_size, | 146 __ Test(Operand(elements, r1, times_pointer_size, |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 230 // | 178 // |
| 231 // value - holds the value to store and is unchanged. | 179 // value - holds the value to store and is unchanged. |
| 232 // | 180 // |
| 233 // scratch0 - used for index into the property dictionary and is clobbered. | 181 // scratch0 - used for index into the property dictionary and is clobbered. |
| 234 // | 182 // |
| 235 // scratch1 - used to hold the capacity of the property dictionary and is | 183 // scratch1 - used to hold the capacity of the property dictionary and is |
| 236 // clobbered. | 184 // clobbered. |
| 237 Label done; | 185 Label done; |
| 238 | 186 |
| 239 // Probe the dictionary. | 187 // Probe the dictionary. |
| 240 GenerateStringDictionaryProbes(masm, | 188 StringDictionaryLookupStub::GeneratePositiveLookup(masm, |
| 241 miss_label, | 189 miss_label, |
| 242 &done, | 190 &done, |
| 243 elements, | 191 elements, |
| 244 name, | 192 name, |
| 245 scratch0, | 193 scratch0, |
| 246 scratch1); | 194 scratch1); |
| 247 | 195 |
| 248 // If probing finds an entry in the dictionary, scratch0 contains the | 196 // If probing finds an entry in the dictionary, scratch0 contains the |
| 249 // index into the dictionary. Check that the value is a normal | 197 // index into the dictionary. Check that the value is a normal |
| 250 // property that is not read only. | 198 // property that is not read only. |
| 251 __ bind(&done); | 199 __ bind(&done); |
| 252 const int kElementsStartOffset = | 200 const int kElementsStartOffset = |
| 253 StringDictionary::kHeaderSize + | 201 StringDictionary::kHeaderSize + |
| 254 StringDictionary::kElementsStartIndex * kPointerSize; | 202 StringDictionary::kElementsStartIndex * kPointerSize; |
| 255 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; | 203 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; |
| 256 const int kTypeAndReadOnlyMask | 204 const int kTypeAndReadOnlyMask |
| (...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 703 &miss, // When not a number. | 651 &miss, // When not a number. |
| 704 &miss, // When index out of range. | 652 &miss, // When index out of range. |
| 705 STRING_INDEX_IS_ARRAY_INDEX); | 653 STRING_INDEX_IS_ARRAY_INDEX); |
| 706 char_at_generator.GenerateFast(masm); | 654 char_at_generator.GenerateFast(masm); |
| 707 __ ret(0); | 655 __ ret(0); |
| 708 | 656 |
| 709 StubRuntimeCallHelper call_helper; | 657 StubRuntimeCallHelper call_helper; |
| 710 char_at_generator.GenerateSlow(masm, call_helper); | 658 char_at_generator.GenerateSlow(masm, call_helper); |
| 711 | 659 |
| 712 __ bind(&miss); | 660 __ bind(&miss); |
| 713 GenerateMiss(masm); | 661 GenerateMiss(masm, false); |
| 714 } | 662 } |
| 715 | 663 |
| 716 | 664 |
| 717 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { | 665 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { |
| 718 // ----------- S t a t e ------------- | 666 // ----------- S t a t e ------------- |
| 719 // -- rax : key | 667 // -- rax : key |
| 720 // -- rdx : receiver | 668 // -- rdx : receiver |
| 721 // -- rsp[0] : return address | 669 // -- rsp[0] : return address |
| 722 // ----------------------------------- | 670 // ----------------------------------- |
| 723 Label slow; | 671 Label slow; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 746 __ push(rcx); // return address | 694 __ push(rcx); // return address |
| 747 | 695 |
| 748 // Perform tail call to the entry. | 696 // Perform tail call to the entry. |
| 749 __ TailCallExternalReference( | 697 __ TailCallExternalReference( |
| 750 ExternalReference(IC_Utility(kKeyedLoadPropertyWithInterceptor), | 698 ExternalReference(IC_Utility(kKeyedLoadPropertyWithInterceptor), |
| 751 masm->isolate()), | 699 masm->isolate()), |
| 752 2, | 700 2, |
| 753 1); | 701 1); |
| 754 | 702 |
| 755 __ bind(&slow); | 703 __ bind(&slow); |
| 756 GenerateMiss(masm); | 704 GenerateMiss(masm, false); |
| 757 } | 705 } |
| 758 | 706 |
| 759 | 707 |
| 760 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, | 708 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, |
| 761 StrictModeFlag strict_mode) { | 709 StrictModeFlag strict_mode) { |
| 762 // ----------- S t a t e ------------- | 710 // ----------- S t a t e ------------- |
| 763 // -- rax : value | 711 // -- rax : value |
| 764 // -- rcx : key | 712 // -- rcx : key |
| 765 // -- rdx : receiver | 713 // -- rdx : receiver |
| 766 // -- rsp[0] : return address | 714 // -- rsp[0] : return address |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 840 // Check the key against the length in the array, compute the | 788 // Check the key against the length in the array, compute the |
| 841 // address to store into and fall through to fast case. | 789 // address to store into and fall through to fast case. |
| 842 __ SmiCompareInteger32(FieldOperand(rdx, JSArray::kLengthOffset), rcx); | 790 __ SmiCompareInteger32(FieldOperand(rdx, JSArray::kLengthOffset), rcx); |
| 843 __ j(below_equal, &extra); | 791 __ j(below_equal, &extra); |
| 844 | 792 |
| 845 // Fast case: Do the store. | 793 // Fast case: Do the store. |
| 846 __ bind(&fast); | 794 __ bind(&fast); |
| 847 // rax: value | 795 // rax: value |
| 848 // rbx: receiver's elements array (a FixedArray) | 796 // rbx: receiver's elements array (a FixedArray) |
| 849 // rcx: index | 797 // rcx: index |
| 850 NearLabel non_smi_value; | 798 Label non_smi_value; |
| 851 __ movq(FieldOperand(rbx, rcx, times_pointer_size, FixedArray::kHeaderSize), | 799 __ movq(FieldOperand(rbx, rcx, times_pointer_size, FixedArray::kHeaderSize), |
| 852 rax); | 800 rax); |
| 853 __ JumpIfNotSmi(rax, &non_smi_value); | 801 __ JumpIfNotSmi(rax, &non_smi_value, Label::kNear); |
| 854 __ ret(0); | 802 __ ret(0); |
| 855 __ bind(&non_smi_value); | 803 __ bind(&non_smi_value); |
| 856 // Slow case that needs to retain rcx for use by RecordWrite. | 804 // Slow case that needs to retain rcx for use by RecordWrite. |
| 857 // Update write barrier for the elements array address. | 805 // Update write barrier for the elements array address. |
| 858 __ movq(rdx, rax); | 806 __ movq(rdx, rax); |
| 859 __ RecordWriteNonSmi(rbx, 0, rdx, rcx, kDontSaveFPRegs); | 807 __ RecordWriteNonSmi(rbx, 0, rdx, rcx, kDontSaveFPRegs); |
| 860 __ ret(0); | 808 __ ret(0); |
| 861 } | 809 } |
| 862 | 810 |
| 863 | 811 |
| (...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1285 __ push(rcx); // name | 1233 __ push(rcx); // name |
| 1286 __ push(rbx); // return address | 1234 __ push(rbx); // return address |
| 1287 | 1235 |
| 1288 // Perform tail call to the entry. | 1236 // Perform tail call to the entry. |
| 1289 ExternalReference ref = | 1237 ExternalReference ref = |
| 1290 ExternalReference(IC_Utility(kLoadIC_Miss), masm->isolate()); | 1238 ExternalReference(IC_Utility(kLoadIC_Miss), masm->isolate()); |
| 1291 __ TailCallExternalReference(ref, 2, 1); | 1239 __ TailCallExternalReference(ref, 2, 1); |
| 1292 } | 1240 } |
| 1293 | 1241 |
| 1294 | 1242 |
| 1295 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { | 1243 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm, bool force_generic) { |
| 1296 // ----------- S t a t e ------------- | 1244 // ----------- S t a t e ------------- |
| 1297 // -- rax : key | 1245 // -- rax : key |
| 1298 // -- rdx : receiver | 1246 // -- rdx : receiver |
| 1299 // -- rsp[0] : return address | 1247 // -- rsp[0] : return address |
| 1300 // ----------------------------------- | 1248 // ----------------------------------- |
| 1301 | 1249 |
| 1302 Counters* counters = masm->isolate()->counters(); | 1250 Counters* counters = masm->isolate()->counters(); |
| 1303 __ IncrementCounter(counters->keyed_load_miss(), 1); | 1251 __ IncrementCounter(counters->keyed_load_miss(), 1); |
| 1304 | 1252 |
| 1305 __ pop(rbx); | 1253 __ pop(rbx); |
| 1306 __ push(rdx); // receiver | 1254 __ push(rdx); // receiver |
| 1307 __ push(rax); // name | 1255 __ push(rax); // name |
| 1308 __ push(rbx); // return address | 1256 __ push(rbx); // return address |
| 1309 | 1257 |
| 1310 // Perform tail call to the entry. | 1258 // Perform tail call to the entry. |
| 1311 ExternalReference ref | 1259 ExternalReference ref = force_generic |
| 1312 = ExternalReference(IC_Utility(kKeyedLoadIC_Miss), masm->isolate()); | 1260 ? ExternalReference(IC_Utility(kKeyedLoadIC_MissForceGeneric), |
| 1261 masm->isolate()) |
| 1262 : ExternalReference(IC_Utility(kKeyedLoadIC_Miss), masm->isolate()); |
| 1313 __ TailCallExternalReference(ref, 2, 1); | 1263 __ TailCallExternalReference(ref, 2, 1); |
| 1314 } | 1264 } |
| 1315 | 1265 |
| 1316 | 1266 |
| 1317 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { | 1267 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { |
| 1318 // ----------- S t a t e ------------- | 1268 // ----------- S t a t e ------------- |
| 1319 // -- rax : key | 1269 // -- rax : key |
| 1320 // -- rdx : receiver | 1270 // -- rdx : receiver |
| 1321 // -- rsp[0] : return address | 1271 // -- rsp[0] : return address |
| 1322 // ----------------------------------- | 1272 // ----------------------------------- |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1486 __ push(rax); // value | 1436 __ push(rax); // value |
| 1487 __ Push(Smi::FromInt(NONE)); // PropertyAttributes | 1437 __ Push(Smi::FromInt(NONE)); // PropertyAttributes |
| 1488 __ Push(Smi::FromInt(strict_mode)); // Strict mode. | 1438 __ Push(Smi::FromInt(strict_mode)); // Strict mode. |
| 1489 __ push(rbx); // return address | 1439 __ push(rbx); // return address |
| 1490 | 1440 |
| 1491 // Do tail-call to runtime routine. | 1441 // Do tail-call to runtime routine. |
| 1492 __ TailCallRuntime(Runtime::kSetProperty, 5, 1); | 1442 __ TailCallRuntime(Runtime::kSetProperty, 5, 1); |
| 1493 } | 1443 } |
| 1494 | 1444 |
| 1495 | 1445 |
| 1496 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { | 1446 void KeyedStoreIC::GenerateSlow(MacroAssembler* masm) { |
| 1497 // ----------- S t a t e ------------- | 1447 // ----------- S t a t e ------------- |
| 1498 // -- rax : value | 1448 // -- rax : value |
| 1499 // -- rcx : key | 1449 // -- rcx : key |
| 1500 // -- rdx : receiver | 1450 // -- rdx : receiver |
| 1501 // -- rsp[0] : return address | 1451 // -- rsp[0] : return address |
| 1502 // ----------------------------------- | 1452 // ----------------------------------- |
| 1503 | 1453 |
| 1504 __ pop(rbx); | 1454 __ pop(rbx); |
| 1505 __ push(rdx); // receiver | 1455 __ push(rdx); // receiver |
| 1506 __ push(rcx); // key | 1456 __ push(rcx); // key |
| 1507 __ push(rax); // value | 1457 __ push(rax); // value |
| 1508 __ push(rbx); // return address | 1458 __ push(rbx); // return address |
| 1509 | 1459 |
| 1510 // Do tail-call to runtime routine. | 1460 // Do tail-call to runtime routine. |
| 1511 ExternalReference ref = | 1461 ExternalReference ref(IC_Utility(kKeyedStoreIC_Slow), masm->isolate()); |
| 1512 ExternalReference(IC_Utility(kKeyedStoreIC_Miss), masm->isolate()); | 1462 __ TailCallExternalReference(ref, 3, 1); |
| 1463 } |
| 1464 |
| 1465 |
| 1466 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm, bool force_generic) { |
| 1467 // ----------- S t a t e ------------- |
| 1468 // -- rax : value |
| 1469 // -- rcx : key |
| 1470 // -- rdx : receiver |
| 1471 // -- rsp[0] : return address |
| 1472 // ----------------------------------- |
| 1473 |
| 1474 __ pop(rbx); |
| 1475 __ push(rdx); // receiver |
| 1476 __ push(rcx); // key |
| 1477 __ push(rax); // value |
| 1478 __ push(rbx); // return address |
| 1479 |
| 1480 // Do tail-call to runtime routine. |
| 1481 ExternalReference ref = force_generic |
| 1482 ? ExternalReference(IC_Utility(kKeyedStoreIC_MissForceGeneric), |
| 1483 masm->isolate()) |
| 1484 : ExternalReference(IC_Utility(kKeyedStoreIC_Miss), masm->isolate()); |
| 1513 __ TailCallExternalReference(ref, 3, 1); | 1485 __ TailCallExternalReference(ref, 3, 1); |
| 1514 } | 1486 } |
| 1515 | 1487 |
| 1516 | 1488 |
| 1517 #undef __ | 1489 #undef __ |
| 1518 | 1490 |
| 1519 | 1491 |
| 1520 Condition CompareIC::ComputeCondition(Token::Value op) { | 1492 Condition CompareIC::ComputeCondition(Token::Value op) { |
| 1521 switch (op) { | 1493 switch (op) { |
| 1522 case Token::EQ_STRICT: | 1494 case Token::EQ_STRICT: |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1609 Condition cc = *jmp_address == Assembler::kJncShortOpcode | 1581 Condition cc = *jmp_address == Assembler::kJncShortOpcode |
| 1610 ? not_zero | 1582 ? not_zero |
| 1611 : zero; | 1583 : zero; |
| 1612 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); | 1584 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); |
| 1613 } | 1585 } |
| 1614 | 1586 |
| 1615 | 1587 |
| 1616 } } // namespace v8::internal | 1588 } } // namespace v8::internal |
| 1617 | 1589 |
| 1618 #endif // V8_TARGET_ARCH_X64 | 1590 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |