ConcurrentG1Refine::ConcurrentG1Refine(G1CollectedHeap* g1h, CardTableEntryClosure* refine_closure) :
  _threads(NULL), _n_threads(0),
  _hot_card_cache(g1h)
{
  // Ergomonically select initial concurrent refinement parameters
  if (FLAG_IS_DEFAULT(G1ConcRefinementGreenZone)) {
    FLAG_SET_DEFAULT(G1ConcRefinementGreenZone, MAX2<int>(ParallelGCThreads, 1));
  }
  set_green_zone(G1ConcRefinementGreenZone);

  if (FLAG_IS_DEFAULT(G1ConcRefinementYellowZone)) {
    FLAG_SET_DEFAULT(G1ConcRefinementYellowZone, green_zone() * 3);
  }
  set_yellow_zone(MAX2<int>(G1ConcRefinementYellowZone, green_zone()));

  if (FLAG_IS_DEFAULT(G1ConcRefinementRedZone)) {
    FLAG_SET_DEFAULT(G1ConcRefinementRedZone, yellow_zone() * 2);
  }
  set_red_zone(MAX2<int>(G1ConcRefinementRedZone, yellow_zone()));

  _n_worker_threads = thread_num();
  // We need one extra thread to do the young gen rset size sampling.
  _n_threads = _n_worker_threads + 1;

  reset_threshold_step();

  _threads = NEW_C_HEAP_ARRAY(ConcurrentG1RefineThread*, _n_threads, mtGC);

  uint worker_id_offset = DirtyCardQueueSet::num_par_ids();

  ConcurrentG1RefineThread *next = NULL;
  for (uint i = _n_threads - 1; i != UINT_MAX; i--) {
    ConcurrentG1RefineThread* t = new ConcurrentG1RefineThread(this, next, refine_closure, worker_id_offset, i);
    assert(t != NULL, "Conc refine should have been created");
    if (t->osthread() == NULL) {
        vm_shutdown_during_initialization("Could not create ConcurrentG1RefineThread");
    }

    assert(t->cg1r() == this, "Conc refine thread should refer to this");
    _threads[i] = t;
    next = t;
  }
}
Пример #2
0
jint ParallelScavengeHeap::initialize() {
  CollectedHeap::pre_initialize();

  // Cannot be initialized until after the flags are parsed
  // GenerationSizer flag_parser;
  _collector_policy = new GenerationSizer();

  size_t yg_min_size = _collector_policy->min_young_gen_size();
  size_t yg_max_size = _collector_policy->max_young_gen_size();
  size_t og_min_size = _collector_policy->min_old_gen_size();
  size_t og_max_size = _collector_policy->max_old_gen_size();
  // Why isn't there a min_perm_gen_size()?
  size_t pg_min_size = _collector_policy->perm_gen_size();
  size_t pg_max_size = _collector_policy->max_perm_gen_size();

  trace_gen_sizes("ps heap raw",
                  pg_min_size, pg_max_size,
                  og_min_size, og_max_size,
                  yg_min_size, yg_max_size);

  // The ReservedSpace ctor used below requires that the page size for the perm
  // gen is <= the page size for the rest of the heap (young + old gens).
  const size_t og_page_sz = os::page_size_for_region(yg_min_size + og_min_size,
                                                     yg_max_size + og_max_size,
                                                     8);
  const size_t pg_page_sz = MIN2(os::page_size_for_region(pg_min_size,
                                                          pg_max_size, 16),
                                 og_page_sz);

  const size_t pg_align = set_alignment(_perm_gen_alignment,  pg_page_sz);
  const size_t og_align = set_alignment(_old_gen_alignment,   og_page_sz);
  const size_t yg_align = set_alignment(_young_gen_alignment, og_page_sz);

  // Update sizes to reflect the selected page size(s).
  //
  // NEEDS_CLEANUP.  The default TwoGenerationCollectorPolicy uses NewRatio; it
  // should check UseAdaptiveSizePolicy.  Changes from generationSizer could
  // move to the common code.
  yg_min_size = align_size_up(yg_min_size, yg_align);
  yg_max_size = align_size_up(yg_max_size, yg_align);
  size_t yg_cur_size =
    align_size_up(_collector_policy->young_gen_size(), yg_align);
  yg_cur_size = MAX2(yg_cur_size, yg_min_size);

  og_min_size = align_size_up(og_min_size, og_align);
  og_max_size = align_size_up(og_max_size, og_align);
  size_t og_cur_size =
    align_size_up(_collector_policy->old_gen_size(), og_align);
  og_cur_size = MAX2(og_cur_size, og_min_size);

  pg_min_size = align_size_up(pg_min_size, pg_align);
  pg_max_size = align_size_up(pg_max_size, pg_align);
  size_t pg_cur_size = pg_min_size;

  trace_gen_sizes("ps heap rnd",
                  pg_min_size, pg_max_size,
                  og_min_size, og_max_size,
                  yg_min_size, yg_max_size);

  const size_t total_reserved = pg_max_size + og_max_size + yg_max_size;
  char* addr = Universe::preferred_heap_base(total_reserved, Universe::UnscaledNarrowOop);

  // The main part of the heap (old gen + young gen) can often use a larger page
  // size than is needed or wanted for the perm gen.  Use the "compound
  // alignment" ReservedSpace ctor to avoid having to use the same page size for
  // all gens.

  ReservedHeapSpace heap_rs(pg_max_size, pg_align, og_max_size + yg_max_size,
                            og_align, addr);

  if (UseCompressedOops) {
    if (addr != NULL && !heap_rs.is_reserved()) {
      // Failed to reserve at specified address - the requested memory
      // region is taken already, for example, by 'java' launcher.
      // Try again to reserver heap higher.
      addr = Universe::preferred_heap_base(total_reserved, Universe::ZeroBasedNarrowOop);
      ReservedHeapSpace heap_rs0(pg_max_size, pg_align, og_max_size + yg_max_size,
                                 og_align, addr);
      if (addr != NULL && !heap_rs0.is_reserved()) {
        // Failed to reserve at specified address again - give up.
        addr = Universe::preferred_heap_base(total_reserved, Universe::HeapBasedNarrowOop);
        assert(addr == NULL, "");
        ReservedHeapSpace heap_rs1(pg_max_size, pg_align, og_max_size + yg_max_size,
                                   og_align, addr);
        heap_rs = heap_rs1;
      } else {
        heap_rs = heap_rs0;
      }
    }
  }

  os::trace_page_sizes("ps perm", pg_min_size, pg_max_size, pg_page_sz,
                       heap_rs.base(), pg_max_size);
  os::trace_page_sizes("ps main", og_min_size + yg_min_size,
                       og_max_size + yg_max_size, og_page_sz,
                       heap_rs.base() + pg_max_size,
                       heap_rs.size() - pg_max_size);
  if (!heap_rs.is_reserved()) {
    vm_shutdown_during_initialization(
      "Could not reserve enough space for object heap");
    return JNI_ENOMEM;
  }

  _reserved = MemRegion((HeapWord*)heap_rs.base(),
                        (HeapWord*)(heap_rs.base() + heap_rs.size()));

  CardTableExtension* const barrier_set = new CardTableExtension(_reserved, 3);
  _barrier_set = barrier_set;
  oopDesc::set_bs(_barrier_set);
  if (_barrier_set == NULL) {
    vm_shutdown_during_initialization(
      "Could not reserve enough space for barrier set");
    return JNI_ENOMEM;
  }

  // Initial young gen size is 4 Mb
  //
  // XXX - what about flag_parser.young_gen_size()?
  const size_t init_young_size = align_size_up(4 * M, yg_align);
  yg_cur_size = MAX2(MIN2(init_young_size, yg_max_size), yg_cur_size);

  // Split the reserved space into perm gen and the main heap (everything else).
  // The main heap uses a different alignment.
  ReservedSpace perm_rs = heap_rs.first_part(pg_max_size);
  ReservedSpace main_rs = heap_rs.last_part(pg_max_size, og_align);

  // Make up the generations
  // Calculate the maximum size that a generation can grow.  This
  // includes growth into the other generation.  Note that the
  // parameter _max_gen_size is kept as the maximum
  // size of the generation as the boundaries currently stand.
  // _max_gen_size is still used as that value.
  double max_gc_pause_sec = ((double) MaxGCPauseMillis)/1000.0;
  double max_gc_minor_pause_sec = ((double) MaxGCMinorPauseMillis)/1000.0;

  _gens = new AdjoiningGenerations(main_rs,
                                   og_cur_size,
                                   og_min_size,
                                   og_max_size,
                                   yg_cur_size,
                                   yg_min_size,
                                   yg_max_size,
                                   yg_align);

  _old_gen = _gens->old_gen();
  _young_gen = _gens->young_gen();

  const size_t eden_capacity = _young_gen->eden_space()->capacity_in_bytes();
  const size_t old_capacity = _old_gen->capacity_in_bytes();
  const size_t initial_promo_size = MIN2(eden_capacity, old_capacity);
  _size_policy =
    new PSAdaptiveSizePolicy(eden_capacity,
                             initial_promo_size,
                             young_gen()->to_space()->capacity_in_bytes(),
                             intra_heap_alignment(),
                             max_gc_pause_sec,
                             max_gc_minor_pause_sec,
                             GCTimeRatio
                             );

  _perm_gen = new PSPermGen(perm_rs,
                            pg_align,
                            pg_cur_size,
                            pg_cur_size,
                            pg_max_size,
                            "perm", 2);

  assert(!UseAdaptiveGCBoundary ||
    (old_gen()->virtual_space()->high_boundary() ==
     young_gen()->virtual_space()->low_boundary()),
    "Boundaries must meet");
  // initialize the policy counters - 2 collectors, 3 generations
  _gc_policy_counters =
    new PSGCAdaptivePolicyCounters("ParScav:MSC", 2, 3, _size_policy);
  _psh = this;

  // Set up the GCTaskManager
  _gc_task_manager = GCTaskManager::create(ParallelGCThreads);

  if (UseParallelOldGC && !PSParallelCompact::initialize()) {
    return JNI_ENOMEM;
  }

  return JNI_OK;
}
Пример #3
0
ConcurrentG1Refine* ConcurrentG1Refine::create(CardTableEntryClosure* refine_closure,
                                               jint* ecode) {
  size_t min_yellow_zone_size = calc_min_yellow_zone_size();
  size_t green_zone = calc_init_green_zone();
  size_t yellow_zone = calc_init_yellow_zone(green_zone, min_yellow_zone_size);
  size_t red_zone = calc_init_red_zone(green_zone, yellow_zone);

  LOG_ZONES("Initial Refinement Zones: "
            "green: " SIZE_FORMAT ", "
            "yellow: " SIZE_FORMAT ", "
            "red: " SIZE_FORMAT ", "
            "min yellow size: " SIZE_FORMAT,
            green_zone, yellow_zone, red_zone, min_yellow_zone_size);

  ConcurrentG1Refine* cg1r = new ConcurrentG1Refine(green_zone,
                                                    yellow_zone,
                                                    red_zone,
                                                    min_yellow_zone_size);

  if (cg1r == NULL) {
    *ecode = JNI_ENOMEM;
    vm_shutdown_during_initialization("Could not create ConcurrentG1Refine");
    return NULL;
  }

  cg1r->_threads = NEW_C_HEAP_ARRAY_RETURN_NULL(ConcurrentG1RefineThread*, cg1r->_n_worker_threads, mtGC);
  if (cg1r->_threads == NULL) {
    *ecode = JNI_ENOMEM;
    vm_shutdown_during_initialization("Could not allocate an array for ConcurrentG1RefineThread");
    return NULL;
  }

  uint worker_id_offset = DirtyCardQueueSet::num_par_ids();

  ConcurrentG1RefineThread *next = NULL;
  for (uint i = cg1r->_n_worker_threads - 1; i != UINT_MAX; i--) {
    Thresholds thresholds = calc_thresholds(green_zone, yellow_zone, i);
    ConcurrentG1RefineThread* t =
      new ConcurrentG1RefineThread(cg1r,
                                   next,
                                   refine_closure,
                                   worker_id_offset,
                                   i,
                                   activation_level(thresholds),
                                   deactivation_level(thresholds));
    assert(t != NULL, "Conc refine should have been created");
    if (t->osthread() == NULL) {
      *ecode = JNI_ENOMEM;
      vm_shutdown_during_initialization("Could not create ConcurrentG1RefineThread");
      return NULL;
    }

    assert(t->cg1r() == cg1r, "Conc refine thread should refer to this");
    cg1r->_threads[i] = t;
    next = t;
  }

  cg1r->_sample_thread = new G1YoungRemSetSamplingThread();
  if (cg1r->_sample_thread->osthread() == NULL) {
    *ecode = JNI_ENOMEM;
    vm_shutdown_during_initialization("Could not create G1YoungRemSetSamplingThread");
    return NULL;
  }

  *ecode = JNI_OK;
  return cg1r;
}
jint ParallelScavengeHeap::initialize() {
  CollectedHeap::pre_initialize();

  // Initialize collector policy
  _collector_policy = new GenerationSizer();
  _collector_policy->initialize_all();

  const size_t heap_size = _collector_policy->max_heap_byte_size();

  ReservedSpace heap_rs = Universe::reserve_heap(heap_size, _collector_policy->heap_alignment());
  MemTracker::record_virtual_memory_type((address)heap_rs.base(), mtJavaHeap);

  os::trace_page_sizes("ps main", _collector_policy->min_heap_byte_size(),
                       heap_size, generation_alignment(),
                       heap_rs.base(),
                       heap_rs.size());
  if (!heap_rs.is_reserved()) {
    vm_shutdown_during_initialization(
      "Could not reserve enough space for object heap");
    return JNI_ENOMEM;
  }

  _reserved = MemRegion((HeapWord*)heap_rs.base(),
                        (HeapWord*)(heap_rs.base() + heap_rs.size()));

  CardTableExtension* const barrier_set = new CardTableExtension(_reserved, 3);
  _barrier_set = barrier_set;
  oopDesc::set_bs(_barrier_set);
  if (_barrier_set == NULL) {
    vm_shutdown_during_initialization(
      "Could not reserve enough space for barrier set");
    return JNI_ENOMEM;
  }

  // Make up the generations
  // Calculate the maximum size that a generation can grow.  This
  // includes growth into the other generation.  Note that the
  // parameter _max_gen_size is kept as the maximum
  // size of the generation as the boundaries currently stand.
  // _max_gen_size is still used as that value.
  double max_gc_pause_sec = ((double) MaxGCPauseMillis)/1000.0;
  double max_gc_minor_pause_sec = ((double) MaxGCMinorPauseMillis)/1000.0;

  _gens = new AdjoiningGenerations(heap_rs, _collector_policy, generation_alignment());

  _old_gen = _gens->old_gen();
  _young_gen = _gens->young_gen();

  const size_t eden_capacity = _young_gen->eden_space()->capacity_in_bytes();
  const size_t old_capacity = _old_gen->capacity_in_bytes();
  const size_t initial_promo_size = MIN2(eden_capacity, old_capacity);
  _size_policy =
    new PSAdaptiveSizePolicy(eden_capacity,
                             initial_promo_size,
                             young_gen()->to_space()->capacity_in_bytes(),
                             _collector_policy->gen_alignment(),
                             max_gc_pause_sec,
                             max_gc_minor_pause_sec,
                             GCTimeRatio
                             );

  assert(!UseAdaptiveGCBoundary ||
    (old_gen()->virtual_space()->high_boundary() ==
     young_gen()->virtual_space()->low_boundary()),
    "Boundaries must meet");
  // initialize the policy counters - 2 collectors, 3 generations
  _gc_policy_counters =
    new PSGCAdaptivePolicyCounters("ParScav:MSC", 2, 3, _size_policy);
  _psh = this;

  // Set up the GCTaskManager
  _gc_task_manager = GCTaskManager::create(ParallelGCThreads);

  if (UseParallelOldGC && !PSParallelCompact::initialize()) {
    return JNI_ENOMEM;
  }

  return JNI_OK;
}
jint ParallelScavengeHeap::initialize() {
  // Cannot be initialized until after the flags are parsed
  GenerationSizer flag_parser;

  size_t max_young_size = flag_parser.max_young_gen_size();
  size_t max_old_size = flag_parser.max_old_gen_size();
  if (UseMPSS && max_young_size + max_old_size >= LargePageHeapSizeThreshold) {
    set_generation_alignment(LargePageSizeInBytes);
  }
  const size_t alignment = generation_alignment();

  // Check alignments
// NEEDS_CLEANUP   The default TwoGenerationCollectorPolicy uses
//   NewRatio;  it should check UseAdaptiveSizePolicy. Changes from
//   generationSizer could move to the common code.
  size_t min_young_size = 
    align_size_up(flag_parser.min_young_gen_size(), alignment);
  size_t young_size = align_size_up(flag_parser.young_gen_size(), alignment);
  max_young_size = align_size_up(max_young_size, alignment);

  size_t min_old_size = 
    align_size_up(flag_parser.min_old_gen_size(), alignment);
  size_t old_size = align_size_up(flag_parser.old_gen_size(), alignment);
  old_size = MAX2(old_size, min_old_size);
  max_old_size = align_size_up(max_old_size, alignment);

  size_t perm_size = align_size_up(flag_parser.perm_gen_size(), alignment);
  size_t max_perm_size = align_size_up(flag_parser.max_perm_gen_size(), 
                                                                  alignment);

  // Calculate the total size.
  size_t total_reserved = max_young_size + max_old_size + max_perm_size;

  if (UseISM || UsePermISM) {
    total_reserved = round_to(total_reserved, LargePageSizeInBytes);
  }

  ReservedSpace heap_rs(total_reserved, alignment, UseISM || UsePermISM);
  if (!heap_rs.is_reserved()) {
    vm_shutdown_during_initialization(
      "Could not reserve enough space for object heap");
    return JNI_ENOMEM;
  }

  _reserved_byte_size = heap_rs.size();
  _reserved = MemRegion((HeapWord*)heap_rs.base(),
			(HeapWord*)(heap_rs.base() + heap_rs.size()));

  HeapWord* boundary = (HeapWord*)(heap_rs.base() + max_young_size);
  CardTableExtension* card_table_barrier_set = new CardTableExtension(_reserved, 3);
  _barrier_set = card_table_barrier_set;

  oopDesc::set_bs(_barrier_set);
  if (_barrier_set == NULL) {
    vm_shutdown_during_initialization(
      "Could not reserve enough space for barrier set"); 
    return JNI_ENOMEM;
  }

  // Initial young gen size is 4 Mb
  size_t init_young_size = align_size_up(4 * M, alignment);
  init_young_size = MAX2(MIN2(init_young_size, max_young_size), young_size);

  // Divide up the reserved space: perm, old, young
  ReservedSpace perm_rs  = heap_rs.first_part(max_perm_size);
  ReservedSpace old_young_rs                
			 = heap_rs.last_part(max_perm_size);
  ReservedSpace old_rs   = old_young_rs.first_part(max_old_size);
  heap_rs                = old_young_rs.last_part(max_old_size);
  ReservedSpace young_rs = heap_rs.first_part(max_young_size);
  assert(young_rs.size() == heap_rs.size(), "Didn't reserve all of the heap");

  // Make up the generations
  // Calculate the maximum size that a generation can grow.  This
  // includes growth into the other generation.  Note that the
  // parameter _max_gen_size is kept as the maximum 
  // size of the generation as the boundaries currently stand.
  // _max_gen_size is still used as that value.
  double max_gc_pause_sec = ((double) MaxGCPauseMillis)/1000.0;
  double max_gc_minor_pause_sec = ((double) MaxGCMinorPauseMillis)/1000.0;

// Regarding SEPARATE_PATHS.  If SEPARATE_PATHS is defined, then
// the generations are created without the use of AdjoiningGenerations
// in the case where boundary moving is not an option.  This is
// being kept until the code review in case there is some desire
// to keep the new code out of the path of the previous code.
// One effect of using AdjoiningGenerations for both cases is that
// is that the generations in AdjoiningGenerations need to be
// PSOldGen and PSYoungGen as opposed to ASPSOldGen and ASPSYoungGen.
// This latter means that methods such as available_for_expansion()
// need to be defined in PSOldGen.

#undef SEPARATE_PATHS
#ifdef SEPARATE_PATHS
  if (UseAdaptiveSizePolicy && UseAdaptiveGCBoundary) {
#endif
    _gens = new AdjoiningGenerations(old_young_rs,
    				     old_size,
		                     min_old_size,
		                     max_old_size,
		                     init_young_size,
		                     min_young_size,
		                     max_young_size,
				     alignment);

    _old_gen = _gens->old_gen();
    _young_gen = _gens->young_gen();

    _size_policy =
      new PSAdaptiveSizePolicy(young_gen()->eden_space()->capacity_in_bytes(),
			       old_gen()->capacity_in_bytes(),
			       young_gen()->to_space()->capacity_in_bytes(),
			       generation_alignment(),
			       intra_generation_alignment(),
			       max_gc_pause_sec,
			       max_gc_minor_pause_sec,
			       GCTimeRatio
			       );

#ifdef SEPARATE_PATHS
  } else {
    // Same as for case where boundary does not move.
    size_t old_size_limit, young_size_limit;
    old_size_limit = max_old_size;
    young_size_limit = max_young_size;

    _young_gen = new PSYoungGen(init_young_size,
                              min_young_size,
                              max_young_size);
    _old_gen = new PSOldGen(old_size,
                          min_old_size,
                          max_old_size,
                          "old", 1);
    _gens = 0;
    _young_gen->initialize(young_rs, alignment);
    _old_gen->initialize(old_rs, alignment, "old", 1);

    _size_policy = 
      new PSAdaptiveSizePolicy(young_gen()->eden_space()->capacity_in_bytes(),
                               old_gen()->capacity_in_bytes(),
                               young_gen()->to_space()->capacity_in_bytes(),
                               generation_alignment(),
			       intra_generation_alignment(),
			       max_gc_pause_sec,
			       max_gc_minor_pause_sec,
			       GCTimeRatio
			       );
  }
#endif

  _perm_gen = new PSPermGen(perm_rs,
			    alignment,
                            perm_size,
                            perm_size,
                            max_perm_size,
                            "perm", 2);

  assert(!UseAdaptiveGCBoundary ||
    (old_gen()->virtual_space()->high_boundary() == 
     young_gen()->virtual_space()->low_boundary()),
    "Boundaries must meet");
  // initialize the policy counters - 2 collectors, 3 generations
  _gc_policy_counters = 
    new PSGCAdaptivePolicyCounters("ParScav:MSC", 2, 3, _size_policy);
  _psh = this;

  return JNI_OK;
}