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

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

Issue 6932010: Unroll more StringDictionary lookup probes both for positive and negative dictionary lookups. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: ported to arm&x64, cleaned up ia32 impl Created 9 years, 7 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
OLDNEW
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 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 __ b(ne, miss); 98 __ b(ne, miss);
99 99
100 __ ldr(elements, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 100 __ ldr(elements, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
101 __ ldr(t1, FieldMemOperand(elements, HeapObject::kMapOffset)); 101 __ ldr(t1, FieldMemOperand(elements, HeapObject::kMapOffset));
102 __ LoadRoot(ip, Heap::kHashTableMapRootIndex); 102 __ LoadRoot(ip, Heap::kHashTableMapRootIndex);
103 __ cmp(t1, ip); 103 __ cmp(t1, ip);
104 __ b(ne, miss); 104 __ b(ne, miss);
105 } 105 }
106 106
107 107
108 // Probe the string dictionary in the |elements| register. Jump to the
109 // |done| label if a property with the given name is found. Jump to
110 // the |miss| label otherwise.
111 static void GenerateStringDictionaryProbes(MacroAssembler* masm,
112 Label* miss,
113 Label* done,
114 Register elements,
115 Register name,
116 Register scratch1,
117 Register scratch2) {
118 // Assert that name contains a string.
119 if (FLAG_debug_code) __ AbortIfNotString(name);
120
121 // Compute the capacity mask.
122 const int kCapacityOffset = StringDictionary::kHeaderSize +
123 StringDictionary::kCapacityIndex * kPointerSize;
124 __ ldr(scratch1, FieldMemOperand(elements, kCapacityOffset));
125 __ mov(scratch1, Operand(scratch1, ASR, kSmiTagSize)); // convert smi to int
126 __ sub(scratch1, scratch1, Operand(1));
127
128 const int kElementsStartOffset = StringDictionary::kHeaderSize +
129 StringDictionary::kElementsStartIndex * kPointerSize;
130
131 // Generate an unrolled loop that performs a few probes before
132 // giving up. Measurements done on Gmail indicate that 2 probes
133 // cover ~93% of loads from dictionaries.
134 static const int kProbes = 4;
135 for (int i = 0; i < kProbes; i++) {
136 // Compute the masked index: (hash + i + i * i) & mask.
137 __ ldr(scratch2, FieldMemOperand(name, String::kHashFieldOffset));
138 if (i > 0) {
139 // Add the probe offset (i + i * i) left shifted to avoid right shifting
140 // the hash in a separate instruction. The value hash + i + i * i is right
141 // shifted in the following and instruction.
142 ASSERT(StringDictionary::GetProbeOffset(i) <
143 1 << (32 - String::kHashFieldOffset));
144 __ add(scratch2, scratch2, Operand(
145 StringDictionary::GetProbeOffset(i) << String::kHashShift));
146 }
147 __ and_(scratch2, scratch1, Operand(scratch2, LSR, String::kHashShift));
148
149 // Scale the index by multiplying by the element size.
150 ASSERT(StringDictionary::kEntrySize == 3);
151 // scratch2 = scratch2 * 3.
152 __ add(scratch2, scratch2, Operand(scratch2, LSL, 1));
153
154 // Check if the key is identical to the name.
155 __ add(scratch2, elements, Operand(scratch2, LSL, 2));
156 __ ldr(ip, FieldMemOperand(scratch2, kElementsStartOffset));
157 __ cmp(name, Operand(ip));
158 if (i != kProbes - 1) {
159 __ b(eq, done);
160 } else {
161 __ b(ne, miss);
162 }
163 }
164 }
165
166
167 // Helper function used from LoadIC/CallIC GenerateNormal. 108 // Helper function used from LoadIC/CallIC GenerateNormal.
168 // 109 //
169 // elements: Property dictionary. It is not clobbered if a jump to the miss 110 // elements: Property dictionary. It is not clobbered if a jump to the miss
170 // label is done. 111 // label is done.
171 // name: Property name. It is not clobbered if a jump to the miss label is 112 // name: Property name. It is not clobbered if a jump to the miss label is
172 // done 113 // done
173 // result: Register for the result. It is only updated if a jump to the miss 114 // result: Register for the result. It is only updated if a jump to the miss
174 // label is not done. Can be the same as elements or name clobbering 115 // label is not done. Can be the same as elements or name clobbering
175 // one of these in the case of not jumping to the miss label. 116 // one of these in the case of not jumping to the miss label.
176 // The two scratch registers need to be different from elements, name and 117 // The two scratch registers need to be different from elements, name and
177 // result. 118 // result.
178 // The generated code assumes that the receiver has slow properties, 119 // The generated code assumes that the receiver has slow properties,
179 // is not a global object and does not have interceptors. 120 // is not a global object and does not have interceptors.
180 static void GenerateDictionaryLoad(MacroAssembler* masm, 121 static void GenerateDictionaryLoad(MacroAssembler* masm,
181 Label* miss, 122 Label* miss,
182 Register elements, 123 Register elements,
183 Register name, 124 Register name,
184 Register result, 125 Register result,
185 Register scratch1, 126 Register scratch1,
186 Register scratch2) { 127 Register scratch2) {
187 // Main use of the scratch registers. 128 // Main use of the scratch registers.
188 // scratch1: Used as temporary and to hold the capacity of the property 129 // scratch1: Used as temporary and to hold the capacity of the property
189 // dictionary. 130 // dictionary.
190 // scratch2: Used as temporary. 131 // scratch2: Used as temporary.
191 Label done; 132 Label done;
192 133
193 // Probe the dictionary. 134 // Probe the dictionary.
194 GenerateStringDictionaryProbes(masm, 135 StringDictionaryLookupStub::GeneratePositiveLookup(masm,
195 miss, 136 miss,
196 &done, 137 &done,
197 elements, 138 elements,
198 name, 139 name,
199 scratch1, 140 scratch1,
200 scratch2); 141 scratch2);
201 142
202 // If probing finds an entry check that the value is a normal 143 // If probing finds an entry check that the value is a normal
203 // property. 144 // property.
204 __ bind(&done); // scratch2 == elements + 4 * index 145 __ bind(&done); // scratch2 == elements + 4 * index
205 const int kElementsStartOffset = StringDictionary::kHeaderSize + 146 const int kElementsStartOffset = StringDictionary::kHeaderSize +
206 StringDictionary::kElementsStartIndex * kPointerSize; 147 StringDictionary::kElementsStartIndex * kPointerSize;
207 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; 148 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
208 __ ldr(scratch1, FieldMemOperand(scratch2, kDetailsOffset)); 149 __ ldr(scratch1, FieldMemOperand(scratch2, kDetailsOffset));
209 __ tst(scratch1, Operand(PropertyDetails::TypeField::mask() << kSmiTagSize)); 150 __ tst(scratch1, Operand(PropertyDetails::TypeField::mask() << kSmiTagSize));
210 __ b(ne, miss); 151 __ b(ne, miss);
(...skipping 22 matching lines...) Expand all
233 Register value, 174 Register value,
234 Register scratch1, 175 Register scratch1,
235 Register scratch2) { 176 Register scratch2) {
236 // Main use of the scratch registers. 177 // Main use of the scratch registers.
237 // scratch1: Used as temporary and to hold the capacity of the property 178 // scratch1: Used as temporary and to hold the capacity of the property
238 // dictionary. 179 // dictionary.
239 // scratch2: Used as temporary. 180 // scratch2: Used as temporary.
240 Label done; 181 Label done;
241 182
242 // Probe the dictionary. 183 // Probe the dictionary.
243 GenerateStringDictionaryProbes(masm, 184 StringDictionaryLookupStub::GeneratePositiveLookup(masm,
244 miss, 185 miss,
245 &done, 186 &done,
246 elements, 187 elements,
247 name, 188 name,
248 scratch1, 189 scratch1,
249 scratch2); 190 scratch2);
250 191
251 // If probing finds an entry in the dictionary check that the value 192 // If probing finds an entry in the dictionary check that the value
252 // is a normal property that is not read only. 193 // is a normal property that is not read only.
253 __ bind(&done); // scratch2 == elements + 4 * index 194 __ bind(&done); // scratch2 == elements + 4 * index
254 const int kElementsStartOffset = StringDictionary::kHeaderSize + 195 const int kElementsStartOffset = StringDictionary::kHeaderSize +
255 StringDictionary::kElementsStartIndex * kPointerSize; 196 StringDictionary::kElementsStartIndex * kPointerSize;
256 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; 197 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
257 const int kTypeAndReadOnlyMask 198 const int kTypeAndReadOnlyMask
258 = (PropertyDetails::TypeField::mask() | 199 = (PropertyDetails::TypeField::mask() |
259 PropertyDetails::AttributesField::encode(READ_ONLY)) << kSmiTagSize; 200 PropertyDetails::AttributesField::encode(READ_ONLY)) << kSmiTagSize;
(...skipping 1313 matching lines...) Expand 10 before | Expand all | Expand 10 after
1573 Register reg = Assembler::GetRn(instr_at_patch); 1514 Register reg = Assembler::GetRn(instr_at_patch);
1574 patcher.masm()->tst(reg, Operand(kSmiTagMask)); 1515 patcher.masm()->tst(reg, Operand(kSmiTagMask));
1575 patcher.EmitCondition(eq); 1516 patcher.EmitCondition(eq);
1576 } 1517 }
1577 } 1518 }
1578 1519
1579 1520
1580 } } // namespace v8::internal 1521 } } // namespace v8::internal
1581 1522
1582 #endif // V8_TARGET_ARCH_ARM 1523 #endif // V8_TARGET_ARCH_ARM
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698