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 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_X64 | 7 #if V8_TARGET_ARCH_X64 |
8 | 8 |
9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
10 #include "src/ic/ic.h" | 10 #include "src/ic/ic.h" |
(...skipping 548 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
559 __ LoadTransitionedArrayMapConditional(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS, | 559 __ LoadTransitionedArrayMapConditional(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS, |
560 rbx, rdi, slow); | 560 rbx, rdi, slow); |
561 mode = AllocationSite::GetMode(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS); | 561 mode = AllocationSite::GetMode(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS); |
562 ElementsTransitionGenerator::GenerateDoubleToObject(masm, receiver, key, | 562 ElementsTransitionGenerator::GenerateDoubleToObject(masm, receiver, key, |
563 value, rbx, mode, slow); | 563 value, rbx, mode, slow); |
564 __ movp(rbx, FieldOperand(receiver, JSObject::kElementsOffset)); | 564 __ movp(rbx, FieldOperand(receiver, JSObject::kElementsOffset)); |
565 __ jmp(&finish_object_store); | 565 __ jmp(&finish_object_store); |
566 } | 566 } |
567 | 567 |
568 | 568 |
569 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, | 569 void KeyedStoreIC::GenerateGeneric( |
570 StrictMode strict_mode) { | 570 MacroAssembler* masm, StrictMode strict_mode, |
| 571 KeyedStoreStubCacheRequirement handler_requirement) { |
571 // Return address is on the stack. | 572 // Return address is on the stack. |
572 Label slow, slow_with_tagged_index, fast_object, fast_object_grow; | 573 Label slow, slow_with_tagged_index, fast_object, fast_object_grow; |
573 Label fast_double, fast_double_grow; | 574 Label fast_double, fast_double_grow; |
574 Label array, extra, check_if_double_array; | 575 Label array, extra, check_if_double_array, maybe_name_key, miss; |
575 Register receiver = StoreDescriptor::ReceiverRegister(); | 576 Register receiver = StoreDescriptor::ReceiverRegister(); |
576 Register key = StoreDescriptor::NameRegister(); | 577 Register key = StoreDescriptor::NameRegister(); |
577 DCHECK(receiver.is(rdx)); | 578 DCHECK(receiver.is(rdx)); |
578 DCHECK(key.is(rcx)); | 579 DCHECK(key.is(rcx)); |
579 | 580 |
580 // Check that the object isn't a smi. | 581 // Check that the object isn't a smi. |
581 __ JumpIfSmi(receiver, &slow_with_tagged_index); | 582 __ JumpIfSmi(receiver, &slow_with_tagged_index); |
582 // Get the map from the receiver. | 583 // Get the map from the receiver. |
583 __ movp(r9, FieldOperand(receiver, HeapObject::kMapOffset)); | 584 __ movp(r9, FieldOperand(receiver, HeapObject::kMapOffset)); |
584 // Check that the receiver does not require access checks and is not observed. | 585 // Check that the receiver does not require access checks and is not observed. |
585 // The generic stub does not perform map checks or handle observed objects. | 586 // The generic stub does not perform map checks or handle observed objects. |
586 __ testb(FieldOperand(r9, Map::kBitFieldOffset), | 587 __ testb(FieldOperand(r9, Map::kBitFieldOffset), |
587 Immediate(1 << Map::kIsAccessCheckNeeded | 1 << Map::kIsObserved)); | 588 Immediate(1 << Map::kIsAccessCheckNeeded | 1 << Map::kIsObserved)); |
588 __ j(not_zero, &slow_with_tagged_index); | 589 __ j(not_zero, &slow_with_tagged_index); |
589 // Check that the key is a smi. | 590 // Check that the key is a smi. |
590 __ JumpIfNotSmi(key, &slow_with_tagged_index); | 591 __ JumpIfNotSmi(key, &maybe_name_key); |
591 __ SmiToInteger32(key, key); | 592 __ SmiToInteger32(key, key); |
592 | 593 |
593 __ CmpInstanceType(r9, JS_ARRAY_TYPE); | 594 __ CmpInstanceType(r9, JS_ARRAY_TYPE); |
594 __ j(equal, &array); | 595 __ j(equal, &array); |
595 // Check that the object is some kind of JSObject. | 596 // Check that the object is some kind of JSObject. |
596 __ CmpInstanceType(r9, FIRST_JS_OBJECT_TYPE); | 597 __ CmpInstanceType(r9, FIRST_JS_OBJECT_TYPE); |
597 __ j(below, &slow); | 598 __ j(below, &slow); |
598 | 599 |
599 // Object case: Check key against length in the elements array. | 600 // Object case: Check key against length in the elements array. |
600 __ movp(rbx, FieldOperand(receiver, JSObject::kElementsOffset)); | 601 __ movp(rbx, FieldOperand(receiver, JSObject::kElementsOffset)); |
601 // Check array bounds. | 602 // Check array bounds. |
602 __ SmiCompareInteger32(FieldOperand(rbx, FixedArray::kLengthOffset), key); | 603 __ SmiCompareInteger32(FieldOperand(rbx, FixedArray::kLengthOffset), key); |
603 // rbx: FixedArray | 604 // rbx: FixedArray |
604 __ j(above, &fast_object); | 605 __ j(above, &fast_object); |
605 | 606 |
606 // Slow case: call runtime. | 607 // Slow case: call runtime. |
607 __ bind(&slow); | 608 __ bind(&slow); |
608 __ Integer32ToSmi(key, key); | 609 __ Integer32ToSmi(key, key); |
609 __ bind(&slow_with_tagged_index); | 610 __ bind(&slow_with_tagged_index); |
610 PropertyICCompiler::GenerateRuntimeSetProperty(masm, strict_mode); | 611 PropertyICCompiler::GenerateRuntimeSetProperty(masm, strict_mode); |
611 // Never returns to here. | 612 // Never returns to here. |
612 | 613 |
| 614 __ bind(&maybe_name_key); |
| 615 __ movp(r9, FieldOperand(key, HeapObject::kMapOffset)); |
| 616 __ movzxbp(r9, FieldOperand(r9, Map::kInstanceTypeOffset)); |
| 617 __ JumpIfNotUniqueNameInstanceType(r9, &slow_with_tagged_index); |
| 618 Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( |
| 619 Code::ComputeHandlerFlags(Code::STORE_IC)); |
| 620 masm->isolate()->stub_cache()->GenerateProbe(masm, flags, false, receiver, |
| 621 key, rbx, no_reg); |
| 622 // Cache miss. |
| 623 if (handler_requirement == kCallRuntimeOnMissingHandler) { |
| 624 __ jmp(&slow_with_tagged_index); |
| 625 } else { |
| 626 DCHECK(handler_requirement == kMissOnMissingHandler); |
| 627 __ jmp(&miss); |
| 628 } |
| 629 |
613 // Extra capacity case: Check if there is extra capacity to | 630 // Extra capacity case: Check if there is extra capacity to |
614 // perform the store and update the length. Used for adding one | 631 // perform the store and update the length. Used for adding one |
615 // element to the array by writing to array[array.length]. | 632 // element to the array by writing to array[array.length]. |
616 __ bind(&extra); | 633 __ bind(&extra); |
617 // receiver is a JSArray. | 634 // receiver is a JSArray. |
618 // rbx: receiver's elements array (a FixedArray) | 635 // rbx: receiver's elements array (a FixedArray) |
619 // flags: smicompare (receiver.length(), rbx) | 636 // flags: smicompare (receiver.length(), rbx) |
620 __ j(not_equal, &slow); // do not leave holes in the array | 637 __ j(not_equal, &slow); // do not leave holes in the array |
621 __ SmiCompareInteger32(FieldOperand(rbx, FixedArray::kLengthOffset), key); | 638 __ SmiCompareInteger32(FieldOperand(rbx, FixedArray::kLengthOffset), key); |
622 __ j(below_equal, &slow); | 639 __ j(below_equal, &slow); |
(...skipping 18 matching lines...) Expand all Loading... |
641 | 658 |
642 // Check the key against the length in the array, compute the | 659 // Check the key against the length in the array, compute the |
643 // address to store into and fall through to fast case. | 660 // address to store into and fall through to fast case. |
644 __ SmiCompareInteger32(FieldOperand(receiver, JSArray::kLengthOffset), key); | 661 __ SmiCompareInteger32(FieldOperand(receiver, JSArray::kLengthOffset), key); |
645 __ j(below_equal, &extra); | 662 __ j(below_equal, &extra); |
646 | 663 |
647 KeyedStoreGenerateGenericHelper(masm, &fast_object, &fast_double, &slow, | 664 KeyedStoreGenerateGenericHelper(masm, &fast_object, &fast_double, &slow, |
648 kCheckMap, kDontIncrementLength); | 665 kCheckMap, kDontIncrementLength); |
649 KeyedStoreGenerateGenericHelper(masm, &fast_object_grow, &fast_double_grow, | 666 KeyedStoreGenerateGenericHelper(masm, &fast_object_grow, &fast_double_grow, |
650 &slow, kDontCheckMap, kIncrementLength); | 667 &slow, kDontCheckMap, kIncrementLength); |
| 668 |
| 669 if (handler_requirement == kMissOnMissingHandler) { |
| 670 __ bind(&miss); |
| 671 GenerateMiss(masm); |
| 672 } |
651 } | 673 } |
652 | 674 |
653 | 675 |
654 static Operand GenerateMappedArgumentsLookup( | 676 static Operand GenerateMappedArgumentsLookup( |
655 MacroAssembler* masm, Register object, Register key, Register scratch1, | 677 MacroAssembler* masm, Register object, Register key, Register scratch1, |
656 Register scratch2, Register scratch3, Label* unmapped_case, | 678 Register scratch2, Register scratch3, Label* unmapped_case, |
657 Label* slow_case) { | 679 Label* slow_case) { |
658 Heap* heap = masm->isolate()->heap(); | 680 Heap* heap = masm->isolate()->heap(); |
659 | 681 |
660 // Check that the receiver is a JSObject. Because of the elements | 682 // Check that the receiver is a JSObject. Because of the elements |
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
981 Condition cc = | 1003 Condition cc = |
982 (check == ENABLE_INLINED_SMI_CHECK) | 1004 (check == ENABLE_INLINED_SMI_CHECK) |
983 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) | 1005 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) |
984 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); | 1006 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); |
985 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); | 1007 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); |
986 } | 1008 } |
987 } | 1009 } |
988 } // namespace v8::internal | 1010 } // namespace v8::internal |
989 | 1011 |
990 #endif // V8_TARGET_ARCH_X64 | 1012 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |