[deoptimizer] Fix the frame size calculation for debugger-inspectable frame construction.
authorjarin <jarin@chromium.org>
Mon, 3 Aug 2015 12:59:41 +0000 (05:59 -0700)
committerCommit bot <commit-bot@chromium.org>
Mon, 3 Aug 2015 12:59:59 +0000 (12:59 +0000)
The calculation now takes into account the size of the arguments object
if it is present in the optimized frame.

(Yang, many thanks for the awesome repro!)

BUG=chromium:514362
LOG=N
R=yangguo@chromium.org

Review URL: https://codereview.chromium.org/1264483008

Cr-Commit-Position: refs/heads/master@{#29973}

src/deoptimizer.cc
src/deoptimizer.h
test/mjsunit/regress/regress-514362.js [new file with mode: 0644]

index d29cb60..7119114 100644 (file)
@@ -154,8 +154,11 @@ DeoptimizedFrameInfo* Deoptimizer::DebuggerInspectableFrame(
   // Always use the actual stack slots when calculating the fp to sp
   // delta adding two for the function and context.
   unsigned stack_slots = code->stack_slots();
+  unsigned arguments_stack_height =
+      Deoptimizer::ComputeOutgoingArgumentSize(code, deoptimization_index);
   unsigned fp_to_sp_delta = (stack_slots * kPointerSize) +
-      StandardFrameConstants::kFixedFrameSizeFromFp;
+                            StandardFrameConstants::kFixedFrameSizeFromFp +
+                            arguments_stack_height;
 
   Deoptimizer* deoptimizer = new Deoptimizer(isolate,
                                              function,
@@ -1770,7 +1773,8 @@ unsigned Deoptimizer::ComputeInputFrameSize() const {
                     StandardFrameConstants::kFixedFrameSizeFromFp;
   if (compiled_code_->kind() == Code::OPTIMIZED_FUNCTION) {
     unsigned stack_slots = compiled_code_->stack_slots();
-    unsigned outgoing_size = ComputeOutgoingArgumentSize();
+    unsigned outgoing_size =
+        ComputeOutgoingArgumentSize(compiled_code_, bailout_id_);
     CHECK(result == fixed_size + (stack_slots * kPointerSize) + outgoing_size);
   }
   return result;
@@ -1798,10 +1802,12 @@ unsigned Deoptimizer::ComputeIncomingArgumentSize(JSFunction* function) const {
 }
 
 
-unsigned Deoptimizer::ComputeOutgoingArgumentSize() const {
+// static
+unsigned Deoptimizer::ComputeOutgoingArgumentSize(Code* code,
+                                                  unsigned bailout_id) {
   DeoptimizationInputData* data =
-      DeoptimizationInputData::cast(compiled_code_->deoptimization_data());
-  unsigned height = data->ArgumentsStackHeight(bailout_id_)->value();
+      DeoptimizationInputData::cast(code->deoptimization_data());
+  unsigned height = data->ArgumentsStackHeight(bailout_id)->value();
   return height * kPointerSize;
 }
 
index 854f08b..db94eb0 100644 (file)
@@ -616,7 +616,7 @@ class Deoptimizer : public Malloced {
   unsigned ComputeFixedSize(JSFunction* function) const;
 
   unsigned ComputeIncomingArgumentSize(JSFunction* function) const;
-  unsigned ComputeOutgoingArgumentSize() const;
+  static unsigned ComputeOutgoingArgumentSize(Code* code, unsigned bailout_id);
 
   Object* ComputeLiteral(int index) const;
 
diff --git a/test/mjsunit/regress/regress-514362.js b/test/mjsunit/regress/regress-514362.js
new file mode 100644 (file)
index 0000000..f69cfec
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --expose-debug-as debug
+
+function bar(x) { debugger; }
+function foo() { bar(arguments[0]); }
+function wrap() { return foo(1); }
+
+wrap();
+wrap();
+%OptimizeFunctionOnNextCall(wrap);
+
+var Debug = debug.Debug;
+Debug.setListener(function(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  for (var i = 0; i < exec_state.frameCount(); i++) exec_state.frame(i);
+});
+
+wrap();