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

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: Fixed a compile time error on the windows bots. Created 4 years, 7 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
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 + metadata size : %10d bytes\n",
2754 isolate->code_and_metadata_size());
2755 PrintF("bytecode + metadata size: %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 // TODO(mythria): Also enable this for BytecodeArray when it supports
2848 // RelocInformation.
rmcilroy 2016/05/23 10:16:30 Bytecode arrays will never have RelocInfo, so this
mythria 2016/05/23 11:27:51 Thanks. I removed the comment. Done.
2849 if (!obj->IsCode()) {
2850 return;
2851 }
2852 Code* code = Code::cast(obj);
2853 RelocIterator it(code);
2854 int delta = 0;
2855 const byte* prev_pc = code->instruction_start();
2856 while (!it.done()) {
2857 if (it.rinfo()->rmode() == RelocInfo::COMMENT) {
2858 delta += static_cast<int>(it.rinfo()->pc() - prev_pc);
2859 CollectCommentStatistics(isolate, &it);
2860 prev_pc = it.rinfo()->pc();
2861 }
2862 it.next();
2863 }
2847 2864
2848 // Collects code size statistics: 2865 DCHECK(code->instruction_start() <= prev_pc &&
2849 // - by code kind 2866 prev_pc <= code->instruction_end());
2850 // - by code comment 2867 delta += static_cast<int>(code->instruction_end() - prev_pc);
2851 void PagedSpace::CollectCodeStatistics() { 2868 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 } 2869 }
2882 2870
2883 2871
2884 void PagedSpace::ReportStatistics() { 2872 void PagedSpace::ReportStatistics() {
2885 int pct = static_cast<int>(Available() * 100 / Capacity()); 2873 int pct = static_cast<int>(Available() * 100 / Capacity());
2886 PrintF(" capacity: %" V8PRIdPTR ", waste: %" V8PRIdPTR 2874 PrintF(" capacity: %" V8PRIdPTR ", waste: %" V8PRIdPTR
2887 ", available: %" V8PRIdPTR ", %%%d\n", 2875 ", available: %" V8PRIdPTR ", %%%d\n",
2888 Capacity(), Waste(), Available(), pct); 2876 Capacity(), Waste(), Available(), pct);
2889 2877
2890 if (heap()->mark_compact_collector()->sweeping_in_progress()) { 2878 if (heap()->mark_compact_collector()->sweeping_in_progress()) {
2891 heap()->mark_compact_collector()->EnsureSweepingCompleted(); 2879 heap()->mark_compact_collector()->EnsureSweepingCompleted();
2892 } 2880 }
2893 ClearHistograms(heap()->isolate()); 2881 ClearHistograms(heap()->isolate());
2894 HeapObjectIterator obj_it(this); 2882 HeapObjectIterator obj_it(this);
2895 for (HeapObject* obj = obj_it.Next(); obj != NULL; obj = obj_it.Next()) 2883 for (HeapObject* obj = obj_it.Next(); obj != NULL; obj = obj_it.Next())
2896 CollectHistogramInfo(obj); 2884 CollectHistogramInfo(obj);
2897 ReportHistogram(heap()->isolate(), true); 2885 ReportHistogram(heap()->isolate(), true);
2898 } 2886 }
2899 #endif 2887 #endif
2900 2888
2889 static void RecordMetadataStatistics(AbstractCode* abstract_code,
rmcilroy 2016/05/23 10:16:30 This is code and metadata sizes isn't it? If so, u
mythria 2016/05/23 11:27:51 Done.
2890 Isolate* isolate) {
2891 int size = abstract_code->InstructionAndMetadataSize();
rmcilroy 2016/05/23 10:16:30 I don't like the name InstructionAndMetadataSize()
mythria 2016/05/23 11:27:51 Done.
2892 if (abstract_code->IsCode()) {
2893 size += isolate->code_and_metadata_size();
2894 isolate->set_code_and_metadata_size(size);
2895 } else {
2896 size += isolate->bytecode_and_metadata_size();
2897 isolate->set_bytecode_and_metadata_size(size);
2898 }
2899 }
2900
2901 // Collects code size statistics:
2902 // - code and metadata size
2903 // - by code kind (only in debug mode)
2904 // - by code comment (only in debug mode)
2905 void PagedSpace::CollectCodeStatistics() {
2906 Isolate* isolate = heap()->isolate();
2907 HeapObjectIterator obj_it(this);
2908 for (HeapObject* obj = obj_it.Next(); obj != NULL; obj = obj_it.Next()) {
2909 if (obj->IsAbstractCode()) {
2910 AbstractCode* code = AbstractCode::cast(obj);
2911 RecordMetadataStatistics(code, isolate);
2912 #ifdef DEBUG
2913 isolate->code_kind_statistics()[code->kind()] += code->Size();
2914 CollectCodeCommentStatistics(obj, isolate);
2915 #endif
2916 }
2917 }
2918 }
2919
2920 void PagedSpace::ResetCodeAndMetadataStatistics(Isolate* isolate) {
2921 isolate->set_code_and_metadata_size(0);
2922 isolate->set_bytecode_and_metadata_size(0);
2923 #ifdef DEBUG
2924 ResetCodeStatistics(isolate);
2925 #endif
2926 }
2901 2927
2902 // ----------------------------------------------------------------------------- 2928 // -----------------------------------------------------------------------------
2903 // MapSpace implementation 2929 // MapSpace implementation
2904 2930
2905 #ifdef VERIFY_HEAP 2931 #ifdef VERIFY_HEAP
2906 void MapSpace::VerifyObject(HeapObject* object) { CHECK(object->IsMap()); } 2932 void MapSpace::VerifyObject(HeapObject* object) { CHECK(object->IsMap()); }
2907 #endif 2933 #endif
2908 2934
2909 2935
2910 // ----------------------------------------------------------------------------- 2936 // -----------------------------------------------------------------------------
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after
3161 HeapObject* element_object = HeapObject::cast(element); 3187 HeapObject* element_object = HeapObject::cast(element);
3162 CHECK(heap()->Contains(element_object)); 3188 CHECK(heap()->Contains(element_object));
3163 CHECK(element_object->map()->IsMap()); 3189 CHECK(element_object->map()->IsMap());
3164 } 3190 }
3165 } 3191 }
3166 } 3192 }
3167 } 3193 }
3168 } 3194 }
3169 #endif 3195 #endif
3170 3196
3197 void LargeObjectSpace::CollectCodeStatistics() {
3198 Isolate* isolate = heap()->isolate();
3199 LargeObjectIterator obj_it(this);
3200 for (HeapObject* obj = obj_it.Next(); obj != NULL; obj = obj_it.Next()) {
3201 if (obj->IsAbstractCode()) {
3202 AbstractCode* code = AbstractCode::cast(obj);
3203 RecordMetadataStatistics(code, isolate);
3204 #ifdef DEBUG
3205 isolate->code_kind_statistics()[code->kind()] += code->Size();
3206 CollectCodeCommentStatistics(obj, isolate);
3207 #endif
3208 }
3209 }
3210 }
3171 3211
3172 #ifdef DEBUG 3212 #ifdef DEBUG
3173 void LargeObjectSpace::Print() { 3213 void LargeObjectSpace::Print() {
3174 OFStream os(stdout); 3214 OFStream os(stdout);
3175 LargeObjectIterator it(this); 3215 LargeObjectIterator it(this);
3176 for (HeapObject* obj = it.Next(); obj != NULL; obj = it.Next()) { 3216 for (HeapObject* obj = it.Next(); obj != NULL; obj = it.Next()) {
3177 obj->Print(os); 3217 obj->Print(os);
3178 } 3218 }
3179 } 3219 }
3180 3220
3181 3221
3182 void LargeObjectSpace::ReportStatistics() { 3222 void LargeObjectSpace::ReportStatistics() {
3183 PrintF(" size: %" V8PRIdPTR "\n", size_); 3223 PrintF(" size: %" V8PRIdPTR "\n", size_);
3184 int num_objects = 0; 3224 int num_objects = 0;
3185 ClearHistograms(heap()->isolate()); 3225 ClearHistograms(heap()->isolate());
3186 LargeObjectIterator it(this); 3226 LargeObjectIterator it(this);
3187 for (HeapObject* obj = it.Next(); obj != NULL; obj = it.Next()) { 3227 for (HeapObject* obj = it.Next(); obj != NULL; obj = it.Next()) {
3188 num_objects++; 3228 num_objects++;
3189 CollectHistogramInfo(obj); 3229 CollectHistogramInfo(obj);
3190 } 3230 }
3191 3231
3192 PrintF( 3232 PrintF(
3193 " number of objects %d, " 3233 " number of objects %d, "
3194 "size of objects %" V8PRIdPTR "\n", 3234 "size of objects %" V8PRIdPTR "\n",
3195 num_objects, objects_size_); 3235 num_objects, objects_size_);
3196 if (num_objects > 0) ReportHistogram(heap()->isolate(), false); 3236 if (num_objects > 0) ReportHistogram(heap()->isolate(), false);
3197 } 3237 }
3198 3238
3199 3239
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() { 3240 void Page::Print() {
3213 // Make a best-effort to print the objects in the page. 3241 // Make a best-effort to print the objects in the page.
3214 PrintF("Page@%p in %s\n", this->address(), 3242 PrintF("Page@%p in %s\n", this->address(),
3215 AllocationSpaceName(this->owner()->identity())); 3243 AllocationSpaceName(this->owner()->identity()));
3216 printf(" --------------------------------------\n"); 3244 printf(" --------------------------------------\n");
3217 HeapObjectIterator objects(this); 3245 HeapObjectIterator objects(this);
3218 unsigned mark_size = 0; 3246 unsigned mark_size = 0;
3219 for (HeapObject* object = objects.Next(); object != NULL; 3247 for (HeapObject* object = objects.Next(); object != NULL;
3220 object = objects.Next()) { 3248 object = objects.Next()) {
3221 bool is_marked = Marking::IsBlackOrGrey(Marking::MarkBitFrom(object)); 3249 bool is_marked = Marking::IsBlackOrGrey(Marking::MarkBitFrom(object));
3222 PrintF(" %c ", (is_marked ? '!' : ' ')); // Indent a little. 3250 PrintF(" %c ", (is_marked ? '!' : ' ')); // Indent a little.
3223 if (is_marked) { 3251 if (is_marked) {
3224 mark_size += object->Size(); 3252 mark_size += object->Size();
3225 } 3253 }
3226 object->ShortPrint(); 3254 object->ShortPrint();
3227 PrintF("\n"); 3255 PrintF("\n");
3228 } 3256 }
3229 printf(" --------------------------------------\n"); 3257 printf(" --------------------------------------\n");
3230 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); 3258 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes());
3231 } 3259 }
3232 3260
3233 #endif // DEBUG 3261 #endif // DEBUG
3234 } // namespace internal 3262 } // namespace internal
3235 } // namespace v8 3263 } // namespace v8
OLDNEW
« src/flag-definitions.h ('K') | « src/heap/spaces.h ('k') | src/isolate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698