Revision: 16046
Author:   [email protected]
Date:     Mon Aug  5 02:53:12 2013
Log:      Merge 15827, 15842, and 15912 into 3.19

Unify SoftDeoptimize and Deoptimize hydrogen instructions

Fix assert/crash in HandlePolymorphicCallNamed caused by 15827

Add regression test for chromium:258519

BUG=chromium:258519
TEST=test/mjsunit/regress/regress-crbug-258519.js
[email protected]

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

Added:
 /branches/3.19/test/mjsunit/regress/regress-crbug-258519.js
Modified:
 /branches/3.19/src/arm/lithium-arm.cc
 /branches/3.19/src/arm/lithium-arm.h
 /branches/3.19/src/arm/lithium-codegen-arm.cc
 /branches/3.19/src/arm/lithium-codegen-arm.h
 /branches/3.19/src/code-stubs-hydrogen.cc
 /branches/3.19/src/hydrogen-environment-liveness.cc
 /branches/3.19/src/hydrogen-gvn.cc
 /branches/3.19/src/hydrogen-instructions.cc
 /branches/3.19/src/hydrogen-instructions.h
 /branches/3.19/src/hydrogen.cc
 /branches/3.19/src/hydrogen.h
 /branches/3.19/src/ia32/lithium-codegen-ia32.cc
 /branches/3.19/src/ia32/lithium-codegen-ia32.h
 /branches/3.19/src/ia32/lithium-ia32.cc
 /branches/3.19/src/ia32/lithium-ia32.h
 /branches/3.19/src/mips/lithium-codegen-mips.cc
 /branches/3.19/src/mips/lithium-codegen-mips.h
 /branches/3.19/src/mips/lithium-mips.cc
 /branches/3.19/src/mips/lithium-mips.h
 /branches/3.19/src/x64/lithium-codegen-x64.cc
 /branches/3.19/src/x64/lithium-codegen-x64.h
 /branches/3.19/src/x64/lithium-x64.cc
 /branches/3.19/src/x64/lithium-x64.h

=======================================
--- /dev/null
+++ /branches/3.19/test/mjsunit/regress/regress-crbug-258519.js Mon Aug 5 02:53:12 2013
@@ -0,0 +1,45 @@
+// Copyright 2013 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.
+
+// Flags: --allow-natives-syntax
+
+var a = {
+  compare_null: function(x) { return null != x; },
+  kaboom: function() {}
+}
+
+function crash(x) {
+  var b = a;
+  b.compare_null(x) && b.kaboom();
+  return "ok";
+}
+
+assertEquals("ok", crash(null));
+assertEquals("ok", crash(null));
+%OptimizeFunctionOnNextCall(crash);
+// Used to throw: "TypeError: Cannot call method 'kaboom' of undefined".
+assertEquals("ok", crash(1));
=======================================
--- /branches/3.19/src/arm/lithium-arm.cc       Tue Jun 18 04:54:54 2013
+++ /branches/3.19/src/arm/lithium-arm.cc       Mon Aug  5 02:53:12 2013
@@ -709,11 +709,6 @@
   UNREACHABLE();
   return NULL;
 }
-
-
-LInstruction* LChunkBuilder::DoSoftDeoptimize(HSoftDeoptimize* instr) {
-  return AssignEnvironment(new(zone()) LDeoptimize);
-}


 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
=======================================
--- /branches/3.19/src/arm/lithium-arm.h        Tue Jun 18 04:54:54 2013
+++ /branches/3.19/src/arm/lithium-arm.h        Mon Aug  5 02:53:12 2013
@@ -434,6 +434,7 @@
 class LDeoptimize: public LTemplateInstruction<0, 0, 0> {
  public:
   DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
+  DECLARE_HYDROGEN_ACCESSOR(Deoptimize)
 };


=======================================
--- /branches/3.19/src/arm/lithium-codegen-arm.cc       Thu Jul 25 04:04:49 2013
+++ /branches/3.19/src/arm/lithium-codegen-arm.cc       Mon Aug  5 02:53:12 2013
@@ -863,12 +863,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) {
@@ -5677,11 +5671,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/3.19/src/arm/lithium-codegen-arm.h        Tue Jun 18 04:54:54 2013
+++ /branches/3.19/src/arm/lithium-codegen-arm.h        Mon Aug  5 02:53:12 2013
@@ -285,7 +285,6 @@
                     LEnvironment* environment,
                     Deoptimizer::BailoutType bailout_type);
   void DeoptimizeIf(Condition cc, LEnvironment* environment);
-  void SoftDeoptimize(LEnvironment* environment);

   void AddToTranslation(Translation* translation,
                         LOperand* op,
=======================================
--- /branches/3.19/src/code-stubs-hydrogen.cc   Tue Jun 18 04:54:54 2013
+++ /branches/3.19/src/code-stubs-hydrogen.cc   Mon Aug  5 02:53:12 2013
@@ -177,7 +177,7 @@
   AddInstruction(context_);
   start_environment->BindContext(context_);

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

   NoObservableSideEffectsScope no_effects(this);

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

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


@@ -409,8 +410,11 @@
     AddStore(object, access, AddLoad(boilerplate, access));
   }

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


=======================================
--- /branches/3.19/src/hydrogen-environment-liveness.cc Wed Jun 5 06:39:03 2013 +++ /branches/3.19/src/hydrogen-environment-liveness.cc Mon Aug 5 02:53:12 2013
@@ -181,15 +181,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/3.19/src/hydrogen-gvn.cc  Mon Jun  3 08:43:46 2013
+++ /branches/3.19/src/hydrogen-gvn.cc  Mon Aug  5 02:53:12 2013
@@ -401,7 +401,7 @@
     GVNFlagSet side_effects;
     while (instr != NULL) {
       side_effects.Add(instr->ChangesFlags());
-      if (instr->IsSoftDeoptimize()) {
+      if (instr->IsDeoptimize()) {
         block_side_effects_[id].RemoveAll();
         side_effects.RemoveAll();
         break;
=======================================
--- /branches/3.19/src/hydrogen-instructions.cc Mon Jul 22 04:32:11 2013
+++ /branches/3.19/src/hydrogen-instructions.cc Mon Aug  5 02:53:12 2013
@@ -2118,16 +2118,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/3.19/src/hydrogen-instructions.h  Tue Jun 18 04:54:54 2013
+++ /branches/3.19/src/hydrogen-instructions.h  Mon Aug  5 02:53:12 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"
@@ -162,7 +163,6 @@
   V(Shl)                                       \
   V(Shr)                                       \
   V(Simulate)                                  \
-  V(SoftDeoptimize)                            \
   V(StackCheck)                                \
   V(StoreContextSlot)                          \
   V(StoreGlobalCell)                           \
@@ -1482,16 +1482,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_;
 };


@@ -1506,59 +1510,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/3.19/src/hydrogen.cc      Mon Jul 22 04:32:11 2013
+++ /branches/3.19/src/hydrogen.cc      Mon Aug  5 02:53:12 2013
@@ -128,26 +128,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,
@@ -670,13 +650,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;
@@ -690,6 +673,8 @@
     : builder_(builder),
       position_(RelocInfo::kNoPosition),
       finished_(false),
+      deopt_then_(false),
+      deopt_else_(false),
       did_then_(false),
       did_else_(false),
       did_and_(false),
@@ -826,14 +811,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);
 }


@@ -858,20 +842,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_);
     }
   }
@@ -979,14 +973,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);
-}


HBoundsCheck* HGraphBuilder::AddBoundsCheck(HValue* index, HValue* length) {
@@ -994,18 +980,6 @@
   AddInstruction(result);
   return result;
 }
-
-
-HReturn* HGraphBuilder::AddReturn(HValue* value) {
-  HValue* context = environment()->LookupContext();
-  int num_parameters = graph()->info()->num_parameters();
-  HValue* params = AddInstruction(new(graph()->zone())
-      HConstant(num_parameters));
-  HReturn* return_instruction = new(graph()->zone())
-      HReturn(value, context, params);
-  current_block()->FinishExit(return_instruction);
-  return return_instruction;
-}


 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) {
@@ -1030,10 +1004,43 @@
   AddInstruction(check);
   return check;
 }
+
+
+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());
   AddInstruction(check);
   return check;
@@ -2494,7 +2501,7 @@
         instr->DeleteAndReplaceWith(last_dummy);
         continue;
       }
-      if (instr->IsSoftDeoptimize()) {
+      if (instr->IsDeoptimize()) {
         ASSERT(block->IsDeoptimizing());
         nullify = true;
       }
@@ -3624,7 +3631,7 @@
   ASSERT(!instr->IsControlInstruction());
   owner()->AddInstruction(instr);
   if (instr->HasObservableSideEffects()) {
-    owner()->AddSimulate(ast_id, REMOVABLE_SIMULATE);
+    owner()->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   }
 }

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

@@ -3722,7 +3729,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);
@@ -3910,7 +3917,7 @@
     VisitVariableDeclaration(scope->function());
   }
   VisitDeclarations(scope->declarations());
-  AddSimulate(BailoutId::Declarations());
+  Add<HSimulate>(BailoutId::Declarations());

   HValue* context = environment()->LookupContext();
   AddInstruction(
@@ -3920,7 +3927,7 @@
   if (HasStackOverflow()) return false;

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

@@ -4657,15 +4664,6 @@
   Push(instr);
   AddInstruction(instr);
 }
-
-
-void HOptimizedGraphBuilder::AddSoftDeoptimize() {
-  if (FLAG_always_opt) return;
-  if (current_block()->IsDeoptimizing()) return;
-  AddInstruction(new(zone()) HSoftDeoptimize());
-  current_block()->MarkAsDeoptimizing();
-  graph()->set_has_soft_deoptimize(true);
-}


 template <class Instruction>
@@ -4774,10 +4772,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();
@@ -4884,7 +4882,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
@@ -4976,7 +4974,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();

@@ -5016,7 +5014,7 @@

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

       HCompareIDAndBranch* compare_ =
@@ -5066,7 +5064,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();
       }
@@ -5160,7 +5158,7 @@

   graph()->set_osr_values(osr_values);

-  AddSimulate(osr_entry_id);
+  Add<HSimulate>(osr_entry_id);
   AddInstruction(new(zone()) HOsrEntry(osr_entry_id));
   HContext* context = new(zone()) HContext;
   AddInstruction(context);
@@ -5176,7 +5174,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 =
     new(zone()) HStackCheck(context, HStackCheck::kBackwardsBranch);
@@ -5351,7 +5349,7 @@

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

   HInstruction* array = AddInstruction(
       new(zone()) HForInCacheArray(
@@ -5955,7 +5953,7 @@
             }
             AddInstruction(store);
             if (store->HasObservableSideEffects()) {
-              AddSimulate(key->id(), REMOVABLE_SIMULATE);
+              Add<HSimulate>(key->id(), REMOVABLE_SIMULATE);
             }
           } else {
             CHECK_ALIVE(VisitForEffect(value));
@@ -6131,7 +6129,7 @@
         break;
     }

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

   Drop(1);  // array literal index
@@ -6435,7 +6433,7 @@
   Push(value);
   store->set_position(position);
   AddInstruction(store);
-  AddSimulate(assignment_id);
+  Add<HSimulate>(assignment_id);
   ast_context()->ReturnValue(Pop());
   return true;
 }
@@ -6492,7 +6490,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, value);
     instr->set_position(position);
@@ -6507,10 +6505,10 @@
       // unoptimized code).
       if (instr->HasObservableSideEffects()) {
         if (ast_context()->IsEffect()) {
-          AddSimulate(id, REMOVABLE_SIMULATE);
+          Add<HSimulate>(id, REMOVABLE_SIMULATE);
         } else {
           Push(value);
-          AddSimulate(id, REMOVABLE_SIMULATE);
+          Add<HSimulate>(id, REMOVABLE_SIMULATE);
           Drop(1);
         }
       }
@@ -6552,7 +6550,7 @@
                              &has_side_effects);
     Drop(3);
     Push(value);
-    AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE);
+    Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
     return ast_context()->ReturnValue(Pop());
   }
 }
@@ -6576,7 +6574,7 @@
     instr->set_position(position);
     AddInstruction(instr);
     if (instr->HasObservableSideEffects()) {
-      AddSimulate(ast_id, REMOVABLE_SIMULATE);
+      Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
     }
   } else {
     HValue* context =  environment()->LookupContext();
@@ -6591,7 +6589,7 @@
     instr->set_position(position);
     AddInstruction(instr);
     ASSERT(instr->HasObservableSideEffects());
-    AddSimulate(ast_id, REMOVABLE_SIMULATE);
+    Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   }
 }

@@ -6649,7 +6647,7 @@
   instr->set_position(position);
   AddInstruction(instr);
   if (instr->HasObservableSideEffects()) {
-    AddSimulate(assignment_id, REMOVABLE_SIMULATE);
+    Add<HSimulate>(assignment_id, REMOVABLE_SIMULATE);
   }
   return ast_context()->ReturnValue(Pop());
 }
@@ -6727,7 +6725,7 @@
new(zone()) HStoreContextSlot(context, var->index(), mode, Top());
         AddInstruction(instr);
         if (instr->HasObservableSideEffects()) {
-          AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE);
+          Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
         }
         break;
       }
@@ -6768,7 +6766,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()));
@@ -6778,7 +6776,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(),
@@ -6796,7 +6794,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();
@@ -6805,7 +6803,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(),
@@ -6817,7 +6815,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());
     }

@@ -6940,7 +6938,7 @@
             context, var->index(), mode, Top());
         AddInstruction(instr);
         if (instr->HasObservableSideEffects()) {
-          AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE);
+          Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
         }
         return ast_context()->ReturnValue(Pop());
       }
@@ -6975,7 +6973,7 @@
   HThrow* instr = new(zone()) HThrow(context, value);
   instr->set_position(expr->position());
   AddInstruction(instr);
-  AddSimulate(expr->id());
+  Add<HSimulate>(expr->id());
   current_block()->FinishExit(new(zone()) HAbnormalExit);
   set_current_block(NULL);
 }
@@ -7007,7 +7005,7 @@
     Handle<String> name,
     Property* expr) {
   if (expr->IsUninitialized()) {
-    AddSoftDeoptimize();
+    Add<HDeoptimize>(Deoptimizer::SOFT);
   } else {
     // OS::DebugBreak();
   }
@@ -7400,7 +7398,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();
 }
@@ -7618,10 +7617,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);
       }
     }
@@ -7810,7 +7809,11 @@
   // 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);
+ // Because the deopt may be the only path in the polymorphic call, make sure + // that the environment stack matches the depth on deopt that it otherwise
+    // would have had after a successful call.
+    Drop(argument_count - (ast_context()->IsEffect() ? 0 : 1));
+    FinishExitWithHardDeoptimization(join);
   } else {
     HValue* context = environment()->LookupContext();
HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count);
@@ -8070,7 +8073,7 @@
   inner_env->BindContext(context);
 #endif

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

@@ -9109,7 +9112,7 @@
   Handle<Type> type = expr->type();
   Representation rep = ToRepresentation(type);
   if (type->Is(Type::None())) {
-    AddSoftDeoptimize();
+    Add<HDeoptimize>(Deoptimizer::SOFT);
     type = handle(Type::Any(), isolate());
   }
   if (instr->IsBinaryOperation()) {
@@ -9125,7 +9128,7 @@
   HValue* value = Pop();
   Handle<Type> info = expr->type();
   if (info->Is(Type::None())) {
-    AddSoftDeoptimize();
+    Add<HDeoptimize>(Deoptimizer::SOFT);
   }
   HInstruction* instr = new(zone()) HBitNot(value);
   return ast_context()->ReturnInstruction(instr, expr->id());
@@ -9282,7 +9285,7 @@
new(zone()) HStoreContextSlot(context, var->index(), mode, after);
         AddInstruction(instr);
         if (instr->HasObservableSideEffects()) {
-          AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE);
+          Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
         }
         break;
       }
@@ -9325,7 +9328,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);
@@ -9355,7 +9358,7 @@
       environment()->SetExpressionStackAt(0, after);
if (returns_original_input) environment()->SetExpressionStackAt(1, input);
       if (store->HasObservableSideEffects()) {
-        AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE);
+        Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
       }

     } else {
@@ -9373,7 +9376,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);
@@ -9390,7 +9393,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);
     }
   }

@@ -9495,11 +9498,11 @@
   Representation right_rep = ToRepresentation(right_type);
   Representation result_rep = ToRepresentation(result_type);
   if (left_type->Is(Type::None())) {
-    AddSoftDeoptimize();
+    Add<HDeoptimize>(Deoptimizer::SOFT);
     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;
@@ -9807,7 +9810,7 @@
   // Check if this expression was ever executed according to type feedback.
// Note that for the special typeof/null/undefined cases we get unknown here.
   if (overall_type->Is(Type::None())) {
-    AddSoftDeoptimize();
+    Add<HDeoptimize>(Deoptimizer::SOFT);
     overall_type = left_type = right_type = handle(Type::Any(), isolate());
   }

@@ -10317,7 +10320,7 @@
context, variable->index(), HStoreContextSlot::kNoCheck, value);
         AddInstruction(store);
         if (store->HasObservableSideEffects()) {
-          AddSimulate(proxy->id(), REMOVABLE_SIMULATE);
+          Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE);
         }
       }
       break;
@@ -10356,7 +10359,7 @@
           context, variable->index(), HStoreContextSlot::kNoCheck, value);
       AddInstruction(store);
       if (store->HasObservableSideEffects()) {
-        AddSimulate(proxy->id(), REMOVABLE_SIMULATE);
+        Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE);
       }
       break;
     }
=======================================
--- /branches/3.19/src/hydrogen.h       Mon Jul 22 04:32:11 2013
+++ /branches/3.19/src/hydrogen.h       Mon Aug  5 02:53:12 2013
@@ -136,17 +136,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);
@@ -181,11 +179,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_;
@@ -991,8 +990,6 @@

   // Adding instructions.
   HInstruction* AddInstruction(HInstruction* instr);
-  void AddSimulate(BailoutId id,
-                   RemovableSimulate removable = FIXED_SIMULATE);
   HBoundsCheck* AddBoundsCheck(HValue* index, HValue* length);

   HReturn* AddReturn(HValue* value);
@@ -1004,6 +1001,18 @@
   void DecrementInNoSideEffectsScope() {
     no_side_effects_scope_count_--;
   }
+
+  void FinishExitWithHardDeoptimization(HBasicBlock* continuation);
+
+  template<class I, class P1>
+  I* Add(P1 p1) {
+    return I::cast(AddInstruction(new (zone()) I(p1)));
+  }
+
+  template<class I, class P1, class P2>
+  I* Add(P1 p1, P2 p2) {
+    return I::cast(AddInstruction(new (zone()) I(p1, p2)));
+  }

  protected:
   virtual bool BuildGraph() = 0;
@@ -1183,7 +1192,6 @@
     void ElseDeopt() {
       Else();
       Deopt();
-      End();
     }

     void Return(HValue* value);
@@ -1196,6 +1204,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;
@@ -1374,11 +1384,64 @@

  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) {
+    if (FLAG_always_opt) return NULL;
+  }
+  if (current_block()->IsDeoptimizing()) return NULL;
+  HDeoptimize* instr = new(zone()) HDeoptimize(type);
+  AddInstruction(instr);
+  if (type == Deoptimizer::SOFT) {
+    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 {
@@ -1445,8 +1508,6 @@
void set_break_scope(BreakAndContinueScope* head) { break_scope_ = head; }

   bool inline_bailout() { return inline_bailout_; }
-
-  void AddSoftDeoptimize();

   void Bailout(const char* reason);

=======================================
--- /branches/3.19/src/ia32/lithium-codegen-ia32.cc     Tue Jul 23 08:29:32 2013
+++ /branches/3.19/src/ia32/lithium-codegen-ia32.cc     Mon Aug  5 02:53:12 2013
@@ -945,12 +945,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) {
@@ -6295,11 +6289,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/3.19/src/ia32/lithium-codegen-ia32.h      Tue Jun 18 04:54:54 2013
+++ /branches/3.19/src/ia32/lithium-codegen-ia32.h      Mon Aug  5 02:53:12 2013
@@ -277,7 +277,6 @@
                     LEnvironment* environment,
                     Deoptimizer::BailoutType bailout_type);
   void DeoptimizeIf(Condition cc, LEnvironment* environment);
-  void SoftDeoptimize(LEnvironment* environment);

   void AddToTranslation(Translation* translation,
                         LOperand* op,
=======================================
--- /branches/3.19/src/ia32/lithium-ia32.cc     Tue Jul 23 08:29:32 2013
+++ /branches/3.19/src/ia32/lithium-ia32.cc     Mon Aug  5 02:53:12 2013
@@ -768,11 +768,6 @@
   UNREACHABLE();
   return NULL;
 }
-
-
-LInstruction* LChunkBuilder::DoSoftDeoptimize(HSoftDeoptimize* instr) {
-  return AssignEnvironment(new(zone()) LDeoptimize);
-}


 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
=======================================
--- /branches/3.19/src/ia32/lithium-ia32.h      Tue Jul 23 08:29:32 2013
+++ /branches/3.19/src/ia32/lithium-ia32.h      Mon Aug  5 02:53:12 2013
@@ -421,6 +421,7 @@
 class LDeoptimize: public LTemplateInstruction<0, 0, 0> {
  public:
   DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
+  DECLARE_HYDROGEN_ACCESSOR(Deoptimize)
 };


=======================================
--- /branches/3.19/src/mips/lithium-codegen-mips.cc     Thu Jul 25 04:04:49 2013
+++ /branches/3.19/src/mips/lithium-codegen-mips.cc     Mon Aug  5 02:53:12 2013
@@ -841,14 +841,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) {
@@ -5651,11 +5643,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/3.19/src/mips/lithium-codegen-mips.h      Tue Jun 18 04:54:54 2013
+++ /branches/3.19/src/mips/lithium-codegen-mips.h      Mon Aug  5 02:53:12 2013
@@ -285,9 +285,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/3.19/src/mips/lithium-mips.cc     Tue Jun 18 04:54:54 2013
+++ /branches/3.19/src/mips/lithium-mips.cc     Mon Aug  5 02:53:12 2013
@@ -713,11 +713,6 @@
   UNREACHABLE();
   return NULL;
 }
-
-
-LInstruction* LChunkBuilder::DoSoftDeoptimize(HSoftDeoptimize* instr) {
-  return AssignEnvironment(new(zone()) LDeoptimize);
-}


 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
=======================================
--- /branches/3.19/src/mips/lithium-mips.h      Tue Jun 18 04:54:54 2013
+++ /branches/3.19/src/mips/lithium-mips.h      Mon Aug  5 02:53:12 2013
@@ -432,6 +432,7 @@
 class LDeoptimize: public LTemplateInstruction<0, 0, 0> {
  public:
   DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
+  DECLARE_HYDROGEN_ACCESSOR(Deoptimize)
 };


=======================================
--- /branches/3.19/src/x64/lithium-codegen-x64.cc       Wed Jun 19 11:17:45 2013
+++ /branches/3.19/src/x64/lithium-codegen-x64.cc       Mon Aug  5 02:53:12 2013
@@ -751,12 +751,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) {
@@ -5399,11 +5393,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/3.19/src/x64/lithium-codegen-x64.h        Tue Jun 18 04:54:54 2013
+++ /branches/3.19/src/x64/lithium-codegen-x64.h        Mon Aug  5 02:53:12 2013
@@ -246,7 +246,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/3.19/src/x64/lithium-x64.cc       Tue Jun 18 04:54:54 2013
+++ /branches/3.19/src/x64/lithium-x64.cc       Mon Aug  5 02:53:12 2013
@@ -717,11 +717,6 @@
   UNREACHABLE();
   return NULL;
 }
-
-
-LInstruction* LChunkBuilder::DoSoftDeoptimize(HSoftDeoptimize* instr) {
-  return AssignEnvironment(new(zone()) LDeoptimize);
-}


 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
=======================================
--- /branches/3.19/src/x64/lithium-x64.h        Tue Jun 18 04:54:54 2013
+++ /branches/3.19/src/x64/lithium-x64.h        Mon Aug  5 02:53:12 2013
@@ -434,6 +434,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