Revision: 8566
Author: [email protected]
Date: Thu Jul 7 07:29:16 2011
Log: Add inspection of arguments for optimized frames
[email protected]
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
http://code.google.com/p/v8/source/detail?r=8566
Modified:
/branches/bleeding_edge/src/deoptimizer.cc
/branches/bleeding_edge/src/deoptimizer.h
/branches/bleeding_edge/src/runtime.cc
/branches/bleeding_edge/test/mjsunit/debug-evaluate-locals-optimized-double.js
/branches/bleeding_edge/test/mjsunit/debug-evaluate-locals-optimized.js
=======================================
--- /branches/bleeding_edge/src/deoptimizer.cc Wed Jul 6 06:02:17 2011
+++ /branches/bleeding_edge/src/deoptimizer.cc Thu Jul 7 07:29:16 2011
@@ -161,8 +161,7 @@
// 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 @@
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);
- }
- info->SetExpression(expression_index, *num);
+ 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);
+ }
}
}
}
@@ -1124,6 +1133,22 @@
return base - ((slot_index + 1) * kPointerSize);
}
}
+
+
+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) {
@@ -1417,6 +1442,11 @@
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 @@
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_);
}
=======================================
--- /branches/bleeding_edge/src/deoptimizer.h Wed Jul 6 06:02:17 2011
+++ /branches/bleeding_edge/src/deoptimizer.h Thu Jul 7 07:29:16 2011
@@ -400,6 +400,12 @@
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);
@@ -661,6 +667,9 @@
// 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_; }
@@ -669,6 +678,12 @@
JSFunction* GetFunction() {
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) {
@@ -681,6 +696,12 @@
void SetFunction(JSFunction* function) {
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) {
@@ -689,7 +710,9 @@
}
JSFunction* function_;
+ int parameters_count_;
int expression_count_;
+ Object** parameters_;
Object** expression_stack_;
friend class Deoptimizer;
=======================================
--- /branches/bleeding_edge/src/runtime.cc Thu Jul 7 05:41:20 2011
+++ /branches/bleeding_edge/src/runtime.cc Thu Jul 7 07:29:16 2011
@@ -10150,8 +10150,12 @@
// 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 @@
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());
+ }
}
}
=======================================
---
/branches/bleeding_edge/test/mjsunit/debug-evaluate-locals-optimized-double.js
Wed Jul 6 06:02:17 2011
+++
/branches/bleeding_edge/test/mjsunit/debug-evaluate-locals-optimized-double.js
Thu Jul 7 07:29:16 2011
@@ -41,14 +41,22 @@
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.
=======================================
--- /branches/bleeding_edge/test/mjsunit/debug-evaluate-locals-optimized.js
Wed Jul 6 06:02:17 2011
+++ /branches/bleeding_edge/test/mjsunit/debug-evaluate-locals-optimized.js
Thu Jul 7 07:29:16 2011
@@ -41,12 +41,18 @@
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.
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev