Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/intermediate_language.h" | 5 #include "vm/intermediate_language.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/dart_entry.h" | 8 #include "vm/dart_entry.h" |
| 9 #include "vm/flow_graph_allocator.h" | 9 #include "vm/flow_graph_allocator.h" |
| 10 #include "vm/flow_graph_builder.h" | 10 #include "vm/flow_graph_builder.h" |
| 11 #include "vm/flow_graph_compiler.h" | 11 #include "vm/flow_graph_compiler.h" |
| 12 #include "vm/flow_graph_optimizer.h" | 12 #include "vm/flow_graph_optimizer.h" |
| 13 #include "vm/locations.h" | 13 #include "vm/locations.h" |
| 14 #include "vm/object.h" | 14 #include "vm/object.h" |
| 15 #include "vm/object_store.h" | 15 #include "vm/object_store.h" |
| 16 #include "vm/os.h" | 16 #include "vm/os.h" |
| 17 #include "vm/scopes.h" | 17 #include "vm/scopes.h" |
| 18 #include "vm/stub_code.h" | 18 #include "vm/stub_code.h" |
| 19 #include "vm/symbols.h" | 19 #include "vm/symbols.h" |
| 20 | 20 |
| 21 namespace dart { | 21 namespace dart { |
| 22 | 22 |
| 23 DECLARE_FLAG(bool, enable_type_checks); | 23 DECLARE_FLAG(bool, enable_type_checks); |
| 24 | 24 |
| 25 | 25 |
| 26 Definition::Definition() | 26 Definition::Definition() |
| 27 : temp_index_(-1), | 27 : range_(NULL), |
| 28 temp_index_(-1), | |
| 28 ssa_temp_index_(-1), | 29 ssa_temp_index_(-1), |
| 29 propagated_type_(AbstractType::Handle()), | 30 propagated_type_(AbstractType::Handle()), |
| 30 propagated_cid_(kIllegalCid), | 31 propagated_cid_(kIllegalCid), |
| 31 input_use_list_(NULL), | 32 input_use_list_(NULL), |
| 32 env_use_list_(NULL), | 33 env_use_list_(NULL), |
| 33 use_kind_(kValue), // Phis and parameters rely on this default. | 34 use_kind_(kValue), // Phis and parameters rely on this default. |
| 34 constant_value_(Object::ZoneHandle(ConstantPropagator::Unknown())) { | 35 constant_value_(Object::ZoneHandle(ConstantPropagator::Unknown())) { |
| 35 } | 36 } |
| 36 | 37 |
| 37 | 38 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 88 bool StrictCompareInstr::AttributesEqual(Instruction* other) const { | 89 bool StrictCompareInstr::AttributesEqual(Instruction* other) const { |
| 89 StrictCompareInstr* other_op = other->AsStrictCompare(); | 90 StrictCompareInstr* other_op = other->AsStrictCompare(); |
| 90 ASSERT(other_op != NULL); | 91 ASSERT(other_op != NULL); |
| 91 return kind() == other_op->kind(); | 92 return kind() == other_op->kind(); |
| 92 } | 93 } |
| 93 | 94 |
| 94 | 95 |
| 95 bool BinarySmiOpInstr::AttributesEqual(Instruction* other) const { | 96 bool BinarySmiOpInstr::AttributesEqual(Instruction* other) const { |
| 96 BinarySmiOpInstr* other_op = other->AsBinarySmiOp(); | 97 BinarySmiOpInstr* other_op = other->AsBinarySmiOp(); |
| 97 ASSERT(other_op != NULL); | 98 ASSERT(other_op != NULL); |
| 98 return op_kind() == other_op->op_kind(); | 99 return (op_kind() == other_op->op_kind()) && |
| 100 (overflow_ == other_op->overflow_); | |
| 99 } | 101 } |
| 100 | 102 |
| 101 | 103 |
| 102 bool LoadFieldInstr::AttributesEqual(Instruction* other) const { | 104 bool LoadFieldInstr::AttributesEqual(Instruction* other) const { |
| 103 LoadFieldInstr* other_load = other->AsLoadField(); | 105 LoadFieldInstr* other_load = other->AsLoadField(); |
| 104 ASSERT(other_load != NULL); | 106 ASSERT(other_load != NULL); |
| 105 ASSERT((offset_in_bytes() != other_load->offset_in_bytes()) || | 107 ASSERT((offset_in_bytes() != other_load->offset_in_bytes()) || |
| 106 ((immutable_ == other_load->immutable_) && | 108 ((immutable_ == other_load->immutable_) && |
| 107 (ResultCid() == other_load->ResultCid()))); | 109 (ResultCid() == other_load->ResultCid()))); |
| 108 return offset_in_bytes() == other_load->offset_in_bytes(); | 110 return offset_in_bytes() == other_load->offset_in_bytes(); |
| (...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 563 definition()->set_input_use_list(this); | 565 definition()->set_input_use_list(this); |
| 564 } | 566 } |
| 565 | 567 |
| 566 | 568 |
| 567 void Value::AddToEnvUseList() { | 569 void Value::AddToEnvUseList() { |
| 568 set_next_use(definition()->env_use_list()); | 570 set_next_use(definition()->env_use_list()); |
| 569 definition()->set_env_use_list(this); | 571 definition()->set_env_use_list(this); |
| 570 } | 572 } |
| 571 | 573 |
| 572 | 574 |
| 575 void Value::RemoveFromInputUseList() { | |
| 576 if (definition_->input_use_list() == this) { | |
| 577 definition_->set_input_use_list(next_use_); | |
| 578 return; | |
| 579 } | |
| 580 | |
| 581 Value* prev = definition_->input_use_list(); | |
| 582 while (prev->next_use_ != this) { | |
| 583 prev = prev->next_use_; | |
| 584 } | |
| 585 prev->next_use_ = next_use_; | |
| 586 definition_ = NULL; | |
| 587 } | |
| 588 | |
| 589 | |
| 573 void Definition::ReplaceUsesWith(Definition* other) { | 590 void Definition::ReplaceUsesWith(Definition* other) { |
| 574 ASSERT(other != NULL); | 591 ASSERT(other != NULL); |
| 575 ASSERT(this != other); | 592 ASSERT(this != other); |
| 576 while (input_use_list_ != NULL) { | 593 while (input_use_list_ != NULL) { |
| 577 Value* current = input_use_list_; | 594 Value* current = input_use_list_; |
| 578 input_use_list_ = input_use_list_->next_use(); | 595 input_use_list_ = input_use_list_->next_use(); |
| 579 current->set_definition(other); | 596 current->set_definition(other); |
| 580 current->AddToInputUseList(); | 597 current->AddToInputUseList(); |
| 581 } | 598 } |
| 582 while (env_use_list_ != NULL) { | 599 while (env_use_list_ != NULL) { |
| (...skipping 621 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1204 } | 1221 } |
| 1205 | 1222 |
| 1206 | 1223 |
| 1207 bool BinarySmiOpInstr::CanDeoptimize() const { | 1224 bool BinarySmiOpInstr::CanDeoptimize() const { |
| 1208 switch (op_kind()) { | 1225 switch (op_kind()) { |
| 1209 case Token::kBIT_AND: | 1226 case Token::kBIT_AND: |
| 1210 case Token::kBIT_OR: | 1227 case Token::kBIT_OR: |
| 1211 case Token::kBIT_XOR: | 1228 case Token::kBIT_XOR: |
| 1212 return false; | 1229 return false; |
| 1213 default: | 1230 default: |
| 1214 return true; | 1231 return overflow_; |
| 1215 } | 1232 } |
| 1216 } | 1233 } |
| 1217 | 1234 |
| 1218 | 1235 |
| 1219 RawAbstractType* BinaryMintOpInstr::CompileType() const { | 1236 RawAbstractType* BinaryMintOpInstr::CompileType() const { |
| 1220 return Type::MintType(); | 1237 return Type::MintType(); |
| 1221 } | 1238 } |
| 1222 | 1239 |
| 1223 | 1240 |
| 1224 intptr_t BinaryMintOpInstr::ResultCid() const { | 1241 intptr_t BinaryMintOpInstr::ResultCid() const { |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1429 LocationSummary* ParallelMoveInstr::MakeLocationSummary() const { | 1446 LocationSummary* ParallelMoveInstr::MakeLocationSummary() const { |
| 1430 return NULL; | 1447 return NULL; |
| 1431 } | 1448 } |
| 1432 | 1449 |
| 1433 | 1450 |
| 1434 void ParallelMoveInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1451 void ParallelMoveInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1435 UNREACHABLE(); | 1452 UNREACHABLE(); |
| 1436 } | 1453 } |
| 1437 | 1454 |
| 1438 | 1455 |
| 1456 LocationSummary* ConstraintInstr::MakeLocationSummary() const { | |
| 1457 UNREACHABLE(); | |
| 1458 return NULL; | |
| 1459 } | |
| 1460 | |
| 1461 | |
| 1462 void ConstraintInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 1463 UNREACHABLE(); | |
| 1464 } | |
| 1465 | |
| 1439 LocationSummary* ThrowInstr::MakeLocationSummary() const { | 1466 LocationSummary* ThrowInstr::MakeLocationSummary() const { |
| 1440 return new LocationSummary(0, 0, LocationSummary::kCall); | 1467 return new LocationSummary(0, 0, LocationSummary::kCall); |
| 1441 } | 1468 } |
| 1442 | 1469 |
| 1443 | 1470 |
| 1444 | 1471 |
| 1445 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1472 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1446 compiler->GenerateCallRuntime(token_pos(), | 1473 compiler->GenerateCallRuntime(token_pos(), |
| 1447 kThrowRuntimeEntry, | 1474 kThrowRuntimeEntry, |
| 1448 locs()); | 1475 locs()); |
| (...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1836 for (Environment::DeepIterator it(copy); !it.Done(); it.Advance()) { | 1863 for (Environment::DeepIterator it(copy); !it.Done(); it.Advance()) { |
| 1837 Value* value = it.CurrentValue(); | 1864 Value* value = it.CurrentValue(); |
| 1838 value->set_instruction(instr); | 1865 value->set_instruction(instr); |
| 1839 value->set_use_index(use_index++); | 1866 value->set_use_index(use_index++); |
| 1840 value->AddToEnvUseList(); | 1867 value->AddToEnvUseList(); |
| 1841 } | 1868 } |
| 1842 instr->env()->outer_ = copy; | 1869 instr->env()->outer_ = copy; |
| 1843 } | 1870 } |
| 1844 | 1871 |
| 1845 | 1872 |
| 1873 bool Definition::InferRange() { | |
| 1874 ASSERT(GetPropagatedCid() == kSmiCid); // Has meaning only for smis. | |
| 1875 if (range_ == NULL) { | |
| 1876 range_ = Range::Unknown(); | |
| 1877 return true; | |
| 1878 } | |
| 1879 return false; | |
| 1880 } | |
| 1881 | |
| 1882 | |
| 1883 bool ConstantInstr::InferRange() { | |
| 1884 ASSERT(value_.IsSmi()); | |
| 1885 if (range_ == NULL) { | |
| 1886 intptr_t value = Smi::Cast(value_).Value(); | |
| 1887 range_ = new Range(RangeBoundary::FromConstant(value), | |
| 1888 RangeBoundary::FromConstant(value)); | |
| 1889 return true; | |
| 1890 } | |
| 1891 return false; | |
| 1892 } | |
| 1893 | |
| 1894 | |
| 1895 RangeBoundary RangeBoundary::LowerBound() const { | |
| 1896 if (IsConstant()) return *this; | |
| 1897 if (symbol()->range() == NULL) return MinSmi(); | |
| 1898 return Add(symbol()->range()->min().LowerBound(), | |
| 1899 RangeBoundary::FromConstant(offset_), | |
| 1900 MinSmi()); | |
| 1901 } | |
| 1902 | |
| 1903 | |
| 1904 RangeBoundary RangeBoundary::UpperBound() const { | |
| 1905 if (IsConstant()) return *this; | |
| 1906 if (symbol()->range() == NULL) return MaxSmi(); | |
| 1907 return Add(symbol()->range()->max().UpperBound(), | |
| 1908 RangeBoundary::FromConstant(offset_), | |
| 1909 MaxSmi()); | |
| 1910 } | |
| 1911 | |
| 1912 | |
| 1913 bool ConstraintInstr::InferRange() { | |
| 1914 Range* value_range = value()->definition()->range(); | |
| 1915 | |
| 1916 // Compute intersection of constraint and value ranges. | |
| 1917 return Range::Update(&range_, | |
| 1918 RangeBoundary::Max(Range::ConstantMin(value_range), | |
| 1919 Range::ConstantMin(constraint())), | |
| 1920 RangeBoundary::Min(Range::ConstantMax(value_range), | |
| 1921 Range::ConstantMax(constraint()))); | |
| 1922 } | |
| 1923 | |
| 1924 | |
| 1925 bool PhiInstr::InferRange() { | |
| 1926 RangeBoundary new_min; | |
| 1927 RangeBoundary new_max; | |
| 1928 | |
| 1929 bool has_inputs_without_range = false; | |
| 1930 for (intptr_t i = 0; i < InputCount(); i++) { | |
| 1931 Range* input_range = InputAt(i)->definition()->range(); | |
| 1932 if (input_range == NULL) { | |
| 1933 has_inputs_without_range = true; | |
| 1934 continue; | |
| 1935 } | |
| 1936 | |
| 1937 if (new_min.IsUnknown()) { | |
| 1938 new_min = Range::ConstantMin(input_range); | |
| 1939 } else { | |
| 1940 new_min = RangeBoundary::Min(new_min, Range::ConstantMin(input_range)); | |
| 1941 } | |
| 1942 | |
| 1943 if (new_max.IsUnknown()) { | |
| 1944 new_max = Range::ConstantMax(input_range); | |
| 1945 } else { | |
| 1946 new_max = RangeBoundary::Max(new_max, Range::ConstantMax(input_range)); | |
| 1947 } | |
| 1948 } | |
| 1949 | |
| 1950 ASSERT(new_min.IsUnknown() == new_max.IsUnknown()); | |
| 1951 if (new_min.IsUnknown()) { | |
| 1952 ASSERT(range_ == NULL); | |
| 1953 return false; | |
| 1954 } | |
| 1955 | |
| 1956 if ((range_ != NULL) && !has_inputs_without_range_) { | |
| 1957 // If phi's range is growing widen it in the direction of growth to | |
|
ngeoffray
2012/09/24 21:44:15
growing widen -> growing, widen
| |
| 1958 // speedup convergence. | |
|
ngeoffray
2012/09/24 21:44:15
What's the check for 'growing' here? At first glan
| |
| 1959 new_min = RangeBoundary::WidenMin(range_->min(), new_min); | |
| 1960 new_max = RangeBoundary::WidenMax(range_->max(), new_max); | |
| 1961 } | |
| 1962 has_inputs_without_range_ = has_inputs_without_range; | |
| 1963 | |
| 1964 return Range::Update(&range_, new_min, new_max); | |
| 1965 } | |
| 1966 | |
| 1967 | |
| 1968 bool BinarySmiOpInstr::InferRange() { | |
| 1969 Range* left_range = left()->definition()->range(); | |
| 1970 Range* right_range = right()->definition()->range(); | |
| 1971 | |
| 1972 if ((left_range == NULL) || (right_range == NULL)) { | |
| 1973 return Range::Update(&range_, | |
| 1974 RangeBoundary::MinSmi(), | |
| 1975 RangeBoundary::MaxSmi()); | |
| 1976 } | |
| 1977 | |
| 1978 RangeBoundary new_min; | |
| 1979 RangeBoundary new_max; | |
| 1980 switch (op_kind()) { | |
| 1981 case Token::kADD: | |
| 1982 new_min = | |
| 1983 RangeBoundary::Add(Range::ConstantMin(left_range), | |
| 1984 Range::ConstantMin(right_range), | |
| 1985 RangeBoundary::OverflowedMinSmi()); | |
| 1986 new_max = | |
| 1987 RangeBoundary::Add(Range::ConstantMax(left_range), | |
| 1988 Range::ConstantMax(right_range), | |
| 1989 RangeBoundary::OverflowedMaxSmi()); | |
| 1990 break; | |
| 1991 | |
| 1992 case Token::kSUB: | |
| 1993 new_min = | |
| 1994 RangeBoundary::Sub(Range::ConstantMin(left_range), | |
| 1995 Range::ConstantMax(right_range), | |
| 1996 RangeBoundary::OverflowedMinSmi()); | |
| 1997 new_max = | |
| 1998 RangeBoundary::Sub(Range::ConstantMax(left_range), | |
| 1999 Range::ConstantMin(right_range), | |
| 2000 RangeBoundary::OverflowedMaxSmi()); | |
| 2001 break; | |
| 2002 | |
| 2003 default: | |
| 2004 if (range_ == NULL) { | |
| 2005 range_ = Range::Unknown(); | |
| 2006 return true; | |
| 2007 } | |
| 2008 return false; | |
| 2009 } | |
| 2010 | |
| 2011 ASSERT(!new_min.IsUnknown() && !new_max.IsUnknown()); | |
| 2012 set_overflow(new_min.Overflowed() || new_max.Overflowed()); | |
| 2013 return Range::Update(&range_, new_min, new_max); | |
| 2014 } | |
| 2015 | |
| 2016 | |
| 1846 #undef __ | 2017 #undef __ |
| 1847 | 2018 |
| 1848 } // namespace dart | 2019 } // namespace dart |
| OLD | NEW |