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

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

Issue 2853003: Port KeyedCallIC implementation to x64 and ARM.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 6 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/x64/full-codegen-x64.cc ('k') | src/x64/stub-cache-x64.cc » ('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 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
50 // must always call a backup property load that is complete. 50 // must always call a backup property load that is complete.
51 // This function is safe to call if the receiver has fast properties, 51 // This function is safe to call if the receiver has fast properties,
52 // or if name is not a symbol, and will jump to the miss_label in that case. 52 // or if name is not a symbol, and will jump to the miss_label in that case.
53 static void GenerateDictionaryLoad(MacroAssembler* masm, 53 static void GenerateDictionaryLoad(MacroAssembler* masm,
54 Label* miss_label, 54 Label* miss_label,
55 Register r0, 55 Register r0,
56 Register r1, 56 Register r1,
57 Register r2, 57 Register r2,
58 Register name, 58 Register name,
59 Register r4, 59 Register r4,
60 Register result,
60 DictionaryCheck check_dictionary) { 61 DictionaryCheck check_dictionary) {
61 // Register use: 62 // Register use:
62 // 63 //
63 // r0 - used to hold the property dictionary. 64 // r0 - used to hold the property dictionary and is unchanged.
64 // 65 //
65 // r1 - initially the receiver. 66 // r1 - used to hold the receiver and is unchanged.
66 // - unchanged on any jump to miss_label.
67 // - holds the result on exit.
68 // 67 //
69 // r2 - used to hold the capacity of the property dictionary. 68 // r2 - used to hold the capacity of the property dictionary.
70 // 69 //
71 // name - holds the name of the property and is unchanged. 70 // name - holds the name of the property and is unchanged.
71 //
72 // r4 - used to hold the index into the property dictionary. 72 // r4 - used to hold the index into the property dictionary.
73 //
74 // result - holds the result on exit if the load succeeded.
73 75
74 Label done; 76 Label done;
75 77
76 // Check for the absence of an interceptor. 78 // Check for the absence of an interceptor.
77 // Load the map into r0. 79 // Load the map into r0.
78 __ movq(r0, FieldOperand(r1, JSObject::kMapOffset)); 80 __ movq(r0, FieldOperand(r1, JSObject::kMapOffset));
79 81
80 // Bail out if the receiver has a named interceptor. 82 // Bail out if the receiver has a named interceptor.
81 __ testl(FieldOperand(r0, Map::kBitFieldOffset), 83 __ testl(FieldOperand(r0, Map::kBitFieldOffset),
82 Immediate(1 << Map::kHasNamedInterceptor)); 84 Immediate(1 << Map::kHasNamedInterceptor));
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
141 143
142 // Check that the value is a normal property. 144 // Check that the value is a normal property.
143 __ bind(&done); 145 __ bind(&done);
144 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; 146 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
145 __ Test(Operand(r0, r4, times_pointer_size, kDetailsOffset - kHeapObjectTag), 147 __ Test(Operand(r0, r4, times_pointer_size, kDetailsOffset - kHeapObjectTag),
146 Smi::FromInt(PropertyDetails::TypeField::mask())); 148 Smi::FromInt(PropertyDetails::TypeField::mask()));
147 __ j(not_zero, miss_label); 149 __ j(not_zero, miss_label);
148 150
149 // Get the value at the masked, scaled index. 151 // Get the value at the masked, scaled index.
150 const int kValueOffset = kElementsStartOffset + kPointerSize; 152 const int kValueOffset = kElementsStartOffset + kPointerSize;
151 __ movq(r1, 153 __ movq(result,
152 Operand(r0, r4, times_pointer_size, kValueOffset - kHeapObjectTag)); 154 Operand(r0, r4, times_pointer_size, kValueOffset - kHeapObjectTag));
153 } 155 }
154 156
155 157
156 static void GenerateNumberDictionaryLoad(MacroAssembler* masm, 158 static void GenerateNumberDictionaryLoad(MacroAssembler* masm,
157 Label* miss, 159 Label* miss,
158 Register elements, 160 Register elements,
159 Register key, 161 Register key,
160 Register r0, 162 Register r0,
161 Register r1, 163 Register r1,
162 Register r2) { 164 Register r2,
165 Register result) {
163 // Register use: 166 // Register use:
164 // 167 //
165 // elements - holds the slow-case elements of the receiver and is unchanged. 168 // elements - holds the slow-case elements of the receiver on entry.
169 // Unchanged unless 'result' is the same register.
166 // 170 //
167 // key - holds the smi key on entry and is unchanged if a branch is 171 // key - holds the smi key on entry.
168 // performed to the miss label. 172 // Unchanged unless 'result' is the same register.
169 // Holds the result on exit if the load succeeded.
170 // 173 //
171 // Scratch registers: 174 // Scratch registers:
172 // 175 //
173 // r0 - holds the untagged key on entry and holds the hash once computed. 176 // r0 - holds the untagged key on entry and holds the hash once computed.
174 // 177 //
175 // r1 - used to hold the capacity mask of the dictionary 178 // r1 - used to hold the capacity mask of the dictionary
176 // 179 //
177 // r2 - used for the index into the dictionary. 180 // r2 - used for the index into the dictionary.
181 //
182 // result - holds the result on exit if the load succeeded.
183 // Allowed to be the same as 'key' or 'result'.
184 // Unchanged on bailout so 'key' or 'result' can be used
185 // in further computation.
186
178 Label done; 187 Label done;
179 188
180 // Compute the hash code from the untagged key. This must be kept in sync 189 // Compute the hash code from the untagged key. This must be kept in sync
181 // with ComputeIntegerHash in utils.h. 190 // with ComputeIntegerHash in utils.h.
182 // 191 //
183 // hash = ~hash + (hash << 15); 192 // hash = ~hash + (hash << 15);
184 __ movl(r1, r0); 193 __ movl(r1, r0);
185 __ notl(r0); 194 __ notl(r0);
186 __ shll(r1, Immediate(15)); 195 __ shll(r1, Immediate(15));
187 __ addl(r0, r1); 196 __ addl(r0, r1);
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 const int kDetailsOffset = 248 const int kDetailsOffset =
240 NumberDictionary::kElementsStartOffset + 2 * kPointerSize; 249 NumberDictionary::kElementsStartOffset + 2 * kPointerSize;
241 ASSERT_EQ(NORMAL, 0); 250 ASSERT_EQ(NORMAL, 0);
242 __ Test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset), 251 __ Test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset),
243 Smi::FromInt(PropertyDetails::TypeField::mask())); 252 Smi::FromInt(PropertyDetails::TypeField::mask()));
244 __ j(not_zero, miss); 253 __ j(not_zero, miss);
245 254
246 // Get the value at the masked, scaled index. 255 // Get the value at the masked, scaled index.
247 const int kValueOffset = 256 const int kValueOffset =
248 NumberDictionary::kElementsStartOffset + kPointerSize; 257 NumberDictionary::kElementsStartOffset + kPointerSize;
249 __ movq(key, FieldOperand(elements, r2, times_pointer_size, kValueOffset)); 258 __ movq(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset));
250 } 259 }
251 260
252 261
253 // One byte opcode for test eax,0xXXXXXXXX. 262 // One byte opcode for test eax,0xXXXXXXXX.
254 static const byte kTestEaxByte = 0xA9; 263 static const byte kTestEaxByte = 0xA9;
255 264
256 265
257 static bool PatchInlinedMapCheck(Address address, Object* map) { 266 static bool PatchInlinedMapCheck(Address address, Object* map) {
258 // Arguments are address of start of call sequence that called 267 // Arguments are address of start of call sequence that called
259 // the IC, 268 // the IC,
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
339 __ pop(rbx); 348 __ pop(rbx);
340 __ push(rdx); // receiver 349 __ push(rdx); // receiver
341 __ push(rax); // name 350 __ push(rax); // name
342 __ push(rbx); // return address 351 __ push(rbx); // return address
343 352
344 // Perform tail call to the entry. 353 // Perform tail call to the entry.
345 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); 354 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
346 } 355 }
347 356
348 357
358 // Checks the receiver for special cases (value type, slow case bits).
359 // Falls through for regular JS object.
360 static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm,
361 Register receiver,
362 Register map,
363 Label* slow) {
364 // Register use:
365 // receiver - holds the receiver and is unchanged.
366 // Scratch registers:
367 // map - used to hold the map of the receiver.
368
369 // Check that the object isn't a smi.
370 __ JumpIfSmi(receiver, slow);
371
372 // Check that the object is some kind of JS object EXCEPT JS Value type.
373 // In the case that the object is a value-wrapper object,
374 // we enter the runtime system to make sure that indexing
375 // into string objects work as intended.
376 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE);
377 __ CmpObjectType(receiver, JS_OBJECT_TYPE, map);
378 __ j(below, slow);
379
380 // Check bit field.
381 __ testb(FieldOperand(map, Map::kBitFieldOffset),
382 Immediate(KeyedLoadIC::kSlowCaseBitFieldMask));
383 __ j(not_zero, slow);
384 }
385
386
387 // Loads an indexed element from a fast case array.
388 static void GenerateFastArrayLoad(MacroAssembler* masm,
389 Register receiver,
390 Register key,
391 Register elements,
392 Register scratch,
393 Register result,
394 Label* not_fast_array,
395 Label* out_of_range) {
396 // Register use:
397 //
398 // receiver - holds the receiver on entry.
399 // Unchanged unless 'result' is the same register.
400 //
401 // key - holds the smi key on entry.
402 // Unchanged unless 'result' is the same register.
403 //
404 // elements - holds the elements of the receiver on exit.
405 //
406 // result - holds the result on exit if the load succeeded.
407 // Allowed to be the the same as 'receiver' or 'key'.
408 // Unchanged on bailout so 'receiver' and 'key' can be safely
409 // used by further computation.
410 //
411 // Scratch registers:
412 //
413 // scratch - used to hold elements of the receiver and the loaded value.
414
415 __ movq(elements, FieldOperand(receiver, JSObject::kElementsOffset));
416 // Check that the object is in fast mode (not dictionary).
417 __ CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
418 Heap::kFixedArrayMapRootIndex);
419 __ j(not_equal, not_fast_array);
420 // Check that the key (index) is within bounds.
421 __ SmiCompare(key, FieldOperand(elements, FixedArray::kLengthOffset));
422 // Unsigned comparison rejects negative indices.
423 __ j(above_equal, out_of_range);
424 // Fast case: Do the load.
425 SmiIndex index = masm->SmiToIndex(scratch, key, kPointerSizeLog2);
426 __ movq(scratch, FieldOperand(elements,
427 index.reg,
428 index.scale,
429 FixedArray::kHeaderSize));
430 __ CompareRoot(scratch, Heap::kTheHoleValueRootIndex);
431 // In case the loaded value is the_hole we have to consult GetProperty
432 // to ensure the prototype chain is searched.
433 __ j(equal, out_of_range);
434 if (!result.is(scratch)) {
435 __ movq(result, scratch);
436 }
437 }
438
439
440 // Checks whether a key is an array index string or a symbol string.
441 // Falls through if the key is a symbol.
442 static void GenerateKeyStringCheck(MacroAssembler* masm,
443 Register key,
444 Register map,
445 Register hash,
446 Label* index_string,
447 Label* not_symbol) {
448 // Register use:
449 // key - holds the key and is unchanged. Assumed to be non-smi.
450 // Scratch registers:
451 // map - used to hold the map of the key.
452 // hash - used to hold the hash of the key.
453 __ CmpObjectType(key, FIRST_NONSTRING_TYPE, map);
454 __ j(above_equal, not_symbol);
455 // Is the string an array index, with cached numeric value?
456 __ movl(hash, FieldOperand(key, String::kHashFieldOffset));
457 __ testl(hash, Immediate(String::kContainsCachedArrayIndexMask));
458 __ j(zero, index_string); // The value in hash is used at jump target.
459
460 // Is the string a symbol?
461 ASSERT(kSymbolTag != 0);
462 __ testb(FieldOperand(map, Map::kInstanceTypeOffset),
463 Immediate(kIsSymbolMask));
464 __ j(zero, not_symbol);
465 }
466
467
468 // Picks out an array index from the hash field.
469 static void GenerateIndexFromHash(MacroAssembler* masm,
470 Register key,
471 Register hash) {
472 // Register use:
473 // key - holds the overwritten key on exit.
474 // hash - holds the key's hash. Clobbered.
475
476 // The assert checks that the constants for the maximum number of digits
477 // for an array index cached in the hash field and the number of bits
478 // reserved for it does not conflict.
479 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
480 (1 << String::kArrayIndexValueBits));
481 // We want the smi-tagged index in key. Even if we subsequently go to
482 // the slow case, converting the key to a smi is always valid.
483 // key: string key
484 // hash: key's hash field, including its array index value.
485 __ and_(hash, Immediate(String::kArrayIndexValueMask));
486 __ shr(hash, Immediate(String::kHashShift));
487 // Here we actually clobber the key which will be used if calling into
488 // runtime later. However as the new key is the numeric value of a string key
489 // there is no difference in using either key.
490 __ Integer32ToSmi(key, hash);
491 }
492
493
349 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { 494 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
350 // ----------- S t a t e ------------- 495 // ----------- S t a t e -------------
351 // -- rax : key 496 // -- rax : key
352 // -- rdx : receiver 497 // -- rdx : receiver
353 // -- rsp[0] : return address 498 // -- rsp[0] : return address
354 // ----------------------------------- 499 // -----------------------------------
355 Label slow, check_string, index_smi, index_string; 500 Label slow, check_string, index_smi, index_string;
356 Label check_pixel_array, probe_dictionary, check_number_dictionary; 501 Label check_pixel_array, probe_dictionary, check_number_dictionary;
357 502
358 // Check that the object isn't a smi. 503 GenerateKeyedLoadReceiverCheck(masm, rdx, rcx, &slow);
359 __ JumpIfSmi(rdx, &slow);
360
361 // Check that the object is some kind of JS object EXCEPT JS Value type.
362 // In the case that the object is a value-wrapper object,
363 // we enter the runtime system to make sure that indexing
364 // into string objects work as intended.
365 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE);
366 __ CmpObjectType(rdx, JS_OBJECT_TYPE, rcx);
367 __ j(below, &slow);
368
369 // Check bit field.
370 __ testb(FieldOperand(rcx, Map::kBitFieldOffset),
371 Immediate(kSlowCaseBitFieldMask));
372 __ j(not_zero, &slow);
373 504
374 // Check that the key is a smi. 505 // Check that the key is a smi.
375 __ JumpIfNotSmi(rax, &check_string); 506 __ JumpIfNotSmi(rax, &check_string);
376 __ bind(&index_smi); 507 __ bind(&index_smi);
377 // Now the key is known to be a smi. This place is also jumped to from below 508 // Now the key is known to be a smi. This place is also jumped to from below
378 // where a numeric string is converted to a smi. 509 // where a numeric string is converted to a smi.
379 __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset)); 510
380 // Check that the object is in fast mode (not dictionary). 511 GenerateFastArrayLoad(masm,
381 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), 512 rdx,
382 Heap::kFixedArrayMapRootIndex); 513 rax,
383 __ j(not_equal, &check_pixel_array); 514 rcx,
384 // Check that the key (index) is within bounds. 515 rbx,
385 __ SmiCompare(rax, FieldOperand(rcx, FixedArray::kLengthOffset)); 516 rax,
386 __ j(above_equal, &slow); // Unsigned comparison rejects negative indices. 517 &check_pixel_array,
387 // Fast case: Do the load. 518 &slow);
388 SmiIndex index = masm->SmiToIndex(rbx, rax, kPointerSizeLog2);
389 __ movq(rbx, FieldOperand(rcx,
390 index.reg,
391 index.scale,
392 FixedArray::kHeaderSize));
393 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
394 // In case the loaded value is the_hole we have to consult GetProperty
395 // to ensure the prototype chain is searched.
396 __ j(equal, &slow);
397 __ movq(rax, rbx);
398 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1); 519 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1);
399 __ ret(0); 520 __ ret(0);
400 521
401 __ bind(&check_pixel_array); 522 __ bind(&check_pixel_array);
402 // Check whether the elements object is a pixel array. 523 // Check whether the elements object is a pixel array.
403 // rdx: receiver 524 // rdx: receiver
404 // rax: key 525 // rax: key
405 // rcx: elements array 526 // rcx: elements array
406 __ SmiToInteger32(rbx, rax); // Used on both directions of next branch. 527 __ SmiToInteger32(rbx, rax); // Used on both directions of next branch.
407 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), 528 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset),
408 Heap::kPixelArrayMapRootIndex); 529 Heap::kPixelArrayMapRootIndex);
409 __ j(not_equal, &check_number_dictionary); 530 __ j(not_equal, &check_number_dictionary);
410 __ cmpl(rbx, FieldOperand(rcx, PixelArray::kLengthOffset)); 531 __ cmpl(rbx, FieldOperand(rcx, PixelArray::kLengthOffset));
411 __ j(above_equal, &slow); 532 __ j(above_equal, &slow);
412 __ movq(rax, FieldOperand(rcx, PixelArray::kExternalPointerOffset)); 533 __ movq(rax, FieldOperand(rcx, PixelArray::kExternalPointerOffset));
413 __ movzxbq(rax, Operand(rax, rbx, times_1, 0)); 534 __ movzxbq(rax, Operand(rax, rbx, times_1, 0));
414 __ Integer32ToSmi(rax, rax); 535 __ Integer32ToSmi(rax, rax);
415 __ ret(0); 536 __ ret(0);
416 537
417 __ bind(&check_number_dictionary); 538 __ bind(&check_number_dictionary);
418 // Check whether the elements is a number dictionary. 539 // Check whether the elements is a number dictionary.
419 // rdx: receiver 540 // rdx: receiver
420 // rax: key 541 // rax: key
421 // rbx: key as untagged int32 542 // rbx: key as untagged int32
422 // rcx: elements 543 // rcx: elements
423 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), 544 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset),
424 Heap::kHashTableMapRootIndex); 545 Heap::kHashTableMapRootIndex);
425 __ j(not_equal, &slow); 546 __ j(not_equal, &slow);
426 GenerateNumberDictionaryLoad(masm, &slow, rcx, rax, rbx, r9, rdi); 547 GenerateNumberDictionaryLoad(masm, &slow, rcx, rax, rbx, r9, rdi, rax);
427 __ ret(0); 548 __ ret(0);
428 549
429 __ bind(&slow); 550 __ bind(&slow);
430 // Slow case: Jump to runtime. 551 // Slow case: Jump to runtime.
431 // rdx: receiver 552 // rdx: receiver
432 // rax: key 553 // rax: key
433 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1); 554 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1);
434 GenerateRuntimeGetProperty(masm); 555 GenerateRuntimeGetProperty(masm);
435 556
436 __ bind(&check_string); 557 __ bind(&check_string);
437 // The key is not a smi. 558 GenerateKeyStringCheck(masm, rax, rcx, rbx, &index_string, &slow);
438 // Is it a string?
439 // rdx: receiver
440 // rax: key
441 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rcx);
442 __ j(above_equal, &slow);
443 // Is the string an array index, with cached numeric value?
444 __ movl(rbx, FieldOperand(rax, String::kHashFieldOffset));
445 __ testl(rbx, Immediate(String::kContainsCachedArrayIndexMask));
446 __ j(zero, &index_string); // The value in rbx is used at jump target.
447
448 // Is the string a symbol?
449 ASSERT(kSymbolTag != 0);
450 __ testb(FieldOperand(rcx, Map::kInstanceTypeOffset),
451 Immediate(kIsSymbolMask));
452 __ j(zero, &slow);
453 559
454 // If the receiver is a fast-case object, check the keyed lookup 560 // If the receiver is a fast-case object, check the keyed lookup
455 // cache. Otherwise probe the dictionary leaving result in rcx. 561 // cache. Otherwise probe the dictionary leaving result in rcx.
456 __ movq(rbx, FieldOperand(rdx, JSObject::kPropertiesOffset)); 562 __ movq(rbx, FieldOperand(rdx, JSObject::kPropertiesOffset));
457 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), 563 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
458 Heap::kHashTableMapRootIndex); 564 Heap::kHashTableMapRootIndex);
459 __ j(equal, &probe_dictionary); 565 __ j(equal, &probe_dictionary);
460 566
461 // Load the map of the receiver, compute the keyed lookup cache hash 567 // Load the map of the receiver, compute the keyed lookup cache hash
462 // based on 32 bits of the map pointer and the string hash. 568 // based on 32 bits of the map pointer and the string hash.
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
502 __ bind(&probe_dictionary); 608 __ bind(&probe_dictionary);
503 // rdx: receiver 609 // rdx: receiver
504 // rax: key 610 // rax: key
505 GenerateDictionaryLoad(masm, 611 GenerateDictionaryLoad(masm,
506 &slow, 612 &slow,
507 rbx, 613 rbx,
508 rdx, 614 rdx,
509 rcx, 615 rcx,
510 rax, 616 rax,
511 rdi, 617 rdi,
618 rax,
512 DICTIONARY_CHECK_DONE); 619 DICTIONARY_CHECK_DONE);
513 __ movq(rax, rdx);
514 __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1); 620 __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1);
515 __ ret(0); 621 __ ret(0);
516 // If the hash field contains an array index pick it out. The assert checks 622
517 // that the constants for the maximum number of digits for an array index
518 // cached in the hash field and the number of bits reserved for it does not
519 // conflict.
520 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
521 (1 << String::kArrayIndexValueBits));
522 __ bind(&index_string); 623 __ bind(&index_string);
523 // We want the smi-tagged index in rax. Even if we subsequently go to 624 GenerateIndexFromHash(masm, rax, rbx);
524 // the slow case, converting the key to a smi is always valid.
525 // rdx: receiver
526 // rax: key (a string)
527 // rbx: key's hash field, including its array index value.
528 __ and_(rbx, Immediate(String::kArrayIndexValueMask));
529 __ shr(rbx, Immediate(String::kHashShift));
530 // Here we actually clobber the key (rax) which will be used if calling into
531 // runtime later. However as the new key is the numeric value of a string key
532 // there is no difference in using either key.
533 __ Integer32ToSmi(rax, rbx);
534 // Now jump to the place where smi keys are handled.
535 __ jmp(&index_smi); 625 __ jmp(&index_smi);
536 } 626 }
537 627
538 628
539 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { 629 void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
540 // ----------- S t a t e ------------- 630 // ----------- S t a t e -------------
541 // -- rax : key 631 // -- rax : key
542 // -- rdx : receiver 632 // -- rdx : receiver
543 // -- rsp[0] : return address 633 // -- rsp[0] : return address
544 // ----------------------------------- 634 // -----------------------------------
(...skipping 557 matching lines...) Expand 10 before | Expand all | Expand 10 after
1102 } 1192 }
1103 __ ret(0); 1193 __ ret(0);
1104 } 1194 }
1105 1195
1106 // Slow case: call runtime. 1196 // Slow case: call runtime.
1107 __ bind(&slow); 1197 __ bind(&slow);
1108 GenerateRuntimeSetProperty(masm); 1198 GenerateRuntimeSetProperty(masm);
1109 } 1199 }
1110 1200
1111 1201
1112 void CallIC::GenerateMiss(MacroAssembler* masm, int argc) { 1202 // Defined in ic.cc.
1203 Object* CallIC_Miss(Arguments args);
1204
1205
1206 static void GenerateCallMiss(MacroAssembler* masm, int argc, IC::UtilityId id) {
1113 // ----------- S t a t e ------------- 1207 // ----------- S t a t e -------------
1114 // rcx : function name 1208 // rcx : function name
1115 // rsp[0] : return address 1209 // rsp[0] : return address
1116 // rsp[8] : argument argc 1210 // rsp[8] : argument argc
1117 // rsp[16] : argument argc - 1 1211 // rsp[16] : argument argc - 1
1118 // ... 1212 // ...
1119 // rsp[argc * 8] : argument 1 1213 // rsp[argc * 8] : argument 1
1120 // rsp[(argc + 1) * 8] : argument 0 = receiver 1214 // rsp[(argc + 1) * 8] : argument 0 = receiver
1121 // ----------------------------------- 1215 // -----------------------------------
1122 // Get the receiver of the function from the stack; 1 ~ return address. 1216 // Get the receiver of the function from the stack; 1 ~ return address.
1123 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 1217 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
1124 1218
1125 // Enter an internal frame. 1219 // Enter an internal frame.
1126 __ EnterInternalFrame(); 1220 __ EnterInternalFrame();
1127 1221
1128 // Push the receiver and the name of the function. 1222 // Push the receiver and the name of the function.
1129 __ push(rdx); 1223 __ push(rdx);
1130 __ push(rcx); 1224 __ push(rcx);
1131 1225
1132 // Call the entry. 1226 // Call the entry.
1133 CEntryStub stub(1); 1227 CEntryStub stub(1);
1134 __ movq(rax, Immediate(2)); 1228 __ movq(rax, Immediate(2));
1135 __ movq(rbx, ExternalReference(IC_Utility(kCallIC_Miss))); 1229 __ movq(rbx, ExternalReference(IC_Utility(id)));
1136 __ CallStub(&stub); 1230 __ CallStub(&stub);
1137 1231
1138 // Move result to rdi and exit the internal frame. 1232 // Move result to rdi and exit the internal frame.
1139 __ movq(rdi, rax); 1233 __ movq(rdi, rax);
1140 __ LeaveInternalFrame(); 1234 __ LeaveInternalFrame();
1141 1235
1142 // Check if the receiver is a global object of some sort. 1236 // Check if the receiver is a global object of some sort.
1143 Label invoke, global; 1237 Label invoke, global;
1144 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); // receiver 1238 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); // receiver
1145 __ JumpIfSmi(rdx, &invoke); 1239 __ JumpIfSmi(rdx, &invoke);
1146 __ CmpObjectType(rdx, JS_GLOBAL_OBJECT_TYPE, rcx); 1240 __ CmpObjectType(rdx, JS_GLOBAL_OBJECT_TYPE, rcx);
1147 __ j(equal, &global); 1241 __ j(equal, &global);
1148 __ CmpInstanceType(rcx, JS_BUILTINS_OBJECT_TYPE); 1242 __ CmpInstanceType(rcx, JS_BUILTINS_OBJECT_TYPE);
1149 __ j(not_equal, &invoke); 1243 __ j(not_equal, &invoke);
1150 1244
1151 // Patch the receiver on the stack. 1245 // Patch the receiver on the stack.
1152 __ bind(&global); 1246 __ bind(&global);
1153 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); 1247 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
1154 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); 1248 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx);
1155 1249
1156 // Invoke the function. 1250 // Invoke the function.
1157 ParameterCount actual(argc); 1251 ParameterCount actual(argc);
1158 __ bind(&invoke); 1252 __ bind(&invoke);
1159 __ InvokeFunction(rdi, actual, JUMP_FUNCTION); 1253 __ InvokeFunction(rdi, actual, JUMP_FUNCTION);
1160 } 1254 }
1161 1255
1162 1256
1163 // Defined in ic.cc. 1257 // The generated code does not accept smi keys.
1164 Object* CallIC_Miss(Arguments args); 1258 // The generated code falls through if both probes miss.
1165 1259 static void GenerateMonomorphicCacheProbe(MacroAssembler* masm,
1166 void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { 1260 int argc,
1261 Code::Kind kind) {
1167 // ----------- S t a t e ------------- 1262 // ----------- S t a t e -------------
1168 // rcx : function name 1263 // rcx : function name
1169 // rsp[0] : return address 1264 // rdx : receiver
1170 // rsp[8] : argument argc
1171 // rsp[16] : argument argc - 1
1172 // ...
1173 // rsp[argc * 8] : argument 1
1174 // rsp[(argc + 1) * 8] : argument 0 = receiver
1175 // ----------------------------------- 1265 // -----------------------------------
1176 Label number, non_number, non_string, boolean, probe, miss; 1266 Label number, non_number, non_string, boolean, probe, miss;
1177 1267
1178 // Get the receiver of the function from the stack; 1 ~ return address.
1179 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
1180
1181 // Probe the stub cache. 1268 // Probe the stub cache.
1182 Code::Flags flags = 1269 Code::Flags flags =
1183 Code::ComputeFlags(Code::CALL_IC, NOT_IN_LOOP, MONOMORPHIC, NORMAL, argc); 1270 Code::ComputeFlags(kind, NOT_IN_LOOP, MONOMORPHIC, NORMAL, argc);
1184 StubCache::GenerateProbe(masm, flags, rdx, rcx, rbx, rax); 1271 StubCache::GenerateProbe(masm, flags, rdx, rcx, rbx, rax);
1185 1272
1186 // If the stub cache probing failed, the receiver might be a value. 1273 // If the stub cache probing failed, the receiver might be a value.
1187 // For value objects, we use the map of the prototype objects for 1274 // For value objects, we use the map of the prototype objects for
1188 // the corresponding JSValue for the cache and that is what we need 1275 // the corresponding JSValue for the cache and that is what we need
1189 // to probe. 1276 // to probe.
1190 // 1277 //
1191 // Check for number. 1278 // Check for number.
1192 __ JumpIfSmi(rdx, &number); 1279 __ JumpIfSmi(rdx, &number);
1193 __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rbx); 1280 __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rbx);
(...skipping 18 matching lines...) Expand all
1212 __ CompareRoot(rdx, Heap::kFalseValueRootIndex); 1299 __ CompareRoot(rdx, Heap::kFalseValueRootIndex);
1213 __ j(not_equal, &miss); 1300 __ j(not_equal, &miss);
1214 __ bind(&boolean); 1301 __ bind(&boolean);
1215 StubCompiler::GenerateLoadGlobalFunctionPrototype( 1302 StubCompiler::GenerateLoadGlobalFunctionPrototype(
1216 masm, Context::BOOLEAN_FUNCTION_INDEX, rdx); 1303 masm, Context::BOOLEAN_FUNCTION_INDEX, rdx);
1217 1304
1218 // Probe the stub cache for the value object. 1305 // Probe the stub cache for the value object.
1219 __ bind(&probe); 1306 __ bind(&probe);
1220 StubCache::GenerateProbe(masm, flags, rdx, rcx, rbx, no_reg); 1307 StubCache::GenerateProbe(masm, flags, rdx, rcx, rbx, no_reg);
1221 1308
1222 // Cache miss: Jump to runtime.
1223 __ bind(&miss); 1309 __ bind(&miss);
1224 GenerateMiss(masm, argc);
1225 } 1310 }
1226 1311
1227 1312
1228 static void GenerateNormalHelper(MacroAssembler* masm, 1313 static void GenerateNormalHelper(MacroAssembler* masm,
1229 int argc, 1314 int argc,
1230 bool is_global_object, 1315 bool is_global_object,
1231 Label* miss) { 1316 Label* miss) {
1232 // ----------- S t a t e ------------- 1317 // ----------- S t a t e -------------
1233 // rcx : function name 1318 // rcx : function name
1234 // rdx : receiver 1319 // rdx : receiver
1235 // rsp[0] : return address 1320 // rsp[0] : return address
1236 // rsp[8] : argument argc 1321 // rsp[8] : argument argc
1237 // rsp[16] : argument argc - 1 1322 // rsp[16] : argument argc - 1
1238 // ... 1323 // ...
1239 // rsp[argc * 8] : argument 1 1324 // rsp[argc * 8] : argument 1
1240 // rsp[(argc + 1) * 8] : argument 0 = receiver 1325 // rsp[(argc + 1) * 8] : argument 0 = receiver
1241 // ----------------------------------- 1326 // -----------------------------------
1242 // Search dictionary - put result in register rdx. 1327 // Search dictionary - put result in register rdx.
1243 GenerateDictionaryLoad(masm, miss, rax, rdx, rbx, rcx, rdi, CHECK_DICTIONARY); 1328 GenerateDictionaryLoad(
1329 masm, miss, rax, rdx, rbx, rcx, rdi, rdi, CHECK_DICTIONARY);
1244 1330
1245 // Move the result to register rdi and check that it isn't a smi. 1331 __ JumpIfSmi(rdi, miss);
1246 __ movq(rdi, rdx);
1247 __ JumpIfSmi(rdx, miss);
1248
1249 // Check that the value is a JavaScript function. 1332 // Check that the value is a JavaScript function.
1250 __ CmpObjectType(rdx, JS_FUNCTION_TYPE, rdx); 1333 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rdx);
1251 __ j(not_equal, miss); 1334 __ j(not_equal, miss);
1252 1335
1253 // Patch the receiver with the global proxy if necessary. 1336 // Patch the receiver with the global proxy if necessary.
1254 if (is_global_object) { 1337 if (is_global_object) {
1255 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
1256 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); 1338 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
1257 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); 1339 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx);
1258 } 1340 }
1259 1341
1260 // Invoke the function. 1342 // Invoke the function.
1261 ParameterCount actual(argc); 1343 ParameterCount actual(argc);
1262 __ InvokeFunction(rdi, actual, JUMP_FUNCTION); 1344 __ InvokeFunction(rdi, actual, JUMP_FUNCTION);
1263 } 1345 }
1264 1346
1265 1347
1266 void CallIC::GenerateNormal(MacroAssembler* masm, int argc) { 1348 // The generated code falls through if the call should be handled by runtime.
1349 static void GenerateCallNormal(MacroAssembler* masm, int argc) {
1267 // ----------- S t a t e ------------- 1350 // ----------- S t a t e -------------
1268 // rcx : function name 1351 // rcx : function name
1269 // rsp[0] : return address 1352 // rsp[0] : return address
1270 // rsp[8] : argument argc 1353 // rsp[8] : argument argc
1271 // rsp[16] : argument argc - 1 1354 // rsp[16] : argument argc - 1
1272 // ... 1355 // ...
1273 // rsp[argc * 8] : argument 1 1356 // rsp[argc * 8] : argument 1
1274 // rsp[(argc + 1) * 8] : argument 0 = receiver 1357 // rsp[(argc + 1) * 8] : argument 0 = receiver
1275 // ----------------------------------- 1358 // -----------------------------------
1276 Label miss, global_object, non_global_object; 1359 Label miss, global_object, non_global_object;
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1317 __ testb(rbx, Immediate(1 << Map::kIsAccessCheckNeeded)); 1400 __ testb(rbx, Immediate(1 << Map::kIsAccessCheckNeeded));
1318 __ j(not_equal, &miss); 1401 __ j(not_equal, &miss);
1319 __ bind(&invoke); 1402 __ bind(&invoke);
1320 GenerateNormalHelper(masm, argc, false, &miss); 1403 GenerateNormalHelper(masm, argc, false, &miss);
1321 1404
1322 // Global object proxy access: Check access rights. 1405 // Global object proxy access: Check access rights.
1323 __ bind(&global_proxy); 1406 __ bind(&global_proxy);
1324 __ CheckAccessGlobalProxy(rdx, rax, &miss); 1407 __ CheckAccessGlobalProxy(rdx, rax, &miss);
1325 __ jmp(&invoke); 1408 __ jmp(&invoke);
1326 1409
1327 // Cache miss: Jump to runtime.
1328 __ bind(&miss); 1410 __ bind(&miss);
1411 }
1412
1413
1414 void CallIC::GenerateMiss(MacroAssembler* masm, int argc) {
1415 // ----------- S t a t e -------------
1416 // rcx : function name
1417 // rsp[0] : return address
1418 // rsp[8] : argument argc
1419 // rsp[16] : argument argc - 1
1420 // ...
1421 // rsp[argc * 8] : argument 1
1422 // rsp[(argc + 1) * 8] : argument 0 = receiver
1423 // -----------------------------------
1424 GenerateCallMiss(masm, argc, IC::kCallIC_Miss);
1425 }
1426
1427
1428 void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
1429 // ----------- S t a t e -------------
1430 // rcx : function name
1431 // rsp[0] : return address
1432 // rsp[8] : argument argc
1433 // rsp[16] : argument argc - 1
1434 // ...
1435 // rsp[argc * 8] : argument 1
1436 // rsp[(argc + 1) * 8] : argument 0 = receiver
1437 // -----------------------------------
1438
1439 // Get the receiver of the function from the stack; 1 ~ return address.
1440 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
1441 GenerateMonomorphicCacheProbe(masm, argc, Code::CALL_IC);
1442 GenerateMiss(masm, argc);
1443 }
1444
1445
1446 void CallIC::GenerateNormal(MacroAssembler* masm, int argc) {
1447 // ----------- S t a t e -------------
1448 // rcx : function name
1449 // rsp[0] : return address
1450 // rsp[8] : argument argc
1451 // rsp[16] : argument argc - 1
1452 // ...
1453 // rsp[argc * 8] : argument 1
1454 // rsp[(argc + 1) * 8] : argument 0 = receiver
1455 // -----------------------------------
1456
1457 GenerateCallNormal(masm, argc);
1329 GenerateMiss(masm, argc); 1458 GenerateMiss(masm, argc);
1330 } 1459 }
1331 1460
1332 1461
1333 void KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) { 1462 void KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) {
1334 UNREACHABLE(); 1463 // ----------- S t a t e -------------
1464 // rcx : function name
1465 // rsp[0] : return address
1466 // rsp[8] : argument argc
1467 // rsp[16] : argument argc - 1
1468 // ...
1469 // rsp[argc * 8] : argument 1
1470 // rsp[(argc + 1) * 8] : argument 0 = receiver
1471 // -----------------------------------
1472
1473 GenerateCallMiss(masm, argc, IC::kKeyedCallIC_Miss);
1335 } 1474 }
1336 1475
1337 1476
1338 void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { 1477 void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
1339 UNREACHABLE(); 1478 // ----------- S t a t e -------------
1479 // rcx : function name
1480 // rsp[0] : return address
1481 // rsp[8] : argument argc
1482 // rsp[16] : argument argc - 1
1483 // ...
1484 // rsp[argc * 8] : argument 1
1485 // rsp[(argc + 1) * 8] : argument 0 = receiver
1486 // -----------------------------------
1487
1488 // Get the receiver of the function from the stack; 1 ~ return address.
1489 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
1490
1491 Label do_call, slow_call, slow_load, slow_reload_receiver;
1492 Label check_number_dictionary, check_string, lookup_monomorphic_cache;
1493 Label index_smi, index_string;
1494
1495 // Check that the key is a smi.
1496 __ JumpIfNotSmi(rcx, &check_string);
1497
1498 __ bind(&index_smi);
1499 // Now the key is known to be a smi. This place is also jumped to from below
1500 // where a numeric string is converted to a smi.
1501
1502 GenerateKeyedLoadReceiverCheck(masm, rdx, rax, &slow_call);
1503
1504 GenerateFastArrayLoad(
1505 masm, rdx, rcx, rax, rbx, rdi, &check_number_dictionary, &slow_load);
1506 __ IncrementCounter(&Counters::keyed_call_generic_smi_fast, 1);
1507
1508 __ bind(&do_call);
1509 // receiver in rdx is not used after this point.
1510 // rcx: key
1511 // rdi: function
1512
1513 // Check that the value in edi is a JavaScript function.
1514 __ JumpIfSmi(rdi, &slow_call);
1515 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rax);
1516 __ j(not_equal, &slow_call);
1517 // Invoke the function.
1518 ParameterCount actual(argc);
1519 __ InvokeFunction(rdi, actual, JUMP_FUNCTION);
1520
1521 __ bind(&check_number_dictionary);
1522 // eax: elements
1523 // ecx: smi key
1524 // Check whether the elements is a number dictionary.
1525 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
1526 Heap::kHashTableMapRootIndex);
1527 __ SmiToInteger32(rbx, rcx);
1528 // ebx: untagged index
1529 GenerateNumberDictionaryLoad(masm, &slow_load, rax, rcx, rbx, r9, rdi, rdi);
1530 __ IncrementCounter(&Counters::keyed_call_generic_smi_dict, 1);
1531 __ jmp(&do_call);
1532
1533 __ bind(&slow_load);
1534 // This branch is taken when calling KeyedCallIC_Miss is neither required
1535 // nor beneficial.
1536 __ IncrementCounter(&Counters::keyed_call_generic_slow_load, 1);
1537 __ EnterInternalFrame();
1538 __ push(rcx); // save the key
1539 __ push(rdx); // pass the receiver
1540 __ push(rcx); // pass the key
1541 __ CallRuntime(Runtime::kKeyedGetProperty, 2);
1542 __ pop(rcx); // restore the key
1543 __ LeaveInternalFrame();
1544 __ movq(rdi, rax);
1545 __ jmp(&do_call);
1546
1547 __ bind(&check_string);
1548 GenerateKeyStringCheck(masm, rcx, rax, rbx, &index_string, &slow_call);
1549
1550 // The key is known to be a symbol.
1551 // If the receiver is a regular JS object with slow properties then do
1552 // a quick inline probe of the receiver's dictionary.
1553 // Otherwise do the monomorphic cache probe.
1554 GenerateKeyedLoadReceiverCheck(masm, rdx, rax, &lookup_monomorphic_cache);
1555
1556 __ movq(rbx, FieldOperand(rdx, JSObject::kPropertiesOffset));
1557 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
1558 Heap::kHashTableMapRootIndex);
1559 __ j(not_equal, &lookup_monomorphic_cache);
1560
1561 GenerateDictionaryLoad(
1562 masm, &slow_load, rbx, rdx, rax, rcx, rdi, rdi, DICTIONARY_CHECK_DONE);
1563 __ IncrementCounter(&Counters::keyed_call_generic_lookup_dict, 1);
1564 __ jmp(&do_call);
1565
1566 __ bind(&lookup_monomorphic_cache);
1567 __ IncrementCounter(&Counters::keyed_call_generic_lookup_cache, 1);
1568 GenerateMonomorphicCacheProbe(masm, argc, Code::KEYED_CALL_IC);
1569 // Fall through on miss.
1570
1571 __ bind(&slow_call);
1572 // This branch is taken if:
1573 // - the receiver requires boxing or access check,
1574 // - the key is neither smi nor symbol,
1575 // - the value loaded is not a function,
1576 // - there is hope that the runtime will create a monomorphic call stub
1577 // that will get fetched next time.
1578 __ IncrementCounter(&Counters::keyed_call_generic_slow, 1);
1579 GenerateMiss(masm, argc);
1580
1581 __ bind(&index_string);
1582 GenerateIndexFromHash(masm, rcx, rbx);
1583 // Now jump to the place where smi keys are handled.
1584 __ jmp(&index_smi);
1340 } 1585 }
1341 1586
1342 1587
1343 void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) { 1588 void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) {
1344 UNREACHABLE(); 1589 // ----------- S t a t e -------------
1590 // rcx : function name
1591 // rsp[0] : return address
1592 // rsp[8] : argument argc
1593 // rsp[16] : argument argc - 1
1594 // ...
1595 // rsp[argc * 8] : argument 1
1596 // rsp[(argc + 1) * 8] : argument 0 = receiver
1597 // -----------------------------------
1598
1599 GenerateCallNormal(masm, argc);
1600 GenerateMiss(masm, argc);
1345 } 1601 }
1346 1602
1347 1603
1348 // The offset from the inlined patch site to the start of the 1604 // The offset from the inlined patch site to the start of the
1349 // inlined load instruction. 1605 // inlined load instruction.
1350 const int LoadIC::kOffsetToLoadInstruction = 20; 1606 const int LoadIC::kOffsetToLoadInstruction = 20;
1351 1607
1352 1608
1353 void LoadIC::ClearInlinedVersion(Address address) { 1609 void LoadIC::ClearInlinedVersion(Address address) {
1354 // Reset the map check of the inlined inobject property load (if 1610 // Reset the map check of the inlined inobject property load (if
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
1445 __ j(equal, &global); 1701 __ j(equal, &global);
1446 1702
1447 // Check for non-global object that requires access check. 1703 // Check for non-global object that requires access check.
1448 __ testl(FieldOperand(rbx, Map::kBitFieldOffset), 1704 __ testl(FieldOperand(rbx, Map::kBitFieldOffset),
1449 Immediate(1 << Map::kIsAccessCheckNeeded)); 1705 Immediate(1 << Map::kIsAccessCheckNeeded));
1450 __ j(not_zero, &miss); 1706 __ j(not_zero, &miss);
1451 1707
1452 // Search the dictionary placing the result in rax. 1708 // Search the dictionary placing the result in rax.
1453 __ bind(&probe); 1709 __ bind(&probe);
1454 GenerateDictionaryLoad(masm, &miss, rdx, rax, rbx, 1710 GenerateDictionaryLoad(masm, &miss, rdx, rax, rbx,
1455 rcx, rdi, CHECK_DICTIONARY); 1711 rcx, rdi, rax, CHECK_DICTIONARY);
1456 __ ret(0); 1712 __ ret(0);
1457 1713
1458 // Global object access: Check access rights. 1714 // Global object access: Check access rights.
1459 __ bind(&global); 1715 __ bind(&global);
1460 __ CheckAccessGlobalProxy(rax, rdx, &miss); 1716 __ CheckAccessGlobalProxy(rax, rdx, &miss);
1461 __ jmp(&probe); 1717 __ jmp(&probe);
1462 1718
1463 // Cache miss: Jump to runtime. 1719 // Cache miss: Jump to runtime.
1464 __ bind(&miss); 1720 __ bind(&miss);
1465 GenerateMiss(masm); 1721 GenerateMiss(masm);
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
1596 GenerateMiss(masm); 1852 GenerateMiss(masm);
1597 } 1853 }
1598 1854
1599 1855
1600 #undef __ 1856 #undef __
1601 1857
1602 1858
1603 } } // namespace v8::internal 1859 } } // namespace v8::internal
1604 1860
1605 #endif // V8_TARGET_ARCH_X64 1861 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/full-codegen-x64.cc ('k') | src/x64/stub-cache-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698