Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(138)

Unified Diff: src/deoptimizer.cc

Issue 1768263004: [turbofan] [deoptimizer] Support inlining of ES6 tail calls. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Addressing comments, StandardFrameConstants -> CommonFrameConstants Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/deoptimizer.h ('k') | src/ia32/deoptimizer-ia32.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/deoptimizer.cc
diff --git a/src/deoptimizer.cc b/src/deoptimizer.cc
index 2ddf1e4f85619d58c03eed0de62685a92f1cf82b..cc865a93b49866a139f2a5adb425fbda0f880fcb 100644
--- a/src/deoptimizer.cc
+++ b/src/deoptimizer.cc
@@ -711,16 +711,38 @@ void Deoptimizer::DoComputeOutputFrames() {
DeoptimizationInputData* input_data =
DeoptimizationInputData::cast(compiled_code_->deoptimization_data());
+ {
+ // Read caller's PC, caller's FP and caller's constant pool values
+ // from input frame. Compute caller's frame top address.
+
+ Register fp_reg = JavaScriptFrame::fp_register();
+ stack_fp_ = input_->GetRegister(fp_reg.code());
+
+ caller_frame_top_ = stack_fp_ + ComputeInputFrameAboveFpFixedSize();
+
+ Address fp_address = input_->GetFramePointerAddress();
+ caller_fp_ = Memory::intptr_at(fp_address);
+ caller_pc_ =
+ Memory::intptr_at(fp_address + CommonFrameConstants::kCallerPCOffset);
+ input_frame_context_ = Memory::intptr_at(
+ fp_address + CommonFrameConstants::kContextOrFrameTypeOffset);
+
+ if (FLAG_enable_embedded_constant_pool) {
+ caller_constant_pool_ = Memory::intptr_at(
+ fp_address + CommonFrameConstants::kConstantPoolOffset);
+ }
+ }
+
if (trace_scope_ != NULL) {
timer.Start();
PrintF(trace_scope_->file(), "[deoptimizing (DEOPT %s): begin ",
MessageFor(bailout_type_));
PrintFunctionName();
PrintF(trace_scope_->file(),
- " (opt #%d) @%d, FP to SP delta: %d]\n",
- input_data->OptimizationId()->value(),
- bailout_id_,
- fp_to_sp_delta_);
+ " (opt #%d) @%d, FP to SP delta: %d, caller sp: 0x%08" V8PRIxPTR
+ "]\n",
+ input_data->OptimizationId()->value(), bailout_id_, fp_to_sp_delta_,
+ caller_frame_top_);
if (bailout_type_ == EAGER || bailout_type_ == SOFT ||
(compiled_code_->is_hydrogen_stub())) {
compiled_code_->PrintDeoptLocation(trace_scope_->file(), from_);
@@ -763,56 +785,42 @@ void Deoptimizer::DoComputeOutputFrames() {
}
output_count_ = static_cast<int>(count);
- {
- // Read caller's PC, caller's FP and caller's constant pool values
- // from input frame. Compute caller's frame top address.
-
- Register fp_reg = JavaScriptFrame::fp_register();
- stack_fp_ = input_->GetRegister(fp_reg.code());
-
- caller_frame_top_ = stack_fp_ + ComputeInputFrameAboveFpFixedSize();
-
- Address fp_address = input_->GetFramePointerAddress();
- caller_fp_ = Memory::intptr_at(fp_address);
- caller_pc_ =
- Memory::intptr_at(fp_address + StandardFrameConstants::kCallerPCOffset);
- input_frame_context_ =
- Memory::intptr_at(fp_address + StandardFrameConstants::kContextOffset);
-
- if (FLAG_enable_embedded_constant_pool) {
- caller_constant_pool_ = Memory::intptr_at(
- fp_address + StandardFrameConstants::kConstantPoolOffset);
- }
- }
-
// Translate each output frame.
- for (size_t i = 0; i < count; ++i) {
+ int frame_index = 0; // output_frame_index
+ for (size_t i = 0; i < count; ++i, ++frame_index) {
// Read the ast node id, function, and frame height for this output frame.
- int frame_index = static_cast<int>(i);
- switch (translated_state_.frames()[i].kind()) {
+ TranslatedFrame* translated_frame = &(translated_state_.frames()[i]);
+ switch (translated_frame->kind()) {
case TranslatedFrame::kFunction:
- DoComputeJSFrame(frame_index, deoptimizing_throw_ && i == count - 1);
+ DoComputeJSFrame(translated_frame, frame_index,
+ deoptimizing_throw_ && i == count - 1);
jsframe_count_++;
break;
case TranslatedFrame::kInterpretedFunction:
- DoComputeInterpretedFrame(frame_index,
+ DoComputeInterpretedFrame(translated_frame, frame_index,
deoptimizing_throw_ && i == count - 1);
jsframe_count_++;
break;
case TranslatedFrame::kArgumentsAdaptor:
- DoComputeArgumentsAdaptorFrame(frame_index);
+ DoComputeArgumentsAdaptorFrame(translated_frame, frame_index);
+ break;
+ case TranslatedFrame::kTailCallerFunction:
+ DoComputeTailCallerFrame(translated_frame, frame_index);
+ // Tail caller frame translations do not produce output frames.
+ frame_index--;
+ output_count_--;
break;
case TranslatedFrame::kConstructStub:
- DoComputeConstructStubFrame(frame_index);
+ DoComputeConstructStubFrame(translated_frame, frame_index);
break;
case TranslatedFrame::kGetter:
- DoComputeAccessorStubFrame(frame_index, false);
+ DoComputeAccessorStubFrame(translated_frame, frame_index, false);
break;
case TranslatedFrame::kSetter:
- DoComputeAccessorStubFrame(frame_index, true);
+ DoComputeAccessorStubFrame(translated_frame, frame_index, true);
break;
case TranslatedFrame::kCompiledStub:
- DoComputeCompiledStubFrame(frame_index);
+ DoComputeCompiledStubFrame(translated_frame, frame_index);
break;
case TranslatedFrame::kInvalid:
FATAL("invalid frame");
@@ -827,19 +835,19 @@ void Deoptimizer::DoComputeOutputFrames() {
PrintF(trace_scope_->file(), "[deoptimizing (%s): end ",
MessageFor(bailout_type_));
PrintFunctionName();
- PrintF(
- trace_scope_->file(),
- " @%d => node=%d, pc=0x%08" V8PRIxPTR ", state=%s, took %0.3f ms]\n",
- bailout_id_, node_id.ToInt(), output_[index]->GetPc(),
- FullCodeGenerator::State2String(static_cast<FullCodeGenerator::State>(
- output_[index]->GetState()->value())),
- ms);
+ PrintF(trace_scope_->file(),
+ " @%d => node=%d, pc=0x%08" V8PRIxPTR ", caller sp=0x%08" V8PRIxPTR
+ ", state=%s, took %0.3f ms]\n",
+ bailout_id_, node_id.ToInt(), output_[index]->GetPc(),
+ caller_frame_top_, FullCodeGenerator::State2String(
+ static_cast<FullCodeGenerator::State>(
+ output_[index]->GetState()->value())),
+ ms);
}
}
-void Deoptimizer::DoComputeJSFrame(int frame_index, bool goto_catch_handler) {
- TranslatedFrame* translated_frame =
- &(translated_state_.frames()[frame_index]);
+void Deoptimizer::DoComputeJSFrame(TranslatedFrame* translated_frame,
+ int frame_index, bool goto_catch_handler) {
SharedFunctionInfo* shared = translated_frame->raw_shared_info();
TranslatedFrame::iterator value_iterator = translated_frame->begin();
@@ -866,8 +874,6 @@ void Deoptimizer::DoComputeJSFrame(int frame_index, bool goto_catch_handler) {
PrintF(trace_scope_->file(), " translating frame ");
base::SmartArrayPointer<char> name = shared->DebugName()->ToCString();
PrintF(trace_scope_->file(), "%s", name.get());
- PrintF(trace_scope_->file(),
- " => node=%d, height=%d\n", node_id.ToInt(), height_in_bytes);
PrintF(trace_scope_->file(), " => node=%d, height=%d%s\n", node_id.ToInt(),
height_in_bytes, goto_catch_handler ? " (throw)" : "");
}
@@ -1001,9 +1007,6 @@ void Deoptimizer::DoComputeJSFrame(int frame_index, bool goto_catch_handler) {
// The function was mentioned explicitly in the BEGIN_FRAME.
output_offset -= kPointerSize;
value = reinterpret_cast<intptr_t>(function);
- // The function for the bottommost output frame should also agree with the
- // input frame.
- DCHECK(!is_bottommost || reinterpret_cast<intptr_t>(function_) == value);
WriteValueToOutput(function, 0, frame_index, output_offset, "function ");
// Translate the rest of the frame.
@@ -1070,10 +1073,9 @@ void Deoptimizer::DoComputeJSFrame(int frame_index, bool goto_catch_handler) {
}
}
-void Deoptimizer::DoComputeInterpretedFrame(int frame_index,
+void Deoptimizer::DoComputeInterpretedFrame(TranslatedFrame* translated_frame,
+ int frame_index,
bool goto_catch_handler) {
- TranslatedFrame* translated_frame =
- &(translated_state_.frames()[frame_index]);
SharedFunctionInfo* shared = translated_frame->raw_shared_info();
TranslatedFrame::iterator value_iterator = translated_frame->begin();
@@ -1219,9 +1221,6 @@ void Deoptimizer::DoComputeInterpretedFrame(int frame_index,
// The function was mentioned explicitly in the BEGIN_FRAME.
output_offset -= kPointerSize;
value = reinterpret_cast<intptr_t>(function);
- // The function for the bottommost output frame should also agree with the
- // input frame.
- DCHECK(!is_bottommost || reinterpret_cast<intptr_t>(function_) == value);
WriteValueToOutput(function, 0, frame_index, output_offset, "function ");
// The new.target slot is only used during function activiation which is
@@ -1305,11 +1304,10 @@ void Deoptimizer::DoComputeInterpretedFrame(int frame_index,
}
}
-
-void Deoptimizer::DoComputeArgumentsAdaptorFrame(int frame_index) {
- TranslatedFrame* translated_frame =
- &(translated_state_.frames()[frame_index]);
+void Deoptimizer::DoComputeArgumentsAdaptorFrame(
+ TranslatedFrame* translated_frame, int frame_index) {
TranslatedFrame::iterator value_iterator = translated_frame->begin();
+ bool is_bottommost = (0 == frame_index);
int input_index = 0;
unsigned height = translated_frame->height();
@@ -1331,15 +1329,19 @@ void Deoptimizer::DoComputeArgumentsAdaptorFrame(int frame_index) {
FrameDescription(output_frame_size, parameter_count);
output_frame->SetFrameType(StackFrame::ARGUMENTS_ADAPTOR);
- // Arguments adaptor can not be topmost or bottommost.
- CHECK(frame_index > 0 && frame_index < output_count_ - 1);
+ // Arguments adaptor can not be topmost.
+ CHECK(frame_index < output_count_ - 1);
CHECK(output_[frame_index] == NULL);
output_[frame_index] = output_frame;
// The top address of the frame is computed from the previous
// frame's top and this frame's size.
intptr_t top_address;
- top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
+ if (is_bottommost) {
+ top_address = caller_frame_top_ - output_frame_size;
+ } else {
+ top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
+ }
output_frame->SetTop(top_address);
// Compute the incoming parameter translation.
@@ -1352,13 +1354,22 @@ void Deoptimizer::DoComputeArgumentsAdaptorFrame(int frame_index) {
// Read caller's PC from the previous frame.
output_offset -= kPCOnStackSize;
- intptr_t callers_pc = output_[frame_index - 1]->GetPc();
- output_frame->SetCallerPc(output_offset, callers_pc);
- DebugPrintOutputSlot(callers_pc, frame_index, output_offset, "caller's pc\n");
+ intptr_t value;
+ if (is_bottommost) {
+ value = caller_pc_;
+ } else {
+ value = output_[frame_index - 1]->GetPc();
+ }
+ output_frame->SetCallerPc(output_offset, value);
+ DebugPrintOutputSlot(value, frame_index, output_offset, "caller's pc\n");
// Read caller's FP from the previous frame, and set this frame's FP.
output_offset -= kFPOnStackSize;
- intptr_t value = output_[frame_index - 1]->GetFp();
+ if (is_bottommost) {
+ value = caller_fp_;
+ } else {
+ value = output_[frame_index - 1]->GetFp();
+ }
output_frame->SetCallerFp(output_offset, value);
intptr_t fp_value = top_address + output_offset;
output_frame->SetFp(fp_value);
@@ -1411,10 +1422,73 @@ void Deoptimizer::DoComputeArgumentsAdaptorFrame(int frame_index) {
}
}
+void Deoptimizer::DoComputeTailCallerFrame(TranslatedFrame* translated_frame,
+ int frame_index) {
+ SharedFunctionInfo* shared = translated_frame->raw_shared_info();
-void Deoptimizer::DoComputeConstructStubFrame(int frame_index) {
- TranslatedFrame* translated_frame =
- &(translated_state_.frames()[frame_index]);
+ bool is_bottommost = (0 == frame_index);
+ // Tail caller frame can't be topmost.
+ DCHECK_NE(output_count_ - 1, frame_index);
+
+ if (trace_scope_ != NULL) {
+ PrintF(trace_scope_->file(), " translating tail caller frame ");
+ base::SmartArrayPointer<char> name = shared->DebugName()->ToCString();
+ PrintF(trace_scope_->file(), "%s\n", name.get());
+ }
+
+ if (!is_bottommost) return;
+
+ // Drop arguments adaptor frame below current frame if it exsits.
+ Address fp_address = input_->GetFramePointerAddress();
+ Address adaptor_fp_address =
+ Memory::Address_at(fp_address + CommonFrameConstants::kCallerFPOffset);
+
+ if (Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR) !=
+ Memory::Object_at(adaptor_fp_address +
+ CommonFrameConstants::kContextOrFrameTypeOffset)) {
+ return;
+ }
+
+ int caller_params_count =
+ Smi::cast(
+ Memory::Object_at(adaptor_fp_address +
+ ArgumentsAdaptorFrameConstants::kLengthOffset))
+ ->value();
+
+ int callee_params_count =
+ function_->shared()->internal_formal_parameter_count();
+
+ // Both caller and callee parameters count do not include receiver.
+ int offset = (caller_params_count - callee_params_count) * kPointerSize;
+ intptr_t new_stack_fp =
+ reinterpret_cast<intptr_t>(adaptor_fp_address) + offset;
+
+ intptr_t new_caller_frame_top = new_stack_fp +
+ (callee_params_count + 1) * kPointerSize +
+ CommonFrameConstants::kFixedFrameSizeAboveFp;
+
+ intptr_t adaptor_caller_pc = Memory::intptr_at(
+ adaptor_fp_address + CommonFrameConstants::kCallerPCOffset);
+ intptr_t adaptor_caller_fp = Memory::intptr_at(
+ adaptor_fp_address + CommonFrameConstants::kCallerFPOffset);
+
+ if (trace_scope_ != NULL) {
+ PrintF(trace_scope_->file(),
+ " dropping caller arguments adaptor frame: offset=%d, "
+ "fp: 0x%08" V8PRIxPTR " -> 0x%08" V8PRIxPTR
+ ", "
+ "caller sp: 0x%08" V8PRIxPTR " -> 0x%08" V8PRIxPTR "\n",
+ offset, stack_fp_, new_stack_fp, caller_frame_top_,
+ new_caller_frame_top);
+ }
+ stack_fp_ = new_stack_fp;
+ caller_frame_top_ = new_caller_frame_top;
+ caller_fp_ = adaptor_caller_fp;
+ caller_pc_ = adaptor_caller_pc;
+}
+
+void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
+ int frame_index) {
TranslatedFrame::iterator value_iterator = translated_frame->begin();
int input_index = 0;
@@ -1534,11 +1608,9 @@ void Deoptimizer::DoComputeConstructStubFrame(int frame_index) {
}
}
-
-void Deoptimizer::DoComputeAccessorStubFrame(int frame_index,
+void Deoptimizer::DoComputeAccessorStubFrame(TranslatedFrame* translated_frame,
+ int frame_index,
bool is_setter_stub_frame) {
- TranslatedFrame* translated_frame =
- &(translated_state_.frames()[frame_index]);
TranslatedFrame::iterator value_iterator = translated_frame->begin();
int input_index = 0;
@@ -1659,8 +1731,8 @@ void Deoptimizer::DoComputeAccessorStubFrame(int frame_index,
}
}
-
-void Deoptimizer::DoComputeCompiledStubFrame(int frame_index) {
+void Deoptimizer::DoComputeCompiledStubFrame(TranslatedFrame* translated_frame,
+ int frame_index) {
//
// FROM TO
// | .... | | .... |
@@ -1696,8 +1768,6 @@ void Deoptimizer::DoComputeCompiledStubFrame(int frame_index) {
// and then, if the descriptor specifies a constant number of stack
// parameters, the stack parameters as well.
- TranslatedFrame* translated_frame =
- &(translated_state_.frames()[frame_index]);
TranslatedFrame::iterator value_iterator = translated_frame->begin();
int input_index = 0;
@@ -1738,8 +1808,7 @@ void Deoptimizer::DoComputeCompiledStubFrame(int frame_index) {
// context and function slots.
Register fp_reg = StubFailureTrampolineFrame::fp_register();
intptr_t top_address =
- stack_fp_ - // input_->GetRegister(fp_reg.code()) -
- StubFailureTrampolineFrameConstants::kFixedFrameSizeFromFp -
+ stack_fp_ - StubFailureTrampolineFrameConstants::kFixedFrameSizeFromFp -
height_in_bytes;
output_frame->SetTop(top_address);
@@ -1990,15 +2059,15 @@ unsigned Deoptimizer::ComputeInputFrameAboveFpFixedSize() const {
unsigned Deoptimizer::ComputeInputFrameSize() const {
// The fp-to-sp delta already takes the context, constant pool pointer and the
// function into account so we have to avoid double counting them.
- unsigned fixed_size_from_fp = ComputeInputFrameAboveFpFixedSize();
- unsigned result = fixed_size_from_fp + fp_to_sp_delta_;
+ unsigned fixed_size_above_fp = ComputeInputFrameAboveFpFixedSize();
+ unsigned result = fixed_size_above_fp + fp_to_sp_delta_;
if (compiled_code_->kind() == Code::OPTIMIZED_FUNCTION) {
unsigned stack_slots = compiled_code_->stack_slots();
unsigned outgoing_size =
ComputeOutgoingArgumentSize(compiled_code_, bailout_id_);
- CHECK(result ==
- fixed_size_from_fp + (stack_slots * kPointerSize) -
- CommonFrameConstants::kFixedFrameSizeAboveFp + outgoing_size);
+ CHECK_EQ(fixed_size_above_fp + (stack_slots * kPointerSize) -
+ CommonFrameConstants::kFixedFrameSizeAboveFp + outgoing_size,
+ result);
}
return result;
}
@@ -2196,6 +2265,10 @@ void Translation::BeginArgumentsAdaptorFrame(int literal_id, unsigned height) {
buffer_->Add(height, zone());
}
+void Translation::BeginTailCallerFrame(int literal_id) {
+ buffer_->Add(TAIL_CALLER_FRAME, zone());
+ buffer_->Add(literal_id, zone());
+}
void Translation::BeginJSFrame(BailoutId node_id,
int literal_id,
@@ -2341,6 +2414,7 @@ int Translation::NumberOfOperandsFor(Opcode opcode) {
case DOUBLE_STACK_SLOT:
case LITERAL:
case COMPILED_STUB_FRAME:
+ case TAIL_CALLER_FRAME:
return 1;
case BEGIN:
case ARGUMENTS_ADAPTOR_FRAME:
@@ -2900,6 +2974,11 @@ TranslatedFrame TranslatedFrame::ArgumentsAdaptorFrame(
shared_info, height);
}
+TranslatedFrame TranslatedFrame::TailCallerFrame(
+ SharedFunctionInfo* shared_info) {
+ return TranslatedFrame(kTailCallerFunction, shared_info->GetIsolate(),
+ shared_info, 0);
+}
TranslatedFrame TranslatedFrame::ConstructStubFrame(
SharedFunctionInfo* shared_info, int height) {
@@ -2934,6 +3013,9 @@ int TranslatedFrame::GetValueCount() {
case kConstructStub:
return 1 + height_;
+ case kTailCallerFunction:
+ return 1; // Function.
+
case kCompiledStub:
return height_;
@@ -3010,6 +3092,18 @@ TranslatedFrame TranslatedState::CreateNextTranslatedFrame(
return TranslatedFrame::ArgumentsAdaptorFrame(shared_info, height);
}
+ case Translation::TAIL_CALLER_FRAME: {
+ SharedFunctionInfo* shared_info =
+ SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
+ if (trace_file != nullptr) {
+ base::SmartArrayPointer<char> name =
+ shared_info->DebugName()->ToCString();
+ PrintF(trace_file, " reading tail caller frame marker %s\n",
+ name.get());
+ }
+ return TranslatedFrame::TailCallerFrame(shared_info);
+ }
+
case Translation::CONSTRUCT_STUB_FRAME: {
SharedFunctionInfo* shared_info =
SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
@@ -3110,6 +3204,7 @@ TranslatedValue TranslatedState::CreateNextTranslatedValue(
case Translation::JS_FRAME:
case Translation::INTERPRETED_FRAME:
case Translation::ARGUMENTS_ADAPTOR_FRAME:
+ case Translation::TAIL_CALLER_FRAME:
case Translation::CONSTRUCT_STUB_FRAME:
case Translation::GETTER_STUB_FRAME:
case Translation::SETTER_STUB_FRAME:
« no previous file with comments | « src/deoptimizer.h ('k') | src/ia32/deoptimizer-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698