| Index: src/deoptimizer.cc
|
| diff --git a/src/deoptimizer.cc b/src/deoptimizer.cc
|
| index 14c1d730d01d6f7b5f8e27b314ec463a9d210443..723d3f692e6b3e45e415534d20d21e1eb977ee03 100644
|
| --- a/src/deoptimizer.cc
|
| +++ b/src/deoptimizer.cc
|
| @@ -534,9 +534,8 @@ Deoptimizer::Deoptimizer(Isolate* isolate,
|
| output_count_(0),
|
| jsframe_count_(0),
|
| output_(NULL),
|
| - deferred_objects_tagged_values_(0),
|
| - deferred_objects_double_values_(0),
|
| - deferred_objects_(0),
|
| + deferred_arguments_objects_values_(0),
|
| + deferred_arguments_objects_(0),
|
| deferred_heap_numbers_(0),
|
| trace_(false) {
|
| // For COMPILED_STUBs called from builtins, the function pointer is a SMI
|
| @@ -1567,14 +1566,15 @@ void Deoptimizer::DoComputeCompiledStubFrame(TranslationIterator* iterator,
|
| void Deoptimizer::MaterializeHeapObjects(JavaScriptFrameIterator* it) {
|
| ASSERT_NE(DEBUGGER, bailout_type_);
|
|
|
| - // 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_));
|
| + // 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_));
|
| }
|
|
|
| // Play it safe and clear all unhandlified values before we continue.
|
| - deferred_objects_tagged_values_.Clear();
|
| + deferred_arguments_objects_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,18 +1591,6 @@ 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();
|
| @@ -1611,9 +1599,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()) {
|
| - ObjectMaterializationDescriptor descriptor =
|
| - deferred_objects_.RemoveLast();
|
| - const int length = descriptor.object_length();
|
| + ArgumentsObjectMaterializationDescriptor descriptor =
|
| + deferred_arguments_objects_.RemoveLast();
|
| + const int length = descriptor.arguments_length();
|
| if (arguments.is_null()) {
|
| if (frame->has_adapted_arguments()) {
|
| // Use the arguments adapter frame we just built to materialize the
|
| @@ -1707,7 +1695,7 @@ void Deoptimizer::MaterializeHeapNumbersForDebuggerInspectableFrame(
|
| #endif
|
|
|
|
|
| -static const char* TraceValueType(bool is_smi, bool is_native = false) {
|
| +static const char* TraceValueType(bool is_smi, bool is_native) {
|
| if (is_native) {
|
| return "native";
|
| } else if (is_smi) {
|
| @@ -1718,204 +1706,6 @@ static const char* TraceValueType(bool is_smi, bool is_native = false) {
|
| }
|
|
|
|
|
| -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,
|
| @@ -1968,6 +1758,7 @@ 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",
|
| @@ -2045,7 +1836,8 @@ 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 ": ",
|
| @@ -2063,7 +1855,8 @@ 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);
|
| @@ -2095,7 +1888,8 @@ 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) &&
|
| @@ -2128,7 +1922,8 @@ 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",
|
| @@ -2159,24 +1954,31 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
|
| }
|
|
|
| case Translation::ARGUMENTS_OBJECT: {
|
| - int length = iterator->Next();
|
| + bool args_known = iterator->Next();
|
| + int args_index = iterator->Next() + 1; // Skip receiver.
|
| + int args_length = iterator->Next() - 1; // Skip receiver.
|
| if (trace_) {
|
| PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- ",
|
| output_[frame_index]->GetTop() + output_offset,
|
| output_offset);
|
| isolate_->heap()->arguments_marker()->ShortPrint();
|
| - PrintF(" ; arguments object (length = %d)\n", length);
|
| + PrintF(" ; %sarguments object\n", args_known ? "" : "dummy ");
|
| }
|
| // 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());
|
| - AddObjectStart(output_[frame_index]->GetTop() + output_offset, length);
|
| + AddArgumentsObject(
|
| + output_[frame_index]->GetTop() + output_offset, args_length);
|
| output_[frame_index]->SetFrameSlot(output_offset, 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);
|
| + // 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);
|
| }
|
| return;
|
| }
|
| @@ -2522,22 +2324,15 @@ Object* Deoptimizer::ComputeLiteral(int index) const {
|
| }
|
|
|
|
|
| -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::AddArgumentsObject(intptr_t slot_address, int argc) {
|
| + ArgumentsObjectMaterializationDescriptor object_desc(
|
| + reinterpret_cast<Address>(slot_address), argc);
|
| + deferred_arguments_objects_.Add(object_desc);
|
| }
|
|
|
|
|
| -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);
|
| +void Deoptimizer::AddArgumentsObjectValue(intptr_t value) {
|
| + deferred_arguments_objects_values_.Add(reinterpret_cast<Object*>(value));
|
| }
|
|
|
|
|
| @@ -2761,12 +2556,6 @@ 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());
|
| @@ -2821,6 +2610,16 @@ 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());
|
| }
|
| @@ -2832,7 +2631,6 @@ 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:
|
| @@ -2849,6 +2647,7 @@ int Translation::NumberOfOperandsFor(Opcode opcode) {
|
| case CONSTRUCT_STUB_FRAME:
|
| return 2;
|
| case JS_FRAME:
|
| + case ARGUMENTS_OBJECT:
|
| return 3;
|
| }
|
| UNREACHABLE();
|
|
|