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 | 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 2239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2250 } | 2250 } |
2251 } | 2251 } |
2252 | 2252 |
2253 void CodeStubAssembler::Use(Label* label) { | 2253 void CodeStubAssembler::Use(Label* label) { |
2254 GotoIf(Word32Equal(Int32Constant(0), Int32Constant(1)), label); | 2254 GotoIf(Word32Equal(Int32Constant(0), Int32Constant(1)), label); |
2255 } | 2255 } |
2256 | 2256 |
2257 void CodeStubAssembler::TryToName(Node* key, Label* if_keyisindex, | 2257 void CodeStubAssembler::TryToName(Node* key, Label* if_keyisindex, |
2258 Variable* var_index, Label* if_keyisunique, | 2258 Variable* var_index, Label* if_keyisunique, |
2259 Label* if_bailout) { | 2259 Label* if_bailout) { |
2260 DCHECK_EQ(MachineRepresentation::kWord32, var_index->rep()); | 2260 DCHECK_EQ(MachineType::PointerRepresentation(), var_index->rep()); |
2261 Comment("TryToName"); | 2261 Comment("TryToName"); |
2262 | 2262 |
2263 Label if_keyissmi(this), if_keyisnotsmi(this); | 2263 Label if_hascachedindex(this), if_keyisnotindex(this); |
2264 Branch(WordIsSmi(key), &if_keyissmi, &if_keyisnotsmi); | 2264 // Handle Smi and HeapNumber keys. |
2265 Bind(&if_keyissmi); | 2265 var_index->Bind(TryToIntptr(key, &if_keyisnotindex)); |
2266 { | 2266 Goto(if_keyisindex); |
2267 // Negative smi keys are named properties. Handle in the runtime. | |
2268 GotoUnless(WordIsPositiveSmi(key), if_bailout); | |
2269 | 2267 |
2270 var_index->Bind(SmiToWord32(key)); | 2268 Bind(&if_keyisnotindex); |
2271 Goto(if_keyisindex); | |
2272 } | |
2273 | |
2274 Bind(&if_keyisnotsmi); | |
2275 | |
2276 Node* key_instance_type = LoadInstanceType(key); | 2269 Node* key_instance_type = LoadInstanceType(key); |
2277 // Symbols are unique. | 2270 // Symbols are unique. |
2278 GotoIf(Word32Equal(key_instance_type, Int32Constant(SYMBOL_TYPE)), | 2271 GotoIf(Word32Equal(key_instance_type, Int32Constant(SYMBOL_TYPE)), |
2279 if_keyisunique); | 2272 if_keyisunique); |
| 2273 // Miss if |key| is not a String. |
| 2274 STATIC_ASSERT(FIRST_NAME_TYPE == FIRST_TYPE); |
| 2275 GotoIf( |
| 2276 Int32GreaterThan(key_instance_type, Int32Constant(FIRST_NONSTRING_TYPE)), |
| 2277 if_bailout); |
| 2278 // |key| is a String. Check if it has a cached array index. |
| 2279 Node* hash = LoadNameHashField(key); |
| 2280 Node* contains_index = |
| 2281 Word32And(hash, Int32Constant(Name::kContainsCachedArrayIndexMask)); |
| 2282 GotoIf(Word32Equal(contains_index, Int32Constant(0)), &if_hascachedindex); |
| 2283 // No cached array index. If the string knows that it contains an index, |
| 2284 // then it must be an uncacheable index. Handle this case in the runtime. |
| 2285 Node* not_an_index = |
| 2286 Word32And(hash, Int32Constant(Name::kIsNotArrayIndexMask)); |
| 2287 GotoIf(Word32Equal(not_an_index, Int32Constant(0)), if_bailout); |
| 2288 // Finally, check if |key| is internalized. |
| 2289 STATIC_ASSERT(kNotInternalizedTag != 0); |
| 2290 Node* not_internalized = |
| 2291 Word32And(key_instance_type, Int32Constant(kIsNotInternalizedMask)); |
| 2292 GotoIf(Word32NotEqual(not_internalized, Int32Constant(0)), if_bailout); |
| 2293 Goto(if_keyisunique); |
2280 | 2294 |
2281 Label if_keyisinternalized(this); | 2295 Bind(&if_hascachedindex); |
2282 Node* bits = | |
2283 WordAnd(key_instance_type, | |
2284 Int32Constant(kIsNotStringMask | kIsNotInternalizedMask)); | |
2285 Branch(Word32Equal(bits, Int32Constant(kStringTag | kInternalizedTag)), | |
2286 &if_keyisinternalized, if_bailout); | |
2287 Bind(&if_keyisinternalized); | |
2288 | |
2289 // Check whether the key is an array index passed in as string. Handle | |
2290 // uniform with smi keys if so. | |
2291 // TODO(verwaest): Also support non-internalized strings. | |
2292 Node* hash = LoadNameHashField(key); | |
2293 Node* bit = Word32And(hash, Int32Constant(Name::kIsNotArrayIndexMask)); | |
2294 GotoIf(Word32NotEqual(bit, Int32Constant(0)), if_keyisunique); | |
2295 // Key is an index. Check if it is small enough to be encoded in the | |
2296 // hash_field. Handle too big array index in runtime. | |
2297 bit = Word32And(hash, Int32Constant(Name::kContainsCachedArrayIndexMask)); | |
2298 GotoIf(Word32NotEqual(bit, Int32Constant(0)), if_bailout); | |
2299 var_index->Bind(BitFieldDecode<Name::ArrayIndexValueBits>(hash)); | 2296 var_index->Bind(BitFieldDecode<Name::ArrayIndexValueBits>(hash)); |
2300 Goto(if_keyisindex); | 2297 Goto(if_keyisindex); |
2301 } | 2298 } |
2302 | 2299 |
2303 template <typename Dictionary> | 2300 template <typename Dictionary> |
2304 Node* CodeStubAssembler::EntryToIndex(Node* entry, int field_index) { | 2301 Node* CodeStubAssembler::EntryToIndex(Node* entry, int field_index) { |
2305 Node* entry_index = Int32Mul(entry, Int32Constant(Dictionary::kEntrySize)); | 2302 Node* entry_index = Int32Mul(entry, Int32Constant(Dictionary::kEntrySize)); |
2306 return Int32Add(entry_index, | 2303 return Int32Add(entry_index, |
2307 Int32Constant(Dictionary::kElementsStartIndex + field_index)); | 2304 Int32Constant(Dictionary::kElementsStartIndex + field_index)); |
2308 } | 2305 } |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2382 Word32Shl(hash, Int32Constant(15))); | 2379 Word32Shl(hash, Int32Constant(15))); |
2383 hash = Word32Xor(hash, Word32Shr(hash, Int32Constant(12))); | 2380 hash = Word32Xor(hash, Word32Shr(hash, Int32Constant(12))); |
2384 hash = Int32Add(hash, Word32Shl(hash, Int32Constant(2))); | 2381 hash = Int32Add(hash, Word32Shl(hash, Int32Constant(2))); |
2385 hash = Word32Xor(hash, Word32Shr(hash, Int32Constant(4))); | 2382 hash = Word32Xor(hash, Word32Shr(hash, Int32Constant(4))); |
2386 hash = Int32Mul(hash, Int32Constant(2057)); | 2383 hash = Int32Mul(hash, Int32Constant(2057)); |
2387 hash = Word32Xor(hash, Word32Shr(hash, Int32Constant(16))); | 2384 hash = Word32Xor(hash, Word32Shr(hash, Int32Constant(16))); |
2388 return Word32And(hash, Int32Constant(0x3fffffff)); | 2385 return Word32And(hash, Int32Constant(0x3fffffff)); |
2389 } | 2386 } |
2390 | 2387 |
2391 template <typename Dictionary> | 2388 template <typename Dictionary> |
2392 void CodeStubAssembler::NumberDictionaryLookup(Node* dictionary, Node* key, | 2389 void CodeStubAssembler::NumberDictionaryLookup(Node* dictionary, |
| 2390 Node* intptr_index, |
2393 Label* if_found, | 2391 Label* if_found, |
2394 Variable* var_entry, | 2392 Variable* var_entry, |
2395 Label* if_not_found) { | 2393 Label* if_not_found) { |
2396 DCHECK_EQ(MachineRepresentation::kWord32, var_entry->rep()); | 2394 DCHECK_EQ(MachineRepresentation::kWord32, var_entry->rep()); |
2397 Comment("NumberDictionaryLookup"); | 2395 Comment("NumberDictionaryLookup"); |
2398 | 2396 |
2399 Node* capacity = LoadAndUntagToWord32FixedArrayElement( | 2397 Node* capacity = LoadAndUntagToWord32FixedArrayElement( |
2400 dictionary, Int32Constant(Dictionary::kCapacityIndex)); | 2398 dictionary, Int32Constant(Dictionary::kCapacityIndex)); |
2401 Node* mask = Int32Sub(capacity, Int32Constant(1)); | 2399 Node* mask = Int32Sub(capacity, Int32Constant(1)); |
2402 | 2400 |
2403 Node* seed; | 2401 Node* seed; |
2404 if (Dictionary::ShapeT::UsesSeed) { | 2402 if (Dictionary::ShapeT::UsesSeed) { |
2405 seed = HashSeed(); | 2403 seed = HashSeed(); |
2406 } else { | 2404 } else { |
2407 seed = Int32Constant(kZeroHashSeed); | 2405 seed = Int32Constant(kZeroHashSeed); |
2408 } | 2406 } |
2409 Node* hash = ComputeIntegerHash(key, seed); | 2407 Node* hash = ComputeIntegerHash(intptr_index, seed); |
2410 Node* key_as_float64 = ChangeUint32ToFloat64(key); | 2408 Node* key_as_float64 = RoundIntPtrToFloat64(intptr_index); |
2411 | 2409 |
2412 // See Dictionary::FirstProbe(). | 2410 // See Dictionary::FirstProbe(). |
2413 Node* count = Int32Constant(0); | 2411 Node* count = Int32Constant(0); |
2414 Node* entry = Word32And(hash, mask); | 2412 Node* entry = Word32And(hash, mask); |
2415 | 2413 |
2416 Node* undefined = UndefinedConstant(); | 2414 Node* undefined = UndefinedConstant(); |
2417 Node* the_hole = TheHoleConstant(); | 2415 Node* the_hole = TheHoleConstant(); |
2418 | 2416 |
2419 Variable var_count(this, MachineRepresentation::kWord32); | 2417 Variable var_count(this, MachineRepresentation::kWord32); |
2420 Variable* loop_vars[] = {&var_count, var_entry}; | 2418 Variable* loop_vars[] = {&var_count, var_entry}; |
2421 Label loop(this, 2, loop_vars); | 2419 Label loop(this, 2, loop_vars); |
2422 var_count.Bind(count); | 2420 var_count.Bind(count); |
2423 var_entry->Bind(entry); | 2421 var_entry->Bind(entry); |
2424 Goto(&loop); | 2422 Goto(&loop); |
2425 Bind(&loop); | 2423 Bind(&loop); |
2426 { | 2424 { |
2427 Node* count = var_count.value(); | 2425 Node* count = var_count.value(); |
2428 Node* entry = var_entry->value(); | 2426 Node* entry = var_entry->value(); |
2429 | 2427 |
2430 Node* index = EntryToIndex<Dictionary>(entry); | 2428 Node* index = EntryToIndex<Dictionary>(entry); |
2431 Node* current = LoadFixedArrayElement(dictionary, index); | 2429 Node* current = LoadFixedArrayElement(dictionary, index); |
2432 GotoIf(WordEqual(current, undefined), if_not_found); | 2430 GotoIf(WordEqual(current, undefined), if_not_found); |
2433 Label next_probe(this); | 2431 Label next_probe(this); |
2434 { | 2432 { |
2435 Label if_currentissmi(this), if_currentisnotsmi(this); | 2433 Label if_currentissmi(this), if_currentisnotsmi(this); |
2436 Branch(WordIsSmi(current), &if_currentissmi, &if_currentisnotsmi); | 2434 Branch(WordIsSmi(current), &if_currentissmi, &if_currentisnotsmi); |
2437 Bind(&if_currentissmi); | 2435 Bind(&if_currentissmi); |
2438 { | 2436 { |
2439 Node* current_value = SmiToWord32(current); | 2437 Node* current_value = SmiUntag(current); |
2440 Branch(Word32Equal(current_value, key), if_found, &next_probe); | 2438 Branch(WordEqual(current_value, intptr_index), if_found, &next_probe); |
2441 } | 2439 } |
2442 Bind(&if_currentisnotsmi); | 2440 Bind(&if_currentisnotsmi); |
2443 { | 2441 { |
2444 GotoIf(WordEqual(current, the_hole), &next_probe); | 2442 GotoIf(WordEqual(current, the_hole), &next_probe); |
2445 // Current must be the Number. | 2443 // Current must be the Number. |
2446 Node* current_value = LoadHeapNumberValue(current); | 2444 Node* current_value = LoadHeapNumberValue(current); |
2447 Branch(Float64Equal(current_value, key_as_float64), if_found, | 2445 Branch(Float64Equal(current_value, key_as_float64), if_found, |
2448 &next_probe); | 2446 &next_probe); |
2449 } | 2447 } |
2450 } | 2448 } |
(...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2810 // Call the accessor. | 2808 // Call the accessor. |
2811 Callable callable = CodeFactory::Call(isolate()); | 2809 Callable callable = CodeFactory::Call(isolate()); |
2812 Node* result = CallJS(callable, context, getter, receiver); | 2810 Node* result = CallJS(callable, context, getter, receiver); |
2813 var_value->Bind(result); | 2811 var_value->Bind(result); |
2814 Goto(if_found_value); | 2812 Goto(if_found_value); |
2815 } | 2813 } |
2816 } | 2814 } |
2817 } | 2815 } |
2818 | 2816 |
2819 void CodeStubAssembler::TryLookupElement(Node* object, Node* map, | 2817 void CodeStubAssembler::TryLookupElement(Node* object, Node* map, |
2820 Node* instance_type, Node* index, | 2818 Node* instance_type, |
2821 Label* if_found, Label* if_not_found, | 2819 Node* intptr_index, Label* if_found, |
| 2820 Label* if_not_found, |
2822 Label* if_bailout) { | 2821 Label* if_bailout) { |
2823 // Handle special objects in runtime. | 2822 // Handle special objects in runtime. |
2824 GotoIf(Int32LessThanOrEqual(instance_type, | 2823 GotoIf(Int32LessThanOrEqual(instance_type, |
2825 Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)), | 2824 Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)), |
2826 if_bailout); | 2825 if_bailout); |
2827 | 2826 |
2828 Node* bit_field2 = LoadMapBitField2(map); | 2827 Node* bit_field2 = LoadMapBitField2(map); |
2829 Node* elements_kind = BitFieldDecode<Map::ElementsKindBits>(bit_field2); | 2828 Node* elements_kind = BitFieldDecode<Map::ElementsKindBits>(bit_field2); |
2830 | 2829 |
2831 // TODO(verwaest): Support other elements kinds as well. | 2830 // TODO(verwaest): Support other elements kinds as well. |
2832 Label if_isobjectorsmi(this), if_isdouble(this), if_isdictionary(this), | 2831 Label if_isobjectorsmi(this), if_isdouble(this), if_isdictionary(this), |
2833 if_isfaststringwrapper(this), if_isslowstringwrapper(this); | 2832 if_isfaststringwrapper(this), if_isslowstringwrapper(this), if_oob(this); |
2834 // clang-format off | 2833 // clang-format off |
2835 int32_t values[] = { | 2834 int32_t values[] = { |
2836 // Handled by {if_isobjectorsmi}. | 2835 // Handled by {if_isobjectorsmi}. |
2837 FAST_SMI_ELEMENTS, FAST_HOLEY_SMI_ELEMENTS, FAST_ELEMENTS, | 2836 FAST_SMI_ELEMENTS, FAST_HOLEY_SMI_ELEMENTS, FAST_ELEMENTS, |
2838 FAST_HOLEY_ELEMENTS, | 2837 FAST_HOLEY_ELEMENTS, |
2839 // Handled by {if_isdouble}. | 2838 // Handled by {if_isdouble}. |
2840 FAST_DOUBLE_ELEMENTS, FAST_HOLEY_DOUBLE_ELEMENTS, | 2839 FAST_DOUBLE_ELEMENTS, FAST_HOLEY_DOUBLE_ELEMENTS, |
2841 // Handled by {if_isdictionary}. | 2840 // Handled by {if_isdictionary}. |
2842 DICTIONARY_ELEMENTS, | 2841 DICTIONARY_ELEMENTS, |
2843 // Handled by {if_isfaststringwrapper}. | 2842 // Handled by {if_isfaststringwrapper}. |
(...skipping 14 matching lines...) Expand all Loading... |
2858 }; | 2857 }; |
2859 // clang-format on | 2858 // clang-format on |
2860 STATIC_ASSERT(arraysize(values) == arraysize(labels)); | 2859 STATIC_ASSERT(arraysize(values) == arraysize(labels)); |
2861 Switch(elements_kind, if_bailout, values, labels, arraysize(values)); | 2860 Switch(elements_kind, if_bailout, values, labels, arraysize(values)); |
2862 | 2861 |
2863 Bind(&if_isobjectorsmi); | 2862 Bind(&if_isobjectorsmi); |
2864 { | 2863 { |
2865 Node* elements = LoadElements(object); | 2864 Node* elements = LoadElements(object); |
2866 Node* length = LoadAndUntagFixedArrayBaseLength(elements); | 2865 Node* length = LoadAndUntagFixedArrayBaseLength(elements); |
2867 | 2866 |
2868 GotoUnless(Uint32LessThan(index, length), if_not_found); | 2867 GotoUnless(UintPtrLessThan(intptr_index, length), &if_oob); |
2869 | 2868 |
2870 Node* element = LoadFixedArrayElement(elements, index); | 2869 Node* element = |
| 2870 LoadFixedArrayElement(elements, intptr_index, 0, INTPTR_PARAMETERS); |
2871 Node* the_hole = TheHoleConstant(); | 2871 Node* the_hole = TheHoleConstant(); |
2872 Branch(WordEqual(element, the_hole), if_not_found, if_found); | 2872 Branch(WordEqual(element, the_hole), if_not_found, if_found); |
2873 } | 2873 } |
2874 Bind(&if_isdouble); | 2874 Bind(&if_isdouble); |
2875 { | 2875 { |
2876 Node* elements = LoadElements(object); | 2876 Node* elements = LoadElements(object); |
2877 Node* length = LoadAndUntagFixedArrayBaseLength(elements); | 2877 Node* length = LoadAndUntagFixedArrayBaseLength(elements); |
2878 | 2878 |
2879 GotoUnless(Uint32LessThan(index, length), if_not_found); | 2879 GotoUnless(UintPtrLessThan(intptr_index, length), &if_oob); |
2880 | 2880 |
2881 if (kPointerSize == kDoubleSize) { | 2881 if (kPointerSize == kDoubleSize) { |
2882 Node* element = | 2882 Node* element = LoadFixedDoubleArrayElement( |
2883 LoadFixedDoubleArrayElement(elements, index, MachineType::Uint64()); | 2883 elements, intptr_index, MachineType::Uint64(), 0, INTPTR_PARAMETERS); |
2884 Node* the_hole = Int64Constant(kHoleNanInt64); | 2884 Node* the_hole = Int64Constant(kHoleNanInt64); |
2885 Branch(Word64Equal(element, the_hole), if_not_found, if_found); | 2885 Branch(Word64Equal(element, the_hole), if_not_found, if_found); |
2886 } else { | 2886 } else { |
2887 Node* element_upper = | 2887 Node* element_upper = LoadFixedDoubleArrayElement( |
2888 LoadFixedDoubleArrayElement(elements, index, MachineType::Uint32(), | 2888 elements, intptr_index, MachineType::Uint32(), |
2889 kIeeeDoubleExponentWordOffset); | 2889 kIeeeDoubleExponentWordOffset, INTPTR_PARAMETERS); |
2890 Branch(Word32Equal(element_upper, Int32Constant(kHoleNanUpper32)), | 2890 Branch(Word32Equal(element_upper, Int32Constant(kHoleNanUpper32)), |
2891 if_not_found, if_found); | 2891 if_not_found, if_found); |
2892 } | 2892 } |
2893 } | 2893 } |
2894 Bind(&if_isdictionary); | 2894 Bind(&if_isdictionary); |
2895 { | 2895 { |
2896 Variable var_entry(this, MachineRepresentation::kWord32); | 2896 Variable var_entry(this, MachineRepresentation::kWord32); |
2897 Node* elements = LoadElements(object); | 2897 Node* elements = LoadElements(object); |
2898 NumberDictionaryLookup<SeededNumberDictionary>(elements, index, if_found, | 2898 NumberDictionaryLookup<SeededNumberDictionary>( |
2899 &var_entry, if_not_found); | 2899 elements, intptr_index, if_found, &var_entry, if_not_found); |
2900 } | 2900 } |
2901 Bind(&if_isfaststringwrapper); | 2901 Bind(&if_isfaststringwrapper); |
2902 { | 2902 { |
2903 AssertInstanceType(object, JS_VALUE_TYPE); | 2903 AssertInstanceType(object, JS_VALUE_TYPE); |
2904 Node* string = LoadJSValueValue(object); | 2904 Node* string = LoadJSValueValue(object); |
2905 Assert(Int32LessThan(LoadInstanceType(string), | 2905 Assert(Int32LessThan(LoadInstanceType(string), |
2906 Int32Constant(FIRST_NONSTRING_TYPE))); | 2906 Int32Constant(FIRST_NONSTRING_TYPE))); |
2907 Node* length = LoadStringLength(string); | 2907 Node* length = LoadStringLength(string); |
2908 GotoIf(Uint32LessThan(index, SmiToWord32(length)), if_found); | 2908 GotoIf(UintPtrLessThan(intptr_index, SmiUntag(length)), if_found); |
2909 Goto(&if_isobjectorsmi); | 2909 Goto(&if_isobjectorsmi); |
2910 } | 2910 } |
2911 Bind(&if_isslowstringwrapper); | 2911 Bind(&if_isslowstringwrapper); |
2912 { | 2912 { |
2913 AssertInstanceType(object, JS_VALUE_TYPE); | 2913 AssertInstanceType(object, JS_VALUE_TYPE); |
2914 Node* string = LoadJSValueValue(object); | 2914 Node* string = LoadJSValueValue(object); |
2915 Assert(Int32LessThan(LoadInstanceType(string), | 2915 Assert(Int32LessThan(LoadInstanceType(string), |
2916 Int32Constant(FIRST_NONSTRING_TYPE))); | 2916 Int32Constant(FIRST_NONSTRING_TYPE))); |
2917 Node* length = LoadStringLength(string); | 2917 Node* length = LoadStringLength(string); |
2918 GotoIf(Uint32LessThan(index, SmiToWord32(length)), if_found); | 2918 GotoIf(UintPtrLessThan(intptr_index, SmiUntag(length)), if_found); |
2919 Goto(&if_isdictionary); | 2919 Goto(&if_isdictionary); |
2920 } | 2920 } |
| 2921 Bind(&if_oob); |
| 2922 { |
| 2923 // Positive OOB indices mean "not found", negative indices must be |
| 2924 // converted to property names. |
| 2925 GotoIf(IntPtrLessThan(intptr_index, IntPtrConstant(0)), if_bailout); |
| 2926 Goto(if_not_found); |
| 2927 } |
2921 } | 2928 } |
2922 | 2929 |
2923 // Instantiate template methods to workaround GCC compilation issue. | 2930 // Instantiate template methods to workaround GCC compilation issue. |
2924 template void CodeStubAssembler::NumberDictionaryLookup<SeededNumberDictionary>( | 2931 template void CodeStubAssembler::NumberDictionaryLookup<SeededNumberDictionary>( |
2925 Node*, Node*, Label*, Variable*, Label*); | 2932 Node*, Node*, Label*, Variable*, Label*); |
2926 template void CodeStubAssembler::NumberDictionaryLookup< | 2933 template void CodeStubAssembler::NumberDictionaryLookup< |
2927 UnseededNumberDictionary>(Node*, Node*, Label*, Variable*, Label*); | 2934 UnseededNumberDictionary>(Node*, Node*, Label*, Variable*, Label*); |
2928 | 2935 |
2929 void CodeStubAssembler::TryPrototypeChainLookup( | 2936 void CodeStubAssembler::TryPrototypeChainLookup( |
2930 Node* receiver, Node* key, LookupInHolder& lookup_property_in_holder, | 2937 Node* receiver, Node* key, LookupInHolder& lookup_property_in_holder, |
2931 LookupInHolder& lookup_element_in_holder, Label* if_end, | 2938 LookupInHolder& lookup_element_in_holder, Label* if_end, |
2932 Label* if_bailout) { | 2939 Label* if_bailout) { |
2933 // Ensure receiver is JSReceiver, otherwise bailout. | 2940 // Ensure receiver is JSReceiver, otherwise bailout. |
2934 Label if_objectisnotsmi(this); | 2941 Label if_objectisnotsmi(this); |
2935 Branch(WordIsSmi(receiver), if_bailout, &if_objectisnotsmi); | 2942 Branch(WordIsSmi(receiver), if_bailout, &if_objectisnotsmi); |
2936 Bind(&if_objectisnotsmi); | 2943 Bind(&if_objectisnotsmi); |
2937 | 2944 |
2938 Node* map = LoadMap(receiver); | 2945 Node* map = LoadMap(receiver); |
2939 Node* instance_type = LoadMapInstanceType(map); | 2946 Node* instance_type = LoadMapInstanceType(map); |
2940 { | 2947 { |
2941 Label if_objectisreceiver(this); | 2948 Label if_objectisreceiver(this); |
2942 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); | 2949 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); |
2943 STATIC_ASSERT(FIRST_JS_RECEIVER_TYPE == JS_PROXY_TYPE); | 2950 STATIC_ASSERT(FIRST_JS_RECEIVER_TYPE == JS_PROXY_TYPE); |
2944 Branch( | 2951 Branch( |
2945 Int32GreaterThan(instance_type, Int32Constant(FIRST_JS_RECEIVER_TYPE)), | 2952 Int32GreaterThan(instance_type, Int32Constant(FIRST_JS_RECEIVER_TYPE)), |
2946 &if_objectisreceiver, if_bailout); | 2953 &if_objectisreceiver, if_bailout); |
2947 Bind(&if_objectisreceiver); | 2954 Bind(&if_objectisreceiver); |
2948 } | 2955 } |
2949 | 2956 |
2950 Variable var_index(this, MachineRepresentation::kWord32); | 2957 Variable var_index(this, MachineType::PointerRepresentation()); |
2951 | 2958 |
2952 Label if_keyisindex(this), if_iskeyunique(this); | 2959 Label if_keyisindex(this), if_iskeyunique(this); |
2953 TryToName(key, &if_keyisindex, &var_index, &if_iskeyunique, if_bailout); | 2960 TryToName(key, &if_keyisindex, &var_index, &if_iskeyunique, if_bailout); |
2954 | 2961 |
2955 Bind(&if_iskeyunique); | 2962 Bind(&if_iskeyunique); |
2956 { | 2963 { |
2957 Variable var_holder(this, MachineRepresentation::kTagged); | 2964 Variable var_holder(this, MachineRepresentation::kTagged); |
2958 Variable var_holder_map(this, MachineRepresentation::kTagged); | 2965 Variable var_holder_map(this, MachineRepresentation::kTagged); |
2959 Variable var_holder_instance_type(this, MachineRepresentation::kWord8); | 2966 Variable var_holder_instance_type(this, MachineRepresentation::kWord8); |
2960 | 2967 |
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3172 } | 3179 } |
3173 | 3180 |
3174 compiler::Node* CodeStubAssembler::ElementOffsetFromIndex(Node* index_node, | 3181 compiler::Node* CodeStubAssembler::ElementOffsetFromIndex(Node* index_node, |
3175 ElementsKind kind, | 3182 ElementsKind kind, |
3176 ParameterMode mode, | 3183 ParameterMode mode, |
3177 int base_size) { | 3184 int base_size) { |
3178 bool is_double = IsFastDoubleElementsKind(kind); | 3185 bool is_double = IsFastDoubleElementsKind(kind); |
3179 int element_size_shift = is_double ? kDoubleSizeLog2 : kPointerSizeLog2; | 3186 int element_size_shift = is_double ? kDoubleSizeLog2 : kPointerSizeLog2; |
3180 int element_size = 1 << element_size_shift; | 3187 int element_size = 1 << element_size_shift; |
3181 int const kSmiShiftBits = kSmiShiftSize + kSmiTagSize; | 3188 int const kSmiShiftBits = kSmiShiftSize + kSmiTagSize; |
3182 int32_t index = 0; | 3189 intptr_t index = 0; |
3183 bool constant_index = false; | 3190 bool constant_index = false; |
3184 if (mode == SMI_PARAMETERS) { | 3191 if (mode == SMI_PARAMETERS) { |
3185 element_size_shift -= kSmiShiftBits; | 3192 element_size_shift -= kSmiShiftBits; |
3186 intptr_t temp = 0; | 3193 constant_index = ToIntPtrConstant(index_node, index); |
3187 constant_index = ToIntPtrConstant(index_node, temp); | 3194 index = index >> kSmiShiftBits; |
3188 index = temp >> kSmiShiftBits; | 3195 } else if (mode == INTEGER_PARAMETERS) { |
| 3196 int32_t temp = 0; |
| 3197 constant_index = ToInt32Constant(index_node, temp); |
| 3198 index = static_cast<intptr_t>(temp); |
3189 } else { | 3199 } else { |
3190 constant_index = ToInt32Constant(index_node, index); | 3200 DCHECK(mode == INTPTR_PARAMETERS); |
| 3201 constant_index = ToIntPtrConstant(index_node, index); |
3191 } | 3202 } |
3192 if (constant_index) { | 3203 if (constant_index) { |
3193 return IntPtrConstant(base_size + element_size * index); | 3204 return IntPtrConstant(base_size + element_size * index); |
3194 } | 3205 } |
3195 if (Is64() && mode == INTEGER_PARAMETERS) { | 3206 if (Is64() && mode == INTEGER_PARAMETERS) { |
3196 index_node = ChangeInt32ToInt64(index_node); | 3207 index_node = ChangeInt32ToInt64(index_node); |
3197 } | 3208 } |
3198 if (base_size == 0) { | 3209 if (base_size == 0) { |
3199 return (element_size_shift >= 0) | 3210 return (element_size_shift >= 0) |
3200 ? WordShl(index_node, IntPtrConstant(element_size_shift)) | 3211 ? WordShl(index_node, IntPtrConstant(element_size_shift)) |
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3476 var_intptr_key.Bind(SmiUntag(key)); | 3487 var_intptr_key.Bind(SmiUntag(key)); |
3477 Goto(&done); | 3488 Goto(&done); |
3478 } | 3489 } |
3479 | 3490 |
3480 Bind(&done); | 3491 Bind(&done); |
3481 return var_intptr_key.value(); | 3492 return var_intptr_key.value(); |
3482 } | 3493 } |
3483 | 3494 |
3484 void CodeStubAssembler::EmitFastElementsBoundsCheck(Node* object, | 3495 void CodeStubAssembler::EmitFastElementsBoundsCheck(Node* object, |
3485 Node* elements, | 3496 Node* elements, |
3486 Node* intptr_key, | 3497 Node* intptr_index, |
3487 Node* is_jsarray_condition, | 3498 Node* is_jsarray_condition, |
3488 Label* miss) { | 3499 Label* miss) { |
3489 Variable var_length(this, MachineRepresentation::kTagged); | 3500 Variable var_length(this, MachineRepresentation::kTagged); |
3490 Label if_array(this), length_loaded(this, &var_length); | 3501 Label if_array(this), length_loaded(this, &var_length); |
3491 GotoIf(is_jsarray_condition, &if_array); | 3502 GotoIf(is_jsarray_condition, &if_array); |
3492 { | 3503 { |
3493 var_length.Bind(SmiUntag(LoadFixedArrayBaseLength(elements))); | 3504 var_length.Bind(SmiUntag(LoadFixedArrayBaseLength(elements))); |
3494 Goto(&length_loaded); | 3505 Goto(&length_loaded); |
3495 } | 3506 } |
3496 Bind(&if_array); | 3507 Bind(&if_array); |
3497 { | 3508 { |
3498 var_length.Bind(SmiUntag(LoadObjectField(object, JSArray::kLengthOffset))); | 3509 var_length.Bind(SmiUntag(LoadObjectField(object, JSArray::kLengthOffset))); |
3499 Goto(&length_loaded); | 3510 Goto(&length_loaded); |
3500 } | 3511 } |
3501 Bind(&length_loaded); | 3512 Bind(&length_loaded); |
3502 GotoUnless(UintPtrLessThan(intptr_key, var_length.value()), miss); | 3513 GotoUnless(UintPtrLessThan(intptr_index, var_length.value()), miss); |
3503 } | 3514 } |
3504 | 3515 |
3505 // |key| should be untagged (int32). | |
3506 void CodeStubAssembler::EmitElementLoad(Node* object, Node* elements, | 3516 void CodeStubAssembler::EmitElementLoad(Node* object, Node* elements, |
3507 Node* elements_kind, Node* key, | 3517 Node* elements_kind, Node* intptr_index, |
3508 Node* is_jsarray_condition, | 3518 Node* is_jsarray_condition, |
3509 Label* if_hole, Label* rebox_double, | 3519 Label* if_hole, Label* rebox_double, |
3510 Variable* var_double_value, | 3520 Variable* var_double_value, |
3511 Label* unimplemented_elements_kind, | 3521 Label* unimplemented_elements_kind, |
3512 Label* out_of_bounds, Label* miss) { | 3522 Label* out_of_bounds, Label* miss) { |
3513 Label if_typed_array(this), if_fast_packed(this), if_fast_holey(this), | 3523 Label if_typed_array(this), if_fast_packed(this), if_fast_holey(this), |
3514 if_fast_double(this), if_fast_holey_double(this), if_nonfast(this), | 3524 if_fast_double(this), if_fast_holey_double(this), if_nonfast(this), |
3515 if_dictionary(this), unreachable(this); | 3525 if_dictionary(this), unreachable(this); |
3516 GotoIf( | 3526 GotoIf( |
3517 IntPtrGreaterThan(elements_kind, IntPtrConstant(LAST_FAST_ELEMENTS_KIND)), | 3527 IntPtrGreaterThan(elements_kind, IntPtrConstant(LAST_FAST_ELEMENTS_KIND)), |
3518 &if_nonfast); | 3528 &if_nonfast); |
3519 | 3529 |
3520 EmitFastElementsBoundsCheck(object, elements, key, is_jsarray_condition, | 3530 EmitFastElementsBoundsCheck(object, elements, intptr_index, |
3521 out_of_bounds); | 3531 is_jsarray_condition, out_of_bounds); |
3522 int32_t kinds[] = {// Handled by if_fast_packed. | 3532 int32_t kinds[] = {// Handled by if_fast_packed. |
3523 FAST_SMI_ELEMENTS, FAST_ELEMENTS, | 3533 FAST_SMI_ELEMENTS, FAST_ELEMENTS, |
3524 // Handled by if_fast_holey. | 3534 // Handled by if_fast_holey. |
3525 FAST_HOLEY_SMI_ELEMENTS, FAST_HOLEY_ELEMENTS, | 3535 FAST_HOLEY_SMI_ELEMENTS, FAST_HOLEY_ELEMENTS, |
3526 // Handled by if_fast_double. | 3536 // Handled by if_fast_double. |
3527 FAST_DOUBLE_ELEMENTS, | 3537 FAST_DOUBLE_ELEMENTS, |
3528 // Handled by if_fast_holey_double. | 3538 // Handled by if_fast_holey_double. |
3529 FAST_HOLEY_DOUBLE_ELEMENTS}; | 3539 FAST_HOLEY_DOUBLE_ELEMENTS}; |
3530 Label* labels[] = {// FAST_{SMI,}_ELEMENTS | 3540 Label* labels[] = {// FAST_{SMI,}_ELEMENTS |
3531 &if_fast_packed, &if_fast_packed, | 3541 &if_fast_packed, &if_fast_packed, |
3532 // FAST_HOLEY_{SMI,}_ELEMENTS | 3542 // FAST_HOLEY_{SMI,}_ELEMENTS |
3533 &if_fast_holey, &if_fast_holey, | 3543 &if_fast_holey, &if_fast_holey, |
3534 // FAST_DOUBLE_ELEMENTS | 3544 // FAST_DOUBLE_ELEMENTS |
3535 &if_fast_double, | 3545 &if_fast_double, |
3536 // FAST_HOLEY_DOUBLE_ELEMENTS | 3546 // FAST_HOLEY_DOUBLE_ELEMENTS |
3537 &if_fast_holey_double}; | 3547 &if_fast_holey_double}; |
3538 Switch(elements_kind, unimplemented_elements_kind, kinds, labels, | 3548 Switch(elements_kind, unimplemented_elements_kind, kinds, labels, |
3539 arraysize(kinds)); | 3549 arraysize(kinds)); |
3540 | 3550 |
3541 Bind(&if_fast_packed); | 3551 Bind(&if_fast_packed); |
3542 { | 3552 { |
3543 Comment("fast packed elements"); | 3553 Comment("fast packed elements"); |
3544 // TODO(jkummerow): The Load*Element helpers add movsxlq instructions | 3554 Return(LoadFixedArrayElement(elements, intptr_index, 0, INTPTR_PARAMETERS)); |
3545 // on x64 which we don't need here, because |key| is an IntPtr already. | |
3546 // Do something about that. | |
3547 Return(LoadFixedArrayElement(elements, key)); | |
3548 } | 3555 } |
3549 | 3556 |
3550 Bind(&if_fast_holey); | 3557 Bind(&if_fast_holey); |
3551 { | 3558 { |
3552 Comment("fast holey elements"); | 3559 Comment("fast holey elements"); |
3553 Node* element = LoadFixedArrayElement(elements, key); | 3560 Node* element = |
| 3561 LoadFixedArrayElement(elements, intptr_index, 0, INTPTR_PARAMETERS); |
3554 GotoIf(WordEqual(element, TheHoleConstant()), if_hole); | 3562 GotoIf(WordEqual(element, TheHoleConstant()), if_hole); |
3555 Return(element); | 3563 Return(element); |
3556 } | 3564 } |
3557 | 3565 |
3558 Bind(&if_fast_double); | 3566 Bind(&if_fast_double); |
3559 { | 3567 { |
3560 Comment("packed double elements"); | 3568 Comment("packed double elements"); |
3561 var_double_value->Bind( | 3569 var_double_value->Bind(LoadFixedDoubleArrayElement( |
3562 LoadFixedDoubleArrayElement(elements, key, MachineType::Float64())); | 3570 elements, intptr_index, MachineType::Float64(), 0, INTPTR_PARAMETERS)); |
3563 Goto(rebox_double); | 3571 Goto(rebox_double); |
3564 } | 3572 } |
3565 | 3573 |
3566 Bind(&if_fast_holey_double); | 3574 Bind(&if_fast_holey_double); |
3567 { | 3575 { |
3568 Comment("holey double elements"); | 3576 Comment("holey double elements"); |
3569 if (kPointerSize == kDoubleSize) { | 3577 if (kPointerSize == kDoubleSize) { |
3570 Node* raw_element = | 3578 Node* raw_element = LoadFixedDoubleArrayElement( |
3571 LoadFixedDoubleArrayElement(elements, key, MachineType::Uint64()); | 3579 elements, intptr_index, MachineType::Uint64(), 0, INTPTR_PARAMETERS); |
3572 Node* the_hole = Int64Constant(kHoleNanInt64); | 3580 Node* the_hole = Int64Constant(kHoleNanInt64); |
3573 GotoIf(Word64Equal(raw_element, the_hole), if_hole); | 3581 GotoIf(Word64Equal(raw_element, the_hole), if_hole); |
3574 } else { | 3582 } else { |
3575 Node* element_upper = LoadFixedDoubleArrayElement( | 3583 Node* element_upper = LoadFixedDoubleArrayElement( |
3576 elements, key, MachineType::Uint32(), kIeeeDoubleExponentWordOffset); | 3584 elements, intptr_index, MachineType::Uint32(), |
| 3585 kIeeeDoubleExponentWordOffset, INTPTR_PARAMETERS); |
3577 GotoIf(Word32Equal(element_upper, Int32Constant(kHoleNanUpper32)), | 3586 GotoIf(Word32Equal(element_upper, Int32Constant(kHoleNanUpper32)), |
3578 if_hole); | 3587 if_hole); |
3579 } | 3588 } |
3580 var_double_value->Bind( | 3589 var_double_value->Bind(LoadFixedDoubleArrayElement( |
3581 LoadFixedDoubleArrayElement(elements, key, MachineType::Float64())); | 3590 elements, intptr_index, MachineType::Float64(), 0, INTPTR_PARAMETERS)); |
3582 Goto(rebox_double); | 3591 Goto(rebox_double); |
3583 } | 3592 } |
3584 | 3593 |
3585 Bind(&if_nonfast); | 3594 Bind(&if_nonfast); |
3586 { | 3595 { |
3587 STATIC_ASSERT(LAST_ELEMENTS_KIND == LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND); | 3596 STATIC_ASSERT(LAST_ELEMENTS_KIND == LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND); |
3588 GotoIf(IntPtrGreaterThanOrEqual( | 3597 GotoIf(IntPtrGreaterThanOrEqual( |
3589 elements_kind, | 3598 elements_kind, |
3590 IntPtrConstant(FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND)), | 3599 IntPtrConstant(FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND)), |
3591 &if_typed_array); | 3600 &if_typed_array); |
3592 GotoIf(IntPtrEqual(elements_kind, IntPtrConstant(DICTIONARY_ELEMENTS)), | 3601 GotoIf(IntPtrEqual(elements_kind, IntPtrConstant(DICTIONARY_ELEMENTS)), |
3593 &if_dictionary); | 3602 &if_dictionary); |
3594 Goto(unimplemented_elements_kind); | 3603 Goto(unimplemented_elements_kind); |
3595 } | 3604 } |
3596 | 3605 |
3597 Bind(&if_dictionary); | 3606 Bind(&if_dictionary); |
3598 { | 3607 { |
3599 Comment("dictionary elements"); | 3608 Comment("dictionary elements"); |
3600 GotoIf(IntPtrLessThan(key, IntPtrConstant(0)), out_of_bounds); | 3609 GotoIf(IntPtrLessThan(intptr_index, IntPtrConstant(0)), out_of_bounds); |
3601 Variable var_entry(this, MachineRepresentation::kWord32); | 3610 Variable var_entry(this, MachineRepresentation::kWord32); |
3602 Label if_found(this); | 3611 Label if_found(this); |
3603 NumberDictionaryLookup<SeededNumberDictionary>(elements, key, &if_found, | 3612 NumberDictionaryLookup<SeededNumberDictionary>( |
3604 &var_entry, if_hole); | 3613 elements, intptr_index, &if_found, &var_entry, if_hole); |
3605 Bind(&if_found); | 3614 Bind(&if_found); |
3606 // Check that the value is a data property. | 3615 // Check that the value is a data property. |
3607 Node* details_index = EntryToIndex<SeededNumberDictionary>( | 3616 Node* details_index = EntryToIndex<SeededNumberDictionary>( |
3608 var_entry.value(), SeededNumberDictionary::kEntryDetailsIndex); | 3617 var_entry.value(), SeededNumberDictionary::kEntryDetailsIndex); |
3609 Node* details = SmiToWord32(LoadFixedArrayElement(elements, details_index)); | 3618 Node* details = SmiToWord32(LoadFixedArrayElement(elements, details_index)); |
3610 Node* kind = BitFieldDecode<PropertyDetails::KindField>(details); | 3619 Node* kind = BitFieldDecode<PropertyDetails::KindField>(details); |
3611 // TODO(jkummerow): Support accessors without missing? | 3620 // TODO(jkummerow): Support accessors without missing? |
3612 GotoUnless(Word32Equal(kind, Int32Constant(kData)), miss); | 3621 GotoUnless(Word32Equal(kind, Int32Constant(kData)), miss); |
3613 // Finally, load the value. | 3622 // Finally, load the value. |
3614 Node* value_index = EntryToIndex<SeededNumberDictionary>( | 3623 Node* value_index = EntryToIndex<SeededNumberDictionary>( |
3615 var_entry.value(), SeededNumberDictionary::kEntryValueIndex); | 3624 var_entry.value(), SeededNumberDictionary::kEntryValueIndex); |
3616 Return(LoadFixedArrayElement(elements, value_index)); | 3625 Return(LoadFixedArrayElement(elements, value_index)); |
3617 } | 3626 } |
3618 | 3627 |
3619 Bind(&if_typed_array); | 3628 Bind(&if_typed_array); |
3620 { | 3629 { |
3621 Comment("typed elements"); | 3630 Comment("typed elements"); |
3622 // Check if buffer has been neutered. | 3631 // Check if buffer has been neutered. |
3623 Node* buffer = LoadObjectField(object, JSArrayBufferView::kBufferOffset); | 3632 Node* buffer = LoadObjectField(object, JSArrayBufferView::kBufferOffset); |
3624 Node* bitfield = LoadObjectField(buffer, JSArrayBuffer::kBitFieldOffset, | 3633 Node* bitfield = LoadObjectField(buffer, JSArrayBuffer::kBitFieldOffset, |
3625 MachineType::Uint32()); | 3634 MachineType::Uint32()); |
3626 Node* neutered_bit = | 3635 Node* neutered_bit = |
3627 Word32And(bitfield, Int32Constant(JSArrayBuffer::WasNeutered::kMask)); | 3636 Word32And(bitfield, Int32Constant(JSArrayBuffer::WasNeutered::kMask)); |
3628 GotoUnless(Word32Equal(neutered_bit, Int32Constant(0)), miss); | 3637 GotoUnless(Word32Equal(neutered_bit, Int32Constant(0)), miss); |
3629 | 3638 |
3630 // Bounds check. | 3639 // Bounds check. |
3631 Node* length = | 3640 Node* length = |
3632 SmiUntag(LoadObjectField(object, JSTypedArray::kLengthOffset)); | 3641 SmiUntag(LoadObjectField(object, JSTypedArray::kLengthOffset)); |
3633 GotoUnless(UintPtrLessThan(key, length), out_of_bounds); | 3642 GotoUnless(UintPtrLessThan(intptr_index, length), out_of_bounds); |
3634 | 3643 |
3635 // Backing store = external_pointer + base_pointer. | 3644 // Backing store = external_pointer + base_pointer. |
3636 Node* external_pointer = | 3645 Node* external_pointer = |
3637 LoadObjectField(elements, FixedTypedArrayBase::kExternalPointerOffset, | 3646 LoadObjectField(elements, FixedTypedArrayBase::kExternalPointerOffset, |
3638 MachineType::Pointer()); | 3647 MachineType::Pointer()); |
3639 Node* base_pointer = | 3648 Node* base_pointer = |
3640 LoadObjectField(elements, FixedTypedArrayBase::kBasePointerOffset); | 3649 LoadObjectField(elements, FixedTypedArrayBase::kBasePointerOffset); |
3641 Node* backing_store = IntPtrAdd(external_pointer, base_pointer); | 3650 Node* backing_store = IntPtrAdd(external_pointer, base_pointer); |
3642 | 3651 |
3643 Label uint8_elements(this), int8_elements(this), uint16_elements(this), | 3652 Label uint8_elements(this), int8_elements(this), uint16_elements(this), |
(...skipping 10 matching lines...) Expand all Loading... |
3654 const int kTypedElementsKindCount = LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND - | 3663 const int kTypedElementsKindCount = LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND - |
3655 FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND + | 3664 FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND + |
3656 1; | 3665 1; |
3657 DCHECK_EQ(kTypedElementsKindCount, arraysize(elements_kinds)); | 3666 DCHECK_EQ(kTypedElementsKindCount, arraysize(elements_kinds)); |
3658 DCHECK_EQ(kTypedElementsKindCount, arraysize(elements_kind_labels)); | 3667 DCHECK_EQ(kTypedElementsKindCount, arraysize(elements_kind_labels)); |
3659 Switch(elements_kind, miss, elements_kinds, elements_kind_labels, | 3668 Switch(elements_kind, miss, elements_kinds, elements_kind_labels, |
3660 static_cast<size_t>(kTypedElementsKindCount)); | 3669 static_cast<size_t>(kTypedElementsKindCount)); |
3661 Bind(&uint8_elements); | 3670 Bind(&uint8_elements); |
3662 { | 3671 { |
3663 Comment("UINT8_ELEMENTS"); // Handles UINT8_CLAMPED_ELEMENTS too. | 3672 Comment("UINT8_ELEMENTS"); // Handles UINT8_CLAMPED_ELEMENTS too. |
3664 Return(SmiTag(Load(MachineType::Uint8(), backing_store, key))); | 3673 Return(SmiTag(Load(MachineType::Uint8(), backing_store, intptr_index))); |
3665 } | 3674 } |
3666 Bind(&int8_elements); | 3675 Bind(&int8_elements); |
3667 { | 3676 { |
3668 Comment("INT8_ELEMENTS"); | 3677 Comment("INT8_ELEMENTS"); |
3669 Return(SmiTag(Load(MachineType::Int8(), backing_store, key))); | 3678 Return(SmiTag(Load(MachineType::Int8(), backing_store, intptr_index))); |
3670 } | 3679 } |
3671 Bind(&uint16_elements); | 3680 Bind(&uint16_elements); |
3672 { | 3681 { |
3673 Comment("UINT16_ELEMENTS"); | 3682 Comment("UINT16_ELEMENTS"); |
3674 Node* index = WordShl(key, IntPtrConstant(1)); | 3683 Node* index = WordShl(intptr_index, IntPtrConstant(1)); |
3675 Return(SmiTag(Load(MachineType::Uint16(), backing_store, index))); | 3684 Return(SmiTag(Load(MachineType::Uint16(), backing_store, index))); |
3676 } | 3685 } |
3677 Bind(&int16_elements); | 3686 Bind(&int16_elements); |
3678 { | 3687 { |
3679 Comment("INT16_ELEMENTS"); | 3688 Comment("INT16_ELEMENTS"); |
3680 Node* index = WordShl(key, IntPtrConstant(1)); | 3689 Node* index = WordShl(intptr_index, IntPtrConstant(1)); |
3681 Return(SmiTag(Load(MachineType::Int16(), backing_store, index))); | 3690 Return(SmiTag(Load(MachineType::Int16(), backing_store, index))); |
3682 } | 3691 } |
3683 Bind(&uint32_elements); | 3692 Bind(&uint32_elements); |
3684 { | 3693 { |
3685 Comment("UINT32_ELEMENTS"); | 3694 Comment("UINT32_ELEMENTS"); |
3686 Node* index = WordShl(key, IntPtrConstant(2)); | 3695 Node* index = WordShl(intptr_index, IntPtrConstant(2)); |
3687 Node* element = Load(MachineType::Uint32(), backing_store, index); | 3696 Node* element = Load(MachineType::Uint32(), backing_store, index); |
3688 Return(ChangeUint32ToTagged(element)); | 3697 Return(ChangeUint32ToTagged(element)); |
3689 } | 3698 } |
3690 Bind(&int32_elements); | 3699 Bind(&int32_elements); |
3691 { | 3700 { |
3692 Comment("INT32_ELEMENTS"); | 3701 Comment("INT32_ELEMENTS"); |
3693 Node* index = WordShl(key, IntPtrConstant(2)); | 3702 Node* index = WordShl(intptr_index, IntPtrConstant(2)); |
3694 Node* element = Load(MachineType::Int32(), backing_store, index); | 3703 Node* element = Load(MachineType::Int32(), backing_store, index); |
3695 Return(ChangeInt32ToTagged(element)); | 3704 Return(ChangeInt32ToTagged(element)); |
3696 } | 3705 } |
3697 Bind(&float32_elements); | 3706 Bind(&float32_elements); |
3698 { | 3707 { |
3699 Comment("FLOAT32_ELEMENTS"); | 3708 Comment("FLOAT32_ELEMENTS"); |
3700 Node* index = WordShl(key, IntPtrConstant(2)); | 3709 Node* index = WordShl(intptr_index, IntPtrConstant(2)); |
3701 Node* element = Load(MachineType::Float32(), backing_store, index); | 3710 Node* element = Load(MachineType::Float32(), backing_store, index); |
3702 var_double_value->Bind(ChangeFloat32ToFloat64(element)); | 3711 var_double_value->Bind(ChangeFloat32ToFloat64(element)); |
3703 Goto(rebox_double); | 3712 Goto(rebox_double); |
3704 } | 3713 } |
3705 Bind(&float64_elements); | 3714 Bind(&float64_elements); |
3706 { | 3715 { |
3707 Comment("FLOAT64_ELEMENTS"); | 3716 Comment("FLOAT64_ELEMENTS"); |
3708 Node* index = WordShl(key, IntPtrConstant(3)); | 3717 Node* index = WordShl(intptr_index, IntPtrConstant(3)); |
3709 Node* element = Load(MachineType::Float64(), backing_store, index); | 3718 Node* element = Load(MachineType::Float64(), backing_store, index); |
3710 var_double_value->Bind(element); | 3719 var_double_value->Bind(element); |
3711 Goto(rebox_double); | 3720 Goto(rebox_double); |
3712 } | 3721 } |
3713 } | 3722 } |
3714 } | 3723 } |
3715 | 3724 |
3716 void CodeStubAssembler::HandleLoadICHandlerCase( | 3725 void CodeStubAssembler::HandleLoadICHandlerCase( |
3717 const LoadICParameters* p, Node* handler, Label* miss, | 3726 const LoadICParameters* p, Node* handler, Label* miss, |
3718 ElementSupport support_elements) { | 3727 ElementSupport support_elements) { |
(...skipping 10 matching lines...) Expand all Loading... |
3729 Node* handler_word = SmiUntag(handler); | 3738 Node* handler_word = SmiUntag(handler); |
3730 if (support_elements == kSupportElements) { | 3739 if (support_elements == kSupportElements) { |
3731 Label property(this); | 3740 Label property(this); |
3732 Node* handler_type = | 3741 Node* handler_type = |
3733 WordAnd(handler_word, IntPtrConstant(LoadHandlerTypeBit::kMask)); | 3742 WordAnd(handler_word, IntPtrConstant(LoadHandlerTypeBit::kMask)); |
3734 GotoUnless( | 3743 GotoUnless( |
3735 WordEqual(handler_type, IntPtrConstant(kLoadICHandlerForElements)), | 3744 WordEqual(handler_type, IntPtrConstant(kLoadICHandlerForElements)), |
3736 &property); | 3745 &property); |
3737 | 3746 |
3738 Comment("element_load"); | 3747 Comment("element_load"); |
3739 Node* key = TryToIntptr(p->name, miss); | 3748 Node* intptr_index = TryToIntptr(p->name, miss); |
3740 Node* elements = LoadElements(p->receiver); | 3749 Node* elements = LoadElements(p->receiver); |
3741 Node* is_jsarray = | 3750 Node* is_jsarray = |
3742 WordAnd(handler_word, IntPtrConstant(KeyedLoadIsJsArray::kMask)); | 3751 WordAnd(handler_word, IntPtrConstant(KeyedLoadIsJsArray::kMask)); |
3743 Node* is_jsarray_condition = WordNotEqual(is_jsarray, IntPtrConstant(0)); | 3752 Node* is_jsarray_condition = WordNotEqual(is_jsarray, IntPtrConstant(0)); |
3744 Node* elements_kind = BitFieldDecode<KeyedLoadElementsKind>(handler_word); | 3753 Node* elements_kind = BitFieldDecode<KeyedLoadElementsKind>(handler_word); |
3745 Label if_hole(this), unimplemented_elements_kind(this); | 3754 Label if_hole(this), unimplemented_elements_kind(this); |
3746 Label* out_of_bounds = miss; | 3755 Label* out_of_bounds = miss; |
3747 EmitElementLoad(p->receiver, elements, elements_kind, key, | 3756 EmitElementLoad(p->receiver, elements, elements_kind, intptr_index, |
3748 is_jsarray_condition, &if_hole, &rebox_double, | 3757 is_jsarray_condition, &if_hole, &rebox_double, |
3749 &var_double_value, &unimplemented_elements_kind, | 3758 &var_double_value, &unimplemented_elements_kind, |
3750 out_of_bounds, miss); | 3759 out_of_bounds, miss); |
3751 | 3760 |
3752 Bind(&unimplemented_elements_kind); | 3761 Bind(&unimplemented_elements_kind); |
3753 { | 3762 { |
3754 // Smi handlers should only be installed for supported elements kinds. | 3763 // Smi handlers should only be installed for supported elements kinds. |
3755 // Crash if we get here. | 3764 // Crash if we get here. |
3756 DebugBreak(); | 3765 DebugBreak(); |
3757 Goto(miss); | 3766 Goto(miss); |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3929 Bind(&miss); | 3938 Bind(&miss); |
3930 { | 3939 { |
3931 Comment("KeyedLoadIC_miss"); | 3940 Comment("KeyedLoadIC_miss"); |
3932 TailCallRuntime(Runtime::kKeyedLoadIC_Miss, p->context, p->receiver, | 3941 TailCallRuntime(Runtime::kKeyedLoadIC_Miss, p->context, p->receiver, |
3933 p->name, p->slot, p->vector); | 3942 p->name, p->slot, p->vector); |
3934 } | 3943 } |
3935 } | 3944 } |
3936 | 3945 |
3937 void CodeStubAssembler::KeyedLoadICGeneric(const LoadICParameters* p) { | 3946 void CodeStubAssembler::KeyedLoadICGeneric(const LoadICParameters* p) { |
3938 Variable var_index(this, MachineType::PointerRepresentation()); | 3947 Variable var_index(this, MachineType::PointerRepresentation()); |
3939 Label if_index(this), if_key_is_not_number(this), if_index_name(this), | 3948 Label if_index(this), if_unique_name(this), if_element_hole(this), |
3940 if_unique_name(this), if_element_hole(this), if_oob(this), slow(this), | 3949 if_oob(this), slow(this), stub_cache_miss(this), |
3941 stub_cache_miss(this), if_property_dictionary(this); | 3950 if_property_dictionary(this); |
3942 | 3951 |
3943 Node* receiver = p->receiver; | 3952 Node* receiver = p->receiver; |
3944 GotoIf(WordIsSmi(receiver), &slow); | 3953 GotoIf(WordIsSmi(receiver), &slow); |
3945 Node* receiver_map = LoadMap(receiver); | 3954 Node* receiver_map = LoadMap(receiver); |
3946 Node* instance_type = LoadMapInstanceType(receiver_map); | 3955 Node* instance_type = LoadMapInstanceType(receiver_map); |
3947 // Receivers requiring non-standard element accesses (interceptors, access | 3956 // Receivers requiring non-standard element accesses (interceptors, access |
3948 // checks, strings and string wrappers, proxies) are handled in the runtime. | 3957 // checks, strings and string wrappers, proxies) are handled in the runtime. |
3949 GotoIf(Int32LessThanOrEqual(instance_type, | 3958 GotoIf(Int32LessThanOrEqual(instance_type, |
3950 Int32Constant(LAST_CUSTOM_ELEMENTS_RECEIVER)), | 3959 Int32Constant(LAST_CUSTOM_ELEMENTS_RECEIVER)), |
3951 &slow); | 3960 &slow); |
3952 | 3961 |
3953 // Check what kind of key we have. | |
3954 Node* key = p->name; | 3962 Node* key = p->name; |
3955 var_index.Bind(TryToIntptr(key, &if_key_is_not_number)); | 3963 TryToName(key, &if_index, &var_index, &if_unique_name, &slow); |
3956 Goto(&if_index); | |
3957 | |
3958 Node* hash = nullptr; | |
3959 // TODO(jkummerow): Unify this with CodeStubAssembler::TryToName(). | |
3960 Bind(&if_key_is_not_number); | |
3961 { | |
3962 Node* key_map = LoadMap(key); | |
3963 Node* key_instance_type = LoadMapInstanceType(key_map); | |
3964 // Jump to the runtime if key is neither String nor Symbol. | |
3965 GotoIf(Int32GreaterThan(key_instance_type, | |
3966 Int32Constant(LAST_UNIQUE_NAME_TYPE)), | |
3967 &slow); | |
3968 // Symbols are always unique names. | |
3969 GotoIf(Word32Equal(key_instance_type, Int32Constant(LAST_UNIQUE_NAME_TYPE)), | |
3970 &if_unique_name); | |
3971 // |key| is a String. Check if it has a cached array index. | |
3972 hash = LoadNameHashField(key); | |
3973 Node* contains_index = | |
3974 Word32And(hash, Int32Constant(Name::kContainsCachedArrayIndexMask)); | |
3975 GotoIf(Word32Equal(contains_index, Int32Constant(0)), &if_index_name); | |
3976 // Otherwise, jump to the runtime if the string is not internalized. | |
3977 STATIC_ASSERT(kNotInternalizedTag != 0); | |
3978 Node* not_internalized = | |
3979 Word32And(key_instance_type, Int32Constant(kIsNotInternalizedMask)); | |
3980 GotoIf(Word32NotEqual(not_internalized, Int32Constant(0)), &slow); | |
3981 Goto(&if_unique_name); | |
3982 } | |
3983 | |
3984 Bind(&if_index_name); | |
3985 { | |
3986 Comment("string key with cached array index"); | |
3987 var_index.Bind(BitFieldDecode<String::ArrayIndexValueBits>(hash)); | |
3988 Goto(&if_index); | |
3989 } | |
3990 | 3964 |
3991 Bind(&if_index); | 3965 Bind(&if_index); |
3992 { | 3966 { |
3993 Comment("integer index"); | 3967 Comment("integer index"); |
3994 Node* index = var_index.value(); | 3968 Node* index = var_index.value(); |
3995 Node* elements = LoadElements(receiver); | 3969 Node* elements = LoadElements(receiver); |
3996 Node* bitfield2 = LoadMapBitField2(receiver_map); | 3970 Node* bitfield2 = LoadMapBitField2(receiver_map); |
3997 Node* elements_kind = BitFieldDecode<Map::ElementsKindBits>(bitfield2); | 3971 Node* elements_kind = BitFieldDecode<Map::ElementsKindBits>(bitfield2); |
3998 Node* is_jsarray_condition = | 3972 Node* is_jsarray_condition = |
3999 Word32Equal(instance_type, Int32Constant(JS_ARRAY_TYPE)); | 3973 Word32Equal(instance_type, Int32Constant(JS_ARRAY_TYPE)); |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4212 Heap::kTheHoleValueRootIndex); | 4186 Heap::kTheHoleValueRootIndex); |
4213 | 4187 |
4214 // Store the WeakCell in the feedback vector. | 4188 // Store the WeakCell in the feedback vector. |
4215 StoreFixedArrayElement(feedback_vector, slot, cell, UPDATE_WRITE_BARRIER, | 4189 StoreFixedArrayElement(feedback_vector, slot, cell, UPDATE_WRITE_BARRIER, |
4216 CodeStubAssembler::SMI_PARAMETERS); | 4190 CodeStubAssembler::SMI_PARAMETERS); |
4217 return cell; | 4191 return cell; |
4218 } | 4192 } |
4219 | 4193 |
4220 } // namespace internal | 4194 } // namespace internal |
4221 } // namespace v8 | 4195 } // namespace v8 |
OLD | NEW |