| 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 |