diff options
Diffstat (limited to 'deps/v8/src/heap.cc')
-rw-r--r-- | deps/v8/src/heap.cc | 198 |
1 files changed, 108 insertions, 90 deletions
diff --git a/deps/v8/src/heap.cc b/deps/v8/src/heap.cc index f88ebda53..1fadec383 100644 --- a/deps/v8/src/heap.cc +++ b/deps/v8/src/heap.cc @@ -134,7 +134,7 @@ Heap::HeapState Heap::gc_state_ = NOT_IN_GC; int Heap::mc_count_ = 0; int Heap::ms_count_ = 0; -int Heap::gc_count_ = 0; +unsigned int Heap::gc_count_ = 0; GCTracer* Heap::tracer_ = NULL; @@ -515,7 +515,6 @@ bool Heap::CollectGarbage(AllocationSpace space, GarbageCollector collector) { #ifdef ENABLE_LOGGING_AND_PROFILING if (FLAG_log_gc) HeapProfiler::WriteSample(); - if (CpuProfiler::is_profiling()) CpuProfiler::ProcessMovedFunctions(); #endif return next_gc_likely_to_collect_more; @@ -1350,9 +1349,8 @@ class ScavengingVisitor : public StaticVisitorBase { HEAP_PROFILE(ObjectMoveEvent(source->address(), target->address())); #if defined(ENABLE_LOGGING_AND_PROFILING) if (Logger::is_logging() || CpuProfiler::is_profiling()) { - if (target->IsJSFunction()) { - PROFILE(FunctionMoveEvent(source->address(), target->address())); - PROFILE(FunctionCreateEventFromMove(JSFunction::cast(target))); + if (target->IsSharedFunctionInfo()) { + PROFILE(SFIMoveEvent(source->address(), target->address())); } } #endif @@ -2924,9 +2922,8 @@ MaybeObject* Heap::AllocateFunctionPrototype(JSFunction* function) { // constructor to the function. Object* result; { MaybeObject* maybe_result = - JSObject::cast(prototype)->SetProperty(constructor_symbol(), - function, - DONT_ENUM); + JSObject::cast(prototype)->SetLocalPropertyIgnoreAttributes( + constructor_symbol(), function, DONT_ENUM); if (!maybe_result->ToObject(&result)) return maybe_result; } return prototype; @@ -3797,9 +3794,9 @@ bool Heap::IdleNotification() { static const int kIdlesBeforeMarkSweep = 7; static const int kIdlesBeforeMarkCompact = 8; static const int kMaxIdleCount = kIdlesBeforeMarkCompact + 1; - static const int kGCsBetweenCleanup = 4; + static const unsigned int kGCsBetweenCleanup = 4; static int number_idle_notifications = 0; - static int last_gc_count = gc_count_; + static unsigned int last_gc_count = gc_count_; bool uncommit = true; bool finished = false; @@ -3808,7 +3805,7 @@ bool Heap::IdleNotification() { // GCs have taken place. This allows another round of cleanup based // on idle notifications if enough work has been carried out to // provoke a number of garbage collections. - if (gc_count_ < last_gc_count + kGCsBetweenCleanup) { + if (gc_count_ - last_gc_count < kGCsBetweenCleanup) { number_idle_notifications = Min(number_idle_notifications + 1, kMaxIdleCount); } else { @@ -5182,32 +5179,77 @@ void HeapIterator::reset() { } -#ifdef DEBUG +#if defined(DEBUG) || defined(LIVE_OBJECT_LIST) + +Object* const PathTracer::kAnyGlobalObject = reinterpret_cast<Object*>(NULL); -static bool search_for_any_global; -static Object* search_target; -static bool found_target; -static List<Object*> object_stack(20); +class PathTracer::MarkVisitor: public ObjectVisitor { + public: + explicit MarkVisitor(PathTracer* tracer) : tracer_(tracer) {} + void VisitPointers(Object** start, Object** end) { + // Scan all HeapObject pointers in [start, end) + for (Object** p = start; !tracer_->found() && (p < end); p++) { + if ((*p)->IsHeapObject()) + tracer_->MarkRecursively(p, this); + } + } + private: + PathTracer* tracer_; +}; -// Tags 0, 1, and 3 are used. Use 2 for marking visited HeapObject. -static const int kMarkTag = 2; -static void MarkObjectRecursively(Object** p); -class MarkObjectVisitor : public ObjectVisitor { +class PathTracer::UnmarkVisitor: public ObjectVisitor { public: + explicit UnmarkVisitor(PathTracer* tracer) : tracer_(tracer) {} void VisitPointers(Object** start, Object** end) { - // Copy all HeapObject pointers in [start, end) + // Scan all HeapObject pointers in [start, end) for (Object** p = start; p < end; p++) { if ((*p)->IsHeapObject()) - MarkObjectRecursively(p); + tracer_->UnmarkRecursively(p, this); } } + + private: + PathTracer* tracer_; }; -static MarkObjectVisitor mark_visitor; -static void MarkObjectRecursively(Object** p) { +void PathTracer::VisitPointers(Object** start, Object** end) { + bool done = ((what_to_find_ == FIND_FIRST) && found_target_); + // Visit all HeapObject pointers in [start, end) + for (Object** p = start; !done && (p < end); p++) { + if ((*p)->IsHeapObject()) { + TracePathFrom(p); + done = ((what_to_find_ == FIND_FIRST) && found_target_); + } + } +} + + +void PathTracer::Reset() { + found_target_ = false; + object_stack_.Clear(); +} + + +void PathTracer::TracePathFrom(Object** root) { + ASSERT((search_target_ == kAnyGlobalObject) || + search_target_->IsHeapObject()); + found_target_in_trace_ = false; + object_stack_.Clear(); + + MarkVisitor mark_visitor(this); + MarkRecursively(root, &mark_visitor); + + UnmarkVisitor unmark_visitor(this); + UnmarkRecursively(root, &unmark_visitor); + + ProcessResults(); +} + + +void PathTracer::MarkRecursively(Object** p, MarkVisitor* mark_visitor) { if (!(*p)->IsHeapObject()) return; HeapObject* obj = HeapObject::cast(*p); @@ -5216,14 +5258,17 @@ static void MarkObjectRecursively(Object** p) { if (!map->IsHeapObject()) return; // visited before - if (found_target) return; // stop if target found - object_stack.Add(obj); - if ((search_for_any_global && obj->IsJSGlobalObject()) || - (!search_for_any_global && (obj == search_target))) { - found_target = true; + if (found_target_in_trace_) return; // stop if target found + object_stack_.Add(obj); + if (((search_target_ == kAnyGlobalObject) && obj->IsJSGlobalObject()) || + (obj == search_target_)) { + found_target_in_trace_ = true; + found_target_ = true; return; } + bool is_global_context = obj->IsGlobalContext(); + // not visited yet Map* map_p = reinterpret_cast<Map*>(HeapObject::cast(map)); @@ -5231,31 +5276,30 @@ static void MarkObjectRecursively(Object** p) { obj->set_map(reinterpret_cast<Map*>(map_addr + kMarkTag)); - MarkObjectRecursively(&map); + // Scan the object body. + if (is_global_context && (visit_mode_ == VISIT_ONLY_STRONG)) { + // This is specialized to scan Context's properly. + Object** start = reinterpret_cast<Object**>(obj->address() + + Context::kHeaderSize); + Object** end = reinterpret_cast<Object**>(obj->address() + + Context::kHeaderSize + Context::FIRST_WEAK_SLOT * kPointerSize); + mark_visitor->VisitPointers(start, end); + } else { + obj->IterateBody(map_p->instance_type(), + obj->SizeFromMap(map_p), + mark_visitor); + } - obj->IterateBody(map_p->instance_type(), obj->SizeFromMap(map_p), - &mark_visitor); + // Scan the map after the body because the body is a lot more interesting + // when doing leak detection. + MarkRecursively(&map, mark_visitor); - if (!found_target) // don't pop if found the target - object_stack.RemoveLast(); + if (!found_target_in_trace_) // don't pop if found the target + object_stack_.RemoveLast(); } -static void UnmarkObjectRecursively(Object** p); -class UnmarkObjectVisitor : public ObjectVisitor { - public: - void VisitPointers(Object** start, Object** end) { - // Copy all HeapObject pointers in [start, end) - for (Object** p = start; p < end; p++) { - if ((*p)->IsHeapObject()) - UnmarkObjectRecursively(p); - } - } -}; - -static UnmarkObjectVisitor unmark_visitor; - -static void UnmarkObjectRecursively(Object** p) { +void PathTracer::UnmarkRecursively(Object** p, UnmarkVisitor* unmark_visitor) { if (!(*p)->IsHeapObject()) return; HeapObject* obj = HeapObject::cast(*p); @@ -5274,63 +5318,38 @@ static void UnmarkObjectRecursively(Object** p) { obj->set_map(reinterpret_cast<Map*>(map_p)); - UnmarkObjectRecursively(reinterpret_cast<Object**>(&map_p)); + UnmarkRecursively(reinterpret_cast<Object**>(&map_p), unmark_visitor); obj->IterateBody(Map::cast(map_p)->instance_type(), obj->SizeFromMap(Map::cast(map_p)), - &unmark_visitor); + unmark_visitor); } -static void MarkRootObjectRecursively(Object** root) { - if (search_for_any_global) { - ASSERT(search_target == NULL); - } else { - ASSERT(search_target->IsHeapObject()); - } - found_target = false; - object_stack.Clear(); - - MarkObjectRecursively(root); - UnmarkObjectRecursively(root); - - if (found_target) { +void PathTracer::ProcessResults() { + if (found_target_) { PrintF("=====================================\n"); PrintF("==== Path to object ====\n"); PrintF("=====================================\n\n"); - ASSERT(!object_stack.is_empty()); - for (int i = 0; i < object_stack.length(); i++) { + ASSERT(!object_stack_.is_empty()); + for (int i = 0; i < object_stack_.length(); i++) { if (i > 0) PrintF("\n |\n |\n V\n\n"); - Object* obj = object_stack[i]; + Object* obj = object_stack_[i]; obj->Print(); } PrintF("=====================================\n"); } } +#endif // DEBUG || LIVE_OBJECT_LIST -// Helper class for visiting HeapObjects recursively. -class MarkRootVisitor: public ObjectVisitor { - public: - void VisitPointers(Object** start, Object** end) { - // Visit all HeapObject pointers in [start, end) - for (Object** p = start; p < end; p++) { - if ((*p)->IsHeapObject()) - MarkRootObjectRecursively(p); - } - } -}; - - +#ifdef DEBUG // Triggers a depth-first traversal of reachable objects from roots // and finds a path to a specific heap object and prints it. void Heap::TracePathToObject(Object* target) { - search_target = target; - search_for_any_global = false; - - MarkRootVisitor root_visitor; - IterateRoots(&root_visitor, VISIT_ONLY_STRONG); + PathTracer tracer(target, PathTracer::FIND_ALL, VISIT_ALL); + IterateRoots(&tracer, VISIT_ONLY_STRONG); } @@ -5338,11 +5357,10 @@ void Heap::TracePathToObject(Object* target) { // and finds a path to any global object and prints it. Useful for // determining the source for leaks of global objects. void Heap::TracePathToGlobal() { - search_target = NULL; - search_for_any_global = true; - - MarkRootVisitor root_visitor; - IterateRoots(&root_visitor, VISIT_ONLY_STRONG); + PathTracer tracer(PathTracer::kAnyGlobalObject, + PathTracer::FIND_ALL, + VISIT_ALL); + IterateRoots(&tracer, VISIT_ONLY_STRONG); } #endif |