Commit e044f0a6 authored by bmeurer's avatar bmeurer Committed by Commit bot

[deoptimizer] Remove uses of TranslationIterator outside the deoptimizer.

Use the new TranslatedState and friends, which work at a higher level
than the TranslationIterator, which will make it easier to change the
deoptimization commands in subsequent CLs.

R=jarin@chromium.org

Review URL: https://codereview.chromium.org/1166353004

Cr-Commit-Position: refs/heads/master@{#28862}
parent 6ca5ffa0
...@@ -2515,8 +2515,8 @@ TranslatedValue TranslatedValue::NewTagged(TranslatedState* container, ...@@ -2515,8 +2515,8 @@ TranslatedValue TranslatedValue::NewTagged(TranslatedState* container,
// static // static
TranslatedValue TranslatedValue::NewInvalid() { TranslatedValue TranslatedValue::NewInvalid(TranslatedState* container) {
return TranslatedValue(nullptr, kInvalid); return TranslatedValue(container, kInvalid);
} }
...@@ -2985,7 +2985,7 @@ TranslatedValue TranslatedState::CreateNextTranslatedValue( ...@@ -2985,7 +2985,7 @@ TranslatedValue TranslatedState::CreateNextTranslatedValue(
case Translation::REGISTER: { case Translation::REGISTER: {
int input_reg = iterator->Next(); int input_reg = iterator->Next();
if (registers == nullptr) return TranslatedValue::NewInvalid(); if (registers == nullptr) return TranslatedValue::NewInvalid(this);
intptr_t value = registers->GetRegister(input_reg); intptr_t value = registers->GetRegister(input_reg);
if (trace_file != nullptr) { if (trace_file != nullptr) {
PrintF(trace_file, "0x%08" V8PRIxPTR " ; %s ", value, PrintF(trace_file, "0x%08" V8PRIxPTR " ; %s ", value,
...@@ -2997,7 +2997,7 @@ TranslatedValue TranslatedState::CreateNextTranslatedValue( ...@@ -2997,7 +2997,7 @@ TranslatedValue TranslatedState::CreateNextTranslatedValue(
case Translation::INT32_REGISTER: { case Translation::INT32_REGISTER: {
int input_reg = iterator->Next(); int input_reg = iterator->Next();
if (registers == nullptr) return TranslatedValue::NewInvalid(); if (registers == nullptr) return TranslatedValue::NewInvalid(this);
intptr_t value = registers->GetRegister(input_reg); intptr_t value = registers->GetRegister(input_reg);
if (trace_file != nullptr) { if (trace_file != nullptr) {
PrintF(trace_file, "%" V8PRIdPTR " ; %s ", value, PrintF(trace_file, "%" V8PRIdPTR " ; %s ", value,
...@@ -3008,7 +3008,7 @@ TranslatedValue TranslatedState::CreateNextTranslatedValue( ...@@ -3008,7 +3008,7 @@ TranslatedValue TranslatedState::CreateNextTranslatedValue(
case Translation::UINT32_REGISTER: { case Translation::UINT32_REGISTER: {
int input_reg = iterator->Next(); int input_reg = iterator->Next();
if (registers == nullptr) return TranslatedValue::NewInvalid(); if (registers == nullptr) return TranslatedValue::NewInvalid(this);
intptr_t value = registers->GetRegister(input_reg); intptr_t value = registers->GetRegister(input_reg);
if (trace_file != nullptr) { if (trace_file != nullptr) {
PrintF(trace_file, "%" V8PRIuPTR " ; %s (uint)", value, PrintF(trace_file, "%" V8PRIuPTR " ; %s (uint)", value,
...@@ -3020,7 +3020,7 @@ TranslatedValue TranslatedState::CreateNextTranslatedValue( ...@@ -3020,7 +3020,7 @@ TranslatedValue TranslatedState::CreateNextTranslatedValue(
case Translation::BOOL_REGISTER: { case Translation::BOOL_REGISTER: {
int input_reg = iterator->Next(); int input_reg = iterator->Next();
if (registers == nullptr) return TranslatedValue::NewInvalid(); if (registers == nullptr) return TranslatedValue::NewInvalid(this);
intptr_t value = registers->GetRegister(input_reg); intptr_t value = registers->GetRegister(input_reg);
if (trace_file != nullptr) { if (trace_file != nullptr) {
PrintF(trace_file, "%" V8PRIdPTR " ; %s (bool)", value, PrintF(trace_file, "%" V8PRIdPTR " ; %s (bool)", value,
...@@ -3031,7 +3031,7 @@ TranslatedValue TranslatedState::CreateNextTranslatedValue( ...@@ -3031,7 +3031,7 @@ TranslatedValue TranslatedState::CreateNextTranslatedValue(
case Translation::DOUBLE_REGISTER: { case Translation::DOUBLE_REGISTER: {
int input_reg = iterator->Next(); int input_reg = iterator->Next();
if (registers == nullptr) return TranslatedValue::NewInvalid(); if (registers == nullptr) return TranslatedValue::NewInvalid(this);
double value = registers->GetDoubleRegister(input_reg); double value = registers->GetDoubleRegister(input_reg);
if (trace_file != nullptr) { if (trace_file != nullptr) {
PrintF(trace_file, "%e ; %s (bool)", value, PrintF(trace_file, "%e ; %s (bool)", value,
......
...@@ -67,7 +67,7 @@ class TranslatedValue BASE_EMBEDDED { ...@@ -67,7 +67,7 @@ class TranslatedValue BASE_EMBEDDED {
static TranslatedValue NewUInt32(TranslatedState* container, uint32_t value); static TranslatedValue NewUInt32(TranslatedState* container, uint32_t value);
static TranslatedValue NewBool(TranslatedState* container, uint32_t value); static TranslatedValue NewBool(TranslatedState* container, uint32_t value);
static TranslatedValue NewTagged(TranslatedState* container, Object* literal); static TranslatedValue NewTagged(TranslatedState* container, Object* literal);
static TranslatedValue NewInvalid(); static TranslatedValue NewInvalid(TranslatedState* container);
Isolate* isolate() const; Isolate* isolate() const;
void MaterializeSimple(); void MaterializeSimple();
...@@ -125,10 +125,10 @@ class TranslatedFrame { ...@@ -125,10 +125,10 @@ class TranslatedFrame {
int GetValueCount(); int GetValueCount();
Kind kind() const { return kind_; } Kind kind() const { return kind_; }
BailoutId node_id() { return node_id_; } BailoutId node_id() const { return node_id_; }
JSFunction* raw_function() { return raw_function_; } JSFunction* raw_function() const { return raw_function_; }
Handle<JSFunction> function() { return function_; } Handle<JSFunction> function() const { return function_; }
int height() { return height_; } int height() const { return height_; }
class iterator { class iterator {
public: public:
...@@ -160,8 +160,13 @@ class TranslatedFrame { ...@@ -160,8 +160,13 @@ class TranslatedFrame {
std::deque<TranslatedValue>::iterator position_; std::deque<TranslatedValue>::iterator position_;
}; };
typedef TranslatedValue& reference;
typedef TranslatedValue const& const_reference;
iterator begin() { return iterator(values_.begin()); } iterator begin() { return iterator(values_.begin()); }
iterator end() { return iterator(values_.end()); } iterator end() { return iterator(values_.end()); }
reference front() { return values_.front(); }
const_reference front() const { return values_.front(); }
private: private:
friend class TranslatedState; friend class TranslatedState;
...@@ -232,6 +237,10 @@ class TranslatedState { ...@@ -232,6 +237,10 @@ class TranslatedState {
// Store newly materialized values into the isolate. // Store newly materialized values into the isolate.
void StoreMaterializedValuesAndDeopt(); void StoreMaterializedValuesAndDeopt();
typedef std::vector<TranslatedFrame>::const_iterator const_iterator;
const_iterator begin() const { return frames_.begin(); }
const_iterator end() const { return frames_.end(); }
std::vector<TranslatedFrame>& frames() { return frames_; } std::vector<TranslatedFrame>& frames() { return frames_; }
TranslatedFrame* GetArgumentsInfoFromJSFrameIndex(int jsframe_index, TranslatedFrame* GetArgumentsInfoFromJSFrameIndex(int jsframe_index,
......
...@@ -884,93 +884,56 @@ void OptimizedFrame::Summarize(List<FrameSummary>* frames) { ...@@ -884,93 +884,56 @@ void OptimizedFrame::Summarize(List<FrameSummary>* frames) {
return JavaScriptFrame::Summarize(frames); return JavaScriptFrame::Summarize(frames);
} }
int deopt_index = Safepoint::kNoDeoptimizationIndex;
DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index);
FixedArray* literal_array = data->LiteralArray();
// BUG(3243555): Since we don't have a lazy-deopt registered at
// throw-statements, we can't use the translation at the call-site of
// throw. An entry with no deoptimization index indicates a call-site
// without a lazy-deopt. As a consequence we are not allowed to inline
// functions containing throw.
DCHECK(deopt_index != Safepoint::kNoDeoptimizationIndex);
TranslationIterator it(data->TranslationByteArray(),
data->TranslationIndex(deopt_index)->value());
Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
DCHECK(opcode == Translation::BEGIN);
it.Next(); // Drop frame count.
int jsframe_count = it.Next();
// We create the summary in reverse order because the frames // We create the summary in reverse order because the frames
// in the deoptimization translation are ordered bottom-to-top. // in the deoptimization translation are ordered bottom-to-top.
TranslatedState state(this);
bool is_constructor = IsConstructor(); bool is_constructor = IsConstructor();
int i = jsframe_count; for (TranslatedFrame const& frame : state) {
while (i > 0) { switch (frame.kind()) {
opcode = static_cast<Translation::Opcode>(it.Next()); case TranslatedFrame::kFunction: {
if (opcode == Translation::JS_FRAME) { BailoutId const ast_id = frame.node_id();
i--; JSFunction* const function = frame.raw_function();
BailoutId ast_id = BailoutId(it.Next());
JSFunction* function = LiteralAt(literal_array, it.Next()); // Get the correct receiver in the optimized frame.
it.Next(); // Skip height. Object* receiver = frame.front().GetRawValue();
if (receiver == isolate()->heap()->arguments_marker()) {
// The translation commands are ordered and the receiver is always // TODO(jarin): Materializing a captured object (or duplicated
// at the first position. // object) is hard, we return undefined for now. This breaks the
// If we are at a call, the receiver is always in a stack slot. // produced stack trace, as constructor frames aren't marked as
// Otherwise we are not guaranteed to get the receiver value. // such anymore.
opcode = static_cast<Translation::Opcode>(it.Next()); receiver = isolate()->heap()->undefined_value();
int index = it.Next();
// Get the correct receiver in the optimized frame.
Object* receiver = NULL;
if (opcode == Translation::LITERAL) {
receiver = data->LiteralArray()->get(index);
} else if (opcode == Translation::STACK_SLOT) {
// Positive index means the value is spilled to the locals
// area. Negative means it is stored in the incoming parameter
// area.
if (index >= 0) {
receiver = GetExpression(index);
} else {
// Index -1 overlaps with last parameter, -n with the first parameter,
// (-n - 1) with the receiver with n being the number of parameters
// of the outermost, optimized frame.
int parameter_count = ComputeParametersCount();
int parameter_index = index + parameter_count;
receiver = (parameter_index == -1)
? this->receiver()
: this->GetParameter(parameter_index);
} }
} else {
// The receiver is not in a stack slot nor in a literal. We give up. Code* code = function->shared()->code();
// TODO(3029): Materializing a captured object (or duplicated DeoptimizationOutputData* output_data =
// object) is hard, we return undefined for now. This breaks the DeoptimizationOutputData::cast(code->deoptimization_data());
// produced stack trace, as constructor frames aren't marked as unsigned entry =
// such anymore. Deoptimizer::GetOutputInfo(output_data, ast_id, function->shared());
receiver = isolate()->heap()->undefined_value(); unsigned pc_offset =
FullCodeGenerator::PcField::decode(entry) + Code::kHeaderSize;
DCHECK(pc_offset > 0);
FrameSummary summary(receiver, function, code, pc_offset,
is_constructor);
frames->Add(summary);
is_constructor = false;
break;
} }
Code* code = function->shared()->code(); case TranslatedFrame::kConstructStub: {
DeoptimizationOutputData* output_data = // The next encountered JS_FRAME will be marked as a constructor call.
DeoptimizationOutputData::cast(code->deoptimization_data()); DCHECK(!is_constructor);
unsigned entry = Deoptimizer::GetOutputInfo(output_data, is_constructor = true;
ast_id, break;
function->shared()); }
unsigned pc_offset =
FullCodeGenerator::PcField::decode(entry) + Code::kHeaderSize; case TranslatedFrame::kInvalid:
DCHECK(pc_offset > 0); UNREACHABLE();
case TranslatedFrame::kArgumentsAdaptor:
FrameSummary summary(receiver, function, code, pc_offset, is_constructor); case TranslatedFrame::kCompiledStub:
frames->Add(summary); case TranslatedFrame::kGetter:
is_constructor = false; case TranslatedFrame::kSetter:
} else if (opcode == Translation::CONSTRUCT_STUB_FRAME) { break;
// The next encountered JS_FRAME will be marked as a constructor call.
it.Skip(Translation::NumberOfOperandsFor(opcode));
DCHECK(!is_constructor);
is_constructor = true;
} else {
// Skip over operands to advance to the next opcode.
it.Skip(Translation::NumberOfOperandsFor(opcode));
} }
} }
DCHECK(!is_constructor); DCHECK(!is_constructor);
...@@ -1024,30 +987,10 @@ void OptimizedFrame::GetFunctions(List<JSFunction*>* functions) { ...@@ -1024,30 +987,10 @@ void OptimizedFrame::GetFunctions(List<JSFunction*>* functions) {
return JavaScriptFrame::GetFunctions(functions); return JavaScriptFrame::GetFunctions(functions);
} }
int deopt_index = Safepoint::kNoDeoptimizationIndex; TranslatedState state(this);
DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index); for (TranslatedFrame const& frame : state) {
FixedArray* literal_array = data->LiteralArray(); if (frame.kind() == TranslatedFrame::kFunction) {
functions->Add(frame.raw_function());
TranslationIterator it(data->TranslationByteArray(),
data->TranslationIndex(deopt_index)->value());
Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
DCHECK(opcode == Translation::BEGIN);
it.Next(); // Drop frame count.
int jsframe_count = it.Next();
// We insert the frames in reverse order because the frames
// in the deoptimization translation are ordered bottom-to-top.
while (jsframe_count > 0) {
opcode = static_cast<Translation::Opcode>(it.Next());
if (opcode == Translation::JS_FRAME) {
jsframe_count--;
it.Next(); // Skip ast id.
JSFunction* function = LiteralAt(literal_array, it.Next());
it.Next(); // Skip height.
functions->Add(function);
} else {
// Skip over operands to advance to the next opcode.
it.Skip(Translation::NumberOfOperandsFor(opcode));
} }
} }
} }
......
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