< prev index next >

src/hotspot/share/gc/g1/g1CollectedHeap.cpp

Print this page
rev 53988 : imported patch 8219100-cleanup-young-collection-prologue

*** 2541,2551 **** // This summary needs to be printed before incrementing total collections. rem_set()->print_periodic_summary_info("Before GC RS summary", total_collections()); // Update common counters. increment_total_collections(full /* full gc */); ! if (full) { increment_old_marking_cycles_started(); } // Fill TLAB's and such double start = os::elapsedTime(); --- 2541,2551 ---- // This summary needs to be printed before incrementing total collections. rem_set()->print_periodic_summary_info("Before GC RS summary", total_collections()); // Update common counters. increment_total_collections(full /* full gc */); ! if (full || collector_state()->in_initial_mark_gc()) { increment_old_marking_cycles_started(); } // Fill TLAB's and such double start = os::elapsedTime();
*** 2863,2899 **** return false; } }; void G1CollectedHeap::start_new_collection_set() { collection_set()->start_incremental_building(); clear_cset_fast_test(); guarantee(_eden.length() == 0, "eden should have been cleared"); policy()->transfer_survivors_to_cset(survivor()); } ! bool ! G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { assert_at_safepoint_on_vm_thread(); guarantee(!is_gc_active(), "collection is not reentrant"); if (GCLocker::check_active_before_gc()) { return false; } - _gc_timer_stw->register_gc_start(); - GCIdMark gc_id_mark; - _gc_tracer_stw->report_gc_start(gc_cause(), _gc_timer_stw->gc_start()); SvcGCMarker sgcm(SvcGCMarker::MINOR); ResourceMark rm; policy()->note_gc_start(); wait_for_root_region_scanning(); print_heap_before_gc(); print_heap_regions(); trace_heap_before_gc(_gc_tracer_stw); --- 2863,2975 ---- return false; } }; void G1CollectedHeap::start_new_collection_set() { + double start = os::elapsedTime(); + collection_set()->start_incremental_building(); clear_cset_fast_test(); guarantee(_eden.length() == 0, "eden should have been cleared"); policy()->transfer_survivors_to_cset(survivor()); + + // We redo the verification but now wrt to the new CSet which + // has just got initialized after the previous CSet was freed. + _cm->verify_no_collection_set_oops_in_stacks(); + + phase_times()->record_start_new_cset_time_ms((os::elapsedTime() - start) * 1000.0); + } + + void G1CollectedHeap::calculate_collection_set(G1EvacuationInfo& evacuation_info, double target_pause_time_ms){ + policy()->finalize_collection_set(target_pause_time_ms, &_survivor); + evacuation_info.set_collectionset_regions(collection_set()->region_length()); + + _cm->verify_no_collection_set_oops_in_stacks(); + + if (_hr_printer.is_active()) { + G1PrintCollectionSetClosure cl(&_hr_printer); + _collection_set.iterate(&cl); + } + } + + G1HeapVerifier::G1VerifyType G1CollectedHeap::young_collection_verify_type() const { + if (collector_state()->in_initial_mark_gc()) { + return G1HeapVerifier::G1VerifyConcurrentStart; + } else if (collector_state()->in_young_only_phase()) { + return G1HeapVerifier::G1VerifyYoungNormal; + } else { + return G1HeapVerifier::G1VerifyMixed; + } + } + + void G1CollectedHeap::verify_before_young_collection(G1HeapVerifier::G1VerifyType type) { + if (VerifyRememberedSets) { + log_info(gc, verify)("[Verifying RemSets before GC]"); + VerifyRegionRemSetClosure v_cl; + heap_region_iterate(&v_cl); + } + _verifier->verify_before_gc(type); + _verifier->check_bitmaps("GC Start"); + } + + void G1CollectedHeap::verify_after_young_collection(G1HeapVerifier::G1VerifyType type) { + if (VerifyRememberedSets) { + log_info(gc, verify)("[Verifying RemSets after GC]"); + VerifyRegionRemSetClosure v_cl; + heap_region_iterate(&v_cl); + } + _verifier->verify_after_gc(type); + _verifier->check_bitmaps("GC End"); + } + + void G1CollectedHeap::expand_heap_after_young_collection(){ + size_t expand_bytes = _heap_sizing_policy->expansion_amount(); + if (expand_bytes > 0) { + // No need for an ergo logging here, + // expansion_amount() does this when it returns a value > 0. + double expand_ms; + if (!expand(expand_bytes, _workers, &expand_ms)) { + // We failed to expand the heap. Cannot do anything about it. + } + phase_times()->record_expand_heap_time(expand_ms); + } + } + + const char* G1CollectedHeap::young_gc_name() const { + if (collector_state()->in_initial_mark_gc()) { + return "Pause Young (Concurrent Start)"; + } else if (collector_state()->in_young_only_phase()) { + if (collector_state()->in_young_gc_before_mixed()) { + return "Pause Young (Prepare Mixed)"; + } else { + return "Pause Young (Normal)"; + } + } else { + return "Pause Young (Mixed)"; + } } ! bool G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { assert_at_safepoint_on_vm_thread(); guarantee(!is_gc_active(), "collection is not reentrant"); if (GCLocker::check_active_before_gc()) { return false; } GCIdMark gc_id_mark; SvcGCMarker sgcm(SvcGCMarker::MINOR); ResourceMark rm; policy()->note_gc_start(); + _gc_timer_stw->register_gc_start(); + _gc_tracer_stw->report_gc_start(gc_cause(), _gc_timer_stw->gc_start()); + wait_for_root_region_scanning(); print_heap_before_gc(); print_heap_regions(); trace_heap_before_gc(_gc_tracer_stw);
*** 2910,2960 **** } // We do not allow initial-mark to be piggy-backed on a mixed GC. assert(!collector_state()->in_initial_mark_gc() || collector_state()->in_young_only_phase(), "sanity"); - // We also do not allow mixed GCs during marking. assert(!collector_state()->mark_or_rebuild_in_progress() || collector_state()->in_young_only_phase(), "sanity"); // Record whether this pause is an initial mark. When the current // thread has completed its logging output and it's safe to signal // the CM thread, the flag's value in the policy has been reset. bool should_start_conc_mark = collector_state()->in_initial_mark_gc(); // Inner scope for scope based logging, timers, and stats collection { G1EvacuationInfo evacuation_info; - if (collector_state()->in_initial_mark_gc()) { - // We are about to start a marking cycle, so we increment the - // full collection counter. - increment_old_marking_cycles_started(); - _cm->gc_tracer_cm()->set_gc_cause(gc_cause()); - } - _gc_tracer_stw->report_yc_type(collector_state()->yc_type()); GCTraceCPUTime tcpu; ! G1HeapVerifier::G1VerifyType verify_type; ! FormatBuffer<> gc_string("Pause Young "); ! if (collector_state()->in_initial_mark_gc()) { ! gc_string.append("(Concurrent Start)"); ! verify_type = G1HeapVerifier::G1VerifyConcurrentStart; ! } else if (collector_state()->in_young_only_phase()) { ! if (collector_state()->in_young_gc_before_mixed()) { ! gc_string.append("(Prepare Mixed)"); ! } else { ! gc_string.append("(Normal)"); ! } ! verify_type = G1HeapVerifier::G1VerifyYoungNormal; ! } else { ! gc_string.append("(Mixed)"); ! verify_type = G1HeapVerifier::G1VerifyMixed; ! } ! GCTraceTime(Info, gc) tm(gc_string, NULL, gc_cause(), true); uint active_workers = WorkerPolicy::calc_active_workers(workers()->total_workers(), workers()->active_workers(), Threads::number_of_non_daemon_threads()); active_workers = workers()->update_active_workers(active_workers); --- 2986,3015 ---- } // We do not allow initial-mark to be piggy-backed on a mixed GC. assert(!collector_state()->in_initial_mark_gc() || collector_state()->in_young_only_phase(), "sanity"); // We also do not allow mixed GCs during marking. assert(!collector_state()->mark_or_rebuild_in_progress() || collector_state()->in_young_only_phase(), "sanity"); // Record whether this pause is an initial mark. When the current // thread has completed its logging output and it's safe to signal // the CM thread, the flag's value in the policy has been reset. bool should_start_conc_mark = collector_state()->in_initial_mark_gc(); + if (should_start_conc_mark) { + _cm->gc_tracer_cm()->set_gc_cause(gc_cause()); + } // Inner scope for scope based logging, timers, and stats collection { G1EvacuationInfo evacuation_info; _gc_tracer_stw->report_yc_type(collector_state()->yc_type()); GCTraceCPUTime tcpu; ! GCTraceTime(Info, gc) tm(young_gc_name(), NULL, gc_cause(), true); uint active_workers = WorkerPolicy::calc_active_workers(workers()->total_workers(), workers()->active_workers(), Threads::number_of_non_daemon_threads()); active_workers = workers()->update_active_workers(active_workers);
*** 2965,3096 **** collector_state()->yc_type() == Mixed /* all_memory_pools_affected */); G1HeapTransition heap_transition(this); size_t heap_used_bytes_before_gc = used(); ! // Don't dynamically change the number of GC threads this early. A value of ! // 0 is used to indicate serial work. When parallel work is done, ! // it will be set. ! ! { // Call to jvmpi::post_class_unload_events must occur outside of active GC IsGCActiveMark x; gc_prologue(false); ! if (VerifyRememberedSets) { ! log_info(gc, verify)("[Verifying RemSets before GC]"); ! VerifyRegionRemSetClosure v_cl; ! heap_region_iterate(&v_cl); ! } ! ! _verifier->verify_before_gc(verify_type); ! _verifier->check_bitmaps("GC Start"); ! ! #if COMPILER2_OR_JVMCI ! DerivedPointerTable::clear(); ! #endif // Please see comment in g1CollectedHeap.hpp and // G1CollectedHeap::ref_processing_init() to see how // reference processing currently works in G1. - - // Enable discovery in the STW reference processor _ref_processor_stw->enable_discovery(); - { // We want to temporarily turn off discovery by the // CM ref processor, if necessary, and turn it back on // on again later if we do. Using a scoped // NoRefDiscovery object will do this. NoRefDiscovery no_cm_discovery(_ref_processor_cm); - // Forget the current alloc region (we might even choose it to be part - // of the collection set!). - _allocator->release_mutator_alloc_region(); - - // This timing is only used by the ergonomics to handle our pause target. - // It is unclear why this should not include the full pause. We will - // investigate this in CR 7178365. - // - // Preserving the old comment here if that helps the investigation: - // - // The elapsed time induced by the start time below deliberately elides - // the possible verification above. - double sample_start_time_sec = os::elapsedTime(); - policy()->record_collection_pause_start(sample_start_time_sec); ! if (collector_state()->in_initial_mark_gc()) { ! concurrent_mark()->pre_initial_mark(); ! } ! ! policy()->finalize_collection_set(target_pause_time_ms, &_survivor); ! ! evacuation_info.set_collectionset_regions(collection_set()->region_length()); ! ! register_humongous_regions_with_cset(); ! ! assert(_verifier->check_cset_fast_test(), "Inconsistency in the InCSetState table."); ! ! // We call this after finalize_cset() to ! // ensure that the CSet has been finalized. ! _cm->verify_no_cset_oops(); ! if (_hr_printer.is_active()) { ! G1PrintCollectionSetClosure cl(&_hr_printer); ! _collection_set.iterate(&cl); ! } ! ! // Initialize the GC alloc regions. ! _allocator->init_gc_alloc_regions(evacuation_info); G1ParScanThreadStateSet per_thread_states(this, workers()->active_workers(), collection_set()->young_region_length(), collection_set()->optional_region_length()); ! pre_evacuate_collection_set(); // Actually do the work... evacuate_collection_set(&per_thread_states); evacuate_optional_collection_set(&per_thread_states); post_evacuate_collection_set(evacuation_info, &per_thread_states); ! const size_t* surviving_young_words = per_thread_states.surviving_young_words(); ! free_collection_set(&_collection_set, evacuation_info, surviving_young_words); ! ! eagerly_reclaim_humongous_regions(); - record_obj_copy_mem_stats(); _survivor_evac_stats.adjust_desired_plab_sz(); _old_evac_stats.adjust_desired_plab_sz(); ! double start = os::elapsedTime(); ! start_new_collection_set(); ! phase_times()->record_start_new_cset_time_ms((os::elapsedTime() - start) * 1000.0); ! ! if (evacuation_failed()) { ! double recalculate_used_start = os::elapsedTime(); ! set_used(recalculate_used()); ! phase_times()->record_evac_fail_recalc_used_time((os::elapsedTime() - recalculate_used_start) * 1000.0); ! ! if (_archive_allocator != NULL) { ! _archive_allocator->clear_used(); ! } ! for (uint i = 0; i < ParallelGCThreads; i++) { ! if (_evacuation_failed_info_array[i].has_failed()) { ! _gc_tracer_stw->report_evacuation_failed(_evacuation_failed_info_array[i]); ! } ! } ! } else { ! // The "used" of the the collection set have already been subtracted ! // when they were freed. Add in the bytes evacuated. ! increase_used(policy()->bytes_copied_during_gc()); ! } ! ! if (collector_state()->in_initial_mark_gc()) { // We have to do this before we notify the CM threads that // they can start working to make sure that all the // appropriate initialization is done on the CM object. concurrent_mark()->post_initial_mark(); // Note that we don't actually trigger the CM thread at --- 3020,3079 ---- collector_state()->yc_type() == Mixed /* all_memory_pools_affected */); G1HeapTransition heap_transition(this); size_t heap_used_bytes_before_gc = used(); ! { IsGCActiveMark x; gc_prologue(false); ! G1HeapVerifier::G1VerifyType verify_type = young_collection_verify_type(); ! verify_before_young_collection(verify_type); ! { ! // The elapsed time induced by the start time below deliberately elides ! // the possible verification above. ! double sample_start_time_sec = os::elapsedTime(); // Please see comment in g1CollectedHeap.hpp and // G1CollectedHeap::ref_processing_init() to see how // reference processing currently works in G1. _ref_processor_stw->enable_discovery(); // We want to temporarily turn off discovery by the // CM ref processor, if necessary, and turn it back on // on again later if we do. Using a scoped // NoRefDiscovery object will do this. NoRefDiscovery no_cm_discovery(_ref_processor_cm); policy()->record_collection_pause_start(sample_start_time_sec); ! // Forget the current allocation region (we might even choose it to be part ! // of the collection set!). ! _allocator->release_mutator_alloc_region(); ! calculate_collection_set(evacuation_info, target_pause_time_ms); G1ParScanThreadStateSet per_thread_states(this, workers()->active_workers(), collection_set()->young_region_length(), collection_set()->optional_region_length()); ! pre_evacuate_collection_set(evacuation_info); // Actually do the work... evacuate_collection_set(&per_thread_states); evacuate_optional_collection_set(&per_thread_states); post_evacuate_collection_set(evacuation_info, &per_thread_states); ! start_new_collection_set(); _survivor_evac_stats.adjust_desired_plab_sz(); _old_evac_stats.adjust_desired_plab_sz(); ! if (should_start_conc_mark) { // We have to do this before we notify the CM threads that // they can start working to make sure that all the // appropriate initialization is done on the CM object. concurrent_mark()->post_initial_mark(); // Note that we don't actually trigger the CM thread at
*** 3100,3152 **** allocate_dummy_regions(); _allocator->init_mutator_alloc_region(); ! { ! size_t expand_bytes = _heap_sizing_policy->expansion_amount(); ! if (expand_bytes > 0) { ! size_t bytes_before = capacity(); ! // No need for an ergo logging here, ! // expansion_amount() does this when it returns a value > 0. ! double expand_ms; ! if (!expand(expand_bytes, _workers, &expand_ms)) { ! // We failed to expand the heap. Cannot do anything about it. ! } ! phase_times()->record_expand_heap_time(expand_ms); ! } ! } - // We redo the verification but now wrt to the new CSet which - // has just got initialized after the previous CSet was freed. - _cm->verify_no_cset_oops(); - - // This timing is only used by the ergonomics to handle our pause target. - // It is unclear why this should not include the full pause. We will - // investigate this in CR 7178365. double sample_end_time_sec = os::elapsedTime(); double pause_time_ms = (sample_end_time_sec - sample_start_time_sec) * MILLIUNITS; size_t total_cards_scanned = phase_times()->sum_thread_work_items(G1GCPhaseTimes::ScanRS, G1GCPhaseTimes::ScanRSScannedCards); policy()->record_collection_pause_end(pause_time_ms, total_cards_scanned, heap_used_bytes_before_gc); - - evacuation_info.set_collectionset_used_before(collection_set()->bytes_used_before()); - evacuation_info.set_bytes_copied(policy()->bytes_copied_during_gc()); - - if (VerifyRememberedSets) { - log_info(gc, verify)("[Verifying RemSets after GC]"); - VerifyRegionRemSetClosure v_cl; - heap_region_iterate(&v_cl); } ! _verifier->verify_after_gc(verify_type); ! _verifier->check_bitmaps("GC End"); ! ! assert(!_ref_processor_stw->discovery_enabled(), "Postcondition"); ! _ref_processor_stw->verify_no_references_recorded(); ! ! // CM reference discovery will be re-enabled if necessary. ! } #ifdef TRACESPINNING ParallelTaskTerminator::print_termination_counts(); #endif --- 3083,3101 ---- allocate_dummy_regions(); _allocator->init_mutator_alloc_region(); ! expand_heap_after_young_collection(); double sample_end_time_sec = os::elapsedTime(); double pause_time_ms = (sample_end_time_sec - sample_start_time_sec) * MILLIUNITS; size_t total_cards_scanned = phase_times()->sum_thread_work_items(G1GCPhaseTimes::ScanRS, G1GCPhaseTimes::ScanRSScannedCards); policy()->record_collection_pause_end(pause_time_ms, total_cards_scanned, heap_used_bytes_before_gc); } ! verify_after_young_collection(verify_type); #ifdef TRACESPINNING ParallelTaskTerminator::print_termination_counts(); #endif
*** 3159,3173 **** } policy()->print_phases(); heap_transition.print(); - // It is not yet to safe to tell the concurrent mark to - // start as we have some optional output below. We don't want the - // output from the concurrent mark thread interfering with this - // logging output either. - _hrm->verify_optional(); _verifier->verify_region_sets_optional(); TASKQUEUE_STATS_ONLY(print_taskqueue_stats()); TASKQUEUE_STATS_ONLY(reset_taskqueue_stats()); --- 3108,3117 ----
*** 3190,3206 **** // It should now be safe to tell the concurrent mark thread to start // without its logging output interfering with the logging output // that came from the pause. if (should_start_conc_mark) { ! // CAUTION: after the doConcurrentMark() call below, ! // the concurrent marking thread(s) could be running ! // concurrently with us. Make sure that anything after ! // this point does not assume that we are the only GC thread ! // running. Note: of course, the actual marking work will ! // not start until the safepoint itself is released in ! // SuspendibleThreadSet::desynchronize(). do_concurrent_mark(); } return true; } --- 3134,3148 ---- // It should now be safe to tell the concurrent mark thread to start // without its logging output interfering with the logging output // that came from the pause. if (should_start_conc_mark) { ! // CAUTION: after the doConcurrentMark() call below, the concurrent marking ! // thread(s) could be running concurrently with us. Make sure that anything ! // after this point does not assume that we are the only GC thread running. ! // Note: of course, the actual marking work will not start until the safepoint ! // itself is released in SuspendibleThreadSet::desynchronize(). do_concurrent_mark(); } return true; }
*** 3677,3686 **** --- 3619,3629 ---- // We have completed copying any necessary live referent objects. assert(pss->queue_is_empty(), "both queue and overflow should be empty"); make_pending_list_reachable(); + assert(!rp->discovery_enabled(), "Postcondition"); rp->verify_no_references_recorded(); double ref_proc_time = os::elapsedTime() - ref_proc_start; phase_times()->record_ref_proc_time(ref_proc_time * 1000.0); }
*** 3699,3721 **** double merge_pss_time_start = os::elapsedTime(); per_thread_states->flush(); phase_times()->record_merge_pss_time_ms((os::elapsedTime() - merge_pss_time_start) * 1000.0); } ! void G1CollectedHeap::pre_evacuate_collection_set() { _expand_heap_after_alloc_failure = true; _evacuation_failed = false; // Disable the hot card cache. _hot_card_cache->reset_hot_cache_claimed_index(); _hot_card_cache->set_use_cache(false); rem_set()->prepare_for_oops_into_collection_set_do(); _preserved_marks_set.assert_empty(); // InitialMark needs claim bits to keep track of the marked-through CLDs. if (collector_state()->in_initial_mark_gc()) { double start_clear_claimed_marks = os::elapsedTime(); ClassLoaderDataGraph::clear_claimed_marks(); double recorded_clear_claimed_marks_time_ms = (os::elapsedTime() - start_clear_claimed_marks) * 1000.0; --- 3642,3676 ---- double merge_pss_time_start = os::elapsedTime(); per_thread_states->flush(); phase_times()->record_merge_pss_time_ms((os::elapsedTime() - merge_pss_time_start) * 1000.0); } ! void G1CollectedHeap::pre_evacuate_collection_set(G1EvacuationInfo& evacuation_info) { _expand_heap_after_alloc_failure = true; _evacuation_failed = false; // Disable the hot card cache. _hot_card_cache->reset_hot_cache_claimed_index(); _hot_card_cache->set_use_cache(false); + // Initialize the GC alloc regions. + _allocator->init_gc_alloc_regions(evacuation_info); + + register_humongous_regions_with_cset(); + assert(_verifier->check_cset_fast_test(), "Inconsistency in the InCSetState table."); + rem_set()->prepare_for_oops_into_collection_set_do(); _preserved_marks_set.assert_empty(); + #if COMPILER2_OR_JVMCI + DerivedPointerTable::clear(); + #endif + // InitialMark needs claim bits to keep track of the marked-through CLDs. if (collector_state()->in_initial_mark_gc()) { + concurrent_mark()->pre_initial_mark(); + double start_clear_claimed_marks = os::elapsedTime(); ClassLoaderDataGraph::clear_claimed_marks(); double recorded_clear_claimed_marks_time_ms = (os::elapsedTime() - start_clear_claimed_marks) * 1000.0;
*** 3918,3940 **** double string_cleanup_time_ms = (os::elapsedTime() - string_dedup_time_ms) * 1000.0; phase_times()->record_string_deduplication_time(string_cleanup_time_ms); } if (evacuation_failed()) { restore_after_evac_failure(); // Reset the G1EvacuationFailureALot counters and flags - // Note: the values are reset only when an actual - // evacuation failure occurs. NOT_PRODUCT(reset_evacuation_should_fail();) } _preserved_marks_set.assert_empty(); - _allocator->release_gc_alloc_regions(evacuation_info); - merge_per_thread_state_info(per_thread_states); // Reset and re-enable the hot card cache. // Note the counts for the cards in the regions in the // collection set are reset when the collection set is freed. --- 3873,3910 ---- double string_cleanup_time_ms = (os::elapsedTime() - string_dedup_time_ms) * 1000.0; phase_times()->record_string_deduplication_time(string_cleanup_time_ms); } + _allocator->release_gc_alloc_regions(evacuation_info); + if (evacuation_failed()) { restore_after_evac_failure(); // Reset the G1EvacuationFailureALot counters and flags NOT_PRODUCT(reset_evacuation_should_fail();) + + double recalculate_used_start = os::elapsedTime(); + set_used(recalculate_used()); + phase_times()->record_evac_fail_recalc_used_time((os::elapsedTime() - recalculate_used_start) * 1000.0); + + if (_archive_allocator != NULL) { + _archive_allocator->clear_used(); + } + for (uint i = 0; i < ParallelGCThreads; i++) { + if (_evacuation_failed_info_array[i].has_failed()) { + _gc_tracer_stw->report_evacuation_failed(_evacuation_failed_info_array[i]); + } + } + } else { + // The "used" of the the collection set have already been subtracted + // when they were freed. Add in the bytes evacuated. + increase_used(policy()->bytes_copied_during_gc()); } _preserved_marks_set.assert_empty(); merge_per_thread_state_info(per_thread_states); // Reset and re-enable the hot card cache. // Note the counts for the cards in the regions in the // collection set are reset when the collection set is freed.
*** 3942,3951 **** --- 3912,3931 ---- _hot_card_cache->set_use_cache(true); purge_code_root_memory(); redirty_logged_cards(); + + free_collection_set(&_collection_set, evacuation_info, per_thread_states->surviving_young_words()); + + eagerly_reclaim_humongous_regions(); + + record_obj_copy_mem_stats(); + + evacuation_info.set_collectionset_used_before(collection_set()->bytes_used_before()); + evacuation_info.set_bytes_copied(policy()->bytes_copied_during_gc()); + #if COMPILER2_OR_JVMCI double start = os::elapsedTime(); DerivedPointerTable::update_pointers(); phase_times()->record_derived_pointer_table_update_time((os::elapsedTime() - start) * 1000.0); #endif
< prev index next >