summaryrefslogtreecommitdiff
path: root/deps/v8/src/heap.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/heap.cc')
-rw-r--r--deps/v8/src/heap.cc198
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