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 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
340 bool IsNone() const { return kind_ == kNone; } | 340 bool IsNone() const { return kind_ == kNone; } |
341 bool IsTagged() const { return kind_ == kTagged; } | 341 bool IsTagged() const { return kind_ == kTagged; } |
342 bool IsInteger32() const { return kind_ == kInteger32; } | 342 bool IsInteger32() const { return kind_ == kInteger32; } |
343 bool IsDouble() const { return kind_ == kDouble; } | 343 bool IsDouble() const { return kind_ == kDouble; } |
344 bool IsExternal() const { return kind_ == kExternal; } | 344 bool IsExternal() const { return kind_ == kExternal; } |
345 bool IsSpecialization() const { | 345 bool IsSpecialization() const { |
346 return kind_ == kInteger32 || kind_ == kDouble; | 346 return kind_ == kInteger32 || kind_ == kDouble; |
347 } | 347 } |
348 const char* Mnemonic() const; | 348 const char* Mnemonic() const; |
349 | 349 |
350 Representation KeyedAccessIndexRequirement() { | |
351 return IsInteger32() ? Integer32() : Tagged(); | |
352 } | |
353 | |
350 private: | 354 private: |
351 explicit Representation(Kind k) : kind_(k) { } | 355 explicit Representation(Kind k) : kind_(k) { } |
352 | 356 |
353 // Make sure kind fits in int8. | 357 // Make sure kind fits in int8. |
354 STATIC_ASSERT(kNumRepresentations <= (1 << kBitsPerByte)); | 358 STATIC_ASSERT(kNumRepresentations <= (1 << kBitsPerByte)); |
355 | 359 |
356 int8_t kind_; | 360 int8_t kind_; |
357 }; | 361 }; |
358 | 362 |
359 | 363 |
(...skipping 2459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2819 | 2823 |
2820 HValue* receiver() { return OperandAt(0); } | 2824 HValue* receiver() { return OperandAt(0); } |
2821 HValue* function() { return OperandAt(1); } | 2825 HValue* function() { return OperandAt(1); } |
2822 | 2826 |
2823 virtual HValue* Canonicalize(); | 2827 virtual HValue* Canonicalize(); |
2824 | 2828 |
2825 DECLARE_CONCRETE_INSTRUCTION(WrapReceiver) | 2829 DECLARE_CONCRETE_INSTRUCTION(WrapReceiver) |
2826 }; | 2830 }; |
2827 | 2831 |
2828 | 2832 |
2833 enum BoundsCheckKeyMode { | |
2834 DONT_ALLOW_SMI_KEY, | |
2835 ALLOW_SMI_KEY | |
2836 }; | |
2837 | |
2838 | |
2839 class HBoundsCheck: public HTemplateInstruction<2> { | |
2840 public: | |
2841 HBoundsCheck(HValue* index, HValue* length, | |
2842 BoundsCheckKeyMode key_mode = DONT_ALLOW_SMI_KEY) | |
2843 : key_mode_(key_mode) { | |
2844 SetOperandAt(0, index); | |
2845 SetOperandAt(1, length); | |
2846 set_representation(Representation::Integer32()); | |
2847 SetFlag(kUseGVN); | |
2848 } | |
2849 | |
2850 virtual Representation RequiredInputRepresentation(int arg_index) { | |
2851 if (key_mode_ == DONT_ALLOW_SMI_KEY || | |
2852 !length()->representation().IsTagged()) { | |
2853 return Representation::Integer32(); | |
2854 } | |
2855 // If the index is tagged and isn't constant, then allow the length | |
2856 // to be tagged, since it is usually already tagged from loading it out of | |
2857 // the length field of a JSArray. This allows for direct comparison without | |
2858 // untagging. | |
2859 if (index()->representation().IsTagged() && !index()->IsConstant()) { | |
2860 return Representation::Tagged(); | |
2861 } | |
2862 // Also allow the length to be tagged if the index is constant, because | |
2863 // it can be tagged to allow direct comparison. | |
2864 if (index()->IsConstant() && | |
2865 index()->representation().IsInteger32() && | |
2866 arg_index == 1) { | |
2867 return Representation::Tagged(); | |
2868 } | |
2869 return Representation::Integer32(); | |
2870 } | |
2871 virtual Representation observed_input_representation(int index) { | |
2872 return Representation::Integer32(); | |
2873 } | |
2874 | |
2875 virtual void PrintDataTo(StringStream* stream); | |
2876 | |
2877 HValue* index() { return OperandAt(0); } | |
2878 HValue* length() { return OperandAt(1); } | |
2879 | |
2880 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck) | |
2881 | |
2882 static HValue* ExtractUncheckedIndex(HValue* index) { | |
2883 return index->IsBoundsCheck() ? HBoundsCheck::cast(index)->index() : index; | |
2884 } | |
2885 | |
2886 protected: | |
2887 virtual bool DataEquals(HValue* other) { return true; } | |
2888 BoundsCheckKeyMode key_mode_; | |
2889 }; | |
2890 | |
2891 | |
2829 class HApplyArguments: public HTemplateInstruction<4> { | 2892 class HApplyArguments: public HTemplateInstruction<4> { |
2830 public: | 2893 public: |
2831 HApplyArguments(HValue* function, | 2894 HApplyArguments(HValue* function, |
2832 HValue* receiver, | 2895 HValue* receiver, |
2833 HValue* length, | 2896 HValue* length, |
2834 HValue* elements) { | 2897 HValue* elements) { |
2835 set_representation(Representation::Tagged()); | 2898 set_representation(Representation::Tagged()); |
2836 SetOperandAt(0, function); | 2899 SetOperandAt(0, function); |
2837 SetOperandAt(1, receiver); | 2900 SetOperandAt(1, receiver); |
2838 SetOperandAt(2, length); | 2901 SetOperandAt(2, length); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2897 DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength) | 2960 DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength) |
2898 | 2961 |
2899 protected: | 2962 protected: |
2900 virtual bool DataEquals(HValue* other) { return true; } | 2963 virtual bool DataEquals(HValue* other) { return true; } |
2901 | 2964 |
2902 private: | 2965 private: |
2903 virtual bool IsDeletable() const { return true; } | 2966 virtual bool IsDeletable() const { return true; } |
2904 }; | 2967 }; |
2905 | 2968 |
2906 | 2969 |
2907 class HAccessArgumentsAt: public HTemplateInstruction<3> { | 2970 class HAccessArgumentsAt: public HTemplateInstruction<4> { |
2908 public: | 2971 public: |
2909 HAccessArgumentsAt(HValue* arguments, HValue* length, HValue* index) { | 2972 HAccessArgumentsAt(HValue* arguments, |
2973 HValue* length, | |
2974 HValue* checked_index) { | |
2910 set_representation(Representation::Tagged()); | 2975 set_representation(Representation::Tagged()); |
2911 SetFlag(kUseGVN); | 2976 SetFlag(kUseGVN); |
2912 SetOperandAt(0, arguments); | 2977 SetOperandAt(0, arguments); |
2913 SetOperandAt(1, length); | 2978 SetOperandAt(1, length); |
2914 SetOperandAt(2, index); | 2979 SetOperandAt(2, HBoundsCheck::ExtractUncheckedIndex(checked_index)); |
2980 SetOperandAt(3, checked_index); | |
2915 } | 2981 } |
2916 | 2982 |
2917 virtual void PrintDataTo(StringStream* stream); | 2983 virtual void PrintDataTo(StringStream* stream); |
2918 | 2984 |
2919 virtual Representation RequiredInputRepresentation(int index) { | 2985 virtual Representation RequiredInputRepresentation(int index) { |
2920 // The arguments elements is considered tagged. | 2986 switch (index) { |
2921 return index == 0 | 2987 // The arguments elements is considered tagged. |
2922 ? Representation::Tagged() | 2988 case 0: return Representation::Tagged(); |
2923 : Representation::Integer32(); | 2989 // The checked index is a control flow dependency do avoid hoisting |
2990 // and therefore it has no representation requirements. | |
2991 case 3: return Representation::None(); | |
2992 default: return Representation::Integer32(); | |
Sven Panne
2012/12/07 10:24:58
default is evil (a maintenance nightmare), please
| |
2993 } | |
2924 } | 2994 } |
2925 | 2995 |
2926 HValue* arguments() { return OperandAt(0); } | 2996 HValue* arguments() { return OperandAt(0); } |
2927 HValue* length() { return OperandAt(1); } | 2997 HValue* length() { return OperandAt(1); } |
2928 HValue* index() { return OperandAt(2); } | 2998 HValue* index() { return OperandAt(2); } |
2999 HValue* checked_index() { return OperandAt(3); } | |
2929 | 3000 |
2930 DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt) | 3001 DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt) |
2931 | 3002 |
2932 virtual bool DataEquals(HValue* other) { return true; } | 3003 virtual bool DataEquals(HValue* other) { return true; } |
2933 }; | 3004 }; |
2934 | 3005 |
2935 | 3006 |
2936 enum BoundsCheckKeyMode { | |
2937 DONT_ALLOW_SMI_KEY, | |
2938 ALLOW_SMI_KEY | |
2939 }; | |
2940 | |
2941 | |
2942 class HBoundsCheck: public HTemplateInstruction<2> { | |
2943 public: | |
2944 HBoundsCheck(HValue* index, HValue* length, | |
2945 BoundsCheckKeyMode key_mode = DONT_ALLOW_SMI_KEY) | |
2946 : key_mode_(key_mode) { | |
2947 SetOperandAt(0, index); | |
2948 SetOperandAt(1, length); | |
2949 set_representation(Representation::Integer32()); | |
2950 SetFlag(kUseGVN); | |
2951 } | |
2952 | |
2953 virtual Representation RequiredInputRepresentation(int arg_index) { | |
2954 if (key_mode_ == DONT_ALLOW_SMI_KEY || | |
2955 !length()->representation().IsTagged()) { | |
2956 return Representation::Integer32(); | |
2957 } | |
2958 // If the index is tagged and isn't constant, then allow the length | |
2959 // to be tagged, since it is usually already tagged from loading it out of | |
2960 // the length field of a JSArray. This allows for direct comparison without | |
2961 // untagging. | |
2962 if (index()->representation().IsTagged() && !index()->IsConstant()) { | |
2963 return Representation::Tagged(); | |
2964 } | |
2965 // Also allow the length to be tagged if the index is constant, because | |
2966 // it can be tagged to allow direct comparison. | |
2967 if (index()->IsConstant() && | |
2968 index()->representation().IsInteger32() && | |
2969 arg_index == 1) { | |
2970 return Representation::Tagged(); | |
2971 } | |
2972 return Representation::Integer32(); | |
2973 } | |
2974 virtual Representation observed_input_representation(int index) { | |
2975 return Representation::Integer32(); | |
2976 } | |
2977 | |
2978 virtual void PrintDataTo(StringStream* stream); | |
2979 | |
2980 HValue* index() { return OperandAt(0); } | |
2981 HValue* length() { return OperandAt(1); } | |
2982 | |
2983 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck) | |
2984 | |
2985 protected: | |
2986 virtual bool DataEquals(HValue* other) { return true; } | |
2987 BoundsCheckKeyMode key_mode_; | |
2988 }; | |
2989 | |
2990 | |
2991 class HBitwiseBinaryOperation: public HBinaryOperation { | 3007 class HBitwiseBinaryOperation: public HBinaryOperation { |
2992 public: | 3008 public: |
2993 HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right) | 3009 HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right) |
2994 : HBinaryOperation(context, left, right) { | 3010 : HBinaryOperation(context, left, right) { |
2995 SetFlag(kFlexibleRepresentation); | 3011 SetFlag(kFlexibleRepresentation); |
2996 SetFlag(kTruncatingToInt32); | 3012 SetFlag(kTruncatingToInt32); |
2997 SetAllSideEffects(); | 3013 SetAllSideEffects(); |
2998 } | 3014 } |
2999 | 3015 |
3000 virtual Representation RequiredInputRepresentation(int index) { | 3016 virtual Representation RequiredInputRepresentation(int index) { |
(...skipping 1334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4335 virtual HValue* GetKey() = 0; | 4351 virtual HValue* GetKey() = 0; |
4336 virtual void SetKey(HValue* key) = 0; | 4352 virtual void SetKey(HValue* key) = 0; |
4337 virtual void SetIndexOffset(uint32_t index_offset) = 0; | 4353 virtual void SetIndexOffset(uint32_t index_offset) = 0; |
4338 virtual bool IsDehoisted() = 0; | 4354 virtual bool IsDehoisted() = 0; |
4339 virtual void SetDehoisted(bool is_dehoisted) = 0; | 4355 virtual void SetDehoisted(bool is_dehoisted) = 0; |
4340 virtual ~ArrayInstructionInterface() { }; | 4356 virtual ~ArrayInstructionInterface() { }; |
4341 }; | 4357 }; |
4342 | 4358 |
4343 | 4359 |
4344 class HLoadKeyed | 4360 class HLoadKeyed |
4345 : public HTemplateInstruction<3>, public ArrayInstructionInterface { | 4361 : public HTemplateInstruction<4>, public ArrayInstructionInterface { |
4346 public: | 4362 public: |
4347 HLoadKeyed(HValue* obj, | 4363 HLoadKeyed(HValue* obj, |
4348 HValue* key, | 4364 HValue* checked_key, |
4349 HValue* dependency, | 4365 HValue* dependency, |
4350 ElementsKind elements_kind) | 4366 ElementsKind elements_kind) |
4351 : bit_field_(0) { | 4367 : bit_field_(0) { |
4352 bit_field_ = ElementsKindField::encode(elements_kind); | 4368 bit_field_ = ElementsKindField::encode(elements_kind); |
4353 | |
4354 SetOperandAt(0, obj); | 4369 SetOperandAt(0, obj); |
4355 SetOperandAt(1, key); | 4370 SetOperandAt(1, HBoundsCheck::ExtractUncheckedIndex(checked_key)); |
4356 SetOperandAt(2, dependency); | 4371 SetOperandAt(2, dependency); |
4372 SetOperandAt(3, checked_key); | |
4357 | 4373 |
4358 if (!is_external()) { | 4374 if (!is_external()) { |
4359 // I can detect the case between storing double (holey and fast) and | 4375 // I can detect the case between storing double (holey and fast) and |
4360 // smi/object by looking at elements_kind_. | 4376 // smi/object by looking at elements_kind_. |
4361 ASSERT(IsFastSmiOrObjectElementsKind(elements_kind) || | 4377 ASSERT(IsFastSmiOrObjectElementsKind(elements_kind) || |
4362 IsFastDoubleElementsKind(elements_kind)); | 4378 IsFastDoubleElementsKind(elements_kind)); |
4363 | 4379 |
4364 if (IsFastSmiOrObjectElementsKind(elements_kind)) { | 4380 if (IsFastSmiOrObjectElementsKind(elements_kind)) { |
4365 if (IsFastSmiElementsKind(elements_kind) && | 4381 if (IsFastSmiElementsKind(elements_kind) && |
4366 IsFastPackedElementsKind(elements_kind)) { | 4382 IsFastPackedElementsKind(elements_kind)) { |
(...skipping 21 matching lines...) Expand all Loading... | |
4388 | 4404 |
4389 SetFlag(kUseGVN); | 4405 SetFlag(kUseGVN); |
4390 } | 4406 } |
4391 | 4407 |
4392 bool is_external() const { | 4408 bool is_external() const { |
4393 return IsExternalArrayElementsKind(elements_kind()); | 4409 return IsExternalArrayElementsKind(elements_kind()); |
4394 } | 4410 } |
4395 HValue* elements() { return OperandAt(0); } | 4411 HValue* elements() { return OperandAt(0); } |
4396 HValue* key() { return OperandAt(1); } | 4412 HValue* key() { return OperandAt(1); } |
4397 HValue* dependency() { return OperandAt(2); } | 4413 HValue* dependency() { return OperandAt(2); } |
4414 HValue* checked_key() { return OperandAt(3); } | |
4398 uint32_t index_offset() { return IndexOffsetField::decode(bit_field_); } | 4415 uint32_t index_offset() { return IndexOffsetField::decode(bit_field_); } |
4399 void SetIndexOffset(uint32_t index_offset) { | 4416 void SetIndexOffset(uint32_t index_offset) { |
4400 bit_field_ = IndexOffsetField::update(bit_field_, index_offset); | 4417 bit_field_ = IndexOffsetField::update(bit_field_, index_offset); |
4401 } | 4418 } |
4402 HValue* GetKey() { return key(); } | 4419 HValue* GetKey() { return key(); } |
4403 void SetKey(HValue* key) { SetOperandAt(1, key); } | 4420 void SetKey(HValue* key) { SetOperandAt(1, key); } |
4404 bool IsDehoisted() { return IsDehoistedField::decode(bit_field_); } | 4421 bool IsDehoisted() { return IsDehoistedField::decode(bit_field_); } |
4405 void SetDehoisted(bool is_dehoisted) { | 4422 void SetDehoisted(bool is_dehoisted) { |
4406 bit_field_ = IsDehoistedField::update(bit_field_, is_dehoisted); | 4423 bit_field_ = IsDehoistedField::update(bit_field_, is_dehoisted); |
4407 } | 4424 } |
4408 ElementsKind elements_kind() const { | 4425 ElementsKind elements_kind() const { |
4409 return ElementsKindField::decode(bit_field_); | 4426 return ElementsKindField::decode(bit_field_); |
4410 } | 4427 } |
4411 | 4428 |
4412 virtual Representation RequiredInputRepresentation(int index) { | 4429 virtual Representation RequiredInputRepresentation(int index) { |
4413 // kind_fast: tagged[int32] (none) | 4430 // kind_fast: tagged[int32] (none) |
4414 // kind_double: tagged[int32] (none) | 4431 // kind_double: tagged[int32] (none) |
4415 // kind_external: external[int32] (none) | 4432 // kind_external: external[int32] (none) |
4416 if (index == 0) { | 4433 if (index == 0) { |
4417 return is_external() ? Representation::External() | 4434 return is_external() ? Representation::External() |
4418 : Representation::Tagged(); | 4435 : Representation::Tagged(); |
4419 } | 4436 } |
4420 if (index == 1) return Representation::Integer32(); | 4437 if (index == 1) { |
4438 return OperandAt(1)->representation().KeyedAccessIndexRequirement(); | |
4439 } | |
4421 return Representation::None(); | 4440 return Representation::None(); |
4422 } | 4441 } |
4423 | 4442 |
4424 virtual Representation observed_input_representation(int index) { | 4443 virtual Representation observed_input_representation(int index) { |
4425 return RequiredInputRepresentation(index); | 4444 return RequiredInputRepresentation(index); |
4426 } | 4445 } |
4427 | 4446 |
4428 virtual void PrintDataTo(StringStream* stream); | 4447 virtual void PrintDataTo(StringStream* stream); |
4429 | 4448 |
4430 bool RequiresHoleCheck() const; | 4449 bool RequiresHoleCheck() const; |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4592 | 4611 |
4593 DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric) | 4612 DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric) |
4594 | 4613 |
4595 private: | 4614 private: |
4596 Handle<String> name_; | 4615 Handle<String> name_; |
4597 StrictModeFlag strict_mode_flag_; | 4616 StrictModeFlag strict_mode_flag_; |
4598 }; | 4617 }; |
4599 | 4618 |
4600 | 4619 |
4601 class HStoreKeyed | 4620 class HStoreKeyed |
4602 : public HTemplateInstruction<3>, public ArrayInstructionInterface { | 4621 : public HTemplateInstruction<4>, public ArrayInstructionInterface { |
4603 public: | 4622 public: |
4604 HStoreKeyed(HValue* obj, HValue* key, HValue* val, | 4623 HStoreKeyed(HValue* obj, HValue* checked_key, HValue* val, |
4605 ElementsKind elements_kind) | 4624 ElementsKind elements_kind) |
4606 : elements_kind_(elements_kind), index_offset_(0), is_dehoisted_(false) { | 4625 : elements_kind_(elements_kind), index_offset_(0), is_dehoisted_(false) { |
4607 SetOperandAt(0, obj); | 4626 SetOperandAt(0, obj); |
4608 SetOperandAt(1, key); | 4627 SetOperandAt(1, HBoundsCheck::ExtractUncheckedIndex(checked_key)); |
4609 SetOperandAt(2, val); | 4628 SetOperandAt(2, val); |
4629 SetOperandAt(3, checked_key); | |
4610 | 4630 |
4611 if (is_external()) { | 4631 if (is_external()) { |
4612 SetGVNFlag(kChangesSpecializedArrayElements); | 4632 SetGVNFlag(kChangesSpecializedArrayElements); |
4613 } else if (IsFastDoubleElementsKind(elements_kind)) { | 4633 } else if (IsFastDoubleElementsKind(elements_kind)) { |
4614 SetGVNFlag(kChangesDoubleArrayElements); | 4634 SetGVNFlag(kChangesDoubleArrayElements); |
4615 SetFlag(kDeoptimizeOnUndefined); | 4635 SetFlag(kDeoptimizeOnUndefined); |
4616 } else { | 4636 } else { |
4617 SetGVNFlag(kChangesArrayElements); | 4637 SetGVNFlag(kChangesArrayElements); |
4618 } | 4638 } |
4619 | 4639 |
4620 // EXTERNAL_{UNSIGNED_,}{BYTE,SHORT,INT}_ELEMENTS are truncating. | 4640 // EXTERNAL_{UNSIGNED_,}{BYTE,SHORT,INT}_ELEMENTS are truncating. |
4621 if (elements_kind >= EXTERNAL_BYTE_ELEMENTS && | 4641 if (elements_kind >= EXTERNAL_BYTE_ELEMENTS && |
4622 elements_kind <= EXTERNAL_UNSIGNED_INT_ELEMENTS) { | 4642 elements_kind <= EXTERNAL_UNSIGNED_INT_ELEMENTS) { |
4623 SetFlag(kTruncatingToInt32); | 4643 SetFlag(kTruncatingToInt32); |
4624 } | 4644 } |
4625 } | 4645 } |
4626 | 4646 |
4627 virtual Representation RequiredInputRepresentation(int index) { | 4647 virtual Representation RequiredInputRepresentation(int index) { |
4628 // kind_fast: tagged[int32] = tagged | 4648 // kind_fast: tagged[int32] = tagged |
4629 // kind_double: tagged[int32] = double | 4649 // kind_double: tagged[int32] = double |
4630 // kind_external: external[int32] = (double | int32) | 4650 // kind_external: external[int32] = (double | int32) |
4631 if (index == 0) { | 4651 if (index == 0) { |
4632 return is_external() ? Representation::External() | 4652 return is_external() ? Representation::External() |
4633 : Representation::Tagged(); | 4653 : Representation::Tagged(); |
4634 } else if (index == 1) { | 4654 } else if (index == 1) { |
4635 return Representation::Integer32(); | 4655 return OperandAt(1)->representation().KeyedAccessIndexRequirement(); |
4656 } else if (index == 3) { | |
4657 return Representation::None(); | |
4636 } | 4658 } |
4637 | 4659 |
4638 ASSERT_EQ(index, 2); | 4660 ASSERT_EQ(index, 2); |
4639 if (IsDoubleOrFloatElementsKind(elements_kind())) { | 4661 if (IsDoubleOrFloatElementsKind(elements_kind())) { |
4640 return Representation::Double(); | 4662 return Representation::Double(); |
4641 } | 4663 } |
4642 | 4664 |
4643 return is_external() ? Representation::Integer32() | 4665 return is_external() ? Representation::Integer32() |
4644 : Representation::Tagged(); | 4666 : Representation::Tagged(); |
4645 } | 4667 } |
(...skipping 10 matching lines...) Expand all Loading... | |
4656 if (is_external()) { | 4678 if (is_external()) { |
4657 return Representation::Integer32(); | 4679 return Representation::Integer32(); |
4658 } | 4680 } |
4659 // For fast object elements kinds, don't assume anything. | 4681 // For fast object elements kinds, don't assume anything. |
4660 return Representation::None(); | 4682 return Representation::None(); |
4661 } | 4683 } |
4662 | 4684 |
4663 HValue* elements() { return OperandAt(0); } | 4685 HValue* elements() { return OperandAt(0); } |
4664 HValue* key() { return OperandAt(1); } | 4686 HValue* key() { return OperandAt(1); } |
4665 HValue* value() { return OperandAt(2); } | 4687 HValue* value() { return OperandAt(2); } |
4688 HValue* checked_key() { return OperandAt(3); } | |
4666 bool value_is_smi() const { | 4689 bool value_is_smi() const { |
4667 return IsFastSmiElementsKind(elements_kind_); | 4690 return IsFastSmiElementsKind(elements_kind_); |
4668 } | 4691 } |
4669 ElementsKind elements_kind() const { return elements_kind_; } | 4692 ElementsKind elements_kind() const { return elements_kind_; } |
4670 uint32_t index_offset() { return index_offset_; } | 4693 uint32_t index_offset() { return index_offset_; } |
4671 void SetIndexOffset(uint32_t index_offset) { index_offset_ = index_offset; } | 4694 void SetIndexOffset(uint32_t index_offset) { index_offset_ = index_offset; } |
4672 HValue* GetKey() { return key(); } | 4695 HValue* GetKey() { return key(); } |
4673 void SetKey(HValue* key) { SetOperandAt(1, key); } | 4696 void SetKey(HValue* key) { SetOperandAt(1, key); } |
4674 bool IsDehoisted() { return is_dehoisted_; } | 4697 bool IsDehoisted() { return is_dehoisted_; } |
4675 void SetDehoisted(bool is_dehoisted) { is_dehoisted_ = is_dehoisted; } | 4698 void SetDehoisted(bool is_dehoisted) { is_dehoisted_ = is_dehoisted; } |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4798 | 4821 |
4799 protected: | 4822 protected: |
4800 virtual bool DataEquals(HValue* other) { return true; } | 4823 virtual bool DataEquals(HValue* other) { return true; } |
4801 | 4824 |
4802 // TODO(svenpanne) Might be safe, but leave it out until we know for sure. | 4825 // TODO(svenpanne) Might be safe, but leave it out until we know for sure. |
4803 // private: | 4826 // private: |
4804 // virtual bool IsDeletable() const { return true; } | 4827 // virtual bool IsDeletable() const { return true; } |
4805 }; | 4828 }; |
4806 | 4829 |
4807 | 4830 |
4808 class HStringCharCodeAt: public HTemplateInstruction<3> { | 4831 class HStringCharCodeAt: public HTemplateInstruction<4> { |
4809 public: | 4832 public: |
4810 HStringCharCodeAt(HValue* context, HValue* string, HValue* index) { | 4833 HStringCharCodeAt(HValue* context, HValue* string, HValue* checked_index) { |
4811 SetOperandAt(0, context); | 4834 SetOperandAt(0, context); |
4812 SetOperandAt(1, string); | 4835 SetOperandAt(1, string); |
4813 SetOperandAt(2, index); | 4836 SetOperandAt(2, HBoundsCheck::ExtractUncheckedIndex(checked_index)); |
4837 SetOperandAt(3, checked_index); | |
4814 set_representation(Representation::Integer32()); | 4838 set_representation(Representation::Integer32()); |
4815 SetFlag(kUseGVN); | 4839 SetFlag(kUseGVN); |
4816 SetGVNFlag(kDependsOnMaps); | 4840 SetGVNFlag(kDependsOnMaps); |
4817 SetGVNFlag(kChangesNewSpacePromotion); | 4841 SetGVNFlag(kChangesNewSpacePromotion); |
4818 } | 4842 } |
4819 | 4843 |
4820 virtual Representation RequiredInputRepresentation(int index) { | 4844 virtual Representation RequiredInputRepresentation(int index) { |
4821 // The index is supposed to be Integer32. | 4845 switch (index) { |
4822 return index == 2 | 4846 // The index is supposed to be Integer32. |
4823 ? Representation::Integer32() | 4847 case 2: return Representation::Integer32(); |
4824 : Representation::Tagged(); | 4848 // The checked index is a control flow dependency do avoid hoisting |
4849 // and therefore it has no representation requirements. | |
4850 case 3: return Representation::None(); | |
4851 default: return Representation::Tagged(); | |
Sven Panne
2012/12/07 10:24:58
see above
| |
4852 } | |
4825 } | 4853 } |
4826 | 4854 |
4827 HValue* context() { return OperandAt(0); } | 4855 HValue* context() { return OperandAt(0); } |
4828 HValue* string() { return OperandAt(1); } | 4856 HValue* string() { return OperandAt(1); } |
4829 HValue* index() { return OperandAt(2); } | 4857 HValue* index() { return OperandAt(2); } |
4858 HValue* checked_index() { return OperandAt(3); } | |
4830 | 4859 |
4831 DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt) | 4860 DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt) |
4832 | 4861 |
4833 protected: | 4862 protected: |
4834 virtual bool DataEquals(HValue* other) { return true; } | 4863 virtual bool DataEquals(HValue* other) { return true; } |
4835 | 4864 |
4836 virtual Range* InferRange(Zone* zone) { | 4865 virtual Range* InferRange(Zone* zone) { |
4837 return new(zone) Range(0, String::kMaxUtf16CodeUnit); | 4866 return new(zone) Range(0, String::kMaxUtf16CodeUnit); |
4838 } | 4867 } |
4839 | 4868 |
(...skipping 550 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5390 virtual bool IsDeletable() const { return true; } | 5419 virtual bool IsDeletable() const { return true; } |
5391 }; | 5420 }; |
5392 | 5421 |
5393 | 5422 |
5394 #undef DECLARE_INSTRUCTION | 5423 #undef DECLARE_INSTRUCTION |
5395 #undef DECLARE_CONCRETE_INSTRUCTION | 5424 #undef DECLARE_CONCRETE_INSTRUCTION |
5396 | 5425 |
5397 } } // namespace v8::internal | 5426 } } // namespace v8::internal |
5398 | 5427 |
5399 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ | 5428 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ |
OLD | NEW |