Commit 8ccb47f5 authored by sgjesse@chromium.org's avatar sgjesse@chromium.org

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
parent 894f57f9
......@@ -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_);
}
......
......@@ -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;
......
......@@ -10150,8 +10150,12 @@ 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 (argument_count < it.frame()->ComputeParametersCount()) {
argument_count = it.frame()->ComputeParametersCount();
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.
......@@ -10220,16 +10224,17 @@ 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())) {
details->set(details_index++, it.frame()->GetParameter(i));
// Parameter value.
if (it.frame()->is_optimized()) {
// Get the value from the deoptimized frame.
details->set(details_index++, deoptimized_frame->GetParameter(i));
} else {
details->set(details_index++, heap->undefined_value());
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());
}
}
}
......
......@@ -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.
......
......@@ -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.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment