Reland "In PrepareForBreakPoints, also purge shared function info not referenced...
authoryangguo@chromium.org <yangguo@chromium.org>
Wed, 29 Oct 2014 10:19:08 +0000 (10:19 +0000)
committeryangguo@chromium.org <yangguo@chromium.org>
Wed, 29 Oct 2014 10:19:44 +0000 (10:19 +0000)
BUG=chromium:424142
LOG=N
R=jarin@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#24970}
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24970 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/debug.cc
test/mjsunit/regress/regress-crbug-424142.js [new file with mode: 0644]

index 6521110..4a58766 100644 (file)
@@ -1894,6 +1894,23 @@ static void RecompileAndRelocateSuspendedGenerators(
 }
 
 
+static bool SkipSharedFunctionInfo(SharedFunctionInfo* shared,
+                                   Object* active_code_marker) {
+  if (!shared->allows_lazy_compilation()) return true;
+  if (!shared->script()->IsScript()) return true;
+  Object* script = shared->script();
+  if (!script->IsScript()) return true;
+  if (Script::cast(script)->type()->value() == Script::TYPE_NATIVE) return true;
+  Code* shared_code = shared->code();
+  return shared_code->gc_metadata() == active_code_marker;
+}
+
+
+static inline bool HasDebugBreakSlots(Code* code) {
+  return code->kind() == Code::FUNCTION && code->has_debug_break_slots();
+}
+
+
 void Debug::PrepareForBreakPoints() {
   // If preparing for the first break point make sure to deoptimize all
   // functions as debugging does not work with optimized code.
@@ -1959,35 +1976,28 @@ void Debug::PrepareForBreakPoints() {
         if (obj->IsJSFunction()) {
           JSFunction* function = JSFunction::cast(obj);
           SharedFunctionInfo* shared = function->shared();
-
-          if (!shared->allows_lazy_compilation()) continue;
-          if (!shared->script()->IsScript()) continue;
-          if (function->IsFromNativeScript()) continue;
-          if (shared->code()->gc_metadata() == active_code_marker) continue;
-
+          if (SkipSharedFunctionInfo(shared, active_code_marker)) continue;
           if (shared->is_generator()) {
             generator_functions.Add(Handle<JSFunction>(function, isolate_));
             continue;
           }
-
+          if (HasDebugBreakSlots(function->code())) continue;
+          Code* fallback = HasDebugBreakSlots(shared->code()) ? shared->code()
+                                                              : *lazy_compile;
           Code::Kind kind = function->code()->kind();
-          if (kind == Code::FUNCTION &&
-              !function->code()->has_debug_break_slots()) {
-            function->ReplaceCode(*lazy_compile);
-            function->shared()->ReplaceCode(*lazy_compile);
-          } else if (kind == Code::BUILTIN &&
-              (function->IsInOptimizationQueue() ||
-               function->IsMarkedForOptimization() ||
-               function->IsMarkedForConcurrentOptimization())) {
-            // Abort in-flight compilation.
-            Code* shared_code = function->shared()->code();
-            if (shared_code->kind() == Code::FUNCTION &&
-                shared_code->has_debug_break_slots()) {
-              function->ReplaceCode(shared_code);
-            } else {
-              function->ReplaceCode(*lazy_compile);
-              function->shared()->ReplaceCode(*lazy_compile);
-            }
+          if (kind == Code::FUNCTION ||
+              (kind == Code::BUILTIN &&  // Abort in-flight compilation.
+               (function->IsInOptimizationQueue() ||
+                function->IsMarkedForOptimization() ||
+                function->IsMarkedForConcurrentOptimization()))) {
+            function->ReplaceCode(fallback);
+          }
+          if (kind == Code::OPTIMIZED_FUNCTION) {
+            // Optimized code can only get here if DeoptimizeAll did not
+            // deoptimize turbo fan code.
+            DCHECK(!FLAG_turbo_deoptimization);
+            DCHECK(function->code()->is_turbofanned());
+            function->ReplaceCode(fallback);
           }
         } else if (obj->IsJSGeneratorObject()) {
           JSGeneratorObject* gen = JSGeneratorObject::cast(obj);
@@ -2007,6 +2017,12 @@ void Debug::PrepareForBreakPoints() {
           gen->set_continuation(code_offset);
 
           suspended_generators.Add(Handle<JSGeneratorObject>(gen, isolate_));
+        } else if (obj->IsSharedFunctionInfo()) {
+          SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
+          if (SkipSharedFunctionInfo(shared, active_code_marker)) continue;
+          if (shared->is_generator()) continue;
+          if (HasDebugBreakSlots(shared->code())) continue;
+          shared->ReplaceCode(*lazy_compile);
         }
       }
 
diff --git a/test/mjsunit/regress/regress-crbug-424142.js b/test/mjsunit/regress/regress-crbug-424142.js
new file mode 100644 (file)
index 0000000..0a370d4
--- /dev/null
@@ -0,0 +1,36 @@
+// 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
+
+(function outer() {
+  var C = (function C_() {
+    var y = 1;
+    function CC() {
+      this.x = 0;
+    }
+    CC.prototype.f = function CCf() {
+      this.x += y;
+      return this.x;
+    };
+    return CC;
+  })();
+
+  var c = new C(0);
+})
+
+function sentinel() {}
+
+Debug = debug.Debug;
+
+var script = Debug.findScript(sentinel);
+var line = 14;
+var line_start = Debug.findScriptSourcePosition(script, line, 0);
+var line_end = Debug.findScriptSourcePosition(script, line + 1, 0) - 1;
+var actual = Debug.setBreakPointByScriptIdAndPosition(
+                 script.id, line_start).actual_position;
+// Make sure the actual break position is within the line where we set
+// the break point.
+assertTrue(line_start <= actual);
+assertTrue(actual <= line_end);