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" |
11 #include "code-stubs.h" | 11 #include "code-stubs.h" |
12 #include "conversions.h" | 12 #include "conversions.h" |
13 #include "data-flow.h" | 13 #include "data-flow.h" |
14 #include "deoptimizer.h" | 14 #include "deoptimizer.h" |
| 15 #include "hydrogen-types.h" |
15 #include "small-pointer-list.h" | 16 #include "small-pointer-list.h" |
16 #include "string-stream.h" | 17 #include "string-stream.h" |
17 #include "unique.h" | 18 #include "unique.h" |
18 #include "utils.h" | 19 #include "utils.h" |
19 #include "zone.h" | 20 #include "zone.h" |
20 | 21 |
21 namespace v8 { | 22 namespace v8 { |
22 namespace internal { | 23 namespace internal { |
23 | 24 |
24 // Forward declarations. | 25 // Forward declarations. |
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
275 bool MulAndCheckOverflow(const Representation& r, Range* other); | 276 bool MulAndCheckOverflow(const Representation& r, Range* other); |
276 | 277 |
277 private: | 278 private: |
278 int32_t lower_; | 279 int32_t lower_; |
279 int32_t upper_; | 280 int32_t upper_; |
280 Range* next_; | 281 Range* next_; |
281 bool can_be_minus_zero_; | 282 bool can_be_minus_zero_; |
282 }; | 283 }; |
283 | 284 |
284 | 285 |
285 class HType V8_FINAL { | |
286 public: | |
287 static HType None() { return HType(kNone); } | |
288 static HType Tagged() { return HType(kTagged); } | |
289 static HType TaggedPrimitive() { return HType(kTaggedPrimitive); } | |
290 static HType TaggedNumber() { return HType(kTaggedNumber); } | |
291 static HType Smi() { return HType(kSmi); } | |
292 static HType HeapNumber() { return HType(kHeapNumber); } | |
293 static HType String() { return HType(kString); } | |
294 static HType Boolean() { return HType(kBoolean); } | |
295 static HType NonPrimitive() { return HType(kNonPrimitive); } | |
296 static HType JSArray() { return HType(kJSArray); } | |
297 static HType JSObject() { return HType(kJSObject); } | |
298 | |
299 // Return the weakest (least precise) common type. | |
300 HType Combine(HType other) { | |
301 return HType(static_cast<Type>(type_ & other.type_)); | |
302 } | |
303 | |
304 bool Equals(const HType& other) const { | |
305 return type_ == other.type_; | |
306 } | |
307 | |
308 bool IsSubtypeOf(const HType& other) { | |
309 return Combine(other).Equals(other); | |
310 } | |
311 | |
312 bool IsTaggedPrimitive() const { | |
313 return ((type_ & kTaggedPrimitive) == kTaggedPrimitive); | |
314 } | |
315 | |
316 bool IsTaggedNumber() const { | |
317 return ((type_ & kTaggedNumber) == kTaggedNumber); | |
318 } | |
319 | |
320 bool IsSmi() const { | |
321 return ((type_ & kSmi) == kSmi); | |
322 } | |
323 | |
324 bool IsHeapNumber() const { | |
325 return ((type_ & kHeapNumber) == kHeapNumber); | |
326 } | |
327 | |
328 bool IsString() const { | |
329 return ((type_ & kString) == kString); | |
330 } | |
331 | |
332 bool IsNonString() const { | |
333 return IsTaggedPrimitive() || IsSmi() || IsHeapNumber() || | |
334 IsBoolean() || IsJSArray(); | |
335 } | |
336 | |
337 bool IsBoolean() const { | |
338 return ((type_ & kBoolean) == kBoolean); | |
339 } | |
340 | |
341 bool IsNonPrimitive() const { | |
342 return ((type_ & kNonPrimitive) == kNonPrimitive); | |
343 } | |
344 | |
345 bool IsJSArray() const { | |
346 return ((type_ & kJSArray) == kJSArray); | |
347 } | |
348 | |
349 bool IsJSObject() const { | |
350 return ((type_ & kJSObject) == kJSObject); | |
351 } | |
352 | |
353 bool IsHeapObject() const { | |
354 return IsHeapNumber() || IsString() || IsBoolean() || IsNonPrimitive(); | |
355 } | |
356 | |
357 bool ToStringOrToNumberCanBeObserved(Representation representation) { | |
358 switch (type_) { | |
359 case kTaggedPrimitive: // fallthru | |
360 case kTaggedNumber: // fallthru | |
361 case kSmi: // fallthru | |
362 case kHeapNumber: // fallthru | |
363 case kString: // fallthru | |
364 case kBoolean: | |
365 return false; | |
366 case kJSArray: // fallthru | |
367 case kJSObject: | |
368 return true; | |
369 case kTagged: | |
370 break; | |
371 } | |
372 return !representation.IsSmiOrInteger32() && !representation.IsDouble(); | |
373 } | |
374 | |
375 static HType TypeFromValue(Handle<Object> value); | |
376 | |
377 const char* ToString(); | |
378 | |
379 private: | |
380 enum Type { | |
381 kNone = 0x0, // 0000 0000 0000 0000 | |
382 kTagged = 0x1, // 0000 0000 0000 0001 | |
383 kTaggedPrimitive = 0x5, // 0000 0000 0000 0101 | |
384 kTaggedNumber = 0xd, // 0000 0000 0000 1101 | |
385 kSmi = 0x1d, // 0000 0000 0001 1101 | |
386 kHeapNumber = 0x2d, // 0000 0000 0010 1101 | |
387 kString = 0x45, // 0000 0000 0100 0101 | |
388 kBoolean = 0x85, // 0000 0000 1000 0101 | |
389 kNonPrimitive = 0x101, // 0000 0001 0000 0001 | |
390 kJSObject = 0x301, // 0000 0011 0000 0001 | |
391 kJSArray = 0x701 // 0000 0111 0000 0001 | |
392 }; | |
393 | |
394 // Make sure type fits in int16. | |
395 STATIC_ASSERT(kJSArray < (1 << (2 * kBitsPerByte))); | |
396 | |
397 explicit HType(Type t) : type_(t) { } | |
398 | |
399 int16_t type_; | |
400 }; | |
401 | |
402 | |
403 class HUseListNode: public ZoneObject { | 286 class HUseListNode: public ZoneObject { |
404 public: | 287 public: |
405 HUseListNode(HValue* value, int index, HUseListNode* tail) | 288 HUseListNode(HValue* value, int index, HUseListNode* tail) |
406 : tail_(tail), value_(value), index_(index) { | 289 : tail_(tail), value_(value), index_(index) { |
407 } | 290 } |
408 | 291 |
409 HUseListNode* tail(); | 292 HUseListNode* tail(); |
410 HValue* value() const { return value_; } | 293 HValue* value() const { return value_; } |
411 int index() const { return index_; } | 294 int index() const { return index_; } |
412 | 295 |
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
720 } | 603 } |
721 return r; | 604 return r; |
722 } | 605 } |
723 | 606 |
724 HType type() const { return type_; } | 607 HType type() const { return type_; } |
725 void set_type(HType new_type) { | 608 void set_type(HType new_type) { |
726 ASSERT(new_type.IsSubtypeOf(type_)); | 609 ASSERT(new_type.IsSubtypeOf(type_)); |
727 type_ = new_type; | 610 type_ = new_type; |
728 } | 611 } |
729 | 612 |
730 bool IsHeapObject() { | |
731 return representation_.IsHeapObject() || type_.IsHeapObject(); | |
732 } | |
733 | |
734 // There are HInstructions that do not really change a value, they | 613 // There are HInstructions that do not really change a value, they |
735 // only add pieces of information to it (like bounds checks, map checks, | 614 // only add pieces of information to it (like bounds checks, map checks, |
736 // smi checks...). | 615 // smi checks...). |
737 // We call these instructions "informative definitions", or "iDef". | 616 // We call these instructions "informative definitions", or "iDef". |
738 // One of the iDef operands is special because it is the value that is | 617 // One of the iDef operands is special because it is the value that is |
739 // "transferred" to the output, we call it the "redefined operand". | 618 // "transferred" to the output, we call it the "redefined operand". |
740 // If an HValue is an iDef it must override RedefinedOperandIndex() so that | 619 // If an HValue is an iDef it must override RedefinedOperandIndex() so that |
741 // it does not return kNoRedefinedOperand; | 620 // it does not return kNoRedefinedOperand; |
742 static const int kNoRedefinedOperand = -1; | 621 static const int kNoRedefinedOperand = -1; |
743 virtual int RedefinedOperandIndex() { return kNoRedefinedOperand; } | 622 virtual int RedefinedOperandIndex() { return kNoRedefinedOperand; } |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
926 if (RedefinedOperand() != NULL) { | 805 if (RedefinedOperand() != NULL) { |
927 return RedefinedOperand()->TryDecompose(decomposition); | 806 return RedefinedOperand()->TryDecompose(decomposition); |
928 } else { | 807 } else { |
929 return false; | 808 return false; |
930 } | 809 } |
931 } | 810 } |
932 | 811 |
933 // Returns true conservatively if the program might be able to observe a | 812 // Returns true conservatively if the program might be able to observe a |
934 // ToString() operation on this value. | 813 // ToString() operation on this value. |
935 bool ToStringCanBeObserved() const { | 814 bool ToStringCanBeObserved() const { |
936 return type().ToStringOrToNumberCanBeObserved(representation()); | 815 return ToStringOrToNumberCanBeObserved(); |
937 } | 816 } |
938 | 817 |
939 // Returns true conservatively if the program might be able to observe a | 818 // Returns true conservatively if the program might be able to observe a |
940 // ToNumber() operation on this value. | 819 // ToNumber() operation on this value. |
941 bool ToNumberCanBeObserved() const { | 820 bool ToNumberCanBeObserved() const { |
942 return type().ToStringOrToNumberCanBeObserved(representation()); | 821 return ToStringOrToNumberCanBeObserved(); |
943 } | 822 } |
944 | 823 |
945 MinusZeroMode GetMinusZeroMode() { | 824 MinusZeroMode GetMinusZeroMode() { |
946 return CheckFlag(kBailoutOnMinusZero) | 825 return CheckFlag(kBailoutOnMinusZero) |
947 ? FAIL_ON_MINUS_ZERO : TREAT_MINUS_ZERO_AS_ZERO; | 826 ? FAIL_ON_MINUS_ZERO : TREAT_MINUS_ZERO_AS_ZERO; |
948 } | 827 } |
949 | 828 |
950 protected: | 829 protected: |
951 // This function must be overridden for instructions with flag kUseGVN, to | 830 // This function must be overridden for instructions with flag kUseGVN, to |
952 // compare the non-Operand parts of the instruction. | 831 // compare the non-Operand parts of the instruction. |
953 virtual bool DataEquals(HValue* other) { | 832 virtual bool DataEquals(HValue* other) { |
954 UNREACHABLE(); | 833 UNREACHABLE(); |
955 return false; | 834 return false; |
956 } | 835 } |
957 | 836 |
| 837 bool ToStringOrToNumberCanBeObserved() const { |
| 838 if (type().IsTaggedPrimitive()) return false; |
| 839 if (type().IsJSObject()) return true; |
| 840 return !representation().IsSmiOrInteger32() && !representation().IsDouble(); |
| 841 } |
| 842 |
958 virtual Representation RepresentationFromInputs() { | 843 virtual Representation RepresentationFromInputs() { |
959 return representation(); | 844 return representation(); |
960 } | 845 } |
961 virtual Representation RepresentationFromUses(); | 846 virtual Representation RepresentationFromUses(); |
962 Representation RepresentationFromUseRequirements(); | 847 Representation RepresentationFromUseRequirements(); |
963 bool HasNonSmiUse(); | 848 bool HasNonSmiUse(); |
964 virtual void UpdateRepresentation(Representation new_rep, | 849 virtual void UpdateRepresentation(Representation new_rep, |
965 HInferRepresentationPhase* h_infer, | 850 HInferRepresentationPhase* h_infer, |
966 const char* reason); | 851 const char* reason); |
967 void AddDependantsToWorklist(HInferRepresentationPhase* h_infer); | 852 void AddDependantsToWorklist(HInferRepresentationPhase* h_infer); |
(...skipping 1864 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2832 is_stability_check_ = true; | 2717 is_stability_check_ = true; |
2833 ClearChangesFlag(kNewSpacePromotion); | 2718 ClearChangesFlag(kNewSpacePromotion); |
2834 ClearDependsOnFlag(kElementsKind); | 2719 ClearDependsOnFlag(kElementsKind); |
2835 ClearDependsOnFlag(kMaps); | 2720 ClearDependsOnFlag(kMaps); |
2836 } | 2721 } |
2837 | 2722 |
2838 virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE { return false; } | 2723 virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE { return false; } |
2839 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE { | 2724 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE { |
2840 return Representation::Tagged(); | 2725 return Representation::Tagged(); |
2841 } | 2726 } |
| 2727 |
| 2728 virtual HType CalculateInferredType() V8_OVERRIDE { |
| 2729 if (value()->type().IsHeapObject()) return value()->type(); |
| 2730 return HType::HeapObject(); |
| 2731 } |
| 2732 |
2842 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE; | 2733 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE; |
2843 | 2734 |
2844 HValue* value() { return OperandAt(0); } | 2735 HValue* value() const { return OperandAt(0); } |
2845 HValue* typecheck() { return OperandAt(1); } | 2736 HValue* typecheck() const { return OperandAt(1); } |
2846 | 2737 |
2847 const UniqueSet<Map>* maps() const { return maps_; } | 2738 const UniqueSet<Map>* maps() const { return maps_; } |
2848 void set_maps(const UniqueSet<Map>* maps) { maps_ = maps; } | 2739 void set_maps(const UniqueSet<Map>* maps) { maps_ = maps; } |
2849 | 2740 |
2850 bool maps_are_stable() const { return maps_are_stable_; } | 2741 bool maps_are_stable() const { return maps_are_stable_; } |
2851 | 2742 |
2852 bool HasMigrationTarget() const { return has_migration_target_; } | 2743 bool HasMigrationTarget() const { return has_migration_target_; } |
2853 | 2744 |
2854 virtual HValue* Canonicalize() V8_OVERRIDE; | 2745 virtual HValue* Canonicalize() V8_OVERRIDE; |
2855 | 2746 |
(...skipping 18 matching lines...) Expand all Loading... |
2874 | 2765 |
2875 protected: | 2766 protected: |
2876 virtual bool DataEquals(HValue* other) V8_OVERRIDE { | 2767 virtual bool DataEquals(HValue* other) V8_OVERRIDE { |
2877 return this->maps()->Equals(HCheckMaps::cast(other)->maps()); | 2768 return this->maps()->Equals(HCheckMaps::cast(other)->maps()); |
2878 } | 2769 } |
2879 | 2770 |
2880 virtual int RedefinedOperandIndex() { return 0; } | 2771 virtual int RedefinedOperandIndex() { return 0; } |
2881 | 2772 |
2882 private: | 2773 private: |
2883 HCheckMaps(HValue* value, const UniqueSet<Map>* maps, bool maps_are_stable) | 2774 HCheckMaps(HValue* value, const UniqueSet<Map>* maps, bool maps_are_stable) |
2884 : HTemplateInstruction<2>(value->type()), maps_(maps), | 2775 : HTemplateInstruction<2>(HType::HeapObject()), maps_(maps), |
2885 has_migration_target_(false), is_stability_check_(false), | 2776 has_migration_target_(false), is_stability_check_(false), |
2886 maps_are_stable_(maps_are_stable) { | 2777 maps_are_stable_(maps_are_stable) { |
2887 ASSERT_NE(0, maps->size()); | 2778 ASSERT_NE(0, maps->size()); |
2888 SetOperandAt(0, value); | 2779 SetOperandAt(0, value); |
2889 // Use the object value for the dependency. | 2780 // Use the object value for the dependency. |
2890 SetOperandAt(1, value); | 2781 SetOperandAt(1, value); |
2891 set_representation(Representation::Tagged()); | 2782 set_representation(Representation::Tagged()); |
2892 SetFlag(kUseGVN); | 2783 SetFlag(kUseGVN); |
2893 SetDependsOnFlag(kMaps); | 2784 SetDependsOnFlag(kMaps); |
2894 SetDependsOnFlag(kElementsKind); | 2785 SetDependsOnFlag(kElementsKind); |
2895 } | 2786 } |
2896 | 2787 |
2897 HCheckMaps(HValue* value, const UniqueSet<Map>* maps, HValue* typecheck) | 2788 HCheckMaps(HValue* value, const UniqueSet<Map>* maps, HValue* typecheck) |
2898 : HTemplateInstruction<2>(value->type()), maps_(maps), | 2789 : HTemplateInstruction<2>(HType::HeapObject()), maps_(maps), |
2899 has_migration_target_(false), is_stability_check_(false), | 2790 has_migration_target_(false), is_stability_check_(false), |
2900 maps_are_stable_(true) { | 2791 maps_are_stable_(true) { |
2901 ASSERT_NE(0, maps->size()); | 2792 ASSERT_NE(0, maps->size()); |
2902 SetOperandAt(0, value); | 2793 SetOperandAt(0, value); |
2903 // Use the object value for the dependency if NULL is passed. | 2794 // Use the object value for the dependency if NULL is passed. |
2904 SetOperandAt(1, typecheck ? typecheck : value); | 2795 SetOperandAt(1, typecheck ? typecheck : value); |
2905 set_representation(Representation::Tagged()); | 2796 set_representation(Representation::Tagged()); |
2906 SetFlag(kUseGVN); | 2797 SetFlag(kUseGVN); |
2907 SetDependsOnFlag(kMaps); | 2798 SetDependsOnFlag(kMaps); |
2908 SetDependsOnFlag(kElementsKind); | 2799 SetDependsOnFlag(kElementsKind); |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2992 }; | 2883 }; |
2993 | 2884 |
2994 DECLARE_INSTRUCTION_FACTORY_P2(HCheckInstanceType, HValue*, Check); | 2885 DECLARE_INSTRUCTION_FACTORY_P2(HCheckInstanceType, HValue*, Check); |
2995 | 2886 |
2996 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE; | 2887 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE; |
2997 | 2888 |
2998 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE { | 2889 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE { |
2999 return Representation::Tagged(); | 2890 return Representation::Tagged(); |
3000 } | 2891 } |
3001 | 2892 |
| 2893 virtual HType CalculateInferredType() V8_OVERRIDE { |
| 2894 switch (check_) { |
| 2895 case IS_SPEC_OBJECT: return HType::JSObject(); |
| 2896 case IS_JS_ARRAY: return HType::JSArray(); |
| 2897 case IS_STRING: return HType::String(); |
| 2898 case IS_INTERNALIZED_STRING: return HType::String(); |
| 2899 } |
| 2900 UNREACHABLE(); |
| 2901 return HType::Tagged(); |
| 2902 } |
| 2903 |
3002 virtual HValue* Canonicalize() V8_OVERRIDE; | 2904 virtual HValue* Canonicalize() V8_OVERRIDE; |
3003 | 2905 |
3004 bool is_interval_check() const { return check_ <= LAST_INTERVAL_CHECK; } | 2906 bool is_interval_check() const { return check_ <= LAST_INTERVAL_CHECK; } |
3005 void GetCheckInterval(InstanceType* first, InstanceType* last); | 2907 void GetCheckInterval(InstanceType* first, InstanceType* last); |
3006 void GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag); | 2908 void GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag); |
3007 | 2909 |
3008 DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType) | 2910 DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType) |
3009 | 2911 |
3010 protected: | 2912 protected: |
3011 // TODO(ager): It could be nice to allow the ommision of instance | 2913 // TODO(ager): It could be nice to allow the ommision of instance |
3012 // type checks if we have already performed an instance type check | 2914 // type checks if we have already performed an instance type check |
3013 // with a larger range. | 2915 // with a larger range. |
3014 virtual bool DataEquals(HValue* other) V8_OVERRIDE { | 2916 virtual bool DataEquals(HValue* other) V8_OVERRIDE { |
3015 HCheckInstanceType* b = HCheckInstanceType::cast(other); | 2917 HCheckInstanceType* b = HCheckInstanceType::cast(other); |
3016 return check_ == b->check_; | 2918 return check_ == b->check_; |
3017 } | 2919 } |
3018 | 2920 |
3019 virtual int RedefinedOperandIndex() { return 0; } | 2921 virtual int RedefinedOperandIndex() { return 0; } |
3020 | 2922 |
3021 private: | 2923 private: |
3022 const char* GetCheckName(); | 2924 const char* GetCheckName(); |
3023 | 2925 |
3024 HCheckInstanceType(HValue* value, Check check) | 2926 HCheckInstanceType(HValue* value, Check check) |
3025 : HUnaryOperation(value), check_(check) { | 2927 : HUnaryOperation(value, HType::HeapObject()), check_(check) { |
3026 set_representation(Representation::Tagged()); | 2928 set_representation(Representation::Tagged()); |
3027 SetFlag(kUseGVN); | 2929 SetFlag(kUseGVN); |
3028 } | 2930 } |
3029 | 2931 |
3030 const Check check_; | 2932 const Check check_; |
3031 }; | 2933 }; |
3032 | 2934 |
3033 | 2935 |
3034 class HCheckSmi V8_FINAL : public HUnaryOperation { | 2936 class HCheckSmi V8_FINAL : public HUnaryOperation { |
3035 public: | 2937 public: |
(...skipping 26 matching lines...) Expand all Loading... |
3062 | 2964 |
3063 class HCheckHeapObject V8_FINAL : public HUnaryOperation { | 2965 class HCheckHeapObject V8_FINAL : public HUnaryOperation { |
3064 public: | 2966 public: |
3065 DECLARE_INSTRUCTION_FACTORY_P1(HCheckHeapObject, HValue*); | 2967 DECLARE_INSTRUCTION_FACTORY_P1(HCheckHeapObject, HValue*); |
3066 | 2968 |
3067 virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE { return false; } | 2969 virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE { return false; } |
3068 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE { | 2970 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE { |
3069 return Representation::Tagged(); | 2971 return Representation::Tagged(); |
3070 } | 2972 } |
3071 | 2973 |
| 2974 virtual HType CalculateInferredType() V8_OVERRIDE { |
| 2975 if (value()->type().IsHeapObject()) return value()->type(); |
| 2976 return HType::HeapObject(); |
| 2977 } |
| 2978 |
3072 #ifdef DEBUG | 2979 #ifdef DEBUG |
3073 virtual void Verify() V8_OVERRIDE; | 2980 virtual void Verify() V8_OVERRIDE; |
3074 #endif | 2981 #endif |
3075 | 2982 |
3076 virtual HValue* Canonicalize() V8_OVERRIDE { | 2983 virtual HValue* Canonicalize() V8_OVERRIDE { |
3077 return value()->type().IsHeapObject() ? NULL : this; | 2984 return value()->type().IsHeapObject() ? NULL : this; |
3078 } | 2985 } |
3079 | 2986 |
3080 DECLARE_CONCRETE_INSTRUCTION(CheckHeapObject) | 2987 DECLARE_CONCRETE_INSTRUCTION(CheckHeapObject) |
3081 | 2988 |
3082 protected: | 2989 protected: |
3083 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; } | 2990 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; } |
3084 | 2991 |
3085 private: | 2992 private: |
3086 explicit HCheckHeapObject(HValue* value) | 2993 explicit HCheckHeapObject(HValue* value) : HUnaryOperation(value) { |
3087 : HUnaryOperation(value, HType::NonPrimitive()) { | |
3088 set_representation(Representation::Tagged()); | 2994 set_representation(Representation::Tagged()); |
3089 SetFlag(kUseGVN); | 2995 SetFlag(kUseGVN); |
3090 } | 2996 } |
3091 }; | 2997 }; |
3092 | 2998 |
3093 | 2999 |
3094 class InductionVariableData; | 3000 class InductionVariableData; |
3095 | 3001 |
3096 | 3002 |
3097 struct InductionVariableLimitUpdate { | 3003 struct InductionVariableLimitUpdate { |
(...skipping 461 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3559 return instruction->Prepend(HConstant::New( | 3465 return instruction->Prepend(HConstant::New( |
3560 zone, context, value, representation)); | 3466 zone, context, value, representation)); |
3561 } | 3467 } |
3562 | 3468 |
3563 static HConstant* CreateAndInsertBefore(Zone* zone, | 3469 static HConstant* CreateAndInsertBefore(Zone* zone, |
3564 Unique<Map> map, | 3470 Unique<Map> map, |
3565 bool map_is_stable, | 3471 bool map_is_stable, |
3566 HInstruction* instruction) { | 3472 HInstruction* instruction) { |
3567 return instruction->Prepend(new(zone) HConstant( | 3473 return instruction->Prepend(new(zone) HConstant( |
3568 map, Unique<Map>(Handle<Map>::null()), map_is_stable, | 3474 map, Unique<Map>(Handle<Map>::null()), map_is_stable, |
3569 Representation::Tagged(), HType::Tagged(), true, | 3475 Representation::Tagged(), HType::HeapObject(), true, |
3570 false, false, MAP_TYPE)); | 3476 false, false, MAP_TYPE)); |
3571 } | 3477 } |
3572 | 3478 |
3573 static HConstant* CreateAndInsertAfter(Zone* zone, | 3479 static HConstant* CreateAndInsertAfter(Zone* zone, |
3574 Unique<Map> map, | 3480 Unique<Map> map, |
3575 bool map_is_stable, | 3481 bool map_is_stable, |
3576 HInstruction* instruction) { | 3482 HInstruction* instruction) { |
3577 return instruction->Append(new(zone) HConstant( | 3483 return instruction->Append(new(zone) HConstant( |
3578 map, Unique<Map>(Handle<Map>::null()), map_is_stable, | 3484 map, Unique<Map>(Handle<Map>::null()), map_is_stable, |
3579 Representation::Tagged(), HType::Tagged(), true, | 3485 Representation::Tagged(), HType::HeapObject(), true, |
3580 false, false, MAP_TYPE)); | 3486 false, false, MAP_TYPE)); |
3581 } | 3487 } |
3582 | 3488 |
3583 Handle<Object> handle(Isolate* isolate) { | 3489 Handle<Object> handle(Isolate* isolate) { |
3584 if (object_.handle().is_null()) { | 3490 if (object_.handle().is_null()) { |
3585 // Default arguments to is_not_in_new_space depend on this heap number | 3491 // Default arguments to is_not_in_new_space depend on this heap number |
3586 // to be tenured so that it's guaranteed not to be located in new space. | 3492 // to be tenured so that it's guaranteed not to be located in new space. |
3587 object_ = Unique<Object>::CreateUninitialized( | 3493 object_ = Unique<Object>::CreateUninitialized( |
3588 isolate->factory()->NewNumber(double_value_, TENURED)); | 3494 isolate->factory()->NewNumber(double_value_, TENURED)); |
3589 } | 3495 } |
(...skipping 590 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4180 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE; | 4086 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE; |
4181 | 4087 |
4182 virtual int RedefinedOperandIndex() V8_OVERRIDE { return 0; } | 4088 virtual int RedefinedOperandIndex() V8_OVERRIDE { return 0; } |
4183 virtual bool IsPurelyInformativeDefinition() V8_OVERRIDE { return true; } | 4089 virtual bool IsPurelyInformativeDefinition() V8_OVERRIDE { return true; } |
4184 }; | 4090 }; |
4185 | 4091 |
4186 | 4092 |
4187 class HBitwiseBinaryOperation : public HBinaryOperation { | 4093 class HBitwiseBinaryOperation : public HBinaryOperation { |
4188 public: | 4094 public: |
4189 HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right, | 4095 HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right, |
4190 HType type = HType::Tagged()) | 4096 HType type = HType::TaggedNumber()) |
4191 : HBinaryOperation(context, left, right, type) { | 4097 : HBinaryOperation(context, left, right, type) { |
4192 SetFlag(kFlexibleRepresentation); | 4098 SetFlag(kFlexibleRepresentation); |
4193 SetFlag(kTruncatingToInt32); | 4099 SetFlag(kTruncatingToInt32); |
4194 SetFlag(kAllowUndefinedAsNaN); | 4100 SetFlag(kAllowUndefinedAsNaN); |
4195 SetAllSideEffects(); | 4101 SetAllSideEffects(); |
4196 } | 4102 } |
4197 | 4103 |
4198 virtual void RepresentationChanged(Representation to) V8_OVERRIDE { | 4104 virtual void RepresentationChanged(Representation to) V8_OVERRIDE { |
4199 if (to.IsTagged() && | 4105 if (to.IsTagged() && |
4200 (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved())) { | 4106 (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved())) { |
(...skipping 932 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5133 return op() == HBitwise::cast(other)->op(); | 5039 return op() == HBitwise::cast(other)->op(); |
5134 } | 5040 } |
5135 | 5041 |
5136 virtual Range* InferRange(Zone* zone) V8_OVERRIDE; | 5042 virtual Range* InferRange(Zone* zone) V8_OVERRIDE; |
5137 | 5043 |
5138 private: | 5044 private: |
5139 HBitwise(HValue* context, | 5045 HBitwise(HValue* context, |
5140 Token::Value op, | 5046 Token::Value op, |
5141 HValue* left, | 5047 HValue* left, |
5142 HValue* right) | 5048 HValue* right) |
5143 : HBitwiseBinaryOperation(context, left, right, HType::TaggedNumber()), | 5049 : HBitwiseBinaryOperation(context, left, right), |
5144 op_(op) { | 5050 op_(op) { |
5145 ASSERT(op == Token::BIT_AND || op == Token::BIT_OR || op == Token::BIT_XOR); | 5051 ASSERT(op == Token::BIT_AND || op == Token::BIT_OR || op == Token::BIT_XOR); |
5146 // BIT_AND with a smi-range positive value will always unset the | 5052 // BIT_AND with a smi-range positive value will always unset the |
5147 // entire sign-extension of the smi-sign. | 5053 // entire sign-extension of the smi-sign. |
5148 if (op == Token::BIT_AND && | 5054 if (op == Token::BIT_AND && |
5149 ((left->IsConstant() && | 5055 ((left->IsConstant() && |
5150 left->representation().IsSmi() && | 5056 left->representation().IsSmi() && |
5151 HConstant::cast(left)->Integer32Value() >= 0) || | 5057 HConstant::cast(left)->Integer32Value() >= 0) || |
5152 (right->IsConstant() && | 5058 (right->IsConstant() && |
5153 right->representation().IsSmi() && | 5059 right->representation().IsSmi() && |
(...skipping 558 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5712 } | 5618 } |
5713 }; | 5619 }; |
5714 | 5620 |
5715 | 5621 |
5716 class HInnerAllocatedObject V8_FINAL : public HTemplateInstruction<2> { | 5622 class HInnerAllocatedObject V8_FINAL : public HTemplateInstruction<2> { |
5717 public: | 5623 public: |
5718 static HInnerAllocatedObject* New(Zone* zone, | 5624 static HInnerAllocatedObject* New(Zone* zone, |
5719 HValue* context, | 5625 HValue* context, |
5720 HValue* value, | 5626 HValue* value, |
5721 HValue* offset, | 5627 HValue* offset, |
5722 HType type = HType::Tagged()) { | 5628 HType type) { |
5723 return new(zone) HInnerAllocatedObject(value, offset, type); | 5629 return new(zone) HInnerAllocatedObject(value, offset, type); |
5724 } | 5630 } |
5725 | 5631 |
5726 HValue* base_object() { return OperandAt(0); } | 5632 HValue* base_object() { return OperandAt(0); } |
5727 HValue* offset() { return OperandAt(1); } | 5633 HValue* offset() { return OperandAt(1); } |
5728 | 5634 |
5729 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE { | 5635 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE { |
5730 return index == 0 ? Representation::Tagged() : Representation::Integer32(); | 5636 return index == 0 ? Representation::Tagged() : Representation::Integer32(); |
5731 } | 5637 } |
5732 | 5638 |
5733 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE; | 5639 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE; |
5734 | 5640 |
5735 DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject) | 5641 DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject) |
5736 | 5642 |
5737 private: | 5643 private: |
5738 HInnerAllocatedObject(HValue* value, | 5644 HInnerAllocatedObject(HValue* value, |
5739 HValue* offset, | 5645 HValue* offset, |
5740 HType type = HType::Tagged()) | 5646 HType type) : HTemplateInstruction<2>(type) { |
5741 : HTemplateInstruction<2>(type) { | |
5742 ASSERT(value->IsAllocate()); | 5647 ASSERT(value->IsAllocate()); |
| 5648 ASSERT(type.IsHeapObject()); |
5743 SetOperandAt(0, value); | 5649 SetOperandAt(0, value); |
5744 SetOperandAt(1, offset); | 5650 SetOperandAt(1, offset); |
5745 set_type(type); | |
5746 set_representation(Representation::Tagged()); | 5651 set_representation(Representation::Tagged()); |
5747 } | 5652 } |
5748 }; | 5653 }; |
5749 | 5654 |
5750 | 5655 |
5751 inline bool StoringValueNeedsWriteBarrier(HValue* value) { | 5656 inline bool StoringValueNeedsWriteBarrier(HValue* value) { |
5752 return !value->type().IsBoolean() | 5657 return !value->type().IsSmi() |
5753 && !value->type().IsSmi() | 5658 && !value->type().IsNull() |
| 5659 && !value->type().IsBoolean() |
| 5660 && !value->type().IsUndefined() |
5754 && !(value->IsConstant() && HConstant::cast(value)->ImmortalImmovable()); | 5661 && !(value->IsConstant() && HConstant::cast(value)->ImmortalImmovable()); |
5755 } | 5662 } |
5756 | 5663 |
5757 | 5664 |
5758 inline bool ReceiverObjectNeedsWriteBarrier(HValue* object, | 5665 inline bool ReceiverObjectNeedsWriteBarrier(HValue* object, |
5759 HValue* value, | 5666 HValue* value, |
5760 HValue* dominator) { | 5667 HValue* dominator) { |
5761 while (object->IsInnerAllocatedObject()) { | 5668 while (object->IsInnerAllocatedObject()) { |
5762 object = HInnerAllocatedObject::cast(object)->base_object(); | 5669 object = HInnerAllocatedObject::cast(object)->base_object(); |
5763 } | 5670 } |
(...skipping 600 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6364 if (SmiValuesAre32Bits()) { | 6271 if (SmiValuesAre32Bits()) { |
6365 set_representation(Representation::Integer32()); | 6272 set_representation(Representation::Integer32()); |
6366 } else { | 6273 } else { |
6367 set_representation(representation); | 6274 set_representation(representation); |
6368 } | 6275 } |
6369 } else if (representation.IsDouble() || | 6276 } else if (representation.IsDouble() || |
6370 representation.IsExternal() || | 6277 representation.IsExternal() || |
6371 representation.IsInteger32()) { | 6278 representation.IsInteger32()) { |
6372 set_representation(representation); | 6279 set_representation(representation); |
6373 } else if (representation.IsHeapObject()) { | 6280 } else if (representation.IsHeapObject()) { |
6374 // TODO(bmeurer): This is probably broken. What we actually want to to | 6281 set_type(HType::HeapObject()); |
6375 // instead is set_representation(Representation::HeapObject()). | |
6376 set_type(HType::NonPrimitive()); | |
6377 set_representation(Representation::Tagged()); | 6282 set_representation(Representation::Tagged()); |
6378 } else { | 6283 } else { |
6379 set_representation(Representation::Tagged()); | 6284 set_representation(Representation::Tagged()); |
6380 } | 6285 } |
6381 access.SetGVNFlags(this, LOAD); | 6286 access.SetGVNFlags(this, LOAD); |
6382 } | 6287 } |
6383 | 6288 |
6384 HLoadNamedField(HValue* object, | 6289 HLoadNamedField(HValue* object, |
6385 HValue* dependency, | 6290 HValue* dependency, |
6386 HObjectAccess access, | 6291 HObjectAccess access, |
6387 const UniqueSet<Map>* maps, | 6292 const UniqueSet<Map>* maps, |
6388 HType type) | 6293 HType type) |
6389 : HTemplateInstruction<2>(type), access_(access), maps_(maps) { | 6294 : HTemplateInstruction<2>(type), access_(access), maps_(maps) { |
6390 ASSERT_NOT_NULL(maps); | 6295 ASSERT_NOT_NULL(maps); |
6391 ASSERT_NE(0, maps->size()); | 6296 ASSERT_NE(0, maps->size()); |
6392 | 6297 |
6393 ASSERT_NOT_NULL(object); | 6298 ASSERT_NOT_NULL(object); |
6394 SetOperandAt(0, object); | 6299 SetOperandAt(0, object); |
6395 SetOperandAt(1, dependency ? dependency : object); | 6300 SetOperandAt(1, dependency ? dependency : object); |
6396 | 6301 |
6397 ASSERT(access.representation().IsHeapObject()); | 6302 ASSERT(access.representation().IsHeapObject()); |
6398 // TODO(bmeurer): This is probably broken. What we actually want to to | 6303 ASSERT(type.IsHeapObject()); |
6399 // instead is set_representation(Representation::HeapObject()). | |
6400 if (!type.IsHeapObject()) set_type(HType::NonPrimitive()); | |
6401 set_representation(Representation::Tagged()); | 6304 set_representation(Representation::Tagged()); |
6402 | 6305 |
6403 access.SetGVNFlags(this, LOAD); | 6306 access.SetGVNFlags(this, LOAD); |
6404 } | 6307 } |
6405 | 6308 |
6406 virtual bool IsDeletable() const V8_OVERRIDE { return true; } | 6309 virtual bool IsDeletable() const V8_OVERRIDE { return true; } |
6407 | 6310 |
6408 HObjectAccess access_; | 6311 HObjectAccess access_; |
6409 const UniqueSet<Map>* maps_; | 6312 const UniqueSet<Map>* maps_; |
6410 }; | 6313 }; |
(...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6806 new_space_dominator()); | 6709 new_space_dominator()); |
6807 } | 6710 } |
6808 | 6711 |
6809 bool NeedsWriteBarrierForMap() { | 6712 bool NeedsWriteBarrierForMap() { |
6810 return ReceiverObjectNeedsWriteBarrier(object(), transition(), | 6713 return ReceiverObjectNeedsWriteBarrier(object(), transition(), |
6811 new_space_dominator()); | 6714 new_space_dominator()); |
6812 } | 6715 } |
6813 | 6716 |
6814 SmiCheck SmiCheckForWriteBarrier() const { | 6717 SmiCheck SmiCheckForWriteBarrier() const { |
6815 if (field_representation().IsHeapObject()) return OMIT_SMI_CHECK; | 6718 if (field_representation().IsHeapObject()) return OMIT_SMI_CHECK; |
6816 if (value()->IsHeapObject()) return OMIT_SMI_CHECK; | 6719 if (value()->type().IsHeapObject()) return OMIT_SMI_CHECK; |
6817 return INLINE_SMI_CHECK; | 6720 return INLINE_SMI_CHECK; |
6818 } | 6721 } |
6819 | 6722 |
6820 Representation field_representation() const { | 6723 Representation field_representation() const { |
6821 return access_.representation(); | 6724 return access_.representation(); |
6822 } | 6725 } |
6823 | 6726 |
6824 void UpdateValue(HValue* value) { | 6727 void UpdateValue(HValue* value) { |
6825 SetOperandAt(1, value); | 6728 SetOperandAt(1, value); |
6826 } | 6729 } |
(...skipping 839 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7666 public: | 7569 public: |
7667 DECLARE_INSTRUCTION_FACTORY_P2(HCheckMapValue, HValue*, HValue*); | 7570 DECLARE_INSTRUCTION_FACTORY_P2(HCheckMapValue, HValue*, HValue*); |
7668 | 7571 |
7669 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE { | 7572 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE { |
7670 return Representation::Tagged(); | 7573 return Representation::Tagged(); |
7671 } | 7574 } |
7672 | 7575 |
7673 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE; | 7576 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE; |
7674 | 7577 |
7675 virtual HType CalculateInferredType() V8_OVERRIDE { | 7578 virtual HType CalculateInferredType() V8_OVERRIDE { |
7676 return HType::Tagged(); | 7579 if (value()->type().IsHeapObject()) return value()->type(); |
| 7580 return HType::HeapObject(); |
7677 } | 7581 } |
7678 | 7582 |
7679 HValue* value() { return OperandAt(0); } | 7583 HValue* value() const { return OperandAt(0); } |
7680 HValue* map() { return OperandAt(1); } | 7584 HValue* map() const { return OperandAt(1); } |
7681 | 7585 |
7682 virtual HValue* Canonicalize() V8_OVERRIDE; | 7586 virtual HValue* Canonicalize() V8_OVERRIDE; |
7683 | 7587 |
7684 DECLARE_CONCRETE_INSTRUCTION(CheckMapValue) | 7588 DECLARE_CONCRETE_INSTRUCTION(CheckMapValue) |
7685 | 7589 |
7686 protected: | 7590 protected: |
7687 virtual int RedefinedOperandIndex() { return 0; } | 7591 virtual int RedefinedOperandIndex() { return 0; } |
7688 | 7592 |
7689 virtual bool DataEquals(HValue* other) V8_OVERRIDE { | 7593 virtual bool DataEquals(HValue* other) V8_OVERRIDE { |
7690 return true; | 7594 return true; |
7691 } | 7595 } |
7692 | 7596 |
7693 private: | 7597 private: |
7694 HCheckMapValue(HValue* value, | 7598 HCheckMapValue(HValue* value, HValue* map) |
7695 HValue* map) { | 7599 : HTemplateInstruction<2>(HType::HeapObject()) { |
7696 SetOperandAt(0, value); | 7600 SetOperandAt(0, value); |
7697 SetOperandAt(1, map); | 7601 SetOperandAt(1, map); |
7698 set_representation(Representation::Tagged()); | 7602 set_representation(Representation::Tagged()); |
7699 SetFlag(kUseGVN); | 7603 SetFlag(kUseGVN); |
7700 SetDependsOnFlag(kMaps); | 7604 SetDependsOnFlag(kMaps); |
7701 SetDependsOnFlag(kElementsKind); | 7605 SetDependsOnFlag(kElementsKind); |
7702 } | 7606 } |
7703 }; | 7607 }; |
7704 | 7608 |
7705 | 7609 |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7810 virtual bool IsDeletable() const V8_OVERRIDE { return true; } | 7714 virtual bool IsDeletable() const V8_OVERRIDE { return true; } |
7811 }; | 7715 }; |
7812 | 7716 |
7813 | 7717 |
7814 #undef DECLARE_INSTRUCTION | 7718 #undef DECLARE_INSTRUCTION |
7815 #undef DECLARE_CONCRETE_INSTRUCTION | 7719 #undef DECLARE_CONCRETE_INSTRUCTION |
7816 | 7720 |
7817 } } // namespace v8::internal | 7721 } } // namespace v8::internal |
7818 | 7722 |
7819 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ | 7723 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ |
OLD | NEW |