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

Reply via email to