OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 1884 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1895 Slot* slot = var->slot(); | 1895 Slot* slot = var->slot(); |
1896 if (slot->type() == Slot::PARAMETER) { | 1896 if (slot->type() == Slot::PARAMETER) { |
1897 return slot->index(); | 1897 return slot->index(); |
1898 } else { | 1898 } else { |
1899 return (variable_count - 1) - slot->index(); | 1899 return (variable_count - 1) - slot->index(); |
1900 } | 1900 } |
1901 } | 1901 } |
1902 | 1902 |
1903 | 1903 |
1904 void Node::InitializeReachingDefinitions(int definition_count, | 1904 void Node::InitializeReachingDefinitions(int definition_count, |
1905 List<BitVector*>* variables) { | 1905 List<BitVector*>* variables, |
| 1906 WorkList<Node>* worklist, |
| 1907 bool mark) { |
| 1908 ASSERT(!IsMarkedWith(mark)); |
1906 rd_.Initialize(definition_count); | 1909 rd_.Initialize(definition_count); |
| 1910 MarkWith(mark); |
| 1911 worklist->Insert(this); |
1907 } | 1912 } |
1908 | 1913 |
1909 | 1914 |
1910 void BlockNode::InitializeReachingDefinitions(int definition_count, | 1915 void BlockNode::InitializeReachingDefinitions(int definition_count, |
1911 List<BitVector*>* variables) { | 1916 List<BitVector*>* variables, |
| 1917 WorkList<Node>* worklist, |
| 1918 bool mark) { |
| 1919 ASSERT(!IsMarkedWith(mark)); |
1912 int instruction_count = instructions_.length(); | 1920 int instruction_count = instructions_.length(); |
1913 int variable_count = variables->length(); | 1921 int variable_count = variables->length(); |
1914 | 1922 |
1915 rd_.Initialize(definition_count); | 1923 rd_.Initialize(definition_count); |
1916 | 1924 |
1917 for (int i = 0; i < instruction_count; i++) { | 1925 for (int i = 0; i < instruction_count; i++) { |
1918 Expression* expr = instructions_[i]->AsExpression(); | 1926 Expression* expr = instructions_[i]->AsExpression(); |
1919 if (expr == NULL) continue; | 1927 if (expr == NULL) continue; |
1920 Variable* var = expr->AssignedVar(); | 1928 Variable* var = expr->AssignedVar(); |
1921 if (var == NULL) continue; | 1929 if (var == NULL) continue; |
1922 | 1930 |
1923 // All definitions of this variable are killed. | 1931 // All definitions of this variable are killed. |
1924 BitVector* def_set = | 1932 BitVector* def_set = |
1925 variables->at(ReachingDefinitions::IndexFor(var, variable_count)); | 1933 variables->at(ReachingDefinitions::IndexFor(var, variable_count)); |
1926 rd_.kill()->Union(*def_set); | 1934 rd_.kill()->Union(*def_set); |
1927 | 1935 |
1928 // All previously generated definitions are not generated. | 1936 // All previously generated definitions are not generated. |
1929 rd_.gen()->Subtract(*def_set); | 1937 rd_.gen()->Subtract(*def_set); |
1930 | 1938 |
1931 // This one is generated. | 1939 // This one is generated. |
1932 rd_.gen()->Add(expr->num()); | 1940 rd_.gen()->Add(expr->num()); |
1933 } | 1941 } |
| 1942 |
| 1943 if (predecessor_ != NULL) { |
| 1944 MarkWith(mark); |
| 1945 worklist->Insert(this); |
| 1946 } |
1934 } | 1947 } |
1935 | 1948 |
1936 | 1949 |
| 1950 void ExitNode::ComputeRDOut(BitVector* result) { |
| 1951 // Should not be the predecessor of any node. |
| 1952 UNREACHABLE(); |
| 1953 } |
| 1954 |
| 1955 |
| 1956 void BlockNode::ComputeRDOut(BitVector* result) { |
| 1957 // All definitions reaching this block ... |
| 1958 result->CopyFrom(*rd_.rd_in()); |
| 1959 // ... except those killed by the block ... |
| 1960 result->Subtract(*rd_.kill()); |
| 1961 // ... but including those generated by the block. |
| 1962 result->Union(*rd_.gen()); |
| 1963 } |
| 1964 |
| 1965 |
| 1966 void BranchNode::ComputeRDOut(BitVector* result) { |
| 1967 // Branch nodes don't kill or generate definitions. |
| 1968 result->CopyFrom(*rd_.rd_in()); |
| 1969 } |
| 1970 |
| 1971 |
| 1972 void JoinNode::ComputeRDOut(BitVector* result) { |
| 1973 // Join nodes don't kill or generate definitions. |
| 1974 result->CopyFrom(*rd_.rd_in()); |
| 1975 } |
| 1976 |
| 1977 |
| 1978 void ExitNode::UpdateRDIn(WorkList<Node>* worklist, bool mark) { |
| 1979 // The exit node has no successors so we can just update in place. New |
| 1980 // RD_in is the union over all predecessors. |
| 1981 int definition_count = rd_.rd_in()->length(); |
| 1982 rd_.rd_in()->Clear(); |
| 1983 for (int i = 0, len = predecessors_.length(); i < len; i++) { |
| 1984 BitVector temp(definition_count); |
| 1985 predecessors_[i]->ComputeRDOut(&temp); |
| 1986 rd_.rd_in()->Union(temp); |
| 1987 } |
| 1988 } |
| 1989 |
| 1990 |
| 1991 void BlockNode::UpdateRDIn(WorkList<Node>* worklist, bool mark) { |
| 1992 // The entry block has no predecessor. Its RD_in does not change. |
| 1993 if (predecessor_ == NULL) return; |
| 1994 |
| 1995 BitVector new_rd_in(rd_.rd_in()->length()); |
| 1996 predecessor_->ComputeRDOut(&new_rd_in); |
| 1997 |
| 1998 if (rd_.rd_in()->Equals(new_rd_in)) return; |
| 1999 |
| 2000 // Update RD_in. |
| 2001 rd_.rd_in()->CopyFrom(new_rd_in); |
| 2002 // Add the successor to the worklist if not already present. |
| 2003 if (!successor_->IsMarkedWith(mark)) { |
| 2004 successor_->MarkWith(mark); |
| 2005 worklist->Insert(successor_); |
| 2006 } |
| 2007 } |
| 2008 |
| 2009 |
| 2010 void BranchNode::UpdateRDIn(WorkList<Node>* worklist, bool mark) { |
| 2011 BitVector new_rd_in(rd_.rd_in()->length()); |
| 2012 predecessor_->ComputeRDOut(&new_rd_in); |
| 2013 |
| 2014 if (rd_.rd_in()->Equals(new_rd_in)) return; |
| 2015 |
| 2016 // Update RD_in. |
| 2017 rd_.rd_in()->CopyFrom(new_rd_in); |
| 2018 // Add the successors to the worklist if not already present. |
| 2019 if (!successor0_->IsMarkedWith(mark)) { |
| 2020 successor0_->MarkWith(mark); |
| 2021 worklist->Insert(successor0_); |
| 2022 } |
| 2023 if (!successor1_->IsMarkedWith(mark)) { |
| 2024 successor1_->MarkWith(mark); |
| 2025 worklist->Insert(successor1_); |
| 2026 } |
| 2027 } |
| 2028 |
| 2029 |
| 2030 void JoinNode::UpdateRDIn(WorkList<Node>* worklist, bool mark) { |
| 2031 int definition_count = rd_.rd_in()->length(); |
| 2032 BitVector new_rd_in(definition_count); |
| 2033 |
| 2034 // New RD_in is the union over all predecessors. |
| 2035 for (int i = 0, len = predecessors_.length(); i < len; i++) { |
| 2036 BitVector temp(definition_count); |
| 2037 predecessors_[i]->ComputeRDOut(&temp); |
| 2038 new_rd_in.Union(temp); |
| 2039 } |
| 2040 |
| 2041 if (rd_.rd_in()->Equals(new_rd_in)) return; |
| 2042 |
| 2043 // Update RD_in. |
| 2044 rd_.rd_in()->CopyFrom(new_rd_in); |
| 2045 // Add the successor to the worklist if not already present. |
| 2046 if (!successor_->IsMarkedWith(mark)) { |
| 2047 successor_->MarkWith(mark); |
| 2048 worklist->Insert(successor_); |
| 2049 } |
| 2050 } |
| 2051 |
| 2052 |
1937 void ReachingDefinitions::Compute() { | 2053 void ReachingDefinitions::Compute() { |
1938 if (definitions_->is_empty()) return; | 2054 if (definitions_->is_empty()) return; |
1939 | 2055 |
1940 int variable_count = variables_.length(); | 2056 int variable_count = variables_.length(); |
1941 int definition_count = definitions_->length(); | 2057 int definition_count = definitions_->length(); |
1942 int block_count = postorder_->length(); | 2058 int node_count = postorder_->length(); |
1943 | 2059 |
1944 // Step 1: For each variable, identify the set of all its definitions in | 2060 // Step 1: For each variable, identify the set of all its definitions in |
1945 // the body. | 2061 // the body. |
1946 for (int i = 0; i < definition_count; i++) { | 2062 for (int i = 0; i < definition_count; i++) { |
1947 Variable* var = definitions_->at(i)->AssignedVar(); | 2063 Variable* var = definitions_->at(i)->AssignedVar(); |
1948 variables_[IndexFor(var, variable_count)]->Add(i); | 2064 variables_[IndexFor(var, variable_count)]->Add(i); |
1949 } | 2065 } |
1950 | 2066 |
1951 if (FLAG_print_graph_text) { | 2067 if (FLAG_print_graph_text) { |
1952 for (int i = 0; i < variable_count; i++) { | 2068 for (int i = 0; i < variable_count; i++) { |
(...skipping 11 matching lines...) Expand all Loading... |
1964 } else { | 2080 } else { |
1965 PrintF(", %d", j); | 2081 PrintF(", %d", j); |
1966 } | 2082 } |
1967 } | 2083 } |
1968 } | 2084 } |
1969 PrintF("}\n"); | 2085 PrintF("}\n"); |
1970 } | 2086 } |
1971 } | 2087 } |
1972 } | 2088 } |
1973 | 2089 |
1974 // Step 2: Compute KILL and GEN for each block node, initialize RD. | 2090 // Step 2: Compute KILL and GEN for each block node, initialize RD_in for |
1975 for (int i = block_count - 1; i >= 0; i--) { | 2091 // all nodes, and mark and add all nodes to the worklist in reverse |
| 2092 // postorder. All nodes should currently have the same mark. |
| 2093 bool mark = postorder_->at(0)->IsMarkedWith(false); // Negation of current. |
| 2094 WorkList<Node> worklist(node_count); |
| 2095 for (int i = node_count - 1; i >= 0; i--) { |
1976 postorder_->at(i)->InitializeReachingDefinitions(definition_count, | 2096 postorder_->at(i)->InitializeReachingDefinitions(definition_count, |
1977 &variables_); | 2097 &variables_, |
| 2098 &worklist, |
| 2099 mark); |
| 2100 } |
| 2101 |
| 2102 // Step 3: Until the worklist is empty, remove an item compute and update |
| 2103 // its rd_in based on its predecessor's rd_out. If rd_in has changed, add |
| 2104 // all necessary successors to the worklist. |
| 2105 while (!worklist.is_empty()) { |
| 2106 Node* node = worklist.Remove(); |
| 2107 node->MarkWith(!mark); |
| 2108 node->UpdateRDIn(&worklist, mark); |
1978 } | 2109 } |
1979 } | 2110 } |
1980 | 2111 |
1981 | 2112 |
1982 } } // namespace v8::internal | 2113 } } // namespace v8::internal |
OLD | NEW |