[turbofan] Add JSStackCheck into loop bodies.

This allows loopy TurboFan code to be interrupted by placing a stack
check (i.e. JSStackCheck node) into each loop. Note that we currently
limit this to non-asm.js code. Also note that stack checks are actually
placed after loop headers and not at back-branches, which allows us to
reuse existing BailoutIds from Crankshaft.

R=titzer@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#27666}
This commit is contained in:
mstarzinger 2015-04-08 05:54:56 -07:00 committed by Commit bot
parent 87a27e42ea
commit 322cfb3589
5 changed files with 6 additions and 19 deletions

View File

@ -1484,12 +1484,6 @@ MaybeHandle<Code> Compiler::GetOptimizedCode(Handle<JSFunction> function,
return MaybeHandle<Code>();
}
// TODO(titzer): Some top-level code times out because of missing interrupt
// checks at back-branches, these are currently marked with --no-turbo-osr.
if (shared->is_toplevel() && !FLAG_turbo_osr) {
return MaybeHandle<Code>();
}
info->SetOptimizing(osr_ast_id, current_code);
if (mode == CONCURRENT) {

View File

@ -2487,6 +2487,12 @@ void AstGraphBuilder::VisitIfNotNull(Statement* stmt) {
void AstGraphBuilder::VisitIterationBody(IterationStatement* stmt,
LoopBuilder* loop) {
ControlScopeForIteration scope(this, stmt, loop);
// TODO(mstarzinger): For now we only allow to interrupt non-asm.js code,
// which is a gigantic hack and should be extended to all code at some point.
if (!info()->shared_info()->asm_function()) {
Node* node = NewNode(javascript()->StackCheck());
PrepareFrameState(node, stmt->StackCheckId());
}
Visit(stmt->body());
}

View File

@ -20037,7 +20037,6 @@ class RequestInterruptTestWithFunctionCall
isolate_, ShouldContinueCallback, v8::External::New(isolate_, this));
env_->Global()->Set(v8_str("ShouldContinue"), func);
i::FLAG_turbo_osr = false; // TODO(titzer): interrupts in TF loops.
CompileRun("while (ShouldContinue()) { }");
}
};
@ -20053,7 +20052,6 @@ class RequestInterruptTestWithMethodCall
isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
env_->Global()->Set(v8_str("Klass"), t->GetFunction());
i::FLAG_turbo_osr = false; // TODO(titzer): interrupts in TF loops.
CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
}
};
@ -20069,7 +20067,6 @@ class RequestInterruptTestWithAccessor
isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
env_->Global()->Set(v8_str("Klass"), t->GetFunction());
i::FLAG_turbo_osr = false; // TODO(titzer): interrupts in TF loops.
CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
}
};
@ -20087,7 +20084,6 @@ class RequestInterruptTestWithNativeAccessor
v8::External::New(isolate_, this));
env_->Global()->Set(v8_str("Klass"), t->GetFunction());
i::FLAG_turbo_osr = false; // TODO(titzer): interrupts in TF loops.
CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
}
@ -20117,7 +20113,6 @@ class RequestInterruptTestWithMethodCallAndInterceptor
env_->Global()->Set(v8_str("Klass"), t->GetFunction());
i::FLAG_turbo_osr = false; // TODO(titzer): interrupts in TF loops.
CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
}
@ -20142,7 +20137,6 @@ class RequestInterruptTestWithMathAbs
v8::External::New(isolate_, this)));
i::FLAG_allow_natives_syntax = true;
i::FLAG_turbo_osr = false; // TODO(titzer): interrupts in TF loops.
CompileRun("function loopish(o) {"
" var pre = 10;"
" while (o.abs(1) > 0) {"
@ -20226,7 +20220,6 @@ class RequestMultipleInterrupts : public RequestInterruptTestBase {
isolate_, ShouldContinueCallback, v8::External::New(isolate_, this));
env_->Global()->Set(v8_str("ShouldContinue"), func);
i::FLAG_turbo_osr = false; // TODO(titzer): interrupts in TF loops.
CompileRun("while (ShouldContinue()) { }");
}

View File

@ -6697,7 +6697,6 @@ TEST(ProcessDebugMessagesThreaded) {
v8::FunctionTemplate::New(isolate, StartSendingCommands);
env->Global()->Set(v8_str("start"), start->GetFunction());
i::FLAG_turbo_osr = false; // TODO(titzer): interrupts in TF loops.
CompileRun("start(); while (true) { }");
CHECK_EQ(20, counting_message_handler_counter);

View File

@ -152,7 +152,6 @@ TEST(TerminateOnlyV8ThreadFromThreadItselfNoLoop) {
// Run a loop that will be infinite if thread termination does not work.
v8::Handle<v8::String> source = v8::String::NewFromUtf8(
CcTest::isolate(), "try { loop(); fail(); } catch(e) { fail(); }");
i::FLAG_turbo_osr = false; // TODO(titzer): interrupts in TF loops.
v8::Script::Compile(source)->Run();
CHECK(!v8::V8::IsExecutionTerminating(CcTest::isolate()));
// Test that we can run the code again after thread termination.
@ -193,7 +192,6 @@ TEST(TerminateOnlyV8ThreadFromOtherThread) {
// Run a loop that will be infinite if thread termination does not work.
v8::Handle<v8::String> source = v8::String::NewFromUtf8(
CcTest::isolate(), "try { loop(); fail(); } catch(e) { fail(); }");
i::FLAG_turbo_osr = false; // TODO(titzer): interrupts in TF loops.
v8::Script::Compile(source)->Run();
thread.Join();
@ -362,7 +360,6 @@ TEST(TerminateCancelTerminateFromThreadItself) {
CHECK(!v8::V8::IsExecutionTerminating(CcTest::isolate()));
v8::Handle<v8::String> source = v8::String::NewFromUtf8(
isolate, "try { doloop(); } catch(e) { fail(); } 'completed';");
i::FLAG_turbo_osr = false; // TODO(titzer): interrupts in TF loops.
// Check that execution completed with correct return value.
CHECK(v8::Script::Compile(source)->Run()->Equals(v8_str("completed")));
}
@ -379,7 +376,6 @@ void MicrotaskLoopForever(const v8::FunctionCallbackInfo<v8::Value>& info) {
// Enqueue another should-not-run task to ensure we clean out the queue
// when we terminate.
isolate->EnqueueMicrotask(v8::Function::New(isolate, MicrotaskShouldNotRun));
i::FLAG_turbo_osr = false; // TODO(titzer): interrupts in TF loops.
CompileRun("terminate(); while (true) { }");
CHECK(v8::V8::IsExecutionTerminating());
}
@ -509,7 +505,6 @@ TEST(TerminationInInnerTryCall) {
v8::Context::Scope context_scope(context);
{
v8::TryCatch try_catch;
i::FLAG_turbo_osr = false; // TODO(titzer): interrupts in TF loops.
CompileRun("inner_try_call_terminate()");
CHECK(try_catch.HasTerminated());
}