Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(264)

Side by Side Diff: src/hydrogen-instructions.h

Issue 20241005: Fix IsDeletable() for HStringAdd, HStringCharCodeAt, HStringCharFromCode. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Add test cases and simplify conditions for removal of checks. Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
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_
OLDNEW
« no previous file with comments | « no previous file | src/hydrogen-instructions.cc » ('j') | test/mjsunit/compiler/dead-string-add-warm.js » ('J')

Powered by Google App Engine
This is Rietveld 408576698