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

Unified Diff: src/deoptimizer.cc

Issue 1936043002: [es6] Properly handle the case when an inlined getter/setter/constructor does a tail call. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Removed too much, fixing Created 4 years, 7 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/crankshaft/x87/lithium-x87.cc ('k') | test/mjsunit/es6/tail-call.js » ('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 3e699922de9f1ed0b4d802b7b9bebe3777b3ae88..f1c21663ca3d07cc34fdfd182a8dca7b553682cf 100644
--- a/src/deoptimizer.cc
+++ b/src/deoptimizer.cc
@@ -968,7 +968,6 @@ void Deoptimizer::DoComputeJSFrame(TranslatedFrame* translated_frame,
// For the bottommost output frame the context can be gotten from the input
// frame. For all subsequent output frames it can be gotten from the function
// so long as we don't inline functions that need local contexts.
- Register context_reg = JavaScriptFrame::context_register();
output_offset -= kPointerSize;
TranslatedFrame::iterator context_pos = value_iterator;
@@ -993,7 +992,10 @@ void Deoptimizer::DoComputeJSFrame(TranslatedFrame* translated_frame,
}
value = reinterpret_cast<intptr_t>(context);
output_frame->SetContext(value);
- if (is_topmost) output_frame->SetRegister(context_reg.code(), value);
+ if (is_topmost) {
+ Register context_reg = JavaScriptFrame::context_register();
+ output_frame->SetRegister(context_reg.code(), value);
+ }
WriteValueToOutput(context, context_input_index, frame_index, output_offset,
"context ");
if (context == isolate_->heap()->arguments_marker()) {
@@ -1493,12 +1495,27 @@ void Deoptimizer::DoComputeTailCallerFrame(TranslatedFrame* translated_frame,
void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
int frame_index) {
TranslatedFrame::iterator value_iterator = translated_frame->begin();
+ bool is_topmost = (output_count_ - 1 == frame_index);
+ // The construct frame could become topmost only if we inlined a constructor
+ // call which does a tail call (otherwise the tail callee's frame would be
+ // the topmost one). So it could only be the LAZY case.
+ CHECK(!is_topmost || bailout_type_ == LAZY);
int input_index = 0;
Builtins* builtins = isolate_->builtins();
Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric);
unsigned height = translated_frame->height();
unsigned height_in_bytes = height * kPointerSize;
+
+ // If the construct frame appears to be topmost we should ensure that the
+ // value of result register is preserved during continuation execution.
+ // We do this here by "pushing" the result of the constructor function to the
+ // top of the reconstructed stack and then using the
+ // FullCodeGenerator::TOS_REG machinery.
+ if (is_topmost) {
+ height_in_bytes += kPointerSize;
+ }
+
// Skip function.
value_iterator++;
input_index++;
@@ -1515,8 +1532,8 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
new (output_frame_size) FrameDescription(output_frame_size);
output_frame->SetFrameType(StackFrame::CONSTRUCT);
- // Construct stub can not be topmost or bottommost.
- DCHECK(frame_index > 0 && frame_index < output_count_ - 1);
+ // Construct stub can not be topmost.
+ DCHECK(frame_index > 0 && frame_index < output_count_);
DCHECK(output_[frame_index] == NULL);
output_[frame_index] = output_frame;
@@ -1551,6 +1568,10 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
output_frame->SetCallerFp(output_offset, value);
intptr_t fp_value = top_address + output_offset;
output_frame->SetFp(fp_value);
+ if (is_topmost) {
+ Register fp_reg = JavaScriptFrame::fp_register();
+ output_frame->SetRegister(fp_reg.code(), fp_value);
+ }
DebugPrintOutputSlot(value, frame_index, output_offset, "caller's fp\n");
if (FLAG_enable_embedded_constant_pool) {
@@ -1573,6 +1594,10 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
output_offset -= kPointerSize;
value = output_[frame_index - 1]->GetContext();
output_frame->SetFrameSlot(output_offset, value);
+ if (is_topmost) {
+ Register context_reg = JavaScriptFrame::context_register();
+ output_frame->SetRegister(context_reg.code(), value);
+ }
DebugPrintOutputSlot(value, frame_index, output_offset, "context\n");
// The allocation site.
@@ -1598,6 +1623,18 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
DebugPrintOutputSlot(value, frame_index, output_offset,
"allocated receiver\n");
+ if (is_topmost) {
+ // Ensure the result is restored back when we return to the stub.
+ output_offset -= kPointerSize;
+ Register result_reg = FullCodeGenerator::result_register();
+ value = input_->GetRegister(result_reg.code());
+ output_frame->SetFrameSlot(output_offset, value);
+ DebugPrintOutputSlot(value, frame_index, output_offset,
+ "constructor result\n");
+
+ output_frame->SetState(Smi::FromInt(FullCodeGenerator::TOS_REG));
+ }
+
CHECK_EQ(0u, output_offset);
intptr_t pc = reinterpret_cast<intptr_t>(
@@ -1608,6 +1645,20 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
intptr_t constant_pool_value =
reinterpret_cast<intptr_t>(construct_stub->constant_pool());
output_frame->SetConstantPool(constant_pool_value);
+ if (is_topmost) {
+ Register constant_pool_reg =
+ JavaScriptFrame::constant_pool_pointer_register();
+ output_frame->SetRegister(constant_pool_reg.code(), fp_value);
+ }
+ }
+
+ // Set the continuation for the topmost frame.
+ if (is_topmost) {
+ Builtins* builtins = isolate_->builtins();
+ DCHECK_EQ(LAZY, bailout_type_);
+ Code* continuation = builtins->builtin(Builtins::kNotifyLazyDeoptimized);
+ output_frame->SetContinuation(
+ reinterpret_cast<intptr_t>(continuation->entry()));
}
}
@@ -1615,6 +1666,11 @@ void Deoptimizer::DoComputeAccessorStubFrame(TranslatedFrame* translated_frame,
int frame_index,
bool is_setter_stub_frame) {
TranslatedFrame::iterator value_iterator = translated_frame->begin();
+ bool is_topmost = (output_count_ - 1 == frame_index);
+ // The accessor frame could become topmost only if we inlined an accessor
+ // call which does a tail call (otherwise the tail callee's frame would be
+ // the topmost one). So it could only be the LAZY case.
+ CHECK(!is_topmost || bailout_type_ == LAZY);
int input_index = 0;
// Skip accessor.
@@ -1625,6 +1681,19 @@ void Deoptimizer::DoComputeAccessorStubFrame(TranslatedFrame* translated_frame,
// frame. This means that we have to use a height of 0.
unsigned height = 0;
unsigned height_in_bytes = height * kPointerSize;
+
+ // If the accessor frame appears to be topmost we should ensure that the
+ // value of result register is preserved during continuation execution.
+ // We do this here by "pushing" the result of the accessor function to the
+ // top of the reconstructed stack and then using the
+ // FullCodeGenerator::TOS_REG machinery.
+ // We don't need to restore the result in case of a setter call because we
+ // have to return the stored value but not the result of the setter function.
+ bool should_preserve_result = is_topmost && !is_setter_stub_frame;
+ if (should_preserve_result) {
+ height_in_bytes += kPointerSize;
+ }
+
const char* kind = is_setter_stub_frame ? "setter" : "getter";
if (trace_scope_ != NULL) {
PrintF(trace_scope_->file(),
@@ -1647,8 +1716,8 @@ void Deoptimizer::DoComputeAccessorStubFrame(TranslatedFrame* translated_frame,
new (output_frame_size) FrameDescription(output_frame_size);
output_frame->SetFrameType(StackFrame::INTERNAL);
- // A frame for an accessor stub can not be the topmost or bottommost one.
- CHECK(frame_index > 0 && frame_index < output_count_ - 1);
+ // A frame for an accessor stub can not be bottommost.
+ CHECK(frame_index > 0 && frame_index < output_count_);
CHECK_NULL(output_[frame_index]);
output_[frame_index] = output_frame;
@@ -1671,6 +1740,10 @@ void Deoptimizer::DoComputeAccessorStubFrame(TranslatedFrame* translated_frame,
output_frame->SetCallerFp(output_offset, value);
intptr_t fp_value = top_address + output_offset;
output_frame->SetFp(fp_value);
+ if (is_topmost) {
+ Register fp_reg = JavaScriptFrame::fp_register();
+ output_frame->SetRegister(fp_reg.code(), fp_value);
+ }
DebugPrintOutputSlot(value, frame_index, output_offset, "caller's fp\n");
if (FLAG_enable_embedded_constant_pool) {
@@ -1705,6 +1778,10 @@ void Deoptimizer::DoComputeAccessorStubFrame(TranslatedFrame* translated_frame,
output_offset -= kPointerSize;
value = output_[frame_index - 1]->GetContext();
output_frame->SetFrameSlot(output_offset, value);
+ if (is_topmost) {
+ Register context_reg = JavaScriptFrame::context_register();
+ output_frame->SetRegister(context_reg.code(), value);
+ }
DebugPrintOutputSlot(value, frame_index, output_offset, "context\n");
// Skip receiver.
@@ -1719,6 +1796,20 @@ void Deoptimizer::DoComputeAccessorStubFrame(TranslatedFrame* translated_frame,
output_offset);
}
+ if (should_preserve_result) {
+ // Ensure the result is restored back when we return to the stub.
+ output_offset -= kPointerSize;
+ Register result_reg = FullCodeGenerator::result_register();
+ value = input_->GetRegister(result_reg.code());
+ output_frame->SetFrameSlot(output_offset, value);
+ DebugPrintOutputSlot(value, frame_index, output_offset,
+ "accessor result\n");
+
+ output_frame->SetState(Smi::FromInt(FullCodeGenerator::TOS_REG));
+ } else {
+ output_frame->SetState(Smi::FromInt(FullCodeGenerator::NO_REGISTERS));
+ }
+
CHECK_EQ(0u, output_offset);
Smi* offset = is_setter_stub_frame ?
@@ -1731,6 +1822,20 @@ void Deoptimizer::DoComputeAccessorStubFrame(TranslatedFrame* translated_frame,
intptr_t constant_pool_value =
reinterpret_cast<intptr_t>(accessor_stub->constant_pool());
output_frame->SetConstantPool(constant_pool_value);
+ if (is_topmost) {
+ Register constant_pool_reg =
+ JavaScriptFrame::constant_pool_pointer_register();
+ output_frame->SetRegister(constant_pool_reg.code(), fp_value);
+ }
+ }
+
+ // Set the continuation for the topmost frame.
+ if (is_topmost) {
+ Builtins* builtins = isolate_->builtins();
+ DCHECK_EQ(LAZY, bailout_type_);
+ Code* continuation = builtins->builtin(Builtins::kNotifyLazyDeoptimized);
+ output_frame->SetContinuation(
+ reinterpret_cast<intptr_t>(continuation->entry()));
}
}
« no previous file with comments | « src/crankshaft/x87/lithium-x87.cc ('k') | test/mjsunit/es6/tail-call.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698