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.
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);
+ }
}
"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
}
GarbageCollectionEpilogue();
+ if (collector == MARK_COMPACTOR && FLAG_track_detached_contexts) {
+ isolate()->CheckDetachedContextsAfterGC();
+ }
tracer()->Stop(collector);
}
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();
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) \
}
+// 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
return store_buffer_hash_set_2_address_;
}
+ void AddDetachedContext(Handle<Context> context);
+ void CheckDetachedContextsAfterGC();
+
private:
explicit Isolate(bool enable_serializer);
v8::Isolate::UseCounterCallback use_counter_callback_;
BasicBlockProfiler* basic_block_profiler_;
+
friend class ExecutionAccess;
friend class HandleScopeImplementer;
friend class OptimizingCompilerThread;