Commit 7a33bd5d authored by ishell's avatar ishell Committed by Commit bot

[es6] Add a flag to the Isolate that defines whether ES2015 tail call...

[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}
parent e7cc6091
...@@ -1933,6 +1933,16 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg, ...@@ -1933,6 +1933,16 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3)); DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3));
Comment cmnt(masm, "[ PrepareForTailCall"); 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. // Drop possible interpreter handler/stub frame.
{ {
Label no_interpreter_frame; Label no_interpreter_frame;
...@@ -1976,6 +1986,7 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg, ...@@ -1976,6 +1986,7 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
ParameterCount callee_args_count(args_reg); ParameterCount callee_args_count(args_reg);
__ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2, __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2,
scratch3); scratch3);
__ bind(&done);
} }
} // namespace } // namespace
......
...@@ -1977,6 +1977,16 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg, ...@@ -1977,6 +1977,16 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3)); DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3));
Comment cmnt(masm, "[ PrepareForTailCall"); 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. // Drop possible interpreter handler/stub frame.
{ {
Label no_interpreter_frame; Label no_interpreter_frame;
...@@ -2017,6 +2027,7 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg, ...@@ -2017,6 +2027,7 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
ParameterCount callee_args_count(args_reg); ParameterCount callee_args_count(args_reg);
__ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2, __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2,
scratch3); scratch3);
__ bind(&done);
} }
} // namespace } // namespace
......
...@@ -1632,6 +1632,10 @@ ExternalReference ExternalReference::cpu_features() { ...@@ -1632,6 +1632,10 @@ ExternalReference ExternalReference::cpu_features() {
return ExternalReference(&CpuFeatures::supported_); 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( ExternalReference ExternalReference::debug_is_active_address(
Isolate* isolate) { Isolate* isolate) {
......
...@@ -1029,6 +1029,9 @@ class ExternalReference BASE_EMBEDDED { ...@@ -1029,6 +1029,9 @@ class ExternalReference BASE_EMBEDDED {
static ExternalReference cpu_features(); 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_is_active_address(Isolate* isolate);
static ExternalReference debug_after_break_target_address(Isolate* isolate); static ExternalReference debug_after_break_target_address(Isolate* isolate);
......
...@@ -172,6 +172,9 @@ ExternalReferenceTable::ExternalReferenceTable(Isolate* isolate) { ...@@ -172,6 +172,9 @@ ExternalReferenceTable::ExternalReferenceTable(Isolate* isolate) {
"Isolate::virtual_slot_register()"); "Isolate::virtual_slot_register()");
Add(ExternalReference::runtime_function_table_address(isolate).address(), Add(ExternalReference::runtime_function_table_address(isolate).address(),
"Runtime::runtime_function_table_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 // Debug addresses
Add(ExternalReference::debug_after_break_target_address(isolate).address(), Add(ExternalReference::debug_after_break_target_address(isolate).address(),
......
...@@ -1886,6 +1886,16 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg, ...@@ -1886,6 +1886,16 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3)); DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3));
Comment cmnt(masm, "[ PrepareForTailCall"); 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. // Drop possible interpreter handler/stub frame.
{ {
Label no_interpreter_frame; Label no_interpreter_frame;
...@@ -1926,6 +1936,7 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg, ...@@ -1926,6 +1936,7 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
ParameterCount callee_args_count(args_reg); ParameterCount callee_args_count(args_reg);
__ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2, __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2,
scratch3, ReturnAddressState::kOnStack, 0); scratch3, ReturnAddressState::kOnStack, 0);
__ bind(&done);
} }
} // namespace } // namespace
......
...@@ -1826,6 +1826,7 @@ Isolate::Isolate(bool enable_serializer) ...@@ -1826,6 +1826,7 @@ Isolate::Isolate(bool enable_serializer)
serializer_enabled_(enable_serializer), serializer_enabled_(enable_serializer),
has_fatal_error_(false), has_fatal_error_(false),
initialized_from_snapshot_(false), initialized_from_snapshot_(false),
is_tail_call_elimination_enabled_(true),
cpu_profiler_(NULL), cpu_profiler_(NULL),
heap_profiler_(NULL), heap_profiler_(NULL),
function_entry_hook_(NULL), function_entry_hook_(NULL),
......
...@@ -1089,6 +1089,16 @@ class Isolate { ...@@ -1089,6 +1089,16 @@ class Isolate {
int GetNextUniqueSharedFunctionInfoId() { return next_unique_sfi_id_++; } int GetNextUniqueSharedFunctionInfoId() { return next_unique_sfi_id_++; }
#endif #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 AddDetachedContext(Handle<Context> context);
void CheckDetachedContextsAfterGC(); void CheckDetachedContextsAfterGC();
...@@ -1277,6 +1287,9 @@ class Isolate { ...@@ -1277,6 +1287,9 @@ class Isolate {
// True if this isolate was initialized from a snapshot. // True if this isolate was initialized from a snapshot.
bool initialized_from_snapshot_; bool initialized_from_snapshot_;
// True if ES2015 tail call elimination feature is enabled.
bool is_tail_call_elimination_enabled_;
// Time stamp at initialization. // Time stamp at initialization.
double time_millis_at_init_; double time_millis_at_init_;
......
...@@ -1957,6 +1957,15 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg, ...@@ -1957,6 +1957,15 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3)); DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3));
Comment cmnt(masm, "[ PrepareForTailCall"); 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. // Drop possible interpreter handler/stub frame.
{ {
Label no_interpreter_frame; Label no_interpreter_frame;
...@@ -2000,6 +2009,7 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg, ...@@ -2000,6 +2009,7 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
ParameterCount callee_args_count(args_reg); ParameterCount callee_args_count(args_reg);
__ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2, __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2,
scratch3); scratch3);
__ bind(&done);
} }
} // namespace } // namespace
......
...@@ -1948,6 +1948,15 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg, ...@@ -1948,6 +1948,15 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3)); DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3));
Comment cmnt(masm, "[ PrepareForTailCall"); 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. // Drop possible interpreter handler/stub frame.
{ {
Label no_interpreter_frame; Label no_interpreter_frame;
...@@ -1990,6 +1999,7 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg, ...@@ -1990,6 +1999,7 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
ParameterCount callee_args_count(args_reg); ParameterCount callee_args_count(args_reg);
__ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2, __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2,
scratch3); scratch3);
__ bind(&done);
} }
} // namespace } // namespace
......
...@@ -1987,6 +1987,16 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg, ...@@ -1987,6 +1987,16 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3)); DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3));
Comment cmnt(masm, "[ PrepareForTailCall"); 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. // Drop possible interpreter handler/stub frame.
{ {
Label no_interpreter_frame; Label no_interpreter_frame;
...@@ -2034,6 +2044,7 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg, ...@@ -2034,6 +2044,7 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
ParameterCount callee_args_count(args_reg); ParameterCount callee_args_count(args_reg);
__ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2, __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2,
scratch3); scratch3);
__ bind(&done);
} }
} // namespace } // namespace
......
...@@ -1949,6 +1949,16 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg, ...@@ -1949,6 +1949,16 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3)); DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3));
Comment cmnt(masm, "[ PrepareForTailCall"); 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. // Drop possible interpreter handler/stub frame.
{ {
Label no_interpreter_frame; Label no_interpreter_frame;
...@@ -1995,6 +2005,7 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg, ...@@ -1995,6 +2005,7 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
ParameterCount callee_args_count(args_reg); ParameterCount callee_args_count(args_reg);
__ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2, __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2,
scratch3); scratch3);
__ bind(&done);
} }
} // namespace } // namespace
......
...@@ -2052,6 +2052,15 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg, ...@@ -2052,6 +2052,15 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3)); DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3));
Comment cmnt(masm, "[ PrepareForTailCall"); 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. // Drop possible interpreter handler/stub frame.
{ {
Label no_interpreter_frame; Label no_interpreter_frame;
...@@ -2091,6 +2100,7 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg, ...@@ -2091,6 +2100,7 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
ParameterCount callee_args_count(args_reg); ParameterCount callee_args_count(args_reg);
__ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2, __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2,
scratch3, ReturnAddressState::kOnStack); scratch3, ReturnAddressState::kOnStack);
__ bind(&done);
} }
} // namespace } // namespace
......
...@@ -1912,6 +1912,16 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg, ...@@ -1912,6 +1912,16 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3)); DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3));
Comment cmnt(masm, "[ PrepareForTailCall"); 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. // Drop possible interpreter handler/stub frame.
{ {
Label no_interpreter_frame; Label no_interpreter_frame;
...@@ -1952,6 +1962,7 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg, ...@@ -1952,6 +1962,7 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
ParameterCount callee_args_count(args_reg); ParameterCount callee_args_count(args_reg);
__ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2, __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2,
scratch3, ReturnAddressState::kOnStack, 0); scratch3, ReturnAddressState::kOnStack, 0);
__ bind(&done);
} }
} // namespace } // namespace
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment