Mercurial > hg > graal-jvmci-8
comparison src/share/vm/gc_implementation/g1/concurrentMark.cpp @ 1835:4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
Summary: Re-enable use of the lock-free versions of region stack push() and pop() by recording aborted regions in a thread-local structure, which are then processed when scanning of the region stack restarts. The previous locking versions of these routines are retained for diagnostic purposes.
Reviewed-by: tonyp, ysr
author | johnc |
---|---|
date | Tue, 28 Sep 2010 09:51:37 -0700 |
parents | 8b10f48633dc |
children | a5c514e74487 |
comparison
equal
deleted
inserted
replaced
1834:22cace5e30b5 | 1835:4805b9f4779e |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved. | 2 * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | 4 * |
5 * This code is free software; you can redistribute it and/or modify it | 5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as | 6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
276 | 276 |
277 CMRegionStack::~CMRegionStack() { | 277 CMRegionStack::~CMRegionStack() { |
278 if (_base != NULL) FREE_C_HEAP_ARRAY(oop, _base); | 278 if (_base != NULL) FREE_C_HEAP_ARRAY(oop, _base); |
279 } | 279 } |
280 | 280 |
281 void CMRegionStack::push(MemRegion mr) { | 281 void CMRegionStack::push_lock_free(MemRegion mr) { |
282 assert(mr.word_size() > 0, "Precondition"); | 282 assert(mr.word_size() > 0, "Precondition"); |
283 while (true) { | 283 while (true) { |
284 if (isFull()) { | 284 jint index = _index; |
285 | |
286 if (index >= _capacity) { | |
285 _overflow = true; | 287 _overflow = true; |
286 return; | 288 return; |
287 } | 289 } |
288 // Otherwise... | 290 // Otherwise... |
289 jint index = _index; | |
290 jint next_index = index+1; | 291 jint next_index = index+1; |
291 jint res = Atomic::cmpxchg(next_index, &_index, index); | 292 jint res = Atomic::cmpxchg(next_index, &_index, index); |
292 if (res == index) { | 293 if (res == index) { |
293 _base[index] = mr; | 294 _base[index] = mr; |
294 return; | 295 return; |
295 } | 296 } |
296 // Otherwise, we need to try again. | 297 // Otherwise, we need to try again. |
297 } | 298 } |
298 } | 299 } |
299 | 300 |
300 // Currently we do not call this at all. Normally we would call it | 301 // Lock-free pop of the region stack. Called during the concurrent |
301 // during the concurrent marking / remark phases but we now call | 302 // marking / remark phases. Should only be called in tandem with |
302 // the lock-based version instead. But we might want to resurrect this | 303 // other lock-free pops. |
303 // code in the future. So, we'll leave it here commented out. | 304 MemRegion CMRegionStack::pop_lock_free() { |
304 #if 0 | |
305 MemRegion CMRegionStack::pop() { | |
306 while (true) { | 305 while (true) { |
307 // Otherwise... | |
308 jint index = _index; | 306 jint index = _index; |
309 | 307 |
310 if (index == 0) { | 308 if (index == 0) { |
311 return MemRegion(); | 309 return MemRegion(); |
312 } | 310 } |
311 // Otherwise... | |
313 jint next_index = index-1; | 312 jint next_index = index-1; |
314 jint res = Atomic::cmpxchg(next_index, &_index, index); | 313 jint res = Atomic::cmpxchg(next_index, &_index, index); |
315 if (res == index) { | 314 if (res == index) { |
316 MemRegion mr = _base[next_index]; | 315 MemRegion mr = _base[next_index]; |
317 if (mr.start() != NULL) { | 316 if (mr.start() != NULL) { |
324 } | 323 } |
325 } | 324 } |
326 // Otherwise, we need to try again. | 325 // Otherwise, we need to try again. |
327 } | 326 } |
328 } | 327 } |
329 #endif // 0 | 328 |
329 #if 0 | |
330 // The routines that manipulate the region stack with a lock are | |
331 // not currently used. They should be retained, however, as a | |
332 // diagnostic aid. | |
330 | 333 |
331 void CMRegionStack::push_with_lock(MemRegion mr) { | 334 void CMRegionStack::push_with_lock(MemRegion mr) { |
332 assert(mr.word_size() > 0, "Precondition"); | 335 assert(mr.word_size() > 0, "Precondition"); |
333 MutexLockerEx x(CMRegionStack_lock, Mutex::_no_safepoint_check_flag); | 336 MutexLockerEx x(CMRegionStack_lock, Mutex::_no_safepoint_check_flag); |
334 | 337 |
359 // that entry was invalidated... let's skip it | 362 // that entry was invalidated... let's skip it |
360 assert(mr.end() == NULL, "invariant"); | 363 assert(mr.end() == NULL, "invariant"); |
361 } | 364 } |
362 } | 365 } |
363 } | 366 } |
367 #endif | |
364 | 368 |
365 bool CMRegionStack::invalidate_entries_into_cset() { | 369 bool CMRegionStack::invalidate_entries_into_cset() { |
366 bool result = false; | 370 bool result = false; |
367 G1CollectedHeap* g1h = G1CollectedHeap::heap(); | 371 G1CollectedHeap* g1h = G1CollectedHeap::heap(); |
368 for (int i = 0; i < _oops_do_bound; ++i) { | 372 for (int i = 0; i < _oops_do_bound; ++i) { |
646 gclog_or_tty->print_cr("[global] resetting"); | 650 gclog_or_tty->print_cr("[global] resetting"); |
647 | 651 |
648 // We do reset all of them, since different phases will use | 652 // We do reset all of them, since different phases will use |
649 // different number of active threads. So, it's easiest to have all | 653 // different number of active threads. So, it's easiest to have all |
650 // of them ready. | 654 // of them ready. |
651 for (int i = 0; i < (int) _max_task_num; ++i) | 655 for (int i = 0; i < (int) _max_task_num; ++i) { |
652 _tasks[i]->reset(_nextMarkBitMap); | 656 _tasks[i]->reset(_nextMarkBitMap); |
657 } | |
653 | 658 |
654 // we need this to make sure that the flag is on during the evac | 659 // we need this to make sure that the flag is on during the evac |
655 // pause with initial mark piggy-backed | 660 // pause with initial mark piggy-backed |
656 set_concurrent_marking_in_progress(); | 661 set_concurrent_marking_in_progress(); |
657 } | 662 } |
986 if (verbose_low()) | 991 if (verbose_low()) |
987 gclog_or_tty->print_cr("[global] region ["PTR_FORMAT", "PTR_FORMAT") " | 992 gclog_or_tty->print_cr("[global] region ["PTR_FORMAT", "PTR_FORMAT") " |
988 "below the finger, pushing it", | 993 "below the finger, pushing it", |
989 mr.start(), mr.end()); | 994 mr.start(), mr.end()); |
990 | 995 |
991 if (!region_stack_push(mr)) { | 996 if (!region_stack_push_lock_free(mr)) { |
992 if (verbose_low()) | 997 if (verbose_low()) |
993 gclog_or_tty->print_cr("[global] region stack has overflown."); | 998 gclog_or_tty->print_cr("[global] region stack has overflown."); |
994 } | 999 } |
995 } | 1000 } |
996 } | 1001 } |
2331 } | 2336 } |
2332 | 2337 |
2333 return NULL; | 2338 return NULL; |
2334 } | 2339 } |
2335 | 2340 |
2341 bool ConcurrentMark::invalidate_aborted_regions_in_cset() { | |
2342 bool result = false; | |
2343 for (int i = 0; i < (int)_max_task_num; ++i) { | |
2344 CMTask* the_task = _tasks[i]; | |
2345 MemRegion mr = the_task->aborted_region(); | |
2346 if (mr.start() != NULL) { | |
2347 assert(mr.end() != NULL, "invariant"); | |
2348 assert(mr.word_size() > 0, "invariant"); | |
2349 HeapRegion* hr = _g1h->heap_region_containing(mr.start()); | |
2350 assert(hr != NULL, "invariant"); | |
2351 if (hr->in_collection_set()) { | |
2352 // The region points into the collection set | |
2353 the_task->set_aborted_region(MemRegion()); | |
2354 result = true; | |
2355 } | |
2356 } | |
2357 } | |
2358 return result; | |
2359 } | |
2360 | |
2361 bool ConcurrentMark::has_aborted_regions() { | |
2362 for (int i = 0; i < (int)_max_task_num; ++i) { | |
2363 CMTask* the_task = _tasks[i]; | |
2364 MemRegion mr = the_task->aborted_region(); | |
2365 if (mr.start() != NULL) { | |
2366 assert(mr.end() != NULL, "invariant"); | |
2367 assert(mr.word_size() > 0, "invariant"); | |
2368 return true; | |
2369 } | |
2370 } | |
2371 return false; | |
2372 } | |
2373 | |
2336 void ConcurrentMark::oops_do(OopClosure* cl) { | 2374 void ConcurrentMark::oops_do(OopClosure* cl) { |
2337 if (_markStack.size() > 0 && verbose_low()) | 2375 if (_markStack.size() > 0 && verbose_low()) |
2338 gclog_or_tty->print_cr("[global] scanning the global marking stack, " | 2376 gclog_or_tty->print_cr("[global] scanning the global marking stack, " |
2339 "size = %d", _markStack.size()); | 2377 "size = %d", _markStack.size()); |
2340 // we first iterate over the contents of the mark stack... | 2378 // we first iterate over the contents of the mark stack... |
2349 | 2387 |
2350 // ...then over the contents of the all the task queues. | 2388 // ...then over the contents of the all the task queues. |
2351 queue->oops_do(cl); | 2389 queue->oops_do(cl); |
2352 } | 2390 } |
2353 | 2391 |
2354 // finally, invalidate any entries that in the region stack that | 2392 // Invalidate any entries, that are in the region stack, that |
2355 // point into the collection set | 2393 // point into the collection set |
2356 if (_regionStack.invalidate_entries_into_cset()) { | 2394 if (_regionStack.invalidate_entries_into_cset()) { |
2357 // otherwise, any gray objects copied during the evacuation pause | 2395 // otherwise, any gray objects copied during the evacuation pause |
2358 // might not be visited. | 2396 // might not be visited. |
2359 assert(_should_gray_objects, "invariant"); | 2397 assert(_should_gray_objects, "invariant"); |
2360 } | 2398 } |
2399 | |
2400 // Invalidate any aborted regions, recorded in the individual CM | |
2401 // tasks, that point into the collection set. | |
2402 if (invalidate_aborted_regions_in_cset()) { | |
2403 // otherwise, any gray objects copied during the evacuation pause | |
2404 // might not be visited. | |
2405 assert(_should_gray_objects, "invariant"); | |
2406 } | |
2407 | |
2361 } | 2408 } |
2362 | 2409 |
2363 void ConcurrentMark::clear_marking_state() { | 2410 void ConcurrentMark::clear_marking_state() { |
2364 _markStack.setEmpty(); | 2411 _markStack.setEmpty(); |
2365 _markStack.clear_overflow(); | 2412 _markStack.clear_overflow(); |
2636 // empty during an evacuation pause. So, we make the fix a bit less | 2683 // empty during an evacuation pause. So, we make the fix a bit less |
2637 // conservative and ensure that regions are pushed on the stack, | 2684 // conservative and ensure that regions are pushed on the stack, |
2638 // irrespective whether all collection set regions are below the | 2685 // irrespective whether all collection set regions are below the |
2639 // finger, if the region stack is not empty. This is expected to be | 2686 // finger, if the region stack is not empty. This is expected to be |
2640 // a rare case, so I don't think it's necessary to be smarted about it. | 2687 // a rare case, so I don't think it's necessary to be smarted about it. |
2641 if (!region_stack_empty()) | 2688 if (!region_stack_empty() || has_aborted_regions()) |
2642 _should_gray_objects = true; | 2689 _should_gray_objects = true; |
2643 } | 2690 } |
2644 | 2691 |
2645 void ConcurrentMark::registerCSetRegion(HeapRegion* hr) { | 2692 void ConcurrentMark::registerCSetRegion(HeapRegion* hr) { |
2646 if (!concurrent_marking_in_progress()) | 2693 if (!concurrent_marking_in_progress()) |
2655 void ConcurrentMark::abort() { | 2702 void ConcurrentMark::abort() { |
2656 // Clear all marks to force marking thread to do nothing | 2703 // Clear all marks to force marking thread to do nothing |
2657 _nextMarkBitMap->clearAll(); | 2704 _nextMarkBitMap->clearAll(); |
2658 // Empty mark stack | 2705 // Empty mark stack |
2659 clear_marking_state(); | 2706 clear_marking_state(); |
2660 for (int i = 0; i < (int)_max_task_num; ++i) | 2707 for (int i = 0; i < (int)_max_task_num; ++i) { |
2661 _tasks[i]->clear_region_fields(); | 2708 _tasks[i]->clear_region_fields(); |
2709 _tasks[i]->clear_aborted_region(); | |
2710 } | |
2662 _has_aborted = true; | 2711 _has_aborted = true; |
2663 | 2712 |
2664 SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set(); | 2713 SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set(); |
2665 satb_mq_set.abandon_partial_marking(); | 2714 satb_mq_set.abandon_partial_marking(); |
2666 // This can be called either during or outside marking, we'll read | 2715 // This can be called either during or outside marking, we'll read |
2934 if (_cm->verbose_low()) | 2983 if (_cm->verbose_low()) |
2935 gclog_or_tty->print_cr("[%d] resetting", _task_id); | 2984 gclog_or_tty->print_cr("[%d] resetting", _task_id); |
2936 | 2985 |
2937 _nextMarkBitMap = nextMarkBitMap; | 2986 _nextMarkBitMap = nextMarkBitMap; |
2938 clear_region_fields(); | 2987 clear_region_fields(); |
2988 clear_aborted_region(); | |
2939 | 2989 |
2940 _calls = 0; | 2990 _calls = 0; |
2941 _elapsed_time_ms = 0.0; | 2991 _elapsed_time_ms = 0.0; |
2942 _termination_time_ms = 0.0; | 2992 _termination_time_ms = 0.0; |
2943 _termination_start_time_ms = 0.0; | 2993 _termination_start_time_ms = 0.0; |
3426 return; | 3476 return; |
3427 | 3477 |
3428 assert(_region_finger == NULL, | 3478 assert(_region_finger == NULL, |
3429 "it should be NULL when we're not scanning a region"); | 3479 "it should be NULL when we're not scanning a region"); |
3430 | 3480 |
3431 if (!_cm->region_stack_empty()) { | 3481 if (!_cm->region_stack_empty() || !_aborted_region.is_empty()) { |
3432 if (_cm->verbose_low()) | 3482 if (_cm->verbose_low()) |
3433 gclog_or_tty->print_cr("[%d] draining region stack, size = %d", | 3483 gclog_or_tty->print_cr("[%d] draining region stack, size = %d", |
3434 _task_id, _cm->region_stack_size()); | 3484 _task_id, _cm->region_stack_size()); |
3435 | 3485 |
3436 MemRegion mr = _cm->region_stack_pop_with_lock(); | 3486 MemRegion mr; |
3437 // it returns MemRegion() if the pop fails | 3487 |
3438 statsOnly(if (mr.start() != NULL) ++_region_stack_pops ); | 3488 if (!_aborted_region.is_empty()) { |
3489 mr = _aborted_region; | |
3490 _aborted_region = MemRegion(); | |
3491 | |
3492 if (_cm->verbose_low()) | |
3493 gclog_or_tty->print_cr("[%d] scanning aborted region [ " PTR_FORMAT ", " PTR_FORMAT " )", | |
3494 _task_id, mr.start(), mr.end()); | |
3495 } else { | |
3496 mr = _cm->region_stack_pop_lock_free(); | |
3497 // it returns MemRegion() if the pop fails | |
3498 statsOnly(if (mr.start() != NULL) ++_region_stack_pops ); | |
3499 } | |
3439 | 3500 |
3440 while (mr.start() != NULL) { | 3501 while (mr.start() != NULL) { |
3441 if (_cm->verbose_medium()) | 3502 if (_cm->verbose_medium()) |
3442 gclog_or_tty->print_cr("[%d] we are scanning region " | 3503 gclog_or_tty->print_cr("[%d] we are scanning region " |
3443 "["PTR_FORMAT", "PTR_FORMAT")", | 3504 "["PTR_FORMAT", "PTR_FORMAT")", |
3444 _task_id, mr.start(), mr.end()); | 3505 _task_id, mr.start(), mr.end()); |
3506 | |
3445 assert(mr.end() <= _cm->finger(), | 3507 assert(mr.end() <= _cm->finger(), |
3446 "otherwise the region shouldn't be on the stack"); | 3508 "otherwise the region shouldn't be on the stack"); |
3447 assert(!mr.is_empty(), "Only non-empty regions live on the region stack"); | 3509 assert(!mr.is_empty(), "Only non-empty regions live on the region stack"); |
3448 if (_nextMarkBitMap->iterate(bc, mr)) { | 3510 if (_nextMarkBitMap->iterate(bc, mr)) { |
3449 assert(!has_aborted(), | 3511 assert(!has_aborted(), |
3452 // We finished iterating over the region without aborting. | 3514 // We finished iterating over the region without aborting. |
3453 regular_clock_call(); | 3515 regular_clock_call(); |
3454 if (has_aborted()) | 3516 if (has_aborted()) |
3455 mr = MemRegion(); | 3517 mr = MemRegion(); |
3456 else { | 3518 else { |
3457 mr = _cm->region_stack_pop_with_lock(); | 3519 mr = _cm->region_stack_pop_lock_free(); |
3458 // it returns MemRegion() if the pop fails | 3520 // it returns MemRegion() if the pop fails |
3459 statsOnly(if (mr.start() != NULL) ++_region_stack_pops ); | 3521 statsOnly(if (mr.start() != NULL) ++_region_stack_pops ); |
3460 } | 3522 } |
3461 } else { | 3523 } else { |
3462 assert(has_aborted(), "currently the only way to do so"); | 3524 assert(has_aborted(), "currently the only way to do so"); |
3465 // false from the do_bit() method. However, inside the | 3527 // false from the do_bit() method. However, inside the |
3466 // do_bit() method we move the _region_finger to point to the | 3528 // do_bit() method we move the _region_finger to point to the |
3467 // object currently being looked at. So, if we bail out, we | 3529 // object currently being looked at. So, if we bail out, we |
3468 // have definitely set _region_finger to something non-null. | 3530 // have definitely set _region_finger to something non-null. |
3469 assert(_region_finger != NULL, "invariant"); | 3531 assert(_region_finger != NULL, "invariant"); |
3532 | |
3533 // Make sure that any previously aborted region has been | |
3534 // cleared. | |
3535 assert(_aborted_region.is_empty(), "aborted region not cleared"); | |
3470 | 3536 |
3471 // The iteration was actually aborted. So now _region_finger | 3537 // The iteration was actually aborted. So now _region_finger |
3472 // points to the address of the object we last scanned. If we | 3538 // points to the address of the object we last scanned. If we |
3473 // leave it there, when we restart this task, we will rescan | 3539 // leave it there, when we restart this task, we will rescan |
3474 // the object. It is easy to avoid this. We move the finger by | 3540 // the object. It is easy to avoid this. We move the finger by |
3478 MemRegion newRegion = | 3544 MemRegion newRegion = |
3479 MemRegion(_nextMarkBitMap->nextWord(_region_finger), mr.end()); | 3545 MemRegion(_nextMarkBitMap->nextWord(_region_finger), mr.end()); |
3480 | 3546 |
3481 if (!newRegion.is_empty()) { | 3547 if (!newRegion.is_empty()) { |
3482 if (_cm->verbose_low()) { | 3548 if (_cm->verbose_low()) { |
3483 gclog_or_tty->print_cr("[%d] pushing unscanned region" | 3549 gclog_or_tty->print_cr("[%d] recording unscanned region" |
3484 "[" PTR_FORMAT "," PTR_FORMAT ") on region stack", | 3550 "[" PTR_FORMAT "," PTR_FORMAT ") in CMTask", |
3485 _task_id, | 3551 _task_id, |
3486 newRegion.start(), newRegion.end()); | 3552 newRegion.start(), newRegion.end()); |
3487 } | 3553 } |
3488 // Now push the part of the region we didn't scan on the | 3554 // Now record the part of the region we didn't scan to |
3489 // region stack to make sure a task scans it later. | 3555 // make sure this task scans it later. |
3490 _cm->region_stack_push_with_lock(newRegion); | 3556 _aborted_region = newRegion; |
3491 } | 3557 } |
3492 // break from while | 3558 // break from while |
3493 mr = MemRegion(); | 3559 mr = MemRegion(); |
3494 } | 3560 } |
3495 _region_finger = NULL; | 3561 _region_finger = NULL; |
3655 assert(time_target_ms >= 1.0, "minimum granularity is 1ms"); | 3721 assert(time_target_ms >= 1.0, "minimum granularity is 1ms"); |
3656 assert(concurrent() == _cm->concurrent(), "they should be the same"); | 3722 assert(concurrent() == _cm->concurrent(), "they should be the same"); |
3657 | 3723 |
3658 assert(concurrent() || _cm->region_stack_empty(), | 3724 assert(concurrent() || _cm->region_stack_empty(), |
3659 "the region stack should have been cleared before remark"); | 3725 "the region stack should have been cleared before remark"); |
3726 assert(concurrent() || !_cm->has_aborted_regions(), | |
3727 "aborted regions should have been cleared before remark"); | |
3660 assert(_region_finger == NULL, | 3728 assert(_region_finger == NULL, |
3661 "this should be non-null only when a region is being scanned"); | 3729 "this should be non-null only when a region is being scanned"); |
3662 | 3730 |
3663 G1CollectorPolicy* g1_policy = _g1h->g1_policy(); | 3731 G1CollectorPolicy* g1_policy = _g1h->g1_policy(); |
3664 assert(_task_queues != NULL, "invariant"); | 3732 assert(_task_queues != NULL, "invariant"); |
3944 // We can now guarantee that the global stack is empty, since | 4012 // We can now guarantee that the global stack is empty, since |
3945 // all other tasks have finished. We separated the guarantees so | 4013 // all other tasks have finished. We separated the guarantees so |
3946 // that, if a condition is false, we can immediately find out | 4014 // that, if a condition is false, we can immediately find out |
3947 // which one. | 4015 // which one. |
3948 guarantee(_cm->out_of_regions(), "only way to reach here"); | 4016 guarantee(_cm->out_of_regions(), "only way to reach here"); |
4017 guarantee(_aborted_region.is_empty(), "only way to reach here"); | |
3949 guarantee(_cm->region_stack_empty(), "only way to reach here"); | 4018 guarantee(_cm->region_stack_empty(), "only way to reach here"); |
3950 guarantee(_cm->mark_stack_empty(), "only way to reach here"); | 4019 guarantee(_cm->mark_stack_empty(), "only way to reach here"); |
3951 guarantee(_task_queue->size() == 0, "only way to reach here"); | 4020 guarantee(_task_queue->size() == 0, "only way to reach here"); |
3952 guarantee(!_cm->has_overflown(), "only way to reach here"); | 4021 guarantee(!_cm->has_overflown(), "only way to reach here"); |
3953 guarantee(!_cm->mark_stack_overflow(), "only way to reach here"); | 4022 guarantee(!_cm->mark_stack_overflow(), "only way to reach here"); |
4043 _task_id(task_id), _cm(cm), | 4112 _task_id(task_id), _cm(cm), |
4044 _claimed(false), | 4113 _claimed(false), |
4045 _nextMarkBitMap(NULL), _hash_seed(17), | 4114 _nextMarkBitMap(NULL), _hash_seed(17), |
4046 _task_queue(task_queue), | 4115 _task_queue(task_queue), |
4047 _task_queues(task_queues), | 4116 _task_queues(task_queues), |
4048 _oop_closure(NULL) { | 4117 _oop_closure(NULL), |
4118 _aborted_region(MemRegion()) { | |
4049 guarantee(task_queue != NULL, "invariant"); | 4119 guarantee(task_queue != NULL, "invariant"); |
4050 guarantee(task_queues != NULL, "invariant"); | 4120 guarantee(task_queues != NULL, "invariant"); |
4051 | 4121 |
4052 statsOnly( _clock_due_to_scanning = 0; | 4122 statsOnly( _clock_due_to_scanning = 0; |
4053 _clock_due_to_marking = 0 ); | 4123 _clock_due_to_marking = 0 ); |