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

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

Issue 10960014: Implement range analysis for smi values. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: cleanup 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 #ifndef VM_INTERMEDIATE_LANGUAGE_H_ 5 #ifndef VM_INTERMEDIATE_LANGUAGE_H_
6 #define VM_INTERMEDIATE_LANGUAGE_H_ 6 #define VM_INTERMEDIATE_LANGUAGE_H_
7 7
8 #include "vm/allocation.h" 8 #include "vm/allocation.h"
9 #include "vm/ast.h" 9 #include "vm/ast.h"
10 #include "vm/growable_array.h" 10 #include "vm/growable_array.h"
11 #include "vm/handles_impl.h" 11 #include "vm/handles_impl.h"
12 #include "vm/locations.h" 12 #include "vm/locations.h"
13 #include "vm/object.h" 13 #include "vm/object.h"
14 14
15 namespace dart { 15 namespace dart {
16 16
17 class BitVector; 17 class BitVector;
18 class BlockEntryInstr; 18 class BlockEntryInstr;
19 class BufferFormatter; 19 class BufferFormatter;
20 class ComparisonInstr; 20 class ComparisonInstr;
21 class ControlInstruction; 21 class ControlInstruction;
22 class Definition; 22 class Definition;
23 class Environment; 23 class Environment;
24 class FlowGraphCompiler; 24 class FlowGraphCompiler;
25 class FlowGraphVisitor; 25 class FlowGraphVisitor;
26 class Instruction; 26 class Instruction;
27 class LocalVariable; 27 class LocalVariable;
28 class Range;
28 29
29 30
30 // TODO(srdjan): Add _ByteArrayBase, get:length. 31 // TODO(srdjan): Add _ByteArrayBase, get:length.
31 32
32 #define RECOGNIZED_LIST(V) \ 33 #define RECOGNIZED_LIST(V) \
33 V(ObjectArray, get:length, ObjectArrayLength) \ 34 V(ObjectArray, get:length, ObjectArrayLength) \
34 V(ImmutableArray, get:length, ImmutableArrayLength) \ 35 V(ImmutableArray, get:length, ImmutableArrayLength) \
35 V(GrowableObjectArray, get:length, GrowableArrayLength) \ 36 V(GrowableObjectArray, get:length, GrowableArrayLength) \
36 V(GrowableObjectArray, get:capacity, GrowableArrayCapacity) \ 37 V(GrowableObjectArray, get:capacity, GrowableArrayCapacity) \
37 V(StringBase, get:length, StringBaseLength) \ 38 V(StringBase, get:length, StringBaseLength) \
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 74
74 Instruction* instruction() const { return instruction_; } 75 Instruction* instruction() const { return instruction_; }
75 void set_instruction(Instruction* instruction) { instruction_ = instruction; } 76 void set_instruction(Instruction* instruction) { instruction_ = instruction; }
76 77
77 intptr_t use_index() const { return use_index_; } 78 intptr_t use_index() const { return use_index_; }
78 void set_use_index(intptr_t index) { use_index_ = index; } 79 void set_use_index(intptr_t index) { use_index_ = index; }
79 80
80 void AddToInputUseList(); 81 void AddToInputUseList();
81 void AddToEnvUseList(); 82 void AddToEnvUseList();
82 83
84 void RemoveFromInputUseList();
85
83 Value* Copy() { return new Value(definition_); } 86 Value* Copy() { return new Value(definition_); }
84 87
85 RawAbstractType* CompileType() const; 88 RawAbstractType* CompileType() const;
86 intptr_t ResultCid() const; 89 intptr_t ResultCid() const;
87 90
88 void PrintTo(BufferFormatter* f) const; 91 void PrintTo(BufferFormatter* f) const;
89 92
90 const char* DebugName() const { return "Value"; } 93 const char* DebugName() const { return "Value"; }
91 94
92 // Return true if the value represents a constant. 95 // Return true if the value represents a constant.
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
245 M(SmiToDouble) \ 248 M(SmiToDouble) \
246 M(CheckClass) \ 249 M(CheckClass) \
247 M(CheckSmi) \ 250 M(CheckSmi) \
248 M(Constant) \ 251 M(Constant) \
249 M(CheckEitherNonSmi) \ 252 M(CheckEitherNonSmi) \
250 M(UnboxedDoubleBinaryOp) \ 253 M(UnboxedDoubleBinaryOp) \
251 M(MathSqrt) \ 254 M(MathSqrt) \
252 M(UnboxDouble) \ 255 M(UnboxDouble) \
253 M(BoxDouble) \ 256 M(BoxDouble) \
254 M(CheckArrayBound) \ 257 M(CheckArrayBound) \
258 M(Constraint) \
255 259
256 260
257 #define FORWARD_DECLARATION(type) class type##Instr; 261 #define FORWARD_DECLARATION(type) class type##Instr;
258 FOR_EACH_INSTRUCTION(FORWARD_DECLARATION) 262 FOR_EACH_INSTRUCTION(FORWARD_DECLARATION)
259 #undef FORWARD_DECLARATION 263 #undef FORWARD_DECLARATION
260 264
261 265
262 // Functions required in all concrete instruction classes. 266 // Functions required in all concrete instruction classes.
263 #define DECLARE_INSTRUCTION(type) \ 267 #define DECLARE_INSTRUCTION(type) \
264 virtual Tag tag() const { return k##type; } \ 268 virtual Tag tag() const { return k##type; } \
265 virtual void Accept(FlowGraphVisitor* visitor); \ 269 virtual void Accept(FlowGraphVisitor* visitor); \
266 virtual type##Instr* As##type() { return this; } \ 270 virtual type##Instr* As##type() { return this; } \
267 virtual const char* DebugName() const { return #type; } \ 271 virtual const char* DebugName() const { return #type; } \
268 virtual LocationSummary* MakeLocationSummary() const; \ 272 virtual LocationSummary* MakeLocationSummary() const; \
269 virtual void EmitNativeCode(FlowGraphCompiler* compiler); \ 273 virtual void EmitNativeCode(FlowGraphCompiler* compiler); \
270 274
271 275
272 class Instruction : public ZoneAllocated { 276 class Instruction : public ZoneAllocated {
273 public: 277 public:
274 #define DECLARE_TAG(type) k##type, 278 #define DECLARE_TAG(type) k##type,
275 enum Tag { 279 enum Tag {
276 FOR_EACH_INSTRUCTION(DECLARE_TAG) 280 FOR_EACH_INSTRUCTION(DECLARE_TAG)
277 }; 281 };
278 #undef DECLARE_TAG 282 #undef DECLARE_TAG
279 283
280 Instruction() 284 Instruction()
281 : deopt_id_(Isolate::Current()->GetNextDeoptId()), 285 : range_(NULL),
286 deopt_id_(Isolate::Current()->GetNextDeoptId()),
282 lifetime_position_(-1), 287 lifetime_position_(-1),
283 previous_(NULL), 288 previous_(NULL),
284 next_(NULL), 289 next_(NULL),
285 env_(NULL), 290 env_(NULL),
286 expr_id_(-1) { } 291 expr_id_(-1) { }
287 292
288 virtual Tag tag() const = 0; 293 virtual Tag tag() const = 0;
289 294
290 intptr_t deopt_id() const { 295 intptr_t deopt_id() const {
291 ASSERT(CanDeoptimize()); 296 ASSERT(CanDeoptimize());
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
428 433
429 // Representation of the value produced by this computation. 434 // Representation of the value produced by this computation.
430 virtual Representation representation() const { 435 virtual Representation representation() const {
431 return kTagged; 436 return kTagged;
432 } 437 }
433 438
434 bool WasEliminated() const { 439 bool WasEliminated() const {
435 return next() == NULL; 440 return next() == NULL;
436 } 441 }
437 442
443 virtual bool InferRange() {
444 return false;
445 }
446
447 virtual Range* range();
448
438 // Returns deoptimization id that corresponds to the deoptimization target 449 // Returns deoptimization id that corresponds to the deoptimization target
439 // that input operands conversions inserted for this instruction can jump 450 // that input operands conversions inserted for this instruction can jump
440 // to. 451 // to.
441 virtual intptr_t DeoptimizationTarget() const { 452 virtual intptr_t DeoptimizationTarget() const {
442 UNREACHABLE(); 453 UNREACHABLE();
443 return Isolate::kNoDeoptId; 454 return Isolate::kNoDeoptId;
444 } 455 }
445 456
446 // Returns a replacement for the instruction or NULL if the instruction can 457 // Returns a replacement for the instruction or NULL if the instruction can
447 // be eliminated. By default returns the this instruction which means no 458 // be eliminated. By default returns the this instruction which means no
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
484 UNREACHABLE(); 495 UNREACHABLE();
485 return false; 496 return false;
486 } 497 }
487 498
488 protected: 499 protected:
489 // Fetch deopt id without checking if this computation can deoptimize. 500 // Fetch deopt id without checking if this computation can deoptimize.
490 intptr_t GetDeoptId() const { 501 intptr_t GetDeoptId() const {
491 return deopt_id_; 502 return deopt_id_;
492 } 503 }
493 504
505 Range* range_;
Florian Schneider 2012/09/21 08:56:44 It seems that range_ can be made a member of Defin
Kevin Millikin (Google) 2012/09/21 08:59:33 Does it buy us anything to make this a pointer ins
Vyacheslav Egorov (Google) 2012/09/21 20:08:07 Done.
Vyacheslav Egorov (Google) 2012/09/21 20:08:07 Pointer allows use also to express _|_ state which
506
494 private: 507 private:
495 friend class Definition; // Needed for InsertBefore, InsertAfter. 508 friend class Definition; // Needed for InsertBefore, InsertAfter.
496 509
497 // Classes that set deopt_id_. 510 // Classes that set deopt_id_.
498 friend class UnboxDoubleInstr; 511 friend class UnboxDoubleInstr;
499 friend class UnboxedDoubleBinaryOpInstr; 512 friend class UnboxedDoubleBinaryOpInstr;
500 friend class MathSqrtInstr; 513 friend class MathSqrtInstr;
501 friend class CheckClassInstr; 514 friend class CheckClassInstr;
502 friend class CheckSmiInstr; 515 friend class CheckSmiInstr;
503 friend class CheckArrayBoundInstr; 516 friend class CheckArrayBoundInstr;
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
716 729
717 virtual bool HasSideEffect() const { return false; } 730 virtual bool HasSideEffect() const { return false; }
718 731
719 intptr_t try_index() const { return try_index_; } 732 intptr_t try_index() const { return try_index_; }
720 733
721 BitVector* loop_info() const { return loop_info_; } 734 BitVector* loop_info() const { return loop_info_; }
722 void set_loop_info(BitVector* loop_info) { 735 void set_loop_info(BitVector* loop_info) {
723 loop_info_ = loop_info; 736 loop_info_ = loop_info;
724 } 737 }
725 738
739 virtual BlockEntryInstr* GetBlock() const {
740 return const_cast<BlockEntryInstr*>(this);
741 }
742
726 protected: 743 protected:
727 explicit BlockEntryInstr(intptr_t try_index) 744 explicit BlockEntryInstr(intptr_t try_index)
728 : try_index_(try_index), 745 : try_index_(try_index),
729 preorder_number_(-1), 746 preorder_number_(-1),
730 postorder_number_(-1), 747 postorder_number_(-1),
731 block_id_(-1), 748 block_id_(-1),
732 dominator_(NULL), 749 dominator_(NULL),
733 dominated_blocks_(1), 750 dominated_blocks_(1),
734 last_instruction_(NULL), 751 last_instruction_(NULL),
735 parallel_move_(NULL), 752 parallel_move_(NULL),
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
922 939
923 GrowableArray<BlockEntryInstr*> predecessors_; 940 GrowableArray<BlockEntryInstr*> predecessors_;
924 ZoneGrowableArray<PhiInstr*>* phis_; 941 ZoneGrowableArray<PhiInstr*>* phis_;
925 intptr_t phi_count_; 942 intptr_t phi_count_;
926 GrowableArray<BlockEntryInstr*> stale_predecessors_; 943 GrowableArray<BlockEntryInstr*> stale_predecessors_;
927 944
928 DISALLOW_COPY_AND_ASSIGN(JoinEntryInstr); 945 DISALLOW_COPY_AND_ASSIGN(JoinEntryInstr);
929 }; 946 };
930 947
931 948
949 class PhiIterator : public ValueObject {
950 public:
951 explicit PhiIterator(JoinEntryInstr* join)
952 : phis_(join->phis()), index_(-1) {
953 Advance();
954 }
955
956 void Advance() {
Kevin Millikin (Google) 2012/09/21 08:59:33 Simpler: void Advance() { ++index_; while (!D
Vyacheslav Egorov (Google) 2012/09/21 20:08:07 This is how it looked initially. I just wanted to
957 if (Done()) return;
Florian Schneider 2012/09/21 08:56:44 I'd rather write ASSERT(!Done());
Vyacheslav Egorov (Google) 2012/09/21 20:08:07 Done.
958
959 intptr_t i = index_ + 1;
960 while ((i < phis_->length()) && ((*phis_)[i] == NULL)) {
961 i++;
962 }
963 index_ = i;
964 }
965
966 bool Done() const {
967 return (phis_ == NULL) || (index_ >= phis_->length());
968 }
969
970 PhiInstr* Current() const {
971 return (*phis_)[index_];
972 }
973
974 private:
975 ZoneGrowableArray<PhiInstr*>* phis_;
976 intptr_t index_;
977 };
978
979
932 class TargetEntryInstr : public BlockEntryInstr { 980 class TargetEntryInstr : public BlockEntryInstr {
933 public: 981 public:
934 explicit TargetEntryInstr(intptr_t try_index) 982 explicit TargetEntryInstr(intptr_t try_index)
935 : BlockEntryInstr(try_index), 983 : BlockEntryInstr(try_index),
936 predecessor_(NULL), 984 predecessor_(NULL),
937 catch_try_index_(CatchClauseNode::kInvalidTryIndex) { } 985 catch_try_index_(CatchClauseNode::kInvalidTryIndex) { }
938 986
939 // Used for exception catch entries. 987 // Used for exception catch entries.
940 TargetEntryInstr(intptr_t try_index, intptr_t catch_try_index) 988 TargetEntryInstr(intptr_t try_index, intptr_t catch_try_index)
941 : BlockEntryInstr(try_index), 989 : BlockEntryInstr(try_index),
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
1099 DISALLOW_COPY_AND_ASSIGN(Definition); 1147 DISALLOW_COPY_AND_ASSIGN(Definition);
1100 }; 1148 };
1101 1149
1102 1150
1103 class PhiInstr : public Definition { 1151 class PhiInstr : public Definition {
1104 public: 1152 public:
1105 explicit PhiInstr(JoinEntryInstr* block, intptr_t num_inputs) 1153 explicit PhiInstr(JoinEntryInstr* block, intptr_t num_inputs)
1106 : block_(block), 1154 : block_(block),
1107 inputs_(num_inputs), 1155 inputs_(num_inputs),
1108 is_alive_(false), 1156 is_alive_(false),
1109 representation_(kTagged) { 1157 representation_(kTagged),
1158 has_unranged_inputs_(true) {
1110 for (intptr_t i = 0; i < num_inputs; ++i) { 1159 for (intptr_t i = 0; i < num_inputs; ++i) {
1111 inputs_.Add(NULL); 1160 inputs_.Add(NULL);
1112 } 1161 }
1113 } 1162 }
1114 1163
1115 // Get the block entry for that instruction. 1164 // Get the block entry for that instruction.
1116 virtual BlockEntryInstr* GetBlock() const { return block(); } 1165 virtual BlockEntryInstr* GetBlock() const { return block(); }
1117 JoinEntryInstr* block() const { return block_; } 1166 JoinEntryInstr* block() const { return block_; }
1118 1167
1119 virtual RawAbstractType* CompileType() const; 1168 virtual RawAbstractType* CompileType() const;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1158 virtual intptr_t ResultCid() const { 1207 virtual intptr_t ResultCid() const {
1159 UNREACHABLE(); 1208 UNREACHABLE();
1160 return kIllegalCid; 1209 return kIllegalCid;
1161 } 1210 }
1162 1211
1163 DECLARE_INSTRUCTION(Phi) 1212 DECLARE_INSTRUCTION(Phi)
1164 1213
1165 virtual void PrintTo(BufferFormatter* f) const; 1214 virtual void PrintTo(BufferFormatter* f) const;
1166 virtual void PrintToVisualizer(BufferFormatter* f) const; 1215 virtual void PrintToVisualizer(BufferFormatter* f) const;
1167 1216
1217 virtual bool InferRange();
1218
1219 virtual Range* range() { return range_; }
1220
1168 private: 1221 private:
1169 friend class JoinEntryInstr; // Direct access to inputs_ array. 1222 friend class JoinEntryInstr; // Direct access to inputs_ array.
1170 1223
1171 JoinEntryInstr* block_; 1224 JoinEntryInstr* block_;
1172 GrowableArray<Value*> inputs_; 1225 GrowableArray<Value*> inputs_;
1173 bool is_alive_; 1226 bool is_alive_;
1174 Representation representation_; 1227 Representation representation_;
1175 1228
1229 bool has_unranged_inputs_;
Florian Schneider 2012/09/21 08:56:44 Maybe rename to has_inputs_without_range_.
Vyacheslav Egorov (Google) 2012/09/21 20:08:07 Done.
1230
1176 DISALLOW_COPY_AND_ASSIGN(PhiInstr); 1231 DISALLOW_COPY_AND_ASSIGN(PhiInstr);
1177 }; 1232 };
1178 1233
1179 1234
1180 class ParameterInstr : public Definition { 1235 class ParameterInstr : public Definition {
1181 public: 1236 public:
1182 explicit ParameterInstr(intptr_t index, GraphEntryInstr* block) 1237 explicit ParameterInstr(intptr_t index, GraphEntryInstr* block)
1183 : index_(index), block_(block) { } 1238 : index_(index), block_(block) { }
1184 1239
1185 DECLARE_INSTRUCTION(Parameter) 1240 DECLARE_INSTRUCTION(Parameter)
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after
1523 protected: 1578 protected:
1524 EmbeddedArray<Value*, N> inputs_; 1579 EmbeddedArray<Value*, N> inputs_;
1525 1580
1526 private: 1581 private:
1527 friend class BranchInstr; 1582 friend class BranchInstr;
1528 1583
1529 LocationSummary* locs_; 1584 LocationSummary* locs_;
1530 }; 1585 };
1531 1586
1532 1587
1588 class RangeBoundary : public ValueObject {
1589 public:
1590 enum Kind { kUnknown, kSymbol, kConstant };
1591
1592 RangeBoundary() : kind_(kUnknown), value_(0), offs_(0) { }
Kevin Millikin (Google) 2012/09/21 08:59:33 Please burn two characters to spell out 'offset'.
Vyacheslav Egorov (Google) 2012/09/21 20:08:07 Done.
1593
1594 static RangeBoundary FromConstant(intptr_t val) {
1595 return RangeBoundary(kConstant, val, 0);
1596 }
1597
1598 static RangeBoundary FromDefinition(Definition* defn, intptr_t offs = 0) {
1599 return RangeBoundary(kSymbol, reinterpret_cast<intptr_t>(defn), offs);
1600 }
1601
1602 static RangeBoundary MinSmi() {
1603 return FromConstant(Smi::kMinValue);
1604 }
1605
1606 static RangeBoundary MaxSmi() {
1607 return FromConstant(Smi::kMaxValue);
1608 }
1609
1610 static RangeBoundary OverflowedMinSmi() {
1611 return FromConstant(Smi::kMinValue - 1);
1612 }
1613
1614 static RangeBoundary OverflowedMaxSmi() {
1615 return FromConstant(Smi::kMaxValue + 1);
1616 }
1617
1618 static RangeBoundary Min(RangeBoundary a, RangeBoundary b) {
1619 const intptr_t min_a = a.LowerBound().value();
1620 const intptr_t min_b = b.LowerBound().value();
1621
1622 return RangeBoundary::FromConstant((min_a < min_b) ? min_a : min_b);
Kevin Millikin (Google) 2012/09/21 08:59:33 You can spell this Utils::Minimum(min_a, min_b)
Vyacheslav Egorov (Google) 2012/09/21 20:08:07 Done.
1623 }
1624
1625 static RangeBoundary Max(RangeBoundary a, RangeBoundary b) {
1626 const intptr_t max_a = a.UpperBound().value();
1627 const intptr_t max_b = b.UpperBound().value();
1628
1629 return RangeBoundary::FromConstant((max_a > max_b) ? max_a : max_b);
1630 }
1631
1632 bool Overflowed() const {
1633 return !Smi::IsValid(value());
1634 }
1635
1636 RangeBoundary Clamp() const {
1637 if (IsConstant()) {
1638 if (value() < Smi::kMinValue) return MinSmi();
1639 if (value() > Smi::kMaxValue) return MaxSmi();
1640 }
1641 return *this;
1642 }
1643
1644 bool Equals(const RangeBoundary& other) const {
1645 return (kind_ == other.kind_) && (value_ == other.value_);
Florian Schneider 2012/09/21 08:56:44 && (offs_ == other.offs_)
Vyacheslav Egorov (Google) 2012/09/21 20:08:07 Nice catch!
1646 }
1647
1648 bool IsUnknown() const { return kind_ == kUnknown; }
1649 bool IsConstant() const { return kind_ == kConstant; }
1650 bool IsSymbol() const { return kind_ == kSymbol; }
1651
1652 intptr_t value() const {
1653 ASSERT(IsConstant());
1654 return value_;
1655 }
1656
1657 Definition* symbol() const {
1658 ASSERT(IsSymbol());
1659 return reinterpret_cast<Definition*>(value_);
1660 }
1661
1662 RangeBoundary LowerBound() const;
1663 RangeBoundary UpperBound() const;
1664
1665 static RangeBoundary WidenMin(const RangeBoundary& old_min,
1666 const RangeBoundary& new_min) {
1667 if (new_min.LowerBound().value() < old_min.LowerBound().value()) {
1668 return MinSmi();
1669 }
1670 return new_min;
1671 }
1672
1673 static RangeBoundary WidenMax(const RangeBoundary& old_max,
1674 const RangeBoundary& new_max) {
1675 if (new_max.UpperBound().value() > old_max.UpperBound().value()) {
1676 return MaxSmi();
1677 }
1678 return new_max;
1679 }
1680
1681 void PrintTo(BufferFormatter* f) const;
1682
1683 static RangeBoundary Add(const RangeBoundary& a,
1684 const RangeBoundary& b,
1685 const RangeBoundary& overflow) {
1686 ASSERT(a.IsConstant() && b.IsConstant());
1687
1688 intptr_t result = a.value() + b.value();
1689 if (!Smi::IsValid64(result)) {
Florian Schneider 2012/09/21 08:56:44 I think this should be Smi::IsValid(intptr_t value
Vyacheslav Egorov (Google) 2012/09/21 20:08:07 Yes. 64 is a leftover of an experiment.
1690 return overflow;
1691 }
1692 return RangeBoundary::FromConstant(result);
1693 }
1694
1695 static RangeBoundary Sub(const RangeBoundary& a,
1696 const RangeBoundary& b,
1697 const RangeBoundary& overflow) {
1698 ASSERT(a.IsConstant() && b.IsConstant());
1699
1700 intptr_t result = a.value() - b.value();
1701 if (!Smi::IsValid64(result)) {
Florian Schneider 2012/09/21 08:56:44 Use Smi::IsValid(intptr_t value) here too.
Vyacheslav Egorov (Google) 2012/09/21 20:08:07 Done.
1702 return overflow;
1703 }
1704 return RangeBoundary::FromConstant(result);
1705 }
1706
1707 private:
1708 RangeBoundary(Kind kind, intptr_t value, intptr_t offs)
1709 : kind_(kind), value_(value), offs_(offs) { }
1710
1711 Kind kind_;
1712 intptr_t value_;
1713 intptr_t offs_;
1714 };
1715
1716
1717 class Range : public ZoneAllocated {
1718 public:
1719 Range(RangeBoundary min, RangeBoundary max) : min_(min), max_(max) { }
1720
1721 static Range* Unknown() {
1722 return new Range(RangeBoundary::MinSmi(), RangeBoundary::MaxSmi());
1723 }
1724
1725 void PrintTo(BufferFormatter* f) const;
1726
1727 const RangeBoundary& min() { return min_; }
1728 const RangeBoundary& max() { return max_; }
1729
1730 bool Equals(Range* other) {
1731 return min_.Equals(other->min_) && max_.Equals(other->max_);
1732 }
1733
1734 static bool Update(Range** range_slot,
1735 const RangeBoundary& min,
1736 const RangeBoundary& max) {
1737 if (*range_slot == NULL) {
1738 *range_slot = new Range(min, max);
1739 return true;
1740 }
1741
1742 Range* range = *range_slot;
1743 if (range->min_.Equals(min) && range->max_.Equals(max)) {
1744 return false;
1745 }
1746
1747 range->min_ = min;
1748 range->max_ = max;
1749
1750 return true;
1751 }
1752
1753 static RangeBoundary ConstantMin(Range* range) {
1754 if (range == NULL) return RangeBoundary::MinSmi();
1755 return range->min().LowerBound();
1756 }
1757
1758 static RangeBoundary ConstantMax(Range* range) {
1759 if (range == NULL) return RangeBoundary::MaxSmi();
1760 return range->max().UpperBound();
1761 }
1762
1763 private:
1764 RangeBoundary min_;
1765 RangeBoundary max_;
1766 };
1767
1768
1769 class ConstraintInstr : public TemplateDefinition<2> {
1770 public:
1771 ConstraintInstr(Value* value, Range* constraint)
1772 : constraint_(constraint) {
1773 inputs_[0] = value;
1774 inputs_[1] = NULL; // Dependency.
1775 }
1776
1777 DECLARE_INSTRUCTION(Constraint)
1778
1779 virtual RawAbstractType* CompileType() const {
1780 return Type::SmiType();
1781 }
1782
1783 virtual bool CanDeoptimize() const { return false; }
1784
1785 virtual bool HasSideEffect() const { return false; }
1786
1787 virtual intptr_t ResultCid() const { return kSmiCid; }
1788
1789 virtual bool AttributesEqual(Definition* other) const {
1790 UNREACHABLE();
1791 return false;
1792 }
1793
1794 virtual void PrintOperandsTo(BufferFormatter* f) const;
1795
1796 Value* value() const { return inputs_[0]; }
1797 Range* constraint() const { return constraint_; }
1798
1799 virtual bool InferRange();
1800
1801 virtual Range* range() {
1802 return range_;
1803 }
1804
1805 void AddDependency(Definition* defn) {
1806 Value* val = new Value(defn);
1807 val->set_use_index(1);
1808 val->set_instruction(this);
1809 val->AddToInputUseList();
1810 set_dependency(val);
1811 }
1812
1813 void RemoveDependency() {
1814 if (dependency() != NULL) {
1815 dependency()->RemoveFromInputUseList();
1816 set_dependency(NULL);
1817 }
1818 }
1819
1820 private:
1821 Value* dependency() {
1822 return inputs_[1];
1823 }
1824
1825 void set_dependency(Value* value) {
1826 inputs_[1] = value;
1827 }
1828
1829 Range* constraint_;
1830
1831 DISALLOW_COPY_AND_ASSIGN(ConstraintInstr);
1832 };
1833
1834
1533 class ConstantInstr : public TemplateDefinition<0> { 1835 class ConstantInstr : public TemplateDefinition<0> {
1534 public: 1836 public:
1535 explicit ConstantInstr(const Object& value) : value_(value) { } 1837 explicit ConstantInstr(const Object& value)
1838 : value_(value) { }
1536 1839
1537 DECLARE_INSTRUCTION(Constant) 1840 DECLARE_INSTRUCTION(Constant)
1538 virtual RawAbstractType* CompileType() const; 1841 virtual RawAbstractType* CompileType() const;
1539 1842
1540 const Object& value() const { return value_; } 1843 const Object& value() const { return value_; }
1541 1844
1542 virtual void PrintOperandsTo(BufferFormatter* f) const; 1845 virtual void PrintOperandsTo(BufferFormatter* f) const;
1543 1846
1544 virtual bool CanDeoptimize() const { return false; } 1847 virtual bool CanDeoptimize() const { return false; }
1545 1848
1546 virtual bool HasSideEffect() const { return false; } 1849 virtual bool HasSideEffect() const { return false; }
1547 1850
1548 virtual intptr_t ResultCid() const; 1851 virtual intptr_t ResultCid() const;
1549 1852
1550 virtual bool AttributesEqual(Instruction* other) const; 1853 virtual bool AttributesEqual(Instruction* other) const;
1551 virtual bool AffectedBySideEffect() const { return false; } 1854 virtual bool AffectedBySideEffect() const { return false; }
1552 1855
1856 virtual Range* range() {
Kevin Millikin (Google) 2012/09/21 08:59:33 This is disconcerting. Simpler just to treat smi
Vyacheslav Egorov (Google) 2012/09/21 20:08:07 Initially I wanted to make range() assert when you
1857 ASSERT(value_.IsSmi());
1858 if (range_ == NULL) {
1859 intptr_t value = Smi::Cast(value_).Value();
1860 range_ = new Range(RangeBoundary::FromConstant(value),
1861 RangeBoundary::FromConstant(value));
1862 }
1863 return range_;
1864 }
1865
1553 private: 1866 private:
1554 const Object& value_; 1867 const Object& value_;
1555 1868
1556 DISALLOW_COPY_AND_ASSIGN(ConstantInstr); 1869 DISALLOW_COPY_AND_ASSIGN(ConstantInstr);
1557 }; 1870 };
1558 1871
1559 1872
1560 class AssertAssignableInstr : public TemplateDefinition<3> { 1873 class AssertAssignableInstr : public TemplateDefinition<3> {
1561 public: 1874 public:
1562 AssertAssignableInstr(intptr_t token_pos, 1875 AssertAssignableInstr(intptr_t token_pos,
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after
1848 InstanceCallInstr* instance_call_; 2161 InstanceCallInstr* instance_call_;
1849 const ICData& ic_data_; 2162 const ICData& ic_data_;
1850 const bool with_checks_; 2163 const bool with_checks_;
1851 2164
1852 DISALLOW_COPY_AND_ASSIGN(PolymorphicInstanceCallInstr); 2165 DISALLOW_COPY_AND_ASSIGN(PolymorphicInstanceCallInstr);
1853 }; 2166 };
1854 2167
1855 2168
1856 class ComparisonInstr : public TemplateDefinition<2> { 2169 class ComparisonInstr : public TemplateDefinition<2> {
1857 public: 2170 public:
1858 ComparisonInstr(Token::Kind kind, Value* left, Value* right) : kind_(kind) { 2171 ComparisonInstr(Token::Kind kind, Value* left, Value* right)
2172 : kind_(kind) {
1859 ASSERT(left != NULL); 2173 ASSERT(left != NULL);
1860 ASSERT(right != NULL); 2174 ASSERT(right != NULL);
1861 inputs_[0] = left; 2175 inputs_[0] = left;
1862 inputs_[1] = right; 2176 inputs_[1] = right;
1863 } 2177 }
1864 2178
1865 Value* left() const { return inputs_[0]; } 2179 Value* left() const { return inputs_[0]; }
1866 Value* right() const { return inputs_[1]; } 2180 Value* right() const { return inputs_[1]; }
1867 2181
1868 virtual ComparisonInstr* AsComparison() { return this; } 2182 virtual ComparisonInstr* AsComparison() { return this; }
(...skipping 1275 matching lines...) Expand 10 before | Expand all | Expand 10 after
3144 }; 3458 };
3145 3459
3146 3460
3147 class BinarySmiOpInstr : public TemplateDefinition<2> { 3461 class BinarySmiOpInstr : public TemplateDefinition<2> {
3148 public: 3462 public:
3149 BinarySmiOpInstr(Token::Kind op_kind, 3463 BinarySmiOpInstr(Token::Kind op_kind,
3150 InstanceCallInstr* instance_call, 3464 InstanceCallInstr* instance_call,
3151 Value* left, 3465 Value* left,
3152 Value* right) 3466 Value* right)
3153 : op_kind_(op_kind), 3467 : op_kind_(op_kind),
3154 instance_call_(instance_call) { 3468 instance_call_(instance_call),
3469 overflow_(true) {
3155 ASSERT(left != NULL); 3470 ASSERT(left != NULL);
3156 ASSERT(right != NULL); 3471 ASSERT(right != NULL);
3157 inputs_[0] = left; 3472 inputs_[0] = left;
3158 inputs_[1] = right; 3473 inputs_[1] = right;
3159 } 3474 }
3160 3475
3161 Value* left() const { return inputs_[0]; } 3476 Value* left() const { return inputs_[0]; }
3162 Value* right() const { return inputs_[1]; } 3477 Value* right() const { return inputs_[1]; }
3163 3478
3164 Token::Kind op_kind() const { return op_kind_; } 3479 Token::Kind op_kind() const { return op_kind_; }
3165 3480
3166 InstanceCallInstr* instance_call() const { return instance_call_; } 3481 InstanceCallInstr* instance_call() const { return instance_call_; }
3167 3482
3168 const ICData* ic_data() const { return instance_call()->ic_data(); } 3483 const ICData* ic_data() const { return instance_call()->ic_data(); }
3169 3484
3170 virtual void PrintOperandsTo(BufferFormatter* f) const; 3485 virtual void PrintOperandsTo(BufferFormatter* f) const;
3171 3486
3172 DECLARE_INSTRUCTION(BinarySmiOp) 3487 DECLARE_INSTRUCTION(BinarySmiOp)
3173 virtual RawAbstractType* CompileType() const; 3488 virtual RawAbstractType* CompileType() const;
3174 3489
3175 virtual bool CanDeoptimize() const; 3490 virtual bool CanDeoptimize() const;
3176 3491
3177 virtual bool HasSideEffect() const { return false; } 3492 virtual bool HasSideEffect() const { return false; }
3178 3493
3179 virtual bool AffectedBySideEffect() const { return false; } 3494 virtual bool AffectedBySideEffect() const { return false; }
3180 virtual bool AttributesEqual(Instruction* other) const; 3495 virtual bool AttributesEqual(Instruction* other) const;
Florian Schneider 2012/09/21 08:56:44 You need to update AttributesEqual to check of ove
Vyacheslav Egorov (Google) 2012/09/21 20:08:07 Yes, thanks for reminding me. I kept this in mind,
3181 3496
3182 virtual intptr_t ResultCid() const; 3497 virtual intptr_t ResultCid() const;
3183 3498
3499 void set_overflow(bool overflow) {
3500 overflow_ = overflow;
3501 }
3502
3503 void PrintTo(BufferFormatter* f) const;
3504
3505 virtual bool InferRange();
3506 virtual Range* range() { return range_; }
3507
3184 private: 3508 private:
3185 const Token::Kind op_kind_; 3509 const Token::Kind op_kind_;
3186 InstanceCallInstr* instance_call_; 3510 InstanceCallInstr* instance_call_;
3511 bool overflow_;
3187 3512
3188 DISALLOW_COPY_AND_ASSIGN(BinarySmiOpInstr); 3513 DISALLOW_COPY_AND_ASSIGN(BinarySmiOpInstr);
3189 }; 3514 };
3190 3515
3191 3516
3192 class BinaryMintOpInstr : public TemplateDefinition<2> { 3517 class BinaryMintOpInstr : public TemplateDefinition<2> {
3193 public: 3518 public:
3194 BinaryMintOpInstr(Token::Kind op_kind, 3519 BinaryMintOpInstr(Token::Kind op_kind,
3195 InstanceCallInstr* instance_call, 3520 InstanceCallInstr* instance_call,
3196 Value* left, 3521 Value* left,
(...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after
3659 ForwardInstructionIterator* current_iterator_; 3984 ForwardInstructionIterator* current_iterator_;
3660 3985
3661 private: 3986 private:
3662 DISALLOW_COPY_AND_ASSIGN(FlowGraphVisitor); 3987 DISALLOW_COPY_AND_ASSIGN(FlowGraphVisitor);
3663 }; 3988 };
3664 3989
3665 3990
3666 } // namespace dart 3991 } // namespace dart
3667 3992
3668 #endif // VM_INTERMEDIATE_LANGUAGE_H_ 3993 #endif // VM_INTERMEDIATE_LANGUAGE_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698