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 "v8.h" | 8 #include "v8.h" |
9 | 9 |
10 #include "allocation.h" | 10 #include "allocation.h" |
(...skipping 2729 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2740 const Heap::RootListIndex index_; | 2740 const Heap::RootListIndex index_; |
2741 }; | 2741 }; |
2742 | 2742 |
2743 | 2743 |
2744 class HCheckMaps V8_FINAL : public HTemplateInstruction<2> { | 2744 class HCheckMaps V8_FINAL : public HTemplateInstruction<2> { |
2745 public: | 2745 public: |
2746 static HCheckMaps* New(Zone* zone, HValue* context, HValue* value, | 2746 static HCheckMaps* New(Zone* zone, HValue* context, HValue* value, |
2747 Handle<Map> map, CompilationInfo* info, | 2747 Handle<Map> map, CompilationInfo* info, |
2748 HValue* typecheck = NULL); | 2748 HValue* typecheck = NULL); |
2749 static HCheckMaps* New(Zone* zone, HValue* context, | 2749 static HCheckMaps* New(Zone* zone, HValue* context, |
2750 HValue* value, SmallMapList* maps, | 2750 HValue* value, SmallMapList* map_list, |
2751 HValue* typecheck = NULL) { | 2751 HValue* typecheck = NULL) { |
2752 HCheckMaps* check_map = new(zone) HCheckMaps(value, zone, typecheck); | 2752 UniqueSet<Map>* maps = new(zone) UniqueSet<Map>(map_list->length(), zone); |
2753 for (int i = 0; i < maps->length(); i++) { | 2753 for (int i = 0; i < map_list->length(); ++i) { |
2754 check_map->Add(maps->at(i), zone); | 2754 maps->Add(Unique<Map>::CreateImmovable(map_list->at(i)), zone); |
2755 } | 2755 } |
2756 return check_map; | 2756 return new(zone) HCheckMaps(value, maps, typecheck); |
2757 } | 2757 } |
2758 | 2758 |
2759 bool CanOmitMapChecks() { return omit_; } | 2759 bool CanOmitMapChecks() { return omit_; } |
2760 | 2760 |
2761 virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE { return false; } | 2761 virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE { return false; } |
2762 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE { | 2762 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE { |
2763 return Representation::Tagged(); | 2763 return Representation::Tagged(); |
2764 } | 2764 } |
2765 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE; | 2765 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE; |
2766 | 2766 |
2767 HValue* value() { return OperandAt(0); } | 2767 HValue* value() { return OperandAt(0); } |
2768 HValue* typecheck() { return OperandAt(1); } | 2768 HValue* typecheck() { return OperandAt(1); } |
2769 | 2769 |
2770 Unique<Map> first_map() const { return map_set_.at(0); } | 2770 const UniqueSet<Map>* maps() const { return maps_; } |
2771 const UniqueSet<Map>* map_set() const { return &map_set_; } | 2771 void set_maps(const UniqueSet<Map>* maps) { maps_ = maps; } |
2772 | |
2773 void set_map_set(UniqueSet<Map>* maps, Zone *zone) { | |
2774 map_set_.Clear(); | |
2775 for (int i = 0; i < maps->size(); i++) { | |
2776 map_set_.Add(maps->at(i), zone); | |
2777 } | |
2778 } | |
2779 | 2772 |
2780 bool has_migration_target() const { | 2773 bool has_migration_target() const { |
2781 return has_migration_target_; | 2774 return has_migration_target_; |
2782 } | 2775 } |
2783 | 2776 |
2784 DECLARE_CONCRETE_INSTRUCTION(CheckMaps) | 2777 DECLARE_CONCRETE_INSTRUCTION(CheckMaps) |
2785 | 2778 |
2786 protected: | 2779 protected: |
2787 virtual bool DataEquals(HValue* other) V8_OVERRIDE { | 2780 virtual bool DataEquals(HValue* other) V8_OVERRIDE { |
2788 return this->map_set_.Equals(&HCheckMaps::cast(other)->map_set_); | 2781 return this->maps()->Equals(HCheckMaps::cast(other)->maps()); |
2789 } | 2782 } |
2790 | 2783 |
2791 virtual int RedefinedOperandIndex() { return 0; } | 2784 virtual int RedefinedOperandIndex() { return 0; } |
2792 | 2785 |
2793 private: | 2786 private: |
2794 void Add(Handle<Map> map, Zone* zone) { | 2787 // Clients should use one of the static New* methods above. |
2795 map_set_.Add(Unique<Map>(map), zone); | 2788 HCheckMaps(HValue* value, const UniqueSet<Map>* maps, HValue* typecheck) |
| 2789 : HTemplateInstruction<2>(value->type()), maps_(maps), |
| 2790 omit_(false), has_migration_target_(false) { |
| 2791 ASSERT_NE(0, maps->size()); |
| 2792 SetOperandAt(0, value); |
| 2793 // Use the object value for the dependency if NULL is passed. |
| 2794 SetOperandAt(1, typecheck ? typecheck : value); |
| 2795 set_representation(Representation::Tagged()); |
| 2796 SetFlag(kUseGVN); |
2796 SetDependsOnFlag(kMaps); | 2797 SetDependsOnFlag(kMaps); |
2797 SetDependsOnFlag(kElementsKind); | 2798 SetDependsOnFlag(kElementsKind); |
2798 | 2799 for (int i = 0; i < maps->size(); ++i) { |
2799 if (!has_migration_target_ && map->is_migration_target()) { | 2800 if (maps->at(i).handle()->is_migration_target()) { |
2800 has_migration_target_ = true; | 2801 SetChangesFlag(kNewSpacePromotion); |
2801 SetChangesFlag(kNewSpacePromotion); | 2802 has_migration_target_ = true; |
| 2803 break; |
| 2804 } |
2802 } | 2805 } |
2803 } | 2806 } |
2804 | 2807 |
2805 // Clients should use one of the static New* methods above. | 2808 const UniqueSet<Map>* maps_; |
2806 HCheckMaps(HValue* value, Zone *zone, HValue* typecheck) | 2809 bool omit_ : 1; |
2807 : HTemplateInstruction<2>(value->type()), | 2810 bool has_migration_target_ : 1; |
2808 omit_(false), has_migration_target_(false) { | |
2809 SetOperandAt(0, value); | |
2810 // Use the object value for the dependency if NULL is passed. | |
2811 SetOperandAt(1, typecheck != NULL ? typecheck : value); | |
2812 set_representation(Representation::Tagged()); | |
2813 SetFlag(kUseGVN); | |
2814 } | |
2815 | |
2816 bool omit_; | |
2817 bool has_migration_target_; | |
2818 UniqueSet<Map> map_set_; | |
2819 }; | 2811 }; |
2820 | 2812 |
2821 | 2813 |
2822 class HCheckValue V8_FINAL : public HUnaryOperation { | 2814 class HCheckValue V8_FINAL : public HUnaryOperation { |
2823 public: | 2815 public: |
2824 static HCheckValue* New(Zone* zone, HValue* context, | 2816 static HCheckValue* New(Zone* zone, HValue* context, |
2825 HValue* value, Handle<JSFunction> func) { | 2817 HValue* value, Handle<JSFunction> func) { |
2826 bool in_new_space = zone->isolate()->heap()->InNewSpace(*func); | 2818 bool in_new_space = zone->isolate()->heap()->InNewSpace(*func); |
2827 // NOTE: We create an uninitialized Unique and initialize it later. | 2819 // NOTE: We create an uninitialized Unique and initialize it later. |
2828 // This is because a JSFunction can move due to GC during graph creation. | 2820 // This is because a JSFunction can move due to GC during graph creation. |
(...skipping 2994 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5823 } | 5815 } |
5824 | 5816 |
5825 inline bool IsExternalMemory() const { | 5817 inline bool IsExternalMemory() const { |
5826 return portion() == kExternalMemory; | 5818 return portion() == kExternalMemory; |
5827 } | 5819 } |
5828 | 5820 |
5829 inline bool IsStringLength() const { | 5821 inline bool IsStringLength() const { |
5830 return portion() == kStringLengths; | 5822 return portion() == kStringLengths; |
5831 } | 5823 } |
5832 | 5824 |
| 5825 inline bool IsMap() const { |
| 5826 return portion() == kMaps; |
| 5827 } |
| 5828 |
5833 inline int offset() const { | 5829 inline int offset() const { |
5834 return OffsetField::decode(value_); | 5830 return OffsetField::decode(value_); |
5835 } | 5831 } |
5836 | 5832 |
5837 inline Representation representation() const { | 5833 inline Representation representation() const { |
5838 return Representation::FromKind(RepresentationField::decode(value_)); | 5834 return Representation::FromKind(RepresentationField::decode(value_)); |
5839 } | 5835 } |
5840 | 5836 |
5841 inline Handle<String> name() const { | 5837 inline Handle<String> name() const { |
5842 return name_; | 5838 return name_; |
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6135 friend class SideEffectsTracker; | 6131 friend class SideEffectsTracker; |
6136 | 6132 |
6137 inline Portion portion() const { | 6133 inline Portion portion() const { |
6138 return PortionField::decode(value_); | 6134 return PortionField::decode(value_); |
6139 } | 6135 } |
6140 }; | 6136 }; |
6141 | 6137 |
6142 | 6138 |
6143 class HLoadNamedField V8_FINAL : public HTemplateInstruction<2> { | 6139 class HLoadNamedField V8_FINAL : public HTemplateInstruction<2> { |
6144 public: | 6140 public: |
6145 DECLARE_INSTRUCTION_FACTORY_P3(HLoadNamedField, HValue*, HValue*, | |
6146 HObjectAccess); | |
6147 static HLoadNamedField* New(Zone* zone, HValue* context, | 6141 static HLoadNamedField* New(Zone* zone, HValue* context, |
6148 HValue* object, HValue* dependency, | 6142 HValue* object, HValue* dependency, |
6149 HObjectAccess access, SmallMapList* maps, | 6143 HObjectAccess access) { |
| 6144 return new(zone) HLoadNamedField( |
| 6145 object, dependency, access, new(zone) UniqueSet<Map>()); |
| 6146 } |
| 6147 static HLoadNamedField* New(Zone* zone, HValue* context, |
| 6148 HValue* object, HValue* dependency, |
| 6149 HObjectAccess access, SmallMapList* map_list, |
6150 CompilationInfo* info) { | 6150 CompilationInfo* info) { |
6151 HLoadNamedField* load_named_field = HLoadNamedField::New( | 6151 UniqueSet<Map>* maps = new(zone) UniqueSet<Map>(map_list->length(), zone); |
6152 zone, context, object, dependency, access); | 6152 for (int i = 0; i < map_list->length(); ++i) { |
6153 for (int i = 0; i < maps->length(); ++i) { | 6153 Handle<Map> map = map_list->at(i); |
6154 Handle<Map> map(maps->at(i)); | 6154 maps->Add(Unique<Map>::CreateImmovable(map), zone); |
6155 load_named_field->map_set_.Add(Unique<Map>(map), zone); | 6155 // TODO(bmeurer): Get rid of this shit! |
6156 if (map->CanTransition()) { | 6156 if (map->CanTransition()) { |
6157 Map::AddDependentCompilationInfo( | 6157 Map::AddDependentCompilationInfo( |
6158 map, DependentCode::kPrototypeCheckGroup, info); | 6158 map, DependentCode::kPrototypeCheckGroup, info); |
6159 } | 6159 } |
6160 } | 6160 } |
6161 return load_named_field; | 6161 return new(zone) HLoadNamedField(object, dependency, access, maps); |
6162 } | 6162 } |
6163 | 6163 |
6164 HValue* object() { return OperandAt(0); } | 6164 HValue* object() { return OperandAt(0); } |
6165 HValue* dependency() { | 6165 HValue* dependency() { |
6166 ASSERT(HasDependency()); | 6166 ASSERT(HasDependency()); |
6167 return OperandAt(1); | 6167 return OperandAt(1); |
6168 } | 6168 } |
6169 bool HasDependency() const { return OperandAt(0) != OperandAt(1); } | 6169 bool HasDependency() const { return OperandAt(0) != OperandAt(1); } |
6170 HObjectAccess access() const { return access_; } | 6170 HObjectAccess access() const { return access_; } |
6171 Representation field_representation() const { | 6171 Representation field_representation() const { |
6172 return access_.representation(); | 6172 return access_.representation(); |
6173 } | 6173 } |
6174 | 6174 |
6175 const UniqueSet<Map>* map_set() const { return &map_set_; } | 6175 const UniqueSet<Map>* maps() const { return maps_; } |
6176 | 6176 |
6177 virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE { return false; } | 6177 virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE { return false; } |
6178 virtual bool HasOutOfBoundsAccess(int size) V8_OVERRIDE { | 6178 virtual bool HasOutOfBoundsAccess(int size) V8_OVERRIDE { |
6179 return !access().IsInobject() || access().offset() >= size; | 6179 return !access().IsInobject() || access().offset() >= size; |
6180 } | 6180 } |
6181 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE { | 6181 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE { |
6182 if (index == 0 && access().IsExternalMemory()) { | 6182 if (index == 0 && access().IsExternalMemory()) { |
6183 // object must be external in case of external memory access | 6183 // object must be external in case of external memory access |
6184 return Representation::External(); | 6184 return Representation::External(); |
6185 } | 6185 } |
6186 return Representation::Tagged(); | 6186 return Representation::Tagged(); |
6187 } | 6187 } |
6188 virtual Range* InferRange(Zone* zone) V8_OVERRIDE; | 6188 virtual Range* InferRange(Zone* zone) V8_OVERRIDE; |
6189 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE; | 6189 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE; |
6190 | 6190 |
6191 DECLARE_CONCRETE_INSTRUCTION(LoadNamedField) | 6191 DECLARE_CONCRETE_INSTRUCTION(LoadNamedField) |
6192 | 6192 |
6193 protected: | 6193 protected: |
6194 virtual bool DataEquals(HValue* other) V8_OVERRIDE { | 6194 virtual bool DataEquals(HValue* other) V8_OVERRIDE { |
6195 HLoadNamedField* b = HLoadNamedField::cast(other); | 6195 HLoadNamedField* b = HLoadNamedField::cast(other); |
6196 return access_.Equals(b->access_) && this->map_set_.Equals(&b->map_set_); | 6196 return access_.Equals(b->access_) && this->maps()->Equals(b->maps()); |
6197 } | 6197 } |
6198 | 6198 |
6199 private: | 6199 private: |
6200 HLoadNamedField(HValue* object, | 6200 HLoadNamedField(HValue* object, |
6201 HValue* dependency, | 6201 HValue* dependency, |
6202 HObjectAccess access, | 6202 HObjectAccess access, |
6203 Handle<Map> map = Handle<Map>::null()) | 6203 const UniqueSet<Map>* maps) |
6204 : access_(access) { | 6204 : access_(access), maps_(maps) { |
6205 ASSERT(object != NULL); | 6205 ASSERT(object != NULL); |
6206 SetOperandAt(0, object); | 6206 SetOperandAt(0, object); |
6207 SetOperandAt(1, dependency != NULL ? dependency : object); | 6207 SetOperandAt(1, dependency != NULL ? dependency : object); |
6208 | 6208 |
6209 Representation representation = access.representation(); | 6209 Representation representation = access.representation(); |
6210 if (representation.IsInteger8() || | 6210 if (representation.IsInteger8() || |
6211 representation.IsUInteger8() || | 6211 representation.IsUInteger8() || |
6212 representation.IsInteger16() || | 6212 representation.IsInteger16() || |
6213 representation.IsUInteger16()) { | 6213 representation.IsUInteger16()) { |
6214 set_representation(Representation::Integer32()); | 6214 set_representation(Representation::Integer32()); |
(...skipping 13 matching lines...) Expand all Loading... |
6228 set_representation(Representation::Tagged()); | 6228 set_representation(Representation::Tagged()); |
6229 } else { | 6229 } else { |
6230 set_representation(Representation::Tagged()); | 6230 set_representation(Representation::Tagged()); |
6231 } | 6231 } |
6232 access.SetGVNFlags(this, LOAD); | 6232 access.SetGVNFlags(this, LOAD); |
6233 } | 6233 } |
6234 | 6234 |
6235 virtual bool IsDeletable() const V8_OVERRIDE { return true; } | 6235 virtual bool IsDeletable() const V8_OVERRIDE { return true; } |
6236 | 6236 |
6237 HObjectAccess access_; | 6237 HObjectAccess access_; |
6238 UniqueSet<Map> map_set_; | 6238 const UniqueSet<Map>* maps_; |
6239 }; | 6239 }; |
6240 | 6240 |
6241 | 6241 |
6242 class HLoadNamedGeneric V8_FINAL : public HTemplateInstruction<2> { | 6242 class HLoadNamedGeneric V8_FINAL : public HTemplateInstruction<2> { |
6243 public: | 6243 public: |
6244 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HLoadNamedGeneric, HValue*, | 6244 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HLoadNamedGeneric, HValue*, |
6245 Handle<Object>); | 6245 Handle<Object>); |
6246 | 6246 |
6247 HValue* context() { return OperandAt(0); } | 6247 HValue* context() { return OperandAt(0); } |
6248 HValue* object() { return OperandAt(1); } | 6248 HValue* object() { return OperandAt(1); } |
(...skipping 1307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7556 virtual bool IsDeletable() const V8_OVERRIDE { return true; } | 7556 virtual bool IsDeletable() const V8_OVERRIDE { return true; } |
7557 }; | 7557 }; |
7558 | 7558 |
7559 | 7559 |
7560 #undef DECLARE_INSTRUCTION | 7560 #undef DECLARE_INSTRUCTION |
7561 #undef DECLARE_CONCRETE_INSTRUCTION | 7561 #undef DECLARE_CONCRETE_INSTRUCTION |
7562 | 7562 |
7563 } } // namespace v8::internal | 7563 } } // namespace v8::internal |
7564 | 7564 |
7565 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ | 7565 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ |
OLD | NEW |