Commit 96164b74 authored by mstarzinger's avatar mstarzinger Committed by Commit bot

[deoptimizer] Clear context before NotifyDeoptimized.

This clears the context register by setting it to Smi(0) before calling
the Runtime::kNotifyDeoptimized helper. The deoptimizer must be able to
materialize all heap objects without any context available. The context
itself might be dematerialized.

With this change we make sure that invariant is maintained even without
escape analysis kicking in. We also satisfy the check that the context
register is either Smi(0) or a valid context. It might have been the
special {arguments_marker} in this particular case.

R=bmeurer@chromium.org
BUG=chromium:644245

Review-Url: https://codereview.chromium.org/2320673002
Cr-Commit-Position: refs/heads/master@{#39267}
parent 4ed27fc8
...@@ -964,10 +964,6 @@ void Deoptimizer::DoComputeJSFrame(TranslatedFrame* translated_frame, ...@@ -964,10 +964,6 @@ void Deoptimizer::DoComputeJSFrame(TranslatedFrame* translated_frame,
} }
value = reinterpret_cast<intptr_t>(context); value = reinterpret_cast<intptr_t>(context);
output_frame->SetContext(value); output_frame->SetContext(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, WriteValueToOutput(context, context_input_index, frame_index, output_offset,
"context "); "context ");
if (context == isolate_->heap()->arguments_marker()) { if (context == isolate_->heap()->arguments_marker()) {
...@@ -1033,6 +1029,15 @@ void Deoptimizer::DoComputeJSFrame(TranslatedFrame* translated_frame, ...@@ -1033,6 +1029,15 @@ void Deoptimizer::DoComputeJSFrame(TranslatedFrame* translated_frame,
: FullCodeGenerator::BailoutStateField::decode(pc_and_state); : FullCodeGenerator::BailoutStateField::decode(pc_and_state);
output_frame->SetState(Smi::FromInt(static_cast<int>(state))); output_frame->SetState(Smi::FromInt(static_cast<int>(state)));
// Clear the context register. The context might be a de-materialized object
// and will be materialized by {Runtime_NotifyDeoptimized}. For additional
// safety we use Smi(0) instead of the potential {arguments_marker} here.
if (is_topmost) {
intptr_t context_value = reinterpret_cast<intptr_t>(Smi::FromInt(0));
Register context_reg = JavaScriptFrame::context_register();
output_frame->SetRegister(context_reg.code(), context_value);
}
// Set the continuation for the topmost frame. // Set the continuation for the topmost frame.
if (is_topmost) { if (is_topmost) {
Builtins* builtins = isolate_->builtins(); Builtins* builtins = isolate_->builtins();
...@@ -1191,10 +1196,6 @@ void Deoptimizer::DoComputeInterpretedFrame(TranslatedFrame* translated_frame, ...@@ -1191,10 +1196,6 @@ void Deoptimizer::DoComputeInterpretedFrame(TranslatedFrame* translated_frame,
Object* context = context_pos->GetRawValue(); Object* context = context_pos->GetRawValue();
value = reinterpret_cast<intptr_t>(context); value = reinterpret_cast<intptr_t>(context);
output_frame->SetContext(value); output_frame->SetContext(value);
if (is_topmost) {
Register context_reg = InterpretedFrame::context_register();
output_frame->SetRegister(context_reg.code(), value);
}
WriteValueToOutput(context, context_input_index, frame_index, output_offset, WriteValueToOutput(context, context_input_index, frame_index, output_offset,
"context "); "context ");
if (context == isolate_->heap()->arguments_marker()) { if (context == isolate_->heap()->arguments_marker()) {
...@@ -1288,6 +1289,15 @@ void Deoptimizer::DoComputeInterpretedFrame(TranslatedFrame* translated_frame, ...@@ -1288,6 +1289,15 @@ void Deoptimizer::DoComputeInterpretedFrame(TranslatedFrame* translated_frame,
} }
} }
// Clear the context register. The context might be a de-materialized object
// and will be materialized by {Runtime_NotifyDeoptimized}. For additional
// safety we use Smi(0) instead of the potential {arguments_marker} here.
if (is_topmost) {
intptr_t context_value = reinterpret_cast<intptr_t>(Smi::FromInt(0));
Register context_reg = JavaScriptFrame::context_register();
output_frame->SetRegister(context_reg.code(), context_value);
}
// Set the continuation for the topmost frame. // Set the continuation for the topmost frame.
if (is_topmost) { if (is_topmost) {
Code* continuation = builtins->builtin(Builtins::kNotifyDeoptimized); Code* continuation = builtins->builtin(Builtins::kNotifyDeoptimized);
...@@ -1591,10 +1601,6 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame, ...@@ -1591,10 +1601,6 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
output_offset -= kPointerSize; output_offset -= kPointerSize;
value = output_[frame_index - 1]->GetContext(); value = output_[frame_index - 1]->GetContext();
output_frame->SetFrameSlot(output_offset, value); 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"); DebugPrintOutputSlot(value, frame_index, output_offset, "context\n");
// The allocation site. // The allocation site.
...@@ -1650,6 +1656,15 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame, ...@@ -1650,6 +1656,15 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
} }
} }
// Clear the context register. The context might be a de-materialized object
// and will be materialized by {Runtime_NotifyDeoptimized}. For additional
// safety we use Smi(0) instead of the potential {arguments_marker} here.
if (is_topmost) {
intptr_t context_value = reinterpret_cast<intptr_t>(Smi::FromInt(0));
Register context_reg = JavaScriptFrame::context_register();
output_frame->SetRegister(context_reg.code(), context_value);
}
// Set the continuation for the topmost frame. // Set the continuation for the topmost frame.
if (is_topmost) { if (is_topmost) {
Builtins* builtins = isolate_->builtins(); Builtins* builtins = isolate_->builtins();
...@@ -1776,10 +1791,6 @@ void Deoptimizer::DoComputeAccessorStubFrame(TranslatedFrame* translated_frame, ...@@ -1776,10 +1791,6 @@ void Deoptimizer::DoComputeAccessorStubFrame(TranslatedFrame* translated_frame,
output_offset -= kPointerSize; output_offset -= kPointerSize;
value = output_[frame_index - 1]->GetContext(); value = output_[frame_index - 1]->GetContext();
output_frame->SetFrameSlot(output_offset, value); 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"); DebugPrintOutputSlot(value, frame_index, output_offset, "context\n");
// Skip receiver. // Skip receiver.
...@@ -1829,6 +1840,15 @@ void Deoptimizer::DoComputeAccessorStubFrame(TranslatedFrame* translated_frame, ...@@ -1829,6 +1840,15 @@ void Deoptimizer::DoComputeAccessorStubFrame(TranslatedFrame* translated_frame,
} }
} }
// Clear the context register. The context might be a de-materialized object
// and will be materialized by {Runtime_NotifyDeoptimized}. For additional
// safety we use Smi(0) instead of the potential {arguments_marker} here.
if (is_topmost) {
intptr_t context_value = reinterpret_cast<intptr_t>(Smi::FromInt(0));
Register context_reg = JavaScriptFrame::context_register();
output_frame->SetRegister(context_reg.code(), context_value);
}
// Set the continuation for the topmost frame. // Set the continuation for the topmost frame.
if (is_topmost) { if (is_topmost) {
Builtins* builtins = isolate_->builtins(); Builtins* builtins = isolate_->builtins();
......
...@@ -172,6 +172,17 @@ RUNTIME_FUNCTION(Runtime_NotifyDeoptimized) { ...@@ -172,6 +172,17 @@ RUNTIME_FUNCTION(Runtime_NotifyDeoptimized) {
DCHECK(optimized_code->kind() == Code::OPTIMIZED_FUNCTION); DCHECK(optimized_code->kind() == Code::OPTIMIZED_FUNCTION);
DCHECK(type == deoptimizer->bailout_type()); DCHECK(type == deoptimizer->bailout_type());
DCHECK_NULL(isolate->context());
// TODO(turbofan): For Crankshaft we restore the context before objects are
// being materialized, because it never de-materializes the context but it
// requires a context to materialize arguments objects. This is specific to
// Crankshaft and can be removed once only TurboFan goes through here.
if (!optimized_code->is_turbofanned()) {
JavaScriptFrameIterator top_it(isolate);
JavaScriptFrame* top_frame = top_it.frame();
isolate->set_context(Context::cast(top_frame->context()));
}
// Make sure to materialize objects before causing any allocation. // Make sure to materialize objects before causing any allocation.
JavaScriptFrameIterator it(isolate); JavaScriptFrameIterator it(isolate);
...@@ -179,9 +190,11 @@ RUNTIME_FUNCTION(Runtime_NotifyDeoptimized) { ...@@ -179,9 +190,11 @@ RUNTIME_FUNCTION(Runtime_NotifyDeoptimized) {
delete deoptimizer; delete deoptimizer;
// Ensure the context register is updated for materialized objects. // Ensure the context register is updated for materialized objects.
JavaScriptFrameIterator top_it(isolate); if (optimized_code->is_turbofanned()) {
JavaScriptFrame* top_frame = top_it.frame(); JavaScriptFrameIterator top_it(isolate);
isolate->set_context(Context::cast(top_frame->context())); JavaScriptFrame* top_frame = top_it.frame();
isolate->set_context(Context::cast(top_frame->context()));
}
if (type == Deoptimizer::LAZY) { if (type == Deoptimizer::LAZY) {
return isolate->heap()->undefined_value(); return isolate->heap()->undefined_value();
......
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