Reviewers: Hannes Payer,

Message:
For discussion. In my local testing (V8 test suite; loading a handful of
websites in Chrome), this didn't flush out any issues. Do we want to land it
anyway, for the benefit of future/broader coverage?

Description:
Introduce --zap-cpp-pointers (off by default)

On GC, zaps heap pointers in C++ stack frames.

Please review this at https://codereview.chromium.org/1108013003/

Base URL: https://chromium.googlesource.com/v8/v8.git@master

Affected files (+81, -0 lines):
  M src/flag-definitions.h
  M src/frames.h
  M src/frames.cc
  M src/heap/heap.cc
  M src/heap/incremental-marking.cc


Index: src/flag-definitions.h
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index c16b2d63c167d342b2955a7a7e5b6da993460422..bfc1076b7272fe844e3a9e29b99ab92023896c84 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -558,6 +558,8 @@ DEFINE_INT(stack_size, V8_DEFAULT_STACK_SIZE_KB,
 // frames.cc
 DEFINE_INT(max_stack_trace_source_length, 300,
"maximum length of function source code printed in a stack trace.")
+DEFINE_BOOL(zap_cpp_pointers, false,
+ "zap heap pointers on the C++ stack during GC (Debug mode only)")

 // full-codegen.cc
 DEFINE_BOOL(always_inline_smi_code, false,
Index: src/frames.cc
diff --git a/src/frames.cc b/src/frames.cc
index f52b3ce4e47a1bf0fd099723fb36d0f0ac604128..9ac127bf0ea372fac67ffd7894ff4d99b577f7c5 100644
--- a/src/frames.cc
+++ b/src/frames.cc
@@ -1520,4 +1520,70 @@ Vector<StackFrame*> CreateStackMap(Isolate* isolate, Zone* zone) {
 }


+#ifdef DEBUG
+
+void ZapHeapPointersInCppFrames(Isolate* isolate, ThreadLocalTop* t) {
+  DCHECK(FLAG_zap_cpp_pointers);
+  if (t == NULL) t = isolate->thread_local_top();
+  for (StackFrameIterator it(isolate, t); !it.done(); it.Advance()) {
+    if (it.frame()->type() != StackFrame::ENTRY) continue;
+
+    EntryFrame* frame = reinterpret_cast<EntryFrame*>(it.frame());
+    // Stack layout (in case there is an exit frame):
+    // - entry frame's FP     <-- frame->fp()
+    // - saved C++ PC
+    // - last C++ stack slot  <-- cpp_start
+    // [C++ stuff...]
+    // - saved FP             <-- cpp_limit (exclusive)
+    // - saved CEntry PC
+    // - exit frame's SP      <-- caller_sp
+    // [exit frame's contents...]
+    // - exit frame's FP      <-- caller_fp
+
+    // Add 2 * kPointerSize for next FP and caller's PC.
+    Address cpp_start = frame->fp() + 2 * kPointerSize;
+
+    Address cpp_limit;
+    const int offset = EntryFrameConstants::kCallerFPOffset;
+    Address caller_fp = Memory::Address_at(frame->fp() + offset);
+
+    if (caller_fp != NULL) {
+ // If there's a previous JavaScript exit frame, stop iterating at its top.
+      const int sp_offset = ExitFrameConstants::kSPOffset;
+      Address caller_sp = Memory::Address_at(caller_fp + sp_offset);
+      // Subtract 2 * kPointerSize for CEntry PC and next FP.
+      cpp_limit = caller_sp - 2 * kPointerSize;
+    } else {
+      DCHECK(caller_fp == NULL);
+      // Reverse the original calculation how the C stack limit was set
+      // in StackGuard::ThreadLocal::Initialize() to estimate the base of
+      // the process' stack.
+      uintptr_t climit = isolate->stack_guard()->real_climit();
+      cpp_limit = reinterpret_cast<Address>(climit) + FLAG_stack_size * KB;
+    }
+
+    PrintF("Iterating EntryFrame, fp=%p, caller_fp=%p\n", frame->fp(),
+           caller_fp);
+    PrintF("Iterating from %p to %p\n", cpp_start, cpp_limit);
+
+    Heap* heap = isolate->heap();
+    NewSpace* new_space = heap->new_space();
+    OldSpace* old_space = heap->old_space();
+    MapSpace* map_space = heap->map_space();
+    LargeObjectSpace* lo_space = heap->lo_space();
+    Object* start_obj = reinterpret_cast<Object*>(cpp_start);
+    Object* limit_obj = reinterpret_cast<Object*>(cpp_limit);
+    for (Object** p = &start_obj; p < &limit_obj; ++p) {
+      if (!(*p)->IsHeapObject()) continue;
+      HeapObject* obj = HeapObject::cast(*p);
+      if (new_space->Contains(obj) || old_space->Contains(obj) ||
+          map_space->Contains(obj) || lo_space->Contains(obj)) {
+        PrintF("Found heap pointer: %p, zapping it!\n", obj);
+        *p = reinterpret_cast<Object*>(kZapValue);
+      }
+    }
+  }
+}
+
+#endif
 } }  // namespace v8::internal
Index: src/frames.h
diff --git a/src/frames.h b/src/frames.h
index 397c7b5db9cf7f912d7c3fe53a9392141b913ae2..fb1771baae7ec548088ce90f0b5a4d7c7c419130 100644
--- a/src/frames.h
+++ b/src/frames.h
@@ -901,6 +901,13 @@ class StackFrameLocator BASE_EMBEDDED {
 // zone memory.
 Vector<StackFrame*> CreateStackMap(Isolate* isolate, Zone* zone);

+#ifdef DEBUG
+// Walks the stack, finds sections belonging to C++ frames, looks for values +// that look like heap pointers inside them, and zaps them. Intended to flush +// out GC safety issues; only call this when the program must be prepared for
+// GC to happen.
+void ZapHeapPointersInCppFrames(Isolate* isolate, ThreadLocalTop* t = NULL);
+#endif
 } }  // namespace v8::internal

 #endif  // V8_FRAMES_H_
Index: src/heap/heap.cc
diff --git a/src/heap/heap.cc b/src/heap/heap.cc
index 8d34738dae81757b9e5918875d6adf41cecf98bb..b3e50b8493502f45207641c2e2cd89c6a3027fda 100644
--- a/src/heap/heap.cc
+++ b/src/heap/heap.cc
@@ -857,6 +857,8 @@ bool Heap::CollectGarbage(GarbageCollector collector, const char* gc_reason,
   // assume that a garbage collection will allow the subsequent
   // allocation attempts to go through.
   allocation_timeout_ = Max(6, FLAG_gc_interval);
+
+  if (FLAG_zap_cpp_pointers) ZapHeapPointersInCppFrames(isolate());
 #endif

   EnsureFillerObjectAtTop();
Index: src/heap/incremental-marking.cc
diff --git a/src/heap/incremental-marking.cc b/src/heap/incremental-marking.cc index 2ba969432d0a009690f08226e19af6086e8da719..4524ce45a6515c7d8944ecc61301f9db4b25871f 100644
--- a/src/heap/incremental-marking.cc
+++ b/src/heap/incremental-marking.cc
@@ -899,6 +899,10 @@ intptr_t IncrementalMarking::Step(intptr_t allocated_bytes,
     return 0;
   }

+#ifdef DEBUG
+  if (FLAG_zap_cpp_pointers) ZapHeapPointersInCppFrames(heap_->isolate());
+#endif
+
   allocated_ += allocated_bytes;

if (marking == DO_NOT_FORCE_MARKING && allocated_ < kAllocatedThreshold &&


--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to