Revision: 15827
Author:   [email protected]
Date:     Tue Jul 23 06:35:10 2013
Log:      Unify SoftDeoptimize and Deoptimize hydrogen instructions

BUG=chromium:258519
[email protected]

Review URL: https://codereview.chromium.org/19528003
http://code.google.com/p/v8/source/detail?r=15827

Modified:
 /branches/bleeding_edge/src/arm/lithium-arm.cc
 /branches/bleeding_edge/src/arm/lithium-arm.h
 /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc
 /branches/bleeding_edge/src/arm/lithium-codegen-arm.h
 /branches/bleeding_edge/src/code-stubs-hydrogen.cc
 /branches/bleeding_edge/src/hydrogen-deoptimizing-mark.cc
 /branches/bleeding_edge/src/hydrogen-environment-liveness.cc
 /branches/bleeding_edge/src/hydrogen-gvn.cc
 /branches/bleeding_edge/src/hydrogen-instructions.cc
 /branches/bleeding_edge/src/hydrogen-instructions.h
 /branches/bleeding_edge/src/hydrogen-osr.cc
 /branches/bleeding_edge/src/hydrogen.cc
 /branches/bleeding_edge/src/hydrogen.h
 /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc
 /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.h
 /branches/bleeding_edge/src/ia32/lithium-ia32.cc
 /branches/bleeding_edge/src/ia32/lithium-ia32.h
 /branches/bleeding_edge/src/mips/lithium-codegen-mips.cc
 /branches/bleeding_edge/src/mips/lithium-codegen-mips.h
 /branches/bleeding_edge/src/mips/lithium-mips.cc
 /branches/bleeding_edge/src/mips/lithium-mips.h
 /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc
 /branches/bleeding_edge/src/x64/lithium-codegen-x64.h
 /branches/bleeding_edge/src/x64/lithium-x64.cc
 /branches/bleeding_edge/src/x64/lithium-x64.h

=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.cc      Tue Jul 23 02:18:42 2013
+++ /branches/bleeding_edge/src/arm/lithium-arm.cc      Tue Jul 23 06:35:10 2013
@@ -699,11 +699,6 @@
   UNREACHABLE();
   return NULL;
 }
-
-
-LInstruction* LChunkBuilder::DoSoftDeoptimize(HSoftDeoptimize* instr) {
-  return AssignEnvironment(new(zone()) LDeoptimize);
-}


 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.h       Tue Jul 23 00:31:46 2013
+++ /branches/bleeding_edge/src/arm/lithium-arm.h       Tue Jul 23 06:35:10 2013
@@ -427,6 +427,7 @@
 class LDeoptimize: public LTemplateInstruction<0, 0, 0> {
  public:
   DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
+  DECLARE_HYDROGEN_ACCESSOR(Deoptimize)
 };


=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Tue Jul 23 02:18:42 2013 +++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Tue Jul 23 06:35:10 2013
@@ -808,12 +808,6 @@
       : Deoptimizer::EAGER;
   DeoptimizeIf(cc, environment, bailout_type);
 }
-
-
-void LCodeGen::SoftDeoptimize(LEnvironment* environment) {
-  ASSERT(!info()->IsStub());
-  DeoptimizeIf(al, environment, Deoptimizer::SOFT);
-}


 void LCodeGen::RegisterDependentCodeForEmbeddedMaps(Handle<Code> code) {
@@ -5646,11 +5640,15 @@


 void LCodeGen::DoDeoptimize(LDeoptimize* instr) {
-  if (instr->hydrogen_value()->IsSoftDeoptimize()) {
-    SoftDeoptimize(instr->environment());
-  } else {
-    DeoptimizeIf(al, instr->environment());
+  Deoptimizer::BailoutType type = instr->hydrogen()->type();
+ // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the + // needed return address), even though the implementation of LAZY and EAGER is + // now identical. When LAZY is eventually completely folded into EAGER, remove
+  // the special case below.
+  if (info()->IsStub() && type == Deoptimizer::EAGER) {
+    type = Deoptimizer::LAZY;
   }
+  DeoptimizeIf(al, instr->environment(), type);
 }


=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.h Mon Jul 15 08:12:16 2013 +++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.h Tue Jul 23 06:35:10 2013
@@ -284,7 +284,6 @@
                     LEnvironment* environment,
                     Deoptimizer::BailoutType bailout_type);
   void DeoptimizeIf(Condition cc, LEnvironment* environment);
-  void SoftDeoptimize(LEnvironment* environment);

   void AddToTranslation(Translation* translation,
                         LOperand* op,
=======================================
--- /branches/bleeding_edge/src/code-stubs-hydrogen.cc Tue Jul 23 02:18:42 2013 +++ /branches/bleeding_edge/src/code-stubs-hydrogen.cc Tue Jul 23 06:35:10 2013
@@ -178,7 +178,7 @@
   AddInstruction(context_);
   start_environment->BindContext(context_);

-  AddSimulate(BailoutId::StubEntry());
+  Add<HSimulate>(BailoutId::StubEntry());

   NoObservableSideEffectsScope no_effects(this);

@@ -397,9 +397,10 @@
                                                length));
   }

-  HValue* result = environment()->Pop();
   checker.ElseDeopt();
-  return result;
+  checker.End();
+
+  return environment()->Pop();
 }


@@ -447,8 +448,11 @@
     AddStore(object, access, AddLoad(boilerplate, access));
   }

+  environment()->Push(object);
   checker.ElseDeopt();
-  return object;
+  checker.End();
+
+  return environment()->Pop();
 }


@@ -929,8 +933,7 @@

   if (FLAG_trace_elements_transitions) {
     // Tracing elements transitions is the job of the runtime.
-    current_block()->FinishExitWithDeoptimization(HDeoptimize::kUseAll);
-    set_current_block(NULL);
+    Add<HDeoptimize>(Deoptimizer::EAGER);
   } else {
     info()->MarkAsSavesCallerDoubles();

=======================================
--- /branches/bleeding_edge/src/hydrogen-deoptimizing-mark.cc Mon Jul 15 02:53:00 2013 +++ /branches/bleeding_edge/src/hydrogen-deoptimizing-mark.cc Tue Jul 23 06:35:10 2013
@@ -107,7 +107,7 @@
         instr->DeleteAndReplaceWith(last_dummy);
         continue;
       }
-      if (instr->IsSoftDeoptimize()) {
+      if (instr->IsDeoptimize()) {
         ASSERT(block->IsDeoptimizing());
         nullify = true;
       }
=======================================
--- /branches/bleeding_edge/src/hydrogen-environment-liveness.cc Thu Jun 27 06:15:10 2013 +++ /branches/bleeding_edge/src/hydrogen-environment-liveness.cc Tue Jul 23 06:35:10 2013
@@ -172,15 +172,6 @@
       last_simulate_ = NULL;
       break;
     }
-    case HValue::kDeoptimize: {
-      // Keep all environment slots alive.
-      HDeoptimize* deopt = HDeoptimize::cast(instr);
-      for (int i = deopt->first_local_index();
-           i < deopt->first_expression_index(); ++i) {
-        live->Add(i);
-      }
-      break;
-    }
     case HValue::kSimulate:
       last_simulate_ = HSimulate::cast(instr);
       went_live_since_last_simulate_.Clear();
=======================================
--- /branches/bleeding_edge/src/hydrogen-gvn.cc Tue Jul 16 01:37:49 2013
+++ /branches/bleeding_edge/src/hydrogen-gvn.cc Tue Jul 23 06:35:10 2013
@@ -401,7 +401,7 @@
     for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
       HInstruction* instr = it.Current();
       side_effects.Add(instr->ChangesFlags());
-      if (instr->IsSoftDeoptimize()) {
+      if (instr->IsDeoptimize()) {
         block_side_effects_[id].RemoveAll();
         side_effects.RemoveAll();
         break;
=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.cc Tue Jul 23 03:01:06 2013 +++ /branches/bleeding_edge/src/hydrogen-instructions.cc Tue Jul 23 06:35:10 2013
@@ -2134,16 +2134,6 @@
     }
   }
 }
-
-
-void HDeoptimize::PrintDataTo(StringStream* stream) {
-  if (OperandCount() == 0) return;
-  OperandAt(0)->PrintNameTo(stream);
-  for (int i = 1; i < OperandCount(); ++i) {
-    stream->Add(" ");
-    OperandAt(i)->PrintNameTo(stream);
-  }
-}


 void HEnterInlined::RegisterReturnTarget(HBasicBlock* return_target,
=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.h Tue Jul 23 03:01:06 2013 +++ /branches/bleeding_edge/src/hydrogen-instructions.h Tue Jul 23 06:35:10 2013
@@ -33,6 +33,7 @@
 #include "allocation.h"
 #include "code-stubs.h"
 #include "data-flow.h"
+#include "deoptimizer.h"
 #include "small-pointer-list.h"
 #include "string-stream.h"
 #include "v8conversions.h"
@@ -167,7 +168,6 @@
   V(Shl)                                       \
   V(Shr)                                       \
   V(Simulate)                                  \
-  V(SoftDeoptimize)                            \
   V(StackCheck)                                \
   V(StoreContextSlot)                          \
   V(StoreGlobalCell)                           \
@@ -1499,16 +1499,20 @@
 };


-// We insert soft-deoptimize when we hit code with unknown typefeedback,
-// so that we get a chance of re-optimizing with useful typefeedback.
-// HSoftDeoptimize does not end a basic block as opposed to HDeoptimize.
-class HSoftDeoptimize: public HTemplateInstruction<0> {
+class HDeoptimize: public HTemplateInstruction<0> {
  public:
+  explicit HDeoptimize(Deoptimizer::BailoutType type) : type_(type) {}
+
   virtual Representation RequiredInputRepresentation(int index) {
     return Representation::None();
   }

-  DECLARE_CONCRETE_INSTRUCTION(SoftDeoptimize)
+  Deoptimizer::BailoutType type() { return type_; }
+
+  DECLARE_CONCRETE_INSTRUCTION(Deoptimize)
+
+ private:
+  Deoptimizer::BailoutType type_;
 };


@@ -1523,59 +1527,6 @@
 };


-class HDeoptimize: public HControlInstruction {
- public:
-  HDeoptimize(int environment_length,
-              int first_local_index,
-              int first_expression_index,
-              Zone* zone)
-      : values_(environment_length, zone),
-        first_local_index_(first_local_index),
-        first_expression_index_(first_expression_index) { }
-
-  virtual Representation RequiredInputRepresentation(int index) {
-    return Representation::None();
-  }
-
-  virtual int OperandCount() { return values_.length(); }
-  virtual HValue* OperandAt(int index) const { return values_[index]; }
-  virtual void PrintDataTo(StringStream* stream);
-
-  virtual int SuccessorCount() { return 0; }
-  virtual HBasicBlock* SuccessorAt(int i) {
-    UNREACHABLE();
-    return NULL;
-  }
-  virtual void SetSuccessorAt(int i, HBasicBlock* block) {
-    UNREACHABLE();
-  }
-
-  void AddEnvironmentValue(HValue* value, Zone* zone) {
-    values_.Add(NULL, zone);
-    SetOperandAt(values_.length() - 1, value);
-  }
-  int first_local_index() { return first_local_index_; }
-  int first_expression_index() { return first_expression_index_; }
-
-  DECLARE_CONCRETE_INSTRUCTION(Deoptimize)
-
-  enum UseEnvironment {
-    kNoUses,
-    kUseAll
-  };
-
- protected:
-  virtual void InternalSetOperandAt(int index, HValue* value) {
-    values_[index] = value;
-  }
-
- private:
-  ZoneList<HValue*> values_;
-  int first_local_index_;
-  int first_expression_index_;
-};
-
-
 class HGoto: public HTemplateControlInstruction<1, 0> {
  public:
   explicit HGoto(HBasicBlock* target) {
=======================================
--- /branches/bleeding_edge/src/hydrogen-osr.cc Fri Jul  5 03:40:14 2013
+++ /branches/bleeding_edge/src/hydrogen-osr.cc Tue Jul 23 06:35:10 2013
@@ -94,7 +94,7 @@
     }
   }

-  builder_->AddSimulate(osr_entry_id);
+  builder_->Add<HSimulate>(osr_entry_id);
   builder_->Add<HOsrEntry>(osr_entry_id);
   HContext* context = builder_->Add<HContext>();
   environment->BindContext(context);
=======================================
--- /branches/bleeding_edge/src/hydrogen.cc     Tue Jul 23 03:01:06 2013
+++ /branches/bleeding_edge/src/hydrogen.cc     Tue Jul 23 06:35:10 2013
@@ -144,26 +144,6 @@
   }
   instr->InsertAfter(last_);
 }
-
-
-HDeoptimize* HBasicBlock::CreateDeoptimize(
-    HDeoptimize::UseEnvironment has_uses) {
-  ASSERT(HasEnvironment());
-  if (has_uses == HDeoptimize::kNoUses)
-    return new(zone()) HDeoptimize(0, 0, 0, zone());
-
-  HEnvironment* environment = last_environment();
-  int first_local_index = environment->first_local_index();
-  int first_expression_index = environment->first_expression_index();
-  HDeoptimize* instr = new(zone()) HDeoptimize(
- environment->length(), first_local_index, first_expression_index, zone());
-  for (int i = 0; i < environment->length(); i++) {
-    HValue* val = environment->values()->at(i);
-    instr->AddEnvironmentValue(val, zone());
-  }
-
-  return instr;
-}


 HSimulate* HBasicBlock::CreateSimulate(BailoutId ast_id,
@@ -700,13 +680,16 @@
     : builder_(builder),
       position_(position),
       finished_(false),
+      deopt_then_(false),
+      deopt_else_(false),
       did_then_(false),
       did_else_(false),
       did_and_(false),
       did_or_(false),
       captured_(false),
       needs_compare_(true),
-      split_edge_merge_block_(NULL) {
+      split_edge_merge_block_(NULL),
+      merge_block_(NULL) {
   HEnvironment* env = builder->environment();
   first_true_block_ = builder->CreateBasicBlock(env->Copy());
   last_true_block_ = NULL;
@@ -720,6 +703,8 @@
     : builder_(builder),
       position_(RelocInfo::kNoPosition),
       finished_(false),
+      deopt_then_(false),
+      deopt_else_(false),
       did_then_(false),
       did_else_(false),
       did_and_(false),
@@ -836,14 +821,13 @@


 void HGraphBuilder::IfBuilder::Deopt() {
-  HBasicBlock* block = builder_->current_block();
-  block->FinishExitWithDeoptimization(HDeoptimize::kUseAll);
-  builder_->set_current_block(NULL);
+  ASSERT(did_then_);
   if (did_else_) {
-    first_false_block_ = NULL;
+    deopt_else_ = true;
   } else {
-    first_true_block_ = NULL;
+    deopt_then_ = true;
   }
+  builder_->Add<HDeoptimize>(Deoptimizer::EAGER);
 }


@@ -868,20 +852,30 @@
       last_true_block_ = builder_->current_block();
     }
     if (first_true_block_ == NULL) {
-      // Deopt on true. Nothing to do, just continue the false block.
+      // Return on true. Nothing to do, just continue the false block.
     } else if (first_false_block_ == NULL) {
       // Deopt on false. Nothing to do except switching to the true block.
       builder_->set_current_block(last_true_block_);
     } else {
- HEnvironment* merge_env = last_true_block_->last_environment()->Copy();
-      merge_block_ = builder_->CreateBasicBlock(merge_env);
+      merge_block_ = builder_->graph()->CreateBasicBlock();
       ASSERT(!finished_);
       if (!did_else_) Else();
       ASSERT(!last_true_block_->IsFinished());
       HBasicBlock* last_false_block = builder_->current_block();
       ASSERT(!last_false_block->IsFinished());
-      last_true_block_->GotoNoSimulate(merge_block_);
-      last_false_block->GotoNoSimulate(merge_block_);
+      if (deopt_then_) {
+        last_false_block->GotoNoSimulate(merge_block_);
+        builder_->PadEnvironmentForContinuation(last_true_block_,
+                                                merge_block_);
+        last_true_block_->GotoNoSimulate(merge_block_);
+      } else {
+        last_true_block_->GotoNoSimulate(merge_block_);
+        if (deopt_else_) {
+          builder_->PadEnvironmentForContinuation(last_false_block,
+                                                  merge_block_);
+        }
+        last_false_block->GotoNoSimulate(merge_block_);
+      }
       builder_->set_current_block(merge_block_);
     }
   }
@@ -989,36 +983,6 @@
   }
   return instr;
 }
-
-
-void HGraphBuilder::AddSimulate(BailoutId id,
-                                RemovableSimulate removable) {
-  ASSERT(current_block() != NULL);
-  ASSERT(no_side_effects_scope_count_ == 0);
-  current_block()->AddSimulate(id, removable);
-}
-
-
-HReturn* HGraphBuilder::AddReturn(HValue* value) {
-  HValue* context = environment()->LookupContext();
-  int num_parameters = graph()->info()->num_parameters();
-  HValue* params = Add<HConstant>(num_parameters);
-  HReturn* return_instruction = new(graph()->zone())
-      HReturn(value, context, params);
-  current_block()->FinishExit(return_instruction);
-  return return_instruction;
-}
-
-
-void HGraphBuilder::AddSoftDeoptimize(SoftDeoptimizeMode mode) {
-  isolate()->counters()->soft_deopts_requested()->Increment();
-  if (FLAG_always_opt && mode == CAN_OMIT_SOFT_DEOPT) return;
-  if (current_block()->IsDeoptimizing()) return;
-  Add<HSoftDeoptimize>();
-  isolate()->counters()->soft_deopts_inserted()->Increment();
-  current_block()->MarkAsDeoptimizing();
-  graph()->set_has_soft_deoptimize(true);
-}


 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) {
@@ -1041,10 +1005,43 @@
   if (obj->type().IsHeapObject()) return obj;
   return Add<HCheckHeapObject>(obj);
 }
+
+
+void HGraphBuilder::FinishExitWithHardDeoptimization(
+    HBasicBlock* continuation) {
+  PadEnvironmentForContinuation(current_block(), continuation);
+  Add<HDeoptimize>(Deoptimizer::EAGER);
+  if (no_side_effects_scope_count_ > 0) {
+    current_block()->GotoNoSimulate(continuation);
+  } else {
+    current_block()->Goto(continuation);
+  }
+}
+
+
+void HGraphBuilder::PadEnvironmentForContinuation(
+    HBasicBlock* from,
+    HBasicBlock* continuation) {
+  if (continuation->last_environment() != NULL) {
+ // When merging from a deopt block to a continuation, resolve differences in + // environment by pushing undefined and popping extra values so that the
+    // environments match during the join.
+ int continuation_env_length = continuation->last_environment()->length();
+    while (continuation_env_length != from->last_environment()->length()) {
+      if (continuation_env_length > from->last_environment()->length()) {
+        from->last_environment()->Push(graph()->GetConstantUndefined());
+      } else {
+        from->last_environment()->Pop();
+      }
+    }
+  } else {
+    ASSERT(continuation->predecessors()->length() == 0);
+  }
+}


 HValue* HGraphBuilder::BuildCheckMap(HValue* obj,
-                                              Handle<Map> map) {
+                                     Handle<Map> map) {
   HCheckMaps* check = HCheckMaps::New(obj, map, zone(), top_info());
   AddInstruction(check);
   return check;
@@ -1720,7 +1717,7 @@
                       input, graph()->GetConstantMinus1());
         Representation rep = Representation::FromType(type);
         if (type->Is(Type::None())) {
-          AddSoftDeoptimize();
+          Add<HDeoptimize>(Deoptimizer::SOFT);
         }
         if (instr->IsBinaryOperation()) {
           HBinaryOperation* binop = HBinaryOperation::cast(instr);
@@ -1731,7 +1728,7 @@
       }
     case Token::BIT_NOT:
       if (type->Is(Type::None())) {
-        AddSoftDeoptimize();
+        Add<HDeoptimize>(Deoptimizer::SOFT);
       }
       return new(zone()) HBitNot(input);
   }
@@ -2639,7 +2636,7 @@
   ASSERT(!instr->IsControlInstruction());
   owner()->AddInstruction(instr);
   if (instr->HasObservableSideEffects()) {
-    owner()->AddSimulate(ast_id, REMOVABLE_SIMULATE);
+    owner()->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   }
 }

@@ -2681,7 +2678,7 @@
   owner()->AddInstruction(instr);
   owner()->Push(instr);
   if (instr->HasObservableSideEffects()) {
-    owner()->AddSimulate(ast_id, REMOVABLE_SIMULATE);
+    owner()->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   }
 }

@@ -2737,7 +2734,7 @@
// this one isn't actually needed (and wouldn't work if it were targeted).
   if (instr->HasObservableSideEffects()) {
     builder->Push(instr);
-    builder->AddSimulate(ast_id, REMOVABLE_SIMULATE);
+    builder->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
     builder->Pop();
   }
   BuildBranch(instr);
@@ -2925,7 +2922,7 @@
     VisitVariableDeclaration(scope->function());
   }
   VisitDeclarations(scope->declarations());
-  AddSimulate(BailoutId::Declarations());
+  Add<HSimulate>(BailoutId::Declarations());

   HValue* context = environment()->LookupContext();
   Add<HStackCheck>(context, HStackCheck::kFunctionEntry);
@@ -2934,7 +2931,7 @@
   if (HasStackOverflow()) return false;

   if (current_block() != NULL) {
-    AddReturn(graph()->GetConstantUndefined());
+    Add<HReturn>(graph()->GetConstantUndefined());
     set_current_block(NULL);
   }

@@ -3224,10 +3221,10 @@
   ASSERT(current_block() != NULL);
   ASSERT(current_block()->HasPredecessor());
   if (stmt->condition()->ToBooleanIsTrue()) {
-    AddSimulate(stmt->ThenId());
+    Add<HSimulate>(stmt->ThenId());
     Visit(stmt->then_statement());
   } else if (stmt->condition()->ToBooleanIsFalse()) {
-    AddSimulate(stmt->ElseId());
+    Add<HSimulate>(stmt->ElseId());
     Visit(stmt->else_statement());
   } else {
     HBasicBlock* cond_true = graph()->CreateBasicBlock();
@@ -3334,7 +3331,7 @@
     // Not an inlined return, so an actual one.
     CHECK_ALIVE(VisitForValue(stmt->expression()));
     HValue* result = environment()->Pop();
-    AddReturn(result);
+    Add<HReturn>(result);
   } else if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) {
// Return from an inlined construct call. In a test context the return value // will always evaluate to true, in a value context the return value needs
@@ -3426,7 +3423,7 @@
   HValue* context = environment()->LookupContext();

   CHECK_ALIVE(VisitForValue(stmt->tag()));
-  AddSimulate(stmt->EntryId());
+  Add<HSimulate>(stmt->EntryId());
   HValue* tag_value = Pop();
   HBasicBlock* first_test_block = current_block();

@@ -3466,7 +3463,7 @@

     if (stmt->switch_type() == SwitchStatement::SMI_SWITCH) {
       if (!clause->compare_type()->Is(Type::Smi())) {
-        AddSoftDeoptimize();
+        Add<HDeoptimize>(Deoptimizer::SOFT);
       }

       HCompareNumericAndBranch* compare_ =
@@ -3516,7 +3513,7 @@
           normal_block = last_block;
           last_block = NULL;  // Cleared to indicate we've handled it.
         }
-      } else if (!curr_test_block->end()->IsDeoptimize()) {
+      } else {
         normal_block = curr_test_block->end()->FirstSuccessor();
         curr_test_block = curr_test_block->end()->SecondSuccessor();
       }
@@ -3570,7 +3567,7 @@
                                            HBasicBlock* loop_entry,
BreakAndContinueInfo* break_info) {
   BreakAndContinueScope push(break_info, this);
-  AddSimulate(stmt->StackCheckId());
+  Add<HSimulate>(stmt->StackCheckId());
   HValue* context = environment()->LookupContext();
   HStackCheck* stack_check = Add<HStackCheck>(
       context, HStackCheck::kBackwardsBranch);
@@ -3731,7 +3728,7 @@

   HInstruction* map = Add<HForInPrepareMap>(
       environment()->LookupContext(), enumerable);
-  AddSimulate(stmt->PrepareId());
+  Add<HSimulate>(stmt->PrepareId());

   HInstruction* array = Add<HForInCacheArray>(
       enumerable, map, DescriptorArray::kEnumCacheBridgeCacheIndex);
@@ -4328,7 +4325,7 @@
             }
             AddInstruction(store);
             if (store->HasObservableSideEffects()) {
-              AddSimulate(key->id(), REMOVABLE_SIMULATE);
+              Add<HSimulate>(key->id(), REMOVABLE_SIMULATE);
             }
           } else {
             CHECK_ALIVE(VisitForEffect(value));
@@ -4493,7 +4490,7 @@
         break;
     }

-    AddSimulate(expr->GetIdForElement(i));
+    Add<HSimulate>(expr->GetIdForElement(i));
   }

   Drop(1);  // array literal index
@@ -4824,7 +4821,7 @@
   if (!ast_context()->IsEffect()) Push(result_value);
   store->set_position(position);
   AddInstruction(store);
-  AddSimulate(assignment_id);
+  Add<HSimulate>(assignment_id);
   if (!ast_context()->IsEffect()) Drop(1);
   ast_context()->ReturnValue(result_value);
   return true;
@@ -4883,7 +4880,7 @@
   // know about and do not want to handle ones we've never seen.  Otherwise
   // use a generic IC.
   if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
-    current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses);
+    FinishExitWithHardDeoptimization(join);
   } else {
HInstruction* instr = BuildStoreNamedGeneric(object, name, store_value);
     instr->set_position(position);
@@ -4900,10 +4897,10 @@
       // unoptimized code).
       if (instr->HasObservableSideEffects()) {
         if (ast_context()->IsEffect()) {
-          AddSimulate(assignment_id, REMOVABLE_SIMULATE);
+          Add<HSimulate>(assignment_id, REMOVABLE_SIMULATE);
         } else {
           Push(result_value);
-          AddSimulate(assignment_id, REMOVABLE_SIMULATE);
+          Add<HSimulate>(assignment_id, REMOVABLE_SIMULATE);
           Drop(1);
         }
       }
@@ -4931,7 +4928,7 @@
     HValue* value = environment()->ExpressionStackAt(0);
     HValue* object = environment()->ExpressionStackAt(1);

-    if (expr->IsUninitialized()) AddSoftDeoptimize();
+    if (expr->IsUninitialized()) Add<HDeoptimize>(Deoptimizer::SOFT);
     return BuildStoreNamed(expr, expr->id(), expr->position(),
expr->AssignmentId(), prop, object, value, value);
   } else {
@@ -4948,7 +4945,7 @@
                              &has_side_effects);
     Drop(3);
     Push(value);
-    AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE);
+    Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
     return ast_context()->ReturnValue(Pop());
   }
 }
@@ -4977,14 +4974,14 @@
       }
       builder.Then();
       builder.Else();
-      AddSoftDeoptimize(MUST_EMIT_SOFT_DEOPT);
+      Add<HDeoptimize>(Deoptimizer::EAGER);
       builder.End();
     }
     HInstruction* instr =
         Add<HStoreGlobalCell>(value, cell, lookup.GetPropertyDetails());
     instr->set_position(position);
     if (instr->HasObservableSideEffects()) {
-      AddSimulate(ast_id, REMOVABLE_SIMULATE);
+      Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
     }
   } else {
     HValue* context =  environment()->LookupContext();
@@ -4994,7 +4991,7 @@
                                  value, function_strict_mode_flag());
     instr->set_position(position);
     ASSERT(instr->HasObservableSideEffects());
-    AddSimulate(ast_id, REMOVABLE_SIMULATE);
+    Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   }
 }

@@ -5056,7 +5053,7 @@
   instr->set_position(position);
   AddInstruction(instr);
   if (instr->HasObservableSideEffects()) {
-    AddSimulate(id, REMOVABLE_SIMULATE);
+    Add<HSimulate>(id, REMOVABLE_SIMULATE);
   }
   if (!ast_context()->IsEffect()) Drop(1);
   return ast_context()->ReturnValue(result_value);
@@ -5134,7 +5131,7 @@
HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(),
                                                           mode, Top());
         if (instr->HasObservableSideEffects()) {
-          AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE);
+          Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
         }
         break;
       }
@@ -5175,7 +5172,7 @@
       if (load == NULL) load = BuildLoadNamedGeneric(object, name, prop);
       PushAndAdd(load);
       if (load->HasObservableSideEffects()) {
-        AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE);
+        Add<HSimulate>(prop->LoadId(), REMOVABLE_SIMULATE);
       }

       CHECK_ALIVE(VisitForValue(expr->value()));
@@ -5185,7 +5182,7 @@
       HInstruction* instr = BuildBinaryOperation(operation, left, right);
       PushAndAdd(instr);
       if (instr->HasObservableSideEffects()) {
-        AddSimulate(operation->id(), REMOVABLE_SIMULATE);
+        Add<HSimulate>(operation->id(), REMOVABLE_SIMULATE);
       }

       return BuildStoreNamed(prop, expr->id(), expr->position(),
@@ -5203,7 +5200,7 @@
           false,  // is_store
           &has_side_effects);
       Push(load);
- if (has_side_effects) AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); + if (has_side_effects) Add<HSimulate>(prop->LoadId(), REMOVABLE_SIMULATE);

       CHECK_ALIVE(VisitForValue(expr->value()));
       HValue* right = Pop();
@@ -5212,7 +5209,7 @@
       HInstruction* instr = BuildBinaryOperation(operation, left, right);
       PushAndAdd(instr);
       if (instr->HasObservableSideEffects()) {
-        AddSimulate(operation->id(), REMOVABLE_SIMULATE);
+        Add<HSimulate>(operation->id(), REMOVABLE_SIMULATE);
       }

       HandleKeyedElementAccess(obj, key, instr, expr, expr->AssignmentId(),
@@ -5224,7 +5221,7 @@
       Drop(3);
       Push(instr);
       ASSERT(has_side_effects);  // Stores always have side effects.
-      AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE);
+      Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
       return ast_context()->ReturnValue(Pop());
     }

@@ -5346,7 +5343,7 @@
HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(),
                                                           mode, Top());
         if (instr->HasObservableSideEffects()) {
-          AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE);
+          Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
         }
         return ast_context()->ReturnValue(Pop());
       }
@@ -5380,7 +5377,7 @@
   HValue* value = environment()->Pop();
   HThrow* instr = Add<HThrow>(context, value);
   instr->set_position(expr->position());
-  AddSimulate(expr->id());
+  Add<HSimulate>(expr->id());
   current_block()->FinishExit(new(zone()) HAbnormalExit);
   set_current_block(NULL);
 }
@@ -5412,7 +5409,7 @@
     Handle<String> name,
     Property* expr) {
   if (expr->IsUninitialized()) {
-    AddSoftDeoptimize();
+    Add<HDeoptimize>(Deoptimizer::SOFT);
   }
   HValue* context = environment()->LookupContext();
   return new(zone()) HLoadNamedGeneric(context, object, name);
@@ -5735,7 +5732,8 @@
   }

   // Deopt if none of the cases matched.
-  current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses);
+  NoObservableSideEffectsScope scope(this);
+  FinishExitWithHardDeoptimization(join);
   set_current_block(join);
   return is_store ? NULL : Pop();
 }
@@ -5771,12 +5769,12 @@
   } else {
     if (is_store) {
if (expr->IsAssignment() && expr->AsAssignment()->IsUninitialized()) {
-        AddSoftDeoptimize();
+        Add<HDeoptimize>(Deoptimizer::SOFT);
       }
       instr = BuildStoreKeyedGeneric(obj, key, val);
     } else {
       if (expr->AsProperty()->IsUninitialized()) {
-        AddSoftDeoptimize();
+        Add<HDeoptimize>(Deoptimizer::SOFT);
       }
       instr = BuildLoadKeyedGeneric(obj, key);
     }
@@ -5955,10 +5953,10 @@
         &has_side_effects);
     if (has_side_effects) {
       if (ast_context()->IsEffect()) {
-        AddSimulate(expr->id(), REMOVABLE_SIMULATE);
+        Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
       } else {
         Push(load);
-        AddSimulate(expr->id(), REMOVABLE_SIMULATE);
+        Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
         Drop(1);
       }
     }
@@ -6060,7 +6058,7 @@
     PreProcessCall(call);
     AddInstruction(call);
     if (!ast_context()->IsEffect()) Push(call);
-    AddSimulate(expr->id(), REMOVABLE_SIMULATE);
+    Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
     if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
   }

@@ -6192,7 +6190,7 @@
   // know about and do not want to handle ones we've never seen.  Otherwise
   // use a generic IC.
if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) {
-    current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses);
+    FinishExitWithHardDeoptimization(join);
   } else {
     HValue* context = environment()->LookupContext();
HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count);
@@ -6450,7 +6448,7 @@
   inner_env->BindContext(context);
 #endif

-  AddSimulate(return_id);
+  Add<HSimulate>(return_id);
   current_block()->UpdateEnvironment(inner_env);
   HArgumentsObject* arguments_object = NULL;

@@ -7628,7 +7626,7 @@
HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(),
                                                           mode, after);
         if (instr->HasObservableSideEffects()) {
-          AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE);
+          Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
         }
         break;
       }
@@ -7671,7 +7669,7 @@
       if (load == NULL) load = BuildLoadNamedGeneric(object, name, prop);
       PushAndAdd(load);
       if (load->HasObservableSideEffects()) {
-        AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE);
+        Add<HSimulate>(prop->LoadId(), REMOVABLE_SIMULATE);
       }

       after = BuildIncrement(returns_original_input, expr);
@@ -7694,7 +7692,7 @@
           false,  // is_store
           &has_side_effects);
       Push(load);
- if (has_side_effects) AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); + if (has_side_effects) Add<HSimulate>(prop->LoadId(), REMOVABLE_SIMULATE);

       after = BuildIncrement(returns_original_input, expr);
       input = environment()->ExpressionStackAt(0);
@@ -7711,7 +7709,7 @@
       environment()->SetExpressionStackAt(0, after);
if (returns_original_input) environment()->SetExpressionStackAt(1, input);
       ASSERT(has_side_effects);  // Stores always have side effects.
-      AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE);
+      Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
     }
   }

@@ -7859,12 +7857,12 @@
   }

   if (left_type->Is(Type::None())) {
-    AddSoftDeoptimize();
+    Add<HDeoptimize>(Deoptimizer::SOFT);
// TODO(rossberg): we should be able to get rid of non-continuous defaults.
     left_type = handle(Type::Any(), isolate());
   }
   if (right_type->Is(Type::None())) {
-    AddSoftDeoptimize();
+    Add<HDeoptimize>(Deoptimizer::SOFT);
     right_type = handle(Type::Any(), isolate());
   }
   HInstruction* instr = NULL;
@@ -8214,7 +8212,7 @@
   // Cases handled below depend on collected type feedback. They should
   // soft deoptimize when there is no type feedback.
   if (combined_type->Is(Type::None())) {
-    AddSoftDeoptimize();
+    Add<HDeoptimize>(Deoptimizer::SOFT);
combined_type = left_type = right_type = handle(Type::Any(), isolate());
   }

@@ -8717,7 +8715,7 @@
         HStoreContextSlot* store = Add<HStoreContextSlot>(
context, variable->index(), HStoreContextSlot::kNoCheck, value);
         if (store->HasObservableSideEffects()) {
-          AddSimulate(proxy->id(), REMOVABLE_SIMULATE);
+          Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE);
         }
       }
       break;
@@ -8755,7 +8753,7 @@
       HStoreContextSlot* store = Add<HStoreContextSlot>(
           context, variable->index(), HStoreContextSlot::kNoCheck, value);
       if (store->HasObservableSideEffects()) {
-        AddSimulate(proxy->id(), REMOVABLE_SIMULATE);
+        Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE);
       }
       break;
     }
=======================================
--- /branches/bleeding_edge/src/hydrogen.h      Tue Jul 23 02:13:59 2013
+++ /branches/bleeding_edge/src/hydrogen.h      Tue Jul 23 06:35:10 2013
@@ -137,17 +137,15 @@
   }

   int PredecessorIndexOf(HBasicBlock* predecessor) const;
-  void AddSimulate(BailoutId ast_id,
-                   RemovableSimulate removable = FIXED_SIMULATE) {
-    AddInstruction(CreateSimulate(ast_id, removable));
+  HSimulate* AddSimulate(BailoutId ast_id,
+                         RemovableSimulate removable = FIXED_SIMULATE) {
+    HSimulate* instr = CreateSimulate(ast_id, removable);
+    AddInstruction(instr);
+    return instr;
   }
   void AssignCommonDominator(HBasicBlock* other);
   void AssignLoopSuccessorDominators();

-  void FinishExitWithDeoptimization(HDeoptimize::UseEnvironment has_uses) {
-    FinishExit(CreateDeoptimize(has_uses));
-  }
-
   // Add the inlined function exit sequence, adding an HLeaveInlined
   // instruction and updating the bailout environment.
   void AddLeaveInlined(HValue* return_value, FunctionState* state);
@@ -182,11 +180,12 @@
 #endif

  private:
+  friend class HGraphBuilder;
+
   void RegisterPredecessor(HBasicBlock* pred);
   void AddDominatedBlock(HBasicBlock* block);

   HSimulate* CreateSimulate(BailoutId ast_id, RemovableSimulate removable);
-  HDeoptimize* CreateDeoptimize(HDeoptimize::UseEnvironment has_uses);

   int block_id_;
   HGraph* graph_;
@@ -1022,11 +1021,6 @@
     return static_cast<I*>(AddInstruction(
             new(zone()) I(p1, p2, p3, p4, p5, p6, p7, p8)));
   }
-
-  void AddSimulate(BailoutId id,
-                   RemovableSimulate removable = FIXED_SIMULATE);
-
-  HReturn* AddReturn(HValue* value);

   void IncrementInNoSideEffectsScope() {
     no_side_effects_scope_count_++;
@@ -1122,12 +1116,7 @@

   void PushAndAdd(HInstruction* instr);

-  enum SoftDeoptimizeMode {
-    MUST_EMIT_SOFT_DEOPT,
-    CAN_OMIT_SOFT_DEOPT
-  };
-
-  void AddSoftDeoptimize(SoftDeoptimizeMode mode = CAN_OMIT_SOFT_DEOPT);
+  void FinishExitWithHardDeoptimization(HBasicBlock* continuation);

   class IfBuilder {
    public:
@@ -1232,7 +1221,6 @@
     void ElseDeopt() {
       Else();
       Deopt();
-      End();
     }

     void Return(HValue* value);
@@ -1245,6 +1233,8 @@
     HGraphBuilder* builder_;
     int position_;
     bool finished_ : 1;
+    bool deopt_then_ : 1;
+    bool deopt_else_ : 1;
     bool did_then_ : 1;
     bool did_else_ : 1;
     bool did_and_ : 1;
@@ -1426,12 +1416,68 @@

  private:
   HGraphBuilder();
+
+  void PadEnvironmentForContinuation(HBasicBlock* from,
+                                     HBasicBlock* continuation);
+
   CompilationInfo* info_;
   HGraph* graph_;
   HBasicBlock* current_block_;
   int no_side_effects_scope_count_;
 };

+
+template<>
+inline HDeoptimize* HGraphBuilder::Add(Deoptimizer::BailoutType type) {
+  if (type == Deoptimizer::SOFT) {
+    isolate()->counters()->soft_deopts_requested()->Increment();
+    if (FLAG_always_opt) return NULL;
+  }
+  if (current_block()->IsDeoptimizing()) return NULL;
+  HDeoptimize* instr = new(zone()) HDeoptimize(type);
+  AddInstruction(instr);
+  if (type == Deoptimizer::SOFT) {
+    isolate()->counters()->soft_deopts_inserted()->Increment();
+    graph()->set_has_soft_deoptimize(true);
+  }
+  current_block()->MarkAsDeoptimizing();
+  return instr;
+}
+
+
+template<>
+inline HSimulate* HGraphBuilder::Add(BailoutId id,
+                                     RemovableSimulate removable) {
+  HSimulate* instr = current_block()->CreateSimulate(id, removable);
+  AddInstruction(instr);
+  return instr;
+}
+
+
+template<>
+inline HSimulate* HGraphBuilder::Add(BailoutId id) {
+  return Add<HSimulate>(id, FIXED_SIMULATE);
+}
+
+
+template<>
+inline HReturn* HGraphBuilder::Add(HValue* value) {
+  HValue* context = environment()->LookupContext();
+  int num_parameters = graph()->info()->num_parameters();
+  HValue* params = Add<HConstant>(num_parameters);
+  HReturn* return_instruction = new(graph()->zone())
+      HReturn(value, context, params);
+  current_block()->FinishExit(return_instruction);
+  return return_instruction;
+}
+
+
+template<>
+inline HReturn* HGraphBuilder::Add(HConstant* p1) {
+  return Add<HReturn>(static_cast<HValue*>(p1));
+}
+
+
 class HOptimizedGraphBuilder: public HGraphBuilder, public AstVisitor {
  public:
   // A class encapsulating (lazily-allocated) break and continue blocks for
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Tue Jul 23 02:18:42 2013 +++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Tue Jul 23 06:35:10 2013
@@ -1001,12 +1001,6 @@
       : Deoptimizer::EAGER;
   DeoptimizeIf(cc, environment, bailout_type);
 }
-
-
-void LCodeGen::SoftDeoptimize(LEnvironment* environment) {
-  ASSERT(!info()->IsStub());
-  DeoptimizeIf(no_condition, environment, Deoptimizer::SOFT);
-}


 void LCodeGen::RegisterDependentCodeForEmbeddedMaps(Handle<Code> code) {
@@ -6323,11 +6317,15 @@


 void LCodeGen::DoDeoptimize(LDeoptimize* instr) {
-  if (instr->hydrogen_value()->IsSoftDeoptimize()) {
-    SoftDeoptimize(instr->environment());
-  } else {
-    DeoptimizeIf(no_condition, instr->environment());
+  Deoptimizer::BailoutType type = instr->hydrogen()->type();
+ // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the + // needed return address), even though the implementation of LAZY and EAGER is + // now identical. When LAZY is eventually completely folded into EAGER, remove
+  // the special case below.
+  if (info()->IsStub() && type == Deoptimizer::EAGER) {
+    type = Deoptimizer::LAZY;
   }
+  DeoptimizeIf(no_condition, instr->environment(), type);
 }


=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.h Mon Jul 15 08:12:16 2013 +++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.h Tue Jul 23 06:35:10 2013
@@ -283,7 +283,6 @@
                     LEnvironment* environment,
                     Deoptimizer::BailoutType bailout_type);
   void DeoptimizeIf(Condition cc, LEnvironment* environment);
-  void SoftDeoptimize(LEnvironment* environment);

   void AddToTranslation(Translation* translation,
                         LOperand* op,
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-ia32.cc Tue Jul 23 02:18:42 2013 +++ /branches/bleeding_edge/src/ia32/lithium-ia32.cc Tue Jul 23 06:35:10 2013
@@ -752,11 +752,6 @@
   UNREACHABLE();
   return NULL;
 }
-
-
-LInstruction* LChunkBuilder::DoSoftDeoptimize(HSoftDeoptimize* instr) {
-  return AssignEnvironment(new(zone()) LDeoptimize);
-}


 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-ia32.h     Tue Jul 23 00:31:46 2013
+++ /branches/bleeding_edge/src/ia32/lithium-ia32.h     Tue Jul 23 06:35:10 2013
@@ -424,6 +424,7 @@
 class LDeoptimize: public LTemplateInstruction<0, 0, 0> {
  public:
   DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
+  DECLARE_HYDROGEN_ACCESSOR(Deoptimize)
 };


=======================================
--- /branches/bleeding_edge/src/mips/lithium-codegen-mips.cc Mon Jul 22 15:00:41 2013 +++ /branches/bleeding_edge/src/mips/lithium-codegen-mips.cc Tue Jul 23 06:35:10 2013
@@ -788,14 +788,6 @@
       : Deoptimizer::EAGER;
   DeoptimizeIf(cc, environment, bailout_type, src1, src2);
 }
-
-
-void LCodeGen::SoftDeoptimize(LEnvironment* environment,
-                              Register src1,
-                              const Operand& src2) {
-  ASSERT(!info()->IsStub());
-  DeoptimizeIf(al, environment, Deoptimizer::SOFT, src1, src2);
-}


 void LCodeGen::RegisterDependentCodeForEmbeddedMaps(Handle<Code> code) {
@@ -5649,11 +5641,15 @@


 void LCodeGen::DoDeoptimize(LDeoptimize* instr) {
-  if (instr->hydrogen_value()->IsSoftDeoptimize()) {
-    SoftDeoptimize(instr->environment(), zero_reg, Operand(zero_reg));
-  } else {
-    DeoptimizeIf(al, instr->environment(), zero_reg, Operand(zero_reg));
+  Deoptimizer::BailoutType type = instr->hydrogen()->type();
+ // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the + // needed return address), even though the implementation of LAZY and EAGER is + // now identical. When LAZY is eventually completely folded into EAGER, remove
+  // the special case below.
+  if (info()->IsStub() && type == Deoptimizer::EAGER) {
+    type = Deoptimizer::LAZY;
   }
+ DeoptimizeIf(al, instr->environment(), type, zero_reg, Operand(zero_reg));
 }


=======================================
--- /branches/bleeding_edge/src/mips/lithium-codegen-mips.h Mon Jul 15 08:12:16 2013 +++ /branches/bleeding_edge/src/mips/lithium-codegen-mips.h Tue Jul 23 06:35:10 2013
@@ -284,9 +284,6 @@
                     LEnvironment* environment,
                     Register src1 = zero_reg,
                     const Operand& src2 = Operand(zero_reg));
-  void SoftDeoptimize(LEnvironment* environment,
-                      Register src1 = zero_reg,
-                      const Operand& src2 = Operand(zero_reg));

   void AddToTranslation(Translation* translation,
                         LOperand* op,
=======================================
--- /branches/bleeding_edge/src/mips/lithium-mips.cc Wed Jul 17 11:39:34 2013 +++ /branches/bleeding_edge/src/mips/lithium-mips.cc Tue Jul 23 06:35:10 2013
@@ -704,11 +704,6 @@
   UNREACHABLE();
   return NULL;
 }
-
-
-LInstruction* LChunkBuilder::DoSoftDeoptimize(HSoftDeoptimize* instr) {
-  return AssignEnvironment(new(zone()) LDeoptimize);
-}


 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
=======================================
--- /branches/bleeding_edge/src/mips/lithium-mips.h     Tue Jul 23 00:31:46 2013
+++ /branches/bleeding_edge/src/mips/lithium-mips.h     Tue Jul 23 06:35:10 2013
@@ -424,6 +424,7 @@
 class LDeoptimize: public LTemplateInstruction<0, 0, 0> {
  public:
   DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
+  DECLARE_HYDROGEN_ACCESSOR(Deoptimize)
 };


=======================================
--- /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Tue Jul 23 02:18:42 2013 +++ /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Tue Jul 23 06:35:10 2013
@@ -695,12 +695,6 @@
       : Deoptimizer::EAGER;
   DeoptimizeIf(cc, environment, bailout_type);
 }
-
-
-void LCodeGen::SoftDeoptimize(LEnvironment* environment) {
-  ASSERT(!info()->IsStub());
-  DeoptimizeIf(no_condition, environment, Deoptimizer::SOFT);
-}


 void LCodeGen::RegisterDependentCodeForEmbeddedMaps(Handle<Code> code) {
@@ -5364,11 +5358,15 @@


 void LCodeGen::DoDeoptimize(LDeoptimize* instr) {
-  if (instr->hydrogen_value()->IsSoftDeoptimize()) {
-    SoftDeoptimize(instr->environment());
-  } else {
-    DeoptimizeIf(no_condition, instr->environment());
+  Deoptimizer::BailoutType type = instr->hydrogen()->type();
+ // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the + // needed return address), even though the implementation of LAZY and EAGER is + // now identical. When LAZY is eventually completely folded into EAGER, remove
+  // the special case below.
+  if (info()->IsStub() && type == Deoptimizer::EAGER) {
+    type = Deoptimizer::LAZY;
   }
+  DeoptimizeIf(no_condition, instr->environment(), type);
 }


=======================================
--- /branches/bleeding_edge/src/x64/lithium-codegen-x64.h Mon Jul 15 08:12:16 2013 +++ /branches/bleeding_edge/src/x64/lithium-codegen-x64.h Tue Jul 23 06:35:10 2013
@@ -245,7 +245,6 @@
                     LEnvironment* environment,
                     Deoptimizer::BailoutType bailout_type);
   void DeoptimizeIf(Condition cc, LEnvironment* environment);
-  void SoftDeoptimize(LEnvironment* environment);
   void AddToTranslation(Translation* translation,
                         LOperand* op,
                         bool is_tagged,
=======================================
--- /branches/bleeding_edge/src/x64/lithium-x64.cc      Tue Jul 23 02:18:42 2013
+++ /branches/bleeding_edge/src/x64/lithium-x64.cc      Tue Jul 23 06:35:10 2013
@@ -708,11 +708,6 @@
   UNREACHABLE();
   return NULL;
 }
-
-
-LInstruction* LChunkBuilder::DoSoftDeoptimize(HSoftDeoptimize* instr) {
-  return AssignEnvironment(new(zone()) LDeoptimize);
-}


 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
=======================================
--- /branches/bleeding_edge/src/x64/lithium-x64.h       Tue Jul 23 00:31:46 2013
+++ /branches/bleeding_edge/src/x64/lithium-x64.h       Tue Jul 23 06:35:10 2013
@@ -427,6 +427,7 @@
 class LDeoptimize: public LTemplateInstruction<0, 0, 0> {
  public:
   DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
+  DECLARE_HYDROGEN_ACCESSOR(Deoptimize)
 };


--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to