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 |