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 20 matching lines...) Expand all Loading... |
31 #include "api.h" | 31 #include "api.h" |
32 #include "bootstrapper.h" | 32 #include "bootstrapper.h" |
33 #include "codegen-inl.h" | 33 #include "codegen-inl.h" |
34 #include "compilation-cache.h" | 34 #include "compilation-cache.h" |
35 #include "debug.h" | 35 #include "debug.h" |
36 #include "heap-profiler.h" | 36 #include "heap-profiler.h" |
37 #include "global-handles.h" | 37 #include "global-handles.h" |
38 #include "mark-compact.h" | 38 #include "mark-compact.h" |
39 #include "natives.h" | 39 #include "natives.h" |
40 #include "objects-visiting.h" | 40 #include "objects-visiting.h" |
41 #include "scanner.h" | 41 #include "scanner-base.h" |
42 #include "scopeinfo.h" | 42 #include "scopeinfo.h" |
43 #include "snapshot.h" | 43 #include "snapshot.h" |
44 #include "v8threads.h" | 44 #include "v8threads.h" |
45 #if V8_TARGET_ARCH_ARM && !V8_INTERPRETED_REGEXP | 45 #if V8_TARGET_ARCH_ARM && !V8_INTERPRETED_REGEXP |
46 #include "regexp-macro-assembler.h" | 46 #include "regexp-macro-assembler.h" |
47 #include "arm/regexp-macro-assembler-arm.h" | 47 #include "arm/regexp-macro-assembler-arm.h" |
48 #endif | 48 #endif |
49 | 49 |
50 | 50 |
51 namespace v8 { | 51 namespace v8 { |
(...skipping 20 matching lines...) Expand all Loading... |
72 intptr_t Heap::old_gen_allocation_limit_ = kMinimumAllocationLimit; | 72 intptr_t Heap::old_gen_allocation_limit_ = kMinimumAllocationLimit; |
73 | 73 |
74 int Heap::old_gen_exhausted_ = false; | 74 int Heap::old_gen_exhausted_ = false; |
75 | 75 |
76 int Heap::amount_of_external_allocated_memory_ = 0; | 76 int Heap::amount_of_external_allocated_memory_ = 0; |
77 int Heap::amount_of_external_allocated_memory_at_last_global_gc_ = 0; | 77 int Heap::amount_of_external_allocated_memory_at_last_global_gc_ = 0; |
78 | 78 |
79 // semispace_size_ should be a power of 2 and old_generation_size_ should be | 79 // semispace_size_ should be a power of 2 and old_generation_size_ should be |
80 // a multiple of Page::kPageSize. | 80 // a multiple of Page::kPageSize. |
81 #if defined(ANDROID) | 81 #if defined(ANDROID) |
82 int Heap::max_semispace_size_ = 2*MB; | 82 static const int default_max_semispace_size_ = 2*MB; |
83 intptr_t Heap::max_old_generation_size_ = 192*MB; | 83 intptr_t Heap::max_old_generation_size_ = 192*MB; |
84 int Heap::initial_semispace_size_ = 128*KB; | 84 int Heap::initial_semispace_size_ = 128*KB; |
85 intptr_t Heap::code_range_size_ = 0; | 85 intptr_t Heap::code_range_size_ = 0; |
86 intptr_t Heap::max_executable_size_ = max_old_generation_size_; | 86 intptr_t Heap::max_executable_size_ = max_old_generation_size_; |
87 #elif defined(V8_TARGET_ARCH_X64) | 87 #elif defined(V8_TARGET_ARCH_X64) |
88 int Heap::max_semispace_size_ = 16*MB; | 88 static const int default_max_semispace_size_ = 16*MB; |
89 intptr_t Heap::max_old_generation_size_ = 1*GB; | 89 intptr_t Heap::max_old_generation_size_ = 1*GB; |
90 int Heap::initial_semispace_size_ = 1*MB; | 90 int Heap::initial_semispace_size_ = 1*MB; |
91 intptr_t Heap::code_range_size_ = 512*MB; | 91 intptr_t Heap::code_range_size_ = 512*MB; |
92 intptr_t Heap::max_executable_size_ = 256*MB; | 92 intptr_t Heap::max_executable_size_ = 256*MB; |
93 #else | 93 #else |
94 int Heap::max_semispace_size_ = 8*MB; | 94 static const int default_max_semispace_size_ = 8*MB; |
95 intptr_t Heap::max_old_generation_size_ = 512*MB; | 95 intptr_t Heap::max_old_generation_size_ = 512*MB; |
96 int Heap::initial_semispace_size_ = 512*KB; | 96 int Heap::initial_semispace_size_ = 512*KB; |
97 intptr_t Heap::code_range_size_ = 0; | 97 intptr_t Heap::code_range_size_ = 0; |
98 intptr_t Heap::max_executable_size_ = 128*MB; | 98 intptr_t Heap::max_executable_size_ = 128*MB; |
99 #endif | 99 #endif |
100 | 100 |
| 101 // Allow build-time customization of the max semispace size. Building |
| 102 // V8 with snapshots and a non-default max semispace size is much |
| 103 // easier if you can define it as part of the build environment. |
| 104 #if defined(V8_MAX_SEMISPACE_SIZE) |
| 105 int Heap::max_semispace_size_ = V8_MAX_SEMISPACE_SIZE; |
| 106 #else |
| 107 int Heap::max_semispace_size_ = default_max_semispace_size_; |
| 108 #endif |
| 109 |
101 // The snapshot semispace size will be the default semispace size if | 110 // The snapshot semispace size will be the default semispace size if |
102 // snapshotting is used and will be the requested semispace size as | 111 // snapshotting is used and will be the requested semispace size as |
103 // set up by ConfigureHeap otherwise. | 112 // set up by ConfigureHeap otherwise. |
104 int Heap::reserved_semispace_size_ = Heap::max_semispace_size_; | 113 int Heap::reserved_semispace_size_ = Heap::max_semispace_size_; |
105 | 114 |
106 List<Heap::GCPrologueCallbackPair> Heap::gc_prologue_callbacks_; | 115 List<Heap::GCPrologueCallbackPair> Heap::gc_prologue_callbacks_; |
107 List<Heap::GCEpilogueCallbackPair> Heap::gc_epilogue_callbacks_; | 116 List<Heap::GCEpilogueCallbackPair> Heap::gc_epilogue_callbacks_; |
108 | 117 |
109 GCCallback Heap::global_gc_prologue_callback_ = NULL; | 118 GCCallback Heap::global_gc_prologue_callback_ = NULL; |
110 GCCallback Heap::global_gc_epilogue_callback_ = NULL; | 119 GCCallback Heap::global_gc_epilogue_callback_ = NULL; |
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
388 | 397 |
389 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) | 398 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) |
390 ReportStatisticsBeforeGC(); | 399 ReportStatisticsBeforeGC(); |
391 #endif | 400 #endif |
392 } | 401 } |
393 | 402 |
394 intptr_t Heap::SizeOfObjects() { | 403 intptr_t Heap::SizeOfObjects() { |
395 intptr_t total = 0; | 404 intptr_t total = 0; |
396 AllSpaces spaces; | 405 AllSpaces spaces; |
397 for (Space* space = spaces.next(); space != NULL; space = spaces.next()) { | 406 for (Space* space = spaces.next(); space != NULL; space = spaces.next()) { |
398 total += space->Size(); | 407 total += space->SizeOfObjects(); |
399 } | 408 } |
400 return total; | 409 return total; |
401 } | 410 } |
402 | 411 |
403 void Heap::GarbageCollectionEpilogue() { | 412 void Heap::GarbageCollectionEpilogue() { |
404 #ifdef DEBUG | 413 #ifdef DEBUG |
405 allow_allocation(true); | 414 allow_allocation(true); |
406 ZapFromSpace(); | 415 ZapFromSpace(); |
407 | 416 |
408 if (FLAG_verify_heap) { | 417 if (FLAG_verify_heap) { |
(...skipping 2824 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3233 return result; | 3242 return result; |
3234 } | 3243 } |
3235 | 3244 |
3236 | 3245 |
3237 MaybeObject* Heap::AllocateStringFromUtf8(Vector<const char> string, | 3246 MaybeObject* Heap::AllocateStringFromUtf8(Vector<const char> string, |
3238 PretenureFlag pretenure) { | 3247 PretenureFlag pretenure) { |
3239 // V8 only supports characters in the Basic Multilingual Plane. | 3248 // V8 only supports characters in the Basic Multilingual Plane. |
3240 const uc32 kMaxSupportedChar = 0xFFFF; | 3249 const uc32 kMaxSupportedChar = 0xFFFF; |
3241 // Count the number of characters in the UTF-8 string and check if | 3250 // Count the number of characters in the UTF-8 string and check if |
3242 // it is an ASCII string. | 3251 // it is an ASCII string. |
3243 Access<Scanner::Utf8Decoder> decoder(Scanner::utf8_decoder()); | 3252 Access<ScannerConstants::Utf8Decoder> |
| 3253 decoder(ScannerConstants::utf8_decoder()); |
3244 decoder->Reset(string.start(), string.length()); | 3254 decoder->Reset(string.start(), string.length()); |
3245 int chars = 0; | 3255 int chars = 0; |
3246 bool is_ascii = true; | 3256 bool is_ascii = true; |
3247 while (decoder->has_more()) { | 3257 while (decoder->has_more()) { |
3248 uc32 r = decoder->GetNext(); | 3258 uc32 r = decoder->GetNext(); |
3249 if (r > String::kMaxAsciiCharCode) is_ascii = false; | 3259 if (r > String::kMaxAsciiCharCode) is_ascii = false; |
3250 chars++; | 3260 chars++; |
3251 } | 3261 } |
3252 | 3262 |
3253 // If the string is ascii, we do not need to convert the characters | 3263 // If the string is ascii, we do not need to convert the characters |
(...skipping 1138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4392 *stats->map_space_capacity = map_space_->Capacity(); | 4402 *stats->map_space_capacity = map_space_->Capacity(); |
4393 *stats->cell_space_size = cell_space_->Size(); | 4403 *stats->cell_space_size = cell_space_->Size(); |
4394 *stats->cell_space_capacity = cell_space_->Capacity(); | 4404 *stats->cell_space_capacity = cell_space_->Capacity(); |
4395 *stats->lo_space_size = lo_space_->Size(); | 4405 *stats->lo_space_size = lo_space_->Size(); |
4396 GlobalHandles::RecordStats(stats); | 4406 GlobalHandles::RecordStats(stats); |
4397 *stats->memory_allocator_size = MemoryAllocator::Size(); | 4407 *stats->memory_allocator_size = MemoryAllocator::Size(); |
4398 *stats->memory_allocator_capacity = | 4408 *stats->memory_allocator_capacity = |
4399 MemoryAllocator::Size() + MemoryAllocator::Available(); | 4409 MemoryAllocator::Size() + MemoryAllocator::Available(); |
4400 *stats->os_error = OS::GetLastError(); | 4410 *stats->os_error = OS::GetLastError(); |
4401 if (take_snapshot) { | 4411 if (take_snapshot) { |
4402 HeapIterator iterator; | 4412 HeapIterator iterator(HeapIterator::kPreciseFiltering); |
4403 for (HeapObject* obj = iterator.next(); | 4413 for (HeapObject* obj = iterator.next(); |
4404 obj != NULL; | 4414 obj != NULL; |
4405 obj = iterator.next()) { | 4415 obj = iterator.next()) { |
4406 // Note: snapshot won't be precise because IsFreeListNode returns true | |
4407 // for any bytearray. | |
4408 if (FreeListNode::IsFreeListNode(obj)) continue; | |
4409 InstanceType type = obj->map()->instance_type(); | 4416 InstanceType type = obj->map()->instance_type(); |
4410 ASSERT(0 <= type && type <= LAST_TYPE); | 4417 ASSERT(0 <= type && type <= LAST_TYPE); |
4411 stats->objects_per_type[type]++; | 4418 stats->objects_per_type[type]++; |
4412 stats->size_per_type[type] += obj->Size(); | 4419 stats->size_per_type[type] += obj->Size(); |
4413 } | 4420 } |
4414 } | 4421 } |
4415 } | 4422 } |
4416 | 4423 |
4417 | 4424 |
4418 intptr_t Heap::PromotedSpaceSize() { | 4425 intptr_t Heap::PromotedSpaceSize() { |
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4753 case OLD_DATA_SPACE: | 4760 case OLD_DATA_SPACE: |
4754 return Heap::old_data_space(); | 4761 return Heap::old_data_space(); |
4755 case CODE_SPACE: | 4762 case CODE_SPACE: |
4756 return Heap::code_space(); | 4763 return Heap::code_space(); |
4757 default: | 4764 default: |
4758 return NULL; | 4765 return NULL; |
4759 } | 4766 } |
4760 } | 4767 } |
4761 | 4768 |
4762 | 4769 |
4763 SpaceIterator::SpaceIterator() : current_space_(FIRST_SPACE), iterator_(NULL) { | 4770 SpaceIterator::SpaceIterator() |
| 4771 : current_space_(FIRST_SPACE), |
| 4772 iterator_(NULL), |
| 4773 size_func_(NULL) { |
| 4774 } |
| 4775 |
| 4776 |
| 4777 SpaceIterator::SpaceIterator(HeapObjectCallback size_func) |
| 4778 : current_space_(FIRST_SPACE), |
| 4779 iterator_(NULL), |
| 4780 size_func_(size_func) { |
4764 } | 4781 } |
4765 | 4782 |
4766 | 4783 |
4767 SpaceIterator::~SpaceIterator() { | 4784 SpaceIterator::~SpaceIterator() { |
4768 // Delete active iterator if any. | 4785 // Delete active iterator if any. |
4769 delete iterator_; | 4786 delete iterator_; |
4770 } | 4787 } |
4771 | 4788 |
4772 | 4789 |
4773 bool SpaceIterator::has_next() { | 4790 bool SpaceIterator::has_next() { |
(...skipping 17 matching lines...) Expand all Loading... |
4791 return CreateIterator(); | 4808 return CreateIterator(); |
4792 } | 4809 } |
4793 | 4810 |
4794 | 4811 |
4795 // Create an iterator for the space to iterate. | 4812 // Create an iterator for the space to iterate. |
4796 ObjectIterator* SpaceIterator::CreateIterator() { | 4813 ObjectIterator* SpaceIterator::CreateIterator() { |
4797 ASSERT(iterator_ == NULL); | 4814 ASSERT(iterator_ == NULL); |
4798 | 4815 |
4799 switch (current_space_) { | 4816 switch (current_space_) { |
4800 case NEW_SPACE: | 4817 case NEW_SPACE: |
4801 iterator_ = new SemiSpaceIterator(Heap::new_space()); | 4818 iterator_ = new SemiSpaceIterator(Heap::new_space(), size_func_); |
4802 break; | 4819 break; |
4803 case OLD_POINTER_SPACE: | 4820 case OLD_POINTER_SPACE: |
4804 iterator_ = new HeapObjectIterator(Heap::old_pointer_space()); | 4821 iterator_ = new HeapObjectIterator(Heap::old_pointer_space(), size_func_); |
4805 break; | 4822 break; |
4806 case OLD_DATA_SPACE: | 4823 case OLD_DATA_SPACE: |
4807 iterator_ = new HeapObjectIterator(Heap::old_data_space()); | 4824 iterator_ = new HeapObjectIterator(Heap::old_data_space(), size_func_); |
4808 break; | 4825 break; |
4809 case CODE_SPACE: | 4826 case CODE_SPACE: |
4810 iterator_ = new HeapObjectIterator(Heap::code_space()); | 4827 iterator_ = new HeapObjectIterator(Heap::code_space(), size_func_); |
4811 break; | 4828 break; |
4812 case MAP_SPACE: | 4829 case MAP_SPACE: |
4813 iterator_ = new HeapObjectIterator(Heap::map_space()); | 4830 iterator_ = new HeapObjectIterator(Heap::map_space(), size_func_); |
4814 break; | 4831 break; |
4815 case CELL_SPACE: | 4832 case CELL_SPACE: |
4816 iterator_ = new HeapObjectIterator(Heap::cell_space()); | 4833 iterator_ = new HeapObjectIterator(Heap::cell_space(), size_func_); |
4817 break; | 4834 break; |
4818 case LO_SPACE: | 4835 case LO_SPACE: |
4819 iterator_ = new LargeObjectIterator(Heap::lo_space()); | 4836 iterator_ = new LargeObjectIterator(Heap::lo_space(), size_func_); |
4820 break; | 4837 break; |
4821 } | 4838 } |
4822 | 4839 |
4823 // Return the newly allocated iterator; | 4840 // Return the newly allocated iterator; |
4824 ASSERT(iterator_ != NULL); | 4841 ASSERT(iterator_ != NULL); |
4825 return iterator_; | 4842 return iterator_; |
4826 } | 4843 } |
4827 | 4844 |
4828 | 4845 |
4829 HeapIterator::HeapIterator() { | 4846 class FreeListNodesFilter { |
| 4847 public: |
| 4848 FreeListNodesFilter() { |
| 4849 MarkFreeListNodes(); |
| 4850 } |
| 4851 |
| 4852 inline bool IsFreeListNode(HeapObject* object) { |
| 4853 if (object->IsMarked()) { |
| 4854 object->ClearMark(); |
| 4855 return true; |
| 4856 } else { |
| 4857 return false; |
| 4858 } |
| 4859 } |
| 4860 |
| 4861 private: |
| 4862 void MarkFreeListNodes() { |
| 4863 Heap::old_pointer_space()->MarkFreeListNodes(); |
| 4864 Heap::old_data_space()->MarkFreeListNodes(); |
| 4865 MarkCodeSpaceFreeListNodes(); |
| 4866 Heap::map_space()->MarkFreeListNodes(); |
| 4867 Heap::cell_space()->MarkFreeListNodes(); |
| 4868 } |
| 4869 |
| 4870 void MarkCodeSpaceFreeListNodes() { |
| 4871 // For code space, using FreeListNode::IsFreeListNode is OK. |
| 4872 HeapObjectIterator iter(Heap::code_space()); |
| 4873 for (HeapObject* obj = iter.next_object(); |
| 4874 obj != NULL; |
| 4875 obj = iter.next_object()) { |
| 4876 if (FreeListNode::IsFreeListNode(obj)) obj->SetMark(); |
| 4877 } |
| 4878 } |
| 4879 |
| 4880 AssertNoAllocation no_alloc; |
| 4881 }; |
| 4882 |
| 4883 |
| 4884 HeapIterator::HeapIterator() |
| 4885 : filtering_(HeapIterator::kNoFiltering), |
| 4886 filter_(NULL) { |
| 4887 Init(); |
| 4888 } |
| 4889 |
| 4890 |
| 4891 HeapIterator::HeapIterator(HeapIterator::FreeListNodesFiltering filtering) |
| 4892 : filtering_(filtering), |
| 4893 filter_(NULL) { |
4830 Init(); | 4894 Init(); |
4831 } | 4895 } |
4832 | 4896 |
4833 | 4897 |
4834 HeapIterator::~HeapIterator() { | 4898 HeapIterator::~HeapIterator() { |
4835 Shutdown(); | 4899 Shutdown(); |
4836 } | 4900 } |
4837 | 4901 |
4838 | 4902 |
4839 void HeapIterator::Init() { | 4903 void HeapIterator::Init() { |
4840 // Start the iteration. | 4904 // Start the iteration. |
4841 space_iterator_ = new SpaceIterator(); | 4905 if (filtering_ == kPreciseFiltering) { |
| 4906 filter_ = new FreeListNodesFilter; |
| 4907 space_iterator_ = |
| 4908 new SpaceIterator(MarkCompactCollector::SizeOfMarkedObject); |
| 4909 } else { |
| 4910 space_iterator_ = new SpaceIterator; |
| 4911 } |
4842 object_iterator_ = space_iterator_->next(); | 4912 object_iterator_ = space_iterator_->next(); |
4843 } | 4913 } |
4844 | 4914 |
4845 | 4915 |
4846 void HeapIterator::Shutdown() { | 4916 void HeapIterator::Shutdown() { |
| 4917 #ifdef DEBUG |
| 4918 // Assert that in precise mode we have iterated through all |
| 4919 // objects. Otherwise, heap will be left in an inconsistent state. |
| 4920 if (filtering_ == kPreciseFiltering) { |
| 4921 ASSERT(object_iterator_ == NULL); |
| 4922 } |
| 4923 #endif |
4847 // Make sure the last iterator is deallocated. | 4924 // Make sure the last iterator is deallocated. |
4848 delete space_iterator_; | 4925 delete space_iterator_; |
4849 space_iterator_ = NULL; | 4926 space_iterator_ = NULL; |
4850 object_iterator_ = NULL; | 4927 object_iterator_ = NULL; |
| 4928 delete filter_; |
| 4929 filter_ = NULL; |
4851 } | 4930 } |
4852 | 4931 |
4853 | 4932 |
4854 HeapObject* HeapIterator::next() { | 4933 HeapObject* HeapIterator::next() { |
| 4934 if (filter_ == NULL) return NextObject(); |
| 4935 |
| 4936 HeapObject* obj = NextObject(); |
| 4937 while (obj != NULL && filter_->IsFreeListNode(obj)) obj = NextObject(); |
| 4938 return obj; |
| 4939 } |
| 4940 |
| 4941 |
| 4942 HeapObject* HeapIterator::NextObject() { |
4855 // No iterator means we are done. | 4943 // No iterator means we are done. |
4856 if (object_iterator_ == NULL) return NULL; | 4944 if (object_iterator_ == NULL) return NULL; |
4857 | 4945 |
4858 if (HeapObject* obj = object_iterator_->next_object()) { | 4946 if (HeapObject* obj = object_iterator_->next_object()) { |
4859 // If the current iterator has more objects we are fine. | 4947 // If the current iterator has more objects we are fine. |
4860 return obj; | 4948 return obj; |
4861 } else { | 4949 } else { |
4862 // Go though the spaces looking for one that has objects. | 4950 // Go though the spaces looking for one that has objects. |
4863 while (space_iterator_->has_next()) { | 4951 while (space_iterator_->has_next()) { |
4864 object_iterator_ = space_iterator_->next(); | 4952 object_iterator_ = space_iterator_->next(); |
(...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5286 void ExternalStringTable::TearDown() { | 5374 void ExternalStringTable::TearDown() { |
5287 new_space_strings_.Free(); | 5375 new_space_strings_.Free(); |
5288 old_space_strings_.Free(); | 5376 old_space_strings_.Free(); |
5289 } | 5377 } |
5290 | 5378 |
5291 | 5379 |
5292 List<Object*> ExternalStringTable::new_space_strings_; | 5380 List<Object*> ExternalStringTable::new_space_strings_; |
5293 List<Object*> ExternalStringTable::old_space_strings_; | 5381 List<Object*> ExternalStringTable::old_space_strings_; |
5294 | 5382 |
5295 } } // namespace v8::internal | 5383 } } // namespace v8::internal |
OLD | NEW |