[deoptimizer] Fix deoptimization in {TranslatedState}.

This ensures the deoptimization triggered due to materialization of
objects by the {TranslatedState} works in conjunction with OSR. The
optimized code used for OSR is not installed on the function, hence
needs to be specified explicitly when requesting deoptimization for
specific stack frames.

R=jarin@chromium.org
TEST=mjsunit/regress/regress-crbug-668795
BUG=chromium:668795

Review-Url: https://codereview.chromium.org/2534143002
Cr-Commit-Position: refs/heads/master@{#41348}
This commit is contained in:
mstarzinger 2016-11-29 03:34:07 -08:00 committed by Commit bot
parent 868abcb085
commit 204babf5a0
5 changed files with 36 additions and 14 deletions

View File

@ -801,8 +801,8 @@ static Handle<Object> ArgumentsForInlinedFunction(
Handle<FixedArray> array = factory->NewFixedArray(argument_count);
bool should_deoptimize = false;
for (int i = 0; i < argument_count; ++i) {
// If we materialize any object, we should deopt because we might alias
// an object that was eliminated by escape analysis.
// If we materialize any object, we should deoptimize the frame because we
// might alias an object that was eliminated by escape analysis.
should_deoptimize = should_deoptimize || iter->IsMaterializedObject();
Handle<Object> value = iter->GetValue();
array->set(i, *value);
@ -811,7 +811,7 @@ static Handle<Object> ArgumentsForInlinedFunction(
arguments->set_elements(*array);
if (should_deoptimize) {
translated_values.StoreMaterializedValuesAndDeopt();
translated_values.StoreMaterializedValuesAndDeopt(frame);
}
// Return the freshly allocated arguments object.

View File

@ -391,14 +391,13 @@ void Deoptimizer::MarkAllCodeForContext(Context* context) {
}
}
void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
void Deoptimizer::DeoptimizeFunction(JSFunction* function, Code* code) {
Isolate* isolate = function->GetIsolate();
RuntimeCallTimerScope runtimeTimer(isolate,
&RuntimeCallStats::DeoptimizeCode);
TimerEventScope<TimerEventDeoptimizeCode> timer(isolate);
TRACE_EVENT0("v8", "V8.DeoptimizeCode");
Code* code = function->code();
if (code == nullptr) code = function->code();
if (code->kind() == Code::OPTIMIZED_FUNCTION) {
// Mark the code for deoptimization and unlink any functions that also
// refer to that code. The code cannot be shared across native contexts,
@ -3934,8 +3933,7 @@ TranslatedFrame* TranslatedState::GetArgumentsInfoFromJSFrameIndex(
return nullptr;
}
void TranslatedState::StoreMaterializedValuesAndDeopt() {
void TranslatedState::StoreMaterializedValuesAndDeopt(JavaScriptFrame* frame) {
MaterializedObjectStore* materialized_store =
isolate_->materialized_object_store();
Handle<FixedArray> previously_materialized_objects =
@ -3981,8 +3979,8 @@ void TranslatedState::StoreMaterializedValuesAndDeopt() {
CHECK(frames_[0].kind() == TranslatedFrame::kFunction ||
frames_[0].kind() == TranslatedFrame::kInterpretedFunction ||
frames_[0].kind() == TranslatedFrame::kTailCallerFunction);
Object* const function = frames_[0].front().GetRawValue();
Deoptimizer::DeoptimizeFunction(JSFunction::cast(function));
CHECK_EQ(frame->function(), frames_[0].front().GetRawValue());
Deoptimizer::DeoptimizeFunction(frame->function(), frame->LookupCode());
}
}

View File

@ -254,7 +254,7 @@ class TranslatedState {
void Prepare(bool has_adapted_arguments, Address stack_frame_pointer);
// Store newly materialized values into the isolate.
void StoreMaterializedValuesAndDeopt();
void StoreMaterializedValuesAndDeopt(JavaScriptFrame* frame);
typedef std::vector<TranslatedFrame>::iterator iterator;
iterator begin() { return frames_.begin(); }
@ -419,8 +419,9 @@ class Deoptimizer : public Malloced {
// Deoptimize the function now. Its current optimized code will never be run
// again and any activations of the optimized code will get deoptimized when
// execution returns.
static void DeoptimizeFunction(JSFunction* function);
// execution returns. If {code} is specified then the given code is targeted
// instead of the function code (e.g. OSR code not installed on function).
static void DeoptimizeFunction(JSFunction* function, Code* code = nullptr);
// Deoptimize all code in the given isolate.
static void DeoptimizeAll(Isolate* isolate);

View File

@ -377,6 +377,8 @@ std::unique_ptr<Handle<Object>[]> GetCallerArguments(Isolate* isolate,
NewArray<Handle<Object>>(*total_argc));
bool should_deoptimize = false;
for (int i = 0; i < argument_count; i++) {
// If we materialize any object, we should deoptimize the frame because we
// might alias an object that was eliminated by escape analysis.
should_deoptimize = should_deoptimize || iter->IsMaterializedObject();
Handle<Object> value = iter->GetValue();
param_data[i] = value;
@ -384,7 +386,7 @@ std::unique_ptr<Handle<Object>[]> GetCallerArguments(Isolate* isolate,
}
if (should_deoptimize) {
translated_values.StoreMaterializedValuesAndDeopt();
translated_values.StoreMaterializedValuesAndDeopt(frame);
}
return param_data;

View File

@ -0,0 +1,21 @@
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --ignition
function g() {
return g.arguments;
}
function f() {
var result = "R:";
for (var i = 0; i < 3; ++i) {
if (i == 1) %OptimizeOsr();
result += g([1])[0];
result += g([2])[0];
}
return result;
}
assertEquals("R:121212", f());