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

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

Issue 1148007: Merge bleeding_edge from version 2.1.3 up to revision 4205... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/partial_snapshots/
Patch Set: Created 10 years, 9 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 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 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
144 Smi::FromInt(PropertyDetails::TypeField::mask())); 144 Smi::FromInt(PropertyDetails::TypeField::mask()));
145 __ j(not_zero, miss_label); 145 __ j(not_zero, miss_label);
146 146
147 // Get the value at the masked, scaled index. 147 // Get the value at the masked, scaled index.
148 const int kValueOffset = kElementsStartOffset + kPointerSize; 148 const int kValueOffset = kElementsStartOffset + kPointerSize;
149 __ movq(r1, 149 __ movq(r1,
150 Operand(r0, r1, times_pointer_size, kValueOffset - kHeapObjectTag)); 150 Operand(r0, r1, times_pointer_size, kValueOffset - kHeapObjectTag));
151 } 151 }
152 152
153 153
154 static void GenerateNumberDictionaryLoad(MacroAssembler* masm,
155 Label* miss,
156 Register elements,
157 Register key,
158 Register r0,
159 Register r1,
160 Register r2) {
161 // Register use:
162 //
163 // elements - holds the slow-case elements of the receiver and is unchanged.
164 //
165 // key - holds the smi key on entry and is unchanged if a branch is
166 // performed to the miss label.
167 //
168 // Scratch registers:
169 //
170 // r0 - holds the untagged key on entry and holds the hash once computed.
171 // Holds the result on exit if the load succeeded.
172 //
173 // r1 - used to hold the capacity mask of the dictionary
174 //
175 // r2 - used for the index into the dictionary.
176 Label done;
177
178 // Compute the hash code from the untagged key. This must be kept in sync
179 // with ComputeIntegerHash in utils.h.
180 //
181 // hash = ~hash + (hash << 15);
182 __ movl(r1, r0);
183 __ notl(r0);
184 __ shll(r1, Immediate(15));
185 __ addl(r0, r1);
186 // hash = hash ^ (hash >> 12);
187 __ movl(r1, r0);
188 __ shrl(r1, Immediate(12));
189 __ xorl(r0, r1);
190 // hash = hash + (hash << 2);
191 __ leal(r0, Operand(r0, r0, times_4, 0));
192 // hash = hash ^ (hash >> 4);
193 __ movl(r1, r0);
194 __ shrl(r1, Immediate(4));
195 __ xorl(r0, r1);
196 // hash = hash * 2057;
197 __ imull(r0, r0, Immediate(2057));
198 // hash = hash ^ (hash >> 16);
199 __ movl(r1, r0);
200 __ shrl(r1, Immediate(16));
201 __ xorl(r0, r1);
202
203 // Compute capacity mask.
204 const int kCapacityOffset =
205 StringDictionary::kHeaderSize +
206 StringDictionary::kCapacityIndex * kPointerSize;
207 __ movq(r1, FieldOperand(elements, kCapacityOffset));
208 __ SmiToInteger32(r1, r1);
209 __ decl(r1);
210
211 const int kElementsStartOffset =
212 NumberDictionary::kHeaderSize +
213 NumberDictionary::kElementsStartIndex * kPointerSize;
214
215 // Generate an unrolled loop that performs a few probes before giving up.
216 const int kProbes = 4;
217 for (int i = 0; i < kProbes; i++) {
218 // Use r2 for index calculations and keep the hash intact in r0.
219 __ movq(r2, r0);
220 // Compute the masked index: (hash + i + i * i) & mask.
221 if (i > 0) {
222 __ addl(r2, Immediate(NumberDictionary::GetProbeOffset(i)));
223 }
224 __ and_(r2, r1);
225
226 // Scale the index by multiplying by the entry size.
227 ASSERT(NumberDictionary::kEntrySize == 3);
228 __ lea(r2, Operand(r2, r2, times_2, 0)); // r2 = r2 * 3
229
230 // Check if the key matches.
231 __ cmpq(key, FieldOperand(elements,
232 r2,
233 times_pointer_size,
234 kElementsStartOffset));
235 if (i != (kProbes - 1)) {
236 __ j(equal, &done);
237 } else {
238 __ j(not_equal, miss);
239 }
240 }
241
242 __ bind(&done);
243 // Check that the value is a normal propety.
244 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
245 ASSERT_EQ(NORMAL, 0);
246 __ Test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset),
247 Smi::FromInt(PropertyDetails::TypeField::mask()));
248 __ j(not_zero, miss);
249
250 // Get the value at the masked, scaled index.
251 const int kValueOffset = kElementsStartOffset + kPointerSize;
252 __ movq(r0, FieldOperand(elements, r2, times_pointer_size, kValueOffset));
253 }
254
255
154 // One byte opcode for test eax,0xXXXXXXXX. 256 // One byte opcode for test eax,0xXXXXXXXX.
155 static const byte kTestEaxByte = 0xA9; 257 static const byte kTestEaxByte = 0xA9;
156 258
157 259
158 static bool PatchInlinedMapCheck(Address address, Object* map) { 260 static bool PatchInlinedMapCheck(Address address, Object* map) {
159 // Arguments are address of start of call sequence that called 261 // Arguments are address of start of call sequence that called
160 // the IC, 262 // the IC,
161 Address test_instruction_address = 263 Address test_instruction_address =
162 address + Assembler::kCallTargetAddressOffset; 264 address + Assembler::kCallTargetAddressOffset;
163 // The keyed load has a fast inlined case if the IC call instruction 265 // The keyed load has a fast inlined case if the IC call instruction
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
248 350
249 351
250 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { 352 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
251 // ----------- S t a t e ------------- 353 // ----------- S t a t e -------------
252 // -- rsp[0] : return address 354 // -- rsp[0] : return address
253 // -- rsp[8] : name 355 // -- rsp[8] : name
254 // -- rsp[16] : receiver 356 // -- rsp[16] : receiver
255 // ----------------------------------- 357 // -----------------------------------
256 Label slow, check_string, index_int, index_string; 358 Label slow, check_string, index_int, index_string;
257 Label check_pixel_array, probe_dictionary; 359 Label check_pixel_array, probe_dictionary;
360 Label check_number_dictionary;
258 361
259 // Load name and receiver. 362 // Load name and receiver.
260 __ movq(rax, Operand(rsp, kPointerSize)); 363 __ movq(rax, Operand(rsp, kPointerSize));
261 __ movq(rcx, Operand(rsp, 2 * kPointerSize)); 364 __ movq(rcx, Operand(rsp, 2 * kPointerSize));
262 365
263 // Check that the object isn't a smi. 366 // Check that the object isn't a smi.
264 __ JumpIfSmi(rcx, &slow); 367 __ JumpIfSmi(rcx, &slow);
265 368
266 // Check that the object is some kind of JS object EXCEPT JS Value type. 369 // Check that the object is some kind of JS object EXCEPT JS Value type.
267 // In the case that the object is a value-wrapper object, 370 // In the case that the object is a value-wrapper object,
268 // we enter the runtime system to make sure that indexing 371 // we enter the runtime system to make sure that indexing
269 // into string objects work as intended. 372 // into string objects work as intended.
270 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE); 373 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE);
271 __ CmpObjectType(rcx, JS_OBJECT_TYPE, rdx); 374 __ CmpObjectType(rcx, JS_OBJECT_TYPE, rdx);
272 __ j(below, &slow); 375 __ j(below, &slow);
273 376
274 // Check bit field. 377 // Check bit field.
275 __ testb(FieldOperand(rdx, Map::kBitFieldOffset), 378 __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
276 Immediate(kSlowCaseBitFieldMask)); 379 Immediate(kSlowCaseBitFieldMask));
277 __ j(not_zero, &slow); 380 __ j(not_zero, &slow);
278 381
279 // Check that the key is a smi. 382 // Check that the key is a smi.
280 __ JumpIfNotSmi(rax, &check_string); 383 __ JumpIfNotSmi(rax, &check_string);
384 // Save key in rbx in case we want it for the number dictionary
385 // case.
386 __ movq(rbx, rax);
281 __ SmiToInteger32(rax, rax); 387 __ SmiToInteger32(rax, rax);
282 // Get the elements array of the object. 388 // Get the elements array of the object.
283 __ bind(&index_int); 389 __ bind(&index_int);
284 __ movq(rcx, FieldOperand(rcx, JSObject::kElementsOffset)); 390 __ movq(rcx, FieldOperand(rcx, JSObject::kElementsOffset));
285 // Check that the object is in fast mode (not dictionary). 391 // Check that the object is in fast mode (not dictionary).
286 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), 392 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset),
287 Heap::kFixedArrayMapRootIndex); 393 Heap::kFixedArrayMapRootIndex);
288 __ j(not_equal, &check_pixel_array); 394 __ j(not_equal, &check_pixel_array);
289 // Check that the key (index) is within bounds. 395 // Check that the key (index) is within bounds.
290 __ cmpl(rax, FieldOperand(rcx, FixedArray::kLengthOffset)); 396 __ cmpl(rax, FieldOperand(rcx, FixedArray::kLengthOffset));
291 __ j(above_equal, &slow); // Unsigned comparison rejects negative indices. 397 __ j(above_equal, &slow); // Unsigned comparison rejects negative indices.
292 // Fast case: Do the load. 398 // Fast case: Do the load.
293 __ movq(rax, Operand(rcx, rax, times_pointer_size, 399 __ movq(rax, Operand(rcx, rax, times_pointer_size,
294 FixedArray::kHeaderSize - kHeapObjectTag)); 400 FixedArray::kHeaderSize - kHeapObjectTag));
295 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); 401 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
296 // In case the loaded value is the_hole we have to consult GetProperty 402 // In case the loaded value is the_hole we have to consult GetProperty
297 // to ensure the prototype chain is searched. 403 // to ensure the prototype chain is searched.
298 __ j(equal, &slow); 404 __ j(equal, &slow);
299 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1); 405 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1);
300 __ ret(0); 406 __ ret(0);
301 407
302 // Check whether the elements is a pixel array. 408 // Check whether the elements is a pixel array.
303 // rax: untagged index 409 // rax: untagged index
304 // rcx: elements array 410 // rcx: elements array
305 __ bind(&check_pixel_array); 411 __ bind(&check_pixel_array);
306 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), 412 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset),
307 Heap::kPixelArrayMapRootIndex); 413 Heap::kPixelArrayMapRootIndex);
308 __ j(not_equal, &slow); 414 __ j(not_equal, &check_number_dictionary);
309 __ cmpl(rax, FieldOperand(rcx, PixelArray::kLengthOffset)); 415 __ cmpl(rax, FieldOperand(rcx, PixelArray::kLengthOffset));
310 __ j(above_equal, &slow); 416 __ j(above_equal, &slow);
311 __ movq(rcx, FieldOperand(rcx, PixelArray::kExternalPointerOffset)); 417 __ movq(rcx, FieldOperand(rcx, PixelArray::kExternalPointerOffset));
312 __ movzxbq(rax, Operand(rcx, rax, times_1, 0)); 418 __ movzxbq(rax, Operand(rcx, rax, times_1, 0));
313 __ Integer32ToSmi(rax, rax); 419 __ Integer32ToSmi(rax, rax);
314 __ ret(0); 420 __ ret(0);
315 421
422 __ bind(&check_number_dictionary);
423 // Check whether the elements is a number dictionary.
424 // rax: untagged index
425 // rbx: key
426 // rcx: elements
427 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset),
428 Heap::kHashTableMapRootIndex);
429 __ j(not_equal, &slow);
430 GenerateNumberDictionaryLoad(masm, &slow, rcx, rbx, rax, rdx, rdi);
431 __ ret(0);
432
316 // Slow case: Load name and receiver from stack and jump to runtime. 433 // Slow case: Load name and receiver from stack and jump to runtime.
317 __ bind(&slow); 434 __ bind(&slow);
318 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1); 435 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1);
319 GenerateRuntimeGetProperty(masm); 436 GenerateRuntimeGetProperty(masm);
320 __ bind(&check_string); 437 __ bind(&check_string);
321 // The key is not a smi. 438 // The key is not a smi.
322 // Is it a string? 439 // Is it a string?
323 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdx); 440 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdx);
324 __ j(above_equal, &slow); 441 __ j(above_equal, &slow);
325 // Is the string an array index, with cached numeric value? 442 // Is the string an array index, with cached numeric value?
(...skipping 1111 matching lines...) Expand 10 before | Expand all | Expand 10 after
1437 __ bind(&miss); 1554 __ bind(&miss);
1438 1555
1439 GenerateMiss(masm); 1556 GenerateMiss(masm);
1440 } 1557 }
1441 1558
1442 1559
1443 #undef __ 1560 #undef __
1444 1561
1445 1562
1446 } } // namespace v8::internal 1563 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698