Do not break in native code (including non-builtin debugger code).
authoryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 27 May 2014 12:21:40 +0000 (12:21 +0000)
committeryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 27 May 2014 12:21:40 +0000 (12:21 +0000)
R=ulan@chromium.org

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

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

src/debug.cc
src/objects-inl.h
src/objects.h
test/mjsunit/debug-break-native.js [new file with mode: 0644]

index 058ec35..932b58a 100644 (file)
@@ -805,6 +805,7 @@ bool Debug::Load() {
 
 void Debug::Unload() {
   ClearAllBreakPoints();
+  ClearStepping();
 
   // Match unmatched PromiseHandlePrologue calls.
   while (thread_local_.promise_on_stack_) PromiseHandleEpilogue();
@@ -1209,7 +1210,7 @@ void Debug::FloodBoundFunctionWithOneShot(Handle<JSFunction> function) {
                         isolate_);
 
   if (!bindee.is_null() && bindee->IsJSFunction() &&
-      !JSFunction::cast(*bindee)->IsBuiltin()) {
+      !JSFunction::cast(*bindee)->IsNative()) {
     Handle<JSFunction> bindee_function(JSFunction::cast(*bindee));
     Debug::FloodWithOneShot(bindee_function);
   }
@@ -1430,7 +1431,7 @@ void Debug::PrepareStep(StepAction step_action,
       frames_it.Advance();
     }
     // Skip builtin functions on the stack.
-    while (!frames_it.done() && frames_it.frame()->function()->IsBuiltin()) {
+    while (!frames_it.done() && frames_it.frame()->function()->IsNative()) {
       frames_it.Advance();
     }
     // Step out: If there is a JavaScript caller frame, we need to
@@ -1517,7 +1518,7 @@ void Debug::PrepareStep(StepAction step_action,
         Handle<JSFunction> js_function(JSFunction::cast(fun));
         if (js_function->shared()->bound()) {
           Debug::FloodBoundFunctionWithOneShot(js_function);
-        } else if (!js_function->IsBuiltin()) {
+        } else if (!js_function->IsNative()) {
           // Don't step into builtins.
           // It will also compile target function if it's not compiled yet.
           FloodWithOneShot(js_function);
@@ -1731,7 +1732,7 @@ void Debug::HandleStepIn(Handle<JSFunction> function,
     if (function->shared()->bound()) {
       // Handle Function.prototype.bind
       Debug::FloodBoundFunctionWithOneShot(function);
-    } else if (!function->IsBuiltin()) {
+    } else if (!function->IsNative()) {
       // Don't allow step into functions in the native context.
       if (function->shared()->code() ==
           isolate->builtins()->builtin(Builtins::kFunctionApply) ||
@@ -1743,7 +1744,7 @@ void Debug::HandleStepIn(Handle<JSFunction> function,
         // function.
         if (!holder.is_null() && holder->IsJSFunction()) {
           Handle<JSFunction> js_function = Handle<JSFunction>::cast(holder);
-          if (!js_function->IsBuiltin()) {
+          if (!js_function->IsNative()) {
             Debug::FloodWithOneShot(js_function);
           } else if (js_function->shared()->bound()) {
             // Handle Function.prototype.bind
@@ -2085,7 +2086,7 @@ void Debug::PrepareForBreakPoints() {
 
           if (!shared->allows_lazy_compilation()) continue;
           if (!shared->script()->IsScript()) continue;
-          if (function->IsBuiltin()) continue;
+          if (function->IsNative()) continue;
           if (shared->code()->gc_metadata() == active_code_marker) continue;
 
           if (shared->is_generator()) {
index 31ebbb1..58c9c96 100644 (file)
@@ -5418,6 +5418,15 @@ bool JSFunction::IsBuiltin() {
 }
 
 
+bool JSFunction::IsNative() {
+  Object* script = shared()->script();
+  bool native = script->IsScript() &&
+                Script::cast(script)->type()->value() == Script::TYPE_NATIVE;
+  ASSERT(!IsBuiltin() || native);  // All builtins are also native.
+  return native;
+}
+
+
 bool JSFunction::NeedsArgumentsAdaption() {
   return shared()->formal_parameter_count() !=
       SharedFunctionInfo::kDontAdaptArgumentsSentinel;
index e89efdf..0c9afd7 100644 (file)
@@ -7492,6 +7492,9 @@ class JSFunction: public JSObject {
   // Tells whether this function is builtin.
   inline bool IsBuiltin();
 
+  // Tells whether this function is defined in a native script.
+  inline bool IsNative();
+
   // Tells whether or not the function needs arguments adaption.
   inline bool NeedsArgumentsAdaption();
 
diff --git a/test/mjsunit/debug-break-native.js b/test/mjsunit/debug-break-native.js
new file mode 100644 (file)
index 0000000..11d7274
--- /dev/null
@@ -0,0 +1,42 @@
+// Copyright 2014 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: --expose-debug-as debug
+
+Debug = debug.Debug
+var exception = null;
+
+function breakListener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    exec_state.prepareStep(Debug.StepAction.StepIn, 1);
+    // Assert that the break happens at an intended location.
+    assertTrue(exec_state.frame(0).sourceLineText().indexOf("// break") > 0);
+  } catch (e) {
+    exception = e;
+  }
+}
+
+Debug.setListener(breakListener);
+
+debugger;                          // break
+
+function f(x) {
+  return x;                        // break
+}                                  // break
+
+Debug.setBreakPoint(f, 0, 0);      // break
+Debug.scripts();                   // break
+debug.MakeMirror(f);               // break
+
+new Error("123").stack;            // break
+Math.sin(0);                       // break
+
+f("this should break");            // break
+
+Debug.setListener(null);           // break
+
+f("this should not break");
+
+assertNull(exception);