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