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 3195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3206 // If we reach this, {string} is a non-indirect, non-external one-byte string. | 3206 // If we reach this, {string} is a non-indirect, non-external one-byte string. |
3207 | 3207 |
3208 Node* const length = LoadStringLength(string); | 3208 Node* const length = LoadStringLength(string); |
3209 Node* const search_range_length = SmiUntag(SmiSub(length, from)); | 3209 Node* const search_range_length = SmiUntag(SmiSub(length, from)); |
3210 | 3210 |
3211 const int offset = SeqOneByteString::kHeaderSize - kHeapObjectTag; | 3211 const int offset = SeqOneByteString::kHeaderSize - kHeapObjectTag; |
3212 Node* const begin = IntPtrConstant(offset); | 3212 Node* const begin = IntPtrConstant(offset); |
3213 Node* const cursor = IntPtrAdd(begin, SmiUntag(from)); | 3213 Node* const cursor = IntPtrAdd(begin, SmiUntag(from)); |
3214 Node* const end = IntPtrAdd(cursor, search_range_length); | 3214 Node* const end = IntPtrAdd(cursor, search_range_length); |
3215 | 3215 |
3216 Variable var_cursor(this, MachineType::PointerRepresentation()); | |
3217 Variable* vars[] = {&var_cursor}; | |
3218 Label loop(this, 1, vars), loop_tail(this); | |
3219 | |
3220 var_cursor.Bind(cursor); | |
3221 var_result.Bind(SmiConstant(Smi::FromInt(-1))); | 3216 var_result.Bind(SmiConstant(Smi::FromInt(-1))); |
3222 | 3217 |
3223 Goto(&loop); | 3218 BuildFastLoop(MachineType::PointerRepresentation(), cursor, end, |
3224 Bind(&loop); | 3219 [string, needle_char, begin, &var_result, &out]( |
3225 { | 3220 CodeStubAssembler* csa, Node* cursor) { |
3226 Node* const cursor = var_cursor.value(); | 3221 Label next(csa); |
| 3222 Node* value = csa->Load(MachineType::Uint8(), string, cursor); |
| 3223 csa->GotoUnless(csa->WordEqual(value, needle_char), &next); |
3227 | 3224 |
3228 Node* value = Load(MachineType::Uint8(), string, cursor); | 3225 // Found a match. |
3229 GotoUnless(WordEqual(value, needle_char), &loop_tail); | 3226 Node* index = csa->SmiTag(csa->IntPtrSub(cursor, begin)); |
| 3227 var_result.Bind(index); |
| 3228 csa->Goto(&out); |
3230 | 3229 |
3231 // Found a match. | 3230 csa->Bind(&next); |
3232 Node* index = SmiTag(IntPtrSub(cursor, begin)); | 3231 }, |
3233 var_result.Bind(index); | 3232 1, IndexAdvanceMode::kPost); |
3234 Goto(&out); | 3233 Goto(&out); |
3235 | |
3236 Bind(&loop_tail); | |
3237 { | |
3238 Node* const new_cursor = IntPtrAdd(cursor, IntPtrConstant(1)); | |
3239 var_cursor.Bind(new_cursor); | |
3240 Branch(IntPtrLessThan(new_cursor, end), &loop, &out); | |
3241 } | |
3242 } | |
3243 | 3234 |
3244 Bind(&runtime); | 3235 Bind(&runtime); |
3245 { | 3236 { |
3246 Node* const pattern = StringFromCharCode(needle_char); | 3237 Node* const pattern = StringFromCharCode(needle_char); |
3247 Node* const result = | 3238 Node* const result = |
3248 CallRuntime(Runtime::kStringIndexOf, context, string, pattern, from); | 3239 CallRuntime(Runtime::kStringIndexOf, context, string, pattern, from); |
3249 var_result.Bind(result); | 3240 var_result.Bind(result); |
3250 var_cursor.Bind(IntPtrConstant(0)); | |
3251 Goto(&out); | 3241 Goto(&out); |
3252 } | 3242 } |
3253 | 3243 |
3254 Bind(&out); | 3244 Bind(&out); |
3255 return var_result.value(); | 3245 return var_result.value(); |
3256 } | 3246 } |
3257 | 3247 |
3258 Node* CodeStubAssembler::StringFromCodePoint(compiler::Node* codepoint, | 3248 Node* CodeStubAssembler::StringFromCodePoint(compiler::Node* codepoint, |
3259 UnicodeEncoding encoding) { | 3249 UnicodeEncoding encoding) { |
3260 Variable var_result(this, MachineRepresentation::kTagged); | 3250 Variable var_result(this, MachineRepresentation::kTagged); |
(...skipping 1546 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4807 GotoIf(WordNotEqual(receiver_map, cached_map), &next_entry); | 4797 GotoIf(WordNotEqual(receiver_map, cached_map), &next_entry); |
4808 | 4798 |
4809 // Found, now call handler. | 4799 // Found, now call handler. |
4810 Node* handler = LoadFixedArrayElement( | 4800 Node* handler = LoadFixedArrayElement( |
4811 feedback, IntPtrConstant(i * kEntrySize + 1), 0, INTPTR_PARAMETERS); | 4801 feedback, IntPtrConstant(i * kEntrySize + 1), 0, INTPTR_PARAMETERS); |
4812 var_handler->Bind(handler); | 4802 var_handler->Bind(handler); |
4813 Goto(if_handler); | 4803 Goto(if_handler); |
4814 | 4804 |
4815 Bind(&next_entry); | 4805 Bind(&next_entry); |
4816 } | 4806 } |
4817 Node* length = LoadAndUntagFixedArrayBaseLength(feedback); | |
4818 | 4807 |
4819 // Loop from {unroll_count}*kEntrySize to {length}. | 4808 // Loop from {unroll_count}*kEntrySize to {length}. |
4820 Variable var_index(this, MachineType::PointerRepresentation()); | 4809 Node* init = IntPtrConstant(unroll_count * kEntrySize); |
4821 Label loop(this, &var_index); | 4810 Node* length = LoadAndUntagFixedArrayBaseLength(feedback); |
4822 var_index.Bind(IntPtrConstant(unroll_count * kEntrySize)); | 4811 BuildFastLoop( |
4823 Goto(&loop); | 4812 MachineType::PointerRepresentation(), init, length, |
4824 Bind(&loop); | 4813 [receiver_map, feedback, if_handler, var_handler](CodeStubAssembler* csa, |
4825 { | 4814 Node* index) { |
4826 Node* index = var_index.value(); | 4815 Node* cached_map = csa->LoadWeakCellValue( |
4827 GotoIf(UintPtrGreaterThanOrEqual(index, length), if_miss); | 4816 csa->LoadFixedArrayElement(feedback, index, 0, INTPTR_PARAMETERS)); |
4828 | 4817 |
4829 Node* cached_map = LoadWeakCellValue( | 4818 Label next_entry(csa); |
4830 LoadFixedArrayElement(feedback, index, 0, INTPTR_PARAMETERS)); | 4819 csa->GotoIf(csa->WordNotEqual(receiver_map, cached_map), &next_entry); |
4831 | 4820 |
4832 Label next_entry(this); | 4821 // Found, now call handler. |
4833 GotoIf(WordNotEqual(receiver_map, cached_map), &next_entry); | 4822 Node* handler = csa->LoadFixedArrayElement( |
| 4823 feedback, index, kPointerSize, INTPTR_PARAMETERS); |
| 4824 var_handler->Bind(handler); |
| 4825 csa->Goto(if_handler); |
4834 | 4826 |
4835 // Found, now call handler. | 4827 csa->Bind(&next_entry); |
4836 Node* handler = | 4828 }, |
4837 LoadFixedArrayElement(feedback, index, kPointerSize, INTPTR_PARAMETERS); | 4829 kEntrySize, IndexAdvanceMode::kPost); |
4838 var_handler->Bind(handler); | 4830 // The loop falls through if no handler was found. |
4839 Goto(if_handler); | 4831 Goto(if_miss); |
4840 | |
4841 Bind(&next_entry); | |
4842 var_index.Bind(IntPtrAdd(index, IntPtrConstant(kEntrySize))); | |
4843 Goto(&loop); | |
4844 } | |
4845 } | 4832 } |
4846 | 4833 |
4847 void CodeStubAssembler::HandleKeyedStorePolymorphicCase( | 4834 void CodeStubAssembler::HandleKeyedStorePolymorphicCase( |
4848 compiler::Node* receiver_map, compiler::Node* feedback, Label* if_handler, | 4835 compiler::Node* receiver_map, compiler::Node* feedback, Label* if_handler, |
4849 Variable* var_handler, Label* if_transition_handler, | 4836 Variable* var_handler, Label* if_transition_handler, |
4850 Variable* var_transition_map_cell, Label* if_miss) { | 4837 Variable* var_transition_map_cell, Label* if_miss) { |
4851 DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep()); | 4838 DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep()); |
4852 DCHECK_EQ(MachineRepresentation::kTagged, var_transition_map_cell->rep()); | 4839 DCHECK_EQ(MachineRepresentation::kTagged, var_transition_map_cell->rep()); |
4853 | 4840 |
4854 const int kEntrySize = 3; | 4841 const int kEntrySize = 3; |
4855 | 4842 |
4856 Variable var_index(this, MachineType::PointerRepresentation()); | 4843 Node* init = IntPtrConstant(0); |
4857 Label loop(this, &var_index); | |
4858 var_index.Bind(IntPtrConstant(0)); | |
4859 Node* length = LoadAndUntagFixedArrayBaseLength(feedback); | 4844 Node* length = LoadAndUntagFixedArrayBaseLength(feedback); |
4860 Goto(&loop); | 4845 BuildFastLoop( |
4861 Bind(&loop); | 4846 MachineType::PointerRepresentation(), init, length, |
4862 { | 4847 [receiver_map, feedback, if_handler, var_handler, if_transition_handler, |
4863 Node* index = var_index.value(); | 4848 var_transition_map_cell](CodeStubAssembler* csa, Node* index) { |
4864 GotoIf(UintPtrGreaterThanOrEqual(index, length), if_miss); | 4849 Node* cached_map = csa->LoadWeakCellValue( |
| 4850 csa->LoadFixedArrayElement(feedback, index, 0, INTPTR_PARAMETERS)); |
| 4851 Label next_entry(csa); |
| 4852 csa->GotoIf(csa->WordNotEqual(receiver_map, cached_map), &next_entry); |
4865 | 4853 |
4866 Node* cached_map = LoadWeakCellValue( | 4854 Node* maybe_transition_map_cell = csa->LoadFixedArrayElement( |
4867 LoadFixedArrayElement(feedback, index, 0, INTPTR_PARAMETERS)); | 4855 feedback, index, kPointerSize, INTPTR_PARAMETERS); |
4868 | 4856 |
4869 Label next_entry(this); | 4857 var_handler->Bind(csa->LoadFixedArrayElement( |
4870 GotoIf(WordNotEqual(receiver_map, cached_map), &next_entry); | 4858 feedback, index, 2 * kPointerSize, INTPTR_PARAMETERS)); |
| 4859 csa->GotoIf( |
| 4860 csa->WordEqual(maybe_transition_map_cell, |
| 4861 csa->LoadRoot(Heap::kUndefinedValueRootIndex)), |
| 4862 if_handler); |
| 4863 var_transition_map_cell->Bind(maybe_transition_map_cell); |
| 4864 csa->Goto(if_transition_handler); |
4871 | 4865 |
4872 Node* maybe_transition_map_cell = | 4866 csa->Bind(&next_entry); |
4873 LoadFixedArrayElement(feedback, index, kPointerSize, INTPTR_PARAMETERS); | 4867 }, |
4874 | 4868 kEntrySize, IndexAdvanceMode::kPost); |
4875 var_handler->Bind(LoadFixedArrayElement(feedback, index, 2 * kPointerSize, | 4869 // The loop falls through if no handler was found. |
4876 INTPTR_PARAMETERS)); | 4870 Goto(if_miss); |
4877 GotoIf(WordEqual(maybe_transition_map_cell, | |
4878 LoadRoot(Heap::kUndefinedValueRootIndex)), | |
4879 if_handler); | |
4880 var_transition_map_cell->Bind(maybe_transition_map_cell); | |
4881 Goto(if_transition_handler); | |
4882 | |
4883 Bind(&next_entry); | |
4884 var_index.Bind(IntPtrAdd(index, IntPtrConstant(kEntrySize))); | |
4885 Goto(&loop); | |
4886 } | |
4887 } | 4871 } |
4888 | 4872 |
4889 compiler::Node* CodeStubAssembler::StubCachePrimaryOffset(compiler::Node* name, | 4873 compiler::Node* CodeStubAssembler::StubCachePrimaryOffset(compiler::Node* name, |
4890 compiler::Node* map) { | 4874 compiler::Node* map) { |
4891 // See v8::internal::StubCache::PrimaryOffset(). | 4875 // See v8::internal::StubCache::PrimaryOffset(). |
4892 STATIC_ASSERT(StubCache::kCacheIndexShift == Name::kHashShift); | 4876 STATIC_ASSERT(StubCache::kCacheIndexShift == Name::kHashShift); |
4893 // Compute the hash of the name (use entire hash field). | 4877 // Compute the hash of the name (use entire hash field). |
4894 Node* hash_field = LoadNameHashField(name); | 4878 Node* hash_field = LoadNameHashField(name); |
4895 CSA_ASSERT(Word32Equal( | 4879 CSA_ASSERT(Word32Equal( |
4896 Word32And(hash_field, Int32Constant(Name::kHashNotComputedMask)), | 4880 Word32And(hash_field, Int32Constant(Name::kHashNotComputedMask)), |
(...skipping 3410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8307 Node* buffer_bit_field = LoadObjectField( | 8291 Node* buffer_bit_field = LoadObjectField( |
8308 buffer, JSArrayBuffer::kBitFieldOffset, MachineType::Uint32()); | 8292 buffer, JSArrayBuffer::kBitFieldOffset, MachineType::Uint32()); |
8309 Node* was_neutered_mask = Int32Constant(JSArrayBuffer::WasNeutered::kMask); | 8293 Node* was_neutered_mask = Int32Constant(JSArrayBuffer::WasNeutered::kMask); |
8310 | 8294 |
8311 return Word32NotEqual(Word32And(buffer_bit_field, was_neutered_mask), | 8295 return Word32NotEqual(Word32And(buffer_bit_field, was_neutered_mask), |
8312 Int32Constant(0)); | 8296 Int32Constant(0)); |
8313 } | 8297 } |
8314 | 8298 |
8315 } // namespace internal | 8299 } // namespace internal |
8316 } // namespace v8 | 8300 } // namespace v8 |
OLD | NEW |