OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 528 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
539 | 539 |
540 HValue* base_; | 540 HValue* base_; |
541 int offset_; | 541 int offset_; |
542 int scale_; | 542 int scale_; |
543 }; | 543 }; |
544 | 544 |
545 | 545 |
546 typedef EnumSet<GVNFlag, int32_t> GVNFlagSet; | 546 typedef EnumSet<GVNFlag, int32_t> GVNFlagSet; |
547 | 547 |
548 | 548 |
| 549 // This class encapsulates encoding and decoding of sources positions from |
| 550 // which hydrogen values originated. |
| 551 // When FLAG_track_hydrogen_positions is set this object encodes the |
| 552 // identifier of the inlining and absolute offset from the start of the |
| 553 // inlined function. |
| 554 // When the flag is not set we simply track absolute offset from the |
| 555 // script start. |
| 556 class HSourcePosition { |
| 557 public: |
| 558 HSourcePosition(const HSourcePosition& other) : value_(other.value_) { } |
| 559 |
| 560 static HSourcePosition Unknown() { |
| 561 return HSourcePosition(RelocInfo::kNoPosition); |
| 562 } |
| 563 |
| 564 bool IsUnknown() const { return value_ == RelocInfo::kNoPosition; } |
| 565 |
| 566 int position() const { return PositionField::decode(value_); } |
| 567 void set_position(int position) { |
| 568 if (FLAG_hydrogen_track_positions) { |
| 569 value_ = static_cast<int>(PositionField::update(value_, position)); |
| 570 } else { |
| 571 value_ = position; |
| 572 } |
| 573 } |
| 574 |
| 575 int inlining_id() const { return InliningIdField::decode(value_); } |
| 576 void set_inlining_id(int inlining_id) { |
| 577 if (FLAG_hydrogen_track_positions) { |
| 578 value_ = static_cast<int>(InliningIdField::update(value_, inlining_id)); |
| 579 } |
| 580 } |
| 581 |
| 582 int raw() const { return value_; } |
| 583 |
| 584 void PrintTo(FILE* f); |
| 585 |
| 586 private: |
| 587 typedef BitField<int, 0, 9> InliningIdField; |
| 588 |
| 589 // Offset from the start of the inlined function. |
| 590 typedef BitField<int, 9, 22> PositionField; |
| 591 |
| 592 // On HPositionInfo can use this constructor. |
| 593 explicit HSourcePosition(int value) : value_(value) { } |
| 594 |
| 595 friend class HPositionInfo; |
| 596 |
| 597 // If FLAG_hydrogen_track_positions is set contains bitfields InliningIdField |
| 598 // and PositionField. |
| 599 // Otherwise contains absolute offset from the script start. |
| 600 int value_; |
| 601 }; |
| 602 |
| 603 |
549 class HValue : public ZoneObject { | 604 class HValue : public ZoneObject { |
550 public: | 605 public: |
551 static const int kNoNumber = -1; | 606 static const int kNoNumber = -1; |
552 | 607 |
553 enum Flag { | 608 enum Flag { |
554 kFlexibleRepresentation, | 609 kFlexibleRepresentation, |
555 kCannotBeTagged, | 610 kCannotBeTagged, |
556 // Participate in Global Value Numbering, i.e. elimination of | 611 // Participate in Global Value Numbering, i.e. elimination of |
557 // unnecessary recomputations. If an instruction sets this flag, it must | 612 // unnecessary recomputations. If an instruction sets this flag, it must |
558 // implement DataEquals(), which will be used to determine if other | 613 // implement DataEquals(), which will be used to determine if other |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
620 | 675 |
621 HValue(HType type = HType::Tagged()) | 676 HValue(HType type = HType::Tagged()) |
622 : block_(NULL), | 677 : block_(NULL), |
623 id_(kNoNumber), | 678 id_(kNoNumber), |
624 type_(type), | 679 type_(type), |
625 use_list_(NULL), | 680 use_list_(NULL), |
626 range_(NULL), | 681 range_(NULL), |
627 flags_(0) {} | 682 flags_(0) {} |
628 virtual ~HValue() {} | 683 virtual ~HValue() {} |
629 | 684 |
630 virtual int position() const { return RelocInfo::kNoPosition; } | 685 virtual HSourcePosition position() const { |
631 virtual int operand_position(int index) const { return position(); } | 686 return HSourcePosition::Unknown(); |
| 687 } |
| 688 virtual HSourcePosition operand_position(int index) const { |
| 689 return position(); |
| 690 } |
632 | 691 |
633 HBasicBlock* block() const { return block_; } | 692 HBasicBlock* block() const { return block_; } |
634 void SetBlock(HBasicBlock* block); | 693 void SetBlock(HBasicBlock* block); |
635 | 694 |
636 // Note: Never call this method for an unlinked value. | 695 // Note: Never call this method for an unlinked value. |
637 Isolate* isolate() const; | 696 Isolate* isolate() const; |
638 | 697 |
639 int id() const { return id_; } | 698 int id() const { return id_; } |
640 void set_id(int id) { id_ = id; } | 699 void set_id(int id) { id_ = id; } |
641 | 700 |
(...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1078 } | 1137 } |
1079 | 1138 |
1080 | 1139 |
1081 // A helper class to represent per-operand position information attached to | 1140 // A helper class to represent per-operand position information attached to |
1082 // the HInstruction in the compact form. Uses tagging to distinguish between | 1141 // the HInstruction in the compact form. Uses tagging to distinguish between |
1083 // case when only instruction's position is available and case when operands' | 1142 // case when only instruction's position is available and case when operands' |
1084 // positions are also available. | 1143 // positions are also available. |
1085 // In the first case it contains intruction's position as a tagged value. | 1144 // In the first case it contains intruction's position as a tagged value. |
1086 // In the second case it points to an array which contains instruction's | 1145 // In the second case it points to an array which contains instruction's |
1087 // position and operands' positions. | 1146 // position and operands' positions. |
1088 // TODO(vegorov): what we really want to track here is a combination of | |
1089 // source position and a script id because cross script inlining can easily | |
1090 // result in optimized functions composed of several scripts. | |
1091 class HPositionInfo { | 1147 class HPositionInfo { |
1092 public: | 1148 public: |
1093 explicit HPositionInfo(int pos) : data_(TagPosition(pos)) { } | 1149 explicit HPositionInfo(int pos) : data_(TagPosition(pos)) { } |
1094 | 1150 |
1095 int position() const { | 1151 HSourcePosition position() const { |
1096 if (has_operand_positions()) { | 1152 if (has_operand_positions()) { |
1097 return static_cast<int>(operand_positions()[kInstructionPosIndex]); | 1153 return operand_positions()[kInstructionPosIndex]; |
1098 } | 1154 } |
1099 return static_cast<int>(UntagPosition(data_)); | 1155 return HSourcePosition(static_cast<int>(UntagPosition(data_))); |
1100 } | 1156 } |
1101 | 1157 |
1102 void set_position(int pos) { | 1158 void set_position(HSourcePosition pos) { |
1103 if (has_operand_positions()) { | 1159 if (has_operand_positions()) { |
1104 operand_positions()[kInstructionPosIndex] = pos; | 1160 operand_positions()[kInstructionPosIndex] = pos; |
1105 } else { | 1161 } else { |
1106 data_ = TagPosition(pos); | 1162 data_ = TagPosition(pos.raw()); |
1107 } | 1163 } |
1108 } | 1164 } |
1109 | 1165 |
1110 void ensure_storage_for_operand_positions(Zone* zone, int operand_count) { | 1166 void ensure_storage_for_operand_positions(Zone* zone, int operand_count) { |
1111 if (has_operand_positions()) { | 1167 if (has_operand_positions()) { |
1112 return; | 1168 return; |
1113 } | 1169 } |
1114 | 1170 |
1115 const int length = kFirstOperandPosIndex + operand_count; | 1171 const int length = kFirstOperandPosIndex + operand_count; |
1116 intptr_t* positions = | 1172 HSourcePosition* positions = |
1117 zone->NewArray<intptr_t>(length); | 1173 zone->NewArray<HSourcePosition>(length); |
1118 for (int i = 0; i < length; i++) { | 1174 for (int i = 0; i < length; i++) { |
1119 positions[i] = RelocInfo::kNoPosition; | 1175 positions[i] = HSourcePosition::Unknown(); |
1120 } | 1176 } |
1121 | 1177 |
1122 const int pos = position(); | 1178 const HSourcePosition pos = position(); |
1123 data_ = reinterpret_cast<intptr_t>(positions); | 1179 data_ = reinterpret_cast<intptr_t>(positions); |
1124 set_position(pos); | 1180 set_position(pos); |
1125 | 1181 |
1126 ASSERT(has_operand_positions()); | 1182 ASSERT(has_operand_positions()); |
1127 } | 1183 } |
1128 | 1184 |
1129 int operand_position(int idx) const { | 1185 HSourcePosition operand_position(int idx) const { |
1130 if (!has_operand_positions()) { | 1186 if (!has_operand_positions()) { |
1131 return position(); | 1187 return position(); |
1132 } | 1188 } |
1133 return static_cast<int>(*operand_position_slot(idx)); | 1189 return *operand_position_slot(idx); |
1134 } | 1190 } |
1135 | 1191 |
1136 void set_operand_position(int idx, int pos) { | 1192 void set_operand_position(int idx, HSourcePosition pos) { |
1137 *operand_position_slot(idx) = pos; | 1193 *operand_position_slot(idx) = pos; |
1138 } | 1194 } |
1139 | 1195 |
1140 private: | 1196 private: |
1141 static const intptr_t kInstructionPosIndex = 0; | 1197 static const intptr_t kInstructionPosIndex = 0; |
1142 static const intptr_t kFirstOperandPosIndex = 1; | 1198 static const intptr_t kFirstOperandPosIndex = 1; |
1143 | 1199 |
1144 intptr_t* operand_position_slot(int idx) const { | 1200 HSourcePosition* operand_position_slot(int idx) const { |
1145 ASSERT(has_operand_positions()); | 1201 ASSERT(has_operand_positions()); |
1146 return &(operand_positions()[kFirstOperandPosIndex + idx]); | 1202 return &(operand_positions()[kFirstOperandPosIndex + idx]); |
1147 } | 1203 } |
1148 | 1204 |
1149 bool has_operand_positions() const { | 1205 bool has_operand_positions() const { |
1150 return !IsTaggedPosition(data_); | 1206 return !IsTaggedPosition(data_); |
1151 } | 1207 } |
1152 | 1208 |
1153 intptr_t* operand_positions() const { | 1209 HSourcePosition* operand_positions() const { |
1154 ASSERT(has_operand_positions()); | 1210 ASSERT(has_operand_positions()); |
1155 return reinterpret_cast<intptr_t*>(data_); | 1211 return reinterpret_cast<HSourcePosition*>(data_); |
1156 } | 1212 } |
1157 | 1213 |
1158 static const intptr_t kPositionTag = 1; | 1214 static const intptr_t kPositionTag = 1; |
1159 static const intptr_t kPositionShift = 1; | 1215 static const intptr_t kPositionShift = 1; |
1160 static bool IsTaggedPosition(intptr_t val) { | 1216 static bool IsTaggedPosition(intptr_t val) { |
1161 return (val & kPositionTag) != 0; | 1217 return (val & kPositionTag) != 0; |
1162 } | 1218 } |
1163 static intptr_t UntagPosition(intptr_t val) { | 1219 static intptr_t UntagPosition(intptr_t val) { |
1164 ASSERT(IsTaggedPosition(val)); | 1220 ASSERT(IsTaggedPosition(val)); |
1165 return val >> kPositionShift; | 1221 return val >> kPositionShift; |
(...skipping 27 matching lines...) Expand all Loading... |
1193 } | 1249 } |
1194 | 1250 |
1195 void InsertAfter(HInstruction* previous); | 1251 void InsertAfter(HInstruction* previous); |
1196 | 1252 |
1197 template<class T> T* Append(T* instr) { | 1253 template<class T> T* Append(T* instr) { |
1198 instr->InsertAfter(this); | 1254 instr->InsertAfter(this); |
1199 return instr; | 1255 return instr; |
1200 } | 1256 } |
1201 | 1257 |
1202 // The position is a write-once variable. | 1258 // The position is a write-once variable. |
1203 virtual int position() const V8_OVERRIDE { | 1259 virtual HSourcePosition position() const V8_OVERRIDE { |
1204 return position_.position(); | 1260 return HSourcePosition(position_.position()); |
1205 } | 1261 } |
1206 bool has_position() const { | 1262 bool has_position() const { |
1207 return position_.position() != RelocInfo::kNoPosition; | 1263 return !position().IsUnknown(); |
1208 } | 1264 } |
1209 void set_position(int position) { | 1265 void set_position(HSourcePosition position) { |
1210 ASSERT(!has_position()); | 1266 ASSERT(!has_position()); |
1211 ASSERT(position != RelocInfo::kNoPosition); | 1267 ASSERT(!position.IsUnknown()); |
1212 position_.set_position(position); | 1268 position_.set_position(position); |
1213 } | 1269 } |
1214 | 1270 |
1215 virtual int operand_position(int index) const V8_OVERRIDE { | 1271 virtual HSourcePosition operand_position(int index) const V8_OVERRIDE { |
1216 const int pos = position_.operand_position(index); | 1272 const HSourcePosition pos = position_.operand_position(index); |
1217 return (pos != RelocInfo::kNoPosition) ? pos : position(); | 1273 return pos.IsUnknown() ? position() : pos; |
1218 } | 1274 } |
1219 void set_operand_position(Zone* zone, int index, int pos) { | 1275 void set_operand_position(Zone* zone, int index, HSourcePosition pos) { |
1220 ASSERT(0 <= index && index < OperandCount()); | 1276 ASSERT(0 <= index && index < OperandCount()); |
1221 position_.ensure_storage_for_operand_positions(zone, OperandCount()); | 1277 position_.ensure_storage_for_operand_positions(zone, OperandCount()); |
1222 position_.set_operand_position(index, pos); | 1278 position_.set_operand_position(index, pos); |
1223 } | 1279 } |
1224 | 1280 |
1225 bool CanTruncateToInt32() const { return CheckFlag(kTruncatingToInt32); } | 1281 bool CanTruncateToInt32() const { return CheckFlag(kTruncatingToInt32); } |
1226 | 1282 |
1227 virtual LInstruction* CompileToLithium(LChunkBuilder* builder) = 0; | 1283 virtual LInstruction* CompileToLithium(LChunkBuilder* builder) = 0; |
1228 | 1284 |
1229 #ifdef DEBUG | 1285 #ifdef DEBUG |
(...skipping 1926 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3156 virtual HValue* OperandAt(int index) const V8_OVERRIDE { | 3212 virtual HValue* OperandAt(int index) const V8_OVERRIDE { |
3157 return inputs_[index]; | 3213 return inputs_[index]; |
3158 } | 3214 } |
3159 HValue* GetRedundantReplacement(); | 3215 HValue* GetRedundantReplacement(); |
3160 void AddInput(HValue* value); | 3216 void AddInput(HValue* value); |
3161 bool HasRealUses(); | 3217 bool HasRealUses(); |
3162 | 3218 |
3163 bool IsReceiver() const { return merged_index_ == 0; } | 3219 bool IsReceiver() const { return merged_index_ == 0; } |
3164 bool HasMergedIndex() const { return merged_index_ != kInvalidMergedIndex; } | 3220 bool HasMergedIndex() const { return merged_index_ != kInvalidMergedIndex; } |
3165 | 3221 |
3166 virtual int position() const V8_OVERRIDE; | 3222 virtual HSourcePosition position() const V8_OVERRIDE; |
3167 | 3223 |
3168 int merged_index() const { return merged_index_; } | 3224 int merged_index() const { return merged_index_; } |
3169 | 3225 |
3170 InductionVariableData* induction_variable_data() { | 3226 InductionVariableData* induction_variable_data() { |
3171 return induction_variable_data_; | 3227 return induction_variable_data_; |
3172 } | 3228 } |
3173 bool IsInductionVariable() { | 3229 bool IsInductionVariable() { |
3174 return induction_variable_data_ != NULL; | 3230 return induction_variable_data_ != NULL; |
3175 } | 3231 } |
3176 bool IsLimitedInductionVariable() { | 3232 bool IsLimitedInductionVariable() { |
(...skipping 484 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3661 | 3717 |
3662 virtual bool IsCommutative() const { return false; } | 3718 virtual bool IsCommutative() const { return false; } |
3663 | 3719 |
3664 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE; | 3720 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE; |
3665 | 3721 |
3666 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE { | 3722 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE { |
3667 if (index == 0) return Representation::Tagged(); | 3723 if (index == 0) return Representation::Tagged(); |
3668 return representation(); | 3724 return representation(); |
3669 } | 3725 } |
3670 | 3726 |
3671 void SetOperandPositions(Zone* zone, int left_pos, int right_pos) { | 3727 void SetOperandPositions(Zone* zone, |
| 3728 HSourcePosition left_pos, |
| 3729 HSourcePosition right_pos) { |
3672 set_operand_position(zone, 1, left_pos); | 3730 set_operand_position(zone, 1, left_pos); |
3673 set_operand_position(zone, 2, right_pos); | 3731 set_operand_position(zone, 2, right_pos); |
3674 } | 3732 } |
3675 | 3733 |
3676 DECLARE_ABSTRACT_INSTRUCTION(BinaryOperation) | 3734 DECLARE_ABSTRACT_INSTRUCTION(BinaryOperation) |
3677 | 3735 |
3678 private: | 3736 private: |
3679 bool IgnoreObservedOutputRepresentation(Representation current_rep); | 3737 bool IgnoreObservedOutputRepresentation(Representation current_rep); |
3680 | 3738 |
3681 Representation observed_input_representation_[2]; | 3739 Representation observed_input_representation_[2]; |
(...skipping 434 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4116 HInferRepresentationPhase* h_infer) V8_OVERRIDE; | 4174 HInferRepresentationPhase* h_infer) V8_OVERRIDE; |
4117 | 4175 |
4118 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE { | 4176 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE { |
4119 return representation(); | 4177 return representation(); |
4120 } | 4178 } |
4121 virtual Representation observed_input_representation(int index) V8_OVERRIDE { | 4179 virtual Representation observed_input_representation(int index) V8_OVERRIDE { |
4122 return observed_input_representation_[index]; | 4180 return observed_input_representation_[index]; |
4123 } | 4181 } |
4124 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE; | 4182 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE; |
4125 | 4183 |
4126 void SetOperandPositions(Zone* zone, int left_pos, int right_pos) { | 4184 void SetOperandPositions(Zone* zone, |
| 4185 HSourcePosition left_pos, |
| 4186 HSourcePosition right_pos) { |
4127 set_operand_position(zone, 0, left_pos); | 4187 set_operand_position(zone, 0, left_pos); |
4128 set_operand_position(zone, 1, right_pos); | 4188 set_operand_position(zone, 1, right_pos); |
4129 } | 4189 } |
4130 | 4190 |
4131 DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch) | 4191 DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch) |
4132 | 4192 |
4133 private: | 4193 private: |
4134 HCompareNumericAndBranch(HValue* left, | 4194 HCompareNumericAndBranch(HValue* left, |
4135 HValue* right, | 4195 HValue* right, |
4136 Token::Value token, | 4196 Token::Value token, |
(...skipping 3318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7455 virtual bool IsDeletable() const V8_OVERRIDE { return true; } | 7515 virtual bool IsDeletable() const V8_OVERRIDE { return true; } |
7456 }; | 7516 }; |
7457 | 7517 |
7458 | 7518 |
7459 #undef DECLARE_INSTRUCTION | 7519 #undef DECLARE_INSTRUCTION |
7460 #undef DECLARE_CONCRETE_INSTRUCTION | 7520 #undef DECLARE_CONCRETE_INSTRUCTION |
7461 | 7521 |
7462 } } // namespace v8::internal | 7522 } } // namespace v8::internal |
7463 | 7523 |
7464 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ | 7524 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ |
OLD | NEW |