Add inspection of arguments for optimized frames

R=svenpanne@chromium.org

BUG=v8:1140
TEST=test/mjsunit/debug-evaluate-locals-optimized.js,test/mjsunit/debug-
evaluate-locals-optimized-doubles.js

Review URL: http://codereview.chromium.org//7310027

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8566 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
sgjesse@chromium.org 2011-07-07 14:29:16 +00:00
parent 894f57f96a
commit 8ccb47f57e
5 changed files with 92 additions and 19 deletions

View File

@ -161,8 +161,7 @@ DeoptimizedFrameInfo* Deoptimizer::DebuggerInspectableFrame(
// Get the "simulated" top and size for the requested frame.
Address top =
reinterpret_cast<Address>(deoptimizer->output_[frame_index]->GetTop());
unsigned size =
deoptimizer->output_[frame_index]->GetFrameSize() / kPointerSize;
unsigned size = deoptimizer->output_[frame_index]->GetFrameSize();
// Done with the GC-unsafe frame descriptions. This re-enables allocation.
deoptimizer->DeleteFrameDescriptions();
@ -557,17 +556,27 @@ void Deoptimizer::MaterializeHeapNumbersForDebuggerInspectableFrame(
Address slot = d.slot_address();
if (top <= slot && slot < top + size) {
Handle<Object> num = isolate_->factory()->NewNumber(d.value());
int expression_index = static_cast<int>(
// 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);
if (FLAG_trace_deopt) {
PrintF("Materializing a new heap number %p [%e] in slot %p"
"for expression stack index %d\n",
"for stack index %d\n",
reinterpret_cast<void*>(*num),
d.value(),
d.slot_address(),
expression_index);
index);
}
if (index >=0) {
info->SetExpression(index, *num);
} else {
// Calculate parameter index subtracting one for the receiver.
int parameter_index =
index + size / kPointerSize - info->expression_count_ - 1;
info->SetParameter(parameter_index, *num);
}
info->SetExpression(expression_index, *num);
}
}
}
@ -1126,6 +1135,22 @@ unsigned FrameDescription::GetOffsetFromSlotIndex(Deoptimizer* deoptimizer,
}
int FrameDescription::ComputeParametersCount() {
return function_->shared()->formal_parameter_count();
}
Object* FrameDescription::GetParameter(Deoptimizer* deoptimizer, int index) {
ASSERT_EQ(Code::FUNCTION, kind_);
ASSERT(index >= 0);
ASSERT(index < ComputeParametersCount());
// The slot indexes for incoming arguments are negative.
unsigned offset = GetOffsetFromSlotIndex(deoptimizer,
index - ComputeParametersCount());
return reinterpret_cast<Object*>(*GetFrameSlotPointer(offset));
}
unsigned FrameDescription::GetExpressionCount(Deoptimizer* deoptimizer) {
ASSERT_EQ(Code::FUNCTION, kind_);
unsigned size = GetFrameSize() - deoptimizer->ComputeFixedSize(GetFunction());
@ -1417,6 +1442,11 @@ DeoptimizedFrameInfo::DeoptimizedFrameInfo(
FrameDescription* output_frame = deoptimizer->output_[frame_index];
SetFunction(output_frame->GetFunction());
expression_count_ = output_frame->GetExpressionCount(deoptimizer);
parameters_count_ = output_frame->ComputeParametersCount();
parameters_ = new Object*[expression_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));
@ -1430,6 +1460,7 @@ DeoptimizedFrameInfo::~DeoptimizedFrameInfo() {
void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) {
v->VisitPointer(reinterpret_cast<Object**>(&function_));
v->VisitPointers(parameters_, parameters_ + parameters_count_);
v->VisitPointers(expression_stack_, expression_stack_ + expression_count_);
}

View File

@ -400,6 +400,12 @@ class FrameDescription {
void SetKind(Code::Kind kind) { kind_ = kind; }
#endif
// Get the incoming arguments count.
int ComputeParametersCount();
// Get a parameter value for an unoptimized frame.
Object* GetParameter(Deoptimizer* deoptimizer, int index);
// Get the expression stack height for a unoptimized frame.
unsigned GetExpressionCount(Deoptimizer* deoptimizer);
@ -662,6 +668,9 @@ class DeoptimizedFrameInfo : public Malloced {
// GC support.
void Iterate(ObjectVisitor* v);
// Return the number of incoming arguments.
int parameters_count() { return parameters_count_; }
// Return the height of the expression stack.
int expression_count() { return expression_count_; }
@ -670,6 +679,12 @@ class DeoptimizedFrameInfo : public Malloced {
return function_;
}
// Get an incoming argument.
Object* GetParameter(int index) {
ASSERT(0 <= index && index < parameters_count());
return parameters_[index];
}
// Get an expression from the expression stack.
Object* GetExpression(int index) {
ASSERT(0 <= index && index < expression_count());
@ -682,6 +697,12 @@ class DeoptimizedFrameInfo : public Malloced {
function_ = function;
}
// Set an incoming argument.
void SetParameter(int index, Object* obj) {
ASSERT(0 <= index && index < parameters_count());
parameters_[index] = obj;
}
// Set an expression on the expression stack.
void SetExpression(int index, Object* obj) {
ASSERT(0 <= index && index < expression_count());
@ -689,7 +710,9 @@ class DeoptimizedFrameInfo : public Malloced {
}
JSFunction* function_;
int parameters_count_;
int expression_count_;
Object** parameters_;
Object** expression_stack_;
friend class Deoptimizer;

View File

@ -10150,9 +10150,13 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
// Find the number of arguments to fill. At least fill the number of
// parameters for the function and fill more if more parameters are provided.
int argument_count = info.number_of_parameters();
if (it.frame()->is_optimized()) {
ASSERT_EQ(argument_count, deoptimized_frame->parameters_count());
} else {
if (argument_count < it.frame()->ComputeParametersCount()) {
argument_count = it.frame()->ComputeParametersCount();
}
}
// Calculate the size of the result.
int details_size = kFrameDetailsFirstDynamicIndex +
@ -10220,18 +10224,19 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
details->set(details_index++, heap->undefined_value());
}
// Parameter value. If we are inspecting an optimized frame, use
// undefined as the value.
//
// TODO(3141533): We should be able to get the actual parameter
// value for optimized frames.
if (!it.frame()->is_optimized() &&
(i < it.frame()->ComputeParametersCount())) {
// Parameter value.
if (it.frame()->is_optimized()) {
// Get the value from the deoptimized frame.
details->set(details_index++, deoptimized_frame->GetParameter(i));
} else {
if (i < it.frame()->ComputeParametersCount()) {
// Get the value from the stack.
details->set(details_index++, it.frame()->GetParameter(i));
} else {
details->set(details_index++, heap->undefined_value());
}
}
}
// Add locals name and value from the temporary copy from the function frame.
for (int i = 0; i < info.NumberOfLocals() * 2; i++) {

View File

@ -41,14 +41,22 @@ function listener(event, exec_state, event_data, data) {
for (var i = 0; i < exec_state.frameCount(); i++) {
var frame = exec_state.frame(i);
// All frames except the bottom one has normal variables a and b.
if (i < exec_state.frameCount() - 1) {
// All frames except the bottom one has normal variables a and b.
assertEquals('a', frame.localName(0));
assertEquals('b', frame.localName(1));
assertEquals(i * 2 + 1 + (i * 2 + 1) / 100,
frame.localValue(0).value());
assertEquals(i * 2 + 2 + (i * 2 + 2) / 100,
frame.localValue(1).value());
// All frames except the bottom one has arguments variables x and y.
assertEquals('x', frame.argumentName(0));
assertEquals('y', frame.argumentName(1));
assertEquals((i + 1) * 2 + 1 + ((i + 1) * 2 + 1) / 100,
frame.argumentValue(0).value());
assertEquals((i + 1) * 2 + 2 + ((i + 1) * 2 + 2) / 100,
frame.argumentValue(1).value());
}
// Check the frame function.

View File

@ -41,12 +41,18 @@ function listener(event, exec_state, event_data, data) {
for (var i = 0; i < exec_state.frameCount(); i++) {
var frame = exec_state.frame(i);
// All frames except the bottom one has normal variables a and b.
if (i < exec_state.frameCount() - 1) {
// All frames except the bottom one has normal variables a and b.
assertEquals('a', frame.localName(0));
assertEquals('b', frame.localName(1));
assertEquals(i * 2 + 1, frame.localValue(0).value());
assertEquals(i * 2 + 2, frame.localValue(1).value());
// All frames except the bottom one has arguments variables x and y.
assertEquals('x', frame.argumentName(0));
assertEquals('y', frame.argumentName(1));
assertEquals((i + 1) * 2 + 1, frame.argumentValue(0).value());
assertEquals((i + 1) * 2 + 2, frame.argumentValue(1).value());
}
// Check the frame function.