OLD | NEW |
1 // Copyright 2017 the V8 project authors. All rights reserved. | 1 // Copyright 2017 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/builtins/builtins-regexp-gen.h" | 5 #include "src/builtins/builtins-regexp-gen.h" |
6 #include "src/builtins/builtins-utils-gen.h" | 6 #include "src/builtins/builtins-utils-gen.h" |
7 #include "src/builtins/builtins.h" | 7 #include "src/builtins/builtins.h" |
8 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
9 #include "src/code-stub-assembler.h" | 9 #include "src/code-stub-assembler.h" |
10 #include "src/objects.h" | 10 #include "src/objects.h" |
(...skipping 714 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
725 | 725 |
726 // Check that {receiver} is coercible to Object and convert it to a String. | 726 // Check that {receiver} is coercible to Object and convert it to a String. |
727 receiver = ToThisString(context, receiver, "String.prototype.concat"); | 727 receiver = ToThisString(context, receiver, "String.prototype.concat"); |
728 | 728 |
729 // Concatenate all the arguments passed to this builtin. | 729 // Concatenate all the arguments passed to this builtin. |
730 VARIABLE(var_result, MachineRepresentation::kTagged); | 730 VARIABLE(var_result, MachineRepresentation::kTagged); |
731 var_result.Bind(receiver); | 731 var_result.Bind(receiver); |
732 arguments.ForEach( | 732 arguments.ForEach( |
733 CodeStubAssembler::VariableList({&var_result}, zone()), | 733 CodeStubAssembler::VariableList({&var_result}, zone()), |
734 [this, context, &var_result](Node* arg) { | 734 [this, context, &var_result](Node* arg) { |
735 arg = CallStub(CodeFactory::ToString(isolate()), context, arg); | 735 arg = ToString_Inline(context, arg); |
736 var_result.Bind(CallStub(CodeFactory::StringAdd(isolate()), context, | 736 var_result.Bind(CallStub(CodeFactory::StringAdd(isolate()), context, |
737 var_result.value(), arg)); | 737 var_result.value(), arg)); |
738 }); | 738 }); |
739 arguments.PopAndReturn(var_result.value()); | 739 arguments.PopAndReturn(var_result.value()); |
740 } | 740 } |
741 | 741 |
742 void StringBuiltinsAssembler::StringIndexOf( | 742 void StringBuiltinsAssembler::StringIndexOf( |
743 Node* const subject_string, Node* const subject_instance_type, | 743 Node* const subject_string, Node* const subject_instance_type, |
744 Node* const search_string, Node* const search_instance_type, | 744 Node* const search_string, Node* const search_instance_type, |
745 Node* const position, std::function<void(Node*)> f_return) { | 745 Node* const position, std::function<void(Node*)> f_return) { |
(...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1142 | 1142 |
1143 Node* const smi_zero = SmiConstant(0); | 1143 Node* const smi_zero = SmiConstant(0); |
1144 | 1144 |
1145 RequireObjectCoercible(context, receiver, "String.prototype.replace"); | 1145 RequireObjectCoercible(context, receiver, "String.prototype.replace"); |
1146 | 1146 |
1147 // Redirect to replacer method if {search[@@replace]} is not undefined. | 1147 // Redirect to replacer method if {search[@@replace]} is not undefined. |
1148 | 1148 |
1149 MaybeCallFunctionAtSymbol( | 1149 MaybeCallFunctionAtSymbol( |
1150 context, search, isolate()->factory()->replace_symbol(), | 1150 context, search, isolate()->factory()->replace_symbol(), |
1151 [=]() { | 1151 [=]() { |
1152 Callable tostring_callable = CodeFactory::ToString(isolate()); | 1152 Node* const subject_string = ToString_Inline(context, receiver); |
1153 Node* const subject_string = | |
1154 CallStub(tostring_callable, context, receiver); | |
1155 | 1153 |
1156 Callable replace_callable = CodeFactory::RegExpReplace(isolate()); | 1154 Callable replace_callable = CodeFactory::RegExpReplace(isolate()); |
1157 return CallStub(replace_callable, context, search, subject_string, | 1155 return CallStub(replace_callable, context, search, subject_string, |
1158 replace); | 1156 replace); |
1159 }, | 1157 }, |
1160 [=](Node* fn) { | 1158 [=](Node* fn) { |
1161 Callable call_callable = CodeFactory::Call(isolate()); | 1159 Callable call_callable = CodeFactory::Call(isolate()); |
1162 return CallJS(call_callable, context, fn, search, receiver, replace); | 1160 return CallJS(call_callable, context, fn, search, receiver, replace); |
1163 }); | 1161 }); |
1164 | 1162 |
1165 // Convert {receiver} and {search} to strings. | 1163 // Convert {receiver} and {search} to strings. |
1166 | 1164 |
1167 Callable tostring_callable = CodeFactory::ToString(isolate()); | |
1168 Callable indexof_callable = CodeFactory::StringIndexOf(isolate()); | 1165 Callable indexof_callable = CodeFactory::StringIndexOf(isolate()); |
1169 | 1166 |
1170 Node* const subject_string = CallStub(tostring_callable, context, receiver); | 1167 Node* const subject_string = ToString_Inline(context, receiver); |
1171 Node* const search_string = CallStub(tostring_callable, context, search); | 1168 Node* const search_string = ToString_Inline(context, search); |
1172 | 1169 |
1173 Node* const subject_length = LoadStringLength(subject_string); | 1170 Node* const subject_length = LoadStringLength(subject_string); |
1174 Node* const search_length = LoadStringLength(search_string); | 1171 Node* const search_length = LoadStringLength(search_string); |
1175 | 1172 |
1176 // Fast-path single-char {search}, long cons {receiver}, and simple string | 1173 // Fast-path single-char {search}, long cons {receiver}, and simple string |
1177 // {replace}. | 1174 // {replace}. |
1178 { | 1175 { |
1179 Label next(this); | 1176 Label next(this); |
1180 | 1177 |
1181 GotoIfNot(SmiEqual(search_length, SmiConstant(1)), &next); | 1178 GotoIfNot(SmiEqual(search_length, SmiConstant(1)), &next); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1215 | 1212 |
1216 // The spec requires to perform ToString(replace) if the {replace} is not | 1213 // The spec requires to perform ToString(replace) if the {replace} is not |
1217 // callable even if we are going to exit here. | 1214 // callable even if we are going to exit here. |
1218 // Since ToString() being applied to Smi does not have side effects for | 1215 // Since ToString() being applied to Smi does not have side effects for |
1219 // numbers we can skip it. | 1216 // numbers we can skip it. |
1220 GotoIf(TaggedIsSmi(replace), &return_subject); | 1217 GotoIf(TaggedIsSmi(replace), &return_subject); |
1221 GotoIf(IsCallableMap(LoadMap(replace)), &return_subject); | 1218 GotoIf(IsCallableMap(LoadMap(replace)), &return_subject); |
1222 | 1219 |
1223 // TODO(jgruber): Could introduce ToStringSideeffectsStub which only | 1220 // TODO(jgruber): Could introduce ToStringSideeffectsStub which only |
1224 // performs observable parts of ToString. | 1221 // performs observable parts of ToString. |
1225 CallStub(tostring_callable, context, replace); | 1222 ToString_Inline(context, replace); |
1226 Goto(&return_subject); | 1223 Goto(&return_subject); |
1227 | 1224 |
1228 BIND(&return_subject); | 1225 BIND(&return_subject); |
1229 Return(subject_string); | 1226 Return(subject_string); |
1230 | 1227 |
1231 BIND(&next); | 1228 BIND(&next); |
1232 } | 1229 } |
1233 | 1230 |
1234 Node* const match_end_index = SmiAdd(match_start_index, search_length); | 1231 Node* const match_end_index = SmiAdd(match_start_index, search_length); |
1235 | 1232 |
(...skipping 22 matching lines...) Expand all Loading... |
1258 GotoIf(TaggedIsSmi(replace), &if_notcallablereplace); | 1255 GotoIf(TaggedIsSmi(replace), &if_notcallablereplace); |
1259 Branch(IsCallableMap(LoadMap(replace)), &if_iscallablereplace, | 1256 Branch(IsCallableMap(LoadMap(replace)), &if_iscallablereplace, |
1260 &if_notcallablereplace); | 1257 &if_notcallablereplace); |
1261 | 1258 |
1262 BIND(&if_iscallablereplace); | 1259 BIND(&if_iscallablereplace); |
1263 { | 1260 { |
1264 Callable call_callable = CodeFactory::Call(isolate()); | 1261 Callable call_callable = CodeFactory::Call(isolate()); |
1265 Node* const replacement = | 1262 Node* const replacement = |
1266 CallJS(call_callable, context, replace, UndefinedConstant(), | 1263 CallJS(call_callable, context, replace, UndefinedConstant(), |
1267 search_string, match_start_index, subject_string); | 1264 search_string, match_start_index, subject_string); |
1268 Node* const replacement_string = | 1265 Node* const replacement_string = ToString_Inline(context, replacement); |
1269 CallStub(tostring_callable, context, replacement); | |
1270 var_result.Bind(CallStub(stringadd_callable, context, var_result.value(), | 1266 var_result.Bind(CallStub(stringadd_callable, context, var_result.value(), |
1271 replacement_string)); | 1267 replacement_string)); |
1272 Goto(&out); | 1268 Goto(&out); |
1273 } | 1269 } |
1274 | 1270 |
1275 BIND(&if_notcallablereplace); | 1271 BIND(&if_notcallablereplace); |
1276 { | 1272 { |
1277 Node* const replace_string = CallStub(tostring_callable, context, replace); | 1273 Node* const replace_string = ToString_Inline(context, replace); |
1278 Node* const replacement = | 1274 Node* const replacement = |
1279 GetSubstitution(context, subject_string, match_start_index, | 1275 GetSubstitution(context, subject_string, match_start_index, |
1280 match_end_index, replace_string); | 1276 match_end_index, replace_string); |
1281 var_result.Bind( | 1277 var_result.Bind( |
1282 CallStub(stringadd_callable, context, var_result.value(), replacement)); | 1278 CallStub(stringadd_callable, context, var_result.value(), replacement)); |
1283 Goto(&out); | 1279 Goto(&out); |
1284 } | 1280 } |
1285 | 1281 |
1286 BIND(&out); | 1282 BIND(&out); |
1287 { | 1283 { |
(...skipping 16 matching lines...) Expand all Loading... |
1304 | 1300 |
1305 Node* const smi_zero = SmiConstant(0); | 1301 Node* const smi_zero = SmiConstant(0); |
1306 | 1302 |
1307 RequireObjectCoercible(context, receiver, "String.prototype.split"); | 1303 RequireObjectCoercible(context, receiver, "String.prototype.split"); |
1308 | 1304 |
1309 // Redirect to splitter method if {separator[@@split]} is not undefined. | 1305 // Redirect to splitter method if {separator[@@split]} is not undefined. |
1310 | 1306 |
1311 MaybeCallFunctionAtSymbol( | 1307 MaybeCallFunctionAtSymbol( |
1312 context, separator, isolate()->factory()->split_symbol(), | 1308 context, separator, isolate()->factory()->split_symbol(), |
1313 [=]() { | 1309 [=]() { |
1314 Callable tostring_callable = CodeFactory::ToString(isolate()); | 1310 Node* const subject_string = ToString_Inline(context, receiver); |
1315 Node* const subject_string = | |
1316 CallStub(tostring_callable, context, receiver); | |
1317 | 1311 |
1318 Callable split_callable = CodeFactory::RegExpSplit(isolate()); | 1312 Callable split_callable = CodeFactory::RegExpSplit(isolate()); |
1319 return CallStub(split_callable, context, separator, subject_string, | 1313 return CallStub(split_callable, context, separator, subject_string, |
1320 limit); | 1314 limit); |
1321 }, | 1315 }, |
1322 [=](Node* fn) { | 1316 [=](Node* fn) { |
1323 Callable call_callable = CodeFactory::Call(isolate()); | 1317 Callable call_callable = CodeFactory::Call(isolate()); |
1324 return CallJS(call_callable, context, fn, separator, receiver, limit); | 1318 return CallJS(call_callable, context, fn, separator, receiver, limit); |
1325 }); | 1319 }); |
1326 | 1320 |
1327 // String and integer conversions. | 1321 // String and integer conversions. |
1328 // TODO(jgruber): The old implementation used Uint32Max instead of SmiMax - | 1322 // TODO(jgruber): The old implementation used Uint32Max instead of SmiMax - |
1329 // but AFAIK there should not be a difference since arrays are capped at Smi | 1323 // but AFAIK there should not be a difference since arrays are capped at Smi |
1330 // lengths. | 1324 // lengths. |
1331 | 1325 |
1332 Callable tostring_callable = CodeFactory::ToString(isolate()); | 1326 Node* const subject_string = ToString_Inline(context, receiver); |
1333 Node* const subject_string = CallStub(tostring_callable, context, receiver); | |
1334 Node* const limit_number = | 1327 Node* const limit_number = |
1335 Select(IsUndefined(limit), [=]() { return SmiConstant(Smi::kMaxValue); }, | 1328 Select(IsUndefined(limit), [=]() { return SmiConstant(Smi::kMaxValue); }, |
1336 [=]() { return ToUint32(context, limit); }, | 1329 [=]() { return ToUint32(context, limit); }, |
1337 MachineRepresentation::kTagged); | 1330 MachineRepresentation::kTagged); |
1338 Node* const separator_string = | 1331 Node* const separator_string = ToString_Inline(context, separator); |
1339 CallStub(tostring_callable, context, separator); | |
1340 | 1332 |
1341 // Shortcut for {limit} == 0. | 1333 // Shortcut for {limit} == 0. |
1342 { | 1334 { |
1343 Label next(this); | 1335 Label next(this); |
1344 GotoIfNot(SmiEqual(limit_number, smi_zero), &next); | 1336 GotoIfNot(SmiEqual(limit_number, smi_zero), &next); |
1345 | 1337 |
1346 const ElementsKind kind = FAST_ELEMENTS; | 1338 const ElementsKind kind = FAST_ELEMENTS; |
1347 Node* const native_context = LoadNativeContext(context); | 1339 Node* const native_context = LoadNativeContext(context); |
1348 Node* const array_map = LoadJSArrayElementsMap(kind, native_context); | 1340 Node* const array_map = LoadJSArrayElementsMap(kind, native_context); |
1349 | 1341 |
(...skipping 435 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1785 CallRuntime(Runtime::kThrowIncompatibleMethodReceiver, context, | 1777 CallRuntime(Runtime::kThrowIncompatibleMethodReceiver, context, |
1786 HeapConstant(factory()->NewStringFromAsciiChecked( | 1778 HeapConstant(factory()->NewStringFromAsciiChecked( |
1787 "String Iterator.prototype.next", TENURED)), | 1779 "String Iterator.prototype.next", TENURED)), |
1788 iterator); | 1780 iterator); |
1789 Unreachable(); | 1781 Unreachable(); |
1790 } | 1782 } |
1791 } | 1783 } |
1792 | 1784 |
1793 } // namespace internal | 1785 } // namespace internal |
1794 } // namespace v8 | 1786 } // namespace v8 |
OLD | NEW |