[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}
This commit is contained in:
parent
6ca5ffa078
commit
e044f0a67e
@ -2515,8 +2515,8 @@ TranslatedValue TranslatedValue::NewTagged(TranslatedState* container,
|
||||
|
||||
|
||||
// static
|
||||
TranslatedValue TranslatedValue::NewInvalid() {
|
||||
return TranslatedValue(nullptr, kInvalid);
|
||||
TranslatedValue TranslatedValue::NewInvalid(TranslatedState* container) {
|
||||
return TranslatedValue(container, kInvalid);
|
||||
}
|
||||
|
||||
|
||||
@ -2985,7 +2985,7 @@ TranslatedValue TranslatedState::CreateNextTranslatedValue(
|
||||
|
||||
case Translation::REGISTER: {
|
||||
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);
|
||||
if (trace_file != nullptr) {
|
||||
PrintF(trace_file, "0x%08" V8PRIxPTR " ; %s ", value,
|
||||
@ -2997,7 +2997,7 @@ TranslatedValue TranslatedState::CreateNextTranslatedValue(
|
||||
|
||||
case Translation::INT32_REGISTER: {
|
||||
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);
|
||||
if (trace_file != nullptr) {
|
||||
PrintF(trace_file, "%" V8PRIdPTR " ; %s ", value,
|
||||
@ -3008,7 +3008,7 @@ TranslatedValue TranslatedState::CreateNextTranslatedValue(
|
||||
|
||||
case Translation::UINT32_REGISTER: {
|
||||
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);
|
||||
if (trace_file != nullptr) {
|
||||
PrintF(trace_file, "%" V8PRIuPTR " ; %s (uint)", value,
|
||||
@ -3020,7 +3020,7 @@ TranslatedValue TranslatedState::CreateNextTranslatedValue(
|
||||
|
||||
case Translation::BOOL_REGISTER: {
|
||||
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);
|
||||
if (trace_file != nullptr) {
|
||||
PrintF(trace_file, "%" V8PRIdPTR " ; %s (bool)", value,
|
||||
@ -3031,7 +3031,7 @@ TranslatedValue TranslatedState::CreateNextTranslatedValue(
|
||||
|
||||
case Translation::DOUBLE_REGISTER: {
|
||||
int input_reg = iterator->Next();
|
||||
if (registers == nullptr) return TranslatedValue::NewInvalid();
|
||||
if (registers == nullptr) return TranslatedValue::NewInvalid(this);
|
||||
double value = registers->GetDoubleRegister(input_reg);
|
||||
if (trace_file != nullptr) {
|
||||
PrintF(trace_file, "%e ; %s (bool)", value,
|
||||
|
@ -67,7 +67,7 @@ class TranslatedValue BASE_EMBEDDED {
|
||||
static TranslatedValue NewUInt32(TranslatedState* container, uint32_t value);
|
||||
static TranslatedValue NewBool(TranslatedState* container, uint32_t value);
|
||||
static TranslatedValue NewTagged(TranslatedState* container, Object* literal);
|
||||
static TranslatedValue NewInvalid();
|
||||
static TranslatedValue NewInvalid(TranslatedState* container);
|
||||
|
||||
Isolate* isolate() const;
|
||||
void MaterializeSimple();
|
||||
@ -125,10 +125,10 @@ class TranslatedFrame {
|
||||
int GetValueCount();
|
||||
|
||||
Kind kind() const { return kind_; }
|
||||
BailoutId node_id() { return node_id_; }
|
||||
JSFunction* raw_function() { return raw_function_; }
|
||||
Handle<JSFunction> function() { return function_; }
|
||||
int height() { return height_; }
|
||||
BailoutId node_id() const { return node_id_; }
|
||||
JSFunction* raw_function() const { return raw_function_; }
|
||||
Handle<JSFunction> function() const { return function_; }
|
||||
int height() const { return height_; }
|
||||
|
||||
class iterator {
|
||||
public:
|
||||
@ -160,8 +160,13 @@ class TranslatedFrame {
|
||||
std::deque<TranslatedValue>::iterator position_;
|
||||
};
|
||||
|
||||
typedef TranslatedValue& reference;
|
||||
typedef TranslatedValue const& const_reference;
|
||||
|
||||
iterator begin() { return iterator(values_.begin()); }
|
||||
iterator end() { return iterator(values_.end()); }
|
||||
reference front() { return values_.front(); }
|
||||
const_reference front() const { return values_.front(); }
|
||||
|
||||
private:
|
||||
friend class TranslatedState;
|
||||
@ -232,6 +237,10 @@ class TranslatedState {
|
||||
// Store newly materialized values into the isolate.
|
||||
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_; }
|
||||
|
||||
TranslatedFrame* GetArgumentsInfoFromJSFrameIndex(int jsframe_index,
|
||||
|
149
src/frames.cc
149
src/frames.cc
@ -884,93 +884,56 @@ void OptimizedFrame::Summarize(List<FrameSummary>* 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
|
||||
// in the deoptimization translation are ordered bottom-to-top.
|
||||
TranslatedState state(this);
|
||||
bool is_constructor = IsConstructor();
|
||||
int i = jsframe_count;
|
||||
while (i > 0) {
|
||||
opcode = static_cast<Translation::Opcode>(it.Next());
|
||||
if (opcode == Translation::JS_FRAME) {
|
||||
i--;
|
||||
BailoutId ast_id = BailoutId(it.Next());
|
||||
JSFunction* function = LiteralAt(literal_array, it.Next());
|
||||
it.Next(); // Skip height.
|
||||
for (TranslatedFrame const& frame : state) {
|
||||
switch (frame.kind()) {
|
||||
case TranslatedFrame::kFunction: {
|
||||
BailoutId const ast_id = frame.node_id();
|
||||
JSFunction* const function = frame.raw_function();
|
||||
|
||||
// The translation commands are ordered and the receiver is always
|
||||
// at the first position.
|
||||
// If we are at a call, the receiver is always in a stack slot.
|
||||
// Otherwise we are not guaranteed to get the receiver value.
|
||||
opcode = static_cast<Translation::Opcode>(it.Next());
|
||||
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);
|
||||
// Get the correct receiver in the optimized frame.
|
||||
Object* receiver = frame.front().GetRawValue();
|
||||
if (receiver == isolate()->heap()->arguments_marker()) {
|
||||
// TODO(jarin): Materializing a captured object (or duplicated
|
||||
// object) is hard, we return undefined for now. This breaks the
|
||||
// produced stack trace, as constructor frames aren't marked as
|
||||
// such anymore.
|
||||
receiver = isolate()->heap()->undefined_value();
|
||||
}
|
||||
} else {
|
||||
// The receiver is not in a stack slot nor in a literal. We give up.
|
||||
// TODO(3029): Materializing a captured object (or duplicated
|
||||
// object) is hard, we return undefined for now. This breaks the
|
||||
// produced stack trace, as constructor frames aren't marked as
|
||||
// such anymore.
|
||||
receiver = isolate()->heap()->undefined_value();
|
||||
|
||||
Code* code = function->shared()->code();
|
||||
DeoptimizationOutputData* output_data =
|
||||
DeoptimizationOutputData::cast(code->deoptimization_data());
|
||||
unsigned entry =
|
||||
Deoptimizer::GetOutputInfo(output_data, ast_id, function->shared());
|
||||
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();
|
||||
DeoptimizationOutputData* output_data =
|
||||
DeoptimizationOutputData::cast(code->deoptimization_data());
|
||||
unsigned entry = Deoptimizer::GetOutputInfo(output_data,
|
||||
ast_id,
|
||||
function->shared());
|
||||
unsigned pc_offset =
|
||||
FullCodeGenerator::PcField::decode(entry) + Code::kHeaderSize;
|
||||
DCHECK(pc_offset > 0);
|
||||
case TranslatedFrame::kConstructStub: {
|
||||
// The next encountered JS_FRAME will be marked as a constructor call.
|
||||
DCHECK(!is_constructor);
|
||||
is_constructor = true;
|
||||
break;
|
||||
}
|
||||
|
||||
FrameSummary summary(receiver, function, code, pc_offset, is_constructor);
|
||||
frames->Add(summary);
|
||||
is_constructor = false;
|
||||
} else if (opcode == Translation::CONSTRUCT_STUB_FRAME) {
|
||||
// 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));
|
||||
case TranslatedFrame::kInvalid:
|
||||
UNREACHABLE();
|
||||
case TranslatedFrame::kArgumentsAdaptor:
|
||||
case TranslatedFrame::kCompiledStub:
|
||||
case TranslatedFrame::kGetter:
|
||||
case TranslatedFrame::kSetter:
|
||||
break;
|
||||
}
|
||||
}
|
||||
DCHECK(!is_constructor);
|
||||
@ -1024,30 +987,10 @@ void OptimizedFrame::GetFunctions(List<JSFunction*>* functions) {
|
||||
return JavaScriptFrame::GetFunctions(functions);
|
||||
}
|
||||
|
||||
int deopt_index = Safepoint::kNoDeoptimizationIndex;
|
||||
DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index);
|
||||
FixedArray* literal_array = data->LiteralArray();
|
||||
|
||||
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));
|
||||
TranslatedState state(this);
|
||||
for (TranslatedFrame const& frame : state) {
|
||||
if (frame.kind() == TranslatedFrame::kFunction) {
|
||||
functions->Add(frame.raw_function());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user