| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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_MIPS | 5 #if V8_TARGET_ARCH_MIPS |
| 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 459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 470 MacroAssembler* masm, Label* fast_object, Label* fast_double, Label* slow, | 470 MacroAssembler* masm, Label* fast_object, Label* fast_double, Label* slow, |
| 471 KeyedStoreCheckMap check_map, KeyedStoreIncrementLength increment_length, | 471 KeyedStoreCheckMap check_map, KeyedStoreIncrementLength increment_length, |
| 472 Register value, Register key, Register receiver, Register receiver_map, | 472 Register value, Register key, Register receiver, Register receiver_map, |
| 473 Register elements_map, Register elements) { | 473 Register elements_map, Register elements) { |
| 474 Label transition_smi_elements; | 474 Label transition_smi_elements; |
| 475 Label finish_object_store, non_double_value, transition_double_elements; | 475 Label finish_object_store, non_double_value, transition_double_elements; |
| 476 Label fast_double_without_map_check; | 476 Label fast_double_without_map_check; |
| 477 | 477 |
| 478 // Fast case: Do the store, could be either Object or double. | 478 // Fast case: Do the store, could be either Object or double. |
| 479 __ bind(fast_object); | 479 __ bind(fast_object); |
| 480 Register scratch_value = t0; | 480 Register scratch = t0; |
| 481 Register scratch2 = t4; |
| 482 Register scratch3 = t5; |
| 481 Register address = t1; | 483 Register address = t1; |
| 484 DCHECK(!AreAliased(value, key, receiver, receiver_map, elements_map, elements, |
| 485 scratch, scratch2, scratch3, address)); |
| 486 |
| 482 if (check_map == kCheckMap) { | 487 if (check_map == kCheckMap) { |
| 483 __ lw(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset)); | 488 __ lw(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset)); |
| 484 __ Branch(fast_double, ne, elements_map, | 489 __ Branch(fast_double, ne, elements_map, |
| 485 Operand(masm->isolate()->factory()->fixed_array_map())); | 490 Operand(masm->isolate()->factory()->fixed_array_map())); |
| 486 } | 491 } |
| 487 | 492 |
| 488 // HOLECHECK: guards "A[i] = V" | 493 // HOLECHECK: guards "A[i] = V" |
| 489 // We have to go to the runtime if the current value is the hole because | 494 // We have to go to the runtime if the current value is the hole because |
| 490 // there may be a callback on the element. | 495 // there may be a callback on the element. |
| 491 Label holecheck_passed1; | 496 Label holecheck_passed1; |
| 492 __ Addu(address, elements, FixedArray::kHeaderSize - kHeapObjectTag); | 497 __ Addu(address, elements, FixedArray::kHeaderSize - kHeapObjectTag); |
| 493 __ sll(at, key, kPointerSizeLog2 - kSmiTagSize); | 498 __ sll(at, key, kPointerSizeLog2 - kSmiTagSize); |
| 494 __ addu(address, address, at); | 499 __ addu(address, address, at); |
| 495 __ lw(scratch_value, MemOperand(address)); | 500 __ lw(scratch, MemOperand(address)); |
| 496 __ Branch(&holecheck_passed1, ne, scratch_value, | 501 __ Branch(&holecheck_passed1, ne, scratch, |
| 497 Operand(masm->isolate()->factory()->the_hole_value())); | 502 Operand(masm->isolate()->factory()->the_hole_value())); |
| 498 __ JumpIfDictionaryInPrototypeChain(receiver, elements_map, scratch_value, | 503 __ JumpIfDictionaryInPrototypeChain(receiver, elements_map, scratch, slow); |
| 499 slow); | |
| 500 | 504 |
| 501 __ bind(&holecheck_passed1); | 505 __ bind(&holecheck_passed1); |
| 502 | 506 |
| 503 // Smi stores don't require further checks. | 507 // Smi stores don't require further checks. |
| 504 Label non_smi_value; | 508 Label non_smi_value; |
| 505 __ JumpIfNotSmi(value, &non_smi_value); | 509 __ JumpIfNotSmi(value, &non_smi_value); |
| 506 | 510 |
| 507 if (increment_length == kIncrementLength) { | 511 if (increment_length == kIncrementLength) { |
| 508 // Add 1 to receiver->length. | 512 // Add 1 to receiver->length. |
| 509 __ Addu(scratch_value, key, Operand(Smi::FromInt(1))); | 513 __ Addu(scratch, key, Operand(Smi::FromInt(1))); |
| 510 __ sw(scratch_value, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 514 __ sw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 511 } | 515 } |
| 512 // It's irrelevant whether array is smi-only or not when writing a smi. | 516 // It's irrelevant whether array is smi-only or not when writing a smi. |
| 513 __ Addu(address, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 517 __ Addu(address, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
| 514 __ sll(scratch_value, key, kPointerSizeLog2 - kSmiTagSize); | 518 __ sll(scratch, key, kPointerSizeLog2 - kSmiTagSize); |
| 515 __ Addu(address, address, scratch_value); | 519 __ Addu(address, address, scratch); |
| 516 __ sw(value, MemOperand(address)); | 520 __ sw(value, MemOperand(address)); |
| 517 __ Ret(); | 521 __ Ret(); |
| 518 | 522 |
| 519 __ bind(&non_smi_value); | 523 __ bind(&non_smi_value); |
| 520 // Escape to elements kind transition case. | 524 // Escape to elements kind transition case. |
| 521 __ CheckFastObjectElements(receiver_map, scratch_value, | 525 __ CheckFastObjectElements(receiver_map, scratch, &transition_smi_elements); |
| 522 &transition_smi_elements); | |
| 523 | 526 |
| 524 // Fast elements array, store the value to the elements backing store. | 527 // Fast elements array, store the value to the elements backing store. |
| 525 __ bind(&finish_object_store); | 528 __ bind(&finish_object_store); |
| 526 if (increment_length == kIncrementLength) { | 529 if (increment_length == kIncrementLength) { |
| 527 // Add 1 to receiver->length. | 530 // Add 1 to receiver->length. |
| 528 __ Addu(scratch_value, key, Operand(Smi::FromInt(1))); | 531 __ Addu(scratch, key, Operand(Smi::FromInt(1))); |
| 529 __ sw(scratch_value, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 532 __ sw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 530 } | 533 } |
| 531 __ Addu(address, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 534 __ Addu(address, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
| 532 __ sll(scratch_value, key, kPointerSizeLog2 - kSmiTagSize); | 535 __ sll(scratch, key, kPointerSizeLog2 - kSmiTagSize); |
| 533 __ Addu(address, address, scratch_value); | 536 __ Addu(address, address, scratch); |
| 534 __ sw(value, MemOperand(address)); | 537 __ sw(value, MemOperand(address)); |
| 535 // Update write barrier for the elements array address. | 538 // Update write barrier for the elements array address. |
| 536 __ mov(scratch_value, value); // Preserve the value which is returned. | 539 __ mov(scratch, value); // Preserve the value which is returned. |
| 537 __ RecordWrite(elements, address, scratch_value, kRAHasNotBeenSaved, | 540 __ RecordWrite(elements, address, scratch, kRAHasNotBeenSaved, |
| 538 kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); | 541 kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); |
| 539 __ Ret(); | 542 __ Ret(); |
| 540 | 543 |
| 541 __ bind(fast_double); | 544 __ bind(fast_double); |
| 542 if (check_map == kCheckMap) { | 545 if (check_map == kCheckMap) { |
| 543 // Check for fast double array case. If this fails, call through to the | 546 // Check for fast double array case. If this fails, call through to the |
| 544 // runtime. | 547 // runtime. |
| 545 __ LoadRoot(at, Heap::kFixedDoubleArrayMapRootIndex); | 548 __ LoadRoot(at, Heap::kFixedDoubleArrayMapRootIndex); |
| 546 __ Branch(slow, ne, elements_map, Operand(at)); | 549 __ Branch(slow, ne, elements_map, Operand(at)); |
| 547 } | 550 } |
| 548 | 551 |
| 549 // HOLECHECK: guards "A[i] double hole?" | 552 // HOLECHECK: guards "A[i] double hole?" |
| 550 // We have to see if the double version of the hole is present. If so | 553 // We have to see if the double version of the hole is present. If so |
| 551 // go to the runtime. | 554 // go to the runtime. |
| 552 __ Addu(address, elements, Operand(FixedDoubleArray::kHeaderSize + | 555 __ Addu(address, elements, Operand(FixedDoubleArray::kHeaderSize + |
| 553 kHoleNanUpper32Offset - kHeapObjectTag)); | 556 kHoleNanUpper32Offset - kHeapObjectTag)); |
| 554 __ sll(at, key, kPointerSizeLog2); | 557 __ sll(at, key, kPointerSizeLog2); |
| 555 __ addu(address, address, at); | 558 __ addu(address, address, at); |
| 556 __ lw(scratch_value, MemOperand(address)); | 559 __ lw(scratch, MemOperand(address)); |
| 557 __ Branch(&fast_double_without_map_check, ne, scratch_value, | 560 __ Branch(&fast_double_without_map_check, ne, scratch, |
| 558 Operand(kHoleNanUpper32)); | 561 Operand(kHoleNanUpper32)); |
| 559 __ JumpIfDictionaryInPrototypeChain(receiver, elements_map, scratch_value, | 562 __ JumpIfDictionaryInPrototypeChain(receiver, elements_map, scratch, slow); |
| 560 slow); | |
| 561 | 563 |
| 562 __ bind(&fast_double_without_map_check); | 564 __ bind(&fast_double_without_map_check); |
| 563 __ StoreNumberToDoubleElements(value, key, | 565 __ StoreNumberToDoubleElements(value, key, elements, scratch, scratch2, |
| 564 elements, // Overwritten. | 566 scratch3, &transition_double_elements); |
| 565 a3, // Scratch regs... | |
| 566 t0, t1, &transition_double_elements); | |
| 567 if (increment_length == kIncrementLength) { | 567 if (increment_length == kIncrementLength) { |
| 568 // Add 1 to receiver->length. | 568 // Add 1 to receiver->length. |
| 569 __ Addu(scratch_value, key, Operand(Smi::FromInt(1))); | 569 __ Addu(scratch, key, Operand(Smi::FromInt(1))); |
| 570 __ sw(scratch_value, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 570 __ sw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 571 } | 571 } |
| 572 __ Ret(); | 572 __ Ret(); |
| 573 | 573 |
| 574 __ bind(&transition_smi_elements); | 574 __ bind(&transition_smi_elements); |
| 575 // Transition the array appropriately depending on the value type. | 575 // Transition the array appropriately depending on the value type. |
| 576 __ lw(t0, FieldMemOperand(value, HeapObject::kMapOffset)); | 576 __ lw(scratch, FieldMemOperand(value, HeapObject::kMapOffset)); |
| 577 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); | 577 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); |
| 578 __ Branch(&non_double_value, ne, t0, Operand(at)); | 578 __ Branch(&non_double_value, ne, scratch, Operand(at)); |
| 579 | 579 |
| 580 // Value is a double. Transition FAST_SMI_ELEMENTS -> | 580 // Value is a double. Transition FAST_SMI_ELEMENTS -> |
| 581 // FAST_DOUBLE_ELEMENTS and complete the store. | 581 // FAST_DOUBLE_ELEMENTS and complete the store. |
| 582 __ LoadTransitionedArrayMapConditional( | 582 __ LoadTransitionedArrayMapConditional( |
| 583 FAST_SMI_ELEMENTS, FAST_DOUBLE_ELEMENTS, receiver_map, t0, slow); | 583 FAST_SMI_ELEMENTS, FAST_DOUBLE_ELEMENTS, receiver_map, scratch, slow); |
| 584 AllocationSiteMode mode = | 584 AllocationSiteMode mode = |
| 585 AllocationSite::GetMode(FAST_SMI_ELEMENTS, FAST_DOUBLE_ELEMENTS); | 585 AllocationSite::GetMode(FAST_SMI_ELEMENTS, FAST_DOUBLE_ELEMENTS); |
| 586 ElementsTransitionGenerator::GenerateSmiToDouble(masm, receiver, key, value, | 586 ElementsTransitionGenerator::GenerateSmiToDouble(masm, receiver, key, value, |
| 587 receiver_map, mode, slow); | 587 receiver_map, mode, slow); |
| 588 __ lw(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); | 588 __ lw(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
| 589 __ jmp(&fast_double_without_map_check); | 589 __ jmp(&fast_double_without_map_check); |
| 590 | 590 |
| 591 __ bind(&non_double_value); | 591 __ bind(&non_double_value); |
| 592 // Value is not a double, FAST_SMI_ELEMENTS -> FAST_ELEMENTS | 592 // Value is not a double, FAST_SMI_ELEMENTS -> FAST_ELEMENTS |
| 593 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, FAST_ELEMENTS, | 593 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, FAST_ELEMENTS, |
| 594 receiver_map, t0, slow); | 594 receiver_map, scratch, slow); |
| 595 mode = AllocationSite::GetMode(FAST_SMI_ELEMENTS, FAST_ELEMENTS); | 595 mode = AllocationSite::GetMode(FAST_SMI_ELEMENTS, FAST_ELEMENTS); |
| 596 ElementsTransitionGenerator::GenerateMapChangeElementsTransition( | 596 ElementsTransitionGenerator::GenerateMapChangeElementsTransition( |
| 597 masm, receiver, key, value, receiver_map, mode, slow); | 597 masm, receiver, key, value, receiver_map, mode, slow); |
| 598 __ lw(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); | 598 __ lw(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
| 599 __ jmp(&finish_object_store); | 599 __ jmp(&finish_object_store); |
| 600 | 600 |
| 601 __ bind(&transition_double_elements); | 601 __ bind(&transition_double_elements); |
| 602 // Elements are FAST_DOUBLE_ELEMENTS, but value is an Object that's not a | 602 // Elements are FAST_DOUBLE_ELEMENTS, but value is an Object that's not a |
| 603 // HeapNumber. Make sure that the receiver is a Array with FAST_ELEMENTS and | 603 // HeapNumber. Make sure that the receiver is a Array with FAST_ELEMENTS and |
| 604 // transition array from FAST_DOUBLE_ELEMENTS to FAST_ELEMENTS | 604 // transition array from FAST_DOUBLE_ELEMENTS to FAST_ELEMENTS |
| 605 __ LoadTransitionedArrayMapConditional(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS, | 605 __ LoadTransitionedArrayMapConditional(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS, |
| 606 receiver_map, t0, slow); | 606 receiver_map, scratch, slow); |
| 607 mode = AllocationSite::GetMode(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS); | 607 mode = AllocationSite::GetMode(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS); |
| 608 ElementsTransitionGenerator::GenerateDoubleToObject( | 608 ElementsTransitionGenerator::GenerateDoubleToObject( |
| 609 masm, receiver, key, value, receiver_map, mode, slow); | 609 masm, receiver, key, value, receiver_map, mode, slow); |
| 610 __ lw(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); | 610 __ lw(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
| 611 __ jmp(&finish_object_store); | 611 __ jmp(&finish_object_store); |
| 612 } | 612 } |
| 613 | 613 |
| 614 | 614 |
| 615 void KeyedStoreIC::GenerateMegamorphic(MacroAssembler* masm, | 615 void KeyedStoreIC::GenerateMegamorphic(MacroAssembler* masm, |
| 616 LanguageMode language_mode) { | 616 LanguageMode language_mode) { |
| (...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 926 break; | 926 break; |
| 927 default: | 927 default: |
| 928 UNIMPLEMENTED(); | 928 UNIMPLEMENTED(); |
| 929 } | 929 } |
| 930 patcher.ChangeBranchCondition(branch_instr, opcode); | 930 patcher.ChangeBranchCondition(branch_instr, opcode); |
| 931 } | 931 } |
| 932 } // namespace internal | 932 } // namespace internal |
| 933 } // namespace v8 | 933 } // namespace v8 |
| 934 | 934 |
| 935 #endif // V8_TARGET_ARCH_MIPS | 935 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |