summaryrefslogtreecommitdiff
path: root/chromium/v8/src/deoptimizer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/v8/src/deoptimizer.cc')
-rw-r--r--chromium/v8/src/deoptimizer.cc352
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;