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:
parent
894f57f96a
commit
8ccb47f57e
@ -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,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++) {
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user