Chromium Code Reviews| Index: src/deoptimizer.cc |
| diff --git a/src/deoptimizer.cc b/src/deoptimizer.cc |
| index aab69c3422abb5450248ddc7cd695fa9192b2f81..f452acf7ef2526d017cbfd1531827f75bc4c81a6 100644 |
| --- a/src/deoptimizer.cc |
| +++ b/src/deoptimizer.cc |
| @@ -1,4 +1,4 @@ |
| -// Copyright 2011 the V8 project authors. All rights reserved. |
| +// Copyright 2012 the V8 project authors. All rights reserved. |
| // Redistribution and use in source and binary forms, with or without |
| // modification, are permitted provided that the following conditions are |
| // met: |
| @@ -104,10 +104,27 @@ Deoptimizer* Deoptimizer::Grab(Isolate* isolate) { |
| return result; |
| } |
| + |
| +int Deoptimizer::ConvertJSFrameIndexToFrameIndex(int jsframe_index) { |
| + if (jsframe_index == 0) return 0; |
| + |
| + int frame_index = 0; |
| + while (jsframe_index >= 0) { |
| + FrameDescription* frame = output_[frame_index]; |
| + if (frame->GetType() == StackFrame::JAVA_SCRIPT) { |
| + jsframe_index--; |
| + } |
| + frame_index++; |
| + } |
| + |
| + return frame_index - 1; |
| +} |
| + |
| + |
| #ifdef ENABLE_DEBUGGER_SUPPORT |
| DeoptimizedFrameInfo* Deoptimizer::DebuggerInspectableFrame( |
| JavaScriptFrame* frame, |
| - int frame_index, |
| + int jsframe_index, |
| Isolate* isolate) { |
| ASSERT(isolate == Isolate::Current()); |
| ASSERT(frame->is_optimized()); |
| @@ -143,22 +160,40 @@ DeoptimizedFrameInfo* Deoptimizer::DebuggerInspectableFrame( |
| // Create the GC safe output frame information and register it for GC |
| // handling. |
| - ASSERT_LT(frame_index, deoptimizer->output_count()); |
| + ASSERT_LT(jsframe_index, deoptimizer->jsframe_count()); |
| + |
| + // Convert JS frame index into frame index. |
| + int frame_index = deoptimizer->ConvertJSFrameIndexToFrameIndex(jsframe_index); |
| + |
| + bool has_arguments_adaptor = |
| + frame_index > 0 && |
| + deoptimizer->output_[frame_index - 1]->GetType() == |
| + StackFrame::ARGUMENTS_ADAPTOR; |
| + |
| DeoptimizedFrameInfo* info = |
| - new DeoptimizedFrameInfo(deoptimizer, frame_index); |
| + new DeoptimizedFrameInfo(deoptimizer, frame_index, has_arguments_adaptor); |
| isolate->deoptimizer_data()->deoptimized_frame_info_ = info; |
| // Get the "simulated" top and size for the requested frame. |
| - Address top = |
| - reinterpret_cast<Address>(deoptimizer->output_[frame_index]->GetTop()); |
| - uint32_t size = deoptimizer->output_[frame_index]->GetFrameSize(); |
| + FrameDescription* parameters_frame = |
| + deoptimizer->output_[ |
| + has_arguments_adaptor ? (frame_index - 1) : frame_index]; |
| + |
| + uint32_t parameters_size = (info->parameters_count() + 1) * kPointerSize; |
| + Address parameters_top = reinterpret_cast<Address>( |
| + parameters_frame->GetTop() + (parameters_frame->GetFrameSize() - |
| + parameters_size)); |
| + |
| + uint32_t expressions_size = info->expression_count() * kPointerSize; |
| + Address expressions_top = reinterpret_cast<Address>( |
| + deoptimizer->output_[frame_index]->GetTop()); |
| // Done with the GC-unsafe frame descriptions. This re-enables allocation. |
| deoptimizer->DeleteFrameDescriptions(); |
| // Allocate a heap number for the doubles belonging to this frame. |
| deoptimizer->MaterializeHeapNumbersForDebuggerInspectableFrame( |
| - top, size, info); |
| + parameters_top, parameters_size, expressions_top, expressions_size, info); |
| // Finished using the deoptimizer instance. |
| delete deoptimizer; |
| @@ -313,6 +348,7 @@ Deoptimizer::Deoptimizer(Isolate* isolate, |
| fp_to_sp_delta_(fp_to_sp_delta), |
| input_(NULL), |
| output_count_(0), |
| + jsframe_count_(0), |
| output_(NULL), |
| frame_alignment_marker_(isolate->heap()->frame_alignment_marker()), |
| has_alignment_padding_(0), |
| @@ -380,6 +416,7 @@ Deoptimizer::Deoptimizer(Isolate* isolate, |
| #ifdef DEBUG |
| input_->SetKind(Code::OPTIMIZED_FUNCTION); |
| #endif |
| + input_->SetType(StackFrame::JAVA_SCRIPT); |
| } |
| @@ -515,6 +552,7 @@ void Deoptimizer::DoComputeOutputFrames() { |
| // Read the number of output frames and allocate an array for their |
| // descriptions. |
| int count = iterator.Next(); |
| + iterator.Next(); // Drop JS frames count. |
| ASSERT(output_ == NULL); |
| output_ = new FrameDescription*[count]; |
| for (int i = 0; i < count; ++i) { |
| @@ -524,7 +562,21 @@ void Deoptimizer::DoComputeOutputFrames() { |
| // Translate each output frame. |
| for (int i = 0; i < count; ++i) { |
| - DoComputeFrame(&iterator, i); |
| + // Read the ast node id, function, and frame height for this output frame. |
| + Translation::Opcode opcode = |
| + static_cast<Translation::Opcode>(iterator.Next()); |
| + switch (opcode) { |
| + case Translation::JS_FRAME: |
| + DoComputeJSFrame(&iterator, i); |
| + jsframe_count_++; |
| + break; |
| + case Translation::ARGUMENTS_ADAPTOR_FRAME: |
| + DoComputeArgumentsAdaptorFrame(&iterator, i); |
| + break; |
| + default: |
| + UNREACHABLE(); |
| + break; |
| + } |
| } |
| // Print some helpful diagnostic information. |
| @@ -565,39 +617,52 @@ void Deoptimizer::MaterializeHeapNumbers() { |
| #ifdef ENABLE_DEBUGGER_SUPPORT |
| void Deoptimizer::MaterializeHeapNumbersForDebuggerInspectableFrame( |
| - Address top, uint32_t size, DeoptimizedFrameInfo* info) { |
| + Address parameters_top, |
| + uint32_t parameters_size, |
| + Address expressions_top, |
| + uint32_t expressions_size, |
| + DeoptimizedFrameInfo* info) { |
| ASSERT_EQ(DEBUGGER, bailout_type_); |
| + Address parameters_bot = parameters_top + parameters_size; |
|
Kevin Millikin (Chromium)
2012/01/24 00:08:54
_bottom reads better.
|
| + Address expressions_bot = expressions_top + expressions_size; |
| for (int i = 0; i < deferred_heap_numbers_.length(); i++) { |
| HeapNumberMaterializationDescriptor d = deferred_heap_numbers_[i]; |
| // Check of the heap number to materialize actually belong to the frame |
| // being extracted. |
| Address slot = d.slot_address(); |
| - if (top <= slot && slot < top + size) { |
| + if (parameters_top <= slot && slot < parameters_bot) { |
| Handle<Object> num = isolate_->factory()->NewNumber(d.value()); |
| - // Calculate the index with the botton of the expression stack |
| - // at index 0, and the fixed part (including incoming arguments) |
| - // at negative indexes. |
| - int index = static_cast<int>( |
| - info->expression_count_ - (slot - top) / kPointerSize - 1); |
| + |
| + int index = (info->parameters_count() - 1) - |
| + (slot - parameters_top) / kPointerSize; |
| + |
| if (FLAG_trace_deopt) { |
| PrintF("Materializing a new heap number %p [%e] in slot %p" |
| - "for stack index %d\n", |
| + "for parameter slot #%d\n", |
| reinterpret_cast<void*>(*num), |
| d.value(), |
| d.slot_address(), |
| index); |
| } |
| - if (index >=0) { |
| - info->SetExpression(index, *num); |
| - } else { |
| - // Calculate parameter index subtracting one for the receiver. |
| - int parameter_index = |
| - index + |
| - static_cast<int>(size) / kPointerSize - |
| - info->expression_count_ - 1; |
| - info->SetParameter(parameter_index, *num); |
| + |
| + info->SetParameter(index, *num); |
| + } else if (expressions_top <= slot && slot < expressions_bot) { |
| + Handle<Object> num = isolate_->factory()->NewNumber(d.value()); |
| + |
| + int index = info->expression_count() - 1 - |
| + (slot - expressions_top) / kPointerSize; |
| + |
| + if (FLAG_trace_deopt) { |
| + PrintF("Materializing a new heap number %p [%e] in slot %p" |
| + "for expression slot #%d\n", |
| + reinterpret_cast<void*>(*num), |
| + d.value(), |
| + d.slot_address(), |
| + index); |
| } |
| + |
| + info->SetExpression(index, *num); |
| } |
| } |
| } |
| @@ -622,7 +687,8 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator, |
| switch (opcode) { |
| case Translation::BEGIN: |
| - case Translation::FRAME: |
| + case Translation::JS_FRAME: |
| + case Translation::ARGUMENTS_ADAPTOR_FRAME: |
| case Translation::DUPLICATE: |
| UNREACHABLE(); |
| return; |
| @@ -691,7 +757,7 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator, |
| case Translation::STACK_SLOT: { |
| int input_slot_index = iterator->Next(); |
| unsigned input_offset = |
| - input_->GetOffsetFromSlotIndex(this, input_slot_index); |
| + input_->GetOffsetFromSlotIndex(input_slot_index); |
| intptr_t input_value = input_->GetFrameSlot(input_offset); |
| if (FLAG_trace_deopt) { |
| PrintF(" 0x%08" V8PRIxPTR ": ", |
| @@ -710,7 +776,7 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator, |
| case Translation::INT32_STACK_SLOT: { |
| int input_slot_index = iterator->Next(); |
| unsigned input_offset = |
| - input_->GetOffsetFromSlotIndex(this, input_slot_index); |
| + input_->GetOffsetFromSlotIndex(input_slot_index); |
| intptr_t value = input_->GetFrameSlot(input_offset); |
| bool is_smi = Smi::IsValid(value); |
| if (FLAG_trace_deopt) { |
| @@ -739,7 +805,7 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator, |
| case Translation::DOUBLE_STACK_SLOT: { |
| int input_slot_index = iterator->Next(); |
| unsigned input_offset = |
| - input_->GetOffsetFromSlotIndex(this, input_slot_index); |
| + input_->GetOffsetFromSlotIndex(input_slot_index); |
| double value = input_->GetDoubleFrameSlot(input_offset); |
| if (FLAG_trace_deopt) { |
| PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- %e ; [esp + %d]\n", |
| @@ -808,7 +874,8 @@ bool Deoptimizer::DoOsrTranslateCommand(TranslationIterator* iterator, |
| switch (opcode) { |
| case Translation::BEGIN: |
| - case Translation::FRAME: |
| + case Translation::JS_FRAME: |
| + case Translation::ARGUMENTS_ADAPTOR_FRAME: |
| case Translation::DUPLICATE: |
| UNREACHABLE(); // Malformed input. |
| return false; |
| @@ -871,7 +938,7 @@ bool Deoptimizer::DoOsrTranslateCommand(TranslationIterator* iterator, |
| case Translation::STACK_SLOT: { |
| int output_index = iterator->Next(); |
| unsigned output_offset = |
| - output->GetOffsetFromSlotIndex(this, output_index); |
| + output->GetOffsetFromSlotIndex(output_index); |
| if (FLAG_trace_osr) { |
| PrintF(" [sp + %d] <- 0x%08" V8PRIxPTR " ; [sp + %d] ", |
| output_offset, |
| @@ -890,7 +957,7 @@ bool Deoptimizer::DoOsrTranslateCommand(TranslationIterator* iterator, |
| int output_index = iterator->Next(); |
| unsigned output_offset = |
| - output->GetOffsetFromSlotIndex(this, output_index); |
| + output->GetOffsetFromSlotIndex(output_index); |
| int int32_value = input_object->IsSmi() |
| ? Smi::cast(input_object)->value() |
| : DoubleToInt32(input_object->Number()); |
| @@ -922,7 +989,7 @@ bool Deoptimizer::DoOsrTranslateCommand(TranslationIterator* iterator, |
| int output_index = iterator->Next(); |
| unsigned output_offset = |
| - output->GetOffsetFromSlotIndex(this, output_index); |
| + output->GetOffsetFromSlotIndex(output_index); |
| double double_value = input_object->Number(); |
| uint64_t int_value = BitCast<uint64_t, double>(double_value); |
| int32_t lower = static_cast<int32_t>(int_value); |
| @@ -1033,8 +1100,8 @@ unsigned Deoptimizer::ComputeInputFrameSize() const { |
| unsigned Deoptimizer::ComputeFixedSize(JSFunction* function) const { |
| // The fixed part of the frame consists of the return address, frame |
| // pointer, function, context, and all the incoming arguments. |
| - static const unsigned kFixedSlotSize = 4 * kPointerSize; |
| - return ComputeIncomingArgumentSize(function) + kFixedSlotSize; |
| + return ComputeIncomingArgumentSize(function) + |
| + StandardFrameConstants::kFixedFrameSize * kPointerSize; |
| } |
| @@ -1154,49 +1221,62 @@ FrameDescription::FrameDescription(uint32_t frame_size, |
| } |
| -unsigned FrameDescription::GetOffsetFromSlotIndex(Deoptimizer* deoptimizer, |
| - int slot_index) { |
| +int FrameDescription::ComputeFixedSize() { |
| + return StandardFrameConstants::kFixedFrameSize * kPointerSize + |
| + (ComputeParametersCount() + 1) * kPointerSize; |
| +} |
| + |
| + |
| +unsigned FrameDescription::GetOffsetFromSlotIndex(int slot_index) { |
| if (slot_index >= 0) { |
| // Local or spill slots. Skip the fixed part of the frame |
| // including all arguments. |
| - unsigned base = |
| - GetFrameSize() - deoptimizer->ComputeFixedSize(GetFunction()); |
| + unsigned base = GetFrameSize() - ComputeFixedSize(); |
| return base - ((slot_index + 1) * kPointerSize); |
| } else { |
| // Incoming parameter. |
| - unsigned base = GetFrameSize() - |
| - deoptimizer->ComputeIncomingArgumentSize(GetFunction()); |
| + int arg_size = (ComputeParametersCount() + 1) * kPointerSize; |
| + unsigned base = GetFrameSize() - arg_size; |
| return base - ((slot_index + 1) * kPointerSize); |
| } |
| } |
| int FrameDescription::ComputeParametersCount() { |
| - return function_->shared()->formal_parameter_count(); |
| + switch (type_) { |
| + case StackFrame::JAVA_SCRIPT: |
| + return function_->shared()->formal_parameter_count(); |
| + case StackFrame::ARGUMENTS_ADAPTOR: { |
| + // Last slot contains number of incomming arguments as a smi. |
| + // Can't use GetExpression(0) because it would cause infinite recursion. |
| + return reinterpret_cast<Smi*>(*GetFrameSlotPointer(0))->value(); |
| + } |
| + default: |
| + UNREACHABLE(); |
| + return 0; |
| + } |
| } |
| -Object* FrameDescription::GetParameter(Deoptimizer* deoptimizer, int index) { |
| - ASSERT_EQ(Code::FUNCTION, kind_); |
| +Object* FrameDescription::GetParameter(int index) { |
| ASSERT(index >= 0); |
| ASSERT(index < ComputeParametersCount()); |
| // The slot indexes for incoming arguments are negative. |
| - unsigned offset = GetOffsetFromSlotIndex(deoptimizer, |
| - index - ComputeParametersCount()); |
| + unsigned offset = GetOffsetFromSlotIndex(index - ComputeParametersCount()); |
| return reinterpret_cast<Object*>(*GetFrameSlotPointer(offset)); |
| } |
| -unsigned FrameDescription::GetExpressionCount(Deoptimizer* deoptimizer) { |
| - ASSERT_EQ(Code::FUNCTION, kind_); |
| - unsigned size = GetFrameSize() - deoptimizer->ComputeFixedSize(GetFunction()); |
| +unsigned FrameDescription::GetExpressionCount() { |
| + ASSERT_EQ(StackFrame::JAVA_SCRIPT, type_); |
| + unsigned size = GetFrameSize() - ComputeFixedSize(); |
| return size / kPointerSize; |
| } |
| -Object* FrameDescription::GetExpression(Deoptimizer* deoptimizer, int index) { |
| - ASSERT_EQ(Code::FUNCTION, kind_); |
| - unsigned offset = GetOffsetFromSlotIndex(deoptimizer, index); |
| +Object* FrameDescription::GetExpression(int index) { |
| + ASSERT_EQ(StackFrame::JAVA_SCRIPT, type_); |
| + unsigned offset = GetOffsetFromSlotIndex(index); |
| return reinterpret_cast<Object*>(*GetFrameSlotPointer(offset)); |
| } |
| @@ -1242,8 +1322,15 @@ Handle<ByteArray> TranslationBuffer::CreateByteArray() { |
| } |
| -void Translation::BeginFrame(int node_id, int literal_id, unsigned height) { |
| - buffer_->Add(FRAME); |
| +void Translation::BeginArgumentsAdaptorFrame(int literal_id, unsigned height) { |
| + buffer_->Add(ARGUMENTS_ADAPTOR_FRAME); |
| + buffer_->Add(literal_id); |
| + buffer_->Add(height); |
| +} |
| + |
| + |
| +void Translation::BeginJSFrame(int node_id, int literal_id, unsigned height) { |
| + buffer_->Add(JS_FRAME); |
| buffer_->Add(node_id); |
| buffer_->Add(literal_id); |
| buffer_->Add(height); |
| @@ -1307,7 +1394,6 @@ int Translation::NumberOfOperandsFor(Opcode opcode) { |
| case ARGUMENTS_OBJECT: |
| case DUPLICATE: |
| return 0; |
| - case BEGIN: |
| case REGISTER: |
| case INT32_REGISTER: |
| case DOUBLE_REGISTER: |
| @@ -1316,7 +1402,10 @@ int Translation::NumberOfOperandsFor(Opcode opcode) { |
| case DOUBLE_STACK_SLOT: |
| case LITERAL: |
| return 1; |
| - case FRAME: |
| + case BEGIN: |
| + case ARGUMENTS_ADAPTOR_FRAME: |
| + return 2; |
| + case JS_FRAME: |
| return 3; |
| } |
| UNREACHABLE(); |
| @@ -1330,8 +1419,10 @@ const char* Translation::StringFor(Opcode opcode) { |
| switch (opcode) { |
| case BEGIN: |
| return "BEGIN"; |
| - case FRAME: |
| - return "FRAME"; |
| + case JS_FRAME: |
| + return "JS_FRAME"; |
| + case ARGUMENTS_ADAPTOR_FRAME: |
| + return "ARGUMENTS_ADAPTOR_FRAME"; |
| case REGISTER: |
| return "REGISTER"; |
| case INT32_REGISTER: |
| @@ -1385,7 +1476,8 @@ SlotRef SlotRef::ComputeSlotForNextArgument(TranslationIterator* iterator, |
| switch (opcode) { |
| case Translation::BEGIN: |
| - case Translation::FRAME: |
| + case Translation::JS_FRAME: |
| + case Translation::ARGUMENTS_ADAPTOR_FRAME: |
| // Peeled off before getting here. |
| break; |
| @@ -1431,9 +1523,27 @@ SlotRef SlotRef::ComputeSlotForNextArgument(TranslationIterator* iterator, |
| } |
| -void SlotRef::ComputeSlotMappingForArguments(JavaScriptFrame* frame, |
| - int inlined_frame_index, |
| - Vector<SlotRef>* args_slots) { |
| +void SlotRef::ComputeSlotsForArguments(Vector<SlotRef>* args_slots, |
| + TranslationIterator* it, |
| + DeoptimizationInputData* data, |
| + JavaScriptFrame* frame) { |
| + // Process the translation commands for the arguments. |
| + |
| + // Skip the translation command for the receiver. |
| + it->Skip(Translation::NumberOfOperandsFor( |
| + static_cast<Translation::Opcode>(it->Next()))); |
| + |
| + // Compute slots for arguments. |
| + for (int i = 0; i < args_slots->length(); ++i) { |
| + (*args_slots)[i] = ComputeSlotForNextArgument(it, data, frame); |
| + } |
| +} |
| + |
| + |
| +Vector<SlotRef> SlotRef::ComputeSlotMappingForArguments( |
| + JavaScriptFrame* frame, |
| + int inlined_jsframe_index, |
| + int formal_parameter_count) { |
| AssertNoAllocation no_gc; |
| int deopt_index = AstNode::kNoNumber; |
| DeoptimizationInputData* data = |
| @@ -1442,51 +1552,73 @@ void SlotRef::ComputeSlotMappingForArguments(JavaScriptFrame* frame, |
| data->TranslationIndex(deopt_index)->value()); |
| Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); |
| ASSERT(opcode == Translation::BEGIN); |
| - int frame_count = it.Next(); |
| - USE(frame_count); |
| - ASSERT(frame_count > inlined_frame_index); |
| - int frames_to_skip = inlined_frame_index; |
| + it.Next(); // Drop frame count. |
| + int jsframe_count = it.Next(); |
| + USE(jsframe_count); |
| + ASSERT(jsframe_count > inlined_jsframe_index); |
| + int jsframes_to_skip = inlined_jsframe_index; |
| while (true) { |
| opcode = static_cast<Translation::Opcode>(it.Next()); |
| - // Skip over operands to advance to the next opcode. |
| - it.Skip(Translation::NumberOfOperandsFor(opcode)); |
| - if (opcode == Translation::FRAME) { |
| - if (frames_to_skip == 0) { |
| + if (opcode == Translation::ARGUMENTS_ADAPTOR_FRAME) { |
| + if (jsframes_to_skip == 0) { |
| + ASSERT(Translation::NumberOfOperandsFor(opcode) == 2); |
| + |
| + it.Skip(1); // literal id |
| + int height = it.Next(); |
| + |
| + // We reached the arguments adaptor frame corresponding to the |
| + // inlined function in question. Number of arguments is height - 1. |
| + Vector<SlotRef> args_slots = |
| + Vector<SlotRef>::New(height - 1); // Minus receiver. |
| + ComputeSlotsForArguments(&args_slots, &it, data, frame); |
| + return args_slots; |
| + } |
| + } else if (opcode == Translation::JS_FRAME) { |
| + if (jsframes_to_skip == 0) { |
| + // Skip over operands to advance to the next opcode. |
| + it.Skip(Translation::NumberOfOperandsFor(opcode)); |
| + |
| // We reached the frame corresponding to the inlined function |
| // in question. Process the translation commands for the |
| - // arguments. |
| - // |
| - // Skip the translation command for the receiver. |
| - it.Skip(Translation::NumberOfOperandsFor( |
| - static_cast<Translation::Opcode>(it.Next()))); |
| - // Compute slots for arguments. |
| - for (int i = 0; i < args_slots->length(); ++i) { |
| - (*args_slots)[i] = ComputeSlotForNextArgument(&it, data, frame); |
| - } |
| - return; |
| + // arguments. Number of arguments is equal to the number of |
| + // format parameter count. |
| + Vector<SlotRef> args_slots = |
| + Vector<SlotRef>::New(formal_parameter_count); |
| + ComputeSlotsForArguments(&args_slots, &it, data, frame); |
| + return args_slots; |
| } |
| - frames_to_skip--; |
| + jsframes_to_skip--; |
| } |
| + |
| + // Skip over operands to advance to the next opcode. |
| + it.Skip(Translation::NumberOfOperandsFor(opcode)); |
| } |
| UNREACHABLE(); |
| + return Vector<SlotRef>(); |
| } |
| #ifdef ENABLE_DEBUGGER_SUPPORT |
| DeoptimizedFrameInfo::DeoptimizedFrameInfo( |
| - Deoptimizer* deoptimizer, int frame_index) { |
| + Deoptimizer* deoptimizer, int frame_index, bool has_arguments_adaptor) { |
| FrameDescription* output_frame = deoptimizer->output_[frame_index]; |
| SetFunction(output_frame->GetFunction()); |
| - expression_count_ = output_frame->GetExpressionCount(deoptimizer); |
| + expression_count_ = output_frame->GetExpressionCount(); |
| + expression_stack_ = new Object*[expression_count_]; |
| + for (int i = 0; i < expression_count_; i++) { |
| + SetExpression(i, output_frame->GetExpression(i)); |
| + } |
| + |
| + if (has_arguments_adaptor) { |
| + output_frame = deoptimizer->output_[frame_index - 1]; |
| + ASSERT(output_frame->GetType() == StackFrame::ARGUMENTS_ADAPTOR); |
| + } |
| + |
| parameters_count_ = output_frame->ComputeParametersCount(); |
| parameters_ = new Object*[parameters_count_]; |
| for (int i = 0; i < parameters_count_; i++) { |
| - SetParameter(i, output_frame->GetParameter(deoptimizer, i)); |
| - } |
| - expression_stack_ = new Object*[expression_count_]; |
| - for (int i = 0; i < expression_count_; i++) { |
| - SetExpression(i, output_frame->GetExpression(deoptimizer, i)); |
| + SetParameter(i, output_frame->GetParameter(i)); |
| } |
| } |