1 /*
   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.
   4  *
   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
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #include "precompiled.hpp"
  26 #include "memory/compactPermGen.hpp"
  27 #include "memory/defNewGeneration.hpp"
  28 #include "memory/filemap.hpp"
  29 #include "memory/genRemSet.hpp"
  30 #include "memory/generationSpec.hpp"
  31 #include "memory/tenuredGeneration.hpp"
  32 #include "runtime/java.hpp"
  33 #ifndef SERIALGC
  34 #include "gc_implementation/concurrentMarkSweep/cmsPermGen.hpp"
  35 #include "gc_implementation/parNew/asParNewGeneration.hpp"
  36 #include "gc_implementation/parNew/parNewGeneration.hpp"
  37 #endif
  38 
  39 Generation* GenerationSpec::init(ReservedSpace rs, int level,
  40                                  GenRemSet* remset) {
  41   switch (name()) {
  42     case Generation::DefNew:
  43       return new DefNewGeneration(rs, init_size(), level);
  44 
  45     case Generation::MarkSweepCompact:
  46       return new TenuredGeneration(rs, init_size(), level, remset);
  47 
  48 #ifndef SERIALGC
  49     case Generation::ParNew:
  50       return new ParNewGeneration(rs, init_size(), level);
  51 
  52     case Generation::ASParNew:
  53       return new ASParNewGeneration(rs,
  54                                     init_size(),
  55                                     init_size() /* min size */,
  56                                     level);
  57 
  58     case Generation::ConcurrentMarkSweep: {
  59       assert(UseConcMarkSweepGC, "UseConcMarkSweepGC should be set");
  60       CardTableRS* ctrs = remset->as_CardTableRS();
  61       if (ctrs == NULL) {
  62         vm_exit_during_initialization("Rem set incompatibility.");
  63       }
  64       // Otherwise
  65       // The constructor creates the CMSCollector if needed,
  66       // else registers with an existing CMSCollector
  67 
  68       ConcurrentMarkSweepGeneration* g = NULL;
  69       g = new ConcurrentMarkSweepGeneration(rs,
  70                  init_size(), level, ctrs, UseCMSAdaptiveFreeLists,
  71                  (FreeBlockDictionary::DictionaryChoice)CMSDictionaryChoice);
  72 
  73       g->initialize_performance_counters();
  74 
  75       return g;
  76     }
  77 
  78     case Generation::ASConcurrentMarkSweep: {
  79       assert(UseConcMarkSweepGC, "UseConcMarkSweepGC should be set");
  80       CardTableRS* ctrs = remset->as_CardTableRS();
  81       if (ctrs == NULL) {
  82         vm_exit_during_initialization("Rem set incompatibility.");
  83       }
  84       // Otherwise
  85       // The constructor creates the CMSCollector if needed,
  86       // else registers with an existing CMSCollector
  87 
  88       ASConcurrentMarkSweepGeneration* g = NULL;
  89       g = new ASConcurrentMarkSweepGeneration(rs,
  90                  init_size(), level, ctrs, UseCMSAdaptiveFreeLists,
  91                  (FreeBlockDictionary::DictionaryChoice)CMSDictionaryChoice);
  92 
  93       g->initialize_performance_counters();
  94 
  95       return g;
  96     }
  97 #endif // SERIALGC
  98 
  99     default:
 100       guarantee(false, "unrecognized GenerationName");
 101       return NULL;
 102   }
 103 }
 104 
 105 
 106 PermanentGenerationSpec::PermanentGenerationSpec(PermGen::Name name,
 107                       size_t init_size, size_t max_size,
 108                       size_t read_only_size, size_t read_write_size,
 109                       size_t misc_data_size, size_t misc_code_size) {
 110   _name = name;
 111   _init_size = init_size;
 112 
 113   if (UseSharedSpaces || DumpSharedSpaces) {
 114     _enable_shared_spaces = true;
 115     if (UseSharedSpaces) {
 116       // Override shared space sizes from those in the file.
 117       FileMapInfo* mapinfo = FileMapInfo::current_info();
 118       _read_only_size = mapinfo->space_capacity(CompactingPermGenGen::ro);
 119       _read_write_size = mapinfo->space_capacity(CompactingPermGenGen::rw);
 120       _misc_data_size = mapinfo->space_capacity(CompactingPermGenGen::md);
 121       _misc_code_size = mapinfo->space_capacity(CompactingPermGenGen::mc);
 122     } else {
 123       _read_only_size = read_only_size;
 124       _read_write_size = read_write_size;
 125       _misc_data_size = misc_data_size;
 126       _misc_code_size = misc_code_size;
 127     }
 128   } else {
 129     _enable_shared_spaces = false;
 130     _read_only_size = 0;
 131     _read_write_size = 0;
 132     _misc_data_size = 0;
 133     _misc_code_size = 0;
 134   }
 135 
 136   _max_size = max_size;
 137 }
 138 
 139 
 140 PermGen* PermanentGenerationSpec::init(ReservedSpace rs,
 141                                        size_t init_size,
 142                                        GenRemSet *remset) {
 143 
 144   // Break the reserved spaces into pieces for the permanent space
 145   // and the shared spaces.
 146   ReservedSpace perm_rs = rs.first_part(_max_size, UseSharedSpaces,
 147                                         UseSharedSpaces);
 148   ReservedSpace shared_rs = rs.last_part(_max_size);
 149 
 150   if (enable_shared_spaces()) {
 151     if (!perm_rs.is_reserved() ||
 152         perm_rs.base() + perm_rs.size() != shared_rs.base()) {
 153       FileMapInfo* mapinfo = FileMapInfo::current_info();
 154       mapinfo->fail_continue("Sharing disabled - unable to "
 155                                  "reserve address space.");
 156       shared_rs.release();
 157       disable_sharing();
 158     }
 159   }
 160 
 161   switch (name()) {
 162     case PermGen::MarkSweepCompact:
 163       return new CompactingPermGen(perm_rs, shared_rs, init_size, remset, this);
 164 
 165 #ifndef SERIALGC
 166     case PermGen::MarkSweep:
 167       guarantee(false, "NYI");
 168       return NULL;
 169 
 170     case PermGen::ConcurrentMarkSweep: {
 171       assert(UseConcMarkSweepGC, "UseConcMarkSweepGC should be set");
 172       CardTableRS* ctrs = remset->as_CardTableRS();
 173       if (ctrs == NULL) {
 174         vm_exit_during_initialization("RemSet/generation incompatibility.");
 175       }
 176       // XXXPERM
 177       return new CMSPermGen(perm_rs, init_size, ctrs,
 178                    (FreeBlockDictionary::DictionaryChoice)CMSDictionaryChoice);
 179     }
 180 #endif // SERIALGC
 181     default:
 182       guarantee(false, "unrecognized GenerationName");
 183       return NULL;
 184   }
 185 }
 186 
 187 
 188 // Alignment
 189 void PermanentGenerationSpec::align(size_t alignment) {
 190   _init_size       = align_size_up(_init_size,       alignment);
 191   _max_size        = align_size_up(_max_size,        alignment);
 192   _read_only_size  = align_size_up(_read_only_size,  alignment);
 193   _read_write_size = align_size_up(_read_write_size, alignment);
 194   _misc_data_size  = align_size_up(_misc_data_size,  alignment);
 195   _misc_code_size  = align_size_up(_misc_code_size,  alignment);
 196 
 197   assert(enable_shared_spaces() || (_read_only_size + _read_write_size == 0),
 198          "Shared space when disabled?");
 199 }