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 2238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2249 } | 2249 } |
2250 } | 2250 } |
2251 | 2251 |
2252 void CodeStubAssembler::Use(Label* label) { | 2252 void CodeStubAssembler::Use(Label* label) { |
2253 GotoIf(Word32Equal(Int32Constant(0), Int32Constant(1)), label); | 2253 GotoIf(Word32Equal(Int32Constant(0), Int32Constant(1)), label); |
2254 } | 2254 } |
2255 | 2255 |
2256 void CodeStubAssembler::TryToName(Node* key, Label* if_keyisindex, | 2256 void CodeStubAssembler::TryToName(Node* key, Label* if_keyisindex, |
2257 Variable* var_index, Label* if_keyisunique, | 2257 Variable* var_index, Label* if_keyisunique, |
2258 Label* if_bailout) { | 2258 Label* if_bailout) { |
2259 DCHECK_EQ(MachineRepresentation::kWord32, var_index->rep()); | 2259 DCHECK_EQ(MachineType::PointerRepresentation(), var_index->rep()); |
2260 Comment("TryToName"); | 2260 Comment("TryToName"); |
2261 | 2261 |
2262 Label if_keyissmi(this), if_keyisnotsmi(this); | 2262 Label if_hascachedindex(this), if_keyisnotindex(this); |
2263 Branch(WordIsSmi(key), &if_keyissmi, &if_keyisnotsmi); | 2263 // Handle Smi and HeapNumber keys. |
2264 Bind(&if_keyissmi); | 2264 var_index->Bind(TryToIntptr(key, &if_keyisnotindex)); |
2265 { | 2265 Goto(if_keyisindex); |
2266 // Negative smi keys are named properties. Handle in the runtime. | |
2267 GotoUnless(WordIsPositiveSmi(key), if_bailout); | |
2268 | 2266 |
2269 var_index->Bind(SmiToWord32(key)); | 2267 Bind(&if_keyisnotindex); |
2270 Goto(if_keyisindex); | |
2271 } | |
2272 | |
2273 Bind(&if_keyisnotsmi); | |
2274 | |
2275 Node* key_instance_type = LoadInstanceType(key); | 2268 Node* key_instance_type = LoadInstanceType(key); |
2276 // Symbols are unique. | 2269 // Symbols are unique. |
2277 GotoIf(Word32Equal(key_instance_type, Int32Constant(SYMBOL_TYPE)), | 2270 GotoIf(Word32Equal(key_instance_type, Int32Constant(SYMBOL_TYPE)), |
2278 if_keyisunique); | 2271 if_keyisunique); |
2272 // Miss if |key| is not a String. | |
2273 GotoIf( | |
2274 Int32GreaterThan(key_instance_type, Int32Constant(LAST_UNIQUE_NAME_TYPE)), | |
Igor Sheludko
2016/09/01 14:31:30
It looks like we are missing FIRST_STRING_TYPE and
Jakob Kummerow
2016/09/05 13:15:54
Done.
| |
2275 if_bailout); | |
2276 // |key| is a String. Check if it has a cached array index. | |
2277 Node* hash = LoadNameHashField(key); | |
2278 Node* contains_index = | |
2279 Word32And(hash, Int32Constant(Name::kContainsCachedArrayIndexMask)); | |
2280 GotoIf(Word32Equal(contains_index, Int32Constant(0)), &if_hascachedindex); | |
Igor Sheludko
2016/09/01 14:31:30
What if the hash field is not computed yet? We can
Igor Sheludko
2016/09/01 15:52:17
Ignore this comment. We set the hash field of a ne
Jakob Kummerow
2016/09/05 13:15:54
Acknowledged. It's also what the handwritten Keyed
| |
2281 // No cached array index; check if |key| is internalized. | |
2282 STATIC_ASSERT(kNotInternalizedTag != 0); | |
2283 Node* not_internalized = | |
2284 Word32And(key_instance_type, Int32Constant(kIsNotInternalizedMask)); | |
2285 GotoIf(Word32NotEqual(not_internalized, Int32Constant(0)), if_bailout); | |
2286 Goto(if_keyisunique); | |
2279 | 2287 |
2280 Label if_keyisinternalized(this); | 2288 Bind(&if_hascachedindex); |
2281 Node* bits = | |
2282 WordAnd(key_instance_type, | |
2283 Int32Constant(kIsNotStringMask | kIsNotInternalizedMask)); | |
2284 Branch(Word32Equal(bits, Int32Constant(kStringTag | kInternalizedTag)), | |
2285 &if_keyisinternalized, if_bailout); | |
2286 Bind(&if_keyisinternalized); | |
2287 | |
2288 // Check whether the key is an array index passed in as string. Handle | |
2289 // uniform with smi keys if so. | |
2290 // TODO(verwaest): Also support non-internalized strings. | |
2291 Node* hash = LoadNameHashField(key); | |
2292 Node* bit = Word32And(hash, Int32Constant(Name::kIsNotArrayIndexMask)); | |
2293 GotoIf(Word32NotEqual(bit, Int32Constant(0)), if_keyisunique); | |
2294 // Key is an index. Check if it is small enough to be encoded in the | |
2295 // hash_field. Handle too big array index in runtime. | |
2296 bit = Word32And(hash, Int32Constant(Name::kContainsCachedArrayIndexMask)); | |
2297 GotoIf(Word32NotEqual(bit, Int32Constant(0)), if_bailout); | |
2298 var_index->Bind(BitFieldDecode<Name::ArrayIndexValueBits>(hash)); | 2289 var_index->Bind(BitFieldDecode<Name::ArrayIndexValueBits>(hash)); |
2299 Goto(if_keyisindex); | 2290 Goto(if_keyisindex); |
2300 } | 2291 } |
2301 | 2292 |
2302 template <typename Dictionary> | 2293 template <typename Dictionary> |
2303 Node* CodeStubAssembler::EntryToIndex(Node* entry, int field_index) { | 2294 Node* CodeStubAssembler::EntryToIndex(Node* entry, int field_index) { |
2304 Node* entry_index = Int32Mul(entry, Int32Constant(Dictionary::kEntrySize)); | 2295 Node* entry_index = Int32Mul(entry, Int32Constant(Dictionary::kEntrySize)); |
2305 return Int32Add(entry_index, | 2296 return Int32Add(entry_index, |
2306 Int32Constant(Dictionary::kElementsStartIndex + field_index)); | 2297 Int32Constant(Dictionary::kElementsStartIndex + field_index)); |
2307 } | 2298 } |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2381 Word32Shl(hash, Int32Constant(15))); | 2372 Word32Shl(hash, Int32Constant(15))); |
2382 hash = Word32Xor(hash, Word32Shr(hash, Int32Constant(12))); | 2373 hash = Word32Xor(hash, Word32Shr(hash, Int32Constant(12))); |
2383 hash = Int32Add(hash, Word32Shl(hash, Int32Constant(2))); | 2374 hash = Int32Add(hash, Word32Shl(hash, Int32Constant(2))); |
2384 hash = Word32Xor(hash, Word32Shr(hash, Int32Constant(4))); | 2375 hash = Word32Xor(hash, Word32Shr(hash, Int32Constant(4))); |
2385 hash = Int32Mul(hash, Int32Constant(2057)); | 2376 hash = Int32Mul(hash, Int32Constant(2057)); |
2386 hash = Word32Xor(hash, Word32Shr(hash, Int32Constant(16))); | 2377 hash = Word32Xor(hash, Word32Shr(hash, Int32Constant(16))); |
2387 return Word32And(hash, Int32Constant(0x3fffffff)); | 2378 return Word32And(hash, Int32Constant(0x3fffffff)); |
2388 } | 2379 } |
2389 | 2380 |
2390 template <typename Dictionary> | 2381 template <typename Dictionary> |
2391 void CodeStubAssembler::NumberDictionaryLookup(Node* dictionary, Node* key, | 2382 void CodeStubAssembler::NumberDictionaryLookup(Node* dictionary, Node* key, |
Igor Sheludko
2016/09/01 14:31:30
Please rename |key| -> |intptr_index| for readabil
Jakob Kummerow
2016/09/05 13:15:54
Done.
| |
2392 Label* if_found, | 2383 Label* if_found, |
2393 Variable* var_entry, | 2384 Variable* var_entry, |
2394 Label* if_not_found) { | 2385 Label* if_not_found) { |
2395 DCHECK_EQ(MachineRepresentation::kWord32, var_entry->rep()); | 2386 DCHECK_EQ(MachineRepresentation::kWord32, var_entry->rep()); |
2396 Comment("NumberDictionaryLookup"); | 2387 Comment("NumberDictionaryLookup"); |
2397 | 2388 |
2398 Node* capacity = LoadAndUntagToWord32FixedArrayElement( | 2389 Node* capacity = LoadAndUntagToWord32FixedArrayElement( |
2399 dictionary, Int32Constant(Dictionary::kCapacityIndex)); | 2390 dictionary, Int32Constant(Dictionary::kCapacityIndex)); |
2400 Node* mask = Int32Sub(capacity, Int32Constant(1)); | 2391 Node* mask = Int32Sub(capacity, Int32Constant(1)); |
2401 | 2392 |
2402 Node* seed; | 2393 Node* seed; |
2403 if (Dictionary::ShapeT::UsesSeed) { | 2394 if (Dictionary::ShapeT::UsesSeed) { |
2404 seed = HashSeed(); | 2395 seed = HashSeed(); |
2405 } else { | 2396 } else { |
2406 seed = Int32Constant(kZeroHashSeed); | 2397 seed = Int32Constant(kZeroHashSeed); |
2407 } | 2398 } |
2408 Node* hash = ComputeIntegerHash(key, seed); | 2399 Node* hash = ComputeIntegerHash(key, seed); |
2409 Node* key_as_float64 = ChangeUint32ToFloat64(key); | 2400 Node* key_as_float64 = RoundIntPtrToFloat64(key); |
2410 | 2401 |
2411 // See Dictionary::FirstProbe(). | 2402 // See Dictionary::FirstProbe(). |
2412 Node* count = Int32Constant(0); | 2403 Node* count = Int32Constant(0); |
2413 Node* entry = Word32And(hash, mask); | 2404 Node* entry = Word32And(hash, mask); |
2414 | 2405 |
2415 Node* undefined = UndefinedConstant(); | 2406 Node* undefined = UndefinedConstant(); |
2416 Node* the_hole = TheHoleConstant(); | 2407 Node* the_hole = TheHoleConstant(); |
2417 | 2408 |
2418 Variable var_count(this, MachineRepresentation::kWord32); | 2409 Variable var_count(this, MachineRepresentation::kWord32); |
2419 Variable* loop_vars[] = {&var_count, var_entry}; | 2410 Variable* loop_vars[] = {&var_count, var_entry}; |
2420 Label loop(this, 2, loop_vars); | 2411 Label loop(this, 2, loop_vars); |
2421 var_count.Bind(count); | 2412 var_count.Bind(count); |
2422 var_entry->Bind(entry); | 2413 var_entry->Bind(entry); |
2423 Goto(&loop); | 2414 Goto(&loop); |
2424 Bind(&loop); | 2415 Bind(&loop); |
2425 { | 2416 { |
2426 Node* count = var_count.value(); | 2417 Node* count = var_count.value(); |
2427 Node* entry = var_entry->value(); | 2418 Node* entry = var_entry->value(); |
2428 | 2419 |
2429 Node* index = EntryToIndex<Dictionary>(entry); | 2420 Node* index = EntryToIndex<Dictionary>(entry); |
2430 Node* current = LoadFixedArrayElement(dictionary, index); | 2421 Node* current = LoadFixedArrayElement(dictionary, index); |
2431 GotoIf(WordEqual(current, undefined), if_not_found); | 2422 GotoIf(WordEqual(current, undefined), if_not_found); |
2432 Label next_probe(this); | 2423 Label next_probe(this); |
2433 { | 2424 { |
2434 Label if_currentissmi(this), if_currentisnotsmi(this); | 2425 Label if_currentissmi(this), if_currentisnotsmi(this); |
2435 Branch(WordIsSmi(current), &if_currentissmi, &if_currentisnotsmi); | 2426 Branch(WordIsSmi(current), &if_currentissmi, &if_currentisnotsmi); |
2436 Bind(&if_currentissmi); | 2427 Bind(&if_currentissmi); |
2437 { | 2428 { |
2438 Node* current_value = SmiToWord32(current); | 2429 Node* current_value = SmiUntag(current); |
2439 Branch(Word32Equal(current_value, key), if_found, &next_probe); | 2430 Branch(WordEqual(current_value, key), if_found, &next_probe); |
2440 } | 2431 } |
2441 Bind(&if_currentisnotsmi); | 2432 Bind(&if_currentisnotsmi); |
2442 { | 2433 { |
2443 GotoIf(WordEqual(current, the_hole), &next_probe); | 2434 GotoIf(WordEqual(current, the_hole), &next_probe); |
2444 // Current must be the Number. | 2435 // Current must be the Number. |
2445 Node* current_value = LoadHeapNumberValue(current); | 2436 Node* current_value = LoadHeapNumberValue(current); |
2446 Branch(Float64Equal(current_value, key_as_float64), if_found, | 2437 Branch(Float64Equal(current_value, key_as_float64), if_found, |
2447 &next_probe); | 2438 &next_probe); |
2448 } | 2439 } |
2449 } | 2440 } |
(...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2809 // Call the accessor. | 2800 // Call the accessor. |
2810 Callable callable = CodeFactory::Call(isolate()); | 2801 Callable callable = CodeFactory::Call(isolate()); |
2811 Node* result = CallJS(callable, context, getter, receiver); | 2802 Node* result = CallJS(callable, context, getter, receiver); |
2812 var_value->Bind(result); | 2803 var_value->Bind(result); |
2813 Goto(if_found_value); | 2804 Goto(if_found_value); |
2814 } | 2805 } |
2815 } | 2806 } |
2816 } | 2807 } |
2817 | 2808 |
2818 void CodeStubAssembler::TryLookupElement(Node* object, Node* map, | 2809 void CodeStubAssembler::TryLookupElement(Node* object, Node* map, |
2819 Node* instance_type, Node* index, | 2810 Node* instance_type, Node* index, |
Igor Sheludko
2016/09/01 14:31:30
Please rename |index| -> |intptr_index| for readab
Jakob Kummerow
2016/09/05 13:15:53
Done.
| |
2820 Label* if_found, Label* if_not_found, | 2811 Label* if_found, Label* if_not_found, |
2821 Label* if_bailout) { | 2812 Label* if_bailout) { |
2822 // Handle special objects in runtime. | 2813 // Handle special objects in runtime. |
2823 GotoIf(Int32LessThanOrEqual(instance_type, | 2814 GotoIf(Int32LessThanOrEqual(instance_type, |
2824 Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)), | 2815 Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)), |
2825 if_bailout); | 2816 if_bailout); |
2826 | 2817 |
2827 Node* bit_field2 = LoadMapBitField2(map); | 2818 Node* bit_field2 = LoadMapBitField2(map); |
2828 Node* elements_kind = BitFieldDecode<Map::ElementsKindBits>(bit_field2); | 2819 Node* elements_kind = BitFieldDecode<Map::ElementsKindBits>(bit_field2); |
2829 | 2820 |
2830 // TODO(verwaest): Support other elements kinds as well. | 2821 // TODO(verwaest): Support other elements kinds as well. |
2831 Label if_isobjectorsmi(this), if_isdouble(this), if_isdictionary(this), | 2822 Label if_isobjectorsmi(this), if_isdouble(this), if_isdictionary(this), |
2832 if_isfaststringwrapper(this), if_isslowstringwrapper(this); | 2823 if_isfaststringwrapper(this), if_isslowstringwrapper(this), if_oob(this); |
2833 // clang-format off | 2824 // clang-format off |
2834 int32_t values[] = { | 2825 int32_t values[] = { |
2835 // Handled by {if_isobjectorsmi}. | 2826 // Handled by {if_isobjectorsmi}. |
2836 FAST_SMI_ELEMENTS, FAST_HOLEY_SMI_ELEMENTS, FAST_ELEMENTS, | 2827 FAST_SMI_ELEMENTS, FAST_HOLEY_SMI_ELEMENTS, FAST_ELEMENTS, |
2837 FAST_HOLEY_ELEMENTS, | 2828 FAST_HOLEY_ELEMENTS, |
2838 // Handled by {if_isdouble}. | 2829 // Handled by {if_isdouble}. |
2839 FAST_DOUBLE_ELEMENTS, FAST_HOLEY_DOUBLE_ELEMENTS, | 2830 FAST_DOUBLE_ELEMENTS, FAST_HOLEY_DOUBLE_ELEMENTS, |
2840 // Handled by {if_isdictionary}. | 2831 // Handled by {if_isdictionary}. |
2841 DICTIONARY_ELEMENTS, | 2832 DICTIONARY_ELEMENTS, |
2842 // Handled by {if_isfaststringwrapper}. | 2833 // Handled by {if_isfaststringwrapper}. |
(...skipping 14 matching lines...) Expand all Loading... | |
2857 }; | 2848 }; |
2858 // clang-format on | 2849 // clang-format on |
2859 STATIC_ASSERT(arraysize(values) == arraysize(labels)); | 2850 STATIC_ASSERT(arraysize(values) == arraysize(labels)); |
2860 Switch(elements_kind, if_bailout, values, labels, arraysize(values)); | 2851 Switch(elements_kind, if_bailout, values, labels, arraysize(values)); |
2861 | 2852 |
2862 Bind(&if_isobjectorsmi); | 2853 Bind(&if_isobjectorsmi); |
2863 { | 2854 { |
2864 Node* elements = LoadElements(object); | 2855 Node* elements = LoadElements(object); |
2865 Node* length = LoadAndUntagFixedArrayBaseLength(elements); | 2856 Node* length = LoadAndUntagFixedArrayBaseLength(elements); |
2866 | 2857 |
2867 GotoUnless(Uint32LessThan(index, length), if_not_found); | 2858 GotoUnless(UintPtrLessThan(index, length), &if_oob); |
2868 | 2859 |
2869 Node* element = LoadFixedArrayElement(elements, index); | 2860 Node* element = |
2861 LoadFixedArrayElement(elements, index, 0, INTPTR_PARAMETERS); | |
2870 Node* the_hole = TheHoleConstant(); | 2862 Node* the_hole = TheHoleConstant(); |
2871 Branch(WordEqual(element, the_hole), if_not_found, if_found); | 2863 Branch(WordEqual(element, the_hole), if_not_found, if_found); |
2872 } | 2864 } |
2873 Bind(&if_isdouble); | 2865 Bind(&if_isdouble); |
2874 { | 2866 { |
2875 Node* elements = LoadElements(object); | 2867 Node* elements = LoadElements(object); |
2876 Node* length = LoadAndUntagFixedArrayBaseLength(elements); | 2868 Node* length = LoadAndUntagFixedArrayBaseLength(elements); |
2877 | 2869 |
2878 GotoUnless(Uint32LessThan(index, length), if_not_found); | 2870 GotoUnless(UintPtrLessThan(index, length), &if_oob); |
2879 | 2871 |
2880 if (kPointerSize == kDoubleSize) { | 2872 if (kPointerSize == kDoubleSize) { |
2881 Node* element = | 2873 Node* element = LoadFixedDoubleArrayElement( |
2882 LoadFixedDoubleArrayElement(elements, index, MachineType::Uint64()); | 2874 elements, index, MachineType::Uint64(), 0, INTPTR_PARAMETERS); |
2883 Node* the_hole = Int64Constant(kHoleNanInt64); | 2875 Node* the_hole = Int64Constant(kHoleNanInt64); |
2884 Branch(Word64Equal(element, the_hole), if_not_found, if_found); | 2876 Branch(Word64Equal(element, the_hole), if_not_found, if_found); |
2885 } else { | 2877 } else { |
2886 Node* element_upper = | 2878 Node* element_upper = LoadFixedDoubleArrayElement( |
2887 LoadFixedDoubleArrayElement(elements, index, MachineType::Uint32(), | 2879 elements, index, MachineType::Uint32(), kIeeeDoubleExponentWordOffset, |
2888 kIeeeDoubleExponentWordOffset); | 2880 INTPTR_PARAMETERS); |
2889 Branch(Word32Equal(element_upper, Int32Constant(kHoleNanUpper32)), | 2881 Branch(Word32Equal(element_upper, Int32Constant(kHoleNanUpper32)), |
2890 if_not_found, if_found); | 2882 if_not_found, if_found); |
2891 } | 2883 } |
2892 } | 2884 } |
2893 Bind(&if_isdictionary); | 2885 Bind(&if_isdictionary); |
2894 { | 2886 { |
2895 Variable var_entry(this, MachineRepresentation::kWord32); | 2887 Variable var_entry(this, MachineRepresentation::kWord32); |
2896 Node* elements = LoadElements(object); | 2888 Node* elements = LoadElements(object); |
2897 NumberDictionaryLookup<SeededNumberDictionary>(elements, index, if_found, | 2889 NumberDictionaryLookup<SeededNumberDictionary>(elements, index, if_found, |
2898 &var_entry, if_not_found); | 2890 &var_entry, if_not_found); |
2899 } | 2891 } |
2900 Bind(&if_isfaststringwrapper); | 2892 Bind(&if_isfaststringwrapper); |
2901 { | 2893 { |
2902 AssertInstanceType(object, JS_VALUE_TYPE); | 2894 AssertInstanceType(object, JS_VALUE_TYPE); |
2903 Node* string = LoadJSValueValue(object); | 2895 Node* string = LoadJSValueValue(object); |
2904 Assert(Int32LessThan(LoadInstanceType(string), | 2896 Assert(Int32LessThan(LoadInstanceType(string), |
2905 Int32Constant(FIRST_NONSTRING_TYPE))); | 2897 Int32Constant(FIRST_NONSTRING_TYPE))); |
2906 Node* length = LoadStringLength(string); | 2898 Node* length = LoadStringLength(string); |
2907 GotoIf(Uint32LessThan(index, SmiToWord32(length)), if_found); | 2899 GotoIf(UintPtrLessThan(index, SmiUntag(length)), if_found); |
2908 Goto(&if_isobjectorsmi); | 2900 Goto(&if_isobjectorsmi); |
2909 } | 2901 } |
2910 Bind(&if_isslowstringwrapper); | 2902 Bind(&if_isslowstringwrapper); |
2911 { | 2903 { |
2912 AssertInstanceType(object, JS_VALUE_TYPE); | 2904 AssertInstanceType(object, JS_VALUE_TYPE); |
2913 Node* string = LoadJSValueValue(object); | 2905 Node* string = LoadJSValueValue(object); |
2914 Assert(Int32LessThan(LoadInstanceType(string), | 2906 Assert(Int32LessThan(LoadInstanceType(string), |
2915 Int32Constant(FIRST_NONSTRING_TYPE))); | 2907 Int32Constant(FIRST_NONSTRING_TYPE))); |
2916 Node* length = LoadStringLength(string); | 2908 Node* length = LoadStringLength(string); |
2917 GotoIf(Uint32LessThan(index, SmiToWord32(length)), if_found); | 2909 GotoIf(UintPtrLessThan(index, SmiUntag(length)), if_found); |
2918 Goto(&if_isdictionary); | 2910 Goto(&if_isdictionary); |
2919 } | 2911 } |
2912 Bind(&if_oob); | |
2913 { | |
2914 // Positive OOB indices mean "not found", negative indices must be | |
2915 // converted to property names. | |
2916 GotoIf(IntPtrLessThan(index, IntPtrConstant(0)), if_bailout); | |
2917 Goto(if_not_found); | |
2918 } | |
2920 } | 2919 } |
2921 | 2920 |
2922 // Instantiate template methods to workaround GCC compilation issue. | 2921 // Instantiate template methods to workaround GCC compilation issue. |
2923 template void CodeStubAssembler::NumberDictionaryLookup<SeededNumberDictionary>( | 2922 template void CodeStubAssembler::NumberDictionaryLookup<SeededNumberDictionary>( |
2924 Node*, Node*, Label*, Variable*, Label*); | 2923 Node*, Node*, Label*, Variable*, Label*); |
2925 template void CodeStubAssembler::NumberDictionaryLookup< | 2924 template void CodeStubAssembler::NumberDictionaryLookup< |
2926 UnseededNumberDictionary>(Node*, Node*, Label*, Variable*, Label*); | 2925 UnseededNumberDictionary>(Node*, Node*, Label*, Variable*, Label*); |
2927 | 2926 |
2928 void CodeStubAssembler::TryPrototypeChainLookup( | 2927 void CodeStubAssembler::TryPrototypeChainLookup( |
2929 Node* receiver, Node* key, LookupInHolder& lookup_property_in_holder, | 2928 Node* receiver, Node* key, LookupInHolder& lookup_property_in_holder, |
2930 LookupInHolder& lookup_element_in_holder, Label* if_end, | 2929 LookupInHolder& lookup_element_in_holder, Label* if_end, |
2931 Label* if_bailout) { | 2930 Label* if_bailout) { |
2932 // Ensure receiver is JSReceiver, otherwise bailout. | 2931 // Ensure receiver is JSReceiver, otherwise bailout. |
2933 Label if_objectisnotsmi(this); | 2932 Label if_objectisnotsmi(this); |
2934 Branch(WordIsSmi(receiver), if_bailout, &if_objectisnotsmi); | 2933 Branch(WordIsSmi(receiver), if_bailout, &if_objectisnotsmi); |
2935 Bind(&if_objectisnotsmi); | 2934 Bind(&if_objectisnotsmi); |
2936 | 2935 |
2937 Node* map = LoadMap(receiver); | 2936 Node* map = LoadMap(receiver); |
2938 Node* instance_type = LoadMapInstanceType(map); | 2937 Node* instance_type = LoadMapInstanceType(map); |
2939 { | 2938 { |
2940 Label if_objectisreceiver(this); | 2939 Label if_objectisreceiver(this); |
2941 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); | 2940 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); |
2942 STATIC_ASSERT(FIRST_JS_RECEIVER_TYPE == JS_PROXY_TYPE); | 2941 STATIC_ASSERT(FIRST_JS_RECEIVER_TYPE == JS_PROXY_TYPE); |
2943 Branch( | 2942 Branch( |
2944 Int32GreaterThan(instance_type, Int32Constant(FIRST_JS_RECEIVER_TYPE)), | 2943 Int32GreaterThan(instance_type, Int32Constant(FIRST_JS_RECEIVER_TYPE)), |
2945 &if_objectisreceiver, if_bailout); | 2944 &if_objectisreceiver, if_bailout); |
2946 Bind(&if_objectisreceiver); | 2945 Bind(&if_objectisreceiver); |
2947 } | 2946 } |
2948 | 2947 |
2949 Variable var_index(this, MachineRepresentation::kWord32); | 2948 Variable var_index(this, MachineType::PointerRepresentation()); |
2950 | 2949 |
2951 Label if_keyisindex(this), if_iskeyunique(this); | 2950 Label if_keyisindex(this), if_iskeyunique(this); |
2952 TryToName(key, &if_keyisindex, &var_index, &if_iskeyunique, if_bailout); | 2951 TryToName(key, &if_keyisindex, &var_index, &if_iskeyunique, if_bailout); |
2953 | 2952 |
2954 Bind(&if_iskeyunique); | 2953 Bind(&if_iskeyunique); |
2955 { | 2954 { |
2956 Variable var_holder(this, MachineRepresentation::kTagged); | 2955 Variable var_holder(this, MachineRepresentation::kTagged); |
2957 Variable var_holder_map(this, MachineRepresentation::kTagged); | 2956 Variable var_holder_map(this, MachineRepresentation::kTagged); |
2958 Variable var_holder_instance_type(this, MachineRepresentation::kWord8); | 2957 Variable var_holder_instance_type(this, MachineRepresentation::kWord8); |
2959 | 2958 |
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3171 } | 3170 } |
3172 | 3171 |
3173 compiler::Node* CodeStubAssembler::ElementOffsetFromIndex(Node* index_node, | 3172 compiler::Node* CodeStubAssembler::ElementOffsetFromIndex(Node* index_node, |
3174 ElementsKind kind, | 3173 ElementsKind kind, |
3175 ParameterMode mode, | 3174 ParameterMode mode, |
3176 int base_size) { | 3175 int base_size) { |
3177 bool is_double = IsFastDoubleElementsKind(kind); | 3176 bool is_double = IsFastDoubleElementsKind(kind); |
3178 int element_size_shift = is_double ? kDoubleSizeLog2 : kPointerSizeLog2; | 3177 int element_size_shift = is_double ? kDoubleSizeLog2 : kPointerSizeLog2; |
3179 int element_size = 1 << element_size_shift; | 3178 int element_size = 1 << element_size_shift; |
3180 int const kSmiShiftBits = kSmiShiftSize + kSmiTagSize; | 3179 int const kSmiShiftBits = kSmiShiftSize + kSmiTagSize; |
3181 int32_t index = 0; | 3180 intptr_t index = 0; |
3182 bool constant_index = false; | 3181 bool constant_index = false; |
3183 if (mode == SMI_PARAMETERS) { | 3182 if (mode == SMI_PARAMETERS) { |
3184 element_size_shift -= kSmiShiftBits; | 3183 element_size_shift -= kSmiShiftBits; |
3185 intptr_t temp = 0; | 3184 constant_index = ToIntPtrConstant(index_node, index); |
3186 constant_index = ToIntPtrConstant(index_node, temp); | 3185 index = index >> kSmiShiftBits; |
3187 index = temp >> kSmiShiftBits; | 3186 } else if (mode == INTEGER_PARAMETERS) { |
3187 int32_t temp = 0; | |
3188 constant_index = ToInt32Constant(index_node, temp); | |
3189 index = static_cast<intptr_t>(temp); | |
3188 } else { | 3190 } else { |
3189 constant_index = ToInt32Constant(index_node, index); | 3191 DCHECK(mode == INTPTR_PARAMETERS); |
3192 constant_index = ToIntPtrConstant(index_node, index); | |
3190 } | 3193 } |
3191 if (constant_index) { | 3194 if (constant_index) { |
3192 return IntPtrConstant(base_size + element_size * index); | 3195 return IntPtrConstant(base_size + element_size * index); |
3193 } | 3196 } |
3194 if (Is64() && mode == INTEGER_PARAMETERS) { | 3197 if (Is64() && mode == INTEGER_PARAMETERS) { |
3195 index_node = ChangeInt32ToInt64(index_node); | 3198 index_node = ChangeInt32ToInt64(index_node); |
3196 } | 3199 } |
3197 if (base_size == 0) { | 3200 if (base_size == 0) { |
3198 return (element_size_shift >= 0) | 3201 return (element_size_shift >= 0) |
3199 ? WordShl(index_node, IntPtrConstant(element_size_shift)) | 3202 ? WordShl(index_node, IntPtrConstant(element_size_shift)) |
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3494 } | 3497 } |
3495 Bind(&if_array); | 3498 Bind(&if_array); |
3496 { | 3499 { |
3497 var_length.Bind(SmiUntag(LoadObjectField(object, JSArray::kLengthOffset))); | 3500 var_length.Bind(SmiUntag(LoadObjectField(object, JSArray::kLengthOffset))); |
3498 Goto(&length_loaded); | 3501 Goto(&length_loaded); |
3499 } | 3502 } |
3500 Bind(&length_loaded); | 3503 Bind(&length_loaded); |
3501 GotoUnless(UintPtrLessThan(intptr_key, var_length.value()), miss); | 3504 GotoUnless(UintPtrLessThan(intptr_key, var_length.value()), miss); |
3502 } | 3505 } |
3503 | 3506 |
3504 // |key| should be untagged (int32). | 3507 // |key| should be untagged (int32). |
Igor Sheludko
2016/09/01 14:31:30
How about renaming |key| to |intptr_index| for rea
Jakob Kummerow
2016/09/05 13:15:53
Done.
| |
3505 void CodeStubAssembler::EmitElementLoad(Node* object, Node* elements, | 3508 void CodeStubAssembler::EmitElementLoad(Node* object, Node* elements, |
3506 Node* elements_kind, Node* key, | 3509 Node* elements_kind, Node* key, |
3507 Node* is_jsarray_condition, | 3510 Node* is_jsarray_condition, |
3508 Label* if_hole, Label* rebox_double, | 3511 Label* if_hole, Label* rebox_double, |
3509 Variable* var_double_value, | 3512 Variable* var_double_value, |
3510 Label* unimplemented_elements_kind, | 3513 Label* unimplemented_elements_kind, |
3511 Label* out_of_bounds, Label* miss) { | 3514 Label* out_of_bounds, Label* miss) { |
3512 Label if_typed_array(this), if_fast_packed(this), if_fast_holey(this), | 3515 Label if_typed_array(this), if_fast_packed(this), if_fast_holey(this), |
3513 if_fast_double(this), if_fast_holey_double(this), if_nonfast(this), | 3516 if_fast_double(this), if_fast_holey_double(this), if_nonfast(this), |
3514 if_dictionary(this), unreachable(this); | 3517 if_dictionary(this), unreachable(this); |
(...skipping 18 matching lines...) Expand all Loading... | |
3533 // FAST_DOUBLE_ELEMENTS | 3536 // FAST_DOUBLE_ELEMENTS |
3534 &if_fast_double, | 3537 &if_fast_double, |
3535 // FAST_HOLEY_DOUBLE_ELEMENTS | 3538 // FAST_HOLEY_DOUBLE_ELEMENTS |
3536 &if_fast_holey_double}; | 3539 &if_fast_holey_double}; |
3537 Switch(elements_kind, unimplemented_elements_kind, kinds, labels, | 3540 Switch(elements_kind, unimplemented_elements_kind, kinds, labels, |
3538 arraysize(kinds)); | 3541 arraysize(kinds)); |
3539 | 3542 |
3540 Bind(&if_fast_packed); | 3543 Bind(&if_fast_packed); |
3541 { | 3544 { |
3542 Comment("fast packed elements"); | 3545 Comment("fast packed elements"); |
3543 // TODO(jkummerow): The Load*Element helpers add movsxlq instructions | 3546 Return(LoadFixedArrayElement(elements, key, 0, INTPTR_PARAMETERS)); |
3544 // on x64 which we don't need here, because |key| is an IntPtr already. | |
3545 // Do something about that. | |
3546 Return(LoadFixedArrayElement(elements, key)); | |
3547 } | 3547 } |
3548 | 3548 |
3549 Bind(&if_fast_holey); | 3549 Bind(&if_fast_holey); |
3550 { | 3550 { |
3551 Comment("fast holey elements"); | 3551 Comment("fast holey elements"); |
3552 Node* element = LoadFixedArrayElement(elements, key); | 3552 Node* element = LoadFixedArrayElement(elements, key, 0, INTPTR_PARAMETERS); |
3553 GotoIf(WordEqual(element, TheHoleConstant()), if_hole); | 3553 GotoIf(WordEqual(element, TheHoleConstant()), if_hole); |
3554 Return(element); | 3554 Return(element); |
3555 } | 3555 } |
3556 | 3556 |
3557 Bind(&if_fast_double); | 3557 Bind(&if_fast_double); |
3558 { | 3558 { |
3559 Comment("packed double elements"); | 3559 Comment("packed double elements"); |
3560 var_double_value->Bind( | 3560 var_double_value->Bind(LoadFixedDoubleArrayElement( |
3561 LoadFixedDoubleArrayElement(elements, key, MachineType::Float64())); | 3561 elements, key, MachineType::Float64(), 0, INTPTR_PARAMETERS)); |
3562 Goto(rebox_double); | 3562 Goto(rebox_double); |
3563 } | 3563 } |
3564 | 3564 |
3565 Bind(&if_fast_holey_double); | 3565 Bind(&if_fast_holey_double); |
3566 { | 3566 { |
3567 Comment("holey double elements"); | 3567 Comment("holey double elements"); |
3568 if (kPointerSize == kDoubleSize) { | 3568 if (kPointerSize == kDoubleSize) { |
3569 Node* raw_element = | 3569 Node* raw_element = LoadFixedDoubleArrayElement( |
3570 LoadFixedDoubleArrayElement(elements, key, MachineType::Uint64()); | 3570 elements, key, MachineType::Uint64(), 0, INTPTR_PARAMETERS); |
3571 Node* the_hole = Int64Constant(kHoleNanInt64); | 3571 Node* the_hole = Int64Constant(kHoleNanInt64); |
3572 GotoIf(Word64Equal(raw_element, the_hole), if_hole); | 3572 GotoIf(Word64Equal(raw_element, the_hole), if_hole); |
3573 } else { | 3573 } else { |
3574 Node* element_upper = LoadFixedDoubleArrayElement( | 3574 Node* element_upper = LoadFixedDoubleArrayElement( |
3575 elements, key, MachineType::Uint32(), kIeeeDoubleExponentWordOffset); | 3575 elements, key, MachineType::Uint32(), kIeeeDoubleExponentWordOffset, |
3576 INTPTR_PARAMETERS); | |
3576 GotoIf(Word32Equal(element_upper, Int32Constant(kHoleNanUpper32)), | 3577 GotoIf(Word32Equal(element_upper, Int32Constant(kHoleNanUpper32)), |
3577 if_hole); | 3578 if_hole); |
3578 } | 3579 } |
3579 var_double_value->Bind( | 3580 var_double_value->Bind(LoadFixedDoubleArrayElement( |
3580 LoadFixedDoubleArrayElement(elements, key, MachineType::Float64())); | 3581 elements, key, MachineType::Float64(), 0, INTPTR_PARAMETERS)); |
3581 Goto(rebox_double); | 3582 Goto(rebox_double); |
3582 } | 3583 } |
3583 | 3584 |
3584 Bind(&if_nonfast); | 3585 Bind(&if_nonfast); |
3585 { | 3586 { |
3586 STATIC_ASSERT(LAST_ELEMENTS_KIND == LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND); | 3587 STATIC_ASSERT(LAST_ELEMENTS_KIND == LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND); |
3587 GotoIf(IntPtrGreaterThanOrEqual( | 3588 GotoIf(IntPtrGreaterThanOrEqual( |
3588 elements_kind, | 3589 elements_kind, |
3589 IntPtrConstant(FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND)), | 3590 IntPtrConstant(FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND)), |
3590 &if_typed_array); | 3591 &if_typed_array); |
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3927 Bind(&miss); | 3928 Bind(&miss); |
3928 { | 3929 { |
3929 Comment("KeyedLoadIC_miss"); | 3930 Comment("KeyedLoadIC_miss"); |
3930 TailCallRuntime(Runtime::kKeyedLoadIC_Miss, p->context, p->receiver, | 3931 TailCallRuntime(Runtime::kKeyedLoadIC_Miss, p->context, p->receiver, |
3931 p->name, p->slot, p->vector); | 3932 p->name, p->slot, p->vector); |
3932 } | 3933 } |
3933 } | 3934 } |
3934 | 3935 |
3935 void CodeStubAssembler::KeyedLoadICGeneric(const LoadICParameters* p) { | 3936 void CodeStubAssembler::KeyedLoadICGeneric(const LoadICParameters* p) { |
3936 Variable var_index(this, MachineType::PointerRepresentation()); | 3937 Variable var_index(this, MachineType::PointerRepresentation()); |
3937 Label if_index(this), if_key_is_not_number(this), if_index_name(this), | 3938 Label if_index(this), if_unique_name(this), if_element_hole(this), |
3938 if_unique_name(this), if_element_hole(this), if_oob(this), slow(this), | 3939 if_oob(this), slow(this), stub_cache_miss(this), |
3939 stub_cache_miss(this), if_property_dictionary(this); | 3940 if_property_dictionary(this); |
3940 | 3941 |
3941 Node* receiver = p->receiver; | 3942 Node* receiver = p->receiver; |
3942 GotoIf(WordIsSmi(receiver), &slow); | 3943 GotoIf(WordIsSmi(receiver), &slow); |
3943 Node* receiver_map = LoadMap(receiver); | 3944 Node* receiver_map = LoadMap(receiver); |
3944 Node* instance_type = LoadMapInstanceType(receiver_map); | 3945 Node* instance_type = LoadMapInstanceType(receiver_map); |
3945 // Receivers requiring non-standard element accesses (interceptors, access | 3946 // Receivers requiring non-standard element accesses (interceptors, access |
3946 // checks, strings and string wrappers, proxies) are handled in the runtime. | 3947 // checks, strings and string wrappers, proxies) are handled in the runtime. |
3947 GotoIf(Int32LessThanOrEqual(instance_type, | 3948 GotoIf(Int32LessThanOrEqual(instance_type, |
3948 Int32Constant(LAST_CUSTOM_ELEMENTS_RECEIVER)), | 3949 Int32Constant(LAST_CUSTOM_ELEMENTS_RECEIVER)), |
3949 &slow); | 3950 &slow); |
3950 | 3951 |
3951 // Check what kind of key we have. | |
3952 Node* key = p->name; | 3952 Node* key = p->name; |
3953 var_index.Bind(TryToIntptr(key, &if_key_is_not_number)); | 3953 TryToName(key, &if_index, &var_index, &if_unique_name, &slow); |
3954 Goto(&if_index); | |
3955 | |
3956 Node* hash = nullptr; | |
3957 // TODO(jkummerow): Unify this with CodeStubAssembler::TryToName(). | |
3958 Bind(&if_key_is_not_number); | |
3959 { | |
3960 Node* key_map = LoadMap(key); | |
3961 Node* key_instance_type = LoadMapInstanceType(key_map); | |
3962 // Jump to the runtime if key is neither String nor Symbol. | |
3963 GotoIf(Int32GreaterThan(key_instance_type, | |
3964 Int32Constant(LAST_UNIQUE_NAME_TYPE)), | |
3965 &slow); | |
3966 // Symbols are always unique names. | |
3967 GotoIf(Word32Equal(key_instance_type, Int32Constant(LAST_UNIQUE_NAME_TYPE)), | |
3968 &if_unique_name); | |
3969 // |key| is a String. Check if it has a cached array index. | |
3970 hash = LoadNameHashField(key); | |
3971 Node* contains_index = | |
3972 Word32And(hash, Int32Constant(Name::kContainsCachedArrayIndexMask)); | |
3973 GotoIf(Word32Equal(contains_index, Int32Constant(0)), &if_index_name); | |
3974 // Otherwise, jump to the runtime if the string is not internalized. | |
3975 STATIC_ASSERT(kNotInternalizedTag != 0); | |
3976 Node* not_internalized = | |
3977 Word32And(key_instance_type, Int32Constant(kIsNotInternalizedMask)); | |
3978 GotoIf(Word32NotEqual(not_internalized, Int32Constant(0)), &slow); | |
3979 Goto(&if_unique_name); | |
3980 } | |
3981 | |
3982 Bind(&if_index_name); | |
3983 { | |
3984 Comment("string key with cached array index"); | |
3985 var_index.Bind(BitFieldDecode<String::ArrayIndexValueBits>(hash)); | |
3986 Goto(&if_index); | |
3987 } | |
3988 | 3954 |
3989 Bind(&if_index); | 3955 Bind(&if_index); |
3990 { | 3956 { |
3991 Comment("integer index"); | 3957 Comment("integer index"); |
3992 Node* index = var_index.value(); | 3958 Node* index = var_index.value(); |
3993 Node* elements = LoadElements(receiver); | 3959 Node* elements = LoadElements(receiver); |
3994 Node* bitfield2 = LoadMapBitField2(receiver_map); | 3960 Node* bitfield2 = LoadMapBitField2(receiver_map); |
3995 Node* elements_kind = BitFieldDecode<Map::ElementsKindBits>(bitfield2); | 3961 Node* elements_kind = BitFieldDecode<Map::ElementsKindBits>(bitfield2); |
3996 Node* is_jsarray_condition = | 3962 Node* is_jsarray_condition = |
3997 Word32Equal(instance_type, Int32Constant(JS_ARRAY_TYPE)); | 3963 Word32Equal(instance_type, Int32Constant(JS_ARRAY_TYPE)); |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4210 Heap::kTheHoleValueRootIndex); | 4176 Heap::kTheHoleValueRootIndex); |
4211 | 4177 |
4212 // Store the WeakCell in the feedback vector. | 4178 // Store the WeakCell in the feedback vector. |
4213 StoreFixedArrayElement(feedback_vector, slot, cell, UPDATE_WRITE_BARRIER, | 4179 StoreFixedArrayElement(feedback_vector, slot, cell, UPDATE_WRITE_BARRIER, |
4214 CodeStubAssembler::SMI_PARAMETERS); | 4180 CodeStubAssembler::SMI_PARAMETERS); |
4215 return cell; | 4181 return cell; |
4216 } | 4182 } |
4217 | 4183 |
4218 } // namespace internal | 4184 } // namespace internal |
4219 } // namespace v8 | 4185 } // namespace v8 |
OLD | NEW |