| 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 |