diff options
Diffstat (limited to 'chromium/v8/src/deoptimizer.cc')
-rw-r--r-- | chromium/v8/src/deoptimizer.cc | 352 |
1 files changed, 93 insertions, 259 deletions
diff --git a/chromium/v8/src/deoptimizer.cc b/chromium/v8/src/deoptimizer.cc index dc9ffc51186..53b9b76377f 100644 --- a/chromium/v8/src/deoptimizer.cc +++ b/chromium/v8/src/deoptimizer.cc @@ -602,12 +602,6 @@ Deoptimizer::Deoptimizer(Isolate* isolate, deferred_objects_double_values_(0), deferred_objects_(0), deferred_heap_numbers_(0), - jsframe_functions_(0), - jsframe_has_adapted_arguments_(0), - materialized_values_(NULL), - materialized_objects_(NULL), - materialization_value_index_(0), - materialization_object_index_(0), trace_(false) { // For COMPILED_STUBs called from builtins, the function pointer is a SMI // indicating an internal frame. @@ -1214,15 +1208,7 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator, unsigned output_offset = output_frame_size; for (int i = 0; i < parameter_count; ++i) { output_offset -= kPointerSize; - int deferred_object_index = deferred_objects_.length(); DoTranslateCommand(iterator, frame_index, output_offset); - // The allocated receiver of a construct stub frame is passed as the - // receiver parameter through the translation. It might be encoding - // a captured object, patch the slot address for a captured object. - if (i == 0 && deferred_objects_.length() > deferred_object_index) { - ASSERT(!deferred_objects_[deferred_object_index].is_arguments()); - deferred_objects_[deferred_object_index].patch_slot_address(top_address); - } } // Read caller's PC from the previous frame. @@ -1647,93 +1633,9 @@ void Deoptimizer::DoComputeCompiledStubFrame(TranslationIterator* iterator, } -Handle<Object> Deoptimizer::MaterializeNextHeapObject() { - int object_index = materialization_object_index_++; - ObjectMaterializationDescriptor desc = deferred_objects_[object_index]; - const int length = desc.object_length(); - - if (desc.duplicate_object() >= 0) { - // Found a previously materialized object by de-duplication. - object_index = desc.duplicate_object(); - materialized_objects_->Add(Handle<Object>()); - } else if (desc.is_arguments() && ArgumentsObjectIsAdapted(object_index)) { - // Use the arguments adapter frame we just built to materialize the - // arguments object. FunctionGetArguments can't throw an exception. - Handle<JSFunction> function = ArgumentsObjectFunction(object_index); - Handle<JSObject> arguments = Handle<JSObject>::cast( - Accessors::FunctionGetArguments(function)); - materialized_objects_->Add(arguments); - materialization_value_index_ += length; - } else if (desc.is_arguments()) { - // Construct an arguments object and copy the parameters to a newly - // allocated arguments object backing store. - Handle<JSFunction> function = ArgumentsObjectFunction(object_index); - Handle<JSObject> arguments = - isolate_->factory()->NewArgumentsObject(function, length); - Handle<FixedArray> array = isolate_->factory()->NewFixedArray(length); - ASSERT(array->length() == length); - arguments->set_elements(*array); - materialized_objects_->Add(arguments); - for (int i = 0; i < length; ++i) { - Handle<Object> value = MaterializeNextValue(); - array->set(i, *value); - } - } else { - // Dispatch on the instance type of the object to be materialized. - Handle<Map> map = Handle<Map>::cast(MaterializeNextValue()); - switch (map->instance_type()) { - case HEAP_NUMBER_TYPE: { - Handle<HeapNumber> number = - Handle<HeapNumber>::cast(MaterializeNextValue()); - materialized_objects_->Add(number); - materialization_value_index_ += kDoubleSize / kPointerSize - 1; - break; - } - case JS_OBJECT_TYPE: { - Handle<JSObject> object = - isolate_->factory()->NewJSObjectFromMap(map, NOT_TENURED, false); - materialized_objects_->Add(object); - Handle<Object> properties = MaterializeNextValue(); - Handle<Object> elements = MaterializeNextValue(); - object->set_properties(FixedArray::cast(*properties)); - object->set_elements(FixedArray::cast(*elements)); - for (int i = 0; i < length - 3; ++i) { - Handle<Object> value = MaterializeNextValue(); - object->FastPropertyAtPut(i, *value); - } - break; - } - default: - PrintF("[couldn't handle instance type %d]\n", map->instance_type()); - UNREACHABLE(); - } - } - - return materialized_objects_->at(object_index); -} - - -Handle<Object> Deoptimizer::MaterializeNextValue() { - int value_index = materialization_value_index_++; - Handle<Object> value = materialized_values_->at(value_index); - if (*value == isolate_->heap()->arguments_marker()) { - value = MaterializeNextHeapObject(); - } - return value; -} - - void Deoptimizer::MaterializeHeapObjects(JavaScriptFrameIterator* it) { ASSERT_NE(DEBUGGER, bailout_type_); - // Walk all JavaScript output frames with the given frame iterator. - for (int frame_index = 0; frame_index < jsframe_count(); ++frame_index) { - if (frame_index != 0) it->Advance(); - JavaScriptFrame* frame = it->frame(); - jsframe_functions_.Add(handle(frame->function(), isolate_)); - jsframe_has_adapted_arguments_.Add(frame->has_adapted_arguments()); - } - // 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) { @@ -1750,7 +1652,7 @@ void Deoptimizer::MaterializeHeapObjects(JavaScriptFrameIterator* it) { HeapNumberMaterializationDescriptor d = deferred_heap_numbers_[i]; Handle<Object> num = isolate_->factory()->NewNumber(d.value()); if (trace_) { - PrintF("Materialized a new heap number %p [%e] in slot %p\n", + PrintF("Materializing a new heap number %p [%e] in slot %p\n", reinterpret_cast<void*>(*num), d.value(), d.slot_address()); @@ -1758,52 +1660,62 @@ void Deoptimizer::MaterializeHeapObjects(JavaScriptFrameIterator* it) { Memory::Object_at(d.slot_address()) = *num; } - // Materialize all heap numbers required for arguments/captured objects. + // 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("Materialized a new heap number %p [%e] for object\n", + PrintF("Materializing a new heap number %p [%e] for arguments object\n", reinterpret_cast<void*>(*num), double_value); } values.Set(i, num); } - // Materialize arguments/captured objects. - if (!deferred_objects_.is_empty()) { - List<Handle<Object> > materialized_objects(deferred_objects_.length()); - materialized_objects_ = &materialized_objects; - materialized_values_ = &values; - - while (materialization_object_index_ < deferred_objects_.length()) { - int object_index = materialization_object_index_; - ObjectMaterializationDescriptor descriptor = - deferred_objects_.at(object_index); - - // Find a previously materialized object by de-duplication or - // materialize a new instance of the object if necessary. Store - // the materialized object into the frame slot. - Handle<Object> object = MaterializeNextHeapObject(); - Memory::Object_at(descriptor.slot_address()) = *object; - if (trace_) { - if (descriptor.is_arguments()) { - PrintF("Materialized %sarguments object of length %d for %p: ", - ArgumentsObjectIsAdapted(object_index) ? "(adapted) " : "", - Handle<JSObject>::cast(object)->elements()->length(), - reinterpret_cast<void*>(descriptor.slot_address())); - } else { - PrintF("Materialized captured object of size %d for %p: ", - Handle<HeapObject>::cast(object)->Size(), + // 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(); + JavaScriptFrame* frame = it->frame(); + Handle<JSFunction> function(frame->function(), isolate_); + 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(); + if (arguments.is_null()) { + if (frame->has_adapted_arguments()) { + // Use the arguments adapter frame we just built to materialize the + // arguments object. FunctionGetArguments can't throw an exception. + arguments = Handle<JSObject>::cast( + Accessors::FunctionGetArguments(function)); + values.RewindBy(length); + } else { + // Construct an arguments object and copy the parameters to a newly + // allocated arguments object backing store. + arguments = + isolate_->factory()->NewArgumentsObject(function, length); + Handle<FixedArray> array = + isolate_->factory()->NewFixedArray(length); + ASSERT(array->length() == length); + for (int i = length - 1; i >= 0 ; --i) { + array->set(i, *values.RemoveLast()); + } + arguments->set_elements(*array); + } + } + frame->SetExpression(i, *arguments); + ASSERT_EQ(Memory::Object_at(descriptor.slot_address()), *arguments); + if (trace_) { + PrintF("Materializing %sarguments object of length %d for %p: ", + frame->has_adapted_arguments() ? "(adapted) " : "", + arguments->elements()->length(), reinterpret_cast<void*>(descriptor.slot_address())); + arguments->ShortPrint(); + PrintF("\n"); } - object->ShortPrint(); - PrintF("\n"); } } - - ASSERT(materialization_object_index_ == materialized_objects_->length()); - ASSERT(materialization_value_index_ == materialized_values_->length()); } } @@ -1874,10 +1786,10 @@ static const char* TraceValueType(bool is_smi, bool is_native = false) { void Deoptimizer::DoTranslateObject(TranslationIterator* iterator, - int object_index, + int object_opcode, int field_index) { disasm::NameConverter converter; - Address object_slot = deferred_objects_[object_index].slot_address(); + Address object_slot = deferred_objects_.last().slot_address(); Translation::Opcode opcode = static_cast<Translation::Opcode>(iterator->Next()); @@ -1890,6 +1802,7 @@ void Deoptimizer::DoTranslateObject(TranslationIterator* iterator, case Translation::GETTER_STUB_FRAME: case Translation::SETTER_STUB_FRAME: case Translation::COMPILED_STUB_FRAME: + case Translation::ARGUMENTS_OBJECT: UNREACHABLE(); return; @@ -2059,50 +1972,6 @@ void Deoptimizer::DoTranslateObject(TranslationIterator* iterator, AddObjectTaggedValue(value); return; } - - case Translation::DUPLICATED_OBJECT: { - int object_index = iterator->Next(); - if (trace_) { - PrintF(" nested @0x%08" V8PRIxPTR ": [field #%d] <- ", - reinterpret_cast<intptr_t>(object_slot), - field_index); - isolate_->heap()->arguments_marker()->ShortPrint(); - PrintF(" ; duplicate of object #%d\n", object_index); - } - // Use the materialization marker value as a sentinel and fill in - // the object after the deoptimized frame is built. - intptr_t value = reinterpret_cast<intptr_t>( - isolate_->heap()->arguments_marker()); - AddObjectDuplication(0, object_index); - AddObjectTaggedValue(value); - return; - } - - case Translation::ARGUMENTS_OBJECT: - case Translation::CAPTURED_OBJECT: { - int length = iterator->Next(); - bool is_args = opcode == Translation::ARGUMENTS_OBJECT; - if (trace_) { - PrintF(" nested @0x%08" V8PRIxPTR ": [field #%d] <- ", - reinterpret_cast<intptr_t>(object_slot), - field_index); - isolate_->heap()->arguments_marker()->ShortPrint(); - PrintF(" ; object (length = %d, is_args = %d)\n", length, is_args); - } - // Use the materialization marker value as a sentinel and fill in - // the object after the deoptimized frame is built. - intptr_t value = reinterpret_cast<intptr_t>( - isolate_->heap()->arguments_marker()); - AddObjectStart(0, length, is_args); - AddObjectTaggedValue(value); - // We save the object values on the side and materialize the actual - // object after the deoptimized frame is built. - int object_index = deferred_objects_.length() - 1; - for (int i = 0; i < length; i++) { - DoTranslateObject(iterator, object_index, i); - } - return; - } } } @@ -2342,48 +2211,25 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator, return; } - case Translation::DUPLICATED_OBJECT: { - int object_index = iterator->Next(); - if (trace_) { - PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- ", - output_[frame_index]->GetTop() + output_offset, - output_offset); - isolate_->heap()->arguments_marker()->ShortPrint(); - PrintF(" ; duplicate of object #%d\n", object_index); - } - // Use the materialization marker value as a sentinel and fill in - // the object after the deoptimized frame is built. - intptr_t value = reinterpret_cast<intptr_t>( - isolate_->heap()->arguments_marker()); - AddObjectDuplication(output_[frame_index]->GetTop() + output_offset, - object_index); - output_[frame_index]->SetFrameSlot(output_offset, value); - return; - } - - case Translation::ARGUMENTS_OBJECT: - case Translation::CAPTURED_OBJECT: { + case Translation::ARGUMENTS_OBJECT: { int length = iterator->Next(); - bool is_args = opcode == Translation::ARGUMENTS_OBJECT; if (trace_) { PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- ", output_[frame_index]->GetTop() + output_offset, output_offset); isolate_->heap()->arguments_marker()->ShortPrint(); - PrintF(" ; object (length = %d, is_args = %d)\n", length, is_args); + PrintF(" ; arguments object (length = %d)\n", length); } - // Use the materialization marker value as a sentinel and fill in - // the object after the deoptimized frame is built. + // 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, is_args); + AddObjectStart(output_[frame_index]->GetTop() + output_offset, length); output_[frame_index]->SetFrameSlot(output_offset, value); - // We save the object values on the side and materialize the actual - // object after the deoptimized frame is built. - int object_index = deferred_objects_.length() - 1; + // 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, object_index, i); + DoTranslateObject(iterator, Translation::ARGUMENTS_OBJECT, i); } return; } @@ -2560,9 +2406,7 @@ bool Deoptimizer::DoOsrTranslateCommand(TranslationIterator* iterator, break; } - case Translation::DUPLICATED_OBJECT: - case Translation::ARGUMENTS_OBJECT: - case Translation::CAPTURED_OBJECT: { + case Translation::ARGUMENTS_OBJECT: { // Optimized code assumes that the argument object has not been // materialized and so bypasses it when doing arguments access. // We should have bailed out before starting the frame @@ -2582,19 +2426,25 @@ void Deoptimizer::PatchInterruptCode(Code* unoptimized_code, Code* replacement_code) { // Iterate over the back edge table and patch every interrupt // call to an unconditional call to the replacement code. + ASSERT(unoptimized_code->kind() == Code::FUNCTION); int loop_nesting_level = unoptimized_code->allow_osr_at_loop_nesting_level(); - - for (FullCodeGenerator::BackEdgeTableIterator back_edges(unoptimized_code); - !back_edges.Done(); - back_edges.Next()) { - if (static_cast<int>(back_edges.loop_depth()) == loop_nesting_level) { + Address back_edge_cursor = unoptimized_code->instruction_start() + + unoptimized_code->back_edge_table_offset(); + uint32_t table_length = Memory::uint32_at(back_edge_cursor); + back_edge_cursor += kIntSize; + for (uint32_t i = 0; i < table_length; ++i) { + uint32_t loop_depth = Memory::uint32_at(back_edge_cursor + 2 * kIntSize); + if (static_cast<int>(loop_depth) == loop_nesting_level) { + // Loop back edge has the loop depth that we want to patch. + uint32_t pc_offset = Memory::uint32_at(back_edge_cursor + kIntSize); + Address pc_after = unoptimized_code->instruction_start() + pc_offset; PatchInterruptCodeAt(unoptimized_code, - back_edges.pc(), + pc_after, interrupt_code, replacement_code); } + back_edge_cursor += FullCodeGenerator::kBackEdgeEntrySize; } - unoptimized_code->set_back_edges_patched_for_osr(true); #ifdef DEBUG Deoptimizer::VerifyInterruptCode( @@ -2607,20 +2457,25 @@ void Deoptimizer::RevertInterruptCode(Code* unoptimized_code, Code* interrupt_code, Code* replacement_code) { // Iterate over the back edge table and revert the patched interrupt calls. + ASSERT(unoptimized_code->kind() == Code::FUNCTION); ASSERT(unoptimized_code->back_edges_patched_for_osr()); int loop_nesting_level = unoptimized_code->allow_osr_at_loop_nesting_level(); - - for (FullCodeGenerator::BackEdgeTableIterator back_edges(unoptimized_code); - !back_edges.Done(); - back_edges.Next()) { - if (static_cast<int>(back_edges.loop_depth()) <= loop_nesting_level) { + Address back_edge_cursor = unoptimized_code->instruction_start() + + unoptimized_code->back_edge_table_offset(); + uint32_t table_length = Memory::uint32_at(back_edge_cursor); + back_edge_cursor += kIntSize; + for (uint32_t i = 0; i < table_length; ++i) { + uint32_t loop_depth = Memory::uint32_at(back_edge_cursor + 2 * kIntSize); + if (static_cast<int>(loop_depth) <= loop_nesting_level) { + uint32_t pc_offset = Memory::uint32_at(back_edge_cursor + kIntSize); + Address pc_after = unoptimized_code->instruction_start() + pc_offset; RevertInterruptCodeAt(unoptimized_code, - back_edges.pc(), + pc_after, interrupt_code, replacement_code); } + back_edge_cursor += FullCodeGenerator::kBackEdgeEntrySize; } - unoptimized_code->set_back_edges_patched_for_osr(false); unoptimized_code->set_allow_osr_at_loop_nesting_level(0); #ifdef DEBUG @@ -2636,18 +2491,24 @@ void Deoptimizer::VerifyInterruptCode(Code* unoptimized_code, Code* interrupt_code, Code* replacement_code, int loop_nesting_level) { - for (FullCodeGenerator::BackEdgeTableIterator back_edges(unoptimized_code); - !back_edges.Done(); - back_edges.Next()) { - uint32_t loop_depth = back_edges.loop_depth(); + CHECK(unoptimized_code->kind() == Code::FUNCTION); + Address back_edge_cursor = unoptimized_code->instruction_start() + + unoptimized_code->back_edge_table_offset(); + uint32_t table_length = Memory::uint32_at(back_edge_cursor); + back_edge_cursor += kIntSize; + for (uint32_t i = 0; i < table_length; ++i) { + uint32_t loop_depth = Memory::uint32_at(back_edge_cursor + 2 * kIntSize); CHECK_LE(static_cast<int>(loop_depth), Code::kMaxLoopNestingMarker); // Assert that all back edges for shallower loops (and only those) // have already been patched. + uint32_t pc_offset = Memory::uint32_at(back_edge_cursor + kIntSize); + Address pc_after = unoptimized_code->instruction_start() + pc_offset; CHECK_EQ((static_cast<int>(loop_depth) <= loop_nesting_level), InterruptCodeIsPatched(unoptimized_code, - back_edges.pc(), + pc_after, interrupt_code, replacement_code)); + back_edge_cursor += FullCodeGenerator::kBackEdgeEntrySize; } } #endif // DEBUG @@ -2710,16 +2571,9 @@ Object* Deoptimizer::ComputeLiteral(int index) const { } -void Deoptimizer::AddObjectStart(intptr_t slot, int length, bool is_args) { +void Deoptimizer::AddObjectStart(intptr_t slot_address, int length) { ObjectMaterializationDescriptor object_desc( - reinterpret_cast<Address>(slot), jsframe_count_, length, -1, is_args); - deferred_objects_.Add(object_desc); -} - - -void Deoptimizer::AddObjectDuplication(intptr_t slot, int object_index) { - ObjectMaterializationDescriptor object_desc( - reinterpret_cast<Address>(slot), jsframe_count_, -1, object_index, false); + reinterpret_cast<Address>(slot_address), length); deferred_objects_.Add(object_desc); } @@ -2947,18 +2801,6 @@ void Translation::BeginArgumentsObject(int args_length) { } -void Translation::BeginCapturedObject(int length) { - buffer_->Add(CAPTURED_OBJECT, zone()); - buffer_->Add(length, zone()); -} - - -void Translation::DuplicateObject(int object_index) { - buffer_->Add(DUPLICATED_OBJECT, zone()); - buffer_->Add(object_index, zone()); -} - - void Translation::StoreRegister(Register reg) { buffer_->Add(REGISTER, zone()); buffer_->Add(reg.code(), zone()); @@ -3027,9 +2869,7 @@ int Translation::NumberOfOperandsFor(Opcode opcode) { switch (opcode) { case GETTER_STUB_FRAME: case SETTER_STUB_FRAME: - case DUPLICATED_OBJECT: case ARGUMENTS_OBJECT: - case CAPTURED_OBJECT: case REGISTER: case INT32_REGISTER: case UINT32_REGISTER: @@ -3089,12 +2929,8 @@ const char* Translation::StringFor(Opcode opcode) { return "DOUBLE_STACK_SLOT"; case LITERAL: return "LITERAL"; - case DUPLICATED_OBJECT: - return "DUPLICATED_OBJECT"; case ARGUMENTS_OBJECT: return "ARGUMENTS_OBJECT"; - case CAPTURED_OBJECT: - return "CAPTURED_OBJECT"; } UNREACHABLE(); return ""; @@ -3138,9 +2974,7 @@ SlotRef SlotRef::ComputeSlotForNextArgument(TranslationIterator* iterator, // Peeled off before getting here. break; - case Translation::DUPLICATED_OBJECT: case Translation::ARGUMENTS_OBJECT: - case Translation::CAPTURED_OBJECT: // This can be only emitted for local slots not for argument slots. break; |