[es6] Add a flag to the Isolate that defines whether ES2015 tail call elimination is enabled or not.

Thus DevTools will be able to disable tail call elimination dynamically upon user's choice.

BUG=v8:4698
LOG=N

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

Cr-Commit-Position: refs/heads/master@{#35098}
This commit is contained in:
ishell 2016-03-29 04:43:46 -07:00 committed by Commit bot
parent e7cc6091f5
commit 7a33bd5da4
14 changed files with 120 additions and 0 deletions

View File

@ -1933,6 +1933,16 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3));
Comment cmnt(masm, "[ PrepareForTailCall");
// Prepare for tail call only if ES2015 tail call elimination is enabled.
Label done;
ExternalReference is_tail_call_elimination_enabled =
ExternalReference::is_tail_call_elimination_enabled_address(
masm->isolate());
__ mov(scratch1, Operand(is_tail_call_elimination_enabled));
__ ldrb(scratch1, MemOperand(scratch1));
__ cmp(scratch1, Operand(0));
__ b(eq, &done);
// Drop possible interpreter handler/stub frame.
{
Label no_interpreter_frame;
@ -1976,6 +1986,7 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
ParameterCount callee_args_count(args_reg);
__ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2,
scratch3);
__ bind(&done);
}
} // namespace

View File

@ -1977,6 +1977,16 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3));
Comment cmnt(masm, "[ PrepareForTailCall");
// Prepare for tail call only if ES2015 tail call elimination is enabled.
Label done;
ExternalReference is_tail_call_elimination_enabled =
ExternalReference::is_tail_call_elimination_enabled_address(
masm->isolate());
__ Mov(scratch1, Operand(is_tail_call_elimination_enabled));
__ Ldrb(scratch1, MemOperand(scratch1));
__ Cmp(scratch1, Operand(0));
__ B(eq, &done);
// Drop possible interpreter handler/stub frame.
{
Label no_interpreter_frame;
@ -2017,6 +2027,7 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
ParameterCount callee_args_count(args_reg);
__ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2,
scratch3);
__ bind(&done);
}
} // namespace

View File

@ -1632,6 +1632,10 @@ ExternalReference ExternalReference::cpu_features() {
return ExternalReference(&CpuFeatures::supported_);
}
ExternalReference ExternalReference::is_tail_call_elimination_enabled_address(
Isolate* isolate) {
return ExternalReference(isolate->is_tail_call_elimination_enabled_address());
}
ExternalReference ExternalReference::debug_is_active_address(
Isolate* isolate) {

View File

@ -1029,6 +1029,9 @@ class ExternalReference BASE_EMBEDDED {
static ExternalReference cpu_features();
static ExternalReference is_tail_call_elimination_enabled_address(
Isolate* isolate);
static ExternalReference debug_is_active_address(Isolate* isolate);
static ExternalReference debug_after_break_target_address(Isolate* isolate);

View File

@ -172,6 +172,9 @@ ExternalReferenceTable::ExternalReferenceTable(Isolate* isolate) {
"Isolate::virtual_slot_register()");
Add(ExternalReference::runtime_function_table_address(isolate).address(),
"Runtime::runtime_function_table_address()");
Add(ExternalReference::is_tail_call_elimination_enabled_address(isolate)
.address(),
"Isolate::is_tail_call_elimination_enabled_address()");
// Debug addresses
Add(ExternalReference::debug_after_break_target_address(isolate).address(),

View File

@ -1886,6 +1886,16 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3));
Comment cmnt(masm, "[ PrepareForTailCall");
// Prepare for tail call only if ES2015 tail call elimination is enabled.
Label done;
ExternalReference is_tail_call_elimination_enabled =
ExternalReference::is_tail_call_elimination_enabled_address(
masm->isolate());
__ movzx_b(scratch1,
Operand::StaticVariable(is_tail_call_elimination_enabled));
__ cmp(scratch1, Immediate(0));
__ j(equal, &done, Label::kNear);
// Drop possible interpreter handler/stub frame.
{
Label no_interpreter_frame;
@ -1926,6 +1936,7 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
ParameterCount callee_args_count(args_reg);
__ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2,
scratch3, ReturnAddressState::kOnStack, 0);
__ bind(&done);
}
} // namespace

View File

@ -1826,6 +1826,7 @@ Isolate::Isolate(bool enable_serializer)
serializer_enabled_(enable_serializer),
has_fatal_error_(false),
initialized_from_snapshot_(false),
is_tail_call_elimination_enabled_(true),
cpu_profiler_(NULL),
heap_profiler_(NULL),
function_entry_hook_(NULL),

View File

@ -1089,6 +1089,16 @@ class Isolate {
int GetNextUniqueSharedFunctionInfoId() { return next_unique_sfi_id_++; }
#endif
// Support for dynamically disabling tail call elimination.
Address is_tail_call_elimination_enabled_address() {
return reinterpret_cast<Address>(&is_tail_call_elimination_enabled_);
}
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 AddDetachedContext(Handle<Context> context);
void CheckDetachedContextsAfterGC();
@ -1277,6 +1287,9 @@ class Isolate {
// True if this isolate was initialized from a snapshot.
bool initialized_from_snapshot_;
// True if ES2015 tail call elimination feature is enabled.
bool is_tail_call_elimination_enabled_;
// Time stamp at initialization.
double time_millis_at_init_;

View File

@ -1957,6 +1957,15 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3));
Comment cmnt(masm, "[ PrepareForTailCall");
// Prepare for tail call only if ES2015 tail call elimination is enabled.
Label done;
ExternalReference is_tail_call_elimination_enabled =
ExternalReference::is_tail_call_elimination_enabled_address(
masm->isolate());
__ li(at, Operand(is_tail_call_elimination_enabled));
__ lb(scratch1, MemOperand(at));
__ Branch(&done, eq, scratch1, Operand(zero_reg));
// Drop possible interpreter handler/stub frame.
{
Label no_interpreter_frame;
@ -2000,6 +2009,7 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
ParameterCount callee_args_count(args_reg);
__ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2,
scratch3);
__ bind(&done);
}
} // namespace

View File

@ -1948,6 +1948,15 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3));
Comment cmnt(masm, "[ PrepareForTailCall");
// Prepare for tail call only if ES2015 tail call elimination is enabled.
Label done;
ExternalReference is_tail_call_elimination_enabled =
ExternalReference::is_tail_call_elimination_enabled_address(
masm->isolate());
__ li(at, Operand(is_tail_call_elimination_enabled));
__ lb(scratch1, MemOperand(at));
__ Branch(&done, eq, scratch1, Operand(zero_reg));
// Drop possible interpreter handler/stub frame.
{
Label no_interpreter_frame;
@ -1990,6 +1999,7 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
ParameterCount callee_args_count(args_reg);
__ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2,
scratch3);
__ bind(&done);
}
} // namespace

View File

@ -1987,6 +1987,16 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3));
Comment cmnt(masm, "[ PrepareForTailCall");
// Prepare for tail call only if ES2015 tail call elimination is enabled.
Label done;
ExternalReference is_tail_call_elimination_enabled =
ExternalReference::is_tail_call_elimination_enabled_address(
masm->isolate());
__ mov(scratch1, Operand(is_tail_call_elimination_enabled));
__ lbz(scratch1, MemOperand(scratch1));
__ cmpi(scratch1, Operand::Zero());
__ beq(&done);
// Drop possible interpreter handler/stub frame.
{
Label no_interpreter_frame;
@ -2034,6 +2044,7 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
ParameterCount callee_args_count(args_reg);
__ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2,
scratch3);
__ bind(&done);
}
} // namespace

View File

@ -1949,6 +1949,16 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3));
Comment cmnt(masm, "[ PrepareForTailCall");
// Prepare for tail call only if ES2015 tail call elimination is active.
Label done;
ExternalReference is_tail_call_elimination_enabled =
ExternalReference::is_tail_call_elimination_enabled_address(
masm->isolate());
__ mov(scratch1, Operand(is_tail_call_elimination_enabled));
__ LoadlB(scratch1, MemOperand(scratch1));
__ CmpP(scratch1, Operand::Zero());
__ beq(&done);
// Drop possible interpreter handler/stub frame.
{
Label no_interpreter_frame;
@ -1995,6 +2005,7 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
ParameterCount callee_args_count(args_reg);
__ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2,
scratch3);
__ bind(&done);
}
} // namespace

View File

@ -2052,6 +2052,15 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3));
Comment cmnt(masm, "[ PrepareForTailCall");
// Prepare for tail call only if ES2015 tail call elimination is active.
Label done;
ExternalReference is_tail_call_elimination_enabled =
ExternalReference::is_tail_call_elimination_enabled_address(
masm->isolate());
__ Move(kScratchRegister, is_tail_call_elimination_enabled);
__ cmpb(Operand(kScratchRegister, 0), Immediate(0));
__ j(equal, &done);
// Drop possible interpreter handler/stub frame.
{
Label no_interpreter_frame;
@ -2091,6 +2100,7 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
ParameterCount callee_args_count(args_reg);
__ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2,
scratch3, ReturnAddressState::kOnStack);
__ bind(&done);
}
} // namespace

View File

@ -1912,6 +1912,16 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3));
Comment cmnt(masm, "[ PrepareForTailCall");
// Prepare for tail call only if ES2015 tail call elimination is enabled.
Label done;
ExternalReference is_tail_call_elimination_enabled =
ExternalReference::is_tail_call_elimination_enabled_address(
masm->isolate());
__ movzx_b(scratch1,
Operand::StaticVariable(is_tail_call_elimination_enabled));
__ cmp(scratch1, Immediate(0));
__ j(equal, &done, Label::kNear);
// Drop possible interpreter handler/stub frame.
{
Label no_interpreter_frame;
@ -1952,6 +1962,7 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
ParameterCount callee_args_count(args_reg);
__ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2,
scratch3, ReturnAddressState::kOnStack, 0);
__ bind(&done);
}
} // namespace