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

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

Issue 2680973002: [stubs] Implement binary-search descriptor lookup in CSA (Closed)
Patch Set: graph_verifier++ Created 3 years, 10 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/accessor-assembler.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 #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 8
9 namespace v8 { 9 namespace v8 {
10 namespace internal { 10 namespace internal {
(...skipping 4730 matching lines...) Expand 10 before | Expand all | Expand 10 after
4741 } 4741 }
4742 4742
4743 template void CodeStubAssembler::Add<NameDictionary>(Node*, Node*, Node*, 4743 template void CodeStubAssembler::Add<NameDictionary>(Node*, Node*, Node*,
4744 Label*); 4744 Label*);
4745 4745
4746 void CodeStubAssembler::DescriptorLookupLinear(Node* unique_name, 4746 void CodeStubAssembler::DescriptorLookupLinear(Node* unique_name,
4747 Node* descriptors, Node* nof, 4747 Node* descriptors, Node* nof,
4748 Label* if_found, 4748 Label* if_found,
4749 Variable* var_name_index, 4749 Variable* var_name_index,
4750 Label* if_not_found) { 4750 Label* if_not_found) {
4751 Comment("DescriptorLookupLinear");
4751 Node* first_inclusive = IntPtrConstant(DescriptorArray::ToKeyIndex(0)); 4752 Node* first_inclusive = IntPtrConstant(DescriptorArray::ToKeyIndex(0));
4752 Node* factor = IntPtrConstant(DescriptorArray::kDescriptorSize); 4753 Node* factor = IntPtrConstant(DescriptorArray::kDescriptorSize);
4753 Node* last_exclusive = IntPtrAdd(first_inclusive, IntPtrMul(nof, factor)); 4754 Node* last_exclusive = IntPtrAdd(first_inclusive, IntPtrMul(nof, factor));
4754 4755
4755 BuildFastLoop(last_exclusive, first_inclusive, 4756 BuildFastLoop(last_exclusive, first_inclusive,
4756 [this, descriptors, unique_name, if_found, 4757 [this, descriptors, unique_name, if_found,
4757 var_name_index](Node* name_index) { 4758 var_name_index](Node* name_index) {
4758 Node* candidate_name = 4759 Node* candidate_name =
4759 LoadFixedArrayElement(descriptors, name_index); 4760 LoadFixedArrayElement(descriptors, name_index);
4760 var_name_index->Bind(name_index); 4761 var_name_index->Bind(name_index);
4761 GotoIf(WordEqual(candidate_name, unique_name), if_found); 4762 GotoIf(WordEqual(candidate_name, unique_name), if_found);
4762 }, 4763 },
4763 -DescriptorArray::kDescriptorSize, INTPTR_PARAMETERS, 4764 -DescriptorArray::kDescriptorSize, INTPTR_PARAMETERS,
4764 IndexAdvanceMode::kPre); 4765 IndexAdvanceMode::kPre);
4765 Goto(if_not_found); 4766 Goto(if_not_found);
4766 } 4767 }
4767 4768
4769 Node* CodeStubAssembler::DescriptorArrayNumberOfEntries(Node* descriptors) {
4770 return LoadAndUntagToWord32FixedArrayElement(
4771 descriptors, IntPtrConstant(DescriptorArray::kDescriptorLengthIndex));
4772 }
4773
4774 namespace {
4775
4776 Node* DescriptorNumberToIndex(CodeStubAssembler* a, Node* descriptor_number) {
4777 Node* descriptor_size = a->Int32Constant(DescriptorArray::kDescriptorSize);
4778 Node* index = a->Int32Mul(descriptor_number, descriptor_size);
4779 return a->ChangeInt32ToIntPtr(index);
4780 }
4781
4782 } // namespace
4783
4784 Node* CodeStubAssembler::DescriptorArrayToKeyIndex(Node* descriptor_number) {
4785 return IntPtrAdd(IntPtrConstant(DescriptorArray::ToKeyIndex(0)),
4786 DescriptorNumberToIndex(this, descriptor_number));
4787 }
4788
4789 Node* CodeStubAssembler::DescriptorArrayGetSortedKeyIndex(
4790 Node* descriptors, Node* descriptor_number) {
4791 const int details_offset = DescriptorArray::ToDetailsIndex(0) * kPointerSize;
4792 Node* details = LoadAndUntagToWord32FixedArrayElement(
4793 descriptors, DescriptorNumberToIndex(this, descriptor_number),
4794 details_offset);
4795 return DecodeWord32<PropertyDetails::DescriptorPointer>(details);
4796 }
4797
4798 Node* CodeStubAssembler::DescriptorArrayGetKey(Node* descriptors,
4799 Node* descriptor_number) {
4800 const int key_offset = DescriptorArray::ToKeyIndex(0) * kPointerSize;
4801 return LoadFixedArrayElement(descriptors,
4802 DescriptorNumberToIndex(this, descriptor_number),
4803 key_offset);
4804 }
4805
4806 void CodeStubAssembler::DescriptorLookupBinary(Node* unique_name,
4807 Node* descriptors, Node* nof,
4808 Label* if_found,
4809 Variable* var_name_index,
4810 Label* if_not_found) {
4811 Comment("DescriptorLookupBinary");
4812 Variable var_low(this, MachineRepresentation::kWord32, Int32Constant(0));
4813 Node* limit =
4814 Int32Sub(DescriptorArrayNumberOfEntries(descriptors), Int32Constant(1));
4815 Variable var_high(this, MachineRepresentation::kWord32, limit);
4816 Node* hash = LoadNameHashField(unique_name);
4817 CSA_ASSERT(this, Word32NotEqual(hash, Int32Constant(0)));
4818
4819 // Assume non-empty array.
4820 CSA_ASSERT(this, Uint32LessThanOrEqual(var_low.value(), var_high.value()));
4821
4822 Variable* loop_vars[] = {&var_high, &var_low};
4823 Label binary_loop(this, 2, loop_vars);
4824 Goto(&binary_loop);
4825 Bind(&binary_loop);
4826 {
4827 // mid = low + (high - low) / 2 (to avoid overflow in "(low + high) / 2").
4828 Node* mid =
4829 Int32Add(var_low.value(),
4830 Word32Shr(Int32Sub(var_high.value(), var_low.value()), 1));
4831 // mid_name = descriptors->GetSortedKey(mid).
4832 Node* sorted_key_index = DescriptorArrayGetSortedKeyIndex(descriptors, mid);
4833 Node* mid_name = DescriptorArrayGetKey(descriptors, sorted_key_index);
4834
4835 Node* mid_hash = LoadNameHashField(mid_name);
4836
4837 Label mid_greater(this), mid_less(this), merge(this);
4838 Branch(Uint32GreaterThanOrEqual(mid_hash, hash), &mid_greater, &mid_less);
4839 Bind(&mid_greater);
4840 {
4841 var_high.Bind(mid);
4842 Goto(&merge);
4843 }
4844 Bind(&mid_less);
4845 {
4846 var_low.Bind(Int32Add(mid, Int32Constant(1)));
4847 Goto(&merge);
4848 }
4849 Bind(&merge);
4850 GotoIf(Word32NotEqual(var_low.value(), var_high.value()), &binary_loop);
4851 }
4852
4853 Label scan_loop(this, &var_low);
4854 Goto(&scan_loop);
4855 Bind(&scan_loop);
4856 {
4857 GotoIf(Int32GreaterThan(var_low.value(), limit), if_not_found);
4858
4859 Node* sort_index =
4860 DescriptorArrayGetSortedKeyIndex(descriptors, var_low.value());
4861 Node* entry = DescriptorArrayGetKey(descriptors, sort_index);
Igor Sheludko 2017/02/09 23:52:07 Maybe s/entry/current_name/ ?
Jakob Kummerow 2017/02/10 00:50:57 Done.
4862 Node* current_hash = LoadNameHashField(entry);
4863 GotoIf(Word32NotEqual(current_hash, hash), if_not_found);
4864 Label next(this);
4865 GotoIf(WordNotEqual(entry, unique_name), &next);
4866 GotoIf(Int32GreaterThanOrEqual(sort_index, nof), if_not_found);
4867 var_name_index->Bind(DescriptorArrayToKeyIndex(sort_index));
4868 Goto(if_found);
4869
4870 Bind(&next);
4871 var_low.Bind(Int32Add(var_low.value(), Int32Constant(1)));
4872 Goto(&scan_loop);
4873 }
4874 }
4875
4876 void CodeStubAssembler::DescriptorLookup(Node* unique_name, Node* descriptors,
4877 Node* bitfield3, Label* if_found,
4878 Variable* var_name_index,
4879 Label* if_not_found) {
4880 Comment("DescriptorArrayLookup");
4881 Node* nof = DecodeWord32<Map::NumberOfOwnDescriptorsBits>(bitfield3);
4882 GotoIf(Word32Equal(nof, Int32Constant(0)), if_not_found);
4883 Label linear_search(this), binary_search(this);
4884 const int kMaxElementsForLinearSearch = 32;
4885 Branch(Int32LessThanOrEqual(nof, Int32Constant(kMaxElementsForLinearSearch)),
4886 &linear_search, &binary_search);
4887 Bind(&linear_search);
4888 {
4889 DescriptorLookupLinear(unique_name, descriptors, ChangeInt32ToIntPtr(nof),
4890 if_found, var_name_index, if_not_found);
4891 }
4892 Bind(&binary_search);
4893 {
4894 DescriptorLookupBinary(unique_name, descriptors, nof, if_found,
4895 var_name_index, if_not_found);
4896 }
4897 }
4898
4768 void CodeStubAssembler::TryLookupProperty( 4899 void CodeStubAssembler::TryLookupProperty(
4769 Node* object, Node* map, Node* instance_type, Node* unique_name, 4900 Node* object, Node* map, Node* instance_type, Node* unique_name,
4770 Label* if_found_fast, Label* if_found_dict, Label* if_found_global, 4901 Label* if_found_fast, Label* if_found_dict, Label* if_found_global,
4771 Variable* var_meta_storage, Variable* var_name_index, Label* if_not_found, 4902 Variable* var_meta_storage, Variable* var_name_index, Label* if_not_found,
4772 Label* if_bailout) { 4903 Label* if_bailout) {
4773 DCHECK_EQ(MachineRepresentation::kTagged, var_meta_storage->rep()); 4904 DCHECK_EQ(MachineRepresentation::kTagged, var_meta_storage->rep());
4774 DCHECK_EQ(MachineType::PointerRepresentation(), var_name_index->rep()); 4905 DCHECK_EQ(MachineType::PointerRepresentation(), var_name_index->rep());
4775 4906
4776 Label if_objectisspecial(this); 4907 Label if_objectisspecial(this);
4777 STATIC_ASSERT(JS_GLOBAL_OBJECT_TYPE <= LAST_SPECIAL_RECEIVER_TYPE); 4908 STATIC_ASSERT(JS_GLOBAL_OBJECT_TYPE <= LAST_SPECIAL_RECEIVER_TYPE);
4778 GotoIf(Int32LessThanOrEqual(instance_type, 4909 GotoIf(Int32LessThanOrEqual(instance_type,
4779 Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)), 4910 Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)),
4780 &if_objectisspecial); 4911 &if_objectisspecial);
4781 4912
4782 uint32_t mask = 4913 uint32_t mask =
4783 1 << Map::kHasNamedInterceptor | 1 << Map::kIsAccessCheckNeeded; 4914 1 << Map::kHasNamedInterceptor | 1 << Map::kIsAccessCheckNeeded;
4784 CSA_ASSERT(this, Word32BinaryNot(IsSetWord32(LoadMapBitField(map), mask))); 4915 CSA_ASSERT(this, Word32BinaryNot(IsSetWord32(LoadMapBitField(map), mask)));
4785 USE(mask); 4916 USE(mask);
4786 4917
4787 Node* bit_field3 = LoadMapBitField3(map); 4918 Node* bit_field3 = LoadMapBitField3(map);
4788 Label if_isfastmap(this), if_isslowmap(this); 4919 Label if_isfastmap(this), if_isslowmap(this);
4789 Branch(IsSetWord32<Map::DictionaryMap>(bit_field3), &if_isslowmap, 4920 Branch(IsSetWord32<Map::DictionaryMap>(bit_field3), &if_isslowmap,
4790 &if_isfastmap); 4921 &if_isfastmap);
4791 Bind(&if_isfastmap); 4922 Bind(&if_isfastmap);
4792 { 4923 {
4793 Comment("DescriptorArrayLookup");
4794 Node* nof =
4795 DecodeWordFromWord32<Map::NumberOfOwnDescriptorsBits>(bit_field3);
4796 // Bail out to the runtime for large numbers of own descriptors. The stub
4797 // only does linear search, which becomes too expensive in that case.
4798 {
4799 static const int32_t kMaxLinear = 210;
4800 GotoIf(UintPtrGreaterThan(nof, IntPtrConstant(kMaxLinear)), if_bailout);
4801 }
4802 Node* descriptors = LoadMapDescriptors(map); 4924 Node* descriptors = LoadMapDescriptors(map);
4803 var_meta_storage->Bind(descriptors); 4925 var_meta_storage->Bind(descriptors);
4804 4926
4805 DescriptorLookupLinear(unique_name, descriptors, nof, if_found_fast, 4927 DescriptorLookup(unique_name, descriptors, bit_field3, if_found_fast,
4806 var_name_index, if_not_found); 4928 var_name_index, if_not_found);
4807 } 4929 }
4808 Bind(&if_isslowmap); 4930 Bind(&if_isslowmap);
4809 { 4931 {
4810 Node* dictionary = LoadProperties(object); 4932 Node* dictionary = LoadProperties(object);
4811 var_meta_storage->Bind(dictionary); 4933 var_meta_storage->Bind(dictionary);
4812 4934
4813 NameDictionaryLookup<NameDictionary>(dictionary, unique_name, if_found_dict, 4935 NameDictionaryLookup<NameDictionary>(dictionary, unique_name, if_found_dict,
4814 var_name_index, if_not_found); 4936 var_name_index, if_not_found);
4815 } 4937 }
4816 Bind(&if_objectisspecial); 4938 Bind(&if_objectisspecial);
(...skipping 3557 matching lines...) Expand 10 before | Expand all | Expand 10 after
8374 formatted.c_str(), TENURED); 8496 formatted.c_str(), TENURED);
8375 CallRuntime(Runtime::kGlobalPrint, NoContextConstant(), 8497 CallRuntime(Runtime::kGlobalPrint, NoContextConstant(),
8376 HeapConstant(string)); 8498 HeapConstant(string));
8377 } 8499 }
8378 CallRuntime(Runtime::kDebugPrint, NoContextConstant(), tagged_value); 8500 CallRuntime(Runtime::kDebugPrint, NoContextConstant(), tagged_value);
8379 #endif 8501 #endif
8380 } 8502 }
8381 8503
8382 } // namespace internal 8504 } // namespace internal
8383 } // namespace v8 8505 } // namespace v8
OLDNEW
« no previous file with comments | « src/code-stub-assembler.h ('k') | src/ic/accessor-assembler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698