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 5183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5194 virtual void PrintDataTo(StringStream* stream); | 5194 virtual void PrintDataTo(StringStream* stream); |
5195 | 5195 |
5196 DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot) | 5196 DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot) |
5197 | 5197 |
5198 private: | 5198 private: |
5199 int slot_index_; | 5199 int slot_index_; |
5200 Mode mode_; | 5200 Mode mode_; |
5201 }; | 5201 }; |
5202 | 5202 |
5203 | 5203 |
5204 // Represents an access to a portion of an object, such as the map pointer, | |
5205 // array elements pointer, etc, but not accesses to array elements themselves. | |
5206 class HObjectAccess { | |
5207 public: | |
5208 inline bool IsInobject() const { | |
5209 return portion_ != kBackingStore; | |
5210 } | |
5211 | |
5212 inline int offset() const { | |
5213 return offset_; | |
5214 } | |
5215 | |
5216 inline Handle<String> name() const { | |
5217 return name_; | |
5218 } | |
5219 | |
5220 static HObjectAccess ForHeapNumberValue() { | |
5221 return HObjectAccess(kInobject, HeapNumber::kValueOffset); | |
5222 } | |
5223 | |
5224 static HObjectAccess ForElementsPointer() { | |
5225 return HObjectAccess(kElementsPointer, JSObject::kElementsOffset); | |
5226 } | |
5227 | |
5228 static HObjectAccess ForArrayLength() { | |
5229 return HObjectAccess(kArrayLengths, JSArray::kLengthOffset); | |
5230 } | |
5231 | |
5232 static HObjectAccess ForFixedArrayLength() { | |
5233 return HObjectAccess(kArrayLengths, FixedArray::kLengthOffset); | |
5234 } | |
5235 | |
5236 static HObjectAccess ForPropertiesPointer() { | |
5237 return HObjectAccess(kInobject, JSObject::kPropertiesOffset); | |
5238 } | |
5239 | |
5240 static HObjectAccess ForMap() { | |
5241 return HObjectAccess(kMaps, JSObject::kMapOffset); | |
5242 } | |
5243 | |
5244 static HObjectAccess ForAllocationSitePayload() { | |
5245 return HObjectAccess(kInobject, AllocationSiteInfo::kPayloadOffset); | |
5246 } | |
5247 | |
5248 // Create an access to an offset in a fixed array header. | |
5249 static HObjectAccess ForFixedArrayHeader(int offset); | |
5250 | |
5251 // Create an access to an in-object property in a JSObject. | |
5252 static HObjectAccess ForJSObjectOffset(int offset); | |
5253 | |
5254 // Create an access to an in-object property in a JSArray. | |
5255 static HObjectAccess ForJSArrayOffset(int offset); | |
5256 | |
5257 // Create an access to the backing store of an object. | |
5258 static HObjectAccess ForBackingStoreOffset(int offset); | |
5259 | |
5260 // Create an access to a resolved field (in-object or backing store). | |
5261 static HObjectAccess ForField(Handle<Map> map, | |
5262 LookupResult *lookup, Handle<String> name = Handle<String>::null()); | |
5263 | |
5264 void PrintTo(StringStream* stream); | |
5265 | |
5266 protected: | |
5267 void SetGVNFlags(HValue *instr, bool is_store); | |
5268 | |
5269 private: | |
5270 // internal use only; different parts of an object or array | |
5271 enum Portion { | |
5272 kMaps, // map of an object | |
5273 kArrayLengths, // the length of an array | |
5274 kElementsPointer, // elements pointer | |
5275 kBackingStore, // some field in the backing store | |
5276 kInobject // some other in-object field | |
5277 }; | |
5278 | |
5279 HObjectAccess(Portion portion, int offset, | |
5280 Handle<String> name = Handle<String>::null()) | |
5281 : portion_(portion), offset_(offset), name_(name) { | |
5282 ASSERT(offset_ == offset); // offset must fit | |
5283 ASSERT(portion_ == portion); // portion must fit | |
5284 } | |
5285 | |
5286 unsigned portion_ : 3; | |
danno
2013/05/14 14:41:58
Can't you just make this "Portion" instead of unsi
| |
5287 unsigned offset_ : 29; | |
5288 Handle<String> name_; | |
5289 | |
5290 friend class HLoadNamedField; | |
5291 friend class HStoreNamedField; | |
5292 }; | |
5293 | |
5294 | |
5204 class HLoadNamedField: public HTemplateInstruction<2> { | 5295 class HLoadNamedField: public HTemplateInstruction<2> { |
5205 public: | 5296 public: |
5206 HLoadNamedField(HValue* object, bool is_in_object, | 5297 HLoadNamedField(HValue* object, |
5207 Representation field_representation, | 5298 HObjectAccess access, |
5208 int offset, HValue* typecheck = NULL) | 5299 HValue* typecheck = NULL, |
5209 : is_in_object_(is_in_object), | 5300 Representation field_representation |
5210 field_representation_(field_representation), | 5301 = Representation::Tagged()) |
5211 offset_(offset) { | 5302 : access_(access), |
5303 field_representation_(field_representation) { | |
5212 ASSERT(object != NULL); | 5304 ASSERT(object != NULL); |
5213 SetOperandAt(0, object); | 5305 SetOperandAt(0, object); |
5214 SetOperandAt(1, typecheck != NULL ? typecheck : object); | 5306 SetOperandAt(1, typecheck != NULL ? typecheck : object); |
5215 | 5307 |
5216 if (FLAG_track_fields && field_representation.IsSmi()) { | 5308 if (FLAG_track_fields && field_representation.IsSmi()) { |
5217 set_type(HType::Smi()); | 5309 set_type(HType::Smi()); |
5218 set_representation(Representation::Tagged()); | 5310 set_representation(Representation::Tagged()); |
5219 } else if (FLAG_track_double_fields && field_representation.IsDouble()) { | 5311 } else if (FLAG_track_double_fields && field_representation.IsDouble()) { |
5220 set_representation(field_representation); | 5312 set_representation(field_representation); |
5313 SetGVNFlag(kDependsOnDoubleFields); | |
danno
2013/05/14 14:41:58
Yikes! Don't you want to only set this inside SetG
| |
5221 } else { | 5314 } else { |
5222 set_representation(Representation::Tagged()); | 5315 set_representation(Representation::Tagged()); |
5223 } | 5316 } |
5224 SetFlag(kUseGVN); | 5317 access.SetGVNFlags(this, false); |
5225 if (FLAG_track_double_fields && representation().IsDouble()) { | |
5226 ASSERT(is_in_object); | |
5227 ASSERT(offset == HeapNumber::kValueOffset); | |
5228 SetGVNFlag(kDependsOnDoubleFields); | |
5229 } else if (is_in_object) { | |
5230 SetGVNFlag(kDependsOnInobjectFields); | |
5231 SetGVNFlag(kDependsOnMaps); | |
5232 } else { | |
5233 SetGVNFlag(kDependsOnBackingStoreFields); | |
5234 SetGVNFlag(kDependsOnMaps); | |
5235 } | |
5236 } | |
5237 | |
5238 static HLoadNamedField* NewArrayLength(Zone* zone, HValue* object, | |
5239 HValue* typecheck, | |
5240 HType type = HType::Tagged()) { | |
5241 Representation representation = | |
5242 type.IsSmi() ? Representation::Smi() : Representation::Tagged(); | |
5243 HLoadNamedField* result = new(zone) HLoadNamedField( | |
5244 object, true, representation, JSArray::kLengthOffset, typecheck); | |
5245 result->set_type(type); | |
5246 result->SetGVNFlag(kDependsOnArrayLengths); | |
5247 result->ClearGVNFlag(kDependsOnInobjectFields); | |
5248 return result; | |
5249 } | 5318 } |
5250 | 5319 |
5251 HValue* object() { return OperandAt(0); } | 5320 HValue* object() { return OperandAt(0); } |
5252 HValue* typecheck() { | 5321 HValue* typecheck() { |
5253 ASSERT(HasTypeCheck()); | 5322 ASSERT(HasTypeCheck()); |
5254 return OperandAt(1); | 5323 return OperandAt(1); |
5255 } | 5324 } |
5256 | 5325 |
5257 bool HasTypeCheck() const { return OperandAt(0) != OperandAt(1); } | 5326 bool HasTypeCheck() const { return OperandAt(0) != OperandAt(1); } |
5258 bool is_in_object() const { return is_in_object_; } | 5327 HObjectAccess access() const { return access_; } |
5328 bool is_in_object() const { return access_.IsInobject(); } | |
5259 Representation field_representation() const { return representation_; } | 5329 Representation field_representation() const { return representation_; } |
5260 int offset() const { return offset_; } | 5330 int offset() const { return access_.offset(); } |
5261 | 5331 |
5262 virtual Representation RequiredInputRepresentation(int index) { | 5332 virtual Representation RequiredInputRepresentation(int index) { |
5263 return Representation::Tagged(); | 5333 return Representation::Tagged(); |
5264 } | 5334 } |
5265 virtual void PrintDataTo(StringStream* stream); | 5335 virtual void PrintDataTo(StringStream* stream); |
5266 | 5336 |
5267 DECLARE_CONCRETE_INSTRUCTION(LoadNamedField) | 5337 DECLARE_CONCRETE_INSTRUCTION(LoadNamedField) |
5268 | 5338 |
5269 protected: | 5339 protected: |
5270 virtual bool DataEquals(HValue* other) { | 5340 virtual bool DataEquals(HValue* other) { |
5271 HLoadNamedField* b = HLoadNamedField::cast(other); | 5341 HLoadNamedField* b = HLoadNamedField::cast(other); |
5272 return is_in_object_ == b->is_in_object_ && offset_ == b->offset_; | 5342 return is_in_object() == b->is_in_object() && offset() == b->offset(); |
5273 } | 5343 } |
5274 | 5344 |
5275 private: | 5345 private: |
5276 virtual bool IsDeletable() const { return true; } | 5346 virtual bool IsDeletable() const { return true; } |
5277 | 5347 |
5278 bool is_in_object_; | 5348 HObjectAccess access_; |
5279 Representation field_representation_; | 5349 Representation field_representation_; |
5280 int offset_; | |
5281 }; | 5350 }; |
5282 | 5351 |
5283 | 5352 |
5284 class HLoadNamedFieldPolymorphic: public HTemplateInstruction<2> { | 5353 class HLoadNamedFieldPolymorphic: public HTemplateInstruction<2> { |
5285 public: | 5354 public: |
5286 HLoadNamedFieldPolymorphic(HValue* context, | 5355 HLoadNamedFieldPolymorphic(HValue* context, |
5287 HValue* object, | 5356 HValue* object, |
5288 SmallMapList* types, | 5357 SmallMapList* types, |
5289 Handle<String> name, | 5358 Handle<String> name, |
5290 Zone* zone); | 5359 Zone* zone); |
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5564 | 5633 |
5565 virtual HValue* Canonicalize(); | 5634 virtual HValue* Canonicalize(); |
5566 | 5635 |
5567 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric) | 5636 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric) |
5568 }; | 5637 }; |
5569 | 5638 |
5570 | 5639 |
5571 class HStoreNamedField: public HTemplateInstruction<2> { | 5640 class HStoreNamedField: public HTemplateInstruction<2> { |
5572 public: | 5641 public: |
5573 HStoreNamedField(HValue* obj, | 5642 HStoreNamedField(HValue* obj, |
5574 Handle<Name> name, | 5643 HObjectAccess access, |
5575 HValue* val, | 5644 HValue* val, |
5576 bool in_object, | 5645 Representation field_representation |
5577 Representation field_representation, | 5646 = Representation::Tagged()) |
5578 int offset) | 5647 : access_(access), |
5579 : name_(name), | |
5580 is_in_object_(in_object), | |
5581 field_representation_(field_representation), | 5648 field_representation_(field_representation), |
5582 offset_(offset), | |
5583 transition_unique_id_(), | 5649 transition_unique_id_(), |
5584 new_space_dominator_(NULL) { | 5650 new_space_dominator_(NULL) { |
5585 SetOperandAt(0, obj); | 5651 SetOperandAt(0, obj); |
5586 SetOperandAt(1, val); | 5652 SetOperandAt(1, val); |
5587 SetFlag(kTrackSideEffectDominators); | 5653 access.SetGVNFlags(this, true); |
5588 if (FLAG_track_double_fields && field_representation.IsDouble()) { | 5654 if (FLAG_track_double_fields && field_representation.IsDouble()) { |
5589 SetGVNFlag(kChangesDoubleFields); | 5655 SetGVNFlag(kChangesDoubleFields); |
5590 } else if (is_in_object_) { | |
5591 SetGVNFlag(kChangesInobjectFields); | |
5592 SetGVNFlag(kDependsOnNewSpacePromotion); | |
5593 } else { | |
5594 SetGVNFlag(kChangesBackingStoreFields); | |
5595 SetGVNFlag(kDependsOnNewSpacePromotion); | |
5596 } | 5656 } |
5597 } | 5657 } |
5598 | 5658 |
5599 DECLARE_CONCRETE_INSTRUCTION(StoreNamedField) | 5659 DECLARE_CONCRETE_INSTRUCTION(StoreNamedField) |
5600 | 5660 |
5601 virtual Representation RequiredInputRepresentation(int index) { | 5661 virtual Representation RequiredInputRepresentation(int index) { |
5602 if (FLAG_track_double_fields && | 5662 if (FLAG_track_double_fields && |
5603 index == 1 && field_representation_.IsDouble()) { | 5663 index == 1 && field_representation_.IsDouble()) { |
5604 return field_representation_; | 5664 return field_representation_; |
5605 } else if (FLAG_track_fields && | 5665 } else if (FLAG_track_fields && |
5606 index == 1 && field_representation_.IsSmi()) { | 5666 index == 1 && field_representation_.IsSmi()) { |
5607 return Representation::Integer32(); | 5667 return Representation::Integer32(); |
5608 } | 5668 } |
5609 return Representation::Tagged(); | 5669 return Representation::Tagged(); |
5610 } | 5670 } |
5611 virtual void SetSideEffectDominator(GVNFlag side_effect, HValue* dominator) { | 5671 virtual void SetSideEffectDominator(GVNFlag side_effect, HValue* dominator) { |
5612 ASSERT(side_effect == kChangesNewSpacePromotion); | 5672 ASSERT(side_effect == kChangesNewSpacePromotion); |
5613 new_space_dominator_ = dominator; | 5673 new_space_dominator_ = dominator; |
5614 } | 5674 } |
5615 virtual void PrintDataTo(StringStream* stream); | 5675 virtual void PrintDataTo(StringStream* stream); |
5616 | 5676 |
5617 HValue* object() { return OperandAt(0); } | 5677 HValue* object() { return OperandAt(0); } |
5618 HValue* value() { return OperandAt(1); } | 5678 HValue* value() { return OperandAt(1); } |
5619 | 5679 |
5620 Handle<Name> name() const { return name_; } | 5680 HObjectAccess access() const { return access_; } |
5621 bool is_in_object() const { return is_in_object_; } | 5681 Handle<String> name() const { return access_.name(); } |
5622 int offset() const { return offset_; } | 5682 bool is_in_object() const { return access_.IsInobject(); } |
5683 int offset() const { return access_.offset(); } | |
5623 Handle<Map> transition() const { return transition_; } | 5684 Handle<Map> transition() const { return transition_; } |
5624 UniqueValueId transition_unique_id() const { return transition_unique_id_; } | 5685 UniqueValueId transition_unique_id() const { return transition_unique_id_; } |
5625 void set_transition(Handle<Map> map) { transition_ = map; } | 5686 void set_transition(Handle<Map> map) { transition_ = map; } |
5626 HValue* new_space_dominator() const { return new_space_dominator_; } | 5687 HValue* new_space_dominator() const { return new_space_dominator_; } |
5627 | 5688 |
5628 bool NeedsWriteBarrier() { | 5689 bool NeedsWriteBarrier() { |
5629 ASSERT(!(FLAG_track_double_fields && field_representation_.IsDouble()) || | 5690 ASSERT(!(FLAG_track_double_fields && field_representation_.IsDouble()) || |
5630 transition_.is_null()); | 5691 transition_.is_null()); |
5631 return (!FLAG_track_fields || !field_representation_.IsSmi()) && | 5692 return (!FLAG_track_fields || !field_representation_.IsSmi()) && |
5632 // If there is a transition, a new storage object needs to be allocated. | 5693 // If there is a transition, a new storage object needs to be allocated. |
5633 !(FLAG_track_double_fields && field_representation_.IsDouble()) && | 5694 !(FLAG_track_double_fields && field_representation_.IsDouble()) && |
5634 StoringValueNeedsWriteBarrier(value()) && | 5695 StoringValueNeedsWriteBarrier(value()) && |
5635 ReceiverObjectNeedsWriteBarrier(object(), new_space_dominator()); | 5696 ReceiverObjectNeedsWriteBarrier(object(), new_space_dominator()); |
5636 } | 5697 } |
5637 | 5698 |
5638 bool NeedsWriteBarrierForMap() { | 5699 bool NeedsWriteBarrierForMap() { |
5639 return ReceiverObjectNeedsWriteBarrier(object(), new_space_dominator()); | 5700 return ReceiverObjectNeedsWriteBarrier(object(), new_space_dominator()); |
5640 } | 5701 } |
5641 | 5702 |
5642 virtual void FinalizeUniqueValueId() { | 5703 virtual void FinalizeUniqueValueId() { |
5643 transition_unique_id_ = UniqueValueId(transition_); | 5704 transition_unique_id_ = UniqueValueId(transition_); |
5644 } | 5705 } |
5645 | 5706 |
5646 Representation field_representation() const { | 5707 Representation field_representation() const { |
5647 return field_representation_; | 5708 return field_representation_; |
5648 } | 5709 } |
5649 | 5710 |
5650 private: | 5711 private: |
5651 Handle<Name> name_; | 5712 HObjectAccess access_; |
5652 bool is_in_object_; | |
5653 Representation field_representation_; | 5713 Representation field_representation_; |
5654 int offset_; | |
5655 Handle<Map> transition_; | 5714 Handle<Map> transition_; |
5656 UniqueValueId transition_unique_id_; | 5715 UniqueValueId transition_unique_id_; |
5657 HValue* new_space_dominator_; | 5716 HValue* new_space_dominator_; |
5658 }; | 5717 }; |
5659 | 5718 |
5660 | 5719 |
5661 class HStoreNamedGeneric: public HTemplateInstruction<3> { | 5720 class HStoreNamedGeneric: public HTemplateInstruction<3> { |
5662 public: | 5721 public: |
5663 HStoreNamedGeneric(HValue* context, | 5722 HStoreNamedGeneric(HValue* context, |
5664 HValue* object, | 5723 HValue* object, |
(...skipping 797 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6462 virtual bool IsDeletable() const { return true; } | 6521 virtual bool IsDeletable() const { return true; } |
6463 }; | 6522 }; |
6464 | 6523 |
6465 | 6524 |
6466 #undef DECLARE_INSTRUCTION | 6525 #undef DECLARE_INSTRUCTION |
6467 #undef DECLARE_CONCRETE_INSTRUCTION | 6526 #undef DECLARE_CONCRETE_INSTRUCTION |
6468 | 6527 |
6469 } } // namespace v8::internal | 6528 } } // namespace v8::internal |
6470 | 6529 |
6471 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ | 6530 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ |
OLD | NEW |