More lazy deoptimization in Turbofan (binops, loads/stores)
authorjarin@chromium.org <jarin@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 11 Aug 2014 10:42:01 +0000 (10:42 +0000)
committerjarin@chromium.org <jarin@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 11 Aug 2014 10:42:01 +0000 (10:42 +0000)
Deoptimizing binory operations, (Load|Store)(Property|Named),
constructors.

This also fixes safepoint lookup to account for lazily deoptimized code.

BUG=
R=bmeurer@chromium.org

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

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

20 files changed:
src/compiler/arm/linkage-arm.cc
src/compiler/arm64/linkage-arm64.cc
src/compiler/ast-graph-builder.cc
src/compiler/ast-graph-builder.h
src/compiler/code-generator.cc
src/compiler/ia32/linkage-ia32.cc
src/compiler/js-generic-lowering.cc
src/compiler/js-operator.h
src/compiler/linkage-impl.h
src/compiler/linkage.cc
src/compiler/linkage.h
src/compiler/operator-properties-inl.h
src/compiler/register-allocator.cc
src/compiler/register-allocator.h
src/compiler/x64/linkage-x64.cc
src/deoptimizer.cc
src/objects.cc
test/cctest/cctest.status
test/cctest/compiler/test-scheduler.cc
test/cctest/test-deoptimization.cc

index 489a0c6..6bea210 100644 (file)
@@ -49,9 +49,10 @@ CallDescriptor* Linkage::GetRuntimeCallDescriptor(
 
 
 CallDescriptor* Linkage::GetStubCallDescriptor(
-    CodeStubInterfaceDescriptor* descriptor, int stack_parameter_count) {
+    CodeStubInterfaceDescriptor* descriptor, int stack_parameter_count,
+    CallDescriptor::DeoptimizationSupport can_deoptimize, Zone* zone) {
   return LinkageHelper::GetStubCallDescriptor<LinkageHelperTraits>(
-      this->info_->zone(), descriptor, stack_parameter_count);
+      zone, descriptor, stack_parameter_count, can_deoptimize);
 }
 
 
index 240cef1..e44c5d8 100644 (file)
@@ -49,9 +49,10 @@ CallDescriptor* Linkage::GetRuntimeCallDescriptor(
 
 
 CallDescriptor* Linkage::GetStubCallDescriptor(
-    CodeStubInterfaceDescriptor* descriptor, int stack_parameter_count) {
+    CodeStubInterfaceDescriptor* descriptor, int stack_parameter_count,
+    CallDescriptor::DeoptimizationSupport can_deoptimize, Zone* zone) {
   return LinkageHelper::GetStubCallDescriptor<LinkageHelperTraits>(
-      this->info_->zone(), descriptor, stack_parameter_count);
+      zone, descriptor, stack_parameter_count, can_deoptimize);
 }
 
 
index 2c242cb..328156b 100644 (file)
@@ -238,8 +238,12 @@ Node* AstGraphBuilder::Environment::Checkpoint(BailoutId ast_id) {
 
 
 AstGraphBuilder::AstContext::AstContext(AstGraphBuilder* own,
-                                        Expression::Context kind)
-    : kind_(kind), owner_(own), outer_(own->ast_context()) {
+                                        Expression::Context kind,
+                                        BailoutId bailout_id)
+    : bailout_id_(bailout_id),
+      kind_(kind),
+      owner_(own),
+      outer_(own->ast_context()) {
   owner()->set_ast_context(this);  // Push.
 #ifdef DEBUG
   original_height_ = environment()->stack_height();
@@ -267,6 +271,28 @@ AstGraphBuilder::AstTestContext::~AstTestContext() {
 }
 
 
+void AstGraphBuilder::AstEffectContext::ProduceValueWithLazyBailout(
+    Node* value) {
+  ProduceValue(value);
+  owner()->BuildLazyBailout(value, bailout_id_);
+}
+
+
+void AstGraphBuilder::AstValueContext::ProduceValueWithLazyBailout(
+    Node* value) {
+  ProduceValue(value);
+  owner()->BuildLazyBailout(value, bailout_id_);
+}
+
+
+void AstGraphBuilder::AstTestContext::ProduceValueWithLazyBailout(Node* value) {
+  environment()->Push(value);
+  owner()->BuildLazyBailout(value, bailout_id_);
+  environment()->Pop();
+  ProduceValue(value);
+}
+
+
 void AstGraphBuilder::AstEffectContext::ProduceValue(Node* value) {
   // The value is ignored.
 }
@@ -333,7 +359,7 @@ void AstGraphBuilder::VisitForValues(ZoneList<Expression*>* exprs) {
 
 
 void AstGraphBuilder::VisitForValue(Expression* expr) {
-  AstValueContext for_value(this);
+  AstValueContext for_value(this, expr->id());
   if (!HasStackOverflow()) {
     expr->Accept(this);
   }
@@ -341,7 +367,7 @@ void AstGraphBuilder::VisitForValue(Expression* expr) {
 
 
 void AstGraphBuilder::VisitForEffect(Expression* expr) {
-  AstEffectContext for_effect(this);
+  AstEffectContext for_effect(this, expr->id());
   if (!HasStackOverflow()) {
     expr->Accept(this);
   }
@@ -349,7 +375,7 @@ void AstGraphBuilder::VisitForEffect(Expression* expr) {
 
 
 void AstGraphBuilder::VisitForTest(Expression* expr) {
-  AstTestContext for_condition(this);
+  AstTestContext for_condition(this, expr->id());
   if (!HasStackOverflow()) {
     expr->Accept(this);
   }
@@ -686,6 +712,8 @@ void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
         Node* index = environment()->Peek(0);
         Node* exit_cond =
             NewNode(javascript()->LessThan(), index, cache_length);
+        // TODO(jarin): provide real bailout id.
+        BuildLazyBailout(exit_cond, BailoutId::None());
         for_loop.BreakUnless(exit_cond);
         // TODO(dcarney): this runtime call should be a handful of
         //                simplified instructions that
@@ -724,6 +752,8 @@ void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
           // is gone.
           Node* res = ProcessArguments(
               javascript()->Call(3, NO_CALL_FUNCTION_FLAGS), 3);
+          // TODO(jarin): provide real bailout id.
+          BuildLazyBailout(res, BailoutId::None());
           Node* property_missing = NewNode(javascript()->StrictEqual(), res,
                                            jsgraph()->ZeroConstant());
           {
@@ -829,7 +859,7 @@ void AstGraphBuilder::VisitConditional(Conditional* expr) {
 
 
 void AstGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
-  Node* value = BuildVariableLoad(expr->var());
+  Node* value = BuildVariableLoad(expr->var(), expr->id());
   ast_context()->ProduceValue(value);
 }
 
@@ -896,7 +926,9 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
             VisitForValue(property->value());
             Node* value = environment()->Pop();
             PrintableUnique<Name> name = MakeUnique(key->AsPropertyName());
-            NewNode(javascript()->StoreNamed(name), literal, value);
+            Node* store =
+                NewNode(javascript()->StoreNamed(name), literal, value);
+            BuildLazyBailout(store, key->id());
           } else {
             VisitForEffect(property->value());
           }
@@ -987,7 +1019,8 @@ void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
     VisitForValue(subexpr);
     Node* value = environment()->Pop();
     Node* index = jsgraph()->Constant(i);
-    NewNode(javascript()->StoreProperty(), literal, index, value);
+    Node* store = NewNode(javascript()->StoreProperty(), literal, index, value);
+    BuildLazyBailout(store, expr->GetIdForElement(i));
   }
 
   environment()->Pop();  // Array literal index.
@@ -1006,7 +1039,8 @@ void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value) {
   switch (assign_type) {
     case VARIABLE: {
       Variable* var = expr->AsVariableProxy()->var();
-      BuildVariableAssignment(var, value, Token::ASSIGN);
+      // TODO(jarin) Fill in the correct bailout id.
+      BuildVariableAssignment(var, value, Token::ASSIGN, BailoutId::None());
       break;
     }
     case NAMED_PROPERTY: {
@@ -1016,7 +1050,9 @@ void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value) {
       value = environment()->Pop();
       PrintableUnique<Name> name =
           MakeUnique(property->key()->AsLiteral()->AsPropertyName());
-      NewNode(javascript()->StoreNamed(name), object, value);
+      Node* store = NewNode(javascript()->StoreNamed(name), object, value);
+      // TODO(jarin) Fill in the correct bailout id.
+      BuildLazyBailout(store, BailoutId::None());
       break;
     }
     case KEYED_PROPERTY: {
@@ -1026,7 +1062,9 @@ void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value) {
       Node* key = environment()->Pop();
       Node* object = environment()->Pop();
       value = environment()->Pop();
-      NewNode(javascript()->StoreProperty(), object, key, value);
+      Node* store = NewNode(javascript()->StoreProperty(), object, key, value);
+      // TODO(jarin) Fill in the correct bailout id.
+      BuildLazyBailout(store, BailoutId::None());
       break;
     }
   }
@@ -1062,7 +1100,7 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) {
     switch (assign_type) {
       case VARIABLE: {
         Variable* variable = expr->target()->AsVariableProxy()->var();
-        old_value = BuildVariableLoad(variable);
+        old_value = BuildVariableLoad(variable, expr->target()->id());
         break;
       }
       case NAMED_PROPERTY: {
@@ -1070,12 +1108,14 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) {
         PrintableUnique<Name> name =
             MakeUnique(property->key()->AsLiteral()->AsPropertyName());
         old_value = NewNode(javascript()->LoadNamed(name), object);
+        BuildLazyBailoutWithPushedNode(old_value, property->LoadId());
         break;
       }
       case KEYED_PROPERTY: {
         Node* key = environment()->Top();
         Node* object = environment()->Peek(1);
         old_value = NewNode(javascript()->LoadProperty(), object, key);
+        BuildLazyBailoutWithPushedNode(old_value, property->LoadId());
         break;
       }
     }
@@ -1085,6 +1125,7 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) {
     Node* left = environment()->Pop();
     Node* value = BuildBinaryOp(left, right, expr->binary_op());
     environment()->Push(value);
+    BuildLazyBailout(value, expr->binary_operation()->id());
   } else {
     VisitForValue(expr->value());
   }
@@ -1094,20 +1135,23 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) {
   switch (assign_type) {
     case VARIABLE: {
       Variable* variable = expr->target()->AsVariableProxy()->var();
-      BuildVariableAssignment(variable, value, expr->op());
+      BuildVariableAssignment(variable, value, expr->op(),
+                              expr->AssignmentId());
       break;
     }
     case NAMED_PROPERTY: {
       Node* object = environment()->Pop();
       PrintableUnique<Name> name =
           MakeUnique(property->key()->AsLiteral()->AsPropertyName());
-      NewNode(javascript()->StoreNamed(name), object, value);
+      Node* store = NewNode(javascript()->StoreNamed(name), object, value);
+      BuildLazyBailout(store, expr->AssignmentId());
       break;
     }
     case KEYED_PROPERTY: {
       Node* key = environment()->Pop();
       Node* object = environment()->Pop();
-      NewNode(javascript()->StoreProperty(), object, key, value);
+      Node* store = NewNode(javascript()->StoreProperty(), object, key, value);
+      BuildLazyBailout(store, expr->AssignmentId());
       break;
     }
   }
@@ -1150,7 +1194,7 @@ void AstGraphBuilder::VisitProperty(Property* expr) {
     Node* object = environment()->Pop();
     value = NewNode(javascript()->LoadProperty(), object, key);
   }
-  ast_context()->ProduceValue(value);
+  ast_context()->ProduceValueWithLazyBailout(value);
 }
 
 
@@ -1167,7 +1211,7 @@ void AstGraphBuilder::VisitCall(Call* expr) {
   switch (call_type) {
     case Call::GLOBAL_CALL: {
       Variable* variable = callee->AsVariableProxy()->var();
-      callee_value = BuildVariableLoad(variable);
+      callee_value = BuildVariableLoad(variable, expr->expression()->id());
       receiver_value = jsgraph()->UndefinedConstant();
       break;
     }
@@ -1194,6 +1238,7 @@ void AstGraphBuilder::VisitCall(Call* expr) {
         Node* key = environment()->Pop();
         callee_value = NewNode(javascript()->LoadProperty(), object, key);
       }
+      BuildLazyBailoutWithPushedNode(callee_value, property->LoadId());
       receiver_value = environment()->Pop();
       // Note that a PROPERTY_CALL requires the receiver to be wrapped into an
       // object for sloppy callees. This could also be modeled explicitly here,
@@ -1248,7 +1293,7 @@ void AstGraphBuilder::VisitCall(Call* expr) {
   // Create node to perform the function call.
   Operator* call = javascript()->Call(args->length() + 2, flags);
   Node* value = ProcessArguments(call, args->length() + 2);
-  ast_context()->ProduceValue(value);
+  ast_context()->ProduceValueWithLazyBailout(value);
 }
 
 
@@ -1262,7 +1307,7 @@ void AstGraphBuilder::VisitCallNew(CallNew* expr) {
   // Create node to perform the construct call.
   Operator* call = javascript()->CallNew(args->length() + 1);
   Node* value = ProcessArguments(call, args->length() + 1);
-  ast_context()->ProduceValue(value);
+  ast_context()->ProduceValueWithLazyBailout(value);
 }
 
 
@@ -1276,6 +1321,9 @@ void AstGraphBuilder::VisitCallJSRuntime(CallRuntime* expr) {
   PrintableUnique<String> unique = MakeUnique(name);
   Node* callee_value = NewNode(javascript()->LoadNamed(unique), receiver_value);
   environment()->Push(callee_value);
+  // TODO(jarin): Find/create a bailout id to deoptimize to (crankshaft
+  // refuses to optimize functions with jsruntime calls).
+  BuildLazyBailout(callee_value, BailoutId::None());
   environment()->Push(receiver_value);
 
   // Evaluate all arguments to the JS runtime call.
@@ -1285,7 +1333,7 @@ void AstGraphBuilder::VisitCallJSRuntime(CallRuntime* expr) {
   // Create node to perform the JS runtime call.
   Operator* call = javascript()->Call(args->length() + 2, flags);
   Node* value = ProcessArguments(call, args->length() + 2);
-  ast_context()->ProduceValue(value);
+  ast_context()->ProduceValueWithLazyBailout(value);
 }
 
 
@@ -1307,9 +1355,7 @@ void AstGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
   Runtime::FunctionId functionId = function->function_id;
   Operator* call = javascript()->Runtime(functionId, args->length());
   Node* value = ProcessArguments(call, args->length());
-  ast_context()->ProduceValue(value);
-
-  BuildLazyBailout(value, expr->id());
+  ast_context()->ProduceValueWithLazyBailout(value);
 }
 
 
@@ -1346,7 +1392,7 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
   switch (assign_type) {
     case VARIABLE: {
       Variable* variable = expr->expression()->AsVariableProxy()->var();
-      old_value = BuildVariableLoad(variable);
+      old_value = BuildVariableLoad(variable, expr->expression()->id());
       stack_depth = 0;
       break;
     }
@@ -1356,6 +1402,7 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
       PrintableUnique<Name> name =
           MakeUnique(property->key()->AsLiteral()->AsPropertyName());
       old_value = NewNode(javascript()->LoadNamed(name), object);
+      BuildLazyBailoutWithPushedNode(old_value, property->LoadId());
       stack_depth = 1;
       break;
     }
@@ -1365,6 +1412,7 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
       Node* key = environment()->Top();
       Node* object = environment()->Peek(1);
       old_value = NewNode(javascript()->LoadProperty(), object, key);
+      BuildLazyBailoutWithPushedNode(old_value, property->LoadId());
       stack_depth = 2;
       break;
     }
@@ -1379,25 +1427,31 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
   // Create node to perform +1/-1 operation.
   Node* value =
       BuildBinaryOp(old_value, jsgraph()->OneConstant(), expr->binary_op());
+  // TODO(jarin) Insert proper bailout id here (will need to change
+  // full code generator).
+  BuildLazyBailout(value, BailoutId::None());
 
   // Store the value.
   switch (assign_type) {
     case VARIABLE: {
       Variable* variable = expr->expression()->AsVariableProxy()->var();
-      BuildVariableAssignment(variable, value, expr->op());
+      BuildVariableAssignment(variable, value, expr->op(),
+                              expr->AssignmentId());
       break;
     }
     case NAMED_PROPERTY: {
       Node* object = environment()->Pop();
       PrintableUnique<Name> name =
           MakeUnique(property->key()->AsLiteral()->AsPropertyName());
-      NewNode(javascript()->StoreNamed(name), object, value);
+      Node* store = NewNode(javascript()->StoreNamed(name), object, value);
+      BuildLazyBailout(store, expr->AssignmentId());
       break;
     }
     case KEYED_PROPERTY: {
       Node* key = environment()->Pop();
       Node* object = environment()->Pop();
-      NewNode(javascript()->StoreProperty(), object, key, value);
+      Node* store = NewNode(javascript()->StoreProperty(), object, key, value);
+      BuildLazyBailout(store, expr->AssignmentId());
       break;
     }
   }
@@ -1422,7 +1476,7 @@ void AstGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
       Node* right = environment()->Pop();
       Node* left = environment()->Pop();
       Node* value = BuildBinaryOp(left, right, expr->op());
-      ast_context()->ProduceValue(value);
+      ast_context()->ProduceValueWithLazyBailout(value);
     }
   }
 }
@@ -1471,6 +1525,8 @@ void AstGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
   Node* left = environment()->Pop();
   Node* value = NewNode(op, left, right);
   ast_context()->ProduceValue(value);
+
+  BuildLazyBailout(value, expr->id());
 }
 
 
@@ -1550,7 +1606,8 @@ void AstGraphBuilder::VisitTypeof(UnaryOperation* expr) {
     // Typeof does not throw a reference error on global variables, hence we
     // perform a non-contextual load in case the operand is a variable proxy.
     Variable* variable = expr->expression()->AsVariableProxy()->var();
-    operand = BuildVariableLoad(variable, NOT_CONTEXTUAL);
+    operand =
+        BuildVariableLoad(variable, expr->expression()->id(), NOT_CONTEXTUAL);
   } else {
     VisitForValue(expr->expression());
     operand = environment()->Pop();
@@ -1650,7 +1707,8 @@ Node* AstGraphBuilder::BuildArgumentsObject(Variable* arguments) {
 
   // Assign the object to the arguments variable.
   DCHECK(arguments->IsContextSlot() || arguments->IsStackAllocated());
-  BuildVariableAssignment(arguments, object, Token::ASSIGN);
+  // This should never lazy deopt, so it is fine to send invalid bailout id.
+  BuildVariableAssignment(arguments, object, Token::ASSIGN, BailoutId::None());
 
   return object;
 }
@@ -1687,6 +1745,7 @@ Node* AstGraphBuilder::BuildHoleCheckThrow(Node* value, Variable* variable,
 
 
 Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
+                                         BailoutId bailout_id,
                                          ContextualMode contextual_mode) {
   Node* the_hole = jsgraph()->TheHoleConstant();
   VariableMode mode = variable->mode();
@@ -1696,7 +1755,9 @@ Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
       Node* global = BuildLoadGlobalObject();
       PrintableUnique<Name> name = MakeUnique(variable->name());
       Operator* op = javascript()->LoadNamed(name, contextual_mode);
-      return NewNode(op, global);
+      Node* node = NewNode(op, global);
+      BuildLazyBailoutWithPushedNode(node, bailout_id);
+      return node;
     }
     case Variable::PARAMETER:
     case Variable::LOCAL: {
@@ -1785,7 +1846,8 @@ Node* AstGraphBuilder::BuildVariableDelete(Variable* variable) {
 
 
 Node* AstGraphBuilder::BuildVariableAssignment(Variable* variable, Node* value,
-                                               Token::Value op) {
+                                               Token::Value op,
+                                               BailoutId bailout_id) {
   Node* the_hole = jsgraph()->TheHoleConstant();
   VariableMode mode = variable->mode();
   switch (variable->location()) {
@@ -1794,7 +1856,9 @@ Node* AstGraphBuilder::BuildVariableAssignment(Variable* variable, Node* value,
       Node* global = BuildLoadGlobalObject();
       PrintableUnique<Name> name = MakeUnique(variable->name());
       Operator* op = javascript()->StoreNamed(name);
-      return NewNode(op, global, value);
+      Node* store = NewNode(op, global, value);
+      BuildLazyBailout(store, bailout_id);
+      return store;
     }
     case Variable::PARAMETER:
     case Variable::LOCAL:
@@ -1958,6 +2022,10 @@ void AstGraphBuilder::BuildLazyBailout(Node* node, BailoutId ast_id) {
 
     NewNode(common()->LazyDeoptimization());
 
+    // TODO(jarin) If ast_id.IsNone(), perhaps we should generate an empty
+    // deopt block and make sure there is no patch entry for this (so
+    // that the deoptimizer dies when trying to deoptimize here).
+
     Node* state_node = environment()->Checkpoint(ast_id);
 
     Node* deoptimize_node = NewNode(common()->Deoptimize(), state_node);
@@ -1970,6 +2038,14 @@ void AstGraphBuilder::BuildLazyBailout(Node* node, BailoutId ast_id) {
     NewNode(common()->Continuation());
   }
 }
+
+
+void AstGraphBuilder::BuildLazyBailoutWithPushedNode(Node* node,
+                                                     BailoutId ast_id) {
+  environment()->Push(node);
+  BuildLazyBailout(node, ast_id);
+  environment()->Pop();
+}
 }
 }
 }  // namespace v8::internal::compiler
index 950529a..861bd5b 100644 (file)
@@ -78,9 +78,11 @@ class AstGraphBuilder : public StructuredGraphBuilder, public AstVisitor {
   Node* BuildArgumentsObject(Variable* arguments);
 
   // Builders for variable load and assignment.
-  Node* BuildVariableAssignment(Variable* var, Node* value, Token::Value op);
+  Node* BuildVariableAssignment(Variable* var, Node* value, Token::Value op,
+                                BailoutId bailout_id);
   Node* BuildVariableDelete(Variable* var);
-  Node* BuildVariableLoad(Variable* var, ContextualMode mode = CONTEXTUAL);
+  Node* BuildVariableLoad(Variable* var, BailoutId bailout_id,
+                          ContextualMode mode = CONTEXTUAL);
 
   // Builders for accessing the function context.
   Node* BuildLoadBuiltinsObject();
@@ -170,6 +172,7 @@ class AstGraphBuilder : public StructuredGraphBuilder, public AstVisitor {
   void VisitForInAssignment(Expression* expr, Node* value);
 
   void BuildLazyBailout(Node* node, BailoutId ast_id);
+  void BuildLazyBailoutWithPushedNode(Node* node, BailoutId ast_id);
 
   DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
   DISALLOW_COPY_AND_ASSIGN(AstGraphBuilder);
@@ -282,6 +285,7 @@ class AstGraphBuilder::AstContext BASE_EMBEDDED {
   // Plug a node into this expression context.  Call this function in tail
   // position in the Visit functions for expressions.
   virtual void ProduceValue(Node* value) = 0;
+  virtual void ProduceValueWithLazyBailout(Node* value) = 0;
 
   // Unplugs a node from this expression context.  Call this to retrieve the
   // result of another Visit function that already plugged the context.
@@ -291,7 +295,8 @@ class AstGraphBuilder::AstContext BASE_EMBEDDED {
   void ReplaceValue() { ProduceValue(ConsumeValue()); }
 
  protected:
-  AstContext(AstGraphBuilder* owner, Expression::Context kind);
+  AstContext(AstGraphBuilder* owner, Expression::Context kind,
+             BailoutId bailout_id);
   virtual ~AstContext();
 
   AstGraphBuilder* owner() const { return owner_; }
@@ -303,6 +308,8 @@ class AstGraphBuilder::AstContext BASE_EMBEDDED {
   int original_height_;
 #endif
 
+  BailoutId bailout_id_;
+
  private:
   Expression::Context kind_;
   AstGraphBuilder* owner_;
@@ -313,10 +320,11 @@ class AstGraphBuilder::AstContext BASE_EMBEDDED {
 // Context to evaluate expression for its side effects only.
 class AstGraphBuilder::AstEffectContext V8_FINAL : public AstContext {
  public:
-  explicit AstEffectContext(AstGraphBuilder* owner)
-      : AstContext(owner, Expression::kEffect) {}
+  explicit AstEffectContext(AstGraphBuilder* owner, BailoutId bailout_id)
+      : AstContext(owner, Expression::kEffect, bailout_id) {}
   virtual ~AstEffectContext();
   virtual void ProduceValue(Node* value) V8_OVERRIDE;
+  virtual void ProduceValueWithLazyBailout(Node* value) V8_OVERRIDE;
   virtual Node* ConsumeValue() V8_OVERRIDE;
 };
 
@@ -324,10 +332,11 @@ class AstGraphBuilder::AstEffectContext V8_FINAL : public AstContext {
 // Context to evaluate expression for its value (and side effects).
 class AstGraphBuilder::AstValueContext V8_FINAL : public AstContext {
  public:
-  explicit AstValueContext(AstGraphBuilder* owner)
-      : AstContext(owner, Expression::kValue) {}
+  explicit AstValueContext(AstGraphBuilder* owner, BailoutId bailout_id)
+      : AstContext(owner, Expression::kValue, bailout_id) {}
   virtual ~AstValueContext();
   virtual void ProduceValue(Node* value) V8_OVERRIDE;
+  virtual void ProduceValueWithLazyBailout(Node* value) V8_OVERRIDE;
   virtual Node* ConsumeValue() V8_OVERRIDE;
 };
 
@@ -335,10 +344,11 @@ class AstGraphBuilder::AstValueContext V8_FINAL : public AstContext {
 // Context to evaluate expression for a condition value (and side effects).
 class AstGraphBuilder::AstTestContext V8_FINAL : public AstContext {
  public:
-  explicit AstTestContext(AstGraphBuilder* owner)
-      : AstContext(owner, Expression::kTest) {}
+  explicit AstTestContext(AstGraphBuilder* owner, BailoutId bailout_id)
+      : AstContext(owner, Expression::kTest, bailout_id) {}
   virtual ~AstTestContext();
   virtual void ProduceValue(Node* value) V8_OVERRIDE;
+  virtual void ProduceValueWithLazyBailout(Node* value) V8_OVERRIDE;
   virtual Node* ConsumeValue() V8_OVERRIDE;
 };
 
index 5c831eb..878ace3 100644 (file)
@@ -215,7 +215,9 @@ void CodeGenerator::PopulateDeoptimizationData(Handle<Code> code_object) {
   for (int i = 0; i < deopt_count; i++) {
     FrameStateDescriptor* descriptor = code()->GetDeoptimizationEntry(i);
     data->SetAstId(i, descriptor->bailout_id());
-    data->SetTranslationIndex(i, Smi::FromInt(0));
+    CHECK_NE(NULL, deoptimization_states_[i]);
+    data->SetTranslationIndex(
+        i, Smi::FromInt(deoptimization_states_[i]->translation_id_));
     data->SetArgumentsStackHeight(i, Smi::FromInt(0));
     data->SetPc(i, Smi::FromInt(-1));
   }
index 803d3f6..6ace8be 100644 (file)
@@ -45,9 +45,10 @@ CallDescriptor* Linkage::GetRuntimeCallDescriptor(
 
 
 CallDescriptor* Linkage::GetStubCallDescriptor(
-    CodeStubInterfaceDescriptor* descriptor, int stack_parameter_count) {
+    CodeStubInterfaceDescriptor* descriptor, int stack_parameter_count,
+    CallDescriptor::DeoptimizationSupport can_deoptimize, Zone* zone) {
   return LinkageHelper::GetStubCallDescriptor<LinkageHelperTraits>(
-      this->info_->zone(), descriptor, stack_parameter_count);
+      zone, descriptor, stack_parameter_count, can_deoptimize);
 }
 
 
index 699f7dd..68cc1ce 100644 (file)
@@ -292,6 +292,14 @@ REPLACE_UNIMPLEMENTED(JSDebugger)
 #undef REPLACE_UNIMPLEMENTED
 
 
+static CallDescriptor::DeoptimizationSupport DeoptimizationSupportForNode(
+    Node* node) {
+  return OperatorProperties::CanLazilyDeoptimize(node->op())
+             ? CallDescriptor::kCanDeoptimize
+             : CallDescriptor::kCannotDeoptimize;
+}
+
+
 void JSGenericLowering::ReplaceWithCompareIC(Node* node, Token::Value token,
                                              bool pure) {
   BinaryOpICStub stub(isolate(), Token::ADD);  // TODO(mstarzinger): Hack.
@@ -324,7 +332,8 @@ void JSGenericLowering::ReplaceWithCompareIC(Node* node, Token::Value token,
 void JSGenericLowering::ReplaceWithICStubCall(Node* node,
                                               HydrogenCodeStub* stub) {
   CodeStubInterfaceDescriptor* d = stub->GetInterfaceDescriptor();
-  CallDescriptor* desc = linkage()->GetStubCallDescriptor(d);
+  CallDescriptor* desc = linkage()->GetStubCallDescriptor(
+      d, 0, DeoptimizationSupportForNode(node));
   Node* stub_code = CodeConstant(stub->GetCode());
   PatchInsertInput(node, 0, stub_code);
   PatchOperator(node, common()->Call(desc));
@@ -355,12 +364,8 @@ void JSGenericLowering::ReplaceWithRuntimeCall(Node* node,
   Operator::Property props = node->op()->properties();
   const Runtime::Function* fun = Runtime::FunctionForId(f);
   int nargs = (nargs_override < 0) ? fun->nargs : nargs_override;
-  CallDescriptor::DeoptimizationSupport deopt =
-      OperatorProperties::CanLazilyDeoptimize(node->op())
-          ? CallDescriptor::kCanDeoptimize
-          : CallDescriptor::kCannotDeoptimize;
-  CallDescriptor* desc =
-      linkage()->GetRuntimeCallDescriptor(f, nargs, props, deopt);
+  CallDescriptor* desc = linkage()->GetRuntimeCallDescriptor(
+      f, nargs, props, DeoptimizationSupportForNode(node));
   Node* ref = ExternalConstant(ExternalReference(f, isolate()));
   Node* arity = Int32Constant(nargs);
   if (!centrystub_constant_.is_set()) {
@@ -508,7 +513,8 @@ Node* JSGenericLowering::LowerJSCallConstruct(Node* node) {
   int arity = OpParameter<int>(node);
   CallConstructStub stub(isolate(), NO_CALL_CONSTRUCTOR_FLAGS);
   CodeStubInterfaceDescriptor* d = GetInterfaceDescriptor(isolate(), &stub);
-  CallDescriptor* desc = linkage()->GetStubCallDescriptor(d, arity);
+  CallDescriptor* desc = linkage()->GetStubCallDescriptor(
+      d, arity, DeoptimizationSupportForNode(node));
   Node* stub_code = CodeConstant(stub.GetCode());
   Node* construct = NodeProperties::GetValueInput(node, 0);
   PatchInsertInput(node, 0, stub_code);
@@ -524,7 +530,8 @@ Node* JSGenericLowering::LowerJSCallFunction(Node* node) {
   CallParameters p = OpParameter<CallParameters>(node);
   CallFunctionStub stub(isolate(), p.arity - 2, p.flags);
   CodeStubInterfaceDescriptor* d = GetInterfaceDescriptor(isolate(), &stub);
-  CallDescriptor* desc = linkage()->GetStubCallDescriptor(d, p.arity - 1);
+  CallDescriptor* desc = linkage()->GetStubCallDescriptor(
+      d, p.arity - 1, DeoptimizationSupportForNode(node));
   Node* stub_code = CodeConstant(stub.GetCode());
   PatchInsertInput(node, 0, stub_code);
   PatchOperator(node, common()->Call(desc));
index d32eb5a..fd9547d 100644 (file)
@@ -5,6 +5,7 @@
 #ifndef V8_COMPILER_JS_OPERATOR_H_
 #define V8_COMPILER_JS_OPERATOR_H_
 
+#include "src/compiler/linkage.h"
 #include "src/compiler/opcodes.h"
 #include "src/compiler/operator.h"
 #include "src/unique.h"
index 212a622..36939cc 100644 (file)
@@ -128,7 +128,8 @@ class LinkageHelper {
   template <typename LinkageTraits>
   static CallDescriptor* GetStubCallDescriptor(
       Zone* zone, CodeStubInterfaceDescriptor* descriptor,
-      int stack_parameter_count) {
+      int stack_parameter_count,
+      CallDescriptor::DeoptimizationSupport can_deoptimize) {
     int register_parameter_count = descriptor->GetEnvironmentParameterCount();
     int parameter_count = register_parameter_count + stack_parameter_count;
     const int code_count = 1;
@@ -165,9 +166,8 @@ class LinkageHelper {
                        locations,                        // locations
                        Operator::kNoProperties,          // properties
                        kNoCalleeSaved,  // callee-saved registers
-                       CallDescriptor::kCannotDeoptimize,  // deoptimization
+                       can_deoptimize,  // deoptimization
                        CodeStub::MajorName(descriptor->MajorKey(), false));
-    // TODO(jarin) should deoptimize!
   }
 
 
index 466f65c..7c3a9fb 100644 (file)
@@ -102,6 +102,14 @@ CallDescriptor* Linkage::GetRuntimeCallDescriptor(
 }
 
 
+CallDescriptor* Linkage::GetStubCallDescriptor(
+    CodeStubInterfaceDescriptor* descriptor, int stack_parameter_count,
+    CallDescriptor::DeoptimizationSupport can_deoptimize) {
+  return GetStubCallDescriptor(descriptor, stack_parameter_count,
+                               can_deoptimize, this->info_->zone());
+}
+
+
 //==============================================================================
 // Provide unimplemented methods on unsupported architectures, to at least link.
 //==============================================================================
@@ -122,7 +130,8 @@ CallDescriptor* Linkage::GetRuntimeCallDescriptor(
 
 
 CallDescriptor* Linkage::GetStubCallDescriptor(
-    CodeStubInterfaceDescriptor* descriptor, int stack_parameter_count) {
+    CodeStubInterfaceDescriptor* descriptor, int stack_parameter_count,
+    CallDescriptor::DeoptimizationSupport can_deoptimize, Zone* zone) {
   UNIMPLEMENTED();
   return NULL;
 }
index 310a87a..7b19303 100644 (file)
@@ -147,8 +147,13 @@ class Linkage : public ZoneObject {
       Operator::Property properties,
       CallDescriptor::DeoptimizationSupport can_deoptimize, Zone* zone);
 
-  CallDescriptor* GetStubCallDescriptor(CodeStubInterfaceDescriptor* descriptor,
-                                        int stack_parameter_count = 0);
+  CallDescriptor* GetStubCallDescriptor(
+      CodeStubInterfaceDescriptor* descriptor, int stack_parameter_count = 0,
+      CallDescriptor::DeoptimizationSupport can_deoptimize =
+          CallDescriptor::kCannotDeoptimize);
+  static CallDescriptor* GetStubCallDescriptor(
+      CodeStubInterfaceDescriptor* descriptor, int stack_parameter_count,
+      CallDescriptor::DeoptimizationSupport can_deoptimize, Zone* zone);
 
   // Creates a call descriptor for simplified C calls that is appropriate
   // for the host platform. This simplified calling convention only supports
index fc9149d..42833fd 100644 (file)
@@ -7,6 +7,7 @@
 
 #include "src/v8.h"
 
+#include "src/compiler/js-operator.h"
 #include "src/compiler/opcodes.h"
 #include "src/compiler/operator-properties.h"
 
@@ -59,6 +60,10 @@ inline int OperatorProperties::GetControlInputCount(Operator* op) {
 #undef OPCODE_CASE
       return static_cast<ControlOperator*>(op)->ControlInputCount();
     default:
+      // If a node can lazily deoptimize, it needs control dependency.
+      if (CanLazilyDeoptimize(op)) {
+        return 1;
+      }
       // Operators that have write effects must have a control
       // dependency. Effect dependencies only ensure the correct order of
       // write/read operations without consideration of control flow. Without an
@@ -130,17 +135,52 @@ inline bool OperatorProperties::IsScheduleRoot(Operator* op) {
 }
 
 inline bool OperatorProperties::CanLazilyDeoptimize(Operator* op) {
-  if (op->opcode() == IrOpcode::kCall) {
-    CallOperator* call_op = reinterpret_cast<CallOperator*>(op);
-    CallDescriptor* descriptor = call_op->parameter();
-    return descriptor->CanLazilyDeoptimize();
+  // TODO(jarin) This function allows turning on lazy deoptimization
+  // incrementally. It will change as we turn on lazy deopt for
+  // more nodes.
+
+  if (!FLAG_turbo_deoptimization) {
+    return false;
   }
-  if (op->opcode() == IrOpcode::kJSCallRuntime) {
-    // TODO(jarin) At the moment, we only support lazy deoptimization for
-    // the %DeoptimizeFunction runtime function.
-    Runtime::FunctionId function =
-        reinterpret_cast<Operator1<Runtime::FunctionId>*>(op)->parameter();
-    return function == Runtime::kDeoptimizeFunction;
+
+  switch (op->opcode()) {
+    case IrOpcode::kCall: {
+      CallOperator* call_op = reinterpret_cast<CallOperator*>(op);
+      CallDescriptor* descriptor = call_op->parameter();
+      return descriptor->CanLazilyDeoptimize();
+    }
+    case IrOpcode::kJSCallRuntime: {
+      Runtime::FunctionId function =
+          reinterpret_cast<Operator1<Runtime::FunctionId>*>(op)->parameter();
+      // TODO(jarin) At the moment, we only support lazy deoptimization for
+      // the %DeoptimizeFunction runtime function.
+      return function == Runtime::kDeoptimizeFunction;
+    }
+
+    // JS function calls
+    case IrOpcode::kJSCallFunction:
+    case IrOpcode::kJSCallConstruct:
+
+    // Binary operations
+    case IrOpcode::kJSBitwiseOr:
+    case IrOpcode::kJSBitwiseXor:
+    case IrOpcode::kJSBitwiseAnd:
+    case IrOpcode::kJSShiftLeft:
+    case IrOpcode::kJSShiftRight:
+    case IrOpcode::kJSShiftRightLogical:
+    case IrOpcode::kJSAdd:
+    case IrOpcode::kJSSubtract:
+    case IrOpcode::kJSMultiply:
+    case IrOpcode::kJSDivide:
+    case IrOpcode::kJSModulus:
+    case IrOpcode::kJSLoadProperty:
+    case IrOpcode::kJSStoreProperty:
+    case IrOpcode::kJSLoadNamed:
+    case IrOpcode::kJSStoreNamed:
+      return true;
+
+    default:
+      return false;
   }
   return false;
 }
index 46446aa..972a904 100644 (file)
@@ -744,6 +744,70 @@ void RegisterAllocator::MeetRegisterConstraints(BasicBlock* block) {
       if (!AllocationOk()) return;
     }
   }
+
+  // Meet register constraints for the instruction in the end.
+  if (!code()->IsGapAt(end)) {
+    MeetRegisterConstraintsForLastInstructionInBlock(block);
+  }
+}
+
+
+void RegisterAllocator::MeetRegisterConstraintsForLastInstructionInBlock(
+    BasicBlock* block) {
+  int end = block->last_instruction_index();
+  Instruction* last_instruction = InstructionAt(end);
+  for (size_t i = 0; i < last_instruction->OutputCount(); i++) {
+    InstructionOperand* output_operand = last_instruction->OutputAt(i);
+    DCHECK(!output_operand->IsConstant());
+    UnallocatedOperand* output = UnallocatedOperand::cast(output_operand);
+    int output_vreg = output->virtual_register();
+    LiveRange* range = LiveRangeFor(output_vreg);
+    bool assigned = false;
+    if (output->HasFixedPolicy()) {
+      AllocateFixed(output, -1, false);
+      // This value is produced on the stack, we never need to spill it.
+      if (output->IsStackSlot()) {
+        range->SetSpillOperand(output);
+        range->SetSpillStartIndex(end);
+        assigned = true;
+      }
+
+      BasicBlock::Successors successors = block->successors();
+      for (BasicBlock::Successors::iterator succ = successors.begin();
+           succ != successors.end(); ++succ) {
+        DCHECK((*succ)->PredecessorCount() == 1);
+        int gap_index = (*succ)->first_instruction_index() + 1;
+        DCHECK(code()->IsGapAt(gap_index));
+
+        // Create an unconstrained operand for the same virtual register
+        // and insert a gap move from the fixed output to the operand.
+        UnallocatedOperand* output_copy =
+            new (code_zone()) UnallocatedOperand(UnallocatedOperand::ANY);
+        output_copy->set_virtual_register(output_vreg);
+
+        code()->AddGapMove(gap_index, output, output_copy);
+      }
+    }
+
+    if (!assigned) {
+      BasicBlock::Successors successors = block->successors();
+      for (BasicBlock::Successors::iterator succ = successors.begin();
+           succ != successors.end(); ++succ) {
+        DCHECK((*succ)->PredecessorCount() == 1);
+        int gap_index = (*succ)->first_instruction_index() + 1;
+        range->SetSpillStartIndex(gap_index);
+
+        // This move to spill operand is not a real use. Liveness analysis
+        // and splitting of live ranges do not account for it.
+        // Thus it should be inserted to a lifetime position corresponding to
+        // the instruction end.
+        GapInstruction* gap = code()->GapAt(gap_index);
+        ParallelMove* move =
+            gap->GetOrCreateParallelMove(GapInstruction::BEFORE, code_zone());
+        move->AddMove(output, range->GetSpillOperand(), code_zone());
+      }
+    }
+  }
 }
 
 
@@ -786,6 +850,8 @@ void RegisterAllocator::MeetConstraintsBetween(Instruction* first,
           code()->AddGapMove(gap_index, first_output, output_copy);
         }
 
+        // Make sure we add a gap move for spilling (if we have not done
+        // so already).
         if (!assigned) {
           range->SetSpillStartIndex(gap_index);
 
index 8a99e6f..881ce37 100644 (file)
@@ -391,6 +391,7 @@ class RegisterAllocator BASE_EMBEDDED {
   void MeetRegisterConstraints(BasicBlock* block);
   void MeetConstraintsBetween(Instruction* first, Instruction* second,
                               int gap_index);
+  void MeetRegisterConstraintsForLastInstructionInBlock(BasicBlock* block);
   void ResolvePhis(BasicBlock* block);
 
   // Helper methods for building intervals.
index 30808e0..9c8b9d0 100644 (file)
@@ -64,9 +64,10 @@ CallDescriptor* Linkage::GetRuntimeCallDescriptor(
 
 
 CallDescriptor* Linkage::GetStubCallDescriptor(
-    CodeStubInterfaceDescriptor* descriptor, int stack_parameter_count) {
+    CodeStubInterfaceDescriptor* descriptor, int stack_parameter_count,
+    CallDescriptor::DeoptimizationSupport can_deoptimize, Zone* zone) {
   return LinkageHelper::GetStubCallDescriptor<LinkageHelperTraits>(
-      this->info_->zone(), descriptor, stack_parameter_count);
+      zone, descriptor, stack_parameter_count, can_deoptimize);
 }
 
 
index b7fe058..1df7df8 100644 (file)
@@ -447,8 +447,11 @@ static int FindPatchAddressForReturnAddress(Code* code, int pc) {
   int patch_count = input_data->ReturnAddressPatchCount();
   for (int i = 0; i < patch_count; i++) {
     int return_pc = input_data->ReturnAddressPc(i)->value();
-    if (pc == return_pc) {
-      return input_data->PatchedAddressPc(i)->value();
+    int patch_pc = input_data->PatchedAddressPc(i)->value();
+    // If the supplied pc matches the return pc or if the address
+    // has been already patched, return the patch pc.
+    if (pc == return_pc || pc == patch_pc) {
+      return patch_pc;
     }
   }
   return -1;
index 645bb4a..a0c2c1e 100644 (file)
@@ -10726,7 +10726,26 @@ int Code::SourceStatementPosition(Address pc) {
 
 SafepointEntry Code::GetSafepointEntry(Address pc) {
   SafepointTable table(this);
-  return table.FindEntry(pc);
+  SafepointEntry entry = table.FindEntry(pc);
+  if (entry.is_valid() || !is_turbofanned()) {
+    return entry;
+  }
+
+  // If the code is turbofanned, we might be looking for
+  // an address that was patched by lazy deoptimization.
+  // In that case look through the patch table, try to
+  // lookup the original address there, and then use this
+  // to find the safepoint entry.
+  DeoptimizationInputData* deopt_data =
+      DeoptimizationInputData::cast(deoptimization_data());
+  intptr_t offset = pc - instruction_start();
+  for (int i = 0; i < deopt_data->ReturnAddressPatchCount(); i++) {
+    if (deopt_data->PatchedAddressPc(i)->value() == offset) {
+      int original_offset = deopt_data->ReturnAddressPc(i)->value();
+      return table.FindEntry(instruction_start() + original_offset);
+    }
+  }
+  return SafepointEntry();
 }
 
 
@@ -11128,7 +11147,7 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint(
   os << "Deoptimization Input Data (deopt points = " << deopt_count << ")\n";
   if (0 != deopt_count) {
     os << " index  ast id    argc     pc";
-    if (FLAG_print_code_verbose) os << "commands";
+    if (FLAG_print_code_verbose) os << "  commands";
     os << "\n";
   }
   for (int i = 0; i < deopt_count; i++) {
@@ -11158,7 +11177,7 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint(
            Translation::BEGIN !=
            (opcode = static_cast<Translation::Opcode>(iterator.Next()))) {
       Vector<char> buf2 = Vector<char>::New(128);
-      SNPrintF(buf2, "%24s    %s ", "", Translation::StringFor(opcode));
+      SNPrintF(buf2, "%27s    %s ", "", Translation::StringFor(opcode));
       os << buf2.start();
 
       switch (opcode) {
@@ -11284,11 +11303,11 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint(
   if (return_address_patch_count != 0) {
     os << "Return address patch data (count = " << return_address_patch_count
        << ")\n";
-    os << "index pc    patched_pc\n";
+    os << " index    pc  patched_pc\n";
   }
   for (int i = 0; i < return_address_patch_count; i++) {
     Vector<char> buf = Vector<char>::New(128);
-    SNPrintF(buf, "%6d  %6d  %10d", i, ReturnAddressPc(i)->value(),
+    SNPrintF(buf, "%6d  %6d  %12d\n", i, ReturnAddressPc(i)->value(),
              PatchedAddressPc(i)->value());
     os << buf.start();
   }
index 5661634..60baaca 100644 (file)
   'test-debug/DebugBreakLoop': [PASS, NO_VARIANTS],
 
   # Support for lazy deoptimization is missing.
-  'test-deoptimization/DeoptimizeSimple': [PASS, NO_VARIANTS],
-  'test-deoptimization/DeoptimizeSimpleNested': [PASS, NO_VARIANTS],
-  'test-deoptimization/DeoptimizeSimpleWithArguments': [PASS, NO_VARIANTS],
-  'test-deoptimization/DeoptimizeBinaryOperation*': [PASS, NO_VARIANTS],
   'test-deoptimization/DeoptimizeCompare': [PASS, NO_VARIANTS],
-  'test-deoptimization/DeoptimizeLoadICStoreIC': [PASS, NO_VARIANTS],
-  'test-deoptimization/DeoptimizeLoadICStoreICNested': [PASS, NO_VARIANTS],
 
   # Support for breakpoints requires using LoadICs and StoreICs.
   'test-debug/BreakPointICStore': [PASS, NO_VARIANTS],
index 757f83a..43c8ae6 100644 (file)
@@ -1713,6 +1713,8 @@ static Handle<JSFunction> Compile(const char* source) {
 
 
 TEST(BuildScheduleTrivialLazyDeoptCall) {
+  FLAG_turbo_deoptimization = true;
+
   HandleAndZoneScope scope;
   Isolate* isolate = scope.main_isolate();
   Graph graph(scope.main_zone());
index a663007..3127acc 100644 (file)
@@ -113,6 +113,8 @@ static Handle<JSFunction> GetJSFunction(v8::Handle<v8::Object> obj,
 
 
 TEST(DeoptimizeSimple) {
+  i::FLAG_turbo_deoptimization = true;
+
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
 
@@ -151,6 +153,8 @@ TEST(DeoptimizeSimple) {
 
 
 TEST(DeoptimizeSimpleWithArguments) {
+  i::FLAG_turbo_deoptimization = true;
+
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
 
@@ -190,6 +194,8 @@ TEST(DeoptimizeSimpleWithArguments) {
 
 
 TEST(DeoptimizeSimpleNested) {
+  i::FLAG_turbo_deoptimization = true;
+
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
 
@@ -215,6 +221,7 @@ TEST(DeoptimizeSimpleNested) {
 
 
 TEST(DeoptimizeRecursive) {
+  i::FLAG_turbo_deoptimization = true;
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
 
@@ -242,6 +249,7 @@ TEST(DeoptimizeRecursive) {
 
 
 TEST(DeoptimizeMultiple) {
+  i::FLAG_turbo_deoptimization = true;
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
 
@@ -270,6 +278,7 @@ TEST(DeoptimizeMultiple) {
 
 
 TEST(DeoptimizeConstructor) {
+  i::FLAG_turbo_deoptimization = true;
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
 
@@ -308,6 +317,7 @@ TEST(DeoptimizeConstructor) {
 
 
 TEST(DeoptimizeConstructorMultiple) {
+  i::FLAG_turbo_deoptimization = true;
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
 
@@ -337,6 +347,7 @@ TEST(DeoptimizeConstructorMultiple) {
 
 
 TEST(DeoptimizeBinaryOperationADDString) {
+  i::FLAG_turbo_deoptimization = true;
   i::FLAG_concurrent_recompilation = false;
   AllowNativesSyntaxNoInlining options;
   LocalContext env;
@@ -428,6 +439,7 @@ static void TestDeoptimizeBinaryOpHelper(LocalContext* env,
 
 
 TEST(DeoptimizeBinaryOperationADD) {
+  i::FLAG_turbo_deoptimization = true;
   i::FLAG_concurrent_recompilation = false;
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
@@ -441,6 +453,7 @@ TEST(DeoptimizeBinaryOperationADD) {
 
 
 TEST(DeoptimizeBinaryOperationSUB) {
+  i::FLAG_turbo_deoptimization = true;
   i::FLAG_concurrent_recompilation = false;
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
@@ -454,6 +467,7 @@ TEST(DeoptimizeBinaryOperationSUB) {
 
 
 TEST(DeoptimizeBinaryOperationMUL) {
+  i::FLAG_turbo_deoptimization = true;
   i::FLAG_concurrent_recompilation = false;
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
@@ -467,6 +481,7 @@ TEST(DeoptimizeBinaryOperationMUL) {
 
 
 TEST(DeoptimizeBinaryOperationDIV) {
+  i::FLAG_turbo_deoptimization = true;
   i::FLAG_concurrent_recompilation = false;
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
@@ -480,6 +495,7 @@ TEST(DeoptimizeBinaryOperationDIV) {
 
 
 TEST(DeoptimizeBinaryOperationMOD) {
+  i::FLAG_turbo_deoptimization = true;
   i::FLAG_concurrent_recompilation = false;
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
@@ -493,6 +509,7 @@ TEST(DeoptimizeBinaryOperationMOD) {
 
 
 TEST(DeoptimizeCompare) {
+  i::FLAG_turbo_deoptimization = true;
   i::FLAG_concurrent_recompilation = false;
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
@@ -537,6 +554,7 @@ TEST(DeoptimizeCompare) {
 
 
 TEST(DeoptimizeLoadICStoreIC) {
+  i::FLAG_turbo_deoptimization = true;
   i::FLAG_concurrent_recompilation = false;
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
@@ -617,6 +635,7 @@ TEST(DeoptimizeLoadICStoreIC) {
 
 
 TEST(DeoptimizeLoadICStoreICNested) {
+  i::FLAG_turbo_deoptimization = true;
   i::FLAG_concurrent_recompilation = false;
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());