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 | 8 |
9 namespace v8 { | 9 namespace v8 { |
10 namespace internal { | 10 namespace internal { |
(...skipping 4703 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4714 } | 4714 } |
4715 | 4715 |
4716 template void CodeStubAssembler::Add<NameDictionary>(Node*, Node*, Node*, | 4716 template void CodeStubAssembler::Add<NameDictionary>(Node*, Node*, Node*, |
4717 Label*); | 4717 Label*); |
4718 | 4718 |
4719 void CodeStubAssembler::DescriptorLookupLinear(Node* unique_name, | 4719 void CodeStubAssembler::DescriptorLookupLinear(Node* unique_name, |
4720 Node* descriptors, Node* nof, | 4720 Node* descriptors, Node* nof, |
4721 Label* if_found, | 4721 Label* if_found, |
4722 Variable* var_name_index, | 4722 Variable* var_name_index, |
4723 Label* if_not_found) { | 4723 Label* if_not_found) { |
| 4724 Comment("DescriptorLookupLinear"); |
4724 Node* first_inclusive = IntPtrConstant(DescriptorArray::ToKeyIndex(0)); | 4725 Node* first_inclusive = IntPtrConstant(DescriptorArray::ToKeyIndex(0)); |
4725 Node* factor = IntPtrConstant(DescriptorArray::kEntrySize); | 4726 Node* factor = IntPtrConstant(DescriptorArray::kEntrySize); |
4726 Node* last_exclusive = IntPtrAdd(first_inclusive, IntPtrMul(nof, factor)); | 4727 Node* last_exclusive = IntPtrAdd(first_inclusive, IntPtrMul(nof, factor)); |
4727 | 4728 |
4728 BuildFastLoop(last_exclusive, first_inclusive, | 4729 BuildFastLoop(last_exclusive, first_inclusive, |
4729 [this, descriptors, unique_name, if_found, | 4730 [this, descriptors, unique_name, if_found, |
4730 var_name_index](Node* name_index) { | 4731 var_name_index](Node* name_index) { |
4731 Node* candidate_name = | 4732 Node* candidate_name = |
4732 LoadFixedArrayElement(descriptors, name_index); | 4733 LoadFixedArrayElement(descriptors, name_index); |
4733 var_name_index->Bind(name_index); | 4734 var_name_index->Bind(name_index); |
4734 GotoIf(WordEqual(candidate_name, unique_name), if_found); | 4735 GotoIf(WordEqual(candidate_name, unique_name), if_found); |
4735 }, | 4736 }, |
4736 -DescriptorArray::kEntrySize, INTPTR_PARAMETERS, | 4737 -DescriptorArray::kEntrySize, INTPTR_PARAMETERS, |
4737 IndexAdvanceMode::kPre); | 4738 IndexAdvanceMode::kPre); |
4738 Goto(if_not_found); | 4739 Goto(if_not_found); |
4739 } | 4740 } |
4740 | 4741 |
| 4742 Node* CodeStubAssembler::DescriptorArrayNumberOfEntries(Node* descriptors) { |
| 4743 return LoadAndUntagToWord32FixedArrayElement( |
| 4744 descriptors, IntPtrConstant(DescriptorArray::kDescriptorLengthIndex)); |
| 4745 } |
| 4746 |
| 4747 namespace { |
| 4748 |
| 4749 Node* DescriptorNumberToIndex(CodeStubAssembler* a, Node* descriptor_number) { |
| 4750 Node* descriptor_size = a->Int32Constant(DescriptorArray::kEntrySize); |
| 4751 Node* index = a->Int32Mul(descriptor_number, descriptor_size); |
| 4752 return a->ChangeInt32ToIntPtr(index); |
| 4753 } |
| 4754 |
| 4755 } // namespace |
| 4756 |
| 4757 Node* CodeStubAssembler::DescriptorArrayToKeyIndex(Node* descriptor_number) { |
| 4758 return IntPtrAdd(IntPtrConstant(DescriptorArray::ToKeyIndex(0)), |
| 4759 DescriptorNumberToIndex(this, descriptor_number)); |
| 4760 } |
| 4761 |
| 4762 Node* CodeStubAssembler::DescriptorArrayGetSortedKeyIndex( |
| 4763 Node* descriptors, Node* descriptor_number) { |
| 4764 const int details_offset = DescriptorArray::ToDetailsIndex(0) * kPointerSize; |
| 4765 Node* details = LoadAndUntagToWord32FixedArrayElement( |
| 4766 descriptors, DescriptorNumberToIndex(this, descriptor_number), |
| 4767 details_offset); |
| 4768 return DecodeWord32<PropertyDetails::DescriptorPointer>(details); |
| 4769 } |
| 4770 |
| 4771 Node* CodeStubAssembler::DescriptorArrayGetKey(Node* descriptors, |
| 4772 Node* descriptor_number) { |
| 4773 const int key_offset = DescriptorArray::ToKeyIndex(0) * kPointerSize; |
| 4774 return LoadFixedArrayElement(descriptors, |
| 4775 DescriptorNumberToIndex(this, descriptor_number), |
| 4776 key_offset); |
| 4777 } |
| 4778 |
| 4779 void CodeStubAssembler::DescriptorLookupBinary(Node* unique_name, |
| 4780 Node* descriptors, Node* nof, |
| 4781 Label* if_found, |
| 4782 Variable* var_name_index, |
| 4783 Label* if_not_found) { |
| 4784 Comment("DescriptorLookupBinary"); |
| 4785 Variable var_low(this, MachineRepresentation::kWord32, Int32Constant(0)); |
| 4786 Node* limit = |
| 4787 Int32Sub(DescriptorArrayNumberOfEntries(descriptors), Int32Constant(1)); |
| 4788 Variable var_high(this, MachineRepresentation::kWord32, limit); |
| 4789 Node* hash = LoadNameHashField(unique_name); |
| 4790 CSA_ASSERT(this, Word32NotEqual(hash, Int32Constant(0))); |
| 4791 |
| 4792 // Assume non-empty array. |
| 4793 CSA_ASSERT(this, Uint32LessThanOrEqual(var_low.value(), var_high.value())); |
| 4794 |
| 4795 Variable* loop_vars[] = {&var_high, &var_low}; |
| 4796 Label binary_loop(this, 2, loop_vars); |
| 4797 Goto(&binary_loop); |
| 4798 Bind(&binary_loop); |
| 4799 { |
| 4800 // mid = low + (high - low) / 2 (to avoid overflow in "(low + high) / 2"). |
| 4801 Node* mid = |
| 4802 Int32Add(var_low.value(), |
| 4803 Word32Shr(Int32Sub(var_high.value(), var_low.value()), 1)); |
| 4804 // mid_name = descriptors->GetSortedKey(mid). |
| 4805 Node* sorted_key_index = DescriptorArrayGetSortedKeyIndex(descriptors, mid); |
| 4806 Node* mid_name = DescriptorArrayGetKey(descriptors, sorted_key_index); |
| 4807 |
| 4808 Node* mid_hash = LoadNameHashField(mid_name); |
| 4809 |
| 4810 Label mid_greater(this), mid_less(this), merge(this); |
| 4811 Branch(Uint32GreaterThanOrEqual(mid_hash, hash), &mid_greater, &mid_less); |
| 4812 Bind(&mid_greater); |
| 4813 { |
| 4814 var_high.Bind(mid); |
| 4815 Goto(&merge); |
| 4816 } |
| 4817 Bind(&mid_less); |
| 4818 { |
| 4819 var_low.Bind(Int32Add(mid, Int32Constant(1))); |
| 4820 Goto(&merge); |
| 4821 } |
| 4822 Bind(&merge); |
| 4823 GotoIf(Word32NotEqual(var_low.value(), var_high.value()), &binary_loop); |
| 4824 } |
| 4825 |
| 4826 Label scan_loop(this, &var_low); |
| 4827 Goto(&scan_loop); |
| 4828 Bind(&scan_loop); |
| 4829 { |
| 4830 GotoIf(Int32GreaterThan(var_low.value(), limit), if_not_found); |
| 4831 |
| 4832 Node* sort_index = |
| 4833 DescriptorArrayGetSortedKeyIndex(descriptors, var_low.value()); |
| 4834 Node* current_name = DescriptorArrayGetKey(descriptors, sort_index); |
| 4835 Node* current_hash = LoadNameHashField(current_name); |
| 4836 GotoIf(Word32NotEqual(current_hash, hash), if_not_found); |
| 4837 Label next(this); |
| 4838 GotoIf(WordNotEqual(current_name, unique_name), &next); |
| 4839 GotoIf(Int32GreaterThanOrEqual(sort_index, nof), if_not_found); |
| 4840 var_name_index->Bind(DescriptorArrayToKeyIndex(sort_index)); |
| 4841 Goto(if_found); |
| 4842 |
| 4843 Bind(&next); |
| 4844 var_low.Bind(Int32Add(var_low.value(), Int32Constant(1))); |
| 4845 Goto(&scan_loop); |
| 4846 } |
| 4847 } |
| 4848 |
| 4849 void CodeStubAssembler::DescriptorLookup(Node* unique_name, Node* descriptors, |
| 4850 Node* bitfield3, Label* if_found, |
| 4851 Variable* var_name_index, |
| 4852 Label* if_not_found) { |
| 4853 Comment("DescriptorArrayLookup"); |
| 4854 Node* nof = DecodeWord32<Map::NumberOfOwnDescriptorsBits>(bitfield3); |
| 4855 GotoIf(Word32Equal(nof, Int32Constant(0)), if_not_found); |
| 4856 Label linear_search(this), binary_search(this); |
| 4857 const int kMaxElementsForLinearSearch = 32; |
| 4858 Branch(Int32LessThanOrEqual(nof, Int32Constant(kMaxElementsForLinearSearch)), |
| 4859 &linear_search, &binary_search); |
| 4860 Bind(&linear_search); |
| 4861 { |
| 4862 DescriptorLookupLinear(unique_name, descriptors, ChangeInt32ToIntPtr(nof), |
| 4863 if_found, var_name_index, if_not_found); |
| 4864 } |
| 4865 Bind(&binary_search); |
| 4866 { |
| 4867 DescriptorLookupBinary(unique_name, descriptors, nof, if_found, |
| 4868 var_name_index, if_not_found); |
| 4869 } |
| 4870 } |
| 4871 |
4741 void CodeStubAssembler::TryLookupProperty( | 4872 void CodeStubAssembler::TryLookupProperty( |
4742 Node* object, Node* map, Node* instance_type, Node* unique_name, | 4873 Node* object, Node* map, Node* instance_type, Node* unique_name, |
4743 Label* if_found_fast, Label* if_found_dict, Label* if_found_global, | 4874 Label* if_found_fast, Label* if_found_dict, Label* if_found_global, |
4744 Variable* var_meta_storage, Variable* var_name_index, Label* if_not_found, | 4875 Variable* var_meta_storage, Variable* var_name_index, Label* if_not_found, |
4745 Label* if_bailout) { | 4876 Label* if_bailout) { |
4746 DCHECK_EQ(MachineRepresentation::kTagged, var_meta_storage->rep()); | 4877 DCHECK_EQ(MachineRepresentation::kTagged, var_meta_storage->rep()); |
4747 DCHECK_EQ(MachineType::PointerRepresentation(), var_name_index->rep()); | 4878 DCHECK_EQ(MachineType::PointerRepresentation(), var_name_index->rep()); |
4748 | 4879 |
4749 Label if_objectisspecial(this); | 4880 Label if_objectisspecial(this); |
4750 STATIC_ASSERT(JS_GLOBAL_OBJECT_TYPE <= LAST_SPECIAL_RECEIVER_TYPE); | 4881 STATIC_ASSERT(JS_GLOBAL_OBJECT_TYPE <= LAST_SPECIAL_RECEIVER_TYPE); |
4751 GotoIf(Int32LessThanOrEqual(instance_type, | 4882 GotoIf(Int32LessThanOrEqual(instance_type, |
4752 Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)), | 4883 Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)), |
4753 &if_objectisspecial); | 4884 &if_objectisspecial); |
4754 | 4885 |
4755 uint32_t mask = | 4886 uint32_t mask = |
4756 1 << Map::kHasNamedInterceptor | 1 << Map::kIsAccessCheckNeeded; | 4887 1 << Map::kHasNamedInterceptor | 1 << Map::kIsAccessCheckNeeded; |
4757 CSA_ASSERT(this, Word32BinaryNot(IsSetWord32(LoadMapBitField(map), mask))); | 4888 CSA_ASSERT(this, Word32BinaryNot(IsSetWord32(LoadMapBitField(map), mask))); |
4758 USE(mask); | 4889 USE(mask); |
4759 | 4890 |
4760 Node* bit_field3 = LoadMapBitField3(map); | 4891 Node* bit_field3 = LoadMapBitField3(map); |
4761 Label if_isfastmap(this), if_isslowmap(this); | 4892 Label if_isfastmap(this), if_isslowmap(this); |
4762 Branch(IsSetWord32<Map::DictionaryMap>(bit_field3), &if_isslowmap, | 4893 Branch(IsSetWord32<Map::DictionaryMap>(bit_field3), &if_isslowmap, |
4763 &if_isfastmap); | 4894 &if_isfastmap); |
4764 Bind(&if_isfastmap); | 4895 Bind(&if_isfastmap); |
4765 { | 4896 { |
4766 Comment("DescriptorArrayLookup"); | |
4767 Node* nof = | |
4768 DecodeWordFromWord32<Map::NumberOfOwnDescriptorsBits>(bit_field3); | |
4769 // Bail out to the runtime for large numbers of own descriptors. The stub | |
4770 // only does linear search, which becomes too expensive in that case. | |
4771 { | |
4772 static const int32_t kMaxLinear = 210; | |
4773 GotoIf(UintPtrGreaterThan(nof, IntPtrConstant(kMaxLinear)), if_bailout); | |
4774 } | |
4775 Node* descriptors = LoadMapDescriptors(map); | 4897 Node* descriptors = LoadMapDescriptors(map); |
4776 var_meta_storage->Bind(descriptors); | 4898 var_meta_storage->Bind(descriptors); |
4777 | 4899 |
4778 DescriptorLookupLinear(unique_name, descriptors, nof, if_found_fast, | 4900 DescriptorLookup(unique_name, descriptors, bit_field3, if_found_fast, |
4779 var_name_index, if_not_found); | 4901 var_name_index, if_not_found); |
4780 } | 4902 } |
4781 Bind(&if_isslowmap); | 4903 Bind(&if_isslowmap); |
4782 { | 4904 { |
4783 Node* dictionary = LoadProperties(object); | 4905 Node* dictionary = LoadProperties(object); |
4784 var_meta_storage->Bind(dictionary); | 4906 var_meta_storage->Bind(dictionary); |
4785 | 4907 |
4786 NameDictionaryLookup<NameDictionary>(dictionary, unique_name, if_found_dict, | 4908 NameDictionaryLookup<NameDictionary>(dictionary, unique_name, if_found_dict, |
4787 var_name_index, if_not_found); | 4909 var_name_index, if_not_found); |
4788 } | 4910 } |
4789 Bind(&if_objectisspecial); | 4911 Bind(&if_objectisspecial); |
(...skipping 3536 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8326 formatted.c_str(), TENURED); | 8448 formatted.c_str(), TENURED); |
8327 CallRuntime(Runtime::kGlobalPrint, NoContextConstant(), | 8449 CallRuntime(Runtime::kGlobalPrint, NoContextConstant(), |
8328 HeapConstant(string)); | 8450 HeapConstant(string)); |
8329 } | 8451 } |
8330 CallRuntime(Runtime::kDebugPrint, NoContextConstant(), tagged_value); | 8452 CallRuntime(Runtime::kDebugPrint, NoContextConstant(), tagged_value); |
8331 #endif | 8453 #endif |
8332 } | 8454 } |
8333 | 8455 |
8334 } // namespace internal | 8456 } // namespace internal |
8335 } // namespace v8 | 8457 } // namespace v8 |
OLD | NEW |