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 1275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1286 BIND(&out); | 1286 BIND(&out); |
1287 { | 1287 { |
1288 Node* const suffix = CallStub(substring_callable, context, subject_string, | 1288 Node* const suffix = CallStub(substring_callable, context, subject_string, |
1289 match_end_index, subject_length); | 1289 match_end_index, subject_length); |
1290 Node* const result = | 1290 Node* const result = |
1291 CallStub(stringadd_callable, context, var_result.value(), suffix); | 1291 CallStub(stringadd_callable, context, var_result.value(), suffix); |
1292 Return(result); | 1292 Return(result); |
1293 } | 1293 } |
1294 } | 1294 } |
1295 | 1295 |
1296 // ES6 section 21.1.3.18 String.prototype.slice ( start, end ) | |
1297 TF_BUILTIN(StringPrototypeSlice, StringBuiltinsAssembler) { | |
1298 Label handle_end(this), out(this); | |
1299 VARIABLE(var_start, MachineRepresentation::kTagged); | |
1300 VARIABLE(var_end, MachineRepresentation::kTagged); | |
1301 | |
1302 Node* const receiver = Parameter(Descriptor::kReceiver); | |
1303 Node* const start = Parameter(Descriptor::kStart); | |
1304 Node* const end = Parameter(Descriptor::kEnd); | |
1305 Node* const context = Parameter(Descriptor::kContext); | |
1306 | |
1307 Node* const smi_zero = SmiConstant(0); | |
1308 | |
1309 // 1. Let O be ? RequireObjectCoercible(this value). | |
1310 RequireObjectCoercible(context, receiver, "String.prototype.slice"); | |
1311 | |
1312 // String and integer conversions. | |
1313 // TODO(jgruber): The old implementation used Uint32Max instead of SmiMax - | |
jgruber
2017/05/11 08:57:40
Nit: This comment doesn't apply here.
mvstanton
2017/05/12 11:00:42
Done.
| |
1314 // but AFAIK there should not be a difference since arrays are capped at Smi | |
1315 // lengths. | |
1316 | |
1317 // 2. Let S be ? ToString(O). | |
1318 Callable tostring_callable = CodeFactory::ToString(isolate()); | |
1319 Node* const subject_string = CallStub(tostring_callable, context, receiver); | |
1320 | |
1321 // 3. Let len be the number of elements in S. | |
1322 Node* const length = LoadStringLength(subject_string); | |
1323 | |
1324 // Conversions and bounds-checks for {start}. | |
jgruber
2017/05/11 08:57:40
From a quick look this seems identical to arg hand
mvstanton
2017/05/12 11:00:42
Indeed, I made a utility method in the string code
| |
1325 { | |
1326 // 4. Let intStart be ? ToInteger(start). | |
1327 Node* const start_int = | |
1328 ToInteger(context, start, CodeStubAssembler::kTruncateMinusZero); | |
1329 | |
1330 Label if_issmi(this), if_isheapnumber(this, Label::kDeferred); | |
1331 Branch(TaggedIsSmi(start_int), &if_issmi, &if_isheapnumber); | |
1332 | |
1333 // 6. If intStart < 0, let from be max(len + intStart, 0); | |
1334 // otherwise, let from be min(intStart, len). | |
1335 BIND(&if_issmi); | |
1336 { | |
1337 Node* const length_plus_start = SmiAdd(length, start_int); | |
jgruber
2017/05/11 08:57:40
Nit: Just noticed that this could move into the Se
mvstanton
2017/05/12 11:00:42
Oh yeah! Done.
| |
1338 var_start.Bind(Select(SmiLessThan(start_int, smi_zero), | |
1339 [&] { return SmiMax(length_plus_start, smi_zero); }, | |
1340 [&] { return SmiMin(start_int, length); }, | |
1341 MachineRepresentation::kTagged)); | |
1342 Goto(&handle_end); | |
1343 } | |
1344 | |
1345 BIND(&if_isheapnumber); | |
1346 { | |
1347 // If {start} is a heap number, it is definitely out of bounds. If it is | |
1348 // negative, {start} = max({string_length} + {start}),0) = 0'. If it is | |
1349 // positive, set {start} to {string_length} which ultimately results in | |
1350 // returning an empty string. | |
1351 Node* const float_zero = Float64Constant(0.); | |
1352 Node* const start_float = LoadHeapNumberValue(start_int); | |
1353 var_start.Bind(SelectTaggedConstant( | |
1354 Float64LessThan(start_float, float_zero), smi_zero, length)); | |
1355 Goto(&handle_end); | |
1356 } | |
1357 } | |
1358 | |
1359 BIND(&handle_end); | |
1360 { | |
1361 // 5. If end is undefined, let intEnd be len; | |
1362 var_end.Bind(length); | |
1363 GotoIf(WordEqual(end, UndefinedConstant()), &out); | |
1364 | |
1365 // else let intEnd be ? ToInteger(end). | |
1366 Node* const end_int = | |
1367 ToInteger(context, end, CodeStubAssembler::kTruncateMinusZero); | |
1368 | |
1369 // 7. If intEnd < 0, let to be max(len + intEnd, 0); | |
1370 // otherwise let to be min(intEnd, len). | |
1371 Label if_issmi(this), if_isheapnumber(this, Label::kDeferred); | |
1372 Branch(TaggedIsSmi(end_int), &if_issmi, &if_isheapnumber); | |
1373 | |
1374 BIND(&if_issmi); | |
1375 { | |
1376 Node* const length_plus_end = SmiAdd(length, end_int); | |
jgruber
2017/05/11 08:57:40
Same here.
mvstanton
2017/05/12 11:00:42
Done.
| |
1377 var_end.Bind(Select(SmiLessThan(end_int, smi_zero), | |
1378 [&] { return SmiMax(length_plus_end, smi_zero); }, | |
1379 [&] { return SmiMin(length, end_int); }, | |
1380 MachineRepresentation::kTagged)); | |
1381 Goto(&out); | |
1382 } | |
1383 | |
1384 BIND(&if_isheapnumber); | |
1385 { | |
1386 // If {end} is a heap number, it is definitely out of bounds. If it is | |
1387 // negative, {int_end} = max({length} + {int_end}),0) = 0'. If it is | |
1388 // positive, set {int_end} to {length} which ultimately results in | |
1389 // returning an empty string. | |
1390 Node* const float_zero = Float64Constant(0.); | |
1391 Node* const end_float = LoadHeapNumberValue(end_int); | |
1392 var_end.Bind(SelectTaggedConstant(Float64LessThan(end_float, float_zero), | |
1393 smi_zero, length)); | |
1394 Goto(&out); | |
1395 } | |
1396 } | |
1397 | |
1398 Label return_emptystring(this); | |
1399 BIND(&out); | |
1400 { | |
1401 GotoIf(SmiLessThanOrEqual(var_end.value(), var_start.value()), | |
1402 &return_emptystring); | |
1403 Node* const result = | |
1404 SubString(context, subject_string, var_start.value(), var_end.value(), | |
1405 SubStringFlags::FROM_TO_ARE_BOUNDED); | |
1406 Return(result); | |
1407 } | |
1408 | |
1409 BIND(&return_emptystring); | |
1410 Return(EmptyStringConstant()); | |
1411 } | |
1412 | |
1296 // ES6 section 21.1.3.19 String.prototype.split ( separator, limit ) | 1413 // ES6 section 21.1.3.19 String.prototype.split ( separator, limit ) |
1297 TF_BUILTIN(StringPrototypeSplit, StringBuiltinsAssembler) { | 1414 TF_BUILTIN(StringPrototypeSplit, StringBuiltinsAssembler) { |
1298 Label out(this); | 1415 Label out(this); |
1299 | 1416 |
1300 Node* const receiver = Parameter(Descriptor::kReceiver); | 1417 Node* const receiver = Parameter(Descriptor::kReceiver); |
1301 Node* const separator = Parameter(Descriptor::kSeparator); | 1418 Node* const separator = Parameter(Descriptor::kSeparator); |
1302 Node* const limit = Parameter(Descriptor::kLimit); | 1419 Node* const limit = Parameter(Descriptor::kLimit); |
1303 Node* const context = Parameter(Descriptor::kContext); | 1420 Node* const context = Parameter(Descriptor::kContext); |
1304 | 1421 |
1305 Node* const smi_zero = SmiConstant(0); | 1422 Node* const smi_zero = SmiConstant(0); |
(...skipping 479 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1785 CallRuntime(Runtime::kThrowIncompatibleMethodReceiver, context, | 1902 CallRuntime(Runtime::kThrowIncompatibleMethodReceiver, context, |
1786 HeapConstant(factory()->NewStringFromAsciiChecked( | 1903 HeapConstant(factory()->NewStringFromAsciiChecked( |
1787 "String Iterator.prototype.next", TENURED)), | 1904 "String Iterator.prototype.next", TENURED)), |
1788 iterator); | 1905 iterator); |
1789 Unreachable(); | 1906 Unreachable(); |
1790 } | 1907 } |
1791 } | 1908 } |
1792 | 1909 |
1793 } // namespace internal | 1910 } // namespace internal |
1794 } // namespace v8 | 1911 } // namespace v8 |
OLD | NEW |