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

Side by Side Diff: src/heap/spaces.cc

Issue 1997363002: Adds support for collecting statistics about code and its metadata. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Addressed comments from Hannes. Created 4 years, 6 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
« no previous file with comments | « src/heap/spaces.h ('k') | src/isolate.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 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
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
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
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
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
OLDNEW
« no previous file with comments | « src/heap/spaces.h ('k') | src/isolate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698