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

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

Issue 7001025: Remove support for branch hints from the IA32 and X64 assembler. (Closed) Base URL: http://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
« no previous file with comments | « src/ia32/full-codegen-ia32.cc ('k') | src/ia32/lithium-codegen-ia32.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 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);
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);
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);
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);
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);
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);
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 // Helper function used to load a property from a dictionary backing 100 // Helper function used to load a property from a dictionary backing
101 // 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
102 // 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
103 // 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
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
139 // If probing finds an entry in the dictionary, r0 contains the 139 // If probing finds an entry in the dictionary, r0 contains the
140 // index into the dictionary. Check that the value is a normal 140 // index into the dictionary. Check that the value is a normal
141 // property. 141 // property.
142 __ bind(&done); 142 __ bind(&done);
143 const int kElementsStartOffset = 143 const int kElementsStartOffset =
144 StringDictionary::kHeaderSize + 144 StringDictionary::kHeaderSize +
145 StringDictionary::kElementsStartIndex * kPointerSize; 145 StringDictionary::kElementsStartIndex * kPointerSize;
146 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; 146 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
147 __ test(Operand(elements, r0, times_4, kDetailsOffset - kHeapObjectTag), 147 __ test(Operand(elements, r0, times_4, kDetailsOffset - kHeapObjectTag),
148 Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize)); 148 Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize));
149 __ j(not_zero, miss_label, not_taken); 149 __ j(not_zero, miss_label);
150 150
151 // Get the value at the masked, scaled index. 151 // Get the value at the masked, scaled index.
152 const int kValueOffset = kElementsStartOffset + kPointerSize; 152 const int kValueOffset = kElementsStartOffset + kPointerSize;
153 __ mov(result, Operand(elements, r0, times_4, kValueOffset - kHeapObjectTag)); 153 __ mov(result, Operand(elements, r0, times_4, kValueOffset - kHeapObjectTag));
154 } 154 }
155 155
156 156
157 // Helper function used to store a property to a dictionary backing 157 // Helper function used to store a property to a dictionary backing
158 // storage. This function may fail to store a property eventhough it 158 // storage. This function may fail to store a property eventhough it
159 // 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
197 __ bind(&done); 197 __ bind(&done);
198 const int kElementsStartOffset = 198 const int kElementsStartOffset =
199 StringDictionary::kHeaderSize + 199 StringDictionary::kHeaderSize +
200 StringDictionary::kElementsStartIndex * kPointerSize; 200 StringDictionary::kElementsStartIndex * kPointerSize;
201 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; 201 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
202 const int kTypeAndReadOnlyMask 202 const int kTypeAndReadOnlyMask
203 = (PropertyDetails::TypeField::mask() | 203 = (PropertyDetails::TypeField::mask() |
204 PropertyDetails::AttributesField::encode(READ_ONLY)) << kSmiTagSize; 204 PropertyDetails::AttributesField::encode(READ_ONLY)) << kSmiTagSize;
205 __ test(Operand(elements, r0, times_4, kDetailsOffset - kHeapObjectTag), 205 __ test(Operand(elements, r0, times_4, kDetailsOffset - kHeapObjectTag),
206 Immediate(kTypeAndReadOnlyMask)); 206 Immediate(kTypeAndReadOnlyMask));
207 __ j(not_zero, miss_label, not_taken); 207 __ j(not_zero, miss_label);
208 208
209 // Store the value at the masked, scaled index. 209 // Store the value at the masked, scaled index.
210 const int kValueOffset = kElementsStartOffset + kPointerSize; 210 const int kValueOffset = kElementsStartOffset + kPointerSize;
211 __ lea(r0, Operand(elements, r0, times_4, kValueOffset - kHeapObjectTag)); 211 __ lea(r0, Operand(elements, r0, times_4, kValueOffset - kHeapObjectTag));
212 __ mov(Operand(r0, 0), value); 212 __ mov(Operand(r0, 0), value);
213 213
214 // Update write barrier. Make sure not to clobber the value. 214 // Update write barrier. Make sure not to clobber the value.
215 __ mov(r1, value); 215 __ mov(r1, value);
216 __ RecordWrite(elements, r0, r1); 216 __ RecordWrite(elements, r0, r1);
217 } 217 }
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 // Scale the index by multiplying by the entry size. 287 // Scale the index by multiplying by the entry size.
288 ASSERT(NumberDictionary::kEntrySize == 3); 288 ASSERT(NumberDictionary::kEntrySize == 3);
289 __ lea(r2, Operand(r2, r2, times_2, 0)); // r2 = r2 * 3 289 __ lea(r2, Operand(r2, r2, times_2, 0)); // r2 = r2 * 3
290 290
291 // Check if the key matches. 291 // Check if the key matches.
292 __ cmp(key, FieldOperand(elements, 292 __ cmp(key, FieldOperand(elements,
293 r2, 293 r2,
294 times_pointer_size, 294 times_pointer_size,
295 NumberDictionary::kElementsStartOffset)); 295 NumberDictionary::kElementsStartOffset));
296 if (i != (kProbes - 1)) { 296 if (i != (kProbes - 1)) {
297 __ j(equal, &done, taken); 297 __ j(equal, &done);
298 } else { 298 } else {
299 __ j(not_equal, miss, not_taken); 299 __ j(not_equal, miss);
300 } 300 }
301 } 301 }
302 302
303 __ bind(&done); 303 __ bind(&done);
304 // Check that the value is a normal propety. 304 // Check that the value is a normal propety.
305 const int kDetailsOffset = 305 const int kDetailsOffset =
306 NumberDictionary::kElementsStartOffset + 2 * kPointerSize; 306 NumberDictionary::kElementsStartOffset + 2 * kPointerSize;
307 ASSERT_EQ(NORMAL, 0); 307 ASSERT_EQ(NORMAL, 0);
308 __ test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset), 308 __ test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset),
309 Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize)); 309 Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize));
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
367 Register map, 367 Register map,
368 int interceptor_bit, 368 int interceptor_bit,
369 Label* slow) { 369 Label* slow) {
370 // Register use: 370 // Register use:
371 // receiver - holds the receiver and is unchanged. 371 // receiver - holds the receiver and is unchanged.
372 // Scratch registers: 372 // Scratch registers:
373 // map - used to hold the map of the receiver. 373 // map - used to hold the map of the receiver.
374 374
375 // Check that the object isn't a smi. 375 // Check that the object isn't a smi.
376 __ test(receiver, Immediate(kSmiTagMask)); 376 __ test(receiver, Immediate(kSmiTagMask));
377 __ j(zero, slow, not_taken); 377 __ j(zero, slow);
378 378
379 // Get the map of the receiver. 379 // Get the map of the receiver.
380 __ mov(map, FieldOperand(receiver, HeapObject::kMapOffset)); 380 __ mov(map, FieldOperand(receiver, HeapObject::kMapOffset));
381 381
382 // Check bit field. 382 // Check bit field.
383 __ test_b(FieldOperand(map, Map::kBitFieldOffset), 383 __ test_b(FieldOperand(map, Map::kBitFieldOffset),
384 (1 << Map::kIsAccessCheckNeeded) | (1 << interceptor_bit)); 384 (1 << Map::kIsAccessCheckNeeded) | (1 << interceptor_bit));
385 __ j(not_zero, slow, not_taken); 385 __ j(not_zero, slow);
386 // 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.
387 // In the case that the object is a value-wrapper object, 387 // In the case that the object is a value-wrapper object,
388 // we enter the runtime system to make sure that indexing 388 // we enter the runtime system to make sure that indexing
389 // into string objects works as intended. 389 // into string objects works as intended.
390 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE); 390 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE);
391 391
392 __ CmpInstanceType(map, JS_OBJECT_TYPE); 392 __ CmpInstanceType(map, JS_OBJECT_TYPE);
393 __ j(below, slow, not_taken); 393 __ j(below, slow);
394 } 394 }
395 395
396 396
397 // Loads an indexed element from a fast case array. 397 // Loads an indexed element from a fast case array.
398 // 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.
399 static void GenerateFastArrayLoad(MacroAssembler* masm, 399 static void GenerateFastArrayLoad(MacroAssembler* masm,
400 Register receiver, 400 Register receiver,
401 Register key, 401 Register key,
402 Register scratch, 402 Register scratch,
403 Register result, 403 Register result,
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
446 // 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.
447 // Scratch registers: 447 // Scratch registers:
448 // map - used to hold the map of the key. 448 // map - used to hold the map of the key.
449 // hash - used to hold the hash of the key. 449 // hash - used to hold the hash of the key.
450 __ CmpObjectType(key, FIRST_NONSTRING_TYPE, map); 450 __ CmpObjectType(key, FIRST_NONSTRING_TYPE, map);
451 __ j(above_equal, not_symbol); 451 __ j(above_equal, not_symbol);
452 452
453 // Is the string an array index, with cached numeric value? 453 // Is the string an array index, with cached numeric value?
454 __ mov(hash, FieldOperand(key, String::kHashFieldOffset)); 454 __ mov(hash, FieldOperand(key, String::kHashFieldOffset));
455 __ test(hash, Immediate(String::kContainsCachedArrayIndexMask)); 455 __ test(hash, Immediate(String::kContainsCachedArrayIndexMask));
456 __ j(zero, index_string, not_taken); 456 __ j(zero, index_string);
457 457
458 // Is the string a symbol? 458 // Is the string a symbol?
459 ASSERT(kSymbolTag != 0); 459 ASSERT(kSymbolTag != 0);
460 __ test_b(FieldOperand(map, Map::kInstanceTypeOffset), kIsSymbolMask); 460 __ test_b(FieldOperand(map, Map::kInstanceTypeOffset), kIsSymbolMask);
461 __ j(zero, not_symbol, not_taken); 461 __ j(zero, not_symbol);
462 } 462 }
463 463
464 464
465 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { 465 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
466 // ----------- S t a t e ------------- 466 // ----------- S t a t e -------------
467 // -- eax : key 467 // -- eax : key
468 // -- edx : receiver 468 // -- edx : receiver
469 // -- esp[0] : return address 469 // -- esp[0] : return address
470 // ----------------------------------- 470 // -----------------------------------
471 Label slow, check_string, index_smi, index_string, property_array_property; 471 Label slow, check_string, index_smi, index_string, property_array_property;
472 Label probe_dictionary, check_number_dictionary; 472 Label probe_dictionary, check_number_dictionary;
473 473
474 // Check that the key is a smi. 474 // Check that the key is a smi.
475 __ test(eax, Immediate(kSmiTagMask)); 475 __ test(eax, Immediate(kSmiTagMask));
476 __ j(not_zero, &check_string, not_taken); 476 __ j(not_zero, &check_string);
477 __ bind(&index_smi); 477 __ bind(&index_smi);
478 // 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
479 // where a numeric string is converted to a smi. 479 // where a numeric string is converted to a smi.
480 480
481 GenerateKeyedLoadReceiverCheck( 481 GenerateKeyedLoadReceiverCheck(
482 masm, edx, ecx, Map::kHasIndexedInterceptor, &slow); 482 masm, edx, ecx, Map::kHasIndexedInterceptor, &slow);
483 483
484 // 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
485 // now in ecx. 485 // now in ecx.
486 __ test_b(FieldOperand(ecx, Map::kBitField2Offset), 486 __ test_b(FieldOperand(ecx, Map::kBitField2Offset),
487 1 << Map::kHasFastElements); 487 1 << Map::kHasFastElements);
488 __ j(zero, &check_number_dictionary, not_taken); 488 __ j(zero, &check_number_dictionary);
489 489
490 GenerateFastArrayLoad(masm, 490 GenerateFastArrayLoad(masm,
491 edx, 491 edx,
492 eax, 492 eax,
493 ecx, 493 ecx,
494 eax, 494 eax,
495 NULL, 495 NULL,
496 &slow); 496 &slow);
497 Isolate* isolate = masm->isolate(); 497 Isolate* isolate = masm->isolate();
498 Counters* counters = isolate->counters(); 498 Counters* counters = isolate->counters();
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
656 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { 656 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
657 // ----------- S t a t e ------------- 657 // ----------- S t a t e -------------
658 // -- eax : key 658 // -- eax : key
659 // -- edx : receiver 659 // -- edx : receiver
660 // -- esp[0] : return address 660 // -- esp[0] : return address
661 // ----------------------------------- 661 // -----------------------------------
662 Label slow; 662 Label slow;
663 663
664 // Check that the receiver isn't a smi. 664 // Check that the receiver isn't a smi.
665 __ test(edx, Immediate(kSmiTagMask)); 665 __ test(edx, Immediate(kSmiTagMask));
666 __ j(zero, &slow, not_taken); 666 __ j(zero, &slow);
667 667
668 // Check that the key is an array index, that is Uint32. 668 // Check that the key is an array index, that is Uint32.
669 __ test(eax, Immediate(kSmiTagMask | kSmiSignMask)); 669 __ test(eax, Immediate(kSmiTagMask | kSmiSignMask));
670 __ j(not_zero, &slow, not_taken); 670 __ j(not_zero, &slow);
671 671
672 // Get the map of the receiver. 672 // Get the map of the receiver.
673 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 673 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
674 674
675 // Check that it has indexed interceptor and access checks 675 // Check that it has indexed interceptor and access checks
676 // are not enabled for this object. 676 // are not enabled for this object.
677 __ movzx_b(ecx, FieldOperand(ecx, Map::kBitFieldOffset)); 677 __ movzx_b(ecx, FieldOperand(ecx, Map::kBitFieldOffset));
678 __ and_(Operand(ecx), Immediate(kSlowCaseBitFieldMask)); 678 __ and_(Operand(ecx), Immediate(kSlowCaseBitFieldMask));
679 __ cmp(Operand(ecx), Immediate(1 << Map::kHasIndexedInterceptor)); 679 __ cmp(Operand(ecx), Immediate(1 << Map::kHasIndexedInterceptor));
680 __ j(not_zero, &slow, not_taken); 680 __ j(not_zero, &slow);
681 681
682 // Everything is fine, call runtime. 682 // Everything is fine, call runtime.
683 __ pop(ecx); 683 __ pop(ecx);
684 __ push(edx); // receiver 684 __ push(edx); // receiver
685 __ push(eax); // key 685 __ push(eax); // key
686 __ push(ecx); // return address 686 __ push(ecx); // return address
687 687
688 // Perform tail call to the entry. 688 // Perform tail call to the entry.
689 ExternalReference ref = 689 ExternalReference ref =
690 ExternalReference(IC_Utility(kKeyedLoadPropertyWithInterceptor), 690 ExternalReference(IC_Utility(kKeyedLoadPropertyWithInterceptor),
(...skipping 10 matching lines...) Expand all
701 // ----------- S t a t e ------------- 701 // ----------- S t a t e -------------
702 // -- eax : value 702 // -- eax : value
703 // -- ecx : key 703 // -- ecx : key
704 // -- edx : receiver 704 // -- edx : receiver
705 // -- esp[0] : return address 705 // -- esp[0] : return address
706 // ----------------------------------- 706 // -----------------------------------
707 Label slow, fast, array, extra; 707 Label slow, fast, array, extra;
708 708
709 // Check that the object isn't a smi. 709 // Check that the object isn't a smi.
710 __ test(edx, Immediate(kSmiTagMask)); 710 __ test(edx, Immediate(kSmiTagMask));
711 __ j(zero, &slow, not_taken); 711 __ j(zero, &slow);
712 // Get the map from the receiver. 712 // Get the map from the receiver.
713 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); 713 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
714 // Check that the receiver does not require access checks. We need 714 // Check that the receiver does not require access checks. We need
715 // 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.
716 __ test_b(FieldOperand(edi, Map::kBitFieldOffset), 716 __ test_b(FieldOperand(edi, Map::kBitFieldOffset),
717 1 << Map::kIsAccessCheckNeeded); 717 1 << Map::kIsAccessCheckNeeded);
718 __ j(not_zero, &slow, not_taken); 718 __ j(not_zero, &slow);
719 // Check that the key is a smi. 719 // Check that the key is a smi.
720 __ test(ecx, Immediate(kSmiTagMask)); 720 __ test(ecx, Immediate(kSmiTagMask));
721 __ j(not_zero, &slow, not_taken); 721 __ j(not_zero, &slow);
722 __ CmpInstanceType(edi, JS_ARRAY_TYPE); 722 __ CmpInstanceType(edi, JS_ARRAY_TYPE);
723 __ j(equal, &array); 723 __ j(equal, &array);
724 // Check that the object is some kind of JS object. 724 // Check that the object is some kind of JS object.
725 __ CmpInstanceType(edi, FIRST_JS_OBJECT_TYPE); 725 __ CmpInstanceType(edi, FIRST_JS_OBJECT_TYPE);
726 __ j(below, &slow, not_taken); 726 __ j(below, &slow);
727 727
728 // Object case: Check key against length in the elements array. 728 // Object case: Check key against length in the elements array.
729 // eax: value 729 // eax: value
730 // edx: JSObject 730 // edx: JSObject
731 // ecx: key (a smi) 731 // ecx: key (a smi)
732 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); 732 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
733 // Check that the object is in fast mode and writable. 733 // Check that the object is in fast mode and writable.
734 __ CheckMap(edi, FACTORY->fixed_array_map(), &slow, true); 734 __ CheckMap(edi, FACTORY->fixed_array_map(), &slow, true);
735 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); 735 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset));
736 __ j(below, &fast, taken); 736 __ j(below, &fast);
737 737
738 // Slow case: call runtime. 738 // Slow case: call runtime.
739 __ bind(&slow); 739 __ bind(&slow);
740 GenerateRuntimeSetProperty(masm, strict_mode); 740 GenerateRuntimeSetProperty(masm, strict_mode);
741 741
742 // Extra capacity case: Check if there is extra capacity to 742 // Extra capacity case: Check if there is extra capacity to
743 // perform the store and update the length. Used for adding one 743 // perform the store and update the length. Used for adding one
744 // element to the array by writing to array[array.length]. 744 // element to the array by writing to array[array.length].
745 __ bind(&extra); 745 __ bind(&extra);
746 // eax: value 746 // eax: value
747 // edx: receiver, a JSArray 747 // edx: receiver, a JSArray
748 // ecx: key, a smi. 748 // ecx: key, a smi.
749 // edi: receiver->elements, a FixedArray 749 // edi: receiver->elements, a FixedArray
750 // flags: compare (ecx, edx.length()) 750 // flags: compare (ecx, edx.length())
751 // do not leave holes in the array: 751 // do not leave holes in the array:
752 __ j(not_equal, &slow, not_taken); 752 __ j(not_equal, &slow);
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);
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);
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);
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);
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);
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);
837 __ cmp(edx, FACTORY->false_value()); 837 __ cmp(edx, FACTORY->false_value());
838 __ j(not_equal, &miss, taken); 838 __ j(not_equal, &miss);
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);
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);
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, Label::kNear); 945 __ j(zero, &invoke, Label::kNear);
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, Label::kNear); 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, Label::kNear); 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));
(...skipping 61 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);
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);
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);
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);
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);
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
« no previous file with comments | « src/ia32/full-codegen-ia32.cc ('k') | src/ia32/lithium-codegen-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698