From d04a7d6d91a7d02fd28d6c5e8954f527c2d23d6a Mon Sep 17 00:00:00 2001 From: "jarin@chromium.org" Date: Mon, 11 Aug 2014 10:42:01 +0000 Subject: [PATCH] More lazy deoptimization in Turbofan (binops, loads/stores) 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 --- src/compiler/arm/linkage-arm.cc | 5 +- src/compiler/arm64/linkage-arm64.cc | 5 +- src/compiler/ast-graph-builder.cc | 142 +++++++++++++++++++++++++-------- src/compiler/ast-graph-builder.h | 28 ++++--- src/compiler/code-generator.cc | 4 +- src/compiler/ia32/linkage-ia32.cc | 5 +- src/compiler/js-generic-lowering.cc | 25 +++--- src/compiler/js-operator.h | 1 + src/compiler/linkage-impl.h | 6 +- src/compiler/linkage.cc | 11 ++- src/compiler/linkage.h | 9 ++- src/compiler/operator-properties-inl.h | 60 +++++++++++--- src/compiler/register-allocator.cc | 66 +++++++++++++++ src/compiler/register-allocator.h | 1 + src/compiler/x64/linkage-x64.cc | 5 +- src/deoptimizer.cc | 7 +- src/objects.cc | 29 +++++-- test/cctest/cctest.status | 6 -- test/cctest/compiler/test-scheduler.cc | 2 + test/cctest/test-deoptimization.cc | 19 +++++ 20 files changed, 347 insertions(+), 89 deletions(-) diff --git a/src/compiler/arm/linkage-arm.cc b/src/compiler/arm/linkage-arm.cc index 489a0c6..6bea210 100644 --- a/src/compiler/arm/linkage-arm.cc +++ b/src/compiler/arm/linkage-arm.cc @@ -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( - this->info_->zone(), descriptor, stack_parameter_count); + zone, descriptor, stack_parameter_count, can_deoptimize); } diff --git a/src/compiler/arm64/linkage-arm64.cc b/src/compiler/arm64/linkage-arm64.cc index 240cef1..e44c5d8 100644 --- a/src/compiler/arm64/linkage-arm64.cc +++ b/src/compiler/arm64/linkage-arm64.cc @@ -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( - this->info_->zone(), descriptor, stack_parameter_count); + zone, descriptor, stack_parameter_count, can_deoptimize); } diff --git a/src/compiler/ast-graph-builder.cc b/src/compiler/ast-graph-builder.cc index 2c242cb..328156b 100644 --- a/src/compiler/ast-graph-builder.cc +++ b/src/compiler/ast-graph-builder.cc @@ -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* 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 = 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 = 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 = 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 = 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 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 = 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 = 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 = 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 = 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 diff --git a/src/compiler/ast-graph-builder.h b/src/compiler/ast-graph-builder.h index 950529a..861bd5b 100644 --- a/src/compiler/ast-graph-builder.h +++ b/src/compiler/ast-graph-builder.h @@ -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; }; diff --git a/src/compiler/code-generator.cc b/src/compiler/code-generator.cc index 5c831eb..878ace3 100644 --- a/src/compiler/code-generator.cc +++ b/src/compiler/code-generator.cc @@ -215,7 +215,9 @@ void CodeGenerator::PopulateDeoptimizationData(Handle 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)); } diff --git a/src/compiler/ia32/linkage-ia32.cc b/src/compiler/ia32/linkage-ia32.cc index 803d3f6..6ace8be 100644 --- a/src/compiler/ia32/linkage-ia32.cc +++ b/src/compiler/ia32/linkage-ia32.cc @@ -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( - this->info_->zone(), descriptor, stack_parameter_count); + zone, descriptor, stack_parameter_count, can_deoptimize); } diff --git a/src/compiler/js-generic-lowering.cc b/src/compiler/js-generic-lowering.cc index 699f7dd..68cc1ce 100644 --- a/src/compiler/js-generic-lowering.cc +++ b/src/compiler/js-generic-lowering.cc @@ -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(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(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)); diff --git a/src/compiler/js-operator.h b/src/compiler/js-operator.h index d32eb5a..fd9547d 100644 --- a/src/compiler/js-operator.h +++ b/src/compiler/js-operator.h @@ -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" diff --git a/src/compiler/linkage-impl.h b/src/compiler/linkage-impl.h index 212a622..36939cc 100644 --- a/src/compiler/linkage-impl.h +++ b/src/compiler/linkage-impl.h @@ -128,7 +128,8 @@ class LinkageHelper { template 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! } diff --git a/src/compiler/linkage.cc b/src/compiler/linkage.cc index 466f65c..7c3a9fb 100644 --- a/src/compiler/linkage.cc +++ b/src/compiler/linkage.cc @@ -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; } diff --git a/src/compiler/linkage.h b/src/compiler/linkage.h index 310a87a..7b19303 100644 --- a/src/compiler/linkage.h +++ b/src/compiler/linkage.h @@ -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 diff --git a/src/compiler/operator-properties-inl.h b/src/compiler/operator-properties-inl.h index fc9149d..42833fd 100644 --- a/src/compiler/operator-properties-inl.h +++ b/src/compiler/operator-properties-inl.h @@ -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(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(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*>(op)->parameter(); - return function == Runtime::kDeoptimizeFunction; + + switch (op->opcode()) { + case IrOpcode::kCall: { + CallOperator* call_op = reinterpret_cast(op); + CallDescriptor* descriptor = call_op->parameter(); + return descriptor->CanLazilyDeoptimize(); + } + case IrOpcode::kJSCallRuntime: { + Runtime::FunctionId function = + reinterpret_cast*>(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; } diff --git a/src/compiler/register-allocator.cc b/src/compiler/register-allocator.cc index 46446aa..972a904 100644 --- a/src/compiler/register-allocator.cc +++ b/src/compiler/register-allocator.cc @@ -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); diff --git a/src/compiler/register-allocator.h b/src/compiler/register-allocator.h index 8a99e6f..881ce37 100644 --- a/src/compiler/register-allocator.h +++ b/src/compiler/register-allocator.h @@ -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. diff --git a/src/compiler/x64/linkage-x64.cc b/src/compiler/x64/linkage-x64.cc index 30808e0..9c8b9d0 100644 --- a/src/compiler/x64/linkage-x64.cc +++ b/src/compiler/x64/linkage-x64.cc @@ -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( - this->info_->zone(), descriptor, stack_parameter_count); + zone, descriptor, stack_parameter_count, can_deoptimize); } diff --git a/src/deoptimizer.cc b/src/deoptimizer.cc index b7fe058..1df7df8 100644 --- a/src/deoptimizer.cc +++ b/src/deoptimizer.cc @@ -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; diff --git a/src/objects.cc b/src/objects.cc index 645bb4a..a0c2c1e 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -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(iterator.Next()))) { Vector buf2 = Vector::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 buf = Vector::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(); } diff --git a/test/cctest/cctest.status b/test/cctest/cctest.status index 5661634..60baaca 100644 --- a/test/cctest/cctest.status +++ b/test/cctest/cctest.status @@ -107,13 +107,7 @@ '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], diff --git a/test/cctest/compiler/test-scheduler.cc b/test/cctest/compiler/test-scheduler.cc index 757f83a..43c8ae6 100644 --- a/test/cctest/compiler/test-scheduler.cc +++ b/test/cctest/compiler/test-scheduler.cc @@ -1713,6 +1713,8 @@ static Handle Compile(const char* source) { TEST(BuildScheduleTrivialLazyDeoptCall) { + FLAG_turbo_deoptimization = true; + HandleAndZoneScope scope; Isolate* isolate = scope.main_isolate(); Graph graph(scope.main_zone()); diff --git a/test/cctest/test-deoptimization.cc b/test/cctest/test-deoptimization.cc index a663007..3127acc 100644 --- a/test/cctest/test-deoptimization.cc +++ b/test/cctest/test-deoptimization.cc @@ -113,6 +113,8 @@ static Handle GetJSFunction(v8::Handle 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()); -- 2.7.4