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

Side by Side Diff: src/hydrogen.cc

Issue 61893009: Add initial hydrogenized NewStringAddStub. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Add test case for --new-string-add. Created 7 years, 1 month 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 | Annotate | Revision Log
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 1451 matching lines...) Expand 10 before | Expand all | Expand 10 after
1462 isolate()->factory()->empty_string(), 1462 isolate()->factory()->empty_string(),
1463 Runtime::FunctionForId(Runtime::kNumberToStringSkipCache), 1463 Runtime::FunctionForId(Runtime::kNumberToStringSkipCache),
1464 1)); 1464 1));
1465 } 1465 }
1466 if_found.End(); 1466 if_found.End();
1467 1467
1468 return Pop(); 1468 return Pop();
1469 } 1469 }
1470 1470
1471 1471
1472 HValue* HGraphBuilder::BuildSeqStringSizeFor(HValue* length,
1473 String::Encoding encoding) {
1474 STATIC_ASSERT((SeqString::kHeaderSize & kObjectAlignmentMask) == 0);
1475 HValue* size = length;
1476 if (encoding == String::TWO_BYTE_ENCODING) {
1477 size = Add<HShl>(length, graph()->GetConstant1());
1478 size->ClearFlag(HValue::kCanOverflow);
1479 size->SetFlag(HValue::kUint32);
1480 }
1481 size = Add<HAdd>(size, Add<HConstant>(static_cast<int32_t>(
1482 SeqString::kHeaderSize + kObjectAlignmentMask)));
1483 size->ClearFlag(HValue::kCanOverflow);
1484 size = Add<HBitwise>(
1485 Token::BIT_AND, size, Add<HConstant>(static_cast<int32_t>(
1486 ~kObjectAlignmentMask)));
1487 return size;
1488 }
1489
1490
1491 void HGraphBuilder::BuildCopySeqStringChars(HValue* src,
1492 HValue* src_offset,
1493 String::Encoding src_encoding,
1494 HValue* dst,
1495 HValue* dst_offset,
1496 String::Encoding dst_encoding,
1497 HValue* length) {
1498 ASSERT(dst_encoding != String::ONE_BYTE_ENCODING ||
1499 src_encoding == String::ONE_BYTE_ENCODING);
1500 LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement);
1501 HValue* index = loop.BeginBody(graph()->GetConstant0(), length, Token::LT);
1502 {
1503 HValue* src_index = Add<HAdd>(src_offset, index);
1504 HValue* value = Add<HSeqStringGetChar>(src_encoding, src, src_index);
1505 HValue* dst_index = Add<HAdd>(dst_offset, index);
1506 Add<HSeqStringSetChar>(dst_encoding, dst, dst_index, value);
1507 }
1508 loop.EndBody();
1509 }
1510
1511
1512 HValue* HGraphBuilder::BuildUncheckedStringAdd(HValue* left,
1513 HValue* right,
1514 PretenureFlag pretenure_flag) {
1515 // Determine the string lengths.
1516 HValue* left_length = Add<HLoadNamedField>(
1517 left, HObjectAccess::ForStringLength());
1518 HValue* right_length = Add<HLoadNamedField>(
1519 right, HObjectAccess::ForStringLength());
1520
1521 // Check if we concatenated the strings here, or if we have to resort to the
1522 // runtime function.
1523 HIfContinuation handled(graph()->CreateBasicBlock(),
1524 graph()->CreateBasicBlock());
1525
1526 // Check if both parameters do not exceed half the max string length, because
1527 // exceptionally long strings should be handled in the runtime. Unfortunately
1528 // we cannot actually check whether the combined length of both strings
1529 // exceeds String::kMaxLength (because of unclear results from the
1530 // representation inference phase), so we use a pessimistic approach here
1531 // instead, checking that the length of either substring does not exceed half
1532 // of String::kMaxLength.
1533 HConstant* max_length = Add<HConstant>(String::kMaxLength / 2);
1534 IfBuilder if_nooverflow(this);
1535 if_nooverflow.If<HCompareNumericAndBranch>(
1536 left_length, max_length, Token::LTE);
1537 if_nooverflow.AndIf<HCompareNumericAndBranch>(
1538 right_length, max_length, Token::LTE);
1539 if_nooverflow.Then();
1540 {
1541 // Determine the string instance types.
1542 HLoadNamedField* left_instance_type = Add<HLoadNamedField>(
1543 Add<HLoadNamedField>(left, HObjectAccess::ForMap()),
1544 HObjectAccess::ForMapInstanceType());
1545 HLoadNamedField* right_instance_type = Add<HLoadNamedField>(
1546 Add<HLoadNamedField>(right, HObjectAccess::ForMap()),
1547 HObjectAccess::ForMapInstanceType());
1548
1549 // Compute difference of instance types.
1550 HValue* xored_instance_types = Add<HBitwise>(
1551 Token::BIT_XOR, left_instance_type, right_instance_type);
1552
1553 // Compute the length of the resulting string.
1554 HValue* length = Add<HAdd>(left_length, right_length);
1555
1556 // Check if we should create a cons string.
1557 IfBuilder if_createcons(this);
1558 if_createcons.If<HCompareNumericAndBranch>(
1559 length, Add<HConstant>(ConsString::kMinLength), Token::GTE);
1560 if_createcons.Then();
1561 {
1562 // Allocate the cons string object. HAllocate does not care whether we
1563 // pass CONS_STRING_TYPE or CONS_ASCII_STRING_TYPE here, so we just use
1564 // CONS_STRING_TYPE here. Below we decide whether the cons string is
1565 // one-byte or two-byte and set the appropriate map.
1566 HAllocate* string = Add<HAllocate>(Add<HConstant>(ConsString::kSize),
1567 HType::String(), pretenure_flag,
1568 CONS_STRING_TYPE);
1569
1570 // Compute the intersection of instance types.
1571 HValue* anded_instance_types = Add<HBitwise>(
1572 Token::BIT_AND, left_instance_type, right_instance_type);
1573
1574 // We create a one-byte cons string if
1575 // 1. both strings are one-byte, or
1576 // 2. at least one of the strings is two-byte, but happens to contain only
1577 // one-byte characters.
1578 // To do this, we check
1579 // 1. if both strings are one-byte, or if the one-byte data hint is set in
1580 // both strings, or
1581 // 2. if one of the strings has the one-byte data hint set and the other
1582 // string is one-byte.
1583 IfBuilder if_onebyte(this);
1584 STATIC_ASSERT(kOneByteStringTag != 0);
1585 STATIC_ASSERT(kOneByteDataHintMask != 0);
1586 if_onebyte.If<HCompareNumericAndBranch>(
1587 Add<HBitwise>(
1588 Token::BIT_AND, anded_instance_types,
1589 Add<HConstant>(static_cast<int32_t>(
1590 kStringEncodingMask | kOneByteDataHintMask))),
1591 graph()->GetConstant0(), Token::NE);
1592 if_onebyte.Or();
1593 STATIC_ASSERT(kOneByteStringTag != 0 &&
1594 kOneByteDataHintTag != 0 &&
1595 kOneByteDataHintTag != kOneByteStringTag);
1596 if_onebyte.If<HCompareNumericAndBranch>(
1597 Add<HBitwise>(
1598 Token::BIT_AND, xored_instance_types,
1599 Add<HConstant>(static_cast<int32_t>(
1600 kOneByteStringTag | kOneByteDataHintTag))),
1601 Add<HConstant>(static_cast<int32_t>(
1602 kOneByteStringTag | kOneByteDataHintTag)), Token::EQ);
1603 if_onebyte.Then();
1604 {
1605 // We can safely skip the write barrier for storing the map here.
1606 Handle<Map> map = isolate()->factory()->cons_ascii_string_map();
1607 AddStoreMapConstantNoWriteBarrier(string, map);
1608 }
1609 if_onebyte.Else();
1610 {
1611 // We can safely skip the write barrier for storing the map here.
1612 Handle<Map> map = isolate()->factory()->cons_string_map();
1613 AddStoreMapConstantNoWriteBarrier(string, map);
1614 }
1615 if_onebyte.End();
1616
1617 // Initialize the cons string fields.
1618 Add<HStoreNamedField>(string, HObjectAccess::ForStringHashField(),
1619 Add<HConstant>(String::kEmptyHashField));
1620 Add<HStoreNamedField>(string, HObjectAccess::ForStringLength(), length);
1621 Add<HStoreNamedField>(string, HObjectAccess::ForConsStringFirst(), left);
1622 Add<HStoreNamedField>(string, HObjectAccess::ForConsStringSecond(),
1623 right);
1624
1625 // Cons string is result.
1626 Push(string);
1627 }
1628 if_createcons.Else();
1629 {
1630 // Compute union of instance types.
1631 HValue* ored_instance_types = Add<HBitwise>(
1632 Token::BIT_OR, left_instance_type, right_instance_type);
1633
1634 // Check if both strings have the same encoding and both are
1635 // sequential.
1636 IfBuilder if_sameencodingandsequential(this);
1637 if_sameencodingandsequential.If<HCompareNumericAndBranch>(
1638 Add<HBitwise>(
1639 Token::BIT_AND, xored_instance_types,
1640 Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))),
1641 graph()->GetConstant0(), Token::EQ);
1642 if_sameencodingandsequential.And();
1643 STATIC_ASSERT(kSeqStringTag == 0);
1644 if_sameencodingandsequential.If<HCompareNumericAndBranch>(
1645 Add<HBitwise>(
1646 Token::BIT_AND, ored_instance_types,
1647 Add<HConstant>(static_cast<int32_t>(kStringRepresentationMask))),
1648 graph()->GetConstant0(), Token::EQ);
1649 if_sameencodingandsequential.Then();
1650 {
1651 // Check if the result is a one-byte string.
1652 IfBuilder if_onebyte(this);
1653 STATIC_ASSERT(kOneByteStringTag != 0);
1654 if_onebyte.If<HCompareNumericAndBranch>(
1655 Add<HBitwise>(
1656 Token::BIT_AND, ored_instance_types,
1657 Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))),
1658 graph()->GetConstant0(), Token::NE);
1659 if_onebyte.Then();
1660 {
1661 // Calculate the number of bytes needed for the characters in the
1662 // string while observing object alignment.
1663 HValue* size = BuildSeqStringSizeFor(
1664 length, String::ONE_BYTE_ENCODING);
1665
1666 // Allocate the ASCII string object.
1667 Handle<Map> map = isolate()->factory()->ascii_string_map();
1668 HAllocate* string = Add<HAllocate>(size, HType::String(),
1669 pretenure_flag, ASCII_STRING_TYPE);
1670 string->set_known_initial_map(map);
1671
1672 // We can safely skip the write barrier for storing map here.
1673 AddStoreMapConstantNoWriteBarrier(string, map);
1674
1675 // Copy bytes from the left string.
1676 BuildCopySeqStringChars(
1677 left, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
1678 string, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
1679 left_length);
1680
1681 // Copy bytes from the right string.
1682 BuildCopySeqStringChars(
1683 right, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
1684 string, left_length, String::ONE_BYTE_ENCODING,
1685 right_length);
1686
1687 // Return the string.
1688 Push(string);
1689 }
1690 if_onebyte.Else();
1691 {
1692 // Calculate the number of bytes needed for the characters in the
1693 // string while observing object alignment.
1694 HValue* size = BuildSeqStringSizeFor(
1695 length, String::TWO_BYTE_ENCODING);
1696
1697 // Allocate the two-byte string object.
1698 Handle<Map> map = isolate()->factory()->string_map();
1699 HAllocate* string = Add<HAllocate>(size, HType::String(),
1700 pretenure_flag, STRING_TYPE);
1701 string->set_known_initial_map(map);
1702
1703 // We can safely skip the write barrier for storing map here.
1704 AddStoreMapConstantNoWriteBarrier(string, map);
1705
1706 // Copy bytes from the left string.
1707 BuildCopySeqStringChars(
1708 left, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
1709 string, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
1710 left_length);
1711
1712 // Copy bytes from the right string.
1713 BuildCopySeqStringChars(
1714 right, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
1715 string, left_length, String::TWO_BYTE_ENCODING,
1716 right_length);
1717
1718 // Return the string.
1719 Push(string);
1720 }
1721 if_onebyte.End();
1722
1723 // Initialize the (common) string fields.
1724 HValue* string = Pop();
1725 Add<HStoreNamedField>(string, HObjectAccess::ForStringHashField(),
1726 Add<HConstant>(String::kEmptyHashField));
1727 Add<HStoreNamedField>(string, HObjectAccess::ForStringLength(),
1728 length);
1729 Push(string);
1730 }
1731 if_sameencodingandsequential.JoinContinuation(&handled);
1732 }
1733 if_createcons.JoinContinuation(&handled);
1734 }
1735 if_nooverflow.JoinContinuation(&handled);
1736
1737 // Check if the strings were concatenated successfully, otherwise fallback to
1738 // add the strings in the runtime.
1739 IfBuilder if_handled(this, &handled);
1740 if_handled.Then();
1741 {
1742 // Count the native string addition.
1743 AddIncrementCounter(isolate()->counters()->string_add_native());
1744 }
1745 if_handled.Else();
1746 {
1747 // Fallback to the runtime to add the two strings.
1748 Add<HPushArgument>(left);
1749 Add<HPushArgument>(right);
1750 Push(Add<HCallRuntime>(isolate()->factory()->empty_string(),
1751 Runtime::FunctionForId(Runtime::kStringAdd),
1752 2));
1753 }
1754 if_handled.End();
1755
1756 return Pop();
1757 }
1758
1759
1760 HValue* HGraphBuilder::BuildStringAdd(HValue* left,
1761 HValue* right,
1762 PretenureFlag pretenure_flag) {
1763 // Determine the string lengths.
1764 HValue* left_length = Add<HLoadNamedField>(
1765 left, HObjectAccess::ForStringLength());
1766 HValue* right_length = Add<HLoadNamedField>(
1767 right, HObjectAccess::ForStringLength());
1768
1769 // Check if left string is empty.
1770 IfBuilder if_leftisempty(this);
1771 if_leftisempty.If<HCompareNumericAndBranch>(
1772 left_length, graph()->GetConstant0(), Token::EQ);
1773 if_leftisempty.Then();
1774 {
1775 // Count the native string addition.
1776 AddIncrementCounter(isolate()->counters()->string_add_native());
1777
1778 // Just return the right string.
1779 Push(right);
1780 }
1781 if_leftisempty.Else();
1782 {
1783 // Check if right string is empty.
1784 IfBuilder if_rightisempty(this);
1785 if_rightisempty.If<HCompareNumericAndBranch>(
1786 right_length, graph()->GetConstant0(), Token::EQ);
1787 if_rightisempty.Then();
1788 {
1789 // Count the native string addition.
1790 AddIncrementCounter(isolate()->counters()->string_add_native());
1791
1792 // Just return the left string.
1793 Push(left);
1794 }
1795 if_rightisempty.Else();
1796 {
1797 // Concatenate the two non-empty strings.
1798 Push(BuildUncheckedStringAdd(left, right, pretenure_flag));
1799 }
1800 if_rightisempty.End();
1801 }
1802 if_leftisempty.End();
1803
1804 return Pop();
1805 }
1806
1807
1472 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( 1808 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
1473 HValue* checked_object, 1809 HValue* checked_object,
1474 HValue* key, 1810 HValue* key,
1475 HValue* val, 1811 HValue* val,
1476 bool is_js_array, 1812 bool is_js_array,
1477 ElementsKind elements_kind, 1813 ElementsKind elements_kind,
1478 bool is_store, 1814 bool is_store,
1479 LoadKeyedHoleMode load_mode, 1815 LoadKeyedHoleMode load_mode,
1480 KeyedAccessStoreMode store_mode) { 1816 KeyedAccessStoreMode store_mode) {
1481 ASSERT(!IsExternalArrayElementsKind(elements_kind) || !is_js_array); 1817 ASSERT(!IsExternalArrayElementsKind(elements_kind) || !is_js_array);
(...skipping 8372 matching lines...) Expand 10 before | Expand all | Expand 10 after
9854 if (ShouldProduceTraceOutput()) { 10190 if (ShouldProduceTraceOutput()) {
9855 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); 10191 isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
9856 } 10192 }
9857 10193
9858 #ifdef DEBUG 10194 #ifdef DEBUG
9859 graph_->Verify(false); // No full verify. 10195 graph_->Verify(false); // No full verify.
9860 #endif 10196 #endif
9861 } 10197 }
9862 10198
9863 } } // namespace v8::internal 10199 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698