| Index: src/hydrogen-instructions.h
 | 
| diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
 | 
| index 3aa15e375a78aee6cbb4b31395cb1a87957ebe54..eea429e6f2b11ea2d506d448e7bf39871886d472 100644
 | 
| --- a/src/hydrogen-instructions.h
 | 
| +++ b/src/hydrogen-instructions.h
 | 
| @@ -64,6 +64,7 @@ class LChunkBuilder;
 | 
|    V(AbnormalExit)                              \
 | 
|    V(AccessArgumentsAt)                         \
 | 
|    V(Add)                                       \
 | 
| +  V(Allocate)                                  \
 | 
|    V(AllocateObject)                            \
 | 
|    V(ApplyArguments)                            \
 | 
|    V(ArgumentsElements)                         \
 | 
| @@ -179,6 +180,7 @@ class LChunkBuilder;
 | 
|    V(Throw)                                     \
 | 
|    V(ToFastProperties)                          \
 | 
|    V(TransitionElementsKind)                    \
 | 
| +  V(TrapAllocationMemento)                     \
 | 
|    V(Typeof)                                    \
 | 
|    V(TypeofIsAndBranch)                         \
 | 
|    V(UnaryMathOperation)                        \
 | 
| @@ -4160,6 +4162,106 @@ class HLoadGlobalGeneric: public HTemplateInstruction<2> {
 | 
|  };
 | 
|  
 | 
|  
 | 
| +class HAllocateObject: public HTemplateInstruction<1> {
 | 
| + public:
 | 
| +  HAllocateObject(HValue* context, Handle<JSFunction> constructor)
 | 
| +      : constructor_(constructor) {
 | 
| +    SetOperandAt(0, context);
 | 
| +    set_representation(Representation::Tagged());
 | 
| +    SetGVNFlag(kChangesNewSpacePromotion);
 | 
| +  }
 | 
| +
 | 
| +  // Maximum instance size for which allocations will be inlined.
 | 
| +  static const int kMaxSize = 64 * kPointerSize;
 | 
| +
 | 
| +  HValue* context() { return OperandAt(0); }
 | 
| +  Handle<JSFunction> constructor() { return constructor_; }
 | 
| +
 | 
| +  virtual Representation RequiredInputRepresentation(int index) {
 | 
| +    return Representation::Tagged();
 | 
| +  }
 | 
| +  virtual Handle<Map> GetMonomorphicJSObjectMap() {
 | 
| +    ASSERT(constructor()->has_initial_map());
 | 
| +    return Handle<Map>(constructor()->initial_map());
 | 
| +  }
 | 
| +  virtual HType CalculateInferredType();
 | 
| +
 | 
| +  DECLARE_CONCRETE_INSTRUCTION(AllocateObject)
 | 
| +
 | 
| + private:
 | 
| +  // TODO(svenpanne) Might be safe, but leave it out until we know for sure.
 | 
| +  //  virtual bool IsDeletable() const { return true; }
 | 
| +
 | 
| +  Handle<JSFunction> constructor_;
 | 
| +};
 | 
| +
 | 
| +
 | 
| +class HAllocate: public HTemplateInstruction<2> {
 | 
| + public:
 | 
| +  enum Flags {
 | 
| +    CAN_ALLOCATE_IN_NEW_SPACE = 1 << 0,
 | 
| +    CAN_ALLOCATE_IN_OLD_DATA_SPACE = 1 << 1,
 | 
| +    CAN_ALLOCATE_IN_OLD_POINTER_SPACE = 1 << 2,
 | 
| +    ALLOCATE_DOUBLE_ALIGNED = 1 << 3
 | 
| +  };
 | 
| +
 | 
| +  HAllocate(HValue* context, HValue* size, HType type, Flags flags)
 | 
| +      : type_(type),
 | 
| +        flags_(flags) {
 | 
| +    ASSERT((flags & CAN_ALLOCATE_IN_OLD_DATA_SPACE) == 0);  // unimplemented
 | 
| +    ASSERT((flags & CAN_ALLOCATE_IN_OLD_POINTER_SPACE) == 0);  // unimplemented
 | 
| +    SetOperandAt(0, context);
 | 
| +    SetOperandAt(1, size);
 | 
| +    set_representation(Representation::Tagged());
 | 
| +    SetGVNFlag(kChangesNewSpacePromotion);
 | 
| +  }
 | 
| +
 | 
| +  HValue* context() { return OperandAt(0); }
 | 
| +  HValue* size() { return OperandAt(1); }
 | 
| +
 | 
| +  virtual Representation RequiredInputRepresentation(int index) {
 | 
| +    if (index == 0) {
 | 
| +      return Representation::Tagged();
 | 
| +    } else {
 | 
| +      return Representation::Integer32();
 | 
| +    }
 | 
| +  }
 | 
| +
 | 
| +  virtual HType CalculateInferredType();
 | 
| +
 | 
| +  bool CanAllocateInNewSpace() const {
 | 
| +    return (flags_ & CAN_ALLOCATE_IN_NEW_SPACE) != 0;
 | 
| +  }
 | 
| +
 | 
| +  bool CanAllocateInOldDataSpace() const {
 | 
| +    return (flags_ & CAN_ALLOCATE_IN_OLD_DATA_SPACE) != 0;
 | 
| +  }
 | 
| +
 | 
| +  bool CanAllocateInOldPointerSpace() const {
 | 
| +    return (flags_ & CAN_ALLOCATE_IN_OLD_POINTER_SPACE) != 0;
 | 
| +  }
 | 
| +
 | 
| +  bool CanAllocateInOldSpace() const {
 | 
| +    return CanAllocateInOldDataSpace() ||
 | 
| +        CanAllocateInOldPointerSpace();
 | 
| +  }
 | 
| +
 | 
| +  bool GuaranteedInNewSpace() const {
 | 
| +    return CanAllocateInNewSpace() && !CanAllocateInOldSpace();
 | 
| +  }
 | 
| +
 | 
| +  bool MustAllocateDoubleAligned() const {
 | 
| +    return (flags_ & ALLOCATE_DOUBLE_ALIGNED) != 0;
 | 
| +  }
 | 
| +
 | 
| +  DECLARE_CONCRETE_INSTRUCTION(Allocate)
 | 
| +
 | 
| + private:
 | 
| +  HType type_;
 | 
| +  Flags flags_;
 | 
| +};
 | 
| +
 | 
| +
 | 
|  inline bool StoringValueNeedsWriteBarrier(HValue* value) {
 | 
|    return !value->type().IsBoolean()
 | 
|        && !value->type().IsSmi()
 | 
| @@ -4169,8 +4271,13 @@ inline bool StoringValueNeedsWriteBarrier(HValue* value) {
 | 
|  
 | 
|  inline bool ReceiverObjectNeedsWriteBarrier(HValue* object,
 | 
|                                              HValue* new_space_dominator) {
 | 
| -  return (!object->IsAllocateObject() && !object->IsFastLiteral()) ||
 | 
| -         (object != new_space_dominator);
 | 
| +  if (object != new_space_dominator) return true;
 | 
| +  if (object->IsFastLiteral()) return false;
 | 
| +  if (object->IsAllocateObject()) return false;
 | 
| +  if (object->IsAllocate()) {
 | 
| +    return !HAllocate::cast(object)->GuaranteedInNewSpace();
 | 
| +  }
 | 
| +  return true;
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -4502,15 +4609,23 @@ class ArrayInstructionInterface {
 | 
|  };
 | 
|  
 | 
|  
 | 
| +enum LoadKeyedHoleMode {
 | 
| +  NEVER_RETURN_HOLE,
 | 
| +  ALLOW_RETURN_HOLE
 | 
| +};
 | 
| +
 | 
| +
 | 
|  class HLoadKeyed
 | 
|      : public HTemplateInstruction<3>, public ArrayInstructionInterface {
 | 
|   public:
 | 
|    HLoadKeyed(HValue* obj,
 | 
|               HValue* key,
 | 
|               HValue* dependency,
 | 
| -             ElementsKind elements_kind)
 | 
| +             ElementsKind elements_kind,
 | 
| +             LoadKeyedHoleMode mode = NEVER_RETURN_HOLE)
 | 
|        : bit_field_(0) {
 | 
| -    bit_field_ = ElementsKindField::encode(elements_kind);
 | 
| +    bit_field_ = ElementsKindField::encode(elements_kind) |
 | 
| +        HoleModeField::encode(mode);
 | 
|  
 | 
|      SetOperandAt(0, obj);
 | 
|      SetOperandAt(1, key);
 | 
| @@ -4523,8 +4638,7 @@ class HLoadKeyed
 | 
|               IsFastDoubleElementsKind(elements_kind));
 | 
|  
 | 
|        if (IsFastSmiOrObjectElementsKind(elements_kind)) {
 | 
| -        if (IsFastSmiElementsKind(elements_kind) &&
 | 
| -            IsFastPackedElementsKind(elements_kind)) {
 | 
| +        if (IsFastSmiElementsKind(elements_kind)) {
 | 
|            set_type(HType::Smi());
 | 
|          }
 | 
|  
 | 
| @@ -4573,6 +4687,9 @@ class HLoadKeyed
 | 
|    ElementsKind elements_kind() const {
 | 
|      return ElementsKindField::decode(bit_field_);
 | 
|    }
 | 
| +  LoadKeyedHoleMode hole_mode() const {
 | 
| +    return HoleModeField::decode(bit_field_);
 | 
| +  }
 | 
|  
 | 
|    virtual Representation RequiredInputRepresentation(int index) {
 | 
|      // kind_fast:       tagged[int32] (none)
 | 
| @@ -4595,6 +4712,7 @@ class HLoadKeyed
 | 
|  
 | 
|    virtual void PrintDataTo(StringStream* stream);
 | 
|  
 | 
| +  bool UsesMustHandleHole() const;
 | 
|    bool RequiresHoleCheck() const;
 | 
|  
 | 
|    virtual Range* InferRange(Zone* zone);
 | 
| @@ -4619,11 +4737,13 @@ class HLoadKeyed
 | 
|    // Establish some checks around our packed fields
 | 
|    enum LoadKeyedBits {
 | 
|      kBitsForElementsKind = 5,
 | 
| -    kBitsForIndexOffset = 26,
 | 
| +    kBitsForHoleMode = 1,
 | 
| +    kBitsForIndexOffset = 25,
 | 
|      kBitsForIsDehoisted = 1,
 | 
|  
 | 
|      kStartElementsKind = 0,
 | 
| -    kStartIndexOffset = kStartElementsKind + kBitsForElementsKind,
 | 
| +    kStartHoleMode = kStartElementsKind + kBitsForElementsKind,
 | 
| +    kStartIndexOffset = kStartHoleMode + kBitsForHoleMode,
 | 
|      kStartIsDehoisted = kStartIndexOffset + kBitsForIndexOffset
 | 
|    };
 | 
|  
 | 
| @@ -4633,6 +4753,9 @@ class HLoadKeyed
 | 
|    class ElementsKindField:
 | 
|      public BitField<ElementsKind, kStartElementsKind, kBitsForElementsKind>
 | 
|      {};  // NOLINT
 | 
| +  class HoleModeField:
 | 
| +    public BitField<LoadKeyedHoleMode, kStartHoleMode, kBitsForHoleMode>
 | 
| +    {};  // NOLINT
 | 
|    class IndexOffsetField:
 | 
|      public BitField<uint32_t, kStartIndexOffset, kBitsForIndexOffset>
 | 
|      {};  // NOLINT
 | 
| @@ -4771,11 +4894,18 @@ class HStoreKeyed
 | 
|   public:
 | 
|    HStoreKeyed(HValue* obj, HValue* key, HValue* val,
 | 
|                ElementsKind elements_kind)
 | 
| -      : elements_kind_(elements_kind), index_offset_(0), is_dehoisted_(false) {
 | 
| +      : elements_kind_(elements_kind),
 | 
| +      index_offset_(0),
 | 
| +      is_dehoisted_(false),
 | 
| +      new_space_dominator_(NULL) {
 | 
|      SetOperandAt(0, obj);
 | 
|      SetOperandAt(1, key);
 | 
|      SetOperandAt(2, val);
 | 
|  
 | 
| +    if (IsFastObjectElementsKind(elements_kind)) {
 | 
| +      SetFlag(kTrackSideEffectDominators);
 | 
| +      SetGVNFlag(kDependsOnNewSpacePromotion);
 | 
| +    }
 | 
|      if (is_external()) {
 | 
|        SetGVNFlag(kChangesSpecializedArrayElements);
 | 
|      } else if (IsFastDoubleElementsKind(elements_kind)) {
 | 
| @@ -4843,11 +4973,19 @@ class HStoreKeyed
 | 
|    bool IsDehoisted() { return is_dehoisted_; }
 | 
|    void SetDehoisted(bool is_dehoisted) { is_dehoisted_ = is_dehoisted; }
 | 
|  
 | 
| +  virtual void SetSideEffectDominator(GVNFlag side_effect, HValue* dominator) {
 | 
| +    ASSERT(side_effect == kChangesNewSpacePromotion);
 | 
| +    new_space_dominator_ = dominator;
 | 
| +  }
 | 
| +
 | 
| +  HValue* new_space_dominator() const { return new_space_dominator_; }
 | 
| +
 | 
|    bool NeedsWriteBarrier() {
 | 
|      if (value_is_smi()) {
 | 
|        return false;
 | 
|      } else {
 | 
| -      return StoringValueNeedsWriteBarrier(value());
 | 
| +      return StoringValueNeedsWriteBarrier(value()) &&
 | 
| +          ReceiverObjectNeedsWriteBarrier(elements(), new_space_dominator());
 | 
|      }
 | 
|    }
 | 
|  
 | 
| @@ -4861,6 +4999,7 @@ class HStoreKeyed
 | 
|    ElementsKind elements_kind_;
 | 
|    uint32_t index_offset_;
 | 
|    bool is_dehoisted_;
 | 
| +  HValue* new_space_dominator_;
 | 
|  };
 | 
|  
 | 
|  
 | 
| @@ -4899,9 +5038,10 @@ class HStoreKeyedGeneric: public HTemplateInstruction<4> {
 | 
|  };
 | 
|  
 | 
|  
 | 
| -class HTransitionElementsKind: public HTemplateInstruction<1> {
 | 
| +class HTransitionElementsKind: public HTemplateInstruction<2> {
 | 
|   public:
 | 
| -  HTransitionElementsKind(HValue* object,
 | 
| +  HTransitionElementsKind(HValue* context,
 | 
| +                          HValue* object,
 | 
|                            Handle<Map> original_map,
 | 
|                            Handle<Map> transitioned_map)
 | 
|        : original_map_(original_map),
 | 
| @@ -4909,6 +5049,7 @@ class HTransitionElementsKind: public HTemplateInstruction<1> {
 | 
|          from_kind_(original_map->elements_kind()),
 | 
|          to_kind_(transitioned_map->elements_kind()) {
 | 
|      SetOperandAt(0, object);
 | 
| +    SetOperandAt(1, context);
 | 
|      SetFlag(kUseGVN);
 | 
|      SetGVNFlag(kChangesElementsKind);
 | 
|      if (original_map->has_fast_double_elements()) {
 | 
| @@ -4927,6 +5068,7 @@ class HTransitionElementsKind: public HTemplateInstruction<1> {
 | 
|    }
 | 
|  
 | 
|    HValue* object() { return OperandAt(0); }
 | 
| +  HValue* context() { return OperandAt(1); }
 | 
|    Handle<Map> original_map() { return original_map_; }
 | 
|    Handle<Map> transitioned_map() { return transitioned_map_; }
 | 
|    ElementsKind from_kind() { return from_kind_; }
 | 
| @@ -5079,40 +5221,6 @@ class HStringLength: public HUnaryOperation {
 | 
|  };
 | 
|  
 | 
|  
 | 
| -class HAllocateObject: public HTemplateInstruction<1> {
 | 
| - public:
 | 
| -  HAllocateObject(HValue* context, Handle<JSFunction> constructor)
 | 
| -      : constructor_(constructor) {
 | 
| -    SetOperandAt(0, context);
 | 
| -    set_representation(Representation::Tagged());
 | 
| -    SetGVNFlag(kChangesNewSpacePromotion);
 | 
| -  }
 | 
| -
 | 
| -  // Maximum instance size for which allocations will be inlined.
 | 
| -  static const int kMaxSize = 64 * kPointerSize;
 | 
| -
 | 
| -  HValue* context() { return OperandAt(0); }
 | 
| -  Handle<JSFunction> constructor() { return constructor_; }
 | 
| -
 | 
| -  virtual Representation RequiredInputRepresentation(int index) {
 | 
| -    return Representation::Tagged();
 | 
| -  }
 | 
| -  virtual Handle<Map> GetMonomorphicJSObjectMap() {
 | 
| -    ASSERT(constructor()->has_initial_map());
 | 
| -    return Handle<Map>(constructor()->initial_map());
 | 
| -  }
 | 
| -  virtual HType CalculateInferredType();
 | 
| -
 | 
| -  DECLARE_CONCRETE_INSTRUCTION(AllocateObject)
 | 
| -
 | 
| - private:
 | 
| -  // TODO(svenpanne) Might be safe, but leave it out until we know for sure.
 | 
| -  //  virtual bool IsDeletable() const { return true; }
 | 
| -
 | 
| -  Handle<JSFunction> constructor_;
 | 
| -};
 | 
| -
 | 
| -
 | 
|  template <int V>
 | 
|  class HMaterializedLiteral: public HTemplateInstruction<V> {
 | 
|   public:
 | 
| @@ -5346,6 +5454,22 @@ class HTypeof: public HTemplateInstruction<2> {
 | 
|  };
 | 
|  
 | 
|  
 | 
| +class HTrapAllocationMemento : public HTemplateInstruction<1> {
 | 
| + public:
 | 
| +  explicit HTrapAllocationMemento(HValue* obj) {
 | 
| +    SetOperandAt(0, obj);
 | 
| +  }
 | 
| +
 | 
| +  virtual Representation RequiredInputRepresentation(int index) {
 | 
| +    return Representation::Tagged();
 | 
| +  }
 | 
| +
 | 
| +  HValue* object() { return OperandAt(0); }
 | 
| +
 | 
| +  DECLARE_CONCRETE_INSTRUCTION(TrapAllocationMemento)
 | 
| +};
 | 
| +
 | 
| +
 | 
|  class HToFastProperties: public HUnaryOperation {
 | 
|   public:
 | 
|    explicit HToFastProperties(HValue* value) : HUnaryOperation(value) {
 | 
| 
 |