Index: src/deoptimizer.cc |
diff --git a/src/deoptimizer.cc b/src/deoptimizer.cc |
index 3e699922de9f1ed0b4d802b7b9bebe3777b3ae88..595bcac5b4a838df2c993a1961fe1576c8b63405 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,20 @@ 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); |
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; |
+ |
+ // We need to restore the result returned from the constructor before |
+ // we return to the construct stub. |
+ if (is_topmost) { |
+ height_in_bytes += kPointerSize; |
+ } |
+ |
// Skip function. |
value_iterator++; |
input_index++; |
@@ -1515,8 +1525,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 +1561,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 +1587,11 @@ 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); |
+ output_frame->SetRegister(context_reg.code(), 153); |
Jarin
2016/05/03 14:42:36
???
Igor Sheludko
2016/05/06 09:50:03
Oops.
|
+ } |
DebugPrintOutputSlot(value, frame_index, output_offset, "context\n"); |
// The allocation site. |
@@ -1598,6 +1617,20 @@ 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)); |
+ } else { |
+ output_frame->SetState(Smi::FromInt(FullCodeGenerator::NO_REGISTERS)); |
+ } |
+ |
CHECK_EQ(0u, output_offset); |
intptr_t pc = reinterpret_cast<intptr_t>( |
@@ -1608,6 +1641,26 @@ 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(); |
+ Code* continuation = builtins->builtin(Builtins::kNotifyDeoptimized); |
+ if (bailout_type_ == LAZY) { |
+ continuation = builtins->builtin(Builtins::kNotifyLazyDeoptimized); |
+ } else if (bailout_type_ == SOFT) { |
+ continuation = builtins->builtin(Builtins::kNotifySoftDeoptimized); |
+ } else { |
+ CHECK_EQ(bailout_type_, EAGER); |
+ } |
+ output_frame->SetContinuation( |
+ reinterpret_cast<intptr_t>(continuation->entry())); |
} |
} |
@@ -1615,6 +1668,7 @@ 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); |
int input_index = 0; |
// Skip accessor. |
@@ -1625,6 +1679,14 @@ 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; |
+ |
+ // We don't need to restore the result in case of 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 +1709,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 +1733,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 +1771,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 +1789,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 +1815,26 @@ 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(); |
+ Code* continuation = builtins->builtin(Builtins::kNotifyDeoptimized); |
+ if (bailout_type_ == LAZY) { |
+ continuation = builtins->builtin(Builtins::kNotifyLazyDeoptimized); |
+ } else if (bailout_type_ == SOFT) { |
+ continuation = builtins->builtin(Builtins::kNotifySoftDeoptimized); |
+ } else { |
+ CHECK_EQ(bailout_type_, EAGER); |
+ } |
+ output_frame->SetContinuation( |
+ reinterpret_cast<intptr_t>(continuation->entry())); |
} |
} |