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 2028 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2039 INSTANCE_TYPE_LIST(DEF_TYPE_NAME) | 2039 INSTANCE_TYPE_LIST(DEF_TYPE_NAME) |
2040 #undef DEF_TYPE_NAME | 2040 #undef DEF_TYPE_NAME |
2041 | 2041 |
2042 #define CLEAR_HISTOGRAM(name) isolate->heap_histograms()[name].clear(); | 2042 #define CLEAR_HISTOGRAM(name) isolate->heap_histograms()[name].clear(); |
2043 INSTANCE_TYPE_LIST(CLEAR_HISTOGRAM) | 2043 INSTANCE_TYPE_LIST(CLEAR_HISTOGRAM) |
2044 #undef CLEAR_HISTOGRAM | 2044 #undef CLEAR_HISTOGRAM |
2045 | 2045 |
2046 isolate->js_spill_information()->Clear(); | 2046 isolate->js_spill_information()->Clear(); |
2047 } | 2047 } |
2048 | 2048 |
2049 | |
2050 static void ClearCodeKindStatistics(int* code_kind_statistics) { | |
2051 for (int i = 0; i < AbstractCode::NUMBER_OF_KINDS; i++) { | |
2052 code_kind_statistics[i] = 0; | |
2053 } | |
2054 } | |
2055 static void ReportCodeKindStatistics(int* code_kind_statistics) { | |
2056 PrintF("\n Code kind histograms: \n"); | |
2057 for (int i = 0; i < AbstractCode::NUMBER_OF_KINDS; i++) { | |
2058 if (code_kind_statistics[i] > 0) { | |
2059 PrintF(" %-20s: %10d bytes\n", | |
2060 AbstractCode::Kind2String(static_cast<AbstractCode::Kind>(i)), | |
2061 code_kind_statistics[i]); | |
2062 } | |
2063 } | |
2064 PrintF("\n"); | |
2065 } | |
2066 | |
2067 static int CollectHistogramInfo(HeapObject* obj) { | 2049 static int CollectHistogramInfo(HeapObject* obj) { |
2068 Isolate* isolate = obj->GetIsolate(); | 2050 Isolate* isolate = obj->GetIsolate(); |
2069 InstanceType type = obj->map()->instance_type(); | 2051 InstanceType type = obj->map()->instance_type(); |
2070 DCHECK(0 <= type && type <= LAST_TYPE); | 2052 DCHECK(0 <= type && type <= LAST_TYPE); |
2071 DCHECK(isolate->heap_histograms()[type].name() != NULL); | 2053 DCHECK(isolate->heap_histograms()[type].name() != NULL); |
2072 isolate->heap_histograms()[type].increment_number(1); | 2054 isolate->heap_histograms()[type].increment_number(1); |
2073 isolate->heap_histograms()[type].increment_bytes(obj->Size()); | 2055 isolate->heap_histograms()[type].increment_bytes(obj->Size()); |
2074 | 2056 |
2075 if (FLAG_collect_heap_spill_statistics && obj->IsJSObject()) { | 2057 if (FLAG_collect_heap_spill_statistics && obj->IsJSObject()) { |
2076 JSObject::cast(obj) | 2058 JSObject::cast(obj) |
(...skipping 677 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2754 return free_list_.Allocate(size_in_bytes); | 2736 return free_list_.Allocate(size_in_bytes); |
2755 } | 2737 } |
2756 | 2738 |
2757 // If sweeper threads are active, wait for them at that point and steal | 2739 // If sweeper threads are active, wait for them at that point and steal |
2758 // elements form their free-lists. Allocation may still fail their which | 2740 // elements form their free-lists. Allocation may still fail their which |
2759 // would indicate that there is not enough memory for the given allocation. | 2741 // would indicate that there is not enough memory for the given allocation. |
2760 return SweepAndRetryAllocation(size_in_bytes); | 2742 return SweepAndRetryAllocation(size_in_bytes); |
2761 } | 2743 } |
2762 | 2744 |
2763 #ifdef DEBUG | 2745 #ifdef DEBUG |
2764 void PagedSpace::ReportCodeStatistics(Isolate* isolate) { | |
2765 CommentStatistic* comments_statistics = | |
2766 isolate->paged_space_comments_statistics(); | |
2767 ReportCodeKindStatistics(isolate->code_kind_statistics()); | |
2768 PrintF("Code size including metadata : %10d bytes\n", | |
2769 isolate->code_and_metadata_size()); | |
2770 PrintF("Bytecode size including metadata: %10d bytes\n", | |
2771 isolate->bytecode_and_metadata_size()); | |
2772 PrintF( | |
2773 "Code comment statistics (\" [ comment-txt : size/ " | |
2774 "count (average)\"):\n"); | |
2775 for (int i = 0; i <= CommentStatistic::kMaxComments; i++) { | |
2776 const CommentStatistic& cs = comments_statistics[i]; | |
2777 if (cs.size > 0) { | |
2778 PrintF(" %-30s: %10d/%6d (%d)\n", cs.comment, cs.size, cs.count, | |
2779 cs.size / cs.count); | |
2780 } | |
2781 } | |
2782 PrintF("\n"); | |
2783 } | |
2784 | |
2785 void PagedSpace::ResetCodeStatistics(Isolate* isolate) { | |
2786 CommentStatistic* comments_statistics = | |
2787 isolate->paged_space_comments_statistics(); | |
2788 ClearCodeKindStatistics(isolate->code_kind_statistics()); | |
2789 for (int i = 0; i < CommentStatistic::kMaxComments; i++) { | |
2790 comments_statistics[i].Clear(); | |
2791 } | |
2792 comments_statistics[CommentStatistic::kMaxComments].comment = "Unknown"; | |
2793 comments_statistics[CommentStatistic::kMaxComments].size = 0; | |
2794 comments_statistics[CommentStatistic::kMaxComments].count = 0; | |
2795 } | |
2796 | |
2797 | |
2798 // Adds comment to 'comment_statistics' table. Performance OK as long as | |
2799 // 'kMaxComments' is small | |
2800 static void EnterComment(Isolate* isolate, const char* comment, int delta) { | |
2801 CommentStatistic* comments_statistics = | |
2802 isolate->paged_space_comments_statistics(); | |
2803 // Do not count empty comments | |
2804 if (delta <= 0) return; | |
2805 CommentStatistic* cs = &comments_statistics[CommentStatistic::kMaxComments]; | |
2806 // Search for a free or matching entry in 'comments_statistics': 'cs' | |
2807 // points to result. | |
2808 for (int i = 0; i < CommentStatistic::kMaxComments; i++) { | |
2809 if (comments_statistics[i].comment == NULL) { | |
2810 cs = &comments_statistics[i]; | |
2811 cs->comment = comment; | |
2812 break; | |
2813 } else if (strcmp(comments_statistics[i].comment, comment) == 0) { | |
2814 cs = &comments_statistics[i]; | |
2815 break; | |
2816 } | |
2817 } | |
2818 // Update entry for 'comment' | |
2819 cs->size += delta; | |
2820 cs->count += 1; | |
2821 } | |
2822 | |
2823 | |
2824 // Call for each nested comment start (start marked with '[ xxx', end marked | |
2825 // with ']'. RelocIterator 'it' must point to a comment reloc info. | |
2826 static void CollectCommentStatistics(Isolate* isolate, RelocIterator* it) { | |
2827 DCHECK(!it->done()); | |
2828 DCHECK(it->rinfo()->rmode() == RelocInfo::COMMENT); | |
2829 const char* tmp = reinterpret_cast<const char*>(it->rinfo()->data()); | |
2830 if (tmp[0] != '[') { | |
2831 // Not a nested comment; skip | |
2832 return; | |
2833 } | |
2834 | |
2835 // Search for end of nested comment or a new nested comment | |
2836 const char* const comment_txt = | |
2837 reinterpret_cast<const char*>(it->rinfo()->data()); | |
2838 const byte* prev_pc = it->rinfo()->pc(); | |
2839 int flat_delta = 0; | |
2840 it->next(); | |
2841 while (true) { | |
2842 // All nested comments must be terminated properly, and therefore exit | |
2843 // from loop. | |
2844 DCHECK(!it->done()); | |
2845 if (it->rinfo()->rmode() == RelocInfo::COMMENT) { | |
2846 const char* const txt = | |
2847 reinterpret_cast<const char*>(it->rinfo()->data()); | |
2848 flat_delta += static_cast<int>(it->rinfo()->pc() - prev_pc); | |
2849 if (txt[0] == ']') break; // End of nested comment | |
2850 // A new comment | |
2851 CollectCommentStatistics(isolate, it); | |
2852 // Skip code that was covered with previous comment | |
2853 prev_pc = it->rinfo()->pc(); | |
2854 } | |
2855 it->next(); | |
2856 } | |
2857 EnterComment(isolate, comment_txt, flat_delta); | |
2858 } | |
2859 | |
2860 // Collects code comment statistics | |
2861 static void CollectCodeCommentStatistics(HeapObject* obj, Isolate* isolate) { | |
2862 if (!obj->IsCode()) { | |
2863 return; | |
2864 } | |
2865 Code* code = Code::cast(obj); | |
2866 RelocIterator it(code); | |
2867 int delta = 0; | |
2868 const byte* prev_pc = code->instruction_start(); | |
2869 while (!it.done()) { | |
2870 if (it.rinfo()->rmode() == RelocInfo::COMMENT) { | |
2871 delta += static_cast<int>(it.rinfo()->pc() - prev_pc); | |
2872 CollectCommentStatistics(isolate, &it); | |
2873 prev_pc = it.rinfo()->pc(); | |
2874 } | |
2875 it.next(); | |
2876 } | |
2877 | |
2878 DCHECK(code->instruction_start() <= prev_pc && | |
2879 prev_pc <= code->instruction_end()); | |
2880 delta += static_cast<int>(code->instruction_end() - prev_pc); | |
2881 EnterComment(isolate, "NoComment", delta); | |
2882 } | |
2883 | |
2884 | |
2885 void PagedSpace::ReportStatistics() { | 2746 void PagedSpace::ReportStatistics() { |
2886 int pct = static_cast<int>(Available() * 100 / Capacity()); | 2747 int pct = static_cast<int>(Available() * 100 / Capacity()); |
2887 PrintF(" capacity: %" V8PRIdPTR ", waste: %" V8PRIdPTR | 2748 PrintF(" capacity: %" V8PRIdPTR ", waste: %" V8PRIdPTR |
2888 ", available: %" V8PRIdPTR ", %%%d\n", | 2749 ", available: %" V8PRIdPTR ", %%%d\n", |
2889 Capacity(), Waste(), Available(), pct); | 2750 Capacity(), Waste(), Available(), pct); |
2890 | 2751 |
2891 if (heap()->mark_compact_collector()->sweeping_in_progress()) { | 2752 if (heap()->mark_compact_collector()->sweeping_in_progress()) { |
2892 heap()->mark_compact_collector()->EnsureSweepingCompleted(); | 2753 heap()->mark_compact_collector()->EnsureSweepingCompleted(); |
2893 } | 2754 } |
2894 ClearHistograms(heap()->isolate()); | 2755 ClearHistograms(heap()->isolate()); |
2895 HeapObjectIterator obj_it(this); | 2756 HeapObjectIterator obj_it(this); |
2896 for (HeapObject* obj = obj_it.Next(); obj != NULL; obj = obj_it.Next()) | 2757 for (HeapObject* obj = obj_it.Next(); obj != NULL; obj = obj_it.Next()) |
2897 CollectHistogramInfo(obj); | 2758 CollectHistogramInfo(obj); |
2898 ReportHistogram(heap()->isolate(), true); | 2759 ReportHistogram(heap()->isolate(), true); |
2899 } | 2760 } |
2900 #endif | 2761 #endif |
2901 | 2762 |
2902 static void RecordCodeSizeIncludingMetadata(AbstractCode* abstract_code, | |
2903 Isolate* isolate) { | |
2904 int size = abstract_code->SizeIncludingMetadata(); | |
2905 if (abstract_code->IsCode()) { | |
2906 size += isolate->code_and_metadata_size(); | |
2907 isolate->set_code_and_metadata_size(size); | |
2908 } else { | |
2909 size += isolate->bytecode_and_metadata_size(); | |
2910 isolate->set_bytecode_and_metadata_size(size); | |
2911 } | |
2912 } | |
2913 | |
2914 // Collects code size statistics: | |
2915 // - code and metadata size | |
2916 // - by code kind (only in debug mode) | |
2917 // - by code comment (only in debug mode) | |
2918 void PagedSpace::CollectCodeStatistics() { | |
2919 Isolate* isolate = heap()->isolate(); | |
2920 HeapObjectIterator obj_it(this); | |
2921 for (HeapObject* obj = obj_it.Next(); obj != NULL; obj = obj_it.Next()) { | |
2922 if (obj->IsAbstractCode()) { | |
2923 AbstractCode* code = AbstractCode::cast(obj); | |
2924 RecordCodeSizeIncludingMetadata(code, isolate); | |
2925 #ifdef DEBUG | |
2926 isolate->code_kind_statistics()[code->kind()] += code->Size(); | |
2927 CollectCodeCommentStatistics(obj, isolate); | |
2928 #endif | |
2929 } | |
2930 } | |
2931 } | |
2932 | |
2933 void PagedSpace::ResetCodeAndMetadataStatistics(Isolate* isolate) { | |
2934 isolate->set_code_and_metadata_size(0); | |
2935 isolate->set_bytecode_and_metadata_size(0); | |
2936 #ifdef DEBUG | |
2937 ResetCodeStatistics(isolate); | |
2938 #endif | |
2939 } | |
2940 | 2763 |
2941 // ----------------------------------------------------------------------------- | 2764 // ----------------------------------------------------------------------------- |
2942 // MapSpace implementation | 2765 // MapSpace implementation |
2943 | 2766 |
2944 #ifdef VERIFY_HEAP | 2767 #ifdef VERIFY_HEAP |
2945 void MapSpace::VerifyObject(HeapObject* object) { CHECK(object->IsMap()); } | 2768 void MapSpace::VerifyObject(HeapObject* object) { CHECK(object->IsMap()); } |
2946 #endif | 2769 #endif |
2947 | 2770 |
2948 | 2771 |
2949 // ----------------------------------------------------------------------------- | 2772 // ----------------------------------------------------------------------------- |
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3190 HeapObject* element_object = HeapObject::cast(element); | 3013 HeapObject* element_object = HeapObject::cast(element); |
3191 CHECK(heap()->Contains(element_object)); | 3014 CHECK(heap()->Contains(element_object)); |
3192 CHECK(element_object->map()->IsMap()); | 3015 CHECK(element_object->map()->IsMap()); |
3193 } | 3016 } |
3194 } | 3017 } |
3195 } | 3018 } |
3196 } | 3019 } |
3197 } | 3020 } |
3198 #endif | 3021 #endif |
3199 | 3022 |
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 RecordCodeSizeIncludingMetadata(code, isolate); | |
3207 #ifdef DEBUG | |
3208 isolate->code_kind_statistics()[code->kind()] += code->Size(); | |
3209 CollectCodeCommentStatistics(obj, isolate); | |
3210 #endif | |
3211 } | |
3212 } | |
3213 } | |
3214 | |
3215 #ifdef DEBUG | 3023 #ifdef DEBUG |
3216 void LargeObjectSpace::Print() { | 3024 void LargeObjectSpace::Print() { |
3217 OFStream os(stdout); | 3025 OFStream os(stdout); |
3218 LargeObjectIterator it(this); | 3026 LargeObjectIterator it(this); |
3219 for (HeapObject* obj = it.Next(); obj != NULL; obj = it.Next()) { | 3027 for (HeapObject* obj = it.Next(); obj != NULL; obj = it.Next()) { |
3220 obj->Print(os); | 3028 obj->Print(os); |
3221 } | 3029 } |
3222 } | 3030 } |
3223 | 3031 |
3224 | 3032 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3257 object->ShortPrint(); | 3065 object->ShortPrint(); |
3258 PrintF("\n"); | 3066 PrintF("\n"); |
3259 } | 3067 } |
3260 printf(" --------------------------------------\n"); | 3068 printf(" --------------------------------------\n"); |
3261 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); | 3069 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); |
3262 } | 3070 } |
3263 | 3071 |
3264 #endif // DEBUG | 3072 #endif // DEBUG |
3265 } // namespace internal | 3073 } // namespace internal |
3266 } // namespace v8 | 3074 } // namespace v8 |
OLD | NEW |