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 5220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5231 virtual void PrintDataTo(StringStream* stream); | 5231 virtual void PrintDataTo(StringStream* stream); |
5232 | 5232 |
5233 DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot) | 5233 DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot) |
5234 | 5234 |
5235 private: | 5235 private: |
5236 int slot_index_; | 5236 int slot_index_; |
5237 Mode mode_; | 5237 Mode mode_; |
5238 }; | 5238 }; |
5239 | 5239 |
5240 | 5240 |
5241 // Represents an access (load or store) to a portion of an object for GVN. | |
5242 // TODO(titzer): only represents non-array-element loads and stores for now | |
5243 class ObjectAccess { | |
5244 public: | |
5245 enum Portion { | |
5246 kElementsKind, | |
danno
2013/04/26 09:39:38
The seems redundant to me. It seems like this is w
titzer
2013/04/30 15:56:47
As discussed in person, I think we can make this w
| |
5247 kArrayLengths, | |
5248 kInobject, | |
5249 kBackingStore, | |
5250 kElementsPointer, | |
5251 kMaps | |
5252 }; | |
5253 | |
5254 ObjectAccess(Portion portion, int offset, bool may_allocate, | |
5255 Handle<String> name = Handle<String>::null()) | |
5256 : portion_(portion), offset_(offset), may_allocate_(may_allocate) { } | |
5257 | |
5258 void SetGVNFlags(HValue *instr, bool is_store) { | |
danno
2013/04/26 09:39:38
Make this protected and add HLoadNamedFiled and HS
titzer
2013/04/30 15:56:47
Done.
| |
5259 // set the appropriate GVN flags for a given load or store instruction | |
5260 if (!is_store) { | |
5261 instr->SetFlag(HValue::kUseGVN); // try to GVN loads | |
5262 instr->SetGVNFlag(kDependsOnMaps); // but don't hoist above map changes | |
5263 } | |
5264 | |
5265 // if this instruction might trigger an allocation | |
5266 if (may_allocate_) instr->SetGVNFlag(kChangesNewSpacePromotion); | |
danno
2013/04/26 09:39:38
When does this actually happen? We should try to g
titzer
2013/04/30 15:56:47
Done.
| |
5267 | |
5268 switch (portion_) { | |
5269 case kElementsKind: | |
5270 instr->SetGVNFlag( | |
5271 is_store ? kChangesElementsKind : kDependsOnElementsKind); | |
danno
2013/04/26 09:39:38
Don't know if it makes the code cleaner, but maybe
titzer
2013/04/30 15:56:47
That method takes a GVNFlagSet and does a shift. I
| |
5272 break; | |
5273 case kArrayLengths: | |
5274 instr->SetGVNFlag( | |
5275 is_store ? kChangesArrayLengths : kDependsOnArrayLengths); | |
5276 break; | |
5277 case kInobject: | |
5278 instr->SetGVNFlag( | |
5279 is_store ? kChangesInobjectFields : kDependsOnInobjectFields); | |
5280 break; | |
5281 case kBackingStore: | |
5282 instr->SetGVNFlag( | |
5283 is_store ? kChangesBackingStoreFields : kDependsOnBackingStoreFields); | |
5284 break; | |
5285 case kElementsPointer: | |
5286 instr->SetGVNFlag( | |
5287 is_store ? kChangesElementsPointer : kDependsOnElementsPointer); | |
5288 break; | |
5289 case kMaps: | |
5290 instr->SetGVNFlag( | |
5291 is_store ? kChangesMaps : kDependsOnMaps); | |
5292 break; | |
5293 } | |
danno
2013/04/26 09:39:38
This guy really belongs in the .cc file.
titzer
2013/04/30 15:56:47
Done.
| |
5294 } | |
5295 | |
5296 inline bool IsInobject() { | |
5297 return portion_ != kBackingStore; | |
5298 } | |
5299 | |
5300 inline int offset() { | |
5301 return offset_; | |
5302 } | |
5303 | |
5304 inline Handle<String> name() { | |
danno
2013/04/26 09:39:38
This can be calculated by looking in the map's fie
titzer
2013/04/30 15:56:47
I agree with that approach in the long run. We can
| |
5305 return name_; | |
5306 } | |
5307 | |
5308 private: | |
5309 Portion portion_; | |
5310 int offset_; | |
5311 bool may_allocate_; | |
5312 Handle<String> name_; | |
danno
2013/04/26 09:39:38
You don't need to store this it can be looked-up i
danno
2013/05/02 14:16:47
You didn't address this comment. Why not?
On 2013
| |
5313 }; | |
5314 | |
5315 | |
5241 class HLoadNamedField: public HTemplateInstruction<2> { | 5316 class HLoadNamedField: public HTemplateInstruction<2> { |
5242 public: | 5317 public: |
5243 HLoadNamedField(HValue* object, bool is_in_object, int offset, | 5318 HLoadNamedField(HValue* object, ObjectAccess access, HValue* typecheck = NULL) |
danno
2013/04/26 09:39:38
Unless the objects is the size of intptr_t, then w
titzer
2013/04/30 15:56:47
Done.
| |
5244 HValue* typecheck = NULL) | 5319 : is_in_object_(access.IsInobject()), |
5245 : is_in_object_(is_in_object), | 5320 offset_(access.offset()) { |
5246 offset_(offset) { | |
5247 ASSERT(object != NULL); | 5321 ASSERT(object != NULL); |
5248 SetOperandAt(0, object); | 5322 SetOperandAt(0, object); |
5249 SetOperandAt(1, typecheck != NULL ? typecheck : object); | 5323 SetOperandAt(1, typecheck != NULL ? typecheck : object); |
5250 | 5324 |
5251 set_representation(Representation::Tagged()); | 5325 set_representation(Representation::Tagged()); |
5252 SetFlag(kUseGVN); | 5326 access.SetGVNFlags(this, false); |
5253 SetGVNFlag(kDependsOnMaps); | |
5254 if (is_in_object) { | |
5255 SetGVNFlag(kDependsOnInobjectFields); | |
5256 } else { | |
5257 SetGVNFlag(kDependsOnBackingStoreFields); | |
5258 } | |
5259 } | |
5260 | |
5261 static HLoadNamedField* NewArrayLength(Zone* zone, HValue* object, | |
5262 HValue* typecheck, | |
5263 HType type = HType::Tagged()) { | |
5264 HLoadNamedField* result = new(zone) HLoadNamedField( | |
5265 object, true, JSArray::kLengthOffset, typecheck); | |
5266 result->set_type(type); | |
5267 result->SetGVNFlag(kDependsOnArrayLengths); | |
5268 result->ClearGVNFlag(kDependsOnInobjectFields); | |
5269 return result; | |
5270 } | 5327 } |
5271 | 5328 |
5272 HValue* object() { return OperandAt(0); } | 5329 HValue* object() { return OperandAt(0); } |
5273 HValue* typecheck() { | 5330 HValue* typecheck() { |
5274 ASSERT(HasTypeCheck()); | 5331 ASSERT(HasTypeCheck()); |
5275 return OperandAt(1); | 5332 return OperandAt(1); |
5276 } | 5333 } |
5277 | 5334 |
5278 bool HasTypeCheck() const { return OperandAt(0) != OperandAt(1); } | 5335 bool HasTypeCheck() const { return OperandAt(0) != OperandAt(1); } |
5279 bool is_in_object() const { return is_in_object_; } | 5336 bool is_in_object() const { return is_in_object_; } |
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5583 | 5640 |
5584 virtual HValue* Canonicalize(); | 5641 virtual HValue* Canonicalize(); |
5585 | 5642 |
5586 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric) | 5643 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric) |
5587 }; | 5644 }; |
5588 | 5645 |
5589 | 5646 |
5590 class HStoreNamedField: public HTemplateInstruction<2> { | 5647 class HStoreNamedField: public HTemplateInstruction<2> { |
5591 public: | 5648 public: |
5592 HStoreNamedField(HValue* obj, | 5649 HStoreNamedField(HValue* obj, |
5593 Handle<String> name, | 5650 ObjectAccess access, |
5594 HValue* val, | 5651 HValue* val) |
5595 bool in_object, | 5652 : name_(access.name()), |
5596 int offset) | 5653 is_in_object_(access.IsInobject()), |
5597 : name_(name), | 5654 offset_(access.offset()), |
5598 is_in_object_(in_object), | |
5599 offset_(offset), | |
5600 transition_unique_id_(), | 5655 transition_unique_id_(), |
5601 new_space_dominator_(NULL) { | 5656 new_space_dominator_(NULL) { |
5602 SetOperandAt(0, obj); | 5657 SetOperandAt(0, obj); |
5603 SetOperandAt(1, val); | 5658 SetOperandAt(1, val); |
5604 SetFlag(kTrackSideEffectDominators); | 5659 SetFlag(kTrackSideEffectDominators); |
5605 SetGVNFlag(kDependsOnNewSpacePromotion); | 5660 access.SetGVNFlags(this, true); |
5606 if (is_in_object_) { | |
5607 SetGVNFlag(kChangesInobjectFields); | |
5608 } else { | |
5609 SetGVNFlag(kChangesBackingStoreFields); | |
5610 } | |
5611 } | 5661 } |
5612 | 5662 |
5613 DECLARE_CONCRETE_INSTRUCTION(StoreNamedField) | 5663 DECLARE_CONCRETE_INSTRUCTION(StoreNamedField) |
5614 | 5664 |
5615 virtual Representation RequiredInputRepresentation(int index) { | 5665 virtual Representation RequiredInputRepresentation(int index) { |
5616 return Representation::Tagged(); | 5666 return Representation::Tagged(); |
5617 } | 5667 } |
5618 virtual void SetSideEffectDominator(GVNFlag side_effect, HValue* dominator) { | 5668 virtual void SetSideEffectDominator(GVNFlag side_effect, HValue* dominator) { |
5619 ASSERT(side_effect == kChangesNewSpacePromotion); | 5669 ASSERT(side_effect == kChangesNewSpacePromotion); |
5620 new_space_dominator_ = dominator; | 5670 new_space_dominator_ = dominator; |
(...skipping 929 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6550 virtual bool IsDeletable() const { return true; } | 6600 virtual bool IsDeletable() const { return true; } |
6551 }; | 6601 }; |
6552 | 6602 |
6553 | 6603 |
6554 #undef DECLARE_INSTRUCTION | 6604 #undef DECLARE_INSTRUCTION |
6555 #undef DECLARE_CONCRETE_INSTRUCTION | 6605 #undef DECLARE_CONCRETE_INSTRUCTION |
6556 | 6606 |
6557 } } // namespace v8::internal | 6607 } } // namespace v8::internal |
6558 | 6608 |
6559 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ | 6609 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ |
OLD | NEW |