Merge revision 7239 (=-7215, -7212) to trunk
Review URL: http://codereview.chromium.org/6676065

git-svn-id: http://v8.googlecode.com/svn/trunk@7241 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index 369a0b8..74c38c2 100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -1604,26 +1604,27 @@
       break;
   }
 
-  // For compound assignments we need another deoptimization point after the
-  // variable/property load.
   if (expr->is_compound()) {
     { AccumulatorValueContext context(this);
       switch (assign_type) {
         case VARIABLE:
           EmitVariableLoad(expr->target()->AsVariableProxy()->var());
-          PrepareForBailout(expr->target(), TOS_REG);
           break;
         case NAMED_PROPERTY:
           EmitNamedPropertyLoad(property);
-          PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG);
           break;
         case KEYED_PROPERTY:
           EmitKeyedPropertyLoad(property);
-          PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG);
           break;
       }
     }
 
+    // For property compound assignments we need another deoptimization
+    // point after the property load.
+    if (property != NULL) {
+      PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG);
+    }
+
     Token::Value op = expr->binary_op();
     __ push(r0);  // Left operand goes on the stack.
     VisitForAccumulatorValue(expr->value());
@@ -3804,11 +3805,7 @@
 
   // We need a second deoptimization point after loading the value
   // in case evaluating the property load my have a side effect.
-  if (assign_type == VARIABLE) {
-    PrepareForBailout(expr->expression(), TOS_REG);
-  } else {
-    PrepareForBailout(expr->increment(), TOS_REG);
-  }
+  PrepareForBailout(expr->increment(), TOS_REG);
 
   // Call ToNumber only if operand is not a smi.
   Label no_conversion;
diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
index 3327cd8..861ea38 100644
--- a/src/arm/lithium-arm.cc
+++ b/src/arm/lithium-arm.cc
@@ -1725,21 +1725,14 @@
 }
 
 
-LInstruction* LChunkBuilder::DoLoadGlobalCell(HLoadGlobalCell* instr) {
-  LLoadGlobalCell* result = new LLoadGlobalCell();
+LInstruction* LChunkBuilder::DoLoadGlobal(HLoadGlobal* instr) {
+  LLoadGlobal* result = new LLoadGlobal();
   return instr->check_hole_value()
       ? AssignEnvironment(DefineAsRegister(result))
       : DefineAsRegister(result);
 }
 
 
-LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
-  LOperand* global_object = UseFixed(instr->global_object(), r0);
-  LLoadGlobalGeneric* result = new LLoadGlobalGeneric(global_object);
-  return MarkAsCall(DefineFixed(result, r0), instr);
-}
-
-
 LInstruction* LChunkBuilder::DoStoreGlobal(HStoreGlobal* instr) {
   if (instr->check_hole_value()) {
     LOperand* temp = TempRegister();
diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h
index d5c4051..a148fdb 100644
--- a/src/arm/lithium-arm.h
+++ b/src/arm/lithium-arm.h
@@ -119,8 +119,7 @@
   V(LoadElements)                               \
   V(LoadExternalArrayPointer)                   \
   V(LoadFunctionPrototype)                      \
-  V(LoadGlobalCell)                             \
-  V(LoadGlobalGeneric)                          \
+  V(LoadGlobal)                                 \
   V(LoadKeyedFastElement)                       \
   V(LoadKeyedGeneric)                           \
   V(LoadNamedField)                             \
@@ -1223,25 +1222,10 @@
 };
 
 
-class LLoadGlobalCell: public LTemplateInstruction<1, 0, 0> {
+class LLoadGlobal: public LTemplateInstruction<1, 0, 0> {
  public:
-  DECLARE_CONCRETE_INSTRUCTION(LoadGlobalCell, "load-global-cell")
-  DECLARE_HYDROGEN_ACCESSOR(LoadGlobalCell)
-};
-
-
-class LLoadGlobalGeneric: public LTemplateInstruction<1, 1, 0> {
- public:
-  explicit LLoadGlobalGeneric(LOperand* global_object) {
-    inputs_[0] = global_object;
-  }
-
-  DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric, "load-global-generic")
-  DECLARE_HYDROGEN_ACCESSOR(LoadGlobalGeneric)
-
-  LOperand* global_object() { return inputs_[0]; }
-  Handle<Object> name() const { return hydrogen()->name(); }
-  bool for_typeof() const { return hydrogen()->for_typeof(); }
+  DECLARE_CONCRETE_INSTRUCTION(LoadGlobal, "load-global")
+  DECLARE_HYDROGEN_ACCESSOR(LoadGlobal)
 };
 
 
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index 3d8d0ba..a2d1df0 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -2106,7 +2106,7 @@
 }
 
 
-void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) {
+void LCodeGen::DoLoadGlobal(LLoadGlobal* instr) {
   Register result = ToRegister(instr->result());
   __ mov(ip, Operand(Handle<Object>(instr->hydrogen()->cell())));
   __ ldr(result, FieldMemOperand(ip, JSGlobalPropertyCell::kValueOffset));
@@ -2118,18 +2118,6 @@
 }
 
 
-void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
-  ASSERT(ToRegister(instr->global_object()).is(r0));
-  ASSERT(ToRegister(instr->result()).is(r0));
-
-  __ mov(r2, Operand(instr->name()));
-  RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET :
-                                               RelocInfo::CODE_TARGET_CONTEXT;
-  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
-  CallCode(ic, mode, instr);
-}
-
-
 void LCodeGen::DoStoreGlobal(LStoreGlobal* instr) {
   Register value = ToRegister(instr->InputAt(0));
   Register scratch = scratch0();
diff --git a/src/ast.cc b/src/ast.cc
index 907ed1d..184aaa5 100644
--- a/src/ast.cc
+++ b/src/ast.cc
@@ -621,21 +621,24 @@
 
 
 bool Call::ComputeGlobalTarget(Handle<GlobalObject> global,
-                               LookupResult* lookup) {
+                               Handle<String> name) {
   target_ = Handle<JSFunction>::null();
   cell_ = Handle<JSGlobalPropertyCell>::null();
-  ASSERT(lookup->IsProperty() &&
-         lookup->type() == NORMAL &&
-         lookup->holder() == *global);
-  cell_ = Handle<JSGlobalPropertyCell>(global->GetPropertyCell(lookup));
-  if (cell_->value()->IsJSFunction()) {
-    Handle<JSFunction> candidate(JSFunction::cast(cell_->value()));
-    // If the function is in new space we assume it's more likely to
-    // change and thus prefer the general IC code.
-    if (!Heap::InNewSpace(*candidate) &&
-        CanCallWithoutIC(candidate, arguments()->length())) {
-      target_ = candidate;
-      return true;
+  LookupResult lookup;
+  global->Lookup(*name, &lookup);
+  if (lookup.IsProperty() &&
+      lookup.type() == NORMAL &&
+      lookup.holder() == *global) {
+    cell_ = Handle<JSGlobalPropertyCell>(global->GetPropertyCell(&lookup));
+    if (cell_->value()->IsJSFunction()) {
+      Handle<JSFunction> candidate(JSFunction::cast(cell_->value()));
+      // If the function is in new space we assume it's more likely to
+      // change and thus prefer the general IC code.
+      if (!Heap::InNewSpace(*candidate) &&
+          CanCallWithoutIC(candidate, arguments()->length())) {
+        target_ = candidate;
+        return true;
+      }
     }
   }
   return false;
diff --git a/src/ast.h b/src/ast.h
index 42a2057..b00612d 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -1307,7 +1307,7 @@
   Handle<JSGlobalPropertyCell> cell() { return cell_; }
 
   bool ComputeTarget(Handle<Map> type, Handle<String> name);
-  bool ComputeGlobalTarget(Handle<GlobalObject> global, LookupResult* lookup);
+  bool ComputeGlobalTarget(Handle<GlobalObject> global, Handle<String> name);
 
   // Bailout support.
   int ReturnId() const { return return_id_; }
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
index d30a519..fa2deb8 100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -1230,17 +1230,12 @@
 }
 
 
-void HLoadGlobalCell::PrintDataTo(StringStream* stream) {
+void HLoadGlobal::PrintDataTo(StringStream* stream) {
   stream->Add("[%p]", *cell());
   if (check_hole_value()) stream->Add(" (deleteable/read-only)");
 }
 
 
-void HLoadGlobalGeneric::PrintDataTo(StringStream* stream) {
-  stream->Add("%o ", *name());
-}
-
-
 void HStoreGlobal::PrintDataTo(StringStream* stream) {
   stream->Add("[%p] = ", *cell());
   value()->PrintNameTo(stream);
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index 775177a..fc376bd 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -122,8 +122,7 @@
   V(LoadElements)                              \
   V(LoadExternalArrayPointer)                  \
   V(LoadFunctionPrototype)                     \
-  V(LoadGlobalCell)                            \
-  V(LoadGlobalGeneric)                         \
+  V(LoadGlobal)                                \
   V(LoadKeyedFastElement)                      \
   V(LoadKeyedGeneric)                          \
   V(LoadNamedField)                            \
@@ -2786,9 +2785,9 @@
 };
 
 
-class HLoadGlobalCell: public HTemplateInstruction<0> {
+class HLoadGlobal: public HTemplateInstruction<0> {
  public:
-  HLoadGlobalCell(Handle<JSGlobalPropertyCell> cell, bool check_hole_value)
+  HLoadGlobal(Handle<JSGlobalPropertyCell> cell, bool check_hole_value)
       : cell_(cell), check_hole_value_(check_hole_value) {
     set_representation(Representation::Tagged());
     SetFlag(kUseGVN);
@@ -2809,11 +2808,11 @@
     return Representation::None();
   }
 
-  DECLARE_CONCRETE_INSTRUCTION(LoadGlobalCell, "load_global_cell")
+  DECLARE_CONCRETE_INSTRUCTION(LoadGlobal, "load_global")
 
  protected:
   virtual bool DataEquals(HValue* other) {
-    HLoadGlobalCell* b = HLoadGlobalCell::cast(other);
+    HLoadGlobal* b = HLoadGlobal::cast(other);
     return cell_.is_identical_to(b->cell());
   }
 
@@ -2823,38 +2822,6 @@
 };
 
 
-class HLoadGlobalGeneric: public HBinaryOperation {
- public:
-  HLoadGlobalGeneric(HValue* context,
-                     HValue* global_object,
-                     Handle<Object> name,
-                     bool for_typeof)
-      : HBinaryOperation(context, global_object),
-        name_(name),
-        for_typeof_(for_typeof) {
-    set_representation(Representation::Tagged());
-    SetAllSideEffects();
-  }
-
-  HValue* context() { return OperandAt(0); }
-  HValue* global_object() { return OperandAt(1); }
-  Handle<Object> name() const { return name_; }
-  bool for_typeof() const { return for_typeof_; }
-
-  virtual void PrintDataTo(StringStream* stream);
-
-  virtual Representation RequiredInputRepresentation(int index) const {
-    return Representation::Tagged();
-  }
-
-  DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric, "load_global_generic")
-
- private:
-  Handle<Object> name_;
-  bool for_typeof_;
-};
-
-
 class HStoreGlobal: public HUnaryOperation {
  public:
   HStoreGlobal(HValue* value,
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 77714f6..95c075e 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -1961,10 +1961,7 @@
 // Implementation of utility classes to represent an expression's context in
 // the AST.
 AstContext::AstContext(HGraphBuilder* owner, Expression::Context kind)
-    : owner_(owner),
-      kind_(kind),
-      outer_(owner->ast_context()),
-      for_typeof_(false) {
+    : owner_(owner), kind_(kind), outer_(owner->ast_context()) {
   owner->set_ast_context(this);  // Push.
 #ifdef DEBUG
   original_length_ = owner->environment()->length();
@@ -2108,14 +2105,6 @@
 }
 
 
-void HGraphBuilder::VisitForTypeOf(Expression* expr) {
-  ValueContext for_value(this);
-  for_value.set_for_typeof(true);
-  Visit(expr);
-}
-
-
-
 void HGraphBuilder::VisitForControl(Expression* expr,
                                     HBasicBlock* true_block,
                                     HBasicBlock* false_block) {
@@ -2808,21 +2797,29 @@
 }
 
 
-HGraphBuilder::GlobalPropertyAccess HGraphBuilder::LookupGlobalProperty(
-    Variable* var, LookupResult* lookup, bool is_store) {
-  if (var->is_this() || !info()->has_global_object()) {
-    return kUseGeneric;
+void HGraphBuilder::LookupGlobalPropertyCell(Variable* var,
+                                             LookupResult* lookup,
+                                             bool is_store) {
+  if (var->is_this()) {
+    BAILOUT("global this reference");
+  }
+  if (!info()->has_global_object()) {
+    BAILOUT("no global object to optimize VariableProxy");
   }
   Handle<GlobalObject> global(info()->global_object());
   global->Lookup(*var->name(), lookup);
-  if (!lookup->IsProperty() ||
-      lookup->type() != NORMAL ||
-      (is_store && lookup->IsReadOnly()) ||
-      lookup->holder() != *global) {
-    return kUseGeneric;
+  if (!lookup->IsProperty()) {
+    BAILOUT("global variable cell not yet introduced");
   }
-
-  return kUseCell;
+  if (lookup->type() != NORMAL) {
+    BAILOUT("global variable has accessors");
+  }
+  if (is_store && lookup->IsReadOnly()) {
+    BAILOUT("read-only global variable");
+  }
+  if (lookup->holder() != *global) {
+    BAILOUT("global property on prototype of global object");
+  }
 }
 
 
@@ -2858,31 +2855,19 @@
     ast_context()->ReturnInstruction(instr, expr->id());
   } else if (variable->is_global()) {
     LookupResult lookup;
-    GlobalPropertyAccess type = LookupGlobalProperty(variable, &lookup, false);
+    LookupGlobalPropertyCell(variable, &lookup, false);
+    CHECK_BAILOUT;
 
-    if (type == kUseCell &&
-        info()->global_object()->IsAccessCheckNeeded()) {
-      type = kUseGeneric;
+    Handle<GlobalObject> global(info()->global_object());
+    // TODO(3039103): Handle global property load through an IC call when access
+    // checks are enabled.
+    if (global->IsAccessCheckNeeded()) {
+      BAILOUT("global object requires access check");
     }
-
-    if (type == kUseCell) {
-      Handle<GlobalObject> global(info()->global_object());
-      Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
-      bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly();
-      HLoadGlobalCell* instr = new HLoadGlobalCell(cell, check_hole);
-      ast_context()->ReturnInstruction(instr, expr->id());
-    } else {
-      HContext* context = new HContext;
-      AddInstruction(context);
-      HGlobalObject* global_object = new HGlobalObject(context);
-      AddInstruction(global_object);
-      HLoadGlobalGeneric* instr =
-          new HLoadGlobalGeneric(context,
-                                 global_object,
-                                 variable->name(),
-                                 ast_context()->is_for_typeof());
-      ast_context()->ReturnInstruction(instr, expr->id());
-    }
+    Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
+    bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly();
+    HLoadGlobal* instr = new HLoadGlobal(cell, check_hole);
+    ast_context()->ReturnInstruction(instr, expr->id());
   } else {
     BAILOUT("reference to a variable which requires dynamic lookup");
   }
@@ -3239,18 +3224,16 @@
                                                    int position,
                                                    int ast_id) {
   LookupResult lookup;
-  GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true);
-  if (type == kUseCell) {
-    bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly();
-    Handle<GlobalObject> global(info()->global_object());
-    Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
-    HInstruction* instr = new HStoreGlobal(value, cell, check_hole);
-    instr->set_position(position);
-    AddInstruction(instr);
-    if (instr->HasSideEffects()) AddSimulate(ast_id);
-  } else {
-    BAILOUT("global store only supported for cells");
-  }
+  LookupGlobalPropertyCell(var, &lookup, true);
+  CHECK_BAILOUT;
+
+  bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly();
+  Handle<GlobalObject> global(info()->global_object());
+  Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
+  HInstruction* instr = new HStoreGlobal(value, cell, check_hole);
+  instr->set_position(position);
+  AddInstruction(instr);
+  if (instr->HasSideEffects()) AddSimulate(ast_id);
 }
 
 
@@ -4345,12 +4328,10 @@
       // If there is a global property cell for the name at compile time and
       // access check is not enabled we assume that the function will not change
       // and generate optimized code for calling the function.
-      LookupResult lookup;
-      GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false);
-      if (type == kUseCell &&
+      if (info()->has_global_object() &&
           !info()->global_object()->IsAccessCheckNeeded()) {
         Handle<GlobalObject> global(info()->global_object());
-        known_global_function = expr->ComputeGlobalTarget(global, &lookup);
+        known_global_function = expr->ComputeGlobalTarget(global, var->name());
       }
       if (known_global_function) {
         // Push the global object instead of the global receiver because
@@ -4553,8 +4534,7 @@
     }
 
   } else if (op == Token::TYPEOF) {
-    VisitForTypeOf(expr->expression());
-    if (HasStackOverflow()) return;
+    VISIT_FOR_VALUE(expr->expression());
     HValue* value = Pop();
     ast_context()->ReturnInstruction(new HTypeof(value), expr->id());
 
@@ -4957,8 +4937,7 @@
   if ((expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT) &&
       left_unary != NULL && left_unary->op() == Token::TYPEOF &&
       right_literal != NULL && right_literal->handle()->IsString()) {
-    VisitForTypeOf(left_unary->expression());
-    if (HasStackOverflow()) return;
+    VISIT_FOR_VALUE(left_unary->expression());
     HValue* left = Pop();
     HInstruction* instr = new HTypeofIs(left,
         Handle<String>::cast(right_literal->handle()));
diff --git a/src/hydrogen.h b/src/hydrogen.h
index 53e908c..235b669 100644
--- a/src/hydrogen.h
+++ b/src/hydrogen.h
@@ -445,9 +445,6 @@
   // the instruction as value.
   virtual void ReturnInstruction(HInstruction* instr, int ast_id) = 0;
 
-  void set_for_typeof(bool for_typeof) { for_typeof_ = for_typeof; }
-  bool is_for_typeof() { return for_typeof_; }
-
  protected:
   AstContext(HGraphBuilder* owner, Expression::Context kind);
   virtual ~AstContext();
@@ -464,7 +461,6 @@
   HGraphBuilder* owner_;
   Expression::Context kind_;
   AstContext* outer_;
-  bool for_typeof_;
 };
 
 
@@ -731,7 +727,6 @@
   void Bind(Variable* var, HValue* value) { environment()->Bind(var, value); }
 
   void VisitForValue(Expression* expr);
-  void VisitForTypeOf(Expression* expr);
   void VisitForEffect(Expression* expr);
   void VisitForControl(Expression* expr,
                        HBasicBlock* true_block,
@@ -767,13 +762,9 @@
   HBasicBlock* CreateLoopHeaderBlock();
 
   // Helpers for flow graph construction.
-  enum GlobalPropertyAccess {
-    kUseCell,
-    kUseGeneric
-  };
-  GlobalPropertyAccess LookupGlobalProperty(Variable* var,
-                                            LookupResult* lookup,
-                                            bool is_store);
+  void LookupGlobalPropertyCell(Variable* var,
+                                LookupResult* lookup,
+                                bool is_store);
 
   bool TryArgumentsAccess(Property* expr);
   bool TryCallApply(Call* expr);
diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc
index c8f5fdf..cf593db 100644
--- a/src/ia32/full-codegen-ia32.cc
+++ b/src/ia32/full-codegen-ia32.cc
@@ -1543,26 +1543,27 @@
     }
   }
 
-  // For compound assignments we need another deoptimization point after the
-  // variable/property load.
   if (expr->is_compound()) {
     { AccumulatorValueContext context(this);
       switch (assign_type) {
         case VARIABLE:
           EmitVariableLoad(expr->target()->AsVariableProxy()->var());
-          PrepareForBailout(expr->target(), TOS_REG);
           break;
         case NAMED_PROPERTY:
           EmitNamedPropertyLoad(property);
-          PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG);
           break;
         case KEYED_PROPERTY:
           EmitKeyedPropertyLoad(property);
-          PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG);
           break;
       }
     }
 
+    // For property compound assignments we need another deoptimization
+    // point after the property load.
+    if (property != NULL) {
+      PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG);
+    }
+
     Token::Value op = expr->binary_op();
     __ push(eax);  // Left operand goes on the stack.
     VisitForAccumulatorValue(expr->value());
@@ -3747,11 +3748,7 @@
 
   // We need a second deoptimization point after loading the value
   // in case evaluating the property load my have a side effect.
-  if (assign_type == VARIABLE) {
-    PrepareForBailout(expr->expression(), TOS_REG);
-  } else {
-    PrepareForBailout(expr->increment(), TOS_REG);
-  }
+  PrepareForBailout(expr->increment(), TOS_REG);
 
   // Call ToNumber only if operand is not a smi.
   NearLabel no_conversion;
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
index 78784b2..09637af 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -2063,7 +2063,7 @@
 }
 
 
-void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) {
+void LCodeGen::DoLoadGlobal(LLoadGlobal* instr) {
   Register result = ToRegister(instr->result());
   __ mov(result, Operand::Cell(instr->hydrogen()->cell()));
   if (instr->hydrogen()->check_hole_value()) {
@@ -2073,19 +2073,6 @@
 }
 
 
-void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
-  ASSERT(ToRegister(instr->context()).is(esi));
-  ASSERT(ToRegister(instr->global_object()).is(eax));
-  ASSERT(ToRegister(instr->result()).is(eax));
-
-  __ mov(ecx, instr->name());
-  RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET :
-                                               RelocInfo::CODE_TARGET_CONTEXT;
-  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
-  CallCode(ic, mode, instr);
-}
-
-
 void LCodeGen::DoStoreGlobal(LStoreGlobal* instr) {
   Register value = ToRegister(instr->InputAt(0));
   Operand cell_operand = Operand::Cell(instr->hydrogen()->cell());
diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc
index 5b83e1e..3408451 100644
--- a/src/ia32/lithium-ia32.cc
+++ b/src/ia32/lithium-ia32.cc
@@ -1745,22 +1745,14 @@
 }
 
 
-LInstruction* LChunkBuilder::DoLoadGlobalCell(HLoadGlobalCell* instr) {
-  LLoadGlobalCell* result = new LLoadGlobalCell;
+LInstruction* LChunkBuilder::DoLoadGlobal(HLoadGlobal* instr) {
+  LLoadGlobal* result = new LLoadGlobal;
   return instr->check_hole_value()
       ? AssignEnvironment(DefineAsRegister(result))
       : DefineAsRegister(result);
 }
 
 
-LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
-  LOperand* context = UseFixed(instr->context(), esi);
-  LOperand* global_object = UseFixed(instr->global_object(), eax);
-  LLoadGlobalGeneric* result = new LLoadGlobalGeneric(context, global_object);
-  return MarkAsCall(DefineFixed(result, eax), instr);
-}
-
-
 LInstruction* LChunkBuilder::DoStoreGlobal(HStoreGlobal* instr) {
   LStoreGlobal* result = new LStoreGlobal(UseRegisterAtStart(instr->value()));
   return instr->check_hole_value() ? AssignEnvironment(result) : result;
diff --git a/src/ia32/lithium-ia32.h b/src/ia32/lithium-ia32.h
index c281d64..3d09267 100644
--- a/src/ia32/lithium-ia32.h
+++ b/src/ia32/lithium-ia32.h
@@ -121,8 +121,7 @@
   V(LoadElements)                               \
   V(LoadExternalArrayPointer)                   \
   V(LoadFunctionPrototype)                      \
-  V(LoadGlobalCell)                             \
-  V(LoadGlobalGeneric)                          \
+  V(LoadGlobal)                                 \
   V(LoadKeyedFastElement)                       \
   V(LoadKeyedGeneric)                           \
   V(LoadNamedField)                             \
@@ -1272,27 +1271,10 @@
 };
 
 
-class LLoadGlobalCell: public LTemplateInstruction<1, 0, 0> {
+class LLoadGlobal: public LTemplateInstruction<1, 0, 0> {
  public:
-  DECLARE_CONCRETE_INSTRUCTION(LoadGlobalCell, "load-global-cell")
-  DECLARE_HYDROGEN_ACCESSOR(LoadGlobalCell)
-};
-
-
-class LLoadGlobalGeneric: public LTemplateInstruction<1, 2, 0> {
- public:
-  LLoadGlobalGeneric(LOperand* context, LOperand* global_object) {
-    inputs_[0] = context;
-    inputs_[1] = global_object;
-  }
-
-  DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric, "load-global-generic")
-  DECLARE_HYDROGEN_ACCESSOR(LoadGlobalGeneric)
-
-  LOperand* context() { return inputs_[0]; }
-  LOperand* global_object() { return inputs_[1]; }
-  Handle<Object> name() const { return hydrogen()->name(); }
-  bool for_typeof() const { return hydrogen()->for_typeof(); }
+  DECLARE_CONCRETE_INSTRUCTION(LoadGlobal, "load-global")
+  DECLARE_HYDROGEN_ACCESSOR(LoadGlobal)
 };
 
 
diff --git a/src/version.cc b/src/version.cc
index 1529f64..f8ab45c 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -35,7 +35,7 @@
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     2
 #define BUILD_NUMBER      3
-#define PATCH_LEVEL       0
+#define PATCH_LEVEL       1
 #define CANDIDATE_VERSION false
 
 // Define SONAME to have the SCons build the put a specific SONAME into the
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc
index 6625afc..4cea0cc 100644
--- a/src/x64/full-codegen-x64.cc
+++ b/src/x64/full-codegen-x64.cc
@@ -1558,26 +1558,27 @@
     }
   }
 
-  // For compound assignments we need another deoptimization point after the
-  // variable/property load.
   if (expr->is_compound()) {
     { AccumulatorValueContext context(this);
       switch (assign_type) {
         case VARIABLE:
           EmitVariableLoad(expr->target()->AsVariableProxy()->var());
-          PrepareForBailout(expr->target(), TOS_REG);
           break;
         case NAMED_PROPERTY:
           EmitNamedPropertyLoad(property);
-          PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG);
           break;
         case KEYED_PROPERTY:
           EmitKeyedPropertyLoad(property);
-          PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG);
           break;
       }
     }
 
+    // For property compound assignments we need another deoptimization
+    // point after the property load.
+    if (property != NULL) {
+      PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG);
+    }
+
     Token::Value op = expr->binary_op();
     __ push(rax);  // Left operand goes on the stack.
     VisitForAccumulatorValue(expr->value());
@@ -3449,11 +3450,7 @@
 
   // We need a second deoptimization point after loading the value
   // in case evaluating the property load my have a side effect.
-  if (assign_type == VARIABLE) {
-    PrepareForBailout(expr->expression(), TOS_REG);
-  } else {
-    PrepareForBailout(expr->increment(), TOS_REG);
-  }
+  PrepareForBailout(expr->increment(), TOS_REG);
 
   // Call ToNumber only if operand is not a smi.
   NearLabel no_conversion;
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
index 9cd0c1c..8809f88 100644
--- a/src/x64/lithium-codegen-x64.cc
+++ b/src/x64/lithium-codegen-x64.cc
@@ -1984,7 +1984,7 @@
 }
 
 
-void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) {
+void LCodeGen::DoLoadGlobal(LLoadGlobal* instr) {
   Register result = ToRegister(instr->result());
   if (result.is(rax)) {
     __ load_rax(instr->hydrogen()->cell().location(),
@@ -2000,18 +2000,6 @@
 }
 
 
-void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
-  ASSERT(ToRegister(instr->global_object()).is(rax));
-  ASSERT(ToRegister(instr->result()).is(rax));
-
-  __ Move(rcx, instr->name());
-  RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET :
-                                               RelocInfo::CODE_TARGET_CONTEXT;
-  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
-  CallCode(ic, mode, instr);
-}
-
-
 void LCodeGen::DoStoreGlobal(LStoreGlobal* instr) {
   Register value = ToRegister(instr->InputAt(0));
   Register temp = ToRegister(instr->TempAt(0));
diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc
index 624d4b5..4882d79 100644
--- a/src/x64/lithium-x64.cc
+++ b/src/x64/lithium-x64.cc
@@ -1716,21 +1716,14 @@
 }
 
 
-LInstruction* LChunkBuilder::DoLoadGlobalCell(HLoadGlobalCell* instr) {
-  LLoadGlobalCell* result = new LLoadGlobalCell;
+LInstruction* LChunkBuilder::DoLoadGlobal(HLoadGlobal* instr) {
+  LLoadGlobal* result = new LLoadGlobal;
   return instr->check_hole_value()
       ? AssignEnvironment(DefineAsRegister(result))
       : DefineAsRegister(result);
 }
 
 
-LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
-  LOperand* global_object = UseFixed(instr->global_object(), rax);
-  LLoadGlobalGeneric* result = new LLoadGlobalGeneric(global_object);
-  return MarkAsCall(DefineFixed(result, rax), instr);
-}
-
-
 LInstruction* LChunkBuilder::DoStoreGlobal(HStoreGlobal* instr) {
   LStoreGlobal* result = new LStoreGlobal(UseRegister(instr->value()),
                                           TempRegister());
diff --git a/src/x64/lithium-x64.h b/src/x64/lithium-x64.h
index e1a9f4e..b43b9ae 100644
--- a/src/x64/lithium-x64.h
+++ b/src/x64/lithium-x64.h
@@ -118,8 +118,7 @@
   V(LoadContextSlot)                            \
   V(LoadElements)                               \
   V(LoadExternalArrayPointer)                   \
-  V(LoadGlobalCell)                             \
-  V(LoadGlobalGeneric)                          \
+  V(LoadGlobal)                                 \
   V(LoadKeyedFastElement)                       \
   V(LoadKeyedGeneric)                           \
   V(LoadNamedField)                             \
@@ -1227,25 +1226,10 @@
 };
 
 
-class LLoadGlobalCell: public LTemplateInstruction<1, 0, 0> {
+class LLoadGlobal: public LTemplateInstruction<1, 0, 0> {
  public:
-  DECLARE_CONCRETE_INSTRUCTION(LoadGlobalCell, "load-global-cell")
-  DECLARE_HYDROGEN_ACCESSOR(LoadGlobalCell)
-};
-
-
-class LLoadGlobalGeneric: public LTemplateInstruction<1, 1, 0> {
- public:
-  explicit LLoadGlobalGeneric(LOperand* global_object) {
-    inputs_[0] = global_object;
-  }
-
-  DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric, "load-global-generic")
-  DECLARE_HYDROGEN_ACCESSOR(LoadGlobalGeneric)
-
-  LOperand* global_object() { return inputs_[0]; }
-  Handle<Object> name() const { return hydrogen()->name(); }
-  bool for_typeof() const { return hydrogen()->for_typeof(); }
+  DECLARE_CONCRETE_INSTRUCTION(LoadGlobal, "load-global")
+  DECLARE_HYDROGEN_ACCESSOR(LoadGlobal)
 };
 
 
diff --git a/test/mjsunit/compiler/global-accessors.js b/test/mjsunit/compiler/global-accessors.js
index bd031a8..e69de29 100644
--- a/test/mjsunit/compiler/global-accessors.js
+++ b/test/mjsunit/compiler/global-accessors.js
@@ -1,47 +0,0 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-//       notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-//       copyright notice, this list of conditions and the following
-//       disclaimer in the documentation and/or other materials provided
-//       with the distribution.
-//     * Neither the name of Google Inc. nor the names of its
-//       contributors may be used to endorse or promote products derived
-//       from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// This test tests that no bailouts are missing by not hitting asserts in debug
-// mode. 
-
-test_count_operation()
-test_compound_assignment()
-
-function f() {}
-function test_count_operation()
-{
-  this.__defineSetter__('x', f);
-  this.__defineGetter__('x', f);
-  x = x++;
-}
-
-function test_compound_assignment()
-{
-  this.__defineSetter__('y', f);
-  this.__defineGetter__('y', f);
-  y += y;
-}