| 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 |