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 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
416 } | 416 } |
417 | 417 |
418 bool IsJSObject() const { | 418 bool IsJSObject() const { |
419 return ((type_ & kJSObject) == kJSObject); | 419 return ((type_ & kJSObject) == kJSObject); |
420 } | 420 } |
421 | 421 |
422 bool IsHeapObject() const { | 422 bool IsHeapObject() const { |
423 return IsHeapNumber() || IsString() || IsBoolean() || IsNonPrimitive(); | 423 return IsHeapNumber() || IsString() || IsBoolean() || IsNonPrimitive(); |
424 } | 424 } |
425 | 425 |
426 bool ToStringOrToNumberCanBeObserved(Representation representation) { | |
427 switch (type_) { | |
Sven Panne
2013/07/29 11:48:08
The usual pattern within v8 is:
switch (foo) {
Michael Starzinger
2013/07/29 12:30:03
+1 on this comment.
| |
428 case kTaggedPrimitive: // fallthru | |
Sven Panne
2013/07/29 11:48:08
Align.
| |
429 case kTaggedNumber: // fallthru | |
430 case kSmi: // fallthru | |
431 case kHeapNumber: // fallthru | |
432 case kString: // fallthru | |
433 case kBoolean: return false; | |
434 case kJSArray: // fallthru | |
435 case kJSObject: return true; | |
436 case kTagged: break; | |
437 } | |
438 return !representation.IsSmiOrInteger32() && !representation.IsDouble(); | |
439 } | |
440 | |
426 static HType TypeFromValue(Handle<Object> value); | 441 static HType TypeFromValue(Handle<Object> value); |
427 | 442 |
428 const char* ToString(); | 443 const char* ToString(); |
429 | 444 |
430 private: | 445 private: |
431 enum Type { | 446 enum Type { |
432 kTagged = 0x1, // 0000 0000 0000 0001 | 447 kTagged = 0x1, // 0000 0000 0000 0001 |
433 kTaggedPrimitive = 0x5, // 0000 0000 0000 0101 | 448 kTaggedPrimitive = 0x5, // 0000 0000 0000 0101 |
434 kTaggedNumber = 0xd, // 0000 0000 0000 1101 | 449 kTaggedNumber = 0xd, // 0000 0000 0000 1101 |
435 kSmi = 0x1d, // 0000 0000 0001 1101 | 450 kSmi = 0x1d, // 0000 0000 0001 1101 |
(...skipping 683 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1119 | 1134 |
1120 bool TryGuaranteeRange(HValue* upper_bound); | 1135 bool TryGuaranteeRange(HValue* upper_bound); |
1121 virtual bool TryDecompose(DecompositionResult* decomposition) { | 1136 virtual bool TryDecompose(DecompositionResult* decomposition) { |
1122 if (RedefinedOperand() != NULL) { | 1137 if (RedefinedOperand() != NULL) { |
1123 return RedefinedOperand()->TryDecompose(decomposition); | 1138 return RedefinedOperand()->TryDecompose(decomposition); |
1124 } else { | 1139 } else { |
1125 return false; | 1140 return false; |
1126 } | 1141 } |
1127 } | 1142 } |
1128 | 1143 |
1144 // Returns true conservatively if the program might be able to observe a | |
1145 // ToString() operation on this value. | |
1146 bool ToStringCanBeObserved() const { | |
1147 return type().ToStringOrToNumberCanBeObserved(representation()); | |
1148 } | |
1149 | |
1150 // Returns true conservatively if the program might be able to observe a | |
1151 // ToNumber() operation on this value. | |
1152 bool ToNumberCanBeObserved() const { | |
1153 return type().ToStringOrToNumberCanBeObserved(representation()); | |
1154 } | |
1155 | |
1129 protected: | 1156 protected: |
1130 void TryGuaranteeRangeRecursive(RangeEvaluationContext* context); | 1157 void TryGuaranteeRangeRecursive(RangeEvaluationContext* context); |
1131 | 1158 |
1132 enum RangeGuaranteeDirection { | 1159 enum RangeGuaranteeDirection { |
1133 DIRECTION_NONE = 0, | 1160 DIRECTION_NONE = 0, |
1134 DIRECTION_UPPER = 1, | 1161 DIRECTION_UPPER = 1, |
1135 DIRECTION_LOWER = 2, | 1162 DIRECTION_LOWER = 2, |
1136 DIRECTION_BOTH = DIRECTION_UPPER | DIRECTION_LOWER | 1163 DIRECTION_BOTH = DIRECTION_UPPER | DIRECTION_LOWER |
1137 }; | 1164 }; |
1138 virtual void SetResponsibilityForRange(RangeGuaranteeDirection direction) {} | 1165 virtual void SetResponsibilityForRange(RangeGuaranteeDirection direction) {} |
(...skipping 2174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3313 int phi_id() { return phi_id_; } | 3340 int phi_id() { return phi_id_; } |
3314 | 3341 |
3315 static HPhi* cast(HValue* value) { | 3342 static HPhi* cast(HValue* value) { |
3316 ASSERT(value->IsPhi()); | 3343 ASSERT(value->IsPhi()); |
3317 return reinterpret_cast<HPhi*>(value); | 3344 return reinterpret_cast<HPhi*>(value); |
3318 } | 3345 } |
3319 virtual Opcode opcode() const { return HValue::kPhi; } | 3346 virtual Opcode opcode() const { return HValue::kPhi; } |
3320 | 3347 |
3321 void SimplifyConstantInputs(); | 3348 void SimplifyConstantInputs(); |
3322 | 3349 |
3323 // TODO(titzer): we can't eliminate the receiver for generating backtraces | |
3324 virtual bool IsDeletable() const { return !IsReceiver(); } | |
3325 | |
3326 protected: | 3350 protected: |
3327 virtual void DeleteFromGraph(); | 3351 virtual void DeleteFromGraph(); |
3328 virtual void InternalSetOperandAt(int index, HValue* value) { | 3352 virtual void InternalSetOperandAt(int index, HValue* value) { |
3329 inputs_[index] = value; | 3353 inputs_[index] = value; |
3330 } | 3354 } |
3331 | 3355 |
3332 virtual bool IsRelationTrueInternal(NumericRelation relation, | 3356 virtual bool IsRelationTrueInternal(NumericRelation relation, |
3333 HValue* other, | 3357 HValue* other, |
3334 int offset = 0, | 3358 int offset = 0, |
3335 int scale = 0); | 3359 int scale = 0); |
3336 | 3360 |
3337 private: | 3361 private: |
3338 ZoneList<HValue*> inputs_; | 3362 ZoneList<HValue*> inputs_; |
3339 int merged_index_; | 3363 int merged_index_; |
3340 | 3364 |
3341 int non_phi_uses_[Representation::kNumRepresentations]; | 3365 int non_phi_uses_[Representation::kNumRepresentations]; |
3342 int indirect_uses_[Representation::kNumRepresentations]; | 3366 int indirect_uses_[Representation::kNumRepresentations]; |
3343 int phi_id_; | 3367 int phi_id_; |
3344 InductionVariableData* induction_variable_data_; | 3368 InductionVariableData* induction_variable_data_; |
3369 | |
3370 // TODO(titzer): we can't eliminate the receiver for generating backtraces | |
3371 virtual bool IsDeletable() const { return !IsReceiver(); } | |
3345 }; | 3372 }; |
3346 | 3373 |
3347 | 3374 |
3348 class HInductionVariableAnnotation : public HUnaryOperation { | 3375 class HInductionVariableAnnotation : public HUnaryOperation { |
3349 public: | 3376 public: |
3350 static HInductionVariableAnnotation* AddToGraph(HPhi* phi, | 3377 static HInductionVariableAnnotation* AddToGraph(HPhi* phi, |
3351 NumericRelation relation, | 3378 NumericRelation relation, |
3352 int operand_index); | 3379 int operand_index); |
3353 | 3380 |
3354 NumericRelation relation() { return relation_; } | 3381 NumericRelation relation() { return relation_; } |
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3646 HBinaryOperation(HValue* context, HValue* left, HValue* right) | 3673 HBinaryOperation(HValue* context, HValue* left, HValue* right) |
3647 : observed_output_representation_(Representation::None()) { | 3674 : observed_output_representation_(Representation::None()) { |
3648 ASSERT(left != NULL && right != NULL); | 3675 ASSERT(left != NULL && right != NULL); |
3649 SetOperandAt(0, context); | 3676 SetOperandAt(0, context); |
3650 SetOperandAt(1, left); | 3677 SetOperandAt(1, left); |
3651 SetOperandAt(2, right); | 3678 SetOperandAt(2, right); |
3652 observed_input_representation_[0] = Representation::None(); | 3679 observed_input_representation_[0] = Representation::None(); |
3653 observed_input_representation_[1] = Representation::None(); | 3680 observed_input_representation_[1] = Representation::None(); |
3654 } | 3681 } |
3655 | 3682 |
3656 HValue* context() { return OperandAt(0); } | 3683 HValue* context() const { return OperandAt(0); } |
3657 HValue* left() { return OperandAt(1); } | 3684 HValue* left() const { return OperandAt(1); } |
3658 HValue* right() { return OperandAt(2); } | 3685 HValue* right() const { return OperandAt(2); } |
3659 | 3686 |
3660 // True if switching left and right operands likely generates better code. | 3687 // True if switching left and right operands likely generates better code. |
3661 bool AreOperandsBetterSwitched() { | 3688 bool AreOperandsBetterSwitched() { |
3662 if (!IsCommutative()) return false; | 3689 if (!IsCommutative()) return false; |
3663 | 3690 |
3664 // Constant operands are better off on the right, they can be inlined in | 3691 // Constant operands are better off on the right, they can be inlined in |
3665 // many situations on most platforms. | 3692 // many situations on most platforms. |
3666 if (left()->IsConstant()) return true; | 3693 if (left()->IsConstant()) return true; |
3667 if (right()->IsConstant()) return false; | 3694 if (right()->IsConstant()) return false; |
3668 | 3695 |
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3902 base_ = index(); | 3929 base_ = index(); |
3903 offset_ = 0; | 3930 offset_ = 0; |
3904 scale_ = 0; | 3931 scale_ = 0; |
3905 return false; | 3932 return false; |
3906 } | 3933 } |
3907 } | 3934 } |
3908 | 3935 |
3909 virtual Representation RequiredInputRepresentation(int arg_index) { | 3936 virtual Representation RequiredInputRepresentation(int arg_index) { |
3910 return representation(); | 3937 return representation(); |
3911 } | 3938 } |
3912 virtual bool IsDeletable() const { | |
3913 return skip_check() && !FLAG_debug_code; | |
3914 } | |
3915 | 3939 |
3916 virtual bool IsRelationTrueInternal(NumericRelation relation, | 3940 virtual bool IsRelationTrueInternal(NumericRelation relation, |
3917 HValue* related_value, | 3941 HValue* related_value, |
3918 int offset = 0, | 3942 int offset = 0, |
3919 int scale = 0); | 3943 int scale = 0); |
3920 | 3944 |
3921 virtual void PrintDataTo(StringStream* stream); | 3945 virtual void PrintDataTo(StringStream* stream); |
3922 virtual void InferRepresentation(HInferRepresentationPhase* h_infer); | 3946 virtual void InferRepresentation(HInferRepresentationPhase* h_infer); |
3923 | 3947 |
3924 HValue* index() { return OperandAt(0); } | 3948 HValue* index() { return OperandAt(0); } |
(...skipping 16 matching lines...) Expand all Loading... | |
3941 } | 3965 } |
3942 | 3966 |
3943 virtual bool DataEquals(HValue* other) { return true; } | 3967 virtual bool DataEquals(HValue* other) { return true; } |
3944 virtual void TryGuaranteeRangeChanging(RangeEvaluationContext* context); | 3968 virtual void TryGuaranteeRangeChanging(RangeEvaluationContext* context); |
3945 bool skip_check_; | 3969 bool skip_check_; |
3946 HValue* base_; | 3970 HValue* base_; |
3947 int offset_; | 3971 int offset_; |
3948 int scale_; | 3972 int scale_; |
3949 RangeGuaranteeDirection responsibility_direction_; | 3973 RangeGuaranteeDirection responsibility_direction_; |
3950 bool allow_equality_; | 3974 bool allow_equality_; |
3975 | |
3976 private: | |
3977 virtual bool IsDeletable() const { | |
3978 return skip_check() && !FLAG_debug_code; | |
3979 } | |
3951 }; | 3980 }; |
3952 | 3981 |
3953 | 3982 |
3954 class HBoundsCheckBaseIndexInformation: public HTemplateInstruction<2> { | 3983 class HBoundsCheckBaseIndexInformation: public HTemplateInstruction<2> { |
3955 public: | 3984 public: |
3956 explicit HBoundsCheckBaseIndexInformation(HBoundsCheck* check) { | 3985 explicit HBoundsCheckBaseIndexInformation(HBoundsCheck* check) { |
3957 DecompositionResult decomposition; | 3986 DecompositionResult decomposition; |
3958 if (check->index()->TryDecompose(&decomposition)) { | 3987 if (check->index()->TryDecompose(&decomposition)) { |
3959 SetOperandAt(0, decomposition.base()); | 3988 SetOperandAt(0, decomposition.base()); |
3960 SetOperandAt(1, check); | 3989 SetOperandAt(1, check); |
(...skipping 2481 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6442 | 6471 |
6443 private: | 6472 private: |
6444 HStringAdd(HValue* context, HValue* left, HValue* right, StringAddFlags flags) | 6473 HStringAdd(HValue* context, HValue* left, HValue* right, StringAddFlags flags) |
6445 : HBinaryOperation(context, left, right), flags_(flags) { | 6474 : HBinaryOperation(context, left, right), flags_(flags) { |
6446 set_representation(Representation::Tagged()); | 6475 set_representation(Representation::Tagged()); |
6447 SetFlag(kUseGVN); | 6476 SetFlag(kUseGVN); |
6448 SetGVNFlag(kDependsOnMaps); | 6477 SetGVNFlag(kDependsOnMaps); |
6449 SetGVNFlag(kChangesNewSpacePromotion); | 6478 SetGVNFlag(kChangesNewSpacePromotion); |
6450 } | 6479 } |
6451 | 6480 |
6452 // TODO(svenpanne) Might be safe, but leave it out until we know for sure. | 6481 // No side-effects except possible allocation. |
6453 // virtual bool IsDeletable() const { return true; } | 6482 // NOTE: this instruction _does not_ call ToString() on its inputs. |
6483 virtual bool IsDeletable() const { return true; } | |
6454 | 6484 |
6455 const StringAddFlags flags_; | 6485 const StringAddFlags flags_; |
6456 }; | 6486 }; |
6457 | 6487 |
6458 | 6488 |
6459 class HStringCharCodeAt: public HTemplateInstruction<3> { | 6489 class HStringCharCodeAt: public HTemplateInstruction<3> { |
6460 public: | 6490 public: |
6461 HStringCharCodeAt(HValue* context, HValue* string, HValue* index) { | 6491 HStringCharCodeAt(HValue* context, HValue* string, HValue* index) { |
6462 SetOperandAt(0, context); | 6492 SetOperandAt(0, context); |
6463 SetOperandAt(1, string); | 6493 SetOperandAt(1, string); |
6464 SetOperandAt(2, index); | 6494 SetOperandAt(2, index); |
6465 set_representation(Representation::Integer32()); | 6495 set_representation(Representation::Integer32()); |
6466 SetFlag(kUseGVN); | 6496 SetFlag(kUseGVN); |
6467 SetGVNFlag(kDependsOnMaps); | 6497 SetGVNFlag(kDependsOnMaps); |
6468 SetGVNFlag(kChangesNewSpacePromotion); | 6498 SetGVNFlag(kChangesNewSpacePromotion); |
6469 } | 6499 } |
6470 | 6500 |
6471 virtual Representation RequiredInputRepresentation(int index) { | 6501 virtual Representation RequiredInputRepresentation(int index) { |
6472 // The index is supposed to be Integer32. | 6502 // The index is supposed to be Integer32. |
6473 return index == 2 | 6503 return index == 2 |
6474 ? Representation::Integer32() | 6504 ? Representation::Integer32() |
6475 : Representation::Tagged(); | 6505 : Representation::Tagged(); |
6476 } | 6506 } |
6477 | 6507 |
6478 HValue* context() { return OperandAt(0); } | 6508 HValue* context() const { return OperandAt(0); } |
6479 HValue* string() { return OperandAt(1); } | 6509 HValue* string() const { return OperandAt(1); } |
6480 HValue* index() { return OperandAt(2); } | 6510 HValue* index() const { return OperandAt(2); } |
6481 | 6511 |
6482 DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt) | 6512 DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt) |
6483 | 6513 |
6484 protected: | 6514 protected: |
6485 virtual bool DataEquals(HValue* other) { return true; } | 6515 virtual bool DataEquals(HValue* other) { return true; } |
6486 | 6516 |
6487 virtual Range* InferRange(Zone* zone) { | 6517 virtual Range* InferRange(Zone* zone) { |
6488 return new(zone) Range(0, String::kMaxUtf16CodeUnit); | 6518 return new(zone) Range(0, String::kMaxUtf16CodeUnit); |
6489 } | 6519 } |
6490 | 6520 |
6491 // TODO(svenpanne) Might be safe, but leave it out until we know for sure. | 6521 private: |
6492 // private: | 6522 // No side effects: runtime function assumes string + number inputs. |
6493 // virtual bool IsDeletable() const { return true; } | 6523 virtual bool IsDeletable() const { return true; } |
6494 }; | 6524 }; |
6495 | 6525 |
6496 | 6526 |
6497 class HStringCharFromCode: public HTemplateInstruction<2> { | 6527 class HStringCharFromCode: public HTemplateInstruction<2> { |
6498 public: | 6528 public: |
6499 static HInstruction* New(Zone* zone, | 6529 static HInstruction* New(Zone* zone, |
6500 HValue* context, | 6530 HValue* context, |
6501 HValue* char_code); | 6531 HValue* char_code); |
6502 | 6532 |
6503 virtual Representation RequiredInputRepresentation(int index) { | 6533 virtual Representation RequiredInputRepresentation(int index) { |
6504 return index == 0 | 6534 return index == 0 |
6505 ? Representation::Tagged() | 6535 ? Representation::Tagged() |
6506 : Representation::Integer32(); | 6536 : Representation::Integer32(); |
6507 } | 6537 } |
6508 virtual HType CalculateInferredType(); | 6538 virtual HType CalculateInferredType() { return HType::String(); } |
6509 | 6539 |
6510 HValue* context() { return OperandAt(0); } | 6540 HValue* context() const { return OperandAt(0); } |
6511 HValue* value() { return OperandAt(1); } | 6541 HValue* value() const { return OperandAt(1); } |
6512 | 6542 |
6513 virtual bool DataEquals(HValue* other) { return true; } | 6543 virtual bool DataEquals(HValue* other) { return true; } |
6514 | 6544 |
6515 DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode) | 6545 DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode) |
6516 | 6546 |
6517 private: | 6547 private: |
6518 HStringCharFromCode(HValue* context, HValue* char_code) { | 6548 HStringCharFromCode(HValue* context, HValue* char_code) { |
6519 SetOperandAt(0, context); | 6549 SetOperandAt(0, context); |
6520 SetOperandAt(1, char_code); | 6550 SetOperandAt(1, char_code); |
6521 set_representation(Representation::Tagged()); | 6551 set_representation(Representation::Tagged()); |
6522 SetFlag(kUseGVN); | 6552 SetFlag(kUseGVN); |
6523 SetGVNFlag(kChangesNewSpacePromotion); | 6553 SetGVNFlag(kChangesNewSpacePromotion); |
6524 } | 6554 } |
6525 | 6555 |
6526 // TODO(svenpanne) Might be safe, but leave it out until we know for sure. | 6556 virtual bool IsDeletable() const { |
6527 // virtual bool IsDeletable() const { return true; } | 6557 return !value()->ToNumberCanBeObserved(); |
6558 } | |
6528 }; | 6559 }; |
6529 | 6560 |
6530 | 6561 |
6531 class HStringLength: public HUnaryOperation { | 6562 class HStringLength: public HUnaryOperation { |
6532 public: | 6563 public: |
6533 static HInstruction* New(Zone* zone, HValue* string); | 6564 static HInstruction* New(Zone* zone, HValue* string); |
6534 | 6565 |
6535 virtual Representation RequiredInputRepresentation(int index) { | 6566 virtual Representation RequiredInputRepresentation(int index) { |
6536 return Representation::Tagged(); | 6567 return Representation::Tagged(); |
6537 } | 6568 } |
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6926 virtual bool IsDeletable() const { return true; } | 6957 virtual bool IsDeletable() const { return true; } |
6927 }; | 6958 }; |
6928 | 6959 |
6929 | 6960 |
6930 #undef DECLARE_INSTRUCTION | 6961 #undef DECLARE_INSTRUCTION |
6931 #undef DECLARE_CONCRETE_INSTRUCTION | 6962 #undef DECLARE_CONCRETE_INSTRUCTION |
6932 | 6963 |
6933 } } // namespace v8::internal | 6964 } } // namespace v8::internal |
6934 | 6965 |
6935 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ | 6966 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ |
OLD | NEW |