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

Side by Side Diff: src/builtins/builtins-array.cc

Issue 2146293003: [builtins] implement Array.prototype.includes in TurboFan (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: move to builtins-array.cc and add indexed interceptor checks Created 4 years, 5 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 2016 the V8 project authors. All rights reserved. 1 // Copyright 2016 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.h" 5 #include "src/builtins/builtins.h"
6 #include "src/builtins/builtins-utils.h" 6 #include "src/builtins/builtins-utils.h"
7
8 #include "src/code-factory.h"
7 #include "src/elements.h" 9 #include "src/elements.h"
8 10
9 namespace v8 { 11 namespace v8 {
10 namespace internal { 12 namespace internal {
11 13
12 namespace { 14 namespace {
13 15
14 inline bool ClampedToInteger(Isolate* isolate, Object* object, int* out) { 16 inline bool ClampedToInteger(Isolate* isolate, Object* object, int* out) {
15 // This is an extended version of ECMA-262 7.1.11 handling signed values 17 // This is an extended version of ECMA-262 7.1.11 handling signed values
16 // Try to convert object to a number and clamp values to [kMinInt, kMaxInt] 18 // Try to convert object to a number and clamp values to [kMinInt, kMaxInt]
(...skipping 1247 matching lines...) Expand 10 before | Expand all | Expand 10 after
1264 assembler->Return(assembler->BooleanConstant(true)); 1266 assembler->Return(assembler->BooleanConstant(true));
1265 1267
1266 assembler->Bind(&return_false); 1268 assembler->Bind(&return_false);
1267 assembler->Return(assembler->BooleanConstant(false)); 1269 assembler->Return(assembler->BooleanConstant(false));
1268 1270
1269 assembler->Bind(&call_runtime); 1271 assembler->Bind(&call_runtime);
1270 assembler->Return( 1272 assembler->Return(
1271 assembler->CallRuntime(Runtime::kArrayIsArray, context, object)); 1273 assembler->CallRuntime(Runtime::kArrayIsArray, context, object));
1272 } 1274 }
1273 1275
1276 void Builtins::Generate_ArrayIncludes(CodeStubAssembler* assembler) {
1277 typedef compiler::Node Node;
1278 typedef CodeStubAssembler::Label Label;
1279 typedef CodeStubAssembler::Variable Variable;
1280
1281 Node* array = assembler->Parameter(0);
1282 Node* search_element = assembler->Parameter(1);
1283 Node* start_from = assembler->Parameter(2);
1284 Node* context = assembler->Parameter(3 + 2);
1285
1286 Node* int32_zero = assembler->Int32Constant(0);
1287 Node* int32_one = assembler->Int32Constant(1);
1288
1289 Node* the_hole = assembler->TheHoleConstant();
1290 Node* undefined = assembler->UndefinedConstant();
1291 Node* heap_number_map = assembler->HeapNumberMapConstant();
1292
1293 Variable len(assembler, MachineRepresentation::kWord32),
Benedikt Meurer 2016/07/19 03:53:19 Nit: Can you rename those to len_var, k_var and n_
1294 k(assembler, MachineRepresentation::kWord32),
1295 n(assembler, MachineRepresentation::kWord32);
Camillo Bruni 2016/07/19 12:08:37 pretty please: use real variable names, k = key, n
1296
1297 Label init_k(assembler), return_true(assembler), return_false(assembler),
1298 call_runtime(assembler);
1299
1300 {
1301 // Take slow path if not a JSArray, if retrieving elements requires
1302 // traversing prototype, or if access checks are required.
1303 Label init_len(assembler);
1304 assembler->BranchIfFastJSArray(array, context, &init_len, &call_runtime);
Benedikt Meurer 2016/07/19 03:53:19 Nit: Move this before the { } block, and start the
1305
1306 assembler->Bind(&init_len);
1307 len.Bind(assembler->SmiToWord(
1308 assembler->LoadObjectField(array, JSArray::kLengthOffset)));
1309
1310 assembler->GotoUnless(assembler->Word32Equal(len.value(), int32_zero),
1311 &init_k);
1312 assembler->Return(assembler->BooleanConstant(false));
1313 }
1314
1315 assembler->Bind(&init_k);
1316 {
1317 Label done(assembler), init_k_smi(assembler), init_k_heap_num(assembler),
1318 init_k_zero(assembler), init_k_n(assembler);
Camillo Bruni 2016/07/19 12:08:37 again, I really like having readable variable name
1319 Callable call_to_integer = CodeFactory::ToInteger(assembler->isolate());
1320 Node* tagged_n = assembler->CallStub(call_to_integer, context, start_from);
1321
1322 assembler->Branch(assembler->WordIsSmi(tagged_n), &init_k_smi,
1323 &init_k_heap_num);
1324
1325 assembler->Bind(&init_k_smi);
1326 {
1327 n.Bind(assembler->SmiToWord32(tagged_n));
1328 assembler->Goto(&init_k_n);
1329 }
1330
1331 assembler->Bind(&init_k_heap_num);
1332 {
1333 Label abort(assembler);
1334 Node* fp_len = assembler->ChangeInt32ToFloat64(len.value());
1335 Node* fp_n = assembler->LoadHeapNumberValue(tagged_n);
1336 assembler->GotoIf(assembler->Float64GreaterThanOrEqual(fp_n, fp_len),
1337 &abort);
Benedikt Meurer 2016/07/19 03:53:19 Instead of the abort label, go to the shared retur
caitp 2016/07/19 19:59:21 The issue with that is that the return_false label
Benedikt Meurer 2016/07/20 03:55:01 That seems suspicious. Maybe a bug in the CodeAsse
danno 2016/07/25 13:53:55 I don't think this is a bug (although I haven't de
1338 n.Bind(assembler->TruncateFloat64ToWord32(fp_n));
Benedikt Meurer 2016/07/19 03:53:18 The fp_n can be outside the valid word32 range. An
caitp 2016/07/19 19:59:21 `len` is pulled directly from kLengthOffset of JSA
Benedikt Meurer 2016/07/20 03:55:01 It could still be negative, i.e. -2^32. Truncating
caitp 2016/07/20 16:07:55 well, here's the rationale for this I came up with
1339 assembler->Goto(&init_k_n);
1340
1341 assembler->Bind(&abort);
1342 assembler->Return(assembler->BooleanConstant(false));
1343 }
1344
1345 assembler->Bind(&init_k_n);
1346 {
1347 Label if_positive(assembler), if_negative(assembler), done(assembler);
1348 assembler->Branch(assembler->Int32LessThan(n.value(), int32_zero),
1349 &if_negative, &if_positive);
1350
1351 assembler->Bind(&if_positive);
1352 {
1353 k.Bind(n.value());
1354 assembler->Goto(&done);
1355 }
1356
1357 assembler->Bind(&if_negative);
1358 {
1359 k.Bind(assembler->Int32Add(len.value(), n.value()));
1360 assembler->Branch(assembler->Int32LessThan(k.value(), int32_zero),
1361 &init_k_zero, &done);
1362 }
1363
1364 assembler->Bind(&init_k_zero);
1365 {
1366 k.Bind(int32_zero);
1367 assembler->Goto(&done);
1368 }
1369
1370 assembler->Bind(&done);
1371 }
1372 }
1373
1374 int32_t element_kinds[] = {
Benedikt Meurer 2016/07/19 03:53:19 Nit: Make this static const. And rename to kElemen
caitp 2016/07/19 19:59:21 Acknowledged. Requires a change to the Switch() pr
Benedikt Meurer 2016/07/20 03:55:01 Acknowledged.
1375 FAST_SMI_ELEMENTS, FAST_HOLEY_SMI_ELEMENTS, FAST_ELEMENTS,
1376 FAST_HOLEY_ELEMENTS, FAST_DOUBLE_ELEMENTS, FAST_HOLEY_DOUBLE_ELEMENTS,
1377 };
1378
1379 Label if_smiorobjects(assembler), if_packed_doubles(assembler),
1380 if_holey_doubles(assembler);
1381 Label* element_kind_handlers[] = {&if_smiorobjects, &if_smiorobjects,
1382 &if_smiorobjects, &if_smiorobjects,
1383 &if_packed_doubles, &if_holey_doubles};
1384
1385 Node* map = assembler->LoadMap(array);
1386 Node* bit_field2 = assembler->LoadMapBitField2(map);
1387 Node* elements_kind =
1388 assembler->BitFieldDecode<Map::ElementsKindBits>(bit_field2);
1389 Node* elements = assembler->LoadElements(array);
1390 assembler->Switch(elements_kind, &return_false, element_kinds,
Benedikt Meurer 2016/07/19 03:53:19 Nice idea!
1391 element_kind_handlers, arraysize(element_kinds));
1392
1393 assembler->Bind(&if_smiorobjects);
1394 {
1395 Variable search_num(assembler, MachineRepresentation::kFloat64);
1396 Label ident_loop(assembler, &k), heap_num_loop(assembler, &search_num),
1397 string_loop(assembler, &k), simd_loop(assembler),
1398 undef_loop(assembler, &k), not_smi(assembler), not_heap_num(assembler);
1399
1400 assembler->GotoUnless(assembler->WordIsSmi(search_element), &not_smi);
1401 search_num.Bind(assembler->SmiToFloat64(search_element));
1402 assembler->Goto(&heap_num_loop);
1403
1404 assembler->Bind(&not_smi);
1405 assembler->GotoIf(assembler->WordEqual(search_element, undefined),
1406 &undef_loop);
1407 Node* map = assembler->LoadMap(search_element);
1408 assembler->GotoIf(assembler->WordNotEqual(map, heap_number_map),
1409 &not_heap_num);
1410 search_num.Bind(assembler->LoadHeapNumberValue(search_element));
1411 assembler->Goto(&heap_num_loop);
1412
1413 assembler->Bind(&not_heap_num);
1414 Node* search_type = assembler->LoadMapInstanceType(map);
1415 assembler->GotoIf(
1416 assembler->Int32LessThan(
1417 search_type, assembler->Int32Constant(FIRST_NONSTRING_TYPE)),
1418 &string_loop);
1419 assembler->GotoIf(
1420 assembler->WordEqual(search_type,
1421 assembler->Int32Constant(SIMD128_VALUE_TYPE)),
1422 &simd_loop);
1423 assembler->Goto(&ident_loop);
1424
1425 assembler->Bind(&ident_loop);
1426 {
1427 assembler->GotoUnless(assembler->Int32LessThan(k.value(), len.value()),
1428 &return_false);
1429 Node* element_k = assembler->LoadFixedArrayElement(elements, k.value());
1430 assembler->GotoIf(assembler->WordEqual(element_k, search_element),
1431 &return_true);
1432
1433 k.Bind(assembler->Int32Add(k.value(), int32_one));
1434 assembler->Goto(&ident_loop);
1435 }
1436
1437 assembler->Bind(&undef_loop);
1438 {
1439 assembler->GotoUnless(assembler->Int32LessThan(k.value(), len.value()),
1440 &return_false);
1441 Node* element_k = assembler->LoadFixedArrayElement(elements, k.value());
1442 assembler->GotoIf(assembler->WordEqual(element_k, undefined),
1443 &return_true);
1444 assembler->GotoIf(assembler->WordEqual(element_k, the_hole),
1445 &return_true);
1446
1447 k.Bind(assembler->Int32Add(k.value(), int32_one));
1448 assembler->Goto(&undef_loop);
1449 }
1450
1451 assembler->Bind(&heap_num_loop);
1452 {
1453 Label nan_loop(assembler, &k), not_nan_loop(assembler, &k);
1454 assembler->BranchIfFloat64IsNaN(search_num.value(), &nan_loop,
1455 &not_nan_loop);
1456
1457 assembler->Bind(&not_nan_loop);
1458 {
1459 Label continue_loop(assembler), not_smi(assembler);
1460 assembler->GotoUnless(assembler->Int32LessThan(k.value(), len.value()),
1461 &return_false);
1462 Node* element_k = assembler->LoadFixedArrayElement(elements, k.value());
1463 assembler->GotoUnless(assembler->WordIsSmi(element_k), &not_smi);
1464 assembler->Branch(
1465 assembler->Float64Equal(search_num.value(),
1466 assembler->SmiToFloat64(element_k)),
1467 &return_true, &continue_loop);
1468
1469 assembler->Bind(&not_smi);
1470 assembler->GotoIf(assembler->WordNotEqual(assembler->LoadMap(element_k),
1471 heap_number_map),
1472 &continue_loop);
1473 assembler->BranchIfFloat64Equal(
1474 search_num.value(), assembler->LoadHeapNumberValue(element_k),
1475 &return_true, &continue_loop);
1476
1477 assembler->Bind(&continue_loop);
1478 k.Bind(assembler->Int32Add(k.value(), int32_one));
1479 assembler->Goto(&not_nan_loop);
1480 }
1481
1482 assembler->Bind(&nan_loop);
1483 {
1484 Label continue_loop(assembler);
1485 assembler->GotoUnless(assembler->Int32LessThan(k.value(), len.value()),
1486 &return_false);
1487 Node* element_k = assembler->LoadFixedArrayElement(elements, k.value());
1488 assembler->GotoIf(assembler->WordIsSmi(element_k), &continue_loop);
1489 assembler->GotoIf(assembler->WordNotEqual(assembler->LoadMap(element_k),
1490 heap_number_map),
1491 &continue_loop);
1492 assembler->BranchIfFloat64IsNaN(
1493 assembler->LoadHeapNumberValue(element_k), &return_true,
1494 &continue_loop);
1495
1496 assembler->Bind(&continue_loop);
1497 k.Bind(assembler->Int32Add(k.value(), int32_one));
1498 assembler->Goto(&nan_loop);
1499 }
1500 }
1501
1502 assembler->Bind(&string_loop);
1503 {
1504 Label continue_loop(assembler);
1505 assembler->GotoUnless(assembler->Int32LessThan(k.value(), len.value()),
1506 &return_false);
1507 Node* element_k = assembler->LoadFixedArrayElement(elements, k.value());
1508 assembler->GotoIf(assembler->WordIsSmi(element_k), &continue_loop);
1509 assembler->GotoUnless(assembler->Int32LessThan(
1510 assembler->LoadMapInstanceType(element_k),
1511 assembler->Int32Constant(FIRST_NONSTRING_TYPE)),
1512 &continue_loop);
1513
1514 Callable callable = CodeFactory::StringEqual(assembler->isolate());
Benedikt Meurer 2016/07/19 03:53:18 Please add a TODO here, that at some point we want
caitp 2016/07/19 19:59:21 Acknowledged.
1515 Node* result =
1516 assembler->CallStub(callable, context, search_element, element_k);
1517 assembler->Branch(
1518 assembler->WordEqual(assembler->BooleanConstant(true), result),
1519 &return_true, &continue_loop);
1520
1521 assembler->Bind(&continue_loop);
1522 k.Bind(assembler->Int32Add(k.value(), int32_one));
1523 assembler->Goto(&string_loop);
1524 }
1525
1526 assembler->Bind(&simd_loop);
1527 {
1528 Label continue_loop(assembler, &k), loop_body(assembler, &k);
1529 Node* map = assembler->LoadMap(search_element);
1530
1531 assembler->Goto(&loop_body);
1532 assembler->Bind(&loop_body);
1533 assembler->GotoUnless(assembler->Int32LessThan(k.value(), len.value()),
1534 &return_false);
1535
1536 Node* element_k = assembler->LoadFixedArrayElement(elements, k.value());
1537 assembler->GotoIf(assembler->WordIsSmi(element_k), &continue_loop);
1538
1539 Node* map_k = assembler->LoadMap(element_k);
1540 assembler->BranchIfSimd128Equal(search_element, map, element_k, map_k,
1541 &return_true, &continue_loop);
1542
1543 assembler->Bind(&continue_loop);
1544 k.Bind(assembler->Int32Add(k.value(), int32_one));
1545 assembler->Goto(&loop_body);
1546 }
1547 }
1548
1549 assembler->Bind(&if_packed_doubles);
1550 {
1551 Label nan_loop(assembler, &k), not_nan_loop(assembler, &k),
1552 hole_loop(assembler, &k), search_notnan(assembler);
1553 Variable search_num(assembler, MachineRepresentation::kFloat64);
1554
1555 assembler->GotoUnless(assembler->WordIsSmi(search_element), &search_notnan);
1556 search_num.Bind(assembler->SmiToFloat64(search_element));
1557 assembler->Goto(&not_nan_loop);
1558
1559 assembler->Bind(&search_notnan);
1560 assembler->GotoIf(assembler->WordNotEqual(
1561 assembler->LoadMap(search_element), heap_number_map),
1562 &return_false);
1563
1564 search_num.Bind(assembler->LoadHeapNumberValue(search_element));
1565
1566 assembler->BranchIfFloat64IsNaN(search_num.value(), &nan_loop,
1567 &not_nan_loop);
1568
1569 // Search for HeapNumber
1570 assembler->Bind(&not_nan_loop);
1571 {
1572 Label continue_loop(assembler);
1573 assembler->GotoUnless(assembler->Int32LessThan(k.value(), len.value()),
1574 &return_false);
1575 Node* element_k = assembler->LoadFixedDoubleArrayElement(
1576 elements, k.value(), MachineType::Float64());
1577 assembler->BranchIfFloat64Equal(element_k, search_num.value(),
1578 &return_true, &continue_loop);
1579 assembler->Bind(&continue_loop);
1580 k.Bind(assembler->Int32Add(k.value(), int32_one));
1581 assembler->Goto(&not_nan_loop);
1582 }
1583
1584 // Search for NaN
1585 assembler->Bind(&nan_loop);
1586 {
1587 Label continue_loop(assembler);
1588 assembler->GotoUnless(assembler->Int32LessThan(k.value(), len.value()),
1589 &return_false);
1590 Node* element_k = assembler->LoadFixedDoubleArrayElement(
1591 elements, k.value(), MachineType::Float64());
1592 assembler->BranchIfFloat64IsNaN(element_k, &return_true, &continue_loop);
1593 assembler->Bind(&continue_loop);
1594 k.Bind(assembler->Int32Add(k.value(), int32_one));
1595 assembler->Goto(&nan_loop);
1596 }
1597 }
1598
1599 assembler->Bind(&if_holey_doubles);
1600 {
1601 Label nan_loop(assembler, &k), not_nan_loop(assembler, &k),
1602 hole_loop(assembler, &k), search_notnan(assembler);
1603 Variable search_num(assembler, MachineRepresentation::kFloat64);
1604
1605 assembler->GotoUnless(assembler->WordIsSmi(search_element), &search_notnan);
1606 search_num.Bind(assembler->SmiToFloat64(search_element));
1607 assembler->Goto(&not_nan_loop);
1608
1609 assembler->Bind(&search_notnan);
1610 assembler->GotoIf(assembler->WordEqual(search_element, undefined),
1611 &hole_loop);
1612 assembler->GotoIf(assembler->WordNotEqual(
1613 assembler->LoadMap(search_element), heap_number_map),
1614 &return_false);
1615
1616 search_num.Bind(assembler->LoadHeapNumberValue(search_element));
1617
1618 assembler->BranchIfFloat64IsNaN(search_num.value(), &nan_loop,
1619 &not_nan_loop);
1620
1621 // Search for HeapNumber
1622 assembler->Bind(&not_nan_loop);
1623 {
1624 Label continue_loop(assembler);
1625 assembler->GotoUnless(assembler->Int32LessThan(k.value(), len.value()),
1626 &return_false);
1627
1628 if (kPointerSize == kDoubleSize) {
Benedikt Meurer 2016/07/19 03:53:19 You don't need this distinction. You can always co
caitp 2016/07/19 19:59:21 Acknowledged. This pattern is used elsewhere thoug
Benedikt Meurer 2016/07/20 03:55:01 Hm, ok, we could also simplify that.
1629 Node* element = assembler->LoadFixedDoubleArrayElement(
1630 elements, k.value(), MachineType::Uint64());
1631 Node* the_hole = assembler->Int64Constant(kHoleNanInt64);
1632 assembler->GotoIf(assembler->Word64Equal(element, the_hole),
1633 &continue_loop);
1634 } else {
1635 Node* element_upper = assembler->LoadFixedDoubleArrayElement(
1636 elements, k.value(), MachineType::Uint32(),
1637 kIeeeDoubleExponentWordOffset);
1638 assembler->GotoIf(
1639 assembler->Word32Equal(element_upper,
1640 assembler->Int32Constant(kHoleNanUpper32)),
1641 &continue_loop);
1642 }
1643
1644 Node* element_k = assembler->LoadFixedDoubleArrayElement(
1645 elements, k.value(), MachineType::Float64());
1646 assembler->BranchIfFloat64Equal(element_k, search_num.value(),
1647 &return_true, &continue_loop);
1648 assembler->Bind(&continue_loop);
1649 k.Bind(assembler->Int32Add(k.value(), int32_one));
1650 assembler->Goto(&not_nan_loop);
1651 }
1652
1653 // Search for NaN
1654 assembler->Bind(&nan_loop);
1655 {
1656 Label continue_loop(assembler);
1657 assembler->GotoUnless(assembler->Int32LessThan(k.value(), len.value()),
1658 &return_false);
1659
1660 if (kPointerSize == kDoubleSize) {
Benedikt Meurer 2016/07/19 03:53:19 See above.
1661 Node* element = assembler->LoadFixedDoubleArrayElement(
1662 elements, k.value(), MachineType::Uint64());
1663 Node* the_hole = assembler->Int64Constant(kHoleNanInt64);
1664 assembler->GotoIf(assembler->Word64Equal(element, the_hole),
1665 &continue_loop);
1666 } else {
1667 Node* element_upper = assembler->LoadFixedDoubleArrayElement(
1668 elements, k.value(), MachineType::Uint32(),
1669 kIeeeDoubleExponentWordOffset);
1670 assembler->GotoIf(
1671 assembler->Word32Equal(element_upper,
1672 assembler->Int32Constant(kHoleNanUpper32)),
1673 &continue_loop);
1674 }
1675
1676 Node* element_k = assembler->LoadFixedDoubleArrayElement(
1677 elements, k.value(), MachineType::Float64());
1678 assembler->BranchIfFloat64IsNaN(element_k, &return_true, &continue_loop);
1679 assembler->Bind(&continue_loop);
1680 k.Bind(assembler->Int32Add(k.value(), int32_one));
1681 assembler->Goto(&nan_loop);
1682 }
1683
1684 // Search for the Hole
1685 assembler->Bind(&hole_loop);
1686 {
1687 assembler->GotoUnless(assembler->Int32LessThan(k.value(), len.value()),
1688 &return_false);
1689
1690 if (kPointerSize == kDoubleSize) {
1691 Node* element = assembler->LoadFixedDoubleArrayElement(
1692 elements, k.value(), MachineType::Uint64());
1693 Node* the_hole = assembler->Int64Constant(kHoleNanInt64);
1694 assembler->GotoIf(assembler->Word64Equal(element, the_hole),
1695 &return_true);
1696 } else {
1697 Node* element_upper = assembler->LoadFixedDoubleArrayElement(
1698 elements, k.value(), MachineType::Uint32(),
1699 kIeeeDoubleExponentWordOffset);
1700 assembler->GotoIf(
1701 assembler->Word32Equal(element_upper,
1702 assembler->Int32Constant(kHoleNanUpper32)),
1703 &return_true);
1704 }
1705
1706 k.Bind(assembler->Int32Add(k.value(), int32_one));
1707 assembler->Goto(&hole_loop);
1708 }
1709 }
1710
1711 assembler->Bind(&return_true);
1712 assembler->Return(assembler->BooleanConstant(true));
1713
1714 assembler->Bind(&return_false);
1715 assembler->Return(assembler->BooleanConstant(false));
1716
1717 assembler->Bind(&call_runtime);
1718 assembler->Return(assembler->CallRuntime(Runtime::kArrayIncludes_Slow,
1719 context, array, search_element,
1720 start_from));
1721 }
1722
1274 } // namespace internal 1723 } // namespace internal
1275 } // namespace v8 1724 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698