Chromium Code Reviews| 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 |