| Index: src/deoptimizer.cc
|
| diff --git a/src/deoptimizer.cc b/src/deoptimizer.cc
|
| index 723d3f692e6b3e45e415534d20d21e1eb977ee03..14c1d730d01d6f7b5f8e27b314ec463a9d210443 100644
|
| --- a/src/deoptimizer.cc
|
| +++ b/src/deoptimizer.cc
|
| @@ -534,8 +534,9 @@ Deoptimizer::Deoptimizer(Isolate* isolate,
|
| output_count_(0),
|
| jsframe_count_(0),
|
| output_(NULL),
|
| - deferred_arguments_objects_values_(0),
|
| - deferred_arguments_objects_(0),
|
| + deferred_objects_tagged_values_(0),
|
| + deferred_objects_double_values_(0),
|
| + deferred_objects_(0),
|
| deferred_heap_numbers_(0),
|
| trace_(false) {
|
| // For COMPILED_STUBs called from builtins, the function pointer is a SMI
|
| @@ -1566,15 +1567,14 @@ void Deoptimizer::DoComputeCompiledStubFrame(TranslationIterator* iterator,
|
| void Deoptimizer::MaterializeHeapObjects(JavaScriptFrameIterator* it) {
|
| ASSERT_NE(DEBUGGER, bailout_type_);
|
|
|
| - // Handlify all argument object values before triggering any allocation.
|
| - List<Handle<Object> > values(deferred_arguments_objects_values_.length());
|
| - for (int i = 0; i < deferred_arguments_objects_values_.length(); ++i) {
|
| - values.Add(Handle<Object>(deferred_arguments_objects_values_[i],
|
| - isolate_));
|
| + // Handlify all tagged object values before triggering any allocation.
|
| + List<Handle<Object> > values(deferred_objects_tagged_values_.length());
|
| + for (int i = 0; i < deferred_objects_tagged_values_.length(); ++i) {
|
| + values.Add(Handle<Object>(deferred_objects_tagged_values_[i], isolate_));
|
| }
|
|
|
| // Play it safe and clear all unhandlified values before we continue.
|
| - deferred_arguments_objects_values_.Clear();
|
| + deferred_objects_tagged_values_.Clear();
|
|
|
| // Materialize all heap numbers before looking at arguments because when the
|
| // output frames are used to materialize arguments objects later on they need
|
| @@ -1591,6 +1591,18 @@ void Deoptimizer::MaterializeHeapObjects(JavaScriptFrameIterator* it) {
|
| Memory::Object_at(d.slot_address()) = *num;
|
| }
|
|
|
| + // Materialize all heap numbers required for arguments objects.
|
| + for (int i = 0; i < values.length(); i++) {
|
| + if (!values.at(i)->IsTheHole()) continue;
|
| + double double_value = deferred_objects_double_values_[i];
|
| + Handle<Object> num = isolate_->factory()->NewNumber(double_value);
|
| + if (trace_) {
|
| + PrintF("Materializing a new heap number %p [%e] for arguments object\n",
|
| + reinterpret_cast<void*>(*num), double_value);
|
| + }
|
| + values.Set(i, num);
|
| + }
|
| +
|
| // Materialize arguments objects one frame at a time.
|
| for (int frame_index = 0; frame_index < jsframe_count(); ++frame_index) {
|
| if (frame_index != 0) it->Advance();
|
| @@ -1599,9 +1611,9 @@ void Deoptimizer::MaterializeHeapObjects(JavaScriptFrameIterator* it) {
|
| Handle<JSObject> arguments;
|
| for (int i = frame->ComputeExpressionsCount() - 1; i >= 0; --i) {
|
| if (frame->GetExpression(i) == isolate_->heap()->arguments_marker()) {
|
| - ArgumentsObjectMaterializationDescriptor descriptor =
|
| - deferred_arguments_objects_.RemoveLast();
|
| - const int length = descriptor.arguments_length();
|
| + ObjectMaterializationDescriptor descriptor =
|
| + deferred_objects_.RemoveLast();
|
| + const int length = descriptor.object_length();
|
| if (arguments.is_null()) {
|
| if (frame->has_adapted_arguments()) {
|
| // Use the arguments adapter frame we just built to materialize the
|
| @@ -1695,7 +1707,7 @@ void Deoptimizer::MaterializeHeapNumbersForDebuggerInspectableFrame(
|
| #endif
|
|
|
|
|
| -static const char* TraceValueType(bool is_smi, bool is_native) {
|
| +static const char* TraceValueType(bool is_smi, bool is_native = false) {
|
| if (is_native) {
|
| return "native";
|
| } else if (is_smi) {
|
| @@ -1706,6 +1718,204 @@ static const char* TraceValueType(bool is_smi, bool is_native) {
|
| }
|
|
|
|
|
| +void Deoptimizer::DoTranslateObject(TranslationIterator* iterator,
|
| + int object_opcode,
|
| + int field_index) {
|
| + disasm::NameConverter converter;
|
| + Address object_slot = deferred_objects_.last().slot_address();
|
| +
|
| + // Ignore commands marked as duplicate and act on the first non-duplicate.
|
| + Translation::Opcode opcode =
|
| + static_cast<Translation::Opcode>(iterator->Next());
|
| + while (opcode == Translation::DUPLICATE) {
|
| + opcode = static_cast<Translation::Opcode>(iterator->Next());
|
| + iterator->Skip(Translation::NumberOfOperandsFor(opcode));
|
| + opcode = static_cast<Translation::Opcode>(iterator->Next());
|
| + }
|
| +
|
| + switch (opcode) {
|
| + case Translation::BEGIN:
|
| + case Translation::JS_FRAME:
|
| + case Translation::ARGUMENTS_ADAPTOR_FRAME:
|
| + case Translation::CONSTRUCT_STUB_FRAME:
|
| + case Translation::GETTER_STUB_FRAME:
|
| + case Translation::SETTER_STUB_FRAME:
|
| + case Translation::COMPILED_STUB_FRAME:
|
| + case Translation::ARGUMENTS_OBJECT:
|
| + case Translation::DUPLICATE:
|
| + UNREACHABLE();
|
| + return;
|
| +
|
| + case Translation::REGISTER: {
|
| + int input_reg = iterator->Next();
|
| + intptr_t input_value = input_->GetRegister(input_reg);
|
| + if (trace_) {
|
| + PrintF(" object @0x%08" V8PRIxPTR ": [field #%d] <- ",
|
| + reinterpret_cast<intptr_t>(object_slot),
|
| + field_index);
|
| + PrintF("0x%08" V8PRIxPTR " ; %s ", input_value,
|
| + converter.NameOfCPURegister(input_reg));
|
| + reinterpret_cast<Object*>(input_value)->ShortPrint();
|
| + PrintF("\n");
|
| + }
|
| + AddObjectTaggedValue(input_value);
|
| + return;
|
| + }
|
| +
|
| + case Translation::INT32_REGISTER: {
|
| + int input_reg = iterator->Next();
|
| + intptr_t value = input_->GetRegister(input_reg);
|
| + bool is_smi = Smi::IsValid(value);
|
| + if (trace_) {
|
| + PrintF(" object @0x%08" V8PRIxPTR ": [field #%d] <- ",
|
| + reinterpret_cast<intptr_t>(object_slot),
|
| + field_index);
|
| + PrintF("%" V8PRIdPTR " ; %s (%s)\n", value,
|
| + converter.NameOfCPURegister(input_reg),
|
| + TraceValueType(is_smi));
|
| + }
|
| + if (is_smi) {
|
| + intptr_t tagged_value =
|
| + reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
|
| + AddObjectTaggedValue(tagged_value);
|
| + } else {
|
| + double double_value = static_cast<double>(static_cast<int32_t>(value));
|
| + AddObjectDoubleValue(double_value);
|
| + }
|
| + return;
|
| + }
|
| +
|
| + case Translation::UINT32_REGISTER: {
|
| + int input_reg = iterator->Next();
|
| + uintptr_t value = static_cast<uintptr_t>(input_->GetRegister(input_reg));
|
| + bool is_smi = (value <= static_cast<uintptr_t>(Smi::kMaxValue));
|
| + if (trace_) {
|
| + PrintF(" object @0x%08" V8PRIxPTR ": [field #%d] <- ",
|
| + reinterpret_cast<intptr_t>(object_slot),
|
| + field_index);
|
| + PrintF("%" V8PRIdPTR " ; uint %s (%s)\n", value,
|
| + converter.NameOfCPURegister(input_reg),
|
| + TraceValueType(is_smi));
|
| + }
|
| + if (is_smi) {
|
| + intptr_t tagged_value =
|
| + reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
|
| + AddObjectTaggedValue(tagged_value);
|
| + } else {
|
| + double double_value = static_cast<double>(static_cast<uint32_t>(value));
|
| + AddObjectDoubleValue(double_value);
|
| + }
|
| + return;
|
| + }
|
| +
|
| + case Translation::DOUBLE_REGISTER: {
|
| + int input_reg = iterator->Next();
|
| + double value = input_->GetDoubleRegister(input_reg);
|
| + if (trace_) {
|
| + PrintF(" object @0x%08" V8PRIxPTR ": [field #%d] <- ",
|
| + reinterpret_cast<intptr_t>(object_slot),
|
| + field_index);
|
| + PrintF("%e ; %s\n", value,
|
| + DoubleRegister::AllocationIndexToString(input_reg));
|
| + }
|
| + AddObjectDoubleValue(value);
|
| + return;
|
| + }
|
| +
|
| + case Translation::STACK_SLOT: {
|
| + int input_slot_index = iterator->Next();
|
| + unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
|
| + intptr_t input_value = input_->GetFrameSlot(input_offset);
|
| + if (trace_) {
|
| + PrintF(" object @0x%08" V8PRIxPTR ": [field #%d] <- ",
|
| + reinterpret_cast<intptr_t>(object_slot),
|
| + field_index);
|
| + PrintF("0x%08" V8PRIxPTR " ; [sp + %d] ", input_value, input_offset);
|
| + reinterpret_cast<Object*>(input_value)->ShortPrint();
|
| + PrintF("\n");
|
| + }
|
| + AddObjectTaggedValue(input_value);
|
| + return;
|
| + }
|
| +
|
| + case Translation::INT32_STACK_SLOT: {
|
| + int input_slot_index = iterator->Next();
|
| + unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
|
| + intptr_t value = input_->GetFrameSlot(input_offset);
|
| + bool is_smi = Smi::IsValid(value);
|
| + if (trace_) {
|
| + PrintF(" object @0x%08" V8PRIxPTR ": [field #%d] <- ",
|
| + reinterpret_cast<intptr_t>(object_slot),
|
| + field_index);
|
| + PrintF("%" V8PRIdPTR " ; [sp + %d] (%s)\n",
|
| + value, input_offset, TraceValueType(is_smi));
|
| + }
|
| + if (is_smi) {
|
| + intptr_t tagged_value =
|
| + reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
|
| + AddObjectTaggedValue(tagged_value);
|
| + } else {
|
| + double double_value = static_cast<double>(static_cast<int32_t>(value));
|
| + AddObjectDoubleValue(double_value);
|
| + }
|
| + return;
|
| + }
|
| +
|
| + case Translation::UINT32_STACK_SLOT: {
|
| + int input_slot_index = iterator->Next();
|
| + unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
|
| + uintptr_t value =
|
| + static_cast<uintptr_t>(input_->GetFrameSlot(input_offset));
|
| + bool is_smi = (value <= static_cast<uintptr_t>(Smi::kMaxValue));
|
| + if (trace_) {
|
| + PrintF(" object @0x%08" V8PRIxPTR ": [field #%d] <- ",
|
| + reinterpret_cast<intptr_t>(object_slot),
|
| + field_index);
|
| + PrintF("%" V8PRIdPTR " ; [sp + %d] (uint %s)\n",
|
| + value, input_offset, TraceValueType(is_smi));
|
| + }
|
| + if (is_smi) {
|
| + intptr_t tagged_value =
|
| + reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
|
| + AddObjectTaggedValue(tagged_value);
|
| + } else {
|
| + double double_value = static_cast<double>(static_cast<uint32_t>(value));
|
| + AddObjectDoubleValue(double_value);
|
| + }
|
| + return;
|
| + }
|
| +
|
| + case Translation::DOUBLE_STACK_SLOT: {
|
| + int input_slot_index = iterator->Next();
|
| + unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
|
| + double value = input_->GetDoubleFrameSlot(input_offset);
|
| + if (trace_) {
|
| + PrintF(" object @0x%08" V8PRIxPTR ": [field #%d] <- ",
|
| + reinterpret_cast<intptr_t>(object_slot),
|
| + field_index);
|
| + PrintF("%e ; [sp + %d]\n", value, input_offset);
|
| + }
|
| + AddObjectDoubleValue(value);
|
| + return;
|
| + }
|
| +
|
| + case Translation::LITERAL: {
|
| + Object* literal = ComputeLiteral(iterator->Next());
|
| + if (trace_) {
|
| + PrintF(" object @0x%08" V8PRIxPTR ": [field #%d] <- ",
|
| + reinterpret_cast<intptr_t>(object_slot),
|
| + field_index);
|
| + literal->ShortPrint();
|
| + PrintF(" ; literal\n");
|
| + }
|
| + intptr_t value = reinterpret_cast<intptr_t>(literal);
|
| + AddObjectTaggedValue(value);
|
| + return;
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
|
| int frame_index,
|
| unsigned output_offset,
|
| @@ -1758,7 +1968,6 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
|
| intptr_t value = input_->GetRegister(input_reg);
|
| bool is_smi = (value_type == TRANSLATED_VALUE_IS_TAGGED) &&
|
| Smi::IsValid(value);
|
| -
|
| if (trace_) {
|
| PrintF(
|
| " 0x%08" V8PRIxPTR ": [top + %d] <- %" V8PRIdPTR " ; %s (%s)\n",
|
| @@ -1836,8 +2045,7 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
|
|
|
| case Translation::STACK_SLOT: {
|
| int input_slot_index = iterator->Next();
|
| - unsigned input_offset =
|
| - input_->GetOffsetFromSlotIndex(input_slot_index);
|
| + unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
|
| intptr_t input_value = input_->GetFrameSlot(input_offset);
|
| if (trace_) {
|
| PrintF(" 0x%08" V8PRIxPTR ": ",
|
| @@ -1855,8 +2063,7 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
|
|
|
| case Translation::INT32_STACK_SLOT: {
|
| int input_slot_index = iterator->Next();
|
| - unsigned input_offset =
|
| - input_->GetOffsetFromSlotIndex(input_slot_index);
|
| + unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
|
| intptr_t value = input_->GetFrameSlot(input_offset);
|
| bool is_smi = (value_type == TRANSLATED_VALUE_IS_TAGGED) &&
|
| Smi::IsValid(value);
|
| @@ -1888,8 +2095,7 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
|
|
|
| case Translation::UINT32_STACK_SLOT: {
|
| int input_slot_index = iterator->Next();
|
| - unsigned input_offset =
|
| - input_->GetOffsetFromSlotIndex(input_slot_index);
|
| + unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
|
| uintptr_t value =
|
| static_cast<uintptr_t>(input_->GetFrameSlot(input_offset));
|
| bool is_smi = (value_type == TRANSLATED_VALUE_IS_TAGGED) &&
|
| @@ -1922,8 +2128,7 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
|
|
|
| case Translation::DOUBLE_STACK_SLOT: {
|
| int input_slot_index = iterator->Next();
|
| - unsigned input_offset =
|
| - input_->GetOffsetFromSlotIndex(input_slot_index);
|
| + unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
|
| double value = input_->GetDoubleFrameSlot(input_offset);
|
| if (trace_) {
|
| PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- %e ; [sp + %d]\n",
|
| @@ -1954,31 +2159,24 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
|
| }
|
|
|
| case Translation::ARGUMENTS_OBJECT: {
|
| - bool args_known = iterator->Next();
|
| - int args_index = iterator->Next() + 1; // Skip receiver.
|
| - int args_length = iterator->Next() - 1; // Skip receiver.
|
| + int length = iterator->Next();
|
| if (trace_) {
|
| PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- ",
|
| output_[frame_index]->GetTop() + output_offset,
|
| output_offset);
|
| isolate_->heap()->arguments_marker()->ShortPrint();
|
| - PrintF(" ; %sarguments object\n", args_known ? "" : "dummy ");
|
| + PrintF(" ; arguments object (length = %d)\n", length);
|
| }
|
| // Use the arguments marker value as a sentinel and fill in the arguments
|
| // object after the deoptimized frame is built.
|
| intptr_t value = reinterpret_cast<intptr_t>(
|
| isolate_->heap()->arguments_marker());
|
| - AddArgumentsObject(
|
| - output_[frame_index]->GetTop() + output_offset, args_length);
|
| + AddObjectStart(output_[frame_index]->GetTop() + output_offset, length);
|
| output_[frame_index]->SetFrameSlot(output_offset, value);
|
| - // We save the tagged argument values on the side and materialize the
|
| - // actual arguments object after the deoptimized frame is built.
|
| - for (int i = 0; i < args_length; i++) {
|
| - unsigned input_offset = input_->GetOffsetFromSlotIndex(args_index + i);
|
| - intptr_t input_value = args_known
|
| - ? input_->GetFrameSlot(input_offset)
|
| - : reinterpret_cast<intptr_t>(isolate_->heap()->the_hole_value());
|
| - AddArgumentsObjectValue(input_value);
|
| + // We save the argument values on the side and materialize the actual
|
| + // arguments object after the deoptimized frame is built.
|
| + for (int i = 0; i < length; i++) {
|
| + DoTranslateObject(iterator, Translation::ARGUMENTS_OBJECT, i);
|
| }
|
| return;
|
| }
|
| @@ -2324,15 +2522,22 @@ Object* Deoptimizer::ComputeLiteral(int index) const {
|
| }
|
|
|
|
|
| -void Deoptimizer::AddArgumentsObject(intptr_t slot_address, int argc) {
|
| - ArgumentsObjectMaterializationDescriptor object_desc(
|
| - reinterpret_cast<Address>(slot_address), argc);
|
| - deferred_arguments_objects_.Add(object_desc);
|
| +void Deoptimizer::AddObjectStart(intptr_t slot_address, int length) {
|
| + ObjectMaterializationDescriptor object_desc(
|
| + reinterpret_cast<Address>(slot_address), length);
|
| + deferred_objects_.Add(object_desc);
|
| }
|
|
|
|
|
| -void Deoptimizer::AddArgumentsObjectValue(intptr_t value) {
|
| - deferred_arguments_objects_values_.Add(reinterpret_cast<Object*>(value));
|
| +void Deoptimizer::AddObjectTaggedValue(intptr_t value) {
|
| + deferred_objects_tagged_values_.Add(reinterpret_cast<Object*>(value));
|
| + deferred_objects_double_values_.Add(isolate()->heap()->nan_value()->value());
|
| +}
|
| +
|
| +
|
| +void Deoptimizer::AddObjectDoubleValue(double value) {
|
| + deferred_objects_tagged_values_.Add(isolate()->heap()->the_hole_value());
|
| + deferred_objects_double_values_.Add(value);
|
| }
|
|
|
|
|
| @@ -2556,6 +2761,12 @@ void Translation::BeginCompiledStubFrame() {
|
| }
|
|
|
|
|
| +void Translation::BeginArgumentsObject(int args_length) {
|
| + buffer_->Add(ARGUMENTS_OBJECT, zone());
|
| + buffer_->Add(args_length, zone());
|
| +}
|
| +
|
| +
|
| void Translation::StoreRegister(Register reg) {
|
| buffer_->Add(REGISTER, zone());
|
| buffer_->Add(reg.code(), zone());
|
| @@ -2610,16 +2821,6 @@ void Translation::StoreLiteral(int literal_id) {
|
| }
|
|
|
|
|
| -void Translation::StoreArgumentsObject(bool args_known,
|
| - int args_index,
|
| - int args_length) {
|
| - buffer_->Add(ARGUMENTS_OBJECT, zone());
|
| - buffer_->Add(args_known, zone());
|
| - buffer_->Add(args_index, zone());
|
| - buffer_->Add(args_length, zone());
|
| -}
|
| -
|
| -
|
| void Translation::MarkDuplicate() {
|
| buffer_->Add(DUPLICATE, zone());
|
| }
|
| @@ -2631,6 +2832,7 @@ int Translation::NumberOfOperandsFor(Opcode opcode) {
|
| return 0;
|
| case GETTER_STUB_FRAME:
|
| case SETTER_STUB_FRAME:
|
| + case ARGUMENTS_OBJECT:
|
| case REGISTER:
|
| case INT32_REGISTER:
|
| case UINT32_REGISTER:
|
| @@ -2647,7 +2849,6 @@ int Translation::NumberOfOperandsFor(Opcode opcode) {
|
| case CONSTRUCT_STUB_FRAME:
|
| return 2;
|
| case JS_FRAME:
|
| - case ARGUMENTS_OBJECT:
|
| return 3;
|
| }
|
| UNREACHABLE();
|
|
|