| 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_ARM | 5 #if V8_TARGET_ARCH_ARM |
| 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 469 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 480 MacroAssembler* masm, Label* fast_object, Label* fast_double, Label* slow, | 480 MacroAssembler* masm, Label* fast_object, Label* fast_double, Label* slow, |
| 481 KeyedStoreCheckMap check_map, KeyedStoreIncrementLength increment_length, | 481 KeyedStoreCheckMap check_map, KeyedStoreIncrementLength increment_length, |
| 482 Register value, Register key, Register receiver, Register receiver_map, | 482 Register value, Register key, Register receiver, Register receiver_map, |
| 483 Register elements_map, Register elements) { | 483 Register elements_map, Register elements) { |
| 484 Label transition_smi_elements; | 484 Label transition_smi_elements; |
| 485 Label finish_object_store, non_double_value, transition_double_elements; | 485 Label finish_object_store, non_double_value, transition_double_elements; |
| 486 Label fast_double_without_map_check; | 486 Label fast_double_without_map_check; |
| 487 | 487 |
| 488 // Fast case: Do the store, could be either Object or double. | 488 // Fast case: Do the store, could be either Object or double. |
| 489 __ bind(fast_object); | 489 __ bind(fast_object); |
| 490 Register scratch_value = r4; | 490 Register scratch = r4; |
| 491 Register address = r5; | 491 Register address = r5; |
| 492 DCHECK(!AreAliased(value, key, receiver, receiver_map, elements_map, elements, |
| 493 scratch, address)); |
| 494 |
| 492 if (check_map == kCheckMap) { | 495 if (check_map == kCheckMap) { |
| 493 __ ldr(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset)); | 496 __ ldr(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset)); |
| 494 __ cmp(elements_map, | 497 __ cmp(elements_map, |
| 495 Operand(masm->isolate()->factory()->fixed_array_map())); | 498 Operand(masm->isolate()->factory()->fixed_array_map())); |
| 496 __ b(ne, fast_double); | 499 __ b(ne, fast_double); |
| 497 } | 500 } |
| 498 | 501 |
| 499 // HOLECHECK: guards "A[i] = V" | 502 // HOLECHECK: guards "A[i] = V" |
| 500 // We have to go to the runtime if the current value is the hole because | 503 // We have to go to the runtime if the current value is the hole because |
| 501 // there may be a callback on the element | 504 // there may be a callback on the element |
| 502 Label holecheck_passed1; | 505 Label holecheck_passed1; |
| 503 __ add(address, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 506 __ add(address, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
| 504 __ ldr(scratch_value, | 507 __ ldr(scratch, MemOperand::PointerAddressFromSmiKey(address, key, PreIndex)); |
| 505 MemOperand::PointerAddressFromSmiKey(address, key, PreIndex)); | 508 __ cmp(scratch, Operand(masm->isolate()->factory()->the_hole_value())); |
| 506 __ cmp(scratch_value, Operand(masm->isolate()->factory()->the_hole_value())); | |
| 507 __ b(ne, &holecheck_passed1); | 509 __ b(ne, &holecheck_passed1); |
| 508 __ JumpIfDictionaryInPrototypeChain(receiver, elements_map, scratch_value, | 510 __ JumpIfDictionaryInPrototypeChain(receiver, elements_map, scratch, slow); |
| 509 slow); | |
| 510 | 511 |
| 511 __ bind(&holecheck_passed1); | 512 __ bind(&holecheck_passed1); |
| 512 | 513 |
| 513 // Smi stores don't require further checks. | 514 // Smi stores don't require further checks. |
| 514 Label non_smi_value; | 515 Label non_smi_value; |
| 515 __ JumpIfNotSmi(value, &non_smi_value); | 516 __ JumpIfNotSmi(value, &non_smi_value); |
| 516 | 517 |
| 517 if (increment_length == kIncrementLength) { | 518 if (increment_length == kIncrementLength) { |
| 518 // Add 1 to receiver->length. | 519 // Add 1 to receiver->length. |
| 519 __ add(scratch_value, key, Operand(Smi::FromInt(1))); | 520 __ add(scratch, key, Operand(Smi::FromInt(1))); |
| 520 __ str(scratch_value, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 521 __ str(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 521 } | 522 } |
| 522 // It's irrelevant whether array is smi-only or not when writing a smi. | 523 // It's irrelevant whether array is smi-only or not when writing a smi. |
| 523 __ add(address, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 524 __ add(address, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
| 524 __ str(value, MemOperand::PointerAddressFromSmiKey(address, key)); | 525 __ str(value, MemOperand::PointerAddressFromSmiKey(address, key)); |
| 525 __ Ret(); | 526 __ Ret(); |
| 526 | 527 |
| 527 __ bind(&non_smi_value); | 528 __ bind(&non_smi_value); |
| 528 // Escape to elements kind transition case. | 529 // Escape to elements kind transition case. |
| 529 __ CheckFastObjectElements(receiver_map, scratch_value, | 530 __ CheckFastObjectElements(receiver_map, scratch, &transition_smi_elements); |
| 530 &transition_smi_elements); | |
| 531 | 531 |
| 532 // Fast elements array, store the value to the elements backing store. | 532 // Fast elements array, store the value to the elements backing store. |
| 533 __ bind(&finish_object_store); | 533 __ bind(&finish_object_store); |
| 534 if (increment_length == kIncrementLength) { | 534 if (increment_length == kIncrementLength) { |
| 535 // Add 1 to receiver->length. | 535 // Add 1 to receiver->length. |
| 536 __ add(scratch_value, key, Operand(Smi::FromInt(1))); | 536 __ add(scratch, key, Operand(Smi::FromInt(1))); |
| 537 __ str(scratch_value, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 537 __ str(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 538 } | 538 } |
| 539 __ add(address, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 539 __ add(address, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
| 540 __ add(address, address, Operand::PointerOffsetFromSmiKey(key)); | 540 __ add(address, address, Operand::PointerOffsetFromSmiKey(key)); |
| 541 __ str(value, MemOperand(address)); | 541 __ str(value, MemOperand(address)); |
| 542 // Update write barrier for the elements array address. | 542 // Update write barrier for the elements array address. |
| 543 __ mov(scratch_value, value); // Preserve the value which is returned. | 543 __ mov(scratch, value); // Preserve the value which is returned. |
| 544 __ RecordWrite(elements, address, scratch_value, kLRHasNotBeenSaved, | 544 __ RecordWrite(elements, address, scratch, kLRHasNotBeenSaved, |
| 545 kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); | 545 kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); |
| 546 __ Ret(); | 546 __ Ret(); |
| 547 | 547 |
| 548 __ bind(fast_double); | 548 __ bind(fast_double); |
| 549 if (check_map == kCheckMap) { | 549 if (check_map == kCheckMap) { |
| 550 // Check for fast double array case. If this fails, call through to the | 550 // Check for fast double array case. If this fails, call through to the |
| 551 // runtime. | 551 // runtime. |
| 552 __ CompareRoot(elements_map, Heap::kFixedDoubleArrayMapRootIndex); | 552 __ CompareRoot(elements_map, Heap::kFixedDoubleArrayMapRootIndex); |
| 553 __ b(ne, slow); | 553 __ b(ne, slow); |
| 554 } | 554 } |
| 555 | 555 |
| 556 // HOLECHECK: guards "A[i] double hole?" | 556 // HOLECHECK: guards "A[i] double hole?" |
| 557 // We have to see if the double version of the hole is present. If so | 557 // We have to see if the double version of the hole is present. If so |
| 558 // go to the runtime. | 558 // go to the runtime. |
| 559 __ add(address, elements, | 559 __ add(address, elements, |
| 560 Operand((FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32)) - | 560 Operand((FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32)) - |
| 561 kHeapObjectTag)); | 561 kHeapObjectTag)); |
| 562 __ ldr(scratch_value, | 562 __ ldr(scratch, MemOperand(address, key, LSL, kPointerSizeLog2, PreIndex)); |
| 563 MemOperand(address, key, LSL, kPointerSizeLog2, PreIndex)); | 563 __ cmp(scratch, Operand(kHoleNanUpper32)); |
| 564 __ cmp(scratch_value, Operand(kHoleNanUpper32)); | |
| 565 __ b(ne, &fast_double_without_map_check); | 564 __ b(ne, &fast_double_without_map_check); |
| 566 __ JumpIfDictionaryInPrototypeChain(receiver, elements_map, scratch_value, | 565 __ JumpIfDictionaryInPrototypeChain(receiver, elements_map, scratch, slow); |
| 567 slow); | |
| 568 | 566 |
| 569 __ bind(&fast_double_without_map_check); | 567 __ bind(&fast_double_without_map_check); |
| 570 __ StoreNumberToDoubleElements(value, key, elements, r3, d0, | 568 __ StoreNumberToDoubleElements(value, key, elements, scratch, d0, |
| 571 &transition_double_elements); | 569 &transition_double_elements); |
| 572 if (increment_length == kIncrementLength) { | 570 if (increment_length == kIncrementLength) { |
| 573 // Add 1 to receiver->length. | 571 // Add 1 to receiver->length. |
| 574 __ add(scratch_value, key, Operand(Smi::FromInt(1))); | 572 __ add(scratch, key, Operand(Smi::FromInt(1))); |
| 575 __ str(scratch_value, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 573 __ str(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 576 } | 574 } |
| 577 __ Ret(); | 575 __ Ret(); |
| 578 | 576 |
| 579 __ bind(&transition_smi_elements); | 577 __ bind(&transition_smi_elements); |
| 580 // Transition the array appropriately depending on the value type. | 578 // Transition the array appropriately depending on the value type. |
| 581 __ ldr(r4, FieldMemOperand(value, HeapObject::kMapOffset)); | 579 __ ldr(scratch, FieldMemOperand(value, HeapObject::kMapOffset)); |
| 582 __ CompareRoot(r4, Heap::kHeapNumberMapRootIndex); | 580 __ CompareRoot(scratch, Heap::kHeapNumberMapRootIndex); |
| 583 __ b(ne, &non_double_value); | 581 __ b(ne, &non_double_value); |
| 584 | 582 |
| 585 // Value is a double. Transition FAST_SMI_ELEMENTS -> | 583 // Value is a double. Transition FAST_SMI_ELEMENTS -> |
| 586 // FAST_DOUBLE_ELEMENTS and complete the store. | 584 // FAST_DOUBLE_ELEMENTS and complete the store. |
| 587 __ LoadTransitionedArrayMapConditional( | 585 __ LoadTransitionedArrayMapConditional( |
| 588 FAST_SMI_ELEMENTS, FAST_DOUBLE_ELEMENTS, receiver_map, r4, slow); | 586 FAST_SMI_ELEMENTS, FAST_DOUBLE_ELEMENTS, receiver_map, scratch, slow); |
| 589 AllocationSiteMode mode = | 587 AllocationSiteMode mode = |
| 590 AllocationSite::GetMode(FAST_SMI_ELEMENTS, FAST_DOUBLE_ELEMENTS); | 588 AllocationSite::GetMode(FAST_SMI_ELEMENTS, FAST_DOUBLE_ELEMENTS); |
| 591 ElementsTransitionGenerator::GenerateSmiToDouble(masm, receiver, key, value, | 589 ElementsTransitionGenerator::GenerateSmiToDouble(masm, receiver, key, value, |
| 592 receiver_map, mode, slow); | 590 receiver_map, mode, slow); |
| 593 __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); | 591 __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
| 594 __ jmp(&fast_double_without_map_check); | 592 __ jmp(&fast_double_without_map_check); |
| 595 | 593 |
| 596 __ bind(&non_double_value); | 594 __ bind(&non_double_value); |
| 597 // Value is not a double, FAST_SMI_ELEMENTS -> FAST_ELEMENTS | 595 // Value is not a double, FAST_SMI_ELEMENTS -> FAST_ELEMENTS |
| 598 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, FAST_ELEMENTS, | 596 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, FAST_ELEMENTS, |
| 599 receiver_map, r4, slow); | 597 receiver_map, scratch, slow); |
| 600 mode = AllocationSite::GetMode(FAST_SMI_ELEMENTS, FAST_ELEMENTS); | 598 mode = AllocationSite::GetMode(FAST_SMI_ELEMENTS, FAST_ELEMENTS); |
| 601 ElementsTransitionGenerator::GenerateMapChangeElementsTransition( | 599 ElementsTransitionGenerator::GenerateMapChangeElementsTransition( |
| 602 masm, receiver, key, value, receiver_map, mode, slow); | 600 masm, receiver, key, value, receiver_map, mode, slow); |
| 603 __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); | 601 __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
| 604 __ jmp(&finish_object_store); | 602 __ jmp(&finish_object_store); |
| 605 | 603 |
| 606 __ bind(&transition_double_elements); | 604 __ bind(&transition_double_elements); |
| 607 // Elements are FAST_DOUBLE_ELEMENTS, but value is an Object that's not a | 605 // Elements are FAST_DOUBLE_ELEMENTS, but value is an Object that's not a |
| 608 // HeapNumber. Make sure that the receiver is a Array with FAST_ELEMENTS and | 606 // HeapNumber. Make sure that the receiver is a Array with FAST_ELEMENTS and |
| 609 // transition array from FAST_DOUBLE_ELEMENTS to FAST_ELEMENTS | 607 // transition array from FAST_DOUBLE_ELEMENTS to FAST_ELEMENTS |
| 610 __ LoadTransitionedArrayMapConditional(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS, | 608 __ LoadTransitionedArrayMapConditional(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS, |
| 611 receiver_map, r4, slow); | 609 receiver_map, scratch, slow); |
| 612 mode = AllocationSite::GetMode(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS); | 610 mode = AllocationSite::GetMode(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS); |
| 613 ElementsTransitionGenerator::GenerateDoubleToObject( | 611 ElementsTransitionGenerator::GenerateDoubleToObject( |
| 614 masm, receiver, key, value, receiver_map, mode, slow); | 612 masm, receiver, key, value, receiver_map, mode, slow); |
| 615 __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); | 613 __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
| 616 __ jmp(&finish_object_store); | 614 __ jmp(&finish_object_store); |
| 617 } | 615 } |
| 618 | 616 |
| 619 | 617 |
| 620 void KeyedStoreIC::GenerateMegamorphic(MacroAssembler* masm, | 618 void KeyedStoreIC::GenerateMegamorphic(MacroAssembler* masm, |
| 621 LanguageMode language_mode) { | 619 LanguageMode language_mode) { |
| (...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 900 patcher.EmitCondition(ne); | 898 patcher.EmitCondition(ne); |
| 901 } else { | 899 } else { |
| 902 DCHECK(Assembler::GetCondition(branch_instr) == ne); | 900 DCHECK(Assembler::GetCondition(branch_instr) == ne); |
| 903 patcher.EmitCondition(eq); | 901 patcher.EmitCondition(eq); |
| 904 } | 902 } |
| 905 } | 903 } |
| 906 } // namespace internal | 904 } // namespace internal |
| 907 } // namespace v8 | 905 } // namespace v8 |
| 908 | 906 |
| 909 #endif // V8_TARGET_ARCH_ARM | 907 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |