Commit b7d27ea5 authored by ulan's avatar ulan Committed by Commit bot

Add a flag to track detached contexts.

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

BUG=

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

Cr-Commit-Position: refs/heads/master@{#26450}
parent 0e3b5386
......@@ -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.
......
......@@ -374,6 +374,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);
}
}
......
......@@ -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
......
......@@ -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();
......
......@@ -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) \
......
......@@ -2568,6 +2568,54 @@ 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);
}
}
if (length == new_length) {
heap()->set_detached_contexts(heap()->empty_fixed_array());
} else {
heap()->RightTrimFixedArray<Heap::FROM_GC>(*detached_contexts,
length - new_length);
}
}
bool StackLimitCheck::JsHasOverflowed() const {
StackGuard* stack_guard = isolate_->stack_guard();
#ifdef USE_SIMULATOR
......
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment