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 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
341 bool IsNone() const { return kind_ == kNone; } | 341 bool IsNone() const { return kind_ == kNone; } |
342 bool IsTagged() const { return kind_ == kTagged; } | 342 bool IsTagged() const { return kind_ == kTagged; } |
343 bool IsInteger32() const { return kind_ == kInteger32; } | 343 bool IsInteger32() const { return kind_ == kInteger32; } |
344 bool IsDouble() const { return kind_ == kDouble; } | 344 bool IsDouble() const { return kind_ == kDouble; } |
345 bool IsExternal() const { return kind_ == kExternal; } | 345 bool IsExternal() const { return kind_ == kExternal; } |
346 bool IsSpecialization() const { | 346 bool IsSpecialization() const { |
347 return kind_ == kInteger32 || kind_ == kDouble; | 347 return kind_ == kInteger32 || kind_ == kDouble; |
348 } | 348 } |
349 const char* Mnemonic() const; | 349 const char* Mnemonic() const; |
350 | 350 |
351 Representation KeyedAccessIndexRequirement() { | |
352 // This is intended to be used in RequiredInputRepresentation for keyed | |
353 // loads and stores to avoid inserting unneeded HChange instructions: | |
354 // keyed loads and stores can work on both int32 and tagged indexes. | |
355 return IsInteger32() ? Integer32() : Tagged(); | |
356 } | |
357 | |
358 private: | 351 private: |
359 explicit Representation(Kind k) : kind_(k) { } | 352 explicit Representation(Kind k) : kind_(k) { } |
360 | 353 |
361 // Make sure kind fits in int8. | 354 // Make sure kind fits in int8. |
362 STATIC_ASSERT(kNumRepresentations <= (1 << kBitsPerByte)); | 355 STATIC_ASSERT(kNumRepresentations <= (1 << kBitsPerByte)); |
363 | 356 |
364 int8_t kind_; | 357 int8_t kind_; |
365 }; | 358 }; |
366 | 359 |
367 | 360 |
(...skipping 2459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2827 | 2820 |
2828 HValue* receiver() { return OperandAt(0); } | 2821 HValue* receiver() { return OperandAt(0); } |
2829 HValue* function() { return OperandAt(1); } | 2822 HValue* function() { return OperandAt(1); } |
2830 | 2823 |
2831 virtual HValue* Canonicalize(); | 2824 virtual HValue* Canonicalize(); |
2832 | 2825 |
2833 DECLARE_CONCRETE_INSTRUCTION(WrapReceiver) | 2826 DECLARE_CONCRETE_INSTRUCTION(WrapReceiver) |
2834 }; | 2827 }; |
2835 | 2828 |
2836 | 2829 |
2837 enum BoundsCheckKeyMode { | |
2838 DONT_ALLOW_SMI_KEY, | |
2839 ALLOW_SMI_KEY | |
2840 }; | |
2841 | |
2842 | |
2843 class HBoundsCheck: public HTemplateInstruction<2> { | |
2844 public: | |
2845 HBoundsCheck(HValue* index, HValue* length, | |
2846 BoundsCheckKeyMode key_mode = DONT_ALLOW_SMI_KEY) | |
2847 : key_mode_(key_mode) { | |
2848 SetOperandAt(0, index); | |
2849 SetOperandAt(1, length); | |
2850 set_representation(Representation::Integer32()); | |
2851 SetFlag(kUseGVN); | |
2852 } | |
2853 | |
2854 virtual Representation RequiredInputRepresentation(int arg_index) { | |
2855 if (key_mode_ == DONT_ALLOW_SMI_KEY || | |
2856 !length()->representation().IsTagged()) { | |
2857 return Representation::Integer32(); | |
2858 } | |
2859 // If the index is tagged and isn't constant, then allow the length | |
2860 // to be tagged, since it is usually already tagged from loading it out of | |
2861 // the length field of a JSArray. This allows for direct comparison without | |
2862 // untagging. | |
2863 if (index()->representation().IsTagged() && !index()->IsConstant()) { | |
2864 return Representation::Tagged(); | |
2865 } | |
2866 // Also allow the length to be tagged if the index is constant, because | |
2867 // it can be tagged to allow direct comparison. | |
2868 if (index()->IsConstant() && | |
2869 index()->representation().IsInteger32() && | |
2870 arg_index == 1) { | |
2871 return Representation::Tagged(); | |
2872 } | |
2873 return Representation::Integer32(); | |
2874 } | |
2875 virtual Representation observed_input_representation(int index) { | |
2876 return Representation::Integer32(); | |
2877 } | |
2878 | |
2879 virtual void PrintDataTo(StringStream* stream); | |
2880 | |
2881 HValue* index() { return OperandAt(0); } | |
2882 HValue* length() { return OperandAt(1); } | |
2883 | |
2884 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck) | |
2885 | |
2886 static HValue* ExtractUncheckedIndex(HValue* index) { | |
2887 return index->IsBoundsCheck() ? HBoundsCheck::cast(index)->index() : index; | |
2888 } | |
2889 | |
2890 protected: | |
2891 virtual bool DataEquals(HValue* other) { return true; } | |
2892 BoundsCheckKeyMode key_mode_; | |
2893 }; | |
2894 | |
2895 | |
2896 class HApplyArguments: public HTemplateInstruction<4> { | 2830 class HApplyArguments: public HTemplateInstruction<4> { |
2897 public: | 2831 public: |
2898 HApplyArguments(HValue* function, | 2832 HApplyArguments(HValue* function, |
2899 HValue* receiver, | 2833 HValue* receiver, |
2900 HValue* length, | 2834 HValue* length, |
2901 HValue* elements) { | 2835 HValue* elements) { |
2902 set_representation(Representation::Tagged()); | 2836 set_representation(Representation::Tagged()); |
2903 SetOperandAt(0, function); | 2837 SetOperandAt(0, function); |
2904 SetOperandAt(1, receiver); | 2838 SetOperandAt(1, receiver); |
2905 SetOperandAt(2, length); | 2839 SetOperandAt(2, length); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2964 DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength) | 2898 DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength) |
2965 | 2899 |
2966 protected: | 2900 protected: |
2967 virtual bool DataEquals(HValue* other) { return true; } | 2901 virtual bool DataEquals(HValue* other) { return true; } |
2968 | 2902 |
2969 private: | 2903 private: |
2970 virtual bool IsDeletable() const { return true; } | 2904 virtual bool IsDeletable() const { return true; } |
2971 }; | 2905 }; |
2972 | 2906 |
2973 | 2907 |
2974 class HAccessArgumentsAt: public HTemplateInstruction<4> { | 2908 class HAccessArgumentsAt: public HTemplateInstruction<3> { |
2975 public: | 2909 public: |
2976 HAccessArgumentsAt(HValue* arguments, | 2910 HAccessArgumentsAt(HValue* arguments, HValue* length, HValue* index) { |
2977 HValue* length, | |
2978 HValue* checked_index) { | |
2979 set_representation(Representation::Tagged()); | 2911 set_representation(Representation::Tagged()); |
2980 SetFlag(kUseGVN); | 2912 SetFlag(kUseGVN); |
2981 SetOperandAt(0, arguments); | 2913 SetOperandAt(0, arguments); |
2982 SetOperandAt(1, length); | 2914 SetOperandAt(1, length); |
2983 SetOperandAt(2, HBoundsCheck::ExtractUncheckedIndex(checked_index)); | 2915 SetOperandAt(2, index); |
2984 SetOperandAt(3, checked_index); | |
2985 } | 2916 } |
2986 | 2917 |
2987 virtual void PrintDataTo(StringStream* stream); | 2918 virtual void PrintDataTo(StringStream* stream); |
2988 | 2919 |
2989 virtual Representation RequiredInputRepresentation(int index) { | 2920 virtual Representation RequiredInputRepresentation(int index) { |
2990 switch (index) { | 2921 // The arguments elements is considered tagged. |
2991 // The arguments elements is considered tagged. | 2922 return index == 0 |
2992 case 0: return Representation::Tagged(); | 2923 ? Representation::Tagged() |
2993 case 1: return Representation::Integer32(); | 2924 : Representation::Integer32(); |
2994 case 2: return Representation::Integer32(); | |
2995 // The checked index is a control flow dependency to avoid hoisting | |
2996 // and therefore it has no representation requirements. | |
2997 case 3: return Representation::None(); | |
2998 default: { | |
2999 UNREACHABLE(); | |
3000 return Representation::None(); | |
3001 } | |
3002 } | |
3003 } | 2925 } |
3004 | 2926 |
3005 HValue* arguments() { return OperandAt(0); } | 2927 HValue* arguments() { return OperandAt(0); } |
3006 HValue* length() { return OperandAt(1); } | 2928 HValue* length() { return OperandAt(1); } |
3007 HValue* index() { return OperandAt(2); } | 2929 HValue* index() { return OperandAt(2); } |
3008 HValue* checked_index() { return OperandAt(3); } | |
3009 | 2930 |
3010 DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt) | 2931 DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt) |
3011 | 2932 |
3012 virtual bool DataEquals(HValue* other) { return true; } | 2933 virtual bool DataEquals(HValue* other) { return true; } |
3013 }; | 2934 }; |
3014 | 2935 |
3015 | 2936 |
| 2937 enum BoundsCheckKeyMode { |
| 2938 DONT_ALLOW_SMI_KEY, |
| 2939 ALLOW_SMI_KEY |
| 2940 }; |
| 2941 |
| 2942 |
| 2943 class HBoundsCheck: public HTemplateInstruction<2> { |
| 2944 public: |
| 2945 HBoundsCheck(HValue* index, HValue* length, |
| 2946 BoundsCheckKeyMode key_mode = DONT_ALLOW_SMI_KEY) |
| 2947 : key_mode_(key_mode) { |
| 2948 SetOperandAt(0, index); |
| 2949 SetOperandAt(1, length); |
| 2950 set_representation(Representation::Integer32()); |
| 2951 SetFlag(kUseGVN); |
| 2952 } |
| 2953 |
| 2954 virtual Representation RequiredInputRepresentation(int arg_index) { |
| 2955 if (key_mode_ == DONT_ALLOW_SMI_KEY || |
| 2956 !length()->representation().IsTagged()) { |
| 2957 return Representation::Integer32(); |
| 2958 } |
| 2959 // If the index is tagged and isn't constant, then allow the length |
| 2960 // to be tagged, since it is usually already tagged from loading it out of |
| 2961 // the length field of a JSArray. This allows for direct comparison without |
| 2962 // untagging. |
| 2963 if (index()->representation().IsTagged() && !index()->IsConstant()) { |
| 2964 return Representation::Tagged(); |
| 2965 } |
| 2966 // Also allow the length to be tagged if the index is constant, because |
| 2967 // it can be tagged to allow direct comparison. |
| 2968 if (index()->IsConstant() && |
| 2969 index()->representation().IsInteger32() && |
| 2970 arg_index == 1) { |
| 2971 return Representation::Tagged(); |
| 2972 } |
| 2973 return Representation::Integer32(); |
| 2974 } |
| 2975 virtual Representation observed_input_representation(int index) { |
| 2976 return Representation::Integer32(); |
| 2977 } |
| 2978 |
| 2979 virtual void PrintDataTo(StringStream* stream); |
| 2980 |
| 2981 HValue* index() { return OperandAt(0); } |
| 2982 HValue* length() { return OperandAt(1); } |
| 2983 |
| 2984 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck) |
| 2985 |
| 2986 protected: |
| 2987 virtual bool DataEquals(HValue* other) { return true; } |
| 2988 BoundsCheckKeyMode key_mode_; |
| 2989 }; |
| 2990 |
| 2991 |
3016 class HBitwiseBinaryOperation: public HBinaryOperation { | 2992 class HBitwiseBinaryOperation: public HBinaryOperation { |
3017 public: | 2993 public: |
3018 HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right) | 2994 HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right) |
3019 : HBinaryOperation(context, left, right) { | 2995 : HBinaryOperation(context, left, right) { |
3020 SetFlag(kFlexibleRepresentation); | 2996 SetFlag(kFlexibleRepresentation); |
3021 SetFlag(kTruncatingToInt32); | 2997 SetFlag(kTruncatingToInt32); |
3022 SetAllSideEffects(); | 2998 SetAllSideEffects(); |
3023 } | 2999 } |
3024 | 3000 |
3025 virtual Representation RequiredInputRepresentation(int index) { | 3001 virtual Representation RequiredInputRepresentation(int index) { |
(...skipping 1346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4372 virtual HValue* GetKey() = 0; | 4348 virtual HValue* GetKey() = 0; |
4373 virtual void SetKey(HValue* key) = 0; | 4349 virtual void SetKey(HValue* key) = 0; |
4374 virtual void SetIndexOffset(uint32_t index_offset) = 0; | 4350 virtual void SetIndexOffset(uint32_t index_offset) = 0; |
4375 virtual bool IsDehoisted() = 0; | 4351 virtual bool IsDehoisted() = 0; |
4376 virtual void SetDehoisted(bool is_dehoisted) = 0; | 4352 virtual void SetDehoisted(bool is_dehoisted) = 0; |
4377 virtual ~ArrayInstructionInterface() { }; | 4353 virtual ~ArrayInstructionInterface() { }; |
4378 }; | 4354 }; |
4379 | 4355 |
4380 | 4356 |
4381 class HLoadKeyed | 4357 class HLoadKeyed |
4382 : public HTemplateInstruction<4>, public ArrayInstructionInterface { | 4358 : public HTemplateInstruction<3>, public ArrayInstructionInterface { |
4383 public: | 4359 public: |
4384 HLoadKeyed(HValue* obj, | 4360 HLoadKeyed(HValue* obj, |
4385 HValue* checked_key, | 4361 HValue* key, |
4386 HValue* dependency, | 4362 HValue* dependency, |
4387 ElementsKind elements_kind) | 4363 ElementsKind elements_kind) |
4388 : bit_field_(0) { | 4364 : bit_field_(0) { |
4389 bit_field_ = ElementsKindField::encode(elements_kind); | 4365 bit_field_ = ElementsKindField::encode(elements_kind); |
| 4366 |
4390 SetOperandAt(0, obj); | 4367 SetOperandAt(0, obj); |
4391 SetOperandAt(1, HBoundsCheck::ExtractUncheckedIndex(checked_key)); | 4368 SetOperandAt(1, key); |
4392 SetOperandAt(2, dependency); | 4369 SetOperandAt(2, dependency); |
4393 SetOperandAt(3, checked_key); | |
4394 | 4370 |
4395 if (!is_external()) { | 4371 if (!is_external()) { |
4396 // I can detect the case between storing double (holey and fast) and | 4372 // I can detect the case between storing double (holey and fast) and |
4397 // smi/object by looking at elements_kind_. | 4373 // smi/object by looking at elements_kind_. |
4398 ASSERT(IsFastSmiOrObjectElementsKind(elements_kind) || | 4374 ASSERT(IsFastSmiOrObjectElementsKind(elements_kind) || |
4399 IsFastDoubleElementsKind(elements_kind)); | 4375 IsFastDoubleElementsKind(elements_kind)); |
4400 | 4376 |
4401 if (IsFastSmiOrObjectElementsKind(elements_kind)) { | 4377 if (IsFastSmiOrObjectElementsKind(elements_kind)) { |
4402 if (IsFastSmiElementsKind(elements_kind) && | 4378 if (IsFastSmiElementsKind(elements_kind) && |
4403 IsFastPackedElementsKind(elements_kind)) { | 4379 IsFastPackedElementsKind(elements_kind)) { |
(...skipping 21 matching lines...) Expand all Loading... |
4425 | 4401 |
4426 SetFlag(kUseGVN); | 4402 SetFlag(kUseGVN); |
4427 } | 4403 } |
4428 | 4404 |
4429 bool is_external() const { | 4405 bool is_external() const { |
4430 return IsExternalArrayElementsKind(elements_kind()); | 4406 return IsExternalArrayElementsKind(elements_kind()); |
4431 } | 4407 } |
4432 HValue* elements() { return OperandAt(0); } | 4408 HValue* elements() { return OperandAt(0); } |
4433 HValue* key() { return OperandAt(1); } | 4409 HValue* key() { return OperandAt(1); } |
4434 HValue* dependency() { return OperandAt(2); } | 4410 HValue* dependency() { return OperandAt(2); } |
4435 HValue* checked_key() { return OperandAt(3); } | |
4436 uint32_t index_offset() { return IndexOffsetField::decode(bit_field_); } | 4411 uint32_t index_offset() { return IndexOffsetField::decode(bit_field_); } |
4437 void SetIndexOffset(uint32_t index_offset) { | 4412 void SetIndexOffset(uint32_t index_offset) { |
4438 bit_field_ = IndexOffsetField::update(bit_field_, index_offset); | 4413 bit_field_ = IndexOffsetField::update(bit_field_, index_offset); |
4439 } | 4414 } |
4440 HValue* GetKey() { return key(); } | 4415 HValue* GetKey() { return key(); } |
4441 void SetKey(HValue* key) { SetOperandAt(1, key); } | 4416 void SetKey(HValue* key) { SetOperandAt(1, key); } |
4442 bool IsDehoisted() { return IsDehoistedField::decode(bit_field_); } | 4417 bool IsDehoisted() { return IsDehoistedField::decode(bit_field_); } |
4443 void SetDehoisted(bool is_dehoisted) { | 4418 void SetDehoisted(bool is_dehoisted) { |
4444 bit_field_ = IsDehoistedField::update(bit_field_, is_dehoisted); | 4419 bit_field_ = IsDehoistedField::update(bit_field_, is_dehoisted); |
4445 } | 4420 } |
4446 ElementsKind elements_kind() const { | 4421 ElementsKind elements_kind() const { |
4447 return ElementsKindField::decode(bit_field_); | 4422 return ElementsKindField::decode(bit_field_); |
4448 } | 4423 } |
4449 | 4424 |
4450 virtual Representation RequiredInputRepresentation(int index) { | 4425 virtual Representation RequiredInputRepresentation(int index) { |
4451 // kind_fast: tagged[int32] (none) | 4426 // kind_fast: tagged[int32] (none) |
4452 // kind_double: tagged[int32] (none) | 4427 // kind_double: tagged[int32] (none) |
4453 // kind_external: external[int32] (none) | 4428 // kind_external: external[int32] (none) |
4454 if (index == 0) { | 4429 if (index == 0) { |
4455 return is_external() ? Representation::External() | 4430 return is_external() ? Representation::External() |
4456 : Representation::Tagged(); | 4431 : Representation::Tagged(); |
4457 } | 4432 } |
4458 if (index == 1) { | 4433 if (index == 1) return Representation::Integer32(); |
4459 return OperandAt(1)->representation().KeyedAccessIndexRequirement(); | |
4460 } | |
4461 return Representation::None(); | 4434 return Representation::None(); |
4462 } | 4435 } |
4463 | 4436 |
4464 virtual Representation observed_input_representation(int index) { | 4437 virtual Representation observed_input_representation(int index) { |
4465 return RequiredInputRepresentation(index); | 4438 return RequiredInputRepresentation(index); |
4466 } | 4439 } |
4467 | 4440 |
4468 virtual void PrintDataTo(StringStream* stream); | 4441 virtual void PrintDataTo(StringStream* stream); |
4469 | 4442 |
4470 bool RequiresHoleCheck() const; | 4443 bool RequiresHoleCheck() const; |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4632 | 4605 |
4633 DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric) | 4606 DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric) |
4634 | 4607 |
4635 private: | 4608 private: |
4636 Handle<String> name_; | 4609 Handle<String> name_; |
4637 StrictModeFlag strict_mode_flag_; | 4610 StrictModeFlag strict_mode_flag_; |
4638 }; | 4611 }; |
4639 | 4612 |
4640 | 4613 |
4641 class HStoreKeyed | 4614 class HStoreKeyed |
4642 : public HTemplateInstruction<4>, public ArrayInstructionInterface { | 4615 : public HTemplateInstruction<3>, public ArrayInstructionInterface { |
4643 public: | 4616 public: |
4644 HStoreKeyed(HValue* obj, HValue* checked_key, HValue* val, | 4617 HStoreKeyed(HValue* obj, HValue* key, HValue* val, |
4645 ElementsKind elements_kind) | 4618 ElementsKind elements_kind) |
4646 : elements_kind_(elements_kind), index_offset_(0), is_dehoisted_(false) { | 4619 : elements_kind_(elements_kind), index_offset_(0), is_dehoisted_(false) { |
4647 SetOperandAt(0, obj); | 4620 SetOperandAt(0, obj); |
4648 SetOperandAt(1, HBoundsCheck::ExtractUncheckedIndex(checked_key)); | 4621 SetOperandAt(1, key); |
4649 SetOperandAt(2, val); | 4622 SetOperandAt(2, val); |
4650 SetOperandAt(3, checked_key); | |
4651 | 4623 |
4652 if (is_external()) { | 4624 if (is_external()) { |
4653 SetGVNFlag(kChangesSpecializedArrayElements); | 4625 SetGVNFlag(kChangesSpecializedArrayElements); |
4654 } else if (IsFastDoubleElementsKind(elements_kind)) { | 4626 } else if (IsFastDoubleElementsKind(elements_kind)) { |
4655 SetGVNFlag(kChangesDoubleArrayElements); | 4627 SetGVNFlag(kChangesDoubleArrayElements); |
4656 SetFlag(kDeoptimizeOnUndefined); | 4628 SetFlag(kDeoptimizeOnUndefined); |
4657 } else { | 4629 } else { |
4658 SetGVNFlag(kChangesArrayElements); | 4630 SetGVNFlag(kChangesArrayElements); |
4659 } | 4631 } |
4660 | 4632 |
4661 // EXTERNAL_{UNSIGNED_,}{BYTE,SHORT,INT}_ELEMENTS are truncating. | 4633 // EXTERNAL_{UNSIGNED_,}{BYTE,SHORT,INT}_ELEMENTS are truncating. |
4662 if (elements_kind >= EXTERNAL_BYTE_ELEMENTS && | 4634 if (elements_kind >= EXTERNAL_BYTE_ELEMENTS && |
4663 elements_kind <= EXTERNAL_UNSIGNED_INT_ELEMENTS) { | 4635 elements_kind <= EXTERNAL_UNSIGNED_INT_ELEMENTS) { |
4664 SetFlag(kTruncatingToInt32); | 4636 SetFlag(kTruncatingToInt32); |
4665 } | 4637 } |
4666 } | 4638 } |
4667 | 4639 |
4668 virtual Representation RequiredInputRepresentation(int index) { | 4640 virtual Representation RequiredInputRepresentation(int index) { |
4669 // kind_fast: tagged[int32] = tagged | 4641 // kind_fast: tagged[int32] = tagged |
4670 // kind_double: tagged[int32] = double | 4642 // kind_double: tagged[int32] = double |
4671 // kind_external: external[int32] = (double | int32) | 4643 // kind_external: external[int32] = (double | int32) |
4672 if (index == 0) { | 4644 if (index == 0) { |
4673 return is_external() ? Representation::External() | 4645 return is_external() ? Representation::External() |
4674 : Representation::Tagged(); | 4646 : Representation::Tagged(); |
4675 } else if (index == 1) { | 4647 } else if (index == 1) { |
4676 return OperandAt(1)->representation().KeyedAccessIndexRequirement(); | 4648 return Representation::Integer32(); |
4677 } else if (index == 3) { | |
4678 return Representation::None(); | |
4679 } | 4649 } |
4680 | 4650 |
4681 ASSERT_EQ(index, 2); | 4651 ASSERT_EQ(index, 2); |
4682 if (IsDoubleOrFloatElementsKind(elements_kind())) { | 4652 if (IsDoubleOrFloatElementsKind(elements_kind())) { |
4683 return Representation::Double(); | 4653 return Representation::Double(); |
4684 } | 4654 } |
4685 | 4655 |
4686 return is_external() ? Representation::Integer32() | 4656 return is_external() ? Representation::Integer32() |
4687 : Representation::Tagged(); | 4657 : Representation::Tagged(); |
4688 } | 4658 } |
(...skipping 10 matching lines...) Expand all Loading... |
4699 if (is_external()) { | 4669 if (is_external()) { |
4700 return Representation::Integer32(); | 4670 return Representation::Integer32(); |
4701 } | 4671 } |
4702 // For fast object elements kinds, don't assume anything. | 4672 // For fast object elements kinds, don't assume anything. |
4703 return Representation::None(); | 4673 return Representation::None(); |
4704 } | 4674 } |
4705 | 4675 |
4706 HValue* elements() { return OperandAt(0); } | 4676 HValue* elements() { return OperandAt(0); } |
4707 HValue* key() { return OperandAt(1); } | 4677 HValue* key() { return OperandAt(1); } |
4708 HValue* value() { return OperandAt(2); } | 4678 HValue* value() { return OperandAt(2); } |
4709 HValue* checked_key() { return OperandAt(3); } | |
4710 bool value_is_smi() const { | 4679 bool value_is_smi() const { |
4711 return IsFastSmiElementsKind(elements_kind_); | 4680 return IsFastSmiElementsKind(elements_kind_); |
4712 } | 4681 } |
4713 ElementsKind elements_kind() const { return elements_kind_; } | 4682 ElementsKind elements_kind() const { return elements_kind_; } |
4714 uint32_t index_offset() { return index_offset_; } | 4683 uint32_t index_offset() { return index_offset_; } |
4715 void SetIndexOffset(uint32_t index_offset) { index_offset_ = index_offset; } | 4684 void SetIndexOffset(uint32_t index_offset) { index_offset_ = index_offset; } |
4716 HValue* GetKey() { return key(); } | 4685 HValue* GetKey() { return key(); } |
4717 void SetKey(HValue* key) { SetOperandAt(1, key); } | 4686 void SetKey(HValue* key) { SetOperandAt(1, key); } |
4718 bool IsDehoisted() { return is_dehoisted_; } | 4687 bool IsDehoisted() { return is_dehoisted_; } |
4719 void SetDehoisted(bool is_dehoisted) { is_dehoisted_ = is_dehoisted; } | 4688 void SetDehoisted(bool is_dehoisted) { is_dehoisted_ = is_dehoisted; } |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4842 | 4811 |
4843 protected: | 4812 protected: |
4844 virtual bool DataEquals(HValue* other) { return true; } | 4813 virtual bool DataEquals(HValue* other) { return true; } |
4845 | 4814 |
4846 // TODO(svenpanne) Might be safe, but leave it out until we know for sure. | 4815 // TODO(svenpanne) Might be safe, but leave it out until we know for sure. |
4847 // private: | 4816 // private: |
4848 // virtual bool IsDeletable() const { return true; } | 4817 // virtual bool IsDeletable() const { return true; } |
4849 }; | 4818 }; |
4850 | 4819 |
4851 | 4820 |
4852 class HStringCharCodeAt: public HTemplateInstruction<4> { | 4821 class HStringCharCodeAt: public HTemplateInstruction<3> { |
4853 public: | 4822 public: |
4854 HStringCharCodeAt(HValue* context, HValue* string, HValue* checked_index) { | 4823 HStringCharCodeAt(HValue* context, HValue* string, HValue* index) { |
4855 SetOperandAt(0, context); | 4824 SetOperandAt(0, context); |
4856 SetOperandAt(1, string); | 4825 SetOperandAt(1, string); |
4857 SetOperandAt(2, HBoundsCheck::ExtractUncheckedIndex(checked_index)); | 4826 SetOperandAt(2, index); |
4858 SetOperandAt(3, checked_index); | |
4859 set_representation(Representation::Integer32()); | 4827 set_representation(Representation::Integer32()); |
4860 SetFlag(kUseGVN); | 4828 SetFlag(kUseGVN); |
4861 SetGVNFlag(kDependsOnMaps); | 4829 SetGVNFlag(kDependsOnMaps); |
4862 SetGVNFlag(kChangesNewSpacePromotion); | 4830 SetGVNFlag(kChangesNewSpacePromotion); |
4863 } | 4831 } |
4864 | 4832 |
4865 virtual Representation RequiredInputRepresentation(int index) { | 4833 virtual Representation RequiredInputRepresentation(int index) { |
4866 switch (index) { | 4834 // The index is supposed to be Integer32. |
4867 case 0: return Representation::Tagged(); | 4835 return index == 2 |
4868 case 1: return Representation::Tagged(); | 4836 ? Representation::Integer32() |
4869 // The index is supposed to be Integer32. | 4837 : Representation::Tagged(); |
4870 case 2: return Representation::Integer32(); | |
4871 // The checked index is a control flow dependency to avoid hoisting | |
4872 // and therefore it has no representation requirements. | |
4873 case 3: return Representation::None(); | |
4874 default: { | |
4875 UNREACHABLE(); | |
4876 return Representation::None(); | |
4877 } | |
4878 } | |
4879 } | 4838 } |
4880 | 4839 |
4881 HValue* context() { return OperandAt(0); } | 4840 HValue* context() { return OperandAt(0); } |
4882 HValue* string() { return OperandAt(1); } | 4841 HValue* string() { return OperandAt(1); } |
4883 HValue* index() { return OperandAt(2); } | 4842 HValue* index() { return OperandAt(2); } |
4884 HValue* checked_index() { return OperandAt(3); } | |
4885 | 4843 |
4886 DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt) | 4844 DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt) |
4887 | 4845 |
4888 protected: | 4846 protected: |
4889 virtual bool DataEquals(HValue* other) { return true; } | 4847 virtual bool DataEquals(HValue* other) { return true; } |
4890 | 4848 |
4891 virtual Range* InferRange(Zone* zone) { | 4849 virtual Range* InferRange(Zone* zone) { |
4892 return new(zone) Range(0, String::kMaxUtf16CodeUnit); | 4850 return new(zone) Range(0, String::kMaxUtf16CodeUnit); |
4893 } | 4851 } |
4894 | 4852 |
(...skipping 577 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5472 virtual bool IsDeletable() const { return true; } | 5430 virtual bool IsDeletable() const { return true; } |
5473 }; | 5431 }; |
5474 | 5432 |
5475 | 5433 |
5476 #undef DECLARE_INSTRUCTION | 5434 #undef DECLARE_INSTRUCTION |
5477 #undef DECLARE_CONCRETE_INSTRUCTION | 5435 #undef DECLARE_CONCRETE_INSTRUCTION |
5478 | 5436 |
5479 } } // namespace v8::internal | 5437 } } // namespace v8::internal |
5480 | 5438 |
5481 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ | 5439 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ |
OLD | NEW |