Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(234)

Side by Side Diff: src/heap.cc

Issue 6541044: Refactored PathTracer in heap.cc.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« src/heap.h ('K') | « src/heap.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 5163 matching lines...) Expand 10 before | Expand all | Expand 10 after
5174 } 5174 }
5175 5175
5176 5176
5177 void HeapIterator::reset() { 5177 void HeapIterator::reset() {
5178 // Restart the iterator. 5178 // Restart the iterator.
5179 Shutdown(); 5179 Shutdown();
5180 Init(); 5180 Init();
5181 } 5181 }
5182 5182
5183 5183
5184 #ifdef DEBUG 5184 #if defined(DEBUG) || defined(LIVE_OBJECT_LIST)
5185 5185
5186 static bool search_for_any_global; 5186 class PathTracer::MarkVisitor: public ObjectVisitor {
5187 static Object* search_target; 5187 public:
5188 static bool found_target; 5188 explicit MarkVisitor(PathTracer* tracer) : tracer_(tracer) {}
5189 static List<Object*> object_stack(20); 5189 void VisitPointers(Object** start, Object** end) {
5190 // Scan all HeapObject pointers in [start, end)
5191 for (Object** p = start; !tracer_->found() && (p < end); p++) {
5192 if ((*p)->IsHeapObject())
5193 tracer_->MarkRecursively(p, this);
5194 }
5195 }
5196
5197 private:
5198 PathTracer* tracer_;
5199 };
5190 5200
5191 5201
5192 // Tags 0, 1, and 3 are used. Use 2 for marking visited HeapObject. 5202 class PathTracer::UnmarkVisitor: public ObjectVisitor {
5193 static const int kMarkTag = 2;
5194
5195 static void MarkObjectRecursively(Object** p);
5196 class MarkObjectVisitor : public ObjectVisitor {
5197 public: 5203 public:
5204 explicit UnmarkVisitor(PathTracer* tracer) : tracer_(tracer) {}
5198 void VisitPointers(Object** start, Object** end) { 5205 void VisitPointers(Object** start, Object** end) {
5199 // Copy all HeapObject pointers in [start, end) 5206 // Scan all HeapObject pointers in [start, end)
5200 for (Object** p = start; p < end; p++) { 5207 for (Object** p = start; p < end; p++) {
5201 if ((*p)->IsHeapObject()) 5208 if ((*p)->IsHeapObject())
5202 MarkObjectRecursively(p); 5209 tracer_->UnmarkRecursively(p, this);
5203 } 5210 }
5204 } 5211 }
5212
5213 private:
5214 PathTracer* tracer_;
5205 }; 5215 };
5206 5216
5207 static MarkObjectVisitor mark_visitor;
5208 5217
5209 static void MarkObjectRecursively(Object** p) { 5218 void PathTracer::TracePathFrom(Object** root) {
5219 if (search_for_any_global_) {
5220 ASSERT(search_target_ == NULL);
5221 } else {
5222 ASSERT(search_target_->IsHeapObject());
5223 }
5224 found_target_in_trace_ = false;
5225 object_stack_.Clear();
5226
5227 MarkVisitor mark_visitor(this);
5228 MarkRecursively(root, &mark_visitor);
5229
5230 UnmarkVisitor unmark_visitor(this);
5231 UnmarkRecursively(root, &unmark_visitor);
5232
5233 ProcessResults();
5234 }
5235
5236
5237 void PathTracer::MarkRecursively(Object** p, MarkVisitor* mark_visitor) {
5210 if (!(*p)->IsHeapObject()) return; 5238 if (!(*p)->IsHeapObject()) return;
5211 5239
5212 HeapObject* obj = HeapObject::cast(*p); 5240 HeapObject* obj = HeapObject::cast(*p);
5213 5241
5214 Object* map = obj->map(); 5242 Object* map = obj->map();
5215 5243
5216 if (!map->IsHeapObject()) return; // visited before 5244 if (!map->IsHeapObject()) return; // visited before
5217 5245
5218 if (found_target) return; // stop if target found 5246 if (found_target_in_trace_) return; // stop if target found
5219 object_stack.Add(obj); 5247 object_stack_.Add(obj);
5220 if ((search_for_any_global && obj->IsJSGlobalObject()) || 5248 if ((search_for_any_global_ && obj->IsJSGlobalObject()) ||
5221 (!search_for_any_global && (obj == search_target))) { 5249 (!search_for_any_global_ && (obj == search_target_))) {
5222 found_target = true; 5250 found_target_in_trace_ = true;
5251 found_target_ = true;
5223 return; 5252 return;
5224 } 5253 }
5225 5254
5255 bool is_global_context = obj->IsGlobalContext();
5256
5226 // not visited yet 5257 // not visited yet
5227 Map* map_p = reinterpret_cast<Map*>(HeapObject::cast(map)); 5258 Map* map_p = reinterpret_cast<Map*>(HeapObject::cast(map));
5228 5259
5229 Address map_addr = map_p->address(); 5260 Address map_addr = map_p->address();
5230 5261
5231 obj->set_map(reinterpret_cast<Map*>(map_addr + kMarkTag)); 5262 obj->set_map(reinterpret_cast<Map*>(map_addr + kMarkTag));
5232 5263
5233 MarkObjectRecursively(&map); 5264 // Scan the object body.
5265 if (is_global_context && skip_weak_refs_) {
5266 // This is specialized to scan Context's properly.
5267 Object** start = reinterpret_cast<Object**>(obj->address() +
5268 Context::kHeaderSize);
5269 Object** end = reinterpret_cast<Object**>(obj->address() +
5270 Context::kHeaderSize + Context::FIRST_WEAK_SLOT * kPointerSize);
5271 mark_visitor->VisitPointers(start, end);
5272 } else {
5273 obj->IterateBody(map_p->instance_type(),
5274 obj->SizeFromMap(map_p),
5275 mark_visitor);
5276 }
5234 5277
5235 obj->IterateBody(map_p->instance_type(), obj->SizeFromMap(map_p), 5278 // Scan the map after the body because the body is a lot more interesting
5236 &mark_visitor); 5279 // when doing leak detection.
5280 MarkRecursively(&map, mark_visitor);
5237 5281
5238 if (!found_target) // don't pop if found the target 5282 if (!found_target_in_trace_) // don't pop if found the target
5239 object_stack.RemoveLast(); 5283 object_stack_.RemoveLast();
5240 } 5284 }
5241 5285
5242 5286
5243 static void UnmarkObjectRecursively(Object** p); 5287 void PathTracer::UnmarkRecursively(Object** p, UnmarkVisitor* unmark_visitor) {
5244 class UnmarkObjectVisitor : public ObjectVisitor {
5245 public:
5246 void VisitPointers(Object** start, Object** end) {
5247 // Copy all HeapObject pointers in [start, end)
5248 for (Object** p = start; p < end; p++) {
5249 if ((*p)->IsHeapObject())
5250 UnmarkObjectRecursively(p);
5251 }
5252 }
5253 };
5254
5255 static UnmarkObjectVisitor unmark_visitor;
5256
5257 static void UnmarkObjectRecursively(Object** p) {
5258 if (!(*p)->IsHeapObject()) return; 5288 if (!(*p)->IsHeapObject()) return;
5259 5289
5260 HeapObject* obj = HeapObject::cast(*p); 5290 HeapObject* obj = HeapObject::cast(*p);
5261 5291
5262 Object* map = obj->map(); 5292 Object* map = obj->map();
5263 5293
5264 if (map->IsHeapObject()) return; // unmarked already 5294 if (map->IsHeapObject()) return; // unmarked already
5265 5295
5266 Address map_addr = reinterpret_cast<Address>(map); 5296 Address map_addr = reinterpret_cast<Address>(map);
5267 5297
5268 map_addr -= kMarkTag; 5298 map_addr -= kMarkTag;
5269 5299
5270 ASSERT_TAG_ALIGNED(map_addr); 5300 ASSERT_TAG_ALIGNED(map_addr);
5271 5301
5272 HeapObject* map_p = HeapObject::FromAddress(map_addr); 5302 HeapObject* map_p = HeapObject::FromAddress(map_addr);
5273 5303
5274 obj->set_map(reinterpret_cast<Map*>(map_p)); 5304 obj->set_map(reinterpret_cast<Map*>(map_p));
5275 5305
5276 UnmarkObjectRecursively(reinterpret_cast<Object**>(&map_p)); 5306 UnmarkRecursively(reinterpret_cast<Object**>(&map_p), unmark_visitor);
5277 5307
5278 obj->IterateBody(Map::cast(map_p)->instance_type(), 5308 obj->IterateBody(Map::cast(map_p)->instance_type(),
5279 obj->SizeFromMap(Map::cast(map_p)), 5309 obj->SizeFromMap(Map::cast(map_p)),
5280 &unmark_visitor); 5310 unmark_visitor);
5281 } 5311 }
5282 5312
5283 5313
5284 static void MarkRootObjectRecursively(Object** root) { 5314 void PathTracer::ProcessResults() {
5285 if (search_for_any_global) { 5315 if (found_target_) {
5286 ASSERT(search_target == NULL);
5287 } else {
5288 ASSERT(search_target->IsHeapObject());
5289 }
5290 found_target = false;
5291 object_stack.Clear();
5292
5293 MarkObjectRecursively(root);
5294 UnmarkObjectRecursively(root);
5295
5296 if (found_target) {
5297 PrintF("=====================================\n"); 5316 PrintF("=====================================\n");
5298 PrintF("==== Path to object ====\n"); 5317 PrintF("==== Path to object ====\n");
5299 PrintF("=====================================\n\n"); 5318 PrintF("=====================================\n\n");
5300 5319
5301 ASSERT(!object_stack.is_empty()); 5320 ASSERT(!object_stack_.is_empty());
5302 for (int i = 0; i < object_stack.length(); i++) { 5321 for (int i = 0; i < object_stack_.length(); i++) {
5303 if (i > 0) PrintF("\n |\n |\n V\n\n"); 5322 if (i > 0) PrintF("\n |\n |\n V\n\n");
5304 Object* obj = object_stack[i]; 5323 Object* obj = object_stack_[i];
5305 obj->Print(); 5324 obj->Print();
5306 } 5325 }
5307 PrintF("=====================================\n"); 5326 PrintF("=====================================\n");
5308 } 5327 }
5309 } 5328 }
5329 #endif // DEBUG || LIVE_OBJECT_LIST
5310 5330
5311 5331
5312 // Helper class for visiting HeapObjects recursively. 5332 #ifdef DEBUG
5313 class MarkRootVisitor: public ObjectVisitor {
5314 public:
5315 void VisitPointers(Object** start, Object** end) {
5316 // Visit all HeapObject pointers in [start, end)
5317 for (Object** p = start; p < end; p++) {
5318 if ((*p)->IsHeapObject())
5319 MarkRootObjectRecursively(p);
5320 }
5321 }
5322 };
5323
5324
5325 // Triggers a depth-first traversal of reachable objects from roots 5333 // Triggers a depth-first traversal of reachable objects from roots
5326 // and finds a path to a specific heap object and prints it. 5334 // and finds a path to a specific heap object and prints it.
5327 void Heap::TracePathToObject(Object* target) { 5335 void Heap::TracePathToObject(Object* target) {
5328 search_target = target; 5336 PathTracer tracer(target, false, PathTracer::FIND_ALL, false);
5329 search_for_any_global = false; 5337 IterateRoots(&tracer, VISIT_ONLY_STRONG);
5330
5331 MarkRootVisitor root_visitor;
5332 IterateRoots(&root_visitor, VISIT_ONLY_STRONG);
5333 } 5338 }
5334 5339
5335 5340
5336 // Triggers a depth-first traversal of reachable objects from roots 5341 // Triggers a depth-first traversal of reachable objects from roots
5337 // and finds a path to any global object and prints it. Useful for 5342 // and finds a path to any global object and prints it. Useful for
5338 // determining the source for leaks of global objects. 5343 // determining the source for leaks of global objects.
5339 void Heap::TracePathToGlobal() { 5344 void Heap::TracePathToGlobal() {
5340 search_target = NULL; 5345 PathTracer tracer(NULL, true, PathTracer::FIND_ALL, false);
5341 search_for_any_global = true; 5346 IterateRoots(&tracer, VISIT_ONLY_STRONG);
5342
5343 MarkRootVisitor root_visitor;
5344 IterateRoots(&root_visitor, VISIT_ONLY_STRONG);
5345 } 5347 }
5346 #endif 5348 #endif
5347 5349
5348 5350
5349 static intptr_t CountTotalHolesSize() { 5351 static intptr_t CountTotalHolesSize() {
5350 intptr_t holes_size = 0; 5352 intptr_t holes_size = 0;
5351 OldSpaces spaces; 5353 OldSpaces spaces;
5352 for (OldSpace* space = spaces.next(); 5354 for (OldSpace* space = spaces.next();
5353 space != NULL; 5355 space != NULL;
5354 space = spaces.next()) { 5356 space = spaces.next()) {
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
5587 void ExternalStringTable::TearDown() { 5589 void ExternalStringTable::TearDown() {
5588 new_space_strings_.Free(); 5590 new_space_strings_.Free();
5589 old_space_strings_.Free(); 5591 old_space_strings_.Free();
5590 } 5592 }
5591 5593
5592 5594
5593 List<Object*> ExternalStringTable::new_space_strings_; 5595 List<Object*> ExternalStringTable::new_space_strings_;
5594 List<Object*> ExternalStringTable::old_space_strings_; 5596 List<Object*> ExternalStringTable::old_space_strings_;
5595 5597
5596 } } // namespace v8::internal 5598 } } // namespace v8::internal
OLDNEW
« src/heap.h ('K') | « src/heap.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698