OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #if V8_TARGET_ARCH_PPC | 5 #if V8_TARGET_ARCH_PPC |
6 | 6 |
7 #include "src/codegen.h" | 7 #include "src/codegen.h" |
8 #include "src/ic/ic.h" | 8 #include "src/ic/ic.h" |
9 #include "src/ic/ic-compiler.h" | 9 #include "src/ic/ic-compiler.h" |
10 #include "src/ic/stub-cache.h" | 10 #include "src/ic/stub-cache.h" |
(...skipping 479 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
490 MacroAssembler* masm, Label* fast_object, Label* fast_double, Label* slow, | 490 MacroAssembler* masm, Label* fast_object, Label* fast_double, Label* slow, |
491 KeyedStoreCheckMap check_map, KeyedStoreIncrementLength increment_length, | 491 KeyedStoreCheckMap check_map, KeyedStoreIncrementLength increment_length, |
492 Register value, Register key, Register receiver, Register receiver_map, | 492 Register value, Register key, Register receiver, Register receiver_map, |
493 Register elements_map, Register elements) { | 493 Register elements_map, Register elements) { |
494 Label transition_smi_elements; | 494 Label transition_smi_elements; |
495 Label finish_object_store, non_double_value, transition_double_elements; | 495 Label finish_object_store, non_double_value, transition_double_elements; |
496 Label fast_double_without_map_check; | 496 Label fast_double_without_map_check; |
497 | 497 |
498 // Fast case: Do the store, could be either Object or double. | 498 // Fast case: Do the store, could be either Object or double. |
499 __ bind(fast_object); | 499 __ bind(fast_object); |
500 Register scratch_value = r7; | 500 Register scratch = r7; |
| 501 Register scratch2 = r0; |
501 Register address = r8; | 502 Register address = r8; |
| 503 DCHECK(!AreAliased(value, key, receiver, receiver_map, elements_map, elements, |
| 504 scratch, scratch2, address)); |
| 505 |
502 if (check_map == kCheckMap) { | 506 if (check_map == kCheckMap) { |
503 __ LoadP(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset)); | 507 __ LoadP(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset)); |
504 __ mov(scratch_value, | 508 __ mov(scratch, Operand(masm->isolate()->factory()->fixed_array_map())); |
505 Operand(masm->isolate()->factory()->fixed_array_map())); | 509 __ cmp(elements_map, scratch); |
506 __ cmp(elements_map, scratch_value); | |
507 __ bne(fast_double); | 510 __ bne(fast_double); |
508 } | 511 } |
509 | 512 |
510 // HOLECHECK: guards "A[i] = V" | 513 // HOLECHECK: guards "A[i] = V" |
511 // We have to go to the runtime if the current value is the hole because | 514 // We have to go to the runtime if the current value is the hole because |
512 // there may be a callback on the element | 515 // there may be a callback on the element |
513 Label holecheck_passed1; | 516 Label holecheck_passed1; |
514 __ addi(address, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 517 __ addi(address, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
515 __ SmiToPtrArrayOffset(scratch_value, key); | 518 __ SmiToPtrArrayOffset(scratch, key); |
516 __ LoadPX(scratch_value, MemOperand(address, scratch_value)); | 519 __ LoadPX(scratch, MemOperand(address, scratch)); |
517 __ Cmpi(scratch_value, Operand(masm->isolate()->factory()->the_hole_value()), | 520 __ Cmpi(scratch, Operand(masm->isolate()->factory()->the_hole_value()), |
518 r0); | 521 scratch2); |
519 __ bne(&holecheck_passed1); | 522 __ bne(&holecheck_passed1); |
520 __ JumpIfDictionaryInPrototypeChain(receiver, elements_map, scratch_value, | 523 __ JumpIfDictionaryInPrototypeChain(receiver, elements_map, scratch, slow); |
521 slow); | |
522 | 524 |
523 __ bind(&holecheck_passed1); | 525 __ bind(&holecheck_passed1); |
524 | 526 |
525 // Smi stores don't require further checks. | 527 // Smi stores don't require further checks. |
526 Label non_smi_value; | 528 Label non_smi_value; |
527 __ JumpIfNotSmi(value, &non_smi_value); | 529 __ JumpIfNotSmi(value, &non_smi_value); |
528 | 530 |
529 if (increment_length == kIncrementLength) { | 531 if (increment_length == kIncrementLength) { |
530 // Add 1 to receiver->length. | 532 // Add 1 to receiver->length. |
531 __ AddSmiLiteral(scratch_value, key, Smi::FromInt(1), r0); | 533 __ AddSmiLiteral(scratch, key, Smi::FromInt(1), scratch2); |
532 __ StoreP(scratch_value, FieldMemOperand(receiver, JSArray::kLengthOffset), | 534 __ StoreP(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset), |
533 r0); | 535 scratch2); |
534 } | 536 } |
535 // It's irrelevant whether array is smi-only or not when writing a smi. | 537 // It's irrelevant whether array is smi-only or not when writing a smi. |
536 __ addi(address, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 538 __ addi(address, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
537 __ SmiToPtrArrayOffset(scratch_value, key); | 539 __ SmiToPtrArrayOffset(scratch, key); |
538 __ StorePX(value, MemOperand(address, scratch_value)); | 540 __ StorePX(value, MemOperand(address, scratch)); |
539 __ Ret(); | 541 __ Ret(); |
540 | 542 |
541 __ bind(&non_smi_value); | 543 __ bind(&non_smi_value); |
542 // Escape to elements kind transition case. | 544 // Escape to elements kind transition case. |
543 __ CheckFastObjectElements(receiver_map, scratch_value, | 545 __ CheckFastObjectElements(receiver_map, scratch, &transition_smi_elements); |
544 &transition_smi_elements); | |
545 | 546 |
546 // Fast elements array, store the value to the elements backing store. | 547 // Fast elements array, store the value to the elements backing store. |
547 __ bind(&finish_object_store); | 548 __ bind(&finish_object_store); |
548 if (increment_length == kIncrementLength) { | 549 if (increment_length == kIncrementLength) { |
549 // Add 1 to receiver->length. | 550 // Add 1 to receiver->length. |
550 __ AddSmiLiteral(scratch_value, key, Smi::FromInt(1), r0); | 551 __ AddSmiLiteral(scratch, key, Smi::FromInt(1), scratch2); |
551 __ StoreP(scratch_value, FieldMemOperand(receiver, JSArray::kLengthOffset), | 552 __ StoreP(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset), |
552 r0); | 553 scratch2); |
553 } | 554 } |
554 __ addi(address, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 555 __ addi(address, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
555 __ SmiToPtrArrayOffset(scratch_value, key); | 556 __ SmiToPtrArrayOffset(scratch, key); |
556 __ StorePUX(value, MemOperand(address, scratch_value)); | 557 __ StorePUX(value, MemOperand(address, scratch)); |
557 // Update write barrier for the elements array address. | 558 // Update write barrier for the elements array address. |
558 __ mr(scratch_value, value); // Preserve the value which is returned. | 559 __ mr(scratch, value); // Preserve the value which is returned. |
559 __ RecordWrite(elements, address, scratch_value, kLRHasNotBeenSaved, | 560 __ RecordWrite(elements, address, scratch, kLRHasNotBeenSaved, |
560 kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); | 561 kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); |
561 __ Ret(); | 562 __ Ret(); |
562 | 563 |
563 __ bind(fast_double); | 564 __ bind(fast_double); |
564 if (check_map == kCheckMap) { | 565 if (check_map == kCheckMap) { |
565 // Check for fast double array case. If this fails, call through to the | 566 // Check for fast double array case. If this fails, call through to the |
566 // runtime. | 567 // runtime. |
567 __ CompareRoot(elements_map, Heap::kFixedDoubleArrayMapRootIndex); | 568 __ CompareRoot(elements_map, Heap::kFixedDoubleArrayMapRootIndex); |
568 __ bne(slow); | 569 __ bne(slow); |
569 } | 570 } |
570 | 571 |
571 // HOLECHECK: guards "A[i] double hole?" | 572 // HOLECHECK: guards "A[i] double hole?" |
572 // We have to see if the double version of the hole is present. If so | 573 // We have to see if the double version of the hole is present. If so |
573 // go to the runtime. | 574 // go to the runtime. |
574 __ addi(address, elements, | 575 __ addi(address, elements, |
575 Operand((FixedDoubleArray::kHeaderSize + Register::kExponentOffset - | 576 Operand((FixedDoubleArray::kHeaderSize + Register::kExponentOffset - |
576 kHeapObjectTag))); | 577 kHeapObjectTag))); |
577 __ SmiToDoubleArrayOffset(scratch_value, key); | 578 __ SmiToDoubleArrayOffset(scratch, key); |
578 __ lwzx(scratch_value, MemOperand(address, scratch_value)); | 579 __ lwzx(scratch, MemOperand(address, scratch)); |
579 __ Cmpi(scratch_value, Operand(kHoleNanUpper32), r0); | 580 __ Cmpi(scratch, Operand(kHoleNanUpper32), scratch2); |
580 __ bne(&fast_double_without_map_check); | 581 __ bne(&fast_double_without_map_check); |
581 __ JumpIfDictionaryInPrototypeChain(receiver, elements_map, scratch_value, | 582 __ JumpIfDictionaryInPrototypeChain(receiver, elements_map, scratch, slow); |
582 slow); | |
583 | 583 |
584 __ bind(&fast_double_without_map_check); | 584 __ bind(&fast_double_without_map_check); |
585 __ StoreNumberToDoubleElements(value, key, elements, r6, d0, | 585 __ StoreNumberToDoubleElements(value, key, elements, scratch, d0, |
586 &transition_double_elements); | 586 &transition_double_elements); |
587 if (increment_length == kIncrementLength) { | 587 if (increment_length == kIncrementLength) { |
588 // Add 1 to receiver->length. | 588 // Add 1 to receiver->length. |
589 __ AddSmiLiteral(scratch_value, key, Smi::FromInt(1), r0); | 589 __ AddSmiLiteral(scratch, key, Smi::FromInt(1), scratch2); |
590 __ StoreP(scratch_value, FieldMemOperand(receiver, JSArray::kLengthOffset), | 590 __ StoreP(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset), |
591 r0); | 591 scratch2); |
592 } | 592 } |
593 __ Ret(); | 593 __ Ret(); |
594 | 594 |
595 __ bind(&transition_smi_elements); | 595 __ bind(&transition_smi_elements); |
596 // Transition the array appropriately depending on the value type. | 596 // Transition the array appropriately depending on the value type. |
597 __ LoadP(r7, FieldMemOperand(value, HeapObject::kMapOffset)); | 597 __ LoadP(r7, FieldMemOperand(value, HeapObject::kMapOffset)); |
598 __ CompareRoot(r7, Heap::kHeapNumberMapRootIndex); | 598 __ CompareRoot(r7, Heap::kHeapNumberMapRootIndex); |
599 __ bne(&non_double_value); | 599 __ bne(&non_double_value); |
600 | 600 |
601 // Value is a double. Transition FAST_SMI_ELEMENTS -> | 601 // Value is a double. Transition FAST_SMI_ELEMENTS -> |
602 // FAST_DOUBLE_ELEMENTS and complete the store. | 602 // FAST_DOUBLE_ELEMENTS and complete the store. |
603 __ LoadTransitionedArrayMapConditional( | 603 __ LoadTransitionedArrayMapConditional( |
604 FAST_SMI_ELEMENTS, FAST_DOUBLE_ELEMENTS, receiver_map, r7, slow); | 604 FAST_SMI_ELEMENTS, FAST_DOUBLE_ELEMENTS, receiver_map, scratch, slow); |
605 AllocationSiteMode mode = | 605 AllocationSiteMode mode = |
606 AllocationSite::GetMode(FAST_SMI_ELEMENTS, FAST_DOUBLE_ELEMENTS); | 606 AllocationSite::GetMode(FAST_SMI_ELEMENTS, FAST_DOUBLE_ELEMENTS); |
607 ElementsTransitionGenerator::GenerateSmiToDouble(masm, receiver, key, value, | 607 ElementsTransitionGenerator::GenerateSmiToDouble(masm, receiver, key, value, |
608 receiver_map, mode, slow); | 608 receiver_map, mode, slow); |
609 __ LoadP(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); | 609 __ LoadP(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
610 __ b(&fast_double_without_map_check); | 610 __ b(&fast_double_without_map_check); |
611 | 611 |
612 __ bind(&non_double_value); | 612 __ bind(&non_double_value); |
613 // Value is not a double, FAST_SMI_ELEMENTS -> FAST_ELEMENTS | 613 // Value is not a double, FAST_SMI_ELEMENTS -> FAST_ELEMENTS |
614 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, FAST_ELEMENTS, | 614 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, FAST_ELEMENTS, |
615 receiver_map, r7, slow); | 615 receiver_map, scratch, slow); |
616 mode = AllocationSite::GetMode(FAST_SMI_ELEMENTS, FAST_ELEMENTS); | 616 mode = AllocationSite::GetMode(FAST_SMI_ELEMENTS, FAST_ELEMENTS); |
617 ElementsTransitionGenerator::GenerateMapChangeElementsTransition( | 617 ElementsTransitionGenerator::GenerateMapChangeElementsTransition( |
618 masm, receiver, key, value, receiver_map, mode, slow); | 618 masm, receiver, key, value, receiver_map, mode, slow); |
619 __ LoadP(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); | 619 __ LoadP(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
620 __ b(&finish_object_store); | 620 __ b(&finish_object_store); |
621 | 621 |
622 __ bind(&transition_double_elements); | 622 __ bind(&transition_double_elements); |
623 // Elements are FAST_DOUBLE_ELEMENTS, but value is an Object that's not a | 623 // Elements are FAST_DOUBLE_ELEMENTS, but value is an Object that's not a |
624 // HeapNumber. Make sure that the receiver is a Array with FAST_ELEMENTS and | 624 // HeapNumber. Make sure that the receiver is a Array with FAST_ELEMENTS and |
625 // transition array from FAST_DOUBLE_ELEMENTS to FAST_ELEMENTS | 625 // transition array from FAST_DOUBLE_ELEMENTS to FAST_ELEMENTS |
626 __ LoadTransitionedArrayMapConditional(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS, | 626 __ LoadTransitionedArrayMapConditional(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS, |
627 receiver_map, r7, slow); | 627 receiver_map, scratch, slow); |
628 mode = AllocationSite::GetMode(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS); | 628 mode = AllocationSite::GetMode(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS); |
629 ElementsTransitionGenerator::GenerateDoubleToObject( | 629 ElementsTransitionGenerator::GenerateDoubleToObject( |
630 masm, receiver, key, value, receiver_map, mode, slow); | 630 masm, receiver, key, value, receiver_map, mode, slow); |
631 __ LoadP(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); | 631 __ LoadP(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
632 __ b(&finish_object_store); | 632 __ b(&finish_object_store); |
633 } | 633 } |
634 | 634 |
635 | 635 |
636 void KeyedStoreIC::GenerateMegamorphic(MacroAssembler* masm, | 636 void KeyedStoreIC::GenerateMegamorphic(MacroAssembler* masm, |
637 LanguageMode language_mode) { | 637 LanguageMode language_mode) { |
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
911 patcher.EmitCondition(ne); | 911 patcher.EmitCondition(ne); |
912 } else { | 912 } else { |
913 DCHECK(Assembler::GetCondition(branch_instr) == ne); | 913 DCHECK(Assembler::GetCondition(branch_instr) == ne); |
914 patcher.EmitCondition(eq); | 914 patcher.EmitCondition(eq); |
915 } | 915 } |
916 } | 916 } |
917 } // namespace internal | 917 } // namespace internal |
918 } // namespace v8 | 918 } // namespace v8 |
919 | 919 |
920 #endif // V8_TARGET_ARCH_PPC | 920 #endif // V8_TARGET_ARCH_PPC |
OLD | NEW |