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

Side by Side Diff: runtime/vm/intermediate_language.cc

Issue 10960014: Implement range analysis for smi values. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: addressed majority of comments Created 8 years, 3 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
OLDNEW
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698