Reviewers: jochen (slow),

Message:
PTAL


https://codereview.chromium.org/898663005/diff/1/src/isolate.cc
File src/isolate.cc (right):

https://codereview.chromium.org/898663005/diff/1/src/isolate.cc#newcode2607
src/isolate.cc:2607: static_cast<void*>(cell->value()), mark_sweeps);
Would be nice to print the retaining path for the context. I'll add that
in future CL after implementing better path tracer in GC.

Description:
Add a flag to track detached contexts.

When embedder detaches the global objects, its context must be garbage
collected eventually.

BUG=

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

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

Affected files (+59, -2 lines):
  M include/v8.h
  M src/bootstrapper.cc
  M src/flag-definitions.h
  M src/heap/heap.h
  M src/heap/heap.cc
  M src/isolate.h
  M src/isolate.cc


Index: include/v8.h
diff --git a/include/v8.h b/include/v8.h
index e8ca3df18f28fd7219384d63e951f3607b6c7883..cb3273c71bbffdfcd1d89e08bae82556266d3b6f 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -6200,7 +6200,7 @@ class Internals {
   static const int kNullValueRootIndex = 7;
   static const int kTrueValueRootIndex = 8;
   static const int kFalseValueRootIndex = 9;
-  static const int kEmptyStringRootIndex = 155;
+  static const int kEmptyStringRootIndex = 156;

// The external allocation limit should be below 256 MB on all architectures
   // to avoid that resource-constrained embedders run low on memory.
Index: src/bootstrapper.cc
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index 6939fc35ddfd0240fc7b342695fc369c8bc4faa2..83b183c4c0a384e1d3d5180a51a32e7de9fa3b37 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -373,6 +373,9 @@ void Bootstrapper::DetachGlobal(Handle<Context> env) {
   global_proxy->set_native_context(*factory->null_value());
   SetObjectPrototype(global_proxy, factory->null_value());
   global_proxy->map()->set_constructor(*factory->null_value());
+  if (FLAG_track_detached_contexts) {
+    env->GetIsolate()->AddDetachedContext(env);
+  }
 }


Index: src/flag-definitions.h
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index ef89cac35af6340d74de8e413d103bcf67ae091c..d458aaeaaa3472be232e2247a7579c230d39ef5e 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -615,6 +615,8 @@ DEFINE_BOOL(trace_incremental_marking, false,
             "trace progress of the incremental marking")
 DEFINE_BOOL(track_gc_object_stats, false,
             "track object counts and memory usage")
+DEFINE_BOOL(track_detached_contexts, false,
+ "track native contexts that are expected to be garbage collected")
 #ifdef VERIFY_HEAP
 DEFINE_BOOL(verify_heap, false, "verify heap pointers before and after GC")
 #endif
Index: src/heap/heap.cc
diff --git a/src/heap/heap.cc b/src/heap/heap.cc
index d5417acf17ae696d7f83fc3172ea2c83b6bcaab6..08d5e03e10109c526cd38cc15175a3c936ad4f31 100644
--- a/src/heap/heap.cc
+++ b/src/heap/heap.cc
@@ -854,6 +854,9 @@ bool Heap::CollectGarbage(GarbageCollector collector, const char* gc_reason,
     }

     GarbageCollectionEpilogue();
+    if (collector == MARK_COMPACTOR && FLAG_track_detached_contexts) {
+      isolate()->CheckDetachedContextsAfterGC();
+    }
     tracer()->Stop(collector);
   }

@@ -3071,6 +3074,8 @@ void Heap::CreateInitialObjects() {
     set_keyed_load_dummy_vector(empty_fixed_array());
   }

+  set_detached_contexts(empty_fixed_array());
+
   Handle<SeededNumberDictionary> slow_element_dictionary =
       SeededNumberDictionary::New(isolate(), 0, TENURED);
   slow_element_dictionary->set_requires_slow_elements();
Index: src/heap/heap.h
diff --git a/src/heap/heap.h b/src/heap/heap.h
index 2975d09f63de15cb16e33a0d1c19ba030b5fc976..e78a7be99f4ed80e531a29bb24e82793c118a00e 100644
--- a/src/heap/heap.h
+++ b/src/heap/heap.h
@@ -183,7 +183,8 @@ namespace internal {
V(FixedArray, materialized_objects, MaterializedObjects) \ V(FixedArray, allocation_sites_scratchpad, AllocationSitesScratchpad) \ V(FixedArray, microtask_queue, MicrotaskQueue) \
-  V(FixedArray, keyed_load_dummy_vector, KeyedLoadDummyVector)
+ V(FixedArray, keyed_load_dummy_vector, KeyedLoadDummyVector) \
+  V(FixedArray, detached_contexts, DetachedContexts)

 // Entries in this list are limited to Smis and are not visited during GC.
#define SMI_ROOT_LIST(V) \
Index: src/isolate.cc
diff --git a/src/isolate.cc b/src/isolate.cc
index 259c2a2c24f62b4451f5bdd9e0771254923db832..b262b53932ace746b4b209294d6e21058b590f68 100644
--- a/src/isolate.cc
+++ b/src/isolate.cc
@@ -2568,6 +2568,48 @@ std::string Isolate::GetTurboCfgFileName() {
 }


+// Heap::detached_contexts tracks detached contexts as pairs
+// (number of GC since the context was detached, the context).
+void Isolate::AddDetachedContext(Handle<Context> context) {
+  HandleScope scope(this);
+  Handle<WeakCell> cell = factory()->NewWeakCell(context);
+  Handle<FixedArray> detached_contexts(heap()->detached_contexts());
+  int length = detached_contexts->length();
+  detached_contexts = FixedArray::CopySize(detached_contexts, length + 2);
+  detached_contexts->set(length, Smi::FromInt(0));
+  detached_contexts->set(length + 1, *cell);
+  heap()->set_detached_contexts(*detached_contexts);
+}
+
+
+void Isolate::CheckDetachedContextsAfterGC() {
+  HandleScope scope(this);
+  Handle<FixedArray> detached_contexts(heap()->detached_contexts());
+  int length = detached_contexts->length();
+  if (length == 0) return;
+  int new_length = 0;
+  for (int i = 0; i < length; i += 2) {
+    int mark_sweeps = Smi::cast(detached_contexts->get(i))->value();
+    WeakCell* cell = WeakCell::cast(detached_contexts->get(i + 1));
+    if (!cell->cleared()) {
+      detached_contexts->set(new_length, Smi::FromInt(mark_sweeps + 1));
+      detached_contexts->set(new_length + 1, cell);
+      new_length += 2;
+    }
+  }
+ PrintF("%d detached contexts are collected out of %d\n", length - new_length,
+         length);
+  for (int i = 0; i < new_length; i += 2) {
+    int mark_sweeps = Smi::cast(detached_contexts->get(i))->value();
+    WeakCell* cell = WeakCell::cast(detached_contexts->get(i + 1));
+    if (mark_sweeps > 3) {
+      PrintF("detached context 0x%p\n survived %d GCs (leak?)\n",
+             static_cast<void*>(cell->value()), mark_sweeps);
+    }
+  }
+}
+
+
 bool StackLimitCheck::JsHasOverflowed() const {
   StackGuard* stack_guard = isolate_->stack_guard();
 #ifdef USE_SIMULATOR
Index: src/isolate.h
diff --git a/src/isolate.h b/src/isolate.h
index 21ac999f8a5cc6f682b9633166f2f9fde1c04a2e..4fb8272cf5b7da77d2b1275cb03615d947e7b296 100644
--- a/src/isolate.h
+++ b/src/isolate.h
@@ -1141,6 +1141,9 @@ class Isolate {
     return store_buffer_hash_set_2_address_;
   }

+  void AddDetachedContext(Handle<Context> context);
+  void CheckDetachedContextsAfterGC();
+
  private:
   explicit Isolate(bool enable_serializer);

@@ -1362,6 +1365,7 @@ class Isolate {
   v8::Isolate::UseCounterCallback use_counter_callback_;
   BasicBlockProfiler* basic_block_profiler_;

+
   friend class ExecutionAccess;
   friend class HandleScopeImplementer;
   friend class OptimizingCompilerThread;


--
--
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