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

Side by Side Diff: src/hydrogen.cc

Issue 6881003: Prevent deopt when assigning double values to typed arrays (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Fixes to make ia32 tests run Created 9 years, 8 months 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/conversions-inl.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 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 901 matching lines...) Expand 10 before | Expand all | Expand 10 after
912 } 912 }
913 913
914 RollBackTo(last_changed_range); 914 RollBackTo(last_changed_range);
915 } 915 }
916 916
917 917
918 void HRangeAnalysis::InferControlFlowRange(HTest* test, HBasicBlock* dest) { 918 void HRangeAnalysis::InferControlFlowRange(HTest* test, HBasicBlock* dest) {
919 ASSERT((test->FirstSuccessor() == dest) == (test->SecondSuccessor() != dest)); 919 ASSERT((test->FirstSuccessor() == dest) == (test->SecondSuccessor() != dest));
920 if (test->value()->IsCompare()) { 920 if (test->value()->IsCompare()) {
921 HCompare* compare = HCompare::cast(test->value()); 921 HCompare* compare = HCompare::cast(test->value());
922 if (compare->GetInputRepresentation().IsInteger32()) { 922 if (compare->GetInputRepresentation().IsInteger()) {
923 Token::Value op = compare->token(); 923 Token::Value op = compare->token();
924 if (test->SecondSuccessor() == dest) { 924 if (test->SecondSuccessor() == dest) {
925 op = Token::NegateCompareOp(op); 925 op = Token::NegateCompareOp(op);
926 } 926 }
927 Token::Value inverted_op = Token::InvertCompareOp(op); 927 Token::Value inverted_op = Token::InvertCompareOp(op);
928 InferControlFlowRange(op, compare->left(), compare->right()); 928 InferControlFlowRange(op, compare->left(), compare->right());
929 InferControlFlowRange(inverted_op, compare->right(), compare->left()); 929 InferControlFlowRange(inverted_op, compare->right(), compare->left());
930 } 930 }
931 } 931 }
932 } 932 }
(...skipping 565 matching lines...) Expand 10 before | Expand all | Expand 10 after
1498 1498
1499 Zone* zone() { return graph_->zone(); } 1499 Zone* zone() { return graph_->zone(); }
1500 1500
1501 HGraph* graph_; 1501 HGraph* graph_;
1502 ZoneList<HValue*> worklist_; 1502 ZoneList<HValue*> worklist_;
1503 BitVector in_worklist_; 1503 BitVector in_worklist_;
1504 }; 1504 };
1505 1505
1506 1506
1507 void HInferRepresentation::AddToWorklist(HValue* current) { 1507 void HInferRepresentation::AddToWorklist(HValue* current) {
1508 if (current->representation().IsSpecialization()) return; 1508 if (current->representation().IsTerminalSpecialization()) return;
1509 if (!current->CheckFlag(HValue::kFlexibleRepresentation)) return; 1509 if (!current->CheckFlag(HValue::kFlexibleRepresentation)) return;
1510 if (in_worklist_.Contains(current->id())) return; 1510 if (in_worklist_.Contains(current->id())) return;
1511 worklist_.Add(current); 1511 worklist_.Add(current);
1512 in_worklist_.Add(current->id()); 1512 in_worklist_.Add(current->id());
1513 } 1513 }
1514 1514
1515 1515
1516 // This method tries to specialize the representation type of the value 1516 // This method tries to specialize the representation type of the value
1517 // given as a parameter. The value is asked to infer its representation type 1517 // given as a parameter. The value is asked to infer its representation type
1518 // based on its inputs. If the inferred type is more specialized, then this 1518 // based on its inputs. If the inferred type is more specialized, then this
1519 // becomes the new representation type of the node. 1519 // becomes the new representation type of the node.
1520 void HInferRepresentation::InferBasedOnInputs(HValue* current) { 1520 void HInferRepresentation::InferBasedOnInputs(HValue* current) {
1521 Representation r = current->representation(); 1521 Representation r = current->representation();
1522 if (r.IsSpecialization()) return; 1522 if (r.IsTerminalSpecialization()) return;
1523 ASSERT(current->CheckFlag(HValue::kFlexibleRepresentation)); 1523 ASSERT(current->CheckFlag(HValue::kFlexibleRepresentation));
1524 Representation inferred = current->InferredRepresentation(); 1524 Representation inferred = current->InferredRepresentation();
1525 if (inferred.IsSpecialization()) { 1525 if (!inferred.Equals(r)) {
1526 current->ChangeRepresentation(inferred); 1526 current->ChangeRepresentation(inferred);
1527 AddDependantsToWorklist(current); 1527 AddDependantsToWorklist(current);
1528 } 1528 }
1529 } 1529 }
1530 1530
1531 1531
1532 void HInferRepresentation::AddDependantsToWorklist(HValue* current) { 1532 void HInferRepresentation::AddDependantsToWorklist(HValue* current) {
1533 for (int i = 0; i < current->uses()->length(); ++i) { 1533 for (int i = 0; i < current->uses()->length(); ++i) {
1534 AddToWorklist(current->uses()->at(i)); 1534 AddToWorklist(current->uses()->at(i));
1535 } 1535 }
1536 for (int i = 0; i < current->OperandCount(); ++i) { 1536 for (int i = 0; i < current->OperandCount(); ++i) {
1537 AddToWorklist(current->OperandAt(i)); 1537 AddToWorklist(current->OperandAt(i));
1538 } 1538 }
1539 } 1539 }
1540 1540
1541 1541
1542 // This method calculates whether specializing the representation of the value 1542 // This method calculates whether specializing the representation of the value
1543 // given as the parameter has a benefit in terms of less necessary type 1543 // given as the parameter has a benefit in terms of less necessary type
1544 // conversions. If there is a benefit, then the representation of the value is 1544 // conversions. If there is a benefit, then the representation of the value is
1545 // specialized. 1545 // specialized.
1546 void HInferRepresentation::InferBasedOnUses(HValue* current) { 1546 void HInferRepresentation::InferBasedOnUses(HValue* current) {
1547 Representation r = current->representation(); 1547 Representation r = current->representation();
1548 if (r.IsSpecialization() || current->HasNoUses()) return; 1548 if (r.IsTerminalSpecialization() || current->HasNoUses()) return;
1549 ASSERT(current->CheckFlag(HValue::kFlexibleRepresentation)); 1549 ASSERT(current->CheckFlag(HValue::kFlexibleRepresentation));
1550 Representation new_rep = TryChange(current); 1550 Representation new_rep = TryChange(current);
1551 if (!new_rep.IsNone()) { 1551 if (!new_rep.IsNone()) {
1552 if (!current->representation().Equals(new_rep)) { 1552 if (!current->representation().Equals(new_rep)) {
1553 current->ChangeRepresentation(new_rep); 1553 current->ChangeRepresentation(new_rep);
1554 AddDependantsToWorklist(current); 1554 AddDependantsToWorklist(current);
1555 } 1555 }
1556 } 1556 }
1557 } 1557 }
1558 1558
(...skipping 12 matching lines...) Expand all
1571 if (req_rep.IsNone()) continue; 1571 if (req_rep.IsNone()) continue;
1572 if (use->IsPhi()) { 1572 if (use->IsPhi()) {
1573 HPhi* phi = HPhi::cast(use); 1573 HPhi* phi = HPhi::cast(use);
1574 phi->AddIndirectUsesTo(&use_count[0]); 1574 phi->AddIndirectUsesTo(&use_count[0]);
1575 } 1575 }
1576 use_count[req_rep.kind()]++; 1576 use_count[req_rep.kind()]++;
1577 } 1577 }
1578 int tagged_count = use_count[Representation::kTagged]; 1578 int tagged_count = use_count[Representation::kTagged];
1579 int double_count = use_count[Representation::kDouble]; 1579 int double_count = use_count[Representation::kDouble];
1580 int int32_count = use_count[Representation::kInteger32]; 1580 int int32_count = use_count[Representation::kInteger32];
1581 int non_tagged_count = double_count + int32_count; 1581 int trunc_int32_count = use_count[Representation::kTruncatedInteger32];
1582 int clamped_rounded_int8_count =
1583 use_count[Representation::kClampedRoundedUInteger8];
1584 int non_tagged_count = double_count + int32_count +
1585 trunc_int32_count + clamped_rounded_int8_count;
1586 int total_use_count = tagged_count + non_tagged_count;
1582 1587
1583 // If a non-loop phi has tagged uses, don't convert it to untagged. 1588 // If a non-loop phi has tagged uses, don't convert it to untagged.
1584 if (current->IsPhi() && !current->block()->IsLoopHeader()) { 1589 if (current->IsPhi() && !current->block()->IsLoopHeader()) {
1585 if (tagged_count > 0) return Representation::None(); 1590 if (tagged_count > 0) return Representation::None();
1586 } 1591 }
1587 1592
1588 if (non_tagged_count >= tagged_count) { 1593 if (non_tagged_count >= tagged_count) {
1589 // More untagged than tagged. 1594 // More untagged than tagged.
1590 if (double_count > 0) { 1595 if (double_count > 0) {
1591 // There is at least one usage that is a double => guess that the 1596 // There is at least one usage that is a double => guess that the
1592 // correct representation is double. 1597 // correct representation is double.
1593 return Representation::Double(); 1598 return Representation::Double();
1594 } else if (int32_count > 0) { 1599 } else if (int32_count > 0) {
1595 return Representation::Integer32(); 1600 return Representation::Integer32();
1601 } else if (clamped_rounded_int8_count > 0 &&
1602 clamped_rounded_int8_count == total_use_count) {
1603 return Representation::ClampedRoundedUInteger8();
1604 } else if (trunc_int32_count > 0 &&
1605 trunc_int32_count == total_use_count) {
1606 return Representation::TruncatedInteger32();
1607 } else {
1608 return Representation::None();
1596 } 1609 }
1597 } 1610 }
1598 return Representation::None(); 1611 return Representation::None();
1599 } 1612 }
1600 1613
1601 1614
1602 void HInferRepresentation::Analyze() { 1615 void HInferRepresentation::Analyze() {
1603 HPhase phase("Infer representations", graph_); 1616 HPhase phase("Infer representations", graph_);
1604 1617
1605 // (1) Initialize bit vectors and count real uses. Each phi 1618 // (1) Initialize bit vectors and count real uses. Each phi
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
1757 next = use->block()->predecessors()->at(index)->end(); 1770 next = use->block()->predecessors()->at(index)->end();
1758 } else { 1771 } else {
1759 next = HInstruction::cast(use); 1772 next = HInstruction::cast(use);
1760 } 1773 }
1761 1774
1762 // For constants we try to make the representation change at compile 1775 // For constants we try to make the representation change at compile
1763 // time. When a representation change is not possible without loss of 1776 // time. When a representation change is not possible without loss of
1764 // information we treat constants like normal instructions and insert the 1777 // information we treat constants like normal instructions and insert the
1765 // change instructions for them. 1778 // change instructions for them.
1766 HInstruction* new_value = NULL; 1779 HInstruction* new_value = NULL;
1767 bool is_truncating = use->CheckFlag(HValue::kTruncatingToInt32);
1768 if (value->IsConstant()) { 1780 if (value->IsConstant()) {
1769 HConstant* constant = HConstant::cast(value); 1781 HConstant* constant = HConstant::cast(value);
1770 // Try to create a new copy of the constant with the new representation. 1782 // Try to create a new copy of the constant with the new representation.
1771 new_value = is_truncating 1783 new_value = to.IsTruncatedInteger32()
1772 ? constant->CopyToTruncatedInt32() 1784 ? constant->CopyToTruncatedInt32()
1773 : constant->CopyToRepresentation(to); 1785 : to.IsClampedRoundedInteger8()
1786 ? constant->CopyToClampedRoundedUInt8()
1787 : constant->CopyToRepresentation(to);
1774 } 1788 }
1775 1789
1776 if (new_value == NULL) { 1790 if (new_value == NULL) {
1791 Representation from = value->representation();
1792 // Don't create changes for representation differences that
1793 // won't generate code.
1794 if (from.IsInteger() && (to.IsInteger32X() || to.IsTruncatedInteger32())) {
1795 return;
1796 }
1797
1777 new_value = 1798 new_value =
1778 new(zone()) HChange(value, value->representation(), to, is_truncating); 1799 new(zone()) HChange(value,
1800 from,
1801 to);
1779 } 1802 }
1780 1803
1781 new_value->InsertBefore(next); 1804 new_value->InsertBefore(next);
1782 value->ReplaceFirstAtUse(use, new_value, to); 1805 value->ReplaceFirstAtUse(use, new_value, to);
1783 } 1806 }
1784 1807
1785 1808
1786 int CompareConversionUses(HValue* a,
1787 HValue* b,
1788 Representation a_rep,
1789 Representation b_rep) {
1790 if (a_rep.kind() > b_rep.kind()) {
1791 // Make sure specializations are separated in the result array.
1792 return 1;
1793 }
1794 // Put truncating conversions before non-truncating conversions.
1795 bool a_truncate = a->CheckFlag(HValue::kTruncatingToInt32);
1796 bool b_truncate = b->CheckFlag(HValue::kTruncatingToInt32);
1797 if (a_truncate != b_truncate) {
1798 return a_truncate ? -1 : 1;
1799 }
1800 // Sort by increasing block ID.
1801 return a->block()->block_id() - b->block()->block_id();
1802 }
1803
1804
1805 void HGraph::InsertRepresentationChangesForValue( 1809 void HGraph::InsertRepresentationChangesForValue(
1806 HValue* current, 1810 HValue* current,
1807 ZoneList<HValue*>* to_convert, 1811 ZoneList<HValue*>* to_convert,
1808 ZoneList<Representation>* to_convert_reps) { 1812 ZoneList<Representation>* to_convert_reps) {
1809 Representation r = current->representation(); 1813 Representation r = current->representation();
1810 if (r.IsNone()) return; 1814 if (r.IsNone()) return;
1811 if (current->uses()->is_empty()) return; 1815 if (current->uses()->is_empty()) return;
1812 1816
1813 // Collect the representation changes in a sorted list. This allows 1817 // Collect the representation changes in a sorted list. This allows
1814 // us to avoid duplicate changes without searching the list. 1818 // us to avoid duplicate changes without searching the list.
1815 ASSERT(to_convert->is_empty()); 1819 ASSERT(to_convert->is_empty());
1816 ASSERT(to_convert_reps->is_empty()); 1820 ASSERT(to_convert_reps->is_empty());
1821 int index = 0;
1817 for (int i = 0; i < current->uses()->length(); ++i) { 1822 for (int i = 0; i < current->uses()->length(); ++i) {
1818 HValue* use = current->uses()->at(i); 1823 HValue* use = current->uses()->at(i);
1819 // The occurrences index means the index within the operand array of "use" 1824 // The occurrences index means the index within the operand array of "use"
1820 // at which "current" is used. While iterating through the use array we 1825 // at which "current" is used. While iterating through the use array we
1821 // also have to iterate over the different occurrence indices. 1826 // also have to iterate over the different occurrence indices.
1822 int occurrence_index = 0; 1827 int occurrence_index = 0;
1823 if (use->UsesMultipleTimes(current)) { 1828 if (use->UsesMultipleTimes(current)) {
1824 occurrence_index = current->uses()->CountOccurrences(use, 0, i - 1); 1829 occurrence_index = current->uses()->CountOccurrences(use, 0, i - 1);
1825 if (FLAG_trace_representation) { 1830 if (FLAG_trace_representation) {
1826 PrintF("Instruction %d is used multiple times at %d; occurrence=%d\n", 1831 PrintF("Instruction %d is used multiple times at %d; occurrence=%d\n",
1827 current->id(), 1832 current->id(),
1828 use->id(), 1833 use->id(),
1829 occurrence_index); 1834 occurrence_index);
1830 } 1835 }
1831 } 1836 }
1832 int operand_index = use->LookupOperandIndex(occurrence_index, current); 1837 int operand_index = use->LookupOperandIndex(occurrence_index, current);
1833 Representation req = use->RequiredInputRepresentation(operand_index); 1838 Representation req = use->RequiredInputRepresentation(operand_index);
1834 if (req.IsNone() || req.Equals(r)) continue; 1839 if (req.IsNone() || req.Equals(r)) continue;
1835 int index = 0;
1836 while (index < to_convert->length() &&
1837 CompareConversionUses(to_convert->at(index),
fschneider 2011/05/10 10:44:53 Thanks for cleaning this up!
1838 use,
1839 to_convert_reps->at(index),
1840 req) < 0) {
1841 ++index;
1842 }
1843 if (FLAG_trace_representation) {
1844 PrintF("Inserting a representation change to %s of %d for use at %d\n",
1845 req.Mnemonic(),
1846 current->id(),
1847 use->id());
1848 }
1849 to_convert->InsertAt(index, use); 1840 to_convert->InsertAt(index, use);
1850 to_convert_reps->InsertAt(index, req); 1841 to_convert_reps->InsertAt(index, req);
1842 ++index;
1851 } 1843 }
1852 1844
1853 for (int i = 0; i < to_convert->length(); ++i) { 1845 for (int i = 0; i < to_convert->length(); ++i) {
1854 HValue* use = to_convert->at(i); 1846 HValue* use = to_convert->at(i);
1855 Representation r_to = to_convert_reps->at(i); 1847 Representation r_to = to_convert_reps->at(i);
1848 if (FLAG_trace_representation) {
1849 PrintF("Inserting a representation change to %s of %d for use at %d\n",
1850 r_to.Mnemonic(),
1851 current->id(),
1852 use->id());
1853 }
1856 InsertRepresentationChangeForUse(current, use, r_to); 1854 InsertRepresentationChangeForUse(current, use, r_to);
1857 } 1855 }
1858 1856
1859 if (current->uses()->is_empty()) { 1857 if (current->uses()->is_empty()) {
1860 ASSERT(current->IsConstant()); 1858 ASSERT(current->IsConstant());
1861 current->Delete(); 1859 current->Delete();
1862 } 1860 }
1863 to_convert->Rewind(0); 1861 to_convert->Rewind(0);
1864 to_convert_reps->Rewind(0); 1862 to_convert_reps->Rewind(0);
1865 } 1863 }
1866 1864
1867 1865
1868 void HGraph::InsertRepresentationChanges() { 1866 void HGraph::InsertRepresentationChanges() {
1869 HPhase phase("Insert representation changes", this); 1867 HPhase phase("Insert representation changes", this);
fschneider 2011/05/10 10:44:53 Not sure that the representation computation does
1870
1871
1872 // Compute truncation flag for phis: Initially assume that all
1873 // int32-phis allow truncation and iteratively remove the ones that
1874 // are used in an operation that does not allow a truncating
1875 // conversion.
1876 // TODO(fschneider): Replace this with a worklist-based iteration.
1877 for (int i = 0; i < phi_list()->length(); i++) {
1878 HPhi* phi = phi_list()->at(i);
1879 if (phi->representation().IsInteger32()) {
1880 phi->SetFlag(HValue::kTruncatingToInt32);
1881 }
1882 }
1883 bool change = true;
1884 while (change) {
1885 change = false;
1886 for (int i = 0; i < phi_list()->length(); i++) {
1887 HPhi* phi = phi_list()->at(i);
1888 if (!phi->CheckFlag(HValue::kTruncatingToInt32)) continue;
1889 for (int j = 0; j < phi->uses()->length(); j++) {
1890 HValue* use = phi->uses()->at(j);
1891 if (!use->CheckFlag(HValue::kTruncatingToInt32)) {
1892 phi->ClearFlag(HValue::kTruncatingToInt32);
1893 change = true;
1894 break;
1895 }
1896 }
1897 }
1898 }
1899
1900 ZoneList<HValue*> value_list(4); 1868 ZoneList<HValue*> value_list(4);
1901 ZoneList<Representation> rep_list(4); 1869 ZoneList<Representation> rep_list(4);
1902 for (int i = 0; i < blocks_.length(); ++i) { 1870 for (int i = 0; i < blocks_.length(); ++i) {
1903 // Process phi instructions first. 1871 // Process phi instructions first.
1904 for (int j = 0; j < blocks_[i]->phis()->length(); j++) { 1872 for (int j = 0; j < blocks_[i]->phis()->length(); j++) {
1905 HPhi* phi = blocks_[i]->phis()->at(j); 1873 HPhi* phi = blocks_[i]->phis()->at(j);
1906 InsertRepresentationChangesForValue(phi, &value_list, &rep_list); 1874 InsertRepresentationChangesForValue(phi, &value_list, &rep_list);
1907 } 1875 }
1908 1876
1909 // Process normal instructions. 1877 // Process normal instructions.
(...skipping 11 matching lines...) Expand all
1921 for (int i = 0; i < blocks_.length(); ++i) { 1889 for (int i = 0; i < blocks_.length(); ++i) {
1922 for (HInstruction* current = blocks_[i]->first(); 1890 for (HInstruction* current = blocks_[i]->first();
1923 current != NULL; 1891 current != NULL;
1924 current = current->next()) { 1892 current = current->next()) {
1925 if (current->IsChange()) { 1893 if (current->IsChange()) {
1926 HChange* change = HChange::cast(current); 1894 HChange* change = HChange::cast(current);
1927 // Propagate flags for negative zero checks upwards from conversions 1895 // Propagate flags for negative zero checks upwards from conversions
1928 // int32-to-tagged and int32-to-double. 1896 // int32-to-tagged and int32-to-double.
1929 Representation from = change->value()->representation(); 1897 Representation from = change->value()->representation();
1930 ASSERT(from.Equals(change->from())); 1898 ASSERT(from.Equals(change->from()));
1931 if (from.IsInteger32()) { 1899 if (from.IsInteger() && !change->to().IsInteger()) {
1932 ASSERT(change->to().IsTagged() || change->to().IsDouble()); 1900 ASSERT(change->to().IsTagged() || change->to().IsDouble());
1933 ASSERT(visited.IsEmpty()); 1901 ASSERT(visited.IsEmpty());
1934 PropagateMinusZeroChecks(change->value(), &visited); 1902 PropagateMinusZeroChecks(change->value(), &visited);
1935 visited.Clear(); 1903 visited.Clear();
1936 } 1904 }
1937 } 1905 }
1938 } 1906 }
1939 } 1907 }
1940 } 1908 }
1941 1909
(...skipping 4208 matching lines...) Expand 10 before | Expand all | Expand 10 after
6150 } 6118 }
6151 } 6119 }
6152 6120
6153 #ifdef DEBUG 6121 #ifdef DEBUG
6154 if (graph_ != NULL) graph_->Verify(); 6122 if (graph_ != NULL) graph_->Verify();
6155 if (allocator_ != NULL) allocator_->Verify(); 6123 if (allocator_ != NULL) allocator_->Verify();
6156 #endif 6124 #endif
6157 } 6125 }
6158 6126
6159 } } // namespace v8::internal 6127 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/conversions-inl.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698