Index: src/deoptimizer.cc |
diff --git a/src/deoptimizer.cc b/src/deoptimizer.cc |
index 8dfe0e181c6b292bede5e1a7d8331d2ca57ac27f..89a06c2d353f95ddeacd527ce297d18e7a120884 100644 |
--- a/src/deoptimizer.cc |
+++ b/src/deoptimizer.cc |
@@ -511,7 +511,7 @@ Code* Deoptimizer::FindOptimizedCode(JSFunction* function) { |
void Deoptimizer::PrintFunctionName() { |
- if (function_ != nullptr && function_->IsJSFunction()) { |
+ if (function_->IsHeapObject() && function_->IsJSFunction()) { |
function_->ShortPrint(trace_scope_->file()); |
} else { |
PrintF(trace_scope_->file(), |
@@ -708,7 +708,10 @@ 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_->IsHeapObject() |
+ ? function_->shared()->internal_formal_parameter_count() |
+ : 0); |
// Do the input frame to output frame(s) translation. |
size_t count = translated_state_.frames().size(); |
@@ -2399,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); |
@@ -2532,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; |
@@ -2790,7 +2799,6 @@ TranslatedValue TranslatedValue::NewArgumentsObject(TranslatedState* container, |
return slot; |
} |
- |
// static |
TranslatedValue TranslatedValue::NewDeferredObject(TranslatedState* container, |
int length, |
@@ -3300,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: |
@@ -3335,16 +3344,74 @@ 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. |
+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); |
+ intptr_t parent_frame_type = Memory::intptr_at( |
+ parent_frame_pointer + CommonFrameConstants::kContextOrFrameTypeOffset); |
+ int length; |
+ Address arguments_frame; |
+ if (parent_frame_type == |
+ StackFrame::TypeToMarker(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) { |
@@ -3366,18 +3433,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: { |
@@ -3388,78 +3467,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: { |
@@ -3471,7 +3593,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: { |
@@ -3483,7 +3608,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: { |
@@ -3494,7 +3621,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: { |
@@ -3505,7 +3635,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: { |
@@ -3516,7 +3648,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: { |
@@ -3527,7 +3661,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: { |
@@ -3539,12 +3676,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 = |
+ TranslatedValue(nullptr, TranslatedValue::kInvalid); |
+ frame.Add(translated_value); |
+ return translated_value.GetChildrenCount(); |
} |
@@ -3559,7 +3702,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()); |
} |
@@ -3568,13 +3712,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 = |
@@ -3589,7 +3734,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)); |
@@ -3612,10 +3757,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"); |
@@ -3623,10 +3767,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(); |