Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(486)

Side by Side Diff: src/x64/ic-x64.cc

Issue 2804029: Implement IC for storing to dictionary case objects.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/v8-counters.h ('k') | src/x64/macro-assembler-x64.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 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 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 __ j(equal, global_object); 54 __ j(equal, global_object);
55 __ cmpb(type, Immediate(JS_BUILTINS_OBJECT_TYPE)); 55 __ cmpb(type, Immediate(JS_BUILTINS_OBJECT_TYPE));
56 __ j(equal, global_object); 56 __ j(equal, global_object);
57 __ cmpb(type, Immediate(JS_GLOBAL_PROXY_TYPE)); 57 __ cmpb(type, Immediate(JS_GLOBAL_PROXY_TYPE));
58 __ j(equal, global_object); 58 __ j(equal, global_object);
59 } 59 }
60 60
61 61
62 // Generated code falls through if the receiver is a regular non-global 62 // Generated code falls through if the receiver is a regular non-global
63 // JS object with slow properties and no interceptors. 63 // JS object with slow properties and no interceptors.
64 static void GenerateDictionaryLoadReceiverCheck(MacroAssembler* masm, 64 static void GenerateStringDictionaryReceiverCheck(MacroAssembler* masm,
65 Register receiver, 65 Register receiver,
66 Register r0, 66 Register r0,
67 Register r1, 67 Register r1,
68 Label* miss) { 68 Label* miss) {
69 // Register usage: 69 // Register usage:
70 // receiver: holds the receiver on entry and is unchanged. 70 // receiver: holds the receiver on entry and is unchanged.
71 // r0: used to hold receiver instance type. 71 // r0: used to hold receiver instance type.
72 // Holds the property dictionary on fall through. 72 // Holds the property dictionary on fall through.
73 // r1: used to hold receivers map. 73 // r1: used to hold receivers map.
74 74
75 __ JumpIfSmi(receiver, miss); 75 __ JumpIfSmi(receiver, miss);
76 76
77 // Check that the receiver is a valid JS object. 77 // Check that the receiver is a valid JS object.
78 __ movq(r1, FieldOperand(receiver, HeapObject::kMapOffset)); 78 __ movq(r1, FieldOperand(receiver, HeapObject::kMapOffset));
(...skipping 12 matching lines...) Expand all
91 (1 << Map::kHasNamedInterceptor))); 91 (1 << Map::kHasNamedInterceptor)));
92 __ j(not_zero, miss); 92 __ j(not_zero, miss);
93 93
94 __ movq(r0, FieldOperand(receiver, JSObject::kPropertiesOffset)); 94 __ movq(r0, FieldOperand(receiver, JSObject::kPropertiesOffset));
95 __ CompareRoot(FieldOperand(r0, HeapObject::kMapOffset), 95 __ CompareRoot(FieldOperand(r0, HeapObject::kMapOffset),
96 Heap::kHashTableMapRootIndex); 96 Heap::kHashTableMapRootIndex);
97 __ j(not_equal, miss); 97 __ j(not_equal, miss);
98 } 98 }
99 99
100 100
101 // Helper function used to load a property from a dictionary backing storage. 101 // Probe the string dictionary in the |elements| register. Jump to the
102 // This function may return false negatives, so miss_label 102 // |done| label if a property with the given name is found leaving the
103 // must always call a backup property load that is complete. 103 // index into the dictionary in |r1|. Jump to the |miss| label
104 // This function is safe to call if name is not a symbol, and will jump to 104 // otherwise.
105 // the miss_label in that case. 105 static void GenerateStringDictionaryProbes(MacroAssembler* masm,
106 // The generated code assumes that the receiver has slow properties, 106 Label* miss,
107 // is not a global object and does not have interceptors. 107 Label* done,
108 static void GenerateDictionaryLoad(MacroAssembler* masm, 108 Register elements,
109 Label* miss_label, 109 Register name,
110 Register elements, 110 Register r0,
111 Register name, 111 Register r1) {
112 Register r0,
113 Register r1,
114 Register result) {
115 // Register use:
116 //
117 // elements - holds the property dictionary on entry and is unchanged.
118 //
119 // name - holds the name of the property on entry and is unchanged.
120 //
121 // r0 - used to hold the capacity of the property dictionary.
122 //
123 // r1 - used to hold the index into the property dictionary.
124 //
125 // result - holds the result on exit if the load succeeded.
126
127 Label done;
128
129 // Compute the capacity mask. 112 // Compute the capacity mask.
130 const int kCapacityOffset = 113 const int kCapacityOffset =
131 StringDictionary::kHeaderSize + 114 StringDictionary::kHeaderSize +
132 StringDictionary::kCapacityIndex * kPointerSize; 115 StringDictionary::kCapacityIndex * kPointerSize;
133 __ SmiToInteger32(r0, FieldOperand(elements, kCapacityOffset)); 116 __ SmiToInteger32(r0, FieldOperand(elements, kCapacityOffset));
134 __ decl(r0); 117 __ decl(r0);
135 118
136 // Generate an unrolled loop that performs a few probes before 119 // Generate an unrolled loop that performs a few probes before
137 // giving up. Measurements done on Gmail indicate that 2 probes 120 // giving up. Measurements done on Gmail indicate that 2 probes
138 // cover ~93% of loads from dictionaries. 121 // cover ~93% of loads from dictionaries.
(...skipping 11 matching lines...) Expand all
150 __ and_(r1, r0); 133 __ and_(r1, r0);
151 134
152 // Scale the index by multiplying by the entry size. 135 // Scale the index by multiplying by the entry size.
153 ASSERT(StringDictionary::kEntrySize == 3); 136 ASSERT(StringDictionary::kEntrySize == 3);
154 __ lea(r1, Operand(r1, r1, times_2, 0)); // r1 = r1 * 3 137 __ lea(r1, Operand(r1, r1, times_2, 0)); // r1 = r1 * 3
155 138
156 // Check if the key is identical to the name. 139 // Check if the key is identical to the name.
157 __ cmpq(name, Operand(elements, r1, times_pointer_size, 140 __ cmpq(name, Operand(elements, r1, times_pointer_size,
158 kElementsStartOffset - kHeapObjectTag)); 141 kElementsStartOffset - kHeapObjectTag));
159 if (i != kProbes - 1) { 142 if (i != kProbes - 1) {
160 __ j(equal, &done); 143 __ j(equal, done);
161 } else { 144 } else {
162 __ j(not_equal, miss_label); 145 __ j(not_equal, miss);
163 } 146 }
164 } 147 }
148 }
165 149
166 // Check that the value is a normal property. 150
151 // Helper function used to load a property from a dictionary backing storage.
152 // This function may return false negatives, so miss_label
153 // must always call a backup property load that is complete.
154 // This function is safe to call if name is not a symbol, and will jump to
155 // the miss_label in that case.
156 // The generated code assumes that the receiver has slow properties,
157 // is not a global object and does not have interceptors.
158 static void GenerateDictionaryLoad(MacroAssembler* masm,
159 Label* miss_label,
160 Register elements,
161 Register name,
162 Register r0,
163 Register r1,
164 Register result) {
165 // Register use:
166 //
167 // elements - holds the property dictionary on entry and is unchanged.
168 //
169 // name - holds the name of the property on entry and is unchanged.
170 //
171 // r0 - used to hold the capacity of the property dictionary.
172 //
173 // r1 - used to hold the index into the property dictionary.
174 //
175 // result - holds the result on exit if the load succeeded.
176
177 Label done;
178
179 // Probe the dictionary.
180 GenerateStringDictionaryProbes(masm,
181 miss_label,
182 &done,
183 elements,
184 name,
185 r0,
186 r1);
187
188 // If probing finds an entry in the dictionary, r0 contains the
189 // index into the dictionary. Check that the value is a normal
190 // property.
167 __ bind(&done); 191 __ bind(&done);
192 const int kElementsStartOffset =
193 StringDictionary::kHeaderSize +
194 StringDictionary::kElementsStartIndex * kPointerSize;
168 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; 195 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
169 __ Test(Operand(elements, r1, times_pointer_size, 196 __ Test(Operand(elements, r1, times_pointer_size,
170 kDetailsOffset - kHeapObjectTag), 197 kDetailsOffset - kHeapObjectTag),
171 Smi::FromInt(PropertyDetails::TypeField::mask())); 198 Smi::FromInt(PropertyDetails::TypeField::mask()));
172 __ j(not_zero, miss_label); 199 __ j(not_zero, miss_label);
173 200
174 // Get the value at the masked, scaled index. 201 // Get the value at the masked, scaled index.
175 const int kValueOffset = kElementsStartOffset + kPointerSize; 202 const int kValueOffset = kElementsStartOffset + kPointerSize;
176 __ movq(result, 203 __ movq(result,
177 Operand(elements, r1, times_pointer_size, 204 Operand(elements, r1, times_pointer_size,
178 kValueOffset - kHeapObjectTag)); 205 kValueOffset - kHeapObjectTag));
179 } 206 }
180 207
181 208
209 // Helper function used to store a property to a dictionary backing
210 // storage. This function may fail to store a property even though it
211 // is in the dictionary, so code at miss_label must always call a
212 // backup property store that is complete. This function is safe to
213 // call if name is not a symbol, and will jump to the miss_label in
214 // that case. The generated code assumes that the receiver has slow
215 // properties, is not a global object and does not have interceptors.
216 static void GenerateDictionaryStore(MacroAssembler* masm,
217 Label* miss_label,
218 Register elements,
219 Register name,
220 Register value,
221 Register scratch0,
222 Register scratch1) {
223 // Register use:
224 //
225 // elements - holds the property dictionary on entry and is clobbered.
226 //
227 // name - holds the name of the property on entry and is unchanged.
228 //
229 // value - holds the value to store and is unchanged.
230 //
231 // scratch0 - used for index into the property dictionary and is clobbered.
232 //
233 // scratch1 - used to hold the capacity of the property dictionary and is
234 // clobbered.
235 Label done;
236
237 // Probe the dictionary.
238 GenerateStringDictionaryProbes(masm,
239 miss_label,
240 &done,
241 elements,
242 name,
243 scratch0,
244 scratch1);
245
246 // If probing finds an entry in the dictionary, scratch0 contains the
247 // index into the dictionary. Check that the value is a normal
248 // property that is not read only.
249 __ bind(&done);
250 const int kElementsStartOffset =
251 StringDictionary::kHeaderSize +
252 StringDictionary::kElementsStartIndex * kPointerSize;
253 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
254 const int kTypeAndReadOnlyMask
255 = (PropertyDetails::TypeField::mask() |
256 PropertyDetails::AttributesField::encode(READ_ONLY)) << kSmiTagSize;
257 __ Test(Operand(elements,
258 scratch1,
259 times_pointer_size,
260 kDetailsOffset - kHeapObjectTag),
261 Smi::FromInt(kTypeAndReadOnlyMask));
262 __ j(not_zero, miss_label);
263
264 // Store the value at the masked, scaled index.
265 const int kValueOffset = kElementsStartOffset + kPointerSize;
266 __ lea(scratch1, Operand(elements,
267 scratch1,
268 times_pointer_size,
269 kValueOffset - kHeapObjectTag));
270 __ movq(Operand(scratch1, 0), value);
271
272 // Update write barrier. Make sure not to clobber the value.
273 __ movq(scratch0, value);
274 __ RecordWrite(elements, scratch1, scratch0);
275 }
276
277
182 static void GenerateNumberDictionaryLoad(MacroAssembler* masm, 278 static void GenerateNumberDictionaryLoad(MacroAssembler* masm,
183 Label* miss, 279 Label* miss,
184 Register elements, 280 Register elements,
185 Register key, 281 Register key,
186 Register r0, 282 Register r0,
187 Register r1, 283 Register r1,
188 Register r2, 284 Register r2,
189 Register result) { 285 Register result) {
190 // Register use: 286 // Register use:
191 // 287 //
(...skipping 1133 matching lines...) Expand 10 before | Expand all | Expand 10 after
1325 // rsp[16] : argument argc - 1 1421 // rsp[16] : argument argc - 1
1326 // ... 1422 // ...
1327 // rsp[argc * 8] : argument 1 1423 // rsp[argc * 8] : argument 1
1328 // rsp[(argc + 1) * 8] : argument 0 = receiver 1424 // rsp[(argc + 1) * 8] : argument 0 = receiver
1329 // ----------------------------------- 1425 // -----------------------------------
1330 Label miss; 1426 Label miss;
1331 1427
1332 // Get the receiver of the function from the stack. 1428 // Get the receiver of the function from the stack.
1333 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 1429 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
1334 1430
1335 GenerateDictionaryLoadReceiverCheck(masm, rdx, rax, rbx, &miss); 1431 GenerateStringDictionaryReceiverCheck(masm, rdx, rax, rbx, &miss);
1336 1432
1337 // rax: elements 1433 // rax: elements
1338 // Search the dictionary placing the result in rdi. 1434 // Search the dictionary placing the result in rdi.
1339 GenerateDictionaryLoad(masm, &miss, rax, rcx, rbx, rdi, rdi); 1435 GenerateDictionaryLoad(masm, &miss, rax, rcx, rbx, rdi, rdi);
1340 1436
1341 GenerateFunctionTailCall(masm, argc, &miss); 1437 GenerateFunctionTailCall(masm, argc, &miss);
1342 1438
1343 __ bind(&miss); 1439 __ bind(&miss);
1344 } 1440 }
1345 1441
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
1609 1705
1610 1706
1611 void LoadIC::GenerateNormal(MacroAssembler* masm) { 1707 void LoadIC::GenerateNormal(MacroAssembler* masm) {
1612 // ----------- S t a t e ------------- 1708 // ----------- S t a t e -------------
1613 // -- rax : receiver 1709 // -- rax : receiver
1614 // -- rcx : name 1710 // -- rcx : name
1615 // -- rsp[0] : return address 1711 // -- rsp[0] : return address
1616 // ----------------------------------- 1712 // -----------------------------------
1617 Label miss; 1713 Label miss;
1618 1714
1619 GenerateDictionaryLoadReceiverCheck(masm, rax, rdx, rbx, &miss); 1715 GenerateStringDictionaryReceiverCheck(masm, rax, rdx, rbx, &miss);
1620 1716
1621 // rdx: elements 1717 // rdx: elements
1622 // Search the dictionary placing the result in rax. 1718 // Search the dictionary placing the result in rax.
1623 GenerateDictionaryLoad(masm, &miss, rdx, rcx, rbx, rdi, rax); 1719 GenerateDictionaryLoad(masm, &miss, rdx, rcx, rbx, rdi, rax);
1624 __ ret(0); 1720 __ ret(0);
1625 1721
1626 // Cache miss: Jump to runtime. 1722 // Cache miss: Jump to runtime.
1627 __ bind(&miss); 1723 __ bind(&miss);
1628 GenerateMiss(masm); 1724 GenerateMiss(masm);
1629 } 1725 }
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
1753 1849
1754 ExternalReference ref = ExternalReference(IC_Utility(kStoreIC_ArrayLength)); 1850 ExternalReference ref = ExternalReference(IC_Utility(kStoreIC_ArrayLength));
1755 __ TailCallExternalReference(ref, 2, 1); 1851 __ TailCallExternalReference(ref, 2, 1);
1756 1852
1757 __ bind(&miss); 1853 __ bind(&miss);
1758 1854
1759 GenerateMiss(masm); 1855 GenerateMiss(masm);
1760 } 1856 }
1761 1857
1762 1858
1859 void StoreIC::GenerateNormal(MacroAssembler* masm) {
1860 // ----------- S t a t e -------------
1861 // -- rax : value
1862 // -- rcx : name
1863 // -- rdx : receiver
1864 // -- rsp[0] : return address
1865 // -----------------------------------
1866
1867 Label miss, restore_miss;
1868
1869 GenerateStringDictionaryReceiverCheck(masm, rdx, rbx, rdi, &miss);
1870
1871 GenerateDictionaryStore(masm, &miss, rbx, rcx, rax, r8, r9);
1872 __ IncrementCounter(&Counters::store_normal_hit, 1);
1873 __ ret(0);
1874
1875 __ bind(&miss);
1876 __ IncrementCounter(&Counters::store_normal_miss, 1);
1877 GenerateMiss(masm);
1878 }
1879
1880
1763 #undef __ 1881 #undef __
1764 1882
1765 1883
1766 } } // namespace v8::internal 1884 } } // namespace v8::internal
1767 1885
1768 #endif // V8_TARGET_ARCH_X64 1886 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/v8-counters.h ('k') | src/x64/macro-assembler-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698