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

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

Issue 2245683002: [stubs] Port KeyedLoadIC_Generic stub to TurboFan (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 4 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(
Jakob Kummerow 2016/08/12 15:07:09 This is pulled out from below (BranchIfFastJSArray
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
633 void CodeStubAssembler::BranchIfFastJSArray(Node* object, Node* context, 662 void CodeStubAssembler::BranchIfFastJSArray(Node* object, Node* context,
634 Label* if_true, Label* if_false) { 663 Label* if_true, Label* if_false) {
635 Node* int32_zero = Int32Constant(0); 664 // Bailout if receiver is a Smi.
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
644 GotoIf(WordIsSmi(object), if_false); 665 GotoIf(WordIsSmi(object), if_false);
645 666
646 Node* map = LoadMap(object); 667 Node* map = LoadMap(object);
647 last_map.Bind(map);
648 668
649 // Bailout if instance type is not JS_ARRAY_TYPE 669 // Bailout if instance type is not JS_ARRAY_TYPE.
650 GotoIf(WordNotEqual(LoadMapInstanceType(map), Int32Constant(JS_ARRAY_TYPE)), 670 GotoIf(WordNotEqual(LoadMapInstanceType(map), Int32Constant(JS_ARRAY_TYPE)),
651 if_false); 671 if_false);
652 672
653 Node* bit_field2 = LoadMapBitField2(map); 673 Node* bit_field2 = LoadMapBitField2(map);
654 Node* elements_kind = BitFieldDecode<Map::ElementsKindBits>(bit_field2); 674 Node* elements_kind = BitFieldDecode<Map::ElementsKindBits>(bit_field2);
655 675
656 // Bailout if slow receiver elements 676 // Bailout if receiver has slow elements.
caitp 2016/08/12 15:49:53 The re-worded comments are appreciated :)
657 GotoIf( 677 GotoIf(
658 Int32GreaterThan(elements_kind, Int32Constant(LAST_FAST_ELEMENTS_KIND)), 678 Int32GreaterThan(elements_kind, Int32Constant(LAST_FAST_ELEMENTS_KIND)),
659 if_false); 679 if_false);
660 680
681 // Check prototype chain if receiver does not have packed elements.
661 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == (FAST_SMI_ELEMENTS | 1)); 682 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == (FAST_SMI_ELEMENTS | 1));
662 STATIC_ASSERT(FAST_HOLEY_ELEMENTS == (FAST_ELEMENTS | 1)); 683 STATIC_ASSERT(FAST_HOLEY_ELEMENTS == (FAST_ELEMENTS | 1));
663 STATIC_ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == (FAST_DOUBLE_ELEMENTS | 1)); 684 STATIC_ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == (FAST_DOUBLE_ELEMENTS | 1));
664 685 Node* holey_elements = Word32And(elements_kind, Int32Constant(1));
665 // Check prototype chain if receiver does not have packed elements 686 GotoIf(Word32Equal(holey_elements, Int32Constant(0)), if_true);
666 Node* holey_elements = Word32And(elements_kind, int32_one); 687 BranchIfPrototypesHaveNoElements(map, if_true, if_false);
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 }
696 } 688 }
697 689
698 Node* CodeStubAssembler::AllocateRawUnaligned(Node* size_in_bytes, 690 Node* CodeStubAssembler::AllocateRawUnaligned(Node* size_in_bytes,
699 AllocationFlags flags, 691 AllocationFlags flags,
700 Node* top_address, 692 Node* top_address,
701 Node* limit_address) { 693 Node* limit_address) {
702 Node* top = Load(MachineType::Pointer(), top_address); 694 Node* top = Load(MachineType::Pointer(), top_address);
703 Node* limit = Load(MachineType::Pointer(), limit_address); 695 Node* limit = Load(MachineType::Pointer(), limit_address);
704 696
705 // If there's not enough space, call the runtime. 697 // If there's not enough space, call the runtime.
(...skipping 2775 matching lines...) Expand 10 before | Expand all | Expand 10 after
3481 Bind(&key_is_smi); 3473 Bind(&key_is_smi);
3482 { 3474 {
3483 var_intptr_key.Bind(SmiUntag(key)); 3475 var_intptr_key.Bind(SmiUntag(key));
3484 Goto(&done); 3476 Goto(&done);
3485 } 3477 }
3486 3478
3487 Bind(&done); 3479 Bind(&done);
3488 return var_intptr_key.value(); 3480 return var_intptr_key.value();
3489 } 3481 }
3490 3482
3491 // |is_jsarray| should be non-zero for JSArrays. 3483 void CodeStubAssembler::EmitFastElementsBoundsCheck(Node* object,
3492 void CodeStubAssembler::EmitBoundsCheck(Node* object, Node* elements, 3484 Node* elements,
3493 Node* intptr_key, Node* is_jsarray, 3485 Node* intptr_key,
3494 Label* miss) { 3486 Node* is_jsarray_condition,
3487 Label* miss) {
3495 Variable var_length(this, MachineRepresentation::kTagged); 3488 Variable var_length(this, MachineRepresentation::kTagged);
3496 Label if_array(this), length_loaded(this, &var_length); 3489 Label if_array(this), length_loaded(this, &var_length);
3497 GotoUnless(WordEqual(is_jsarray, IntPtrConstant(0)), &if_array); 3490 GotoIf(is_jsarray_condition, &if_array);
3498 { 3491 {
3499 var_length.Bind(SmiUntag(LoadFixedArrayBaseLength(elements))); 3492 var_length.Bind(SmiUntag(LoadFixedArrayBaseLength(elements)));
3500 Goto(&length_loaded); 3493 Goto(&length_loaded);
3501 } 3494 }
3502 Bind(&if_array); 3495 Bind(&if_array);
3503 { 3496 {
3504 var_length.Bind(SmiUntag(LoadObjectField(object, JSArray::kLengthOffset))); 3497 var_length.Bind(SmiUntag(LoadObjectField(object, JSArray::kLengthOffset)));
3505 Goto(&length_loaded); 3498 Goto(&length_loaded);
3506 } 3499 }
3507 Bind(&length_loaded); 3500 Bind(&length_loaded);
3508 GotoUnless(UintPtrLessThan(intptr_key, var_length.value()), miss); 3501 GotoUnless(UintPtrLessThan(intptr_key, var_length.value()), miss);
3509 } 3502 }
3510 3503
3511 // |key| should be untagged (int32). 3504 // |key| should be untagged (int32).
3512 void CodeStubAssembler::EmitElementLoad(Node* object, Node* elements, 3505 void CodeStubAssembler::EmitElementLoad(Node* object, Node* elements,
3513 Node* elements_kind, Node* key, 3506 Node* elements_kind, Node* key,
3507 Node* is_jsarray_condition,
3514 Label* if_hole, Label* rebox_double, 3508 Label* if_hole, Label* rebox_double,
3515 Variable* var_double_value, 3509 Variable* var_double_value,
3516 Label* miss) { 3510 Label* unimplemented_elements_kind,
3511 Label* out_of_bounds, Label* miss) {
3517 Label if_typed_array(this), if_fast_packed(this), if_fast_holey(this), 3512 Label if_typed_array(this), if_fast_packed(this), if_fast_holey(this),
3518 if_fast_double(this), if_fast_holey_double(this), 3513 if_fast_double(this), if_fast_holey_double(this), if_nonfast(this),
3519 unimplemented_elements_kind(this); 3514 if_dictionary(this), unreachable(this);
3520 STATIC_ASSERT(LAST_ELEMENTS_KIND == LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND);
3521 GotoIf( 3515 GotoIf(
3522 IntPtrGreaterThanOrEqual( 3516 IntPtrGreaterThan(elements_kind, IntPtrConstant(LAST_FAST_ELEMENTS_KIND)),
3523 elements_kind, IntPtrConstant(FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND)), 3517 &if_nonfast);
3524 &if_typed_array);
3525 3518
3519 EmitFastElementsBoundsCheck(object, elements, key, is_jsarray_condition,
3520 out_of_bounds);
3526 int32_t kinds[] = {// Handled by if_fast_packed. 3521 int32_t kinds[] = {// Handled by if_fast_packed.
3527 FAST_SMI_ELEMENTS, FAST_ELEMENTS, 3522 FAST_SMI_ELEMENTS, FAST_ELEMENTS,
3528 // Handled by if_fast_holey. 3523 // Handled by if_fast_holey.
3529 FAST_HOLEY_SMI_ELEMENTS, FAST_HOLEY_ELEMENTS, 3524 FAST_HOLEY_SMI_ELEMENTS, FAST_HOLEY_ELEMENTS,
3530 // Handled by if_fast_double. 3525 // Handled by if_fast_double.
3531 FAST_DOUBLE_ELEMENTS, 3526 FAST_DOUBLE_ELEMENTS,
3532 // Handled by if_fast_holey_double. 3527 // Handled by if_fast_holey_double.
3533 FAST_HOLEY_DOUBLE_ELEMENTS}; 3528 FAST_HOLEY_DOUBLE_ELEMENTS};
3534 Label* labels[] = {// FAST_{SMI,}_ELEMENTS 3529 Label* labels[] = {// FAST_{SMI,}_ELEMENTS
3535 &if_fast_packed, &if_fast_packed, 3530 &if_fast_packed, &if_fast_packed,
3536 // FAST_HOLEY_{SMI,}_ELEMENTS 3531 // FAST_HOLEY_{SMI,}_ELEMENTS
3537 &if_fast_holey, &if_fast_holey, 3532 &if_fast_holey, &if_fast_holey,
3538 // FAST_DOUBLE_ELEMENTS 3533 // FAST_DOUBLE_ELEMENTS
3539 &if_fast_double, 3534 &if_fast_double,
3540 // FAST_HOLEY_DOUBLE_ELEMENTS 3535 // FAST_HOLEY_DOUBLE_ELEMENTS
3541 &if_fast_holey_double}; 3536 &if_fast_holey_double};
3542 Switch(elements_kind, &unimplemented_elements_kind, kinds, labels, 3537 Switch(elements_kind, unimplemented_elements_kind, kinds, labels,
3543 arraysize(kinds)); 3538 arraysize(kinds));
3544 Bind(&unimplemented_elements_kind);
3545 {
3546 // Crash if we get here.
3547 DebugBreak();
3548 Goto(miss);
3549 }
3550 3539
3551 Bind(&if_fast_packed); 3540 Bind(&if_fast_packed);
3552 { 3541 {
3553 Comment("fast packed elements"); 3542 Comment("fast packed elements");
3554 // TODO(jkummerow): The Load*Element helpers add movsxlq instructions 3543 // TODO(jkummerow): The Load*Element helpers add movsxlq instructions
3555 // on x64 which we don't need here, because |key| is an IntPtr already. 3544 // on x64 which we don't need here, because |key| is an IntPtr already.
3556 // Do something about that. 3545 // Do something about that.
3557 Return(LoadFixedArrayElement(elements, key)); 3546 Return(LoadFixedArrayElement(elements, key));
3558 } 3547 }
3559 3548
(...skipping 25 matching lines...) Expand all
3585 Node* element_upper = LoadFixedDoubleArrayElement( 3574 Node* element_upper = LoadFixedDoubleArrayElement(
3586 elements, key, MachineType::Uint32(), kIeeeDoubleExponentWordOffset); 3575 elements, key, MachineType::Uint32(), kIeeeDoubleExponentWordOffset);
3587 GotoIf(Word32Equal(element_upper, Int32Constant(kHoleNanUpper32)), 3576 GotoIf(Word32Equal(element_upper, Int32Constant(kHoleNanUpper32)),
3588 if_hole); 3577 if_hole);
3589 } 3578 }
3590 var_double_value->Bind( 3579 var_double_value->Bind(
3591 LoadFixedDoubleArrayElement(elements, key, MachineType::Float64())); 3580 LoadFixedDoubleArrayElement(elements, key, MachineType::Float64()));
3592 Goto(rebox_double); 3581 Goto(rebox_double);
3593 } 3582 }
3594 3583
3584 Bind(&if_nonfast);
3585 {
3586 STATIC_ASSERT(LAST_ELEMENTS_KIND == LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND);
3587 GotoIf(IntPtrGreaterThanOrEqual(
3588 elements_kind,
3589 IntPtrConstant(FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND)),
3590 &if_typed_array);
3591 GotoIf(IntPtrEqual(elements_kind, IntPtrConstant(DICTIONARY_ELEMENTS)),
3592 &if_dictionary);
3593 Goto(unimplemented_elements_kind);
3594 }
3595
3596 Bind(&if_dictionary);
3597 {
3598 Comment("dictionary elements");
3599 Variable var_entry(this, MachineRepresentation::kWord32);
3600 Label if_found(this);
3601 NumberDictionaryLookup<SeededNumberDictionary>(elements, key, &if_found,
3602 &var_entry, if_hole);
3603 Bind(&if_found);
3604 // Check that the value is a data property.
3605 Node* details_index = EntryToIndex<SeededNumberDictionary>(
3606 var_entry.value(), SeededNumberDictionary::kEntryDetailsIndex);
3607 Node* details = SmiToWord32(LoadFixedArrayElement(elements, details_index));
3608 Node* kind = BitFieldDecode<PropertyDetails::KindField>(details);
3609 // TODO(jkummerow): Support accessors without missing?
3610 GotoUnless(Word32Equal(kind, Int32Constant(kData)), miss);
3611 // Finally, load the value.
3612 Node* value_index = EntryToIndex<SeededNumberDictionary>(
3613 var_entry.value(), SeededNumberDictionary::kEntryValueIndex);
3614 Return(LoadFixedArrayElement(elements, value_index));
3615 }
3616
3595 Bind(&if_typed_array); 3617 Bind(&if_typed_array);
3596 { 3618 {
3597 Comment("typed elements"); 3619 Comment("typed elements");
3598 // Check if buffer has been neutered. 3620 // Check if buffer has been neutered.
3599 Node* buffer = LoadObjectField(object, JSArrayBufferView::kBufferOffset); 3621 Node* buffer = LoadObjectField(object, JSArrayBufferView::kBufferOffset);
3600 Node* bitfield = LoadObjectField(buffer, JSArrayBuffer::kBitFieldOffset, 3622 Node* bitfield = LoadObjectField(buffer, JSArrayBuffer::kBitFieldOffset,
3601 MachineType::Uint32()); 3623 MachineType::Uint32());
3602 Node* neutered_bit = 3624 Node* neutered_bit =
3603 Word32And(bitfield, Int32Constant(JSArrayBuffer::WasNeutered::kMask)); 3625 Word32And(bitfield, Int32Constant(JSArrayBuffer::WasNeutered::kMask));
3604 GotoUnless(Word32Equal(neutered_bit, Int32Constant(0)), miss); 3626 GotoUnless(Word32Equal(neutered_bit, Int32Constant(0)), miss);
3627
3628 // Bounds check.
3629 Node* length =
3630 SmiUntag(LoadObjectField(object, JSTypedArray::kLengthOffset));
3631 GotoUnless(UintPtrLessThan(key, length), out_of_bounds);
3632
3605 // Backing store = external_pointer + base_pointer. 3633 // Backing store = external_pointer + base_pointer.
3606 Node* external_pointer = 3634 Node* external_pointer =
3607 LoadObjectField(elements, FixedTypedArrayBase::kExternalPointerOffset, 3635 LoadObjectField(elements, FixedTypedArrayBase::kExternalPointerOffset,
3608 MachineType::Pointer()); 3636 MachineType::Pointer());
3609 Node* base_pointer = 3637 Node* base_pointer =
3610 LoadObjectField(elements, FixedTypedArrayBase::kBasePointerOffset); 3638 LoadObjectField(elements, FixedTypedArrayBase::kBasePointerOffset);
3611 Node* backing_store = IntPtrAdd(external_pointer, base_pointer); 3639 Node* backing_store = IntPtrAdd(external_pointer, base_pointer);
3612 3640
3613 Label uint8_elements(this), int8_elements(this), uint16_elements(this), 3641 Label uint8_elements(this), int8_elements(this), uint16_elements(this),
3614 int16_elements(this), uint32_elements(this), int32_elements(this), 3642 int16_elements(this), uint32_elements(this), int32_elements(this),
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
3703 WordAnd(handler_word, IntPtrConstant(LoadHandlerTypeBit::kMask)); 3731 WordAnd(handler_word, IntPtrConstant(LoadHandlerTypeBit::kMask));
3704 GotoUnless( 3732 GotoUnless(
3705 WordEqual(handler_type, IntPtrConstant(kLoadICHandlerForElements)), 3733 WordEqual(handler_type, IntPtrConstant(kLoadICHandlerForElements)),
3706 &property); 3734 &property);
3707 3735
3708 Comment("element_load"); 3736 Comment("element_load");
3709 Node* key = TryToIntptr(p->name, miss); 3737 Node* key = TryToIntptr(p->name, miss);
3710 Node* elements = LoadElements(p->receiver); 3738 Node* elements = LoadElements(p->receiver);
3711 Node* is_jsarray = 3739 Node* is_jsarray =
3712 WordAnd(handler_word, IntPtrConstant(KeyedLoadIsJsArray::kMask)); 3740 WordAnd(handler_word, IntPtrConstant(KeyedLoadIsJsArray::kMask));
3713 EmitBoundsCheck(p->receiver, elements, key, is_jsarray, miss); 3741 Node* is_jsarray_condition = WordNotEqual(is_jsarray, IntPtrConstant(0));
3714 Label if_hole(this); 3742 Node* elements_kind = BitFieldDecode<KeyedLoadElementsKind>(handler_word);
3743 Label if_hole(this), unimplemented_elements_kind(this);
3744 Label* out_of_bounds = miss;
3745 EmitElementLoad(p->receiver, elements, elements_kind, key,
3746 is_jsarray_condition, &if_hole, &rebox_double,
3747 &var_double_value, &unimplemented_elements_kind,
3748 out_of_bounds, miss);
3715 3749
3716 Node* elements_kind = BitFieldDecode<KeyedLoadElementsKind>(handler_word); 3750 Bind(&unimplemented_elements_kind);
3717 3751 {
3718 EmitElementLoad(p->receiver, elements, elements_kind, key, &if_hole, 3752 // Smi handlers should only be installed for supported elements kinds.
3719 &rebox_double, &var_double_value, miss); 3753 // Crash if we get here.
3754 DebugBreak();
3755 Goto(miss);
3756 }
3720 3757
3721 Bind(&if_hole); 3758 Bind(&if_hole);
3722 { 3759 {
3723 Comment("convert hole"); 3760 Comment("convert hole");
3724 Node* convert_hole = 3761 Node* convert_hole =
3725 WordAnd(handler_word, IntPtrConstant(KeyedLoadConvertHole::kMask)); 3762 WordAnd(handler_word, IntPtrConstant(KeyedLoadConvertHole::kMask));
3726 GotoIf(WordEqual(convert_hole, IntPtrConstant(0)), miss); 3763 GotoIf(WordEqual(convert_hole, IntPtrConstant(0)), miss);
3727 Node* protector_cell = LoadRoot(Heap::kArrayProtectorRootIndex); 3764 Node* protector_cell = LoadRoot(Heap::kArrayProtectorRootIndex);
3728 DCHECK(isolate()->heap()->array_protector()->IsPropertyCell()); 3765 DCHECK(isolate()->heap()->array_protector()->IsPropertyCell());
3729 GotoUnless( 3766 GotoUnless(
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
3888 &miss, 1); 3925 &miss, 1);
3889 } 3926 }
3890 Bind(&miss); 3927 Bind(&miss);
3891 { 3928 {
3892 Comment("KeyedLoadIC_miss"); 3929 Comment("KeyedLoadIC_miss");
3893 TailCallRuntime(Runtime::kKeyedLoadIC_Miss, p->context, p->receiver, 3930 TailCallRuntime(Runtime::kKeyedLoadIC_Miss, p->context, p->receiver,
3894 p->name, p->slot, p->vector); 3931 p->name, p->slot, p->vector);
3895 } 3932 }
3896 } 3933 }
3897 3934
3935 // |interceptor_kind| is one of Map::kHas{Indexed,Named}Interceptor.
3936 void CodeStubAssembler::EmitSpecialReceiverCheck(Node* receiver_map,
3937 int interceptor_kind,
3938 Label* miss) {
3939 Node* bitfield = LoadMapBitField(receiver_map);
3940 Node* mask =
3941 Int32Constant((1 << Map::kIsAccessCheckNeeded) | (1 << interceptor_kind));
3942 GotoUnless(Word32Equal(Word32And(bitfield, mask), Int32Constant(0)), miss);
3943 }
3944
3945 void CodeStubAssembler::KeyedLoadICGeneric(const LoadICParameters* p) {
3946 Variable var_index(this, MachineType::PointerRepresentation());
3947 Label if_index(this), if_key_is_not_number(this), if_index_name(this),
3948 if_unique_name(this), if_element_hole(this), if_oob(this), slow(this),
3949 stub_cache_miss(this), if_property_dictionary(this);
3950
3951 Node* receiver = p->receiver;
3952 GotoIf(WordIsSmi(receiver), &slow);
3953 // Check that the receiver is some kind of JS object but not a JSValue.
Toon Verwaest 2016/08/23 10:39:43 Seems like you want to check for LAST_CUSTOM_ELEME
Jakob Kummerow 2016/08/25 13:03:50 Done.
3954 // Specifically, string wrappers are unimplemented in the stub.
3955 STATIC_ASSERT(JS_API_OBJECT_TYPE > JS_VALUE_TYPE);
3956 Node* receiver_map = LoadMap(receiver);
3957 Node* instance_type = LoadMapInstanceType(receiver_map);
3958 GotoIf(Int32LessThan(instance_type, Int32Constant(JS_API_OBJECT_TYPE)),
Toon Verwaest 2016/08/23 10:39:43 You want JS_SPECIAL_API_OBJECT_TYPE I think, not J
Jakob Kummerow 2016/08/25 13:03:50 Done.
3959 &slow);
3960
3961 // Check what kind of key we have.
3962 Node* key = p->name;
3963 var_index.Bind(TryToIntptr(key, &if_key_is_not_number));
3964 Goto(&if_index);
3965
3966 Node* hash = nullptr;
3967 // TODO(jkummerow): Unify this with CodeStubAssembler::TryToName().
Toon Verwaest 2016/08/23 10:39:43 Why not already do this? I'd prefer not have this
Jakob Kummerow 2016/08/25 13:03:51 The current implementation is a faithful port of t
3968 Bind(&if_key_is_not_number);
3969 {
3970 Node* key_map = LoadMap(key);
3971 Node* key_instance_type = LoadMapInstanceType(key_map);
3972 // Jump to the runtime if key is neither String nor Symbol.
3973 GotoIf(Int32GreaterThan(key_instance_type,
3974 Int32Constant(LAST_UNIQUE_NAME_TYPE)),
3975 &slow);
3976 // Symbols are always unique names.
3977 GotoIf(Word32Equal(key_instance_type, Int32Constant(LAST_UNIQUE_NAME_TYPE)),
3978 &if_unique_name);
3979 // |key| is a String. Check if it has a cached array index.
3980 hash = LoadNameHashField(key);
3981 Node* contains_index =
3982 Word32And(hash, Int32Constant(Name::kContainsCachedArrayIndexMask));
3983 GotoIf(Word32Equal(contains_index, Int32Constant(0)), &if_index_name);
3984 // Otherwise, jump to the runtime if the string is not internalized.
3985 STATIC_ASSERT(kNotInternalizedTag != 0);
3986 Node* not_internalized =
3987 Word32And(key_instance_type, Int32Constant(kIsNotInternalizedMask));
3988 GotoIf(Word32NotEqual(not_internalized, Int32Constant(0)), &slow);
3989 Goto(&if_unique_name);
3990 }
3991
3992 Bind(&if_index_name);
3993 {
3994 Comment("string key with cached array index");
3995 var_index.Bind(BitFieldDecode<String::ArrayIndexValueBits>(hash));
3996 Goto(&if_index);
3997 }
3998
3999 Bind(&if_index);
4000 {
4001 Comment("integer index");
4002 // Check if receiver requires access checks or has interceptor.
4003 EmitSpecialReceiverCheck(receiver_map, Map::kHasIndexedInterceptor, &slow);
4004
4005 Node* index = var_index.value();
4006 Node* elements = LoadElements(receiver);
4007 Node* bitfield2 = LoadMapBitField2(receiver_map);
4008 Node* elements_kind = BitFieldDecode<Map::ElementsKindBits>(bitfield2);
4009 Node* is_jsarray_condition =
4010 Word32Equal(instance_type, Int32Constant(JS_ARRAY_TYPE));
4011 Variable var_double_value(this, MachineRepresentation::kFloat64);
4012 Label rebox_double(this, &var_double_value);
4013
4014 // Unimplemented elements kinds fall back to a runtime call.
4015 Label* unimplemented_elements_kind = &slow;
4016 IncrementCounter(isolate()->counters()->ic_keyed_load_generic_smi(), 1);
4017 EmitElementLoad(receiver, elements, elements_kind, index,
4018 is_jsarray_condition, &if_element_hole, &rebox_double,
4019 &var_double_value, unimplemented_elements_kind, &if_oob,
4020 &slow);
4021
4022 Bind(&rebox_double);
4023 Return(AllocateHeapNumberWithValue(var_double_value.value()));
4024 }
4025
4026 Bind(&if_oob);
4027 {
4028 Comment("out of bounds");
4029 Node* index = var_index.value();
4030 // Negative keys can't take the fast OOB path.
4031 GotoIf(IntPtrLessThan(index, IntPtrConstant(0)), &slow);
4032 // Positive OOB indices are effectively the same as hole loads.
4033 Goto(&if_element_hole);
4034 }
4035
4036 Bind(&if_element_hole);
4037 {
4038 Comment("found the hole");
4039 Label return_undefined(this);
4040 BranchIfPrototypesHaveNoElements(receiver_map, &return_undefined, &slow);
4041
4042 Bind(&return_undefined);
4043 Return(UndefinedConstant());
4044 }
4045
4046 Node* properties = nullptr;
4047 Bind(&if_unique_name);
4048 {
4049 Comment("key is unique name");
4050 // Check if receiver requires access checks or has interceptor.
4051 EmitSpecialReceiverCheck(receiver_map, Map::kHasNamedInterceptor, &slow);
4052 // Check if the receiver has fast or slow properties.
4053 properties = LoadProperties(receiver);
4054 Node* properties_map = LoadMap(properties);
4055 GotoIf(WordEqual(properties_map, LoadRoot(Heap::kHashTableMapRootIndex)),
4056 &if_property_dictionary);
4057
4058 Comment("stub cache probe for fast property load");
4059 Variable var_handler(this, MachineRepresentation::kTagged);
4060 Label found_handler(this, &var_handler), stub_cache_miss(this);
4061 TryProbeStubCache(isolate()->load_stub_cache(), receiver, key,
4062 &found_handler, &var_handler, &stub_cache_miss);
4063 Bind(&found_handler);
4064 { HandleLoadICHandlerCase(p, var_handler.value(), &slow); }
4065
4066 Bind(&stub_cache_miss);
4067 {
4068 Comment("KeyedLoadGeneric_miss");
4069 TailCallRuntime(Runtime::kKeyedLoadIC_Miss, p->context, p->receiver,
4070 p->name, p->slot, p->vector);
4071 }
4072 }
4073
4074 Bind(&if_property_dictionary);
4075 {
4076 Comment("dictionary property load");
4077 // Check if the receiver is the global object.
4078 GotoIf(Word32Equal(instance_type, Int32Constant(JS_GLOBAL_OBJECT_TYPE)),
Toon Verwaest 2016/08/23 10:39:43 These types are already excluded with LAST_SPECIAL
Jakob Kummerow 2016/08/25 13:03:50 Done.
4079 &slow);
4080 GotoIf(Word32Equal(instance_type, Int32Constant(JS_GLOBAL_PROXY_TYPE)),
Toon Verwaest 2016/08/23 10:39:43 This type will never have a property dictionary an
Jakob Kummerow 2016/08/25 13:03:50 Done.
4081 &slow);
4082 Variable var_name_index(this, MachineRepresentation::kWord32);
4083 Label dictionary_found(this, &var_name_index);
4084 NameDictionaryLookup<NameDictionary>(properties, key, &dictionary_found,
4085 &var_name_index, &slow);
4086 Bind(&dictionary_found);
4087 {
4088 Variable var_details(this, MachineRepresentation::kWord32);
4089 Variable var_value(this, MachineRepresentation::kTagged);
4090 LoadPropertyFromNameDictionary(properties, var_name_index.value(),
4091 &var_details, &var_value);
4092 Node* kind =
4093 BitFieldDecode<PropertyDetails::KindField>(var_details.value());
4094 // TODO(jkummerow): Support accessors without missing?
4095 GotoUnless(Word32Equal(kind, Int32Constant(kData)), &slow);
4096 IncrementCounter(isolate()->counters()->ic_keyed_load_generic_symbol(),
4097 1);
4098 Return(var_value.value());
4099 }
4100 }
4101
4102 Bind(&slow);
4103 {
4104 Comment("KeyedLoadGeneric_slow");
4105 IncrementCounter(isolate()->counters()->ic_keyed_load_generic_slow(), 1);
4106 // TODO(jkummerow): Should we use the GetProperty TF stub instead?
4107 TailCallRuntime(Runtime::kKeyedGetProperty, p->context, p->receiver,
4108 p->name);
4109 }
4110 }
4111
3898 void CodeStubAssembler::LoadGlobalIC(const LoadICParameters* p) { 4112 void CodeStubAssembler::LoadGlobalIC(const LoadICParameters* p) {
3899 Label try_handler(this), miss(this); 4113 Label try_handler(this), miss(this);
3900 Node* weak_cell = 4114 Node* weak_cell =
3901 LoadFixedArrayElement(p->vector, p->slot, 0, SMI_PARAMETERS); 4115 LoadFixedArrayElement(p->vector, p->slot, 0, SMI_PARAMETERS);
3902 AssertInstanceType(weak_cell, WEAK_CELL_TYPE); 4116 AssertInstanceType(weak_cell, WEAK_CELL_TYPE);
3903 4117
3904 // Load value or try handler case if the {weak_cell} is cleared. 4118 // Load value or try handler case if the {weak_cell} is cleared.
3905 Node* property_cell = LoadWeakCellValue(weak_cell, &try_handler); 4119 Node* property_cell = LoadWeakCellValue(weak_cell, &try_handler);
3906 AssertInstanceType(property_cell, PROPERTY_CELL_TYPE); 4120 AssertInstanceType(property_cell, PROPERTY_CELL_TYPE);
3907 4121
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
4013 Heap::kTheHoleValueRootIndex); 4227 Heap::kTheHoleValueRootIndex);
4014 4228
4015 // Store the WeakCell in the feedback vector. 4229 // Store the WeakCell in the feedback vector.
4016 StoreFixedArrayElement(feedback_vector, slot, cell, UPDATE_WRITE_BARRIER, 4230 StoreFixedArrayElement(feedback_vector, slot, cell, UPDATE_WRITE_BARRIER,
4017 CodeStubAssembler::SMI_PARAMETERS); 4231 CodeStubAssembler::SMI_PARAMETERS);
4018 return cell; 4232 return cell;
4019 } 4233 }
4020 4234
4021 } // namespace internal 4235 } // namespace internal
4022 } // namespace v8 4236 } // 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