Version 3.1.4

Fixed incorrect compare of prototypes of the global object (issue 1082).

Fixed a bug in optimizing calls to global functions (issue 1106).

Made optimized Function.prototype.apply safe for non-JSObject first arguments (issue 1128).

Fixed an error related to element accessors on Object.prototype and parser errors (issue 1130).

Fixed a bug in sorting an array with large array indices (issue 1131).

Properly treat exceptions thrown while compiling (issue 1132).

Fixed bug in register requirements for function.apply (issue 1133).

Fixed a representation change bug in the Hydrogen graph construction (issue 1134).

Fixed the semantics of delete on parameters (issue 1136).

Fixed a optimizer bug related to moving instructions with side effects (issue 1138).

Added support for the global object in Object.keys (issue 1150).

Fixed incorrect value for Math.LOG10E (issue http://code.google.com/p/chromium/issues/detail?id=72555)

Performance improvements on the IA32 platform.

Implement assignment to undefined reference in ES5 Strict Mode.



git-svn-id: http://v8.googlecode.com/svn/trunk@6768 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index 05ff68c..a0d932f 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -48,6 +48,7 @@
 
 #define HYDROGEN_ALL_INSTRUCTION_LIST(V)       \
   V(ArithmeticBinaryOperation)                 \
+  V(BinaryCall)                                \
   V(BinaryOperation)                           \
   V(BitwiseBinaryOperation)                    \
   V(Call)                                      \
@@ -58,6 +59,7 @@
   V(Phi)                                       \
   V(StoreKeyed)                                \
   V(StoreNamed)                                \
+  V(UnaryCall)                                 \
   V(UnaryControlInstruction)                   \
   V(UnaryOperation)                            \
   HYDROGEN_CONCRETE_INSTRUCTION_LIST(V)
@@ -127,12 +129,15 @@
   V(LoadKeyedGeneric)                          \
   V(LoadNamedField)                            \
   V(LoadNamedGeneric)                          \
+  V(LoadPixelArrayElement)                     \
+  V(LoadPixelArrayExternalPointer)             \
   V(Mod)                                       \
   V(Mul)                                       \
   V(ObjectLiteral)                             \
   V(OsrEntry)                                  \
   V(OuterContext)                              \
   V(Parameter)                                 \
+  V(PixelArrayLength)                          \
   V(Power)                                     \
   V(PushArgument)                              \
   V(RegExpLiteral)                             \
@@ -164,6 +169,7 @@
   V(InobjectFields)                            \
   V(BackingStoreFields)                        \
   V(ArrayElements)                             \
+  V(PixelArrayElements)                        \
   V(GlobalVars)                                \
   V(Maps)                                      \
   V(ArrayLengths)                              \
@@ -289,6 +295,7 @@
     kTagged,
     kDouble,
     kInteger32,
+    kExternal,
     kNumRepresentations
   };
 
@@ -298,6 +305,7 @@
   static Representation Tagged() { return Representation(kTagged); }
   static Representation Integer32() { return Representation(kInteger32); }
   static Representation Double() { return Representation(kDouble); }
+  static Representation External() { return Representation(kExternal); }
 
   bool Equals(const Representation& other) const {
     return kind_ == other.kind_;
@@ -308,6 +316,7 @@
   bool IsTagged() const { return kind_ == kTagged; }
   bool IsInteger32() const { return kind_ == kInteger32; }
   bool IsDouble() const { return kind_ == kDouble; }
+  bool IsExternal() const { return kind_ == kExternal; }
   bool IsSpecialization() const {
     return kind_ == kInteger32 || kind_ == kDouble;
   }
@@ -602,9 +611,6 @@
 
   virtual HType CalculateInferredType() const;
 
-  // Helper for type conversions used by normal and phi instructions.
-  void InsertInputConversion(HInstruction* previous, int index, HType type);
-
 #ifdef DEBUG
   virtual void Verify() = 0;
 #endif
@@ -1041,27 +1047,15 @@
 
 class HPushArgument: public HUnaryOperation {
  public:
-  explicit HPushArgument(HValue* value)
-      : HUnaryOperation(value), argument_index_(-1) {
-    set_representation(Representation::Tagged());
-  }
+  explicit HPushArgument(HValue* value) : HUnaryOperation(value) { }
 
   virtual Representation RequiredInputRepresentation(int index) const {
     return Representation::Tagged();
   }
 
-  virtual void PrintDataTo(StringStream* stream) const;
   HValue* argument() const { return OperandAt(0); }
-  int argument_index() const { return argument_index_; }
-  void set_argument_index(int index) {
-    ASSERT(argument_index_ == -1 || index == argument_index_);
-    argument_index_ = index;
-  }
 
   DECLARE_CONCRETE_INSTRUCTION(PushArgument, "push_argument")
-
- private:
-  int argument_index_;
 };
 
 
@@ -1124,36 +1118,80 @@
 
 class HCall: public HInstruction {
  public:
-  // Construct a call with uninitialized arguments. The argument count
-  // includes the receiver.
-  explicit HCall(int count);
+  // The argument count includes the receiver.
+  explicit HCall(int argument_count) : argument_count_(argument_count) {
+    set_representation(Representation::Tagged());
+    SetAllSideEffects();
+  }
 
   virtual HType CalculateInferredType() const { return HType::Tagged(); }
 
-  // TODO(3190496): This needs a cleanup. We don't want the arguments
-  // be operands of the call instruction. This results in bad code quality.
-  virtual int argument_count() const { return arguments_.length(); }
-  virtual int OperandCount() const { return argument_count(); }
-  virtual HValue* OperandAt(int index) const { return arguments_[index]; }
-  virtual HPushArgument* PushArgumentAt(int index) const {
-    return HPushArgument::cast(OperandAt(index));
-  }
-  virtual HValue* ArgumentAt(int index) const {
-    return PushArgumentAt(index)->argument();
-  }
-  virtual void SetArgumentAt(int index, HPushArgument* push_argument);
+  virtual int argument_count() const { return argument_count_; }
 
   virtual void PrintDataTo(StringStream* stream) const;
 
   DECLARE_INSTRUCTION(Call)
 
- protected:
-  virtual void InternalSetOperandAt(int index, HValue* value) {
-    arguments_[index] = value;
+ private:
+  int argument_count_;
+};
+
+
+class HUnaryCall: public HCall {
+ public:
+  HUnaryCall(HValue* value, int argument_count)
+      : HCall(argument_count), value_(NULL) {
+    SetOperandAt(0, value);
   }
 
-  int argument_count_;
-  Vector<HValue*> arguments_;
+  virtual void PrintDataTo(StringStream* stream) const;
+
+  HValue* value() const { return value_; }
+
+  virtual int OperandCount() const { return 1; }
+  virtual HValue* OperandAt(int index) const {
+    ASSERT(index == 0);
+    return value_;
+  }
+
+  DECLARE_INSTRUCTION(UnaryCall)
+
+ protected:
+  virtual void InternalSetOperandAt(int index, HValue* value) {
+    ASSERT(index == 0);
+    value_ = value;
+  }
+
+ private:
+  HValue* value_;
+};
+
+
+class HBinaryCall: public HCall {
+ public:
+  HBinaryCall(HValue* first, HValue* second, int argument_count)
+      : HCall(argument_count) {
+    SetOperandAt(0, first);
+    SetOperandAt(1, second);
+  }
+
+  virtual void PrintDataTo(StringStream* stream) const;
+
+  HValue* first() const { return operands_[0]; }
+  HValue* second() const { return operands_[1]; }
+
+  virtual int OperandCount() const { return 2; }
+  virtual HValue* OperandAt(int index) const { return operands_[index]; }
+
+  DECLARE_INSTRUCTION(BinaryCall)
+
+ protected:
+  virtual void InternalSetOperandAt(int index, HValue* value) {
+    operands_[index] = value;
+  }
+
+ private:
+  HOperandVector<2> operands_;
 };
 
 
@@ -1163,6 +1201,7 @@
       : HCall(argument_count), function_(function) { }
 
   Handle<JSFunction> function() const { return function_; }
+
   bool IsApplyFunction() const {
     return function_->code() == Builtins::builtin(Builtins::FunctionApply);
   }
@@ -1176,42 +1215,32 @@
 };
 
 
-class HCallKeyed: public HCall {
+class HCallKeyed: public HBinaryCall {
  public:
-  HCallKeyed(HValue* key, int argument_count)
-      : HCall(argument_count + 1) {
-    SetOperandAt(0, key);
+  HCallKeyed(HValue* context, HValue* key, int argument_count)
+      : HBinaryCall(context, key, argument_count) {
   }
 
   virtual Representation RequiredInputRepresentation(int index) const {
     return Representation::Tagged();
   }
 
-  // TODO(3190496): This is a hack to get an additional operand that
-  // is not an argument to work with the current setup. This _needs_ a cleanup.
-  // (see HCall)
-  virtual void PrintDataTo(StringStream* stream) const;
-  HValue* key() const { return OperandAt(0); }
-  virtual int argument_count() const { return arguments_.length() - 1; }
-  virtual int OperandCount() const { return arguments_.length(); }
-  virtual HValue* OperandAt(int index) const { return arguments_[index]; }
-  virtual HPushArgument* PushArgumentAt(int index) const {
-    return HPushArgument::cast(OperandAt(index + 1));
-  }
-  virtual void SetArgumentAt(int index, HPushArgument* push_argument) {
-    HCall::SetArgumentAt(index + 1, push_argument);
-  }
+  HValue* context() const { return first(); }
+  HValue* key() const { return second(); }
 
   DECLARE_CONCRETE_INSTRUCTION(CallKeyed, "call_keyed")
 };
 
 
-class HCallNamed: public HCall {
+class HCallNamed: public HUnaryCall {
  public:
-  HCallNamed(Handle<String> name, int argument_count)
-      : HCall(argument_count), name_(name) { }
+  HCallNamed(HValue* context, Handle<String> name, int argument_count)
+      : HUnaryCall(context, argument_count), name_(name) {
+  }
+
   virtual void PrintDataTo(StringStream* stream) const;
 
+  HValue* context() const { return value(); }
   Handle<String> name() const { return name_; }
 
   DECLARE_CONCRETE_INSTRUCTION(CallNamed, "call_named")
@@ -1221,21 +1250,27 @@
 };
 
 
-class HCallFunction: public HCall {
+class HCallFunction: public HUnaryCall {
  public:
-  explicit HCallFunction(int argument_count) : HCall(argument_count) { }
+  HCallFunction(HValue* context, int argument_count)
+      : HUnaryCall(context, argument_count) {
+  }
+
+  HValue* context() const { return value(); }
 
   DECLARE_CONCRETE_INSTRUCTION(CallFunction, "call_function")
 };
 
 
-class HCallGlobal: public HCall {
+class HCallGlobal: public HUnaryCall {
  public:
-  HCallGlobal(Handle<String> name, int argument_count)
-      : HCall(argument_count), name_(name) { }
+  HCallGlobal(HValue* context, Handle<String> name, int argument_count)
+      : HUnaryCall(context, argument_count), name_(name) {
+  }
 
   virtual void PrintDataTo(StringStream* stream) const;
 
+  HValue* context() const { return value(); }
   Handle<String> name() const { return name_; }
 
   DECLARE_CONCRETE_INSTRUCTION(CallGlobal, "call_global")
@@ -1247,10 +1282,11 @@
 
 class HCallKnownGlobal: public HCall {
  public:
-  HCallKnownGlobal(Handle<JSFunction> target,
-                   int argument_count)
+  HCallKnownGlobal(Handle<JSFunction> target, int argument_count)
       : HCall(argument_count), target_(target) { }
 
+  virtual void PrintDataTo(StringStream* stream) const;
+
   Handle<JSFunction> target() const { return target_; }
 
   DECLARE_CONCRETE_INSTRUCTION(CallKnownGlobal, "call_known_global")
@@ -1260,15 +1296,18 @@
 };
 
 
-class HCallNew: public HCall {
+class HCallNew: public HBinaryCall {
  public:
-  explicit HCallNew(int argument_count) : HCall(argument_count) { }
+  HCallNew(HValue* context, HValue* constructor, int argument_count)
+      : HBinaryCall(context, constructor, argument_count) {
+  }
 
   virtual Representation RequiredInputRepresentation(int index) const {
     return Representation::Tagged();
   }
 
-  HValue* constructor() const { return ArgumentAt(0); }
+  HValue* context() const { return first(); }
+  HValue* constructor() const { return second(); }
 
   DECLARE_CONCRETE_INSTRUCTION(CallNew, "call_new")
 };
@@ -1334,6 +1373,27 @@
 };
 
 
+class HPixelArrayLength: public HUnaryOperation {
+ public:
+  explicit HPixelArrayLength(HValue* value) : HUnaryOperation(value) {
+    set_representation(Representation::Integer32());
+    // The result of this instruction is idempotent as long as its inputs don't
+    // change.  The length of a pixel array cannot change once set, so it's not
+    // necessary to introduce a kDependsOnArrayLengths or any other dependency.
+    SetFlag(kUseGVN);
+  }
+
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::Tagged();
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(PixelArrayLength, "pixel_array_length")
+
+ protected:
+  virtual bool DataEquals(HValue* other) const { return true; }
+};
+
+
 class HBitNot: public HUnaryOperation {
  public:
   explicit HBitNot(HValue* value) : HUnaryOperation(value) {
@@ -1452,6 +1512,30 @@
 };
 
 
+class HLoadPixelArrayExternalPointer: public HUnaryOperation {
+ public:
+  explicit HLoadPixelArrayExternalPointer(HValue* value)
+      : HUnaryOperation(value) {
+    set_representation(Representation::External());
+    // The result of this instruction is idempotent as long as its inputs don't
+    // change.  The external array of a pixel array elements object cannot
+    // change once set, so it's no necessary to introduce any additional
+    // dependencies on top of the inputs.
+    SetFlag(kUseGVN);
+  }
+
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::Tagged();
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(LoadPixelArrayExternalPointer,
+                               "load-pixel-array-external-pointer")
+
+ protected:
+  virtual bool DataEquals(HValue* other) const { return true; }
+};
+
+
 class HCheckMap: public HUnaryOperation {
  public:
   HCheckMap(HValue* value, Handle<Map> map)
@@ -1861,7 +1945,6 @@
     operands_[index] = value;
   }
 
- private:
   HOperandVector<2> operands_;
 };
 
@@ -2073,7 +2156,11 @@
   }
 
   void SetInputRepresentation(Representation r);
-  virtual bool EmitAtUses() const { return uses()->length() <= 1; }
+
+  virtual bool EmitAtUses() const {
+    return !HasSideEffects() && (uses()->length() <= 1);
+  }
+
   virtual Representation RequiredInputRepresentation(int index) const {
     return input_representation_;
   }
@@ -2111,7 +2198,10 @@
     SetFlag(kUseGVN);
   }
 
-  virtual bool EmitAtUses() const { return uses()->length() <= 1; }
+  virtual bool EmitAtUses() const {
+    return !HasSideEffects() && (uses()->length() <= 1);
+  }
+
   virtual Representation RequiredInputRepresentation(int index) const {
     return Representation::Tagged();
   }
@@ -2130,7 +2220,11 @@
     set_representation(Representation::Tagged());
     SetFlag(kUseGVN);
   }
-  virtual bool EmitAtUses() const { return uses()->length() <= 1; }
+
+  virtual bool EmitAtUses() const {
+    return !HasSideEffects() && (uses()->length() <= 1);
+  }
+
   virtual Representation RequiredInputRepresentation(int index) const {
     return Representation::Tagged();
   }
@@ -2187,7 +2281,9 @@
     SetFlag(kUseGVN);
   }
 
-  virtual bool EmitAtUses() const { return uses()->length() <= 1; }
+  virtual bool EmitAtUses() const {
+    return !HasSideEffects() && (uses()->length() <= 1);
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(IsConstructCall, "is_construct_call")
 
@@ -2278,20 +2374,42 @@
 };
 
 
-class HInstanceOf: public HBinaryOperation {
+class HInstanceOf: public HInstruction {
  public:
-  HInstanceOf(HValue* left, HValue* right) : HBinaryOperation(left, right) {
+  HInstanceOf(HValue* context, HValue* left, HValue* right) {
+    SetOperandAt(0, context);
+    SetOperandAt(1, left);
+    SetOperandAt(2, right);
     set_representation(Representation::Tagged());
     SetAllSideEffects();
   }
 
-  virtual bool EmitAtUses() const { return uses()->length() <= 1; }
+  HValue* context() const { return operands_[0]; }
+  HValue* left() const { return operands_[1]; }
+  HValue* right() const { return operands_[2]; }
+
+  virtual bool EmitAtUses() const {
+    return !HasSideEffects() && (uses()->length() <= 1);
+  }
 
   virtual Representation RequiredInputRepresentation(int index) const {
     return Representation::Tagged();
   }
 
+  virtual void PrintDataTo(StringStream* stream) const;
+
+  virtual int OperandCount() const { return 3; }
+  virtual HValue* OperandAt(int index) const { return operands_[index]; }
+
   DECLARE_CONCRETE_INSTRUCTION(InstanceOf, "instance_of")
+
+ protected:
+  virtual void InternalSetOperandAt(int index, HValue* value) {
+    operands_[index] = value;
+  }
+
+ private:
+  HOperandVector<3> operands_;
 };
 
 
@@ -2560,18 +2678,17 @@
 };
 
 
-class HCallStub: public HInstruction {
+class HCallStub: public HUnaryCall {
  public:
-  HCallStub(CodeStub::Major major_key, int argument_count)
-      : major_key_(major_key),
-        argument_count_(argument_count),
+  HCallStub(HValue* context, CodeStub::Major major_key, int argument_count)
+      : HUnaryCall(context, argument_count),
+        major_key_(major_key),
         transcendental_type_(TranscendentalCache::kNumberOfCaches) {
-    set_representation(Representation::Tagged());
-    SetAllSideEffects();
   }
 
   CodeStub::Major major_key() { return major_key_; }
-  int argument_count() { return argument_count_; }
+
+  HValue* context() const { return value(); }
 
   void set_transcendental_type(TranscendentalCache::Type transcendental_type) {
     transcendental_type_ = transcendental_type;
@@ -2579,13 +2696,13 @@
   TranscendentalCache::Type transcendental_type() {
     return transcendental_type_;
   }
+
   virtual void PrintDataTo(StringStream* stream) const;
 
   DECLARE_CONCRETE_INSTRUCTION(CallStub, "call_stub")
 
  private:
   CodeStub::Major major_key_;
-  int argument_count_;
   TranscendentalCache::Type transcendental_type_;
 };
 
@@ -2763,15 +2880,16 @@
 };
 
 
-class HLoadNamedGeneric: public HUnaryOperation {
+class HLoadNamedGeneric: public HBinaryOperation {
  public:
-  HLoadNamedGeneric(HValue* object, Handle<Object> name)
-      : HUnaryOperation(object), name_(name) {
+  HLoadNamedGeneric(HValue* context, HValue* object, Handle<Object> name)
+      : HBinaryOperation(context, object), name_(name) {
     set_representation(Representation::Tagged());
     SetAllSideEffects();
   }
 
-  HValue* object() const { return OperandAt(0); }
+  HValue* context() const { return OperandAt(0); }
+  HValue* object() const { return OperandAt(1); }
   Handle<Object> name() const { return name_; }
 
   virtual Representation RequiredInputRepresentation(int index) const {
@@ -2846,19 +2964,67 @@
 };
 
 
+class HLoadPixelArrayElement: public HBinaryOperation {
+ public:
+  HLoadPixelArrayElement(HValue* external_elements, HValue* key)
+      : HBinaryOperation(external_elements, key) {
+    set_representation(Representation::Integer32());
+    SetFlag(kDependsOnPixelArrayElements);
+    // Native code could change the pixel array.
+    SetFlag(kDependsOnCalls);
+    SetFlag(kUseGVN);
+  }
+
+  virtual void PrintDataTo(StringStream* stream) const;
+
+  virtual Representation RequiredInputRepresentation(int index) const {
+    // The key is supposed to be Integer32, but the base pointer
+    // for the element load is a naked pointer.
+    return (index == 1) ? Representation::Integer32()
+        : Representation::External();
+  }
+
+  HValue* external_pointer() const { return OperandAt(0); }
+  HValue* key() const { return OperandAt(1); }
+
+  DECLARE_CONCRETE_INSTRUCTION(LoadPixelArrayElement,
+                               "load_pixel_array_element")
+
+ protected:
+  virtual bool DataEquals(HValue* other) const { return true; }
+};
+
+
 class HLoadKeyedGeneric: public HLoadKeyed {
  public:
-  HLoadKeyedGeneric(HValue* obj, HValue* key) : HLoadKeyed(obj, key) {
+  HLoadKeyedGeneric(HContext* context, HValue* obj, HValue* key)
+      : HLoadKeyed(obj, key), context_(NULL) {
+    SetOperandAt(2, context);
     SetAllSideEffects();
   }
 
+  HValue* context() const { return context_; }
+  HValue* object() const { return operands_[0]; }
+  HValue* key() const { return operands_[1]; }
+
+  virtual int OperandCount() const { return 3; }
+  virtual HValue* OperandAt(int index) const {
+    return (index < 2) ? operands_[index] : context_;
+  }
+
   DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric, "load_keyed_generic")
+
+ protected:
+  virtual void InternalSetOperandAt(int index, HValue* value);
+
+ private:
+  HValue* context_;
 };
 
 
 class HStoreNamed: public HBinaryOperation {
  public:
-  HStoreNamed(HValue* obj, Handle<Object> name, HValue* val)
+  HStoreNamed(HValue* obj, Handle<String> name, HValue* val)
       : HBinaryOperation(obj, val), name_(name) {
   }
 
@@ -2869,21 +3035,21 @@
   virtual void PrintDataTo(StringStream* stream) const;
 
   HValue* object() const { return OperandAt(0); }
-  Handle<Object> name() const { return name_; }
+  Handle<String> name() const { return name_; }
   HValue* value() const { return OperandAt(1); }
   void set_value(HValue* value) { SetOperandAt(1, value); }
 
   DECLARE_INSTRUCTION(StoreNamed)
 
  private:
-  Handle<Object> name_;
+  Handle<String> name_;
 };
 
 
 class HStoreNamedField: public HStoreNamed {
  public:
   HStoreNamedField(HValue* obj,
-                   Handle<Object> name,
+                   Handle<String> name,
                    HValue* val,
                    bool in_object,
                    int offset)
@@ -2922,12 +3088,32 @@
 
 class HStoreNamedGeneric: public HStoreNamed {
  public:
-  HStoreNamedGeneric(HValue* obj, Handle<Object> name, HValue* val)
-      : HStoreNamed(obj, name, val) {
+  HStoreNamedGeneric(HValue* context,
+                     HValue* object,
+                     Handle<String> name,
+                     HValue* value)
+      : HStoreNamed(object, name, value), context_(NULL) {
+    SetOperandAt(2, context);
     SetAllSideEffects();
   }
 
+  HValue* context() const { return context_; }
+  HValue* object() const { return operands_[0]; }
+  HValue* value() const { return operands_[1]; }
+
+  virtual int OperandCount() const { return 3; }
+
+  virtual HValue* OperandAt(int index) const {
+    return (index < 2) ? operands_[index] : context_;
+  }
+
   DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric, "store_named_generic")
+
+ protected:
+  virtual void InternalSetOperandAt(int index, HValue* value);
+
+ private:
+  HValue* context_;
 };
 
 
@@ -2962,7 +3148,6 @@
     operands_[index] = value;
   }
 
- private:
   HOperandVector<3> operands_;
 };
 
@@ -2987,12 +3172,33 @@
 
 class HStoreKeyedGeneric: public HStoreKeyed {
  public:
-  HStoreKeyedGeneric(HValue* obj, HValue* key, HValue* val)
-      : HStoreKeyed(obj, key, val) {
+  HStoreKeyedGeneric(HValue* context,
+                     HValue* object,
+                     HValue* key,
+                     HValue* value)
+      : HStoreKeyed(object, key, value), context_(NULL) {
+    SetOperandAt(3, context);
     SetAllSideEffects();
   }
 
+  HValue* context() const { return context_; }
+  HValue* object() const { return operands_[0]; }
+  HValue* key() const { return operands_[1]; }
+  HValue* value() const { return operands_[2]; }
+
+  virtual int OperandCount() const { return 4; }
+
+  virtual HValue* OperandAt(int index) const {
+    return (index < 3) ? operands_[index] : context_;
+  }
+
   DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric, "store_keyed_generic")
+
+ protected:
+  virtual void InternalSetOperandAt(int index, HValue* value);
+
+ private:
+  HValue* context_;
 };
 
 
@@ -3094,22 +3300,36 @@
 
 class HObjectLiteral: public HMaterializedLiteral {
  public:
-  HObjectLiteral(Handle<FixedArray> constant_properties,
+  HObjectLiteral(HValue* context,
+                 Handle<FixedArray> constant_properties,
                  bool fast_elements,
                  int literal_index,
                  int depth)
       : HMaterializedLiteral(literal_index, depth),
+        context_(NULL),
         constant_properties_(constant_properties),
-        fast_elements_(fast_elements) {}
+        fast_elements_(fast_elements) {
+    SetOperandAt(0, context);
+  }
 
+  HValue* context() const { return context_; }
   Handle<FixedArray> constant_properties() const {
     return constant_properties_;
   }
   bool fast_elements() const { return fast_elements_; }
 
+  virtual int OperandCount() const { return 1; }
+  virtual HValue* OperandAt(int index) const { return context_; }
+
   DECLARE_CONCRETE_INSTRUCTION(ObjectLiteral, "object_literal")
 
+ protected:
+  virtual void InternalSetOperandAt(int index, HValue* value) {
+    context_ = value;
+  }
+
  private:
+  HValue* context_;
   Handle<FixedArray> constant_properties_;
   bool fast_elements_;
 };