Reland "Add handling for argument adaptor frames to inlining."
authorsigurds@chromium.org <sigurds@chromium.org>
Thu, 18 Sep 2014 08:56:52 +0000 (08:56 +0000)
committersigurds@chromium.org <sigurds@chromium.org>
Thu, 18 Sep 2014 08:56:52 +0000 (08:56 +0000)
Original: https://codereview.chromium.org/573703002/

Reland Fixes:
- Add deopt framestate to CollectStackTrace runtime call

R=mstarzinger@chromium.org

Review URL: https://codereview.chromium.org/544953006

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24023 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

20 files changed:
src/compiler/ast-graph-builder.cc
src/compiler/code-generator.cc
src/compiler/code-generator.h
src/compiler/common-operator.cc
src/compiler/common-operator.h
src/compiler/instruction-selector-impl.h
src/compiler/instruction-selector-unittest.cc
src/compiler/instruction-selector.cc
src/compiler/instruction.h
src/compiler/js-inlining.cc
src/compiler/js-inlining.h
src/compiler/linkage.cc
src/compiler/node-properties-inl.h
src/compiler/node-properties.h
src/compiler/node.h
src/frames.cc
test/cctest/cctest.status
test/cctest/compiler/test-codegen-deopt.cc
test/cctest/compiler/test-js-typed-lowering.cc
test/cctest/compiler/test-run-inlining.cc

index 5c61471..0364078 100644 (file)
@@ -224,7 +224,7 @@ Node* AstGraphBuilder::Environment::Checkpoint(
   UpdateStateValues(&stack_node_, parameters_count() + locals_count(),
                     stack_height());
 
-  const Operator* op = common()->FrameState(ast_id, combine);
+  const Operator* op = common()->FrameState(JS_FRAME, ast_id, combine);
 
   return graph()->NewNode(op, parameters_node_, locals_node_, stack_node_,
                           GetContext(),
@@ -2020,12 +2020,10 @@ Node* AstGraphBuilder::BuildBinaryOp(Node* left, Node* right, Token::Value op) {
 void AstGraphBuilder::PrepareFrameState(Node* node, BailoutId ast_id,
                                         OutputFrameStateCombine combine) {
   if (OperatorProperties::HasFrameStateInput(node->op())) {
-    int frame_state_index = NodeProperties::GetFrameStateIndex(node);
-
-    DCHECK(node->InputAt(frame_state_index)->op()->opcode() == IrOpcode::kDead);
-
-    Node* frame_state_node = environment()->Checkpoint(ast_id, combine);
-    node->ReplaceInput(frame_state_index, frame_state_node);
+    DCHECK(NodeProperties::GetFrameStateInput(node)->opcode() ==
+           IrOpcode::kDead);
+    NodeProperties::ReplaceFrameStateInput(
+        node, environment()->Checkpoint(ast_id, combine));
   }
 }
 
index 574d1ae..ae0e102 100644 (file)
@@ -246,7 +246,7 @@ void CodeGenerator::AddSafepointAndDeopt(Instruction* instr) {
     // (just after the code address).
     InstructionOperandConverter converter(this, instr);
     // Deoptimization info starts at argument 1
-    int frame_state_offset = 1;
+    size_t frame_state_offset = 1;
     FrameStateDescriptor* descriptor =
         GetFrameStateDescriptor(instr, frame_state_offset);
     int pc_offset = masm()->pc_offset();
@@ -266,7 +266,7 @@ void CodeGenerator::AddSafepointAndDeopt(Instruction* instr) {
     // Make sure all the values live in stack slots or they are immediates.
     // (The values should not live in register because registers are clobbered
     // by calls.)
-    for (int i = 0; i < descriptor->size(); i++) {
+    for (size_t i = 0; i < descriptor->size(); i++) {
       InstructionOperand* op = instr->InputAt(frame_state_offset + 1 + i);
       CHECK(op->IsStackSlot() || op->IsImmediate());
     }
@@ -287,40 +287,48 @@ int CodeGenerator::DefineDeoptimizationLiteral(Handle<Object> literal) {
 
 
 FrameStateDescriptor* CodeGenerator::GetFrameStateDescriptor(
-    Instruction* instr, int frame_state_offset) {
+    Instruction* instr, size_t frame_state_offset) {
   InstructionOperandConverter i(this, instr);
-  InstructionSequence::StateId state_id =
-      InstructionSequence::StateId::FromInt(i.InputInt32(frame_state_offset));
+  InstructionSequence::StateId state_id = InstructionSequence::StateId::FromInt(
+      i.InputInt32(static_cast<int>(frame_state_offset)));
   return code()->GetFrameStateDescriptor(state_id);
 }
 
 
 void CodeGenerator::BuildTranslationForFrameStateDescriptor(
     FrameStateDescriptor* descriptor, Instruction* instr,
-    Translation* translation, int frame_state_offset,
+    Translation* translation, size_t frame_state_offset,
     OutputFrameStateCombine state_combine) {
   // Outer-most state must be added to translation first.
   if (descriptor->outer_state() != NULL) {
-    BuildTranslationForFrameStateDescriptor(
-        descriptor->outer_state(), instr, translation,
-        frame_state_offset + descriptor->size(), kIgnoreOutput);
+    BuildTranslationForFrameStateDescriptor(descriptor->outer_state(), instr,
+                                            translation, frame_state_offset,
+                                            kIgnoreOutput);
   }
 
-  int height = descriptor->size() - descriptor->parameters_count();
-  switch (state_combine) {
-    case kPushOutput:
-      height++;
+  int id = Translation::kSelfLiteralId;
+  if (!descriptor->jsfunction().is_null()) {
+    id = DefineDeoptimizationLiteral(
+        Handle<Object>::cast(descriptor->jsfunction().ToHandleChecked()));
+  }
+
+  switch (descriptor->type()) {
+    case JS_FRAME:
+      translation->BeginJSFrame(
+          descriptor->bailout_id(), id,
+          static_cast<unsigned int>(descriptor->GetHeight(state_combine)));
       break;
-    case kIgnoreOutput:
+    case ARGUMENTS_ADAPTOR:
+      translation->BeginArgumentsAdaptorFrame(
+          id, static_cast<unsigned int>(descriptor->parameters_count()));
       break;
   }
 
-  translation->BeginJSFrame(descriptor->bailout_id(),
-                            Translation::kSelfLiteralId, height);
-
-  for (int i = 0; i < descriptor->size(); i++) {
-    AddTranslationForOperand(translation, instr,
-                             instr->InputAt(i + frame_state_offset));
+  frame_state_offset += descriptor->outer_state()->GetTotalSize();
+  for (size_t i = 0; i < descriptor->size(); i++) {
+    AddTranslationForOperand(
+        translation, instr,
+        instr->InputAt(static_cast<int>(frame_state_offset + i)));
   }
 
   switch (state_combine) {
@@ -335,14 +343,15 @@ void CodeGenerator::BuildTranslationForFrameStateDescriptor(
 
 
 int CodeGenerator::BuildTranslation(Instruction* instr, int pc_offset,
-                                    int frame_state_offset,
+                                    size_t frame_state_offset,
                                     OutputFrameStateCombine state_combine) {
   FrameStateDescriptor* descriptor =
       GetFrameStateDescriptor(instr, frame_state_offset);
   frame_state_offset++;
 
-  int frame_count = descriptor->GetFrameCount();
-  Translation translation(&translations_, frame_count, frame_count, zone());
+  Translation translation(
+      &translations_, static_cast<int>(descriptor->GetFrameCount()),
+      static_cast<int>(descriptor->GetJSFrameCount()), zone());
   BuildTranslationForFrameStateDescriptor(descriptor, instr, &translation,
                                           frame_state_offset, state_combine);
 
index 78ac990..dfc98cd 100644 (file)
@@ -87,13 +87,13 @@ class CodeGenerator FINAL : public GapResolver::Assembler {
   void PopulateDeoptimizationData(Handle<Code> code);
   int DefineDeoptimizationLiteral(Handle<Object> literal);
   FrameStateDescriptor* GetFrameStateDescriptor(Instruction* instr,
-                                                int frame_state_offset);
+                                                size_t frame_state_offset);
   int BuildTranslation(Instruction* instr, int pc_offset,
-                       int frame_state_offset,
+                       size_t frame_state_offset,
                        OutputFrameStateCombine state_combine);
   void BuildTranslationForFrameStateDescriptor(
       FrameStateDescriptor* descriptor, Instruction* instr,
-      Translation* translation, int frame_state_offset,
+      Translation* translation, size_t frame_state_offset,
       OutputFrameStateCombine state_combine);
   void AddTranslationForOperand(Translation* translation, Instruction* instr,
                                 InstructionOperand* op);
index e104b96..9034843 100644 (file)
@@ -206,10 +206,11 @@ const Operator* CommonOperatorBuilder::StateValues(int arguments) {
 
 
 const Operator* CommonOperatorBuilder::FrameState(
-    BailoutId bailout_id, OutputFrameStateCombine combine) {
+    FrameStateType type, BailoutId bailout_id,
+    OutputFrameStateCombine state_combine, MaybeHandle<JSFunction> jsfunction) {
   return new (zone()) Operator1<FrameStateCallInfo>(
       IrOpcode::kFrameState, Operator::kPure, 4, 1, "FrameState",
-      FrameStateCallInfo(bailout_id, combine));
+      FrameStateCallInfo(type, bailout_id, state_combine, jsfunction));
 }
 
 
index 137155e..52c0af2 100644 (file)
@@ -6,6 +6,7 @@
 #define V8_COMPILER_COMMON_OPERATOR_H_
 
 #include "src/compiler/machine-type.h"
+#include "src/unique.h"
 
 namespace v8 {
 namespace internal {
@@ -13,9 +14,6 @@ namespace internal {
 // Forward declarations.
 class ExternalReference;
 class OStream;
-template <typename>
-class Unique;
-class Zone;
 
 
 namespace compiler {
@@ -34,18 +32,34 @@ enum OutputFrameStateCombine {
 };
 
 
+// The type of stack frame that a FrameState node represents.
+enum FrameStateType {
+  JS_FRAME,          // Represents an unoptimized JavaScriptFrame.
+  ARGUMENTS_ADAPTOR  // Represents an ArgumentsAdaptorFrame.
+};
+
+
 class FrameStateCallInfo FINAL {
  public:
-  FrameStateCallInfo(BailoutId bailout_id,
-                     OutputFrameStateCombine state_combine)
-      : bailout_id_(bailout_id), frame_state_combine_(state_combine) {}
-
+  FrameStateCallInfo(
+      FrameStateType type, BailoutId bailout_id,
+      OutputFrameStateCombine state_combine,
+      MaybeHandle<JSFunction> jsfunction = MaybeHandle<JSFunction>())
+      : type_(type),
+        bailout_id_(bailout_id),
+        frame_state_combine_(state_combine),
+        jsfunction_(jsfunction) {}
+
+  FrameStateType type() const { return type_; }
   BailoutId bailout_id() const { return bailout_id_; }
   OutputFrameStateCombine state_combine() const { return frame_state_combine_; }
+  MaybeHandle<JSFunction> jsfunction() const { return jsfunction_; }
 
  private:
+  FrameStateType type_;
   BailoutId bailout_id_;
   OutputFrameStateCombine frame_state_combine_;
+  MaybeHandle<JSFunction> jsfunction_;
 };
 
 
@@ -81,8 +95,10 @@ class CommonOperatorBuilder FINAL {
   const Operator* ValueEffect(int arguments);
   const Operator* Finish(int arguments);
   const Operator* StateValues(int arguments);
-  const Operator* FrameState(BailoutId bailout_id,
-                             OutputFrameStateCombine combine);
+  const Operator* FrameState(
+      FrameStateType type, BailoutId bailout_id,
+      OutputFrameStateCombine state_combine,
+      MaybeHandle<JSFunction> jsfunction = MaybeHandle<JSFunction>());
   const Operator* Call(const CallDescriptor* descriptor);
   const Operator* Projection(size_t index);
 
index 6f3a6df..d00109e 100644 (file)
@@ -348,7 +348,7 @@ struct CallBuffer {
   size_t frame_state_value_count() const {
     return (frame_state_descriptor == NULL)
                ? 0
-               : (frame_state_descriptor->total_size() +
+               : (frame_state_descriptor->GetTotalSize() +
                   1);  // Include deopt id.
   }
 };
index f987e0f..aa70735 100644 (file)
@@ -303,9 +303,9 @@ TARGET_TEST_F(InstructionSelectorTest, CallJSFunctionWithDeopt) {
   Node* stack = m.NewNode(m.common()->StateValues(0));
   Node* context_dummy = m.Int32Constant(0);
 
-  Node* state_node =
-      m.NewNode(m.common()->FrameState(bailout_id, kPushOutput), parameters,
-                locals, stack, context_dummy, m.UndefinedConstant());
+  Node* state_node = m.NewNode(
+      m.common()->FrameState(JS_FRAME, bailout_id, kPushOutput), parameters,
+      locals, stack, context_dummy, m.UndefinedConstant());
   Node* call = m.CallJS0(function_node, receiver, context, state_node);
   m.Return(call);
 
@@ -344,8 +344,8 @@ TARGET_TEST_F(InstructionSelectorTest, CallFunctionStubWithDeopt) {
 
   Node* context_sentinel = m.Int32Constant(0);
   Node* frame_state_before = m.NewNode(
-      m.common()->FrameState(bailout_id_before, kPushOutput), parameters,
-      locals, stack, context_sentinel, m.UndefinedConstant());
+      m.common()->FrameState(JS_FRAME, bailout_id_before, kPushOutput),
+      parameters, locals, stack, context_sentinel, m.UndefinedConstant());
 
   // Build the call.
   Node* call = m.CallFunctionStub0(function_node, receiver, context,
@@ -383,9 +383,9 @@ TARGET_TEST_F(InstructionSelectorTest, CallFunctionStubWithDeopt) {
       s.GetFrameStateDescriptor(deopt_id_before);
   EXPECT_EQ(bailout_id_before, desc_before->bailout_id());
   EXPECT_EQ(kPushOutput, desc_before->state_combine());
-  EXPECT_EQ(1, desc_before->parameters_count());
-  EXPECT_EQ(1, desc_before->locals_count());
-  EXPECT_EQ(1, desc_before->stack_count());
+  EXPECT_EQ(1u, desc_before->parameters_count());
+  EXPECT_EQ(1u, desc_before->locals_count());
+  EXPECT_EQ(1u, desc_before->stack_count());
   EXPECT_EQ(43, s.ToInt32(call_instr->InputAt(2)));
   EXPECT_EQ(0, s.ToInt32(call_instr->InputAt(3)));
   EXPECT_EQ(44, s.ToInt32(call_instr->InputAt(4)));
@@ -419,18 +419,18 @@ TARGET_TEST_F(InstructionSelectorTest,
   Node* parameters = m.NewNode(m.common()->StateValues(1), m.Int32Constant(63));
   Node* locals = m.NewNode(m.common()->StateValues(1), m.Int32Constant(64));
   Node* stack = m.NewNode(m.common()->StateValues(1), m.Int32Constant(65));
-  Node* frame_state_parent =
-      m.NewNode(m.common()->FrameState(bailout_id_parent, kIgnoreOutput),
-                parameters, locals, stack, context, m.UndefinedConstant());
+  Node* frame_state_parent = m.NewNode(
+      m.common()->FrameState(JS_FRAME, bailout_id_parent, kIgnoreOutput),
+      parameters, locals, stack, context, m.UndefinedConstant());
 
   Node* context2 = m.Int32Constant(46);
   Node* parameters2 =
       m.NewNode(m.common()->StateValues(1), m.Int32Constant(43));
   Node* locals2 = m.NewNode(m.common()->StateValues(1), m.Int32Constant(44));
   Node* stack2 = m.NewNode(m.common()->StateValues(1), m.Int32Constant(45));
-  Node* frame_state_before =
-      m.NewNode(m.common()->FrameState(bailout_id_before, kPushOutput),
-                parameters2, locals2, stack2, context2, frame_state_parent);
+  Node* frame_state_before = m.NewNode(
+      m.common()->FrameState(JS_FRAME, bailout_id_before, kPushOutput),
+      parameters2, locals2, stack2, context2, frame_state_parent);
 
   // Build the call.
   Node* call = m.CallFunctionStub0(function_node, receiver, context2,
@@ -467,9 +467,9 @@ TARGET_TEST_F(InstructionSelectorTest,
   FrameStateDescriptor* desc_before =
       s.GetFrameStateDescriptor(deopt_id_before);
   EXPECT_EQ(bailout_id_before, desc_before->bailout_id());
-  EXPECT_EQ(1, desc_before->parameters_count());
-  EXPECT_EQ(1, desc_before->locals_count());
-  EXPECT_EQ(1, desc_before->stack_count());
+  EXPECT_EQ(1u, desc_before->parameters_count());
+  EXPECT_EQ(1u, desc_before->locals_count());
+  EXPECT_EQ(1u, desc_before->stack_count());
   EXPECT_EQ(63, s.ToInt32(call_instr->InputAt(2)));
   // Context:
   EXPECT_EQ(66, s.ToInt32(call_instr->InputAt(3)));
index dec46b6..6bc41f4 100644 (file)
@@ -1037,14 +1037,16 @@ void InstructionSelector::AddFrameStateInputs(
   DCHECK_EQ(descriptor->stack_count(), stack->InputCount());
 
   OperandGenerator g(this);
-  for (int i = 0; i < descriptor->parameters_count(); i++) {
+  for (int i = 0; i < static_cast<int>(descriptor->parameters_count()); i++) {
     inputs->push_back(UseOrImmediate(&g, parameters->InputAt(i)));
   }
-  inputs->push_back(UseOrImmediate(&g, context));
-  for (int i = 0; i < descriptor->locals_count(); i++) {
+  if (descriptor->HasContext()) {
+    inputs->push_back(UseOrImmediate(&g, context));
+  }
+  for (int i = 0; i < static_cast<int>(descriptor->locals_count()); i++) {
     inputs->push_back(UseOrImmediate(&g, locals->InputAt(i)));
   }
-  for (int i = 0; i < descriptor->stack_count(); i++) {
+  for (int i = 0; i < static_cast<int>(descriptor->stack_count()); i++) {
     inputs->push_back(UseOrImmediate(&g, stack->InputAt(i)));
   }
 }
index e2399b6..6d00784 100644 (file)
@@ -702,55 +702,84 @@ class Constant FINAL {
 class FrameStateDescriptor : public ZoneObject {
  public:
   FrameStateDescriptor(const FrameStateCallInfo& state_info,
-                       int parameters_count, int locals_count, int stack_count,
+                       size_t parameters_count, size_t locals_count,
+                       size_t stack_count,
                        FrameStateDescriptor* outer_state = NULL)
-      : bailout_id_(state_info.bailout_id()),
+      : type_(state_info.type()),
+        bailout_id_(state_info.bailout_id()),
         frame_state_combine_(state_info.state_combine()),
         parameters_count_(parameters_count),
         locals_count_(locals_count),
         stack_count_(stack_count),
-        outer_state_(outer_state) {}
+        outer_state_(outer_state),
+        jsfunction_(state_info.jsfunction()) {}
 
+  FrameStateType type() const { return type_; }
   BailoutId bailout_id() const { return bailout_id_; }
   OutputFrameStateCombine state_combine() const { return frame_state_combine_; }
-  int parameters_count() { return parameters_count_; }
-  int locals_count() { return locals_count_; }
-  int stack_count() { return stack_count_; }
-  FrameStateDescriptor* outer_state() { return outer_state_; }
-  void set_outer_state(FrameStateDescriptor* outer_state) {
-    outer_state_ = outer_state;
-  }
+  size_t parameters_count() const { return parameters_count_; }
+  size_t locals_count() const { return locals_count_; }
+  size_t stack_count() const { return stack_count_; }
+  FrameStateDescriptor* outer_state() const { return outer_state_; }
+  MaybeHandle<JSFunction> jsfunction() const { return jsfunction_; }
 
-  int size() {
+  size_t size() const {
     return parameters_count_ + locals_count_ + stack_count_ +
-           1;  // Includes context.
+           (HasContext() ? 1 : 0);
   }
 
-  int total_size() {
-    int total_size = 0;
-    for (FrameStateDescriptor* iter = this; iter != NULL;
+  size_t GetTotalSize() const {
+    size_t total_size = 0;
+    for (const FrameStateDescriptor* iter = this; iter != NULL;
          iter = iter->outer_state_) {
       total_size += iter->size();
     }
     return total_size;
   }
 
-  int GetFrameCount() {
-    int count = 0;
-    for (FrameStateDescriptor* iter = this; iter != NULL;
+  size_t GetHeight(OutputFrameStateCombine override) const {
+    size_t height = size() - parameters_count();
+    switch (override) {
+      case kPushOutput:
+        ++height;
+        break;
+      case kIgnoreOutput:
+        break;
+    }
+    return height;
+  }
+
+  size_t GetFrameCount() const {
+    size_t count = 0;
+    for (const FrameStateDescriptor* iter = this; iter != NULL;
          iter = iter->outer_state_) {
       ++count;
     }
     return count;
   }
 
+  size_t GetJSFrameCount() const {
+    size_t count = 0;
+    for (const FrameStateDescriptor* iter = this; iter != NULL;
+         iter = iter->outer_state_) {
+      if (iter->type_ == JS_FRAME) {
+        ++count;
+      }
+    }
+    return count;
+  }
+
+  bool HasContext() const { return type_ == JS_FRAME; }
+
  private:
+  FrameStateType type_;
   BailoutId bailout_id_;
   OutputFrameStateCombine frame_state_combine_;
-  int parameters_count_;
-  int locals_count_;
-  int stack_count_;
+  size_t parameters_count_;
+  size_t locals_count_;
+  size_t stack_count_;
   FrameStateDescriptor* outer_state_;
+  MaybeHandle<JSFunction> jsfunction_;
 };
 
 OStream& operator<<(OStream& os, const Constant& constant);
index b908ae8..4166ace 100644 (file)
@@ -15,6 +15,7 @@
 #include "src/compiler/node-properties-inl.h"
 #include "src/compiler/simplified-operator.h"
 #include "src/compiler/typer.h"
+#include "src/full-codegen.h"
 #include "src/parser.h"
 #include "src/rewriter.h"
 #include "src/scopes.h"
@@ -54,7 +55,6 @@ void JSInliner::Inline() {
 // test cases, where similar code is currently duplicated).
 static void Parse(Handle<JSFunction> function, CompilationInfoWithZone* info) {
   CHECK(Parser::Parse(info));
-  info->SetOptimizing(BailoutId::None(), Handle<Code>(function->code()));
   CHECK(Rewriter::Rewrite(info));
   CHECK(Scope::Analyze(info));
   CHECK_NE(NULL, info->scope());
@@ -90,6 +90,16 @@ class Inlinee {
     DCHECK_EQ(IrOpcode::kReturn, unique_return->opcode());
     return unique_return;
   }
+
+  // Counts JSFunction, Receiver, arguments, context but not effect, control.
+  size_t total_parameters() { return start_->op()->OutputCount(); }
+
+  // Counts only formal parameters.
+  size_t formal_parameters() {
+    DCHECK_GE(total_parameters(), 3);
+    return total_parameters() - 3;
+  }
+
   // Inline this graph at {call}, use {jsgraph} and its zone to create
   // any new nodes.
   void InlineAtCall(JSGraph* jsgraph, Node* call);
@@ -196,7 +206,7 @@ class CopyVisitor : public NullNodeVisitor {
 
  private:
   void ReplaceSentinels() {
-    for (int id = 0; id < source_graph_->NodeCount(); ++id) {
+    for (NodeId id = 0; id < source_graph_->NodeCount(); ++id) {
       Node* sentinel = sentinels_[id];
       if (sentinel == NULL) continue;
       Node* copy = copies_[id];
@@ -235,11 +245,8 @@ void Inlinee::InlineAtCall(JSGraph* jsgraph, Node* call) {
       NodeProperties::GetValueInput(call, 0),
       NodeProperties::GetEffectInput(call));
 
-  // {inlinee_inputs} counts JSFunction, Receiver, arguments, context,
-  // but not effect, control.
-  int inlinee_inputs = start_->op()->OutputCount();
   // Context is last argument.
-  int inlinee_context_index = inlinee_inputs - 1;
+  int inlinee_context_index = static_cast<int>(total_parameters()) - 1;
   // {inliner_inputs} counts JSFunction, Receiver, arguments, but not
   // context, effect, control.
   int inliner_inputs = OperatorProperties::GetValueInputCount(call->op());
@@ -299,10 +306,74 @@ void Inlinee::InlineAtCall(JSGraph* jsgraph, Node* call) {
 }
 
 
-void JSInliner::TryInlineCall(Node* call) {
-  DCHECK_EQ(IrOpcode::kJSCallFunction, call->opcode());
+// TODO(turbofan) Provide such accessors for every node, possibly even
+// generate them.
+class JSCallFunctionAccessor {
+ public:
+  explicit JSCallFunctionAccessor(Node* call) : call_(call) {
+    DCHECK_EQ(IrOpcode::kJSCallFunction, call->opcode());
+  }
+
+  Node* jsfunction() { return call_->InputAt(0); }
+
+  Node* receiver() { return call_->InputAt(1); }
+
+  Node* formal_argument(size_t index) {
+    DCHECK(index < formal_arguments());
+    return call_->InputAt(static_cast<int>(2 + index));
+  }
+
+  size_t formal_arguments() {
+    // {value_inputs} includes jsfunction and receiver.
+    size_t value_inputs = OperatorProperties::GetValueInputCount(call_->op());
+    DCHECK_GE(call_->InputCount(), 2);
+    return value_inputs - 2;
+  }
+
+  Node* frame_state() { return NodeProperties::GetFrameStateInput(call_); }
+
+ private:
+  Node* call_;
+};
+
+
+void JSInliner::AddClosureToFrameState(Node* frame_state,
+                                       Handle<JSFunction> jsfunction) {
+  FrameStateCallInfo call_info = OpParameter<FrameStateCallInfo>(frame_state);
+  const Operator* op = jsgraph_->common()->FrameState(
+      FrameStateType::JS_FRAME, call_info.bailout_id(),
+      call_info.state_combine(), jsfunction);
+  frame_state->set_op(op);
+}
+
+
+Node* JSInliner::CreateArgumentsAdaptorFrameState(JSCallFunctionAccessor* call,
+                                                  Handle<JSFunction> jsfunction,
+                                                  Zone* temp_zone) {
+  const Operator* op =
+      jsgraph_->common()->FrameState(FrameStateType::ARGUMENTS_ADAPTOR,
+                                     BailoutId(-1), kIgnoreOutput, jsfunction);
+  const Operator* op0 = jsgraph_->common()->StateValues(0);
+  Node* node0 = jsgraph_->graph()->NewNode(op0);
+  NodeVector params(temp_zone);
+  params.push_back(call->receiver());
+  for (size_t argument = 0; argument != call->formal_arguments(); ++argument) {
+    params.push_back(call->formal_argument(argument));
+  }
+  const Operator* op_param =
+      jsgraph_->common()->StateValues(static_cast<int>(params.size()));
+  Node* params_node = jsgraph_->graph()->NewNode(
+      op_param, static_cast<int>(params.size()), &params.front());
+  return jsgraph_->graph()->NewNode(op, params_node, node0, node0,
+                                    jsgraph_->UndefinedConstant(),
+                                    call->frame_state());
+}
+
 
-  HeapObjectMatcher<JSFunction> match(call->InputAt(0));
+void JSInliner::TryInlineCall(Node* call_node) {
+  JSCallFunctionAccessor call(call_node);
+
+  HeapObjectMatcher<JSFunction> match(call.jsfunction());
   if (!match.HasValue()) {
     return;
   }
@@ -322,6 +393,18 @@ void JSInliner::TryInlineCall(Node* call) {
   CompilationInfoWithZone info(function);
   Parse(function, &info);
 
+  if (!function->shared()->has_deoptimization_support()) {
+    // TODO(turbofan) In the future, unoptimized code with deopt support could
+    // be generated lazily once deopt is triggered.
+    info.EnableDeoptimizationSupport();
+    if (!FullCodeGenerator::MakeCode(&info)) {
+      DCHECK(false);
+      return;
+    }
+    function->shared()->EnableDeoptimizationSupport(*info.code());
+    function->shared()->set_feedback_vector(*info.feedback_vector());
+  }
+
   if (info.scope()->arguments() != NULL) {
     // For now do not inline functions that use their arguments array.
     SmartArrayPointer<char> name = function->shared()->DebugName()->ToCString();
@@ -353,7 +436,24 @@ void JSInliner::TryInlineCall(Node* call) {
   visitor.CopyGraph();
 
   Inlinee inlinee(visitor.GetCopy(graph.start()), visitor.GetCopy(graph.end()));
-  inlinee.InlineAtCall(jsgraph_, call);
+
+  Node* outer_frame_state = call.frame_state();
+  // Insert argument adaptor frame if required.
+  if (call.formal_arguments() != inlinee.formal_parameters()) {
+    outer_frame_state =
+        CreateArgumentsAdaptorFrameState(&call, function, info.zone());
+  }
+
+  for (NodeVectorConstIter it = visitor.copies().begin();
+       it != visitor.copies().end(); ++it) {
+    Node* node = *it;
+    if (node != NULL && node->opcode() == IrOpcode::kFrameState) {
+      AddClosureToFrameState(node, function);
+      NodeProperties::ReplaceFrameStateInput(node, outer_frame_state);
+    }
+  }
+
+  inlinee.InlineAtCall(jsgraph_, call_node);
 }
 }
 }
index a434571..f135170 100644 (file)
@@ -12,6 +12,8 @@ namespace v8 {
 namespace internal {
 namespace compiler {
 
+class JSCallFunctionAccessor;
+
 class JSInliner {
  public:
   JSInliner(CompilationInfo* info, JSGraph* jsgraph)
@@ -25,6 +27,10 @@ class JSInliner {
   CompilationInfo* info_;
   JSGraph* jsgraph_;
 
+  Node* CreateArgumentsAdaptorFrameState(JSCallFunctionAccessor* call,
+                                         Handle<JSFunction> jsfunction,
+                                         Zone* temp_zone);
+  void AddClosureToFrameState(Node* frame_state, Handle<JSFunction> jsfunction);
   static void UnifyReturn(Graph* graph);
 };
 }
index e459b1e..465a667 100644 (file)
@@ -123,6 +123,9 @@ bool Linkage::NeedsFrameState(Runtime::FunctionId function) {
     case Runtime::kPrepareStep:
     case Runtime::kSetScriptBreakPoint:
     case Runtime::kStackGuard:
+    case Runtime::kCheckExecutionState:
+    case Runtime::kDebugEvaluate:
+    case Runtime::kCollectStackTrace:
       return true;
     default:
       return false;
index bc52dfd..3f6d531 100644 (file)
@@ -162,6 +162,12 @@ inline void NodeProperties::ReplaceEffectInput(Node* node, Node* effect,
   return node->ReplaceInput(FirstEffectIndex(node) + index, effect);
 }
 
+inline void NodeProperties::ReplaceFrameStateInput(Node* node,
+                                                   Node* frame_state) {
+  DCHECK(OperatorProperties::HasFrameStateInput(node->op()));
+  node->ReplaceInput(FirstFrameStateIndex(node), frame_state);
+}
+
 inline void NodeProperties::RemoveNonValueInputs(Node* node) {
   node->TrimInputCount(OperatorProperties::GetValueInputCount(node->op()));
 }
index 6bc9856..94bd731 100644 (file)
@@ -35,6 +35,7 @@ class NodeProperties {
   static inline void ReplaceControlInput(Node* node, Node* control);
   static inline void ReplaceEffectInput(Node* node, Node* effect,
                                         int index = 0);
+  static inline void ReplaceFrameStateInput(Node* node, Node* frame_state);
   static inline void RemoveNonValueInputs(Node* node);
   static inline void ReplaceWithValue(Node* node, Node* value,
                                       Node* effect = NULL);
index 73787f0..c3f5a53 100644 (file)
@@ -71,6 +71,7 @@ typedef NodeSet::reverse_iterator NodeSetRIter;
 
 typedef ZoneVector<Node*> NodeVector;
 typedef NodeVector::iterator NodeVectorIter;
+typedef NodeVector::const_iterator NodeVectorConstIter;
 typedef NodeVector::reverse_iterator NodeVectorRIter;
 
 typedef ZoneVector<NodeVector> NodeVectorVector;
index 01c0a49..f116fd2 100644 (file)
@@ -932,9 +932,9 @@ void OptimizedFrame::Summarize(List<FrameSummary>* frames) {
   DCHECK(frames->length() == 0);
   DCHECK(is_optimized());
 
-  // Delegate to JS frame in absence of inlining.
-  // TODO(turbofan): Revisit once we support inlining.
-  if (LookupCode()->is_turbofanned()) {
+  // Delegate to JS frame in absence of turbofan deoptimization.
+  // TODO(turbofan): Revisit once we support deoptimization across the board.
+  if (LookupCode()->is_turbofanned() && !FLAG_turbo_deoptimization) {
     return JavaScriptFrame::Summarize(frames);
   }
 
@@ -1059,9 +1059,9 @@ DeoptimizationInputData* OptimizedFrame::GetDeoptimizationData(
 int OptimizedFrame::GetInlineCount() {
   DCHECK(is_optimized());
 
-  // Delegate to JS frame in absence of inlining.
-  // TODO(turbofan): Revisit once we support inlining.
-  if (LookupCode()->is_turbofanned()) {
+  // Delegate to JS frame in absence of turbofan deoptimization.
+  // TODO(turbofan): Revisit once we support deoptimization across the board.
+  if (LookupCode()->is_turbofanned() && !FLAG_turbo_deoptimization) {
     return JavaScriptFrame::GetInlineCount();
   }
 
@@ -1083,9 +1083,9 @@ void OptimizedFrame::GetFunctions(List<JSFunction*>* functions) {
   DCHECK(functions->length() == 0);
   DCHECK(is_optimized());
 
-  // Delegate to JS frame in absence of inlining.
-  // TODO(turbofan): Revisit once we support inlining.
-  if (LookupCode()->is_turbofanned()) {
+  // Delegate to JS frame in absence of turbofan deoptimization.
+  // TODO(turbofan): Revisit once we support deoptimization across the board.
+  if (LookupCode()->is_turbofanned() && !FLAG_turbo_deoptimization) {
     return JavaScriptFrame::GetFunctions(functions);
   }
 
index 86bc794..44ad3ae 100644 (file)
   ##############################################################################
   # TurboFan compiler failures.
 
-  # Scheduler cannot handle free-floating loops yet
-  'test-run-inlining/InlineLoop': [SKIP],
-
   # TODO(dcarney): C calls are broken all over the place.
   'test-run-machops/RunCall*': [SKIP],
   'test-run-machops/RunLoadImmIndex': [SKIP],
   'test-run-machops/RunSpillLotsOfThingsWithCall': [SKIP],
 
-  # TODO(sigurds): The schedule is borked with multiple inlinees.
+  # TODO(sigurds): The schedule is borked with multiple inlinees,
+  # and cannot handle free-floating loops yet
   'test-run-inlining/InlineTwiceDependentDiamond': [SKIP],
   'test-run-inlining/InlineTwiceDependentDiamondDifferent': [SKIP],
+  'test-run-inlining/InlineLoop': [SKIP],
 
   # Some tests are just too slow to run for now.
   'test-api/Threading*': [PASS, NO_VARIANTS],
index fb036a0..5b6c358 100644 (file)
@@ -148,9 +148,9 @@ class TrivialDeoptCodegenTester : public DeoptCodegenTester {
     Node* locals = m.NewNode(common.StateValues(0));
     Node* stack = m.NewNode(common.StateValues(0));
 
-    Node* state_node =
-        m.NewNode(common.FrameState(bailout_id, kIgnoreOutput), parameters,
-                  locals, stack, caller_context_node, m.UndefinedConstant());
+    Node* state_node = m.NewNode(
+        common.FrameState(JS_FRAME, bailout_id, kIgnoreOutput), parameters,
+        locals, stack, caller_context_node, m.UndefinedConstant());
 
     Handle<Context> context(deopt_function->context(), CcTest::i_isolate());
     Unique<Object> context_constant =
@@ -262,9 +262,9 @@ class TrivialRuntimeDeoptCodegenTester : public DeoptCodegenTester {
     Node* locals = m.NewNode(common.StateValues(0));
     Node* stack = m.NewNode(common.StateValues(0));
 
-    Node* state_node =
-        m.NewNode(common.FrameState(bailout_id, kIgnoreOutput), parameters,
-                  locals, stack, context_node, m.UndefinedConstant());
+    Node* state_node = m.NewNode(
+        common.FrameState(JS_FRAME, bailout_id, kIgnoreOutput), parameters,
+        locals, stack, context_node, m.UndefinedConstant());
 
     m.CallRuntime1(Runtime::kDeoptimizeFunction, this_fun_node, context_node,
                    state_node);
index 26ca766..afb9ed5 100644 (file)
@@ -60,7 +60,7 @@ class JSTypedLoweringTester : public HandleAndZoneScope {
     Node* stack = graph.NewNode(common.StateValues(0));
 
     Node* state_node =
-        graph.NewNode(common.FrameState(BailoutId(0), kIgnoreOutput),
+        graph.NewNode(common.FrameState(JS_FRAME, BailoutId(0), kIgnoreOutput),
                       parameters, locals, stack, context, UndefinedConstant());
 
     return state_node;
index 1e52b35..ad82fec 100644 (file)
 using namespace v8::internal;
 using namespace v8::internal::compiler;
 
-// TODO(sigurds) At the moment we do not write optimization frames when
-// inlining, thus the reported stack depth changes depending on inlining.
-// AssertStackDepth checks the stack depth actually changes as a simple way
-// to ensure that inlining actually occurs.
-// Once inlining creates optimization frames, all these unit tests need to
-// check that the optimization frame is there.
-
-
-static void AssertStackDepth(const v8::FunctionCallbackInfo<v8::Value>& args) {
-  v8::HandleScope scope(args.GetIsolate());
-  v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
-      args.GetIsolate(), 10, v8::StackTrace::kDetailed);
-  CHECK_EQ(args[0]->ToInt32()->Value(), stackTrace->GetFrameCount());
+// Helper to determine inline count via JavaScriptFrame::GetInlineCount.
+// Note that a count of 1 indicates that no inlining has occured.
+static void AssertInlineCount(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  StackTraceFrameIterator it(CcTest::i_isolate());
+  int frames_seen = 0;
+  JavaScriptFrame* topmost = it.frame();
+  while (!it.done()) {
+    JavaScriptFrame* frame = it.frame();
+    PrintF("%d %s, inline count: %d\n", frames_seen,
+           frame->function()->shared()->DebugName()->ToCString().get(),
+           frame->GetInlineCount());
+    frames_seen++;
+    it.Advance();
+  }
+  CHECK_EQ(args[0]->ToInt32()->Value(), topmost->GetInlineCount());
 }
 
 
-static void InstallAssertStackDepthHelper(v8::Isolate* isolate) {
+static void InstallAssertInlineCountHelper(v8::Isolate* isolate) {
   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   v8::Local<v8::FunctionTemplate> t =
-      v8::FunctionTemplate::New(isolate, AssertStackDepth);
-  context->Global()->Set(v8_str("AssertStackDepth"), t->GetFunction());
+      v8::FunctionTemplate::New(isolate, AssertInlineCount);
+  context->Global()->Set(v8_str("AssertInlineCount"), t->GetFunction());
 }
 
 
 TEST(SimpleInlining) {
+  FLAG_turbo_deoptimization = true;
   FunctionTester T(
       "(function(){"
-      "function foo(s) { AssertStackDepth(1); return s; };"
+      "function foo(s) { AssertInlineCount(2); return s; };"
       "function bar(s, t) { return foo(s); };"
       "return bar;})();",
       CompilationInfo::kInliningEnabled |
           CompilationInfo::kContextSpecializing |
           CompilationInfo::kTypingEnabled);
 
-  InstallAssertStackDepthHelper(CcTest::isolate());
+  InstallAssertInlineCountHelper(CcTest::isolate());
+  T.CheckCall(T.Val(1), T.Val(1), T.Val(2));
+}
+
+
+TEST(SimpleInliningDeopt) {
+  FLAG_turbo_deoptimization = true;
+  FunctionTester T(
+      "(function(){"
+      "function foo(s) { %DeoptimizeFunction(bar); return "
+      "s; };"
+      "function bar(s, t) { return foo(s); };"
+      "return bar;})();",
+      CompilationInfo::kInliningEnabled |
+          CompilationInfo::kContextSpecializing |
+          CompilationInfo::kTypingEnabled);
+
+  InstallAssertInlineCountHelper(CcTest::isolate());
   T.CheckCall(T.Val(1), T.Val(1), T.Val(2));
 }
 
 
 TEST(SimpleInliningContext) {
+  FLAG_turbo_deoptimization = true;
   FunctionTester T(
       "(function () {"
-      "function foo(s) { AssertStackDepth(1); var x = 12; return s + x; };"
+      "function foo(s) { AssertInlineCount(2); var x = 12; return s + x; };"
       "function bar(s, t) { return foo(s); };"
       "return bar;"
       "})();",
@@ -61,12 +82,33 @@ TEST(SimpleInliningContext) {
           CompilationInfo::kContextSpecializing |
           CompilationInfo::kTypingEnabled);
 
-  InstallAssertStackDepthHelper(CcTest::isolate());
+  InstallAssertInlineCountHelper(CcTest::isolate());
+  T.CheckCall(T.Val(13), T.Val(1), T.Val(2));
+}
+
+
+TEST(SimpleInliningContextDeopt) {
+  FLAG_turbo_deoptimization = true;
+  FunctionTester T(
+      "(function () {"
+      "function foo(s) { "
+      "  AssertInlineCount(2); %DeoptimizeFunction(bar); var x = 12;"
+      "  return s + x;"
+      "};"
+      "function bar(s, t) { return foo(s); };"
+      "return bar;"
+      "})();",
+      CompilationInfo::kInliningEnabled |
+          CompilationInfo::kContextSpecializing |
+          CompilationInfo::kTypingEnabled);
+
+  InstallAssertInlineCountHelper(CcTest::isolate());
   T.CheckCall(T.Val(13), T.Val(1), T.Val(2));
 }
 
 
 TEST(CaptureContext) {
+  FLAG_turbo_deoptimization = true;
   FunctionTester T(
       "var f = (function () {"
       "var x = 42;"
@@ -78,7 +120,7 @@ TEST(CaptureContext) {
           CompilationInfo::kContextSpecializing |
           CompilationInfo::kTypingEnabled);
 
-  InstallAssertStackDepthHelper(CcTest::isolate());
+  InstallAssertInlineCountHelper(CcTest::isolate());
   T.CheckCall(T.Val(42 + 12), T.Val(12), T.undefined());
 }
 
@@ -86,42 +128,65 @@ TEST(CaptureContext) {
 // TODO(sigurds) For now we do not inline any native functions. If we do at
 // some point, change this test.
 TEST(DontInlineEval) {
+  FLAG_turbo_deoptimization = true;
   FunctionTester T(
       "var x = 42;"
       "(function () {"
-      "function bar(s, t) { return eval(\"AssertStackDepth(2); x\") };"
+      "function bar(s, t) { return eval(\"AssertInlineCount(1); x\") };"
       "return bar;"
       "})();",
       CompilationInfo::kInliningEnabled |
           CompilationInfo::kContextSpecializing |
           CompilationInfo::kTypingEnabled);
 
-  InstallAssertStackDepthHelper(CcTest::isolate());
+  InstallAssertInlineCountHelper(CcTest::isolate());
   T.CheckCall(T.Val(42), T.Val("x"), T.undefined());
 }
 
 
 TEST(InlineOmitArguments) {
+  FLAG_turbo_deoptimization = true;
   FunctionTester T(
       "(function () {"
       "var x = 42;"
-      "function bar(s, t, u, v) { AssertStackDepth(1); return x + s; };"
+      "function bar(s, t, u, v) { AssertInlineCount(2); return x + s; };"
       "return (function (s,t) { return bar(s); });"
       "})();",
       CompilationInfo::kInliningEnabled |
           CompilationInfo::kContextSpecializing |
           CompilationInfo::kTypingEnabled);
 
-  InstallAssertStackDepthHelper(CcTest::isolate());
+  InstallAssertInlineCountHelper(CcTest::isolate());
   T.CheckCall(T.Val(42 + 12), T.Val(12), T.undefined());
 }
 
 
+TEST(InlineOmitArgumentsDeopt) {
+  FLAG_turbo_deoptimization = true;
+  FunctionTester T(
+      "(function () {"
+      "function foo(s,t,u,v) { AssertInlineCount(2); %DeoptimizeFunction(bar); "
+      "return baz(); };"
+      "function bar() { return foo(11); };"
+      "function baz() { return foo.arguments.length == 1 && "
+      "                        foo.arguments[0] == 11 ; }"
+      "return bar;"
+      "})();",
+      CompilationInfo::kInliningEnabled |
+          CompilationInfo::kContextSpecializing |
+          CompilationInfo::kTypingEnabled);
+
+  InstallAssertInlineCountHelper(CcTest::isolate());
+  T.CheckCall(T.true_value(), T.Val(12), T.Val(14));
+}
+
+
 TEST(InlineSurplusArguments) {
+  FLAG_turbo_deoptimization = true;
   FunctionTester T(
       "(function () {"
       "var x = 42;"
-      "function foo(s) { AssertStackDepth(1); return x + s; };"
+      "function foo(s) { AssertInlineCount(2); return x + s; };"
       "function bar(s,t) { return foo(s,t,13); };"
       "return bar;"
       "})();",
@@ -129,32 +194,56 @@ TEST(InlineSurplusArguments) {
           CompilationInfo::kContextSpecializing |
           CompilationInfo::kTypingEnabled);
 
-  InstallAssertStackDepthHelper(CcTest::isolate());
+  InstallAssertInlineCountHelper(CcTest::isolate());
   T.CheckCall(T.Val(42 + 12), T.Val(12), T.undefined());
 }
 
 
+TEST(InlineSurplusArgumentsDeopt) {
+  FLAG_turbo_deoptimization = true;
+  FunctionTester T(
+      "(function () {"
+      "function foo(s) { AssertInlineCount(2); %DeoptimizeFunction(bar); "
+      "return baz(); };"
+      "function bar() { return foo(13, 14, 15); };"
+      "function baz() { return foo.arguments.length == 3 && "
+      "                        foo.arguments[0] == 13 && "
+      "                        foo.arguments[1] == 14 && "
+      "                        foo.arguments[2] == 15; }"
+      "return bar;"
+      "})();",
+      CompilationInfo::kInliningEnabled |
+          CompilationInfo::kContextSpecializing |
+          CompilationInfo::kTypingEnabled);
+
+  InstallAssertInlineCountHelper(CcTest::isolate());
+  T.CheckCall(T.true_value(), T.Val(12), T.Val(14));
+}
+
+
 TEST(InlineTwice) {
+  FLAG_turbo_deoptimization = true;
   FunctionTester T(
       "(function () {"
       "var x = 42;"
-      "function bar(s) { AssertStackDepth(1); return x + s; };"
+      "function bar(s) { AssertInlineCount(2); return x + s; };"
       "return (function (s,t) { return bar(s) + bar(t); });"
       "})();",
       CompilationInfo::kInliningEnabled |
           CompilationInfo::kContextSpecializing |
           CompilationInfo::kTypingEnabled);
 
-  InstallAssertStackDepthHelper(CcTest::isolate());
+  InstallAssertInlineCountHelper(CcTest::isolate());
   T.CheckCall(T.Val(2 * 42 + 12 + 4), T.Val(12), T.Val(4));
 }
 
 
 TEST(InlineTwiceDependent) {
+  FLAG_turbo_deoptimization = true;
   FunctionTester T(
       "(function () {"
       "var x = 42;"
-      "function foo(s) { AssertStackDepth(1); return x + s; };"
+      "function foo(s) { AssertInlineCount(2); return x + s; };"
       "function bar(s,t) { return foo(foo(s)); };"
       "return bar;"
       "})();",
@@ -162,16 +251,17 @@ TEST(InlineTwiceDependent) {
           CompilationInfo::kContextSpecializing |
           CompilationInfo::kTypingEnabled);
 
-  InstallAssertStackDepthHelper(CcTest::isolate());
+  InstallAssertInlineCountHelper(CcTest::isolate());
   T.CheckCall(T.Val(42 + 42 + 12), T.Val(12), T.Val(4));
 }
 
 
 TEST(InlineTwiceDependentDiamond) {
+  FLAG_turbo_deoptimization = true;
   FunctionTester T(
       "(function () {"
       "var x = 41;"
-      "function foo(s) { AssertStackDepth(1); if (s % 2 == 0) {"
+      "function foo(s) { AssertInlineCount(2); if (s % 2 == 0) {"
       "                  return x - s } else { return x + s; } };"
       "function bar(s,t) { return foo(foo(s)); };"
       "return bar;"
@@ -180,16 +270,17 @@ TEST(InlineTwiceDependentDiamond) {
           CompilationInfo::kContextSpecializing |
           CompilationInfo::kTypingEnabled);
 
-  InstallAssertStackDepthHelper(CcTest::isolate());
+  InstallAssertInlineCountHelper(CcTest::isolate());
   T.CheckCall(T.Val(-11), T.Val(11), T.Val(4));
 }
 
 
 TEST(InlineTwiceDependentDiamondDifferent) {
+  FLAG_turbo_deoptimization = true;
   FunctionTester T(
       "(function () {"
       "var x = 41;"
-      "function foo(s,t) { AssertStackDepth(1); if (s % 2 == 0) {"
+      "function foo(s,t) { AssertInlineCount(2); if (s % 2 == 0) {"
       "                    return x - s * t } else { return x + s * t; } };"
       "function bar(s,t) { return foo(foo(s, 3), 5); };"
       "return bar;"
@@ -198,16 +289,17 @@ TEST(InlineTwiceDependentDiamondDifferent) {
           CompilationInfo::kContextSpecializing |
           CompilationInfo::kTypingEnabled);
 
-  InstallAssertStackDepthHelper(CcTest::isolate());
+  InstallAssertInlineCountHelper(CcTest::isolate());
   T.CheckCall(T.Val(-329), T.Val(11), T.Val(4));
 }
 
 
 TEST(InlineLoop) {
+  FLAG_turbo_deoptimization = true;
   FunctionTester T(
       "(function () {"
       "var x = 41;"
-      "function foo(s) { AssertStackDepth(1); while (s > 0) {"
+      "function foo(s) { AssertInlineCount(2); while (s > 0) {"
       "                  s = s - 1; }; return s; };"
       "function bar(s,t) { return foo(foo(s)); };"
       "return bar;"
@@ -216,12 +308,13 @@ TEST(InlineLoop) {
           CompilationInfo::kContextSpecializing |
           CompilationInfo::kTypingEnabled);
 
-  InstallAssertStackDepthHelper(CcTest::isolate());
+  InstallAssertInlineCountHelper(CcTest::isolate());
   T.CheckCall(T.Val(0.0), T.Val(11), T.Val(4));
 }
 
 
 TEST(InlineStrictIntoNonStrict) {
+  FLAG_turbo_deoptimization = true;
   FunctionTester T(
       "(function () {"
       "var x = Object.create({}, { y: { value:42, writable:false } });"
@@ -234,12 +327,13 @@ TEST(InlineStrictIntoNonStrict) {
           CompilationInfo::kContextSpecializing |
           CompilationInfo::kTypingEnabled);
 
-  InstallAssertStackDepthHelper(CcTest::isolate());
+  InstallAssertInlineCountHelper(CcTest::isolate());
   T.CheckThrows(T.undefined(), T.undefined());
 }
 
 
 TEST(InlineNonStrictIntoStrict) {
+  FLAG_turbo_deoptimization = true;
   FunctionTester T(
       "(function () {"
       "var x = Object.create({}, { y: { value:42, writable:false } });"
@@ -251,7 +345,7 @@ TEST(InlineNonStrictIntoStrict) {
           CompilationInfo::kContextSpecializing |
           CompilationInfo::kTypingEnabled);
 
-  InstallAssertStackDepthHelper(CcTest::isolate());
+  InstallAssertInlineCountHelper(CcTest::isolate());
   T.CheckCall(T.Val(42), T.undefined(), T.undefined());
 }