Chromium Code Reviews| Index: src/deoptimizer.cc |
| diff --git a/src/deoptimizer.cc b/src/deoptimizer.cc |
| index f61d40fe21d8e4b4cb09455dc61e956cda38f123..33bb5131a884827e583428eac252f455077d771f 100644 |
| --- a/src/deoptimizer.cc |
| +++ b/src/deoptimizer.cc |
| @@ -708,7 +708,8 @@ void Deoptimizer::DoComputeOutputFrames() { |
| translated_state_.Init( |
| input_->GetFramePointerAddress(), &state_iterator, |
| input_data->LiteralArray(), input_->GetRegisterValues(), |
| - trace_scope_ == nullptr ? nullptr : trace_scope_->file()); |
| + trace_scope_ == nullptr ? nullptr : trace_scope_->file(), |
| + function_ ? function_->shared()->internal_formal_parameter_count() : 0); |
| // Do the input frame to output frame(s) translation. |
| size_t count = translated_state_.frames().size(); |
| @@ -2401,6 +2402,10 @@ void Translation::BeginArgumentsObject(int args_length) { |
| buffer_->Add(args_length); |
| } |
| +void Translation::ArgumentsElements(bool is_rest) { |
| + buffer_->Add(ARGUMENTS_ELEMENTS); |
| + buffer_->Add(is_rest); |
| +} |
| void Translation::BeginCapturedObject(int length) { |
| buffer_->Add(CAPTURED_OBJECT); |
| @@ -2534,6 +2539,8 @@ int Translation::NumberOfOperandsFor(Opcode opcode) { |
| case INTERPRETED_FRAME: |
| case CONSTRUCT_STUB_FRAME: |
| return 3; |
| + case ARGUMENTS_ELEMENTS: |
| + return 1; |
| } |
| FATAL("Unexpected translation type"); |
| return -1; |
| @@ -2792,7 +2799,6 @@ TranslatedValue TranslatedValue::NewArgumentsObject(TranslatedState* container, |
| return slot; |
| } |
| - |
| // static |
| TranslatedValue TranslatedValue::NewDeferredObject(TranslatedState* container, |
| int length, |
| @@ -3302,6 +3308,7 @@ TranslatedFrame TranslatedState::CreateNextTranslatedFrame( |
| case Translation::BEGIN: |
| case Translation::DUPLICATED_OBJECT: |
| case Translation::ARGUMENTS_OBJECT: |
| + case Translation::ARGUMENTS_ELEMENTS: |
| case Translation::CAPTURED_OBJECT: |
| case Translation::REGISTER: |
| case Translation::INT32_REGISTER: |
| @@ -3337,16 +3344,73 @@ void TranslatedFrame::AdvanceIterator( |
| } |
| } |
| +// Creates translated values for an arguments backing store, or the backing |
| +// store for the rest parameters if {is_rest} is true. The TranslatedValue |
| +// objects for the fields are not read from the TranslationIterator, but instead |
| +// created on-the-fly based on dynamic information in the optimized frame. |
|
Jarin
2017/02/27 13:24:34
Awesome, thanks for the comments here and below!
|
| +void TranslatedState::CreateArgumentsElementsTranslatedValues( |
| + int frame_index, Address input_frame_pointer, bool is_rest) { |
| + TranslatedFrame& frame = frames_[frame_index]; |
| + |
| + Address parent_frame_pointer = *reinterpret_cast<Address*>( |
| + input_frame_pointer + StandardFrameConstants::kCallerFPOffset); |
| + Object* parent_frame_type = *reinterpret_cast<Object**>( |
| + parent_frame_pointer + CommonFrameConstants::kContextOrFrameTypeOffset); |
| + int length; |
| + Address arguments_frame; |
| + if (parent_frame_type == Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)) { |
| + length = Smi::cast(*reinterpret_cast<Object**>( |
| + parent_frame_pointer + |
| + ArgumentsAdaptorFrameConstants::kLengthOffset)) |
| + ->value(); |
| + arguments_frame = parent_frame_pointer; |
| + } else { |
| + length = formal_parameter_count_; |
| + arguments_frame = input_frame_pointer; |
| + } |
| + |
| + if (is_rest) { |
| + // If the actual number of arguments is less than the number of formal |
| + // parameters, we have zero rest parameters. |
| + length = std::max(0, length - formal_parameter_count_); |
| + } |
| + |
| + int object_index = static_cast<int>(object_positions_.size()); |
| + int value_index = static_cast<int>(frame.values_.size()); |
| + object_positions_.push_back({frame_index, value_index}); |
| + frame.Add(TranslatedValue::NewDeferredObject( |
| + this, length + FixedArray::kHeaderSize / kPointerSize, object_index)); |
| + |
| + frame.Add( |
| + TranslatedValue::NewTagged(this, isolate_->heap()->fixed_array_map())); |
| + frame.Add(TranslatedValue::NewInt32(this, length)); |
| + |
| + for (int i = length - 1; i >= 0; --i) { |
| + Address argument_slot = arguments_frame + |
| + CommonFrameConstants::kFixedFrameSizeAboveFp + |
| + i * kPointerSize; |
| + frame.Add(TranslatedValue::NewTagged( |
| + this, *reinterpret_cast<Object**>(argument_slot))); |
| + } |
| +} |
| -// We can't intermix stack decoding and allocations because |
| -// deoptimization infrastracture is not GC safe. |
| +// We can't intermix stack decoding and allocations because the deoptimization |
| +// infrastracture is not GC safe. |
| // Thus we build a temporary structure in malloced space. |
| -TranslatedValue TranslatedState::CreateNextTranslatedValue( |
| - int frame_index, int value_index, TranslationIterator* iterator, |
| - FixedArray* literal_array, Address fp, RegisterValues* registers, |
| - FILE* trace_file) { |
| +// The TranslatedValue objects created correspond to the static translation |
| +// instructions from the TranslationIterator, except for |
| +// Translation::ARGUMENTS_ELEMENTS, where the number and values of the |
| +// FixedArray elements depend on dynamic information from the optimized frame. |
| +// Returns the number of expected nested translations from the |
| +// TranslationIterator. |
| +int TranslatedState::CreateNextTranslatedValue( |
| + int frame_index, TranslationIterator* iterator, FixedArray* literal_array, |
| + Address fp, RegisterValues* registers, FILE* trace_file) { |
| disasm::NameConverter converter; |
| + TranslatedFrame& frame = frames_[frame_index]; |
| + int value_index = static_cast<int>(frame.values_.size()); |
| + |
| Translation::Opcode opcode = |
| static_cast<Translation::Opcode>(iterator->Next()); |
| switch (opcode) { |
| @@ -3368,18 +3432,30 @@ TranslatedValue TranslatedState::CreateNextTranslatedValue( |
| PrintF(trace_file, "duplicated object #%d", object_id); |
| } |
| object_positions_.push_back(object_positions_[object_id]); |
| - return TranslatedValue::NewDuplicateObject(this, object_id); |
| + TranslatedValue translated_value = |
| + TranslatedValue::NewDuplicateObject(this, object_id); |
| + frame.Add(translated_value); |
| + return translated_value.GetChildrenCount(); |
| } |
| case Translation::ARGUMENTS_OBJECT: { |
| int arg_count = iterator->Next(); |
| int object_index = static_cast<int>(object_positions_.size()); |
| if (trace_file != nullptr) { |
| - PrintF(trace_file, "argumets object #%d (length = %d)", object_index, |
| + PrintF(trace_file, "arguments object #%d (length = %d)", object_index, |
| arg_count); |
| } |
| object_positions_.push_back({frame_index, value_index}); |
| - return TranslatedValue::NewArgumentsObject(this, arg_count, object_index); |
| + TranslatedValue translated_value = |
| + TranslatedValue::NewArgumentsObject(this, arg_count, object_index); |
| + frame.Add(translated_value); |
| + return translated_value.GetChildrenCount(); |
| + } |
| + |
| + case Translation::ARGUMENTS_ELEMENTS: { |
| + bool is_rest = iterator->Next(); |
| + CreateArgumentsElementsTranslatedValues(frame_index, fp, is_rest); |
| + return 0; |
| } |
| case Translation::CAPTURED_OBJECT: { |
| @@ -3390,78 +3466,121 @@ TranslatedValue TranslatedState::CreateNextTranslatedValue( |
| field_count); |
| } |
| object_positions_.push_back({frame_index, value_index}); |
| - return TranslatedValue::NewDeferredObject(this, field_count, |
| - object_index); |
| + TranslatedValue translated_value = |
| + TranslatedValue::NewDeferredObject(this, field_count, object_index); |
| + frame.Add(translated_value); |
| + return translated_value.GetChildrenCount(); |
| } |
| case Translation::REGISTER: { |
| int input_reg = iterator->Next(); |
| - if (registers == nullptr) return TranslatedValue::NewInvalid(this); |
| + if (registers == nullptr) { |
| + TranslatedValue translated_value = TranslatedValue::NewInvalid(this); |
| + frame.Add(translated_value); |
| + return translated_value.GetChildrenCount(); |
| + } |
| intptr_t value = registers->GetRegister(input_reg); |
| if (trace_file != nullptr) { |
| PrintF(trace_file, "0x%08" V8PRIxPTR " ; %s ", value, |
| converter.NameOfCPURegister(input_reg)); |
| reinterpret_cast<Object*>(value)->ShortPrint(trace_file); |
| } |
| - return TranslatedValue::NewTagged(this, reinterpret_cast<Object*>(value)); |
| + TranslatedValue translated_value = |
| + TranslatedValue::NewTagged(this, reinterpret_cast<Object*>(value)); |
| + frame.Add(translated_value); |
| + return translated_value.GetChildrenCount(); |
| } |
| case Translation::INT32_REGISTER: { |
| int input_reg = iterator->Next(); |
| - if (registers == nullptr) return TranslatedValue::NewInvalid(this); |
| + if (registers == nullptr) { |
| + TranslatedValue translated_value = TranslatedValue::NewInvalid(this); |
| + frame.Add(translated_value); |
| + return translated_value.GetChildrenCount(); |
| + } |
| intptr_t value = registers->GetRegister(input_reg); |
| if (trace_file != nullptr) { |
| PrintF(trace_file, "%" V8PRIdPTR " ; %s ", value, |
| converter.NameOfCPURegister(input_reg)); |
| } |
| - return TranslatedValue::NewInt32(this, static_cast<int32_t>(value)); |
| + TranslatedValue translated_value = |
| + TranslatedValue::NewInt32(this, static_cast<int32_t>(value)); |
| + frame.Add(translated_value); |
| + return translated_value.GetChildrenCount(); |
| } |
| case Translation::UINT32_REGISTER: { |
| int input_reg = iterator->Next(); |
| - if (registers == nullptr) return TranslatedValue::NewInvalid(this); |
| + if (registers == nullptr) { |
| + TranslatedValue translated_value = TranslatedValue::NewInvalid(this); |
| + frame.Add(translated_value); |
| + return translated_value.GetChildrenCount(); |
| + } |
| intptr_t value = registers->GetRegister(input_reg); |
| if (trace_file != nullptr) { |
| PrintF(trace_file, "%" V8PRIuPTR " ; %s (uint)", value, |
| converter.NameOfCPURegister(input_reg)); |
| reinterpret_cast<Object*>(value)->ShortPrint(trace_file); |
| } |
| - return TranslatedValue::NewUInt32(this, static_cast<uint32_t>(value)); |
| + TranslatedValue translated_value = |
| + TranslatedValue::NewUInt32(this, static_cast<uint32_t>(value)); |
| + frame.Add(translated_value); |
| + return translated_value.GetChildrenCount(); |
| } |
| case Translation::BOOL_REGISTER: { |
| int input_reg = iterator->Next(); |
| - if (registers == nullptr) return TranslatedValue::NewInvalid(this); |
| + if (registers == nullptr) { |
| + TranslatedValue translated_value = TranslatedValue::NewInvalid(this); |
| + frame.Add(translated_value); |
| + return translated_value.GetChildrenCount(); |
| + } |
| intptr_t value = registers->GetRegister(input_reg); |
| if (trace_file != nullptr) { |
| PrintF(trace_file, "%" V8PRIdPTR " ; %s (bool)", value, |
| converter.NameOfCPURegister(input_reg)); |
| } |
| - return TranslatedValue::NewBool(this, static_cast<uint32_t>(value)); |
| + TranslatedValue translated_value = |
| + TranslatedValue::NewBool(this, static_cast<uint32_t>(value)); |
| + frame.Add(translated_value); |
| + return translated_value.GetChildrenCount(); |
| } |
| case Translation::FLOAT_REGISTER: { |
| int input_reg = iterator->Next(); |
| - if (registers == nullptr) return TranslatedValue::NewInvalid(this); |
| + if (registers == nullptr) { |
| + TranslatedValue translated_value = TranslatedValue::NewInvalid(this); |
| + frame.Add(translated_value); |
| + return translated_value.GetChildrenCount(); |
| + } |
| Float32 value = registers->GetFloatRegister(input_reg); |
| if (trace_file != nullptr) { |
| PrintF(trace_file, "%e ; %s (float)", value.get_scalar(), |
| RegisterConfiguration::Crankshaft()->GetFloatRegisterName( |
| input_reg)); |
| } |
| - return TranslatedValue::NewFloat(this, value); |
| + TranslatedValue translated_value = TranslatedValue::NewFloat(this, value); |
| + frame.Add(translated_value); |
| + return translated_value.GetChildrenCount(); |
| } |
| case Translation::DOUBLE_REGISTER: { |
| int input_reg = iterator->Next(); |
| - if (registers == nullptr) return TranslatedValue::NewInvalid(this); |
| + if (registers == nullptr) { |
| + TranslatedValue translated_value = TranslatedValue::NewInvalid(this); |
| + frame.Add(translated_value); |
| + return translated_value.GetChildrenCount(); |
| + } |
| Float64 value = registers->GetDoubleRegister(input_reg); |
| if (trace_file != nullptr) { |
| PrintF(trace_file, "%e ; %s (double)", value.get_scalar(), |
| RegisterConfiguration::Crankshaft()->GetDoubleRegisterName( |
| input_reg)); |
| } |
| - return TranslatedValue::NewDouble(this, value); |
| + TranslatedValue translated_value = |
| + TranslatedValue::NewDouble(this, value); |
| + frame.Add(translated_value); |
| + return translated_value.GetChildrenCount(); |
| } |
| case Translation::STACK_SLOT: { |
| @@ -3473,7 +3592,10 @@ TranslatedValue TranslatedState::CreateNextTranslatedValue( |
| slot_offset < 0 ? '-' : '+', std::abs(slot_offset)); |
| reinterpret_cast<Object*>(value)->ShortPrint(trace_file); |
| } |
| - return TranslatedValue::NewTagged(this, reinterpret_cast<Object*>(value)); |
| + TranslatedValue translated_value = |
| + TranslatedValue::NewTagged(this, reinterpret_cast<Object*>(value)); |
| + frame.Add(translated_value); |
| + return translated_value.GetChildrenCount(); |
| } |
| case Translation::INT32_STACK_SLOT: { |
| @@ -3485,7 +3607,9 @@ TranslatedValue TranslatedState::CreateNextTranslatedValue( |
| static_cast<int32_t>(value), slot_offset < 0 ? '-' : '+', |
| std::abs(slot_offset)); |
| } |
| - return TranslatedValue::NewInt32(this, value); |
| + TranslatedValue translated_value = TranslatedValue::NewInt32(this, value); |
| + frame.Add(translated_value); |
| + return translated_value.GetChildrenCount(); |
| } |
| case Translation::UINT32_STACK_SLOT: { |
| @@ -3496,7 +3620,10 @@ TranslatedValue TranslatedState::CreateNextTranslatedValue( |
| PrintF(trace_file, "%u ; (uint) [fp %c %d] ", value, |
| slot_offset < 0 ? '-' : '+', std::abs(slot_offset)); |
| } |
| - return TranslatedValue::NewUInt32(this, value); |
| + TranslatedValue translated_value = |
| + TranslatedValue::NewUInt32(this, value); |
| + frame.Add(translated_value); |
| + return translated_value.GetChildrenCount(); |
| } |
| case Translation::BOOL_STACK_SLOT: { |
| @@ -3507,7 +3634,9 @@ TranslatedValue TranslatedState::CreateNextTranslatedValue( |
| PrintF(trace_file, "%u ; (bool) [fp %c %d] ", value, |
| slot_offset < 0 ? '-' : '+', std::abs(slot_offset)); |
| } |
| - return TranslatedValue::NewBool(this, value); |
| + TranslatedValue translated_value = TranslatedValue::NewBool(this, value); |
| + frame.Add(translated_value); |
| + return translated_value.GetChildrenCount(); |
| } |
| case Translation::FLOAT_STACK_SLOT: { |
| @@ -3518,7 +3647,9 @@ TranslatedValue TranslatedState::CreateNextTranslatedValue( |
| PrintF(trace_file, "%e ; (float) [fp %c %d] ", value.get_scalar(), |
| slot_offset < 0 ? '-' : '+', std::abs(slot_offset)); |
| } |
| - return TranslatedValue::NewFloat(this, value); |
| + TranslatedValue translated_value = TranslatedValue::NewFloat(this, value); |
| + frame.Add(translated_value); |
| + return translated_value.GetChildrenCount(); |
| } |
| case Translation::DOUBLE_STACK_SLOT: { |
| @@ -3529,7 +3660,10 @@ TranslatedValue TranslatedState::CreateNextTranslatedValue( |
| PrintF(trace_file, "%e ; (double) [fp %c %d] ", value.get_scalar(), |
| slot_offset < 0 ? '-' : '+', std::abs(slot_offset)); |
| } |
| - return TranslatedValue::NewDouble(this, value); |
| + TranslatedValue translated_value = |
| + TranslatedValue::NewDouble(this, value); |
| + frame.Add(translated_value); |
| + return translated_value.GetChildrenCount(); |
| } |
| case Translation::LITERAL: { |
| @@ -3541,12 +3675,18 @@ TranslatedValue TranslatedState::CreateNextTranslatedValue( |
| reinterpret_cast<Object*>(value)->ShortPrint(trace_file); |
| } |
| - return TranslatedValue::NewTagged(this, value); |
| + TranslatedValue translated_value = |
| + TranslatedValue::NewTagged(this, value); |
| + frame.Add(translated_value); |
| + return translated_value.GetChildrenCount(); |
| } |
| } |
| FATAL("We should never get here - unexpected deopt info."); |
| - return TranslatedValue(nullptr, TranslatedValue::kInvalid); |
| + TranslatedValue translated_value = |
|
Jarin
2017/02/27 13:24:34
This is unreachable code. Just say "return 0;" her
|
| + TranslatedValue(nullptr, TranslatedValue::kInvalid); |
| + frame.Add(translated_value); |
| + return translated_value.GetChildrenCount(); |
| } |
| @@ -3561,7 +3701,8 @@ TranslatedState::TranslatedState(JavaScriptFrame* frame) |
| TranslationIterator it(data->TranslationByteArray(), |
| data->TranslationIndex(deopt_index)->value()); |
| Init(frame->fp(), &it, data->LiteralArray(), nullptr /* registers */, |
| - nullptr /* trace file */); |
| + nullptr /* trace file */, |
| + frame->function()->shared()->internal_formal_parameter_count()); |
| } |
| @@ -3570,13 +3711,14 @@ TranslatedState::TranslatedState() |
| stack_frame_pointer_(nullptr), |
| has_adapted_arguments_(false) {} |
| - |
| void TranslatedState::Init(Address input_frame_pointer, |
| TranslationIterator* iterator, |
| FixedArray* literal_array, RegisterValues* registers, |
| - FILE* trace_file) { |
| + FILE* trace_file, int formal_parameter_count) { |
| DCHECK(frames_.empty()); |
| + formal_parameter_count_ = formal_parameter_count; |
| + |
| isolate_ = literal_array->GetIsolate(); |
| // Read out the 'header' translation. |
| Translation::Opcode opcode = |
| @@ -3591,7 +3733,7 @@ void TranslatedState::Init(Address input_frame_pointer, |
| std::stack<int> nested_counts; |
| // Read the frames |
| - for (int i = 0; i < count; i++) { |
| + for (int frame_index = 0; frame_index < count; frame_index++) { |
| // Read the frame descriptor. |
| frames_.push_back(CreateNextTranslatedFrame( |
| iterator, literal_array, input_frame_pointer, trace_file)); |
| @@ -3614,10 +3756,9 @@ void TranslatedState::Init(Address input_frame_pointer, |
| } |
| } |
| - TranslatedValue value = CreateNextTranslatedValue( |
| - i, static_cast<int>(frame.values_.size()), iterator, literal_array, |
| - input_frame_pointer, registers, trace_file); |
| - frame.Add(value); |
| + int nested_count = |
| + CreateNextTranslatedValue(frame_index, iterator, literal_array, |
| + input_frame_pointer, registers, trace_file); |
| if (trace_file != nullptr) { |
| PrintF(trace_file, "\n"); |
| @@ -3625,10 +3766,9 @@ void TranslatedState::Init(Address input_frame_pointer, |
| // Update the value count and resolve the nesting. |
| values_to_process--; |
| - int children_count = value.GetChildrenCount(); |
| - if (children_count > 0) { |
| + if (nested_count > 0) { |
| nested_counts.push(values_to_process); |
| - values_to_process = children_count; |
| + values_to_process = nested_count; |
| } else { |
| while (values_to_process == 0 && !nested_counts.empty()) { |
| values_to_process = nested_counts.top(); |