| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef V8_HYDROGEN_INSTRUCTIONS_H_ | 5 #ifndef V8_HYDROGEN_INSTRUCTIONS_H_ |
| 6 #define V8_HYDROGEN_INSTRUCTIONS_H_ | 6 #define V8_HYDROGEN_INSTRUCTIONS_H_ |
| 7 | 7 |
| 8 #include <cstring> | 8 #include <cstring> |
| 9 #include <iosfwd> | 9 #include <iosfwd> |
| 10 | 10 |
| (...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 405 | 405 |
| 406 HValue* base_; | 406 HValue* base_; |
| 407 int offset_; | 407 int offset_; |
| 408 int scale_; | 408 int scale_; |
| 409 }; | 409 }; |
| 410 | 410 |
| 411 | 411 |
| 412 typedef EnumSet<GVNFlag, int32_t> GVNFlagSet; | 412 typedef EnumSet<GVNFlag, int32_t> GVNFlagSet; |
| 413 | 413 |
| 414 | 414 |
| 415 // This class encapsulates encoding and decoding of sources positions from | |
| 416 // which hydrogen values originated. | |
| 417 // When FLAG_track_hydrogen_positions is set this object encodes the | |
| 418 // identifier of the inlining and absolute offset from the start of the | |
| 419 // inlined function. | |
| 420 // When the flag is not set we simply track absolute offset from the | |
| 421 // script start. | |
| 422 class HSourcePosition { | |
| 423 public: | |
| 424 HSourcePosition(const HSourcePosition& other) : value_(other.value_) { } | |
| 425 | |
| 426 static HSourcePosition Unknown() { | |
| 427 return HSourcePosition(RelocInfo::kNoPosition); | |
| 428 } | |
| 429 static HSourcePosition FromRaw(int raw_value) { | |
| 430 return HSourcePosition(raw_value); | |
| 431 } | |
| 432 | |
| 433 bool IsUnknown() const { return value_ == RelocInfo::kNoPosition; } | |
| 434 | |
| 435 int position() const { return PositionField::decode(value_); } | |
| 436 void set_position(int position) { | |
| 437 if (FLAG_hydrogen_track_positions) { | |
| 438 value_ = static_cast<int>(PositionField::update(value_, position)); | |
| 439 } else { | |
| 440 value_ = position; | |
| 441 } | |
| 442 } | |
| 443 | |
| 444 int inlining_id() const { return InliningIdField::decode(value_); } | |
| 445 void set_inlining_id(int inlining_id) { | |
| 446 if (FLAG_hydrogen_track_positions) { | |
| 447 value_ = static_cast<int>(InliningIdField::update(value_, inlining_id)); | |
| 448 } | |
| 449 } | |
| 450 | |
| 451 int raw() const { return value_; } | |
| 452 | |
| 453 private: | |
| 454 typedef BitField<int, 0, 9> InliningIdField; | |
| 455 | |
| 456 // Offset from the start of the inlined function. | |
| 457 typedef BitField<int, 9, 23> PositionField; | |
| 458 | |
| 459 explicit HSourcePosition(int value) : value_(value) { } | |
| 460 | |
| 461 friend class HPositionInfo; | |
| 462 friend class LCodeGenBase; | |
| 463 | |
| 464 // If FLAG_hydrogen_track_positions is set contains bitfields InliningIdField | |
| 465 // and PositionField. | |
| 466 // Otherwise contains absolute offset from the script start. | |
| 467 int value_; | |
| 468 }; | |
| 469 | |
| 470 | |
| 471 std::ostream& operator<<(std::ostream& os, const HSourcePosition& p); | |
| 472 | |
| 473 | |
| 474 class HValue : public ZoneObject { | 415 class HValue : public ZoneObject { |
| 475 public: | 416 public: |
| 476 static const int kNoNumber = -1; | 417 static const int kNoNumber = -1; |
| 477 | 418 |
| 478 enum Flag { | 419 enum Flag { |
| 479 kFlexibleRepresentation, | 420 kFlexibleRepresentation, |
| 480 kCannotBeTagged, | 421 kCannotBeTagged, |
| 481 // Participate in Global Value Numbering, i.e. elimination of | 422 // Participate in Global Value Numbering, i.e. elimination of |
| 482 // unnecessary recomputations. If an instruction sets this flag, it must | 423 // unnecessary recomputations. If an instruction sets this flag, it must |
| 483 // implement DataEquals(), which will be used to determine if other | 424 // implement DataEquals(), which will be used to determine if other |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 559 id_(kNoNumber), | 500 id_(kNoNumber), |
| 560 type_(type), | 501 type_(type), |
| 561 use_list_(NULL), | 502 use_list_(NULL), |
| 562 range_(NULL), | 503 range_(NULL), |
| 563 #ifdef DEBUG | 504 #ifdef DEBUG |
| 564 range_poisoned_(false), | 505 range_poisoned_(false), |
| 565 #endif | 506 #endif |
| 566 flags_(0) {} | 507 flags_(0) {} |
| 567 virtual ~HValue() {} | 508 virtual ~HValue() {} |
| 568 | 509 |
| 569 virtual HSourcePosition position() const { | 510 virtual SourcePosition position() const { return SourcePosition::Unknown(); } |
| 570 return HSourcePosition::Unknown(); | 511 virtual SourcePosition operand_position(int index) const { |
| 571 } | |
| 572 virtual HSourcePosition operand_position(int index) const { | |
| 573 return position(); | 512 return position(); |
| 574 } | 513 } |
| 575 | 514 |
| 576 HBasicBlock* block() const { return block_; } | 515 HBasicBlock* block() const { return block_; } |
| 577 void SetBlock(HBasicBlock* block); | 516 void SetBlock(HBasicBlock* block); |
| 578 | 517 |
| 579 // Note: Never call this method for an unlinked value. | 518 // Note: Never call this method for an unlinked value. |
| 580 Isolate* isolate() const; | 519 Isolate* isolate() const; |
| 581 | 520 |
| 582 int id() const { return id_; } | 521 int id() const { return id_; } |
| (...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1032 // the HInstruction in the compact form. Uses tagging to distinguish between | 971 // the HInstruction in the compact form. Uses tagging to distinguish between |
| 1033 // case when only instruction's position is available and case when operands' | 972 // case when only instruction's position is available and case when operands' |
| 1034 // positions are also available. | 973 // positions are also available. |
| 1035 // In the first case it contains intruction's position as a tagged value. | 974 // In the first case it contains intruction's position as a tagged value. |
| 1036 // In the second case it points to an array which contains instruction's | 975 // In the second case it points to an array which contains instruction's |
| 1037 // position and operands' positions. | 976 // position and operands' positions. |
| 1038 class HPositionInfo { | 977 class HPositionInfo { |
| 1039 public: | 978 public: |
| 1040 explicit HPositionInfo(int pos) : data_(TagPosition(pos)) { } | 979 explicit HPositionInfo(int pos) : data_(TagPosition(pos)) { } |
| 1041 | 980 |
| 1042 HSourcePosition position() const { | 981 SourcePosition position() const { |
| 1043 if (has_operand_positions()) { | 982 if (has_operand_positions()) { |
| 1044 return operand_positions()[kInstructionPosIndex]; | 983 return operand_positions()[kInstructionPosIndex]; |
| 1045 } | 984 } |
| 1046 return HSourcePosition(static_cast<int>(UntagPosition(data_))); | 985 return SourcePosition(static_cast<int>(UntagPosition(data_))); |
| 1047 } | 986 } |
| 1048 | 987 |
| 1049 void set_position(HSourcePosition pos) { | 988 void set_position(SourcePosition pos) { |
| 1050 if (has_operand_positions()) { | 989 if (has_operand_positions()) { |
| 1051 operand_positions()[kInstructionPosIndex] = pos; | 990 operand_positions()[kInstructionPosIndex] = pos; |
| 1052 } else { | 991 } else { |
| 1053 data_ = TagPosition(pos.raw()); | 992 data_ = TagPosition(pos.raw()); |
| 1054 } | 993 } |
| 1055 } | 994 } |
| 1056 | 995 |
| 1057 void ensure_storage_for_operand_positions(Zone* zone, int operand_count) { | 996 void ensure_storage_for_operand_positions(Zone* zone, int operand_count) { |
| 1058 if (has_operand_positions()) { | 997 if (has_operand_positions()) { |
| 1059 return; | 998 return; |
| 1060 } | 999 } |
| 1061 | 1000 |
| 1062 const int length = kFirstOperandPosIndex + operand_count; | 1001 const int length = kFirstOperandPosIndex + operand_count; |
| 1063 HSourcePosition* positions = | 1002 SourcePosition* positions = zone->NewArray<SourcePosition>(length); |
| 1064 zone->NewArray<HSourcePosition>(length); | |
| 1065 for (int i = 0; i < length; i++) { | 1003 for (int i = 0; i < length; i++) { |
| 1066 positions[i] = HSourcePosition::Unknown(); | 1004 positions[i] = SourcePosition::Unknown(); |
| 1067 } | 1005 } |
| 1068 | 1006 |
| 1069 const HSourcePosition pos = position(); | 1007 const SourcePosition pos = position(); |
| 1070 data_ = reinterpret_cast<intptr_t>(positions); | 1008 data_ = reinterpret_cast<intptr_t>(positions); |
| 1071 set_position(pos); | 1009 set_position(pos); |
| 1072 | 1010 |
| 1073 DCHECK(has_operand_positions()); | 1011 DCHECK(has_operand_positions()); |
| 1074 } | 1012 } |
| 1075 | 1013 |
| 1076 HSourcePosition operand_position(int idx) const { | 1014 SourcePosition operand_position(int idx) const { |
| 1077 if (!has_operand_positions()) { | 1015 if (!has_operand_positions()) { |
| 1078 return position(); | 1016 return position(); |
| 1079 } | 1017 } |
| 1080 return *operand_position_slot(idx); | 1018 return *operand_position_slot(idx); |
| 1081 } | 1019 } |
| 1082 | 1020 |
| 1083 void set_operand_position(int idx, HSourcePosition pos) { | 1021 void set_operand_position(int idx, SourcePosition pos) { |
| 1084 *operand_position_slot(idx) = pos; | 1022 *operand_position_slot(idx) = pos; |
| 1085 } | 1023 } |
| 1086 | 1024 |
| 1087 private: | 1025 private: |
| 1088 static const intptr_t kInstructionPosIndex = 0; | 1026 static const intptr_t kInstructionPosIndex = 0; |
| 1089 static const intptr_t kFirstOperandPosIndex = 1; | 1027 static const intptr_t kFirstOperandPosIndex = 1; |
| 1090 | 1028 |
| 1091 HSourcePosition* operand_position_slot(int idx) const { | 1029 SourcePosition* operand_position_slot(int idx) const { |
| 1092 DCHECK(has_operand_positions()); | 1030 DCHECK(has_operand_positions()); |
| 1093 return &(operand_positions()[kFirstOperandPosIndex + idx]); | 1031 return &(operand_positions()[kFirstOperandPosIndex + idx]); |
| 1094 } | 1032 } |
| 1095 | 1033 |
| 1096 bool has_operand_positions() const { | 1034 bool has_operand_positions() const { |
| 1097 return !IsTaggedPosition(data_); | 1035 return !IsTaggedPosition(data_); |
| 1098 } | 1036 } |
| 1099 | 1037 |
| 1100 HSourcePosition* operand_positions() const { | 1038 SourcePosition* operand_positions() const { |
| 1101 DCHECK(has_operand_positions()); | 1039 DCHECK(has_operand_positions()); |
| 1102 return reinterpret_cast<HSourcePosition*>(data_); | 1040 return reinterpret_cast<SourcePosition*>(data_); |
| 1103 } | 1041 } |
| 1104 | 1042 |
| 1105 static const intptr_t kPositionTag = 1; | 1043 static const intptr_t kPositionTag = 1; |
| 1106 static const intptr_t kPositionShift = 1; | 1044 static const intptr_t kPositionShift = 1; |
| 1107 static bool IsTaggedPosition(intptr_t val) { | 1045 static bool IsTaggedPosition(intptr_t val) { |
| 1108 return (val & kPositionTag) != 0; | 1046 return (val & kPositionTag) != 0; |
| 1109 } | 1047 } |
| 1110 static intptr_t UntagPosition(intptr_t val) { | 1048 static intptr_t UntagPosition(intptr_t val) { |
| 1111 DCHECK(IsTaggedPosition(val)); | 1049 DCHECK(IsTaggedPosition(val)); |
| 1112 return val >> kPositionShift; | 1050 return val >> kPositionShift; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1140 } | 1078 } |
| 1141 | 1079 |
| 1142 void InsertAfter(HInstruction* previous); | 1080 void InsertAfter(HInstruction* previous); |
| 1143 | 1081 |
| 1144 template<class T> T* Append(T* instr) { | 1082 template<class T> T* Append(T* instr) { |
| 1145 instr->InsertAfter(this); | 1083 instr->InsertAfter(this); |
| 1146 return instr; | 1084 return instr; |
| 1147 } | 1085 } |
| 1148 | 1086 |
| 1149 // The position is a write-once variable. | 1087 // The position is a write-once variable. |
| 1150 HSourcePosition position() const OVERRIDE { | 1088 SourcePosition position() const OVERRIDE { |
| 1151 return HSourcePosition(position_.position()); | 1089 return SourcePosition(position_.position()); |
| 1152 } | 1090 } |
| 1153 bool has_position() const { | 1091 bool has_position() const { |
| 1154 return !position().IsUnknown(); | 1092 return !position().IsUnknown(); |
| 1155 } | 1093 } |
| 1156 void set_position(HSourcePosition position) { | 1094 void set_position(SourcePosition position) { |
| 1157 DCHECK(!has_position()); | 1095 DCHECK(!has_position()); |
| 1158 DCHECK(!position.IsUnknown()); | 1096 DCHECK(!position.IsUnknown()); |
| 1159 position_.set_position(position); | 1097 position_.set_position(position); |
| 1160 } | 1098 } |
| 1161 | 1099 |
| 1162 HSourcePosition operand_position(int index) const OVERRIDE { | 1100 SourcePosition operand_position(int index) const OVERRIDE { |
| 1163 const HSourcePosition pos = position_.operand_position(index); | 1101 const SourcePosition pos = position_.operand_position(index); |
| 1164 return pos.IsUnknown() ? position() : pos; | 1102 return pos.IsUnknown() ? position() : pos; |
| 1165 } | 1103 } |
| 1166 void set_operand_position(Zone* zone, int index, HSourcePosition pos) { | 1104 void set_operand_position(Zone* zone, int index, SourcePosition pos) { |
| 1167 DCHECK(0 <= index && index < OperandCount()); | 1105 DCHECK(0 <= index && index < OperandCount()); |
| 1168 position_.ensure_storage_for_operand_positions(zone, OperandCount()); | 1106 position_.ensure_storage_for_operand_positions(zone, OperandCount()); |
| 1169 position_.set_operand_position(index, pos); | 1107 position_.set_operand_position(index, pos); |
| 1170 } | 1108 } |
| 1171 | 1109 |
| 1172 bool Dominates(HInstruction* other); | 1110 bool Dominates(HInstruction* other); |
| 1173 bool CanTruncateToSmi() const { return CheckFlag(kTruncatingToSmi); } | 1111 bool CanTruncateToSmi() const { return CheckFlag(kTruncatingToSmi); } |
| 1174 bool CanTruncateToInt32() const { return CheckFlag(kTruncatingToInt32); } | 1112 bool CanTruncateToInt32() const { return CheckFlag(kTruncatingToInt32); } |
| 1175 | 1113 |
| 1176 virtual LInstruction* CompileToLithium(LChunkBuilder* builder) = 0; | 1114 virtual LInstruction* CompileToLithium(LChunkBuilder* builder) = 0; |
| (...skipping 2116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3293 HType CalculateInferredType() OVERRIDE; | 3231 HType CalculateInferredType() OVERRIDE; |
| 3294 int OperandCount() const OVERRIDE { return inputs_.length(); } | 3232 int OperandCount() const OVERRIDE { return inputs_.length(); } |
| 3295 HValue* OperandAt(int index) const OVERRIDE { return inputs_[index]; } | 3233 HValue* OperandAt(int index) const OVERRIDE { return inputs_[index]; } |
| 3296 HValue* GetRedundantReplacement(); | 3234 HValue* GetRedundantReplacement(); |
| 3297 void AddInput(HValue* value); | 3235 void AddInput(HValue* value); |
| 3298 bool HasRealUses(); | 3236 bool HasRealUses(); |
| 3299 | 3237 |
| 3300 bool IsReceiver() const { return merged_index_ == 0; } | 3238 bool IsReceiver() const { return merged_index_ == 0; } |
| 3301 bool HasMergedIndex() const { return merged_index_ != kInvalidMergedIndex; } | 3239 bool HasMergedIndex() const { return merged_index_ != kInvalidMergedIndex; } |
| 3302 | 3240 |
| 3303 HSourcePosition position() const OVERRIDE; | 3241 SourcePosition position() const OVERRIDE; |
| 3304 | 3242 |
| 3305 int merged_index() const { return merged_index_; } | 3243 int merged_index() const { return merged_index_; } |
| 3306 | 3244 |
| 3307 InductionVariableData* induction_variable_data() { | 3245 InductionVariableData* induction_variable_data() { |
| 3308 return induction_variable_data_; | 3246 return induction_variable_data_; |
| 3309 } | 3247 } |
| 3310 bool IsInductionVariable() { | 3248 bool IsInductionVariable() { |
| 3311 return induction_variable_data_ != NULL; | 3249 return induction_variable_data_ != NULL; |
| 3312 } | 3250 } |
| 3313 bool IsLimitedInductionVariable() { | 3251 bool IsLimitedInductionVariable() { |
| (...skipping 548 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3862 | 3800 |
| 3863 virtual bool IsCommutative() const { return false; } | 3801 virtual bool IsCommutative() const { return false; } |
| 3864 | 3802 |
| 3865 std::ostream& PrintDataTo(std::ostream& os) const OVERRIDE; // NOLINT | 3803 std::ostream& PrintDataTo(std::ostream& os) const OVERRIDE; // NOLINT |
| 3866 | 3804 |
| 3867 Representation RequiredInputRepresentation(int index) OVERRIDE { | 3805 Representation RequiredInputRepresentation(int index) OVERRIDE { |
| 3868 if (index == 0) return Representation::Tagged(); | 3806 if (index == 0) return Representation::Tagged(); |
| 3869 return representation(); | 3807 return representation(); |
| 3870 } | 3808 } |
| 3871 | 3809 |
| 3872 void SetOperandPositions(Zone* zone, | 3810 void SetOperandPositions(Zone* zone, SourcePosition left_pos, |
| 3873 HSourcePosition left_pos, | 3811 SourcePosition right_pos) { |
| 3874 HSourcePosition right_pos) { | |
| 3875 set_operand_position(zone, 1, left_pos); | 3812 set_operand_position(zone, 1, left_pos); |
| 3876 set_operand_position(zone, 2, right_pos); | 3813 set_operand_position(zone, 2, right_pos); |
| 3877 } | 3814 } |
| 3878 | 3815 |
| 3879 bool RightIsPowerOf2() { | 3816 bool RightIsPowerOf2() { |
| 3880 if (!right()->IsInteger32Constant()) return false; | 3817 if (!right()->IsInteger32Constant()) return false; |
| 3881 int32_t value = right()->GetInteger32Constant(); | 3818 int32_t value = right()->GetInteger32Constant(); |
| 3882 if (value < 0) { | 3819 if (value < 0) { |
| 3883 return base::bits::IsPowerOfTwo32(static_cast<uint32_t>(-value)); | 3820 return base::bits::IsPowerOfTwo32(static_cast<uint32_t>(-value)); |
| 3884 } | 3821 } |
| (...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4322 return representation(); | 4259 return representation(); |
| 4323 } | 4260 } |
| 4324 Representation observed_input_representation(int index) OVERRIDE { | 4261 Representation observed_input_representation(int index) OVERRIDE { |
| 4325 return observed_input_representation_[index]; | 4262 return observed_input_representation_[index]; |
| 4326 } | 4263 } |
| 4327 | 4264 |
| 4328 bool KnownSuccessorBlock(HBasicBlock** block) OVERRIDE; | 4265 bool KnownSuccessorBlock(HBasicBlock** block) OVERRIDE; |
| 4329 | 4266 |
| 4330 std::ostream& PrintDataTo(std::ostream& os) const OVERRIDE; // NOLINT | 4267 std::ostream& PrintDataTo(std::ostream& os) const OVERRIDE; // NOLINT |
| 4331 | 4268 |
| 4332 void SetOperandPositions(Zone* zone, | 4269 void SetOperandPositions(Zone* zone, SourcePosition left_pos, |
| 4333 HSourcePosition left_pos, | 4270 SourcePosition right_pos) { |
| 4334 HSourcePosition right_pos) { | |
| 4335 set_operand_position(zone, 0, left_pos); | 4271 set_operand_position(zone, 0, left_pos); |
| 4336 set_operand_position(zone, 1, right_pos); | 4272 set_operand_position(zone, 1, right_pos); |
| 4337 } | 4273 } |
| 4338 | 4274 |
| 4339 DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch) | 4275 DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch) |
| 4340 | 4276 |
| 4341 private: | 4277 private: |
| 4342 HCompareNumericAndBranch(HValue* left, | 4278 HCompareNumericAndBranch(HValue* left, |
| 4343 HValue* right, | 4279 HValue* right, |
| 4344 Token::Value token, | 4280 Token::Value token, |
| (...skipping 3656 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8001 }; | 7937 }; |
| 8002 | 7938 |
| 8003 | 7939 |
| 8004 | 7940 |
| 8005 #undef DECLARE_INSTRUCTION | 7941 #undef DECLARE_INSTRUCTION |
| 8006 #undef DECLARE_CONCRETE_INSTRUCTION | 7942 #undef DECLARE_CONCRETE_INSTRUCTION |
| 8007 | 7943 |
| 8008 } } // namespace v8::internal | 7944 } } // namespace v8::internal |
| 8009 | 7945 |
| 8010 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ | 7946 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ |
| OLD | NEW |