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

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: Improved test coverage and fixed bug. 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
« no previous file with comments | « src/deoptimizer.h ('k') | src/hydrogen.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/deoptimizer.cc
diff --git a/src/deoptimizer.cc b/src/deoptimizer.cc
index d1b00f8bdea718a71eca5d12d47900cd2f677883..d7d392a966a8203cbe236a03d79c8656dd207203 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,21 @@ void Deoptimizer::DoComputeOutputFrames() {
}
-void Deoptimizer::MaterializeHeapNumbers() {
+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 because when the
+ // output frames are used to materialize arguments objects later on they need
+ // to already contain valid heap numbers.
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 +660,55 @@ void Deoptimizer::MaterializeHeapNumbers() {
d.value(),
d.slot_address());
}
-
Memory::Object_at(d.slot_address()) = *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();
+ 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_.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
+ // arguments object. FunctionGetArguments can't throw an exception,
+ // so cast away the doubt with an assert.
+ arguments = Handle<JSObject>(JSObject::cast(
+ Accessors::FunctionGetArguments(*function,
+ NULL)->ToObjectUnchecked()));
+ 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 (FLAG_trace_deopt) {
+ PrintF("Materializing %sarguments object for %p: ",
+ frame->has_adapted_arguments() ? "(adapted) " : "",
+ reinterpret_cast<void*>(descriptor.slot_address()));
+ arguments->ShortPrint();
+ PrintF("\n");
+ }
+ }
+ }
+ }
}
@@ -932,8 +994,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 +1003,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 +1358,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 +1654,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 +1668,6 @@ void Translation::MarkDuplicate() {
int Translation::NumberOfOperandsFor(Opcode opcode) {
switch (opcode) {
- case ARGUMENTS_OBJECT:
case DUPLICATE:
return 0;
case GETTER_STUB_FRAME:
@@ -1600,6 +1685,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;
« no previous file with comments | « src/deoptimizer.h ('k') | src/hydrogen.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698