| 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;
|
|
|