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 |