Chromium Code Reviews| Index: src/hydrogen-instructions.h | 
| diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h | 
| index 47a9da3b45deb917e7b4a5c213b4db57a3625d1d..8d303485ba7071ce1c68764b812644578d37bb2f 100644 | 
| --- a/src/hydrogen-instructions.h | 
| +++ b/src/hydrogen-instructions.h | 
| @@ -347,6 +347,10 @@ class Representation { | 
| } | 
| const char* Mnemonic() const; | 
| + Representation KeyedAccessIndexRequirement() { | 
| + return IsInteger32() ? Integer32() : Tagged(); | 
| 
 
Sven Panne
2012/12/06 14:59:02
I think we should add an assertion here about the
 
Massi
2012/12/07 10:11:11
Well, this representation is meant to be used as r
 
Sven Panne
2012/12/07 10:24:58
Well, in general RequiredInputRepresentation doesn
 
 | 
| + } | 
| + | 
| private: | 
| explicit Representation(Kind k) : kind_(k) { } | 
| @@ -2826,6 +2830,65 @@ class HWrapReceiver: public HTemplateInstruction<2> { | 
| }; | 
| +enum BoundsCheckKeyMode { | 
| + DONT_ALLOW_SMI_KEY, | 
| + ALLOW_SMI_KEY | 
| +}; | 
| + | 
| + | 
| +class HBoundsCheck: public HTemplateInstruction<2> { | 
| + public: | 
| + HBoundsCheck(HValue* index, HValue* length, | 
| + BoundsCheckKeyMode key_mode = DONT_ALLOW_SMI_KEY) | 
| + : key_mode_(key_mode) { | 
| + SetOperandAt(0, index); | 
| + SetOperandAt(1, length); | 
| + set_representation(Representation::Integer32()); | 
| + SetFlag(kUseGVN); | 
| + } | 
| + | 
| + virtual Representation RequiredInputRepresentation(int arg_index) { | 
| + if (key_mode_ == DONT_ALLOW_SMI_KEY || | 
| + !length()->representation().IsTagged()) { | 
| + return Representation::Integer32(); | 
| + } | 
| + // If the index is tagged and isn't constant, then allow the length | 
| + // to be tagged, since it is usually already tagged from loading it out of | 
| + // the length field of a JSArray. This allows for direct comparison without | 
| + // untagging. | 
| + if (index()->representation().IsTagged() && !index()->IsConstant()) { | 
| + return Representation::Tagged(); | 
| + } | 
| + // Also allow the length to be tagged if the index is constant, because | 
| + // it can be tagged to allow direct comparison. | 
| + if (index()->IsConstant() && | 
| + index()->representation().IsInteger32() && | 
| + arg_index == 1) { | 
| + return Representation::Tagged(); | 
| + } | 
| + return Representation::Integer32(); | 
| + } | 
| + virtual Representation observed_input_representation(int index) { | 
| + return Representation::Integer32(); | 
| + } | 
| + | 
| + virtual void PrintDataTo(StringStream* stream); | 
| + | 
| + HValue* index() { return OperandAt(0); } | 
| + HValue* length() { return OperandAt(1); } | 
| + | 
| + DECLARE_CONCRETE_INSTRUCTION(BoundsCheck) | 
| + | 
| + static HValue* ExtractUncheckedIndex(HValue* index) { | 
| + return index->IsBoundsCheck() ? HBoundsCheck::cast(index)->index() : index; | 
| + } | 
| + | 
| + protected: | 
| + virtual bool DataEquals(HValue* other) { return true; } | 
| + BoundsCheckKeyMode key_mode_; | 
| +}; | 
| + | 
| + | 
| class HApplyArguments: public HTemplateInstruction<4> { | 
| public: | 
| HApplyArguments(HValue* function, | 
| @@ -2904,14 +2967,17 @@ class HArgumentsLength: public HUnaryOperation { | 
| }; | 
| -class HAccessArgumentsAt: public HTemplateInstruction<3> { | 
| +class HAccessArgumentsAt: public HTemplateInstruction<4> { | 
| public: | 
| - HAccessArgumentsAt(HValue* arguments, HValue* length, HValue* index) { | 
| + HAccessArgumentsAt(HValue* arguments, | 
| + HValue* length, | 
| + HValue* checked_index) { | 
| set_representation(Representation::Tagged()); | 
| SetFlag(kUseGVN); | 
| SetOperandAt(0, arguments); | 
| SetOperandAt(1, length); | 
| - SetOperandAt(2, index); | 
| + SetOperandAt(2, HBoundsCheck::ExtractUncheckedIndex(checked_index)); | 
| + SetOperandAt(3, checked_index); | 
| } | 
| virtual void PrintDataTo(StringStream* stream); | 
| @@ -2919,13 +2985,15 @@ class HAccessArgumentsAt: public HTemplateInstruction<3> { | 
| virtual Representation RequiredInputRepresentation(int index) { | 
| // The arguments elements is considered tagged. | 
| return index == 0 | 
| - ? Representation::Tagged() | 
| - : Representation::Integer32(); | 
| + ? Representation::Tagged() : | 
| 
 
Sven Panne
2012/12/06 14:59:02
Formatting nit: Consistently indent the ternary op
 
Massi
2012/12/07 10:11:11
Done.
 
 | 
| + (index == 3 ? Representation::None() : | 
| 
 
Sven Panne
2012/12/06 14:59:02
Hmmm, I would have expected
 checked_index()->rep
 
Massi
2012/12/07 10:11:11
Done.
 
 | 
| + Representation::Integer32()); | 
| } | 
| HValue* arguments() { return OperandAt(0); } | 
| HValue* length() { return OperandAt(1); } | 
| HValue* index() { return OperandAt(2); } | 
| + HValue* checked_index() { return OperandAt(3); } | 
| DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt) | 
| @@ -2933,61 +3001,6 @@ class HAccessArgumentsAt: public HTemplateInstruction<3> { | 
| }; | 
| -enum BoundsCheckKeyMode { | 
| - DONT_ALLOW_SMI_KEY, | 
| - ALLOW_SMI_KEY | 
| -}; | 
| - | 
| - | 
| -class HBoundsCheck: public HTemplateInstruction<2> { | 
| - public: | 
| - HBoundsCheck(HValue* index, HValue* length, | 
| - BoundsCheckKeyMode key_mode = DONT_ALLOW_SMI_KEY) | 
| - : key_mode_(key_mode) { | 
| - SetOperandAt(0, index); | 
| - SetOperandAt(1, length); | 
| - set_representation(Representation::Integer32()); | 
| - SetFlag(kUseGVN); | 
| - } | 
| - | 
| - virtual Representation RequiredInputRepresentation(int arg_index) { | 
| - if (key_mode_ == DONT_ALLOW_SMI_KEY || | 
| - !length()->representation().IsTagged()) { | 
| - return Representation::Integer32(); | 
| - } | 
| - // If the index is tagged and isn't constant, then allow the length | 
| - // to be tagged, since it is usually already tagged from loading it out of | 
| - // the length field of a JSArray. This allows for direct comparison without | 
| - // untagging. | 
| - if (index()->representation().IsTagged() && !index()->IsConstant()) { | 
| - return Representation::Tagged(); | 
| - } | 
| - // Also allow the length to be tagged if the index is constant, because | 
| - // it can be tagged to allow direct comparison. | 
| - if (index()->IsConstant() && | 
| - index()->representation().IsInteger32() && | 
| - arg_index == 1) { | 
| - return Representation::Tagged(); | 
| - } | 
| - return Representation::Integer32(); | 
| - } | 
| - virtual Representation observed_input_representation(int index) { | 
| - return Representation::Integer32(); | 
| - } | 
| - | 
| - virtual void PrintDataTo(StringStream* stream); | 
| - | 
| - HValue* index() { return OperandAt(0); } | 
| - HValue* length() { return OperandAt(1); } | 
| - | 
| - DECLARE_CONCRETE_INSTRUCTION(BoundsCheck) | 
| - | 
| - protected: | 
| - virtual bool DataEquals(HValue* other) { return true; } | 
| - BoundsCheckKeyMode key_mode_; | 
| -}; | 
| - | 
| - | 
| class HBitwiseBinaryOperation: public HBinaryOperation { | 
| public: | 
| HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right) | 
| @@ -4342,18 +4355,18 @@ class ArrayInstructionInterface { | 
| class HLoadKeyed | 
| - : public HTemplateInstruction<3>, public ArrayInstructionInterface { | 
| + : public HTemplateInstruction<4>, public ArrayInstructionInterface { | 
| public: | 
| HLoadKeyed(HValue* obj, | 
| - HValue* key, | 
| + HValue* checked_key, | 
| HValue* dependency, | 
| ElementsKind elements_kind) | 
| : bit_field_(0) { | 
| bit_field_ = ElementsKindField::encode(elements_kind); | 
| - | 
| SetOperandAt(0, obj); | 
| - SetOperandAt(1, key); | 
| + SetOperandAt(1, HBoundsCheck::ExtractUncheckedIndex(checked_key)); | 
| SetOperandAt(2, dependency); | 
| + SetOperandAt(3, checked_key); | 
| if (!is_external()) { | 
| // I can detect the case between storing double (holey and fast) and | 
| @@ -4395,6 +4408,7 @@ class HLoadKeyed | 
| HValue* elements() { return OperandAt(0); } | 
| HValue* key() { return OperandAt(1); } | 
| HValue* dependency() { return OperandAt(2); } | 
| + HValue* checked_key() { return OperandAt(3); } | 
| uint32_t index_offset() { return IndexOffsetField::decode(bit_field_); } | 
| void SetIndexOffset(uint32_t index_offset) { | 
| bit_field_ = IndexOffsetField::update(bit_field_, index_offset); | 
| @@ -4417,7 +4431,9 @@ class HLoadKeyed | 
| return is_external() ? Representation::External() | 
| : Representation::Tagged(); | 
| } | 
| - if (index == 1) return Representation::Integer32(); | 
| + if (index == 1) { | 
| + return OperandAt(1)->representation().KeyedAccessIndexRequirement(); | 
| + } | 
| return Representation::None(); | 
| } | 
| @@ -4599,14 +4615,15 @@ class HStoreNamedGeneric: public HTemplateInstruction<3> { | 
| class HStoreKeyed | 
| - : public HTemplateInstruction<3>, public ArrayInstructionInterface { | 
| + : public HTemplateInstruction<4>, public ArrayInstructionInterface { | 
| public: | 
| - HStoreKeyed(HValue* obj, HValue* key, HValue* val, | 
| + HStoreKeyed(HValue* obj, HValue* checked_key, HValue* val, | 
| ElementsKind elements_kind) | 
| : elements_kind_(elements_kind), index_offset_(0), is_dehoisted_(false) { | 
| SetOperandAt(0, obj); | 
| - SetOperandAt(1, key); | 
| + SetOperandAt(1, HBoundsCheck::ExtractUncheckedIndex(checked_key)); | 
| SetOperandAt(2, val); | 
| + SetOperandAt(3, checked_key); | 
| if (is_external()) { | 
| SetGVNFlag(kChangesSpecializedArrayElements); | 
| @@ -4632,7 +4649,9 @@ class HStoreKeyed | 
| return is_external() ? Representation::External() | 
| : Representation::Tagged(); | 
| } else if (index == 1) { | 
| - return Representation::Integer32(); | 
| + return OperandAt(1)->representation().KeyedAccessIndexRequirement(); | 
| + } else if (index == 3) { | 
| + return Representation::None(); | 
| } | 
| ASSERT_EQ(index, 2); | 
| @@ -4663,6 +4682,7 @@ class HStoreKeyed | 
| HValue* elements() { return OperandAt(0); } | 
| HValue* key() { return OperandAt(1); } | 
| HValue* value() { return OperandAt(2); } | 
| + HValue* checked_key() { return OperandAt(3); } | 
| bool value_is_smi() const { | 
| return IsFastSmiElementsKind(elements_kind_); | 
| } | 
| @@ -4805,12 +4825,13 @@ class HStringAdd: public HBinaryOperation { | 
| }; | 
| -class HStringCharCodeAt: public HTemplateInstruction<3> { | 
| +class HStringCharCodeAt: public HTemplateInstruction<4> { | 
| public: | 
| - HStringCharCodeAt(HValue* context, HValue* string, HValue* index) { | 
| + HStringCharCodeAt(HValue* context, HValue* string, HValue* checked_index) { | 
| SetOperandAt(0, context); | 
| SetOperandAt(1, string); | 
| - SetOperandAt(2, index); | 
| + SetOperandAt(2, HBoundsCheck::ExtractUncheckedIndex(checked_index)); | 
| + SetOperandAt(3, checked_index); | 
| set_representation(Representation::Integer32()); | 
| SetFlag(kUseGVN); | 
| SetGVNFlag(kDependsOnMaps); | 
| @@ -4819,14 +4840,15 @@ class HStringCharCodeAt: public HTemplateInstruction<3> { | 
| virtual Representation RequiredInputRepresentation(int index) { | 
| // The index is supposed to be Integer32. | 
| - return index == 2 | 
| - ? Representation::Integer32() | 
| - : Representation::Tagged(); | 
| + return index == 2 ? | 
| + Representation::Integer32() : | 
| + (index == 3 ? Representation::None() : Representation::Tagged()); | 
| 
 
Sven Panne
2012/12/06 14:59:02
See comments regarding indentation/adding a commen
 
Massi
2012/12/07 10:11:11
Done.
 
 | 
| } | 
| HValue* context() { return OperandAt(0); } | 
| HValue* string() { return OperandAt(1); } | 
| HValue* index() { return OperandAt(2); } | 
| + HValue* checked_index() { return OperandAt(3); } | 
| DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt) |