[api] Add a switch that controls if ES2015 tail call elimination feature is enabled or not.
BUG=v8:4698 LOG=N TBR=rossberg@chromium.org Review URL: https://codereview.chromium.org/1842763002 Cr-Commit-Position: refs/heads/master@{#35132}
This commit is contained in:
parent
40bdbef975
commit
037f7f6215
@ -276,6 +276,14 @@ class V8_EXPORT Debug {
|
||||
*/
|
||||
static MaybeLocal<Array> GetInternalProperties(Isolate* isolate,
|
||||
Local<Value> value);
|
||||
|
||||
/**
|
||||
* Defines if the ES2015 tail call elimination feature is enabled or not.
|
||||
* The change of this flag triggers deoptimization of all functions that
|
||||
* contain calls at tail position.
|
||||
*/
|
||||
static bool IsTailCallEliminationEnabled(Isolate* isolate);
|
||||
static void SetTailCallEliminationEnabled(Isolate* isolate, bool enabled);
|
||||
};
|
||||
|
||||
|
||||
|
@ -8089,6 +8089,15 @@ void Debug::SetLiveEditEnabled(Isolate* isolate, bool enable) {
|
||||
internal_isolate->debug()->set_live_edit_enabled(enable);
|
||||
}
|
||||
|
||||
bool Debug::IsTailCallEliminationEnabled(Isolate* isolate) {
|
||||
i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
|
||||
return internal_isolate->is_tail_call_elimination_enabled();
|
||||
}
|
||||
|
||||
void Debug::SetTailCallEliminationEnabled(Isolate* isolate, bool enabled) {
|
||||
i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
|
||||
internal_isolate->SetTailCallEliminationEnabled(enabled);
|
||||
}
|
||||
|
||||
MaybeLocal<Array> Debug::GetInternalProperties(Isolate* v8_isolate,
|
||||
Local<Value> value) {
|
||||
|
@ -927,7 +927,13 @@ void BytecodeGraphBuilder::BuildCall(TailCallMode tail_call_mode) {
|
||||
|
||||
void BytecodeGraphBuilder::VisitCall() { BuildCall(TailCallMode::kDisallow); }
|
||||
|
||||
void BytecodeGraphBuilder::VisitTailCall() { BuildCall(TailCallMode::kAllow); }
|
||||
void BytecodeGraphBuilder::VisitTailCall() {
|
||||
TailCallMode tail_call_mode =
|
||||
bytecode_array_->GetIsolate()->is_tail_call_elimination_enabled()
|
||||
? TailCallMode::kAllow
|
||||
: TailCallMode::kDisallow;
|
||||
BuildCall(tail_call_mode);
|
||||
}
|
||||
|
||||
void BytecodeGraphBuilder::VisitCallJSRuntime() {
|
||||
FrameStateBeforeAndAfter states(this);
|
||||
|
@ -2885,6 +2885,14 @@ std::string Isolate::GetTurboCfgFileName() {
|
||||
}
|
||||
}
|
||||
|
||||
void Isolate::SetTailCallEliminationEnabled(bool enabled) {
|
||||
if (is_tail_call_elimination_enabled_ == enabled) return;
|
||||
is_tail_call_elimination_enabled_ = enabled;
|
||||
// TODO(ishell): Introduce DependencyGroup::kTailCallChangedGroup to
|
||||
// deoptimize only those functions that are affected by the change of this
|
||||
// flag.
|
||||
internal::Deoptimizer::DeoptimizeAll(this);
|
||||
}
|
||||
|
||||
// Heap::detached_contexts tracks detached contexts as pairs
|
||||
// (number of GC since the context was detached, the context).
|
||||
|
@ -1096,9 +1096,7 @@ class Isolate {
|
||||
bool is_tail_call_elimination_enabled() const {
|
||||
return is_tail_call_elimination_enabled_;
|
||||
}
|
||||
void set_tail_call_elimination_enabled(bool enabled) {
|
||||
is_tail_call_elimination_enabled_ = enabled;
|
||||
}
|
||||
void SetTailCallEliminationEnabled(bool enabled);
|
||||
|
||||
void AddDetachedContext(Handle<Context> context);
|
||||
void CheckDetachedContextsAfterGC();
|
||||
|
@ -784,7 +784,8 @@ Parser::Parser(ParseInfo* info)
|
||||
DCHECK(!info->script().is_null() || info->source_stream() != NULL);
|
||||
set_allow_lazy(info->allow_lazy_parsing());
|
||||
set_allow_natives(FLAG_allow_natives_syntax || info->is_native());
|
||||
set_allow_tailcalls(FLAG_harmony_tailcalls && !info->is_native());
|
||||
set_allow_tailcalls(FLAG_harmony_tailcalls && !info->is_native() &&
|
||||
info->isolate()->is_tail_call_elimination_enabled());
|
||||
set_allow_harmony_sloppy(FLAG_harmony_sloppy);
|
||||
set_allow_harmony_sloppy_function(FLAG_harmony_sloppy_function);
|
||||
set_allow_harmony_sloppy_let(FLAG_harmony_sloppy_let);
|
||||
|
@ -8070,3 +8070,60 @@ TEST(BreakLocationIterator) {
|
||||
|
||||
DisableDebugger(isolate);
|
||||
}
|
||||
|
||||
TEST(DisableTailCallElimination) {
|
||||
i::FLAG_allow_natives_syntax = true;
|
||||
i::FLAG_harmony_tailcalls = true;
|
||||
// TODO(ishell, 4698): Investigate why TurboFan in --always-opt mode makes
|
||||
// stack[2].getFunctionName() return null.
|
||||
i::FLAG_turbo_inlining = false;
|
||||
|
||||
DebugLocalContext env;
|
||||
v8::Isolate* isolate = env->GetIsolate();
|
||||
v8::HandleScope scope(isolate);
|
||||
CHECK(v8::Debug::IsTailCallEliminationEnabled(isolate));
|
||||
|
||||
CompileRun(
|
||||
"'use strict'; \n"
|
||||
"Error.prepareStackTrace = (error,stack) => { \n"
|
||||
" error.strace = stack; \n"
|
||||
" return error.message + \"\\n at \" + stack.join(\"\\n at \"); \n"
|
||||
"} \n"
|
||||
" \n"
|
||||
"function getCaller() { \n"
|
||||
" var e = new Error(); \n"
|
||||
" e.stack; // prepare stack trace \n"
|
||||
" var stack = e.strace; \n"
|
||||
" %GlobalPrint('caller: '); \n"
|
||||
" %GlobalPrint(stack[2].getFunctionName()); \n"
|
||||
" %GlobalPrint('\\n'); \n"
|
||||
" return stack[2].getFunctionName(); \n"
|
||||
"} \n"
|
||||
"function f() { \n"
|
||||
" var caller = getCaller(); \n"
|
||||
" if (caller === 'g') return 1; \n"
|
||||
" if (caller === 'h') return 2; \n"
|
||||
" return 0; \n"
|
||||
"} \n"
|
||||
"function g() { \n"
|
||||
" return f(); \n"
|
||||
"} \n"
|
||||
"function h() { \n"
|
||||
" var result = g(); \n"
|
||||
" return result; \n"
|
||||
"} \n"
|
||||
"%NeverOptimizeFunction(getCaller); \n"
|
||||
"%NeverOptimizeFunction(f); \n"
|
||||
"%NeverOptimizeFunction(h); \n"
|
||||
"");
|
||||
ExpectInt32("h();", 2);
|
||||
ExpectInt32("h(); %OptimizeFunctionOnNextCall(g); h();", 2);
|
||||
v8::Debug::SetTailCallEliminationEnabled(isolate, false);
|
||||
CHECK(!v8::Debug::IsTailCallEliminationEnabled(isolate));
|
||||
ExpectInt32("h();", 1);
|
||||
ExpectInt32("h(); %OptimizeFunctionOnNextCall(g); h();", 1);
|
||||
v8::Debug::SetTailCallEliminationEnabled(isolate, true);
|
||||
CHECK(v8::Debug::IsTailCallEliminationEnabled(isolate));
|
||||
ExpectInt32("h();", 2);
|
||||
ExpectInt32("h(); %OptimizeFunctionOnNextCall(g); h();", 2);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user