OLD | NEW |
---|---|
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 #include "src/code-stub-assembler.h" | 4 #include "src/code-stub-assembler.h" |
5 #include "src/code-factory.h" | 5 #include "src/code-factory.h" |
6 #include "src/frames-inl.h" | 6 #include "src/frames-inl.h" |
7 #include "src/frames.h" | 7 #include "src/frames.h" |
8 #include "src/ic/handler-configuration.h" | 8 #include "src/ic/handler-configuration.h" |
9 #include "src/ic/stub-cache.h" | 9 #include "src/ic/stub-cache.h" |
10 | 10 |
(...skipping 662 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
673 | 673 |
674 Node* map = LoadMap(object); | 674 Node* map = LoadMap(object); |
675 | 675 |
676 // Bailout if instance type is not JS_ARRAY_TYPE. | 676 // Bailout if instance type is not JS_ARRAY_TYPE. |
677 GotoIf(WordNotEqual(LoadMapInstanceType(map), Int32Constant(JS_ARRAY_TYPE)), | 677 GotoIf(WordNotEqual(LoadMapInstanceType(map), Int32Constant(JS_ARRAY_TYPE)), |
678 if_false); | 678 if_false); |
679 | 679 |
680 Node* elements_kind = LoadMapElementsKind(map); | 680 Node* elements_kind = LoadMapElementsKind(map); |
681 | 681 |
682 // Bailout if receiver has slow elements. | 682 // Bailout if receiver has slow elements. |
683 GotoIf( | 683 GotoUnless(IsFastElementsKind(elements_kind), if_false); |
Benedikt Meurer
2016/11/09 20:00:32
Nice!
| |
684 Int32GreaterThan(elements_kind, Int32Constant(LAST_FAST_ELEMENTS_KIND)), | |
685 if_false); | |
686 | 684 |
687 // Check prototype chain if receiver does not have packed elements. | 685 // Check prototype chain if receiver does not have packed elements. |
688 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == (FAST_SMI_ELEMENTS | 1)); | 686 GotoUnless(IsHoleyFastElementsKind(elements_kind), if_true); |
689 STATIC_ASSERT(FAST_HOLEY_ELEMENTS == (FAST_ELEMENTS | 1)); | 687 |
690 STATIC_ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == (FAST_DOUBLE_ELEMENTS | 1)); | |
691 Node* holey_elements = Word32And(elements_kind, Int32Constant(1)); | |
692 GotoIf(Word32Equal(holey_elements, Int32Constant(0)), if_true); | |
693 BranchIfPrototypesHaveNoElements(map, if_true, if_false); | 688 BranchIfPrototypesHaveNoElements(map, if_true, if_false); |
694 } | 689 } |
695 | 690 |
696 Node* CodeStubAssembler::AllocateRawUnaligned(Node* size_in_bytes, | 691 Node* CodeStubAssembler::AllocateRawUnaligned(Node* size_in_bytes, |
697 AllocationFlags flags, | 692 AllocationFlags flags, |
698 Node* top_address, | 693 Node* top_address, |
699 Node* limit_address) { | 694 Node* limit_address) { |
700 Node* top = Load(MachineType::Pointer(), top_address); | 695 Node* top = Load(MachineType::Pointer(), top_address); |
701 Node* limit = Load(MachineType::Pointer(), limit_address); | 696 Node* limit = Load(MachineType::Pointer(), limit_address); |
702 | 697 |
(...skipping 8000 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8703 Branch(Word32Equal(array_type, Int32Constant(JS_TYPED_ARRAY_TYPE)), | 8698 Branch(Word32Equal(array_type, Int32Constant(JS_TYPED_ARRAY_TYPE)), |
8704 &if_istypedarray, &if_isgeneric); | 8699 &if_istypedarray, &if_isgeneric); |
8705 | 8700 |
8706 Bind(&if_isgeneric); | 8701 Bind(&if_isgeneric); |
8707 { | 8702 { |
8708 Label if_isfast(this), if_isslow(this); | 8703 Label if_isfast(this), if_isslow(this); |
8709 BranchIfFastJSArray(array, context, &if_isfast, &if_isslow); | 8704 BranchIfFastJSArray(array, context, &if_isfast, &if_isslow); |
8710 | 8705 |
8711 Bind(&if_isfast); | 8706 Bind(&if_isfast); |
8712 { | 8707 { |
8713 Node* map_index = | 8708 Label if_ispacked(this), if_isholey(this); |
8714 IntPtrAdd(IntPtrConstant(kBaseMapIndex + kFastIteratorOffset), | 8709 Node* elements_kind = LoadMapElementsKind(array_map); |
8715 LoadMapElementsKind(array_map)); | 8710 Branch(IsHoleyFastElementsKind(elements_kind), &if_isholey, |
8716 CSA_ASSERT(IntPtrGreaterThanOrEqual( | 8711 &if_ispacked); |
8717 map_index, IntPtrConstant(kBaseMapIndex + kFastIteratorOffset))); | |
8718 CSA_ASSERT(IntPtrLessThan( | |
8719 map_index, IntPtrConstant(kBaseMapIndex + kSlowIteratorOffset))); | |
8720 | 8712 |
8721 var_map_index.Bind(map_index); | 8713 Bind(&if_isholey); |
8722 var_array_map.Bind(array_map); | 8714 { |
8723 Goto(&allocate_iterator); | 8715 // Fast holey JSArrays can treat the hole as undefined if the |
8716 // protector cell is valid, and the prototype chain is unchanged from | |
8717 // its initial state (because the protector cell is only tracked for | |
8718 // initial the Array and Object prototypes). Check these conditions | |
8719 // here, and take the slow path if any fail. | |
8720 Node* protector_cell = LoadRoot(Heap::kArrayProtectorRootIndex); | |
8721 DCHECK(isolate()->heap()->array_protector()->IsPropertyCell()); | |
8722 GotoUnless( | |
8723 WordEqual( | |
8724 LoadObjectField(protector_cell, PropertyCell::kValueOffset), | |
8725 SmiConstant(Smi::FromInt(Isolate::kArrayProtectorValid))), | |
8726 &if_isslow); | |
8727 | |
8728 Node* native_context = LoadNativeContext(context); | |
8729 | |
8730 Node* prototype = LoadMapPrototype(array_map); | |
8731 Node* array_prototype = LoadContextElement( | |
8732 native_context, Context::INITIAL_ARRAY_PROTOTYPE_INDEX); | |
8733 GotoUnless(WordEqual(prototype, array_prototype), &if_isslow); | |
8734 | |
8735 Node* map = LoadMap(prototype); | |
8736 prototype = LoadMapPrototype(map); | |
8737 Node* object_prototype = LoadContextElement( | |
8738 native_context, Context::INITIAL_OBJECT_PROTOTYPE_INDEX); | |
8739 GotoUnless(WordEqual(prototype, object_prototype), &if_isslow); | |
8740 | |
8741 map = LoadMap(prototype); | |
8742 prototype = LoadMapPrototype(map); | |
8743 Branch(IsNull(prototype), &if_ispacked, &if_isslow); | |
8744 } | |
8745 Bind(&if_ispacked); | |
8746 { | |
8747 Node* map_index = | |
8748 IntPtrAdd(IntPtrConstant(kBaseMapIndex + kFastIteratorOffset), | |
8749 LoadMapElementsKind(array_map)); | |
8750 CSA_ASSERT(IntPtrGreaterThanOrEqual( | |
8751 map_index, IntPtrConstant(kBaseMapIndex + kFastIteratorOffset))); | |
8752 CSA_ASSERT(IntPtrLessThan( | |
8753 map_index, IntPtrConstant(kBaseMapIndex + kSlowIteratorOffset))); | |
8754 | |
8755 var_map_index.Bind(map_index); | |
8756 var_array_map.Bind(array_map); | |
8757 Goto(&allocate_iterator); | |
8758 } | |
8724 } | 8759 } |
8725 | 8760 |
8726 Bind(&if_isslow); | 8761 Bind(&if_isslow); |
8727 { | 8762 { |
8728 Node* map_index = IntPtrAdd(IntPtrConstant(kBaseMapIndex), | 8763 Node* map_index = IntPtrAdd(IntPtrConstant(kBaseMapIndex), |
8729 IntPtrConstant(kSlowIteratorOffset)); | 8764 IntPtrConstant(kSlowIteratorOffset)); |
8730 var_map_index.Bind(map_index); | 8765 var_map_index.Bind(map_index); |
8731 var_array_map.Bind(UndefinedConstant()); | 8766 var_array_map.Bind(UndefinedConstant()); |
8732 Goto(&allocate_iterator); | 8767 Goto(&allocate_iterator); |
8733 } | 8768 } |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8853 }, | 8888 }, |
8854 -kPointerSize, CodeStubAssembler::IndexAdvanceMode::kPost); | 8889 -kPointerSize, CodeStubAssembler::IndexAdvanceMode::kPost); |
8855 } | 8890 } |
8856 | 8891 |
8857 void CodeStubArguments::PopAndReturn(compiler::Node* value) { | 8892 void CodeStubArguments::PopAndReturn(compiler::Node* value) { |
8858 assembler_->PopAndReturn( | 8893 assembler_->PopAndReturn( |
8859 assembler_->IntPtrAddFoldConstants(argc_, assembler_->IntPtrConstant(1)), | 8894 assembler_->IntPtrAddFoldConstants(argc_, assembler_->IntPtrConstant(1)), |
8860 value); | 8895 value); |
8861 } | 8896 } |
8862 | 8897 |
8898 compiler::Node* CodeStubAssembler::IsFastElementsKind( | |
8899 compiler::Node* elements_kind) { | |
8900 return Uint32LessThanOrEqual(elements_kind, | |
8901 Int32Constant(LAST_FAST_ELEMENTS_KIND)); | |
8902 } | |
8903 | |
8904 compiler::Node* CodeStubAssembler::IsHoleyFastElementsKind( | |
8905 compiler::Node* elements_kind) { | |
8906 CSA_ASSERT(IsFastElementsKind(elements_kind)); | |
8907 | |
8908 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == (FAST_SMI_ELEMENTS | 1)); | |
8909 STATIC_ASSERT(FAST_HOLEY_ELEMENTS == (FAST_ELEMENTS | 1)); | |
8910 STATIC_ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == (FAST_DOUBLE_ELEMENTS | 1)); | |
8911 | |
8912 // Check prototype chain if receiver does not have packed elements. | |
8913 Node* holey_elements = Word32And(elements_kind, Int32Constant(1)); | |
8914 return Word32Equal(holey_elements, Int32Constant(1)); | |
8915 } | |
8916 | |
8863 } // namespace internal | 8917 } // namespace internal |
8864 } // namespace v8 | 8918 } // namespace v8 |
OLD | NEW |