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