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

Side by Side Diff: src/heap.cc

Issue 6580038: [Isolates] Merge from bleeding_edge, revisions 5934-6100. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/isolates/
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
« no previous file with comments | « src/heap.h ('k') | src/heap-inl.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 3282 matching lines...) Expand 10 before | Expand all | Expand 10 after
3293 3293
3294 // Copy the characters into the new object. 3294 // Copy the characters into the new object.
3295 SeqAsciiString* string_result = SeqAsciiString::cast(result); 3295 SeqAsciiString* string_result = SeqAsciiString::cast(result);
3296 for (int i = 0; i < string.length(); i++) { 3296 for (int i = 0; i < string.length(); i++) {
3297 string_result->SeqAsciiStringSet(i, string[i]); 3297 string_result->SeqAsciiStringSet(i, string[i]);
3298 } 3298 }
3299 return result; 3299 return result;
3300 } 3300 }
3301 3301
3302 3302
3303 MaybeObject* Heap::AllocateStringFromUtf8(Vector<const char> string, 3303 MaybeObject* Heap::AllocateStringFromUtf8Slow(Vector<const char> string,
3304 PretenureFlag pretenure) { 3304 PretenureFlag pretenure) {
3305 // V8 only supports characters in the Basic Multilingual Plane. 3305 // V8 only supports characters in the Basic Multilingual Plane.
3306 const uc32 kMaxSupportedChar = 0xFFFF; 3306 const uc32 kMaxSupportedChar = 0xFFFF;
3307 // Count the number of characters in the UTF-8 string and check if 3307 // Count the number of characters in the UTF-8 string and check if
3308 // it is an ASCII string. 3308 // it is an ASCII string.
3309 Access<ScannerConstants::Utf8Decoder> 3309 Access<ScannerConstants::Utf8Decoder>
3310 decoder(isolate_->scanner_constants()->utf8_decoder()); 3310 decoder(isolate_->scanner_constants()->utf8_decoder());
3311 decoder->Reset(string.start(), string.length()); 3311 decoder->Reset(string.start(), string.length());
3312 int chars = 0; 3312 int chars = 0;
3313 bool is_ascii = true;
3314 while (decoder->has_more()) { 3313 while (decoder->has_more()) {
3315 uc32 r = decoder->GetNext(); 3314 decoder->GetNext();
3316 if (r > String::kMaxAsciiCharCode) is_ascii = false;
3317 chars++; 3315 chars++;
3318 } 3316 }
3319 3317
3320 // If the string is ascii, we do not need to convert the characters
3321 // since UTF8 is backwards compatible with ascii.
3322 if (is_ascii) return AllocateStringFromAscii(string, pretenure);
3323
3324 Object* result; 3318 Object* result;
3325 { MaybeObject* maybe_result = AllocateRawTwoByteString(chars, pretenure); 3319 { MaybeObject* maybe_result = AllocateRawTwoByteString(chars, pretenure);
3326 if (!maybe_result->ToObject(&result)) return maybe_result; 3320 if (!maybe_result->ToObject(&result)) return maybe_result;
3327 } 3321 }
3328 3322
3329 // Convert and copy the characters into the new object. 3323 // Convert and copy the characters into the new object.
3330 String* string_result = String::cast(result); 3324 String* string_result = String::cast(result);
3331 decoder->Reset(string.start(), string.length()); 3325 decoder->Reset(string.start(), string.length());
3332 for (int i = 0; i < chars; i++) { 3326 for (int i = 0; i < chars; i++) {
3333 uc32 r = decoder->GetNext(); 3327 uc32 r = decoder->GetNext();
(...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after
3763 } 3757 }
3764 Struct::cast(result)->InitializeBody(size); 3758 Struct::cast(result)->InitializeBody(size);
3765 return result; 3759 return result;
3766 } 3760 }
3767 3761
3768 3762
3769 bool Heap::IdleNotification() { 3763 bool Heap::IdleNotification() {
3770 static const int kIdlesBeforeScavenge = 4; 3764 static const int kIdlesBeforeScavenge = 4;
3771 static const int kIdlesBeforeMarkSweep = 7; 3765 static const int kIdlesBeforeMarkSweep = 7;
3772 static const int kIdlesBeforeMarkCompact = 8; 3766 static const int kIdlesBeforeMarkCompact = 8;
3767 static const int kMaxIdleCount = kIdlesBeforeMarkCompact + 1;
3768 static const int kGCsBetweenCleanup = 4;
3769
3773 if (!last_idle_notification_gc_count_init_) { 3770 if (!last_idle_notification_gc_count_init_) {
3774 last_idle_notification_gc_count_ = gc_count_; 3771 last_idle_notification_gc_count_ = gc_count_;
3775 last_idle_notification_gc_count_init_ = true; 3772 last_idle_notification_gc_count_init_ = true;
3776 } 3773 }
3777 3774
3778 bool uncommit = true; 3775 bool uncommit = true;
3779 bool finished = false; 3776 bool finished = false;
3780 3777
3781 if (last_idle_notification_gc_count_ == gc_count_) { 3778 // Reset the number of idle notifications received when a number of
3782 number_idle_notifications_++; 3779 // GCs have taken place. This allows another round of cleanup based
3780 // on idle notifications if enough work has been carried out to
3781 // provoke a number of garbage collections.
3782 if (gc_count_ < last_idle_notification_gc_count_ + kGCsBetweenCleanup) {
3783 number_idle_notifications_ =
3784 Min(number_idle_notifications_ + 1, kMaxIdleCount);
3783 } else { 3785 } else {
3784 number_idle_notifications_ = 0; 3786 number_idle_notifications_ = 0;
3785 last_idle_notification_gc_count_ = gc_count_; 3787 last_idle_notification_gc_count_ = gc_count_;
3786 } 3788 }
3787 3789
3788 if (number_idle_notifications_ == kIdlesBeforeScavenge) { 3790 if (number_idle_notifications_ == kIdlesBeforeScavenge) {
3789 if (contexts_disposed_ > 0) { 3791 if (contexts_disposed_ > 0) {
3790 HistogramTimerScope scope(isolate_->counters()->gc_context()); 3792 HistogramTimerScope scope(isolate_->counters()->gc_context());
3791 CollectAllGarbage(false); 3793 CollectAllGarbage(false);
3792 } else { 3794 } else {
3793 CollectGarbage(NEW_SPACE); 3795 CollectGarbage(NEW_SPACE);
3794 } 3796 }
3795 new_space_.Shrink(); 3797 new_space_.Shrink();
3796 last_idle_notification_gc_count_ = gc_count_; 3798 last_idle_notification_gc_count_ = gc_count_;
3797
3798 } else if (number_idle_notifications_ == kIdlesBeforeMarkSweep) { 3799 } else if (number_idle_notifications_ == kIdlesBeforeMarkSweep) {
3799 // Before doing the mark-sweep collections we clear the 3800 // Before doing the mark-sweep collections we clear the
3800 // compilation cache to avoid hanging on to source code and 3801 // compilation cache to avoid hanging on to source code and
3801 // generated code for cached functions. 3802 // generated code for cached functions.
3802 isolate_->compilation_cache()->Clear(); 3803 isolate_->compilation_cache()->Clear();
3803 3804
3804 CollectAllGarbage(false); 3805 CollectAllGarbage(false);
3805 new_space_.Shrink(); 3806 new_space_.Shrink();
3806 last_idle_notification_gc_count_ = gc_count_; 3807 last_idle_notification_gc_count_ = gc_count_;
3807 3808
3808 } else if (number_idle_notifications_ == kIdlesBeforeMarkCompact) { 3809 } else if (number_idle_notifications_ == kIdlesBeforeMarkCompact) {
3809 CollectAllGarbage(true); 3810 CollectAllGarbage(true);
3810 new_space_.Shrink(); 3811 new_space_.Shrink();
3811 last_idle_notification_gc_count_ = gc_count_; 3812 last_idle_notification_gc_count_ = gc_count_;
3812 number_idle_notifications_ = 0; 3813 number_idle_notifications_ = 0;
3813 finished = true; 3814 finished = true;
3814
3815 } else if (contexts_disposed_ > 0) { 3815 } else if (contexts_disposed_ > 0) {
3816 if (FLAG_expose_gc) { 3816 if (FLAG_expose_gc) {
3817 contexts_disposed_ = 0; 3817 contexts_disposed_ = 0;
3818 } else { 3818 } else {
3819 HistogramTimerScope scope(isolate_->counters()->gc_context()); 3819 HistogramTimerScope scope(isolate_->counters()->gc_context());
3820 CollectAllGarbage(false); 3820 CollectAllGarbage(false);
3821 last_idle_notification_gc_count_ = gc_count_; 3821 last_idle_notification_gc_count_ = gc_count_;
3822 } 3822 }
3823 // If this is the first idle notification, we reset the 3823 // If this is the first idle notification, we reset the
3824 // notification count to avoid letting idle notifications for 3824 // notification count to avoid letting idle notifications for
3825 // context disposal garbage collections start a potentially too 3825 // context disposal garbage collections start a potentially too
3826 // aggressive idle GC cycle. 3826 // aggressive idle GC cycle.
3827 if (number_idle_notifications_ <= 1) { 3827 if (number_idle_notifications_ <= 1) {
3828 number_idle_notifications_ = 0; 3828 number_idle_notifications_ = 0;
3829 uncommit = false; 3829 uncommit = false;
3830 } 3830 }
3831 } else if (number_idle_notifications_ > kIdlesBeforeMarkCompact) {
3832 // If we have received more than kIdlesBeforeMarkCompact idle
3833 // notifications we do not perform any cleanup because we don't
3834 // expect to gain much by doing so.
3835 finished = true;
3831 } 3836 }
3832 3837
3833 // Make sure that we have no pending context disposals and 3838 // Make sure that we have no pending context disposals and
3834 // conditionally uncommit from space. 3839 // conditionally uncommit from space.
3835 ASSERT(contexts_disposed_ == 0); 3840 ASSERT(contexts_disposed_ == 0);
3836 if (uncommit) UncommitFromSpace(); 3841 if (uncommit) UncommitFromSpace();
3837 return finished; 3842 return finished;
3838 } 3843 }
3839 3844
3840 3845
(...skipping 647 matching lines...) Expand 10 before | Expand all | Expand 10 after
4488 *stats->cell_space_capacity = cell_space_->Capacity(); 4493 *stats->cell_space_capacity = cell_space_->Capacity();
4489 *stats->lo_space_size = lo_space_->Size(); 4494 *stats->lo_space_size = lo_space_->Size();
4490 isolate_->global_handles()->RecordStats(stats); 4495 isolate_->global_handles()->RecordStats(stats);
4491 *stats->memory_allocator_size = isolate()->memory_allocator()->Size(); 4496 *stats->memory_allocator_size = isolate()->memory_allocator()->Size();
4492 *stats->memory_allocator_capacity = 4497 *stats->memory_allocator_capacity =
4493 isolate()->memory_allocator()->Size() + 4498 isolate()->memory_allocator()->Size() +
4494 isolate()->memory_allocator()->Available(); 4499 isolate()->memory_allocator()->Available();
4495 *stats->os_error = OS::GetLastError(); 4500 *stats->os_error = OS::GetLastError();
4496 isolate()->memory_allocator()->Available(); 4501 isolate()->memory_allocator()->Available();
4497 if (take_snapshot) { 4502 if (take_snapshot) {
4498 HeapIterator iterator(HeapIterator::kPreciseFiltering); 4503 HeapIterator iterator(HeapIterator::kFilterFreeListNodes);
4499 for (HeapObject* obj = iterator.next(); 4504 for (HeapObject* obj = iterator.next();
4500 obj != NULL; 4505 obj != NULL;
4501 obj = iterator.next()) { 4506 obj = iterator.next()) {
4502 InstanceType type = obj->map()->instance_type(); 4507 InstanceType type = obj->map()->instance_type();
4503 ASSERT(0 <= type && type <= LAST_TYPE); 4508 ASSERT(0 <= type && type <= LAST_TYPE);
4504 stats->objects_per_type[type]++; 4509 stats->objects_per_type[type]++;
4505 stats->size_per_type[type] += obj->Size(); 4510 stats->size_per_type[type] += obj->Size();
4506 } 4511 }
4507 } 4512 }
4508 } 4513 }
(...skipping 603 matching lines...) Expand 10 before | Expand all | Expand 10 after
5112 iterator_ = new LargeObjectIterator(HEAP->lo_space(), size_func_); 5117 iterator_ = new LargeObjectIterator(HEAP->lo_space(), size_func_);
5113 break; 5118 break;
5114 } 5119 }
5115 5120
5116 // Return the newly allocated iterator; 5121 // Return the newly allocated iterator;
5117 ASSERT(iterator_ != NULL); 5122 ASSERT(iterator_ != NULL);
5118 return iterator_; 5123 return iterator_;
5119 } 5124 }
5120 5125
5121 5126
5122 class FreeListNodesFilter { 5127 class HeapObjectsFilter {
5128 public:
5129 virtual ~HeapObjectsFilter() {}
5130 virtual bool SkipObject(HeapObject* object) = 0;
5131 };
5132
5133
5134 class FreeListNodesFilter : public HeapObjectsFilter {
5123 public: 5135 public:
5124 FreeListNodesFilter() { 5136 FreeListNodesFilter() {
5125 MarkFreeListNodes(); 5137 MarkFreeListNodes();
5126 } 5138 }
5127 5139
5128 inline bool IsFreeListNode(HeapObject* object) { 5140 bool SkipObject(HeapObject* object) {
5129 if (object->IsMarked()) { 5141 if (object->IsMarked()) {
5130 object->ClearMark(); 5142 object->ClearMark();
5131 return true; 5143 return true;
5132 } else { 5144 } else {
5133 return false; 5145 return false;
5134 } 5146 }
5135 } 5147 }
5136 5148
5137 private: 5149 private:
5138 void MarkFreeListNodes() { 5150 void MarkFreeListNodes() {
(...skipping 12 matching lines...) Expand all
5151 obj != NULL; 5163 obj != NULL;
5152 obj = iter.next_object()) { 5164 obj = iter.next_object()) {
5153 if (FreeListNode::IsFreeListNode(obj)) obj->SetMark(); 5165 if (FreeListNode::IsFreeListNode(obj)) obj->SetMark();
5154 } 5166 }
5155 } 5167 }
5156 5168
5157 AssertNoAllocation no_alloc; 5169 AssertNoAllocation no_alloc;
5158 }; 5170 };
5159 5171
5160 5172
5173 class UnreachableObjectsFilter : public HeapObjectsFilter {
5174 public:
5175 UnreachableObjectsFilter() {
5176 MarkUnreachableObjects();
5177 }
5178
5179 bool SkipObject(HeapObject* object) {
5180 if (object->IsMarked()) {
5181 object->ClearMark();
5182 return true;
5183 } else {
5184 return false;
5185 }
5186 }
5187
5188 private:
5189 class UnmarkingVisitor : public ObjectVisitor {
5190 public:
5191 UnmarkingVisitor() : list_(10) {}
5192
5193 void VisitPointers(Object** start, Object** end) {
5194 for (Object** p = start; p < end; p++) {
5195 if (!(*p)->IsHeapObject()) continue;
5196 HeapObject* obj = HeapObject::cast(*p);
5197 if (obj->IsMarked()) {
5198 obj->ClearMark();
5199 list_.Add(obj);
5200 }
5201 }
5202 }
5203
5204 bool can_process() { return !list_.is_empty(); }
5205
5206 void ProcessNext() {
5207 HeapObject* obj = list_.RemoveLast();
5208 obj->Iterate(this);
5209 }
5210
5211 private:
5212 List<HeapObject*> list_;
5213 };
5214
5215 void MarkUnreachableObjects() {
5216 HeapIterator iterator;
5217 for (HeapObject* obj = iterator.next();
5218 obj != NULL;
5219 obj = iterator.next()) {
5220 obj->SetMark();
5221 }
5222 UnmarkingVisitor visitor;
5223 HEAP->IterateRoots(&visitor, VISIT_ONLY_STRONG);
5224 while (visitor.can_process())
5225 visitor.ProcessNext();
5226 }
5227
5228 AssertNoAllocation no_alloc;
5229 };
5230
5231
5161 HeapIterator::HeapIterator() 5232 HeapIterator::HeapIterator()
5162 : filtering_(HeapIterator::kNoFiltering), 5233 : filtering_(HeapIterator::kNoFiltering),
5163 filter_(NULL) { 5234 filter_(NULL) {
5164 Init(); 5235 Init();
5165 } 5236 }
5166 5237
5167 5238
5168 HeapIterator::HeapIterator(HeapIterator::FreeListNodesFiltering filtering) 5239 HeapIterator::HeapIterator(HeapIterator::HeapObjectsFiltering filtering)
5169 : filtering_(filtering), 5240 : filtering_(filtering),
5170 filter_(NULL) { 5241 filter_(NULL) {
5171 Init(); 5242 Init();
5172 } 5243 }
5173 5244
5174 5245
5175 HeapIterator::~HeapIterator() { 5246 HeapIterator::~HeapIterator() {
5176 Shutdown(); 5247 Shutdown();
5177 } 5248 }
5178 5249
5179 5250
5180 void HeapIterator::Init() { 5251 void HeapIterator::Init() {
5181 // Start the iteration. 5252 // Start the iteration.
5182 if (filtering_ == kPreciseFiltering) { 5253 space_iterator_ = filtering_ == kNoFiltering ? new SpaceIterator :
5183 filter_ = new FreeListNodesFilter; 5254 new SpaceIterator(MarkCompactCollector::SizeOfMarkedObject);
5184 space_iterator_ = 5255 switch (filtering_) {
5185 new SpaceIterator(MarkCompactCollector::SizeOfMarkedObject); 5256 case kFilterFreeListNodes:
5186 } else { 5257 filter_ = new FreeListNodesFilter;
5187 space_iterator_ = new SpaceIterator; 5258 break;
5259 case kFilterUnreachable:
5260 filter_ = new UnreachableObjectsFilter;
5261 break;
5262 default:
5263 break;
5188 } 5264 }
5189 object_iterator_ = space_iterator_->next(); 5265 object_iterator_ = space_iterator_->next();
5190 } 5266 }
5191 5267
5192 5268
5193 void HeapIterator::Shutdown() { 5269 void HeapIterator::Shutdown() {
5194 #ifdef DEBUG 5270 #ifdef DEBUG
5195 // Assert that in precise mode we have iterated through all 5271 // Assert that in filtering mode we have iterated through all
5196 // objects. Otherwise, heap will be left in an inconsistent state. 5272 // objects. Otherwise, heap will be left in an inconsistent state.
5197 if (filtering_ == kPreciseFiltering) { 5273 if (filtering_ != kNoFiltering) {
5198 ASSERT(object_iterator_ == NULL); 5274 ASSERT(object_iterator_ == NULL);
5199 } 5275 }
5200 #endif 5276 #endif
5201 // Make sure the last iterator is deallocated. 5277 // Make sure the last iterator is deallocated.
5202 delete space_iterator_; 5278 delete space_iterator_;
5203 space_iterator_ = NULL; 5279 space_iterator_ = NULL;
5204 object_iterator_ = NULL; 5280 object_iterator_ = NULL;
5205 delete filter_; 5281 delete filter_;
5206 filter_ = NULL; 5282 filter_ = NULL;
5207 } 5283 }
5208 5284
5209 5285
5210 HeapObject* HeapIterator::next() { 5286 HeapObject* HeapIterator::next() {
5211 if (filter_ == NULL) return NextObject(); 5287 if (filter_ == NULL) return NextObject();
5212 5288
5213 HeapObject* obj = NextObject(); 5289 HeapObject* obj = NextObject();
5214 while (obj != NULL && filter_->IsFreeListNode(obj)) obj = NextObject(); 5290 while (obj != NULL && filter_->SkipObject(obj)) obj = NextObject();
5215 return obj; 5291 return obj;
5216 } 5292 }
5217 5293
5218 5294
5219 HeapObject* HeapIterator::NextObject() { 5295 HeapObject* HeapIterator::NextObject() {
5220 // No iterator means we are done. 5296 // No iterator means we are done.
5221 if (object_iterator_ == NULL) return NULL; 5297 if (object_iterator_ == NULL) return NULL;
5222 5298
5223 if (HeapObject* obj = object_iterator_->next_object()) { 5299 if (HeapObject* obj = object_iterator_->next_object()) {
5224 // If the current iterator has more objects we are fine. 5300 // If the current iterator has more objects we are fine.
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after
5499 } 5575 }
5500 5576
5501 5577
5502 void ExternalStringTable::TearDown() { 5578 void ExternalStringTable::TearDown() {
5503 new_space_strings_.Free(); 5579 new_space_strings_.Free();
5504 old_space_strings_.Free(); 5580 old_space_strings_.Free();
5505 } 5581 }
5506 5582
5507 5583
5508 } } // namespace v8::internal 5584 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/heap.h ('k') | src/heap-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698