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