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 #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 Loading... | |
| 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 Loading... | |
| 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; } \ |
| (...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 716 | 720 |
| 717 virtual bool HasSideEffect() const { return false; } | 721 virtual bool HasSideEffect() const { return false; } |
| 718 | 722 |
| 719 intptr_t try_index() const { return try_index_; } | 723 intptr_t try_index() const { return try_index_; } |
| 720 | 724 |
| 721 BitVector* loop_info() const { return loop_info_; } | 725 BitVector* loop_info() const { return loop_info_; } |
| 722 void set_loop_info(BitVector* loop_info) { | 726 void set_loop_info(BitVector* loop_info) { |
| 723 loop_info_ = loop_info; | 727 loop_info_ = loop_info; |
| 724 } | 728 } |
| 725 | 729 |
| 730 virtual BlockEntryInstr* GetBlock() const { | |
| 731 return const_cast<BlockEntryInstr*>(this); | |
| 732 } | |
| 733 | |
| 726 protected: | 734 protected: |
| 727 explicit BlockEntryInstr(intptr_t try_index) | 735 explicit BlockEntryInstr(intptr_t try_index) |
| 728 : try_index_(try_index), | 736 : try_index_(try_index), |
| 729 preorder_number_(-1), | 737 preorder_number_(-1), |
| 730 postorder_number_(-1), | 738 postorder_number_(-1), |
| 731 block_id_(-1), | 739 block_id_(-1), |
| 732 dominator_(NULL), | 740 dominator_(NULL), |
| 733 dominated_blocks_(1), | 741 dominated_blocks_(1), |
| 734 last_instruction_(NULL), | 742 last_instruction_(NULL), |
| 735 parallel_move_(NULL), | 743 parallel_move_(NULL), |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 922 | 930 |
| 923 GrowableArray<BlockEntryInstr*> predecessors_; | 931 GrowableArray<BlockEntryInstr*> predecessors_; |
| 924 ZoneGrowableArray<PhiInstr*>* phis_; | 932 ZoneGrowableArray<PhiInstr*>* phis_; |
| 925 intptr_t phi_count_; | 933 intptr_t phi_count_; |
| 926 GrowableArray<BlockEntryInstr*> stale_predecessors_; | 934 GrowableArray<BlockEntryInstr*> stale_predecessors_; |
| 927 | 935 |
| 928 DISALLOW_COPY_AND_ASSIGN(JoinEntryInstr); | 936 DISALLOW_COPY_AND_ASSIGN(JoinEntryInstr); |
| 929 }; | 937 }; |
| 930 | 938 |
| 931 | 939 |
| 940 class PhiIterator : public ValueObject { | |
| 941 public: | |
| 942 explicit PhiIterator(JoinEntryInstr* join) | |
| 943 : phis_(join->phis()), index_(-1) { | |
| 944 if (!Done()) Advance(); // Advance to the first smi. | |
| 945 } | |
| 946 | |
| 947 void Advance() { | |
| 948 ASSERT(!Done()); | |
| 949 do { | |
| 950 index_++; | |
| 951 } while (!Done() && (Current() == NULL)); | |
| 952 } | |
| 953 | |
| 954 bool Done() const { | |
| 955 return (phis_ == NULL) || (index_ >= phis_->length()); | |
| 956 } | |
| 957 | |
| 958 PhiInstr* Current() const { | |
| 959 return (*phis_)[index_]; | |
| 960 } | |
| 961 | |
| 962 private: | |
| 963 ZoneGrowableArray<PhiInstr*>* phis_; | |
| 964 intptr_t index_; | |
| 965 }; | |
| 966 | |
| 967 | |
| 932 class TargetEntryInstr : public BlockEntryInstr { | 968 class TargetEntryInstr : public BlockEntryInstr { |
| 933 public: | 969 public: |
| 934 explicit TargetEntryInstr(intptr_t try_index) | 970 explicit TargetEntryInstr(intptr_t try_index) |
| 935 : BlockEntryInstr(try_index), | 971 : BlockEntryInstr(try_index), |
| 936 predecessor_(NULL), | 972 predecessor_(NULL), |
| 937 catch_try_index_(CatchClauseNode::kInvalidTryIndex) { } | 973 catch_try_index_(CatchClauseNode::kInvalidTryIndex) { } |
| 938 | 974 |
| 939 // Used for exception catch entries. | 975 // Used for exception catch entries. |
| 940 TargetEntryInstr(intptr_t try_index, intptr_t catch_try_index) | 976 TargetEntryInstr(intptr_t try_index, intptr_t catch_try_index) |
| 941 : BlockEntryInstr(try_index), | 977 : BlockEntryInstr(try_index), |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1071 virtual void PrintTo(BufferFormatter* f) const; | 1107 virtual void PrintTo(BufferFormatter* f) const; |
| 1072 virtual void PrintOperandsTo(BufferFormatter* f) const; | 1108 virtual void PrintOperandsTo(BufferFormatter* f) const; |
| 1073 virtual void PrintToVisualizer(BufferFormatter* f) const; | 1109 virtual void PrintToVisualizer(BufferFormatter* f) const; |
| 1074 | 1110 |
| 1075 // A value in the constant propagation lattice. | 1111 // A value in the constant propagation lattice. |
| 1076 // - non-constant sentinel | 1112 // - non-constant sentinel |
| 1077 // - a constant (any non-sentinel value) | 1113 // - a constant (any non-sentinel value) |
| 1078 // - unknown sentinel | 1114 // - unknown sentinel |
| 1079 Object& constant_value() const { return constant_value_; } | 1115 Object& constant_value() const { return constant_value_; } |
| 1080 | 1116 |
| 1117 virtual bool InferRange(); | |
| 1118 | |
| 1119 Range* range() const { return range_; } | |
| 1120 | |
| 1081 // Definitions can be canonicalized only into definitions to ensure | 1121 // Definitions can be canonicalized only into definitions to ensure |
| 1082 // this check statically we override base Canonicalize with a Canonicalize | 1122 // this check statically we override base Canonicalize with a Canonicalize |
| 1083 // returning Definition (return type is covariant). | 1123 // returning Definition (return type is covariant). |
| 1084 virtual Definition* Canonicalize(); | 1124 virtual Definition* Canonicalize(); |
| 1085 | 1125 |
| 1126 protected: | |
| 1127 Range* range_; | |
| 1128 | |
| 1086 private: | 1129 private: |
| 1087 intptr_t temp_index_; | 1130 intptr_t temp_index_; |
| 1088 intptr_t ssa_temp_index_; | 1131 intptr_t ssa_temp_index_; |
| 1089 // TODO(regis): GrowableArray<const AbstractType*> propagated_types_; | 1132 // TODO(regis): GrowableArray<const AbstractType*> propagated_types_; |
| 1090 // For now: | 1133 // For now: |
| 1091 AbstractType& propagated_type_; | 1134 AbstractType& propagated_type_; |
| 1092 intptr_t propagated_cid_; | 1135 intptr_t propagated_cid_; |
| 1093 Value* input_use_list_; | 1136 Value* input_use_list_; |
| 1094 Value* env_use_list_; | 1137 Value* env_use_list_; |
| 1095 UseKind use_kind_; | 1138 UseKind use_kind_; |
| 1096 | 1139 |
| 1097 Object& constant_value_; | 1140 Object& constant_value_; |
| 1098 | 1141 |
| 1099 DISALLOW_COPY_AND_ASSIGN(Definition); | 1142 DISALLOW_COPY_AND_ASSIGN(Definition); |
| 1100 }; | 1143 }; |
| 1101 | 1144 |
| 1102 | 1145 |
| 1103 class PhiInstr : public Definition { | 1146 class PhiInstr : public Definition { |
| 1104 public: | 1147 public: |
| 1105 explicit PhiInstr(JoinEntryInstr* block, intptr_t num_inputs) | 1148 explicit PhiInstr(JoinEntryInstr* block, intptr_t num_inputs) |
| 1106 : block_(block), | 1149 : block_(block), |
| 1107 inputs_(num_inputs), | 1150 inputs_(num_inputs), |
| 1108 is_alive_(false), | 1151 is_alive_(false), |
| 1109 representation_(kTagged) { | 1152 representation_(kTagged), |
| 1153 has_inputs_without_range_(true) { | |
| 1110 for (intptr_t i = 0; i < num_inputs; ++i) { | 1154 for (intptr_t i = 0; i < num_inputs; ++i) { |
| 1111 inputs_.Add(NULL); | 1155 inputs_.Add(NULL); |
| 1112 } | 1156 } |
| 1113 } | 1157 } |
| 1114 | 1158 |
| 1115 // Get the block entry for that instruction. | 1159 // Get the block entry for that instruction. |
| 1116 virtual BlockEntryInstr* GetBlock() const { return block(); } | 1160 virtual BlockEntryInstr* GetBlock() const { return block(); } |
| 1117 JoinEntryInstr* block() const { return block_; } | 1161 JoinEntryInstr* block() const { return block_; } |
| 1118 | 1162 |
| 1119 virtual RawAbstractType* CompileType() const; | 1163 virtual RawAbstractType* CompileType() const; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1158 virtual intptr_t ResultCid() const { | 1202 virtual intptr_t ResultCid() const { |
| 1159 UNREACHABLE(); | 1203 UNREACHABLE(); |
| 1160 return kIllegalCid; | 1204 return kIllegalCid; |
| 1161 } | 1205 } |
| 1162 | 1206 |
| 1163 DECLARE_INSTRUCTION(Phi) | 1207 DECLARE_INSTRUCTION(Phi) |
| 1164 | 1208 |
| 1165 virtual void PrintTo(BufferFormatter* f) const; | 1209 virtual void PrintTo(BufferFormatter* f) const; |
| 1166 virtual void PrintToVisualizer(BufferFormatter* f) const; | 1210 virtual void PrintToVisualizer(BufferFormatter* f) const; |
| 1167 | 1211 |
| 1212 virtual bool InferRange(); | |
| 1213 | |
| 1168 private: | 1214 private: |
| 1169 friend class JoinEntryInstr; // Direct access to inputs_ array. | 1215 friend class JoinEntryInstr; // Direct access to inputs_ array. |
| 1170 | 1216 |
| 1171 JoinEntryInstr* block_; | 1217 JoinEntryInstr* block_; |
| 1172 GrowableArray<Value*> inputs_; | 1218 GrowableArray<Value*> inputs_; |
| 1173 bool is_alive_; | 1219 bool is_alive_; |
| 1174 Representation representation_; | 1220 Representation representation_; |
| 1175 | 1221 |
| 1222 // Used to determine an interation of a range analysis after all phi inputs | |
|
ngeoffray
2012/09/24 21:44:15
interation -> iteration
| |
| 1223 // were initialized to apply widening. | |
| 1224 bool has_inputs_without_range_; | |
| 1225 | |
| 1176 DISALLOW_COPY_AND_ASSIGN(PhiInstr); | 1226 DISALLOW_COPY_AND_ASSIGN(PhiInstr); |
| 1177 }; | 1227 }; |
| 1178 | 1228 |
| 1179 | 1229 |
| 1180 class ParameterInstr : public Definition { | 1230 class ParameterInstr : public Definition { |
| 1181 public: | 1231 public: |
| 1182 explicit ParameterInstr(intptr_t index, GraphEntryInstr* block) | 1232 explicit ParameterInstr(intptr_t index, GraphEntryInstr* block) |
| 1183 : index_(index), block_(block) { } | 1233 : index_(index), block_(block) { } |
| 1184 | 1234 |
| 1185 DECLARE_INSTRUCTION(Parameter) | 1235 DECLARE_INSTRUCTION(Parameter) |
| (...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1523 protected: | 1573 protected: |
| 1524 EmbeddedArray<Value*, N> inputs_; | 1574 EmbeddedArray<Value*, N> inputs_; |
| 1525 | 1575 |
| 1526 private: | 1576 private: |
| 1527 friend class BranchInstr; | 1577 friend class BranchInstr; |
| 1528 | 1578 |
| 1529 LocationSummary* locs_; | 1579 LocationSummary* locs_; |
| 1530 }; | 1580 }; |
| 1531 | 1581 |
| 1532 | 1582 |
| 1583 class RangeBoundary : public ValueObject { | |
| 1584 public: | |
| 1585 enum Kind { kUnknown, kSymbol, kConstant }; | |
| 1586 | |
| 1587 RangeBoundary() : kind_(kUnknown), value_(0), offset_(0) { } | |
| 1588 | |
| 1589 static RangeBoundary FromConstant(intptr_t val) { | |
| 1590 return RangeBoundary(kConstant, val, 0); | |
| 1591 } | |
| 1592 | |
| 1593 static RangeBoundary FromDefinition(Definition* defn, intptr_t offs = 0) { | |
| 1594 return RangeBoundary(kSymbol, reinterpret_cast<intptr_t>(defn), offs); | |
| 1595 } | |
| 1596 | |
| 1597 static RangeBoundary MinSmi() { | |
| 1598 return FromConstant(Smi::kMinValue); | |
| 1599 } | |
| 1600 | |
| 1601 static RangeBoundary MaxSmi() { | |
| 1602 return FromConstant(Smi::kMaxValue); | |
| 1603 } | |
| 1604 | |
| 1605 static RangeBoundary OverflowedMinSmi() { | |
| 1606 return FromConstant(Smi::kMinValue - 1); | |
| 1607 } | |
| 1608 | |
| 1609 static RangeBoundary OverflowedMaxSmi() { | |
| 1610 return FromConstant(Smi::kMaxValue + 1); | |
| 1611 } | |
| 1612 | |
| 1613 static RangeBoundary Min(RangeBoundary a, RangeBoundary b) { | |
| 1614 const intptr_t min_a = a.LowerBound().value(); | |
| 1615 const intptr_t min_b = b.LowerBound().value(); | |
| 1616 | |
| 1617 return RangeBoundary::FromConstant(Utils::Minimum(min_a, min_b)); | |
| 1618 } | |
| 1619 | |
| 1620 static RangeBoundary Max(RangeBoundary a, RangeBoundary b) { | |
| 1621 const intptr_t max_a = a.UpperBound().value(); | |
| 1622 const intptr_t max_b = b.UpperBound().value(); | |
| 1623 | |
| 1624 return RangeBoundary::FromConstant(Utils::Maximum(max_a, max_b)); | |
| 1625 } | |
| 1626 | |
| 1627 bool Overflowed() const { | |
| 1628 return !Smi::IsValid(value()); | |
| 1629 } | |
| 1630 | |
| 1631 RangeBoundary Clamp() const { | |
| 1632 if (IsConstant()) { | |
| 1633 if (value() < Smi::kMinValue) return MinSmi(); | |
| 1634 if (value() > Smi::kMaxValue) return MaxSmi(); | |
| 1635 } | |
| 1636 return *this; | |
| 1637 } | |
| 1638 | |
| 1639 bool Equals(const RangeBoundary& other) const { | |
| 1640 return (kind_ == other.kind_) && (value_ == other.value_); | |
| 1641 } | |
| 1642 | |
| 1643 bool IsUnknown() const { return kind_ == kUnknown; } | |
| 1644 bool IsConstant() const { return kind_ == kConstant; } | |
| 1645 bool IsSymbol() const { return kind_ == kSymbol; } | |
| 1646 | |
| 1647 intptr_t value() const { | |
| 1648 ASSERT(IsConstant()); | |
| 1649 return value_; | |
| 1650 } | |
| 1651 | |
| 1652 Definition* symbol() const { | |
| 1653 ASSERT(IsSymbol()); | |
| 1654 return reinterpret_cast<Definition*>(value_); | |
| 1655 } | |
| 1656 | |
| 1657 RangeBoundary LowerBound() const; | |
| 1658 RangeBoundary UpperBound() const; | |
| 1659 | |
| 1660 static RangeBoundary WidenMin(const RangeBoundary& old_min, | |
| 1661 const RangeBoundary& new_min) { | |
| 1662 if (new_min.LowerBound().value() < old_min.LowerBound().value()) { | |
| 1663 return MinSmi(); | |
| 1664 } | |
| 1665 return new_min; | |
| 1666 } | |
| 1667 | |
| 1668 static RangeBoundary WidenMax(const RangeBoundary& old_max, | |
| 1669 const RangeBoundary& new_max) { | |
| 1670 if (new_max.UpperBound().value() > old_max.UpperBound().value()) { | |
| 1671 return MaxSmi(); | |
| 1672 } | |
| 1673 return new_max; | |
| 1674 } | |
| 1675 | |
| 1676 void PrintTo(BufferFormatter* f) const; | |
| 1677 | |
| 1678 static RangeBoundary Add(const RangeBoundary& a, | |
| 1679 const RangeBoundary& b, | |
| 1680 const RangeBoundary& overflow) { | |
| 1681 ASSERT(a.IsConstant() && b.IsConstant()); | |
| 1682 | |
| 1683 intptr_t result = a.value() + b.value(); | |
| 1684 if (!Smi::IsValid(result)) { | |
| 1685 return overflow; | |
| 1686 } | |
| 1687 return RangeBoundary::FromConstant(result); | |
| 1688 } | |
| 1689 | |
| 1690 static RangeBoundary Sub(const RangeBoundary& a, | |
| 1691 const RangeBoundary& b, | |
| 1692 const RangeBoundary& overflow) { | |
| 1693 ASSERT(a.IsConstant() && b.IsConstant()); | |
| 1694 | |
| 1695 intptr_t result = a.value() - b.value(); | |
| 1696 if (!Smi::IsValid(result)) { | |
| 1697 return overflow; | |
| 1698 } | |
| 1699 return RangeBoundary::FromConstant(result); | |
| 1700 } | |
| 1701 | |
| 1702 private: | |
| 1703 RangeBoundary(Kind kind, intptr_t value, intptr_t offset) | |
| 1704 : kind_(kind), value_(value), offset_(offset) { } | |
| 1705 | |
| 1706 Kind kind_; | |
| 1707 intptr_t value_; | |
| 1708 intptr_t offset_; | |
| 1709 }; | |
| 1710 | |
| 1711 | |
| 1712 class Range : public ZoneAllocated { | |
| 1713 public: | |
| 1714 Range(RangeBoundary min, RangeBoundary max) : min_(min), max_(max) { } | |
| 1715 | |
| 1716 static Range* Unknown() { | |
| 1717 return new Range(RangeBoundary::MinSmi(), RangeBoundary::MaxSmi()); | |
| 1718 } | |
| 1719 | |
| 1720 void PrintTo(BufferFormatter* f) const; | |
| 1721 | |
| 1722 const RangeBoundary& min() { return min_; } | |
| 1723 const RangeBoundary& max() { return max_; } | |
| 1724 | |
| 1725 bool Equals(Range* other) { | |
| 1726 return min_.Equals(other->min_) && max_.Equals(other->max_); | |
| 1727 } | |
| 1728 | |
| 1729 static bool Update(Range** range_slot, | |
| 1730 const RangeBoundary& min, | |
| 1731 const RangeBoundary& max) { | |
| 1732 if (*range_slot == NULL) { | |
| 1733 *range_slot = new Range(min, max); | |
| 1734 return true; | |
| 1735 } | |
| 1736 | |
| 1737 Range* range = *range_slot; | |
| 1738 if (range->min_.Equals(min) && range->max_.Equals(max)) { | |
| 1739 return false; | |
| 1740 } | |
| 1741 | |
| 1742 range->min_ = min; | |
| 1743 range->max_ = max; | |
| 1744 | |
| 1745 return true; | |
| 1746 } | |
| 1747 | |
| 1748 static RangeBoundary ConstantMin(Range* range) { | |
| 1749 if (range == NULL) return RangeBoundary::MinSmi(); | |
| 1750 return range->min().LowerBound(); | |
| 1751 } | |
| 1752 | |
| 1753 static RangeBoundary ConstantMax(Range* range) { | |
| 1754 if (range == NULL) return RangeBoundary::MaxSmi(); | |
| 1755 return range->max().UpperBound(); | |
| 1756 } | |
| 1757 | |
| 1758 private: | |
| 1759 RangeBoundary min_; | |
| 1760 RangeBoundary max_; | |
| 1761 }; | |
| 1762 | |
| 1763 | |
| 1764 class ConstraintInstr : public TemplateDefinition<2> { | |
| 1765 public: | |
| 1766 ConstraintInstr(Value* value, Range* constraint) | |
| 1767 : constraint_(constraint) { | |
| 1768 inputs_[0] = value; | |
| 1769 inputs_[1] = NULL; // Dependency. | |
| 1770 } | |
| 1771 | |
| 1772 DECLARE_INSTRUCTION(Constraint) | |
| 1773 | |
| 1774 virtual RawAbstractType* CompileType() const { | |
| 1775 return Type::SmiType(); | |
| 1776 } | |
| 1777 | |
| 1778 virtual bool CanDeoptimize() const { return false; } | |
| 1779 | |
| 1780 virtual bool HasSideEffect() const { return false; } | |
| 1781 | |
| 1782 virtual intptr_t ResultCid() const { return kSmiCid; } | |
| 1783 | |
| 1784 virtual bool AttributesEqual(Definition* other) const { | |
| 1785 UNREACHABLE(); | |
| 1786 return false; | |
| 1787 } | |
| 1788 | |
| 1789 virtual void PrintOperandsTo(BufferFormatter* f) const; | |
| 1790 | |
| 1791 Value* value() const { return inputs_[0]; } | |
| 1792 Range* constraint() const { return constraint_; } | |
| 1793 | |
| 1794 virtual bool InferRange(); | |
| 1795 | |
| 1796 void AddDependency(Definition* defn) { | |
| 1797 Value* val = new Value(defn); | |
| 1798 val->set_use_index(1); | |
| 1799 val->set_instruction(this); | |
| 1800 val->AddToInputUseList(); | |
| 1801 set_dependency(val); | |
| 1802 } | |
| 1803 | |
| 1804 void RemoveDependency() { | |
| 1805 if (dependency() != NULL) { | |
| 1806 dependency()->RemoveFromInputUseList(); | |
| 1807 set_dependency(NULL); | |
| 1808 } | |
| 1809 } | |
| 1810 | |
| 1811 private: | |
| 1812 Value* dependency() { | |
| 1813 return inputs_[1]; | |
| 1814 } | |
| 1815 | |
| 1816 void set_dependency(Value* value) { | |
| 1817 inputs_[1] = value; | |
| 1818 } | |
| 1819 | |
| 1820 Range* constraint_; | |
| 1821 | |
| 1822 DISALLOW_COPY_AND_ASSIGN(ConstraintInstr); | |
| 1823 }; | |
| 1824 | |
| 1825 | |
| 1533 class ConstantInstr : public TemplateDefinition<0> { | 1826 class ConstantInstr : public TemplateDefinition<0> { |
| 1534 public: | 1827 public: |
| 1535 explicit ConstantInstr(const Object& value) : value_(value) { } | 1828 explicit ConstantInstr(const Object& value) |
| 1829 : value_(value) { } | |
| 1536 | 1830 |
| 1537 DECLARE_INSTRUCTION(Constant) | 1831 DECLARE_INSTRUCTION(Constant) |
| 1538 virtual RawAbstractType* CompileType() const; | 1832 virtual RawAbstractType* CompileType() const; |
| 1539 | 1833 |
| 1540 const Object& value() const { return value_; } | 1834 const Object& value() const { return value_; } |
| 1541 | 1835 |
| 1542 virtual void PrintOperandsTo(BufferFormatter* f) const; | 1836 virtual void PrintOperandsTo(BufferFormatter* f) const; |
| 1543 | 1837 |
| 1544 virtual bool CanDeoptimize() const { return false; } | 1838 virtual bool CanDeoptimize() const { return false; } |
| 1545 | 1839 |
| 1546 virtual bool HasSideEffect() const { return false; } | 1840 virtual bool HasSideEffect() const { return false; } |
| 1547 | 1841 |
| 1548 virtual intptr_t ResultCid() const; | 1842 virtual intptr_t ResultCid() const; |
| 1549 | 1843 |
| 1550 virtual bool AttributesEqual(Instruction* other) const; | 1844 virtual bool AttributesEqual(Instruction* other) const; |
| 1551 virtual bool AffectedBySideEffect() const { return false; } | 1845 virtual bool AffectedBySideEffect() const { return false; } |
| 1552 | 1846 |
| 1847 virtual bool InferRange(); | |
| 1848 | |
| 1553 private: | 1849 private: |
| 1554 const Object& value_; | 1850 const Object& value_; |
| 1555 | 1851 |
| 1556 DISALLOW_COPY_AND_ASSIGN(ConstantInstr); | 1852 DISALLOW_COPY_AND_ASSIGN(ConstantInstr); |
| 1557 }; | 1853 }; |
| 1558 | 1854 |
| 1559 | 1855 |
| 1560 class AssertAssignableInstr : public TemplateDefinition<3> { | 1856 class AssertAssignableInstr : public TemplateDefinition<3> { |
| 1561 public: | 1857 public: |
| 1562 AssertAssignableInstr(intptr_t token_pos, | 1858 AssertAssignableInstr(intptr_t token_pos, |
| (...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1848 InstanceCallInstr* instance_call_; | 2144 InstanceCallInstr* instance_call_; |
| 1849 const ICData& ic_data_; | 2145 const ICData& ic_data_; |
| 1850 const bool with_checks_; | 2146 const bool with_checks_; |
| 1851 | 2147 |
| 1852 DISALLOW_COPY_AND_ASSIGN(PolymorphicInstanceCallInstr); | 2148 DISALLOW_COPY_AND_ASSIGN(PolymorphicInstanceCallInstr); |
| 1853 }; | 2149 }; |
| 1854 | 2150 |
| 1855 | 2151 |
| 1856 class ComparisonInstr : public TemplateDefinition<2> { | 2152 class ComparisonInstr : public TemplateDefinition<2> { |
| 1857 public: | 2153 public: |
| 1858 ComparisonInstr(Token::Kind kind, Value* left, Value* right) : kind_(kind) { | 2154 ComparisonInstr(Token::Kind kind, Value* left, Value* right) |
| 2155 : kind_(kind) { | |
| 1859 ASSERT(left != NULL); | 2156 ASSERT(left != NULL); |
| 1860 ASSERT(right != NULL); | 2157 ASSERT(right != NULL); |
| 1861 inputs_[0] = left; | 2158 inputs_[0] = left; |
| 1862 inputs_[1] = right; | 2159 inputs_[1] = right; |
| 1863 } | 2160 } |
| 1864 | 2161 |
| 1865 Value* left() const { return inputs_[0]; } | 2162 Value* left() const { return inputs_[0]; } |
| 1866 Value* right() const { return inputs_[1]; } | 2163 Value* right() const { return inputs_[1]; } |
| 1867 | 2164 |
| 1868 virtual ComparisonInstr* AsComparison() { return this; } | 2165 virtual ComparisonInstr* AsComparison() { return this; } |
| (...skipping 1275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3144 }; | 3441 }; |
| 3145 | 3442 |
| 3146 | 3443 |
| 3147 class BinarySmiOpInstr : public TemplateDefinition<2> { | 3444 class BinarySmiOpInstr : public TemplateDefinition<2> { |
| 3148 public: | 3445 public: |
| 3149 BinarySmiOpInstr(Token::Kind op_kind, | 3446 BinarySmiOpInstr(Token::Kind op_kind, |
| 3150 InstanceCallInstr* instance_call, | 3447 InstanceCallInstr* instance_call, |
| 3151 Value* left, | 3448 Value* left, |
| 3152 Value* right) | 3449 Value* right) |
| 3153 : op_kind_(op_kind), | 3450 : op_kind_(op_kind), |
| 3154 instance_call_(instance_call) { | 3451 instance_call_(instance_call), |
| 3452 overflow_(true) { | |
| 3155 ASSERT(left != NULL); | 3453 ASSERT(left != NULL); |
| 3156 ASSERT(right != NULL); | 3454 ASSERT(right != NULL); |
| 3157 inputs_[0] = left; | 3455 inputs_[0] = left; |
| 3158 inputs_[1] = right; | 3456 inputs_[1] = right; |
| 3159 } | 3457 } |
| 3160 | 3458 |
| 3161 Value* left() const { return inputs_[0]; } | 3459 Value* left() const { return inputs_[0]; } |
| 3162 Value* right() const { return inputs_[1]; } | 3460 Value* right() const { return inputs_[1]; } |
| 3163 | 3461 |
| 3164 Token::Kind op_kind() const { return op_kind_; } | 3462 Token::Kind op_kind() const { return op_kind_; } |
| 3165 | 3463 |
| 3166 InstanceCallInstr* instance_call() const { return instance_call_; } | 3464 InstanceCallInstr* instance_call() const { return instance_call_; } |
| 3167 | 3465 |
| 3168 const ICData* ic_data() const { return instance_call()->ic_data(); } | 3466 const ICData* ic_data() const { return instance_call()->ic_data(); } |
| 3169 | 3467 |
| 3170 virtual void PrintOperandsTo(BufferFormatter* f) const; | 3468 virtual void PrintOperandsTo(BufferFormatter* f) const; |
| 3171 | 3469 |
| 3172 DECLARE_INSTRUCTION(BinarySmiOp) | 3470 DECLARE_INSTRUCTION(BinarySmiOp) |
| 3173 virtual RawAbstractType* CompileType() const; | 3471 virtual RawAbstractType* CompileType() const; |
| 3174 | 3472 |
| 3175 virtual bool CanDeoptimize() const; | 3473 virtual bool CanDeoptimize() const; |
| 3176 | 3474 |
| 3177 virtual bool HasSideEffect() const { return false; } | 3475 virtual bool HasSideEffect() const { return false; } |
| 3178 | 3476 |
| 3179 virtual bool AffectedBySideEffect() const { return false; } | 3477 virtual bool AffectedBySideEffect() const { return false; } |
| 3180 virtual bool AttributesEqual(Instruction* other) const; | 3478 virtual bool AttributesEqual(Instruction* other) const; |
| 3181 | 3479 |
| 3182 virtual intptr_t ResultCid() const; | 3480 virtual intptr_t ResultCid() const; |
| 3183 | 3481 |
| 3482 void set_overflow(bool overflow) { | |
| 3483 overflow_ = overflow; | |
| 3484 } | |
| 3485 | |
| 3486 void PrintTo(BufferFormatter* f) const; | |
| 3487 | |
| 3488 virtual bool InferRange(); | |
| 3489 | |
| 3184 private: | 3490 private: |
| 3185 const Token::Kind op_kind_; | 3491 const Token::Kind op_kind_; |
| 3186 InstanceCallInstr* instance_call_; | 3492 InstanceCallInstr* instance_call_; |
| 3493 bool overflow_; | |
| 3187 | 3494 |
| 3188 DISALLOW_COPY_AND_ASSIGN(BinarySmiOpInstr); | 3495 DISALLOW_COPY_AND_ASSIGN(BinarySmiOpInstr); |
| 3189 }; | 3496 }; |
| 3190 | 3497 |
| 3191 | 3498 |
| 3192 class BinaryMintOpInstr : public TemplateDefinition<2> { | 3499 class BinaryMintOpInstr : public TemplateDefinition<2> { |
| 3193 public: | 3500 public: |
| 3194 BinaryMintOpInstr(Token::Kind op_kind, | 3501 BinaryMintOpInstr(Token::Kind op_kind, |
| 3195 InstanceCallInstr* instance_call, | 3502 InstanceCallInstr* instance_call, |
| 3196 Value* left, | 3503 Value* left, |
| (...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3659 ForwardInstructionIterator* current_iterator_; | 3966 ForwardInstructionIterator* current_iterator_; |
| 3660 | 3967 |
| 3661 private: | 3968 private: |
| 3662 DISALLOW_COPY_AND_ASSIGN(FlowGraphVisitor); | 3969 DISALLOW_COPY_AND_ASSIGN(FlowGraphVisitor); |
| 3663 }; | 3970 }; |
| 3664 | 3971 |
| 3665 | 3972 |
| 3666 } // namespace dart | 3973 } // namespace dart |
| 3667 | 3974 |
| 3668 #endif // VM_INTERMEDIATE_LANGUAGE_H_ | 3975 #endif // VM_INTERMEDIATE_LANGUAGE_H_ |
| OLD | NEW |