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

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

Issue 2754003: Add logic from KeyedLoadIC generic stub to KeyedCallIC megamorphic stub.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | src/ic.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 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
50 // must always call a backup property load that is complete. 50 // must always call a backup property load that is complete.
51 // This function is safe to call if the receiver has fast properties, 51 // This function is safe to call if the receiver has fast properties,
52 // or if name is not a symbol, and will jump to the miss_label in that case. 52 // or if name is not a symbol, and will jump to the miss_label in that case.
53 static void GenerateDictionaryLoad(MacroAssembler* masm, 53 static void GenerateDictionaryLoad(MacroAssembler* masm,
54 Label* miss_label, 54 Label* miss_label,
55 Register receiver, 55 Register receiver,
56 Register name, 56 Register name,
57 Register r0, 57 Register r0,
58 Register r1, 58 Register r1,
59 Register r2, 59 Register r2,
60 Register result,
60 DictionaryCheck check_dictionary) { 61 DictionaryCheck check_dictionary) {
61 // Register use: 62 // Register use:
62 // 63 //
63 // name - holds the name of the property and is unchanged. 64 // name - holds the name of the property and is unchanged.
64 // receiver - holds the receiver and is unchanged. 65 // receiver - holds the receiver and is unchanged.
65 // Scratch registers: 66 // Scratch registers:
66 // r0 - used to hold the property dictionary. 67 // r0 - used to hold the property dictionary.
67 // 68 //
68 // r1 - used for the index into the property dictionary 69 // r1 - used for the index into the property dictionary
69 // - holds the result on exit.
70 // 70 //
71 // r2 - used to hold the capacity of the property dictionary. 71 // r2 - used to hold the capacity of the property dictionary.
72 //
73 // result - holds the result on exit.
72 74
73 Label done; 75 Label done;
74 76
75 // Check for the absence of an interceptor. 77 // Check for the absence of an interceptor.
76 // Load the map into r0. 78 // Load the map into r0.
77 __ mov(r0, FieldOperand(receiver, JSObject::kMapOffset)); 79 __ mov(r0, FieldOperand(receiver, JSObject::kMapOffset));
78 80
79 // Bail out if the receiver has a named interceptor. 81 // Bail out if the receiver has a named interceptor.
80 __ test(FieldOperand(r0, Map::kBitFieldOffset), 82 __ test(FieldOperand(r0, Map::kBitFieldOffset),
81 Immediate(1 << Map::kHasNamedInterceptor)); 83 Immediate(1 << Map::kHasNamedInterceptor));
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 144
143 // Check that the value is a normal property. 145 // Check that the value is a normal property.
144 __ bind(&done); 146 __ bind(&done);
145 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; 147 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
146 __ test(Operand(r0, r1, times_4, kDetailsOffset - kHeapObjectTag), 148 __ test(Operand(r0, r1, times_4, kDetailsOffset - kHeapObjectTag),
147 Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize)); 149 Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize));
148 __ j(not_zero, miss_label, not_taken); 150 __ j(not_zero, miss_label, not_taken);
149 151
150 // Get the value at the masked, scaled index. 152 // Get the value at the masked, scaled index.
151 const int kValueOffset = kElementsStartOffset + kPointerSize; 153 const int kValueOffset = kElementsStartOffset + kPointerSize;
152 __ mov(r1, Operand(r0, r1, times_4, kValueOffset - kHeapObjectTag)); 154 __ mov(result, Operand(r0, r1, times_4, kValueOffset - kHeapObjectTag));
153 } 155 }
154 156
155 157
156 static void GenerateNumberDictionaryLoad(MacroAssembler* masm, 158 static void GenerateNumberDictionaryLoad(MacroAssembler* masm,
157 Label* miss, 159 Label* miss,
158 Register elements, 160 Register elements,
159 Register key, 161 Register key,
160 Register r0, 162 Register r0,
161 Register r1, 163 Register r1,
162 Register r2) { 164 Register r2,
165 Register result) {
163 // Register use: 166 // Register use:
164 // 167 //
165 // elements - holds the slow-case elements of the receiver and is unchanged. 168 // elements - holds the slow-case elements of the receiver and is unchanged.
166 // 169 //
167 // key - holds the smi key on entry and is unchanged if a branch is 170 // key - holds the smi key on entry and is unchanged.
168 // performed to the miss label. If the load succeeds and we
169 // fall through, key holds the result on exit.
170 // 171 //
171 // Scratch registers: 172 // Scratch registers:
172 // 173 //
173 // r0 - holds the untagged key on entry and holds the hash once computed. 174 // r0 - holds the untagged key on entry and holds the hash once computed.
174 // 175 //
175 // r1 - used to hold the capacity mask of the dictionary 176 // r1 - used to hold the capacity mask of the dictionary
176 // 177 //
177 // r2 - used for the index into the dictionary. 178 // r2 - used for the index into the dictionary.
179 //
180 // result - holds the result on exit if the load succeeds and we fall through.
181
178 Label done; 182 Label done;
179 183
180 // Compute the hash code from the untagged key. This must be kept in sync 184 // Compute the hash code from the untagged key. This must be kept in sync
181 // with ComputeIntegerHash in utils.h. 185 // with ComputeIntegerHash in utils.h.
182 // 186 //
183 // hash = ~hash + (hash << 15); 187 // hash = ~hash + (hash << 15);
184 __ mov(r1, r0); 188 __ mov(r1, r0);
185 __ not_(r0); 189 __ not_(r0);
186 __ shl(r1, 15); 190 __ shl(r1, 15);
187 __ add(r0, Operand(r1)); 191 __ add(r0, Operand(r1));
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 const int kDetailsOffset = 243 const int kDetailsOffset =
240 NumberDictionary::kElementsStartOffset + 2 * kPointerSize; 244 NumberDictionary::kElementsStartOffset + 2 * kPointerSize;
241 ASSERT_EQ(NORMAL, 0); 245 ASSERT_EQ(NORMAL, 0);
242 __ test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset), 246 __ test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset),
243 Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize)); 247 Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize));
244 __ j(not_zero, miss); 248 __ j(not_zero, miss);
245 249
246 // Get the value at the masked, scaled index. 250 // Get the value at the masked, scaled index.
247 const int kValueOffset = 251 const int kValueOffset =
248 NumberDictionary::kElementsStartOffset + kPointerSize; 252 NumberDictionary::kElementsStartOffset + kPointerSize;
249 __ mov(key, FieldOperand(elements, r2, times_pointer_size, kValueOffset)); 253 __ mov(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset));
250 } 254 }
251 255
252 256
253 // The offset from the inlined patch site to the start of the 257 // The offset from the inlined patch site to the start of the
254 // inlined load instruction. It is 7 bytes (test eax, imm) plus 258 // inlined load instruction. It is 7 bytes (test eax, imm) plus
255 // 6 bytes (jne slow_label). 259 // 6 bytes (jne slow_label).
256 const int LoadIC::kOffsetToLoadInstruction = 13; 260 const int LoadIC::kOffsetToLoadInstruction = 13;
257 261
258 262
259 void LoadIC::GenerateArrayLength(MacroAssembler* masm) { 263 void LoadIC::GenerateArrayLength(MacroAssembler* masm) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
291 // -- esp[0] : return address 295 // -- esp[0] : return address
292 // ----------------------------------- 296 // -----------------------------------
293 Label miss; 297 Label miss;
294 298
295 StubCompiler::GenerateLoadFunctionPrototype(masm, eax, edx, ebx, &miss); 299 StubCompiler::GenerateLoadFunctionPrototype(masm, eax, edx, ebx, &miss);
296 __ bind(&miss); 300 __ bind(&miss);
297 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); 301 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
298 } 302 }
299 303
300 304
305 // Checks the receiver for special cases (value type, slow case bits).
306 // Falls through for regular JS object.
307 static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm,
308 Register receiver,
309 Register r0,
310 Label* slow) {
311 // Register use:
312 // receiver - holds the receiver and is unchanged.
313 // Scratch registers:
314 // r0 - used to hold the map of the receiver.
315
316 // Check that the object isn't a smi.
317 __ test(receiver, Immediate(kSmiTagMask));
318 __ j(zero, slow, not_taken);
319
320 // Get the map of the receiver.
321 __ mov(r0, FieldOperand(receiver, HeapObject::kMapOffset));
322
323 // Check bit field.
324 __ test_b(FieldOperand(r0, Map::kBitFieldOffset),
325 KeyedLoadIC::kSlowCaseBitFieldMask);
326 __ j(not_zero, slow, not_taken);
327 // Check that the object is some kind of JS object EXCEPT JS Value type.
328 // In the case that the object is a value-wrapper object,
329 // we enter the runtime system to make sure that indexing
330 // into string objects works as intended.
331 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE);
332
333 __ CmpInstanceType(r0, JS_OBJECT_TYPE);
334 __ j(below, slow, not_taken);
335 }
336
337
338 // Loads an indexed element from a fast case array.
339 static void GenerateFastArrayLoad(MacroAssembler* masm,
340 Register receiver,
341 Register key,
342 Register scratch,
343 Register result,
344 Label* not_fast_array,
345 Label* out_of_range) {
346 // Register use:
347 // receiver - holds the receiver and is unchanged.
348 // key - holds the key and is unchanged (must be a smi).
349 // Scratch registers:
350 // scratch - used to hold elements of the receiver and the loaded value.
351 // result - holds the result on exit if the load succeeds and
352 // we fall through.
353
354 __ mov(scratch, FieldOperand(receiver, JSObject::kElementsOffset));
355 // Check that the object is in fast mode (not dictionary).
356 __ CheckMap(scratch, Factory::fixed_array_map(), not_fast_array, true);
357 // Check that the key (index) is within bounds.
358 __ cmp(key, FieldOperand(scratch, FixedArray::kLengthOffset));
359 __ j(above_equal, out_of_range);
360 // Fast case: Do the load.
361 ASSERT((kPointerSize == 4) && (kSmiTagSize == 1) && (kSmiTag == 0));
362 __ mov(scratch, FieldOperand(scratch, key, times_2, FixedArray::kHeaderSize));
363 __ cmp(Operand(scratch), Immediate(Factory::the_hole_value()));
364 // In case the loaded value is the_hole we have to consult GetProperty
365 // to ensure the prototype chain is searched.
366 __ j(equal, out_of_range);
367 if (!result.is(scratch)) {
368 __ mov(result, scratch);
369 }
370 }
371
372
373 // Checks whether a key is an array index string or a symbol string.
374 // Falls through if a key is a symbol.
375 static void GenerateKeyStringCheck(MacroAssembler* masm,
376 Register key,
377 Register map,
378 Register hash,
379 Label* index_string,
380 Label* not_symbol) {
381 // Register use:
382 // key - holds the key and is unchanged. Assumed to be non-smi.
383 // Scratch registers:
384 // map - used to hold the map of the key.
385 // hash - used to hold the hash of the key.
386 __ CmpObjectType(key, FIRST_NONSTRING_TYPE, map);
387 __ j(above_equal, not_symbol);
388
389 // Is the string an array index, with cached numeric value?
390 __ mov(hash, FieldOperand(key, String::kHashFieldOffset));
391 __ test(hash, Immediate(String::kContainsCachedArrayIndexMask));
392 __ j(zero, index_string, not_taken);
393
394 // Is the string a symbol?
395 ASSERT(kSymbolTag != 0);
396 __ test_b(FieldOperand(map, Map::kInstanceTypeOffset), kIsSymbolMask);
397 __ j(zero, not_symbol, not_taken);
398 }
399
400
401 // Picks out an array index from the hash field.
402 // The generated code never falls through.
403 static void GenerateIndexFromHash(MacroAssembler* masm,
404 Register key,
405 Register hash,
406 Label* index_smi) {
407 // Register use:
408 // key - holds the overwritten key on exit.
409 // hash - holds the key's hash. Clobbered.
410
411 // The assert checks that the constants for the maximum number of digits
412 // for an array index cached in the hash field and the number of bits
413 // reserved for it does not conflict.
414 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
415 (1 << String::kArrayIndexValueBits));
416 // We want the smi-tagged index in key. kArrayIndexValueMask has zeros in
417 // the low kHashShift bits.
418 // key: string key
419 // ebx: hash field.
420 ASSERT(String::kHashShift >= kSmiTagSize);
421 __ and_(hash, String::kArrayIndexValueMask);
422 __ shr(hash, String::kHashShift - kSmiTagSize);
423 // Here we actually clobber the key which will be used if calling into
424 // runtime later. However as the new key is the numeric value of a string key
425 // there is no difference in using either key.
426 __ mov(key, hash);
427 // Now jump to the place where smi keys are handled.
428 __ jmp(index_smi);
429 }
430
431
301 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { 432 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
302 // ----------- S t a t e ------------- 433 // ----------- S t a t e -------------
303 // -- eax : key 434 // -- eax : key
304 // -- edx : receiver 435 // -- edx : receiver
305 // -- esp[0] : return address 436 // -- esp[0] : return address
306 // ----------------------------------- 437 // -----------------------------------
307 Label slow, check_string, index_smi, index_string; 438 Label slow, check_string, index_smi, index_string;
308 Label check_pixel_array, probe_dictionary, check_number_dictionary; 439 Label check_pixel_array, probe_dictionary, check_number_dictionary;
309 440
310 // Check that the object isn't a smi. 441 GenerateKeyedLoadReceiverCheck(masm, edx, ecx, &slow);
311 __ test(edx, Immediate(kSmiTagMask));
312 __ j(zero, &slow, not_taken);
313 442
314 // Get the map of the receiver.
315 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
316
317 // Check bit field.
318 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), kSlowCaseBitFieldMask);
319 __ j(not_zero, &slow, not_taken);
320 // Check that the object is some kind of JS object EXCEPT JS Value type.
321 // In the case that the object is a value-wrapper object,
322 // we enter the runtime system to make sure that indexing
323 // into string objects work as intended.
324 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE);
325 __ CmpInstanceType(ecx, JS_OBJECT_TYPE);
326 __ j(below, &slow, not_taken);
327 // Check that the key is a smi. 443 // Check that the key is a smi.
328 __ test(eax, Immediate(kSmiTagMask)); 444 __ test(eax, Immediate(kSmiTagMask));
329 __ j(not_zero, &check_string, not_taken); 445 __ j(not_zero, &check_string, not_taken);
330 __ bind(&index_smi); 446 __ bind(&index_smi);
331 // Now the key is known to be a smi. This place is also jumped to from below 447 // Now the key is known to be a smi. This place is also jumped to from
332 // where a numeric string is converted to a smi. 448 // where a numeric string is converted to a smi.
333 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); 449
334 // Check that the object is in fast mode (not dictionary). 450 GenerateFastArrayLoad(masm,
335 __ CheckMap(ecx, Factory::fixed_array_map(), &check_pixel_array, true); 451 edx,
336 // Check that the key (index) is within bounds. 452 eax,
337 __ cmp(eax, FieldOperand(ecx, FixedArray::kLengthOffset)); 453 ecx,
338 __ j(above_equal, &slow); 454 eax,
339 // Fast case: Do the load. 455 &check_pixel_array,
340 ASSERT((kPointerSize == 4) && (kSmiTagSize == 1) && (kSmiTag == 0)); 456 &slow);
341 __ mov(ecx, FieldOperand(ecx, eax, times_2, FixedArray::kHeaderSize));
342 __ cmp(Operand(ecx), Immediate(Factory::the_hole_value()));
343 // In case the loaded value is the_hole we have to consult GetProperty
344 // to ensure the prototype chain is searched.
345 __ j(equal, &slow);
346 __ mov(eax, ecx);
347 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1); 457 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1);
348 __ ret(0); 458 __ ret(0);
349 459
350 __ bind(&check_pixel_array); 460 __ bind(&check_pixel_array);
351 // Check whether the elements is a pixel array. 461 // Check whether the elements is a pixel array.
352 // edx: receiver 462 // edx: receiver
353 // eax: key 463 // eax: key
354 // ecx: elements 464 // ecx: elements
355 __ mov(ebx, eax); 465 __ mov(ebx, eax);
356 __ SmiUntag(ebx); 466 __ SmiUntag(ebx);
(...skipping 15 matching lines...) Expand all
372 Label slow_pop_receiver; 482 Label slow_pop_receiver;
373 // Push receiver on the stack to free up a register for the dictionary 483 // Push receiver on the stack to free up a register for the dictionary
374 // probing. 484 // probing.
375 __ push(edx); 485 __ push(edx);
376 GenerateNumberDictionaryLoad(masm, 486 GenerateNumberDictionaryLoad(masm,
377 &slow_pop_receiver, 487 &slow_pop_receiver,
378 ecx, 488 ecx,
379 eax, 489 eax,
380 ebx, 490 ebx,
381 edx, 491 edx,
382 edi); 492 edi,
493 eax);
383 // Pop receiver before returning. 494 // Pop receiver before returning.
384 __ pop(edx); 495 __ pop(edx);
385 __ ret(0); 496 __ ret(0);
386 497
387 __ bind(&slow_pop_receiver); 498 __ bind(&slow_pop_receiver);
388 // Pop the receiver from the stack and jump to runtime. 499 // Pop the receiver from the stack and jump to runtime.
389 __ pop(edx); 500 __ pop(edx);
390 501
391 __ bind(&slow); 502 __ bind(&slow);
392 // Slow case: jump to runtime. 503 // Slow case: jump to runtime.
393 // edx: receiver 504 // edx: receiver
394 // eax: key 505 // eax: key
395 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1); 506 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1);
396 GenerateRuntimeGetProperty(masm); 507 GenerateRuntimeGetProperty(masm);
397 508
398 __ bind(&check_string); 509 __ bind(&check_string);
399 // The key is not a smi. 510 GenerateKeyStringCheck(masm, eax, ecx, ebx, &index_string, &slow);
400 // Is it a string?
401 // edx: receiver
402 // eax: key
403 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, ecx);
404 __ j(above_equal, &slow);
405 // Is the string an array index, with cached numeric value?
406 __ mov(ebx, FieldOperand(eax, String::kHashFieldOffset));
407 __ test(ebx, Immediate(String::kContainsCachedArrayIndexMask));
408 __ j(zero, &index_string, not_taken);
409
410 // Is the string a symbol?
411 // ecx: key map.
412 ASSERT(kSymbolTag != 0);
413 __ test_b(FieldOperand(ecx, Map::kInstanceTypeOffset), kIsSymbolMask);
414 __ j(zero, &slow, not_taken);
415 511
416 // If the receiver is a fast-case object, check the keyed lookup 512 // If the receiver is a fast-case object, check the keyed lookup
417 // cache. Otherwise probe the dictionary. 513 // cache. Otherwise probe the dictionary.
418 __ mov(ebx, FieldOperand(edx, JSObject::kPropertiesOffset)); 514 __ mov(ebx, FieldOperand(edx, JSObject::kPropertiesOffset));
419 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), 515 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
420 Immediate(Factory::hash_table_map())); 516 Immediate(Factory::hash_table_map()));
421 __ j(equal, &probe_dictionary); 517 __ j(equal, &probe_dictionary);
422 518
423 // Load the map of the receiver, compute the keyed lookup cache hash 519 // Load the map of the receiver, compute the keyed lookup cache hash
424 // based on 32 bits of the map pointer and the string hash. 520 // based on 32 bits of the map pointer and the string hash.
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
465 // Do a quick inline probe of the receiver's dictionary, if it 561 // Do a quick inline probe of the receiver's dictionary, if it
466 // exists. 562 // exists.
467 __ bind(&probe_dictionary); 563 __ bind(&probe_dictionary);
468 GenerateDictionaryLoad(masm, 564 GenerateDictionaryLoad(masm,
469 &slow, 565 &slow,
470 edx, 566 edx,
471 eax, 567 eax,
472 ebx, 568 ebx,
473 ecx, 569 ecx,
474 edi, 570 edi,
571 eax,
475 DICTIONARY_CHECK_DONE); 572 DICTIONARY_CHECK_DONE);
476 __ mov(eax, ecx);
477 __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1); 573 __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1);
478 __ ret(0); 574 __ ret(0);
479 575
480 // If the hash field contains an array index pick it out. The assert checks
481 // that the constants for the maximum number of digits for an array index
482 // cached in the hash field and the number of bits reserved for it does not
483 // conflict.
484 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
485 (1 << String::kArrayIndexValueBits));
486 __ bind(&index_string); 576 __ bind(&index_string);
487 // We want the smi-tagged index in eax. kArrayIndexValueMask has zeros in 577 GenerateIndexFromHash(masm, eax, ebx, &index_smi);
488 // the low kHashShift bits.
489 // eax: key (string).
490 // ebx: hash field.
491 // edx: receiver.
492 ASSERT(String::kHashShift >= kSmiTagSize);
493 __ and_(ebx, String::kArrayIndexValueMask);
494 __ shr(ebx, String::kHashShift - kSmiTagSize);
495 // Here we actually clobber the key (eax) which will be used if calling into
496 // runtime later. However as the new key is the numeric value of a string key
497 // there is no difference in using either key.
498 __ mov(eax, ebx);
499 // Now jump to the place where smi keys are handled.
500 __ jmp(&index_smi);
501 } 578 }
502 579
503 580
504 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { 581 void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
505 // ----------- S t a t e ------------- 582 // ----------- S t a t e -------------
506 // -- eax : key (index) 583 // -- eax : key (index)
507 // -- edx : receiver 584 // -- edx : receiver
508 // -- esp[0] : return address 585 // -- esp[0] : return address
509 // ----------------------------------- 586 // -----------------------------------
510 Label miss; 587 Label miss;
(...skipping 597 matching lines...) Expand 10 before | Expand all | Expand 10 after
1108 // -- ecx : name 1185 // -- ecx : name
1109 // -- edx : receiver 1186 // -- edx : receiver
1110 // -- esp[0] : return address 1187 // -- esp[0] : return address
1111 // -- esp[(argc - n) * 4] : arg[n] (zero-based) 1188 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
1112 // -- ... 1189 // -- ...
1113 // -- esp[(argc + 1) * 4] : receiver 1190 // -- esp[(argc + 1) * 4] : receiver
1114 // ----------------------------------- 1191 // -----------------------------------
1115 1192
1116 // Search dictionary - put result in register edi. 1193 // Search dictionary - put result in register edi.
1117 __ mov(edi, edx); 1194 __ mov(edi, edx);
1118 GenerateDictionaryLoad(masm, miss, edx, ecx, eax, edi, ebx, CHECK_DICTIONARY); 1195 GenerateDictionaryLoad(
1196 masm, miss, edx, ecx, eax, edi, ebx, edi, CHECK_DICTIONARY);
1119 1197
1120 // Check that the result is not a smi. 1198 // Check that the result is not a smi.
1121 __ test(edi, Immediate(kSmiTagMask)); 1199 __ test(edi, Immediate(kSmiTagMask));
1122 __ j(zero, miss, not_taken); 1200 __ j(zero, miss, not_taken);
1123 1201
1124 // Check that the value is a JavaScript function, fetching its map into eax. 1202 // Check that the value is a JavaScript function, fetching its map into eax.
1125 __ CmpObjectType(edi, JS_FUNCTION_TYPE, eax); 1203 __ CmpObjectType(edi, JS_FUNCTION_TYPE, eax);
1126 __ j(not_equal, miss, not_taken); 1204 __ j(not_equal, miss, not_taken);
1127 1205
1128 // Patch the receiver on stack with the global proxy if necessary. 1206 // Patch the receiver on stack with the global proxy if necessary.
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
1286 // -- ecx : name 1364 // -- ecx : name
1287 // -- esp[0] : return address 1365 // -- esp[0] : return address
1288 // -- esp[(argc - n) * 4] : arg[n] (zero-based) 1366 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
1289 // -- ... 1367 // -- ...
1290 // -- esp[(argc + 1) * 4] : receiver 1368 // -- esp[(argc + 1) * 4] : receiver
1291 // ----------------------------------- 1369 // -----------------------------------
1292 1370
1293 // Get the receiver of the function from the stack; 1 ~ return address. 1371 // Get the receiver of the function from the stack; 1 ~ return address.
1294 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 1372 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1295 1373
1296 Label miss, skip_probe; 1374 Label do_call, slow_call, slow_load, slow_reload_receiver;
1375 Label check_number_dictionary, check_string, lookup_monomorphic_cache;
1376 Label index_smi, index_string;
1297 1377
1298 // Do not probe monomorphic cache if a key is a smi. 1378 // Check that the key is a smi.
1299 __ test(ecx, Immediate(kSmiTagMask)); 1379 __ test(ecx, Immediate(kSmiTagMask));
1300 __ j(equal, &skip_probe, taken); 1380 __ j(not_zero, &check_string, not_taken);
1301 1381
1302 GenerateMonomorphicCacheProbe(masm, argc, Code::KEYED_CALL_IC, &skip_probe); 1382 __ bind(&index_smi);
1383 // Now the key is known to be a smi. This place is also jumped to from
1384 // where a numeric string is converted to a smi.
1303 1385
1304 __ bind(&skip_probe); 1386 GenerateKeyedLoadReceiverCheck(masm, edx, eax, &slow_call);
1305 1387
1306 __ mov(eax, ecx); 1388 GenerateFastArrayLoad(masm,
1307 __ EnterInternalFrame(); 1389 edx,
1308 __ push(ecx); 1390 ecx,
1309 __ call(Handle<Code>(Builtins::builtin(Builtins::KeyedLoadIC_Generic)), 1391 eax,
1310 RelocInfo::CODE_TARGET); 1392 edi,
1311 __ pop(ecx); 1393 &check_number_dictionary,
1312 __ LeaveInternalFrame(); 1394 &slow_load);
1313 __ mov(edi, eax); 1395 __ IncrementCounter(&Counters::keyed_call_generic_smi_fast, 1);
1314 1396
1315 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 1397 __ bind(&do_call);
1398 // receiver in edx is not used after this point.
1399 // ecx: key
1400 // edi: function
1316 1401
1317 // Check that the receiver isn't a smi. 1402 // Check that the value in edi is a JavaScript function.
1318 __ test(edx, Immediate(kSmiTagMask));
1319 __ j(zero, &miss, not_taken);
1320
1321 // Check that the receiver is a valid JS object.
1322 __ CmpObjectType(edx, FIRST_JS_OBJECT_TYPE, eax);
1323 __ j(below, &miss, not_taken);
1324
1325 // Check that the value is a JavaScript function.
1326 __ test(edi, Immediate(kSmiTagMask)); 1403 __ test(edi, Immediate(kSmiTagMask));
1327 __ j(zero, &miss, not_taken); 1404 __ j(zero, &slow_call, not_taken);
1328 __ CmpObjectType(edi, JS_FUNCTION_TYPE, eax); 1405 __ CmpObjectType(edi, JS_FUNCTION_TYPE, eax);
1329 __ j(not_equal, &miss, not_taken); 1406 __ j(not_equal, &slow_call, not_taken);
1330
1331 // Invoke the function. 1407 // Invoke the function.
1332 ParameterCount actual(argc); 1408 ParameterCount actual(argc);
1333 __ InvokeFunction(edi, actual, JUMP_FUNCTION); 1409 __ InvokeFunction(edi, actual, JUMP_FUNCTION);
1334 1410
1335 __ bind(&miss); 1411 __ bind(&check_number_dictionary);
1412 // eax: elements
1413 // ecx: smi key
1414 // Check whether the elements is a number dictionary.
1415 __ CheckMap(eax, Factory::hash_table_map(), &slow_load, true);
1416 __ mov(ebx, ecx);
1417 __ SmiUntag(ebx);
1418 // ebx: untagged index
1419 // Receiver in edx will be clobbered, need to reload it on miss.
1420 GenerateNumberDictionaryLoad(masm,
1421 &slow_reload_receiver,
1422 eax,
1423 ecx,
1424 ebx,
1425 edx,
1426 edi,
1427 edi);
1428 __ IncrementCounter(&Counters::keyed_call_generic_smi_dict, 1);
1429 __ jmp(&do_call);
1430
1431 __ bind(&slow_reload_receiver);
1432 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1433
1434 __ bind(&slow_load);
1435 // This branch is taken when calling KeyedCallIC_Miss is neither required
1436 // nor beneficial.
1437 __ IncrementCounter(&Counters::keyed_call_generic_slow_load, 1);
1438 __ EnterInternalFrame();
1439 __ push(ecx); // save the key
1440 __ push(edx); // pass the receiver
1441 __ push(ecx); // pass the key
1442 __ CallRuntime(Runtime::kKeyedGetProperty, 2);
1443 __ pop(ecx); // restore the key
1444 __ LeaveInternalFrame();
1445 __ mov(edi, eax);
1446 __ jmp(&do_call);
1447
1448 __ bind(&check_string);
1449 GenerateKeyStringCheck(masm, ecx, eax, ebx, &index_string, &slow_call);
1450
1451 // The key is known to be a symbol.
1452 // If the receiver is a regular JS object with slow properties then do
1453 // a quick inline probe of the receiver's dictionary.
1454 // Otherwise do the monomorphic cache probe.
1455 GenerateKeyedLoadReceiverCheck(masm, edx, eax, &lookup_monomorphic_cache);
1456
1457 __ mov(ebx, FieldOperand(edx, JSObject::kPropertiesOffset));
1458 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
1459 Immediate(Factory::hash_table_map()));
1460 __ j(not_equal, &lookup_monomorphic_cache, not_taken);
1461
1462 GenerateDictionaryLoad(masm,
1463 &slow_load,
1464 edx,
1465 ecx,
1466 ebx,
1467 eax,
1468 edi,
1469 edi,
1470 DICTIONARY_CHECK_DONE);
1471 __ IncrementCounter(&Counters::keyed_call_generic_lookup_dict, 1);
1472 __ jmp(&do_call);
1473
1474 __ bind(&lookup_monomorphic_cache);
1475 __ IncrementCounter(&Counters::keyed_call_generic_lookup_cache, 1);
1476 GenerateMonomorphicCacheProbe(masm, argc, Code::KEYED_CALL_IC, &slow_call);
1477 // Fall through on miss.
1478
1479 __ bind(&slow_call);
1480 // This branch is taken if:
1481 // - the receiver requires boxing or access check,
1482 // - the key is neither smi nor symbol,
1483 // - the value loaded is not a function,
1484 // - there is hope that the runtime will create a monomorphic call stub
1485 // that will get fetched next time.
1486 __ IncrementCounter(&Counters::keyed_call_generic_slow, 1);
1336 GenerateMiss(masm, argc); 1487 GenerateMiss(masm, argc);
1488
1489 __ bind(&index_string);
1490 GenerateIndexFromHash(masm, ecx, ebx, &index_smi);
1337 } 1491 }
1338 1492
1339 1493
1340 void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) { 1494 void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) {
1341 Label miss; 1495 Label miss;
1342 GenerateCallNormal(masm, argc, &miss); 1496 GenerateCallNormal(masm, argc, &miss);
1343 __ bind(&miss); 1497 __ bind(&miss);
1344 GenerateMiss(masm, argc); 1498 GenerateMiss(masm, argc);
1345 } 1499 }
1346 1500
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
1403 1557
1404 // Search the dictionary placing the result in eax. 1558 // Search the dictionary placing the result in eax.
1405 __ bind(&probe); 1559 __ bind(&probe);
1406 GenerateDictionaryLoad(masm, 1560 GenerateDictionaryLoad(masm,
1407 &miss, 1561 &miss,
1408 eax, 1562 eax,
1409 ecx, 1563 ecx,
1410 edx, 1564 edx,
1411 edi, 1565 edi,
1412 ebx, 1566 ebx,
1567 edi,
1413 CHECK_DICTIONARY); 1568 CHECK_DICTIONARY);
1414 __ mov(eax, edi); 1569 __ mov(eax, edi);
1415 __ ret(0); 1570 __ ret(0);
1416 1571
1417 // Global object access: Check access rights. 1572 // Global object access: Check access rights.
1418 __ bind(&global); 1573 __ bind(&global);
1419 __ CheckAccessGlobalProxy(eax, edx, &miss); 1574 __ CheckAccessGlobalProxy(eax, edx, &miss);
1420 __ jmp(&probe); 1575 __ jmp(&probe);
1421 1576
1422 // Cache miss: Jump to runtime. 1577 // Cache miss: Jump to runtime.
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after
1706 ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss)); 1861 ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss));
1707 __ TailCallExternalReference(ref, 3, 1); 1862 __ TailCallExternalReference(ref, 3, 1);
1708 } 1863 }
1709 1864
1710 #undef __ 1865 #undef __
1711 1866
1712 1867
1713 } } // namespace v8::internal 1868 } } // namespace v8::internal
1714 1869
1715 #endif // V8_TARGET_ARCH_IA32 1870 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « no previous file | src/ic.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698