| Index: src/hydrogen-instructions.h
|
| diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
|
| index aa513e707b235c8a20a63a55acacfa78b6189e82..2d57537596b612ffff8aa628dac5b0bac9cb8027 100644
|
| --- a/src/hydrogen-instructions.h
|
| +++ b/src/hydrogen-instructions.h
|
| @@ -673,6 +673,31 @@ class HValue: public ZoneObject {
|
| return NULL;
|
| }
|
|
|
| + // There are HInstructions that do not really change a value, they
|
| + // only add pieces of information to it (like bounds checks, map checks,
|
| + // smi checks...).
|
| + // We call these instructions "informative definitions", or "iDef".
|
| + // One of the iDef operands is special because it is the value that is
|
| + // "transferred" to the output, we call it the "redefined operand".
|
| + // If an HValue is an iDef it must override RedefinedOperandIndex() so that
|
| + // it does not return kNoRedefinedOperand;
|
| + static const int kNoRedefinedOperand = -1;
|
| + virtual int RedefinedOperandIndex() { return kNoRedefinedOperand; }
|
| + bool IsInformativeDefinition() {
|
| + return RedefinedOperandIndex() != kNoRedefinedOperand;
|
| + }
|
| + HValue* RedefinedOperand() {
|
| + ASSERT(IsInformativeDefinition());
|
| + return OperandAt(RedefinedOperandIndex());
|
| + }
|
| +
|
| + // This method must always return the original HValue SSA definition
|
| + // (regardless of any iDef of this value).
|
| + HValue* ActualValue() {
|
| + return IsInformativeDefinition() ? RedefinedOperand()->ActualValue()
|
| + : this;
|
| + }
|
| +
|
| bool IsDefinedAfter(HBasicBlock* other) const;
|
|
|
| // Operands.
|
| @@ -3020,44 +3045,38 @@ enum BoundsCheckKeyMode {
|
| class HBoundsCheck: public HTemplateInstruction<2> {
|
| public:
|
| HBoundsCheck(HValue* index, HValue* length,
|
| - BoundsCheckKeyMode key_mode = DONT_ALLOW_SMI_KEY)
|
| + BoundsCheckKeyMode key_mode = DONT_ALLOW_SMI_KEY,
|
| + Representation r = Representation::None())
|
| : key_mode_(key_mode) {
|
| SetOperandAt(0, index);
|
| SetOperandAt(1, length);
|
| - set_representation(Representation::Integer32());
|
| + if (r.IsNone()) {
|
| + // In the normal compilation pipeline the representation is flexible
|
| + // (see comment to RequiredInputRepresentation).
|
| + SetFlag(kFlexibleRepresentation);
|
| + } else {
|
| + // When compiling stubs we want to set the representation explicitly
|
| + // so the compilation pipeline can skip the HInferRepresentation phase.
|
| + set_representation(r);
|
| + }
|
| 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();
|
| + return representation();
|
| }
|
| virtual Representation observed_input_representation(int index) {
|
| return Representation::Integer32();
|
| }
|
|
|
| virtual void PrintDataTo(StringStream* stream);
|
| + virtual void InferRepresentation(HInferRepresentation* h_infer);
|
|
|
| HValue* index() { return OperandAt(0); }
|
| HValue* length() { return OperandAt(1); }
|
|
|
| + virtual int RedefinedOperandIndex() { return 0; }
|
| +
|
| DECLARE_CONCRETE_INSTRUCTION(BoundsCheck)
|
|
|
| protected:
|
| @@ -4433,6 +4452,11 @@ class ArrayInstructionInterface {
|
| virtual bool IsDehoisted() = 0;
|
| virtual void SetDehoisted(bool is_dehoisted) = 0;
|
| virtual ~ArrayInstructionInterface() { };
|
| +
|
| + static Representation KeyedAccessIndexRequirement(Representation r) {
|
| + return r.IsInteger32() ? Representation::Integer32()
|
| + : Representation::Tagged();
|
| + }
|
| };
|
|
|
|
|
| @@ -4516,7 +4540,10 @@ class HLoadKeyed
|
| return is_external() ? Representation::External()
|
| : Representation::Tagged();
|
| }
|
| - if (index == 1) return Representation::Integer32();
|
| + if (index == 1) {
|
| + return ArrayInstructionInterface::KeyedAccessIndexRequirement(
|
| + OperandAt(1)->representation());
|
| + }
|
| return Representation::None();
|
| }
|
|
|
| @@ -4731,7 +4758,8 @@ class HStoreKeyed
|
| return is_external() ? Representation::External()
|
| : Representation::Tagged();
|
| } else if (index == 1) {
|
| - return Representation::Integer32();
|
| + return ArrayInstructionInterface::KeyedAccessIndexRequirement(
|
| + OperandAt(1)->representation());
|
| }
|
|
|
| ASSERT_EQ(index, 2);
|
|
|