OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/code-stubs.h" | 7 #include "src/code-stubs.h" |
8 #include "src/field-index.h" | 8 #include "src/field-index.h" |
9 #include "src/hydrogen.h" | 9 #include "src/hydrogen.h" |
10 #include "src/lithium.h" | 10 #include "src/lithium.h" |
(...skipping 1372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1383 } | 1383 } |
1384 | 1384 |
1385 | 1385 |
1386 template<> | 1386 template<> |
1387 HValue* CodeStubGraphBuilder<KeyedLoadDictionaryElementStub>::BuildCodeStub() { | 1387 HValue* CodeStubGraphBuilder<KeyedLoadDictionaryElementStub>::BuildCodeStub() { |
1388 HValue* receiver = GetParameter(0); | 1388 HValue* receiver = GetParameter(0); |
1389 HValue* key = GetParameter(1); | 1389 HValue* key = GetParameter(1); |
1390 | 1390 |
1391 Add<HCheckSmi>(key); | 1391 Add<HCheckSmi>(key); |
1392 | 1392 |
1393 return BuildUncheckedDictionaryElementLoad(receiver, key); | 1393 HValue* elements = AddLoadElements(receiver); |
| 1394 |
| 1395 HValue* hash = BuildElementIndexHash(key); |
| 1396 |
| 1397 return BuildUncheckedDictionaryElementLoad(receiver, elements, key, hash); |
1394 } | 1398 } |
1395 | 1399 |
1396 | 1400 |
1397 Handle<Code> KeyedLoadDictionaryElementStub::GenerateCode() { | 1401 Handle<Code> KeyedLoadDictionaryElementStub::GenerateCode() { |
1398 return DoGenerateCode(this); | 1402 return DoGenerateCode(this); |
1399 } | 1403 } |
1400 | 1404 |
1401 | 1405 |
1402 template<> | 1406 template<> |
1403 HValue* CodeStubGraphBuilder<RegExpConstructResultStub>::BuildCodeStub() { | 1407 HValue* CodeStubGraphBuilder<RegExpConstructResultStub>::BuildCodeStub() { |
1404 // Determine the parameters. | 1408 // Determine the parameters. |
1405 HValue* length = GetParameter(RegExpConstructResultStub::kLength); | 1409 HValue* length = GetParameter(RegExpConstructResultStub::kLength); |
1406 HValue* index = GetParameter(RegExpConstructResultStub::kIndex); | 1410 HValue* index = GetParameter(RegExpConstructResultStub::kIndex); |
1407 HValue* input = GetParameter(RegExpConstructResultStub::kInput); | 1411 HValue* input = GetParameter(RegExpConstructResultStub::kInput); |
1408 | 1412 |
1409 info()->MarkMustNotHaveEagerFrame(); | 1413 info()->MarkMustNotHaveEagerFrame(); |
1410 | 1414 |
1411 return BuildRegExpConstructResult(length, index, input); | 1415 return BuildRegExpConstructResult(length, index, input); |
1412 } | 1416 } |
1413 | 1417 |
1414 | 1418 |
1415 Handle<Code> RegExpConstructResultStub::GenerateCode() { | 1419 Handle<Code> RegExpConstructResultStub::GenerateCode() { |
1416 return DoGenerateCode(this); | 1420 return DoGenerateCode(this); |
1417 } | 1421 } |
1418 | 1422 |
1419 | 1423 |
| 1424 template <> |
| 1425 class CodeStubGraphBuilder<KeyedLoadGenericElementStub> |
| 1426 : public CodeStubGraphBuilderBase { |
| 1427 public: |
| 1428 CodeStubGraphBuilder(Isolate* isolate, |
| 1429 KeyedLoadGenericElementStub* stub) |
| 1430 : CodeStubGraphBuilderBase(isolate, stub) {} |
| 1431 |
| 1432 protected: |
| 1433 virtual HValue* BuildCodeStub(); |
| 1434 |
| 1435 void BuildElementsKindLimitCheck(HGraphBuilder::IfBuilder* if_builder, |
| 1436 HValue* bit_field2, |
| 1437 ElementsKind kind); |
| 1438 |
| 1439 void BuildFastElementLoad(HGraphBuilder::IfBuilder* if_builder, |
| 1440 HValue* receiver, |
| 1441 HValue* key, |
| 1442 HValue* instance_type, |
| 1443 HValue* bit_field2, |
| 1444 ElementsKind kind); |
| 1445 |
| 1446 void BuildExternalElementLoad(HGraphBuilder::IfBuilder* if_builder, |
| 1447 HValue* receiver, |
| 1448 HValue* key, |
| 1449 HValue* instance_type, |
| 1450 HValue* bit_field2, |
| 1451 ElementsKind kind); |
| 1452 |
| 1453 KeyedLoadGenericElementStub* casted_stub() { |
| 1454 return static_cast<KeyedLoadGenericElementStub*>(stub()); |
| 1455 } |
| 1456 }; |
| 1457 |
| 1458 |
| 1459 void CodeStubGraphBuilder< |
| 1460 KeyedLoadGenericElementStub>::BuildElementsKindLimitCheck( |
| 1461 HGraphBuilder::IfBuilder* if_builder, |
| 1462 HValue* bit_field2, |
| 1463 ElementsKind kind) { |
| 1464 ElementsKind next_kind = static_cast<ElementsKind>(kind + 1); |
| 1465 HValue* kind_limit = Add<HConstant>( |
| 1466 static_cast<int>(Map::ElementsKindBits::encode(next_kind))); |
| 1467 |
| 1468 if_builder->If<HCompareNumericAndBranch>(bit_field2, kind_limit, Token::LT); |
| 1469 if_builder->Then(); |
| 1470 } |
| 1471 |
| 1472 |
| 1473 void CodeStubGraphBuilder<KeyedLoadGenericElementStub>::BuildFastElementLoad( |
| 1474 HGraphBuilder::IfBuilder* if_builder, |
| 1475 HValue* receiver, |
| 1476 HValue* key, |
| 1477 HValue* instance_type, |
| 1478 HValue* bit_field2, |
| 1479 ElementsKind kind) { |
| 1480 ASSERT(!IsExternalArrayElementsKind(kind)); |
| 1481 |
| 1482 BuildElementsKindLimitCheck(if_builder, bit_field2, kind); |
| 1483 |
| 1484 IfBuilder js_array_check(this); |
| 1485 js_array_check.If<HCompareNumericAndBranch>( |
| 1486 instance_type, Add<HConstant>(JS_ARRAY_TYPE), Token::EQ); |
| 1487 js_array_check.Then(); |
| 1488 Push(BuildUncheckedMonomorphicElementAccess(receiver, key, NULL, |
| 1489 true, kind, |
| 1490 LOAD, NEVER_RETURN_HOLE, |
| 1491 STANDARD_STORE)); |
| 1492 js_array_check.Else(); |
| 1493 Push(BuildUncheckedMonomorphicElementAccess(receiver, key, NULL, |
| 1494 false, kind, |
| 1495 LOAD, NEVER_RETURN_HOLE, |
| 1496 STANDARD_STORE)); |
| 1497 js_array_check.End(); |
| 1498 } |
| 1499 |
| 1500 |
| 1501 void CodeStubGraphBuilder< |
| 1502 KeyedLoadGenericElementStub>::BuildExternalElementLoad( |
| 1503 HGraphBuilder::IfBuilder* if_builder, |
| 1504 HValue* receiver, |
| 1505 HValue* key, |
| 1506 HValue* instance_type, |
| 1507 HValue* bit_field2, |
| 1508 ElementsKind kind) { |
| 1509 ASSERT(IsExternalArrayElementsKind(kind)); |
| 1510 |
| 1511 BuildElementsKindLimitCheck(if_builder, bit_field2, kind); |
| 1512 |
| 1513 Push(BuildUncheckedMonomorphicElementAccess(receiver, key, NULL, |
| 1514 false, kind, |
| 1515 LOAD, NEVER_RETURN_HOLE, |
| 1516 STANDARD_STORE)); |
| 1517 } |
| 1518 |
| 1519 |
| 1520 HValue* CodeStubGraphBuilder<KeyedLoadGenericElementStub>::BuildCodeStub() { |
| 1521 HValue* receiver = GetParameter(0); |
| 1522 HValue* key = GetParameter(1); |
| 1523 |
| 1524 // Split into a smi/integer case and unique string case. |
| 1525 HIfContinuation index_name_split_continuation(graph()->CreateBasicBlock(), |
| 1526 graph()->CreateBasicBlock()); |
| 1527 |
| 1528 BuildKeyedIndexCheck(key, &index_name_split_continuation); |
| 1529 |
| 1530 IfBuilder index_name_split(this, &index_name_split_continuation); |
| 1531 index_name_split.Then(); |
| 1532 { |
| 1533 // Key is an index (number) |
| 1534 key = Pop(); |
| 1535 |
| 1536 int bit_field_mask = (1 << Map::kIsAccessCheckNeeded) | |
| 1537 (1 << Map::kHasIndexedInterceptor); |
| 1538 BuildJSObjectCheck(receiver, bit_field_mask); |
| 1539 |
| 1540 HValue* map = Add<HLoadNamedField>(receiver, static_cast<HValue*>(NULL), |
| 1541 HObjectAccess::ForMap()); |
| 1542 |
| 1543 HValue* instance_type = |
| 1544 Add<HLoadNamedField>(map, static_cast<HValue*>(NULL), |
| 1545 HObjectAccess::ForMapInstanceType()); |
| 1546 |
| 1547 HValue* bit_field2 = Add<HLoadNamedField>(map, |
| 1548 static_cast<HValue*>(NULL), |
| 1549 HObjectAccess::ForMapBitField2()); |
| 1550 |
| 1551 IfBuilder kind_if(this); |
| 1552 BuildFastElementLoad(&kind_if, receiver, key, instance_type, bit_field2, |
| 1553 FAST_HOLEY_ELEMENTS); |
| 1554 |
| 1555 kind_if.Else(); |
| 1556 { |
| 1557 BuildFastElementLoad(&kind_if, receiver, key, instance_type, bit_field2, |
| 1558 FAST_HOLEY_DOUBLE_ELEMENTS); |
| 1559 } |
| 1560 kind_if.Else(); |
| 1561 |
| 1562 // The DICTIONARY_ELEMENTS check generates a "kind_if.Then" |
| 1563 BuildElementsKindLimitCheck(&kind_if, bit_field2, DICTIONARY_ELEMENTS); |
| 1564 { |
| 1565 HValue* elements = AddLoadElements(receiver); |
| 1566 |
| 1567 HValue* hash = BuildElementIndexHash(key); |
| 1568 |
| 1569 Push(BuildUncheckedDictionaryElementLoad(receiver, elements, key, hash)); |
| 1570 } |
| 1571 kind_if.Else(); |
| 1572 |
| 1573 // The SLOPPY_ARGUMENTS_ELEMENTS check generates a "kind_if.Then" |
| 1574 BuildElementsKindLimitCheck(&kind_if, bit_field2, |
| 1575 SLOPPY_ARGUMENTS_ELEMENTS); |
| 1576 // Non-strict elements are not handled. |
| 1577 Add<HDeoptimize>("non-strict elements in KeyedLoadGenericElementStub", |
| 1578 Deoptimizer::EAGER); |
| 1579 Push(graph()->GetConstant0()); |
| 1580 |
| 1581 kind_if.Else(); |
| 1582 BuildExternalElementLoad(&kind_if, receiver, key, instance_type, bit_field2, |
| 1583 EXTERNAL_INT8_ELEMENTS); |
| 1584 |
| 1585 kind_if.Else(); |
| 1586 BuildExternalElementLoad(&kind_if, receiver, key, instance_type, bit_field2, |
| 1587 EXTERNAL_UINT8_ELEMENTS); |
| 1588 |
| 1589 kind_if.Else(); |
| 1590 BuildExternalElementLoad(&kind_if, receiver, key, instance_type, bit_field2, |
| 1591 EXTERNAL_INT16_ELEMENTS); |
| 1592 |
| 1593 kind_if.Else(); |
| 1594 BuildExternalElementLoad(&kind_if, receiver, key, instance_type, bit_field2, |
| 1595 EXTERNAL_UINT16_ELEMENTS); |
| 1596 |
| 1597 kind_if.Else(); |
| 1598 BuildExternalElementLoad(&kind_if, receiver, key, instance_type, bit_field2, |
| 1599 EXTERNAL_INT32_ELEMENTS); |
| 1600 |
| 1601 kind_if.Else(); |
| 1602 BuildExternalElementLoad(&kind_if, receiver, key, instance_type, bit_field2, |
| 1603 EXTERNAL_UINT32_ELEMENTS); |
| 1604 |
| 1605 kind_if.Else(); |
| 1606 BuildExternalElementLoad(&kind_if, receiver, key, instance_type, bit_field2, |
| 1607 EXTERNAL_FLOAT32_ELEMENTS); |
| 1608 |
| 1609 kind_if.Else(); |
| 1610 BuildExternalElementLoad(&kind_if, receiver, key, instance_type, bit_field2, |
| 1611 EXTERNAL_FLOAT64_ELEMENTS); |
| 1612 |
| 1613 kind_if.Else(); |
| 1614 BuildExternalElementLoad(&kind_if, receiver, key, instance_type, bit_field2, |
| 1615 EXTERNAL_UINT8_CLAMPED_ELEMENTS); |
| 1616 |
| 1617 kind_if.ElseDeopt("ElementsKind unhandled in KeyedLoadGenericElementStub"); |
| 1618 |
| 1619 kind_if.End(); |
| 1620 } |
| 1621 index_name_split.Else(); |
| 1622 { |
| 1623 // Key is a unique string. |
| 1624 key = Pop(); |
| 1625 |
| 1626 int bit_field_mask = (1 << Map::kIsAccessCheckNeeded) | |
| 1627 (1 << Map::kHasNamedInterceptor); |
| 1628 BuildJSObjectCheck(receiver, bit_field_mask); |
| 1629 |
| 1630 HIfContinuation continuation; |
| 1631 BuildTestForDictionaryProperties(receiver, &continuation); |
| 1632 IfBuilder if_dict_properties(this, &continuation); |
| 1633 if_dict_properties.Then(); |
| 1634 { |
| 1635 // Key is string, properties are dictionary mode |
| 1636 BuildNonGlobalObjectCheck(receiver); |
| 1637 |
| 1638 HValue* properties = Add<HLoadNamedField>( |
| 1639 receiver, static_cast<HValue*>(NULL), |
| 1640 HObjectAccess::ForPropertiesPointer()); |
| 1641 |
| 1642 HValue* hash = |
| 1643 Add<HLoadNamedField>(key, static_cast<HValue*>(NULL), |
| 1644 HObjectAccess::ForNameHashField()); |
| 1645 |
| 1646 HValue* value = BuildUncheckedDictionaryElementLoad(receiver, |
| 1647 properties, |
| 1648 key, |
| 1649 hash); |
| 1650 Push(value); |
| 1651 } |
| 1652 if_dict_properties.Else(); |
| 1653 { |
| 1654 // Key is string, properties are fast mode |
| 1655 HValue* hash = BuildKeyedLookupCacheHash(receiver, key); |
| 1656 |
| 1657 ExternalReference cache_keys_ref = |
| 1658 ExternalReference::keyed_lookup_cache_keys(isolate()); |
| 1659 HValue* cache_keys = Add<HConstant>(cache_keys_ref); |
| 1660 |
| 1661 HValue* map = Add<HLoadNamedField>(receiver, static_cast<HValue*>(NULL), |
| 1662 HObjectAccess::ForMap()); |
| 1663 HValue* base_index = AddUncasted<HMul>(hash, Add<HConstant>(2)); |
| 1664 base_index->ClearFlag(HValue::kCanOverflow); |
| 1665 |
| 1666 IfBuilder lookup_if(this); |
| 1667 for (int probe = 0; probe < KeyedLookupCache::kEntriesPerBucket; |
| 1668 ++probe) { |
| 1669 int probe_base = probe * KeyedLookupCache::kEntryLength; |
| 1670 HValue* map_index = AddUncasted<HAdd>(base_index, |
| 1671 Add<HConstant>(probe_base + KeyedLookupCache::kMapIndex)); |
| 1672 map_index->ClearFlag(HValue::kCanOverflow); |
| 1673 HValue* key_index = AddUncasted<HAdd>(base_index, |
| 1674 Add<HConstant>(probe_base + KeyedLookupCache::kKeyIndex)); |
| 1675 key_index->ClearFlag(HValue::kCanOverflow); |
| 1676 HValue* map_to_check = Add<HLoadKeyed>(cache_keys, |
| 1677 map_index, |
| 1678 static_cast<HValue*>(NULL), |
| 1679 FAST_ELEMENTS, |
| 1680 NEVER_RETURN_HOLE, 0); |
| 1681 lookup_if.If<HCompareObjectEqAndBranch>(map_to_check, map); |
| 1682 lookup_if.And(); |
| 1683 HValue* key_to_check = Add<HLoadKeyed>(cache_keys, |
| 1684 key_index, |
| 1685 static_cast<HValue*>(NULL), |
| 1686 FAST_ELEMENTS, |
| 1687 NEVER_RETURN_HOLE, 0); |
| 1688 lookup_if.If<HCompareObjectEqAndBranch>(key_to_check, key); |
| 1689 lookup_if.Then(); |
| 1690 { |
| 1691 ExternalReference cache_field_offsets_ref = |
| 1692 ExternalReference::keyed_lookup_cache_field_offsets(isolate()); |
| 1693 HValue* cache_field_offsets = Add<HConstant>(cache_field_offsets_ref); |
| 1694 HValue* index = AddUncasted<HAdd>(hash, |
| 1695 Add<HConstant>(probe)); |
| 1696 index->ClearFlag(HValue::kCanOverflow); |
| 1697 HValue* property_index = Add<HLoadKeyed>(cache_field_offsets, |
| 1698 index, |
| 1699 static_cast<HValue*>(NULL), |
| 1700 EXTERNAL_INT32_ELEMENTS, |
| 1701 NEVER_RETURN_HOLE, 0); |
| 1702 Push(property_index); |
| 1703 } |
| 1704 lookup_if.Else(); |
| 1705 } |
| 1706 Add<HDeoptimize>("KeyedLoad fall-back", Deoptimizer::EAGER); |
| 1707 Push(graph()->GetConstant0()); |
| 1708 lookup_if.End(); |
| 1709 Push(Add<HLoadFieldByIndex>(receiver, Pop())); |
| 1710 } |
| 1711 if_dict_properties.End(); |
| 1712 } |
| 1713 index_name_split.End(); |
| 1714 |
| 1715 return Pop(); |
| 1716 } |
| 1717 |
| 1718 |
| 1719 Handle<Code> KeyedLoadGenericElementStub::GenerateCode() { |
| 1720 return DoGenerateCode(this); |
| 1721 } |
| 1722 |
| 1723 |
1420 } } // namespace v8::internal | 1724 } } // namespace v8::internal |
OLD | NEW |