| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 156 CodeStub::IncrementalMarkingRecordWrite) { | 156 CodeStub::IncrementalMarkingRecordWrite) { |
| 157 Object* e = stubs->ValueAt(i); | 157 Object* e = stubs->ValueAt(i); |
| 158 if (e->IsCode()) { | 158 if (e->IsCode()) { |
| 159 IncrementalMarkingRecordWriteStub::Patch(Code::cast(e), enable); | 159 IncrementalMarkingRecordWriteStub::Patch(Code::cast(e), enable); |
| 160 } | 160 } |
| 161 } | 161 } |
| 162 } | 162 } |
| 163 } | 163 } |
| 164 } | 164 } |
| 165 | 165 |
| 166 static VirtualMemory* marking_stack_memory = NULL; |
| 167 |
| 168 static void EnsureMarkingStackIsCommitted() { |
| 169 if (marking_stack_memory == NULL) { |
| 170 marking_stack_memory = new VirtualMemory(4*MB); |
| 171 marking_stack_memory->Commit( |
| 172 reinterpret_cast<Address>(marking_stack_memory->address()), |
| 173 marking_stack_memory->size(), |
| 174 false); // Not executable. |
| 175 } |
| 176 } |
| 177 |
| 166 | 178 |
| 167 void IncrementalMarking::Start() { | 179 void IncrementalMarking::Start() { |
| 168 if (FLAG_trace_incremental_marking) { | 180 if (FLAG_trace_incremental_marking) { |
| 169 PrintF("[IncrementalMarking] Start\n"); | 181 PrintF("[IncrementalMarking] Start\n"); |
| 170 } | 182 } |
| 171 ASSERT(FLAG_incremental_marking); | 183 ASSERT(FLAG_incremental_marking); |
| 172 ASSERT(state_ == STOPPED); | 184 ASSERT(state_ == STOPPED); |
| 173 state_ = MARKING; | 185 state_ = MARKING; |
| 174 | 186 |
| 175 PatchIncrementalMarkingRecordWriteStubs(true); | 187 PatchIncrementalMarkingRecordWriteStubs(true); |
| 176 | 188 |
| 177 Heap::EnsureFromSpaceIsCommitted(); | 189 // Heap::EnsureFromSpaceIsCommitted(); |
| 190 EnsureMarkingStackIsCommitted(); |
| 178 | 191 |
| 179 // Initialize marking stack. | 192 // Initialize marking stack. |
| 180 marking_stack_.Initialize(Heap::new_space()->FromSpaceLow(), | 193 Address addr = static_cast<Address>(marking_stack_memory->address()); |
| 181 Heap::new_space()->FromSpaceHigh()); | 194 marking_stack_.Initialize(addr, |
| 195 addr + marking_stack_memory->size()); |
| 182 | 196 |
| 183 // Clear markbits. | 197 // Clear markbits. |
| 184 Address new_space_bottom = Heap::new_space()->bottom(); | 198 Address new_space_low = Heap::new_space()->ToSpaceLow(); |
| 185 uintptr_t new_space_size = | 199 Address new_space_high = Heap::new_space()->ToSpaceHigh(); |
| 186 RoundUp(Heap::new_space()->top() - new_space_bottom, 32 * kPointerSize); | 200 Marking::ClearRange(new_space_low, |
| 187 | 201 static_cast<int>(new_space_high - new_space_low)); |
| 188 Marking::ClearRange(new_space_bottom, new_space_size); | |
| 189 | 202 |
| 190 ClearMarkbits(); | 203 ClearMarkbits(); |
| 191 | 204 |
| 192 #ifdef DEBUG | 205 #ifdef DEBUG |
| 193 VerifyMarkbitsAreClean(); | 206 VerifyMarkbitsAreClean(); |
| 194 #endif | 207 #endif |
| 195 | 208 |
| 196 // Mark strong roots grey. | 209 // Mark strong roots grey. |
| 197 IncrementalMarkingRootMarkingVisitor visitor; | 210 IncrementalMarkingRootMarkingVisitor visitor; |
| 198 Heap::IterateStrongRoots(&visitor, VISIT_ONLY_STRONG); | 211 Heap::IterateStrongRoots(&visitor, VISIT_ONLY_STRONG); |
| 199 | 212 |
| 200 // Ready to start incremental marking. | 213 // Ready to start incremental marking. |
| 201 if (FLAG_trace_incremental_marking) { | 214 if (FLAG_trace_incremental_marking) { |
| 202 PrintF("[IncrementalMarking] Running\n"); | 215 PrintF("[IncrementalMarking] Running\n"); |
| 203 } | 216 } |
| 204 } | 217 } |
| 205 | 218 |
| 206 | 219 |
| 220 void IncrementalMarking::PrepareForScavenge() { |
| 221 if (IsStopped()) return; |
| 222 |
| 223 Address new_space_low = Heap::new_space()->FromSpaceLow(); |
| 224 Address new_space_high = Heap::new_space()->FromSpaceHigh(); |
| 225 Marking::ClearRange(new_space_low, |
| 226 static_cast<int>(new_space_high - new_space_low)); |
| 227 } |
| 228 |
| 229 |
| 230 void IncrementalMarking::UpdateMarkingStackAfterScavenge() { |
| 231 if (IsStopped()) return; |
| 232 |
| 233 HeapObject** current = marking_stack_.low(); |
| 234 HeapObject** top = marking_stack_.top(); |
| 235 HeapObject** new_top = current; |
| 236 |
| 237 while (current < top) { |
| 238 HeapObject* obj = *current++; |
| 239 if (Heap::InNewSpace(obj)) { |
| 240 MapWord map_word = obj->map_word(); |
| 241 if (map_word.IsForwardingAddress()) { |
| 242 HeapObject* dest = map_word.ToForwardingAddress(); |
| 243 MarkWhiteObjectGrey(dest, Marking::MarkBitFrom(dest)); |
| 244 *new_top++ = dest; |
| 245 ASSERT(Color(obj) == Color(dest)); |
| 246 } |
| 247 } else { |
| 248 *new_top++ = obj; |
| 249 } |
| 250 } |
| 251 |
| 252 marking_stack_.set_top(new_top); |
| 253 } |
| 254 |
| 255 |
| 207 void IncrementalMarking::Hurry() { | 256 void IncrementalMarking::Hurry() { |
| 208 if (state() == MARKING) { | 257 if (state() == MARKING) { |
| 209 double start = 0.0; | 258 double start = 0.0; |
| 210 if (FLAG_trace_incremental_marking) { | 259 if (FLAG_trace_incremental_marking) { |
| 211 PrintF("[IncrementalMarking] Hurry\n"); | 260 PrintF("[IncrementalMarking] Hurry\n"); |
| 212 start = OS::TimeCurrentMillis(); | 261 start = OS::TimeCurrentMillis(); |
| 213 } | 262 } |
| 214 // TODO(gc) hurry can mark objects it encounters black as mutator | 263 // TODO(gc) hurry can mark objects it encounters black as mutator |
| 215 // was stopped. | 264 // was stopped. |
| 216 Map* filler_map = Heap::one_pointer_filler_map(); | 265 Map* filler_map = Heap::one_pointer_filler_map(); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 247 state_ = COMPLETE; | 296 state_ = COMPLETE; |
| 248 // We completed marking. | 297 // We completed marking. |
| 249 if (FLAG_trace_incremental_marking) { | 298 if (FLAG_trace_incremental_marking) { |
| 250 PrintF("[IncrementalMarking] Complete (normal)\n"); | 299 PrintF("[IncrementalMarking] Complete (normal)\n"); |
| 251 } | 300 } |
| 252 StackGuard::RequestGC(); | 301 StackGuard::RequestGC(); |
| 253 } | 302 } |
| 254 | 303 |
| 255 | 304 |
| 256 void IncrementalMarking::Step(intptr_t allocated_bytes) { | 305 void IncrementalMarking::Step(intptr_t allocated_bytes) { |
| 257 if (state_ == MARKING) { | 306 if (state_ == MARKING && Heap::gc_state() == Heap::NOT_IN_GC) { |
| 258 allocated += allocated_bytes; | 307 allocated += allocated_bytes; |
| 259 | 308 |
| 260 if (allocated >= kAllocatedThreshold) { | 309 if (allocated >= kAllocatedThreshold) { |
| 261 intptr_t bytes_to_process = allocated * kAllocationMarkingFactor; | 310 intptr_t bytes_to_process = allocated * kAllocationMarkingFactor; |
| 262 int count = 0; | 311 int count = 0; |
| 263 double start = 0; | |
| 264 if (FLAG_trace_incremental_marking) { | |
| 265 PrintF("[IncrementalMarking] Marking %d bytes\n", bytes_to_process); | |
| 266 start = OS::TimeCurrentMillis(); | |
| 267 } | |
| 268 | 312 |
| 269 Map* filler_map = Heap::one_pointer_filler_map(); | 313 Map* filler_map = Heap::one_pointer_filler_map(); |
| 270 while (!marking_stack_.is_empty() && bytes_to_process > 0) { | 314 while (!marking_stack_.is_empty() && bytes_to_process > 0) { |
| 271 HeapObject* obj = marking_stack_.Pop(); | 315 HeapObject* obj = marking_stack_.Pop(); |
| 272 | 316 |
| 273 // Explicitly skip one word fillers. Incremental markbit patterns are | 317 // Explicitly skip one word fillers. Incremental markbit patterns are |
| 274 // correct only for objects that occupy at least two words. | 318 // correct only for objects that occupy at least two words. |
| 275 if (obj->map() != filler_map) { | 319 if (obj->map() != filler_map) { |
| 276 ASSERT(IsGrey(Marking::MarkBitFrom(obj))); | 320 ASSERT(IsGrey(Marking::MarkBitFrom(obj))); |
| 277 Map* map = obj->map(); | 321 Map* map = obj->map(); |
| 278 int size = obj->SizeFromMap(map); | 322 int size = obj->SizeFromMap(map); |
| 279 bytes_to_process -= size; | 323 bytes_to_process -= size; |
| 280 MarkBit map_mark_bit = Marking::MarkBitFrom(map); | 324 MarkBit map_mark_bit = Marking::MarkBitFrom(map); |
| 281 if (IsWhite(map_mark_bit)) WhiteToGrey(map, map_mark_bit); | 325 if (IsWhite(map_mark_bit)) WhiteToGrey(map, map_mark_bit); |
| 282 obj->IterateBody(map->instance_type(), size, &marking_visitor); | 326 obj->IterateBody(map->instance_type(), size, &marking_visitor); |
| 283 MarkBit obj_mark_bit = Marking::MarkBitFrom(obj); | 327 MarkBit obj_mark_bit = Marking::MarkBitFrom(obj); |
| 284 MarkBlack(obj_mark_bit); | 328 MarkBlack(obj_mark_bit); |
| 285 } | 329 } |
| 286 count++; | 330 count++; |
| 287 } | 331 } |
| 288 if (FLAG_trace_incremental_marking) { | |
| 289 double end = OS::TimeCurrentMillis(); | |
| 290 PrintF("[IncrementalMarking] %d objects marked, spent %d ms\n", | |
| 291 count, | |
| 292 static_cast<int>(end - start)); | |
| 293 } | |
| 294 allocated = 0; | 332 allocated = 0; |
| 295 if (marking_stack_.is_empty()) MarkingComplete(); | 333 if (marking_stack_.is_empty()) MarkingComplete(); |
| 296 } | 334 } |
| 297 } | 335 } |
| 298 } | 336 } |
| 299 | 337 |
| 300 | 338 |
| 301 } } // namespace v8::internal | 339 } } // namespace v8::internal |
| OLD | NEW |