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

Side by Side Diff: src/heap/mark-compact.cc

Issue 1421903012: [heap] Separate out optimized code map processing. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Make verifier happy. Created 5 years, 1 month 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/mark-compact.h ('k') | src/heap/mark-compact-inl.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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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/mark-compact.h" 5 #include "src/heap/mark-compact.h"
6 6
7 #include "src/base/atomicops.h" 7 #include "src/base/atomicops.h"
8 #include "src/base/bits.h" 8 #include "src/base/bits.h"
9 #include "src/base/sys-info.h" 9 #include "src/base/sys-info.h"
10 #include "src/code-stubs.h" 10 #include "src/code-stubs.h"
(...skipping 966 matching lines...) Expand 10 before | Expand all | Expand 10 after
977 isolate_->heap()->mark_compact_collector()->RecordSlot(candidate, code_slot, 977 isolate_->heap()->mark_compact_collector()->RecordSlot(candidate, code_slot,
978 *code_slot); 978 *code_slot);
979 979
980 candidate = next_candidate; 980 candidate = next_candidate;
981 } 981 }
982 982
983 shared_function_info_candidates_head_ = NULL; 983 shared_function_info_candidates_head_ = NULL;
984 } 984 }
985 985
986 986
987 void CodeFlusher::ProcessOptimizedCodeMaps() {
988 STATIC_ASSERT(SharedFunctionInfo::kEntryLength == 4);
989
990 SharedFunctionInfo* holder = optimized_code_map_holder_head_;
991 SharedFunctionInfo* next_holder;
992
993 while (holder != NULL) {
994 next_holder = GetNextCodeMap(holder);
995 ClearNextCodeMap(holder);
996
997 // Process context-dependent entries in the optimized code map.
998 FixedArray* code_map = FixedArray::cast(holder->optimized_code_map());
999 int new_length = SharedFunctionInfo::kEntriesStart;
1000 int old_length = code_map->length();
1001 for (int i = SharedFunctionInfo::kEntriesStart; i < old_length;
1002 i += SharedFunctionInfo::kEntryLength) {
1003 // Each entry contains [ context, code, literals, ast-id ] as fields.
1004 STATIC_ASSERT(SharedFunctionInfo::kEntryLength == 4);
1005 Context* context =
1006 Context::cast(code_map->get(i + SharedFunctionInfo::kContextOffset));
1007 HeapObject* code = HeapObject::cast(
1008 code_map->get(i + SharedFunctionInfo::kCachedCodeOffset));
1009 FixedArray* literals = FixedArray::cast(
1010 code_map->get(i + SharedFunctionInfo::kLiteralsOffset));
1011 Smi* ast_id =
1012 Smi::cast(code_map->get(i + SharedFunctionInfo::kOsrAstIdOffset));
1013 if (Marking::IsWhite(Marking::MarkBitFrom(context))) continue;
1014 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(context)));
1015 if (Marking::IsWhite(Marking::MarkBitFrom(code))) continue;
1016 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(code)));
1017 if (Marking::IsWhite(Marking::MarkBitFrom(literals))) continue;
1018 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(literals)));
1019 // Move every slot in the entry and record slots when needed.
1020 code_map->set(new_length + SharedFunctionInfo::kCachedCodeOffset, code);
1021 code_map->set(new_length + SharedFunctionInfo::kContextOffset, context);
1022 code_map->set(new_length + SharedFunctionInfo::kLiteralsOffset, literals);
1023 code_map->set(new_length + SharedFunctionInfo::kOsrAstIdOffset, ast_id);
1024 Object** code_slot = code_map->RawFieldOfElementAt(
1025 new_length + SharedFunctionInfo::kCachedCodeOffset);
1026 isolate_->heap()->mark_compact_collector()->RecordSlot(
1027 code_map, code_slot, *code_slot);
1028 Object** context_slot = code_map->RawFieldOfElementAt(
1029 new_length + SharedFunctionInfo::kContextOffset);
1030 isolate_->heap()->mark_compact_collector()->RecordSlot(
1031 code_map, context_slot, *context_slot);
1032 Object** literals_slot = code_map->RawFieldOfElementAt(
1033 new_length + SharedFunctionInfo::kLiteralsOffset);
1034 isolate_->heap()->mark_compact_collector()->RecordSlot(
1035 code_map, literals_slot, *literals_slot);
1036 new_length += SharedFunctionInfo::kEntryLength;
1037 }
1038
1039 // Process context-independent entry in the optimized code map.
1040 Object* shared_object = code_map->get(SharedFunctionInfo::kSharedCodeIndex);
1041 if (shared_object->IsCode()) {
1042 Code* shared_code = Code::cast(shared_object);
1043 if (Marking::IsWhite(Marking::MarkBitFrom(shared_code))) {
1044 code_map->set_undefined(SharedFunctionInfo::kSharedCodeIndex);
1045 } else {
1046 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(shared_code)));
1047 Object** slot =
1048 code_map->RawFieldOfElementAt(SharedFunctionInfo::kSharedCodeIndex);
1049 isolate_->heap()->mark_compact_collector()->RecordSlot(code_map, slot,
1050 *slot);
1051 }
1052 }
1053
1054 // Trim the optimized code map if entries have been removed.
1055 if (new_length < old_length) {
1056 holder->TrimOptimizedCodeMap(old_length - new_length);
1057 }
1058
1059 holder = next_holder;
1060 }
1061
1062 optimized_code_map_holder_head_ = NULL;
1063 }
1064
1065
1066 void CodeFlusher::EvictCandidate(SharedFunctionInfo* shared_info) { 987 void CodeFlusher::EvictCandidate(SharedFunctionInfo* shared_info) {
1067 // Make sure previous flushing decisions are revisited. 988 // Make sure previous flushing decisions are revisited.
1068 isolate_->heap()->incremental_marking()->RecordWrites(shared_info); 989 isolate_->heap()->incremental_marking()->RecordWrites(shared_info);
1069 990
1070 if (FLAG_trace_code_flushing) { 991 if (FLAG_trace_code_flushing) {
1071 PrintF("[code-flushing abandons function-info: "); 992 PrintF("[code-flushing abandons function-info: ");
1072 shared_info->ShortPrint(); 993 shared_info->ShortPrint();
1073 PrintF("]\n"); 994 PrintF("]\n");
1074 } 995 }
1075 996
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1126 ClearNextCandidate(function, undefined); 1047 ClearNextCandidate(function, undefined);
1127 break; 1048 break;
1128 } 1049 }
1129 1050
1130 candidate = next_candidate; 1051 candidate = next_candidate;
1131 } 1052 }
1132 } 1053 }
1133 } 1054 }
1134 1055
1135 1056
1136 void CodeFlusher::EvictOptimizedCodeMap(SharedFunctionInfo* code_map_holder) {
1137 FixedArray* code_map =
1138 FixedArray::cast(code_map_holder->optimized_code_map());
1139 DCHECK(!code_map->get(SharedFunctionInfo::kNextMapIndex)->IsUndefined());
1140
1141 // Make sure previous flushing decisions are revisited.
1142 isolate_->heap()->incremental_marking()->RecordWrites(code_map);
1143 isolate_->heap()->incremental_marking()->RecordWrites(code_map_holder);
1144
1145 if (FLAG_trace_code_flushing) {
1146 PrintF("[code-flushing abandons code-map: ");
1147 code_map_holder->ShortPrint();
1148 PrintF("]\n");
1149 }
1150
1151 SharedFunctionInfo* holder = optimized_code_map_holder_head_;
1152 SharedFunctionInfo* next_holder;
1153 if (holder == code_map_holder) {
1154 next_holder = GetNextCodeMap(code_map_holder);
1155 optimized_code_map_holder_head_ = next_holder;
1156 ClearNextCodeMap(code_map_holder);
1157 } else {
1158 while (holder != NULL) {
1159 next_holder = GetNextCodeMap(holder);
1160
1161 if (next_holder == code_map_holder) {
1162 next_holder = GetNextCodeMap(code_map_holder);
1163 SetNextCodeMap(holder, next_holder);
1164 ClearNextCodeMap(code_map_holder);
1165 break;
1166 }
1167
1168 holder = next_holder;
1169 }
1170 }
1171 }
1172
1173
1174 void CodeFlusher::EvictJSFunctionCandidates() { 1057 void CodeFlusher::EvictJSFunctionCandidates() {
1175 JSFunction* candidate = jsfunction_candidates_head_; 1058 JSFunction* candidate = jsfunction_candidates_head_;
1176 JSFunction* next_candidate; 1059 JSFunction* next_candidate;
1177 while (candidate != NULL) { 1060 while (candidate != NULL) {
1178 next_candidate = GetNextCandidate(candidate); 1061 next_candidate = GetNextCandidate(candidate);
1179 EvictCandidate(candidate); 1062 EvictCandidate(candidate);
1180 candidate = next_candidate; 1063 candidate = next_candidate;
1181 } 1064 }
1182 DCHECK(jsfunction_candidates_head_ == NULL); 1065 DCHECK(jsfunction_candidates_head_ == NULL);
1183 } 1066 }
1184 1067
1185 1068
1186 void CodeFlusher::EvictSharedFunctionInfoCandidates() { 1069 void CodeFlusher::EvictSharedFunctionInfoCandidates() {
1187 SharedFunctionInfo* candidate = shared_function_info_candidates_head_; 1070 SharedFunctionInfo* candidate = shared_function_info_candidates_head_;
1188 SharedFunctionInfo* next_candidate; 1071 SharedFunctionInfo* next_candidate;
1189 while (candidate != NULL) { 1072 while (candidate != NULL) {
1190 next_candidate = GetNextCandidate(candidate); 1073 next_candidate = GetNextCandidate(candidate);
1191 EvictCandidate(candidate); 1074 EvictCandidate(candidate);
1192 candidate = next_candidate; 1075 candidate = next_candidate;
1193 } 1076 }
1194 DCHECK(shared_function_info_candidates_head_ == NULL); 1077 DCHECK(shared_function_info_candidates_head_ == NULL);
1195 } 1078 }
1196 1079
1197 1080
1198 void CodeFlusher::EvictOptimizedCodeMaps() {
1199 SharedFunctionInfo* holder = optimized_code_map_holder_head_;
1200 SharedFunctionInfo* next_holder;
1201 while (holder != NULL) {
1202 next_holder = GetNextCodeMap(holder);
1203 EvictOptimizedCodeMap(holder);
1204 holder = next_holder;
1205 }
1206 DCHECK(optimized_code_map_holder_head_ == NULL);
1207 }
1208
1209
1210 void CodeFlusher::IteratePointersToFromSpace(ObjectVisitor* v) { 1081 void CodeFlusher::IteratePointersToFromSpace(ObjectVisitor* v) {
1211 Heap* heap = isolate_->heap(); 1082 Heap* heap = isolate_->heap();
1212 1083
1213 JSFunction** slot = &jsfunction_candidates_head_; 1084 JSFunction** slot = &jsfunction_candidates_head_;
1214 JSFunction* candidate = jsfunction_candidates_head_; 1085 JSFunction* candidate = jsfunction_candidates_head_;
1215 while (candidate != NULL) { 1086 while (candidate != NULL) {
1216 if (heap->InFromSpace(candidate)) { 1087 if (heap->InFromSpace(candidate)) {
1217 v->VisitPointer(reinterpret_cast<Object**>(slot)); 1088 v->VisitPointer(reinterpret_cast<Object**>(slot));
1218 } 1089 }
1219 candidate = GetNextCandidate(*slot); 1090 candidate = GetNextCandidate(*slot);
(...skipping 1007 matching lines...) Expand 10 before | Expand all | Expand 10 after
2227 heap()->isolate()->global_handles()->RemoveImplicitRefGroups(); 2098 heap()->isolate()->global_handles()->RemoveImplicitRefGroups();
2228 } 2099 }
2229 2100
2230 // Flush code from collected candidates. 2101 // Flush code from collected candidates.
2231 if (is_code_flushing_enabled()) { 2102 if (is_code_flushing_enabled()) {
2232 GCTracer::Scope gc_scope(heap()->tracer(), 2103 GCTracer::Scope gc_scope(heap()->tracer(),
2233 GCTracer::Scope::MC_MARK_CODE_FLUSH); 2104 GCTracer::Scope::MC_MARK_CODE_FLUSH);
2234 code_flusher_->ProcessCandidates(); 2105 code_flusher_->ProcessCandidates();
2235 } 2106 }
2236 2107
2108 // Process and clear all optimized code maps.
2109 if (!FLAG_flush_optimized_code_cache) {
2110 GCTracer::Scope gc_scope(heap()->tracer(),
2111 GCTracer::Scope::MC_MARK_OPTIMIZED_CODE_MAPS);
2112 ProcessAndClearOptimizedCodeMaps();
2113 }
2114
2237 if (FLAG_track_gc_object_stats) { 2115 if (FLAG_track_gc_object_stats) {
2238 if (FLAG_trace_gc_object_stats) { 2116 if (FLAG_trace_gc_object_stats) {
2239 heap()->object_stats_->TraceObjectStats(); 2117 heap()->object_stats_->TraceObjectStats();
2240 } 2118 }
2241 heap()->object_stats_->CheckpointObjectStats(); 2119 heap()->object_stats_->CheckpointObjectStats();
2242 } 2120 }
2243 } 2121 }
2244 2122
2245 2123
2124 void MarkCompactCollector::ProcessAndClearOptimizedCodeMaps() {
2125 SharedFunctionInfo::Iterator iterator(isolate());
2126 while (SharedFunctionInfo* shared = iterator.Next()) {
2127 if (shared->optimized_code_map()->IsSmi()) continue;
2128
2129 // Process context-dependent entries in the optimized code map.
2130 FixedArray* code_map = FixedArray::cast(shared->optimized_code_map());
2131 int new_length = SharedFunctionInfo::kEntriesStart;
2132 int old_length = code_map->length();
2133 for (int i = SharedFunctionInfo::kEntriesStart; i < old_length;
2134 i += SharedFunctionInfo::kEntryLength) {
2135 // Each entry contains [ context, code, literals, ast-id ] as fields.
2136 STATIC_ASSERT(SharedFunctionInfo::kEntryLength == 4);
2137 Context* context =
2138 Context::cast(code_map->get(i + SharedFunctionInfo::kContextOffset));
2139 HeapObject* code = HeapObject::cast(
2140 code_map->get(i + SharedFunctionInfo::kCachedCodeOffset));
2141 FixedArray* literals = FixedArray::cast(
2142 code_map->get(i + SharedFunctionInfo::kLiteralsOffset));
2143 Smi* ast_id =
2144 Smi::cast(code_map->get(i + SharedFunctionInfo::kOsrAstIdOffset));
2145 if (Marking::IsWhite(Marking::MarkBitFrom(context))) continue;
2146 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(context)));
2147 if (Marking::IsWhite(Marking::MarkBitFrom(code))) continue;
2148 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(code)));
2149 if (Marking::IsWhite(Marking::MarkBitFrom(literals))) continue;
2150 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(literals)));
2151 // Move every slot in the entry and record slots when needed.
2152 code_map->set(new_length + SharedFunctionInfo::kCachedCodeOffset, code);
2153 code_map->set(new_length + SharedFunctionInfo::kContextOffset, context);
2154 code_map->set(new_length + SharedFunctionInfo::kLiteralsOffset, literals);
2155 code_map->set(new_length + SharedFunctionInfo::kOsrAstIdOffset, ast_id);
2156 Object** code_slot = code_map->RawFieldOfElementAt(
2157 new_length + SharedFunctionInfo::kCachedCodeOffset);
2158 RecordSlot(code_map, code_slot, *code_slot);
2159 Object** context_slot = code_map->RawFieldOfElementAt(
2160 new_length + SharedFunctionInfo::kContextOffset);
2161 RecordSlot(code_map, context_slot, *context_slot);
2162 Object** literals_slot = code_map->RawFieldOfElementAt(
2163 new_length + SharedFunctionInfo::kLiteralsOffset);
2164 RecordSlot(code_map, literals_slot, *literals_slot);
2165 new_length += SharedFunctionInfo::kEntryLength;
2166 }
2167
2168 // Process context-independent entry in the optimized code map.
2169 Object* shared_object = code_map->get(SharedFunctionInfo::kSharedCodeIndex);
2170 if (shared_object->IsCode()) {
2171 Code* shared_code = Code::cast(shared_object);
2172 if (Marking::IsWhite(Marking::MarkBitFrom(shared_code))) {
2173 code_map->set_undefined(SharedFunctionInfo::kSharedCodeIndex);
2174 } else {
2175 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(shared_code)));
2176 Object** slot =
2177 code_map->RawFieldOfElementAt(SharedFunctionInfo::kSharedCodeIndex);
2178 RecordSlot(code_map, slot, *slot);
2179 }
2180 }
2181
2182 // Trim the optimized code map if entries have been removed.
2183 if (new_length < old_length) {
2184 shared->TrimOptimizedCodeMap(old_length - new_length);
2185 }
2186 }
2187 }
2188
2189
2246 void MarkCompactCollector::ClearNonLiveReferences() { 2190 void MarkCompactCollector::ClearNonLiveReferences() {
2247 GCTracer::Scope gc_scope(heap()->tracer(), 2191 GCTracer::Scope gc_scope(heap()->tracer(),
2248 GCTracer::Scope::MC_NONLIVEREFERENCES); 2192 GCTracer::Scope::MC_NONLIVEREFERENCES);
2249 // Iterate over the map space, setting map transitions that go from 2193 // Iterate over the map space, setting map transitions that go from
2250 // a marked map to an unmarked map to null transitions. This action 2194 // a marked map to an unmarked map to null transitions. This action
2251 // is carried out only on maps of JSObjects and related subtypes. 2195 // is carried out only on maps of JSObjects and related subtypes.
2252 HeapObjectIterator map_iterator(heap()->map_space()); 2196 HeapObjectIterator map_iterator(heap()->map_space());
2253 for (HeapObject* obj = map_iterator.Next(); obj != NULL; 2197 for (HeapObject* obj = map_iterator.Next(); obj != NULL;
2254 obj = map_iterator.Next()) { 2198 obj = map_iterator.Next()) {
2255 Map* map = Map::cast(obj); 2199 Map* map = Map::cast(obj);
(...skipping 2374 matching lines...) Expand 10 before | Expand all | Expand 10 after
4630 MarkBit mark_bit = Marking::MarkBitFrom(host); 4574 MarkBit mark_bit = Marking::MarkBitFrom(host);
4631 if (Marking::IsBlack(mark_bit)) { 4575 if (Marking::IsBlack(mark_bit)) {
4632 RelocInfo rinfo(pc, RelocInfo::CODE_TARGET, 0, host); 4576 RelocInfo rinfo(pc, RelocInfo::CODE_TARGET, 0, host);
4633 RecordRelocSlot(&rinfo, target); 4577 RecordRelocSlot(&rinfo, target);
4634 } 4578 }
4635 } 4579 }
4636 } 4580 }
4637 4581
4638 } // namespace internal 4582 } // namespace internal
4639 } // namespace v8 4583 } // namespace v8
OLDNEW
« no previous file with comments | « src/heap/mark-compact.h ('k') | src/heap/mark-compact-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698