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 BuildReceiverCheck(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 BuildReceiverCheck(receiver, bit_field_mask); | |
Toon Verwaest
2014/06/10 11:33:43
Any reason why you don't put this outside of the i
Toon Verwaest
2014/06/10 11:37:07
Aarg, you already indicated this in the comments o
| |
1629 | |
1630 HIfContinuation continuation; | |
1631 BuildCheckForDictionaryProperties(receiver, &continuation); | |
1632 IfBuilder if_dict_properties(this, &continuation); | |
1633 if_dict_properties.Then(); | |
1634 { | |
1635 // Key is string, properties are dictionary mode | |
1636 BuildGlobalInstanceTypeCheck(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 HValue* map_index = AddUncasted<HAdd>(base_index, | |
1670 Add<HConstant>(probe * 2)); | |
Toon Verwaest
2014/06/10 11:33:43
* KeyedLookupCache::kEntryLength + KeyedLookupCach
danno
2014/06/11 08:08:00
Done.
| |
1671 map_index->ClearFlag(HValue::kCanOverflow); | |
1672 HValue* key_index = AddUncasted<HAdd>(base_index, | |
1673 Add<HConstant>(probe * 2 + 1)); | |
Toon Verwaest
2014/06/10 11:33:43
+ KeyedLookupCache::kKeyIndex
danno
2014/06/11 08:08:00
Done.
| |
1674 key_index->ClearFlag(HValue::kCanOverflow); | |
1675 HValue* map_to_check = Add<HLoadKeyed>(cache_keys, | |
1676 map_index, | |
1677 static_cast<HValue*>(NULL), | |
1678 FAST_ELEMENTS, | |
1679 NEVER_RETURN_HOLE, 0); | |
1680 lookup_if.If<HCompareObjectEqAndBranch>(map_to_check, map); | |
1681 lookup_if.And(); | |
1682 HValue* key_to_check = Add<HLoadKeyed>(cache_keys, | |
1683 key_index, | |
1684 static_cast<HValue*>(NULL), | |
1685 FAST_ELEMENTS, | |
1686 NEVER_RETURN_HOLE, 0); | |
1687 lookup_if.If<HCompareObjectEqAndBranch>(key_to_check, key); | |
1688 lookup_if.Then(); | |
1689 { | |
1690 ExternalReference cache_field_offsets_ref = | |
1691 ExternalReference::keyed_lookup_cache_field_offsets(isolate()); | |
1692 HValue* cache_field_offsets = Add<HConstant>(cache_field_offsets_ref); | |
1693 HValue* index = AddUncasted<HAdd>(hash, | |
1694 Add<HConstant>(probe)); | |
1695 index->ClearFlag(HValue::kCanOverflow); | |
1696 HValue* property_index = Add<HLoadKeyed>(cache_field_offsets, | |
1697 index, | |
1698 static_cast<HValue*>(NULL), | |
1699 EXTERNAL_INT32_ELEMENTS, | |
1700 NEVER_RETURN_HOLE, 0); | |
1701 Push(property_index); | |
1702 } | |
1703 lookup_if.Else(); | |
1704 } | |
1705 Add<HDeoptimize>("KeyedLoad fall-back", Deoptimizer::EAGER); | |
1706 Push(graph()->GetConstant0()); | |
1707 lookup_if.End(); | |
1708 Push(Add<HLoadFieldByIndex>(receiver, Pop())); | |
1709 } | |
1710 if_dict_properties.End(); | |
1711 } | |
1712 index_name_split.End(); | |
1713 | |
1714 return Pop(); | |
1715 } | |
1716 | |
1717 | |
1718 Handle<Code> KeyedLoadGenericElementStub::GenerateCode() { | |
1719 return DoGenerateCode(this); | |
1720 } | |
1721 | |
1722 | |
1420 } } // namespace v8::internal | 1723 } } // namespace v8::internal |
OLD | NEW |