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

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

Issue 6928060: Merge Label and NearLabel (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: 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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 43
44 #define __ ACCESS_MASM(masm) 44 #define __ ACCESS_MASM(masm)
45 45
46 46
47 static void GenerateGlobalInstanceTypeCheck(MacroAssembler* masm, 47 static void GenerateGlobalInstanceTypeCheck(MacroAssembler* masm,
48 Register type, 48 Register type,
49 Label* global_object) { 49 Label* global_object) {
50 // Register usage: 50 // Register usage:
51 // type: holds the receiver instance type on entry. 51 // type: holds the receiver instance type on entry.
52 __ cmp(type, JS_GLOBAL_OBJECT_TYPE); 52 __ cmp(type, JS_GLOBAL_OBJECT_TYPE);
53 __ j(equal, global_object, not_taken); 53 __ j(equal, global_object, Label::kFar, not_taken);
54 __ cmp(type, JS_BUILTINS_OBJECT_TYPE); 54 __ cmp(type, JS_BUILTINS_OBJECT_TYPE);
55 __ j(equal, global_object, not_taken); 55 __ j(equal, global_object, Label::kFar, not_taken);
56 __ cmp(type, JS_GLOBAL_PROXY_TYPE); 56 __ cmp(type, JS_GLOBAL_PROXY_TYPE);
57 __ j(equal, global_object, not_taken); 57 __ j(equal, global_object, Label::kFar, not_taken);
58 } 58 }
59 59
60 60
61 // Generated code falls through if the receiver is a regular non-global 61 // Generated code falls through if the receiver is a regular non-global
62 // JS object with slow properties and no interceptors. 62 // JS object with slow properties and no interceptors.
63 static void GenerateStringDictionaryReceiverCheck(MacroAssembler* masm, 63 static void GenerateStringDictionaryReceiverCheck(MacroAssembler* masm,
64 Register receiver, 64 Register receiver,
65 Register r0, 65 Register r0,
66 Register r1, 66 Register r1,
67 Label* miss) { 67 Label* miss) {
68 // Register usage: 68 // Register usage:
69 // receiver: holds the receiver on entry and is unchanged. 69 // receiver: holds the receiver on entry and is unchanged.
70 // r0: used to hold receiver instance type. 70 // r0: used to hold receiver instance type.
71 // Holds the property dictionary on fall through. 71 // Holds the property dictionary on fall through.
72 // r1: used to hold receivers map. 72 // r1: used to hold receivers map.
73 73
74 // Check that the receiver isn't a smi. 74 // Check that the receiver isn't a smi.
75 __ test(receiver, Immediate(kSmiTagMask)); 75 __ test(receiver, Immediate(kSmiTagMask));
76 __ j(zero, miss, not_taken); 76 __ j(zero, miss, Label::kFar, not_taken);
77 77
78 // Check that the receiver is a valid JS object. 78 // Check that the receiver is a valid JS object.
79 __ mov(r1, FieldOperand(receiver, HeapObject::kMapOffset)); 79 __ mov(r1, FieldOperand(receiver, HeapObject::kMapOffset));
80 __ movzx_b(r0, FieldOperand(r1, Map::kInstanceTypeOffset)); 80 __ movzx_b(r0, FieldOperand(r1, Map::kInstanceTypeOffset));
81 __ cmp(r0, FIRST_JS_OBJECT_TYPE); 81 __ cmp(r0, FIRST_JS_OBJECT_TYPE);
82 __ j(below, miss, not_taken); 82 __ j(below, miss, Label::kFar, not_taken);
83 83
84 // If this assert fails, we have to check upper bound too. 84 // If this assert fails, we have to check upper bound too.
85 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); 85 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
86 86
87 GenerateGlobalInstanceTypeCheck(masm, r0, miss); 87 GenerateGlobalInstanceTypeCheck(masm, r0, miss);
88 88
89 // Check for non-global object that requires access check. 89 // Check for non-global object that requires access check.
90 __ test_b(FieldOperand(r1, Map::kBitFieldOffset), 90 __ test_b(FieldOperand(r1, Map::kBitFieldOffset),
91 (1 << Map::kIsAccessCheckNeeded) | 91 (1 << Map::kIsAccessCheckNeeded) |
92 (1 << Map::kHasNamedInterceptor)); 92 (1 << Map::kHasNamedInterceptor));
93 __ j(not_zero, miss, not_taken); 93 __ j(not_zero, miss, Label::kFar, not_taken);
94 94
95 __ mov(r0, FieldOperand(receiver, JSObject::kPropertiesOffset)); 95 __ mov(r0, FieldOperand(receiver, JSObject::kPropertiesOffset));
96 __ CheckMap(r0, FACTORY->hash_table_map(), miss, true); 96 __ CheckMap(r0, FACTORY->hash_table_map(), miss, true);
97 } 97 }
98 98
99 99
100
101 // Helper function used to load a property from a dictionary backing 100 // Helper function used to load a property from a dictionary backing
102 // storage. This function may fail to load a property even though it is 101 // storage. This function may fail to load a property even though it is
103 // in the dictionary, so code at miss_label must always call a backup 102 // in the dictionary, so code at miss_label must always call a backup
104 // property load that is complete. This function is safe to call if 103 // property load that is complete. This function is safe to call if
105 // name is not a symbol, and will jump to the miss_label in that 104 // name is not a symbol, and will jump to the miss_label in that
106 // case. The generated code assumes that the receiver has slow 105 // case. The generated code assumes that the receiver has slow
107 // properties, is not a global object and does not have interceptors. 106 // properties, is not a global object and does not have interceptors.
108 static void GenerateDictionaryLoad(MacroAssembler* masm, 107 static void GenerateDictionaryLoad(MacroAssembler* masm,
109 Label* miss_label, 108 Label* miss_label,
110 Register elements, 109 Register elements,
(...skipping 29 matching lines...) Expand all
140 // If probing finds an entry in the dictionary, r0 contains the 139 // If probing finds an entry in the dictionary, r0 contains the
141 // index into the dictionary. Check that the value is a normal 140 // index into the dictionary. Check that the value is a normal
142 // property. 141 // property.
143 __ bind(&done); 142 __ bind(&done);
144 const int kElementsStartOffset = 143 const int kElementsStartOffset =
145 StringDictionary::kHeaderSize + 144 StringDictionary::kHeaderSize +
146 StringDictionary::kElementsStartIndex * kPointerSize; 145 StringDictionary::kElementsStartIndex * kPointerSize;
147 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; 146 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
148 __ test(Operand(elements, r0, times_4, kDetailsOffset - kHeapObjectTag), 147 __ test(Operand(elements, r0, times_4, kDetailsOffset - kHeapObjectTag),
149 Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize)); 148 Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize));
150 __ j(not_zero, miss_label, not_taken); 149 __ j(not_zero, miss_label, Label::kFar, not_taken);
151 150
152 // Get the value at the masked, scaled index. 151 // Get the value at the masked, scaled index.
153 const int kValueOffset = kElementsStartOffset + kPointerSize; 152 const int kValueOffset = kElementsStartOffset + kPointerSize;
154 __ mov(result, Operand(elements, r0, times_4, kValueOffset - kHeapObjectTag)); 153 __ mov(result, Operand(elements, r0, times_4, kValueOffset - kHeapObjectTag));
155 } 154 }
156 155
157 156
158 // Helper function used to store a property to a dictionary backing 157 // Helper function used to store a property to a dictionary backing
159 // storage. This function may fail to store a property eventhough it 158 // storage. This function may fail to store a property eventhough it
160 // is in the dictionary, so code at miss_label must always call a 159 // is in the dictionary, so code at miss_label must always call a
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 __ bind(&done); 197 __ bind(&done);
199 const int kElementsStartOffset = 198 const int kElementsStartOffset =
200 StringDictionary::kHeaderSize + 199 StringDictionary::kHeaderSize +
201 StringDictionary::kElementsStartIndex * kPointerSize; 200 StringDictionary::kElementsStartIndex * kPointerSize;
202 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; 201 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
203 const int kTypeAndReadOnlyMask 202 const int kTypeAndReadOnlyMask
204 = (PropertyDetails::TypeField::mask() | 203 = (PropertyDetails::TypeField::mask() |
205 PropertyDetails::AttributesField::encode(READ_ONLY)) << kSmiTagSize; 204 PropertyDetails::AttributesField::encode(READ_ONLY)) << kSmiTagSize;
206 __ test(Operand(elements, r0, times_4, kDetailsOffset - kHeapObjectTag), 205 __ test(Operand(elements, r0, times_4, kDetailsOffset - kHeapObjectTag),
207 Immediate(kTypeAndReadOnlyMask)); 206 Immediate(kTypeAndReadOnlyMask));
208 __ j(not_zero, miss_label, not_taken); 207 __ j(not_zero, miss_label, Label::kFar, not_taken);
209 208
210 // Store the value at the masked, scaled index. 209 // Store the value at the masked, scaled index.
211 const int kValueOffset = kElementsStartOffset + kPointerSize; 210 const int kValueOffset = kElementsStartOffset + kPointerSize;
212 __ lea(r0, Operand(elements, r0, times_4, kValueOffset - kHeapObjectTag)); 211 __ lea(r0, Operand(elements, r0, times_4, kValueOffset - kHeapObjectTag));
213 __ mov(Operand(r0, 0), value); 212 __ mov(Operand(r0, 0), value);
214 213
215 // Update write barrier. Make sure not to clobber the value. 214 // Update write barrier. Make sure not to clobber the value.
216 __ mov(r1, value); 215 __ mov(r1, value);
217 __ RecordWrite(elements, r0, r1); 216 __ RecordWrite(elements, r0, r1);
218 } 217 }
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
288 // Scale the index by multiplying by the entry size. 287 // Scale the index by multiplying by the entry size.
289 ASSERT(NumberDictionary::kEntrySize == 3); 288 ASSERT(NumberDictionary::kEntrySize == 3);
290 __ lea(r2, Operand(r2, r2, times_2, 0)); // r2 = r2 * 3 289 __ lea(r2, Operand(r2, r2, times_2, 0)); // r2 = r2 * 3
291 290
292 // Check if the key matches. 291 // Check if the key matches.
293 __ cmp(key, FieldOperand(elements, 292 __ cmp(key, FieldOperand(elements,
294 r2, 293 r2,
295 times_pointer_size, 294 times_pointer_size,
296 NumberDictionary::kElementsStartOffset)); 295 NumberDictionary::kElementsStartOffset));
297 if (i != (kProbes - 1)) { 296 if (i != (kProbes - 1)) {
298 __ j(equal, &done, taken); 297 __ j(equal, &done, Label::kFar, taken);
299 } else { 298 } else {
300 __ j(not_equal, miss, not_taken); 299 __ j(not_equal, miss, Label::kFar, not_taken);
301 } 300 }
302 } 301 }
303 302
304 __ bind(&done); 303 __ bind(&done);
305 // Check that the value is a normal propety. 304 // Check that the value is a normal propety.
306 const int kDetailsOffset = 305 const int kDetailsOffset =
307 NumberDictionary::kElementsStartOffset + 2 * kPointerSize; 306 NumberDictionary::kElementsStartOffset + 2 * kPointerSize;
308 ASSERT_EQ(NORMAL, 0); 307 ASSERT_EQ(NORMAL, 0);
309 __ test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset), 308 __ test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset),
310 Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize)); 309 Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize));
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
368 Register map, 367 Register map,
369 int interceptor_bit, 368 int interceptor_bit,
370 Label* slow) { 369 Label* slow) {
371 // Register use: 370 // Register use:
372 // receiver - holds the receiver and is unchanged. 371 // receiver - holds the receiver and is unchanged.
373 // Scratch registers: 372 // Scratch registers:
374 // map - used to hold the map of the receiver. 373 // map - used to hold the map of the receiver.
375 374
376 // Check that the object isn't a smi. 375 // Check that the object isn't a smi.
377 __ test(receiver, Immediate(kSmiTagMask)); 376 __ test(receiver, Immediate(kSmiTagMask));
378 __ j(zero, slow, not_taken); 377 __ j(zero, slow, Label::kFar, not_taken);
379 378
380 // Get the map of the receiver. 379 // Get the map of the receiver.
381 __ mov(map, FieldOperand(receiver, HeapObject::kMapOffset)); 380 __ mov(map, FieldOperand(receiver, HeapObject::kMapOffset));
382 381
383 // Check bit field. 382 // Check bit field.
384 __ test_b(FieldOperand(map, Map::kBitFieldOffset), 383 __ test_b(FieldOperand(map, Map::kBitFieldOffset),
385 (1 << Map::kIsAccessCheckNeeded) | (1 << interceptor_bit)); 384 (1 << Map::kIsAccessCheckNeeded) | (1 << interceptor_bit));
386 __ j(not_zero, slow, not_taken); 385 __ j(not_zero, slow, Label::kFar, not_taken);
387 // Check that the object is some kind of JS object EXCEPT JS Value type. 386 // Check that the object is some kind of JS object EXCEPT JS Value type.
388 // In the case that the object is a value-wrapper object, 387 // In the case that the object is a value-wrapper object,
389 // we enter the runtime system to make sure that indexing 388 // we enter the runtime system to make sure that indexing
390 // into string objects works as intended. 389 // into string objects works as intended.
391 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE); 390 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE);
392 391
393 __ CmpInstanceType(map, JS_OBJECT_TYPE); 392 __ CmpInstanceType(map, JS_OBJECT_TYPE);
394 __ j(below, slow, not_taken); 393 __ j(below, slow, Label::kFar, not_taken);
395 } 394 }
396 395
397 396
398 // Loads an indexed element from a fast case array. 397 // Loads an indexed element from a fast case array.
399 // If not_fast_array is NULL, doesn't perform the elements map check. 398 // If not_fast_array is NULL, doesn't perform the elements map check.
400 static void GenerateFastArrayLoad(MacroAssembler* masm, 399 static void GenerateFastArrayLoad(MacroAssembler* masm,
401 Register receiver, 400 Register receiver,
402 Register key, 401 Register key,
403 Register scratch, 402 Register scratch,
404 Register result, 403 Register result,
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
447 // key - holds the key and is unchanged. Assumed to be non-smi. 446 // key - holds the key and is unchanged. Assumed to be non-smi.
448 // Scratch registers: 447 // Scratch registers:
449 // map - used to hold the map of the key. 448 // map - used to hold the map of the key.
450 // hash - used to hold the hash of the key. 449 // hash - used to hold the hash of the key.
451 __ CmpObjectType(key, FIRST_NONSTRING_TYPE, map); 450 __ CmpObjectType(key, FIRST_NONSTRING_TYPE, map);
452 __ j(above_equal, not_symbol); 451 __ j(above_equal, not_symbol);
453 452
454 // Is the string an array index, with cached numeric value? 453 // Is the string an array index, with cached numeric value?
455 __ mov(hash, FieldOperand(key, String::kHashFieldOffset)); 454 __ mov(hash, FieldOperand(key, String::kHashFieldOffset));
456 __ test(hash, Immediate(String::kContainsCachedArrayIndexMask)); 455 __ test(hash, Immediate(String::kContainsCachedArrayIndexMask));
457 __ j(zero, index_string, not_taken); 456 __ j(zero, index_string, Label::kFar, not_taken);
458 457
459 // Is the string a symbol? 458 // Is the string a symbol?
460 ASSERT(kSymbolTag != 0); 459 ASSERT(kSymbolTag != 0);
461 __ test_b(FieldOperand(map, Map::kInstanceTypeOffset), kIsSymbolMask); 460 __ test_b(FieldOperand(map, Map::kInstanceTypeOffset), kIsSymbolMask);
462 __ j(zero, not_symbol, not_taken); 461 __ j(zero, not_symbol, Label::kFar, not_taken);
463 } 462 }
464 463
465 464
466 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { 465 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
467 // ----------- S t a t e ------------- 466 // ----------- S t a t e -------------
468 // -- eax : key 467 // -- eax : key
469 // -- edx : receiver 468 // -- edx : receiver
470 // -- esp[0] : return address 469 // -- esp[0] : return address
471 // ----------------------------------- 470 // -----------------------------------
472 Label slow, check_string, index_smi, index_string, property_array_property; 471 Label slow, check_string, index_smi, index_string, property_array_property;
473 Label probe_dictionary, check_number_dictionary; 472 Label probe_dictionary, check_number_dictionary;
474 473
475 // Check that the key is a smi. 474 // Check that the key is a smi.
476 __ test(eax, Immediate(kSmiTagMask)); 475 __ test(eax, Immediate(kSmiTagMask));
477 __ j(not_zero, &check_string, not_taken); 476 __ j(not_zero, &check_string, Label::kFar, not_taken);
478 __ bind(&index_smi); 477 __ bind(&index_smi);
479 // Now the key is known to be a smi. This place is also jumped to from 478 // Now the key is known to be a smi. This place is also jumped to from
480 // where a numeric string is converted to a smi. 479 // where a numeric string is converted to a smi.
481 480
482 GenerateKeyedLoadReceiverCheck( 481 GenerateKeyedLoadReceiverCheck(
483 masm, edx, ecx, Map::kHasIndexedInterceptor, &slow); 482 masm, edx, ecx, Map::kHasIndexedInterceptor, &slow);
484 483
485 // Check the "has fast elements" bit in the receiver's map which is 484 // Check the "has fast elements" bit in the receiver's map which is
486 // now in ecx. 485 // now in ecx.
487 __ test_b(FieldOperand(ecx, Map::kBitField2Offset), 486 __ test_b(FieldOperand(ecx, Map::kBitField2Offset),
488 1 << Map::kHasFastElements); 487 1 << Map::kHasFastElements);
489 __ j(zero, &check_number_dictionary, not_taken); 488 __ j(zero, &check_number_dictionary, Label::kFar, not_taken);
490 489
491 GenerateFastArrayLoad(masm, 490 GenerateFastArrayLoad(masm,
492 edx, 491 edx,
493 eax, 492 eax,
494 ecx, 493 ecx,
495 eax, 494 eax,
496 NULL, 495 NULL,
497 &slow); 496 &slow);
498 Isolate* isolate = masm->isolate(); 497 Isolate* isolate = masm->isolate();
499 Counters* counters = isolate->counters(); 498 Counters* counters = isolate->counters();
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
657 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { 656 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
658 // ----------- S t a t e ------------- 657 // ----------- S t a t e -------------
659 // -- eax : key 658 // -- eax : key
660 // -- edx : receiver 659 // -- edx : receiver
661 // -- esp[0] : return address 660 // -- esp[0] : return address
662 // ----------------------------------- 661 // -----------------------------------
663 Label slow; 662 Label slow;
664 663
665 // Check that the receiver isn't a smi. 664 // Check that the receiver isn't a smi.
666 __ test(edx, Immediate(kSmiTagMask)); 665 __ test(edx, Immediate(kSmiTagMask));
667 __ j(zero, &slow, not_taken); 666 __ j(zero, &slow, Label::kFar, not_taken);
668 667
669 // Check that the key is an array index, that is Uint32. 668 // Check that the key is an array index, that is Uint32.
670 __ test(eax, Immediate(kSmiTagMask | kSmiSignMask)); 669 __ test(eax, Immediate(kSmiTagMask | kSmiSignMask));
671 __ j(not_zero, &slow, not_taken); 670 __ j(not_zero, &slow, Label::kFar, not_taken);
672 671
673 // Get the map of the receiver. 672 // Get the map of the receiver.
674 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 673 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
675 674
676 // Check that it has indexed interceptor and access checks 675 // Check that it has indexed interceptor and access checks
677 // are not enabled for this object. 676 // are not enabled for this object.
678 __ movzx_b(ecx, FieldOperand(ecx, Map::kBitFieldOffset)); 677 __ movzx_b(ecx, FieldOperand(ecx, Map::kBitFieldOffset));
679 __ and_(Operand(ecx), Immediate(kSlowCaseBitFieldMask)); 678 __ and_(Operand(ecx), Immediate(kSlowCaseBitFieldMask));
680 __ cmp(Operand(ecx), Immediate(1 << Map::kHasIndexedInterceptor)); 679 __ cmp(Operand(ecx), Immediate(1 << Map::kHasIndexedInterceptor));
681 __ j(not_zero, &slow, not_taken); 680 __ j(not_zero, &slow, Label::kFar, not_taken);
682 681
683 // Everything is fine, call runtime. 682 // Everything is fine, call runtime.
684 __ pop(ecx); 683 __ pop(ecx);
685 __ push(edx); // receiver 684 __ push(edx); // receiver
686 __ push(eax); // key 685 __ push(eax); // key
687 __ push(ecx); // return address 686 __ push(ecx); // return address
688 687
689 // Perform tail call to the entry. 688 // Perform tail call to the entry.
690 ExternalReference ref = 689 ExternalReference ref =
691 ExternalReference(IC_Utility(kKeyedLoadPropertyWithInterceptor), 690 ExternalReference(IC_Utility(kKeyedLoadPropertyWithInterceptor),
(...skipping 10 matching lines...) Expand all
702 // ----------- S t a t e ------------- 701 // ----------- S t a t e -------------
703 // -- eax : value 702 // -- eax : value
704 // -- ecx : key 703 // -- ecx : key
705 // -- edx : receiver 704 // -- edx : receiver
706 // -- esp[0] : return address 705 // -- esp[0] : return address
707 // ----------------------------------- 706 // -----------------------------------
708 Label slow, fast, array, extra; 707 Label slow, fast, array, extra;
709 708
710 // Check that the object isn't a smi. 709 // Check that the object isn't a smi.
711 __ test(edx, Immediate(kSmiTagMask)); 710 __ test(edx, Immediate(kSmiTagMask));
712 __ j(zero, &slow, not_taken); 711 __ j(zero, &slow, Label::kFar, not_taken);
713 // Get the map from the receiver. 712 // Get the map from the receiver.
714 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); 713 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
715 // Check that the receiver does not require access checks. We need 714 // Check that the receiver does not require access checks. We need
716 // to do this because this generic stub does not perform map checks. 715 // to do this because this generic stub does not perform map checks.
717 __ test_b(FieldOperand(edi, Map::kBitFieldOffset), 716 __ test_b(FieldOperand(edi, Map::kBitFieldOffset),
718 1 << Map::kIsAccessCheckNeeded); 717 1 << Map::kIsAccessCheckNeeded);
719 __ j(not_zero, &slow, not_taken); 718 __ j(not_zero, &slow, Label::kFar, not_taken);
720 // Check that the key is a smi. 719 // Check that the key is a smi.
721 __ test(ecx, Immediate(kSmiTagMask)); 720 __ test(ecx, Immediate(kSmiTagMask));
722 __ j(not_zero, &slow, not_taken); 721 __ j(not_zero, &slow, Label::kFar, not_taken);
723 __ CmpInstanceType(edi, JS_ARRAY_TYPE); 722 __ CmpInstanceType(edi, JS_ARRAY_TYPE);
724 __ j(equal, &array); 723 __ j(equal, &array);
725 // Check that the object is some kind of JS object. 724 // Check that the object is some kind of JS object.
726 __ CmpInstanceType(edi, FIRST_JS_OBJECT_TYPE); 725 __ CmpInstanceType(edi, FIRST_JS_OBJECT_TYPE);
727 __ j(below, &slow, not_taken); 726 __ j(below, &slow, Label::kFar, not_taken);
728 727
729 // Object case: Check key against length in the elements array. 728 // Object case: Check key against length in the elements array.
730 // eax: value 729 // eax: value
731 // edx: JSObject 730 // edx: JSObject
732 // ecx: key (a smi) 731 // ecx: key (a smi)
733 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); 732 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
734 // Check that the object is in fast mode and writable. 733 // Check that the object is in fast mode and writable.
735 __ CheckMap(edi, FACTORY->fixed_array_map(), &slow, true); 734 __ CheckMap(edi, FACTORY->fixed_array_map(), &slow, true);
736 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); 735 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset));
737 __ j(below, &fast, taken); 736 __ j(below, &fast, Label::kFar, taken);
738 737
739 // Slow case: call runtime. 738 // Slow case: call runtime.
740 __ bind(&slow); 739 __ bind(&slow);
741 GenerateRuntimeSetProperty(masm, strict_mode); 740 GenerateRuntimeSetProperty(masm, strict_mode);
742 741
743 // Extra capacity case: Check if there is extra capacity to 742 // Extra capacity case: Check if there is extra capacity to
744 // perform the store and update the length. Used for adding one 743 // perform the store and update the length. Used for adding one
745 // element to the array by writing to array[array.length]. 744 // element to the array by writing to array[array.length].
746 __ bind(&extra); 745 __ bind(&extra);
747 // eax: value 746 // eax: value
748 // edx: receiver, a JSArray 747 // edx: receiver, a JSArray
749 // ecx: key, a smi. 748 // ecx: key, a smi.
750 // edi: receiver->elements, a FixedArray 749 // edi: receiver->elements, a FixedArray
751 // flags: compare (ecx, edx.length()) 750 // flags: compare (ecx, edx.length())
752 __ j(not_equal, &slow, not_taken); // do not leave holes in the array 751 // do not leave holes in the array:
752 __ j(not_equal, &slow, Label::kFar, not_taken);
753 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); 753 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset));
754 __ j(above_equal, &slow, not_taken); 754 __ j(above_equal, &slow, Label::kFar, not_taken);
755 // Add 1 to receiver->length, and go to fast array write. 755 // Add 1 to receiver->length, and go to fast array write.
756 __ add(FieldOperand(edx, JSArray::kLengthOffset), 756 __ add(FieldOperand(edx, JSArray::kLengthOffset),
757 Immediate(Smi::FromInt(1))); 757 Immediate(Smi::FromInt(1)));
758 __ jmp(&fast); 758 __ jmp(&fast);
759 759
760 // Array case: Get the length and the elements array from the JS 760 // Array case: Get the length and the elements array from the JS
761 // array. Check that the array is in fast mode (and writable); if it 761 // array. Check that the array is in fast mode (and writable); if it
762 // is the length is always a smi. 762 // is the length is always a smi.
763 __ bind(&array); 763 __ bind(&array);
764 // eax: value 764 // eax: value
765 // edx: receiver, a JSArray 765 // edx: receiver, a JSArray
766 // ecx: key, a smi. 766 // ecx: key, a smi.
767 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); 767 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
768 __ CheckMap(edi, FACTORY->fixed_array_map(), &slow, true); 768 __ CheckMap(edi, FACTORY->fixed_array_map(), &slow, true);
769 769
770 // Check the key against the length in the array, compute the 770 // Check the key against the length in the array, compute the
771 // address to store into and fall through to fast case. 771 // address to store into and fall through to fast case.
772 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // Compare smis. 772 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // Compare smis.
773 __ j(above_equal, &extra, not_taken); 773 __ j(above_equal, &extra, Label::kFar, not_taken);
774 774
775 // Fast case: Do the store. 775 // Fast case: Do the store.
776 __ bind(&fast); 776 __ bind(&fast);
777 // eax: value 777 // eax: value
778 // ecx: key (a smi) 778 // ecx: key (a smi)
779 // edx: receiver 779 // edx: receiver
780 // edi: FixedArray receiver->elements 780 // edi: FixedArray receiver->elements
781 __ mov(CodeGenerator::FixedArrayElementOperand(edi, ecx), eax); 781 __ mov(CodeGenerator::FixedArrayElementOperand(edi, ecx), eax);
782 // Update write barrier for the elements array address. 782 // Update write barrier for the elements array address.
783 __ mov(edx, Operand(eax)); 783 __ mov(edx, Operand(eax));
(...skipping 23 matching lines...) Expand all
807 Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, edx, ecx, ebx, 807 Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, edx, ecx, ebx,
808 eax); 808 eax);
809 809
810 // If the stub cache probing failed, the receiver might be a value. 810 // If the stub cache probing failed, the receiver might be a value.
811 // For value objects, we use the map of the prototype objects for 811 // For value objects, we use the map of the prototype objects for
812 // the corresponding JSValue for the cache and that is what we need 812 // the corresponding JSValue for the cache and that is what we need
813 // to probe. 813 // to probe.
814 // 814 //
815 // Check for number. 815 // Check for number.
816 __ test(edx, Immediate(kSmiTagMask)); 816 __ test(edx, Immediate(kSmiTagMask));
817 __ j(zero, &number, not_taken); 817 __ j(zero, &number, Label::kFar, not_taken);
818 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ebx); 818 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ebx);
819 __ j(not_equal, &non_number, taken); 819 __ j(not_equal, &non_number, Label::kFar, taken);
820 __ bind(&number); 820 __ bind(&number);
821 StubCompiler::GenerateLoadGlobalFunctionPrototype( 821 StubCompiler::GenerateLoadGlobalFunctionPrototype(
822 masm, Context::NUMBER_FUNCTION_INDEX, edx); 822 masm, Context::NUMBER_FUNCTION_INDEX, edx);
823 __ jmp(&probe); 823 __ jmp(&probe);
824 824
825 // Check for string. 825 // Check for string.
826 __ bind(&non_number); 826 __ bind(&non_number);
827 __ CmpInstanceType(ebx, FIRST_NONSTRING_TYPE); 827 __ CmpInstanceType(ebx, FIRST_NONSTRING_TYPE);
828 __ j(above_equal, &non_string, taken); 828 __ j(above_equal, &non_string, Label::kFar, taken);
829 StubCompiler::GenerateLoadGlobalFunctionPrototype( 829 StubCompiler::GenerateLoadGlobalFunctionPrototype(
830 masm, Context::STRING_FUNCTION_INDEX, edx); 830 masm, Context::STRING_FUNCTION_INDEX, edx);
831 __ jmp(&probe); 831 __ jmp(&probe);
832 832
833 // Check for boolean. 833 // Check for boolean.
834 __ bind(&non_string); 834 __ bind(&non_string);
835 __ cmp(edx, FACTORY->true_value()); 835 __ cmp(edx, FACTORY->true_value());
836 __ j(equal, &boolean, not_taken); 836 __ j(equal, &boolean, Label::kFar, not_taken);
837 __ cmp(edx, FACTORY->false_value()); 837 __ cmp(edx, FACTORY->false_value());
838 __ j(not_equal, &miss, taken); 838 __ j(not_equal, &miss, Label::kFar, taken);
839 __ bind(&boolean); 839 __ bind(&boolean);
840 StubCompiler::GenerateLoadGlobalFunctionPrototype( 840 StubCompiler::GenerateLoadGlobalFunctionPrototype(
841 masm, Context::BOOLEAN_FUNCTION_INDEX, edx); 841 masm, Context::BOOLEAN_FUNCTION_INDEX, edx);
842 842
843 // Probe the stub cache for the value object. 843 // Probe the stub cache for the value object.
844 __ bind(&probe); 844 __ bind(&probe);
845 Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, edx, ecx, ebx, 845 Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, edx, ecx, ebx,
846 no_reg); 846 no_reg);
847 __ bind(&miss); 847 __ bind(&miss);
848 } 848 }
849 849
850 850
851 static void GenerateFunctionTailCall(MacroAssembler* masm, 851 static void GenerateFunctionTailCall(MacroAssembler* masm,
852 int argc, 852 int argc,
853 Label* miss) { 853 Label* miss) {
854 // ----------- S t a t e ------------- 854 // ----------- S t a t e -------------
855 // -- ecx : name 855 // -- ecx : name
856 // -- edi : function 856 // -- edi : function
857 // -- esp[0] : return address 857 // -- esp[0] : return address
858 // -- esp[(argc - n) * 4] : arg[n] (zero-based) 858 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
859 // -- ... 859 // -- ...
860 // -- esp[(argc + 1) * 4] : receiver 860 // -- esp[(argc + 1) * 4] : receiver
861 // ----------------------------------- 861 // -----------------------------------
862 862
863 // Check that the result is not a smi. 863 // Check that the result is not a smi.
864 __ test(edi, Immediate(kSmiTagMask)); 864 __ test(edi, Immediate(kSmiTagMask));
865 __ j(zero, miss, not_taken); 865 __ j(zero, miss, Label::kFar, not_taken);
866 866
867 // Check that the value is a JavaScript function, fetching its map into eax. 867 // Check that the value is a JavaScript function, fetching its map into eax.
868 __ CmpObjectType(edi, JS_FUNCTION_TYPE, eax); 868 __ CmpObjectType(edi, JS_FUNCTION_TYPE, eax);
869 __ j(not_equal, miss, not_taken); 869 __ j(not_equal, miss, Label::kFar, not_taken);
870 870
871 // Invoke the function. 871 // Invoke the function.
872 ParameterCount actual(argc); 872 ParameterCount actual(argc);
873 __ InvokeFunction(edi, actual, JUMP_FUNCTION); 873 __ InvokeFunction(edi, actual, JUMP_FUNCTION);
874 } 874 }
875 875
876 // The generated code falls through if the call should be handled by runtime. 876 // The generated code falls through if the call should be handled by runtime.
877 static void GenerateCallNormal(MacroAssembler* masm, int argc) { 877 static void GenerateCallNormal(MacroAssembler* masm, int argc) {
878 // ----------- S t a t e ------------- 878 // ----------- S t a t e -------------
879 // -- ecx : name 879 // -- ecx : name
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
935 // Move result to edi and exit the internal frame. 935 // Move result to edi and exit the internal frame.
936 __ mov(edi, eax); 936 __ mov(edi, eax);
937 __ LeaveInternalFrame(); 937 __ LeaveInternalFrame();
938 938
939 // Check if the receiver is a global object of some sort. 939 // Check if the receiver is a global object of some sort.
940 // This can happen only for regular CallIC but not KeyedCallIC. 940 // This can happen only for regular CallIC but not KeyedCallIC.
941 if (id == IC::kCallIC_Miss) { 941 if (id == IC::kCallIC_Miss) {
942 Label invoke, global; 942 Label invoke, global;
943 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); // receiver 943 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); // receiver
944 __ test(edx, Immediate(kSmiTagMask)); 944 __ test(edx, Immediate(kSmiTagMask));
945 __ j(zero, &invoke, not_taken); 945 __ j(zero, &invoke, Label::kNear, not_taken);
946 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); 946 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
947 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); 947 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
948 __ cmp(ebx, JS_GLOBAL_OBJECT_TYPE); 948 __ cmp(ebx, JS_GLOBAL_OBJECT_TYPE);
949 __ j(equal, &global); 949 __ j(equal, &global, Label::kNear);
950 __ cmp(ebx, JS_BUILTINS_OBJECT_TYPE); 950 __ cmp(ebx, JS_BUILTINS_OBJECT_TYPE);
951 __ j(not_equal, &invoke); 951 __ j(not_equal, &invoke, Label::kNear);
952 952
953 // Patch the receiver on the stack. 953 // Patch the receiver on the stack.
954 __ bind(&global); 954 __ bind(&global);
955 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); 955 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
956 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); 956 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
957 __ bind(&invoke); 957 __ bind(&invoke);
958 } 958 }
959 959
960 // Invoke the function. 960 // Invoke the function.
961 ParameterCount actual(argc); 961 ParameterCount actual(argc);
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1017 1017
1018 // Get the receiver of the function from the stack; 1 ~ return address. 1018 // Get the receiver of the function from the stack; 1 ~ return address.
1019 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 1019 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1020 1020
1021 Label do_call, slow_call, slow_load, slow_reload_receiver; 1021 Label do_call, slow_call, slow_load, slow_reload_receiver;
1022 Label check_number_dictionary, check_string, lookup_monomorphic_cache; 1022 Label check_number_dictionary, check_string, lookup_monomorphic_cache;
1023 Label index_smi, index_string; 1023 Label index_smi, index_string;
1024 1024
1025 // Check that the key is a smi. 1025 // Check that the key is a smi.
1026 __ test(ecx, Immediate(kSmiTagMask)); 1026 __ test(ecx, Immediate(kSmiTagMask));
1027 __ j(not_zero, &check_string, not_taken); 1027 __ j(not_zero, &check_string, Label::kFar, not_taken);
1028 1028
1029 __ bind(&index_smi); 1029 __ bind(&index_smi);
1030 // Now the key is known to be a smi. This place is also jumped to from 1030 // Now the key is known to be a smi. This place is also jumped to from
1031 // where a numeric string is converted to a smi. 1031 // where a numeric string is converted to a smi.
1032 1032
1033 GenerateKeyedLoadReceiverCheck( 1033 GenerateKeyedLoadReceiverCheck(
1034 masm, edx, eax, Map::kHasIndexedInterceptor, &slow_call); 1034 masm, edx, eax, Map::kHasIndexedInterceptor, &slow_call);
1035 1035
1036 GenerateFastArrayLoad( 1036 GenerateFastArrayLoad(
1037 masm, edx, ecx, eax, edi, &check_number_dictionary, &slow_load); 1037 masm, edx, ecx, eax, edi, &check_number_dictionary, &slow_load);
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after
1307 // Value must be a number, but only smis are accepted as the most common case. 1307 // Value must be a number, but only smis are accepted as the most common case.
1308 1308
1309 Label miss; 1309 Label miss;
1310 1310
1311 Register receiver = edx; 1311 Register receiver = edx;
1312 Register value = eax; 1312 Register value = eax;
1313 Register scratch = ebx; 1313 Register scratch = ebx;
1314 1314
1315 // Check that the receiver isn't a smi. 1315 // Check that the receiver isn't a smi.
1316 __ test(receiver, Immediate(kSmiTagMask)); 1316 __ test(receiver, Immediate(kSmiTagMask));
1317 __ j(zero, &miss, not_taken); 1317 __ j(zero, &miss, Label::kFar, not_taken);
1318 1318
1319 // Check that the object is a JS array. 1319 // Check that the object is a JS array.
1320 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch); 1320 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch);
1321 __ j(not_equal, &miss, not_taken); 1321 __ j(not_equal, &miss, Label::kFar, not_taken);
1322 1322
1323 // Check that elements are FixedArray. 1323 // Check that elements are FixedArray.
1324 // We rely on StoreIC_ArrayLength below to deal with all types of 1324 // We rely on StoreIC_ArrayLength below to deal with all types of
1325 // fast elements (including COW). 1325 // fast elements (including COW).
1326 __ mov(scratch, FieldOperand(receiver, JSArray::kElementsOffset)); 1326 __ mov(scratch, FieldOperand(receiver, JSArray::kElementsOffset));
1327 __ CmpObjectType(scratch, FIXED_ARRAY_TYPE, scratch); 1327 __ CmpObjectType(scratch, FIXED_ARRAY_TYPE, scratch);
1328 __ j(not_equal, &miss, not_taken); 1328 __ j(not_equal, &miss, Label::kFar, not_taken);
1329 1329
1330 // Check that value is a smi. 1330 // Check that value is a smi.
1331 __ test(value, Immediate(kSmiTagMask)); 1331 __ test(value, Immediate(kSmiTagMask));
1332 __ j(not_zero, &miss, not_taken); 1332 __ j(not_zero, &miss, Label::kFar, not_taken);
1333 1333
1334 // Prepare tail call to StoreIC_ArrayLength. 1334 // Prepare tail call to StoreIC_ArrayLength.
1335 __ pop(scratch); 1335 __ pop(scratch);
1336 __ push(receiver); 1336 __ push(receiver);
1337 __ push(value); 1337 __ push(value);
1338 __ push(scratch); // return address 1338 __ push(scratch); // return address
1339 1339
1340 ExternalReference ref = 1340 ExternalReference ref =
1341 ExternalReference(IC_Utility(kStoreIC_ArrayLength), masm->isolate()); 1341 ExternalReference(IC_Utility(kStoreIC_ArrayLength), masm->isolate());
1342 __ TailCallExternalReference(ref, 2, 1); 1342 __ TailCallExternalReference(ref, 2, 1);
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
1538 Condition cc = *jmp_address == Assembler::kJncShortOpcode 1538 Condition cc = *jmp_address == Assembler::kJncShortOpcode
1539 ? not_zero 1539 ? not_zero
1540 : zero; 1540 : zero;
1541 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); 1541 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc);
1542 } 1542 }
1543 1543
1544 1544
1545 } } // namespace v8::internal 1545 } } // namespace v8::internal
1546 1546
1547 #endif // V8_TARGET_ARCH_IA32 1547 #endif // V8_TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698