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

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: 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
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 1436 matching lines...) Expand 10 before | Expand all | Expand 10 after
1447 isolate()->factory()->empty_string(), 1447 isolate()->factory()->empty_string(),
1448 Runtime::FunctionForId(Runtime::kNumberToStringSkipCache), 1448 Runtime::FunctionForId(Runtime::kNumberToStringSkipCache),
1449 1)); 1449 1));
1450 } 1450 }
1451 if_found.End(); 1451 if_found.End();
1452 1452
1453 return Pop(); 1453 return Pop();
1454 } 1454 }
1455 1455
1456 1456
1457 void HGraphBuilder::BuildCopySeqStringChars(HValue* src,
1458 HValue* src_offset,
1459 String::Encoding src_encoding,
1460 HValue* dst,
1461 HValue* dst_offset,
1462 String::Encoding dst_encoding,
1463 HValue* length) {
1464 ASSERT(dst_encoding != String::ONE_BYTE_ENCODING ||
1465 src_encoding == String::ONE_BYTE_ENCODING);
1466 LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement);
1467 HValue* index = loop.BeginBody(graph()->GetConstant0(), length, Token::LT);
1468 {
1469 HValue* src_index = Add<HAdd>(src_offset, index);
1470 HValue* value = Add<HSeqStringGetChar>(src_encoding, src, src_index);
1471 HValue* dst_index = Add<HAdd>(dst_offset, index);
1472 Add<HSeqStringSetChar>(dst_encoding, dst, dst_index, value);
1473 }
1474 loop.EndBody();
1475 }
1476
1477
1478 HValue* HGraphBuilder::BuildUncheckedStringAdd(HValue* left,
1479 HValue* right,
1480 PretenureFlag pretenure_flag) {
1481 // Determine the string lengths.
1482 HValue* left_length = Add<HLoadNamedField>(
1483 left, HObjectAccess::ForStringLength());
1484 HValue* right_length = Add<HLoadNamedField>(
1485 right, HObjectAccess::ForStringLength());
1486
1487 // Check if we concatenated the strings here, or if we have to resort to the
1488 // runtime function.
1489 HIfContinuation handled(graph()->CreateBasicBlock(),
1490 graph()->CreateBasicBlock());
1491
1492 // Check if both parameters do not exceed half the max string length, because
1493 // exceptionally long strings should be handled in the runtime. This may be
1494 // too pessimistic, but it's the only portable way to express this in Hydrogen
1495 // right now.
mvstanton 2013/11/08 10:17:50 I appreciate the detailed comments on this long an
Benedikt Meurer 2013/11/08 13:21:08 Done.
1496 HConstant* max_length = Add<HConstant>(
1497 static_cast<int32_t>(String::kMaxLength / 2));
1498 IfBuilder if_nooverflow(this);
1499 if_nooverflow.If<HCompareNumericAndBranch>(
1500 left_length, max_length, Token::LTE);
1501 if_nooverflow.AndIf<HCompareNumericAndBranch>(
1502 right_length, max_length, Token::LTE);
1503 if_nooverflow.Then();
1504 {
1505 // Determine the string instance types.
1506 HLoadNamedField* left_instance_type = Add<HLoadNamedField>(
1507 Add<HLoadNamedField>(left, HObjectAccess::ForMap()),
1508 HObjectAccess::ForMapInstanceType());
1509 HLoadNamedField* right_instance_type = Add<HLoadNamedField>(
1510 Add<HLoadNamedField>(right, HObjectAccess::ForMap()),
1511 HObjectAccess::ForMapInstanceType());
1512
1513 // Compute the length of the resulting string.
1514 HValue* length = Add<HAdd>(left_length, right_length);
1515
1516 // Check if we should create a cons string.
1517 IfBuilder if_createcons(this);
1518 if_createcons.If<HCompareNumericAndBranch>(
1519 length,
1520 Add<HConstant>(static_cast<int32_t>(ConsString::kMinLength)),
1521 Token::GTE);
1522 if_createcons.Then();
1523 {
1524 // Allocate the cons string object. HAllocate does not care whether we
1525 // pass CONS_STRING_TYPE or CONS_ASCII_STRING_TYPE here, so we just use
1526 // CONS_STRING_TYPE here. Below we decide whether the cons string is
1527 // one-byte or two-byte and set the appropriate map.
1528 HAllocate* string = Add<HAllocate>(Add<HConstant>(ConsString::kSize),
1529 HType::String(), pretenure_flag,
1530 CONS_STRING_TYPE);
1531
1532 // We create a one-byte cons string if
1533 // 1. both strings are one-byte, or
1534 // 2. at least one of the strings is two-byte, but happens to contain only
1535 // one-byte characters.
1536 // To do this, we check
1537 // 1. if both strings are one-byte, or
1538 // 2. if the one-byte data hint is set in both strings, or
1539 // 3. if one of the strings has the one-byte data hint set and the other
1540 // string is one-byte.
1541 IfBuilder if_onebyte(this);
1542 STATIC_ASSERT(kTwoByteStringTag == 0);
1543 if_onebyte.If<HCompareNumericAndBranch>(
1544 Add<HBitwise>(
1545 Token::BIT_AND,
1546 Add<HBitwise>(
1547 Token::BIT_AND, left_instance_type, right_instance_type),
1548 Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))),
1549 graph()->GetConstant0(),
1550 Token::NE);
1551 if_onebyte.Or();
1552 STATIC_ASSERT(kOneByteDataHintMask != 0);
1553 if_onebyte.If<HCompareNumericAndBranch>(
1554 Add<HBitwise>(
1555 Token::BIT_AND,
1556 Add<HBitwise>(
1557 Token::BIT_AND, left_instance_type, right_instance_type),
1558 Add<HConstant>(static_cast<int32_t>(kOneByteDataHintMask))),
mvstanton 2013/11/08 10:17:50 These hurt my eyes. :) How about a helper function
Benedikt Meurer 2013/11/08 13:21:08 I'm not sure that's going to make it better. Tried
1559 graph()->GetConstant0(),
1560 Token::NE);
1561 if_onebyte.Or();
1562 STATIC_ASSERT(kOneByteStringTag != 0 &&
1563 kOneByteDataHintTag != 0 &&
1564 kOneByteDataHintTag != kOneByteStringTag);
1565 if_onebyte.If<HCompareNumericAndBranch>(
1566 Add<HBitwise>(
1567 Token::BIT_AND,
1568 Add<HBitwise>(
1569 Token::BIT_XOR, left_instance_type, right_instance_type),
1570 Add<HConstant>(static_cast<int32_t>(
1571 kOneByteStringTag | kOneByteDataHintTag))),
1572 Add<HConstant>(static_cast<int32_t>(
1573 kOneByteStringTag | kOneByteDataHintTag)),
1574 Token::EQ);
1575 if_onebyte.Then();
1576 {
1577 // We can safely skip the write barrier for storing the map here.
1578 HStoreNamedField* store_map = AddStoreMapConstant(
1579 string, isolate()->factory()->cons_ascii_string_map());
1580 store_map->SkipWriteBarrier();
1581 }
1582 if_onebyte.Else();
1583 {
1584 // We can safely skip the write barrier for storing the map here.
1585 HStoreNamedField* store_map = AddStoreMapConstant(
1586 string, isolate()->factory()->cons_string_map());
1587 store_map->SkipWriteBarrier();
1588 }
1589 if_onebyte.End();
1590
1591 // Initialize the cons string fields.
1592 Add<HStoreNamedField>(string, HObjectAccess::ForStringHashField(),
1593 Add<HConstant>(String::kEmptyHashField));
1594 Add<HStoreNamedField>(string, HObjectAccess::ForStringLength(), length);
1595 Add<HStoreNamedField>(string, HObjectAccess::ForConsStringFirst(), left);
1596 Add<HStoreNamedField>(string, HObjectAccess::ForConsStringSecond(),
1597 right);
1598
1599 // Cons string is result.
1600 Push(string);
1601 }
1602 if_createcons.Else();
1603 {
1604 // Check if both strings have the same encoding and both are
1605 // sequential.
1606 IfBuilder if_sameencodingandsequential(this);
1607 if_sameencodingandsequential.If<HCompareNumericAndBranch>(
1608 Add<HBitwise>(
1609 Token::BIT_AND,
1610 Add<HBitwise>(
1611 Token::BIT_XOR, left_instance_type, right_instance_type),
1612 Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))),
mvstanton 2013/11/08 10:17:50 More instances of your typical pattern here, OP1(O
1613 graph()->GetConstant0(), Token::EQ);
1614 if_sameencodingandsequential.And();
1615 if_sameencodingandsequential.If<HCompareNumericAndBranch>(
1616 Add<HBitwise>(
1617 Token::BIT_AND,
1618 Add<HBitwise>(
1619 Token::BIT_OR, left_instance_type, right_instance_type),
1620 Add<HConstant>(static_cast<int32_t>(kStringRepresentationMask))),
1621 Add<HConstant>(static_cast<int32_t>(kSeqStringTag)), Token::EQ);
1622 if_sameencodingandsequential.Then();
1623 {
1624 // Check if the result is a one-byte string.
1625 IfBuilder if_onebyte(this);
1626 if_onebyte.If<HCompareNumericAndBranch>(
1627 Add<HBitwise>(
1628 Token::BIT_AND,
1629 Add<HBitwise>(
1630 Token::BIT_OR, left_instance_type, right_instance_type),
1631 Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))),
1632 Add<HConstant>(static_cast<int32_t>(kTwoByteStringTag)), Token::NE);
1633 if_onebyte.Then();
1634 {
1635 // Calculate the number of bytes needed for the characters in the
1636 // string while observing object alignment.
1637 STATIC_ASSERT(kOneByteSize == 1);
1638 STATIC_ASSERT((SeqOneByteString::kHeaderSize &
1639 kObjectAlignmentMask) == 0);
1640 HValue* size = Add<HAdd>(
1641 length, Add<HConstant>(static_cast<int32_t>(
1642 SeqOneByteString::kHeaderSize + kObjectAlignmentMask)));
1643 size->ClearFlag(HValue::kCanOverflow);
1644 size = Add<HBitwise>(
1645 Token::BIT_AND, size, Add<HConstant>(static_cast<int32_t>(
1646 ~kObjectAlignmentMask)));
1647
mvstanton 2013/11/08 10:17:50 The size operand calculation above is very tricky
Benedikt Meurer 2013/11/08 13:21:08 Done.
1648 // Allocate the ASCII string object.
1649 Handle<Map> map = isolate()->factory()->ascii_string_map();
1650 HAllocate* string = Add<HAllocate>(size, HType::String(),
1651 pretenure_flag, ASCII_STRING_TYPE);
1652 string->set_known_initial_map(map);
1653
1654 // We can safely skip the write barrier for storing map here.
1655 HStoreNamedField* store_map = AddStoreMapConstant(string, map);
mvstanton 2013/11/08 10:17:50 AddStoreMapConstantNoWriteBarrier() again, or as a
Benedikt Meurer 2013/11/08 13:21:08 Done.
1656 store_map->SkipWriteBarrier();
1657
1658 // Copy bytes from the left string.
1659 BuildCopySeqStringChars(
1660 left, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
1661 string, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
1662 left_length);
1663
1664 // Copy bytes from the right string.
1665 BuildCopySeqStringChars(
1666 right, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
1667 string, left_length, String::ONE_BYTE_ENCODING,
1668 right_length);
1669
1670 // Return the string.
1671 Push(string);
1672 }
1673 if_onebyte.Else();
1674 {
1675 // Calculate the number of bytes needed for the characters in the
1676 // string while observing object alignment.
1677 STATIC_ASSERT(kUC16Size == 2);
1678 STATIC_ASSERT((SeqTwoByteString::kHeaderSize &
1679 kObjectAlignmentMask) == 0);
1680 HValue* size = Add<HShl>(length, graph()->GetConstant1());
1681 size->ClearFlag(HValue::kCanOverflow);
1682 size->SetFlag(HValue::kUint32);
1683 size = Add<HAdd>(
1684 size, Add<HConstant>(static_cast<int32_t>(
1685 SeqTwoByteString::kHeaderSize + kObjectAlignmentMask)));
1686 size->ClearFlag(HValue::kCanOverflow);
1687 size = Add<HBitwise>(
1688 Token::BIT_AND, size, Add<HConstant>(static_cast<int32_t>(
1689 ~kObjectAlignmentMask)));
1690
1691 // Allocate the two-byte string object.
1692 Handle<Map> map = isolate()->factory()->string_map();
1693 HAllocate* string = Add<HAllocate>(size, HType::String(),
1694 pretenure_flag, STRING_TYPE);
1695 string->set_known_initial_map(map);
1696
1697 // We can safely skip the write barrier for storing map here.
1698 HStoreNamedField* store_map = AddStoreMapConstant(string, map);
mvstanton 2013/11/08 10:17:50 Could you add a variant to AddStoreMapConstant eit
Benedikt Meurer 2013/11/08 13:21:08 Done.
1699 store_map->SkipWriteBarrier();
1700
1701 // Copy bytes from the left string.
1702 BuildCopySeqStringChars(
1703 left, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
1704 string, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
1705 left_length);
1706
1707 // Copy bytes from the right string.
1708 BuildCopySeqStringChars(
1709 right, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
1710 string, left_length, String::TWO_BYTE_ENCODING,
1711 right_length);
1712
1713 // Return the string.
1714 Push(string);
1715 }
1716 if_onebyte.End();
1717
1718 // Initialize the (common) string fields.
1719 HValue* string = Pop();
1720 Add<HStoreNamedField>(string, HObjectAccess::ForStringHashField(),
1721 Add<HConstant>(String::kEmptyHashField));
1722 Add<HStoreNamedField>(string, HObjectAccess::ForStringLength(),
1723 length);
1724 Push(string);
1725 }
1726 if_sameencodingandsequential.JoinContinuation(&handled);
1727 }
1728 if_createcons.JoinContinuation(&handled);
1729 }
1730 if_nooverflow.JoinContinuation(&handled);
1731
1732 // Check if the strings were concatenated successfully, otherwise fallback to
1733 // add the strings in the runtime.
1734 IfBuilder if_handled(this, &handled);
1735 if_handled.Then();
1736 {
1737 // Count the native string addition.
1738 AddIncrementCounter(isolate()->counters()->string_add_native());
1739 }
1740 if_handled.Else();
1741 {
1742 // Fallback to the runtime to add the two strings.
1743 Add<HPushArgument>(left);
1744 Add<HPushArgument>(right);
1745 Push(Add<HCallRuntime>(isolate()->factory()->empty_string(),
1746 Runtime::FunctionForId(Runtime::kStringAdd),
1747 2));
1748 }
1749 if_handled.End();
1750
1751 return Pop();
1752 }
1753
1754
1755 HValue* HGraphBuilder::BuildStringAdd(HValue* left,
1756 HValue* right,
1757 PretenureFlag pretenure_flag) {
1758 // Determine the string lengths.
1759 HValue* left_length = Add<HLoadNamedField>(
1760 left, HObjectAccess::ForStringLength());
1761 HValue* right_length = Add<HLoadNamedField>(
1762 right, HObjectAccess::ForStringLength());
1763
1764 // Check if left string is empty.
1765 IfBuilder if_leftisempty(this);
1766 if_leftisempty.If<HCompareNumericAndBranch>(
1767 left_length, graph()->GetConstant0(), Token::EQ);
1768 if_leftisempty.Then();
1769 {
1770 // Just return the right string.
1771 Push(right);
1772 }
1773 if_leftisempty.Else();
1774 {
1775 // Check if right string is empty.
1776 IfBuilder if_rightisempty(this);
1777 if_rightisempty.If<HCompareNumericAndBranch>(
1778 right_length, graph()->GetConstant0(), Token::EQ);
1779 if_rightisempty.Then();
1780 {
1781 // Just return the left string.
1782 Push(left);
1783 }
1784 if_rightisempty.Else();
1785 {
1786 // Concatenate the two non-empty strings.
1787 Push(BuildUncheckedStringAdd(left, right, pretenure_flag));
1788 }
1789 if_rightisempty.End();
1790 }
1791 if_leftisempty.End();
1792
1793 return Pop();
1794 }
1795
1796
1457 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( 1797 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
1458 HValue* checked_object, 1798 HValue* checked_object,
1459 HValue* key, 1799 HValue* key,
1460 HValue* val, 1800 HValue* val,
1461 bool is_js_array, 1801 bool is_js_array,
1462 ElementsKind elements_kind, 1802 ElementsKind elements_kind,
1463 bool is_store, 1803 bool is_store,
1464 LoadKeyedHoleMode load_mode, 1804 LoadKeyedHoleMode load_mode,
1465 KeyedAccessStoreMode store_mode) { 1805 KeyedAccessStoreMode store_mode) {
1466 ASSERT(!IsExternalArrayElementsKind(elements_kind) || !is_js_array); 1806 ASSERT(!IsExternalArrayElementsKind(elements_kind) || !is_js_array);
(...skipping 8389 matching lines...) Expand 10 before | Expand all | Expand 10 after
9856 if (ShouldProduceTraceOutput()) { 10196 if (ShouldProduceTraceOutput()) {
9857 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); 10197 isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
9858 } 10198 }
9859 10199
9860 #ifdef DEBUG 10200 #ifdef DEBUG
9861 graph_->Verify(false); // No full verify. 10201 graph_->Verify(false); // No full verify.
9862 #endif 10202 #endif
9863 } 10203 }
9864 10204
9865 } } // namespace v8::internal 10205 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698