| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 692 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 703 | 703 |
| 704 DEFINE_GET_CONSTANT(Undefined, undefined, HType::Tagged(), false) | 704 DEFINE_GET_CONSTANT(Undefined, undefined, HType::Tagged(), false) |
| 705 DEFINE_GET_CONSTANT(True, true, HType::Boolean(), true) | 705 DEFINE_GET_CONSTANT(True, true, HType::Boolean(), true) |
| 706 DEFINE_GET_CONSTANT(False, false, HType::Boolean(), false) | 706 DEFINE_GET_CONSTANT(False, false, HType::Boolean(), false) |
| 707 DEFINE_GET_CONSTANT(Hole, the_hole, HType::Tagged(), false) | 707 DEFINE_GET_CONSTANT(Hole, the_hole, HType::Tagged(), false) |
| 708 DEFINE_GET_CONSTANT(Null, null, HType::Tagged(), false) | 708 DEFINE_GET_CONSTANT(Null, null, HType::Tagged(), false) |
| 709 | 709 |
| 710 | 710 |
| 711 #undef DEFINE_GET_CONSTANT | 711 #undef DEFINE_GET_CONSTANT |
| 712 | 712 |
| 713 #define DEFINE_IS_CONSTANT(Name, name) \ |
| 714 bool HGraph::IsConstant##Name(HConstant* constant) { \ |
| 715 return constant_##name##_.is_set() && constant == constant_##name##_.get(); \ |
| 716 } |
| 717 DEFINE_IS_CONSTANT(Undefined, undefined) |
| 718 DEFINE_IS_CONSTANT(0, 0) |
| 719 DEFINE_IS_CONSTANT(1, 1) |
| 720 DEFINE_IS_CONSTANT(Minus1, minus1) |
| 721 DEFINE_IS_CONSTANT(True, true) |
| 722 DEFINE_IS_CONSTANT(False, false) |
| 723 DEFINE_IS_CONSTANT(Hole, the_hole) |
| 724 DEFINE_IS_CONSTANT(Null, null) |
| 725 |
| 726 #undef DEFINE_IS_CONSTANT |
| 727 |
| 713 | 728 |
| 714 HConstant* HGraph::GetInvalidContext() { | 729 HConstant* HGraph::GetInvalidContext() { |
| 715 return GetConstant(&constant_invalid_context_, 0xFFFFC0C7); | 730 return GetConstant(&constant_invalid_context_, 0xFFFFC0C7); |
| 716 } | 731 } |
| 717 | 732 |
| 718 | 733 |
| 719 bool HGraph::IsStandardConstant(HConstant* constant) { | 734 bool HGraph::IsStandardConstant(HConstant* constant) { |
| 720 if (constant == GetConstantUndefined()) return true; | 735 if (IsConstantUndefined(constant)) return true; |
| 721 if (constant == GetConstant0()) return true; | 736 if (IsConstant0(constant)) return true; |
| 722 if (constant == GetConstant1()) return true; | 737 if (IsConstant1(constant)) return true; |
| 723 if (constant == GetConstantMinus1()) return true; | 738 if (IsConstantMinus1(constant)) return true; |
| 724 if (constant == GetConstantTrue()) return true; | 739 if (IsConstantTrue(constant)) return true; |
| 725 if (constant == GetConstantFalse()) return true; | 740 if (IsConstantFalse(constant)) return true; |
| 726 if (constant == GetConstantHole()) return true; | 741 if (IsConstantHole(constant)) return true; |
| 727 if (constant == GetConstantNull()) return true; | 742 if (IsConstantNull(constant)) return true; |
| 728 return false; | 743 return false; |
| 729 } | 744 } |
| 730 | 745 |
| 731 | 746 |
| 732 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder) | 747 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder) |
| 733 : builder_(builder), | 748 : builder_(builder), |
| 734 finished_(false), | 749 finished_(false), |
| 735 deopt_then_(false), | 750 deopt_then_(false), |
| 736 deopt_else_(false), | 751 deopt_else_(false), |
| 737 did_then_(false), | 752 did_then_(false), |
| (...skipping 711 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1449 isolate()->factory()->empty_string(), | 1464 isolate()->factory()->empty_string(), |
| 1450 Runtime::FunctionForId(Runtime::kNumberToStringSkipCache), | 1465 Runtime::FunctionForId(Runtime::kNumberToStringSkipCache), |
| 1451 1)); | 1466 1)); |
| 1452 } | 1467 } |
| 1453 if_found.End(); | 1468 if_found.End(); |
| 1454 | 1469 |
| 1455 return Pop(); | 1470 return Pop(); |
| 1456 } | 1471 } |
| 1457 | 1472 |
| 1458 | 1473 |
| 1474 HValue* HGraphBuilder::BuildSeqStringSizeFor(HValue* length, |
| 1475 String::Encoding encoding) { |
| 1476 STATIC_ASSERT((SeqString::kHeaderSize & kObjectAlignmentMask) == 0); |
| 1477 HValue* size = length; |
| 1478 if (encoding == String::TWO_BYTE_ENCODING) { |
| 1479 size = Add<HShl>(length, graph()->GetConstant1()); |
| 1480 size->ClearFlag(HValue::kCanOverflow); |
| 1481 size->SetFlag(HValue::kUint32); |
| 1482 } |
| 1483 size = Add<HAdd>(size, Add<HConstant>(static_cast<int32_t>( |
| 1484 SeqString::kHeaderSize + kObjectAlignmentMask))); |
| 1485 size->ClearFlag(HValue::kCanOverflow); |
| 1486 size = Add<HBitwise>( |
| 1487 Token::BIT_AND, size, Add<HConstant>(static_cast<int32_t>( |
| 1488 ~kObjectAlignmentMask))); |
| 1489 return size; |
| 1490 } |
| 1491 |
| 1492 |
| 1493 void HGraphBuilder::BuildCopySeqStringChars(HValue* src, |
| 1494 HValue* src_offset, |
| 1495 String::Encoding src_encoding, |
| 1496 HValue* dst, |
| 1497 HValue* dst_offset, |
| 1498 String::Encoding dst_encoding, |
| 1499 HValue* length) { |
| 1500 ASSERT(dst_encoding != String::ONE_BYTE_ENCODING || |
| 1501 src_encoding == String::ONE_BYTE_ENCODING); |
| 1502 LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement); |
| 1503 HValue* index = loop.BeginBody(graph()->GetConstant0(), length, Token::LT); |
| 1504 { |
| 1505 HValue* src_index = Add<HAdd>(src_offset, index); |
| 1506 HValue* value = Add<HSeqStringGetChar>(src_encoding, src, src_index); |
| 1507 HValue* dst_index = Add<HAdd>(dst_offset, index); |
| 1508 Add<HSeqStringSetChar>(dst_encoding, dst, dst_index, value); |
| 1509 } |
| 1510 loop.EndBody(); |
| 1511 } |
| 1512 |
| 1513 |
| 1514 HValue* HGraphBuilder::BuildUncheckedStringAdd(HValue* left, |
| 1515 HValue* right, |
| 1516 PretenureFlag pretenure_flag) { |
| 1517 // Determine the string lengths. |
| 1518 HValue* left_length = Add<HLoadNamedField>( |
| 1519 left, HObjectAccess::ForStringLength()); |
| 1520 HValue* right_length = Add<HLoadNamedField>( |
| 1521 right, HObjectAccess::ForStringLength()); |
| 1522 |
| 1523 // Check if we concatenated the strings here, or if we have to resort to the |
| 1524 // runtime function. |
| 1525 HIfContinuation handled(graph()->CreateBasicBlock(), |
| 1526 graph()->CreateBasicBlock()); |
| 1527 |
| 1528 // Check if both parameters do not exceed half the max string length, because |
| 1529 // exceptionally long strings should be handled in the runtime. Unfortunately |
| 1530 // we cannot actually check whether the combined length of both strings |
| 1531 // exceeds String::kMaxLength (because of unclear results from the |
| 1532 // representation inference phase), so we use a pessimistic approach here |
| 1533 // instead, checking that the length of either substring does not exceed half |
| 1534 // of String::kMaxLength. |
| 1535 HConstant* max_length = Add<HConstant>(String::kMaxLength / 2); |
| 1536 IfBuilder if_nooverflow(this); |
| 1537 if_nooverflow.If<HCompareNumericAndBranch>( |
| 1538 left_length, max_length, Token::LTE); |
| 1539 if_nooverflow.AndIf<HCompareNumericAndBranch>( |
| 1540 right_length, max_length, Token::LTE); |
| 1541 if_nooverflow.Then(); |
| 1542 { |
| 1543 // Determine the string instance types. |
| 1544 HLoadNamedField* left_instance_type = Add<HLoadNamedField>( |
| 1545 Add<HLoadNamedField>(left, HObjectAccess::ForMap()), |
| 1546 HObjectAccess::ForMapInstanceType()); |
| 1547 HLoadNamedField* right_instance_type = Add<HLoadNamedField>( |
| 1548 Add<HLoadNamedField>(right, HObjectAccess::ForMap()), |
| 1549 HObjectAccess::ForMapInstanceType()); |
| 1550 |
| 1551 // Compute difference of instance types. |
| 1552 HValue* xored_instance_types = Add<HBitwise>( |
| 1553 Token::BIT_XOR, left_instance_type, right_instance_type); |
| 1554 |
| 1555 // Compute the length of the resulting string. |
| 1556 HValue* length = Add<HAdd>(left_length, right_length); |
| 1557 |
| 1558 // Check if we should create a cons string. |
| 1559 IfBuilder if_createcons(this); |
| 1560 if_createcons.If<HCompareNumericAndBranch>( |
| 1561 length, Add<HConstant>(ConsString::kMinLength), Token::GTE); |
| 1562 if_createcons.Then(); |
| 1563 { |
| 1564 // Allocate the cons string object. HAllocate does not care whether we |
| 1565 // pass CONS_STRING_TYPE or CONS_ASCII_STRING_TYPE here, so we just use |
| 1566 // CONS_STRING_TYPE here. Below we decide whether the cons string is |
| 1567 // one-byte or two-byte and set the appropriate map. |
| 1568 HAllocate* string = Add<HAllocate>(Add<HConstant>(ConsString::kSize), |
| 1569 HType::String(), pretenure_flag, |
| 1570 CONS_STRING_TYPE); |
| 1571 |
| 1572 // Compute the intersection of instance types. |
| 1573 HValue* anded_instance_types = Add<HBitwise>( |
| 1574 Token::BIT_AND, left_instance_type, right_instance_type); |
| 1575 |
| 1576 // We create a one-byte cons string if |
| 1577 // 1. both strings are one-byte, or |
| 1578 // 2. at least one of the strings is two-byte, but happens to contain only |
| 1579 // one-byte characters. |
| 1580 // To do this, we check |
| 1581 // 1. if both strings are one-byte, or if the one-byte data hint is set in |
| 1582 // both strings, or |
| 1583 // 2. if one of the strings has the one-byte data hint set and the other |
| 1584 // string is one-byte. |
| 1585 IfBuilder if_onebyte(this); |
| 1586 STATIC_ASSERT(kOneByteStringTag != 0); |
| 1587 STATIC_ASSERT(kOneByteDataHintMask != 0); |
| 1588 if_onebyte.If<HCompareNumericAndBranch>( |
| 1589 Add<HBitwise>( |
| 1590 Token::BIT_AND, anded_instance_types, |
| 1591 Add<HConstant>(static_cast<int32_t>( |
| 1592 kStringEncodingMask | kOneByteDataHintMask))), |
| 1593 graph()->GetConstant0(), Token::NE); |
| 1594 if_onebyte.Or(); |
| 1595 STATIC_ASSERT(kOneByteStringTag != 0 && |
| 1596 kOneByteDataHintTag != 0 && |
| 1597 kOneByteDataHintTag != kOneByteStringTag); |
| 1598 if_onebyte.If<HCompareNumericAndBranch>( |
| 1599 Add<HBitwise>( |
| 1600 Token::BIT_AND, xored_instance_types, |
| 1601 Add<HConstant>(static_cast<int32_t>( |
| 1602 kOneByteStringTag | kOneByteDataHintTag))), |
| 1603 Add<HConstant>(static_cast<int32_t>( |
| 1604 kOneByteStringTag | kOneByteDataHintTag)), Token::EQ); |
| 1605 if_onebyte.Then(); |
| 1606 { |
| 1607 // We can safely skip the write barrier for storing the map here. |
| 1608 Handle<Map> map = isolate()->factory()->cons_ascii_string_map(); |
| 1609 AddStoreMapConstantNoWriteBarrier(string, map); |
| 1610 } |
| 1611 if_onebyte.Else(); |
| 1612 { |
| 1613 // We can safely skip the write barrier for storing the map here. |
| 1614 Handle<Map> map = isolate()->factory()->cons_string_map(); |
| 1615 AddStoreMapConstantNoWriteBarrier(string, map); |
| 1616 } |
| 1617 if_onebyte.End(); |
| 1618 |
| 1619 // Initialize the cons string fields. |
| 1620 Add<HStoreNamedField>(string, HObjectAccess::ForStringHashField(), |
| 1621 Add<HConstant>(String::kEmptyHashField)); |
| 1622 Add<HStoreNamedField>(string, HObjectAccess::ForStringLength(), length); |
| 1623 Add<HStoreNamedField>(string, HObjectAccess::ForConsStringFirst(), left); |
| 1624 Add<HStoreNamedField>(string, HObjectAccess::ForConsStringSecond(), |
| 1625 right); |
| 1626 |
| 1627 // Cons string is result. |
| 1628 Push(string); |
| 1629 } |
| 1630 if_createcons.Else(); |
| 1631 { |
| 1632 // Compute union of instance types. |
| 1633 HValue* ored_instance_types = Add<HBitwise>( |
| 1634 Token::BIT_OR, left_instance_type, right_instance_type); |
| 1635 |
| 1636 // Check if both strings have the same encoding and both are |
| 1637 // sequential. |
| 1638 IfBuilder if_sameencodingandsequential(this); |
| 1639 if_sameencodingandsequential.If<HCompareNumericAndBranch>( |
| 1640 Add<HBitwise>( |
| 1641 Token::BIT_AND, xored_instance_types, |
| 1642 Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))), |
| 1643 graph()->GetConstant0(), Token::EQ); |
| 1644 if_sameencodingandsequential.And(); |
| 1645 STATIC_ASSERT(kSeqStringTag == 0); |
| 1646 if_sameencodingandsequential.If<HCompareNumericAndBranch>( |
| 1647 Add<HBitwise>( |
| 1648 Token::BIT_AND, ored_instance_types, |
| 1649 Add<HConstant>(static_cast<int32_t>(kStringRepresentationMask))), |
| 1650 graph()->GetConstant0(), Token::EQ); |
| 1651 if_sameencodingandsequential.Then(); |
| 1652 { |
| 1653 // Check if the result is a one-byte string. |
| 1654 IfBuilder if_onebyte(this); |
| 1655 STATIC_ASSERT(kOneByteStringTag != 0); |
| 1656 if_onebyte.If<HCompareNumericAndBranch>( |
| 1657 Add<HBitwise>( |
| 1658 Token::BIT_AND, ored_instance_types, |
| 1659 Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))), |
| 1660 graph()->GetConstant0(), Token::NE); |
| 1661 if_onebyte.Then(); |
| 1662 { |
| 1663 // Calculate the number of bytes needed for the characters in the |
| 1664 // string while observing object alignment. |
| 1665 HValue* size = BuildSeqStringSizeFor( |
| 1666 length, String::ONE_BYTE_ENCODING); |
| 1667 |
| 1668 // Allocate the ASCII string object. |
| 1669 Handle<Map> map = isolate()->factory()->ascii_string_map(); |
| 1670 HAllocate* string = Add<HAllocate>(size, HType::String(), |
| 1671 pretenure_flag, ASCII_STRING_TYPE); |
| 1672 string->set_known_initial_map(map); |
| 1673 |
| 1674 // We can safely skip the write barrier for storing map here. |
| 1675 AddStoreMapConstantNoWriteBarrier(string, map); |
| 1676 |
| 1677 // Copy bytes from the left string. |
| 1678 BuildCopySeqStringChars( |
| 1679 left, graph()->GetConstant0(), String::ONE_BYTE_ENCODING, |
| 1680 string, graph()->GetConstant0(), String::ONE_BYTE_ENCODING, |
| 1681 left_length); |
| 1682 |
| 1683 // Copy bytes from the right string. |
| 1684 BuildCopySeqStringChars( |
| 1685 right, graph()->GetConstant0(), String::ONE_BYTE_ENCODING, |
| 1686 string, left_length, String::ONE_BYTE_ENCODING, |
| 1687 right_length); |
| 1688 |
| 1689 // Return the string. |
| 1690 Push(string); |
| 1691 } |
| 1692 if_onebyte.Else(); |
| 1693 { |
| 1694 // Calculate the number of bytes needed for the characters in the |
| 1695 // string while observing object alignment. |
| 1696 HValue* size = BuildSeqStringSizeFor( |
| 1697 length, String::TWO_BYTE_ENCODING); |
| 1698 |
| 1699 // Allocate the two-byte string object. |
| 1700 Handle<Map> map = isolate()->factory()->string_map(); |
| 1701 HAllocate* string = Add<HAllocate>(size, HType::String(), |
| 1702 pretenure_flag, STRING_TYPE); |
| 1703 string->set_known_initial_map(map); |
| 1704 |
| 1705 // We can safely skip the write barrier for storing map here. |
| 1706 AddStoreMapConstantNoWriteBarrier(string, map); |
| 1707 |
| 1708 // Copy bytes from the left string. |
| 1709 BuildCopySeqStringChars( |
| 1710 left, graph()->GetConstant0(), String::TWO_BYTE_ENCODING, |
| 1711 string, graph()->GetConstant0(), String::TWO_BYTE_ENCODING, |
| 1712 left_length); |
| 1713 |
| 1714 // Copy bytes from the right string. |
| 1715 BuildCopySeqStringChars( |
| 1716 right, graph()->GetConstant0(), String::TWO_BYTE_ENCODING, |
| 1717 string, left_length, String::TWO_BYTE_ENCODING, |
| 1718 right_length); |
| 1719 |
| 1720 // Return the string. |
| 1721 Push(string); |
| 1722 } |
| 1723 if_onebyte.End(); |
| 1724 |
| 1725 // Initialize the (common) string fields. |
| 1726 HValue* string = Pop(); |
| 1727 Add<HStoreNamedField>(string, HObjectAccess::ForStringHashField(), |
| 1728 Add<HConstant>(String::kEmptyHashField)); |
| 1729 Add<HStoreNamedField>(string, HObjectAccess::ForStringLength(), |
| 1730 length); |
| 1731 Push(string); |
| 1732 } |
| 1733 if_sameencodingandsequential.JoinContinuation(&handled); |
| 1734 } |
| 1735 if_createcons.JoinContinuation(&handled); |
| 1736 } |
| 1737 if_nooverflow.JoinContinuation(&handled); |
| 1738 |
| 1739 // Check if the strings were concatenated successfully, otherwise fallback to |
| 1740 // add the strings in the runtime. |
| 1741 IfBuilder if_handled(this, &handled); |
| 1742 if_handled.Then(); |
| 1743 { |
| 1744 // Count the native string addition. |
| 1745 AddIncrementCounter(isolate()->counters()->string_add_native()); |
| 1746 } |
| 1747 if_handled.Else(); |
| 1748 { |
| 1749 // Fallback to the runtime to add the two strings. |
| 1750 Add<HPushArgument>(left); |
| 1751 Add<HPushArgument>(right); |
| 1752 Push(Add<HCallRuntime>(isolate()->factory()->empty_string(), |
| 1753 Runtime::FunctionForId(Runtime::kStringAdd), |
| 1754 2)); |
| 1755 } |
| 1756 if_handled.End(); |
| 1757 |
| 1758 return Pop(); |
| 1759 } |
| 1760 |
| 1761 |
| 1762 HValue* HGraphBuilder::BuildStringAdd(HValue* left, |
| 1763 HValue* right, |
| 1764 PretenureFlag pretenure_flag) { |
| 1765 // Determine the string lengths. |
| 1766 HValue* left_length = Add<HLoadNamedField>( |
| 1767 left, HObjectAccess::ForStringLength()); |
| 1768 HValue* right_length = Add<HLoadNamedField>( |
| 1769 right, HObjectAccess::ForStringLength()); |
| 1770 |
| 1771 // Check if left string is empty. |
| 1772 IfBuilder if_leftisempty(this); |
| 1773 if_leftisempty.If<HCompareNumericAndBranch>( |
| 1774 left_length, graph()->GetConstant0(), Token::EQ); |
| 1775 if_leftisempty.Then(); |
| 1776 { |
| 1777 // Count the native string addition. |
| 1778 AddIncrementCounter(isolate()->counters()->string_add_native()); |
| 1779 |
| 1780 // Just return the right string. |
| 1781 Push(right); |
| 1782 } |
| 1783 if_leftisempty.Else(); |
| 1784 { |
| 1785 // Check if right string is empty. |
| 1786 IfBuilder if_rightisempty(this); |
| 1787 if_rightisempty.If<HCompareNumericAndBranch>( |
| 1788 right_length, graph()->GetConstant0(), Token::EQ); |
| 1789 if_rightisempty.Then(); |
| 1790 { |
| 1791 // Count the native string addition. |
| 1792 AddIncrementCounter(isolate()->counters()->string_add_native()); |
| 1793 |
| 1794 // Just return the left string. |
| 1795 Push(left); |
| 1796 } |
| 1797 if_rightisempty.Else(); |
| 1798 { |
| 1799 // Concatenate the two non-empty strings. |
| 1800 Push(BuildUncheckedStringAdd(left, right, pretenure_flag)); |
| 1801 } |
| 1802 if_rightisempty.End(); |
| 1803 } |
| 1804 if_leftisempty.End(); |
| 1805 |
| 1806 return Pop(); |
| 1807 } |
| 1808 |
| 1809 |
| 1459 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( | 1810 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( |
| 1460 HValue* checked_object, | 1811 HValue* checked_object, |
| 1461 HValue* key, | 1812 HValue* key, |
| 1462 HValue* val, | 1813 HValue* val, |
| 1463 bool is_js_array, | 1814 bool is_js_array, |
| 1464 ElementsKind elements_kind, | 1815 ElementsKind elements_kind, |
| 1465 bool is_store, | 1816 bool is_store, |
| 1466 LoadKeyedHoleMode load_mode, | 1817 LoadKeyedHoleMode load_mode, |
| 1467 KeyedAccessStoreMode store_mode) { | 1818 KeyedAccessStoreMode store_mode) { |
| 1468 ASSERT(!IsExternalArrayElementsKind(elements_kind) || !is_js_array); | 1819 ASSERT(!IsExternalArrayElementsKind(elements_kind) || !is_js_array); |
| (...skipping 807 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2276 phi_list_(NULL), | 2627 phi_list_(NULL), |
| 2277 uint32_instructions_(NULL), | 2628 uint32_instructions_(NULL), |
| 2278 osr_(NULL), | 2629 osr_(NULL), |
| 2279 info_(info), | 2630 info_(info), |
| 2280 zone_(info->zone()), | 2631 zone_(info->zone()), |
| 2281 is_recursive_(false), | 2632 is_recursive_(false), |
| 2282 use_optimistic_licm_(false), | 2633 use_optimistic_licm_(false), |
| 2283 depends_on_empty_array_proto_elements_(false), | 2634 depends_on_empty_array_proto_elements_(false), |
| 2284 type_change_checksum_(0), | 2635 type_change_checksum_(0), |
| 2285 maximum_environment_size_(0), | 2636 maximum_environment_size_(0), |
| 2286 no_side_effects_scope_count_(0) { | 2637 no_side_effects_scope_count_(0), |
| 2638 disallow_adding_new_values_(false) { |
| 2287 if (info->IsStub()) { | 2639 if (info->IsStub()) { |
| 2288 HydrogenCodeStub* stub = info->code_stub(); | 2640 HydrogenCodeStub* stub = info->code_stub(); |
| 2289 CodeStubInterfaceDescriptor* descriptor = | 2641 CodeStubInterfaceDescriptor* descriptor = |
| 2290 stub->GetInterfaceDescriptor(isolate_); | 2642 stub->GetInterfaceDescriptor(isolate_); |
| 2291 start_environment_ = | 2643 start_environment_ = |
| 2292 new(zone_) HEnvironment(zone_, descriptor->environment_length()); | 2644 new(zone_) HEnvironment(zone_, descriptor->environment_length()); |
| 2293 } else { | 2645 } else { |
| 2294 start_environment_ = | 2646 start_environment_ = |
| 2295 new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_); | 2647 new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_); |
| 2296 } | 2648 } |
| (...skipping 2008 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4305 } | 4657 } |
| 4306 } | 4658 } |
| 4307 return true; | 4659 return true; |
| 4308 } | 4660 } |
| 4309 | 4661 |
| 4310 | 4662 |
| 4311 void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { | 4663 void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { |
| 4312 ASSERT(!HasStackOverflow()); | 4664 ASSERT(!HasStackOverflow()); |
| 4313 ASSERT(current_block() != NULL); | 4665 ASSERT(current_block() != NULL); |
| 4314 ASSERT(current_block()->HasPredecessor()); | 4666 ASSERT(current_block()->HasPredecessor()); |
| 4667 expr->BuildConstantProperties(isolate()); |
| 4315 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); | 4668 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); |
| 4316 HInstruction* literal; | 4669 HInstruction* literal; |
| 4317 | 4670 |
| 4318 // Check whether to use fast or slow deep-copying for boilerplate. | 4671 // Check whether to use fast or slow deep-copying for boilerplate. |
| 4319 int max_properties = kMaxFastLiteralProperties; | 4672 int max_properties = kMaxFastLiteralProperties; |
| 4320 Handle<Object> literals_cell(closure->literals()->get(expr->literal_index()), | 4673 Handle<Object> literals_cell(closure->literals()->get(expr->literal_index()), |
| 4321 isolate()); | 4674 isolate()); |
| 4322 Handle<AllocationSite> site; | 4675 Handle<AllocationSite> site; |
| 4323 Handle<JSObject> boilerplate; | 4676 Handle<JSObject> boilerplate; |
| 4324 if (!literals_cell->IsUndefined()) { | 4677 if (!literals_cell->IsUndefined()) { |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4426 } else { | 4779 } else { |
| 4427 return ast_context()->ReturnValue(Pop()); | 4780 return ast_context()->ReturnValue(Pop()); |
| 4428 } | 4781 } |
| 4429 } | 4782 } |
| 4430 | 4783 |
| 4431 | 4784 |
| 4432 void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { | 4785 void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { |
| 4433 ASSERT(!HasStackOverflow()); | 4786 ASSERT(!HasStackOverflow()); |
| 4434 ASSERT(current_block() != NULL); | 4787 ASSERT(current_block() != NULL); |
| 4435 ASSERT(current_block()->HasPredecessor()); | 4788 ASSERT(current_block()->HasPredecessor()); |
| 4789 expr->BuildConstantElements(isolate()); |
| 4436 ZoneList<Expression*>* subexprs = expr->values(); | 4790 ZoneList<Expression*>* subexprs = expr->values(); |
| 4437 int length = subexprs->length(); | 4791 int length = subexprs->length(); |
| 4438 HInstruction* literal; | 4792 HInstruction* literal; |
| 4439 | 4793 |
| 4440 Handle<AllocationSite> site; | 4794 Handle<AllocationSite> site; |
| 4441 Handle<FixedArray> literals(environment()->closure()->literals(), isolate()); | 4795 Handle<FixedArray> literals(environment()->closure()->literals(), isolate()); |
| 4442 bool uninitialized = false; | 4796 bool uninitialized = false; |
| 4443 Handle<Object> literals_cell(literals->get(expr->literal_index()), | 4797 Handle<Object> literals_cell(literals->get(expr->literal_index()), |
| 4444 isolate()); | 4798 isolate()); |
| 4445 Handle<JSObject> boilerplate_object; | 4799 Handle<JSObject> boilerplate_object; |
| (...skipping 1940 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6386 int nodes_added = InliningAstSize(target); | 6740 int nodes_added = InliningAstSize(target); |
| 6387 if (nodes_added == kNotInlinable) return false; | 6741 if (nodes_added == kNotInlinable) return false; |
| 6388 | 6742 |
| 6389 Handle<JSFunction> caller = current_info()->closure(); | 6743 Handle<JSFunction> caller = current_info()->closure(); |
| 6390 | 6744 |
| 6391 if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) { | 6745 if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) { |
| 6392 TraceInline(target, caller, "target AST is too large [early]"); | 6746 TraceInline(target, caller, "target AST is too large [early]"); |
| 6393 return false; | 6747 return false; |
| 6394 } | 6748 } |
| 6395 | 6749 |
| 6396 #if !V8_TARGET_ARCH_IA32 && !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_MIPS | |
| 6397 // Target must be able to use caller's context. | |
| 6398 CompilationInfo* outer_info = current_info(); | |
| 6399 if (target->context() != outer_info->closure()->context() || | |
| 6400 outer_info->scope()->contains_with() || | |
| 6401 outer_info->scope()->num_heap_slots() > 0) { | |
| 6402 TraceInline(target, caller, "target requires context change"); | |
| 6403 return false; | |
| 6404 } | |
| 6405 #endif | |
| 6406 | |
| 6407 | |
| 6408 // Don't inline deeper than the maximum number of inlining levels. | 6750 // Don't inline deeper than the maximum number of inlining levels. |
| 6409 HEnvironment* env = environment(); | 6751 HEnvironment* env = environment(); |
| 6410 int current_level = 1; | 6752 int current_level = 1; |
| 6411 while (env->outer() != NULL) { | 6753 while (env->outer() != NULL) { |
| 6412 if (current_level == FLAG_max_inlining_levels) { | 6754 if (current_level == FLAG_max_inlining_levels) { |
| 6413 TraceInline(target, caller, "inline depth limit reached"); | 6755 TraceInline(target, caller, "inline depth limit reached"); |
| 6414 return false; | 6756 return false; |
| 6415 } | 6757 } |
| 6416 if (env->outer()->frame_type() == JS_FUNCTION) { | 6758 if (env->outer()->frame_type() == JS_FUNCTION) { |
| 6417 current_level++; | 6759 current_level++; |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6535 HConstant* undefined = graph()->GetConstantUndefined(); | 6877 HConstant* undefined = graph()->GetConstantUndefined(); |
| 6536 bool undefined_receiver = HEnvironment::UseUndefinedReceiver( | 6878 bool undefined_receiver = HEnvironment::UseUndefinedReceiver( |
| 6537 target, function, call_kind, inlining_kind); | 6879 target, function, call_kind, inlining_kind); |
| 6538 HEnvironment* inner_env = | 6880 HEnvironment* inner_env = |
| 6539 environment()->CopyForInlining(target, | 6881 environment()->CopyForInlining(target, |
| 6540 arguments_count, | 6882 arguments_count, |
| 6541 function, | 6883 function, |
| 6542 undefined, | 6884 undefined, |
| 6543 function_state()->inlining_kind(), | 6885 function_state()->inlining_kind(), |
| 6544 undefined_receiver); | 6886 undefined_receiver); |
| 6545 #if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS | 6887 |
| 6546 // IA32, ARM and MIPS only, overwrite the caller's context in the | |
| 6547 // deoptimization environment with the correct one. | |
| 6548 // | |
| 6549 // TODO(kmillikin): implement the same inlining on other platforms so we | |
| 6550 // can remove the unsightly ifdefs in this function. | |
| 6551 HConstant* context = Add<HConstant>(Handle<Context>(target->context())); | 6888 HConstant* context = Add<HConstant>(Handle<Context>(target->context())); |
| 6552 inner_env->BindContext(context); | 6889 inner_env->BindContext(context); |
| 6553 #endif | |
| 6554 | 6890 |
| 6555 Add<HSimulate>(return_id); | 6891 Add<HSimulate>(return_id); |
| 6556 current_block()->UpdateEnvironment(inner_env); | 6892 current_block()->UpdateEnvironment(inner_env); |
| 6557 HArgumentsObject* arguments_object = NULL; | 6893 HArgumentsObject* arguments_object = NULL; |
| 6558 | 6894 |
| 6559 // If the function uses arguments object create and bind one, also copy | 6895 // If the function uses arguments object create and bind one, also copy |
| 6560 // current arguments values to use them for materialization. | 6896 // current arguments values to use them for materialization. |
| 6561 if (function->scope()->arguments() != NULL) { | 6897 if (function->scope()->arguments() != NULL) { |
| 6562 ASSERT(function->scope()->arguments()->IsStackAllocated()); | 6898 ASSERT(function->scope()->arguments()->IsStackAllocated()); |
| 6563 HEnvironment* arguments_env = inner_env->arguments_environment(); | 6899 HEnvironment* arguments_env = inner_env->arguments_environment(); |
| (...skipping 3292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9856 if (ShouldProduceTraceOutput()) { | 10192 if (ShouldProduceTraceOutput()) { |
| 9857 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 10193 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 9858 } | 10194 } |
| 9859 | 10195 |
| 9860 #ifdef DEBUG | 10196 #ifdef DEBUG |
| 9861 graph_->Verify(false); // No full verify. | 10197 graph_->Verify(false); // No full verify. |
| 9862 #endif | 10198 #endif |
| 9863 } | 10199 } |
| 9864 | 10200 |
| 9865 } } // namespace v8::internal | 10201 } } // namespace v8::internal |
| OLD | NEW |