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

Side by Side Diff: src/builtins/builtins-string-gen.cc

Issue 2870013004: [builtins] String.prototype.slice as a CSA builtin. (Closed)
Patch Set: Flags for SubString. Created 3 years, 7 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 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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698