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

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 Object* const PathTracer::kAnyGlobalObject = reinterpret_cast<Object*>(NULL);
5187 static Object* search_target; 5187
5188 static bool found_target; 5188 class PathTracer::MarkVisitor: public ObjectVisitor {
5189 static List<Object*> object_stack(20); 5189 public:
5190 explicit MarkVisitor(PathTracer* tracer) : tracer_(tracer) {}
5191 void VisitPointers(Object** start, Object** end) {
5192 // Scan all HeapObject pointers in [start, end)
5193 for (Object** p = start; !tracer_->found() && (p < end); p++) {
5194 if ((*p)->IsHeapObject())
5195 tracer_->MarkRecursively(p, this);
5196 }
5197 }
5198
5199 private:
5200 PathTracer* tracer_;
5201 };
5190 5202
5191 5203
5192 // Tags 0, 1, and 3 are used. Use 2 for marking visited HeapObject. 5204 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: 5205 public:
5206 explicit UnmarkVisitor(PathTracer* tracer) : tracer_(tracer) {}
5198 void VisitPointers(Object** start, Object** end) { 5207 void VisitPointers(Object** start, Object** end) {
5199 // Copy all HeapObject pointers in [start, end) 5208 // Scan all HeapObject pointers in [start, end)
5200 for (Object** p = start; p < end; p++) { 5209 for (Object** p = start; p < end; p++) {
5201 if ((*p)->IsHeapObject()) 5210 if ((*p)->IsHeapObject())
5202 MarkObjectRecursively(p); 5211 tracer_->UnmarkRecursively(p, this);
5203 } 5212 }
5204 } 5213 }
5214
5215 private:
5216 PathTracer* tracer_;
5205 }; 5217 };
5206 5218
5207 static MarkObjectVisitor mark_visitor;
5208 5219
5209 static void MarkObjectRecursively(Object** p) { 5220 void PathTracer::VisitPointers(Object** start, Object** end) {
5221 bool done = ((what_to_find_ == FIND_FIRST) && found_target_);
5222 // Visit all HeapObject pointers in [start, end)
5223 for (Object** p = start; !done && (p < end); p++) {
5224 if ((*p)->IsHeapObject()) {
5225 TracePathFrom(p);
5226 done = ((what_to_find_ == FIND_FIRST) && found_target_);
5227 }
5228 }
5229 }
5230
5231
5232 void PathTracer::Reset() {
5233 found_target_ = false;
5234 object_stack_.Clear();
5235 }
5236
5237
5238 void PathTracer::TracePathFrom(Object** root) {
5239 ASSERT((search_target_ == kAnyGlobalObject) ||
5240 search_target_->IsHeapObject());
5241 found_target_in_trace_ = false;
5242 object_stack_.Clear();
5243
5244 MarkVisitor mark_visitor(this);
5245 MarkRecursively(root, &mark_visitor);
5246
5247 UnmarkVisitor unmark_visitor(this);
5248 UnmarkRecursively(root, &unmark_visitor);
5249
5250 ProcessResults();
5251 }
5252
5253
5254 void PathTracer::MarkRecursively(Object** p, MarkVisitor* mark_visitor) {
5210 if (!(*p)->IsHeapObject()) return; 5255 if (!(*p)->IsHeapObject()) return;
5211 5256
5212 HeapObject* obj = HeapObject::cast(*p); 5257 HeapObject* obj = HeapObject::cast(*p);
5213 5258
5214 Object* map = obj->map(); 5259 Object* map = obj->map();
5215 5260
5216 if (!map->IsHeapObject()) return; // visited before 5261 if (!map->IsHeapObject()) return; // visited before
5217 5262
5218 if (found_target) return; // stop if target found 5263 if (found_target_in_trace_) return; // stop if target found
5219 object_stack.Add(obj); 5264 object_stack_.Add(obj);
5220 if ((search_for_any_global && obj->IsJSGlobalObject()) || 5265 if (((search_target_ == kAnyGlobalObject) && obj->IsJSGlobalObject()) ||
5221 (!search_for_any_global && (obj == search_target))) { 5266 (obj == search_target_)) {
5222 found_target = true; 5267 found_target_in_trace_ = true;
5268 found_target_ = true;
5223 return; 5269 return;
5224 } 5270 }
5225 5271
5272 bool is_global_context = obj->IsGlobalContext();
5273
5226 // not visited yet 5274 // not visited yet
5227 Map* map_p = reinterpret_cast<Map*>(HeapObject::cast(map)); 5275 Map* map_p = reinterpret_cast<Map*>(HeapObject::cast(map));
5228 5276
5229 Address map_addr = map_p->address(); 5277 Address map_addr = map_p->address();
5230 5278
5231 obj->set_map(reinterpret_cast<Map*>(map_addr + kMarkTag)); 5279 obj->set_map(reinterpret_cast<Map*>(map_addr + kMarkTag));
5232 5280
5233 MarkObjectRecursively(&map); 5281 // Scan the object body.
5282 if (is_global_context && (visit_mode_ == VISIT_ONLY_STRONG)) {
5283 // This is specialized to scan Context's properly.
5284 Object** start = reinterpret_cast<Object**>(obj->address() +
5285 Context::kHeaderSize);
5286 Object** end = reinterpret_cast<Object**>(obj->address() +
5287 Context::kHeaderSize + Context::FIRST_WEAK_SLOT * kPointerSize);
5288 mark_visitor->VisitPointers(start, end);
5289 } else {
5290 obj->IterateBody(map_p->instance_type(),
5291 obj->SizeFromMap(map_p),
5292 mark_visitor);
5293 }
5234 5294
5235 obj->IterateBody(map_p->instance_type(), obj->SizeFromMap(map_p), 5295 // Scan the map after the body because the body is a lot more interesting
5236 &mark_visitor); 5296 // when doing leak detection.
5297 MarkRecursively(&map, mark_visitor);
5237 5298
5238 if (!found_target) // don't pop if found the target 5299 if (!found_target_in_trace_) // don't pop if found the target
5239 object_stack.RemoveLast(); 5300 object_stack_.RemoveLast();
5240 } 5301 }
5241 5302
5242 5303
5243 static void UnmarkObjectRecursively(Object** p); 5304 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; 5305 if (!(*p)->IsHeapObject()) return;
5259 5306
5260 HeapObject* obj = HeapObject::cast(*p); 5307 HeapObject* obj = HeapObject::cast(*p);
5261 5308
5262 Object* map = obj->map(); 5309 Object* map = obj->map();
5263 5310
5264 if (map->IsHeapObject()) return; // unmarked already 5311 if (map->IsHeapObject()) return; // unmarked already
5265 5312
5266 Address map_addr = reinterpret_cast<Address>(map); 5313 Address map_addr = reinterpret_cast<Address>(map);
5267 5314
5268 map_addr -= kMarkTag; 5315 map_addr -= kMarkTag;
5269 5316
5270 ASSERT_TAG_ALIGNED(map_addr); 5317 ASSERT_TAG_ALIGNED(map_addr);
5271 5318
5272 HeapObject* map_p = HeapObject::FromAddress(map_addr); 5319 HeapObject* map_p = HeapObject::FromAddress(map_addr);
5273 5320
5274 obj->set_map(reinterpret_cast<Map*>(map_p)); 5321 obj->set_map(reinterpret_cast<Map*>(map_p));
5275 5322
5276 UnmarkObjectRecursively(reinterpret_cast<Object**>(&map_p)); 5323 UnmarkRecursively(reinterpret_cast<Object**>(&map_p), unmark_visitor);
5277 5324
5278 obj->IterateBody(Map::cast(map_p)->instance_type(), 5325 obj->IterateBody(Map::cast(map_p)->instance_type(),
5279 obj->SizeFromMap(Map::cast(map_p)), 5326 obj->SizeFromMap(Map::cast(map_p)),
5280 &unmark_visitor); 5327 unmark_visitor);
5281 } 5328 }
5282 5329
5283 5330
5284 static void MarkRootObjectRecursively(Object** root) { 5331 void PathTracer::ProcessResults() {
5285 if (search_for_any_global) { 5332 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"); 5333 PrintF("=====================================\n");
5298 PrintF("==== Path to object ====\n"); 5334 PrintF("==== Path to object ====\n");
5299 PrintF("=====================================\n\n"); 5335 PrintF("=====================================\n\n");
5300 5336
5301 ASSERT(!object_stack.is_empty()); 5337 ASSERT(!object_stack_.is_empty());
5302 for (int i = 0; i < object_stack.length(); i++) { 5338 for (int i = 0; i < object_stack_.length(); i++) {
5303 if (i > 0) PrintF("\n |\n |\n V\n\n"); 5339 if (i > 0) PrintF("\n |\n |\n V\n\n");
5304 Object* obj = object_stack[i]; 5340 Object* obj = object_stack_[i];
5305 obj->Print(); 5341 obj->Print();
5306 } 5342 }
5307 PrintF("=====================================\n"); 5343 PrintF("=====================================\n");
5308 } 5344 }
5309 } 5345 }
5346 #endif // DEBUG || LIVE_OBJECT_LIST
5310 5347
5311 5348
5312 // Helper class for visiting HeapObjects recursively. 5349 #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 5350 // Triggers a depth-first traversal of reachable objects from roots
5326 // and finds a path to a specific heap object and prints it. 5351 // and finds a path to a specific heap object and prints it.
5327 void Heap::TracePathToObject(Object* target) { 5352 void Heap::TracePathToObject(Object* target) {
5328 search_target = target; 5353 PathTracer tracer(target, PathTracer::FIND_ALL, VISIT_ALL);
5329 search_for_any_global = false; 5354 IterateRoots(&tracer, VISIT_ONLY_STRONG);
5330
5331 MarkRootVisitor root_visitor;
5332 IterateRoots(&root_visitor, VISIT_ONLY_STRONG);
5333 } 5355 }
5334 5356
5335 5357
5336 // Triggers a depth-first traversal of reachable objects from roots 5358 // Triggers a depth-first traversal of reachable objects from roots
5337 // and finds a path to any global object and prints it. Useful for 5359 // and finds a path to any global object and prints it. Useful for
5338 // determining the source for leaks of global objects. 5360 // determining the source for leaks of global objects.
5339 void Heap::TracePathToGlobal() { 5361 void Heap::TracePathToGlobal() {
5340 search_target = NULL; 5362 PathTracer tracer(PathTracer::kAnyGlobalObject,
5341 search_for_any_global = true; 5363 PathTracer::FIND_ALL,
5342 5364 VISIT_ALL);
5343 MarkRootVisitor root_visitor; 5365 IterateRoots(&tracer, VISIT_ONLY_STRONG);
5344 IterateRoots(&root_visitor, VISIT_ONLY_STRONG);
5345 } 5366 }
5346 #endif 5367 #endif
5347 5368
5348 5369
5349 static intptr_t CountTotalHolesSize() { 5370 static intptr_t CountTotalHolesSize() {
5350 intptr_t holes_size = 0; 5371 intptr_t holes_size = 0;
5351 OldSpaces spaces; 5372 OldSpaces spaces;
5352 for (OldSpace* space = spaces.next(); 5373 for (OldSpace* space = spaces.next();
5353 space != NULL; 5374 space != NULL;
5354 space = spaces.next()) { 5375 space = spaces.next()) {
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
5587 void ExternalStringTable::TearDown() { 5608 void ExternalStringTable::TearDown() {
5588 new_space_strings_.Free(); 5609 new_space_strings_.Free();
5589 old_space_strings_.Free(); 5610 old_space_strings_.Free();
5590 } 5611 }
5591 5612
5592 5613
5593 List<Object*> ExternalStringTable::new_space_strings_; 5614 List<Object*> ExternalStringTable::new_space_strings_;
5594 List<Object*> ExternalStringTable::old_space_strings_; 5615 List<Object*> ExternalStringTable::old_space_strings_;
5595 5616
5596 } } // namespace v8::internal 5617 } } // 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