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

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

Issue 2395453002: [stubs] Add String and JSReceiver instance type predicates (Closed)
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 the V8 project authors. All rights reserved. 1 // Copyright 2016 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 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 742 matching lines...) Expand 10 before | Expand all | Expand 10 after
753 // The {value} is a HeapObject, load its map. 753 // The {value} is a HeapObject, load its map.
754 Node* value_map = LoadMap(value); 754 Node* value_map = LoadMap(value);
755 755
756 // Load the {value}s instance type. 756 // Load the {value}s instance type.
757 Node* value_instance_type = LoadMapInstanceType(value_map); 757 Node* value_instance_type = LoadMapInstanceType(value_map);
758 758
759 // Dispatch based on the instance type; we distinguish all String instance 759 // Dispatch based on the instance type; we distinguish all String instance
760 // types, the HeapNumber type and everything else. 760 // types, the HeapNumber type and everything else.
761 GotoIf(Word32Equal(value_instance_type, Int32Constant(HEAP_NUMBER_TYPE)), 761 GotoIf(Word32Equal(value_instance_type, Int32Constant(HEAP_NUMBER_TYPE)),
762 &if_valueisheapnumber); 762 &if_valueisheapnumber);
763 Branch( 763 Branch(IsStringInstanceType(value_instance_type), &if_valueisstring,
764 Int32LessThan(value_instance_type, Int32Constant(FIRST_NONSTRING_TYPE)), 764 &if_valueisother);
765 &if_valueisstring, &if_valueisother);
766 765
767 Bind(&if_valueisstring); 766 Bind(&if_valueisstring);
768 { 767 {
769 // Load the string length field of the {value}. 768 // Load the string length field of the {value}.
770 Node* value_length = LoadObjectField(value, String::kLengthOffset); 769 Node* value_length = LoadObjectField(value, String::kLengthOffset);
771 770
772 // Check if the {value} is the empty string. 771 // Check if the {value} is the empty string.
773 BranchIfSmiEqual(value_length, SmiConstant(0), if_false, if_true); 772 BranchIfSmiEqual(value_length, SmiConstant(0), if_false, if_true);
774 } 773 }
775 774
(...skipping 1300 matching lines...) Expand 10 before | Expand all | Expand 10 after
2076 Label if_valueissmi(this, Label::kDeferred), if_valueisnotsmi(this), 2075 Label if_valueissmi(this, Label::kDeferred), if_valueisnotsmi(this),
2077 if_valueisstring(this); 2076 if_valueisstring(this);
2078 Branch(WordIsSmi(value), &if_valueissmi, &if_valueisnotsmi); 2077 Branch(WordIsSmi(value), &if_valueissmi, &if_valueisnotsmi);
2079 Bind(&if_valueisnotsmi); 2078 Bind(&if_valueisnotsmi);
2080 { 2079 {
2081 // Load the instance type of the {value}. 2080 // Load the instance type of the {value}.
2082 Node* value_instance_type = LoadInstanceType(value); 2081 Node* value_instance_type = LoadInstanceType(value);
2083 2082
2084 // Check if the {value} is already String. 2083 // Check if the {value} is already String.
2085 Label if_valueisnotstring(this, Label::kDeferred); 2084 Label if_valueisnotstring(this, Label::kDeferred);
2086 Branch( 2085 Branch(IsStringInstanceType(value_instance_type), &if_valueisstring,
2087 Int32LessThan(value_instance_type, Int32Constant(FIRST_NONSTRING_TYPE)), 2086 &if_valueisnotstring);
2088 &if_valueisstring, &if_valueisnotstring);
2089 Bind(&if_valueisnotstring); 2087 Bind(&if_valueisnotstring);
2090 { 2088 {
2091 // Check if the {value} is null. 2089 // Check if the {value} is null.
2092 Label if_valueisnullorundefined(this, Label::kDeferred), 2090 Label if_valueisnullorundefined(this, Label::kDeferred),
2093 if_valueisnotnullorundefined(this, Label::kDeferred), 2091 if_valueisnotnullorundefined(this, Label::kDeferred),
2094 if_valueisnotnull(this, Label::kDeferred); 2092 if_valueisnotnull(this, Label::kDeferred);
2095 Branch(WordEqual(value, NullConstant()), &if_valueisnullorundefined, 2093 Branch(WordEqual(value, NullConstant()), &if_valueisnullorundefined,
2096 &if_valueisnotnull); 2094 &if_valueisnotnull);
2097 Bind(&if_valueisnotnull); 2095 Bind(&if_valueisnotnull);
2098 { 2096 {
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
2171 switch (primitive_type) { 2169 switch (primitive_type) {
2172 case PrimitiveType::kBoolean: 2170 case PrimitiveType::kBoolean:
2173 GotoIf(WordEqual(value_map, BooleanMapConstant()), &done_loop); 2171 GotoIf(WordEqual(value_map, BooleanMapConstant()), &done_loop);
2174 break; 2172 break;
2175 case PrimitiveType::kNumber: 2173 case PrimitiveType::kNumber:
2176 GotoIf( 2174 GotoIf(
2177 Word32Equal(value_instance_type, Int32Constant(HEAP_NUMBER_TYPE)), 2175 Word32Equal(value_instance_type, Int32Constant(HEAP_NUMBER_TYPE)),
2178 &done_loop); 2176 &done_loop);
2179 break; 2177 break;
2180 case PrimitiveType::kString: 2178 case PrimitiveType::kString:
2181 GotoIf(Int32LessThan(value_instance_type, 2179 GotoIf(IsStringInstanceType(value_instance_type), &done_loop);
2182 Int32Constant(FIRST_NONSTRING_TYPE)),
2183 &done_loop);
2184 break; 2180 break;
2185 case PrimitiveType::kSymbol: 2181 case PrimitiveType::kSymbol:
2186 GotoIf(Word32Equal(value_instance_type, Int32Constant(SYMBOL_TYPE)), 2182 GotoIf(Word32Equal(value_instance_type, Int32Constant(SYMBOL_TYPE)),
2187 &done_loop); 2183 &done_loop);
2188 break; 2184 break;
2189 } 2185 }
2190 Goto(&done_throw); 2186 Goto(&done_throw);
2191 } 2187 }
2192 } 2188 }
2193 2189
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
2225 Runtime::kThrowIncompatibleMethodReceiver, context, 2221 Runtime::kThrowIncompatibleMethodReceiver, context,
2226 HeapConstant(factory()->NewStringFromAsciiChecked(method_name, TENURED)), 2222 HeapConstant(factory()->NewStringFromAsciiChecked(method_name, TENURED)),
2227 value); 2223 value);
2228 var_value_map.Bind(UndefinedConstant()); 2224 var_value_map.Bind(UndefinedConstant());
2229 Goto(&out); // Never reached. 2225 Goto(&out); // Never reached.
2230 2226
2231 Bind(&out); 2227 Bind(&out);
2232 return var_value_map.value(); 2228 return var_value_map.value();
2233 } 2229 }
2234 2230
2231 Node* CodeStubAssembler::IsStringInstanceType(Node* instance_type) {
2232 STATIC_ASSERT(INTERNALIZED_STRING_TYPE == FIRST_TYPE);
2233 return Int32LessThan(instance_type, Int32Constant(FIRST_NONSTRING_TYPE));
2234 }
2235
2236 Node* CodeStubAssembler::IsJSReceiverInstanceType(Node* instance_type) {
2237 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
2238 return Int32GreaterThanOrEqual(instance_type,
2239 Int32Constant(FIRST_JS_RECEIVER_TYPE));
2240 }
2241
2235 Node* CodeStubAssembler::StringCharCodeAt(Node* string, Node* index) { 2242 Node* CodeStubAssembler::StringCharCodeAt(Node* string, Node* index) {
2236 // Translate the {index} into a Word. 2243 // Translate the {index} into a Word.
2237 index = SmiToWord(index); 2244 index = SmiToWord(index);
2238 2245
2239 // We may need to loop in case of cons or sliced strings. 2246 // We may need to loop in case of cons or sliced strings.
2240 Variable var_index(this, MachineType::PointerRepresentation()); 2247 Variable var_index(this, MachineType::PointerRepresentation());
2241 Variable var_result(this, MachineRepresentation::kWord32); 2248 Variable var_result(this, MachineRepresentation::kWord32);
2242 Variable var_string(this, MachineRepresentation::kTagged); 2249 Variable var_string(this, MachineRepresentation::kTagged);
2243 Variable* loop_vars[] = {&var_index, &var_string}; 2250 Variable* loop_vars[] = {&var_index, &var_string};
2244 Label done_loop(this, &var_result), loop(this, 2, loop_vars); 2251 Label done_loop(this, &var_result), loop(this, 2, loop_vars);
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after
2530 // Make sure first argument is a string. 2537 // Make sure first argument is a string.
2531 2538
2532 // Bailout if receiver is a Smi. 2539 // Bailout if receiver is a Smi.
2533 GotoIf(WordIsSmi(string), &runtime); 2540 GotoIf(WordIsSmi(string), &runtime);
2534 2541
2535 // Load the instance type of the {string}. 2542 // Load the instance type of the {string}.
2536 Node* const instance_type = LoadInstanceType(string); 2543 Node* const instance_type = LoadInstanceType(string);
2537 var_instance_type.Bind(instance_type); 2544 var_instance_type.Bind(instance_type);
2538 2545
2539 // Check if {string} is a String. 2546 // Check if {string} is a String.
2540 GotoIf(Int32GreaterThanOrEqual(instance_type, 2547 GotoUnless(IsStringInstanceType(instance_type), &runtime);
2541 Int32Constant(FIRST_NONSTRING_TYPE)),
2542 &runtime);
2543 2548
2544 // Make sure that both from and to are non-negative smis. 2549 // Make sure that both from and to are non-negative smis.
2545 2550
2546 GotoUnless(WordIsPositiveSmi(from), &runtime); 2551 GotoUnless(WordIsPositiveSmi(from), &runtime);
2547 GotoUnless(WordIsPositiveSmi(to), &runtime); 2552 GotoUnless(WordIsPositiveSmi(to), &runtime);
2548 2553
2549 Node* const substr_length = SmiSub(to, from); 2554 Node* const substr_length = SmiSub(to, from);
2550 Node* const string_length = LoadStringLength(string); 2555 Node* const string_length = LoadStringLength(string);
2551 2556
2552 // Begin dispatching based on substring length. 2557 // Begin dispatching based on substring length.
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after
2878 Bind(&loop); 2883 Bind(&loop);
2879 { 2884 {
2880 // Load the current {input} value (known to be a HeapObject). 2885 // Load the current {input} value (known to be a HeapObject).
2881 Node* input = var_input.value(); 2886 Node* input = var_input.value();
2882 2887
2883 // Dispatch on the {input} instance type. 2888 // Dispatch on the {input} instance type.
2884 Node* input_instance_type = LoadInstanceType(input); 2889 Node* input_instance_type = LoadInstanceType(input);
2885 Label if_inputisstring(this), if_inputisoddball(this), 2890 Label if_inputisstring(this), if_inputisoddball(this),
2886 if_inputisreceiver(this, Label::kDeferred), 2891 if_inputisreceiver(this, Label::kDeferred),
2887 if_inputisother(this, Label::kDeferred); 2892 if_inputisother(this, Label::kDeferred);
2888 GotoIf( 2893 GotoIf(IsStringInstanceType(input_instance_type), &if_inputisstring);
2889 Int32LessThan(input_instance_type, Int32Constant(FIRST_NONSTRING_TYPE)),
2890 &if_inputisstring);
2891 GotoIf(Word32Equal(input_instance_type, Int32Constant(ODDBALL_TYPE)), 2894 GotoIf(Word32Equal(input_instance_type, Int32Constant(ODDBALL_TYPE)),
2892 &if_inputisoddball); 2895 &if_inputisoddball);
2893 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); 2896 Branch(IsJSReceiverInstanceType(input_instance_type), &if_inputisreceiver,
2894 Branch(Int32GreaterThanOrEqual(input_instance_type, 2897 &if_inputisother);
2895 Int32Constant(FIRST_JS_RECEIVER_TYPE)),
2896 &if_inputisreceiver, &if_inputisother);
2897 2898
2898 Bind(&if_inputisstring); 2899 Bind(&if_inputisstring);
2899 { 2900 {
2900 // The {input} is a String, use the fast stub to convert it to a Number. 2901 // The {input} is a String, use the fast stub to convert it to a Number.
2901 var_result.Bind(StringToNumber(context, input)); 2902 var_result.Bind(StringToNumber(context, input));
2902 Goto(&end); 2903 Goto(&end);
2903 } 2904 }
2904 2905
2905 Bind(&if_inputisoddball); 2906 Bind(&if_inputisoddball);
2906 { 2907 {
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
3095 // Handle Smi and HeapNumber keys. 3096 // Handle Smi and HeapNumber keys.
3096 var_index->Bind(TryToIntptr(key, &if_keyisnotindex)); 3097 var_index->Bind(TryToIntptr(key, &if_keyisnotindex));
3097 Goto(if_keyisindex); 3098 Goto(if_keyisindex);
3098 3099
3099 Bind(&if_keyisnotindex); 3100 Bind(&if_keyisnotindex);
3100 Node* key_instance_type = LoadInstanceType(key); 3101 Node* key_instance_type = LoadInstanceType(key);
3101 // Symbols are unique. 3102 // Symbols are unique.
3102 GotoIf(Word32Equal(key_instance_type, Int32Constant(SYMBOL_TYPE)), 3103 GotoIf(Word32Equal(key_instance_type, Int32Constant(SYMBOL_TYPE)),
3103 if_keyisunique); 3104 if_keyisunique);
3104 // Miss if |key| is not a String. 3105 // Miss if |key| is not a String.
3105 STATIC_ASSERT(FIRST_NAME_TYPE == FIRST_TYPE); 3106 STATIC_ASSERT(FIRST_NAME_TYPE == FIRST_TYPE);
Igor Sheludko 2016/10/05 08:02:27 You can now remove this assert from here.
3106 GotoIf( 3107 GotoUnless(IsStringInstanceType(key_instance_type), if_bailout);
jgruber 2016/10/04 13:35:54 Igor: I'm assuming the original code was bugged (s
Igor Sheludko 2016/10/05 08:02:27 FIRST_NONSTRING_TYPE is actually a SYMBOL_TYPE whi
3107 Int32GreaterThan(key_instance_type, Int32Constant(FIRST_NONSTRING_TYPE)),
3108 if_bailout);
3109 // |key| is a String. Check if it has a cached array index. 3108 // |key| is a String. Check if it has a cached array index.
3110 Node* hash = LoadNameHashField(key); 3109 Node* hash = LoadNameHashField(key);
3111 Node* contains_index = 3110 Node* contains_index =
3112 Word32And(hash, Int32Constant(Name::kContainsCachedArrayIndexMask)); 3111 Word32And(hash, Int32Constant(Name::kContainsCachedArrayIndexMask));
3113 GotoIf(Word32Equal(contains_index, Int32Constant(0)), &if_hascachedindex); 3112 GotoIf(Word32Equal(contains_index, Int32Constant(0)), &if_hascachedindex);
3114 // No cached array index. If the string knows that it contains an index, 3113 // No cached array index. If the string knows that it contains an index,
3115 // then it must be an uncacheable index. Handle this case in the runtime. 3114 // then it must be an uncacheable index. Handle this case in the runtime.
3116 Node* not_an_index = 3115 Node* not_an_index =
3117 Word32And(hash, Int32Constant(Name::kIsNotArrayIndexMask)); 3116 Word32And(hash, Int32Constant(Name::kIsNotArrayIndexMask));
3118 GotoIf(Word32Equal(not_an_index, Int32Constant(0)), if_bailout); 3117 GotoIf(Word32Equal(not_an_index, Int32Constant(0)), if_bailout);
(...skipping 626 matching lines...) Expand 10 before | Expand all | Expand 10 after
3745 { 3744 {
3746 Variable var_entry(this, MachineType::PointerRepresentation()); 3745 Variable var_entry(this, MachineType::PointerRepresentation());
3747 Node* elements = LoadElements(object); 3746 Node* elements = LoadElements(object);
3748 NumberDictionaryLookup<SeededNumberDictionary>( 3747 NumberDictionaryLookup<SeededNumberDictionary>(
3749 elements, intptr_index, if_found, &var_entry, if_not_found); 3748 elements, intptr_index, if_found, &var_entry, if_not_found);
3750 } 3749 }
3751 Bind(&if_isfaststringwrapper); 3750 Bind(&if_isfaststringwrapper);
3752 { 3751 {
3753 AssertInstanceType(object, JS_VALUE_TYPE); 3752 AssertInstanceType(object, JS_VALUE_TYPE);
3754 Node* string = LoadJSValueValue(object); 3753 Node* string = LoadJSValueValue(object);
3755 Assert(Int32LessThan(LoadInstanceType(string), 3754 Assert(IsStringInstanceType(LoadInstanceType(string)));
3756 Int32Constant(FIRST_NONSTRING_TYPE)));
3757 Node* length = LoadStringLength(string); 3755 Node* length = LoadStringLength(string);
3758 GotoIf(UintPtrLessThan(intptr_index, SmiUntag(length)), if_found); 3756 GotoIf(UintPtrLessThan(intptr_index, SmiUntag(length)), if_found);
3759 Goto(&if_isobjectorsmi); 3757 Goto(&if_isobjectorsmi);
3760 } 3758 }
3761 Bind(&if_isslowstringwrapper); 3759 Bind(&if_isslowstringwrapper);
3762 { 3760 {
3763 AssertInstanceType(object, JS_VALUE_TYPE); 3761 AssertInstanceType(object, JS_VALUE_TYPE);
3764 Node* string = LoadJSValueValue(object); 3762 Node* string = LoadJSValueValue(object);
3765 Assert(Int32LessThan(LoadInstanceType(string), 3763 Assert(IsStringInstanceType(LoadInstanceType(string)));
3766 Int32Constant(FIRST_NONSTRING_TYPE)));
3767 Node* length = LoadStringLength(string); 3764 Node* length = LoadStringLength(string);
3768 GotoIf(UintPtrLessThan(intptr_index, SmiUntag(length)), if_found); 3765 GotoIf(UintPtrLessThan(intptr_index, SmiUntag(length)), if_found);
3769 Goto(&if_isdictionary); 3766 Goto(&if_isdictionary);
3770 } 3767 }
3771 Bind(&if_oob); 3768 Bind(&if_oob);
3772 { 3769 {
3773 // Positive OOB indices mean "not found", negative indices must be 3770 // Positive OOB indices mean "not found", negative indices must be
3774 // converted to property names. 3771 // converted to property names.
3775 GotoIf(IntPtrLessThan(intptr_index, IntPtrConstant(0)), if_bailout); 3772 GotoIf(IntPtrLessThan(intptr_index, IntPtrConstant(0)), if_bailout);
3776 Goto(if_not_found); 3773 Goto(if_not_found);
(...skipping 1918 matching lines...) Expand 10 before | Expand all | Expand 10 after
5695 Heap::kTheHoleValueRootIndex); 5692 Heap::kTheHoleValueRootIndex);
5696 5693
5697 // Store the WeakCell in the feedback vector. 5694 // Store the WeakCell in the feedback vector.
5698 StoreFixedArrayElement(feedback_vector, slot, cell, UPDATE_WRITE_BARRIER, 5695 StoreFixedArrayElement(feedback_vector, slot, cell, UPDATE_WRITE_BARRIER,
5699 CodeStubAssembler::SMI_PARAMETERS); 5696 CodeStubAssembler::SMI_PARAMETERS);
5700 return cell; 5697 return cell;
5701 } 5698 }
5702 5699
5703 } // namespace internal 5700 } // namespace internal
5704 } // namespace v8 5701 } // namespace v8
OLDNEW
« no previous file with comments | « src/code-stub-assembler.h ('k') | src/code-stubs.cc » ('j') | src/code-stubs.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698