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

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

Issue 7060010: Merge bleeding edge into the GC branch up to 7948. The asserts (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
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.h » ('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, DONT_DO_SMI_CHECK);
97 } 97 }
98 98
99 99
100 // Probe the string dictionary in the |elements| register. Jump to the
101 // |done| label if a property with the given name is found leaving the
102 // index into the dictionary in |r0|. Jump to the |miss| label
103 // otherwise.
104 static void GenerateStringDictionaryProbes(MacroAssembler* masm,
105 Label* miss,
106 Label* done,
107 Register elements,
108 Register name,
109 Register r0,
110 Register r1) {
111 // Assert that name contains a string.
112 if (FLAG_debug_code) __ AbortIfNotString(name);
113
114 // Compute the capacity mask.
115 const int kCapacityOffset =
116 StringDictionary::kHeaderSize +
117 StringDictionary::kCapacityIndex * kPointerSize;
118 __ mov(r1, FieldOperand(elements, kCapacityOffset));
119 __ shr(r1, kSmiTagSize); // convert smi to int
120 __ dec(r1);
121
122 // Generate an unrolled loop that performs a few probes before
123 // giving up. Measurements done on Gmail indicate that 2 probes
124 // cover ~93% of loads from dictionaries.
125 static const int kProbes = 4;
126 const int kElementsStartOffset =
127 StringDictionary::kHeaderSize +
128 StringDictionary::kElementsStartIndex * kPointerSize;
129 for (int i = 0; i < kProbes; i++) {
130 // Compute the masked index: (hash + i + i * i) & mask.
131 __ mov(r0, FieldOperand(name, String::kHashFieldOffset));
132 __ shr(r0, String::kHashShift);
133 if (i > 0) {
134 __ add(Operand(r0), Immediate(StringDictionary::GetProbeOffset(i)));
135 }
136 __ and_(r0, Operand(r1));
137
138 // Scale the index by multiplying by the entry size.
139 ASSERT(StringDictionary::kEntrySize == 3);
140 __ lea(r0, Operand(r0, r0, times_2, 0)); // r0 = r0 * 3
141
142 // Check if the key is identical to the name.
143 __ cmp(name, Operand(elements, r0, times_4,
144 kElementsStartOffset - kHeapObjectTag));
145 if (i != kProbes - 1) {
146 __ j(equal, done, taken);
147 } else {
148 __ j(not_equal, miss, not_taken);
149 }
150 }
151 }
152
153
154
155 // Helper function used to load a property from a dictionary backing 100 // Helper function used to load a property from a dictionary backing
156 // 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
157 // 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
158 // 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
159 // 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
160 // case. The generated code assumes that the receiver has slow 105 // case. The generated code assumes that the receiver has slow
161 // properties, is not a global object and does not have interceptors. 106 // properties, is not a global object and does not have interceptors.
162 static void GenerateDictionaryLoad(MacroAssembler* masm, 107 static void GenerateDictionaryLoad(MacroAssembler* masm,
163 Label* miss_label, 108 Label* miss_label,
164 Register elements, 109 Register elements,
(...skipping 11 matching lines...) Expand all
176 // 121 //
177 // r0 - used for the index into the property dictionary 122 // r0 - used for the index into the property dictionary
178 // 123 //
179 // r1 - used to hold the capacity of the property dictionary. 124 // r1 - used to hold the capacity of the property dictionary.
180 // 125 //
181 // result - holds the result on exit. 126 // result - holds the result on exit.
182 127
183 Label done; 128 Label done;
184 129
185 // Probe the dictionary. 130 // Probe the dictionary.
186 GenerateStringDictionaryProbes(masm, 131 StringDictionaryLookupStub::GeneratePositiveLookup(masm,
187 miss_label, 132 miss_label,
188 &done, 133 &done,
189 elements, 134 elements,
190 name, 135 name,
191 r0, 136 r0,
192 r1); 137 r1);
193 138
194 // If probing finds an entry in the dictionary, r0 contains the 139 // If probing finds an entry in the dictionary, r0 contains the
195 // index into the dictionary. Check that the value is a normal 140 // index into the dictionary. Check that the value is a normal
196 // property. 141 // property.
197 __ bind(&done); 142 __ bind(&done);
198 const int kElementsStartOffset = 143 const int kElementsStartOffset =
199 StringDictionary::kHeaderSize + 144 StringDictionary::kHeaderSize +
200 StringDictionary::kElementsStartIndex * kPointerSize; 145 StringDictionary::kElementsStartIndex * kPointerSize;
201 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; 146 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
202 __ test(Operand(elements, r0, times_4, kDetailsOffset - kHeapObjectTag), 147 __ test(Operand(elements, r0, times_4, kDetailsOffset - kHeapObjectTag),
203 Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize)); 148 Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize));
204 __ j(not_zero, miss_label, not_taken); 149 __ j(not_zero, miss_label);
205 150
206 // Get the value at the masked, scaled index. 151 // Get the value at the masked, scaled index.
207 const int kValueOffset = kElementsStartOffset + kPointerSize; 152 const int kValueOffset = kElementsStartOffset + kPointerSize;
208 __ mov(result, Operand(elements, r0, times_4, kValueOffset - kHeapObjectTag)); 153 __ mov(result, Operand(elements, r0, times_4, kValueOffset - kHeapObjectTag));
209 } 154 }
210 155
211 156
212 // Helper function used to store a property to a dictionary backing 157 // Helper function used to store a property to a dictionary backing
213 // storage. This function may fail to store a property eventhough it 158 // storage. This function may fail to store a property eventhough it
214 // 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 16 matching lines...) Expand all
231 // 176 //
232 // value - holds the value to store and is unchanged. 177 // value - holds the value to store and is unchanged.
233 // 178 //
234 // r0 - used for index into the property dictionary and is clobbered. 179 // r0 - used for index into the property dictionary and is clobbered.
235 // 180 //
236 // r1 - used to hold the capacity of the property dictionary and is clobbered. 181 // r1 - used to hold the capacity of the property dictionary and is clobbered.
237 Label done; 182 Label done;
238 183
239 184
240 // Probe the dictionary. 185 // Probe the dictionary.
241 GenerateStringDictionaryProbes(masm, 186 StringDictionaryLookupStub::GeneratePositiveLookup(masm,
242 miss_label, 187 miss_label,
243 &done, 188 &done,
244 elements, 189 elements,
245 name, 190 name,
246 r0, 191 r0,
247 r1); 192 r1);
248 193
249 // If probing finds an entry in the dictionary, r0 contains the 194 // If probing finds an entry in the dictionary, r0 contains the
250 // index into the dictionary. Check that the value is a normal 195 // index into the dictionary. Check that the value is a normal
251 // property that is not read only. 196 // property that is not read only.
252 __ bind(&done); 197 __ bind(&done);
253 const int kElementsStartOffset = 198 const int kElementsStartOffset =
254 StringDictionary::kHeaderSize + 199 StringDictionary::kHeaderSize +
255 StringDictionary::kElementsStartIndex * kPointerSize; 200 StringDictionary::kElementsStartIndex * kPointerSize;
256 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; 201 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
257 const int kTypeAndReadOnlyMask 202 const int kTypeAndReadOnlyMask
258 = (PropertyDetails::TypeField::mask() | 203 = (PropertyDetails::TypeField::mask() |
259 PropertyDetails::AttributesField::encode(READ_ONLY)) << kSmiTagSize; 204 PropertyDetails::AttributesField::encode(READ_ONLY)) << kSmiTagSize;
260 __ test(Operand(elements, r0, times_4, kDetailsOffset - kHeapObjectTag), 205 __ test(Operand(elements, r0, times_4, kDetailsOffset - kHeapObjectTag),
261 Immediate(kTypeAndReadOnlyMask)); 206 Immediate(kTypeAndReadOnlyMask));
262 __ j(not_zero, miss_label, not_taken); 207 __ j(not_zero, miss_label);
263 208
264 // Store the value at the masked, scaled index. 209 // Store the value at the masked, scaled index.
265 const int kValueOffset = kElementsStartOffset + kPointerSize; 210 const int kValueOffset = kElementsStartOffset + kPointerSize;
266 __ lea(r0, Operand(elements, r0, times_4, kValueOffset - kHeapObjectTag)); 211 __ lea(r0, Operand(elements, r0, times_4, kValueOffset - kHeapObjectTag));
267 __ mov(Operand(r0, 0), value); 212 __ mov(Operand(r0, 0), value);
268 213
269 // Update write barrier. Make sure not to clobber the value. 214 // Update write barrier. Make sure not to clobber the value.
270 __ mov(r1, value); 215 __ mov(r1, value);
271 __ RecordWrite(elements, r0, r1, kDontSaveFPRegs); 216 __ RecordWrite(elements, r0, r1, kDontSaveFPRegs);
272 } 217 }
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
342 // Scale the index by multiplying by the entry size. 287 // Scale the index by multiplying by the entry size.
343 ASSERT(NumberDictionary::kEntrySize == 3); 288 ASSERT(NumberDictionary::kEntrySize == 3);
344 __ lea(r2, Operand(r2, r2, times_2, 0)); // r2 = r2 * 3 289 __ lea(r2, Operand(r2, r2, times_2, 0)); // r2 = r2 * 3
345 290
346 // Check if the key matches. 291 // Check if the key matches.
347 __ cmp(key, FieldOperand(elements, 292 __ cmp(key, FieldOperand(elements,
348 r2, 293 r2,
349 times_pointer_size, 294 times_pointer_size,
350 NumberDictionary::kElementsStartOffset)); 295 NumberDictionary::kElementsStartOffset));
351 if (i != (kProbes - 1)) { 296 if (i != (kProbes - 1)) {
352 __ j(equal, &done, taken); 297 __ j(equal, &done);
353 } else { 298 } else {
354 __ j(not_equal, miss, not_taken); 299 __ j(not_equal, miss);
355 } 300 }
356 } 301 }
357 302
358 __ bind(&done); 303 __ bind(&done);
359 // Check that the value is a normal propety. 304 // Check that the value is a normal propety.
360 const int kDetailsOffset = 305 const int kDetailsOffset =
361 NumberDictionary::kElementsStartOffset + 2 * kPointerSize; 306 NumberDictionary::kElementsStartOffset + 2 * kPointerSize;
362 ASSERT_EQ(NORMAL, 0); 307 ASSERT_EQ(NORMAL, 0);
363 __ test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset), 308 __ test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset),
364 Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize)); 309 Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize));
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
422 Register map, 367 Register map,
423 int interceptor_bit, 368 int interceptor_bit,
424 Label* slow) { 369 Label* slow) {
425 // Register use: 370 // Register use:
426 // receiver - holds the receiver and is unchanged. 371 // receiver - holds the receiver and is unchanged.
427 // Scratch registers: 372 // Scratch registers:
428 // map - used to hold the map of the receiver. 373 // map - used to hold the map of the receiver.
429 374
430 // Check that the object isn't a smi. 375 // Check that the object isn't a smi.
431 __ test(receiver, Immediate(kSmiTagMask)); 376 __ test(receiver, Immediate(kSmiTagMask));
432 __ j(zero, slow, not_taken); 377 __ j(zero, slow);
433 378
434 // Get the map of the receiver. 379 // Get the map of the receiver.
435 __ mov(map, FieldOperand(receiver, HeapObject::kMapOffset)); 380 __ mov(map, FieldOperand(receiver, HeapObject::kMapOffset));
436 381
437 // Check bit field. 382 // Check bit field.
438 __ test_b(FieldOperand(map, Map::kBitFieldOffset), 383 __ test_b(FieldOperand(map, Map::kBitFieldOffset),
439 (1 << Map::kIsAccessCheckNeeded) | (1 << interceptor_bit)); 384 (1 << Map::kIsAccessCheckNeeded) | (1 << interceptor_bit));
440 __ j(not_zero, slow, not_taken); 385 __ j(not_zero, slow);
441 // 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.
442 // In the case that the object is a value-wrapper object, 387 // In the case that the object is a value-wrapper object,
443 // we enter the runtime system to make sure that indexing 388 // we enter the runtime system to make sure that indexing
444 // into string objects works as intended. 389 // into string objects works as intended.
445 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE); 390 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE);
446 391
447 __ CmpInstanceType(map, JS_OBJECT_TYPE); 392 __ CmpInstanceType(map, JS_OBJECT_TYPE);
448 __ j(below, slow, not_taken); 393 __ j(below, slow);
449 } 394 }
450 395
451 396
452 // Loads an indexed element from a fast case array. 397 // Loads an indexed element from a fast case array.
453 // 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.
454 static void GenerateFastArrayLoad(MacroAssembler* masm, 399 static void GenerateFastArrayLoad(MacroAssembler* masm,
455 Register receiver, 400 Register receiver,
456 Register key, 401 Register key,
457 Register scratch, 402 Register scratch,
458 Register result, 403 Register result,
459 Label* not_fast_array, 404 Label* not_fast_array,
460 Label* out_of_range) { 405 Label* out_of_range) {
461 // Register use: 406 // Register use:
462 // receiver - holds the receiver and is unchanged. 407 // receiver - holds the receiver and is unchanged.
463 // key - holds the key and is unchanged (must be a smi). 408 // key - holds the key and is unchanged (must be a smi).
464 // Scratch registers: 409 // Scratch registers:
465 // scratch - used to hold elements of the receiver and the loaded value. 410 // scratch - used to hold elements of the receiver and the loaded value.
466 // result - holds the result on exit if the load succeeds and 411 // result - holds the result on exit if the load succeeds and
467 // we fall through. 412 // we fall through.
468 413
469 __ mov(scratch, FieldOperand(receiver, JSObject::kElementsOffset)); 414 __ mov(scratch, FieldOperand(receiver, JSObject::kElementsOffset));
470 if (not_fast_array != NULL) { 415 if (not_fast_array != NULL) {
471 // Check that the object is in fast mode and writable. 416 // Check that the object is in fast mode and writable.
472 __ CheckMap(scratch, FACTORY->fixed_array_map(), not_fast_array, true); 417 __ CheckMap(scratch,
418 FACTORY->fixed_array_map(),
419 not_fast_array,
420 DONT_DO_SMI_CHECK);
473 } else { 421 } else {
474 __ AssertFastElements(scratch); 422 __ AssertFastElements(scratch);
475 } 423 }
476 // Check that the key (index) is within bounds. 424 // Check that the key (index) is within bounds.
477 __ cmp(key, FieldOperand(scratch, FixedArray::kLengthOffset)); 425 __ cmp(key, FieldOperand(scratch, FixedArray::kLengthOffset));
478 __ j(above_equal, out_of_range); 426 __ j(above_equal, out_of_range);
479 // Fast case: Do the load. 427 // Fast case: Do the load.
480 ASSERT((kPointerSize == 4) && (kSmiTagSize == 1) && (kSmiTag == 0)); 428 ASSERT((kPointerSize == 4) && (kSmiTagSize == 1) && (kSmiTag == 0));
481 __ mov(scratch, FieldOperand(scratch, key, times_2, FixedArray::kHeaderSize)); 429 __ mov(scratch, FieldOperand(scratch, key, times_2, FixedArray::kHeaderSize));
482 __ cmp(Operand(scratch), Immediate(FACTORY->the_hole_value())); 430 __ cmp(Operand(scratch), Immediate(FACTORY->the_hole_value()));
(...skipping 18 matching lines...) Expand all
501 // key - holds the key and is unchanged. Assumed to be non-smi. 449 // key - holds the key and is unchanged. Assumed to be non-smi.
502 // Scratch registers: 450 // Scratch registers:
503 // map - used to hold the map of the key. 451 // map - used to hold the map of the key.
504 // hash - used to hold the hash of the key. 452 // hash - used to hold the hash of the key.
505 __ CmpObjectType(key, FIRST_NONSTRING_TYPE, map); 453 __ CmpObjectType(key, FIRST_NONSTRING_TYPE, map);
506 __ j(above_equal, not_symbol); 454 __ j(above_equal, not_symbol);
507 455
508 // Is the string an array index, with cached numeric value? 456 // Is the string an array index, with cached numeric value?
509 __ mov(hash, FieldOperand(key, String::kHashFieldOffset)); 457 __ mov(hash, FieldOperand(key, String::kHashFieldOffset));
510 __ test(hash, Immediate(String::kContainsCachedArrayIndexMask)); 458 __ test(hash, Immediate(String::kContainsCachedArrayIndexMask));
511 __ j(zero, index_string, not_taken); 459 __ j(zero, index_string);
512 460
513 // Is the string a symbol? 461 // Is the string a symbol?
514 ASSERT(kSymbolTag != 0); 462 ASSERT(kSymbolTag != 0);
515 __ test_b(FieldOperand(map, Map::kInstanceTypeOffset), kIsSymbolMask); 463 __ test_b(FieldOperand(map, Map::kInstanceTypeOffset), kIsSymbolMask);
516 __ j(zero, not_symbol, not_taken); 464 __ j(zero, not_symbol);
517 } 465 }
518 466
519 467
520 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { 468 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
521 // ----------- S t a t e ------------- 469 // ----------- S t a t e -------------
522 // -- eax : key 470 // -- eax : key
523 // -- edx : receiver 471 // -- edx : receiver
524 // -- esp[0] : return address 472 // -- esp[0] : return address
525 // ----------------------------------- 473 // -----------------------------------
526 Label slow, check_string, index_smi, index_string, property_array_property; 474 Label slow, check_string, index_smi, index_string, property_array_property;
527 Label probe_dictionary, check_number_dictionary; 475 Label probe_dictionary, check_number_dictionary;
528 476
529 // Check that the key is a smi. 477 // Check that the key is a smi.
530 __ test(eax, Immediate(kSmiTagMask)); 478 __ test(eax, Immediate(kSmiTagMask));
531 __ j(not_zero, &check_string, not_taken); 479 __ j(not_zero, &check_string);
532 __ bind(&index_smi); 480 __ bind(&index_smi);
533 // Now the key is known to be a smi. This place is also jumped to from 481 // Now the key is known to be a smi. This place is also jumped to from
534 // where a numeric string is converted to a smi. 482 // where a numeric string is converted to a smi.
535 483
536 GenerateKeyedLoadReceiverCheck( 484 GenerateKeyedLoadReceiverCheck(
537 masm, edx, ecx, Map::kHasIndexedInterceptor, &slow); 485 masm, edx, ecx, Map::kHasIndexedInterceptor, &slow);
538 486
539 // Check the "has fast elements" bit in the receiver's map which is 487 // Check the "has fast elements" bit in the receiver's map which is
540 // now in ecx. 488 // now in ecx.
541 __ test_b(FieldOperand(ecx, Map::kBitField2Offset), 489 __ test_b(FieldOperand(ecx, Map::kBitField2Offset),
542 1 << Map::kHasFastElements); 490 1 << Map::kHasFastElements);
543 __ j(zero, &check_number_dictionary, not_taken); 491 __ j(zero, &check_number_dictionary);
544 492
545 GenerateFastArrayLoad(masm, 493 GenerateFastArrayLoad(masm,
546 edx, 494 edx,
547 eax, 495 eax,
548 ecx, 496 ecx,
549 eax, 497 eax,
550 NULL, 498 NULL,
551 &slow); 499 &slow);
552 Isolate* isolate = masm->isolate(); 500 Isolate* isolate = masm->isolate();
553 Counters* counters = isolate->counters(); 501 Counters* counters = isolate->counters();
554 __ IncrementCounter(counters->keyed_load_generic_smi(), 1); 502 __ IncrementCounter(counters->keyed_load_generic_smi(), 1);
555 __ ret(0); 503 __ ret(0);
556 504
557 __ bind(&check_number_dictionary); 505 __ bind(&check_number_dictionary);
558 __ mov(ebx, eax); 506 __ mov(ebx, eax);
559 __ SmiUntag(ebx); 507 __ SmiUntag(ebx);
560 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); 508 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset));
561 509
562 // Check whether the elements is a number dictionary. 510 // Check whether the elements is a number dictionary.
563 // edx: receiver 511 // edx: receiver
564 // ebx: untagged index 512 // ebx: untagged index
565 // eax: key 513 // eax: key
566 // ecx: elements 514 // ecx: elements
567 __ CheckMap(ecx, isolate->factory()->hash_table_map(), &slow, true); 515 __ CheckMap(ecx,
516 isolate->factory()->hash_table_map(),
517 &slow,
518 DONT_DO_SMI_CHECK);
568 Label slow_pop_receiver; 519 Label slow_pop_receiver;
569 // Push receiver on the stack to free up a register for the dictionary 520 // Push receiver on the stack to free up a register for the dictionary
570 // probing. 521 // probing.
571 __ push(edx); 522 __ push(edx);
572 GenerateNumberDictionaryLoad(masm, 523 GenerateNumberDictionaryLoad(masm,
573 &slow_pop_receiver, 524 &slow_pop_receiver,
574 ecx, 525 ecx,
575 eax, 526 eax,
576 ebx, 527 ebx,
577 edx, 528 edx,
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
697 &miss, // When not a number. 648 &miss, // When not a number.
698 &miss, // When index out of range. 649 &miss, // When index out of range.
699 STRING_INDEX_IS_ARRAY_INDEX); 650 STRING_INDEX_IS_ARRAY_INDEX);
700 char_at_generator.GenerateFast(masm); 651 char_at_generator.GenerateFast(masm);
701 __ ret(0); 652 __ ret(0);
702 653
703 StubRuntimeCallHelper call_helper; 654 StubRuntimeCallHelper call_helper;
704 char_at_generator.GenerateSlow(masm, call_helper); 655 char_at_generator.GenerateSlow(masm, call_helper);
705 656
706 __ bind(&miss); 657 __ bind(&miss);
707 GenerateMiss(masm); 658 GenerateMiss(masm, false);
708 } 659 }
709 660
710 661
711 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { 662 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
712 // ----------- S t a t e ------------- 663 // ----------- S t a t e -------------
713 // -- eax : key 664 // -- eax : key
714 // -- edx : receiver 665 // -- edx : receiver
715 // -- esp[0] : return address 666 // -- esp[0] : return address
716 // ----------------------------------- 667 // -----------------------------------
717 Label slow; 668 Label slow;
718 669
719 // Check that the receiver isn't a smi. 670 // Check that the receiver isn't a smi.
720 __ test(edx, Immediate(kSmiTagMask)); 671 __ test(edx, Immediate(kSmiTagMask));
721 __ j(zero, &slow, not_taken); 672 __ j(zero, &slow);
722 673
723 // Check that the key is an array index, that is Uint32. 674 // Check that the key is an array index, that is Uint32.
724 __ test(eax, Immediate(kSmiTagMask | kSmiSignMask)); 675 __ test(eax, Immediate(kSmiTagMask | kSmiSignMask));
725 __ j(not_zero, &slow, not_taken); 676 __ j(not_zero, &slow);
726 677
727 // Get the map of the receiver. 678 // Get the map of the receiver.
728 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 679 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
729 680
730 // Check that it has indexed interceptor and access checks 681 // Check that it has indexed interceptor and access checks
731 // are not enabled for this object. 682 // are not enabled for this object.
732 __ movzx_b(ecx, FieldOperand(ecx, Map::kBitFieldOffset)); 683 __ movzx_b(ecx, FieldOperand(ecx, Map::kBitFieldOffset));
733 __ and_(Operand(ecx), Immediate(kSlowCaseBitFieldMask)); 684 __ and_(Operand(ecx), Immediate(kSlowCaseBitFieldMask));
734 __ cmp(Operand(ecx), Immediate(1 << Map::kHasIndexedInterceptor)); 685 __ cmp(Operand(ecx), Immediate(1 << Map::kHasIndexedInterceptor));
735 __ j(not_zero, &slow, not_taken); 686 __ j(not_zero, &slow);
736 687
737 // Everything is fine, call runtime. 688 // Everything is fine, call runtime.
738 __ pop(ecx); 689 __ pop(ecx);
739 __ push(edx); // receiver 690 __ push(edx); // receiver
740 __ push(eax); // key 691 __ push(eax); // key
741 __ push(ecx); // return address 692 __ push(ecx); // return address
742 693
743 // Perform tail call to the entry. 694 // Perform tail call to the entry.
744 ExternalReference ref = 695 ExternalReference ref =
745 ExternalReference(IC_Utility(kKeyedLoadPropertyWithInterceptor), 696 ExternalReference(IC_Utility(kKeyedLoadPropertyWithInterceptor),
746 masm->isolate()); 697 masm->isolate());
747 __ TailCallExternalReference(ref, 2, 1); 698 __ TailCallExternalReference(ref, 2, 1);
748 699
749 __ bind(&slow); 700 __ bind(&slow);
750 GenerateMiss(masm); 701 GenerateMiss(masm, false);
751 } 702 }
752 703
753 704
754 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, 705 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
755 StrictModeFlag strict_mode) { 706 StrictModeFlag strict_mode) {
756 // ----------- S t a t e ------------- 707 // ----------- S t a t e -------------
757 // -- eax : value 708 // -- eax : value
758 // -- ecx : key 709 // -- ecx : key
759 // -- edx : receiver 710 // -- edx : receiver
760 // -- esp[0] : return address 711 // -- esp[0] : return address
761 // ----------------------------------- 712 // -----------------------------------
762 Label slow, fast, array, extra; 713 Label slow, fast, array, extra;
763 714
764 // Check that the object isn't a smi. 715 // Check that the object isn't a smi.
765 __ test(edx, Immediate(kSmiTagMask)); 716 __ test(edx, Immediate(kSmiTagMask));
766 __ j(zero, &slow, not_taken); 717 __ j(zero, &slow);
767 // Get the map from the receiver. 718 // Get the map from the receiver.
768 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); 719 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
769 // Check that the receiver does not require access checks. We need 720 // Check that the receiver does not require access checks. We need
770 // to do this because this generic stub does not perform map checks. 721 // to do this because this generic stub does not perform map checks.
771 __ test_b(FieldOperand(edi, Map::kBitFieldOffset), 722 __ test_b(FieldOperand(edi, Map::kBitFieldOffset),
772 1 << Map::kIsAccessCheckNeeded); 723 1 << Map::kIsAccessCheckNeeded);
773 __ j(not_zero, &slow, not_taken); 724 __ j(not_zero, &slow);
774 // Check that the key is a smi. 725 // Check that the key is a smi.
775 __ test(ecx, Immediate(kSmiTagMask)); 726 __ test(ecx, Immediate(kSmiTagMask));
776 __ j(not_zero, &slow, not_taken); 727 __ j(not_zero, &slow);
777 __ CmpInstanceType(edi, JS_ARRAY_TYPE); 728 __ CmpInstanceType(edi, JS_ARRAY_TYPE);
778 __ j(equal, &array); 729 __ j(equal, &array);
779 // Check that the object is some kind of JS object. 730 // Check that the object is some kind of JS object.
780 __ CmpInstanceType(edi, FIRST_JS_OBJECT_TYPE); 731 __ CmpInstanceType(edi, FIRST_JS_OBJECT_TYPE);
781 __ j(below, &slow, not_taken); 732 __ j(below, &slow);
782 733
783 // Object case: Check key against length in the elements array. 734 // Object case: Check key against length in the elements array.
784 // eax: value 735 // eax: value
785 // edx: JSObject 736 // edx: JSObject
786 // ecx: key (a smi) 737 // ecx: key (a smi)
787 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); 738 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
788 // Check that the object is in fast mode and writable. 739 // Check that the object is in fast mode and writable.
789 __ CheckMap(edi, FACTORY->fixed_array_map(), &slow, true); 740 __ CheckMap(edi, FACTORY->fixed_array_map(), &slow, DONT_DO_SMI_CHECK);
790 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); 741 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset));
791 __ j(below, &fast, taken); 742 __ j(below, &fast);
792 743
793 // Slow case: call runtime. 744 // Slow case: call runtime.
794 __ bind(&slow); 745 __ bind(&slow);
795 GenerateRuntimeSetProperty(masm, strict_mode); 746 GenerateRuntimeSetProperty(masm, strict_mode);
796 747
797 // Extra capacity case: Check if there is extra capacity to 748 // Extra capacity case: Check if there is extra capacity to
798 // perform the store and update the length. Used for adding one 749 // perform the store and update the length. Used for adding one
799 // element to the array by writing to array[array.length]. 750 // element to the array by writing to array[array.length].
800 __ bind(&extra); 751 __ bind(&extra);
801 // eax: value 752 // eax: value
802 // edx: receiver, a JSArray 753 // edx: receiver, a JSArray
803 // ecx: key, a smi. 754 // ecx: key, a smi.
804 // edi: receiver->elements, a FixedArray 755 // edi: receiver->elements, a FixedArray
805 // flags: compare (ecx, edx.length()) 756 // flags: compare (ecx, edx.length())
806 __ j(not_equal, &slow, not_taken); // do not leave holes in the array 757 // do not leave holes in the array:
758 __ j(not_equal, &slow);
807 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); 759 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset));
808 __ j(above_equal, &slow, not_taken); 760 __ j(above_equal, &slow);
809 // Add 1 to receiver->length, and go to fast array write. 761 // Add 1 to receiver->length, and go to fast array write.
810 __ add(FieldOperand(edx, JSArray::kLengthOffset), 762 __ add(FieldOperand(edx, JSArray::kLengthOffset),
811 Immediate(Smi::FromInt(1))); 763 Immediate(Smi::FromInt(1)));
812 __ jmp(&fast); 764 __ jmp(&fast);
813 765
814 // Array case: Get the length and the elements array from the JS 766 // Array case: Get the length and the elements array from the JS
815 // array. Check that the array is in fast mode (and writable); if it 767 // array. Check that the array is in fast mode (and writable); if it
816 // is the length is always a smi. 768 // is the length is always a smi.
817 __ bind(&array); 769 __ bind(&array);
818 // eax: value 770 // eax: value
819 // edx: receiver, a JSArray 771 // edx: receiver, a JSArray
820 // ecx: key, a smi. 772 // ecx: key, a smi.
821 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); 773 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
822 __ CheckMap(edi, FACTORY->fixed_array_map(), &slow, true); 774 __ CheckMap(edi, FACTORY->fixed_array_map(), &slow, DONT_DO_SMI_CHECK);
823 775
824 // Check the key against the length in the array, compute the 776 // Check the key against the length in the array, compute the
825 // address to store into and fall through to fast case. 777 // address to store into and fall through to fast case.
826 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // Compare smis. 778 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // Compare smis.
827 __ j(above_equal, &extra, not_taken); 779 __ j(above_equal, &extra);
828 780
829 // Fast case: Do the store. 781 // Fast case: Do the store.
830 __ bind(&fast); 782 __ bind(&fast);
831 // eax: value 783 // eax: value
832 // ecx: key (a smi) 784 // ecx: key (a smi)
833 // edx: receiver 785 // edx: receiver
834 // edi: FixedArray receiver->elements 786 // edi: FixedArray receiver->elements
835 __ mov(CodeGenerator::FixedArrayElementOperand(edi, ecx), eax); 787 __ mov(CodeGenerator::FixedArrayElementOperand(edi, ecx), eax);
836 788
837 // Update write barrier for the elements array address. 789 // Update write barrier for the elements array address.
(...skipping 24 matching lines...) Expand all
862 Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, edx, ecx, ebx, 814 Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, edx, ecx, ebx,
863 eax); 815 eax);
864 816
865 // If the stub cache probing failed, the receiver might be a value. 817 // If the stub cache probing failed, the receiver might be a value.
866 // For value objects, we use the map of the prototype objects for 818 // For value objects, we use the map of the prototype objects for
867 // the corresponding JSValue for the cache and that is what we need 819 // the corresponding JSValue for the cache and that is what we need
868 // to probe. 820 // to probe.
869 // 821 //
870 // Check for number. 822 // Check for number.
871 __ test(edx, Immediate(kSmiTagMask)); 823 __ test(edx, Immediate(kSmiTagMask));
872 __ j(zero, &number, not_taken); 824 __ j(zero, &number);
873 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ebx); 825 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ebx);
874 __ j(not_equal, &non_number, taken); 826 __ j(not_equal, &non_number);
875 __ bind(&number); 827 __ bind(&number);
876 StubCompiler::GenerateLoadGlobalFunctionPrototype( 828 StubCompiler::GenerateLoadGlobalFunctionPrototype(
877 masm, Context::NUMBER_FUNCTION_INDEX, edx); 829 masm, Context::NUMBER_FUNCTION_INDEX, edx);
878 __ jmp(&probe); 830 __ jmp(&probe);
879 831
880 // Check for string. 832 // Check for string.
881 __ bind(&non_number); 833 __ bind(&non_number);
882 __ CmpInstanceType(ebx, FIRST_NONSTRING_TYPE); 834 __ CmpInstanceType(ebx, FIRST_NONSTRING_TYPE);
883 __ j(above_equal, &non_string, taken); 835 __ j(above_equal, &non_string);
884 StubCompiler::GenerateLoadGlobalFunctionPrototype( 836 StubCompiler::GenerateLoadGlobalFunctionPrototype(
885 masm, Context::STRING_FUNCTION_INDEX, edx); 837 masm, Context::STRING_FUNCTION_INDEX, edx);
886 __ jmp(&probe); 838 __ jmp(&probe);
887 839
888 // Check for boolean. 840 // Check for boolean.
889 __ bind(&non_string); 841 __ bind(&non_string);
890 __ cmp(edx, FACTORY->true_value()); 842 __ cmp(edx, FACTORY->true_value());
891 __ j(equal, &boolean, not_taken); 843 __ j(equal, &boolean);
892 __ cmp(edx, FACTORY->false_value()); 844 __ cmp(edx, FACTORY->false_value());
893 __ j(not_equal, &miss, taken); 845 __ j(not_equal, &miss);
894 __ bind(&boolean); 846 __ bind(&boolean);
895 StubCompiler::GenerateLoadGlobalFunctionPrototype( 847 StubCompiler::GenerateLoadGlobalFunctionPrototype(
896 masm, Context::BOOLEAN_FUNCTION_INDEX, edx); 848 masm, Context::BOOLEAN_FUNCTION_INDEX, edx);
897 849
898 // Probe the stub cache for the value object. 850 // Probe the stub cache for the value object.
899 __ bind(&probe); 851 __ bind(&probe);
900 Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, edx, ecx, ebx, 852 Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, edx, ecx, ebx,
901 no_reg); 853 no_reg);
902 __ bind(&miss); 854 __ bind(&miss);
903 } 855 }
904 856
905 857
906 static void GenerateFunctionTailCall(MacroAssembler* masm, 858 static void GenerateFunctionTailCall(MacroAssembler* masm,
907 int argc, 859 int argc,
908 Label* miss) { 860 Label* miss) {
909 // ----------- S t a t e ------------- 861 // ----------- S t a t e -------------
910 // -- ecx : name 862 // -- ecx : name
911 // -- edi : function 863 // -- edi : function
912 // -- esp[0] : return address 864 // -- esp[0] : return address
913 // -- esp[(argc - n) * 4] : arg[n] (zero-based) 865 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
914 // -- ... 866 // -- ...
915 // -- esp[(argc + 1) * 4] : receiver 867 // -- esp[(argc + 1) * 4] : receiver
916 // ----------------------------------- 868 // -----------------------------------
917 869
918 // Check that the result is not a smi. 870 // Check that the result is not a smi.
919 __ test(edi, Immediate(kSmiTagMask)); 871 __ test(edi, Immediate(kSmiTagMask));
920 __ j(zero, miss, not_taken); 872 __ j(zero, miss);
921 873
922 // Check that the value is a JavaScript function, fetching its map into eax. 874 // Check that the value is a JavaScript function, fetching its map into eax.
923 __ CmpObjectType(edi, JS_FUNCTION_TYPE, eax); 875 __ CmpObjectType(edi, JS_FUNCTION_TYPE, eax);
924 __ j(not_equal, miss, not_taken); 876 __ j(not_equal, miss);
925 877
926 // Invoke the function. 878 // Invoke the function.
927 ParameterCount actual(argc); 879 ParameterCount actual(argc);
928 __ InvokeFunction(edi, actual, JUMP_FUNCTION); 880 __ InvokeFunction(edi, actual, JUMP_FUNCTION);
929 } 881 }
930 882
931 // The generated code falls through if the call should be handled by runtime. 883 // The generated code falls through if the call should be handled by runtime.
932 static void GenerateCallNormal(MacroAssembler* masm, int argc) { 884 static void GenerateCallNormal(MacroAssembler* masm, int argc) {
933 // ----------- S t a t e ------------- 885 // ----------- S t a t e -------------
934 // -- ecx : name 886 // -- ecx : name
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
990 // Move result to edi and exit the internal frame. 942 // Move result to edi and exit the internal frame.
991 __ mov(edi, eax); 943 __ mov(edi, eax);
992 __ LeaveInternalFrame(); 944 __ LeaveInternalFrame();
993 945
994 // Check if the receiver is a global object of some sort. 946 // Check if the receiver is a global object of some sort.
995 // This can happen only for regular CallIC but not KeyedCallIC. 947 // This can happen only for regular CallIC but not KeyedCallIC.
996 if (id == IC::kCallIC_Miss) { 948 if (id == IC::kCallIC_Miss) {
997 Label invoke, global; 949 Label invoke, global;
998 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); // receiver 950 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); // receiver
999 __ test(edx, Immediate(kSmiTagMask)); 951 __ test(edx, Immediate(kSmiTagMask));
1000 __ j(zero, &invoke, not_taken); 952 __ j(zero, &invoke, Label::kNear);
1001 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); 953 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
1002 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); 954 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
1003 __ cmp(ebx, JS_GLOBAL_OBJECT_TYPE); 955 __ cmp(ebx, JS_GLOBAL_OBJECT_TYPE);
1004 __ j(equal, &global); 956 __ j(equal, &global, Label::kNear);
1005 __ cmp(ebx, JS_BUILTINS_OBJECT_TYPE); 957 __ cmp(ebx, JS_BUILTINS_OBJECT_TYPE);
1006 __ j(not_equal, &invoke); 958 __ j(not_equal, &invoke, Label::kNear);
1007 959
1008 // Patch the receiver on the stack. 960 // Patch the receiver on the stack.
1009 __ bind(&global); 961 __ bind(&global);
1010 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); 962 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
1011 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); 963 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
1012 __ bind(&invoke); 964 __ bind(&invoke);
1013 } 965 }
1014 966
1015 // Invoke the function. 967 // Invoke the function.
1016 ParameterCount actual(argc); 968 ParameterCount actual(argc);
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1072 1024
1073 // Get the receiver of the function from the stack; 1 ~ return address. 1025 // Get the receiver of the function from the stack; 1 ~ return address.
1074 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 1026 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1075 1027
1076 Label do_call, slow_call, slow_load, slow_reload_receiver; 1028 Label do_call, slow_call, slow_load, slow_reload_receiver;
1077 Label check_number_dictionary, check_string, lookup_monomorphic_cache; 1029 Label check_number_dictionary, check_string, lookup_monomorphic_cache;
1078 Label index_smi, index_string; 1030 Label index_smi, index_string;
1079 1031
1080 // Check that the key is a smi. 1032 // Check that the key is a smi.
1081 __ test(ecx, Immediate(kSmiTagMask)); 1033 __ test(ecx, Immediate(kSmiTagMask));
1082 __ j(not_zero, &check_string, not_taken); 1034 __ j(not_zero, &check_string);
1083 1035
1084 __ bind(&index_smi); 1036 __ bind(&index_smi);
1085 // Now the key is known to be a smi. This place is also jumped to from 1037 // Now the key is known to be a smi. This place is also jumped to from
1086 // where a numeric string is converted to a smi. 1038 // where a numeric string is converted to a smi.
1087 1039
1088 GenerateKeyedLoadReceiverCheck( 1040 GenerateKeyedLoadReceiverCheck(
1089 masm, edx, eax, Map::kHasIndexedInterceptor, &slow_call); 1041 masm, edx, eax, Map::kHasIndexedInterceptor, &slow_call);
1090 1042
1091 GenerateFastArrayLoad( 1043 GenerateFastArrayLoad(
1092 masm, edx, ecx, eax, edi, &check_number_dictionary, &slow_load); 1044 masm, edx, ecx, eax, edi, &check_number_dictionary, &slow_load);
1093 Isolate* isolate = masm->isolate(); 1045 Isolate* isolate = masm->isolate();
1094 Counters* counters = isolate->counters(); 1046 Counters* counters = isolate->counters();
1095 __ IncrementCounter(counters->keyed_call_generic_smi_fast(), 1); 1047 __ IncrementCounter(counters->keyed_call_generic_smi_fast(), 1);
1096 1048
1097 __ bind(&do_call); 1049 __ bind(&do_call);
1098 // receiver in edx is not used after this point. 1050 // receiver in edx is not used after this point.
1099 // ecx: key 1051 // ecx: key
1100 // edi: function 1052 // edi: function
1101 GenerateFunctionTailCall(masm, argc, &slow_call); 1053 GenerateFunctionTailCall(masm, argc, &slow_call);
1102 1054
1103 __ bind(&check_number_dictionary); 1055 __ bind(&check_number_dictionary);
1104 // eax: elements 1056 // eax: elements
1105 // ecx: smi key 1057 // ecx: smi key
1106 // Check whether the elements is a number dictionary. 1058 // Check whether the elements is a number dictionary.
1107 __ CheckMap(eax, isolate->factory()->hash_table_map(), &slow_load, true); 1059 __ CheckMap(eax,
1060 isolate->factory()->hash_table_map(),
1061 &slow_load,
1062 DONT_DO_SMI_CHECK);
1108 __ mov(ebx, ecx); 1063 __ mov(ebx, ecx);
1109 __ SmiUntag(ebx); 1064 __ SmiUntag(ebx);
1110 // ebx: untagged index 1065 // ebx: untagged index
1111 // Receiver in edx will be clobbered, need to reload it on miss. 1066 // Receiver in edx will be clobbered, need to reload it on miss.
1112 GenerateNumberDictionaryLoad( 1067 GenerateNumberDictionaryLoad(
1113 masm, &slow_reload_receiver, eax, ecx, ebx, edx, edi, edi); 1068 masm, &slow_reload_receiver, eax, ecx, ebx, edx, edi, edi);
1114 __ IncrementCounter(counters->keyed_call_generic_smi_dict(), 1); 1069 __ IncrementCounter(counters->keyed_call_generic_smi_dict(), 1);
1115 __ jmp(&do_call); 1070 __ jmp(&do_call);
1116 1071
1117 __ bind(&slow_reload_receiver); 1072 __ bind(&slow_reload_receiver);
(...skipping 20 matching lines...) Expand all
1138 // If the receiver is a regular JS object with slow properties then do 1093 // If the receiver is a regular JS object with slow properties then do
1139 // a quick inline probe of the receiver's dictionary. 1094 // a quick inline probe of the receiver's dictionary.
1140 // Otherwise do the monomorphic cache probe. 1095 // Otherwise do the monomorphic cache probe.
1141 GenerateKeyedLoadReceiverCheck( 1096 GenerateKeyedLoadReceiverCheck(
1142 masm, edx, eax, Map::kHasNamedInterceptor, &lookup_monomorphic_cache); 1097 masm, edx, eax, Map::kHasNamedInterceptor, &lookup_monomorphic_cache);
1143 1098
1144 __ mov(ebx, FieldOperand(edx, JSObject::kPropertiesOffset)); 1099 __ mov(ebx, FieldOperand(edx, JSObject::kPropertiesOffset));
1145 __ CheckMap(ebx, 1100 __ CheckMap(ebx,
1146 isolate->factory()->hash_table_map(), 1101 isolate->factory()->hash_table_map(),
1147 &lookup_monomorphic_cache, 1102 &lookup_monomorphic_cache,
1148 true); 1103 DONT_DO_SMI_CHECK);
1149 1104
1150 GenerateDictionaryLoad(masm, &slow_load, ebx, ecx, eax, edi, edi); 1105 GenerateDictionaryLoad(masm, &slow_load, ebx, ecx, eax, edi, edi);
1151 __ IncrementCounter(counters->keyed_call_generic_lookup_dict(), 1); 1106 __ IncrementCounter(counters->keyed_call_generic_lookup_dict(), 1);
1152 __ jmp(&do_call); 1107 __ jmp(&do_call);
1153 1108
1154 __ bind(&lookup_monomorphic_cache); 1109 __ bind(&lookup_monomorphic_cache);
1155 __ IncrementCounter(counters->keyed_call_generic_lookup_cache(), 1); 1110 __ IncrementCounter(counters->keyed_call_generic_lookup_cache(), 1);
1156 GenerateMonomorphicCacheProbe(masm, argc, Code::KEYED_CALL_IC); 1111 GenerateMonomorphicCacheProbe(masm, argc, Code::KEYED_CALL_IC);
1157 // Fall through on miss. 1112 // Fall through on miss.
1158 1113
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
1261 __ push(ecx); // name 1216 __ push(ecx); // name
1262 __ push(ebx); // return address 1217 __ push(ebx); // return address
1263 1218
1264 // Perform tail call to the entry. 1219 // Perform tail call to the entry.
1265 ExternalReference ref = 1220 ExternalReference ref =
1266 ExternalReference(IC_Utility(kLoadIC_Miss), masm->isolate()); 1221 ExternalReference(IC_Utility(kLoadIC_Miss), masm->isolate());
1267 __ TailCallExternalReference(ref, 2, 1); 1222 __ TailCallExternalReference(ref, 2, 1);
1268 } 1223 }
1269 1224
1270 1225
1271 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { 1226 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm, bool force_generic) {
1272 // ----------- S t a t e ------------- 1227 // ----------- S t a t e -------------
1273 // -- eax : key 1228 // -- eax : key
1274 // -- edx : receiver 1229 // -- edx : receiver
1275 // -- esp[0] : return address 1230 // -- esp[0] : return address
1276 // ----------------------------------- 1231 // -----------------------------------
1277 1232
1278 __ IncrementCounter(masm->isolate()->counters()->keyed_load_miss(), 1); 1233 __ IncrementCounter(masm->isolate()->counters()->keyed_load_miss(), 1);
1279 1234
1280 __ pop(ebx); 1235 __ pop(ebx);
1281 __ push(edx); // receiver 1236 __ push(edx); // receiver
1282 __ push(eax); // name 1237 __ push(eax); // name
1283 __ push(ebx); // return address 1238 __ push(ebx); // return address
1284 1239
1285 // Perform tail call to the entry. 1240 // Perform tail call to the entry.
1286 ExternalReference ref = 1241 ExternalReference ref = force_generic
1287 ExternalReference(IC_Utility(kKeyedLoadIC_Miss), masm->isolate()); 1242 ? ExternalReference(IC_Utility(kKeyedLoadIC_MissForceGeneric),
1243 masm->isolate())
1244 : ExternalReference(IC_Utility(kKeyedLoadIC_Miss), masm->isolate());
1288 __ TailCallExternalReference(ref, 2, 1); 1245 __ TailCallExternalReference(ref, 2, 1);
1289 } 1246 }
1290 1247
1291 1248
1292 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { 1249 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
1293 // ----------- S t a t e ------------- 1250 // ----------- S t a t e -------------
1294 // -- eax : key 1251 // -- eax : key
1295 // -- edx : receiver 1252 // -- edx : receiver
1296 // -- esp[0] : return address 1253 // -- esp[0] : return address
1297 // ----------------------------------- 1254 // -----------------------------------
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
1362 // Value must be a number, but only smis are accepted as the most common case. 1319 // Value must be a number, but only smis are accepted as the most common case.
1363 1320
1364 Label miss; 1321 Label miss;
1365 1322
1366 Register receiver = edx; 1323 Register receiver = edx;
1367 Register value = eax; 1324 Register value = eax;
1368 Register scratch = ebx; 1325 Register scratch = ebx;
1369 1326
1370 // Check that the receiver isn't a smi. 1327 // Check that the receiver isn't a smi.
1371 __ test(receiver, Immediate(kSmiTagMask)); 1328 __ test(receiver, Immediate(kSmiTagMask));
1372 __ j(zero, &miss, not_taken); 1329 __ j(zero, &miss);
1373 1330
1374 // Check that the object is a JS array. 1331 // Check that the object is a JS array.
1375 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch); 1332 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch);
1376 __ j(not_equal, &miss, not_taken); 1333 __ j(not_equal, &miss);
1377 1334
1378 // Check that elements are FixedArray. 1335 // Check that elements are FixedArray.
1379 // We rely on StoreIC_ArrayLength below to deal with all types of 1336 // We rely on StoreIC_ArrayLength below to deal with all types of
1380 // fast elements (including COW). 1337 // fast elements (including COW).
1381 __ mov(scratch, FieldOperand(receiver, JSArray::kElementsOffset)); 1338 __ mov(scratch, FieldOperand(receiver, JSArray::kElementsOffset));
1382 __ CmpObjectType(scratch, FIXED_ARRAY_TYPE, scratch); 1339 __ CmpObjectType(scratch, FIXED_ARRAY_TYPE, scratch);
1383 __ j(not_equal, &miss, not_taken); 1340 __ j(not_equal, &miss);
1384 1341
1385 // Check that value is a smi. 1342 // Check that value is a smi.
1386 __ test(value, Immediate(kSmiTagMask)); 1343 __ test(value, Immediate(kSmiTagMask));
1387 __ j(not_zero, &miss, not_taken); 1344 __ j(not_zero, &miss);
1388 1345
1389 // Prepare tail call to StoreIC_ArrayLength. 1346 // Prepare tail call to StoreIC_ArrayLength.
1390 __ pop(scratch); 1347 __ pop(scratch);
1391 __ push(receiver); 1348 __ push(receiver);
1392 __ push(value); 1349 __ push(value);
1393 __ push(scratch); // return address 1350 __ push(scratch); // return address
1394 1351
1395 ExternalReference ref = 1352 ExternalReference ref =
1396 ExternalReference(IC_Utility(kStoreIC_ArrayLength), masm->isolate()); 1353 ExternalReference(IC_Utility(kStoreIC_ArrayLength), masm->isolate());
1397 __ TailCallExternalReference(ref, 2, 1); 1354 __ TailCallExternalReference(ref, 2, 1);
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
1469 __ push(eax); 1426 __ push(eax);
1470 __ push(Immediate(Smi::FromInt(NONE))); // PropertyAttributes 1427 __ push(Immediate(Smi::FromInt(NONE))); // PropertyAttributes
1471 __ push(Immediate(Smi::FromInt(strict_mode))); // Strict mode. 1428 __ push(Immediate(Smi::FromInt(strict_mode))); // Strict mode.
1472 __ push(ebx); // return address 1429 __ push(ebx); // return address
1473 1430
1474 // Do tail-call to runtime routine. 1431 // Do tail-call to runtime routine.
1475 __ TailCallRuntime(Runtime::kSetProperty, 5, 1); 1432 __ TailCallRuntime(Runtime::kSetProperty, 5, 1);
1476 } 1433 }
1477 1434
1478 1435
1479 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { 1436 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm, bool force_generic) {
1480 // ----------- S t a t e ------------- 1437 // ----------- S t a t e -------------
1481 // -- eax : value 1438 // -- eax : value
1482 // -- ecx : key 1439 // -- ecx : key
1483 // -- edx : receiver 1440 // -- edx : receiver
1484 // -- esp[0] : return address 1441 // -- esp[0] : return address
1485 // ----------------------------------- 1442 // -----------------------------------
1486 1443
1487 __ pop(ebx); 1444 __ pop(ebx);
1488 __ push(edx); 1445 __ push(edx);
1489 __ push(ecx); 1446 __ push(ecx);
1490 __ push(eax); 1447 __ push(eax);
1491 __ push(ebx); 1448 __ push(ebx);
1492 1449
1493 // Do tail-call to runtime routine. 1450 // Do tail-call to runtime routine.
1494 ExternalReference ref = 1451 ExternalReference ref = force_generic
1495 ExternalReference(IC_Utility(kKeyedStoreIC_Miss), masm->isolate()); 1452 ? ExternalReference(IC_Utility(kKeyedStoreIC_MissForceGeneric),
1453 masm->isolate())
1454 : ExternalReference(IC_Utility(kKeyedStoreIC_Miss), masm->isolate());
1455 __ TailCallExternalReference(ref, 3, 1);
1456 }
1457
1458
1459 void KeyedStoreIC::GenerateSlow(MacroAssembler* masm) {
1460 // ----------- S t a t e -------------
1461 // -- eax : value
1462 // -- ecx : key
1463 // -- edx : receiver
1464 // -- esp[0] : return address
1465 // -----------------------------------
1466
1467 __ pop(ebx);
1468 __ push(edx);
1469 __ push(ecx);
1470 __ push(eax);
1471 __ push(ebx); // return address
1472
1473 // Do tail-call to runtime routine.
1474 ExternalReference ref(IC_Utility(kKeyedStoreIC_Slow), masm->isolate());
1496 __ TailCallExternalReference(ref, 3, 1); 1475 __ TailCallExternalReference(ref, 3, 1);
1497 } 1476 }
1498 1477
1499 1478
1500 #undef __ 1479 #undef __
1501 1480
1502 1481
1503 Condition CompareIC::ComputeCondition(Token::Value op) { 1482 Condition CompareIC::ComputeCondition(Token::Value op) {
1504 switch (op) { 1483 switch (op) {
1505 case Token::EQ_STRICT: 1484 case Token::EQ_STRICT:
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
1593 Condition cc = *jmp_address == Assembler::kJncShortOpcode 1572 Condition cc = *jmp_address == Assembler::kJncShortOpcode
1594 ? not_zero 1573 ? not_zero
1595 : zero; 1574 : zero;
1596 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); 1575 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc);
1597 } 1576 }
1598 1577
1599 1578
1600 } } // namespace v8::internal 1579 } } // namespace v8::internal
1601 1580
1602 #endif // V8_TARGET_ARCH_IA32 1581 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/full-codegen-ia32.cc ('k') | src/ia32/lithium-codegen-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698