Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(184)

Unified Diff: src/deoptimizer.cc

Issue 10908194: Fix arguments object materialization during deopt. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Ported to other architectures. Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/deoptimizer.cc
diff --git a/src/deoptimizer.cc b/src/deoptimizer.cc
index d1b00f8bdea718a71eca5d12d47900cd2f677883..255efca7148eb0d9a97b8df3d2e5fa954e4f1cf5 100644
--- a/src/deoptimizer.cc
+++ b/src/deoptimizer.cc
@@ -27,6 +27,7 @@
#include "v8.h"
+#include "accessors.h"
#include "codegen.h"
#include "deoptimizer.h"
#include "disasm.h"
@@ -368,6 +369,8 @@ Deoptimizer::Deoptimizer(Isolate* isolate,
output_count_(0),
jsframe_count_(0),
output_(NULL),
+ deferred_arguments_objects_values_(0),
+ deferred_arguments_objects_(0),
deferred_heap_numbers_(0) {
if (FLAG_trace_deopt && type != OSR) {
if (type == DEBUGGER) {
@@ -633,8 +636,47 @@ void Deoptimizer::DoComputeOutputFrames() {
}
-void Deoptimizer::MaterializeHeapNumbers() {
+static void MaterializeArgumentsObjectUsingOutputFrame(
+ Isolate* isolate, JavaScriptFrame* frame) {
+ Handle<JSFunction> function(JSFunction::cast(frame->function()), isolate);
+ Handle<Object> arguments;
+ for (int i = frame->ComputeExpressionsCount() - 1; i >= 0; --i) {
+ if (frame->GetExpression(i) == isolate->heap()->arguments_marker()) {
+ if (arguments.is_null()) {
+ // FunctionGetArguments can't throw an exception, so cast away the
+ // doubt with an assert.
+ arguments = Handle<Object>(
+ Accessors::FunctionGetArguments(*function,
+ NULL)->ToObjectUnchecked());
+ ASSERT(*arguments != isolate->heap()->null_value());
+ ASSERT(*arguments != isolate->heap()->undefined_value());
+ }
+ frame->SetExpression(i, *arguments);
+ if (FLAG_trace_deopt) {
+ PrintF("Materializing arguments object for frame %p - %p: ",
+ reinterpret_cast<void*>(frame->sp()),
+ reinterpret_cast<void*>(frame->fp()));
+ arguments->ShortPrint();
+ PrintF("\n");
+ }
+ }
+ }
+}
+
+
+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]));
+ }
+
+ // Play it safe and clear all unhandlified values before we continue.
+ deferred_arguments_objects_values_.Clear();
+
+ // Materialize all heap numbers before looking at arguments.
Sven Panne 2012/09/12 07:14:22 Describe why this is necessary to do before argume
Michael Starzinger 2012/09/12 10:07:28 Done.
for (int i = 0; i < deferred_heap_numbers_.length(); i++) {
HeapNumberMaterializationDescriptor d = deferred_heap_numbers_[i];
Handle<Object> num = isolate_->factory()->NewNumber(d.value());
@@ -644,9 +686,52 @@ void Deoptimizer::MaterializeHeapNumbers() {
d.value(),
d.slot_address());
}
-
Memory::Object_at(d.slot_address()) = *num;
}
+
+ // Materialize arguments objects one frame at a time.
+ int values_index = 0;
+ int arguments_index = 0;
+ for (int frame_index = 0; frame_index < jsframe_count(); ++frame_index) {
+ if (frame_index != 0) it->Advance();
+ JavaScriptFrame* frame = it->frame();
+ Handle<JSFunction> function(JSFunction::cast(frame->function()), isolate_);
+ 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_[arguments_index++];
+ const int length = descriptor.arguments_length();
+ if (arguments.is_null()) {
+ // 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 = 0; i < length; ++i) {
+ array->set(i, *values[values_index++]);
+ }
+ arguments->set_elements(*array);
+ } else {
+ values_index += length;
+ }
+ if (!frame->has_adapted_arguments()) {
Sven Panne 2012/09/12 07:14:22 Can rearrange things a bit here so that we have a
Michael Starzinger 2012/09/12 10:07:28 Done. I removed the static helper method completel
+ frame->SetExpression(i, *arguments);
+ if (FLAG_trace_deopt) {
+ PrintF("Materializing arguments object for %p: ",
+ reinterpret_cast<void*>(descriptor.slot_address()));
+ arguments->ShortPrint();
+ PrintF("\n");
+ }
+ }
+ }
+ }
+ if (frame->has_adapted_arguments()) {
+ MaterializeArgumentsObjectUsingOutputFrame(isolate_, frame);
+ }
+ }
+ ASSERT_EQ(values_index, values.length());
+ ASSERT_EQ(arguments_index, deferred_arguments_objects_.length());
}
@@ -932,8 +1017,8 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
}
case Translation::ARGUMENTS_OBJECT: {
- // Use the arguments marker value as a sentinel and fill in the arguments
- // object after the deoptimized frame is built.
+ int args_index = iterator->Next() + 1; // Skip receiver.
+ int args_length = iterator->Next() - 1; // Skip receiver.
if (FLAG_trace_deopt) {
PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- ",
output_[frame_index]->GetTop() + output_offset,
@@ -941,9 +1026,20 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
isolate_->heap()->arguments_marker()->ShortPrint();
PrintF(" ; arguments object\n");
}
+ // 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);
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 = input_->GetFrameSlot(input_offset);
+ AddArgumentsObjectValue(input_value);
+ }
return;
}
}
@@ -1285,8 +1381,19 @@ Object* Deoptimizer::ComputeLiteral(int index) const {
}
-void Deoptimizer::AddDoubleValue(intptr_t slot_address,
- double value) {
+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::AddArgumentsObjectValue(intptr_t value) {
+ deferred_arguments_objects_values_.Add(reinterpret_cast<Object*>(value));
+}
+
+
+void Deoptimizer::AddDoubleValue(intptr_t slot_address, double value) {
HeapNumberMaterializationDescriptor value_desc(
reinterpret_cast<Address>(slot_address), value);
deferred_heap_numbers_.Add(value_desc);
@@ -1570,8 +1677,10 @@ void Translation::StoreLiteral(int literal_id) {
}
-void Translation::StoreArgumentsObject() {
+void Translation::StoreArgumentsObject(int args_index, int args_length) {
buffer_->Add(ARGUMENTS_OBJECT, zone());
+ buffer_->Add(args_index, zone());
+ buffer_->Add(args_length, zone());
}
@@ -1582,7 +1691,6 @@ void Translation::MarkDuplicate() {
int Translation::NumberOfOperandsFor(Opcode opcode) {
switch (opcode) {
- case ARGUMENTS_OBJECT:
case DUPLICATE:
return 0;
case GETTER_STUB_FRAME:
@@ -1600,6 +1708,7 @@ int Translation::NumberOfOperandsFor(Opcode opcode) {
case BEGIN:
case ARGUMENTS_ADAPTOR_FRAME:
case CONSTRUCT_STUB_FRAME:
+ case ARGUMENTS_OBJECT:
return 2;
case JS_FRAME:
return 3;

Powered by Google App Engine
This is Rietveld 408576698