OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/heap/spaces.h" | 5 #include "src/heap/spaces.h" |
6 | 6 |
7 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
8 #include "src/base/platform/platform.h" | 8 #include "src/base/platform/platform.h" |
9 #include "src/base/platform/semaphore.h" | 9 #include "src/base/platform/semaphore.h" |
10 #include "src/full-codegen/full-codegen.h" | 10 #include "src/full-codegen/full-codegen.h" |
(...skipping 1999 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2010 Initialize(space->bottom(), space->top()); | 2010 Initialize(space->bottom(), space->top()); |
2011 } | 2011 } |
2012 | 2012 |
2013 | 2013 |
2014 void SemiSpaceIterator::Initialize(Address start, Address end) { | 2014 void SemiSpaceIterator::Initialize(Address start, Address end) { |
2015 SemiSpace::AssertValidRange(start, end); | 2015 SemiSpace::AssertValidRange(start, end); |
2016 current_ = start; | 2016 current_ = start; |
2017 limit_ = end; | 2017 limit_ = end; |
2018 } | 2018 } |
2019 | 2019 |
2020 | |
2021 #ifdef DEBUG | 2020 #ifdef DEBUG |
2022 // heap_histograms is shared, always clear it before using it. | 2021 // heap_histograms is shared, always clear it before using it. |
2023 static void ClearHistograms(Isolate* isolate) { | 2022 static void ClearHistograms(Isolate* isolate) { |
2024 // We reset the name each time, though it hasn't changed. | 2023 // We reset the name each time, though it hasn't changed. |
2025 #define DEF_TYPE_NAME(name) isolate->heap_histograms()[name].set_name(#name); | 2024 #define DEF_TYPE_NAME(name) isolate->heap_histograms()[name].set_name(#name); |
2026 INSTANCE_TYPE_LIST(DEF_TYPE_NAME) | 2025 INSTANCE_TYPE_LIST(DEF_TYPE_NAME) |
2027 #undef DEF_TYPE_NAME | 2026 #undef DEF_TYPE_NAME |
2028 | 2027 |
2029 #define CLEAR_HISTOGRAM(name) isolate->heap_histograms()[name].clear(); | 2028 #define CLEAR_HISTOGRAM(name) isolate->heap_histograms()[name].clear(); |
2030 INSTANCE_TYPE_LIST(CLEAR_HISTOGRAM) | 2029 INSTANCE_TYPE_LIST(CLEAR_HISTOGRAM) |
2031 #undef CLEAR_HISTOGRAM | 2030 #undef CLEAR_HISTOGRAM |
2032 | 2031 |
2033 isolate->js_spill_information()->Clear(); | 2032 isolate->js_spill_information()->Clear(); |
2034 } | 2033 } |
2035 | 2034 |
2036 | 2035 |
2037 static void ClearCodeKindStatistics(int* code_kind_statistics) { | 2036 static void ClearCodeKindStatistics(int* code_kind_statistics) { |
2038 for (int i = 0; i < Code::NUMBER_OF_KINDS; i++) { | 2037 for (int i = 0; i < AbstractCode::NUMBER_OF_KINDS; i++) { |
2039 code_kind_statistics[i] = 0; | 2038 code_kind_statistics[i] = 0; |
2040 } | 2039 } |
2041 } | 2040 } |
2042 | |
2043 | |
2044 static void ReportCodeKindStatistics(int* code_kind_statistics) { | 2041 static void ReportCodeKindStatistics(int* code_kind_statistics) { |
2045 PrintF("\n Code kind histograms: \n"); | 2042 PrintF("\n Code kind histograms: \n"); |
2046 for (int i = 0; i < Code::NUMBER_OF_KINDS; i++) { | 2043 for (int i = 0; i < AbstractCode::NUMBER_OF_KINDS; i++) { |
2047 if (code_kind_statistics[i] > 0) { | 2044 if (code_kind_statistics[i] > 0) { |
2048 PrintF(" %-20s: %10d bytes\n", | 2045 PrintF(" %-20s: %10d bytes\n", |
2049 Code::Kind2String(static_cast<Code::Kind>(i)), | 2046 AbstractCode::Kind2String(static_cast<AbstractCode::Kind>(i)), |
2050 code_kind_statistics[i]); | 2047 code_kind_statistics[i]); |
2051 } | 2048 } |
2052 } | 2049 } |
2053 PrintF("\n"); | 2050 PrintF("\n"); |
2054 } | 2051 } |
2055 | 2052 |
2056 | |
2057 static int CollectHistogramInfo(HeapObject* obj) { | 2053 static int CollectHistogramInfo(HeapObject* obj) { |
2058 Isolate* isolate = obj->GetIsolate(); | 2054 Isolate* isolate = obj->GetIsolate(); |
2059 InstanceType type = obj->map()->instance_type(); | 2055 InstanceType type = obj->map()->instance_type(); |
2060 DCHECK(0 <= type && type <= LAST_TYPE); | 2056 DCHECK(0 <= type && type <= LAST_TYPE); |
2061 DCHECK(isolate->heap_histograms()[type].name() != NULL); | 2057 DCHECK(isolate->heap_histograms()[type].name() != NULL); |
2062 isolate->heap_histograms()[type].increment_number(1); | 2058 isolate->heap_histograms()[type].increment_number(1); |
2063 isolate->heap_histograms()[type].increment_bytes(obj->Size()); | 2059 isolate->heap_histograms()[type].increment_bytes(obj->Size()); |
2064 | 2060 |
2065 if (FLAG_collect_heap_spill_statistics && obj->IsJSObject()) { | 2061 if (FLAG_collect_heap_spill_statistics && obj->IsJSObject()) { |
2066 JSObject::cast(obj) | 2062 JSObject::cast(obj) |
(...skipping 675 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2742 (size_in_bytes <= free_list_.Available())); | 2738 (size_in_bytes <= free_list_.Available())); |
2743 return free_list_.Allocate(size_in_bytes); | 2739 return free_list_.Allocate(size_in_bytes); |
2744 } | 2740 } |
2745 | 2741 |
2746 // If sweeper threads are active, wait for them at that point and steal | 2742 // If sweeper threads are active, wait for them at that point and steal |
2747 // elements form their free-lists. Allocation may still fail their which | 2743 // elements form their free-lists. Allocation may still fail their which |
2748 // would indicate that there is not enough memory for the given allocation. | 2744 // would indicate that there is not enough memory for the given allocation. |
2749 return SweepAndRetryAllocation(size_in_bytes); | 2745 return SweepAndRetryAllocation(size_in_bytes); |
2750 } | 2746 } |
2751 | 2747 |
2752 | |
2753 #ifdef DEBUG | 2748 #ifdef DEBUG |
2754 void PagedSpace::ReportCodeStatistics(Isolate* isolate) { | 2749 void PagedSpace::ReportCodeStatistics(Isolate* isolate) { |
2755 CommentStatistic* comments_statistics = | 2750 CommentStatistic* comments_statistics = |
2756 isolate->paged_space_comments_statistics(); | 2751 isolate->paged_space_comments_statistics(); |
2757 ReportCodeKindStatistics(isolate->code_kind_statistics()); | 2752 ReportCodeKindStatistics(isolate->code_kind_statistics()); |
| 2753 PrintF("Code size including metadata : %10d bytes\n", |
| 2754 isolate->code_and_metadata_size()); |
| 2755 PrintF("Bytecode size including metadata: %10d bytes\n", |
| 2756 isolate->bytecode_and_metadata_size()); |
2758 PrintF( | 2757 PrintF( |
2759 "Code comment statistics (\" [ comment-txt : size/ " | 2758 "Code comment statistics (\" [ comment-txt : size/ " |
2760 "count (average)\"):\n"); | 2759 "count (average)\"):\n"); |
2761 for (int i = 0; i <= CommentStatistic::kMaxComments; i++) { | 2760 for (int i = 0; i <= CommentStatistic::kMaxComments; i++) { |
2762 const CommentStatistic& cs = comments_statistics[i]; | 2761 const CommentStatistic& cs = comments_statistics[i]; |
2763 if (cs.size > 0) { | 2762 if (cs.size > 0) { |
2764 PrintF(" %-30s: %10d/%6d (%d)\n", cs.comment, cs.size, cs.count, | 2763 PrintF(" %-30s: %10d/%6d (%d)\n", cs.comment, cs.size, cs.count, |
2765 cs.size / cs.count); | 2764 cs.size / cs.count); |
2766 } | 2765 } |
2767 } | 2766 } |
2768 PrintF("\n"); | 2767 PrintF("\n"); |
2769 } | 2768 } |
2770 | 2769 |
2771 | |
2772 void PagedSpace::ResetCodeStatistics(Isolate* isolate) { | 2770 void PagedSpace::ResetCodeStatistics(Isolate* isolate) { |
2773 CommentStatistic* comments_statistics = | 2771 CommentStatistic* comments_statistics = |
2774 isolate->paged_space_comments_statistics(); | 2772 isolate->paged_space_comments_statistics(); |
2775 ClearCodeKindStatistics(isolate->code_kind_statistics()); | 2773 ClearCodeKindStatistics(isolate->code_kind_statistics()); |
2776 for (int i = 0; i < CommentStatistic::kMaxComments; i++) { | 2774 for (int i = 0; i < CommentStatistic::kMaxComments; i++) { |
2777 comments_statistics[i].Clear(); | 2775 comments_statistics[i].Clear(); |
2778 } | 2776 } |
2779 comments_statistics[CommentStatistic::kMaxComments].comment = "Unknown"; | 2777 comments_statistics[CommentStatistic::kMaxComments].comment = "Unknown"; |
2780 comments_statistics[CommentStatistic::kMaxComments].size = 0; | 2778 comments_statistics[CommentStatistic::kMaxComments].size = 0; |
2781 comments_statistics[CommentStatistic::kMaxComments].count = 0; | 2779 comments_statistics[CommentStatistic::kMaxComments].count = 0; |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2837 // A new comment | 2835 // A new comment |
2838 CollectCommentStatistics(isolate, it); | 2836 CollectCommentStatistics(isolate, it); |
2839 // Skip code that was covered with previous comment | 2837 // Skip code that was covered with previous comment |
2840 prev_pc = it->rinfo()->pc(); | 2838 prev_pc = it->rinfo()->pc(); |
2841 } | 2839 } |
2842 it->next(); | 2840 it->next(); |
2843 } | 2841 } |
2844 EnterComment(isolate, comment_txt, flat_delta); | 2842 EnterComment(isolate, comment_txt, flat_delta); |
2845 } | 2843 } |
2846 | 2844 |
| 2845 // Collects code comment statistics |
| 2846 static void CollectCodeCommentStatistics(HeapObject* obj, Isolate* isolate) { |
| 2847 if (!obj->IsCode()) { |
| 2848 return; |
| 2849 } |
| 2850 Code* code = Code::cast(obj); |
| 2851 RelocIterator it(code); |
| 2852 int delta = 0; |
| 2853 const byte* prev_pc = code->instruction_start(); |
| 2854 while (!it.done()) { |
| 2855 if (it.rinfo()->rmode() == RelocInfo::COMMENT) { |
| 2856 delta += static_cast<int>(it.rinfo()->pc() - prev_pc); |
| 2857 CollectCommentStatistics(isolate, &it); |
| 2858 prev_pc = it.rinfo()->pc(); |
| 2859 } |
| 2860 it.next(); |
| 2861 } |
2847 | 2862 |
2848 // Collects code size statistics: | 2863 DCHECK(code->instruction_start() <= prev_pc && |
2849 // - by code kind | 2864 prev_pc <= code->instruction_end()); |
2850 // - by code comment | 2865 delta += static_cast<int>(code->instruction_end() - prev_pc); |
2851 void PagedSpace::CollectCodeStatistics() { | 2866 EnterComment(isolate, "NoComment", delta); |
2852 Isolate* isolate = heap()->isolate(); | |
2853 HeapObjectIterator obj_it(this); | |
2854 for (HeapObject* obj = obj_it.Next(); obj != NULL; obj = obj_it.Next()) { | |
2855 if (obj->IsAbstractCode()) { | |
2856 AbstractCode* code = AbstractCode::cast(obj); | |
2857 isolate->code_kind_statistics()[code->kind()] += code->Size(); | |
2858 } | |
2859 if (obj->IsCode()) { | |
2860 // TODO(mythria): Also enable this for BytecodeArray when it supports | |
2861 // RelocInformation. | |
2862 Code* code = Code::cast(obj); | |
2863 RelocIterator it(code); | |
2864 int delta = 0; | |
2865 const byte* prev_pc = code->instruction_start(); | |
2866 while (!it.done()) { | |
2867 if (it.rinfo()->rmode() == RelocInfo::COMMENT) { | |
2868 delta += static_cast<int>(it.rinfo()->pc() - prev_pc); | |
2869 CollectCommentStatistics(isolate, &it); | |
2870 prev_pc = it.rinfo()->pc(); | |
2871 } | |
2872 it.next(); | |
2873 } | |
2874 | |
2875 DCHECK(code->instruction_start() <= prev_pc && | |
2876 prev_pc <= code->instruction_end()); | |
2877 delta += static_cast<int>(code->instruction_end() - prev_pc); | |
2878 EnterComment(isolate, "NoComment", delta); | |
2879 } | |
2880 } | |
2881 } | 2867 } |
2882 | 2868 |
2883 | 2869 |
2884 void PagedSpace::ReportStatistics() { | 2870 void PagedSpace::ReportStatistics() { |
2885 int pct = static_cast<int>(Available() * 100 / Capacity()); | 2871 int pct = static_cast<int>(Available() * 100 / Capacity()); |
2886 PrintF(" capacity: %" V8PRIdPTR ", waste: %" V8PRIdPTR | 2872 PrintF(" capacity: %" V8PRIdPTR ", waste: %" V8PRIdPTR |
2887 ", available: %" V8PRIdPTR ", %%%d\n", | 2873 ", available: %" V8PRIdPTR ", %%%d\n", |
2888 Capacity(), Waste(), Available(), pct); | 2874 Capacity(), Waste(), Available(), pct); |
2889 | 2875 |
2890 if (heap()->mark_compact_collector()->sweeping_in_progress()) { | 2876 if (heap()->mark_compact_collector()->sweeping_in_progress()) { |
2891 heap()->mark_compact_collector()->EnsureSweepingCompleted(); | 2877 heap()->mark_compact_collector()->EnsureSweepingCompleted(); |
2892 } | 2878 } |
2893 ClearHistograms(heap()->isolate()); | 2879 ClearHistograms(heap()->isolate()); |
2894 HeapObjectIterator obj_it(this); | 2880 HeapObjectIterator obj_it(this); |
2895 for (HeapObject* obj = obj_it.Next(); obj != NULL; obj = obj_it.Next()) | 2881 for (HeapObject* obj = obj_it.Next(); obj != NULL; obj = obj_it.Next()) |
2896 CollectHistogramInfo(obj); | 2882 CollectHistogramInfo(obj); |
2897 ReportHistogram(heap()->isolate(), true); | 2883 ReportHistogram(heap()->isolate(), true); |
2898 } | 2884 } |
2899 #endif | 2885 #endif |
2900 | 2886 |
| 2887 static void RecordCodeSizeIncludingMetadata(AbstractCode* abstract_code, |
| 2888 Isolate* isolate) { |
| 2889 int size = abstract_code->SizeIncludingMetadata(); |
| 2890 if (abstract_code->IsCode()) { |
| 2891 size += isolate->code_and_metadata_size(); |
| 2892 isolate->set_code_and_metadata_size(size); |
| 2893 } else { |
| 2894 size += isolate->bytecode_and_metadata_size(); |
| 2895 isolate->set_bytecode_and_metadata_size(size); |
| 2896 } |
| 2897 } |
| 2898 |
| 2899 // Collects code size statistics: |
| 2900 // - code and metadata size |
| 2901 // - by code kind (only in debug mode) |
| 2902 // - by code comment (only in debug mode) |
| 2903 void PagedSpace::CollectCodeStatistics() { |
| 2904 Isolate* isolate = heap()->isolate(); |
| 2905 HeapObjectIterator obj_it(this); |
| 2906 for (HeapObject* obj = obj_it.Next(); obj != NULL; obj = obj_it.Next()) { |
| 2907 if (obj->IsAbstractCode()) { |
| 2908 AbstractCode* code = AbstractCode::cast(obj); |
| 2909 RecordCodeSizeIncludingMetadata(code, isolate); |
| 2910 #ifdef DEBUG |
| 2911 isolate->code_kind_statistics()[code->kind()] += code->Size(); |
| 2912 CollectCodeCommentStatistics(obj, isolate); |
| 2913 #endif |
| 2914 } |
| 2915 } |
| 2916 } |
| 2917 |
| 2918 void PagedSpace::ResetCodeAndMetadataStatistics(Isolate* isolate) { |
| 2919 isolate->set_code_and_metadata_size(0); |
| 2920 isolate->set_bytecode_and_metadata_size(0); |
| 2921 #ifdef DEBUG |
| 2922 ResetCodeStatistics(isolate); |
| 2923 #endif |
| 2924 } |
2901 | 2925 |
2902 // ----------------------------------------------------------------------------- | 2926 // ----------------------------------------------------------------------------- |
2903 // MapSpace implementation | 2927 // MapSpace implementation |
2904 | 2928 |
2905 #ifdef VERIFY_HEAP | 2929 #ifdef VERIFY_HEAP |
2906 void MapSpace::VerifyObject(HeapObject* object) { CHECK(object->IsMap()); } | 2930 void MapSpace::VerifyObject(HeapObject* object) { CHECK(object->IsMap()); } |
2907 #endif | 2931 #endif |
2908 | 2932 |
2909 | 2933 |
2910 // ----------------------------------------------------------------------------- | 2934 // ----------------------------------------------------------------------------- |
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3161 HeapObject* element_object = HeapObject::cast(element); | 3185 HeapObject* element_object = HeapObject::cast(element); |
3162 CHECK(heap()->Contains(element_object)); | 3186 CHECK(heap()->Contains(element_object)); |
3163 CHECK(element_object->map()->IsMap()); | 3187 CHECK(element_object->map()->IsMap()); |
3164 } | 3188 } |
3165 } | 3189 } |
3166 } | 3190 } |
3167 } | 3191 } |
3168 } | 3192 } |
3169 #endif | 3193 #endif |
3170 | 3194 |
| 3195 void LargeObjectSpace::CollectCodeStatistics() { |
| 3196 Isolate* isolate = heap()->isolate(); |
| 3197 LargeObjectIterator obj_it(this); |
| 3198 for (HeapObject* obj = obj_it.Next(); obj != NULL; obj = obj_it.Next()) { |
| 3199 if (obj->IsAbstractCode()) { |
| 3200 AbstractCode* code = AbstractCode::cast(obj); |
| 3201 RecordCodeSizeIncludingMetadata(code, isolate); |
| 3202 #ifdef DEBUG |
| 3203 isolate->code_kind_statistics()[code->kind()] += code->Size(); |
| 3204 CollectCodeCommentStatistics(obj, isolate); |
| 3205 #endif |
| 3206 } |
| 3207 } |
| 3208 } |
3171 | 3209 |
3172 #ifdef DEBUG | 3210 #ifdef DEBUG |
3173 void LargeObjectSpace::Print() { | 3211 void LargeObjectSpace::Print() { |
3174 OFStream os(stdout); | 3212 OFStream os(stdout); |
3175 LargeObjectIterator it(this); | 3213 LargeObjectIterator it(this); |
3176 for (HeapObject* obj = it.Next(); obj != NULL; obj = it.Next()) { | 3214 for (HeapObject* obj = it.Next(); obj != NULL; obj = it.Next()) { |
3177 obj->Print(os); | 3215 obj->Print(os); |
3178 } | 3216 } |
3179 } | 3217 } |
3180 | 3218 |
3181 | 3219 |
3182 void LargeObjectSpace::ReportStatistics() { | 3220 void LargeObjectSpace::ReportStatistics() { |
3183 PrintF(" size: %" V8PRIdPTR "\n", size_); | 3221 PrintF(" size: %" V8PRIdPTR "\n", size_); |
3184 int num_objects = 0; | 3222 int num_objects = 0; |
3185 ClearHistograms(heap()->isolate()); | 3223 ClearHistograms(heap()->isolate()); |
3186 LargeObjectIterator it(this); | 3224 LargeObjectIterator it(this); |
3187 for (HeapObject* obj = it.Next(); obj != NULL; obj = it.Next()) { | 3225 for (HeapObject* obj = it.Next(); obj != NULL; obj = it.Next()) { |
3188 num_objects++; | 3226 num_objects++; |
3189 CollectHistogramInfo(obj); | 3227 CollectHistogramInfo(obj); |
3190 } | 3228 } |
3191 | 3229 |
3192 PrintF( | 3230 PrintF( |
3193 " number of objects %d, " | 3231 " number of objects %d, " |
3194 "size of objects %" V8PRIdPTR "\n", | 3232 "size of objects %" V8PRIdPTR "\n", |
3195 num_objects, objects_size_); | 3233 num_objects, objects_size_); |
3196 if (num_objects > 0) ReportHistogram(heap()->isolate(), false); | 3234 if (num_objects > 0) ReportHistogram(heap()->isolate(), false); |
3197 } | 3235 } |
3198 | 3236 |
3199 | 3237 |
3200 void LargeObjectSpace::CollectCodeStatistics() { | |
3201 Isolate* isolate = heap()->isolate(); | |
3202 LargeObjectIterator obj_it(this); | |
3203 for (HeapObject* obj = obj_it.Next(); obj != NULL; obj = obj_it.Next()) { | |
3204 if (obj->IsAbstractCode()) { | |
3205 AbstractCode* code = AbstractCode::cast(obj); | |
3206 isolate->code_kind_statistics()[code->kind()] += code->Size(); | |
3207 } | |
3208 } | |
3209 } | |
3210 | |
3211 | |
3212 void Page::Print() { | 3238 void Page::Print() { |
3213 // Make a best-effort to print the objects in the page. | 3239 // Make a best-effort to print the objects in the page. |
3214 PrintF("Page@%p in %s\n", this->address(), | 3240 PrintF("Page@%p in %s\n", this->address(), |
3215 AllocationSpaceName(this->owner()->identity())); | 3241 AllocationSpaceName(this->owner()->identity())); |
3216 printf(" --------------------------------------\n"); | 3242 printf(" --------------------------------------\n"); |
3217 HeapObjectIterator objects(this); | 3243 HeapObjectIterator objects(this); |
3218 unsigned mark_size = 0; | 3244 unsigned mark_size = 0; |
3219 for (HeapObject* object = objects.Next(); object != NULL; | 3245 for (HeapObject* object = objects.Next(); object != NULL; |
3220 object = objects.Next()) { | 3246 object = objects.Next()) { |
3221 bool is_marked = Marking::IsBlackOrGrey(Marking::MarkBitFrom(object)); | 3247 bool is_marked = Marking::IsBlackOrGrey(Marking::MarkBitFrom(object)); |
3222 PrintF(" %c ", (is_marked ? '!' : ' ')); // Indent a little. | 3248 PrintF(" %c ", (is_marked ? '!' : ' ')); // Indent a little. |
3223 if (is_marked) { | 3249 if (is_marked) { |
3224 mark_size += object->Size(); | 3250 mark_size += object->Size(); |
3225 } | 3251 } |
3226 object->ShortPrint(); | 3252 object->ShortPrint(); |
3227 PrintF("\n"); | 3253 PrintF("\n"); |
3228 } | 3254 } |
3229 printf(" --------------------------------------\n"); | 3255 printf(" --------------------------------------\n"); |
3230 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); | 3256 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); |
3231 } | 3257 } |
3232 | 3258 |
3233 #endif // DEBUG | 3259 #endif // DEBUG |
3234 } // namespace internal | 3260 } // namespace internal |
3235 } // namespace v8 | 3261 } // namespace v8 |
OLD | NEW |