changeset 5685:438fe38c63c8

Merge
author mgronlun
date Fri, 15 Nov 2013 21:39:27 +0100
parents 5280822ddfcd 854a42db7069
children d61a1a166f44
files src/share/vm/runtime/globals.hpp
diffstat 63 files changed, 1644 insertions(+), 765 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Thu Nov 14 20:03:15 2013 +0100
+++ b/.hgtags	Fri Nov 15 21:39:27 2013 +0100
@@ -393,3 +393,5 @@
 3b32d287da89a47a45d16f6d9ba5bd3cd9bf4b3e hs25-b57
 9ebaac78a8a0061fb9597e07f806498cb626cdeb jdk8-b115
 e510dfdec6dd701410f3398ed86ebcdff0cca63a hs25-b58
+52b076e6ffae247c1c7d8b7aba995195be2b6fc2 jdk8-b116
+c78d517c7ea47501b456e707afd4b78e7b5b202e hs25-b59
--- a/make/hotspot_version	Thu Nov 14 20:03:15 2013 +0100
+++ b/make/hotspot_version	Fri Nov 15 21:39:27 2013 +0100
@@ -35,7 +35,7 @@
 
 HS_MAJOR_VER=25
 HS_MINOR_VER=0
-HS_BUILD_NUMBER=59
+HS_BUILD_NUMBER=60
 
 JDK_MAJOR_VER=1
 JDK_MINOR_VER=8
--- a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Fri Nov 15 21:39:27 2013 +0100
@@ -1002,18 +1002,6 @@
   // and the vm will find there should this case occur.
   Address callee_target_addr(G2_thread, JavaThread::callee_target_offset());
   __ st_ptr(G5_method, callee_target_addr);
-
-  if (StressNonEntrant) {
-    // Open a big window for deopt failure
-    __ save_frame(0);
-    __ mov(G0, L0);
-    Label loop;
-    __ bind(loop);
-    __ sub(L0, 1, L0);
-    __ br_null_short(L0, Assembler::pt, loop);
-    __ restore();
-  }
-
   __ jmpl(G3, 0, G0);
   __ delayed()->nop();
 }
--- a/src/share/vm/c1/c1_GraphBuilder.cpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/c1/c1_GraphBuilder.cpp	Fri Nov 15 21:39:27 2013 +0100
@@ -4338,6 +4338,11 @@
 #endif // PRODUCT
 
 void GraphBuilder::profile_call(ciMethod* callee, Value recv, ciKlass* known_holder, Values* obj_args, bool inlined) {
+  // A default method's holder is an interface
+  if (known_holder != NULL && known_holder->is_interface()) {
+    assert(known_holder->is_instance_klass() && ((ciInstanceKlass*)known_holder)->has_default_methods(), "should be default method");
+    known_holder = NULL;
+  }
   append(new ProfileCall(method(), bci(), callee, recv, known_holder, obj_args, inlined));
 }
 
--- a/src/share/vm/c1/c1_LIRGenerator.cpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/c1/c1_LIRGenerator.cpp	Fri Nov 15 21:39:27 2013 +0100
@@ -2574,8 +2574,25 @@
   __ jump(x->default_sux());
 }
 
-
-ciKlass* LIRGenerator::profile_arg_type(ciMethodData* md, int md_base_offset, int md_offset, intptr_t profiled_k, Value arg, LIR_Opr& mdp, bool not_null, ciKlass* signature_k) {
+/**
+ * Emit profiling code if needed for arguments, parameters, return value types
+ *
+ * @param md                    MDO the code will update at runtime
+ * @param md_base_offset        common offset in the MDO for this profile and subsequent ones
+ * @param md_offset             offset in the MDO (on top of md_base_offset) for this profile
+ * @param profiled_k            current profile
+ * @param obj                   IR node for the object to be profiled
+ * @param mdp                   register to hold the pointer inside the MDO (md + md_base_offset).
+ *                              Set once we find an update to make and use for next ones.
+ * @param not_null              true if we know obj cannot be null
+ * @param signature_at_call_k   signature at call for obj
+ * @param callee_signature_k    signature of callee for obj
+ *                              at call and callee signatures differ at method handle call
+ * @return                      the only klass we know will ever be seen at this profile point
+ */
+ciKlass* LIRGenerator::profile_type(ciMethodData* md, int md_base_offset, int md_offset, intptr_t profiled_k,
+                                    Value obj, LIR_Opr& mdp, bool not_null, ciKlass* signature_at_call_k,
+                                    ciKlass* callee_signature_k) {
   ciKlass* result = NULL;
   bool do_null = !not_null && !TypeEntries::was_null_seen(profiled_k);
   bool do_update = !TypeEntries::is_type_unknown(profiled_k);
@@ -2590,9 +2607,9 @@
   if (do_update) {
     // try to find exact type, using CHA if possible, so that loading
     // the klass from the object can be avoided
-    ciType* type = arg->exact_type();
+    ciType* type = obj->exact_type();
     if (type == NULL) {
-      type = arg->declared_type();
+      type = obj->declared_type();
       type = comp->cha_exact_type(type);
     }
     assert(type == NULL || type->is_klass(), "type should be class");
@@ -2608,23 +2625,33 @@
   ciKlass* exact_signature_k = NULL;
   if (do_update) {
     // Is the type from the signature exact (the only one possible)?
-    exact_signature_k = signature_k->exact_klass();
+    exact_signature_k = signature_at_call_k->exact_klass();
     if (exact_signature_k == NULL) {
-      exact_signature_k = comp->cha_exact_type(signature_k);
+      exact_signature_k = comp->cha_exact_type(signature_at_call_k);
     } else {
       result = exact_signature_k;
-      do_update = false;
       // Known statically. No need to emit any code: prevent
       // LIR_Assembler::emit_profile_type() from emitting useless code
       profiled_k = ciTypeEntries::with_status(result, profiled_k);
     }
     if (exact_signature_k != NULL && exact_klass != exact_signature_k) {
-      assert(exact_klass == NULL, "arg and signature disagree?");
+      assert(exact_klass == NULL, "obj and signature disagree?");
       // sometimes the type of the signature is better than the best type
       // the compiler has
       exact_klass = exact_signature_k;
-      do_update = exact_klass == NULL || ciTypeEntries::valid_ciklass(profiled_k) != exact_klass;
     }
+    if (callee_signature_k != NULL &&
+        callee_signature_k != signature_at_call_k) {
+      ciKlass* improved_klass = callee_signature_k->exact_klass();
+      if (improved_klass == NULL) {
+        improved_klass = comp->cha_exact_type(callee_signature_k);
+      }
+      if (improved_klass != NULL && exact_klass != improved_klass) {
+        assert(exact_klass == NULL, "obj and signature disagree?");
+        exact_klass = exact_signature_k;
+      }
+    }
+    do_update = exact_klass == NULL || ciTypeEntries::valid_ciklass(profiled_k) != exact_klass;
   }
 
   if (!do_null && !do_update) {
@@ -2640,7 +2667,7 @@
       __ leal(LIR_OprFact::address(base_type_address), mdp);
     }
   }
-  LIRItem value(arg, this);
+  LIRItem value(obj, this);
   value.load_item();
   __ profile_type(new LIR_Address(mdp, md_offset, T_METADATA),
                   value.result(), exact_klass, profiled_k, new_pointer_register(), not_null, exact_signature_k != NULL);
@@ -2665,9 +2692,9 @@
         if (t == T_OBJECT || t == T_ARRAY) {
           intptr_t profiled_k = parameters->type(j);
           Local* local = x->state()->local_at(java_index)->as_Local();
-          ciKlass* exact = profile_arg_type(md, md->byte_offset_of_slot(parameters_type_data, ParametersTypeData::type_offset(0)),
-                                            in_bytes(ParametersTypeData::type_offset(j)) - in_bytes(ParametersTypeData::type_offset(0)),
-                                            profiled_k, local, mdp, false, local->declared_type()->as_klass());
+          ciKlass* exact = profile_type(md, md->byte_offset_of_slot(parameters_type_data, ParametersTypeData::type_offset(0)),
+                                        in_bytes(ParametersTypeData::type_offset(j)) - in_bytes(ParametersTypeData::type_offset(0)),
+                                        profiled_k, local, mdp, false, local->declared_type()->as_klass(), NULL);
           // If the profile is known statically set it once for all and do not emit any code
           if (exact != NULL) {
             md->set_parameter_type(j, exact);
@@ -3129,19 +3156,28 @@
       Bytecodes::Code bc = x->method()->java_code_at_bci(bci);
       int start = 0;
       int stop = data->is_CallTypeData() ? ((ciCallTypeData*)data)->number_of_arguments() : ((ciVirtualCallTypeData*)data)->number_of_arguments();
-      if (x->nb_profiled_args() < stop) {
-        // if called through method handle invoke, some arguments may have been popped
-        stop = x->nb_profiled_args();
+      if (x->inlined() && x->callee()->is_static() && Bytecodes::has_receiver(bc)) {
+        // first argument is not profiled at call (method handle invoke)
+        assert(x->method()->raw_code_at_bci(bci) == Bytecodes::_invokehandle, "invokehandle expected");
+        start = 1;
       }
-      ciSignature* sig = x->callee()->signature();
+      ciSignature* callee_signature = x->callee()->signature();
       // method handle call to virtual method
       bool has_receiver = x->inlined() && !x->callee()->is_static() && !Bytecodes::has_receiver(bc);
-      ciSignatureStream sig_stream(sig, has_receiver ? x->callee()->holder() : NULL);
-      for (int i = 0; i < stop; i++) {
+      ciSignatureStream callee_signature_stream(callee_signature, has_receiver ? x->callee()->holder() : NULL);
+
+      bool ignored_will_link;
+      ciSignature* signature_at_call = NULL;
+      x->method()->get_method_at_bci(bci, ignored_will_link, &signature_at_call);
+      ciSignatureStream signature_at_call_stream(signature_at_call);
+
+      // if called through method handle invoke, some arguments may have been popped
+      for (int i = 0; i < stop && i+start < x->nb_profiled_args(); i++) {
         int off = in_bytes(TypeEntriesAtCall::argument_type_offset(i)) - in_bytes(TypeEntriesAtCall::args_data_offset());
-        ciKlass* exact = profile_arg_type(md, base_offset, off,
-                                          args->type(i), x->profiled_arg_at(i+start), mdp,
-                                          !x->arg_needs_null_check(i+start), sig_stream.next_klass());
+        ciKlass* exact = profile_type(md, base_offset, off,
+                                      args->type(i), x->profiled_arg_at(i+start), mdp,
+                                      !x->arg_needs_null_check(i+start),
+                                      signature_at_call_stream.next_klass(), callee_signature_stream.next_klass());
         if (exact != NULL) {
           md->set_argument_type(bci, i, exact);
         }
@@ -3176,8 +3212,8 @@
         int bci = x->bci_of_invoke();
         Bytecodes::Code bc = x->method()->java_code_at_bci(bci);
         // The first parameter is the receiver so that's what we start
-        // with if it exists. On exception if method handle call to
-        // virtual method has receiver in the args list
+        // with if it exists. One exception is method handle call to
+        // virtual method: the receiver is in the args list
         if (arg == NULL || !Bytecodes::has_receiver(bc)) {
           i = 1;
           arg = x->profiled_arg_at(0);
@@ -3186,9 +3222,9 @@
         int k = 0; // to iterate on the profile data
         for (;;) {
           intptr_t profiled_k = parameters->type(k);
-          ciKlass* exact = profile_arg_type(md, md->byte_offset_of_slot(parameters_type_data, ParametersTypeData::type_offset(0)),
-                                            in_bytes(ParametersTypeData::type_offset(k)) - in_bytes(ParametersTypeData::type_offset(0)),
-                                            profiled_k, arg, mdp, not_null, sig_stream.next_klass());
+          ciKlass* exact = profile_type(md, md->byte_offset_of_slot(parameters_type_data, ParametersTypeData::type_offset(0)),
+                                        in_bytes(ParametersTypeData::type_offset(k)) - in_bytes(ParametersTypeData::type_offset(0)),
+                                        profiled_k, arg, mdp, not_null, sig_stream.next_klass(), NULL);
           // If the profile is known statically set it once for all and do not emit any code
           if (exact != NULL) {
             md->set_parameter_type(k, exact);
@@ -3247,9 +3283,16 @@
   assert(data->is_CallTypeData() || data->is_VirtualCallTypeData(), "wrong profile data type");
   ciReturnTypeEntry* ret = data->is_CallTypeData() ? ((ciCallTypeData*)data)->ret() : ((ciVirtualCallTypeData*)data)->ret();
   LIR_Opr mdp = LIR_OprFact::illegalOpr;
-  ciKlass* exact = profile_arg_type(md, 0, md->byte_offset_of_slot(data, ret->type_offset()),
-                                    ret->type(), x->ret(), mdp,
-                                    !x->needs_null_check(), x->callee()->signature()->return_type()->as_klass());
+
+  bool ignored_will_link;
+  ciSignature* signature_at_call = NULL;
+  x->method()->get_method_at_bci(bci, ignored_will_link, &signature_at_call);
+
+  ciKlass* exact = profile_type(md, 0, md->byte_offset_of_slot(data, ret->type_offset()),
+                                ret->type(), x->ret(), mdp,
+                                !x->needs_null_check(),
+                                signature_at_call->return_type()->as_klass(),
+                                x->callee()->signature()->return_type()->as_klass());
   if (exact != NULL) {
     md->set_return_type(bci, exact);
   }
--- a/src/share/vm/c1/c1_LIRGenerator.hpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/c1/c1_LIRGenerator.hpp	Fri Nov 15 21:39:27 2013 +0100
@@ -434,7 +434,9 @@
   void do_ThreadIDIntrinsic(Intrinsic* x);
   void do_ClassIDIntrinsic(Intrinsic* x);
 #endif
-  ciKlass* profile_arg_type(ciMethodData* md, int md_first_offset, int md_offset, intptr_t profiled_k, Value arg, LIR_Opr& mdp, bool not_null, ciKlass* signature_k);
+  ciKlass* profile_type(ciMethodData* md, int md_first_offset, int md_offset, intptr_t profiled_k,
+                        Value arg, LIR_Opr& mdp, bool not_null, ciKlass* signature_at_call_k,
+                        ciKlass* callee_signature_k);
   void profile_arguments(ProfileCall* x);
   void profile_parameters(Base* x);
   void profile_parameters_at_call(ProfileCall* x);
--- a/src/share/vm/c1/c1_globals.hpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/c1/c1_globals.hpp	Fri Nov 15 21:39:27 2013 +0100
@@ -341,9 +341,6 @@
   diagnostic(bool, C1PatchInvokeDynamic, true,                              \
              "Patch invokedynamic appendix not known at compile time")      \
                                                                             \
-  develop(intx, MaxForceInlineLevel, 100,                                   \
-          "maximum number of nested @ForceInline calls that are inlined")   \
-                                                                            \
 
 
 // Read default values for c1 globals
--- a/src/share/vm/ci/ciEnv.cpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/ci/ciEnv.cpp	Fri Nov 15 21:39:27 2013 +0100
@@ -935,7 +935,9 @@
 
     // Prevent SystemDictionary::add_to_hierarchy from running
     // and invalidating our dependencies until we install this method.
+    // No safepoints are allowed. Otherwise, class redefinition can occur in between.
     MutexLocker ml(Compile_lock);
+    No_Safepoint_Verifier nsv;
 
     // Change in Jvmti state may invalidate compilation.
     if (!failing() &&
@@ -1001,16 +1003,6 @@
     // Free codeBlobs
     code_buffer->free_blob();
 
-    // stress test 6243940 by immediately making the method
-    // non-entrant behind the system's back. This has serious
-    // side effects on the code cache and is not meant for
-    // general stress testing
-    if (nm != NULL && StressNonEntrant) {
-      MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag);
-      NativeJump::patch_verified_entry(nm->entry_point(), nm->verified_entry_point(),
-                  SharedRuntime::get_handle_wrong_method_stub());
-    }
-
     if (nm == NULL) {
       // The CodeCache is full.  Print out warning and disable compilation.
       record_failure("code cache is full");
@@ -1036,11 +1028,11 @@
             char *method_name = method->name_and_sig_as_C_string();
             tty->print_cr("Replacing method %s", method_name);
           }
-          if (old != NULL ) {
+          if (old != NULL) {
             old->make_not_entrant();
           }
         }
-        if (TraceNMethodInstalls ) {
+        if (TraceNMethodInstalls) {
           ResourceMark rm;
           char *method_name = method->name_and_sig_as_C_string();
           ttyLocker ttyl;
@@ -1051,7 +1043,7 @@
         // Allow the code to be executed
         method->set_code(method, nm);
       } else {
-        if (TraceNMethodInstalls ) {
+        if (TraceNMethodInstalls) {
           ResourceMark rm;
           char *method_name = method->name_and_sig_as_C_string();
           ttyLocker ttyl;
@@ -1061,7 +1053,6 @@
                         entry_bci);
         }
         method->method_holder()->add_osr_nmethod(nm);
-
       }
     }
   }
--- a/src/share/vm/ci/ciMethodData.hpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/ci/ciMethodData.hpp	Fri Nov 15 21:39:27 2013 +0100
@@ -77,7 +77,9 @@
   static ciKlass* valid_ciklass(intptr_t k) {
     if (!TypeEntries::is_type_none(k) &&
         !TypeEntries::is_type_unknown(k)) {
-      return (ciKlass*)TypeEntries::klass_part(k);
+      ciKlass* res = (ciKlass*)TypeEntries::klass_part(k);
+      assert(res != NULL, "invalid");
+      return res;
     } else {
       return NULL;
     }
--- a/src/share/vm/code/nmethod.cpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/code/nmethod.cpp	Fri Nov 15 21:39:27 2013 +0100
@@ -618,21 +618,18 @@
         // record this nmethod as dependent on this klass
         InstanceKlass::cast(klass)->add_dependent_nmethod(nm);
       }
-    }
-    NOT_PRODUCT(if (nm != NULL)  nmethod_stats.note_nmethod(nm));
-    if (PrintAssembly && nm != NULL) {
-      Disassembler::decode(nm);
+      NOT_PRODUCT(nmethod_stats.note_nmethod(nm));
+      if (PrintAssembly) {
+        Disassembler::decode(nm);
+      }
     }
   }
-
-  // verify nmethod
-  debug_only(if (nm) nm->verify();) // might block
-
+  // Do verification and logging outside CodeCache_lock.
   if (nm != NULL) {
+    // Safepoints in nmethod::verify aren't allowed because nm hasn't been installed yet.
+    DEBUG_ONLY(nm->verify();)
     nm->log_new_nmethod();
   }
-
-  // done
   return nm;
 }
 
@@ -1262,7 +1259,7 @@
 
   set_osr_link(NULL);
   //set_scavenge_root_link(NULL); // done by prune_scavenge_root_nmethods
-  NMethodSweeper::notify();
+  NMethodSweeper::report_state_change(this);
 }
 
 void nmethod::invalidate_osr_method() {
@@ -1296,7 +1293,9 @@
   }
 }
 
-// Common functionality for both make_not_entrant and make_zombie
+/**
+ * Common functionality for both make_not_entrant and make_zombie
+ */
 bool nmethod::make_not_entrant_or_zombie(unsigned int state) {
   assert(state == zombie || state == not_entrant, "must be zombie or not_entrant");
   assert(!is_zombie(), "should not already be a zombie");
@@ -1420,9 +1419,7 @@
     tty->print_cr("nmethod <" INTPTR_FORMAT "> code made %s", this, (state == not_entrant) ? "not entrant" : "zombie");
   }
 
-  // Make sweeper aware that there is a zombie method that needs to be removed
-  NMethodSweeper::notify();
-
+  NMethodSweeper::report_state_change(this);
   return true;
 }
 
@@ -2395,20 +2392,23 @@
 
 
 void nmethod::verify_interrupt_point(address call_site) {
-  // This code does not work in release mode since
-  // owns_lock only is available in debug mode.
-  CompiledIC* ic = NULL;
-  Thread *cur = Thread::current();
-  if (CompiledIC_lock->owner() == cur ||
-      ((cur->is_VM_thread() || cur->is_ConcurrentGC_thread()) &&
-       SafepointSynchronize::is_at_safepoint())) {
-    ic = CompiledIC_at(this, call_site);
-    CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops());
-  } else {
-    MutexLocker ml_verify (CompiledIC_lock);
-    ic = CompiledIC_at(this, call_site);
+  // Verify IC only when nmethod installation is finished.
+  bool is_installed = (method()->code() == this) // nmethod is in state 'alive' and installed
+                      || !this->is_in_use();     // nmethod is installed, but not in 'alive' state
+  if (is_installed) {
+    Thread *cur = Thread::current();
+    if (CompiledIC_lock->owner() == cur ||
+        ((cur->is_VM_thread() || cur->is_ConcurrentGC_thread()) &&
+         SafepointSynchronize::is_at_safepoint())) {
+      CompiledIC_at(this, call_site);
+      CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops());
+    } else {
+      MutexLocker ml_verify (CompiledIC_lock);
+      CompiledIC_at(this, call_site);
+    }
   }
-  PcDesc* pd = pc_desc_at(ic->end_of_call());
+
+  PcDesc* pd = pc_desc_at(nativeCall_at(call_site)->return_address());
   assert(pd != NULL, "PcDesc must exist");
   for (ScopeDesc* sd = new ScopeDesc(this, pd->scope_decode_offset(),
                                      pd->obj_decode_offset(), pd->should_reexecute(),
--- a/src/share/vm/compiler/compileBroker.cpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/compiler/compileBroker.cpp	Fri Nov 15 21:39:27 2013 +0100
@@ -126,6 +126,7 @@
 
 bool CompileBroker::_initialized = false;
 volatile bool CompileBroker::_should_block = false;
+volatile jint CompileBroker::_print_compilation_warning = 0;
 volatile jint CompileBroker::_should_compile_new_jobs = run_compilation;
 
 // The installed compiler(s)
@@ -2027,11 +2028,10 @@
 #endif
 }
 
-// ------------------------------------------------------------------
-// CompileBroker::handle_full_code_cache
-//
-// The CodeCache is full.  Print out warning and disable compilation or
-// try code cache cleaning so compilation can continue later.
+/**
+ * The CodeCache is full.  Print out warning and disable compilation
+ * or try code cache cleaning so compilation can continue later.
+ */
 void CompileBroker::handle_full_code_cache() {
   UseInterpreter = true;
   if (UseCompiler || AlwaysCompileLoopMethods ) {
@@ -2048,12 +2048,9 @@
       xtty->stamp();
       xtty->end_elem();
     }
-    warning("CodeCache is full. Compiler has been disabled.");
-    warning("Try increasing the code cache size using -XX:ReservedCodeCacheSize=");
 
     CodeCache::report_codemem_full();
 
-
 #ifndef PRODUCT
     if (CompileTheWorld || ExitOnFullCodeCache) {
       codecache_print(/* detailed= */ true);
@@ -2066,17 +2063,22 @@
       // Since code cache is full, immediately stop new compiles
       if (CompileBroker::set_should_compile_new_jobs(CompileBroker::stop_compilation)) {
         NMethodSweeper::log_sweep("disable_compiler");
-
-        // Switch to 'vm_state'. This ensures that possibly_sweep() can be called
-        // without having to consider the state in which the current thread is.
-        ThreadInVMfromUnknown in_vm;
-        NMethodSweeper::possibly_sweep();
       }
+      // Switch to 'vm_state'. This ensures that possibly_sweep() can be called
+      // without having to consider the state in which the current thread is.
+      ThreadInVMfromUnknown in_vm;
+      NMethodSweeper::possibly_sweep();
     } else {
       disable_compilation_forever();
     }
+
+    // Print warning only once
+    if (should_print_compiler_warning()) {
+      warning("CodeCache is full. Compiler has been disabled.");
+      warning("Try increasing the code cache size using -XX:ReservedCodeCacheSize=");
+      codecache_print(/* detailed= */ true);
+    }
   }
-  codecache_print(/* detailed= */ true);
 }
 
 // ------------------------------------------------------------------
--- a/src/share/vm/compiler/compileBroker.hpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/compiler/compileBroker.hpp	Fri Nov 15 21:39:27 2013 +0100
@@ -315,6 +315,8 @@
   static int _sum_nmethod_code_size;
   static long _peak_compilation_time;
 
+  static volatile jint _print_compilation_warning;
+
   static CompilerThread* make_compiler_thread(const char* name, CompileQueue* queue, CompilerCounters* counters, AbstractCompiler* comp, TRAPS);
   static void init_compiler_threads(int c1_compiler_count, int c2_compiler_count);
   static bool compilation_is_complete  (methodHandle method, int osr_bci, int comp_level);
@@ -418,7 +420,11 @@
     return _should_compile_new_jobs == shutdown_compilaton;
   }
   static void handle_full_code_cache();
-
+  // Ensures that warning is only printed once.
+  static bool should_print_compiler_warning() {
+    jint old = Atomic::cmpxchg(1, &_print_compilation_warning, 0);
+    return old == 0;
+  }
   // Return total compilation ticks
   static jlong total_compilation_ticks() {
     return _perf_total_compilation != NULL ? _perf_total_compilation->get_value() : 0;
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.cpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.cpp	Fri Nov 15 21:39:27 2013 +0100
@@ -47,8 +47,9 @@
 // ConcurrentMarkSweepPolicy methods
 //
 
-ConcurrentMarkSweepPolicy::ConcurrentMarkSweepPolicy() {
-  initialize_all();
+void ConcurrentMarkSweepPolicy::initialize_alignments() {
+  _space_alignment = _gen_alignment = (uintx)Generation::GenGrain;
+  _heap_alignment = compute_heap_alignment();
 }
 
 void ConcurrentMarkSweepPolicy::initialize_generations() {
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.hpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.hpp	Fri Nov 15 21:39:27 2013 +0100
@@ -29,10 +29,11 @@
 
 class ConcurrentMarkSweepPolicy : public TwoGenerationCollectorPolicy {
  protected:
+  void initialize_alignments();
   void initialize_generations();
 
  public:
-  ConcurrentMarkSweepPolicy();
+  ConcurrentMarkSweepPolicy() {}
 
   ConcurrentMarkSweepPolicy* as_concurrent_mark_sweep_policy() { return this; }
 
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Fri Nov 15 21:39:27 2013 +0100
@@ -594,9 +594,9 @@
   _verification_mark_bm(0, Mutex::leaf + 1, "CMS_verification_mark_bm_lock"),
   _completed_initialization(false),
   _collector_policy(cp),
-  _should_unload_classes(false),
+  _should_unload_classes(CMSClassUnloadingEnabled),
   _concurrent_cycles_since_last_unload(0),
-  _roots_scanning_options(0),
+  _roots_scanning_options(SharedHeap::SO_None),
   _inter_sweep_estimate(CMS_SweepWeight, CMS_SweepPadding),
   _intra_sweep_estimate(CMS_SweepWeight, CMS_SweepPadding),
   _gc_tracer_cm(new (ResourceObj::C_HEAP, mtGC) CMSTracer()),
@@ -788,14 +788,6 @@
              && _survivor_chunk_index == 0),
          "Error");
 
-  // Choose what strong roots should be scanned depending on verification options
-  if (!CMSClassUnloadingEnabled) {
-    // If class unloading is disabled we want to include all classes into the root set.
-    add_root_scanning_option(SharedHeap::SO_AllClasses);
-  } else {
-    add_root_scanning_option(SharedHeap::SO_SystemClasses);
-  }
-
   NOT_PRODUCT(_overflow_counter = CMSMarkStackOverflowInterval;)
   _gc_counters = new CollectorCounters("CMS", 1);
   _completed_initialization = true;
@@ -2532,6 +2524,9 @@
   // Snapshot the soft reference policy to be used in this collection cycle.
   ref_processor()->setup_policy(clear_all_soft_refs);
 
+  // Decide if class unloading should be done
+  update_should_unload_classes();
+
   bool init_mark_was_synchronous = false; // until proven otherwise
   while (_collectorState != Idling) {
     if (TraceCMSState) {
@@ -3310,7 +3305,10 @@
                              || VerifyBeforeExit;
   const  int  rso           =   SharedHeap::SO_Strings | SharedHeap::SO_CodeCache;
 
+  // We set the proper root for this CMS cycle here.
   if (should_unload_classes()) {   // Should unload classes this cycle
+    remove_root_scanning_option(SharedHeap::SO_AllClasses);
+    add_root_scanning_option(SharedHeap::SO_SystemClasses);
     remove_root_scanning_option(rso);  // Shrink the root set appropriately
     set_verifying(should_verify);    // Set verification state for this cycle
     return;                            // Nothing else needs to be done at this time
@@ -3318,6 +3316,9 @@
 
   // Not unloading classes this cycle
   assert(!should_unload_classes(), "Inconsitency!");
+  remove_root_scanning_option(SharedHeap::SO_SystemClasses);
+  add_root_scanning_option(SharedHeap::SO_AllClasses);
+
   if ((!verifying() || unloaded_classes_last_cycle()) && should_verify) {
     // Include symbols, strings and code cache elements to prevent their resurrection.
     add_root_scanning_option(rso);
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Fri Nov 15 21:39:27 2013 +0100
@@ -2008,7 +2008,7 @@
 
   size_t init_byte_size = collector_policy()->initial_heap_byte_size();
   size_t max_byte_size = collector_policy()->max_heap_byte_size();
-  size_t heap_alignment = collector_policy()->max_alignment();
+  size_t heap_alignment = collector_policy()->heap_alignment();
 
   // Ensure that the sizes are properly aligned.
   Universe::check_alignment(init_byte_size, HeapRegion::GrainBytes, "g1 heap");
@@ -6656,13 +6656,18 @@
     if (!oopDesc::is_null(heap_oop)) {
       oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
       HeapRegion* hr = _g1h->heap_region_containing(obj);
-      assert(!hr->isHumongous(), "code root in humongous region?");
+      assert(!hr->continuesHumongous(),
+             err_msg("trying to add code root "PTR_FORMAT" in continuation of humongous region "HR_FORMAT
+                     " starting at "HR_FORMAT,
+                     _nm, HR_FORMAT_PARAMS(hr), HR_FORMAT_PARAMS(hr->humongous_start_region())));
 
       // HeapRegion::add_strong_code_root() avoids adding duplicate
       // entries but having duplicates is  OK since we "mark" nmethods
       // as visited when we scan the strong code root lists during the GC.
       hr->add_strong_code_root(_nm);
-      assert(hr->rem_set()->strong_code_roots_list_contains(_nm), "add failed?");
+      assert(hr->rem_set()->strong_code_roots_list_contains(_nm),
+             err_msg("failed to add code root "PTR_FORMAT" to remembered set of region "HR_FORMAT,
+                     _nm, HR_FORMAT_PARAMS(hr)));
     }
   }
 
@@ -6683,9 +6688,15 @@
     if (!oopDesc::is_null(heap_oop)) {
       oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
       HeapRegion* hr = _g1h->heap_region_containing(obj);
-      assert(!hr->isHumongous(), "code root in humongous region?");
+      assert(!hr->continuesHumongous(),
+             err_msg("trying to remove code root "PTR_FORMAT" in continuation of humongous region "HR_FORMAT
+                     " starting at "HR_FORMAT,
+                     _nm, HR_FORMAT_PARAMS(hr), HR_FORMAT_PARAMS(hr->humongous_start_region())));
+
       hr->remove_strong_code_root(_nm);
-      assert(!hr->rem_set()->strong_code_roots_list_contains(_nm), "remove failed?");
+      assert(!hr->rem_set()->strong_code_roots_list_contains(_nm),
+             err_msg("failed to remove code root "PTR_FORMAT" of region "HR_FORMAT,
+                     _nm, HR_FORMAT_PARAMS(hr)));
     }
   }
 
@@ -6716,7 +6727,9 @@
 class MigrateCodeRootsHeapRegionClosure: public HeapRegionClosure {
 public:
   bool doHeapRegion(HeapRegion *hr) {
-    assert(!hr->isHumongous(), "humongous region in collection set?");
+    assert(!hr->isHumongous(),
+           err_msg("humongous region "HR_FORMAT" should not have been added to collection set",
+                   HR_FORMAT_PARAMS(hr)));
     hr->migrate_strong_code_roots();
     return false;
   }
@@ -6796,9 +6809,13 @@
 
   bool doHeapRegion(HeapRegion *hr) {
     HeapRegionRemSet* hrrs = hr->rem_set();
-    if (hr->isHumongous()) {
-      // Code roots should never be attached to a humongous region
-      assert(hrrs->strong_code_roots_list_length() == 0, "sanity");
+    if (hr->continuesHumongous()) {
+      // Code roots should never be attached to a continuation of a humongous region
+      assert(hrrs->strong_code_roots_list_length() == 0,
+             err_msg("code roots should never be attached to continuations of humongous region "HR_FORMAT
+                     " starting at "HR_FORMAT", but has "INT32_FORMAT,
+                     HR_FORMAT_PARAMS(hr), HR_FORMAT_PARAMS(hr->humongous_start_region()),
+                     hrrs->strong_code_roots_list_length()));
       return false;
     }
 
--- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Fri Nov 15 21:39:27 2013 +0100
@@ -313,27 +313,38 @@
   // for the first time during initialization.
   _reserve_regions = 0;
 
-  initialize_all();
   _collectionSetChooser = new CollectionSetChooser();
-  _young_gen_sizer = new G1YoungGenSizer(); // Must be after call to initialize_flags
+}
+
+void G1CollectorPolicy::initialize_alignments() {
+  _space_alignment = HeapRegion::GrainBytes;
+  size_t card_table_alignment = GenRemSet::max_alignment_constraint(GenRemSet::CardTable);
+  size_t page_size = UseLargePages ? os::large_page_size() : os::vm_page_size();
+  _heap_alignment = MAX3(card_table_alignment, _space_alignment, page_size);
 }
 
 void G1CollectorPolicy::initialize_flags() {
-  _min_alignment = HeapRegion::GrainBytes;
-  size_t card_table_alignment = GenRemSet::max_alignment_constraint(rem_set_name());
-  size_t page_size = UseLargePages ? os::large_page_size() : os::vm_page_size();
-  _max_alignment = MAX3(card_table_alignment, _min_alignment, page_size);
+  if (G1HeapRegionSize != HeapRegion::GrainBytes) {
+    FLAG_SET_ERGO(uintx, G1HeapRegionSize, HeapRegion::GrainBytes);
+  }
+
   if (SurvivorRatio < 1) {
     vm_exit_during_initialization("Invalid survivor ratio specified");
   }
   CollectorPolicy::initialize_flags();
+  _young_gen_sizer = new G1YoungGenSizer(); // Must be after call to initialize_flags
 }
 
-G1YoungGenSizer::G1YoungGenSizer() : _sizer_kind(SizerDefaults), _adaptive_size(true) {
-  assert(G1NewSizePercent <= G1MaxNewSizePercent, "Min larger than max");
-  assert(G1NewSizePercent > 0 && G1NewSizePercent < 100, "Min out of bounds");
-  assert(G1MaxNewSizePercent > 0 && G1MaxNewSizePercent < 100, "Max out of bounds");
+void G1CollectorPolicy::post_heap_initialize() {
+  uintx max_regions = G1CollectedHeap::heap()->max_regions();
+  size_t max_young_size = (size_t)_young_gen_sizer->max_young_length(max_regions) * HeapRegion::GrainBytes;
+  if (max_young_size != MaxNewSize) {
+    FLAG_SET_ERGO(uintx, MaxNewSize, max_young_size);
+  }
+}
 
+G1YoungGenSizer::G1YoungGenSizer() : _sizer_kind(SizerDefaults), _adaptive_size(true),
+        _min_desired_young_length(0), _max_desired_young_length(0) {
   if (FLAG_IS_CMDLINE(NewRatio)) {
     if (FLAG_IS_CMDLINE(NewSize) || FLAG_IS_CMDLINE(MaxNewSize)) {
       warning("-XX:NewSize and -XX:MaxNewSize override -XX:NewRatio");
@@ -344,8 +355,13 @@
     }
   }
 
-  if (FLAG_IS_CMDLINE(NewSize) && FLAG_IS_CMDLINE(MaxNewSize) && NewSize > MaxNewSize) {
-    vm_exit_during_initialization("Initial young gen size set larger than the maximum young gen size");
+  if (NewSize > MaxNewSize) {
+    if (FLAG_IS_CMDLINE(MaxNewSize)) {
+      warning("NewSize (" SIZE_FORMAT "k) is greater than the MaxNewSize (" SIZE_FORMAT "k). "
+              "A new max generation size of " SIZE_FORMAT "k will be used.",
+              NewSize/K, MaxNewSize/K, NewSize/K);
+    }
+    MaxNewSize = NewSize;
   }
 
   if (FLAG_IS_CMDLINE(NewSize)) {
@@ -378,34 +394,48 @@
   return MAX2(1U, default_value);
 }
 
-void G1YoungGenSizer::heap_size_changed(uint new_number_of_heap_regions) {
-  assert(new_number_of_heap_regions > 0, "Heap must be initialized");
+void G1YoungGenSizer::recalculate_min_max_young_length(uint number_of_heap_regions, uint* min_young_length, uint* max_young_length) {
+  assert(number_of_heap_regions > 0, "Heap must be initialized");
 
   switch (_sizer_kind) {
     case SizerDefaults:
-      _min_desired_young_length = calculate_default_min_length(new_number_of_heap_regions);
-      _max_desired_young_length = calculate_default_max_length(new_number_of_heap_regions);
+      *min_young_length = calculate_default_min_length(number_of_heap_regions);
+      *max_young_length = calculate_default_max_length(number_of_heap_regions);
       break;
     case SizerNewSizeOnly:
-      _max_desired_young_length = calculate_default_max_length(new_number_of_heap_regions);
-      _max_desired_young_length = MAX2(_min_desired_young_length, _max_desired_young_length);
+      *max_young_length = calculate_default_max_length(number_of_heap_regions);
+      *max_young_length = MAX2(*min_young_length, *max_young_length);
       break;
     case SizerMaxNewSizeOnly:
-      _min_desired_young_length = calculate_default_min_length(new_number_of_heap_regions);
-      _min_desired_young_length = MIN2(_min_desired_young_length, _max_desired_young_length);
+      *min_young_length = calculate_default_min_length(number_of_heap_regions);
+      *min_young_length = MIN2(*min_young_length, *max_young_length);
       break;
     case SizerMaxAndNewSize:
       // Do nothing. Values set on the command line, don't update them at runtime.
       break;
     case SizerNewRatio:
-      _min_desired_young_length = new_number_of_heap_regions / (NewRatio + 1);
-      _max_desired_young_length = _min_desired_young_length;
+      *min_young_length = number_of_heap_regions / (NewRatio + 1);
+      *max_young_length = *min_young_length;
       break;
     default:
       ShouldNotReachHere();
   }
 
-  assert(_min_desired_young_length <= _max_desired_young_length, "Invalid min/max young gen size values");
+  assert(*min_young_length <= *max_young_length, "Invalid min/max young gen size values");
+}
+
+uint G1YoungGenSizer::max_young_length(uint number_of_heap_regions) {
+  // We need to pass the desired values because recalculation may not update these
+  // values in some cases.
+  uint temp = _min_desired_young_length;
+  uint result = _max_desired_young_length;
+  recalculate_min_max_young_length(number_of_heap_regions, &temp, &result);
+  return result;
+}
+
+void G1YoungGenSizer::heap_size_changed(uint new_number_of_heap_regions) {
+  recalculate_min_max_young_length(new_number_of_heap_regions, &_min_desired_young_length,
+          &_max_desired_young_length);
 }
 
 void G1CollectorPolicy::init() {
--- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp	Fri Nov 15 21:39:27 2013 +0100
@@ -136,8 +136,16 @@
   uint calculate_default_min_length(uint new_number_of_heap_regions);
   uint calculate_default_max_length(uint new_number_of_heap_regions);
 
+  // Update the given values for minimum and maximum young gen length in regions
+  // given the number of heap regions depending on the kind of sizing algorithm.
+  void recalculate_min_max_young_length(uint number_of_heap_regions, uint* min_young_length, uint* max_young_length);
+
 public:
   G1YoungGenSizer();
+  // Calculate the maximum length of the young gen given the number of regions
+  // depending on the sizing algorithm.
+  uint max_young_length(uint number_of_heap_regions);
+
   void heap_size_changed(uint new_number_of_heap_regions);
   uint min_desired_young_length() {
     return _min_desired_young_length;
@@ -165,13 +173,9 @@
 
   G1MMUTracker* _mmu_tracker;
 
+  void initialize_alignments();
   void initialize_flags();
 
-  void initialize_all() {
-    initialize_flags();
-    initialize_size_info();
-  }
-
   CollectionSetChooser* _collectionSetChooser;
 
   double _full_collection_start_sec;
@@ -217,7 +221,6 @@
     return _during_marking;
   }
 
-private:
   enum PredictionConstants {
     TruncatedSeqLength = 10
   };
@@ -665,8 +668,6 @@
 
   BarrierSet::Name barrier_set_name() { return BarrierSet::G1SATBCTLogging; }
 
-  GenRemSet::Name  rem_set_name()     { return GenRemSet::CardTable; }
-
   bool need_to_start_conc_mark(const char* source, size_t alloc_word_size = 0);
 
   // Record the start and end of an evacuation pause.
@@ -934,6 +935,7 @@
   // Calculates survivor space parameters.
   void update_survivors_policy();
 
+  virtual void post_heap_initialize();
 };
 
 // This should move to some place more general...
--- a/src/share/vm/gc_implementation/g1/g1RemSet.cpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/gc_implementation/g1/g1RemSet.cpp	Fri Nov 15 21:39:27 2013 +0100
@@ -377,11 +377,6 @@
   DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
   dcqs.concatenate_logs();
 
-  if (G1CollectedHeap::use_parallel_gc_threads()) {
-    // Don't set the number of workers here.  It will be set
-    // when the task is run
-    // _seq_task->set_n_termination((int)n_workers());
-  }
   guarantee( _cards_scanned == NULL, "invariant" );
   _cards_scanned = NEW_C_HEAP_ARRAY(size_t, n_workers(), mtGC);
   for (uint i = 0; i < n_workers(); ++i) {
--- a/src/share/vm/gc_implementation/g1/heapRegion.cpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/gc_implementation/g1/heapRegion.cpp	Fri Nov 15 21:39:27 2013 +0100
@@ -174,11 +174,6 @@
     region_size = MAX_REGION_SIZE;
   }
 
-  if (region_size != G1HeapRegionSize) {
-    // Update the flag to make sure that PrintFlagsFinal logs the correct value
-    FLAG_SET_ERGO(uintx, G1HeapRegionSize, region_size);
-  }
-
   // And recalculate the log.
   region_size_log = log2_long((jlong) region_size);
 
@@ -606,7 +601,9 @@
 
 void HeapRegion::migrate_strong_code_roots() {
   assert(in_collection_set(), "only collection set regions");
-  assert(!isHumongous(), "not humongous regions");
+  assert(!isHumongous(),
+          err_msg("humongous region "HR_FORMAT" should not have been added to collection set",
+                  HR_FORMAT_PARAMS(this)));
 
   HeapRegionRemSet* hrrs = rem_set();
   hrrs->migrate_strong_code_roots();
@@ -727,12 +724,11 @@
     return;
   }
 
-  // An H-region should have an empty strong code root list
-  if (isHumongous()) {
+  if (continuesHumongous()) {
     if (strong_code_roots_length > 0) {
-      gclog_or_tty->print_cr("region ["PTR_FORMAT","PTR_FORMAT"] is humongous "
-                             "but has "INT32_FORMAT" code root entries",
-                             bottom(), end(), strong_code_roots_length);
+      gclog_or_tty->print_cr("region "HR_FORMAT" is a continuation of a humongous "
+                             "region but has "INT32_FORMAT" code root entries",
+                             HR_FORMAT_PARAMS(this), strong_code_roots_length);
       *failures = true;
     }
     return;
--- a/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp	Fri Nov 15 21:39:27 2013 +0100
@@ -1004,7 +1004,9 @@
 
 void HeapRegionRemSet::migrate_strong_code_roots() {
   assert(hr()->in_collection_set(), "only collection set regions");
-  assert(!hr()->isHumongous(), "not humongous regions");
+  assert(!hr()->isHumongous(),
+         err_msg("humongous region "HR_FORMAT" should not have been added to the collection set",
+                 HR_FORMAT_PARAMS(hr())));
 
   ResourceMark rm;
 
--- a/src/share/vm/gc_implementation/parallelScavenge/adjoiningGenerations.cpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/gc_implementation/parallelScavenge/adjoiningGenerations.cpp	Fri Nov 15 21:39:27 2013 +0100
@@ -25,6 +25,7 @@
 #include "precompiled.hpp"
 #include "gc_implementation/parallelScavenge/adjoiningGenerations.hpp"
 #include "gc_implementation/parallelScavenge/adjoiningVirtualSpaces.hpp"
+#include "gc_implementation/parallelScavenge/generationSizer.hpp"
 #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp"
 
 // If boundary moving is being used, create the young gen and old
@@ -32,15 +33,17 @@
 // the old behavior otherwise (with PSYoungGen and PSOldGen).
 
 AdjoiningGenerations::AdjoiningGenerations(ReservedSpace old_young_rs,
-                                           size_t init_low_byte_size,
-                                           size_t min_low_byte_size,
-                                           size_t max_low_byte_size,
-                                           size_t init_high_byte_size,
-                                           size_t min_high_byte_size,
-                                           size_t max_high_byte_size,
+                                           GenerationSizer* policy,
                                            size_t alignment) :
-  _virtual_spaces(old_young_rs, min_low_byte_size,
-                  min_high_byte_size, alignment) {
+  _virtual_spaces(old_young_rs, policy->min_gen1_size(),
+                  policy->min_gen0_size(), alignment) {
+  size_t init_low_byte_size = policy->initial_gen1_size();
+  size_t min_low_byte_size = policy->min_gen1_size();
+  size_t max_low_byte_size = policy->max_gen1_size();
+  size_t init_high_byte_size = policy->initial_gen0_size();
+  size_t min_high_byte_size = policy->min_gen0_size();
+  size_t max_high_byte_size = policy->max_gen0_size();
+
   assert(min_low_byte_size <= init_low_byte_size &&
          init_low_byte_size <= max_low_byte_size, "Parameter check");
   assert(min_high_byte_size <= init_high_byte_size &&
--- a/src/share/vm/gc_implementation/parallelScavenge/adjoiningGenerations.hpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/gc_implementation/parallelScavenge/adjoiningGenerations.hpp	Fri Nov 15 21:39:27 2013 +0100
@@ -28,6 +28,7 @@
 #include "gc_implementation/parallelScavenge/adjoiningVirtualSpaces.hpp"
 #include "gc_implementation/parallelScavenge/asPSOldGen.hpp"
 #include "gc_implementation/parallelScavenge/asPSYoungGen.hpp"
+#include "gc_implementation/parallelScavenge/generationSizer.hpp"
 
 
 // Contains two generations that both use an AdjoiningVirtualSpaces.
@@ -56,14 +57,7 @@
   bool request_young_gen_expansion(size_t desired_change_in_bytes);
 
  public:
-  AdjoiningGenerations(ReservedSpace rs,
-                       size_t init_low_byte_size,
-                       size_t min_low_byte_size,
-                       size_t max_low_byte_size,
-                       size_t init_high_byte_size,
-                       size_t min_high_byte_size,
-                       size_t max_high_bytes_size,
-                       size_t alignment);
+  AdjoiningGenerations(ReservedSpace rs, GenerationSizer* policy, size_t alignment);
 
   // Accessors
   PSYoungGen* young_gen() { return _young_gen; }
--- a/src/share/vm/gc_implementation/parallelScavenge/asPSOldGen.cpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/gc_implementation/parallelScavenge/asPSOldGen.cpp	Fri Nov 15 21:39:27 2013 +0100
@@ -54,7 +54,6 @@
                        int level) :
   PSOldGen(initial_size, min_size, size_limit, gen_name, level),
   _gen_size_limit(size_limit)
-
 {}
 
 ASPSOldGen::ASPSOldGen(PSVirtualSpace* vs,
@@ -65,13 +64,11 @@
                        int level) :
   PSOldGen(initial_size, min_size, size_limit, gen_name, level),
   _gen_size_limit(size_limit)
-
 {
   _virtual_space = vs;
 }
 
 void ASPSOldGen::initialize_work(const char* perf_data_name, int level) {
-
   PSOldGen::initialize_work(perf_data_name, level);
 
   // The old gen can grow to gen_size_limit().  _reserve reflects only
@@ -94,7 +91,7 @@
 
   ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
   size_t result =  gen_size_limit() - virtual_space()->committed_size();
-  size_t result_aligned = align_size_down(result, heap->old_gen_alignment());
+  size_t result_aligned = align_size_down(result, heap->generation_alignment());
   return result_aligned;
 }
 
@@ -105,7 +102,7 @@
   }
 
   ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
-  const size_t gen_alignment = heap->old_gen_alignment();
+  const size_t gen_alignment = heap->generation_alignment();
   PSAdaptiveSizePolicy* policy = heap->size_policy();
   const size_t working_size =
     used_in_bytes() + (size_t) policy->avg_promoted()->padded_average();
--- a/src/share/vm/gc_implementation/parallelScavenge/asPSYoungGen.cpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/gc_implementation/parallelScavenge/asPSYoungGen.cpp	Fri Nov 15 21:39:27 2013 +0100
@@ -70,13 +70,12 @@
 }
 
 size_t ASPSYoungGen::available_for_expansion() {
-
   size_t current_committed_size = virtual_space()->committed_size();
   assert((gen_size_limit() >= current_committed_size),
     "generation size limit is wrong");
   ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
   size_t result =  gen_size_limit() - current_committed_size;
-  size_t result_aligned = align_size_down(result, heap->young_gen_alignment());
+  size_t result_aligned = align_size_down(result, heap->generation_alignment());
   return result_aligned;
 }
 
@@ -85,7 +84,6 @@
 // Future implementations could check the survivors and if to_space is in the
 // right place (below from_space), take a chunk from to_space.
 size_t ASPSYoungGen::available_for_contraction() {
-
   size_t uncommitted_bytes = virtual_space()->uncommitted_size();
   if (uncommitted_bytes != 0) {
     return uncommitted_bytes;
@@ -94,8 +92,8 @@
   if (eden_space()->is_empty()) {
     // Respect the minimum size for eden and for the young gen as a whole.
     ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
-    const size_t eden_alignment = heap->intra_heap_alignment();
-    const size_t gen_alignment = heap->young_gen_alignment();
+    const size_t eden_alignment = heap->space_alignment();
+    const size_t gen_alignment = heap->generation_alignment();
 
     assert(eden_space()->capacity_in_bytes() >= eden_alignment,
       "Alignment is wrong");
@@ -121,7 +119,6 @@
       gclog_or_tty->print_cr("  gen_avail %d K", gen_avail/K);
     }
     return result_aligned;
-
   }
 
   return 0;
@@ -132,7 +129,7 @@
 // to_space can be.
 size_t ASPSYoungGen::available_to_live() {
   ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
-  const size_t alignment = heap->intra_heap_alignment();
+  const size_t alignment = heap->space_alignment();
 
   // Include any space that is committed but is not in eden.
   size_t available = pointer_delta(eden_space()->bottom(),
@@ -296,7 +293,7 @@
   assert(eden_start < from_start, "Cannot push into from_space");
 
   ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
-  const size_t alignment = heap->intra_heap_alignment();
+  const size_t alignment = heap->space_alignment();
   const bool maintain_minimum =
     (requested_eden_size + 2 * requested_survivor_size) <= min_gen_size();
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/gc_implementation/parallelScavenge/generationSizer.cpp	Fri Nov 15 21:39:27 2013 +0100
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc_implementation/parallelScavenge/generationSizer.hpp"
+#include "memory/collectorPolicy.hpp"
+
+void GenerationSizer::trace_gen_sizes(const char* const str) {
+  if (TracePageSizes) {
+    tty->print_cr("%s:  " SIZE_FORMAT "," SIZE_FORMAT " "
+                  SIZE_FORMAT "," SIZE_FORMAT " "
+                  SIZE_FORMAT,
+                  str,
+                  _min_gen1_size / K, _max_gen1_size / K,
+                  _min_gen0_size / K, _max_gen0_size / K,
+                  _max_heap_byte_size / K);
+  }
+}
+
+void GenerationSizer::initialize_alignments() {
+  _space_alignment = _gen_alignment = default_gen_alignment();
+  _heap_alignment = compute_heap_alignment();
+}
+
+void GenerationSizer::initialize_flags() {
+  // Do basic sizing work
+  TwoGenerationCollectorPolicy::initialize_flags();
+
+  assert(UseSerialGC ||
+          !FLAG_IS_DEFAULT(ParallelGCThreads) ||
+          (ParallelGCThreads > 0),
+         "ParallelGCThreads should be set before flag initialization");
+
+  // The survivor ratio's are calculated "raw", unlike the
+  // default gc, which adds 2 to the ratio value. We need to
+  // make sure the values are valid before using them.
+  if (MinSurvivorRatio < 3) {
+    FLAG_SET_ERGO(uintx, MinSurvivorRatio, 3);
+  }
+
+  if (InitialSurvivorRatio < 3) {
+    FLAG_SET_ERGO(uintx, InitialSurvivorRatio, 3);
+  }
+}
+
+void GenerationSizer::initialize_size_info() {
+  trace_gen_sizes("ps heap raw");
+  const size_t page_sz = os::page_size_for_region(_min_heap_byte_size,
+                                                  _max_heap_byte_size,
+                                                  8);
+
+  // Can a page size be something else than a power of two?
+  assert(is_power_of_2((intptr_t)page_sz), "must be a power of 2");
+  size_t new_alignment = round_to(page_sz, _gen_alignment);
+  if (new_alignment != _gen_alignment) {
+    _gen_alignment = new_alignment;
+    _space_alignment = new_alignment;
+    // Redo everything from the start
+    initialize_flags();
+  }
+  TwoGenerationCollectorPolicy::initialize_size_info();
+
+  trace_gen_sizes("ps heap rnd");
+}
--- a/src/share/vm/gc_implementation/parallelScavenge/generationSizer.hpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/gc_implementation/parallelScavenge/generationSizer.hpp	Fri Nov 15 21:39:27 2013 +0100
@@ -31,41 +31,17 @@
 // TwoGenerationCollectorPolicy. Lets reuse it!
 
 class GenerationSizer : public TwoGenerationCollectorPolicy {
- public:
-  GenerationSizer() {
-    // Partial init only!
-    initialize_flags();
-    initialize_size_info();
-  }
+ private:
 
-  void initialize_flags() {
-    // Do basic sizing work
-    TwoGenerationCollectorPolicy::initialize_flags();
+  void trace_gen_sizes(const char* const str);
 
-    assert(UseSerialGC ||
-           !FLAG_IS_DEFAULT(ParallelGCThreads) ||
-           (ParallelGCThreads > 0),
-           "ParallelGCThreads should be set before flag initialization");
+  // The alignment used for boundary between young gen and old gen
+  static size_t default_gen_alignment() { return 64 * K * HeapWordSize; }
 
-    // The survivor ratio's are calculated "raw", unlike the
-    // default gc, which adds 2 to the ratio value. We need to
-    // make sure the values are valid before using them.
-    if (MinSurvivorRatio < 3) {
-      MinSurvivorRatio = 3;
-    }
+ protected:
 
-    if (InitialSurvivorRatio < 3) {
-      InitialSurvivorRatio = 3;
-    }
-  }
-
-  size_t min_young_gen_size() { return _min_gen0_size; }
-  size_t young_gen_size()     { return _initial_gen0_size; }
-  size_t max_young_gen_size() { return _max_gen0_size; }
-
-  size_t min_old_gen_size()   { return _min_gen1_size; }
-  size_t old_gen_size()       { return _initial_gen1_size; }
-  size_t max_old_gen_size()   { return _max_gen1_size; }
+  void initialize_alignments();
+  void initialize_flags();
+  void initialize_size_info();
 };
-
 #endif // SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_GENERATIONSIZER_HPP
--- a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp	Fri Nov 15 21:39:27 2013 +0100
@@ -52,76 +52,20 @@
 ParallelScavengeHeap* ParallelScavengeHeap::_psh = NULL;
 GCTaskManager* ParallelScavengeHeap::_gc_task_manager = NULL;
 
-static void trace_gen_sizes(const char* const str,
-                            size_t og_min, size_t og_max,
-                            size_t yg_min, size_t yg_max)
-{
-  if (TracePageSizes) {
-    tty->print_cr("%s:  " SIZE_FORMAT "," SIZE_FORMAT " "
-                  SIZE_FORMAT "," SIZE_FORMAT " "
-                  SIZE_FORMAT,
-                  str,
-                  og_min / K, og_max / K,
-                  yg_min / K, yg_max / K,
-                  (og_max + yg_max) / K);
-  }
-}
-
 jint ParallelScavengeHeap::initialize() {
   CollectedHeap::pre_initialize();
 
-  // Cannot be initialized until after the flags are parsed
-  // GenerationSizer flag_parser;
+  // Initialize collector policy
   _collector_policy = new GenerationSizer();
+  _collector_policy->initialize_all();
 
-  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();
+  const size_t heap_size = _collector_policy->max_heap_byte_size();
 
-  trace_gen_sizes("ps heap raw",
-                  og_min_size, og_max_size,
-                  yg_min_size, yg_max_size);
-
-  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 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);
-  // Align old gen size down to preserve specified heap size.
-  assert(og_align == yg_align, "sanity");
-  og_max_size = align_size_down(og_max_size, og_align);
-  og_max_size = MAX2(og_max_size, og_min_size);
-  size_t og_cur_size =
-    align_size_down(_collector_policy->old_gen_size(), og_align);
-  og_cur_size = MAX2(og_cur_size, og_min_size);
-
-  trace_gen_sizes("ps heap rnd",
-                  og_min_size, og_max_size,
-                  yg_min_size, yg_max_size);
-
-  const size_t heap_size = og_max_size + yg_max_size;
-
-  ReservedSpace heap_rs = Universe::reserve_heap(heap_size, og_align);
-
+  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", og_min_size + yg_min_size,
-                       og_max_size + yg_max_size, og_page_sz,
+  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()) {
@@ -142,12 +86,6 @@
     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);
-
   // Make up the generations
   // Calculate the maximum size that a generation can grow.  This
   // includes growth into the other generation.  Note that the
@@ -157,14 +95,7 @@
   double max_gc_pause_sec = ((double) MaxGCPauseMillis)/1000.0;
   double max_gc_minor_pause_sec = ((double) MaxGCMinorPauseMillis)/1000.0;
 
-  _gens = new AdjoiningGenerations(heap_rs,
-                                   og_cur_size,
-                                   og_min_size,
-                                   og_max_size,
-                                   yg_cur_size,
-                                   yg_min_size,
-                                   yg_max_size,
-                                   yg_align);
+  _gens = new AdjoiningGenerations(heap_rs, _collector_policy, generation_alignment());
 
   _old_gen = _gens->old_gen();
   _young_gen = _gens->young_gen();
@@ -176,7 +107,7 @@
     new PSAdaptiveSizePolicy(eden_capacity,
                              initial_promo_size,
                              young_gen()->to_space()->capacity_in_bytes(),
-                             intra_heap_alignment(),
+                             _collector_policy->gen_alignment(),
                              max_gc_pause_sec,
                              max_gc_minor_pause_sec,
                              GCTimeRatio
--- a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp	Fri Nov 15 21:39:27 2013 +0100
@@ -25,6 +25,7 @@
 #ifndef SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PARALLELSCAVENGEHEAP_HPP
 #define SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PARALLELSCAVENGEHEAP_HPP
 
+#include "gc_implementation/parallelScavenge/generationSizer.hpp"
 #include "gc_implementation/parallelScavenge/objectStartArray.hpp"
 #include "gc_implementation/parallelScavenge/psGCAdaptivePolicyCounters.hpp"
 #include "gc_implementation/parallelScavenge/psOldGen.hpp"
@@ -32,14 +33,12 @@
 #include "gc_implementation/shared/gcPolicyCounters.hpp"
 #include "gc_implementation/shared/gcWhen.hpp"
 #include "gc_interface/collectedHeap.inline.hpp"
+#include "memory/collectorPolicy.hpp"
 #include "utilities/ostream.hpp"
 
 class AdjoiningGenerations;
-class CollectorPolicy;
 class GCHeapSummary;
 class GCTaskManager;
-class GenerationSizer;
-class CollectorPolicy;
 class PSAdaptiveSizePolicy;
 class PSHeapSummary;
 
@@ -50,24 +49,20 @@
   static PSOldGen*   _old_gen;
 
   // Sizing policy for entire heap
-  static PSAdaptiveSizePolicy* _size_policy;
-  static PSGCAdaptivePolicyCounters*   _gc_policy_counters;
+  static PSAdaptiveSizePolicy*       _size_policy;
+  static PSGCAdaptivePolicyCounters* _gc_policy_counters;
 
   static ParallelScavengeHeap* _psh;
 
-  size_t _young_gen_alignment;
-  size_t _old_gen_alignment;
-
   GenerationSizer* _collector_policy;
 
-  inline size_t set_alignment(size_t& var, size_t val);
-
   // Collection of generations that are adjacent in the
   // space reserved for the heap.
   AdjoiningGenerations* _gens;
   unsigned int _death_march_count;
 
-  static GCTaskManager*          _gc_task_manager;      // The task manager.
+  // The task manager
+  static GCTaskManager* _gc_task_manager;
 
   void trace_heap(GCWhen::Type when, GCTracer* tracer);
 
@@ -80,16 +75,7 @@
   HeapWord* mem_allocate_old_gen(size_t size);
 
  public:
-  ParallelScavengeHeap() : CollectedHeap() {
-    _death_march_count = 0;
-    set_alignment(_young_gen_alignment, intra_heap_alignment());
-    set_alignment(_old_gen_alignment, intra_heap_alignment());
-  }
-
-  // Return the (conservative) maximum heap alignment
-  static size_t conservative_max_heap_alignment() {
-    return intra_heap_alignment();
-  }
+  ParallelScavengeHeap() : CollectedHeap(), _death_march_count(0) { }
 
   // For use by VM operations
   enum CollectionType {
@@ -103,8 +89,8 @@
 
   virtual CollectorPolicy* collector_policy() const { return (CollectorPolicy*) _collector_policy; }
 
-  static PSYoungGen* young_gen()     { return _young_gen; }
-  static PSOldGen* old_gen()         { return _old_gen; }
+  static PSYoungGen* young_gen() { return _young_gen; }
+  static PSOldGen* old_gen()     { return _old_gen; }
 
   virtual PSAdaptiveSizePolicy* size_policy() { return _size_policy; }
 
@@ -121,13 +107,15 @@
 
   void post_initialize();
   void update_counters();
-  // The alignment used for the various generations.
-  size_t young_gen_alignment() const { return _young_gen_alignment; }
-  size_t old_gen_alignment()  const { return _old_gen_alignment; }
 
-  // The alignment used for eden and survivors within the young gen
-  // and for boundary between young gen and old gen.
-  static size_t intra_heap_alignment() { return 64 * K * HeapWordSize; }
+  // The alignment used for the various areas
+  size_t space_alignment()      { return _collector_policy->space_alignment(); }
+  size_t generation_alignment() { return _collector_policy->gen_alignment(); }
+
+  // Return the (conservative) maximum heap alignment
+  static size_t conservative_max_heap_alignment() {
+    return CollectorPolicy::compute_heap_alignment();
+  }
 
   size_t capacity() const;
   size_t used() const;
@@ -157,16 +145,15 @@
   virtual bool is_in_partial_collection(const void *p);
 #endif
 
-  bool is_in_young(oop p);        // reserved part
-  bool is_in_old(oop p);          // reserved part
+  bool is_in_young(oop p);  // reserved part
+  bool is_in_old(oop p);    // reserved part
 
   // Memory allocation.   "gc_time_limit_was_exceeded" will
   // be set to true if the adaptive size policy determine that
   // an excessive amount of time is being spent doing collections
   // and caused a NULL to be returned.  If a NULL is not returned,
   // "gc_time_limit_was_exceeded" has an undefined meaning.
-  HeapWord* mem_allocate(size_t size,
-                         bool* gc_overhead_limit_was_exceeded);
+  HeapWord* mem_allocate(size_t size, bool* gc_overhead_limit_was_exceeded);
 
   // Allocation attempt(s) during a safepoint. It should never be called
   // to allocate a new TLAB as this allocation might be satisfied out
@@ -257,17 +244,10 @@
 
   // Call these in sequential code around the processing of strong roots.
   class ParStrongRootsScope : public MarkingCodeBlobClosure::MarkScope {
-  public:
+   public:
     ParStrongRootsScope();
     ~ParStrongRootsScope();
   };
 };
 
-inline size_t ParallelScavengeHeap::set_alignment(size_t& var, size_t val)
-{
-  assert(is_power_of_2((intptr_t)val), "must be a power of 2");
-  var = round_to(val, intra_heap_alignment());
-  return var;
-}
-
 #endif // SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PARALLELSCAVENGEHEAP_HPP
--- a/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp	Fri Nov 15 21:39:27 2013 +0100
@@ -37,7 +37,7 @@
 PSAdaptiveSizePolicy::PSAdaptiveSizePolicy(size_t init_eden_size,
                                            size_t init_promo_size,
                                            size_t init_survivor_size,
-                                           size_t intra_generation_alignment,
+                                           size_t space_alignment,
                                            double gc_pause_goal_sec,
                                            double gc_minor_pause_goal_sec,
                                            uint gc_cost_ratio) :
@@ -46,9 +46,8 @@
                         init_survivor_size,
                         gc_pause_goal_sec,
                         gc_cost_ratio),
-     _collection_cost_margin_fraction(AdaptiveSizePolicyCollectionCostMargin/
-       100.0),
-     _intra_generation_alignment(intra_generation_alignment),
+     _collection_cost_margin_fraction(AdaptiveSizePolicyCollectionCostMargin / 100.0),
+     _space_alignment(space_alignment),
      _live_at_last_full_gc(init_promo_size),
      _gc_minor_pause_goal_sec(gc_minor_pause_goal_sec),
      _latest_major_mutator_interval_seconds(0),
@@ -353,11 +352,10 @@
   }
 
   // Align everything and make a final limit check
-  const size_t alignment = _intra_generation_alignment;
-  desired_eden_size  = align_size_up(desired_eden_size, alignment);
-  desired_eden_size  = MAX2(desired_eden_size, alignment);
+  desired_eden_size  = align_size_up(desired_eden_size, _space_alignment);
+  desired_eden_size  = MAX2(desired_eden_size, _space_alignment);
 
-  eden_limit  = align_size_down(eden_limit, alignment);
+  eden_limit  = align_size_down(eden_limit, _space_alignment);
 
   // And one last limit check, now that we've aligned things.
   if (desired_eden_size > eden_limit) {
@@ -561,11 +559,10 @@
   }
 
   // Align everything and make a final limit check
-  const size_t alignment = _intra_generation_alignment;
-  desired_promo_size = align_size_up(desired_promo_size, alignment);
-  desired_promo_size = MAX2(desired_promo_size, alignment);
+  desired_promo_size = align_size_up(desired_promo_size, _space_alignment);
+  desired_promo_size = MAX2(desired_promo_size, _space_alignment);
 
-  promo_limit = align_size_down(promo_limit, alignment);
+  promo_limit = align_size_down(promo_limit, _space_alignment);
 
   // And one last limit check, now that we've aligned things.
   desired_promo_size = MIN2(desired_promo_size, promo_limit);
@@ -650,7 +647,7 @@
     }
     // If the desired eden size is as small as it will get,
     // try to adjust the old gen size.
-    if (*desired_eden_size_ptr <= _intra_generation_alignment) {
+    if (*desired_eden_size_ptr <= _space_alignment) {
       // Vary the old gen size to reduce the young gen pause.  This
       // may not be a good idea.  This is just a test.
       if (minor_pause_old_estimator()->decrement_will_decrease()) {
@@ -755,7 +752,7 @@
       // If the promo size is at the minimum (i.e., the old gen
       // size will not actually decrease), consider changing the
       // young gen size.
-      if (*desired_promo_size_ptr < _intra_generation_alignment) {
+      if (*desired_promo_size_ptr < _space_alignment) {
         // If increasing the young generation will decrease the old gen
         // pause, do it.
         // During startup there is noise in the statistics for deciding
@@ -1066,24 +1063,24 @@
 
 size_t PSAdaptiveSizePolicy::eden_increment_aligned_up(size_t cur_eden) {
   size_t result = eden_increment(cur_eden, YoungGenerationSizeIncrement);
-  return align_size_up(result, _intra_generation_alignment);
+  return align_size_up(result, _space_alignment);
 }
 
 size_t PSAdaptiveSizePolicy::eden_increment_aligned_down(size_t cur_eden) {
   size_t result = eden_increment(cur_eden);
-  return align_size_down(result, _intra_generation_alignment);
+  return align_size_down(result, _space_alignment);
 }
 
 size_t PSAdaptiveSizePolicy::eden_increment_with_supplement_aligned_up(
   size_t cur_eden) {
   size_t result = eden_increment(cur_eden,
     YoungGenerationSizeIncrement + _young_gen_size_increment_supplement);
-  return align_size_up(result, _intra_generation_alignment);
+  return align_size_up(result, _space_alignment);
 }
 
 size_t PSAdaptiveSizePolicy::eden_decrement_aligned_down(size_t cur_eden) {
   size_t eden_heap_delta = eden_decrement(cur_eden);
-  return align_size_down(eden_heap_delta, _intra_generation_alignment);
+  return align_size_down(eden_heap_delta, _space_alignment);
 }
 
 size_t PSAdaptiveSizePolicy::eden_decrement(size_t cur_eden) {
@@ -1105,24 +1102,24 @@
 
 size_t PSAdaptiveSizePolicy::promo_increment_aligned_up(size_t cur_promo) {
   size_t result =  promo_increment(cur_promo, TenuredGenerationSizeIncrement);
-  return align_size_up(result, _intra_generation_alignment);
+  return align_size_up(result, _space_alignment);
 }
 
 size_t PSAdaptiveSizePolicy::promo_increment_aligned_down(size_t cur_promo) {
   size_t result =  promo_increment(cur_promo, TenuredGenerationSizeIncrement);
-  return align_size_down(result, _intra_generation_alignment);
+  return align_size_down(result, _space_alignment);
 }
 
 size_t PSAdaptiveSizePolicy::promo_increment_with_supplement_aligned_up(
   size_t cur_promo) {
   size_t result =  promo_increment(cur_promo,
     TenuredGenerationSizeIncrement + _old_gen_size_increment_supplement);
-  return align_size_up(result, _intra_generation_alignment);
+  return align_size_up(result, _space_alignment);
 }
 
 size_t PSAdaptiveSizePolicy::promo_decrement_aligned_down(size_t cur_promo) {
   size_t promo_heap_delta = promo_decrement(cur_promo);
-  return align_size_down(promo_heap_delta, _intra_generation_alignment);
+  return align_size_down(promo_heap_delta, _space_alignment);
 }
 
 size_t PSAdaptiveSizePolicy::promo_decrement(size_t cur_promo) {
@@ -1135,9 +1132,9 @@
                                              bool is_survivor_overflow,
                                              uint tenuring_threshold,
                                              size_t survivor_limit) {
-  assert(survivor_limit >= _intra_generation_alignment,
+  assert(survivor_limit >= _space_alignment,
          "survivor_limit too small");
-  assert((size_t)align_size_down(survivor_limit, _intra_generation_alignment)
+  assert((size_t)align_size_down(survivor_limit, _space_alignment)
          == survivor_limit, "survivor_limit not aligned");
 
   // This method is called even if the tenuring threshold and survivor
@@ -1201,8 +1198,8 @@
   // We're trying to pad the survivor size as little as possible without
   // overflowing the survivor spaces.
   size_t target_size = align_size_up((size_t)_avg_survived->padded_average(),
-                                     _intra_generation_alignment);
-  target_size = MAX2(target_size, _intra_generation_alignment);
+                                     _space_alignment);
+  target_size = MAX2(target_size, _space_alignment);
 
   if (target_size > survivor_limit) {
     // Target size is bigger than we can handle. Let's also reduce
--- a/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp	Fri Nov 15 21:39:27 2013 +0100
@@ -91,7 +91,7 @@
   // for making ergonomic decisions.
   double _latest_major_mutator_interval_seconds;
 
-  const size_t _intra_generation_alignment; // alignment for eden, survivors
+  const size_t _space_alignment; // alignment for eden, survivors
 
   const double _gc_minor_pause_goal_sec;    // goal for maximum minor gc pause
 
@@ -229,7 +229,7 @@
   PSAdaptiveSizePolicy(size_t init_eden_size,
                        size_t init_promo_size,
                        size_t init_survivor_size,
-                       size_t intra_generation_alignment,
+                       size_t space_alignment,
                        double gc_pause_goal_sec,
                        double gc_minor_pause_goal_sec,
                        uint gc_time_ratio);
@@ -378,7 +378,7 @@
     // remain almost full anyway (top() will be near end(), but there will be a
     // large filler object at the bottom).
     const size_t sz = gen_size / MinSurvivorRatio;
-    const size_t alignment = _intra_generation_alignment;
+    const size_t alignment = _space_alignment;
     return sz > alignment ? align_size_down(sz, alignment) : alignment;
   }
 
--- a/src/share/vm/gc_implementation/parallelScavenge/psYoungGen.cpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/gc_implementation/parallelScavenge/psYoungGen.cpp	Fri Nov 15 21:39:27 2013 +0100
@@ -103,7 +103,7 @@
 
   // Compute maximum space sizes for performance counters
   ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
-  size_t alignment = heap->intra_heap_alignment();
+  size_t alignment = heap->space_alignment();
   size_t size = virtual_space()->reserved_size();
 
   size_t max_survivor_size;
@@ -156,8 +156,9 @@
   assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity");
 
   // Compute sizes
-  size_t alignment = heap->intra_heap_alignment();
+  size_t alignment = heap->space_alignment();
   size_t size = virtual_space()->committed_size();
+  assert(size >= 3 * alignment, "Young space is not large enough for eden + 2 survivors");
 
   size_t survivor_size = size / InitialSurvivorRatio;
   survivor_size = align_size_down(survivor_size, alignment);
@@ -207,7 +208,7 @@
 #ifndef PRODUCT
 void PSYoungGen::space_invariants() {
   ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
-  const size_t alignment = heap->intra_heap_alignment();
+  const size_t alignment = heap->space_alignment();
 
   // Currently, our eden size cannot shrink to zero
   guarantee(eden_space()->capacity_in_bytes() >= alignment, "eden too small");
@@ -491,7 +492,7 @@
   char* to_end     = (char*)to_space()->end();
 
   ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
-  const size_t alignment = heap->intra_heap_alignment();
+  const size_t alignment = heap->space_alignment();
   const bool maintain_minimum =
     (requested_eden_size + 2 * requested_survivor_size) <= min_gen_size();
 
@@ -840,8 +841,8 @@
 size_t PSYoungGen::available_to_live() {
   size_t delta_in_survivor = 0;
   ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
-  const size_t space_alignment = heap->intra_heap_alignment();
-  const size_t gen_alignment = heap->young_gen_alignment();
+  const size_t space_alignment = heap->space_alignment();
+  const size_t gen_alignment = heap->generation_alignment();
 
   MutableSpace* space_shrinking = NULL;
   if (from_space()->end() > to_space()->end()) {
--- a/src/share/vm/gc_interface/collectedHeap.cpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/gc_interface/collectedHeap.cpp	Fri Nov 15 21:39:27 2013 +0100
@@ -469,6 +469,10 @@
   fill_with_object_impl(start, words, zap);
 }
 
+void CollectedHeap::post_initialize() {
+  collector_policy()->post_heap_initialize();
+}
+
 HeapWord* CollectedHeap::allocate_new_tlab(size_t size) {
   guarantee(false, "thread-local allocation buffers not supported");
   return NULL;
--- a/src/share/vm/memory/collectorPolicy.cpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/memory/collectorPolicy.cpp	Fri Nov 15 21:39:27 2013 +0100
@@ -47,54 +47,107 @@
 
 // CollectorPolicy methods.
 
+CollectorPolicy::CollectorPolicy() :
+    _space_alignment(0),
+    _heap_alignment(0),
+    _initial_heap_byte_size(InitialHeapSize),
+    _max_heap_byte_size(MaxHeapSize),
+    _min_heap_byte_size(Arguments::min_heap_size()),
+    _max_heap_size_cmdline(false),
+    _size_policy(NULL),
+    _should_clear_all_soft_refs(false),
+    _all_soft_refs_clear(false)
+{}
+
+#ifdef ASSERT
+void CollectorPolicy::assert_flags() {
+  assert(InitialHeapSize <= MaxHeapSize, "Ergonomics decided on incompatible initial and maximum heap sizes");
+  assert(InitialHeapSize % _heap_alignment == 0, "InitialHeapSize alignment");
+  assert(MaxHeapSize % _heap_alignment == 0, "MaxHeapSize alignment");
+}
+
+void CollectorPolicy::assert_size_info() {
+  assert(InitialHeapSize == _initial_heap_byte_size, "Discrepancy between InitialHeapSize flag and local storage");
+  assert(MaxHeapSize == _max_heap_byte_size, "Discrepancy between MaxHeapSize flag and local storage");
+  assert(_max_heap_byte_size >= _min_heap_byte_size, "Ergonomics decided on incompatible minimum and maximum heap sizes");
+  assert(_initial_heap_byte_size >= _min_heap_byte_size, "Ergonomics decided on incompatible initial and minimum heap sizes");
+  assert(_max_heap_byte_size >= _initial_heap_byte_size, "Ergonomics decided on incompatible initial and maximum heap sizes");
+  assert(_min_heap_byte_size % _heap_alignment == 0, "min_heap_byte_size alignment");
+  assert(_initial_heap_byte_size % _heap_alignment == 0, "initial_heap_byte_size alignment");
+  assert(_max_heap_byte_size % _heap_alignment == 0, "max_heap_byte_size alignment");
+}
+#endif // ASSERT
+
 void CollectorPolicy::initialize_flags() {
-  assert(_max_alignment >= _min_alignment,
-         err_msg("max_alignment: " SIZE_FORMAT " less than min_alignment: " SIZE_FORMAT,
-                 _max_alignment, _min_alignment));
-  assert(_max_alignment % _min_alignment == 0,
-         err_msg("max_alignment: " SIZE_FORMAT " not aligned by min_alignment: " SIZE_FORMAT,
-                 _max_alignment, _min_alignment));
+  assert(_space_alignment != 0, "Space alignment not set up properly");
+  assert(_heap_alignment != 0, "Heap alignment not set up properly");
+  assert(_heap_alignment >= _space_alignment,
+         err_msg("heap_alignment: " SIZE_FORMAT " less than space_alignment: " SIZE_FORMAT,
+                 _heap_alignment, _space_alignment));
+  assert(_heap_alignment % _space_alignment == 0,
+         err_msg("heap_alignment: " SIZE_FORMAT " not aligned by space_alignment: " SIZE_FORMAT,
+                 _heap_alignment, _space_alignment));
 
-  if (MaxHeapSize < InitialHeapSize) {
-    vm_exit_during_initialization("Incompatible initial and maximum heap sizes specified");
+  if (FLAG_IS_CMDLINE(MaxHeapSize)) {
+    if (FLAG_IS_CMDLINE(InitialHeapSize) && InitialHeapSize > MaxHeapSize) {
+      vm_exit_during_initialization("Initial heap size set to a larger value than the maximum heap size");
+    }
+    if (_min_heap_byte_size != 0 && MaxHeapSize < _min_heap_byte_size) {
+      vm_exit_during_initialization("Incompatible minimum and maximum heap sizes specified");
+    }
+    _max_heap_size_cmdline = true;
   }
 
-  MinHeapDeltaBytes = align_size_up(MinHeapDeltaBytes, _min_alignment);
+  // Check heap parameter properties
+  if (InitialHeapSize < M) {
+    vm_exit_during_initialization("Too small initial heap");
+  }
+  if (_min_heap_byte_size < M) {
+    vm_exit_during_initialization("Too small minimum heap");
+  }
+
+  // User inputs from -Xmx and -Xms must be aligned
+  _min_heap_byte_size = align_size_up(_min_heap_byte_size, _heap_alignment);
+  uintx aligned_initial_heap_size = align_size_up(InitialHeapSize, _heap_alignment);
+  uintx aligned_max_heap_size = align_size_up(MaxHeapSize, _heap_alignment);
+
+  // Write back to flags if the values changed
+  if (aligned_initial_heap_size != InitialHeapSize) {
+    FLAG_SET_ERGO(uintx, InitialHeapSize, aligned_initial_heap_size);
+  }
+  if (aligned_max_heap_size != MaxHeapSize) {
+    FLAG_SET_ERGO(uintx, MaxHeapSize, aligned_max_heap_size);
+  }
+
+  if (FLAG_IS_CMDLINE(InitialHeapSize) && _min_heap_byte_size != 0 &&
+      InitialHeapSize < _min_heap_byte_size) {
+    vm_exit_during_initialization("Incompatible minimum and initial heap sizes specified");
+  }
+  if (!FLAG_IS_DEFAULT(InitialHeapSize) && InitialHeapSize > MaxHeapSize) {
+    FLAG_SET_ERGO(uintx, MaxHeapSize, InitialHeapSize);
+  } else if (!FLAG_IS_DEFAULT(MaxHeapSize) && InitialHeapSize > MaxHeapSize) {
+    FLAG_SET_ERGO(uintx, InitialHeapSize, MaxHeapSize);
+    if (InitialHeapSize < _min_heap_byte_size) {
+      _min_heap_byte_size = InitialHeapSize;
+    }
+  }
+
+  _initial_heap_byte_size = InitialHeapSize;
+  _max_heap_byte_size = MaxHeapSize;
+
+  FLAG_SET_ERGO(uintx, MinHeapDeltaBytes, align_size_up(MinHeapDeltaBytes, _space_alignment));
+
+  DEBUG_ONLY(CollectorPolicy::assert_flags();)
 }
 
 void CollectorPolicy::initialize_size_info() {
-  // User inputs from -mx and ms must be aligned
-  _min_heap_byte_size = align_size_up(Arguments::min_heap_size(), _min_alignment);
-  _initial_heap_byte_size = align_size_up(InitialHeapSize, _min_alignment);
-  _max_heap_byte_size = align_size_up(MaxHeapSize, _max_alignment);
-
-  // Check heap parameter properties
-  if (_initial_heap_byte_size < M) {
-    vm_exit_during_initialization("Too small initial heap");
-  }
-  // Check heap parameter properties
-  if (_min_heap_byte_size < M) {
-    vm_exit_during_initialization("Too small minimum heap");
-  }
-  if (_initial_heap_byte_size <= NewSize) {
-     // make sure there is at least some room in old space
-    vm_exit_during_initialization("Too small initial heap for new size specified");
-  }
-  if (_max_heap_byte_size < _min_heap_byte_size) {
-    vm_exit_during_initialization("Incompatible minimum and maximum heap sizes specified");
-  }
-  if (_initial_heap_byte_size < _min_heap_byte_size) {
-    vm_exit_during_initialization("Incompatible minimum and initial heap sizes specified");
-  }
-  if (_max_heap_byte_size < _initial_heap_byte_size) {
-    vm_exit_during_initialization("Incompatible initial and maximum heap sizes specified");
-  }
-
   if (PrintGCDetails && Verbose) {
     gclog_or_tty->print_cr("Minimum heap " SIZE_FORMAT "  Initial heap "
       SIZE_FORMAT "  Maximum heap " SIZE_FORMAT,
       _min_heap_byte_size, _initial_heap_byte_size, _max_heap_byte_size);
   }
+
+  DEBUG_ONLY(CollectorPolicy::assert_size_info();)
 }
 
 bool CollectorPolicy::use_should_clear_all_soft_refs(bool v) {
@@ -105,7 +158,6 @@
 
 GenRemSet* CollectorPolicy::create_rem_set(MemRegion whole_heap,
                                            int max_covered_regions) {
-  assert(rem_set_name() == GenRemSet::CardTable, "unrecognized GenRemSet::Name");
   return new CardTableRS(whole_heap, max_covered_regions);
 }
 
@@ -119,7 +171,7 @@
   _all_soft_refs_clear = true;
 }
 
-size_t CollectorPolicy::compute_max_alignment() {
+size_t CollectorPolicy::compute_heap_alignment() {
   // The card marking array and the offset arrays for old generations are
   // committed in os pages as well. Make sure they are entirely full (to
   // avoid partial page problems), e.g. if 512 bytes heap corresponds to 1
@@ -146,18 +198,21 @@
 
 // GenCollectorPolicy methods.
 
+GenCollectorPolicy::GenCollectorPolicy() :
+    _min_gen0_size(0),
+    _initial_gen0_size(0),
+    _max_gen0_size(0),
+    _gen_alignment(0),
+    _generations(NULL)
+{}
+
 size_t GenCollectorPolicy::scale_by_NewRatio_aligned(size_t base_size) {
-  size_t x = base_size / (NewRatio+1);
-  size_t new_gen_size = x > _min_alignment ?
-                     align_size_down(x, _min_alignment) :
-                     _min_alignment;
-  return new_gen_size;
+  return align_size_down_bounded(base_size / (NewRatio + 1), _gen_alignment);
 }
 
 size_t GenCollectorPolicy::bound_minus_alignment(size_t desired_size,
                                                  size_t maximum_size) {
-  size_t alignment = _min_alignment;
-  size_t max_minus = maximum_size - alignment;
+  size_t max_minus = maximum_size - _gen_alignment;
   return desired_size < max_minus ? desired_size : max_minus;
 }
 
@@ -165,7 +220,7 @@
 void GenCollectorPolicy::initialize_size_policy(size_t init_eden_size,
                                                 size_t init_promo_size,
                                                 size_t init_survivor_size) {
-  const double max_gc_pause_sec = ((double) MaxGCPauseMillis)/1000.0;
+  const double max_gc_pause_sec = ((double) MaxGCPauseMillis) / 1000.0;
   _size_policy = new AdaptiveSizePolicy(init_eden_size,
                                         init_promo_size,
                                         init_survivor_size,
@@ -173,100 +228,181 @@
                                         GCTimeRatio);
 }
 
+size_t GenCollectorPolicy::young_gen_size_lower_bound() {
+  // The young generation must be aligned and have room for eden + two survivors
+  return align_size_up(3 * _space_alignment, _gen_alignment);
+}
+
+#ifdef ASSERT
+void GenCollectorPolicy::assert_flags() {
+  CollectorPolicy::assert_flags();
+  assert(NewSize >= _min_gen0_size, "Ergonomics decided on a too small young gen size");
+  assert(NewSize <= MaxNewSize, "Ergonomics decided on incompatible initial and maximum young gen sizes");
+  assert(FLAG_IS_DEFAULT(MaxNewSize) || MaxNewSize < MaxHeapSize, "Ergonomics decided on incompatible maximum young gen and heap sizes");
+  assert(NewSize % _gen_alignment == 0, "NewSize alignment");
+  assert(FLAG_IS_DEFAULT(MaxNewSize) || MaxNewSize % _gen_alignment == 0, "MaxNewSize alignment");
+}
+
+void TwoGenerationCollectorPolicy::assert_flags() {
+  GenCollectorPolicy::assert_flags();
+  assert(OldSize + NewSize <= MaxHeapSize, "Ergonomics decided on incompatible generation and heap sizes");
+  assert(OldSize % _gen_alignment == 0, "OldSize alignment");
+}
+
+void GenCollectorPolicy::assert_size_info() {
+  CollectorPolicy::assert_size_info();
+  // GenCollectorPolicy::initialize_size_info may update the MaxNewSize
+  assert(MaxNewSize < MaxHeapSize, "Ergonomics decided on incompatible maximum young and heap sizes");
+  assert(NewSize == _initial_gen0_size, "Discrepancy between NewSize flag and local storage");
+  assert(MaxNewSize == _max_gen0_size, "Discrepancy between MaxNewSize flag and local storage");
+  assert(_min_gen0_size <= _initial_gen0_size, "Ergonomics decided on incompatible minimum and initial young gen sizes");
+  assert(_initial_gen0_size <= _max_gen0_size, "Ergonomics decided on incompatible initial and maximum young gen sizes");
+  assert(_min_gen0_size % _gen_alignment == 0, "_min_gen0_size alignment");
+  assert(_initial_gen0_size % _gen_alignment == 0, "_initial_gen0_size alignment");
+  assert(_max_gen0_size % _gen_alignment == 0, "_max_gen0_size alignment");
+}
+
+void TwoGenerationCollectorPolicy::assert_size_info() {
+  GenCollectorPolicy::assert_size_info();
+  assert(OldSize == _initial_gen1_size, "Discrepancy between OldSize flag and local storage");
+  assert(_min_gen1_size <= _initial_gen1_size, "Ergonomics decided on incompatible minimum and initial old gen sizes");
+  assert(_initial_gen1_size <= _max_gen1_size, "Ergonomics decided on incompatible initial and maximum old gen sizes");
+  assert(_max_gen1_size % _gen_alignment == 0, "_max_gen1_size alignment");
+  assert(_initial_gen1_size % _gen_alignment == 0, "_initial_gen1_size alignment");
+  assert(_max_heap_byte_size <= (_max_gen0_size + _max_gen1_size), "Total maximum heap sizes must be sum of generation maximum sizes");
+}
+#endif // ASSERT
+
 void GenCollectorPolicy::initialize_flags() {
-  // All sizes must be multiples of the generation granularity.
-  _min_alignment = (uintx) Generation::GenGrain;
-  _max_alignment = compute_max_alignment();
-
   CollectorPolicy::initialize_flags();
 
-  // All generational heaps have a youngest gen; handle those flags here.
+  assert(_gen_alignment != 0, "Generation alignment not set up properly");
+  assert(_heap_alignment >= _gen_alignment,
+         err_msg("heap_alignment: " SIZE_FORMAT " less than gen_alignment: " SIZE_FORMAT,
+                 _heap_alignment, _gen_alignment));
+  assert(_gen_alignment % _space_alignment == 0,
+         err_msg("gen_alignment: " SIZE_FORMAT " not aligned by space_alignment: " SIZE_FORMAT,
+                 _gen_alignment, _space_alignment));
+  assert(_heap_alignment % _gen_alignment == 0,
+         err_msg("heap_alignment: " SIZE_FORMAT " not aligned by gen_alignment: " SIZE_FORMAT,
+                 _heap_alignment, _gen_alignment));
 
-  // Adjust max size parameters
+  // All generational heaps have a youngest gen; handle those flags here
+
+  // Make sure the heap is large enough for two generations
+  uintx smallest_new_size = young_gen_size_lower_bound();
+  uintx smallest_heap_size = align_size_up(smallest_new_size + align_size_up(_space_alignment, _gen_alignment),
+                                           _heap_alignment);
+  if (MaxHeapSize < smallest_heap_size) {
+    FLAG_SET_ERGO(uintx, MaxHeapSize, smallest_heap_size);
+    _max_heap_byte_size = MaxHeapSize;
+  }
+  // If needed, synchronize _min_heap_byte size and _initial_heap_byte_size
+  if (_min_heap_byte_size < smallest_heap_size) {
+    _min_heap_byte_size = smallest_heap_size;
+    if (InitialHeapSize < _min_heap_byte_size) {
+      FLAG_SET_ERGO(uintx, InitialHeapSize, smallest_heap_size);
+      _initial_heap_byte_size = smallest_heap_size;
+    }
+  }
+
+  // Now take the actual NewSize into account. We will silently increase NewSize
+  // if the user specified a smaller value.
+  smallest_new_size = MAX2(smallest_new_size, (uintx)align_size_down(NewSize, _gen_alignment));
+  if (smallest_new_size != NewSize) {
+    FLAG_SET_ERGO(uintx, NewSize, smallest_new_size);
+  }
+  _initial_gen0_size = NewSize;
+
+  if (!FLAG_IS_DEFAULT(MaxNewSize)) {
+    uintx min_new_size = MAX2(_gen_alignment, _min_gen0_size);
+
+    if (MaxNewSize >= MaxHeapSize) {
+      // Make sure there is room for an old generation
+      uintx smaller_max_new_size = MaxHeapSize - _gen_alignment;
+      if (FLAG_IS_CMDLINE(MaxNewSize)) {
+        warning("MaxNewSize (" SIZE_FORMAT "k) is equal to or greater than the entire "
+                "heap (" SIZE_FORMAT "k).  A new max generation size of " SIZE_FORMAT "k will be used.",
+                MaxNewSize/K, MaxHeapSize/K, smaller_max_new_size/K);
+      }
+      FLAG_SET_ERGO(uintx, MaxNewSize, smaller_max_new_size);
+      if (NewSize > MaxNewSize) {
+        FLAG_SET_ERGO(uintx, NewSize, MaxNewSize);
+        _initial_gen0_size = NewSize;
+      }
+    } else if (MaxNewSize < min_new_size) {
+      FLAG_SET_ERGO(uintx, MaxNewSize, min_new_size);
+    } else if (!is_size_aligned(MaxNewSize, _gen_alignment)) {
+      FLAG_SET_ERGO(uintx, MaxNewSize, align_size_down(MaxNewSize, _gen_alignment));
+    }
+    _max_gen0_size = MaxNewSize;
+  }
+
   if (NewSize > MaxNewSize) {
-    MaxNewSize = NewSize;
+    // At this point this should only happen if the user specifies a large NewSize and/or
+    // a small (but not too small) MaxNewSize.
+    if (FLAG_IS_CMDLINE(MaxNewSize)) {
+      warning("NewSize (" SIZE_FORMAT "k) is greater than the MaxNewSize (" SIZE_FORMAT "k). "
+              "A new max generation size of " SIZE_FORMAT "k will be used.",
+              NewSize/K, MaxNewSize/K, NewSize/K);
+    }
+    FLAG_SET_ERGO(uintx, MaxNewSize, NewSize);
+    _max_gen0_size = MaxNewSize;
   }
-  NewSize = align_size_down(NewSize, _min_alignment);
-  MaxNewSize = align_size_down(MaxNewSize, _min_alignment);
 
-  // Check validity of heap flags
-  assert(NewSize     % _min_alignment == 0, "eden space alignment");
-  assert(MaxNewSize  % _min_alignment == 0, "survivor space alignment");
-
-  if (NewSize < 3 * _min_alignment) {
-     // make sure there room for eden and two survivor spaces
-    vm_exit_during_initialization("Too small new size specified");
-  }
   if (SurvivorRatio < 1 || NewRatio < 1) {
     vm_exit_during_initialization("Invalid young gen ratio specified");
   }
+
+  DEBUG_ONLY(GenCollectorPolicy::assert_flags();)
 }
 
 void TwoGenerationCollectorPolicy::initialize_flags() {
   GenCollectorPolicy::initialize_flags();
 
-  OldSize = align_size_down(OldSize, _min_alignment);
+  if (!is_size_aligned(OldSize, _gen_alignment)) {
+    FLAG_SET_ERGO(uintx, OldSize, align_size_down(OldSize, _gen_alignment));
+  }
 
-  if (FLAG_IS_CMDLINE(OldSize) && FLAG_IS_DEFAULT(NewSize)) {
+  if (FLAG_IS_CMDLINE(OldSize) && FLAG_IS_DEFAULT(MaxHeapSize)) {
     // NewRatio will be used later to set the young generation size so we use
     // it to calculate how big the heap should be based on the requested OldSize
     // and NewRatio.
     assert(NewRatio > 0, "NewRatio should have been set up earlier");
     size_t calculated_heapsize = (OldSize / NewRatio) * (NewRatio + 1);
 
-    calculated_heapsize = align_size_up(calculated_heapsize, _max_alignment);
-    MaxHeapSize = calculated_heapsize;
-    InitialHeapSize = calculated_heapsize;
+    calculated_heapsize = align_size_up(calculated_heapsize, _heap_alignment);
+    FLAG_SET_ERGO(uintx, MaxHeapSize, calculated_heapsize);
+    _max_heap_byte_size = MaxHeapSize;
+    FLAG_SET_ERGO(uintx, InitialHeapSize, calculated_heapsize);
+    _initial_heap_byte_size = InitialHeapSize;
   }
-  MaxHeapSize = align_size_up(MaxHeapSize, _max_alignment);
 
   // adjust max heap size if necessary
   if (NewSize + OldSize > MaxHeapSize) {
-    if (FLAG_IS_CMDLINE(MaxHeapSize)) {
+    if (_max_heap_size_cmdline) {
       // somebody set a maximum heap size with the intention that we should not
       // exceed it. Adjust New/OldSize as necessary.
       uintx calculated_size = NewSize + OldSize;
       double shrink_factor = (double) MaxHeapSize / calculated_size;
-      // align
-      NewSize = align_size_down((uintx) (NewSize * shrink_factor), _min_alignment);
+      uintx smaller_new_size = align_size_down((uintx)(NewSize * shrink_factor), _gen_alignment);
+      FLAG_SET_ERGO(uintx, NewSize, MAX2(young_gen_size_lower_bound(), smaller_new_size));
+      _initial_gen0_size = NewSize;
+
       // OldSize is already aligned because above we aligned MaxHeapSize to
-      // _max_alignment, and we just made sure that NewSize is aligned to
-      // _min_alignment. In initialize_flags() we verified that _max_alignment
-      // is a multiple of _min_alignment.
-      OldSize = MaxHeapSize - NewSize;
+      // _heap_alignment, and we just made sure that NewSize is aligned to
+      // _gen_alignment. In initialize_flags() we verified that _heap_alignment
+      // is a multiple of _gen_alignment.
+      FLAG_SET_ERGO(uintx, OldSize, MaxHeapSize - NewSize);
     } else {
-      MaxHeapSize = NewSize + OldSize;
+      FLAG_SET_ERGO(uintx, MaxHeapSize, align_size_up(NewSize + OldSize, _heap_alignment));
+      _max_heap_byte_size = MaxHeapSize;
     }
   }
-  // need to do this again
-  MaxHeapSize = align_size_up(MaxHeapSize, _max_alignment);
-
-  // adjust max heap size if necessary
-  if (NewSize + OldSize > MaxHeapSize) {
-    if (FLAG_IS_CMDLINE(MaxHeapSize)) {
-      // somebody set a maximum heap size with the intention that we should not
-      // exceed it. Adjust New/OldSize as necessary.
-      uintx calculated_size = NewSize + OldSize;
-      double shrink_factor = (double) MaxHeapSize / calculated_size;
-      // align
-      NewSize = align_size_down((uintx) (NewSize * shrink_factor), _min_alignment);
-      // OldSize is already aligned because above we aligned MaxHeapSize to
-      // _max_alignment, and we just made sure that NewSize is aligned to
-      // _min_alignment. In initialize_flags() we verified that _max_alignment
-      // is a multiple of _min_alignment.
-      OldSize = MaxHeapSize - NewSize;
-    } else {
-      MaxHeapSize = NewSize + OldSize;
-    }
-  }
-  // need to do this again
-  MaxHeapSize = align_size_up(MaxHeapSize, _max_alignment);
 
   always_do_update_barrier = UseConcMarkSweepGC;
 
-  // Check validity of heap flags
-  assert(OldSize     % _min_alignment == 0, "old space alignment");
-  assert(MaxHeapSize % _max_alignment == 0, "maximum heap alignment");
+  DEBUG_ONLY(TwoGenerationCollectorPolicy::assert_flags();)
 }
 
 // Values set on the command line win over any ergonomically
@@ -281,7 +417,7 @@
 void GenCollectorPolicy::initialize_size_info() {
   CollectorPolicy::initialize_size_info();
 
-  // _min_alignment is used for alignment within a generation.
+  // _space_alignment is used for alignment within a generation.
   // There is additional alignment done down stream for some
   // collectors that sometimes causes unwanted rounding up of
   // generations sizes.
@@ -289,35 +425,8 @@
   // Determine maximum size of gen0
 
   size_t max_new_size = 0;
-  if (FLAG_IS_CMDLINE(MaxNewSize) || FLAG_IS_ERGO(MaxNewSize)) {
-    if (MaxNewSize < _min_alignment) {
-      max_new_size = _min_alignment;
-    }
-    if (MaxNewSize >= _max_heap_byte_size) {
-      max_new_size = align_size_down(_max_heap_byte_size - _min_alignment,
-                                     _min_alignment);
-      warning("MaxNewSize (" SIZE_FORMAT "k) is equal to or "
-        "greater than the entire heap (" SIZE_FORMAT "k).  A "
-        "new generation size of " SIZE_FORMAT "k will be used.",
-        MaxNewSize/K, _max_heap_byte_size/K, max_new_size/K);
-    } else {
-      max_new_size = align_size_down(MaxNewSize, _min_alignment);
-    }
-
-  // The case for FLAG_IS_ERGO(MaxNewSize) could be treated
-  // specially at this point to just use an ergonomically set
-  // MaxNewSize to set max_new_size.  For cases with small
-  // heaps such a policy often did not work because the MaxNewSize
-  // was larger than the entire heap.  The interpretation given
-  // to ergonomically set flags is that the flags are set
-  // by different collectors for their own special needs but
-  // are not allowed to badly shape the heap.  This allows the
-  // different collectors to decide what's best for themselves
-  // without having to factor in the overall heap shape.  It
-  // can be the case in the future that the collectors would
-  // only make "wise" ergonomics choices and this policy could
-  // just accept those choices.  The choices currently made are
-  // not always "wise".
+  if (!FLAG_IS_DEFAULT(MaxNewSize)) {
+    max_new_size = MaxNewSize;
   } else {
     max_new_size = scale_by_NewRatio_aligned(_max_heap_byte_size);
     // Bound the maximum size by NewSize below (since it historically
@@ -386,11 +495,22 @@
     _min_gen0_size = MIN2(_min_gen0_size, _initial_gen0_size);
   }
 
+  // Write back to flags if necessary
+  if (NewSize != _initial_gen0_size) {
+    FLAG_SET_ERGO(uintx, NewSize, _initial_gen0_size);
+  }
+
+  if (MaxNewSize != _max_gen0_size) {
+    FLAG_SET_ERGO(uintx, MaxNewSize, _max_gen0_size);
+  }
+
   if (PrintGCDetails && Verbose) {
     gclog_or_tty->print_cr("1: Minimum gen0 " SIZE_FORMAT "  Initial gen0 "
       SIZE_FORMAT "  Maximum gen0 " SIZE_FORMAT,
       _min_gen0_size, _initial_gen0_size, _max_gen0_size);
   }
+
+  DEBUG_ONLY(GenCollectorPolicy::assert_size_info();)
 }
 
 // Call this method during the sizing of the gen1 to make
@@ -403,23 +523,18 @@
 // keeping it simple also seems a worthwhile goal.
 bool TwoGenerationCollectorPolicy::adjust_gen0_sizes(size_t* gen0_size_ptr,
                                                      size_t* gen1_size_ptr,
-                                                     const size_t heap_size,
-                                                     const size_t min_gen1_size) {
+                                                     const size_t heap_size) {
   bool result = false;
 
-  if ((*gen1_size_ptr + *gen0_size_ptr) > heap_size) {
-    if ((heap_size < (*gen0_size_ptr + min_gen1_size)) &&
-        (heap_size >= min_gen1_size + _min_alignment)) {
-      // Adjust gen0 down to accommodate min_gen1_size
-      *gen0_size_ptr = heap_size - min_gen1_size;
-      *gen0_size_ptr =
-        MAX2((uintx)align_size_down(*gen0_size_ptr, _min_alignment), _min_alignment);
-      assert(*gen0_size_ptr > 0, "Min gen0 is too large");
+  if ((*gen0_size_ptr + *gen1_size_ptr) > heap_size) {
+    uintx smallest_new_size = young_gen_size_lower_bound();
+    if ((heap_size < (*gen0_size_ptr + _min_gen1_size)) &&
+        (heap_size >= _min_gen1_size + smallest_new_size)) {
+      // Adjust gen0 down to accommodate _min_gen1_size
+      *gen0_size_ptr = align_size_down_bounded(heap_size - _min_gen1_size, _gen_alignment);
       result = true;
     } else {
-      *gen1_size_ptr = heap_size - *gen0_size_ptr;
-      *gen1_size_ptr =
-        MAX2((uintx)align_size_down(*gen1_size_ptr, _min_alignment), _min_alignment);
+      *gen1_size_ptr = align_size_down_bounded(heap_size - *gen0_size_ptr, _gen_alignment);
     }
   }
   return result;
@@ -440,41 +555,36 @@
   // The maximum gen1 size can be determined from the maximum gen0
   // and maximum heap size since no explicit flags exits
   // for setting the gen1 maximum.
-  _max_gen1_size = _max_heap_byte_size - _max_gen0_size;
-  _max_gen1_size =
-    MAX2((uintx)align_size_down(_max_gen1_size, _min_alignment), _min_alignment);
+  _max_gen1_size = MAX2(_max_heap_byte_size - _max_gen0_size, _gen_alignment);
+
   // If no explicit command line flag has been set for the
   // gen1 size, use what is left for gen1.
-  if (FLAG_IS_DEFAULT(OldSize) || FLAG_IS_ERGO(OldSize)) {
-    // The user has not specified any value or ergonomics
-    // has chosen a value (which may or may not be consistent
+  if (!FLAG_IS_CMDLINE(OldSize)) {
+    // The user has not specified any value but the ergonomics
+    // may have chosen a value (which may or may not be consistent
     // with the overall heap size).  In either case make
     // the minimum, maximum and initial sizes consistent
     // with the gen0 sizes and the overall heap sizes.
-    assert(_min_heap_byte_size > _min_gen0_size,
-      "gen0 has an unexpected minimum size");
-    _min_gen1_size = _min_heap_byte_size - _min_gen0_size;
-    _min_gen1_size =
-      MAX2((uintx)align_size_down(_min_gen1_size, _min_alignment), _min_alignment);
-    _initial_gen1_size = _initial_heap_byte_size - _initial_gen0_size;
-    _initial_gen1_size =
-      MAX2((uintx)align_size_down(_initial_gen1_size, _min_alignment), _min_alignment);
+    _min_gen1_size = MAX2(_min_heap_byte_size - _min_gen0_size, _gen_alignment);
+    _initial_gen1_size = MAX2(_initial_heap_byte_size - _initial_gen0_size, _gen_alignment);
+    // _max_gen1_size has already been made consistent above
+    FLAG_SET_ERGO(uintx, OldSize, _initial_gen1_size);
   } else {
     // It's been explicitly set on the command line.  Use the
     // OldSize and then determine the consequences.
-    _min_gen1_size = OldSize;
+    _min_gen1_size = MIN2(OldSize, _min_heap_byte_size - _min_gen0_size);
     _initial_gen1_size = OldSize;
 
     // If the user has explicitly set an OldSize that is inconsistent
     // with other command line flags, issue a warning.
     // The generation minimums and the overall heap mimimum should
-    // be within one heap alignment.
-    if ((_min_gen1_size + _min_gen0_size + _min_alignment) < _min_heap_byte_size) {
+    // be within one generation alignment.
+    if ((_min_gen1_size + _min_gen0_size + _gen_alignment) < _min_heap_byte_size) {
       warning("Inconsistency between minimum heap size and minimum "
               "generation sizes: using minimum heap = " SIZE_FORMAT,
               _min_heap_byte_size);
     }
-    if ((OldSize > _max_gen1_size)) {
+    if (OldSize > _max_gen1_size) {
       warning("Inconsistency between maximum heap size and maximum "
               "generation sizes: using maximum heap = " SIZE_FORMAT
               " -XX:OldSize flag is being ignored",
@@ -482,8 +592,7 @@
     }
     // If there is an inconsistency between the OldSize and the minimum and/or
     // initial size of gen0, since OldSize was explicitly set, OldSize wins.
-    if (adjust_gen0_sizes(&_min_gen0_size, &_min_gen1_size,
-                          _min_heap_byte_size, OldSize)) {
+    if (adjust_gen0_sizes(&_min_gen0_size, &_min_gen1_size, _min_heap_byte_size)) {
       if (PrintGCDetails && Verbose) {
         gclog_or_tty->print_cr("2: Minimum gen0 " SIZE_FORMAT "  Initial gen0 "
               SIZE_FORMAT "  Maximum gen0 " SIZE_FORMAT,
@@ -492,7 +601,7 @@
     }
     // Initial size
     if (adjust_gen0_sizes(&_initial_gen0_size, &_initial_gen1_size,
-                          _initial_heap_byte_size, OldSize)) {
+                          _initial_heap_byte_size)) {
       if (PrintGCDetails && Verbose) {
         gclog_or_tty->print_cr("3: Minimum gen0 " SIZE_FORMAT "  Initial gen0 "
           SIZE_FORMAT "  Maximum gen0 " SIZE_FORMAT,
@@ -507,11 +616,26 @@
   _initial_gen1_size = MAX2(_initial_gen1_size, _min_gen1_size);
   _initial_gen1_size = MIN2(_initial_gen1_size, _max_gen1_size);
 
+  // Write back to flags if necessary
+  if (NewSize != _initial_gen0_size) {
+    FLAG_SET_ERGO(uintx, NewSize, _initial_gen0_size);
+  }
+
+  if (MaxNewSize != _max_gen0_size) {
+    FLAG_SET_ERGO(uintx, MaxNewSize, _max_gen0_size);
+  }
+
+  if (OldSize != _initial_gen1_size) {
+    FLAG_SET_ERGO(uintx, OldSize, _initial_gen1_size);
+  }
+
   if (PrintGCDetails && Verbose) {
     gclog_or_tty->print_cr("Minimum gen1 " SIZE_FORMAT "  Initial gen1 "
       SIZE_FORMAT "  Maximum gen1 " SIZE_FORMAT,
       _min_gen1_size, _initial_gen1_size, _max_gen1_size);
   }
+
+  DEBUG_ONLY(TwoGenerationCollectorPolicy::assert_size_info();)
 }
 
 HeapWord* GenCollectorPolicy::mem_allocate_work(size_t size,
@@ -605,9 +729,7 @@
       gc_count_before = Universe::heap()->total_collections();
     }
 
-    VM_GenCollectForAllocation op(size,
-                                  is_tlab,
-                                  gc_count_before);
+    VM_GenCollectForAllocation op(size, is_tlab, gc_count_before);
     VMThread::execute(&op);
     if (op.prologue_succeeded()) {
       result = op.result();
@@ -836,14 +958,16 @@
 // MarkSweepPolicy methods
 //
 
-MarkSweepPolicy::MarkSweepPolicy() {
-  initialize_all();
+void MarkSweepPolicy::initialize_alignments() {
+  _space_alignment = _gen_alignment = (uintx)Generation::GenGrain;
+  _heap_alignment = compute_heap_alignment();
 }
 
 void MarkSweepPolicy::initialize_generations() {
   _generations = NEW_C_HEAP_ARRAY3(GenerationSpecPtr, number_of_generations(), mtGC, 0, AllocFailStrategy::RETURN_NULL);
-  if (_generations == NULL)
+  if (_generations == NULL) {
     vm_exit_during_initialization("Unable to allocate gen spec");
+  }
 
   if (UseParNewGC) {
     _generations[0] = new GenerationSpec(Generation::ParNew, _initial_gen0_size, _max_gen0_size);
@@ -852,8 +976,9 @@
   }
   _generations[1] = new GenerationSpec(Generation::MarkSweepCompact, _initial_gen1_size, _max_gen1_size);
 
-  if (_generations[0] == NULL || _generations[1] == NULL)
+  if (_generations[0] == NULL || _generations[1] == NULL) {
     vm_exit_during_initialization("Unable to allocate gen spec");
+  }
 }
 
 void MarkSweepPolicy::initialize_gc_policy_counters() {
--- a/src/share/vm/memory/collectorPolicy.hpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/memory/collectorPolicy.hpp	Fri Nov 15 21:39:27 2013 +0100
@@ -61,17 +61,23 @@
  protected:
   GCPolicyCounters* _gc_policy_counters;
 
-  // Requires that the concrete subclass sets the alignment constraints
-  // before calling.
+  virtual void initialize_alignments() = 0;
   virtual void initialize_flags();
   virtual void initialize_size_info();
 
+  DEBUG_ONLY(virtual void assert_flags();)
+  DEBUG_ONLY(virtual void assert_size_info();)
+
   size_t _initial_heap_byte_size;
   size_t _max_heap_byte_size;
   size_t _min_heap_byte_size;
 
-  size_t _min_alignment;
-  size_t _max_alignment;
+  size_t _space_alignment;
+  size_t _heap_alignment;
+
+  // Needed to keep information if MaxHeapSize was set on the command line
+  // when the flag value is aligned etc by ergonomics
+  bool _max_heap_size_cmdline;
 
   // The sizing of the heap are controlled by a sizing policy.
   AdaptiveSizePolicy* _size_policy;
@@ -79,6 +85,7 @@
   // Set to true when policy wants soft refs cleared.
   // Reset to false by gc after it clears all soft refs.
   bool _should_clear_all_soft_refs;
+
   // Set to true by the GC if the just-completed gc cleared all
   // softrefs.  This is set to true whenever a gc clears all softrefs, and
   // set to false each time gc returns to the mutator.  For example, in the
@@ -86,23 +93,20 @@
   // mem_allocate() where it returns op.result()
   bool _all_soft_refs_clear;
 
-  CollectorPolicy() :
-    _min_alignment(1),
-    _max_alignment(1),
-    _initial_heap_byte_size(0),
-    _max_heap_byte_size(0),
-    _min_heap_byte_size(0),
-    _size_policy(NULL),
-    _should_clear_all_soft_refs(false),
-    _all_soft_refs_clear(false)
-  {}
+  CollectorPolicy();
 
  public:
+  virtual void initialize_all() {
+    initialize_alignments();
+    initialize_flags();
+    initialize_size_info();
+  }
+
   // Return maximum heap alignment that may be imposed by the policy
-  static size_t compute_max_alignment();
+  static size_t compute_heap_alignment();
 
-  size_t min_alignment()                       { return _min_alignment; }
-  size_t max_alignment()                       { return _max_alignment; }
+  size_t space_alignment()        { return _space_alignment; }
+  size_t heap_alignment()         { return _heap_alignment; }
 
   size_t initial_heap_byte_size() { return _initial_heap_byte_size; }
   size_t max_heap_byte_size()     { return _max_heap_byte_size; }
@@ -151,7 +155,6 @@
 
 
   virtual BarrierSet::Name barrier_set_name() = 0;
-  virtual GenRemSet::Name  rem_set_name() = 0;
 
   // Create the remembered set (to cover the given reserved region,
   // allowing breaking up into at most "max_covered_regions").
@@ -195,6 +198,9 @@
     return false;
   }
 
+  // Do any updates required to global flags that are due to heap initialization
+  // changes
+  virtual void post_heap_initialize() = 0;
 };
 
 class ClearedAllSoftRefs : public StackObj {
@@ -219,6 +225,10 @@
   size_t _initial_gen0_size;
   size_t _max_gen0_size;
 
+  // _gen_alignment and _space_alignment will have the same value most of the
+  // time. When using large pages they can differ.
+  size_t _gen_alignment;
+
   GenerationSpec **_generations;
 
   // Return true if an allocation should be attempted in the older
@@ -229,41 +239,50 @@
   void initialize_flags();
   void initialize_size_info();
 
+  DEBUG_ONLY(void assert_flags();)
+  DEBUG_ONLY(void assert_size_info();)
+
   // Try to allocate space by expanding the heap.
   virtual HeapWord* expand_heap_and_allocate(size_t size, bool is_tlab);
 
- // Scale the base_size by NewRation according to
+  // Compute max heap alignment
+  size_t compute_max_alignment();
+
+ // Scale the base_size by NewRatio according to
  //     result = base_size / (NewRatio + 1)
  // and align by min_alignment()
  size_t scale_by_NewRatio_aligned(size_t base_size);
 
- // Bound the value by the given maximum minus the
- // min_alignment.
+ // Bound the value by the given maximum minus the min_alignment
  size_t bound_minus_alignment(size_t desired_size, size_t maximum_size);
 
  public:
+  GenCollectorPolicy();
+
   // Accessors
   size_t min_gen0_size()     { return _min_gen0_size; }
   size_t initial_gen0_size() { return _initial_gen0_size; }
   size_t max_gen0_size()     { return _max_gen0_size; }
+  size_t gen_alignment()     { return _gen_alignment; }
 
   virtual int number_of_generations() = 0;
 
-  virtual GenerationSpec **generations()       {
+  virtual GenerationSpec **generations() {
     assert(_generations != NULL, "Sanity check");
     return _generations;
   }
 
   virtual GenCollectorPolicy* as_generation_policy() { return this; }
 
-  virtual void initialize_generations() = 0;
+  virtual void initialize_generations() { };
 
   virtual void initialize_all() {
-    initialize_flags();
-    initialize_size_info();
+    CollectorPolicy::initialize_all();
     initialize_generations();
   }
 
+  size_t young_gen_size_lower_bound();
+
   HeapWord* mem_allocate_work(size_t size,
                               bool is_tlab,
                               bool* gc_overhead_limit_was_exceeded);
@@ -274,6 +293,10 @@
   virtual void initialize_size_policy(size_t init_eden_size,
                                       size_t init_promo_size,
                                       size_t init_survivor_size);
+
+  virtual void post_heap_initialize() {
+    assert(_max_gen0_size == MaxNewSize, "Should be taken care of by initialize_size_info");
+  }
 };
 
 // All of hotspot's current collectors are subtypes of this
@@ -290,9 +313,14 @@
 
   void initialize_flags();
   void initialize_size_info();
-  void initialize_generations()                { ShouldNotReachHere(); }
+
+  DEBUG_ONLY(void assert_flags();)
+  DEBUG_ONLY(void assert_size_info();)
 
  public:
+  TwoGenerationCollectorPolicy() : GenCollectorPolicy(), _min_gen1_size(0),
+    _initial_gen1_size(0), _max_gen1_size(0) {}
+
   // Accessors
   size_t min_gen1_size()     { return _min_gen1_size; }
   size_t initial_gen1_size() { return _initial_gen1_size; }
@@ -301,25 +329,25 @@
   // Inherited methods
   TwoGenerationCollectorPolicy* as_two_generation_policy() { return this; }
 
-  int number_of_generations()                  { return 2; }
-  BarrierSet::Name barrier_set_name()          { return BarrierSet::CardTableModRef; }
-  GenRemSet::Name rem_set_name()               { return GenRemSet::CardTable; }
+  int number_of_generations()          { return 2; }
+  BarrierSet::Name barrier_set_name()  { return BarrierSet::CardTableModRef; }
 
   virtual CollectorPolicy::Name kind() {
     return CollectorPolicy::TwoGenerationCollectorPolicyKind;
   }
 
-  // Returns true is gen0 sizes were adjusted
+  // Returns true if gen0 sizes were adjusted
   bool adjust_gen0_sizes(size_t* gen0_size_ptr, size_t* gen1_size_ptr,
-                         const size_t heap_size, const size_t min_gen1_size);
+                         const size_t heap_size);
 };
 
 class MarkSweepPolicy : public TwoGenerationCollectorPolicy {
  protected:
+  void initialize_alignments();
   void initialize_generations();
 
  public:
-  MarkSweepPolicy();
+  MarkSweepPolicy() {}
 
   MarkSweepPolicy* as_mark_sweep_policy() { return this; }
 
--- a/src/share/vm/memory/defNewGeneration.cpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/memory/defNewGeneration.cpp	Fri Nov 15 21:39:27 2013 +0100
@@ -204,7 +204,7 @@
   // Compute the maximum eden and survivor space sizes. These sizes
   // are computed assuming the entire reserved space is committed.
   // These values are exported as performance counters.
-  uintx alignment = GenCollectedHeap::heap()->collector_policy()->min_alignment();
+  uintx alignment = GenCollectedHeap::heap()->collector_policy()->space_alignment();
   uintx size = _virtual_space.reserved_size();
   _max_survivor_size = compute_survivor_size(size, alignment);
   _max_eden_size = size - (2*_max_survivor_size);
@@ -235,7 +235,7 @@
                                                 bool clear_space,
                                                 bool mangle_space) {
   uintx alignment =
-    GenCollectedHeap::heap()->collector_policy()->min_alignment();
+    GenCollectedHeap::heap()->collector_policy()->space_alignment();
 
   // If the spaces are being cleared (only done at heap initialization
   // currently), the survivor spaces need not be empty.
@@ -473,7 +473,7 @@
 }
 
 size_t DefNewGeneration::max_capacity() const {
-  const size_t alignment = GenCollectedHeap::heap()->collector_policy()->min_alignment();
+  const size_t alignment = GenCollectedHeap::heap()->collector_policy()->space_alignment();
   const size_t reserved_bytes = reserved().byte_size();
   return reserved_bytes - compute_survivor_size(reserved_bytes, alignment);
 }
--- a/src/share/vm/memory/genCollectedHeap.cpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/memory/genCollectedHeap.cpp	Fri Nov 15 21:39:27 2013 +0100
@@ -111,7 +111,7 @@
   int n_covered_regions = 0;
   ReservedSpace heap_rs;
 
-  size_t heap_alignment = collector_policy()->max_alignment();
+  size_t heap_alignment = collector_policy()->heap_alignment();
 
   heap_address = allocate(heap_alignment, &total_reserved,
                           &n_covered_regions, &heap_rs);
@@ -1053,12 +1053,6 @@
   }
 }
 
-void GenCollectedHeap::compute_new_generation_sizes(int collectedGen) {
-  for (int i = 0; i <= collectedGen; i++) {
-    _gens[i]->compute_new_size();
-  }
-}
-
 GenCollectedHeap* GenCollectedHeap::heap() {
   assert(_gch != NULL, "Uninitialized access to GenCollectedHeap::heap()");
   assert(_gch->kind() == CollectedHeap::GenCollectedHeap, "not a generational heap");
--- a/src/share/vm/memory/genCollectedHeap.hpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/memory/genCollectedHeap.hpp	Fri Nov 15 21:39:27 2013 +0100
@@ -86,10 +86,6 @@
   NOT_PRODUCT(static size_t _skip_header_HeapWords;)
 
 protected:
-  // Directs each generation up to and including "collectedGen" to recompute
-  // its desired size.
-  void compute_new_generation_sizes(int collectedGen);
-
   // Helper functions for allocation
   HeapWord* attempt_allocation(size_t size,
                                bool   is_tlab,
--- a/src/share/vm/memory/metaspace.cpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/memory/metaspace.cpp	Fri Nov 15 21:39:27 2013 +0100
@@ -2975,11 +2975,6 @@
 
 #endif
 
-// Align down. If the aligning result in 0, return 'alignment'.
-static size_t restricted_align_down(size_t size, size_t alignment) {
-  return MAX2(alignment, align_size_down_(size, alignment));
-}
-
 void Metaspace::ergo_initialize() {
   if (DumpSharedSpaces) {
     // Using large pages when dumping the shared archive is currently not implemented.
@@ -3002,13 +2997,13 @@
   // Ideally, we would be able to set the default value of MaxMetaspaceSize in
   // globals.hpp to the aligned value, but this is not possible, since the
   // alignment depends on other flags being parsed.
-  MaxMetaspaceSize = restricted_align_down(MaxMetaspaceSize, _reserve_alignment);
+  MaxMetaspaceSize = align_size_down_bounded(MaxMetaspaceSize, _reserve_alignment);
 
   if (MetaspaceSize > MaxMetaspaceSize) {
     MetaspaceSize = MaxMetaspaceSize;
   }
 
-  MetaspaceSize = restricted_align_down(MetaspaceSize, _commit_alignment);
+  MetaspaceSize = align_size_down_bounded(MetaspaceSize, _commit_alignment);
 
   assert(MetaspaceSize <= MaxMetaspaceSize, "MetaspaceSize should be limited by MaxMetaspaceSize");
 
@@ -3016,10 +3011,10 @@
     vm_exit_during_initialization("Too small initial Metaspace size");
   }
 
-  MinMetaspaceExpansion = restricted_align_down(MinMetaspaceExpansion, _commit_alignment);
-  MaxMetaspaceExpansion = restricted_align_down(MaxMetaspaceExpansion, _commit_alignment);
-
-  CompressedClassSpaceSize = restricted_align_down(CompressedClassSpaceSize, _reserve_alignment);
+  MinMetaspaceExpansion = align_size_down_bounded(MinMetaspaceExpansion, _commit_alignment);
+  MaxMetaspaceExpansion = align_size_down_bounded(MaxMetaspaceExpansion, _commit_alignment);
+
+  CompressedClassSpaceSize = align_size_down_bounded(CompressedClassSpaceSize, _reserve_alignment);
   set_compressed_class_space_size(CompressedClassSpaceSize);
 }
 
--- a/src/share/vm/memory/sharedHeap.cpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/memory/sharedHeap.cpp	Fri Nov 15 21:39:27 2013 +0100
@@ -247,6 +247,7 @@
 }
 
 void SharedHeap::post_initialize() {
+  CollectedHeap::post_initialize();
   ref_processing_init();
 }
 
--- a/src/share/vm/memory/universe.cpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/memory/universe.cpp	Fri Nov 15 21:39:27 2013 +0100
@@ -785,6 +785,7 @@
   } else if (UseG1GC) {
 #if INCLUDE_ALL_GCS
     G1CollectorPolicy* g1p = new G1CollectorPolicy();
+    g1p->initialize_all();
     G1CollectedHeap* g1h = new G1CollectedHeap(g1p);
     Universe::_collectedHeap = g1h;
 #else  // INCLUDE_ALL_GCS
@@ -809,6 +810,7 @@
     } else { // default old generation
       gc_policy = new MarkSweepPolicy();
     }
+    gc_policy->initialize_all();
 
     Universe::_collectedHeap = new GenCollectedHeap(gc_policy);
   }
@@ -1041,7 +1043,7 @@
     Universe::_virtual_machine_error_instance =
       InstanceKlass::cast(k)->allocate_instance(CHECK_false);
 
-    Universe::_vm_exception               = InstanceKlass::cast(k)->allocate_instance(CHECK_false);
+    Universe::_vm_exception = InstanceKlass::cast(k)->allocate_instance(CHECK_false);
 
   if (!DumpSharedSpaces) {
     // These are the only Java fields that are currently set during shared space dumping.
--- a/src/share/vm/oops/instanceKlass.cpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/oops/instanceKlass.cpp	Fri Nov 15 21:39:27 2013 +0100
@@ -2211,6 +2211,10 @@
            data = mdo->next_data(data)) {
         data->clean_weak_klass_links(is_alive);
       }
+      ParametersTypeData* parameters = mdo->parameters_type_data();
+      if (parameters != NULL) {
+        parameters->clean_weak_klass_links(is_alive);
+      }
     }
   }
 }
--- a/src/share/vm/oops/methodData.cpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/oops/methodData.cpp	Fri Nov 15 21:39:27 2013 +0100
@@ -275,23 +275,23 @@
 }
 
 bool TypeEntries::is_loader_alive(BoolObjectClosure* is_alive_cl, intptr_t p) {
-  return !is_type_none(p) &&
-    !((Klass*)klass_part(p))->is_loader_alive(is_alive_cl);
+  Klass* k = (Klass*)klass_part(p);
+  return k != NULL && k->is_loader_alive(is_alive_cl);
 }
 
 void TypeStackSlotEntries::clean_weak_klass_links(BoolObjectClosure* is_alive_cl) {
   for (int i = 0; i < _number_of_entries; i++) {
     intptr_t p = type(i);
-    if (is_loader_alive(is_alive_cl, p)) {
-      set_type(i, type_none());
+    if (!is_loader_alive(is_alive_cl, p)) {
+      set_type(i, with_status((Klass*)NULL, p));
     }
   }
 }
 
 void ReturnTypeEntry::clean_weak_klass_links(BoolObjectClosure* is_alive_cl) {
   intptr_t p = type();
-  if (is_loader_alive(is_alive_cl, p)) {
-    set_type(type_none());
+  if (!is_loader_alive(is_alive_cl, p)) {
+    set_type(with_status((Klass*)NULL, p));
   }
 }
 
--- a/src/share/vm/oops/methodData.hpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/oops/methodData.hpp	Fri Nov 15 21:39:27 2013 +0100
@@ -690,7 +690,6 @@
   // recorded type: cell without bit 0 and 1
   static intptr_t klass_part(intptr_t v) {
     intptr_t r = v & type_klass_mask;
-    assert (r != 0, "invalid");
     return r;
   }
 
@@ -698,7 +697,9 @@
   static Klass* valid_klass(intptr_t k) {
     if (!is_type_none(k) &&
         !is_type_unknown(k)) {
-      return (Klass*)klass_part(k);
+      Klass* res = (Klass*)klass_part(k);
+      assert(res != NULL, "invalid");
+      return res;
     } else {
       return NULL;
     }
--- a/src/share/vm/opto/bytecodeInfo.cpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/opto/bytecodeInfo.cpp	Fri Nov 15 21:39:27 2013 +0100
@@ -389,6 +389,10 @@
     return false;
   }
   if (inline_level() > _max_inline_level) {
+    if (callee_method->force_inline() && inline_level() > MaxForceInlineLevel) {
+      set_msg("MaxForceInlineLevel");
+      return false;
+    }
     if (!callee_method->force_inline() || !IncrementalInline) {
       set_msg("inlining too deep");
       return false;
--- a/src/share/vm/opto/callGenerator.cpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/opto/callGenerator.cpp	Fri Nov 15 21:39:27 2013 +0100
@@ -776,7 +776,7 @@
         guarantee(!target->is_method_handle_intrinsic(), "should not happen");  // XXX remove
         const int vtable_index = Method::invalid_vtable_index;
         CallGenerator* cg = C->call_generator(target, vtable_index, false, jvms, true, PROB_ALWAYS, NULL, true, true);
-        assert(!cg->is_late_inline() || cg->is_mh_late_inline(), "no late inline here");
+        assert(cg == NULL || !cg->is_late_inline() || cg->is_mh_late_inline(), "no late inline here");
         if (cg != NULL && cg->is_inline())
           return cg;
       }
@@ -846,7 +846,7 @@
         }
 
         CallGenerator* cg = C->call_generator(target, vtable_index, call_does_dispatch, jvms, true, PROB_ALWAYS, speculative_receiver_type, true, true);
-        assert(!cg->is_late_inline() || cg->is_mh_late_inline(), "no late inline here");
+        assert(cg == NULL || !cg->is_late_inline() || cg->is_mh_late_inline(), "no late inline here");
         if (cg != NULL && cg->is_inline())
           return cg;
       }
--- a/src/share/vm/opto/loopopts.cpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/opto/loopopts.cpp	Fri Nov 15 21:39:27 2013 +0100
@@ -42,6 +42,13 @@
     // so disable this for now
     return NULL;
   }
+
+  if (n->is_MathExact()) {
+    // MathExact has projections that are not correctly handled in the code
+    // below.
+    return NULL;
+  }
+
   int wins = 0;
   assert(!n->is_CFG(), "");
   assert(region->is_Region(), "");
--- a/src/share/vm/opto/matcher.cpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/opto/matcher.cpp	Fri Nov 15 21:39:27 2013 +0100
@@ -464,17 +464,17 @@
   C->FIRST_STACK_mask().Clear();
 
   // Add in the incoming argument area
-  OptoReg::Name init = OptoReg::add(_old_SP, C->out_preserve_stack_slots());
-  for (i = init; i < _in_arg_limit; i = OptoReg::add(i,1))
+  OptoReg::Name init_in = OptoReg::add(_old_SP, C->out_preserve_stack_slots());
+  for (i = init_in; i < _in_arg_limit; i = OptoReg::add(i,1)) {
     C->FIRST_STACK_mask().Insert(i);
-
+  }
   // Add in all bits past the outgoing argument area
   guarantee(RegMask::can_represent_arg(OptoReg::add(_out_arg_limit,-1)),
             "must be able to represent all call arguments in reg mask");
-  init = _out_arg_limit;
-  for (i = init; RegMask::can_represent(i); i = OptoReg::add(i,1))
+  OptoReg::Name init = _out_arg_limit;
+  for (i = init; RegMask::can_represent(i); i = OptoReg::add(i,1)) {
     C->FIRST_STACK_mask().Insert(i);
-
+  }
   // Finally, set the "infinite stack" bit.
   C->FIRST_STACK_mask().set_AllStack();
 
@@ -506,16 +506,36 @@
      idealreg2spillmask[Op_VecS]->OR(C->FIRST_STACK_mask());
   }
   if (Matcher::vector_size_supported(T_FLOAT,2)) {
+    // For VecD we need dual alignment and 8 bytes (2 slots) for spills.
+    // RA guarantees such alignment since it is needed for Double and Long values.
     *idealreg2spillmask[Op_VecD] = *idealreg2regmask[Op_VecD];
      idealreg2spillmask[Op_VecD]->OR(aligned_stack_mask);
   }
   if (Matcher::vector_size_supported(T_FLOAT,4)) {
+    // For VecX we need quadro alignment and 16 bytes (4 slots) for spills.
+    //
+    // RA can use input arguments stack slots for spills but until RA
+    // we don't know frame size and offset of input arg stack slots.
+    //
+    // Exclude last input arg stack slots to avoid spilling vectors there
+    // otherwise vector spills could stomp over stack slots in caller frame.
+    OptoReg::Name in = OptoReg::add(_in_arg_limit, -1);
+    for (int k = 1; (in >= init_in) && (k < RegMask::SlotsPerVecX); k++) {
+      aligned_stack_mask.Remove(in);
+      in = OptoReg::add(in, -1);
+    }
      aligned_stack_mask.clear_to_sets(RegMask::SlotsPerVecX);
      assert(aligned_stack_mask.is_AllStack(), "should be infinite stack");
     *idealreg2spillmask[Op_VecX] = *idealreg2regmask[Op_VecX];
      idealreg2spillmask[Op_VecX]->OR(aligned_stack_mask);
   }
   if (Matcher::vector_size_supported(T_FLOAT,8)) {
+    // For VecY we need octo alignment and 32 bytes (8 slots) for spills.
+    OptoReg::Name in = OptoReg::add(_in_arg_limit, -1);
+    for (int k = 1; (in >= init_in) && (k < RegMask::SlotsPerVecY); k++) {
+      aligned_stack_mask.Remove(in);
+      in = OptoReg::add(in, -1);
+    }
      aligned_stack_mask.clear_to_sets(RegMask::SlotsPerVecY);
      assert(aligned_stack_mask.is_AllStack(), "should be infinite stack");
     *idealreg2spillmask[Op_VecY] = *idealreg2regmask[Op_VecY];
--- a/src/share/vm/opto/mathexactnode.hpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/opto/mathexactnode.hpp	Fri Nov 15 21:39:27 2013 +0100
@@ -49,7 +49,7 @@
   virtual Node* Identity(PhaseTransform* phase) { return this; }
   virtual Node* Ideal(PhaseGVN* phase, bool can_reshape) { return NULL; }
   virtual const Type* Value(PhaseTransform* phase) const { return bottom_type(); }
-  virtual uint hash() const { return Node::hash(); }
+  virtual uint hash() const { return NO_HASH; }
   virtual bool is_CFG() const { return false; }
   virtual uint ideal_reg() const { return NotAMachineReg; }
 
--- a/src/share/vm/prims/whitebox.cpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/prims/whitebox.cpp	Fri Nov 15 21:39:27 2013 +0100
@@ -107,7 +107,7 @@
   gclog_or_tty->print_cr("Minimum heap "SIZE_FORMAT" Initial heap "
     SIZE_FORMAT" Maximum heap "SIZE_FORMAT" Min alignment "SIZE_FORMAT" Max alignment "SIZE_FORMAT,
     p->min_heap_byte_size(), p->initial_heap_byte_size(), p->max_heap_byte_size(),
-    p->min_alignment(), p->max_alignment());
+    p->space_alignment(), p->heap_alignment());
 }
 WB_END
 
--- a/src/share/vm/runtime/arguments.cpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/runtime/arguments.cpp	Fri Nov 15 21:39:27 2013 +0100
@@ -1132,9 +1132,6 @@
     Tier3InvokeNotifyFreqLog = 0;
     Tier4InvocationThreshold = 0;
   }
-  if (FLAG_IS_DEFAULT(NmethodSweepFraction)) {
-    FLAG_SET_DEFAULT(NmethodSweepFraction, 1 + ReservedCodeCacheSize / (16 * M));
-  }
 }
 
 #if INCLUDE_ALL_GCS
@@ -1408,7 +1405,7 @@
   // NULL page is located before the heap, we pad the NULL page to the conservative
   // maximum alignment that the GC may ever impose upon the heap.
   size_t displacement_due_to_null_page = align_size_up_(os::vm_page_size(),
-    Arguments::conservative_max_heap_alignment());
+                                                        _conservative_max_heap_alignment);
 
   LP64_ONLY(return OopEncodingHeapMax - displacement_due_to_null_page);
   NOT_LP64(ShouldNotReachHere(); return 0);
@@ -1505,7 +1502,7 @@
   }
 #endif // INCLUDE_ALL_GCS
   _conservative_max_heap_alignment = MAX3(heap_alignment, os::max_page_size(),
-    CollectorPolicy::compute_max_alignment());
+    CollectorPolicy::compute_heap_alignment());
 }
 
 void Arguments::set_ergonomics_flags() {
@@ -2165,6 +2162,10 @@
 
 #if INCLUDE_ALL_GCS
   if (UseG1GC) {
+    status = status && verify_percentage(G1NewSizePercent, "G1NewSizePercent");
+    status = status && verify_percentage(G1MaxNewSizePercent, "G1MaxNewSizePercent");
+    status = status && verify_interval(G1NewSizePercent, 0, G1MaxNewSizePercent, "G1NewSizePercent");
+
     status = status && verify_percentage(InitiatingHeapOccupancyPercent,
                                          "InitiatingHeapOccupancyPercent");
     status = status && verify_min_value(G1RefProcDrainInterval, 1,
@@ -2681,9 +2682,10 @@
         describe_range_error(errcode);
         return JNI_EINVAL;
       }
+      set_min_heap_size((uintx)long_initial_heap_size);
+      // Currently the minimum size and the initial heap sizes are the same.
+      // Can be overridden with -XX:InitialHeapSize.
       FLAG_SET_CMDLINE(uintx, InitialHeapSize, (uintx)long_initial_heap_size);
-      // Currently the minimum size and the initial heap sizes are the same.
-      set_min_heap_size(InitialHeapSize);
     // -Xmx
     } else if (match_option(option, "-Xmx", &tail) || match_option(option, "-XX:MaxHeapSize=", &tail)) {
       julong long_max_heap_size = 0;
@@ -3643,6 +3645,11 @@
         "Incompatible compilation policy selected", NULL);
     }
   }
+  // Set NmethodSweepFraction after the size of the code cache is adapted (in case of tiered)
+  if (FLAG_IS_DEFAULT(NmethodSweepFraction)) {
+    FLAG_SET_DEFAULT(NmethodSweepFraction, 1 + ReservedCodeCacheSize / (16 * M));
+  }
+
 
   // Set heap size based on available physical memory
   set_heap_size();
--- a/src/share/vm/runtime/globals.hpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/runtime/globals.hpp	Fri Nov 15 21:39:27 2013 +0100
@@ -2954,6 +2954,9 @@
   product(intx, MaxRecursiveInlineLevel, 1,                                 \
           "maximum number of nested recursive calls that are inlined")      \
                                                                             \
+  develop(intx, MaxForceInlineLevel, 100,                                   \
+          "maximum number of nested @ForceInline calls that are inlined")   \
+                                                                            \
   product_pd(intx, InlineSmallCode,                                         \
           "Only inline already compiled methods if their code size is "     \
           "less than this")                                                 \
@@ -3019,9 +3022,6 @@
   notproduct(intx, ZombieALotInterval,     5,                               \
           "Number of exits until ZombieALot kicks in")                      \
                                                                             \
-  develop(bool, StressNonEntrant, false,                                    \
-          "Mark nmethods non-entrant at registration")                      \
-                                                                            \
   diagnostic(intx, MallocVerifyInterval,     0,                             \
           "If non-zero, verify C heap after every N calls to "              \
           "malloc/realloc/free")                                            \
@@ -3289,7 +3289,7 @@
           "Exit the VM if we fill the code cache")                          \
                                                                             \
   product(bool, UseCodeCacheFlushing, true,                                 \
-          "Attempt to clean the code cache before shutting off compiler")   \
+          "Remove cold/old nmethods from the code cache")                   \
                                                                             \
   /* interpreter debugging */                                               \
   develop(intx, BinarySwitchThreshold, 5,                                   \
--- a/src/share/vm/runtime/sweeper.cpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/runtime/sweeper.cpp	Fri Nov 15 21:39:27 2013 +0100
@@ -112,14 +112,13 @@
   if (_records != NULL) {
     _records[_sweep_index].traversal = _traversals;
     _records[_sweep_index].traversal_mark = nm->_stack_traversal_mark;
-    _records[_sweep_index].invocation = _invocations;
+    _records[_sweep_index].invocation = _sweep_fractions_left;
     _records[_sweep_index].compile_id = nm->compile_id();
     _records[_sweep_index].kind = nm->compile_kind();
     _records[_sweep_index].state = nm->_state;
     _records[_sweep_index].vep = nm->verified_entry_point();
     _records[_sweep_index].uep = nm->entry_point();
     _records[_sweep_index].line = line;
-
     _sweep_index = (_sweep_index + 1) % SweeperLogEntries;
   }
 }
@@ -127,26 +126,29 @@
 #define SWEEP(nm)
 #endif
 
-nmethod*  NMethodSweeper::_current         = NULL; // Current nmethod
-long      NMethodSweeper::_traversals      = 0;    // Nof. stack traversals performed
-int       NMethodSweeper::_seen            = 0;    // Nof. nmethods we have currently processed in current pass of CodeCache
-int       NMethodSweeper::_flushed_count   = 0;    // Nof. nmethods flushed in current sweep
-int       NMethodSweeper::_zombified_count = 0;    // Nof. nmethods made zombie in current sweep
-int       NMethodSweeper::_marked_count    = 0;    // Nof. nmethods marked for reclaim in current sweep
+nmethod* NMethodSweeper::_current                      = NULL; // Current nmethod
+long     NMethodSweeper::_traversals                   = 0;    // Stack scan count, also sweep ID.
+long     NMethodSweeper::_time_counter                 = 0;    // Virtual time used to periodically invoke sweeper
+long     NMethodSweeper::_last_sweep                   = 0;    // Value of _time_counter when the last sweep happened
+int      NMethodSweeper::_seen                         = 0;    // Nof. nmethod we have currently processed in current pass of CodeCache
+int      NMethodSweeper::_flushed_count                = 0;    // Nof. nmethods flushed in current sweep
+int      NMethodSweeper::_zombified_count              = 0;    // Nof. nmethods made zombie in current sweep
+int      NMethodSweeper::_marked_for_reclamation_count = 0;    // Nof. nmethods marked for reclaim in current sweep
 
-volatile int NMethodSweeper::_invocations   = 0; // Nof. invocations left until we are completed with this pass
-volatile int NMethodSweeper::_sweep_started = 0; // Whether a sweep is in progress.
+volatile bool NMethodSweeper::_should_sweep            = true; // Indicates if we should invoke the sweeper
+volatile int  NMethodSweeper::_sweep_fractions_left    = 0;    // Nof. invocations left until we are completed with this pass
+volatile int  NMethodSweeper::_sweep_started           = 0;    // Flag to control conc sweeper
+volatile int  NMethodSweeper::_bytes_changed           = 0;    // Counts the total nmethod size if the nmethod changed from:
+                                                               //   1) alive       -> not_entrant
+                                                               //   2) not_entrant -> zombie
+                                                               //   3) zombie      -> marked_for_reclamation
 
-jint      NMethodSweeper::_locked_seen               = 0;
-jint      NMethodSweeper::_not_entrant_seen_on_stack = 0;
-bool      NMethodSweeper::_request_mark_phase        = false;
-
-int       NMethodSweeper::_total_nof_methods_reclaimed = 0;
-jlong     NMethodSweeper::_total_time_sweeping         = 0;
-jlong     NMethodSweeper::_total_time_this_sweep       = 0;
-jlong     NMethodSweeper::_peak_sweep_time             = 0;
-jlong     NMethodSweeper::_peak_sweep_fraction_time    = 0;
-int       NMethodSweeper::_hotness_counter_reset_val   = 0;
+int   NMethodSweeper::_total_nof_methods_reclaimed     = 0;    // Accumulated nof methods flushed
+jlong NMethodSweeper::_total_time_sweeping             = 0;    // Accumulated time sweeping
+jlong NMethodSweeper::_total_time_this_sweep           = 0;    // Total time this sweep
+jlong NMethodSweeper::_peak_sweep_time                 = 0;    // Peak time for a full sweep
+jlong NMethodSweeper::_peak_sweep_fraction_time        = 0;    // Peak time sweeping one fraction
+int   NMethodSweeper::_hotness_counter_reset_val       = 0;
 
 
 class MarkActivationClosure: public CodeBlobClosure {
@@ -197,13 +199,16 @@
     return;
   }
 
+  // Increase time so that we can estimate when to invoke the sweeper again.
+  _time_counter++;
+
   // Check for restart
   assert(CodeCache::find_blob_unsafe(_current) == _current, "Sweeper nmethod cached state invalid");
-  if (!sweep_in_progress() && need_marking_phase()) {
-    _seen        = 0;
-    _invocations = NmethodSweepFraction;
-    _current     = CodeCache::first_nmethod();
-    _traversals  += 1;
+  if (!sweep_in_progress()) {
+    _seen = 0;
+    _sweep_fractions_left = NmethodSweepFraction;
+    _current = CodeCache::first_nmethod();
+    _traversals += 1;
     _total_time_this_sweep = 0;
 
     if (PrintMethodFlushing) {
@@ -211,10 +216,6 @@
     }
     Threads::nmethods_do(&mark_activation_closure);
 
-    // reset the flags since we started a scan from the beginning.
-    reset_nmethod_marking();
-    _locked_seen = 0;
-    _not_entrant_seen_on_stack = 0;
   } else {
     // Only set hotness counter
     Threads::nmethods_do(&set_hotness_closure);
@@ -222,14 +223,48 @@
 
   OrderAccess::storestore();
 }
-
+/**
+ * This function invokes the sweeper if at least one of the three conditions is met:
+ *    (1) The code cache is getting full
+ *    (2) There are sufficient state changes in/since the last sweep.
+ *    (3) We have not been sweeping for 'some time'
+ */
 void NMethodSweeper::possibly_sweep() {
   assert(JavaThread::current()->thread_state() == _thread_in_vm, "must run in vm mode");
   if (!MethodFlushing || !sweep_in_progress()) {
     return;
   }
 
-  if (_invocations > 0) {
+  // If there was no state change while nmethod sweeping, 'should_sweep' will be false.
+  // This is one of the two places where should_sweep can be set to true. The general
+  // idea is as follows: If there is enough free space in the code cache, there is no
+  // need to invoke the sweeper. The following formula (which determines whether to invoke
+  // the sweeper or not) depends on the assumption that for larger ReservedCodeCacheSizes
+  // we need less frequent sweeps than for smaller ReservedCodecCacheSizes. Furthermore,
+  // the formula considers how much space in the code cache is currently used. Here are
+  // some examples that will (hopefully) help in understanding.
+  //
+  // Small ReservedCodeCacheSizes:  (e.g., < 16M) We invoke the sweeper every time, since
+  //                                              the result of the division is 0. This
+  //                                              keeps the used code cache size small
+  //                                              (important for embedded Java)
+  // Large ReservedCodeCacheSize :  (e.g., 256M + code cache is 10% full). The formula
+  //                                              computes: (256 / 16) - 1 = 15
+  //                                              As a result, we invoke the sweeper after
+  //                                              15 invocations of 'mark_active_nmethods.
+  // Large ReservedCodeCacheSize:   (e.g., 256M + code Cache is 90% full). The formula
+  //                                              computes: (256 / 16) - 10 = 6.
+  if (!_should_sweep) {
+    int time_since_last_sweep = _time_counter - _last_sweep;
+    double wait_until_next_sweep = (ReservedCodeCacheSize / (16 * M)) - time_since_last_sweep -
+                                CodeCache::reverse_free_ratio();
+
+    if ((wait_until_next_sweep <= 0.0) || !CompileBroker::should_compile_new_jobs()) {
+      _should_sweep = true;
+    }
+  }
+
+  if (_should_sweep && _sweep_fractions_left > 0) {
     // Only one thread at a time will sweep
     jint old = Atomic::cmpxchg( 1, &_sweep_started, 0 );
     if (old != 0) {
@@ -242,31 +277,46 @@
       memset(_records, 0, sizeof(SweeperRecord) * SweeperLogEntries);
     }
 #endif
-    if (_invocations > 0) {
+
+    if (_sweep_fractions_left > 0) {
       sweep_code_cache();
-      _invocations--;
+      _sweep_fractions_left--;
+    }
+
+    // We are done with sweeping the code cache once.
+    if (_sweep_fractions_left == 0) {
+      _last_sweep = _time_counter;
+      // Reset flag; temporarily disables sweeper
+      _should_sweep = false;
+      // If there was enough state change, 'possibly_enable_sweeper()'
+      // sets '_should_sweep' to true
+      possibly_enable_sweeper();
+      // Reset _bytes_changed only if there was enough state change. _bytes_changed
+      // can further increase by calls to 'report_state_change'.
+      if (_should_sweep) {
+        _bytes_changed = 0;
+      }
     }
     _sweep_started = 0;
   }
 }
 
 void NMethodSweeper::sweep_code_cache() {
-
   jlong sweep_start_counter = os::elapsed_counter();
 
-  _flushed_count   = 0;
-  _zombified_count = 0;
-  _marked_count    = 0;
+  _flushed_count                = 0;
+  _zombified_count              = 0;
+  _marked_for_reclamation_count = 0;
 
   if (PrintMethodFlushing && Verbose) {
-    tty->print_cr("### Sweep at %d out of %d. Invocations left: %d", _seen, CodeCache::nof_nmethods(), _invocations);
+    tty->print_cr("### Sweep at %d out of %d. Invocations left: %d", _seen, CodeCache::nof_nmethods(), _sweep_fractions_left);
   }
 
   if (!CompileBroker::should_compile_new_jobs()) {
     // If we have turned off compilations we might as well do full sweeps
     // in order to reach the clean state faster. Otherwise the sleeping compiler
     // threads will slow down sweeping.
-    _invocations = 1;
+    _sweep_fractions_left = 1;
   }
 
   // We want to visit all nmethods after NmethodSweepFraction
@@ -274,7 +324,7 @@
   // remaining number of invocations.  This is only an estimate since
   // the number of nmethods changes during the sweep so the final
   // stage must iterate until it there are no more nmethods.
-  int todo = (CodeCache::nof_nmethods() - _seen) / _invocations;
+  int todo = (CodeCache::nof_nmethods() - _seen) / _sweep_fractions_left;
   int swept_count = 0;
 
 
@@ -286,11 +336,11 @@
     MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
 
     // The last invocation iterates until there are no more nmethods
-    for (int i = 0; (i < todo || _invocations == 1) && _current != NULL; i++) {
+    for (int i = 0; (i < todo || _sweep_fractions_left == 1) && _current != NULL; i++) {
       swept_count++;
       if (SafepointSynchronize::is_synchronizing()) { // Safepoint request
         if (PrintMethodFlushing && Verbose) {
-          tty->print_cr("### Sweep at %d out of %d, invocation: %d, yielding to safepoint", _seen, CodeCache::nof_nmethods(), _invocations);
+          tty->print_cr("### Sweep at %d out of %d, invocation: %d, yielding to safepoint", _seen, CodeCache::nof_nmethods(), _sweep_fractions_left);
         }
         MutexUnlockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
 
@@ -314,19 +364,7 @@
     }
   }
 
-  assert(_invocations > 1 || _current == NULL, "must have scanned the whole cache");
-
-  if (!sweep_in_progress() && !need_marking_phase() && (_locked_seen || _not_entrant_seen_on_stack)) {
-    // we've completed a scan without making progress but there were
-    // nmethods we were unable to process either because they were
-    // locked or were still on stack. We don't have to aggressively
-    // clean them up so just stop scanning. We could scan once more
-    // but that complicates the control logic and it's unlikely to
-    // matter much.
-    if (PrintMethodFlushing) {
-      tty->print_cr("### Couldn't make progress on some nmethods so stopping sweep");
-    }
-  }
+  assert(_sweep_fractions_left > 1 || _current == NULL, "must have scanned the whole cache");
 
   jlong sweep_end_counter = os::elapsed_counter();
   jlong sweep_time = sweep_end_counter - sweep_start_counter;
@@ -340,21 +378,21 @@
     event.set_starttime(sweep_start_counter);
     event.set_endtime(sweep_end_counter);
     event.set_sweepIndex(_traversals);
-    event.set_sweepFractionIndex(NmethodSweepFraction - _invocations + 1);
+    event.set_sweepFractionIndex(NmethodSweepFraction - _sweep_fractions_left + 1);
     event.set_sweptCount(swept_count);
     event.set_flushedCount(_flushed_count);
-    event.set_markedCount(_marked_count);
+    event.set_markedCount(_marked_for_reclamation_count);
     event.set_zombifiedCount(_zombified_count);
     event.commit();
   }
 
 #ifdef ASSERT
   if(PrintMethodFlushing) {
-    tty->print_cr("### sweeper:      sweep time(%d): " INT64_FORMAT, _invocations, (jlong)sweep_time);
+    tty->print_cr("### sweeper:      sweep time(%d): " INT64_FORMAT, _sweep_fractions_left, (jlong)sweep_time);
   }
 #endif
 
-  if (_invocations == 1) {
+  if (_sweep_fractions_left == 1) {
     _peak_sweep_time = MAX2(_peak_sweep_time, _total_time_this_sweep);
     log_sweep("finished");
   }
@@ -368,12 +406,37 @@
   // it only makes sense to re-enable compilation if we have actually freed memory.
   // Note that typically several kB are released for sweeping 16MB of the code
   // cache. As a result, 'freed_memory' > 0 to restart the compiler.
-  if (UseCodeCacheFlushing && (!CompileBroker::should_compile_new_jobs() && (freed_memory > 0))) {
+  if (!CompileBroker::should_compile_new_jobs() && (freed_memory > 0)) {
     CompileBroker::set_should_compile_new_jobs(CompileBroker::run_compilation);
     log_sweep("restart_compiler");
   }
 }
 
+/**
+ * This function updates the sweeper statistics that keep track of nmethods
+ * state changes. If there is 'enough' state change, the sweeper is invoked
+ * as soon as possible. There can be data races on _bytes_changed. The data
+ * races are benign, since it does not matter if we loose a couple of bytes.
+ * In the worst case we call the sweeper a little later. Also, we are guaranteed
+ * to invoke the sweeper if the code cache gets full.
+ */
+void NMethodSweeper::report_state_change(nmethod* nm) {
+  _bytes_changed += nm->total_size();
+  possibly_enable_sweeper();
+}
+
+/**
+ * Function determines if there was 'enough' state change in the code cache to invoke
+ * the sweeper again. Currently, we determine 'enough' as more than 1% state change in
+ * the code cache since the last sweep.
+ */
+void NMethodSweeper::possibly_enable_sweeper() {
+  double percent_changed = ((double)_bytes_changed / (double)ReservedCodeCacheSize) * 100;
+  if (percent_changed > 1.0) {
+    _should_sweep = true;
+  }
+}
+
 class NMethodMarker: public StackObj {
  private:
   CompilerThread* _thread;
@@ -424,9 +487,6 @@
       MutexLocker cl(CompiledIC_lock);
       nm->cleanup_inline_caches();
       SWEEP(nm);
-    } else {
-      _locked_seen++;
-      SWEEP(nm);
     }
     return freed_memory;
   }
@@ -448,8 +508,9 @@
         tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (zombie) being marked for reclamation", nm->compile_id(), nm);
       }
       nm->mark_for_reclamation();
-      request_nmethod_marking();
-      _marked_count++;
+      // Keep track of code cache state change
+      _bytes_changed += nm->total_size();
+      _marked_for_reclamation_count++;
       SWEEP(nm);
     }
   } else if (nm->is_not_entrant()) {
@@ -459,18 +520,14 @@
       if (PrintMethodFlushing && Verbose) {
         tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (not entrant) being made zombie", nm->compile_id(), nm);
       }
+      // Code cache state change is tracked in make_zombie()
       nm->make_zombie();
-      request_nmethod_marking();
       _zombified_count++;
       SWEEP(nm);
     } else {
       // Still alive, clean up its inline caches
       MutexLocker cl(CompiledIC_lock);
       nm->cleanup_inline_caches();
-      // we coudn't transition this nmethod so don't immediately
-      // request a rescan.  If this method stays on the stack for a
-      // long time we don't want to keep rescanning the code cache.
-      _not_entrant_seen_on_stack++;
       SWEEP(nm);
     }
   } else if (nm->is_unloaded()) {
@@ -485,8 +542,8 @@
       release_nmethod(nm);
       _flushed_count++;
     } else {
+      // Code cache state change is tracked in make_zombie()
       nm->make_zombie();
-      request_nmethod_marking();
       _zombified_count++;
       SWEEP(nm);
     }
@@ -514,7 +571,11 @@
           //    The second condition ensures that methods are not immediately made not-entrant
           //    after compilation.
           nm->make_not_entrant();
-          request_nmethod_marking();
+          // Code cache state change is tracked in make_not_entrant()
+          if (PrintMethodFlushing && Verbose) {
+            tty->print_cr("### Nmethod %d/" PTR_FORMAT "made not-entrant: hotness counter %d/%d threshold %f",
+                          nm->compile_id(), nm, nm->hotness_counter(), reset_val, threshold);
+          }
         }
       }
     }
--- a/src/share/vm/runtime/sweeper.hpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/runtime/sweeper.hpp	Fri Nov 15 21:39:27 2013 +0100
@@ -53,22 +53,22 @@
 //     is full.
 
 class NMethodSweeper : public AllStatic {
-  static long      _traversals;      // Stack scan count, also sweep ID.
-  static nmethod*  _current;         // Current nmethod
-  static int       _seen;            // Nof. nmethod we have currently processed in current pass of CodeCache
-  static int       _flushed_count;   // Nof. nmethods flushed in current sweep
-  static int       _zombified_count; // Nof. nmethods made zombie in current sweep
-  static int       _marked_count;    // Nof. nmethods marked for reclaim in current sweep
+  static long      _traversals;                   // Stack scan count, also sweep ID.
+  static long      _time_counter;                 // Virtual time used to periodically invoke sweeper
+  static long      _last_sweep;                   // Value of _time_counter when the last sweep happened
+  static nmethod*  _current;                      // Current nmethod
+  static int       _seen;                         // Nof. nmethod we have currently processed in current pass of CodeCache
+  static int       _flushed_count;                // Nof. nmethods flushed in current sweep
+  static int       _zombified_count;              // Nof. nmethods made zombie in current sweep
+  static int       _marked_for_reclamation_count; // Nof. nmethods marked for reclaim in current sweep
 
-  static volatile int  _invocations;   // No. of invocations left until we are completed with this pass
-  static volatile int  _sweep_started; // Flag to control conc sweeper
-
-  //The following are reset in mark_active_nmethods and synchronized by the safepoint
-  static bool      _request_mark_phase;        // Indicates that a change has happend and we need another mark pahse,
-                                               // always checked and reset at a safepoint so memory will be in sync.
-  static int       _locked_seen;               // Number of locked nmethods encountered during the scan
-  static int       _not_entrant_seen_on_stack; // Number of not entrant nmethod were are still on stack
-
+  static volatile int  _sweep_fractions_left;     // Nof. invocations left until we are completed with this pass
+  static volatile int  _sweep_started;            // Flag to control conc sweeper
+  static volatile bool _should_sweep;             // Indicates if we should invoke the sweeper
+  static volatile int _bytes_changed;             // Counts the total nmethod size if the nmethod changed from:
+                                                  //   1) alive       -> not_entrant
+                                                  //   2) not_entrant -> zombie
+                                                  //   3) zombie      -> marked_for_reclamation
   // Stat counters
   static int       _total_nof_methods_reclaimed;  // Accumulated nof methods flushed
   static jlong     _total_time_sweeping;          // Accumulated time sweeping
@@ -81,9 +81,6 @@
 
   static bool sweep_in_progress();
   static void sweep_code_cache();
-  static void request_nmethod_marking() { _request_mark_phase = true; }
-  static void reset_nmethod_marking()   { _request_mark_phase = false; }
-  static bool need_marking_phase()      { return _request_mark_phase; }
 
   static int _hotness_counter_reset_val;
 
@@ -109,13 +106,8 @@
 
   static int sort_nmethods_by_hotness(nmethod** nm1, nmethod** nm2);
   static int hotness_counter_reset_val();
-
-  static void notify() {
-    // Request a new sweep of the code cache from the beginning. No
-    // need to synchronize the setting of this flag since it only
-    // changes to false at safepoint so we can never overwrite it with false.
-     request_nmethod_marking();
-  }
+  static void report_state_change(nmethod* nm);
+  static void possibly_enable_sweeper();
 };
 
 #endif // SHARE_VM_RUNTIME_SWEEPER_HPP
--- a/src/share/vm/utilities/globalDefinitions.hpp	Thu Nov 14 20:03:15 2013 +0100
+++ b/src/share/vm/utilities/globalDefinitions.hpp	Fri Nov 15 21:39:27 2013 +0100
@@ -456,6 +456,13 @@
   return (void*) align_size_up_((uintptr_t)addr, size);
 }
 
+// Align down with a lower bound. If the aligning results in 0, return 'alignment'.
+
+inline size_t align_size_down_bounded(size_t size, size_t alignment) {
+  size_t aligned_size = align_size_down_(size, alignment);
+  return aligned_size > 0 ? aligned_size : alignment;
+}
+
 // Clamp an address to be within a specific page
 // 1. If addr is on the page it is returned as is
 // 2. If addr is above the page_address the start of the *next* page will be returned
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/intrinsics/mathexact/GVNTest.java	Fri Nov 15 21:39:27 2013 +0100
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8028207
+ * @summary Verify that GVN doesn't mess up the two addExacts
+ * @compile GVNTest.java
+ * @run main GVNTest
+ *
+ */
+
+public class GVNTest {
+  public static int result = 0;
+  public static int value = 93;
+  public static void main(String[] args) {
+    for (int i = 0; i < 50000; ++i) {
+      result = runTest(value + i);
+      result = runTest(value + i);
+      result = runTest(value + i);
+      result = runTest(value + i);
+      result = runTest(value + i);
+    }
+  }
+
+  public static int runTest(int value) {
+    int v = value + value;
+    int sum = 0;
+    if (v < 4032) {
+      for (int i = 0; i < 1023; ++i) {
+        sum += Math.addExact(value, value);
+      }
+    } else {
+      for (int i = 0; i < 321; ++i) {
+        sum += Math.addExact(value, value);
+      }
+    }
+    return sum + v;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/intrinsics/mathexact/SplitThruPhiTest.java	Fri Nov 15 21:39:27 2013 +0100
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8028198
+ * @summary Verify that split through phi does the right thing
+ * @compile SplitThruPhiTest.java
+ * @run main SplitThruPhiTest
+ *
+ */
+
+public class SplitThruPhiTest {
+  public static volatile int value = 19;
+  public static int store = 0;
+  public static void main(String[] args) {
+    for (int i = 0; i < 150000; ++i) {
+      store = runTest(value);
+    }
+  }
+
+  public static int runTest(int val) {
+    int result = Math.addExact(val, 1);
+    int total = 0;
+    for (int i = val; i < 200; i = Math.addExact(i, 1)) {
+      total += i;
+    }
+    return total;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/profiling/TestUnexpectedProfilingMismatch.java	Fri Nov 15 21:39:27 2013 +0100
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8027631
+ * @summary profiling of arguments at calls cannot rely on signature of callee for types
+ * @run main/othervm -XX:-BackgroundCompilation -XX:TieredStopAtLevel=3 -XX:TypeProfileLevel=111 -XX:Tier3InvocationThreshold=200 -XX:Tier0InvokeNotifyFreqLog=7 TestUnexpectedProfilingMismatch
+ *
+ */
+
+import java.lang.invoke.*;
+
+public class TestUnexpectedProfilingMismatch {
+
+    static class A {
+    }
+
+    static class B {
+    }
+
+    static void mA(A a) {
+    }
+
+    static void mB(B b) {
+    }
+
+    static final MethodHandle mhA;
+    static final MethodHandle mhB;
+    static {
+        MethodHandles.Lookup lookup = MethodHandles.lookup();
+        MethodType mt = MethodType.methodType(void.class, A.class);
+        MethodHandle res = null;
+        try {
+            res = lookup.findStatic(TestUnexpectedProfilingMismatch.class, "mA", mt);
+        } catch(NoSuchMethodException ex) {
+        } catch(IllegalAccessException ex) {
+        }
+        mhA = res;
+        mt = MethodType.methodType(void.class, B.class);
+        try {
+            res = lookup.findStatic(TestUnexpectedProfilingMismatch.class, "mB", mt);
+        } catch(NoSuchMethodException ex) {
+        } catch(IllegalAccessException ex) {
+        }
+        mhB = res;
+    }
+
+    void m1(A a, boolean doit) throws Throwable {
+        if (doit) {
+            mhA.invoke(a);
+        }
+    }
+
+    void m2(B b) throws Throwable {
+        mhB.invoke(b);
+    }
+
+    static public void main(String[] args) {
+        TestUnexpectedProfilingMismatch tih = new TestUnexpectedProfilingMismatch();
+        A a = new A();
+        B b = new B();
+        try {
+            for (int i = 0; i < 256 - 1; i++) {
+                tih.m1(a, true);
+            }
+            // Will trigger the compilation but will also run once
+            // more interpreted with a non null MDO which it will
+            // update. Make it skip the body of the method.
+            tih.m1(a, false);
+            // Compile this one as well and do the profiling
+            for (int i = 0; i < 256; i++) {
+                tih.m2(b);
+            }
+            // Will run and see a conflict
+            tih.m1(a, true);
+        } catch(Throwable ex) {
+            ex.printStackTrace();
+        }
+        System.out.println("TEST PASSED");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/profiling/unloadingconflict/B.java	Fri Nov 15 21:39:27 2013 +0100
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+public class B {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/profiling/unloadingconflict/TestProfileConflictClassUnloading.java	Fri Nov 15 21:39:27 2013 +0100
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8027572
+ * @summary class unloading resets profile, method compiled after the profile is first set and before class loading sets unknown bit with not recorded class
+ * @build B
+ * @run main/othervm -XX:TypeProfileLevel=222 -XX:-BackgroundCompilation TestProfileConflictClassUnloading
+ *
+ */
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.file.Paths;
+
+public class TestProfileConflictClassUnloading {
+    static class A {
+    }
+
+
+    static void m1(Object o) {
+    }
+
+    static void m2(Object o) {
+        m1(o);
+    }
+
+    static void m3(A a, boolean do_call) {
+        if (!do_call) {
+            return;
+        }
+        m2(a);
+    }
+
+    public static ClassLoader newClassLoader() {
+        try {
+            return new URLClassLoader(new URL[] {
+                    Paths.get(System.getProperty("test.classes",".")).toUri().toURL(),
+            }, null);
+        } catch (MalformedURLException e){
+            throw new RuntimeException("Unexpected URL conversion failure", e);
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        ClassLoader loader = newClassLoader();
+        Object o = loader.loadClass("B").newInstance();
+        // collect conflicting profiles
+        for (int i = 0; i < 5000; i++) {
+            m2(o);
+        }
+        // prepare for conflict
+        A a = new A();
+        for (int i = 0; i < 5000; i++) {
+            m3(a, false);
+        }
+        // unload class in profile
+        o = null;
+        loader = null;
+        System.gc();
+        // record the conflict
+        m3(a, true);
+        // trigger another GC
+        System.gc();
+    }
+}
--- a/test/gc/arguments/TestMaxHeapSizeTools.java	Thu Nov 14 20:03:15 2013 +0100
+++ b/test/gc/arguments/TestMaxHeapSizeTools.java	Fri Nov 15 21:39:27 2013 +0100
@@ -64,32 +64,29 @@
     long newPlusOldSize = values[0] + values[1];
     long smallValue = newPlusOldSize / 2;
     long largeValue = newPlusOldSize * 2;
+    long maxHeapSize = largeValue + (2 * 1024 * 1024);
 
     // -Xms is not set
-    checkErgonomics(new String[] { gcflag, "-Xmx16M" }, values, -1, -1);
-    checkErgonomics(new String[] { gcflag, "-Xmx16M", "-XX:InitialHeapSize=" + smallValue }, values, smallValue, smallValue);
-    checkErgonomics(new String[] { gcflag, "-Xmx16M", "-XX:InitialHeapSize=" + largeValue }, values, -1, largeValue);
-    checkErgonomics(new String[] { gcflag, "-Xmx16M", "-XX:InitialHeapSize=0" }, values, -1, -1);
+    checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize }, values, -1, -1);
+    checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:InitialHeapSize=" + smallValue }, values, -1, smallValue);
+    checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:InitialHeapSize=" + largeValue }, values, -1, largeValue);
+    checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:InitialHeapSize=0" }, values, -1, -1);
 
     // -Xms is set to zero
-    checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms0" }, values, -1, -1);
-    checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms0", "-XX:InitialHeapSize=" + smallValue }, values, smallValue, smallValue);
-    checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms0", "-XX:InitialHeapSize=" + largeValue }, values, -1, largeValue);
-    checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms0", "-XX:InitialHeapSize=0" }, values, -1, -1);
+    checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0" }, values, -1, -1);
+    checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:InitialHeapSize=" + smallValue }, values, -1, smallValue);
+    checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:InitialHeapSize=" + largeValue }, values, -1, largeValue);
+    checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:InitialHeapSize=0" }, values, -1, -1);
 
     // -Xms is set to small value
-    checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms" + smallValue }, values, -1, -1);
-    checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms" + smallValue, "-XX:InitialHeapSize=" + smallValue }, values, smallValue, smallValue);
-    checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms" + smallValue, "-XX:InitialHeapSize=" + largeValue }, values, smallValue, largeValue);
-    checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms" + smallValue, "-XX:InitialHeapSize=0" }, values, smallValue, -1);
+    checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + smallValue }, values, -1, -1);
+    checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + smallValue, "-XX:InitialHeapSize=" + smallValue }, values, smallValue, smallValue);
+    checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + smallValue, "-XX:InitialHeapSize=" + largeValue }, values, smallValue, largeValue);
+    checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + smallValue, "-XX:InitialHeapSize=0" }, values, smallValue, -1);
 
     // -Xms is set to large value
-    checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms" + largeValue }, values, largeValue, largeValue);
-    // the next case has already been checked elsewhere and gives an error
-    // checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms" + largeValue, "-XX:InitialHeapSize=" + smallValue }, values, smallValue, smallValue);
-    // the next case has already been checked elsewhere too
-    // checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms" + largeValue, "-XX:InitialHeapSize=" + largeValue }, values, values[0], largeValue);
-    checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms" + largeValue, "-XX:InitialHeapSize=0" }, values, largeValue, -1);
+    checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + largeValue }, values, largeValue, largeValue);
+    checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + largeValue, "-XX:InitialHeapSize=0" }, values, largeValue, -1);
   }
 
   private static long align_up(long value, long alignment) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/arguments/TestMaxNewSize.java	Fri Nov 15 21:39:27 2013 +0100
@@ -0,0 +1,122 @@
+/*
+* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* This code is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License version 2 only, as
+* published by the Free Software Foundation.
+*
+* This code is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+* version 2 for more details (a copy is included in the LICENSE file that
+* accompanied this code).
+*
+* You should have received a copy of the GNU General Public License version
+* 2 along with this work; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+*
+* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+* or visit www.oracle.com if you need additional information or have any
+* questions.
+*/
+
+/*
+ * @test TestMaxNewSize
+ * @key gc
+ * @bug 7057939
+ * @summary Make sure that MaxNewSize always has a useful value after argument
+ * processing.
+ * @library /testlibrary
+ * @build TestMaxNewSize
+ * @run main TestMaxNewSize -XX:+UseSerialGC
+ * @run main TestMaxNewSize -XX:+UseParallelGC
+ * @run main TestMaxNewSize -XX:+UseConcMarkSweepGC
+ * @run main TestMaxNewSize -XX:+UseG1GC
+ * @author thomas.schatzl@oracle.com, jesper.wilhelmsson@oracle.com
+ */
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import java.math.BigInteger;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import com.oracle.java.testlibrary.*;
+
+public class TestMaxNewSize {
+
+  private static void checkMaxNewSize(String[] flags, int heapsize) throws Exception {
+    BigInteger actual = new BigInteger(getMaxNewSize(flags));
+    System.out.println(actual);
+    if (actual.compareTo(new BigInteger((new Long(heapsize)).toString())) == 1) {
+      throw new RuntimeException("MaxNewSize value set to \"" + actual +
+        "\", expected otherwise when running with the following flags: " + Arrays.asList(flags).toString());
+    }
+  }
+
+  private static void checkIncompatibleNewSize(String[] flags) throws Exception {
+    ArrayList<String> finalargs = new ArrayList<String>();
+    finalargs.addAll(Arrays.asList(flags));
+    finalargs.add("-version");
+
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(finalargs.toArray(new String[0]));
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    output.shouldContain("Initial young gen size set larger than the maximum young gen size");
+  }
+
+  private static boolean isRunningG1(String[] args) {
+    for (int i = 0; i < args.length; i++) {
+      if (args[i].contains("+UseG1GC")) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  private static String getMaxNewSize(String[] flags) throws Exception {
+    ArrayList<String> finalargs = new ArrayList<String>();
+    finalargs.addAll(Arrays.asList(flags));
+    if (isRunningG1(flags)) {
+      finalargs.add("-XX:G1HeapRegionSize=1M");
+    }
+    finalargs.add("-XX:+PrintFlagsFinal");
+    finalargs.add("-version");
+
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(finalargs.toArray(new String[0]));
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    output.shouldHaveExitValue(0);
+    String stdout = output.getStdout();
+    //System.out.println(stdout);
+    return getFlagValue("MaxNewSize", stdout);
+  }
+
+  private static String getFlagValue(String flag, String where) {
+    Matcher m = Pattern.compile(flag + "\\s+:?=\\s+\\d+").matcher(where);
+    if (!m.find()) {
+      throw new RuntimeException("Could not find value for flag " + flag + " in output string");
+    }
+    String match = m.group();
+    return match.substring(match.lastIndexOf(" ") + 1, match.length());
+  }
+
+  public static void main(String args[]) throws Exception {
+    String gcName = args[0];
+    final int M32 = 32 * 1024 * 1024;
+    final int M64 = 64 * 1024 * 1024;
+    final int M96 = 96 * 1024 * 1024;
+    final int M128 = 128 * 1024 * 1024;
+    checkMaxNewSize(new String[] { gcName, "-Xmx128M" }, M128);
+    checkMaxNewSize(new String[] { gcName, "-Xmx128M", "-XX:NewRatio=5" }, M128);
+    checkMaxNewSize(new String[] { gcName, "-Xmx128M", "-XX:NewSize=32M" }, M128);
+    checkMaxNewSize(new String[] { gcName, "-Xmx128M", "-XX:OldSize=96M" }, M128);
+    checkMaxNewSize(new String[] { gcName, "-Xmx128M", "-XX:MaxNewSize=32M" }, M32);
+    checkMaxNewSize(new String[] { gcName, "-Xmx128M", "-XX:NewSize=32M", "-XX:MaxNewSize=32M" }, M32);
+    checkMaxNewSize(new String[] { gcName, "-Xmx128M", "-XX:NewRatio=6", "-XX:MaxNewSize=32M" }, M32);
+    checkMaxNewSize(new String[] { gcName, "-Xmx128M", "-Xms96M" }, M128);
+    checkMaxNewSize(new String[] { gcName, "-Xmx96M", "-Xms96M" }, M96);
+    checkMaxNewSize(new String[] { gcName, "-XX:NewSize=128M", "-XX:MaxNewSize=50M"}, M128);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/g1/TestHumongousCodeCacheRoots.java	Fri Nov 15 21:39:27 2013 +0100
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @key regression
+ * @key gc
+ * @bug 8027756
+ * @library /testlibrary /testlibrary/whitebox
+ * @build TestHumongousCodeCacheRoots
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @summary Humongous objects may have references from the code cache
+ * @run main TestHumongousCodeCacheRoots
+*/
+
+import com.oracle.java.testlibrary.*;
+import sun.hotspot.WhiteBox;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+class TestHumongousCodeCacheRootsHelper {
+
+    static final int n = 1000000;
+    static final int[] AA = new int[n];
+    static final int[] BB = new int[n];
+
+    public static void main(String args[]) throws Exception {
+        // do some work so that the compiler compiles this method, inlining the
+        // reference to the integer array (which is a humonguous object) into
+        // the code cache.
+        for(int i = 0; i < n; i++) {
+            AA[i] = 0;
+            BB[i] = 0;
+        }
+        // trigger a GC that checks that the verification code allows humongous
+        // objects with code cache roots; objects should be all live here.
+        System.gc();
+
+        // deoptimize everyhing: this should make all compiled code zombies.
+        WhiteBox wb = WhiteBox.getWhiteBox();
+        wb.deoptimizeAll();
+
+        // trigger a GC that checks that the verification code allows humongous
+        // objects with code cache roots; objects should be all live here.
+        System.gc();
+
+        // wait a little for the code cache sweeper to try to clean up zombie nmethods
+        // and unregister the code roots.
+        try { Thread.sleep(5000); } catch (InterruptedException ex) { }
+
+        // do some work on the arrays to make sure that they need to be live after the GCs
+        for(int i = 0; i < n; i++) {
+            AA[i] = 1;
+            BB[i] = 10;
+        }
+
+        System.out.println();
+    }
+}
+
+public class TestHumongousCodeCacheRoots {
+
+  /**
+   * Executes a class in a new VM process with the given parameters.
+   * @param vmargs Arguments to the VM to run
+   * @param classname Name of the class to run
+   * @param arguments Arguments to the class
+   * @param useTestDotJavaDotOpts Use test.java.opts as part of the VM argument string
+   * @return The OutputAnalyzer with the results for the invocation.
+   */
+  public static OutputAnalyzer runWhiteBoxTest(String[] vmargs, String classname, String[] arguments, boolean useTestDotJavaDotOpts) throws Exception {
+    ArrayList<String> finalargs = new ArrayList<String>();
+
+    String[] whiteboxOpts = new String[] {
+      "-Xbootclasspath/a:.",
+      "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI",
+      "-cp", System.getProperty("java.class.path"),
+    };
+
+    if (useTestDotJavaDotOpts) {
+      // System.getProperty("test.java.opts") is '' if no options is set,
+      // we need to skip such a result
+      String[] externalVMOpts = new String[0];
+      if (System.getProperty("test.java.opts") != null && System.getProperty("test.java.opts").length() != 0) {
+        externalVMOpts = System.getProperty("test.java.opts").split(" ");
+      }
+      finalargs.addAll(Arrays.asList(externalVMOpts));
+    }
+
+    finalargs.addAll(Arrays.asList(vmargs));
+    finalargs.addAll(Arrays.asList(whiteboxOpts));
+    finalargs.add(classname);
+    finalargs.addAll(Arrays.asList(arguments));
+
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(finalargs.toArray(new String[0]));
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    output.shouldHaveExitValue(0);
+
+    return output;
+  }
+
+  public static void runTest(String compiler, String[] other) throws Exception {
+    ArrayList<String> joined = new ArrayList<String>();
+    joined.add(compiler);
+    joined.addAll(Arrays.asList(other));
+    runWhiteBoxTest(joined.toArray(new String[0]), TestHumongousCodeCacheRootsHelper.class.getName(),
+      new String[] {}, false);
+  }
+
+  public static void main(String[] args) throws Exception {
+    final String[] baseArguments = new String[] {
+      "-XX:+UseG1GC", "-XX:G1HeapRegionSize=1M", "-Xmx100M", // make sure we get a humongous region
+      "-XX:+UnlockDiagnosticVMOptions",
+      "-XX:InitiatingHeapOccupancyPercent=1", // strong code root marking
+      "-XX:+G1VerifyHeapRegionCodeRoots", "-XX:+VerifyAfterGC", // make sure that verification is run
+      "-XX:NmethodSweepFraction=1", "-XX:NmethodSweepCheckInterval=1",  // make the code cache sweep more predictable
+    };
+    runTest("-client", baseArguments);
+    runTest("-server", baseArguments);
+  }
+}
+