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

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

Issue 2470001: Change keyed load IC interface on x64 to pass arguments in registers. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/x64/full-codegen-x64.cc ('k') | src/x64/stub-cache-x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after
306 306
307 void KeyedStoreIC::RestoreInlinedVersion(Address address) { 307 void KeyedStoreIC::RestoreInlinedVersion(Address address) {
308 // Restore the fast-case elements map check so that the inlined 308 // Restore the fast-case elements map check so that the inlined
309 // version can be used again. 309 // version can be used again.
310 PatchInlinedStore(address, Heap::fixed_array_map()); 310 PatchInlinedStore(address, Heap::fixed_array_map());
311 } 311 }
312 312
313 313
314 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { 314 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
315 // ----------- S t a t e ------------- 315 // ----------- S t a t e -------------
316 // -- rax : key
317 // -- rdx : receiver
316 // -- rsp[0] : return address 318 // -- rsp[0] : return address
317 // -- rsp[8] : name
318 // -- rsp[16] : receiver
319 // ----------------------------------- 319 // -----------------------------------
320 320
321 __ pop(rbx); 321 __ pop(rbx);
322 __ push(Operand(rsp, 1 * kPointerSize)); // receiver 322 __ push(rdx); // receiver
323 __ push(Operand(rsp, 1 * kPointerSize)); // name 323 __ push(rax); // name
324 __ push(rbx); // return address 324 __ push(rbx); // return address
325 325
326 // Perform tail call to the entry. 326 // Perform tail call to the entry.
327 ExternalReference ref = ExternalReference(IC_Utility(kKeyedLoadIC_Miss)); 327 ExternalReference ref = ExternalReference(IC_Utility(kKeyedLoadIC_Miss));
328 __ TailCallExternalReference(ref, 2, 1); 328 __ TailCallExternalReference(ref, 2, 1);
329 } 329 }
330 330
331 331
332 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { 332 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
333 // ----------- S t a t e ------------- 333 // ----------- S t a t e -------------
334 // -- rax : key
335 // -- rdx : receiver
334 // -- rsp[0] : return address 336 // -- rsp[0] : return address
335 // -- rsp[8] : name
336 // -- rsp[16] : receiver
337 // ----------------------------------- 337 // -----------------------------------
338 338
339 __ pop(rbx); 339 __ pop(rbx);
340 __ push(Operand(rsp, 1 * kPointerSize)); // receiver 340 __ push(rdx); // receiver
341 __ push(Operand(rsp, 1 * kPointerSize)); // name 341 __ push(rax); // name
342 __ push(rbx); // return address 342 __ push(rbx); // return address
343 343
344 // Perform tail call to the entry. 344 // Perform tail call to the entry.
345 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); 345 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
346 } 346 }
347 347
348 348
349 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { 349 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
350 // ----------- S t a t e ------------- 350 // ----------- S t a t e -------------
351 // -- rax : key
352 // -- rdx : receiver
351 // -- rsp[0] : return address 353 // -- rsp[0] : return address
352 // -- rsp[8] : name
353 // -- rsp[16] : receiver
354 // ----------------------------------- 354 // -----------------------------------
355 Label slow, check_string, index_smi, index_string; 355 Label slow, check_string, index_smi, index_string;
356 Label check_pixel_array, probe_dictionary, check_number_dictionary; 356 Label check_pixel_array, probe_dictionary, check_number_dictionary;
357 357
358 // Load name and receiver.
359 __ movq(rax, Operand(rsp, kPointerSize));
360 __ movq(rcx, Operand(rsp, 2 * kPointerSize));
361
362 // Check that the object isn't a smi. 358 // Check that the object isn't a smi.
363 __ JumpIfSmi(rcx, &slow); 359 __ JumpIfSmi(rdx, &slow);
364 360
365 // Check that the object is some kind of JS object EXCEPT JS Value type. 361 // Check that the object is some kind of JS object EXCEPT JS Value type.
366 // In the case that the object is a value-wrapper object, 362 // In the case that the object is a value-wrapper object,
367 // we enter the runtime system to make sure that indexing 363 // we enter the runtime system to make sure that indexing
368 // into string objects work as intended. 364 // into string objects work as intended.
369 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE); 365 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE);
370 __ CmpObjectType(rcx, JS_OBJECT_TYPE, rdx); 366 __ CmpObjectType(rdx, JS_OBJECT_TYPE, rcx);
371 __ j(below, &slow); 367 __ j(below, &slow);
372 368
373 // Check bit field. 369 // Check bit field.
374 __ testb(FieldOperand(rdx, Map::kBitFieldOffset), 370 __ testb(FieldOperand(rcx, Map::kBitFieldOffset),
375 Immediate(kSlowCaseBitFieldMask)); 371 Immediate(kSlowCaseBitFieldMask));
376 __ j(not_zero, &slow); 372 __ j(not_zero, &slow);
377 373
378 // Check that the key is a smi. 374 // Check that the key is a smi.
379 __ JumpIfNotSmi(rax, &check_string); 375 __ JumpIfNotSmi(rax, &check_string);
380 __ bind(&index_smi); 376 __ bind(&index_smi);
381 // Now the key is known to be a smi. This place is also jumped to from below 377 // Now the key is known to be a smi. This place is also jumped to from below
382 // where a numeric string is converted to a smi. 378 // where a numeric string is converted to a smi.
383 __ movq(rcx, FieldOperand(rcx, JSObject::kElementsOffset)); 379 __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset));
384 // Check that the object is in fast mode (not dictionary). 380 // Check that the object is in fast mode (not dictionary).
385 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), 381 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset),
386 Heap::kFixedArrayMapRootIndex); 382 Heap::kFixedArrayMapRootIndex);
387 __ j(not_equal, &check_pixel_array); 383 __ j(not_equal, &check_pixel_array);
388 // Check that the key (index) is within bounds. 384 // Check that the key (index) is within bounds.
389 __ SmiCompare(rax, FieldOperand(rcx, FixedArray::kLengthOffset)); 385 __ SmiCompare(rax, FieldOperand(rcx, FixedArray::kLengthOffset));
390 __ j(above_equal, &slow); // Unsigned comparison rejects negative indices. 386 __ j(above_equal, &slow); // Unsigned comparison rejects negative indices.
391 // Fast case: Do the load. 387 // Fast case: Do the load.
392 SmiIndex index = masm->SmiToIndex(rax, rax, kPointerSizeLog2); 388 SmiIndex index = masm->SmiToIndex(rbx, rax, kPointerSizeLog2);
393 __ movq(rax, FieldOperand(rcx, 389 __ movq(rbx, FieldOperand(rcx,
394 index.reg, 390 index.reg,
395 index.scale, 391 index.scale,
396 FixedArray::kHeaderSize)); 392 FixedArray::kHeaderSize));
397 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); 393 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
398 // In case the loaded value is the_hole we have to consult GetProperty 394 // In case the loaded value is the_hole we have to consult GetProperty
399 // to ensure the prototype chain is searched. 395 // to ensure the prototype chain is searched.
400 __ j(equal, &slow); 396 __ j(equal, &slow);
397 __ movq(rax, rbx);
401 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1); 398 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1);
402 __ ret(0); 399 __ ret(0);
403 400
404 // Check whether the elements is a pixel array. 401 __ bind(&check_pixel_array);
402 // Check whether the elements object is a pixel array.
403 // rdx: receiver
405 // rax: key 404 // rax: key
406 // rcx: elements array 405 // rcx: elements array
407 __ bind(&check_pixel_array); 406 __ SmiToInteger32(rbx, rax); // Used on both directions of next branch.
408 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), 407 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset),
409 Heap::kPixelArrayMapRootIndex); 408 Heap::kPixelArrayMapRootIndex);
410 __ j(not_equal, &check_number_dictionary); 409 __ j(not_equal, &check_number_dictionary);
411 __ SmiToInteger32(rax, rax); 410 __ cmpl(rbx, FieldOperand(rcx, PixelArray::kLengthOffset));
412 __ cmpl(rax, FieldOperand(rcx, PixelArray::kLengthOffset));
413 __ j(above_equal, &slow); 411 __ j(above_equal, &slow);
414 __ movq(rcx, FieldOperand(rcx, PixelArray::kExternalPointerOffset)); 412 __ movq(rax, FieldOperand(rcx, PixelArray::kExternalPointerOffset));
415 __ movzxbq(rax, Operand(rcx, rax, times_1, 0)); 413 __ movzxbq(rax, Operand(rax, rbx, times_1, 0));
416 __ Integer32ToSmi(rax, rax); 414 __ Integer32ToSmi(rax, rax);
417 __ ret(0); 415 __ ret(0);
418 416
419 __ bind(&check_number_dictionary); 417 __ bind(&check_number_dictionary);
420 // Check whether the elements is a number dictionary. 418 // Check whether the elements is a number dictionary.
419 // rdx: receiver
421 // rax: key 420 // rax: key
421 // rbx: key as untagged int32
422 // rcx: elements 422 // rcx: elements
423 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), 423 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset),
424 Heap::kHashTableMapRootIndex); 424 Heap::kHashTableMapRootIndex);
425 __ j(not_equal, &slow); 425 __ j(not_equal, &slow);
426 __ SmiToInteger32(rbx, rax); 426 GenerateNumberDictionaryLoad(masm, &slow, rcx, rax, rbx, r9, rdi);
427 GenerateNumberDictionaryLoad(masm, &slow, rcx, rax, rbx, rdx, rdi);
428 __ ret(0); 427 __ ret(0);
429 428
430 // Slow case: Load name and receiver from stack and jump to runtime.
431 __ bind(&slow); 429 __ bind(&slow);
430 // Slow case: Jump to runtime.
431 // rdx: receiver
432 // rax: key
432 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1); 433 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1);
433 GenerateRuntimeGetProperty(masm); 434 GenerateRuntimeGetProperty(masm);
435
434 __ bind(&check_string); 436 __ bind(&check_string);
435 // The key is not a smi. 437 // The key is not a smi.
436 // Is it a string? 438 // Is it a string?
437 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdx); 439 // rdx: receiver
440 // rax: key
441 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rcx);
438 __ j(above_equal, &slow); 442 __ j(above_equal, &slow);
439 // Is the string an array index, with cached numeric value? 443 // Is the string an array index, with cached numeric value?
440 __ movl(rbx, FieldOperand(rax, String::kHashFieldOffset)); 444 __ movl(rbx, FieldOperand(rax, String::kHashFieldOffset));
441 __ testl(rbx, Immediate(String::kIsArrayIndexMask)); 445 __ testl(rbx, Immediate(String::kIsArrayIndexMask));
446 __ j(not_zero, &index_string); // The value in rbx is used at jump target.
442 447
443 // Is the string a symbol? 448 // Is the string a symbol?
444 // rcx: key map.
445 __ j(not_zero, &index_string); // The value in rbx is used at jump target.
446 ASSERT(kSymbolTag != 0); 449 ASSERT(kSymbolTag != 0);
447 __ testb(FieldOperand(rdx, Map::kInstanceTypeOffset), 450 __ testb(FieldOperand(rcx, Map::kInstanceTypeOffset),
448 Immediate(kIsSymbolMask)); 451 Immediate(kIsSymbolMask));
449 __ j(zero, &slow); 452 __ j(zero, &slow);
450 453
451 // If the receiver is a fast-case object, check the keyed lookup 454 // If the receiver is a fast-case object, check the keyed lookup
452 // cache. Otherwise probe the dictionary leaving result in rcx. 455 // cache. Otherwise probe the dictionary leaving result in rcx.
453 __ movq(rbx, FieldOperand(rcx, JSObject::kPropertiesOffset)); 456 __ movq(rbx, FieldOperand(rdx, JSObject::kPropertiesOffset));
454 __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset), Factory::hash_table_map()); 457 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
458 Heap::kHashTableMapRootIndex);
455 __ j(equal, &probe_dictionary); 459 __ j(equal, &probe_dictionary);
456 460
457 // Load the map of the receiver, compute the keyed lookup cache hash 461 // Load the map of the receiver, compute the keyed lookup cache hash
458 // based on 32 bits of the map pointer and the string hash. 462 // based on 32 bits of the map pointer and the string hash.
459 __ movq(rbx, FieldOperand(rcx, HeapObject::kMapOffset)); 463 __ movq(rbx, FieldOperand(rdx, HeapObject::kMapOffset));
460 __ movl(rdx, rbx); 464 __ movl(rcx, rbx);
461 __ shr(rdx, Immediate(KeyedLookupCache::kMapHashShift)); 465 __ shr(rcx, Immediate(KeyedLookupCache::kMapHashShift));
462 __ movl(rax, FieldOperand(rax, String::kHashFieldOffset)); 466 __ movl(rdi, FieldOperand(rax, String::kHashFieldOffset));
463 __ shr(rax, Immediate(String::kHashShift)); 467 __ shr(rdi, Immediate(String::kHashShift));
464 __ xor_(rdx, rax); 468 __ xor_(rcx, rdi);
465 __ and_(rdx, Immediate(KeyedLookupCache::kCapacityMask)); 469 __ and_(rcx, Immediate(KeyedLookupCache::kCapacityMask));
466 470
467 // Load the key (consisting of map and symbol) from the cache and 471 // Load the key (consisting of map and symbol) from the cache and
468 // check for match. 472 // check for match.
469 ExternalReference cache_keys 473 ExternalReference cache_keys
470 = ExternalReference::keyed_lookup_cache_keys(); 474 = ExternalReference::keyed_lookup_cache_keys();
471 __ movq(rdi, rdx); 475 __ movq(rdi, rcx);
472 __ shl(rdi, Immediate(kPointerSizeLog2 + 1)); 476 __ shl(rdi, Immediate(kPointerSizeLog2 + 1));
473 __ movq(kScratchRegister, cache_keys); 477 __ movq(kScratchRegister, cache_keys);
474 __ cmpq(rbx, Operand(kScratchRegister, rdi, times_1, 0)); 478 __ cmpq(rbx, Operand(kScratchRegister, rdi, times_1, 0));
475 __ j(not_equal, &slow); 479 __ j(not_equal, &slow);
476 __ movq(rdi, Operand(kScratchRegister, rdi, times_1, kPointerSize)); 480 __ cmpq(rax, Operand(kScratchRegister, rdi, times_1, kPointerSize));
477 __ cmpq(Operand(rsp, kPointerSize), rdi);
478 __ j(not_equal, &slow); 481 __ j(not_equal, &slow);
479 482
480 // Get field offset which is a 32-bit integer and check that it is 483 // Get field offset which is a 32-bit integer and check that it is
481 // an in-object property. 484 // an in-object property.
482 ExternalReference cache_field_offsets 485 ExternalReference cache_field_offsets
483 = ExternalReference::keyed_lookup_cache_field_offsets(); 486 = ExternalReference::keyed_lookup_cache_field_offsets();
484 __ movq(kScratchRegister, cache_field_offsets); 487 __ movq(kScratchRegister, cache_field_offsets);
485 __ movl(rax, Operand(kScratchRegister, rdx, times_4, 0)); 488 __ movl(rdi, Operand(kScratchRegister, rcx, times_4, 0));
486 __ movzxbq(rdx, FieldOperand(rbx, Map::kInObjectPropertiesOffset)); 489 __ movzxbq(rcx, FieldOperand(rbx, Map::kInObjectPropertiesOffset));
487 __ cmpq(rax, rdx); 490 __ subq(rdi, rcx);
488 __ j(above_equal, &slow); 491 __ j(above_equal, &slow);
489 492
490 // Load in-object property. 493 // Load in-object property.
491 __ subq(rax, rdx); 494 __ movzxbq(rcx, FieldOperand(rbx, Map::kInstanceSizeOffset));
492 __ movzxbq(rdx, FieldOperand(rbx, Map::kInstanceSizeOffset)); 495 __ addq(rcx, rdi);
493 __ addq(rax, rdx); 496 __ movq(rax, FieldOperand(rdx, rcx, times_pointer_size, 0));
494 __ movq(rax, FieldOperand(rcx, rax, times_pointer_size, 0));
495 __ IncrementCounter(&Counters::keyed_load_generic_lookup_cache, 1); 497 __ IncrementCounter(&Counters::keyed_load_generic_lookup_cache, 1);
496 __ ret(0); 498 __ ret(0);
497 499
498 // Do a quick inline probe of the receiver's dictionary, if it 500 // Do a quick inline probe of the receiver's dictionary, if it
499 // exists. 501 // exists.
500 __ bind(&probe_dictionary); 502 __ bind(&probe_dictionary);
503 // rdx: receiver
504 // rax: key
501 GenerateDictionaryLoad(masm, 505 GenerateDictionaryLoad(masm,
502 &slow, 506 &slow,
503 rbx, 507 rbx,
508 rdx,
504 rcx, 509 rcx,
505 rdx,
506 rax, 510 rax,
507 rdi, 511 rdi,
508 DICTIONARY_CHECK_DONE); 512 DICTIONARY_CHECK_DONE);
509 __ movq(rax, rcx); 513 __ movq(rax, rdx);
510 __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1); 514 __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1);
511 __ ret(0); 515 __ ret(0);
512 // If the hash field contains an array index pick it out. The assert checks 516 // If the hash field contains an array index pick it out. The assert checks
513 // that the constants for the maximum number of digits for an array index 517 // that the constants for the maximum number of digits for an array index
514 // cached in the hash field and the number of bits reserved for it does not 518 // cached in the hash field and the number of bits reserved for it does not
515 // conflict. 519 // conflict.
516 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) < 520 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
517 (1 << String::kArrayIndexValueBits)); 521 (1 << String::kArrayIndexValueBits));
518 __ bind(&index_string); 522 __ bind(&index_string);
519 // We want the smi-tagged index in rax. 523 // We want the smi-tagged index in rax. Even if we subsequently go to
520 // rax: key (string). 524 // the slow case, converting the key to a smi is always valid.
521 // rbx: hash field. 525 // rdx: receiver
522 // rdx: receiver. 526 // rax: key (a string)
527 // rbx: key's hash field, including its array index value.
523 __ and_(rbx, Immediate(String::kArrayIndexValueMask)); 528 __ and_(rbx, Immediate(String::kArrayIndexValueMask));
524 __ shr(rbx, Immediate(String::kHashShift)); 529 __ shr(rbx, Immediate(String::kHashShift));
525 // Here we actually clobber the key (rax) which will be used if calling into 530 // Here we actually clobber the key (rax) which will be used if calling into
526 // runtime later. However as the new key is the numeric value of a string key 531 // runtime later. However as the new key is the numeric value of a string key
527 // there is no difference in using either key. 532 // there is no difference in using either key.
528 __ Integer32ToSmi(rax, rbx); 533 __ Integer32ToSmi(rax, rbx);
529 // Now jump to the place where smi keys are handled. 534 // Now jump to the place where smi keys are handled.
530 __ jmp(&index_smi); 535 __ jmp(&index_smi);
531 } 536 }
532 537
533 538
534 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { 539 void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
535 // ----------- S t a t e ------------- 540 // ----------- S t a t e -------------
541 // -- rax : key
542 // -- rdx : receiver
536 // -- rsp[0] : return address 543 // -- rsp[0] : return address
537 // -- rsp[8] : name (index)
538 // -- rsp[16] : receiver
539 // ----------------------------------- 544 // -----------------------------------
540 Label miss; 545 Label miss;
541 Label index_out_of_range; 546 Label index_out_of_range;
542 547
543 Register receiver = rdx; 548 Register receiver = rdx;
544 Register index = rax; 549 Register index = rax;
545 Register scratch1 = rbx; 550 Register scratch1 = rbx;
546 Register scratch2 = rcx; 551 Register scratch2 = rcx;
547 Register result = rax; 552 Register result = rax;
548 553
549 __ movq(index, Operand(rsp, 1 * kPointerSize));
550 __ movq(receiver, Operand(rsp, 2 * kPointerSize));
551
552 StringCharAtGenerator char_at_generator(receiver, 554 StringCharAtGenerator char_at_generator(receiver,
553 index, 555 index,
554 scratch1, 556 scratch1,
555 scratch2, 557 scratch2,
556 result, 558 result,
557 &miss, // When not a string. 559 &miss, // When not a string.
558 &miss, // When not a number. 560 &miss, // When not a number.
559 &index_out_of_range, 561 &index_out_of_range,
560 STRING_INDEX_IS_ARRAY_INDEX); 562 STRING_INDEX_IS_ARRAY_INDEX);
561 char_at_generator.GenerateFast(masm); 563 char_at_generator.GenerateFast(masm);
562 __ ret(0); 564 __ ret(0);
563 565
564 ICRuntimeCallHelper call_helper; 566 ICRuntimeCallHelper call_helper;
565 char_at_generator.GenerateSlow(masm, call_helper); 567 char_at_generator.GenerateSlow(masm, call_helper);
566 568
567 __ bind(&index_out_of_range); 569 __ bind(&index_out_of_range);
568 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 570 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
569 __ ret(0); 571 __ ret(0);
570 572
571 __ bind(&miss); 573 __ bind(&miss);
572 GenerateMiss(masm); 574 GenerateMiss(masm);
573 } 575 }
574 576
575 577
576 void KeyedLoadIC::GenerateExternalArray(MacroAssembler* masm, 578 void KeyedLoadIC::GenerateExternalArray(MacroAssembler* masm,
577 ExternalArrayType array_type) { 579 ExternalArrayType array_type) {
578 // ----------- S t a t e ------------- 580 // ----------- S t a t e -------------
581 // -- rax : key
582 // -- rdx : receiver
579 // -- rsp[0] : return address 583 // -- rsp[0] : return address
580 // -- rsp[8] : name
581 // -- rsp[16] : receiver
582 // ----------------------------------- 584 // -----------------------------------
583 Label slow, failed_allocation; 585 Label slow, failed_allocation;
584 586
585 // Load name and receiver.
586 __ movq(rax, Operand(rsp, kPointerSize));
587 __ movq(rcx, Operand(rsp, 2 * kPointerSize));
588
589 // Check that the object isn't a smi. 587 // Check that the object isn't a smi.
590 __ JumpIfSmi(rcx, &slow); 588 __ JumpIfSmi(rdx, &slow);
591 589
592 // Check that the key is a smi. 590 // Check that the key is a smi.
593 __ JumpIfNotSmi(rax, &slow); 591 __ JumpIfNotSmi(rax, &slow);
594 592
595 // Check that the object is a JS object. 593 // Check that the object is a JS object.
596 __ CmpObjectType(rcx, JS_OBJECT_TYPE, rdx); 594 __ CmpObjectType(rdx, JS_OBJECT_TYPE, rcx);
597 __ j(not_equal, &slow); 595 __ j(not_equal, &slow);
598 // Check that the receiver does not require access checks. We need 596 // Check that the receiver does not require access checks. We need
599 // to check this explicitly since this generic stub does not perform 597 // to check this explicitly since this generic stub does not perform
600 // map checks. The map is already in rdx. 598 // map checks. The map is already in rdx.
601 __ testb(FieldOperand(rdx, Map::kBitFieldOffset), 599 __ testb(FieldOperand(rcx, Map::kBitFieldOffset),
602 Immediate(1 << Map::kIsAccessCheckNeeded)); 600 Immediate(1 << Map::kIsAccessCheckNeeded));
603 __ j(not_zero, &slow); 601 __ j(not_zero, &slow);
604 602
605 // Check that the elements array is the appropriate type of 603 // Check that the elements array is the appropriate type of
606 // ExternalArray. 604 // ExternalArray.
607 // rax: index (as a smi) 605 // rax: index (as a smi)
608 // rcx: JSObject 606 // rdx: JSObject
609 __ movq(rcx, FieldOperand(rcx, JSObject::kElementsOffset)); 607 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
610 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), 608 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
611 Heap::RootIndexForExternalArrayType(array_type)); 609 Heap::RootIndexForExternalArrayType(array_type));
612 __ j(not_equal, &slow); 610 __ j(not_equal, &slow);
613 611
614 // Check that the index is in range. 612 // Check that the index is in range.
615 __ SmiToInteger32(rax, rax); 613 __ SmiToInteger32(rcx, rax);
616 __ cmpl(rax, FieldOperand(rcx, ExternalArray::kLengthOffset)); 614 __ cmpl(rcx, FieldOperand(rbx, ExternalArray::kLengthOffset));
617 // Unsigned comparison catches both negative and too-large values. 615 // Unsigned comparison catches both negative and too-large values.
618 __ j(above_equal, &slow); 616 __ j(above_equal, &slow);
619 617
620 // rax: untagged index 618 // rax: index (as a smi)
621 // rcx: elements array 619 // rdx: receiver (JSObject)
622 __ movq(rcx, FieldOperand(rcx, ExternalArray::kExternalPointerOffset)); 620 // rcx: untagged index
623 // rcx: base pointer of external storage 621 // rbx: elements array
622 __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset));
623 // rbx: base pointer of external storage
624 switch (array_type) { 624 switch (array_type) {
625 case kExternalByteArray: 625 case kExternalByteArray:
626 __ movsxbq(rax, Operand(rcx, rax, times_1, 0)); 626 __ movsxbq(rcx, Operand(rbx, rcx, times_1, 0));
627 break; 627 break;
628 case kExternalUnsignedByteArray: 628 case kExternalUnsignedByteArray:
629 __ movzxbq(rax, Operand(rcx, rax, times_1, 0)); 629 __ movzxbq(rcx, Operand(rbx, rcx, times_1, 0));
630 break; 630 break;
631 case kExternalShortArray: 631 case kExternalShortArray:
632 __ movsxwq(rax, Operand(rcx, rax, times_2, 0)); 632 __ movsxwq(rcx, Operand(rbx, rcx, times_2, 0));
633 break; 633 break;
634 case kExternalUnsignedShortArray: 634 case kExternalUnsignedShortArray:
635 __ movzxwq(rax, Operand(rcx, rax, times_2, 0)); 635 __ movzxwq(rcx, Operand(rbx, rcx, times_2, 0));
636 break; 636 break;
637 case kExternalIntArray: 637 case kExternalIntArray:
638 __ movsxlq(rax, Operand(rcx, rax, times_4, 0)); 638 __ movsxlq(rcx, Operand(rbx, rcx, times_4, 0));
639 break; 639 break;
640 case kExternalUnsignedIntArray: 640 case kExternalUnsignedIntArray:
641 __ movl(rax, Operand(rcx, rax, times_4, 0)); 641 __ movl(rcx, Operand(rbx, rcx, times_4, 0));
642 break; 642 break;
643 case kExternalFloatArray: 643 case kExternalFloatArray:
644 __ fld_s(Operand(rcx, rax, times_4, 0)); 644 __ fld_s(Operand(rbx, rcx, times_4, 0));
645 break; 645 break;
646 default: 646 default:
647 UNREACHABLE(); 647 UNREACHABLE();
648 break; 648 break;
649 } 649 }
650 650
651 // rax: index
652 // rdx: receiver
651 // For integer array types: 653 // For integer array types:
652 // rax: value 654 // rcx: value
653 // For floating-point array type: 655 // For floating-point array type:
654 // FP(0): value 656 // FP(0): value
655 657
656 if (array_type == kExternalIntArray || 658 if (array_type == kExternalIntArray ||
657 array_type == kExternalUnsignedIntArray) { 659 array_type == kExternalUnsignedIntArray) {
658 // For the Int and UnsignedInt array types, we need to see whether 660 // For the Int and UnsignedInt array types, we need to see whether
659 // the value can be represented in a Smi. If not, we need to convert 661 // the value can be represented in a Smi. If not, we need to convert
660 // it to a HeapNumber. 662 // it to a HeapNumber.
661 Label box_int; 663 Label box_int;
662 if (array_type == kExternalIntArray) { 664 if (array_type == kExternalIntArray) {
663 __ JumpIfNotValidSmiValue(rax, &box_int); 665 __ JumpIfNotValidSmiValue(rcx, &box_int);
664 } else { 666 } else {
665 ASSERT_EQ(array_type, kExternalUnsignedIntArray); 667 ASSERT_EQ(array_type, kExternalUnsignedIntArray);
666 __ JumpIfUIntNotValidSmiValue(rax, &box_int); 668 __ JumpIfUIntNotValidSmiValue(rcx, &box_int);
667 } 669 }
668 670
669 __ Integer32ToSmi(rax, rax); 671 __ Integer32ToSmi(rax, rcx);
670 __ ret(0); 672 __ ret(0);
671 673
672 __ bind(&box_int); 674 __ bind(&box_int);
673 675
674 // Allocate a HeapNumber for the int and perform int-to-double 676 // Allocate a HeapNumber for the int and perform int-to-double
675 // conversion. 677 // conversion.
676 __ push(rax); 678 __ push(rcx);
677 if (array_type == kExternalIntArray) { 679 if (array_type == kExternalIntArray) {
678 __ fild_s(Operand(rsp, 0)); 680 __ fild_s(Operand(rsp, 0));
679 } else { 681 } else {
680 ASSERT(array_type == kExternalUnsignedIntArray); 682 ASSERT(array_type == kExternalUnsignedIntArray);
681 // Need to zero-extend the value. 683 // The value is zero-extended on the stack, because all pushes are
684 // 64-bit and we loaded the value from memory with movl.
682 __ fild_d(Operand(rsp, 0)); 685 __ fild_d(Operand(rsp, 0));
683 } 686 }
684 __ pop(rax); 687 __ pop(rcx);
685 // FP(0): value 688 // FP(0): value
686 __ AllocateHeapNumber(rax, rbx, &failed_allocation); 689 __ AllocateHeapNumber(rcx, rbx, &failed_allocation);
687 // Set the value. 690 // Set the value.
691 __ movq(rax, rcx);
688 __ fstp_d(FieldOperand(rax, HeapNumber::kValueOffset)); 692 __ fstp_d(FieldOperand(rax, HeapNumber::kValueOffset));
689 __ ret(0); 693 __ ret(0);
690 } else if (array_type == kExternalFloatArray) { 694 } else if (array_type == kExternalFloatArray) {
691 // For the floating-point array type, we need to always allocate a 695 // For the floating-point array type, we need to always allocate a
692 // HeapNumber. 696 // HeapNumber.
693 __ AllocateHeapNumber(rax, rbx, &failed_allocation); 697 __ AllocateHeapNumber(rcx, rbx, &failed_allocation);
694 // Set the value. 698 // Set the value.
699 __ movq(rax, rcx);
695 __ fstp_d(FieldOperand(rax, HeapNumber::kValueOffset)); 700 __ fstp_d(FieldOperand(rax, HeapNumber::kValueOffset));
696 __ ret(0); 701 __ ret(0);
697 } else { 702 } else {
698 __ Integer32ToSmi(rax, rax); 703 __ Integer32ToSmi(rax, rcx);
699 __ ret(0); 704 __ ret(0);
700 } 705 }
701 706
702 // If we fail allocation of the HeapNumber, we still have a value on 707 // If we fail allocation of the HeapNumber, we still have a value on
703 // top of the FPU stack. Remove it. 708 // top of the FPU stack. Remove it.
704 __ bind(&failed_allocation); 709 __ bind(&failed_allocation);
705 __ ffree(); 710 __ ffree();
706 __ fincstp(); 711 __ fincstp();
707 // Fall through to slow case. 712 // Fall through to slow case.
708 713
709 // Slow case: Load name and receiver from stack and jump to runtime. 714 // Slow case: Jump to runtime.
710 __ bind(&slow); 715 __ bind(&slow);
711 __ IncrementCounter(&Counters::keyed_load_external_array_slow, 1); 716 __ IncrementCounter(&Counters::keyed_load_external_array_slow, 1);
712 GenerateRuntimeGetProperty(masm); 717 GenerateRuntimeGetProperty(masm);
713 } 718 }
714 719
715 720
716 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { 721 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
717 // ----------- S t a t e ------------- 722 // ----------- S t a t e -------------
723 // -- rax : key
724 // -- rdx : receiver
718 // -- rsp[0] : return address 725 // -- rsp[0] : return address
719 // -- rsp[8] : key
720 // -- rsp[16] : receiver
721 // ----------------------------------- 726 // -----------------------------------
722 Label slow; 727 Label slow;
723 728
724 // Load key and receiver.
725 __ movq(rax, Operand(rsp, kPointerSize));
726 __ movq(rcx, Operand(rsp, 2 * kPointerSize));
727
728 // Check that the receiver isn't a smi. 729 // Check that the receiver isn't a smi.
729 __ JumpIfSmi(rcx, &slow); 730 __ JumpIfSmi(rdx, &slow);
730 731
731 // Check that the key is a smi. 732 // Check that the key is a smi.
732 __ JumpIfNotSmi(rax, &slow); 733 __ JumpIfNotSmi(rax, &slow);
733 734
734 // Get the map of the receiver. 735 // Get the map of the receiver.
735 __ movq(rdx, FieldOperand(rcx, HeapObject::kMapOffset)); 736 __ movq(rcx, FieldOperand(rdx, HeapObject::kMapOffset));
736 737
737 // Check that it has indexed interceptor and access checks 738 // Check that it has indexed interceptor and access checks
738 // are not enabled for this object. 739 // are not enabled for this object.
739 __ movb(rdx, FieldOperand(rdx, Map::kBitFieldOffset)); 740 __ movb(rcx, FieldOperand(rcx, Map::kBitFieldOffset));
740 __ andb(rdx, Immediate(kSlowCaseBitFieldMask)); 741 __ andb(rcx, Immediate(kSlowCaseBitFieldMask));
741 __ cmpb(rdx, Immediate(1 << Map::kHasIndexedInterceptor)); 742 __ cmpb(rcx, Immediate(1 << Map::kHasIndexedInterceptor));
742 __ j(not_zero, &slow); 743 __ j(not_zero, &slow);
743 744
744 // Everything is fine, call runtime. 745 // Everything is fine, call runtime.
745 __ pop(rdx); 746 __ pop(rcx);
746 __ push(rcx); // receiver 747 __ push(rdx); // receiver
747 __ push(rax); // key 748 __ push(rax); // key
748 __ push(rdx); // return address 749 __ push(rcx); // return address
749 750
750 // Perform tail call to the entry. 751 // Perform tail call to the entry.
751 __ TailCallExternalReference(ExternalReference( 752 __ TailCallExternalReference(ExternalReference(
752 IC_Utility(kKeyedLoadPropertyWithInterceptor)), 2, 1); 753 IC_Utility(kKeyedLoadPropertyWithInterceptor)), 2, 1);
753 754
754 __ bind(&slow); 755 __ bind(&slow);
755 GenerateMiss(masm); 756 GenerateMiss(masm);
756 } 757 }
757 758
758 759
(...skipping 821 matching lines...) Expand 10 before | Expand all | Expand 10 after
1580 GenerateMiss(masm); 1581 GenerateMiss(masm);
1581 } 1582 }
1582 1583
1583 1584
1584 #undef __ 1585 #undef __
1585 1586
1586 1587
1587 } } // namespace v8::internal 1588 } } // namespace v8::internal
1588 1589
1589 #endif // V8_TARGET_ARCH_X64 1590 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/full-codegen-x64.cc ('k') | src/x64/stub-cache-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698