Do not materialize uninitialized const for debug evaluate.
authoryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 12 Aug 2013 13:35:46 +0000 (13:35 +0000)
committeryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 12 Aug 2013 13:35:46 +0000 (13:35 +0000)
R=prybin@chromium.org
BUG=

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16148 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/runtime.cc
test/mjsunit/debug-evaluate-const.js [new file with mode: 0644]
test/mjsunit/debug-evaluate-locals.js

index 56aa19e..10de6f9 100644 (file)
@@ -11227,6 +11227,7 @@ static Handle<JSObject> MaterializeStackLocalsWithFrameInspector(
                              ? frame_inspector->GetParameter(i)
                              : isolate->heap()->undefined_value(),
                          isolate);
+    ASSERT(!value->IsTheHole());
 
     RETURN_IF_EMPTY_HANDLE_VALUE(
         isolate,
@@ -11241,12 +11242,15 @@ static Handle<JSObject> MaterializeStackLocalsWithFrameInspector(
 
   // Second fill all stack locals.
   for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
+    Handle<Object> value(frame_inspector->GetExpression(i), isolate);
+    if (value->IsTheHole()) continue;
+
     RETURN_IF_EMPTY_HANDLE_VALUE(
         isolate,
         SetProperty(isolate,
                     target,
                     Handle<String>(scope_info->StackLocalName(i)),
-                    Handle<Object>(frame_inspector->GetExpression(i), isolate),
+                    value,
                     NONE,
                     kNonStrictMode),
         Handle<JSObject>());
@@ -11273,6 +11277,7 @@ static void UpdateStackLocalsFromMaterializedObject(Isolate* isolate,
 
   // Parameters.
   for (int i = 0; i < scope_info->ParameterCount(); ++i) {
+    ASSERT(!frame->GetParameter(i)->IsTheHole());
     HandleScope scope(isolate);
     Handle<Object> value = GetProperty(
         isolate, target, Handle<String>(scope_info->ParameterName(i)));
@@ -11281,6 +11286,7 @@ static void UpdateStackLocalsFromMaterializedObject(Isolate* isolate,
 
   // Stack locals.
   for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
+    if (frame->GetExpression(i)->IsTheHole()) continue;
     HandleScope scope(isolate);
     Handle<Object> value = GetProperty(
         isolate, target, Handle<String>(scope_info->StackLocalName(i)));
diff --git a/test/mjsunit/debug-evaluate-const.js b/test/mjsunit/debug-evaluate-const.js
new file mode 100644 (file)
index 0000000..cb9695b
--- /dev/null
@@ -0,0 +1,121 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --expose-debug-as debug
+
+Debug = debug.Debug
+
+listenerComplete = false;
+exception = false;
+
+// var0:   init after break point, changed by debug eval.
+// const0: init before break point, changed by debug eval.
+// const1: init after break point, materialized but untouched by debug eval.
+// const2: init after break point, materialized and changed by debug eval.
+// const3: context allocated const, init before break point, changed by eval.
+function f() {
+  var var1 = 21;
+  const const3 = 3;
+
+  function g() {
+    const const0 = 0;
+    assertEquals(undefined, const1);
+    assertEquals(undefined, const2);
+    assertEquals(3, const3);
+    assertEquals(21, var1);
+
+    debugger;  // Break point.
+
+    assertEquals(30, var0);
+    // TODO(yangguo): debug evaluate should not be able to alter
+    //                stack-allocated const values
+    // assertEquals(0, const0);
+    assertEquals(undefined, const1);
+    assertEquals(undefined, const2);
+    var var0 = 20;
+    const const1 = 1;
+    const const2 = 2;
+    assertEquals(20, var0);
+    assertEquals(1, const1);
+    assertEquals(2, const2);
+  }
+
+  g();
+
+  assertEquals(31, var1);
+  assertEquals(3, const3);
+}
+
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var frame = exec_state.frame(0);
+    var evaluate = function(something) {
+      return frame.evaluate(something).value()
+    }
+
+    var count = frame.localCount();
+    assertEquals(4, count);
+    var expectation = { "const0" : 0,
+                        "const1" : undefined,
+                        "const2" : undefined,
+                        "const3" : 3,
+                        "var0"   : undefined,
+                        "var1"   : 21 };
+    for (var i = 0; i < frame.localCount(); ++i) {
+      var name = frame.localName(i);
+      var value = frame.localValue(i).value();
+      assertEquals(expectation[name], value);
+    }
+
+    evaluate('const0 = 10');
+    evaluate('const2 = 12');
+    evaluate('const3 = 13');
+    evaluate('var0 = 30');
+    evaluate('var1 = 31');
+
+    // Indicate that all was processed.
+    listenerComplete = true;
+  } catch (e) {
+    exception = e;
+    print("Caught something. " + e + " " + e.stack);
+  };
+};
+
+// Run and compile before debugger is active.
+try { f(); } catch (e) { }
+
+Debug.setListener(listener);
+
+f();
+
+Debug.setListener(null);
+
+assertFalse(exception, "exception in listener")
+assertTrue(listenerComplete);
+
index e6326e1..ba3e92d 100644 (file)
@@ -134,7 +134,7 @@ function listener(event, exec_state, event_data, data) {
       listenerComplete = true;
     }
   } catch (e) {
-    exception = e
+    exception = e;
     print("Caught something. " + e + " " + e.stack);
   };
 };