Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(410)

Side by Side Diff: src/code-stub-assembler.cc

Issue 2303793002: Revert of [stubs] Port KeyedLoadIC_Generic stub to TurboFan (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/code-stub-assembler.h ('k') | src/ic/handler-compiler.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 the V8 project authors. All rights reserved. 1 // Copyright 2016 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/code-stub-assembler.h" 5 #include "src/code-stub-assembler.h"
6 #include "src/code-factory.h" 6 #include "src/code-factory.h"
7 #include "src/frames-inl.h" 7 #include "src/frames-inl.h"
8 #include "src/frames.h" 8 #include "src/frames.h"
9 #include "src/ic/handler-configuration.h" 9 #include "src/ic/handler-configuration.h"
10 #include "src/ic/stub-cache.h" 10 #include "src/ic/stub-cache.h"
(...skipping 612 matching lines...) Expand 10 before | Expand all | Expand 10 after
623 623
624 // Bitwise comparison succeeded, {lhs} and {rhs} considered equal. 624 // Bitwise comparison succeeded, {lhs} and {rhs} considered equal.
625 Goto(if_equal); 625 Goto(if_equal);
626 } 626 }
627 } 627 }
628 628
629 Bind(&if_mapnotsame); 629 Bind(&if_mapnotsame);
630 Goto(if_notequal); 630 Goto(if_notequal);
631 } 631 }
632 632
633 void CodeStubAssembler::BranchIfPrototypesHaveNoElements(
634 Node* receiver_map, Label* definitely_no_elements,
635 Label* possibly_elements) {
636 Variable var_map(this, MachineRepresentation::kTagged);
637 var_map.Bind(receiver_map);
638 Label loop_body(this, &var_map);
639 Node* empty_elements = LoadRoot(Heap::kEmptyFixedArrayRootIndex);
640 Goto(&loop_body);
641
642 Bind(&loop_body);
643 {
644 Node* map = var_map.value();
645 Node* prototype = LoadMapPrototype(map);
646 GotoIf(WordEqual(prototype, NullConstant()), definitely_no_elements);
647 Node* prototype_map = LoadMap(prototype);
648 // Pessimistically assume elements if a Proxy, Special API Object,
649 // or JSValue wrapper is found on the prototype chain. After this
650 // instance type check, it's not necessary to check for interceptors or
651 // access checks.
652 GotoIf(Int32LessThanOrEqual(LoadMapInstanceType(prototype_map),
653 Int32Constant(LAST_CUSTOM_ELEMENTS_RECEIVER)),
654 possibly_elements);
655 GotoIf(WordNotEqual(LoadElements(prototype), empty_elements),
656 possibly_elements);
657 var_map.Bind(prototype_map);
658 Goto(&loop_body);
659 }
660 }
661
662 void CodeStubAssembler::BranchIfFastJSArray(Node* object, Node* context, 633 void CodeStubAssembler::BranchIfFastJSArray(Node* object, Node* context,
663 Label* if_true, Label* if_false) { 634 Label* if_true, Label* if_false) {
664 // Bailout if receiver is a Smi. 635 Node* int32_zero = Int32Constant(0);
636 Node* int32_one = Int32Constant(1);
637
638 Node* empty_elements = LoadRoot(Heap::kEmptyFixedArrayRootIndex);
639
640 Variable last_map(this, MachineRepresentation::kTagged);
641 Label check_prototype(this);
642
643 // Bailout if Smi
665 GotoIf(WordIsSmi(object), if_false); 644 GotoIf(WordIsSmi(object), if_false);
666 645
667 Node* map = LoadMap(object); 646 Node* map = LoadMap(object);
647 last_map.Bind(map);
668 648
669 // Bailout if instance type is not JS_ARRAY_TYPE. 649 // Bailout if instance type is not JS_ARRAY_TYPE
670 GotoIf(WordNotEqual(LoadMapInstanceType(map), Int32Constant(JS_ARRAY_TYPE)), 650 GotoIf(WordNotEqual(LoadMapInstanceType(map), Int32Constant(JS_ARRAY_TYPE)),
671 if_false); 651 if_false);
672 652
673 Node* bit_field2 = LoadMapBitField2(map); 653 Node* bit_field2 = LoadMapBitField2(map);
674 Node* elements_kind = BitFieldDecode<Map::ElementsKindBits>(bit_field2); 654 Node* elements_kind = BitFieldDecode<Map::ElementsKindBits>(bit_field2);
675 655
676 // Bailout if receiver has slow elements. 656 // Bailout if slow receiver elements
677 GotoIf( 657 GotoIf(
678 Int32GreaterThan(elements_kind, Int32Constant(LAST_FAST_ELEMENTS_KIND)), 658 Int32GreaterThan(elements_kind, Int32Constant(LAST_FAST_ELEMENTS_KIND)),
679 if_false); 659 if_false);
680 660
681 // Check prototype chain if receiver does not have packed elements.
682 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == (FAST_SMI_ELEMENTS | 1)); 661 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == (FAST_SMI_ELEMENTS | 1));
683 STATIC_ASSERT(FAST_HOLEY_ELEMENTS == (FAST_ELEMENTS | 1)); 662 STATIC_ASSERT(FAST_HOLEY_ELEMENTS == (FAST_ELEMENTS | 1));
684 STATIC_ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == (FAST_DOUBLE_ELEMENTS | 1)); 663 STATIC_ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == (FAST_DOUBLE_ELEMENTS | 1));
685 Node* holey_elements = Word32And(elements_kind, Int32Constant(1)); 664
686 GotoIf(Word32Equal(holey_elements, Int32Constant(0)), if_true); 665 // Check prototype chain if receiver does not have packed elements
687 BranchIfPrototypesHaveNoElements(map, if_true, if_false); 666 Node* holey_elements = Word32And(elements_kind, int32_one);
667 Branch(Word32Equal(holey_elements, int32_zero), if_true, &check_prototype);
668
669 Bind(&check_prototype);
670 {
671 Label loop_body(this, &last_map);
672 Goto(&loop_body);
673 Bind(&loop_body);
674 Node* current_map = last_map.value();
675 Node* proto = LoadObjectField(current_map, Map::kPrototypeOffset);
676
677 // End loop
678 GotoIf(WordEqual(proto, NullConstant()), if_true);
679
680 // ASSERT: proto->IsHeapObject()
681 Node* proto_map = LoadMap(proto);
682
683 // Bailout if a Proxy, API Object, or JSValue wrapper found in prototype
684 // Because of this bailout, it's not necessary to check for interceptors or
685 // access checks on the prototype chain.
686 GotoIf(Int32LessThanOrEqual(LoadMapInstanceType(proto_map),
687 Int32Constant(LAST_CUSTOM_ELEMENTS_RECEIVER)),
688 if_false);
689
690 // Bailout if prototype contains non-empty elements
691 GotoUnless(WordEqual(LoadElements(proto), empty_elements), if_false);
692
693 last_map.Bind(proto_map);
694 Goto(&loop_body);
695 }
688 } 696 }
689 697
690 Node* CodeStubAssembler::AllocateRawUnaligned(Node* size_in_bytes, 698 Node* CodeStubAssembler::AllocateRawUnaligned(Node* size_in_bytes,
691 AllocationFlags flags, 699 AllocationFlags flags,
692 Node* top_address, 700 Node* top_address,
693 Node* limit_address) { 701 Node* limit_address) {
694 Node* top = Load(MachineType::Pointer(), top_address); 702 Node* top = Load(MachineType::Pointer(), top_address);
695 Node* limit = Load(MachineType::Pointer(), limit_address); 703 Node* limit = Load(MachineType::Pointer(), limit_address);
696 704
697 // If there's not enough space, call the runtime. 705 // If there's not enough space, call the runtime.
(...skipping 2776 matching lines...) Expand 10 before | Expand all | Expand 10 after
3474 Bind(&key_is_smi); 3482 Bind(&key_is_smi);
3475 { 3483 {
3476 var_intptr_key.Bind(SmiUntag(key)); 3484 var_intptr_key.Bind(SmiUntag(key));
3477 Goto(&done); 3485 Goto(&done);
3478 } 3486 }
3479 3487
3480 Bind(&done); 3488 Bind(&done);
3481 return var_intptr_key.value(); 3489 return var_intptr_key.value();
3482 } 3490 }
3483 3491
3484 void CodeStubAssembler::EmitFastElementsBoundsCheck(Node* object, 3492 // |is_jsarray| should be non-zero for JSArrays.
3485 Node* elements, 3493 void CodeStubAssembler::EmitBoundsCheck(Node* object, Node* elements,
3486 Node* intptr_key, 3494 Node* intptr_key, Node* is_jsarray,
3487 Node* is_jsarray_condition, 3495 Label* miss) {
3488 Label* miss) {
3489 Variable var_length(this, MachineRepresentation::kTagged); 3496 Variable var_length(this, MachineRepresentation::kTagged);
3490 Label if_array(this), length_loaded(this, &var_length); 3497 Label if_array(this), length_loaded(this, &var_length);
3491 GotoIf(is_jsarray_condition, &if_array); 3498 GotoUnless(WordEqual(is_jsarray, IntPtrConstant(0)), &if_array);
3492 { 3499 {
3493 var_length.Bind(SmiUntag(LoadFixedArrayBaseLength(elements))); 3500 var_length.Bind(SmiUntag(LoadFixedArrayBaseLength(elements)));
3494 Goto(&length_loaded); 3501 Goto(&length_loaded);
3495 } 3502 }
3496 Bind(&if_array); 3503 Bind(&if_array);
3497 { 3504 {
3498 var_length.Bind(SmiUntag(LoadObjectField(object, JSArray::kLengthOffset))); 3505 var_length.Bind(SmiUntag(LoadObjectField(object, JSArray::kLengthOffset)));
3499 Goto(&length_loaded); 3506 Goto(&length_loaded);
3500 } 3507 }
3501 Bind(&length_loaded); 3508 Bind(&length_loaded);
3502 GotoUnless(UintPtrLessThan(intptr_key, var_length.value()), miss); 3509 GotoUnless(UintPtrLessThan(intptr_key, var_length.value()), miss);
3503 } 3510 }
3504 3511
3505 // |key| should be untagged (int32). 3512 // |key| should be untagged (int32).
3506 void CodeStubAssembler::EmitElementLoad(Node* object, Node* elements, 3513 void CodeStubAssembler::EmitElementLoad(Node* object, Node* elements,
3507 Node* elements_kind, Node* key, 3514 Node* elements_kind, Node* key,
3508 Node* is_jsarray_condition,
3509 Label* if_hole, Label* rebox_double, 3515 Label* if_hole, Label* rebox_double,
3510 Variable* var_double_value, 3516 Variable* var_double_value,
3511 Label* unimplemented_elements_kind, 3517 Label* miss) {
3512 Label* out_of_bounds, Label* miss) {
3513 Label if_typed_array(this), if_fast_packed(this), if_fast_holey(this), 3518 Label if_typed_array(this), if_fast_packed(this), if_fast_holey(this),
3514 if_fast_double(this), if_fast_holey_double(this), if_nonfast(this), 3519 if_fast_double(this), if_fast_holey_double(this),
3515 if_dictionary(this), unreachable(this); 3520 unimplemented_elements_kind(this);
3521 STATIC_ASSERT(LAST_ELEMENTS_KIND == LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND);
3516 GotoIf( 3522 GotoIf(
3517 IntPtrGreaterThan(elements_kind, IntPtrConstant(LAST_FAST_ELEMENTS_KIND)), 3523 IntPtrGreaterThanOrEqual(
3518 &if_nonfast); 3524 elements_kind, IntPtrConstant(FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND)),
3525 &if_typed_array);
3519 3526
3520 EmitFastElementsBoundsCheck(object, elements, key, is_jsarray_condition,
3521 out_of_bounds);
3522 int32_t kinds[] = {// Handled by if_fast_packed. 3527 int32_t kinds[] = {// Handled by if_fast_packed.
3523 FAST_SMI_ELEMENTS, FAST_ELEMENTS, 3528 FAST_SMI_ELEMENTS, FAST_ELEMENTS,
3524 // Handled by if_fast_holey. 3529 // Handled by if_fast_holey.
3525 FAST_HOLEY_SMI_ELEMENTS, FAST_HOLEY_ELEMENTS, 3530 FAST_HOLEY_SMI_ELEMENTS, FAST_HOLEY_ELEMENTS,
3526 // Handled by if_fast_double. 3531 // Handled by if_fast_double.
3527 FAST_DOUBLE_ELEMENTS, 3532 FAST_DOUBLE_ELEMENTS,
3528 // Handled by if_fast_holey_double. 3533 // Handled by if_fast_holey_double.
3529 FAST_HOLEY_DOUBLE_ELEMENTS}; 3534 FAST_HOLEY_DOUBLE_ELEMENTS};
3530 Label* labels[] = {// FAST_{SMI,}_ELEMENTS 3535 Label* labels[] = {// FAST_{SMI,}_ELEMENTS
3531 &if_fast_packed, &if_fast_packed, 3536 &if_fast_packed, &if_fast_packed,
3532 // FAST_HOLEY_{SMI,}_ELEMENTS 3537 // FAST_HOLEY_{SMI,}_ELEMENTS
3533 &if_fast_holey, &if_fast_holey, 3538 &if_fast_holey, &if_fast_holey,
3534 // FAST_DOUBLE_ELEMENTS 3539 // FAST_DOUBLE_ELEMENTS
3535 &if_fast_double, 3540 &if_fast_double,
3536 // FAST_HOLEY_DOUBLE_ELEMENTS 3541 // FAST_HOLEY_DOUBLE_ELEMENTS
3537 &if_fast_holey_double}; 3542 &if_fast_holey_double};
3538 Switch(elements_kind, unimplemented_elements_kind, kinds, labels, 3543 Switch(elements_kind, &unimplemented_elements_kind, kinds, labels,
3539 arraysize(kinds)); 3544 arraysize(kinds));
3545 Bind(&unimplemented_elements_kind);
3546 {
3547 // Crash if we get here.
3548 DebugBreak();
3549 Goto(miss);
3550 }
3540 3551
3541 Bind(&if_fast_packed); 3552 Bind(&if_fast_packed);
3542 { 3553 {
3543 Comment("fast packed elements"); 3554 Comment("fast packed elements");
3544 // TODO(jkummerow): The Load*Element helpers add movsxlq instructions 3555 // TODO(jkummerow): The Load*Element helpers add movsxlq instructions
3545 // on x64 which we don't need here, because |key| is an IntPtr already. 3556 // on x64 which we don't need here, because |key| is an IntPtr already.
3546 // Do something about that. 3557 // Do something about that.
3547 Return(LoadFixedArrayElement(elements, key)); 3558 Return(LoadFixedArrayElement(elements, key));
3548 } 3559 }
3549 3560
(...skipping 25 matching lines...) Expand all
3575 Node* element_upper = LoadFixedDoubleArrayElement( 3586 Node* element_upper = LoadFixedDoubleArrayElement(
3576 elements, key, MachineType::Uint32(), kIeeeDoubleExponentWordOffset); 3587 elements, key, MachineType::Uint32(), kIeeeDoubleExponentWordOffset);
3577 GotoIf(Word32Equal(element_upper, Int32Constant(kHoleNanUpper32)), 3588 GotoIf(Word32Equal(element_upper, Int32Constant(kHoleNanUpper32)),
3578 if_hole); 3589 if_hole);
3579 } 3590 }
3580 var_double_value->Bind( 3591 var_double_value->Bind(
3581 LoadFixedDoubleArrayElement(elements, key, MachineType::Float64())); 3592 LoadFixedDoubleArrayElement(elements, key, MachineType::Float64()));
3582 Goto(rebox_double); 3593 Goto(rebox_double);
3583 } 3594 }
3584 3595
3585 Bind(&if_nonfast);
3586 {
3587 STATIC_ASSERT(LAST_ELEMENTS_KIND == LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND);
3588 GotoIf(IntPtrGreaterThanOrEqual(
3589 elements_kind,
3590 IntPtrConstant(FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND)),
3591 &if_typed_array);
3592 GotoIf(IntPtrEqual(elements_kind, IntPtrConstant(DICTIONARY_ELEMENTS)),
3593 &if_dictionary);
3594 Goto(unimplemented_elements_kind);
3595 }
3596
3597 Bind(&if_dictionary);
3598 {
3599 Comment("dictionary elements");
3600 Variable var_entry(this, MachineRepresentation::kWord32);
3601 Label if_found(this);
3602 NumberDictionaryLookup<SeededNumberDictionary>(elements, key, &if_found,
3603 &var_entry, if_hole);
3604 Bind(&if_found);
3605 // Check that the value is a data property.
3606 Node* details_index = EntryToIndex<SeededNumberDictionary>(
3607 var_entry.value(), SeededNumberDictionary::kEntryDetailsIndex);
3608 Node* details = SmiToWord32(LoadFixedArrayElement(elements, details_index));
3609 Node* kind = BitFieldDecode<PropertyDetails::KindField>(details);
3610 // TODO(jkummerow): Support accessors without missing?
3611 GotoUnless(Word32Equal(kind, Int32Constant(kData)), miss);
3612 // Finally, load the value.
3613 Node* value_index = EntryToIndex<SeededNumberDictionary>(
3614 var_entry.value(), SeededNumberDictionary::kEntryValueIndex);
3615 Return(LoadFixedArrayElement(elements, value_index));
3616 }
3617
3618 Bind(&if_typed_array); 3596 Bind(&if_typed_array);
3619 { 3597 {
3620 Comment("typed elements"); 3598 Comment("typed elements");
3621 // Check if buffer has been neutered. 3599 // Check if buffer has been neutered.
3622 Node* buffer = LoadObjectField(object, JSArrayBufferView::kBufferOffset); 3600 Node* buffer = LoadObjectField(object, JSArrayBufferView::kBufferOffset);
3623 Node* bitfield = LoadObjectField(buffer, JSArrayBuffer::kBitFieldOffset, 3601 Node* bitfield = LoadObjectField(buffer, JSArrayBuffer::kBitFieldOffset,
3624 MachineType::Uint32()); 3602 MachineType::Uint32());
3625 Node* neutered_bit = 3603 Node* neutered_bit =
3626 Word32And(bitfield, Int32Constant(JSArrayBuffer::WasNeutered::kMask)); 3604 Word32And(bitfield, Int32Constant(JSArrayBuffer::WasNeutered::kMask));
3627 GotoUnless(Word32Equal(neutered_bit, Int32Constant(0)), miss); 3605 GotoUnless(Word32Equal(neutered_bit, Int32Constant(0)), miss);
3628
3629 // Bounds check.
3630 Node* length =
3631 SmiUntag(LoadObjectField(object, JSTypedArray::kLengthOffset));
3632 GotoUnless(UintPtrLessThan(key, length), out_of_bounds);
3633
3634 // Backing store = external_pointer + base_pointer. 3606 // Backing store = external_pointer + base_pointer.
3635 Node* external_pointer = 3607 Node* external_pointer =
3636 LoadObjectField(elements, FixedTypedArrayBase::kExternalPointerOffset, 3608 LoadObjectField(elements, FixedTypedArrayBase::kExternalPointerOffset,
3637 MachineType::Pointer()); 3609 MachineType::Pointer());
3638 Node* base_pointer = 3610 Node* base_pointer =
3639 LoadObjectField(elements, FixedTypedArrayBase::kBasePointerOffset); 3611 LoadObjectField(elements, FixedTypedArrayBase::kBasePointerOffset);
3640 Node* backing_store = IntPtrAdd(external_pointer, base_pointer); 3612 Node* backing_store = IntPtrAdd(external_pointer, base_pointer);
3641 3613
3642 Label uint8_elements(this), int8_elements(this), uint16_elements(this), 3614 Label uint8_elements(this), int8_elements(this), uint16_elements(this),
3643 int16_elements(this), uint32_elements(this), int32_elements(this), 3615 int16_elements(this), uint32_elements(this), int32_elements(this),
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
3732 WordAnd(handler_word, IntPtrConstant(LoadHandlerTypeBit::kMask)); 3704 WordAnd(handler_word, IntPtrConstant(LoadHandlerTypeBit::kMask));
3733 GotoUnless( 3705 GotoUnless(
3734 WordEqual(handler_type, IntPtrConstant(kLoadICHandlerForElements)), 3706 WordEqual(handler_type, IntPtrConstant(kLoadICHandlerForElements)),
3735 &property); 3707 &property);
3736 3708
3737 Comment("element_load"); 3709 Comment("element_load");
3738 Node* key = TryToIntptr(p->name, miss); 3710 Node* key = TryToIntptr(p->name, miss);
3739 Node* elements = LoadElements(p->receiver); 3711 Node* elements = LoadElements(p->receiver);
3740 Node* is_jsarray = 3712 Node* is_jsarray =
3741 WordAnd(handler_word, IntPtrConstant(KeyedLoadIsJsArray::kMask)); 3713 WordAnd(handler_word, IntPtrConstant(KeyedLoadIsJsArray::kMask));
3742 Node* is_jsarray_condition = WordNotEqual(is_jsarray, IntPtrConstant(0)); 3714 EmitBoundsCheck(p->receiver, elements, key, is_jsarray, miss);
3715 Label if_hole(this);
3716
3743 Node* elements_kind = BitFieldDecode<KeyedLoadElementsKind>(handler_word); 3717 Node* elements_kind = BitFieldDecode<KeyedLoadElementsKind>(handler_word);
3744 Label if_hole(this), unimplemented_elements_kind(this);
3745 Label* out_of_bounds = miss;
3746 EmitElementLoad(p->receiver, elements, elements_kind, key,
3747 is_jsarray_condition, &if_hole, &rebox_double,
3748 &var_double_value, &unimplemented_elements_kind,
3749 out_of_bounds, miss);
3750 3718
3751 Bind(&unimplemented_elements_kind); 3719 EmitElementLoad(p->receiver, elements, elements_kind, key, &if_hole,
3752 { 3720 &rebox_double, &var_double_value, miss);
3753 // Smi handlers should only be installed for supported elements kinds.
3754 // Crash if we get here.
3755 DebugBreak();
3756 Goto(miss);
3757 }
3758 3721
3759 Bind(&if_hole); 3722 Bind(&if_hole);
3760 { 3723 {
3761 Comment("convert hole"); 3724 Comment("convert hole");
3762 Node* convert_hole = 3725 Node* convert_hole =
3763 WordAnd(handler_word, IntPtrConstant(KeyedLoadConvertHole::kMask)); 3726 WordAnd(handler_word, IntPtrConstant(KeyedLoadConvertHole::kMask));
3764 GotoIf(WordEqual(convert_hole, IntPtrConstant(0)), miss); 3727 GotoIf(WordEqual(convert_hole, IntPtrConstant(0)), miss);
3765 Node* protector_cell = LoadRoot(Heap::kArrayProtectorRootIndex); 3728 Node* protector_cell = LoadRoot(Heap::kArrayProtectorRootIndex);
3766 DCHECK(isolate()->heap()->array_protector()->IsPropertyCell()); 3729 DCHECK(isolate()->heap()->array_protector()->IsPropertyCell());
3767 GotoUnless( 3730 GotoUnless(
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
3926 &miss, 1); 3889 &miss, 1);
3927 } 3890 }
3928 Bind(&miss); 3891 Bind(&miss);
3929 { 3892 {
3930 Comment("KeyedLoadIC_miss"); 3893 Comment("KeyedLoadIC_miss");
3931 TailCallRuntime(Runtime::kKeyedLoadIC_Miss, p->context, p->receiver, 3894 TailCallRuntime(Runtime::kKeyedLoadIC_Miss, p->context, p->receiver,
3932 p->name, p->slot, p->vector); 3895 p->name, p->slot, p->vector);
3933 } 3896 }
3934 } 3897 }
3935 3898
3936 void CodeStubAssembler::KeyedLoadICGeneric(const LoadICParameters* p) {
3937 Variable var_index(this, MachineType::PointerRepresentation());
3938 Label if_index(this), if_key_is_not_number(this), if_index_name(this),
3939 if_unique_name(this), if_element_hole(this), if_oob(this), slow(this),
3940 stub_cache_miss(this), if_property_dictionary(this);
3941
3942 Node* receiver = p->receiver;
3943 GotoIf(WordIsSmi(receiver), &slow);
3944 Node* receiver_map = LoadMap(receiver);
3945 Node* instance_type = LoadMapInstanceType(receiver_map);
3946 // Receivers requiring non-standard element accesses (interceptors, access
3947 // checks, strings and string wrappers, proxies) are handled in the runtime.
3948 GotoIf(Int32LessThanOrEqual(instance_type,
3949 Int32Constant(LAST_CUSTOM_ELEMENTS_RECEIVER)),
3950 &slow);
3951
3952 // Check what kind of key we have.
3953 Node* key = p->name;
3954 var_index.Bind(TryToIntptr(key, &if_key_is_not_number));
3955 Goto(&if_index);
3956
3957 Node* hash = nullptr;
3958 // TODO(jkummerow): Unify this with CodeStubAssembler::TryToName().
3959 Bind(&if_key_is_not_number);
3960 {
3961 Node* key_map = LoadMap(key);
3962 Node* key_instance_type = LoadMapInstanceType(key_map);
3963 // Jump to the runtime if key is neither String nor Symbol.
3964 GotoIf(Int32GreaterThan(key_instance_type,
3965 Int32Constant(LAST_UNIQUE_NAME_TYPE)),
3966 &slow);
3967 // Symbols are always unique names.
3968 GotoIf(Word32Equal(key_instance_type, Int32Constant(LAST_UNIQUE_NAME_TYPE)),
3969 &if_unique_name);
3970 // |key| is a String. Check if it has a cached array index.
3971 hash = LoadNameHashField(key);
3972 Node* contains_index =
3973 Word32And(hash, Int32Constant(Name::kContainsCachedArrayIndexMask));
3974 GotoIf(Word32Equal(contains_index, Int32Constant(0)), &if_index_name);
3975 // Otherwise, jump to the runtime if the string is not internalized.
3976 STATIC_ASSERT(kNotInternalizedTag != 0);
3977 Node* not_internalized =
3978 Word32And(key_instance_type, Int32Constant(kIsNotInternalizedMask));
3979 GotoIf(Word32NotEqual(not_internalized, Int32Constant(0)), &slow);
3980 Goto(&if_unique_name);
3981 }
3982
3983 Bind(&if_index_name);
3984 {
3985 Comment("string key with cached array index");
3986 var_index.Bind(BitFieldDecode<String::ArrayIndexValueBits>(hash));
3987 Goto(&if_index);
3988 }
3989
3990 Bind(&if_index);
3991 {
3992 Comment("integer index");
3993 Node* index = var_index.value();
3994 Node* elements = LoadElements(receiver);
3995 Node* bitfield2 = LoadMapBitField2(receiver_map);
3996 Node* elements_kind = BitFieldDecode<Map::ElementsKindBits>(bitfield2);
3997 Node* is_jsarray_condition =
3998 Word32Equal(instance_type, Int32Constant(JS_ARRAY_TYPE));
3999 Variable var_double_value(this, MachineRepresentation::kFloat64);
4000 Label rebox_double(this, &var_double_value);
4001
4002 // Unimplemented elements kinds fall back to a runtime call.
4003 Label* unimplemented_elements_kind = &slow;
4004 IncrementCounter(isolate()->counters()->ic_keyed_load_generic_smi(), 1);
4005 EmitElementLoad(receiver, elements, elements_kind, index,
4006 is_jsarray_condition, &if_element_hole, &rebox_double,
4007 &var_double_value, unimplemented_elements_kind, &if_oob,
4008 &slow);
4009
4010 Bind(&rebox_double);
4011 Return(AllocateHeapNumberWithValue(var_double_value.value()));
4012 }
4013
4014 Bind(&if_oob);
4015 {
4016 Comment("out of bounds");
4017 Node* index = var_index.value();
4018 // Negative keys can't take the fast OOB path.
4019 GotoIf(IntPtrLessThan(index, IntPtrConstant(0)), &slow);
4020 // Positive OOB indices are effectively the same as hole loads.
4021 Goto(&if_element_hole);
4022 }
4023
4024 Bind(&if_element_hole);
4025 {
4026 Comment("found the hole");
4027 Label return_undefined(this);
4028 BranchIfPrototypesHaveNoElements(receiver_map, &return_undefined, &slow);
4029
4030 Bind(&return_undefined);
4031 Return(UndefinedConstant());
4032 }
4033
4034 Node* properties = nullptr;
4035 Bind(&if_unique_name);
4036 {
4037 Comment("key is unique name");
4038 // Check if the receiver has fast or slow properties.
4039 properties = LoadProperties(receiver);
4040 Node* properties_map = LoadMap(properties);
4041 GotoIf(WordEqual(properties_map, LoadRoot(Heap::kHashTableMapRootIndex)),
4042 &if_property_dictionary);
4043
4044 Comment("stub cache probe for fast property load");
4045 Variable var_handler(this, MachineRepresentation::kTagged);
4046 Label found_handler(this, &var_handler), stub_cache_miss(this);
4047 TryProbeStubCache(isolate()->load_stub_cache(), receiver, key,
4048 &found_handler, &var_handler, &stub_cache_miss);
4049 Bind(&found_handler);
4050 { HandleLoadICHandlerCase(p, var_handler.value(), &slow); }
4051
4052 Bind(&stub_cache_miss);
4053 {
4054 Comment("KeyedLoadGeneric_miss");
4055 TailCallRuntime(Runtime::kKeyedLoadIC_Miss, p->context, p->receiver,
4056 p->name, p->slot, p->vector);
4057 }
4058 }
4059
4060 Bind(&if_property_dictionary);
4061 {
4062 Comment("dictionary property load");
4063 // We checked for LAST_CUSTOM_ELEMENTS_RECEIVER before, which rules out
4064 // seeing global objects here (which would need special handling).
4065
4066 Variable var_name_index(this, MachineRepresentation::kWord32);
4067 Label dictionary_found(this, &var_name_index);
4068 NameDictionaryLookup<NameDictionary>(properties, key, &dictionary_found,
4069 &var_name_index, &slow);
4070 Bind(&dictionary_found);
4071 {
4072 Variable var_details(this, MachineRepresentation::kWord32);
4073 Variable var_value(this, MachineRepresentation::kTagged);
4074 LoadPropertyFromNameDictionary(properties, var_name_index.value(),
4075 &var_details, &var_value);
4076 Node* kind =
4077 BitFieldDecode<PropertyDetails::KindField>(var_details.value());
4078 // TODO(jkummerow): Support accessors without missing?
4079 GotoUnless(Word32Equal(kind, Int32Constant(kData)), &slow);
4080 IncrementCounter(isolate()->counters()->ic_keyed_load_generic_symbol(),
4081 1);
4082 Return(var_value.value());
4083 }
4084 }
4085
4086 Bind(&slow);
4087 {
4088 Comment("KeyedLoadGeneric_slow");
4089 IncrementCounter(isolate()->counters()->ic_keyed_load_generic_slow(), 1);
4090 // TODO(jkummerow): Should we use the GetProperty TF stub instead?
4091 TailCallRuntime(Runtime::kKeyedGetProperty, p->context, p->receiver,
4092 p->name);
4093 }
4094 }
4095
4096 void CodeStubAssembler::LoadGlobalIC(const LoadICParameters* p) { 3899 void CodeStubAssembler::LoadGlobalIC(const LoadICParameters* p) {
4097 Label try_handler(this), miss(this); 3900 Label try_handler(this), miss(this);
4098 Node* weak_cell = 3901 Node* weak_cell =
4099 LoadFixedArrayElement(p->vector, p->slot, 0, SMI_PARAMETERS); 3902 LoadFixedArrayElement(p->vector, p->slot, 0, SMI_PARAMETERS);
4100 AssertInstanceType(weak_cell, WEAK_CELL_TYPE); 3903 AssertInstanceType(weak_cell, WEAK_CELL_TYPE);
4101 3904
4102 // Load value or try handler case if the {weak_cell} is cleared. 3905 // Load value or try handler case if the {weak_cell} is cleared.
4103 Node* property_cell = LoadWeakCellValue(weak_cell, &try_handler); 3906 Node* property_cell = LoadWeakCellValue(weak_cell, &try_handler);
4104 AssertInstanceType(property_cell, PROPERTY_CELL_TYPE); 3907 AssertInstanceType(property_cell, PROPERTY_CELL_TYPE);
4105 3908
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
4211 Heap::kTheHoleValueRootIndex); 4014 Heap::kTheHoleValueRootIndex);
4212 4015
4213 // Store the WeakCell in the feedback vector. 4016 // Store the WeakCell in the feedback vector.
4214 StoreFixedArrayElement(feedback_vector, slot, cell, UPDATE_WRITE_BARRIER, 4017 StoreFixedArrayElement(feedback_vector, slot, cell, UPDATE_WRITE_BARRIER,
4215 CodeStubAssembler::SMI_PARAMETERS); 4018 CodeStubAssembler::SMI_PARAMETERS);
4216 return cell; 4019 return cell;
4217 } 4020 }
4218 4021
4219 } // namespace internal 4022 } // namespace internal
4220 } // namespace v8 4023 } // namespace v8
OLDNEW
« no previous file with comments | « src/code-stub-assembler.h ('k') | src/ic/handler-compiler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698