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

Side by Side Diff: src/heap.cc

Issue 6614010: [Isolates] Merge 6700:7030 from bleeding_edge to isolates. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/isolates/
Patch Set: '' Created 9 years, 9 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
« no previous file with comments | « src/heap.h ('k') | src/heap-profiler.h » ('j') | 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 493 matching lines...) Expand 10 before | Expand all | Expand 10 after
504 next_gc_likely_to_collect_more = 504 next_gc_likely_to_collect_more =
505 PerformGarbageCollection(collector, &tracer); 505 PerformGarbageCollection(collector, &tracer);
506 rate->Stop(); 506 rate->Stop();
507 507
508 GarbageCollectionEpilogue(); 508 GarbageCollectionEpilogue();
509 } 509 }
510 510
511 511
512 #ifdef ENABLE_LOGGING_AND_PROFILING 512 #ifdef ENABLE_LOGGING_AND_PROFILING
513 if (FLAG_log_gc) HeapProfiler::WriteSample(); 513 if (FLAG_log_gc) HeapProfiler::WriteSample();
514 if (CpuProfiler::is_profiling()) CpuProfiler::ProcessMovedFunctions();
515 #endif 514 #endif
516 515
517 return next_gc_likely_to_collect_more; 516 return next_gc_likely_to_collect_more;
518 } 517 }
519 518
520 519
521 void Heap::PerformScavenge() { 520 void Heap::PerformScavenge() {
522 GCTracer tracer(this); 521 GCTracer tracer(this);
523 PerformGarbageCollection(SCAVENGER, &tracer); 522 PerformGarbageCollection(SCAVENGER, &tracer);
524 } 523 }
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after
836 } 835 }
837 836
838 837
839 void Heap::MarkCompactPrologue(bool is_compacting) { 838 void Heap::MarkCompactPrologue(bool is_compacting) {
840 // At any old GC clear the keyed lookup cache to enable collection of unused 839 // At any old GC clear the keyed lookup cache to enable collection of unused
841 // maps. 840 // maps.
842 isolate_->keyed_lookup_cache()->Clear(); 841 isolate_->keyed_lookup_cache()->Clear();
843 isolate_->context_slot_cache()->Clear(); 842 isolate_->context_slot_cache()->Clear();
844 isolate_->descriptor_lookup_cache()->Clear(); 843 isolate_->descriptor_lookup_cache()->Clear();
845 844
846 isolate_->runtime_profiler()->MarkCompactPrologue(is_compacting);
847
848 isolate_->compilation_cache()->MarkCompactPrologue(); 845 isolate_->compilation_cache()->MarkCompactPrologue();
849 846
850 CompletelyClearInstanceofCache(); 847 CompletelyClearInstanceofCache();
851 848
852 if (is_compacting) FlushNumberStringCache(); 849 if (is_compacting) FlushNumberStringCache();
853 850
854 ClearNormalizedMapCaches(); 851 ClearNormalizedMapCaches();
855 } 852 }
856 853
857 854
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
1017 Address value_address = 1014 Address value_address =
1018 reinterpret_cast<Address>(cell) + 1015 reinterpret_cast<Address>(cell) +
1019 (JSGlobalPropertyCell::kValueOffset - kHeapObjectTag); 1016 (JSGlobalPropertyCell::kValueOffset - kHeapObjectTag);
1020 scavenge_visitor.VisitPointer(reinterpret_cast<Object**>(value_address)); 1017 scavenge_visitor.VisitPointer(reinterpret_cast<Object**>(value_address));
1021 } 1018 }
1022 } 1019 }
1023 1020
1024 // Scavenge object reachable from the global contexts list directly. 1021 // Scavenge object reachable from the global contexts list directly.
1025 scavenge_visitor.VisitPointer(BitCast<Object**>(&global_contexts_list_)); 1022 scavenge_visitor.VisitPointer(BitCast<Object**>(&global_contexts_list_));
1026 1023
1027 // Scavenge objects reachable from the runtime-profiler sampler
1028 // window directly.
1029 RuntimeProfiler* runtime_profiler = isolate_->runtime_profiler();
1030 Object** sampler_window_address = runtime_profiler->SamplerWindowAddress();
1031 int sampler_window_size = runtime_profiler->SamplerWindowSize();
1032 scavenge_visitor.VisitPointers(
1033 sampler_window_address,
1034 sampler_window_address + sampler_window_size);
1035
1036 new_space_front = DoScavenge(&scavenge_visitor, new_space_front); 1024 new_space_front = DoScavenge(&scavenge_visitor, new_space_front);
1037 1025
1038 UpdateNewSpaceReferencesInExternalStringTable( 1026 UpdateNewSpaceReferencesInExternalStringTable(
1039 &UpdateNewSpaceReferenceInExternalStringTableEntry); 1027 &UpdateNewSpaceReferenceInExternalStringTableEntry);
1040 1028
1041 LiveObjectList::UpdateReferencesForScavengeGC(); 1029 LiveObjectList::UpdateReferencesForScavengeGC();
1030 isolate()->runtime_profiler()->UpdateSamplesAfterScavenge();
1042 1031
1043 ASSERT(new_space_front == new_space_.top()); 1032 ASSERT(new_space_front == new_space_.top());
1044 1033
1045 is_safe_to_read_maps_ = true; 1034 is_safe_to_read_maps_ = true;
1046 1035
1047 // Set age mark. 1036 // Set age mark.
1048 new_space_.set_age_mark(new_space_.top()); 1037 new_space_.set_age_mark(new_space_.top());
1049 1038
1050 // Update how much has survived scavenge. 1039 // Update how much has survived scavenge.
1051 IncrementYoungSurvivorsCounter(static_cast<int>( 1040 IncrementYoungSurvivorsCounter(static_cast<int>(
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after
1322 1311
1323 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) 1312 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
1324 // Update NewSpace stats if necessary. 1313 // Update NewSpace stats if necessary.
1325 RecordCopiedObject(heap, target); 1314 RecordCopiedObject(heap, target);
1326 #endif 1315 #endif
1327 HEAP_PROFILE(heap, ObjectMoveEvent(source->address(), target->address())); 1316 HEAP_PROFILE(heap, ObjectMoveEvent(source->address(), target->address()));
1328 #if defined(ENABLE_LOGGING_AND_PROFILING) 1317 #if defined(ENABLE_LOGGING_AND_PROFILING)
1329 Isolate* isolate = heap->isolate(); 1318 Isolate* isolate = heap->isolate();
1330 if (isolate->logger()->is_logging() || 1319 if (isolate->logger()->is_logging() ||
1331 isolate->cpu_profiler()->is_profiling()) { 1320 isolate->cpu_profiler()->is_profiling()) {
1332 if (target->IsJSFunction()) { 1321 if (target->IsSharedFunctionInfo()) {
1333 PROFILE(FunctionMoveEvent(heap, source->address(), target->address())); 1322 PROFILE(SFIMoveEvent(source->address(), target->address()));
1334 PROFILE(FunctionCreateEventFromMove(heap, JSFunction::cast(target)));
1335 } 1323 }
1336 } 1324 }
1337 #endif 1325 #endif
1338 return target; 1326 return target;
1339 } 1327 }
1340 1328
1341 1329
1342 template<ObjectContents object_contents, SizeRestriction size_restriction> 1330 template<ObjectContents object_contents, SizeRestriction size_restriction>
1343 static inline void EvacuateObject(Map* map, 1331 static inline void EvacuateObject(Map* map,
1344 HeapObject** slot, 1332 HeapObject** slot,
(...skipping 1567 matching lines...) Expand 10 before | Expand all | Expand 10 after
2912 JSFunction* object_function = 2900 JSFunction* object_function =
2913 function->context()->global_context()->object_function(); 2901 function->context()->global_context()->object_function();
2914 Object* prototype; 2902 Object* prototype;
2915 { MaybeObject* maybe_prototype = AllocateJSObject(object_function); 2903 { MaybeObject* maybe_prototype = AllocateJSObject(object_function);
2916 if (!maybe_prototype->ToObject(&prototype)) return maybe_prototype; 2904 if (!maybe_prototype->ToObject(&prototype)) return maybe_prototype;
2917 } 2905 }
2918 // When creating the prototype for the function we must set its 2906 // When creating the prototype for the function we must set its
2919 // constructor to the function. 2907 // constructor to the function.
2920 Object* result; 2908 Object* result;
2921 { MaybeObject* maybe_result = 2909 { MaybeObject* maybe_result =
2922 JSObject::cast(prototype)->SetProperty(constructor_symbol(), 2910 JSObject::cast(prototype)->SetLocalPropertyIgnoreAttributes(
2923 function, 2911 constructor_symbol(), function, DONT_ENUM);
2924 DONT_ENUM);
2925 if (!maybe_result->ToObject(&result)) return maybe_result; 2912 if (!maybe_result->ToObject(&result)) return maybe_result;
2926 } 2913 }
2927 return prototype; 2914 return prototype;
2928 } 2915 }
2929 2916
2930 2917
2931 MaybeObject* Heap::AllocateFunction(Map* function_map, 2918 MaybeObject* Heap::AllocateFunction(Map* function_map,
2932 SharedFunctionInfo* shared, 2919 SharedFunctionInfo* shared,
2933 Object* prototype, 2920 Object* prototype,
2934 PretenureFlag pretenure) { 2921 PretenureFlag pretenure) {
(...skipping 869 matching lines...) Expand 10 before | Expand all | Expand 10 after
3804 Struct::cast(result)->InitializeBody(size); 3791 Struct::cast(result)->InitializeBody(size);
3805 return result; 3792 return result;
3806 } 3793 }
3807 3794
3808 3795
3809 bool Heap::IdleNotification() { 3796 bool Heap::IdleNotification() {
3810 static const int kIdlesBeforeScavenge = 4; 3797 static const int kIdlesBeforeScavenge = 4;
3811 static const int kIdlesBeforeMarkSweep = 7; 3798 static const int kIdlesBeforeMarkSweep = 7;
3812 static const int kIdlesBeforeMarkCompact = 8; 3799 static const int kIdlesBeforeMarkCompact = 8;
3813 static const int kMaxIdleCount = kIdlesBeforeMarkCompact + 1; 3800 static const int kMaxIdleCount = kIdlesBeforeMarkCompact + 1;
3814 static const int kGCsBetweenCleanup = 4; 3801 static const unsigned int kGCsBetweenCleanup = 4;
3815 3802
3816 if (!last_idle_notification_gc_count_init_) { 3803 if (!last_idle_notification_gc_count_init_) {
3817 last_idle_notification_gc_count_ = gc_count_; 3804 last_idle_notification_gc_count_ = gc_count_;
3818 last_idle_notification_gc_count_init_ = true; 3805 last_idle_notification_gc_count_init_ = true;
3819 } 3806 }
3820 3807
3821 bool uncommit = true; 3808 bool uncommit = true;
3822 bool finished = false; 3809 bool finished = false;
3823 3810
3824 // Reset the number of idle notifications received when a number of 3811 // Reset the number of idle notifications received when a number of
3825 // GCs have taken place. This allows another round of cleanup based 3812 // GCs have taken place. This allows another round of cleanup based
3826 // on idle notifications if enough work has been carried out to 3813 // on idle notifications if enough work has been carried out to
3827 // provoke a number of garbage collections. 3814 // provoke a number of garbage collections.
3828 if (gc_count_ < last_idle_notification_gc_count_ + kGCsBetweenCleanup) { 3815 if (gc_count_ - last_idle_notification_gc_count_ < kGCsBetweenCleanup) {
3829 number_idle_notifications_ = 3816 number_idle_notifications_ =
3830 Min(number_idle_notifications_ + 1, kMaxIdleCount); 3817 Min(number_idle_notifications_ + 1, kMaxIdleCount);
3831 } else { 3818 } else {
3832 number_idle_notifications_ = 0; 3819 number_idle_notifications_ = 0;
3833 last_idle_notification_gc_count_ = gc_count_; 3820 last_idle_notification_gc_count_ = gc_count_;
3834 } 3821 }
3835 3822
3836 if (number_idle_notifications_ == kIdlesBeforeScavenge) { 3823 if (number_idle_notifications_ == kIdlesBeforeScavenge) {
3837 if (contexts_disposed_ > 0) { 3824 if (contexts_disposed_ > 0) {
3838 HistogramTimerScope scope(isolate_->counters()->gc_context()); 3825 HistogramTimerScope scope(isolate_->counters()->gc_context());
(...skipping 1551 matching lines...) Expand 10 before | Expand all | Expand 10 after
5390 } 5377 }
5391 5378
5392 5379
5393 void HeapIterator::reset() { 5380 void HeapIterator::reset() {
5394 // Restart the iterator. 5381 // Restart the iterator.
5395 Shutdown(); 5382 Shutdown();
5396 Init(); 5383 Init();
5397 } 5384 }
5398 5385
5399 5386
5387 #if defined(DEBUG) || defined(LIVE_OBJECT_LIST)
5388
5389 Object* const PathTracer::kAnyGlobalObject = reinterpret_cast<Object*>(NULL);
5390
5391 class PathTracer::MarkVisitor: public ObjectVisitor {
5392 public:
5393 explicit MarkVisitor(PathTracer* tracer) : tracer_(tracer) {}
5394 void VisitPointers(Object** start, Object** end) {
5395 // Scan all HeapObject pointers in [start, end)
5396 for (Object** p = start; !tracer_->found() && (p < end); p++) {
5397 if ((*p)->IsHeapObject())
5398 tracer_->MarkRecursively(p, this);
5399 }
5400 }
5401
5402 private:
5403 PathTracer* tracer_;
5404 };
5405
5406
5407 class PathTracer::UnmarkVisitor: public ObjectVisitor {
5408 public:
5409 explicit UnmarkVisitor(PathTracer* tracer) : tracer_(tracer) {}
5410 void VisitPointers(Object** start, Object** end) {
5411 // Scan all HeapObject pointers in [start, end)
5412 for (Object** p = start; p < end; p++) {
5413 if ((*p)->IsHeapObject())
5414 tracer_->UnmarkRecursively(p, this);
5415 }
5416 }
5417
5418 private:
5419 PathTracer* tracer_;
5420 };
5421
5422
5423 void PathTracer::VisitPointers(Object** start, Object** end) {
5424 bool done = ((what_to_find_ == FIND_FIRST) && found_target_);
5425 // Visit all HeapObject pointers in [start, end)
5426 for (Object** p = start; !done && (p < end); p++) {
5427 if ((*p)->IsHeapObject()) {
5428 TracePathFrom(p);
5429 done = ((what_to_find_ == FIND_FIRST) && found_target_);
5430 }
5431 }
5432 }
5433
5434
5435 void PathTracer::Reset() {
5436 found_target_ = false;
5437 object_stack_.Clear();
5438 }
5439
5440
5441 void PathTracer::TracePathFrom(Object** root) {
5442 ASSERT((search_target_ == kAnyGlobalObject) ||
5443 search_target_->IsHeapObject());
5444 found_target_in_trace_ = false;
5445 object_stack_.Clear();
5446
5447 MarkVisitor mark_visitor(this);
5448 MarkRecursively(root, &mark_visitor);
5449
5450 UnmarkVisitor unmark_visitor(this);
5451 UnmarkRecursively(root, &unmark_visitor);
5452
5453 ProcessResults();
5454 }
5455
5456
5457 void PathTracer::MarkRecursively(Object** p, MarkVisitor* mark_visitor) {
5458 if (!(*p)->IsHeapObject()) return;
5459
5460 HeapObject* obj = HeapObject::cast(*p);
5461
5462 Object* map = obj->map();
5463
5464 if (!map->IsHeapObject()) return; // visited before
5465
5466 if (found_target_in_trace_) return; // stop if target found
5467 object_stack_.Add(obj);
5468 if (((search_target_ == kAnyGlobalObject) && obj->IsJSGlobalObject()) ||
5469 (obj == search_target_)) {
5470 found_target_in_trace_ = true;
5471 found_target_ = true;
5472 return;
5473 }
5474
5475 bool is_global_context = obj->IsGlobalContext();
5476
5477 // not visited yet
5478 Map* map_p = reinterpret_cast<Map*>(HeapObject::cast(map));
5479
5480 Address map_addr = map_p->address();
5481
5482 obj->set_map(reinterpret_cast<Map*>(map_addr + kMarkTag));
5483
5484 // Scan the object body.
5485 if (is_global_context && (visit_mode_ == VISIT_ONLY_STRONG)) {
5486 // This is specialized to scan Context's properly.
5487 Object** start = reinterpret_cast<Object**>(obj->address() +
5488 Context::kHeaderSize);
5489 Object** end = reinterpret_cast<Object**>(obj->address() +
5490 Context::kHeaderSize + Context::FIRST_WEAK_SLOT * kPointerSize);
5491 mark_visitor->VisitPointers(start, end);
5492 } else {
5493 obj->IterateBody(map_p->instance_type(),
5494 obj->SizeFromMap(map_p),
5495 mark_visitor);
5496 }
5497
5498 // Scan the map after the body because the body is a lot more interesting
5499 // when doing leak detection.
5500 MarkRecursively(&map, mark_visitor);
5501
5502 if (!found_target_in_trace_) // don't pop if found the target
5503 object_stack_.RemoveLast();
5504 }
5505
5506
5507 void PathTracer::UnmarkRecursively(Object** p, UnmarkVisitor* unmark_visitor) {
5508 if (!(*p)->IsHeapObject()) return;
5509
5510 HeapObject* obj = HeapObject::cast(*p);
5511
5512 Object* map = obj->map();
5513
5514 if (map->IsHeapObject()) return; // unmarked already
5515
5516 Address map_addr = reinterpret_cast<Address>(map);
5517
5518 map_addr -= kMarkTag;
5519
5520 ASSERT_TAG_ALIGNED(map_addr);
5521
5522 HeapObject* map_p = HeapObject::FromAddress(map_addr);
5523
5524 obj->set_map(reinterpret_cast<Map*>(map_p));
5525
5526 UnmarkRecursively(reinterpret_cast<Object**>(&map_p), unmark_visitor);
5527
5528 obj->IterateBody(Map::cast(map_p)->instance_type(),
5529 obj->SizeFromMap(Map::cast(map_p)),
5530 unmark_visitor);
5531 }
5532
5533
5534 void PathTracer::ProcessResults() {
5535 if (found_target_) {
5536 PrintF("=====================================\n");
5537 PrintF("==== Path to object ====\n");
5538 PrintF("=====================================\n\n");
5539
5540 ASSERT(!object_stack_.is_empty());
5541 for (int i = 0; i < object_stack_.length(); i++) {
5542 if (i > 0) PrintF("\n |\n |\n V\n\n");
5543 Object* obj = object_stack_[i];
5544 #ifdef OBJECT_PRINT
5545 obj->Print();
5546 #else
5547 obj->ShortPrint();
5548 #endif
5549 }
5550 PrintF("=====================================\n");
5551 }
5552 }
5553 #endif // DEBUG || LIVE_OBJECT_LIST
5554
5555
5400 #ifdef DEBUG 5556 #ifdef DEBUG
5401 // Triggers a depth-first traversal of reachable objects from roots 5557 // Triggers a depth-first traversal of reachable objects from roots
5402 // and finds a path to a specific heap object and prints it. 5558 // and finds a path to a specific heap object and prints it.
5403 void Heap::TracePathToObject(Object* target) { 5559 void Heap::TracePathToObject(Object* target) {
5404 debug_utils_->search_target_ = target; 5560 PathTracer tracer(target, PathTracer::FIND_ALL, VISIT_ALL);
5405 debug_utils_->search_for_any_global_ = false; 5561 IterateRoots(&tracer, VISIT_ONLY_STRONG);
5406
5407 HeapDebugUtils::MarkRootVisitor root_visitor(debug_utils_);
5408 IterateRoots(&root_visitor, VISIT_ONLY_STRONG);
5409 } 5562 }
5410 5563
5411 5564
5412 // Triggers a depth-first traversal of reachable objects from roots 5565 // Triggers a depth-first traversal of reachable objects from roots
5413 // and finds a path to any global object and prints it. Useful for 5566 // and finds a path to any global object and prints it. Useful for
5414 // determining the source for leaks of global objects. 5567 // determining the source for leaks of global objects.
5415 void Heap::TracePathToGlobal() { 5568 void Heap::TracePathToGlobal() {
5416 debug_utils_->search_target_ = NULL; 5569 PathTracer tracer(PathTracer::kAnyGlobalObject,
5417 debug_utils_->search_for_any_global_ = true; 5570 PathTracer::FIND_ALL,
5418 5571 VISIT_ALL);
5419 HeapDebugUtils::MarkRootVisitor root_visitor(debug_utils_); 5572 IterateRoots(&tracer, VISIT_ONLY_STRONG);
5420 IterateRoots(&root_visitor, VISIT_ONLY_STRONG);
5421 } 5573 }
5422 #endif 5574 #endif
5423 5575
5424 5576
5425 static intptr_t CountTotalHolesSize() { 5577 static intptr_t CountTotalHolesSize() {
5426 intptr_t holes_size = 0; 5578 intptr_t holes_size = 0;
5427 OldSpaces spaces; 5579 OldSpaces spaces;
5428 for (OldSpace* space = spaces.next(); 5580 for (OldSpace* space = spaces.next();
5429 space != NULL; 5581 space != NULL;
5430 space = spaces.next()) { 5582 space = spaces.next()) {
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after
5651 } 5803 }
5652 5804
5653 5805
5654 void ExternalStringTable::TearDown() { 5806 void ExternalStringTable::TearDown() {
5655 new_space_strings_.Free(); 5807 new_space_strings_.Free();
5656 old_space_strings_.Free(); 5808 old_space_strings_.Free();
5657 } 5809 }
5658 5810
5659 5811
5660 } } // namespace v8::internal 5812 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/heap.h ('k') | src/heap-profiler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698