Merge
authorkvn
Thu, 25 Jun 2015 09:48:50 -0700
changeset 31412 32477ea959ee
parent 31411 92e500124bca (current diff)
parent 31402 78cd32274693 (diff)
child 31413 96a5b57297a3
Merge
hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp
hotspot/src/share/vm/opto/c2_globals.hpp
hotspot/src/share/vm/runtime/globals.hpp
hotspot/src/share/vm/runtime/vmStructs.cpp
--- a/hotspot/agent/make/Makefile	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/agent/make/Makefile	Thu Jun 25 09:48:50 2015 -0700
@@ -58,6 +58,7 @@
 sun.jvm.hotspot.debugger.dummy \
 sun.jvm.hotspot.debugger.linux \
 sun.jvm.hotspot.debugger.linux.amd64 \
+sun.jvm.hotspot.debugger.linux.aarch64 \
 sun.jvm.hotspot.debugger.linux.ppc64 \
 sun.jvm.hotspot.debugger.linux.x86 \
 sun.jvm.hotspot.debugger.posix \
@@ -65,6 +66,7 @@
 sun.jvm.hotspot.debugger.ppc64 \
 sun.jvm.hotspot.debugger.proc \
 sun.jvm.hotspot.debugger.proc.amd64 \
+sun.jvm.hotspot.debugger.proc.aarch64 \
 sun.jvm.hotspot.debugger.proc.ppc64 \
 sun.jvm.hotspot.debugger.proc.sparc \
 sun.jvm.hotspot.debugger.proc.x86 \
@@ -91,11 +93,13 @@
 sun.jvm.hotspot.prims \
 sun.jvm.hotspot.runtime \
 sun.jvm.hotspot.runtime.amd64 \
+sun.jvm.hotspot.runtime.aarch64 \
 sun.jvm.hotspot.runtime.bsd \
 sun.jvm.hotspot.runtime.bsd_amd64 \
 sun.jvm.hotspot.runtime.bsd_x86 \
 sun.jvm.hotspot.runtime.linux \
 sun.jvm.hotspot.runtime.linux_amd64 \
+sun.jvm.hotspot.runtime.linux_aarch64 \
 sun.jvm.hotspot.runtime.linux_ppc64 \
 sun.jvm.hotspot.runtime.linux_sparc \
 sun.jvm.hotspot.runtime.linux_x86 \
@@ -149,16 +153,19 @@
 sun/jvm/hotspot/debugger/linux/*.java \
 sun/jvm/hotspot/debugger/linux/ppc64/*.java \
 sun/jvm/hotspot/debugger/linux/x86/*.java \
+sun/jvm/hotspot/debugger/linux/aarch64/*.java \
 sun/jvm/hotspot/debugger/posix/*.java \
 sun/jvm/hotspot/debugger/posix/elf/*.java \
 sun/jvm/hotspot/debugger/ppc64/*.java \
 sun/jvm/hotspot/debugger/proc/*.java \
 sun/jvm/hotspot/debugger/proc/amd64/*.java \
+sun/jvm/hotspot/debugger/proc/aarch64/*.java \
 sun/jvm/hotspot/debugger/proc/ppc64/*.java \
 sun/jvm/hotspot/debugger/proc/sparc/*.java \
 sun/jvm/hotspot/debugger/proc/x86/*.java \
 sun/jvm/hotspot/debugger/remote/*.java \
 sun/jvm/hotspot/debugger/remote/amd64/*.java \
+sun/jvm/hotspot/debugger/remote/aarch64/*.java \
 sun/jvm/hotspot/debugger/remote/ppc64/*.java \
 sun/jvm/hotspot/debugger/remote/sparc/*.java \
 sun/jvm/hotspot/debugger/remote/x86/*.java \
@@ -178,11 +185,13 @@
 sun/jvm/hotspot/prims/*.java \
 sun/jvm/hotspot/runtime/*.java \
 sun/jvm/hotspot/runtime/amd64/*.java \
+sun/jvm/hotspot/runtime/aarch64/*.java \
 sun/jvm/hotspot/runtime/bsd/*.java \
 sun/jvm/hotspot/runtime/bsd_amd64/*.java \
 sun/jvm/hotspot/runtime/bsd_x86/*.java \
 sun/jvm/hotspot/runtime/linux/*.java \
 sun/jvm/hotspot/runtime/linux_amd64/*.java \
+sun/jvm/hotspot/runtime/linux_aarch64/*.java \
 sun/jvm/hotspot/runtime/linux_ppc64/*.java \
 sun/jvm/hotspot/runtime/linux_sparc/*.java \
 sun/jvm/hotspot/runtime/linux_x86/*.java \
--- a/hotspot/agent/src/os/linux/LinuxDebuggerLocal.c	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/agent/src/os/linux/LinuxDebuggerLocal.c	Thu Jun 25 09:48:50 2015 -0700
@@ -53,6 +53,10 @@
 #include "sun_jvm_hotspot_debugger_ppc64_PPC64ThreadContext.h"
 #endif
 
+#ifdef aarch64
+#include "sun_jvm_hotspot_debugger_aarch64_AARCH64ThreadContext.h"
+#endif
+
 static jfieldID p_ps_prochandle_ID = 0;
 static jfieldID threadList_ID = 0;
 static jfieldID loadObjectList_ID = 0;
@@ -368,7 +372,7 @@
 #define NPRGREG sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_NPRGREG
 #endif
 #ifdef aarch64
-#define NPRGREG 32
+#define NPRGREG sun_jvm_hotspot_debugger_aarch64_AARCH64ThreadContext_NPRGREG
 #endif
 #if defined(sparc) || defined(sparcv9)
 #define NPRGREG sun_jvm_hotspot_debugger_sparc_SPARCThreadContext_NPRGREG
@@ -473,6 +477,13 @@
 
 #define REG_INDEX(reg) sun_jvm_hotspot_debugger_aarch64_AARCH64ThreadContext_##reg
 
+  {
+    int i;
+    for (i = 0; i < 31; i++)
+      regs[i] = gregs.regs[i];
+    regs[REG_INDEX(SP)] = gregs.sp;
+    regs[REG_INDEX(PC)] = gregs.pc;
+  }
 #endif /* aarch64 */
 
 #ifdef ppc64
--- a/hotspot/agent/src/os/linux/Makefile	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/agent/src/os/linux/Makefile	Thu Jun 25 09:48:50 2015 -0700
@@ -53,14 +53,15 @@
         $(JAVAH) -jni -classpath ../../../build/classes -d $(ARCH) \
 		sun.jvm.hotspot.debugger.x86.X86ThreadContext \
 		sun.jvm.hotspot.debugger.sparc.SPARCThreadContext \
-		sun.jvm.hotspot.debugger.amd64.AMD64ThreadContext 
+		sun.jvm.hotspot.debugger.amd64.AMD64ThreadContext \
+		sun.jvm.hotspot.debugger.aarch64.AARCH64ThreadContext 
         $(GCC) $(CFLAGS) $< -o $@
 
 $(ARCH)/sadis.o:  ../../share/native/sadis.c
         $(JAVAH) -jni -classpath ../../../build/classes -d $(ARCH) \
                 sun.jvm.hotspot.asm.Disassembler
         $(GCC) $(CFLAGS) $< -o $@
- 
+
 $(ARCH)/%.o: %.c
         $(GCC) $(CFLAGS) $< -o $@
 
--- a/hotspot/agent/src/os/linux/libproc.h	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/agent/src/os/linux/libproc.h	Thu Jun 25 09:48:50 2015 -0700
@@ -72,6 +72,7 @@
 #define user_regs_struct  pt_regs
 #endif
 #if defined(aarch64)
+#include <asm/ptrace.h>
 #define user_regs_struct user_pt_regs
 #endif
 
--- a/hotspot/agent/src/os/linux/proc_service.h	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/agent/src/os/linux/proc_service.h	Thu Jun 25 09:48:50 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, 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
@@ -30,7 +30,7 @@
 
 // Linux does not have the proc service library, though it does provide the
 // thread_db library which can be used to manipulate threads without having
-// to know the details of LinuxThreads or NPTL
+// to know the details of NPTL
 
 // copied from Solaris "proc_service.h"
 typedef enum {
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/HSDB.java	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/HSDB.java	Thu Jun 25 09:48:50 2015 -0700
@@ -983,19 +983,15 @@
                                                      curFrame.getFP(),
                                                      anno));
             } else {
-              if (VM.getVM().getCPU().equals("x86") || VM.getVM().getCPU().equals("amd64")) {
-                // For C2, which has null frame pointers on x86/amd64
-                CodeBlob cb = VM.getVM().getCodeCache().findBlob(curFrame.getPC());
-                Address sp = curFrame.getSP();
-                if (Assert.ASSERTS_ENABLED) {
-                  Assert.that(cb.getFrameSize() > 0, "CodeBlob must have non-zero frame size");
-                }
-                annoPanel.addAnnotation(new Annotation(sp,
-                                                       sp.addOffsetTo(cb.getFrameSize()),
-                                                       anno));
-              } else {
-                Assert.that(VM.getVM().getCPU().equals("ia64"), "only ia64 should reach here");
+              // For C2, which has null frame pointers on x86/amd64/aarch64
+              CodeBlob cb = VM.getVM().getCodeCache().findBlob(curFrame.getPC());
+              Address sp = curFrame.getSP();
+              if (Assert.ASSERTS_ENABLED) {
+                Assert.that(cb.getFrameSize() > 0, "CodeBlob must have non-zero frame size");
               }
+              annoPanel.addAnnotation(new Annotation(sp,
+                                                     sp.addOffsetTo(cb.getFrameSize()),
+                                                     anno));
             }
 
             // Add interpreter frame annotations
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/aarch64/AARCH64ThreadContext.java	Thu Jun 25 09:48:50 2015 -0700
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Red Hat Inc.
+ * 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.
+ *
+ */
+
+package sun.jvm.hotspot.debugger.aarch64;
+
+import java.lang.annotation.Native;
+
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.debugger.cdbg.*;
+
+/** Specifies the thread context on aarch64 platforms; only a sub-portion
+ * of the context is guaranteed to be present on all operating
+ * systems. */
+
+public abstract class AARCH64ThreadContext implements ThreadContext {
+    // Taken from /usr/include/asm/sigcontext.h on Linux/AARCH64.
+
+    // NOTE: the indices for the various registers must be maintained as
+    // listed across various operating systems. However, only a small
+    // subset of the registers' values are guaranteed to be present (and
+    // must be present for the SA's stack walking to work)
+
+    // One instance of the Native annotation is enough to trigger header generation
+    // for this file.
+    @Native
+    public static final int R0 = 0;
+    public static final int R1 = 1;
+    public static final int R2 = 2;
+    public static final int R3 = 3;
+    public static final int R4 = 4;
+    public static final int R5 = 5;
+    public static final int R6 = 6;
+    public static final int R7 = 7;
+    public static final int R8 = 8;
+    public static final int R9 = 9;
+    public static final int R10 = 10;
+    public static final int R11 = 11;
+    public static final int R12 = 12;
+    public static final int R13 = 13;
+    public static final int R14 = 14;
+    public static final int R15 = 15;
+    public static final int R16 = 16;
+    public static final int R17 = 17;
+    public static final int R18 = 18;
+    public static final int R19 = 19;
+    public static final int R20 = 20;
+    public static final int R21 = 21;
+    public static final int R22 = 22;
+    public static final int R23 = 23;
+    public static final int R24 = 24;
+    public static final int R25 = 25;
+    public static final int R26 = 26;
+    public static final int R27 = 27;
+    public static final int R28 = 28;
+    public static final int FP = 29;
+    public static final int LR = 30;
+    public static final int SP = 31;
+    public static final int PC = 32;
+
+    public static final int NPRGREG = 33;
+
+    private long[] data;
+
+    public AARCH64ThreadContext() {
+        data = new long[NPRGREG];
+    }
+
+    public int getNumRegisters() {
+        return NPRGREG;
+    }
+
+    public String getRegisterName(int index) {
+        switch (index) {
+        case LR: return "lr";
+        case SP: return "sp";
+        case PC: return "pc";
+        default:
+            return "r" + index;
+        }
+    }
+
+    public void setRegister(int index, long value) {
+        data[index] = value;
+    }
+
+    public long getRegister(int index) {
+        return data[index];
+    }
+
+    public CFrame getTopFrame(Debugger dbg) {
+        return null;
+    }
+
+    /** This can't be implemented in this class since we would have to
+     * tie the implementation to, for example, the debugging system */
+    public abstract void setRegisterAsAddress(int index, Address value);
+
+    /** This can't be implemented in this class since we would have to
+     * tie the implementation to, for example, the debugging system */
+    public abstract Address getRegisterAsAddress(int index);
+}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/LinuxCDebugger.java	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/LinuxCDebugger.java	Thu Jun 25 09:48:50 2015 -0700
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Red Hat Inc.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,12 +32,14 @@
 import sun.jvm.hotspot.debugger.cdbg.*;
 import sun.jvm.hotspot.debugger.x86.*;
 import sun.jvm.hotspot.debugger.amd64.*;
+import sun.jvm.hotspot.debugger.aarch64.*;
 import sun.jvm.hotspot.debugger.sparc.*;
 import sun.jvm.hotspot.debugger.ppc64.*;
 import sun.jvm.hotspot.debugger.linux.x86.*;
 import sun.jvm.hotspot.debugger.linux.amd64.*;
 import sun.jvm.hotspot.debugger.linux.sparc.*;
 import sun.jvm.hotspot.debugger.linux.ppc64.*;
+import sun.jvm.hotspot.debugger.linux.aarch64.*;
 import sun.jvm.hotspot.utilities.*;
 
 class LinuxCDebugger implements CDebugger {
@@ -106,6 +109,13 @@
         Address pc  = context.getRegisterAsAddress(PPC64ThreadContext.PC);
         if (pc == null) return null;
         return new LinuxPPC64CFrame(dbg, sp, pc, LinuxDebuggerLocal.getAddressSize());
+    } else if (cpu.equals("aarch64")) {
+       AARCH64ThreadContext context = (AARCH64ThreadContext) thread.getContext();
+       Address fp = context.getRegisterAsAddress(AARCH64ThreadContext.FP);
+       if (fp == null) return null;
+       Address pc  = context.getRegisterAsAddress(AARCH64ThreadContext.PC);
+       if (pc == null) return null;
+       return new LinuxAARCH64CFrame(dbg, fp, pc);
      } else {
        // Runtime exception thrown by LinuxThreadContextFactory if unknown cpu
        ThreadContext context = (ThreadContext) thread.getContext();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/aarch64/LinuxAARCH64CFrame.java	Thu Jun 25 09:48:50 2015 -0700
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Red Hat Inc.
+ * 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.
+ *
+ */
+
+package sun.jvm.hotspot.debugger.linux.aarch64;
+
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.debugger.aarch64.*;
+import sun.jvm.hotspot.debugger.linux.*;
+import sun.jvm.hotspot.debugger.cdbg.*;
+import sun.jvm.hotspot.debugger.cdbg.basic.*;
+
+final public class LinuxAARCH64CFrame extends BasicCFrame {
+   public LinuxAARCH64CFrame(LinuxDebugger dbg, Address fp, Address pc) {
+      super(dbg.getCDebugger());
+      this.fp = fp;
+      this.pc = pc;
+      this.dbg = dbg;
+   }
+
+   // override base class impl to avoid ELF parsing
+   public ClosestSymbol closestSymbolToPC() {
+      // try native lookup in debugger.
+      return dbg.lookup(dbg.getAddressValue(pc()));
+   }
+
+   public Address pc() {
+      return pc;
+   }
+
+   public Address localVariableBase() {
+      return fp;
+   }
+
+   public CFrame sender(ThreadProxy thread) {
+      AARCH64ThreadContext context = (AARCH64ThreadContext) thread.getContext();
+      Address rsp = context.getRegisterAsAddress(AARCH64ThreadContext.SP);
+
+      if ((fp == null) || fp.lessThan(rsp)) {
+        return null;
+      }
+
+      // Check alignment of fp
+      if (dbg.getAddressValue(fp) % (2 * ADDRESS_SIZE) != 0) {
+        return null;
+      }
+
+      Address nextFP = fp.getAddressAt(0 * ADDRESS_SIZE);
+      if (nextFP == null || nextFP.lessThanOrEqual(fp)) {
+        return null;
+      }
+      Address nextPC  = fp.getAddressAt(1 * ADDRESS_SIZE);
+      if (nextPC == null) {
+        return null;
+      }
+      return new LinuxAARCH64CFrame(dbg, nextFP, nextPC);
+   }
+
+   // package/class internals only
+   private static final int ADDRESS_SIZE = 8;
+   private Address pc;
+   private Address sp;
+   private Address fp;
+   private LinuxDebugger dbg;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/aarch64/LinuxAARCH64ThreadContext.java	Thu Jun 25 09:48:50 2015 -0700
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Red Hat Inc.
+ * 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.
+ *
+ */
+
+package sun.jvm.hotspot.debugger.linux.aarch64;
+
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.debugger.aarch64.*;
+import sun.jvm.hotspot.debugger.linux.*;
+
+public class LinuxAARCH64ThreadContext extends AARCH64ThreadContext {
+  private LinuxDebugger debugger;
+
+  public LinuxAARCH64ThreadContext(LinuxDebugger debugger) {
+    super();
+    this.debugger = debugger;
+  }
+
+  public void setRegisterAsAddress(int index, Address value) {
+    setRegister(index, debugger.getAddressValue(value));
+  }
+
+  public Address getRegisterAsAddress(int index) {
+    return debugger.newAddress(getRegister(index));
+  }
+}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/proc/ProcDebuggerLocal.java	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/proc/ProcDebuggerLocal.java	Thu Jun 25 09:48:50 2015 -0700
@@ -31,11 +31,13 @@
 import sun.jvm.hotspot.debugger.*;
 import sun.jvm.hotspot.debugger.cdbg.*;
 import sun.jvm.hotspot.debugger.proc.amd64.*;
+import sun.jvm.hotspot.debugger.proc.aarch64.*;
 import sun.jvm.hotspot.debugger.proc.sparc.*;
 import sun.jvm.hotspot.debugger.proc.ppc64.*;
 import sun.jvm.hotspot.debugger.proc.x86.*;
 import sun.jvm.hotspot.debugger.ppc64.*;
 import sun.jvm.hotspot.debugger.amd64.*;
+import sun.jvm.hotspot.debugger.aarch64.*;
 import sun.jvm.hotspot.debugger.sparc.*;
 import sun.jvm.hotspot.debugger.x86.*;
 import sun.jvm.hotspot.utilities.*;
@@ -88,6 +90,10 @@
             threadFactory = new ProcAMD64ThreadFactory(this);
             pcRegIndex = AMD64ThreadContext.RIP;
             fpRegIndex = AMD64ThreadContext.RBP;
+        } else if (cpu.equals("aarch64")) {
+            threadFactory = new ProcAARCH64ThreadFactory(this);
+            pcRegIndex = AARCH64ThreadContext.PC;
+            fpRegIndex = AARCH64ThreadContext.FP;
         } else if (cpu.equals("ppc64")) {
             threadFactory = new ProcPPC64ThreadFactory(this);
             pcRegIndex = PPC64ThreadContext.PC;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/proc/aarch64/ProcAARCH64Thread.java	Thu Jun 25 09:48:50 2015 -0700
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Red Hat Inc.
+ * 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.
+ *
+ */
+
+package sun.jvm.hotspot.debugger.proc.aarch64;
+
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.debugger.aarch64.*;
+import sun.jvm.hotspot.debugger.proc.*;
+import sun.jvm.hotspot.utilities.*;
+
+public class ProcAARCH64Thread implements ThreadProxy {
+    private ProcDebugger debugger;
+    private int         id;
+
+    public ProcAARCH64Thread(ProcDebugger debugger, Address addr) {
+        this.debugger = debugger;
+
+        // FIXME: the size here should be configurable. However, making it
+        // so would produce a dependency on the "types" package from the
+        // debugger package, which is not desired.
+        this.id       = (int) addr.getCIntegerAt(0, 4, true);
+    }
+
+    public ProcAARCH64Thread(ProcDebugger debugger, long id) {
+        this.debugger = debugger;
+        this.id = (int) id;
+    }
+
+    public ThreadContext getContext() throws IllegalThreadStateException {
+        ProcAARCH64ThreadContext context = new ProcAARCH64ThreadContext(debugger);
+        long[] regs = debugger.getThreadIntegerRegisterSet(id);
+        if (Assert.ASSERTS_ENABLED) {
+            Assert.that(regs.length == AARCH64ThreadContext.NPRGREG, "size mismatch");
+        }
+        for (int i = 0; i < regs.length; i++) {
+            context.setRegister(i, regs[i]);
+        }
+        return context;
+    }
+
+    public boolean canSetContext() throws DebuggerException {
+        return false;
+    }
+
+    public void setContext(ThreadContext context)
+    throws IllegalThreadStateException, DebuggerException {
+        throw new DebuggerException("Unimplemented");
+    }
+
+    public String toString() {
+        return "t@" + id;
+    }
+
+    public boolean equals(Object obj) {
+        if ((obj == null) || !(obj instanceof ProcAARCH64Thread)) {
+            return false;
+        }
+
+        return (((ProcAARCH64Thread) obj).id == id);
+    }
+
+    public int hashCode() {
+        return id;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/proc/aarch64/ProcAARCH64ThreadContext.java	Thu Jun 25 09:48:50 2015 -0700
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Red Hat Inc.
+ * 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.
+ *
+ */
+
+package sun.jvm.hotspot.debugger.proc.aarch64;
+
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.debugger.aarch64.*;
+import sun.jvm.hotspot.debugger.proc.*;
+
+public class ProcAARCH64ThreadContext extends AARCH64ThreadContext {
+    private ProcDebugger debugger;
+
+    public ProcAARCH64ThreadContext(ProcDebugger debugger) {
+        super();
+        this.debugger = debugger;
+    }
+
+    public void setRegisterAsAddress(int index, Address value) {
+        setRegister(index, debugger.getAddressValue(value));
+    }
+
+    public Address getRegisterAsAddress(int index) {
+        return debugger.newAddress(getRegister(index));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/proc/aarch64/ProcAARCH64ThreadFactory.java	Thu Jun 25 09:48:50 2015 -0700
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Red Hat Inc.
+ * 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.
+ *
+ */
+
+package sun.jvm.hotspot.debugger.proc.aarch64;
+
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.debugger.proc.*;
+
+public class ProcAARCH64ThreadFactory implements ProcThreadFactory {
+    private ProcDebugger debugger;
+
+    public ProcAARCH64ThreadFactory(ProcDebugger debugger) {
+        this.debugger = debugger;
+    }
+
+    public ThreadProxy createThreadWrapper(Address threadIdentifierAddr) {
+        return new ProcAARCH64Thread(debugger, threadIdentifierAddr);
+    }
+
+    public ThreadProxy createThreadWrapper(long id) {
+        return new ProcAARCH64Thread(debugger, id);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/remote/aarch64/RemoteAARCH64Thread.java	Thu Jun 25 09:48:50 2015 -0700
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Red Hat Inc.
+ * 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.
+ *
+ */
+
+package sun.jvm.hotspot.debugger.remote.aarch64;
+
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.debugger.aarch64.*;
+import sun.jvm.hotspot.debugger.remote.*;
+import sun.jvm.hotspot.utilities.*;
+
+public class RemoteAARCH64Thread extends RemoteThread  {
+  public RemoteAARCH64Thread(RemoteDebuggerClient debugger, Address addr) {
+     super(debugger, addr);
+  }
+
+  public RemoteAARCH64Thread(RemoteDebuggerClient debugger, long id) {
+     super(debugger, id);
+  }
+
+  public ThreadContext getContext() throws IllegalThreadStateException {
+    RemoteAARCH64ThreadContext context = new RemoteAARCH64ThreadContext(debugger);
+    long[] regs = (addr != null)? debugger.getThreadIntegerRegisterSet(addr) :
+                                  debugger.getThreadIntegerRegisterSet(id);
+    if (Assert.ASSERTS_ENABLED) {
+      Assert.that(regs.length == AARCH64ThreadContext.NPRGREG, "size of register set must match");
+    }
+    for (int i = 0; i < regs.length; i++) {
+      context.setRegister(i, regs[i]);
+    }
+    return context;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/remote/aarch64/RemoteAARCH64ThreadContext.java	Thu Jun 25 09:48:50 2015 -0700
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Red Hat Inc.
+ * 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.
+ *
+ */
+
+package sun.jvm.hotspot.debugger.remote.aarch64;
+
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.debugger.aarch64.*;
+import sun.jvm.hotspot.debugger.remote.*;
+
+public class RemoteAARCH64ThreadContext extends AARCH64ThreadContext {
+  private RemoteDebuggerClient debugger;
+
+  public RemoteAARCH64ThreadContext(RemoteDebuggerClient debugger) {
+    super();
+    this.debugger = debugger;
+  }
+
+  public void setRegisterAsAddress(int index, Address value) {
+    setRegister(index, debugger.getAddressValue(value));
+  }
+
+  public Address getRegisterAsAddress(int index) {
+    return debugger.newAddress(getRegister(index));
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/remote/aarch64/RemoteAARCH64ThreadFactory.java	Thu Jun 25 09:48:50 2015 -0700
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Red Hat Inc.
+ * 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.
+ *
+ */
+
+package sun.jvm.hotspot.debugger.remote.aarch64;
+
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.debugger.remote.*;
+
+public class RemoteAARCH64ThreadFactory implements RemoteThreadFactory {
+  private RemoteDebuggerClient debugger;
+
+  public RemoteAARCH64ThreadFactory(RemoteDebuggerClient debugger) {
+    this.debugger = debugger;
+  }
+
+  public ThreadProxy createThreadWrapper(Address threadIdentifierAddr) {
+    return new RemoteAARCH64Thread(debugger, threadIdentifierAddr);
+  }
+
+  public ThreadProxy createThreadWrapper(long id) {
+    return new RemoteAARCH64Thread(debugger, id);
+  }
+}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc/shared/Generation.java	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc/shared/Generation.java	Thu Jun 25 09:48:50 2015 -0700
@@ -49,7 +49,6 @@
 public abstract class Generation extends VMObject {
   private static long          reservedFieldOffset;
   private static long          virtualSpaceFieldOffset;
-  private static CIntegerField levelField;
   protected static final int  K = 1024;
   // Fields for class StatRecord
   private static Field         statRecordField;
@@ -75,7 +74,6 @@
 
     reservedFieldOffset     = type.getField("_reserved").getOffset();
     virtualSpaceFieldOffset = type.getField("_virtual_space").getOffset();
-    levelField              = type.getCIntegerField("_level");
     // StatRecord
     statRecordField         = type.getField("_stat_record");
     type                    = db.lookupType("Generation::StatRecord");
@@ -130,14 +128,6 @@
      }
   }
 
-  public GenerationSpec spec() {
-    return ((GenCollectedHeap) VM.getVM().getUniverse().heap()).spec(level());
-  }
-
-  public int level() {
-    return (int) levelField.getValue(addr);
-  }
-
   public int invocations() {
     return getStatRecord().getInvocations();
   }
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/Frame.java	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/Frame.java	Thu Jun 25 09:48:50 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, 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
@@ -357,12 +357,6 @@
   // FIXME: avoiding implementing this for now if possible
   //  public void interpreter_frame_set_monitor_end(BasicObjectLock* value);
   //  public void interpreter_frame_verify_monitor(BasicObjectLock* value) const;
-  //
-  // Tells whether the current interpreter_frame frame pointer
-  // corresponds to the old compiled/deoptimized fp
-  // The receiver used to be a top level frame
-  // public boolean interpreter_frame_equals_unpacked_fp(intptr_t* fp);
-
   //--------------------------------------------------------------------------------
   // Method and constant pool cache:
   //
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/Threads.java	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/Threads.java	Thu Jun 25 09:48:50 2015 -0700
@@ -35,6 +35,7 @@
 import sun.jvm.hotspot.runtime.win32_x86.Win32X86JavaThreadPDAccess;
 import sun.jvm.hotspot.runtime.linux_x86.LinuxX86JavaThreadPDAccess;
 import sun.jvm.hotspot.runtime.linux_amd64.LinuxAMD64JavaThreadPDAccess;
+import sun.jvm.hotspot.runtime.linux_aarch64.LinuxAARCH64JavaThreadPDAccess;
 import sun.jvm.hotspot.runtime.linux_ppc64.LinuxPPC64JavaThreadPDAccess;
 import sun.jvm.hotspot.runtime.linux_sparc.LinuxSPARCJavaThreadPDAccess;
 import sun.jvm.hotspot.runtime.bsd_x86.BsdX86JavaThreadPDAccess;
@@ -91,6 +92,8 @@
                 access = new LinuxSPARCJavaThreadPDAccess();
             } else if (cpu.equals("ppc64")) {
                 access = new LinuxPPC64JavaThreadPDAccess();
+            } else if (cpu.equals("aarch64")) {
+                access = new LinuxAARCH64JavaThreadPDAccess();
             } else {
               try {
                 access = (JavaThreadPDAccess)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/aarch64/AARCH64CurrentFrameGuess.java	Thu Jun 25 09:48:50 2015 -0700
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Red Hat Inc.
+ * 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.
+ *
+ */
+
+package sun.jvm.hotspot.runtime.aarch64;
+
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.debugger.aarch64.*;
+import sun.jvm.hotspot.code.*;
+import sun.jvm.hotspot.interpreter.*;
+import sun.jvm.hotspot.runtime.*;
+import sun.jvm.hotspot.runtime.aarch64.*;
+
+/** <P> Should be able to be used on all aarch64 platforms we support
+    (Linux/aarch64) to implement JavaThread's "currentFrameGuess()"
+    functionality. Input is an AARCH64ThreadContext; output is SP, FP,
+    and PC for an AARCH64Frame. Instantiation of the AARCH64Frame is
+    left to the caller, since we may need to subclass AARCH64Frame to
+    support signal handler frames on Unix platforms. </P>
+
+    <P> Algorithm is to walk up the stack within a given range (say,
+    512K at most) looking for a plausible PC and SP for a Java frame,
+    also considering those coming in from the context. If we find a PC
+    that belongs to the VM (i.e., in generated code like the
+    interpreter or CodeCache) then we try to find an associated FP.
+    We repeat this until we either find a complete frame or run out of
+    stack to look at. </P> */
+
+public class AARCH64CurrentFrameGuess {
+  private AARCH64ThreadContext context;
+  private JavaThread       thread;
+  private Address          spFound;
+  private Address          fpFound;
+  private Address          pcFound;
+
+  private static final boolean DEBUG = System.getProperty("sun.jvm.hotspot.runtime.aarch64.AARCH64Frame.DEBUG")
+                                       != null;
+
+  public AARCH64CurrentFrameGuess(AARCH64ThreadContext context,
+                              JavaThread thread) {
+    this.context = context;
+    this.thread  = thread;
+  }
+
+  /** Returns false if not able to find a frame within a reasonable range. */
+  public boolean run(long regionInBytesToSearch) {
+    Address sp  = context.getRegisterAsAddress(AARCH64ThreadContext.SP);
+    Address pc  = context.getRegisterAsAddress(AARCH64ThreadContext.PC);
+    Address fp  = context.getRegisterAsAddress(AARCH64ThreadContext.FP);
+    if (sp == null) {
+      // Bail out if no last java frame either
+      if (thread.getLastJavaSP() != null) {
+        setValues(thread.getLastJavaSP(), thread.getLastJavaFP(), null);
+        return true;
+      }
+      return false;
+    }
+    Address end = sp.addOffsetTo(regionInBytesToSearch);
+    VM vm       = VM.getVM();
+
+    setValues(null, null, null); // Assume we're not going to find anything
+
+    if (vm.isJavaPCDbg(pc)) {
+      if (vm.isClientCompiler()) {
+        // If the topmost frame is a Java frame, we are (pretty much)
+        // guaranteed to have a viable FP. We should be more robust
+        // than this (we have the potential for losing entire threads'
+        // stack traces) but need to see how much work we really have
+        // to do here. Searching the stack for an (SP, FP) pair is
+        // hard since it's easy to misinterpret inter-frame stack
+        // pointers as base-of-frame pointers; we also don't know the
+        // sizes of C1 frames (not registered in the nmethod) so can't
+        // derive them from SP.
+
+        setValues(sp, fp, pc);
+        return true;
+      } else {
+        if (vm.getInterpreter().contains(pc)) {
+          if (DEBUG) {
+            System.out.println("CurrentFrameGuess: choosing interpreter frame: sp = " +
+                               sp + ", fp = " + fp + ", pc = " + pc);
+          }
+          setValues(sp, fp, pc);
+          return true;
+        }
+
+        // For the server compiler, FP is not guaranteed to be valid
+        // for compiled code. In addition, an earlier attempt at a
+        // non-searching algorithm (see below) failed because the
+        // stack pointer from the thread context was pointing
+        // (considerably) beyond the ostensible end of the stack, into
+        // garbage; walking from the topmost frame back caused a crash.
+        //
+        // This algorithm takes the current PC as a given and tries to
+        // find the correct corresponding SP by walking up the stack
+        // and repeatedly performing stackwalks (very inefficient).
+        //
+        // FIXME: there is something wrong with stackwalking across
+        // adapter frames...this is likely to be the root cause of the
+        // failure with the simpler algorithm below.
+
+        for (long offset = 0;
+             offset < regionInBytesToSearch;
+             offset += vm.getAddressSize()) {
+          try {
+            Address curSP = sp.addOffsetTo(offset);
+            Frame frame = new AARCH64Frame(curSP, null, pc);
+            RegisterMap map = thread.newRegisterMap(false);
+            while (frame != null) {
+              if (frame.isEntryFrame() && frame.entryFrameIsFirst()) {
+                // We were able to traverse all the way to the
+                // bottommost Java frame.
+                // This sp looks good. Keep it.
+                if (DEBUG) {
+                  System.out.println("CurrentFrameGuess: Choosing sp = " + curSP + ", pc = " + pc);
+                }
+                setValues(curSP, null, pc);
+                return true;
+              }
+              frame = frame.sender(map);
+            }
+          } catch (Exception e) {
+            if (DEBUG) {
+              System.out.println("CurrentFrameGuess: Exception " + e + " at offset " + offset);
+            }
+            // Bad SP. Try another.
+          }
+        }
+
+        // Were not able to find a plausible SP to go with this PC.
+        // Bail out.
+        return false;
+
+        /*
+        // Original algorithm which does not work because SP was
+        // pointing beyond where it should have:
+
+        // For the server compiler, FP is not guaranteed to be valid
+        // for compiled code. We see whether the PC is in the
+        // interpreter and take care of that, otherwise we run code
+        // (unfortunately) duplicated from AARCH64Frame.senderForCompiledFrame.
+
+        CodeCache cc = vm.getCodeCache();
+        if (cc.contains(pc)) {
+          CodeBlob cb = cc.findBlob(pc);
+
+          // See if we can derive a frame pointer from SP and PC
+          // NOTE: This is the code duplicated from AARCH64Frame
+          Address saved_fp = null;
+          int llink_offset = cb.getLinkOffset();
+          if (llink_offset >= 0) {
+            // Restore base-pointer, since next frame might be an interpreter frame.
+            Address fp_addr = sp.addOffsetTo(VM.getVM().getAddressSize() * llink_offset);
+            saved_fp = fp_addr.getAddressAt(0);
+          }
+
+          setValues(sp, saved_fp, pc);
+          return true;
+        }
+        */
+      }
+    } else {
+      // If the current program counter was not known to us as a Java
+      // PC, we currently assume that we are in the run-time system
+      // and attempt to look to thread-local storage for saved SP and
+      // FP. Note that if these are null (because we were, in fact,
+      // in Java code, i.e., vtable stubs or similar, and the SA
+      // didn't have enough insight into the target VM to understand
+      // that) then we are going to lose the entire stack trace for
+      // the thread, which is sub-optimal. FIXME.
+
+      if (DEBUG) {
+        System.out.println("CurrentFrameGuess: choosing last Java frame: sp = " +
+                           thread.getLastJavaSP() + ", fp = " + thread.getLastJavaFP());
+      }
+      if (thread.getLastJavaSP() == null) {
+        return false; // No known Java frames on stack
+      }
+
+      // The runtime has a nasty habit of not saving fp in the frame
+      // anchor, leaving us to grovel about in the stack to find a
+      // plausible address.  Fortunately, this only happens in
+      // compiled code; there we always have a valid PC, and we always
+      // push LR and FP onto the stack as a pair, with FP at the lower
+      // address.
+      pc = thread.getLastJavaPC();
+      fp = thread.getLastJavaFP();
+      sp = thread.getLastJavaSP();
+
+      if (fp == null) {
+        CodeCache cc = vm.getCodeCache();
+        if (cc.contains(pc)) {
+          CodeBlob cb = cc.findBlob(pc);
+          if (DEBUG) {
+            System.out.println("FP is null.  Found blob frame size " + cb.getFrameSize());
+          }
+          // See if we can derive a frame pointer from SP and PC
+          long link_offset = cb.getFrameSize() - 2 * VM.getVM().getAddressSize();
+          if (link_offset >= 0) {
+            fp = sp.addOffsetTo(link_offset);
+          }
+        }
+      }
+
+      setValues(sp, fp, null);
+
+      return true;
+    }
+  }
+
+  public Address getSP() { return spFound; }
+  public Address getFP() { return fpFound; }
+  /** May be null if getting values from thread-local storage; take
+      care to call the correct AARCH64Frame constructor to recover this if
+      necessary */
+  public Address getPC() { return pcFound; }
+
+  private void setValues(Address sp, Address fp, Address pc) {
+    spFound = sp;
+    fpFound = fp;
+    pcFound = pc;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/aarch64/AARCH64Frame.java	Thu Jun 25 09:48:50 2015 -0700
@@ -0,0 +1,555 @@
+/*
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Red Hat Inc.
+ * 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.
+ *
+ */
+
+package sun.jvm.hotspot.runtime.aarch64;
+
+import java.util.*;
+import sun.jvm.hotspot.code.*;
+import sun.jvm.hotspot.compiler.*;
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.oops.*;
+import sun.jvm.hotspot.runtime.*;
+import sun.jvm.hotspot.types.*;
+import sun.jvm.hotspot.utilities.*;
+
+/** Specialization of and implementation of abstract methods of the
+    Frame class for the aarch64 family of CPUs. */
+
+public class AARCH64Frame extends Frame {
+  private static final boolean DEBUG;
+  static {
+    DEBUG = System.getProperty("sun.jvm.hotspot.runtime.aarch64.AARCH64Frame.DEBUG") != null;
+  }
+
+  // All frames
+  private static final int LINK_OFFSET                =  0;
+  private static final int RETURN_ADDR_OFFSET         =  1;
+  private static final int SENDER_SP_OFFSET           =  2;
+
+  // Interpreter frames
+  private static final int INTERPRETER_FRAME_MIRROR_OFFSET    =  2; // for native calls only
+  private static final int INTERPRETER_FRAME_SENDER_SP_OFFSET = -1;
+  private static final int INTERPRETER_FRAME_LAST_SP_OFFSET   = INTERPRETER_FRAME_SENDER_SP_OFFSET - 1;
+  private static final int INTERPRETER_FRAME_METHOD_OFFSET    = INTERPRETER_FRAME_LAST_SP_OFFSET - 1;
+  private static       int INTERPRETER_FRAME_MDX_OFFSET;         // Non-core builds only
+  private static       int INTERPRETER_FRAME_CACHE_OFFSET;
+  private static       int INTERPRETER_FRAME_LOCALS_OFFSET;
+  private static       int INTERPRETER_FRAME_BCX_OFFSET;
+  private static       int INTERPRETER_FRAME_INITIAL_SP_OFFSET;
+  private static       int INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET;
+  private static       int INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET;
+
+  // Entry frames
+  private static       int ENTRY_FRAME_CALL_WRAPPER_OFFSET = -8;
+
+  // Native frames
+  private static final int NATIVE_FRAME_INITIAL_PARAM_OFFSET =  2;
+
+  private static VMReg fp = new VMReg(29);
+
+  static {
+    VM.registerVMInitializedObserver(new Observer() {
+        public void update(Observable o, Object data) {
+          initialize(VM.getVM().getTypeDataBase());
+        }
+      });
+  }
+
+  private static synchronized void initialize(TypeDataBase db) {
+    INTERPRETER_FRAME_MDX_OFFSET                  = INTERPRETER_FRAME_METHOD_OFFSET - 1;
+    INTERPRETER_FRAME_CACHE_OFFSET                = INTERPRETER_FRAME_MDX_OFFSET - 1;
+    INTERPRETER_FRAME_LOCALS_OFFSET               = INTERPRETER_FRAME_CACHE_OFFSET - 1;
+    INTERPRETER_FRAME_BCX_OFFSET                  = INTERPRETER_FRAME_LOCALS_OFFSET - 1;
+    INTERPRETER_FRAME_INITIAL_SP_OFFSET           = INTERPRETER_FRAME_BCX_OFFSET - 1;
+    INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET    = INTERPRETER_FRAME_INITIAL_SP_OFFSET;
+    INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET;
+  }
+
+
+  // an additional field beyond sp and pc:
+  Address raw_fp; // frame pointer
+  private Address raw_unextendedSP;
+
+  private AARCH64Frame() {
+  }
+
+  private void adjustForDeopt() {
+    if ( pc != null) {
+      // Look for a deopt pc and if it is deopted convert to original pc
+      CodeBlob cb = VM.getVM().getCodeCache().findBlob(pc);
+      if (cb != null && cb.isJavaMethod()) {
+        NMethod nm = (NMethod) cb;
+        if (pc.equals(nm.deoptHandlerBegin())) {
+          if (Assert.ASSERTS_ENABLED) {
+            Assert.that(this.getUnextendedSP() != null, "null SP in Java frame");
+          }
+          // adjust pc if frame is deoptimized.
+          pc = this.getUnextendedSP().getAddressAt(nm.origPCOffset());
+          deoptimized = true;
+        }
+      }
+    }
+  }
+
+  public AARCH64Frame(Address raw_sp, Address raw_fp, Address pc) {
+    this.raw_sp = raw_sp;
+    this.raw_unextendedSP = raw_sp;
+    this.raw_fp = raw_fp;
+    this.pc = pc;
+    adjustUnextendedSP();
+
+    // Frame must be fully constructed before this call
+    adjustForDeopt();
+
+    if (DEBUG) {
+      System.out.println("AARCH64Frame(sp, fp, pc): " + this);
+      dumpStack();
+    }
+  }
+
+  public AARCH64Frame(Address raw_sp, Address raw_fp) {
+    this.raw_sp = raw_sp;
+    this.raw_unextendedSP = raw_sp;
+    this.raw_fp = raw_fp;
+    this.pc = raw_sp.getAddressAt(-1 * VM.getVM().getAddressSize());
+    adjustUnextendedSP();
+
+    // Frame must be fully constructed before this call
+    adjustForDeopt();
+
+    if (DEBUG) {
+      System.out.println("AARCH64Frame(sp, fp): " + this);
+      dumpStack();
+    }
+  }
+
+  public AARCH64Frame(Address raw_sp, Address raw_unextendedSp, Address raw_fp, Address pc) {
+    this.raw_sp = raw_sp;
+    this.raw_unextendedSP = raw_unextendedSp;
+    this.raw_fp = raw_fp;
+    this.pc = pc;
+    adjustUnextendedSP();
+
+    // Frame must be fully constructed before this call
+    adjustForDeopt();
+
+    if (DEBUG) {
+      System.out.println("AARCH64Frame(sp, unextendedSP, fp, pc): " + this);
+      dumpStack();
+    }
+
+  }
+
+  public Object clone() {
+    AARCH64Frame frame = new AARCH64Frame();
+    frame.raw_sp = raw_sp;
+    frame.raw_unextendedSP = raw_unextendedSP;
+    frame.raw_fp = raw_fp;
+    frame.pc = pc;
+    frame.deoptimized = deoptimized;
+    return frame;
+  }
+
+  public boolean equals(Object arg) {
+    if (arg == null) {
+      return false;
+    }
+
+    if (!(arg instanceof AARCH64Frame)) {
+      return false;
+    }
+
+    AARCH64Frame other = (AARCH64Frame) arg;
+
+    return (AddressOps.equal(getSP(), other.getSP()) &&
+            AddressOps.equal(getUnextendedSP(), other.getUnextendedSP()) &&
+            AddressOps.equal(getFP(), other.getFP()) &&
+            AddressOps.equal(getPC(), other.getPC()));
+  }
+
+  public int hashCode() {
+    if (raw_sp == null) {
+      return 0;
+    }
+
+    return raw_sp.hashCode();
+  }
+
+  public String toString() {
+    return "sp: " + (getSP() == null? "null" : getSP().toString()) +
+         ", unextendedSP: " + (getUnextendedSP() == null? "null" : getUnextendedSP().toString()) +
+         ", fp: " + (getFP() == null? "null" : getFP().toString()) +
+         ", pc: " + (pc == null? "null" : pc.toString());
+  }
+
+  // accessors for the instance variables
+  public Address getFP() { return raw_fp; }
+  public Address getSP() { return raw_sp; }
+  public Address getID() { return raw_sp; }
+
+  // FIXME: not implemented yet
+  public boolean isSignalHandlerFrameDbg() { return false; }
+  public int     getSignalNumberDbg()      { return 0;     }
+  public String  getSignalNameDbg()        { return null;  }
+
+  public boolean isInterpretedFrameValid() {
+    if (Assert.ASSERTS_ENABLED) {
+      Assert.that(isInterpretedFrame(), "Not an interpreted frame");
+    }
+
+    // These are reasonable sanity checks
+    if (getFP() == null || getFP().andWithMask(0x3) != null) {
+      return false;
+    }
+
+    if (getSP() == null || getSP().andWithMask(0x3) != null) {
+      return false;
+    }
+
+    if (getFP().addOffsetTo(INTERPRETER_FRAME_INITIAL_SP_OFFSET * VM.getVM().getAddressSize()).lessThan(getSP())) {
+      return false;
+    }
+
+    // These are hacks to keep us out of trouble.
+    // The problem with these is that they mask other problems
+    if (getFP().lessThanOrEqual(getSP())) {
+      // this attempts to deal with unsigned comparison above
+      return false;
+    }
+
+    if (getFP().minus(getSP()) > 4096 * VM.getVM().getAddressSize()) {
+      // stack frames shouldn't be large.
+      return false;
+    }
+
+    return true;
+  }
+
+  // FIXME: not applicable in current system
+  //  void    patch_pc(Thread* thread, address pc);
+
+  public Frame sender(RegisterMap regMap, CodeBlob cb) {
+    AARCH64RegisterMap map = (AARCH64RegisterMap) regMap;
+
+    if (Assert.ASSERTS_ENABLED) {
+      Assert.that(map != null, "map must be set");
+    }
+
+    // Default is we done have to follow them. The sender_for_xxx will
+    // update it accordingly
+    map.setIncludeArgumentOops(false);
+
+    if (isEntryFrame())       return senderForEntryFrame(map);
+    if (isInterpretedFrame()) return senderForInterpreterFrame(map);
+
+    if(cb == null) {
+      cb = VM.getVM().getCodeCache().findBlob(getPC());
+    } else {
+      if (Assert.ASSERTS_ENABLED) {
+        Assert.that(cb.equals(VM.getVM().getCodeCache().findBlob(getPC())), "Must be the same");
+      }
+    }
+
+    if (cb != null) {
+      return senderForCompiledFrame(map, cb);
+    }
+
+    // Must be native-compiled frame, i.e. the marshaling code for native
+    // methods that exists in the core system.
+    return new AARCH64Frame(getSenderSP(), getLink(), getSenderPC());
+  }
+
+  private Frame senderForEntryFrame(AARCH64RegisterMap map) {
+    if (DEBUG) {
+      System.out.println("senderForEntryFrame");
+    }
+    if (Assert.ASSERTS_ENABLED) {
+      Assert.that(map != null, "map must be set");
+    }
+    // Java frame called from C; skip all C frames and return top C
+    // frame of that chunk as the sender
+    AARCH64JavaCallWrapper jcw = (AARCH64JavaCallWrapper) getEntryFrameCallWrapper();
+    if (Assert.ASSERTS_ENABLED) {
+      Assert.that(!entryFrameIsFirst(), "next Java fp must be non zero");
+      Assert.that(jcw.getLastJavaSP().greaterThan(getSP()), "must be above this frame on stack");
+    }
+    AARCH64Frame fr;
+    if (jcw.getLastJavaPC() != null) {
+      fr = new AARCH64Frame(jcw.getLastJavaSP(), jcw.getLastJavaFP(), jcw.getLastJavaPC());
+    } else {
+      fr = new AARCH64Frame(jcw.getLastJavaSP(), jcw.getLastJavaFP());
+    }
+    map.clear();
+    if (Assert.ASSERTS_ENABLED) {
+      Assert.that(map.getIncludeArgumentOops(), "should be set by clear");
+    }
+    return fr;
+  }
+
+  //------------------------------------------------------------------------------
+  // frame::adjust_unextended_sp
+  private void adjustUnextendedSP() {
+    // If we are returning to a compiled MethodHandle call site, the
+    // saved_fp will in fact be a saved value of the unextended SP.  The
+    // simplest way to tell whether we are returning to such a call site
+    // is as follows:
+
+    CodeBlob cb = cb();
+    NMethod senderNm = (cb == null) ? null : cb.asNMethodOrNull();
+    if (senderNm != null) {
+      // If the sender PC is a deoptimization point, get the original
+      // PC.  For MethodHandle call site the unextended_sp is stored in
+      // saved_fp.
+      if (senderNm.isDeoptMhEntry(getPC())) {
+        // DEBUG_ONLY(verifyDeoptMhOriginalPc(senderNm, getFP()));
+        raw_unextendedSP = getFP();
+      }
+      else if (senderNm.isDeoptEntry(getPC())) {
+        // DEBUG_ONLY(verifyDeoptOriginalPc(senderNm, raw_unextendedSp));
+      }
+      else if (senderNm.isMethodHandleReturn(getPC())) {
+        raw_unextendedSP = getFP();
+      }
+    }
+  }
+
+  private Frame senderForInterpreterFrame(AARCH64RegisterMap map) {
+    if (DEBUG) {
+      System.out.println("senderForInterpreterFrame");
+    }
+    Address unextendedSP = addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0);
+    Address sp = addressOfStackSlot(SENDER_SP_OFFSET);
+    // We do not need to update the callee-save register mapping because above
+    // us is either another interpreter frame or a converter-frame, but never
+    // directly a compiled frame.
+    // 11/24/04 SFG. With the removal of adapter frames this is no longer true.
+    // However c2 no longer uses callee save register for java calls so there
+    // are no callee register to find.
+
+    if (map.getUpdateMap())
+      updateMapWithSavedLink(map, addressOfStackSlot(LINK_OFFSET));
+
+    return new AARCH64Frame(sp, unextendedSP, getLink(), getSenderPC());
+  }
+
+  private void updateMapWithSavedLink(RegisterMap map, Address savedFPAddr) {
+    map.setLocation(fp, savedFPAddr);
+  }
+
+  private Frame senderForCompiledFrame(AARCH64RegisterMap map, CodeBlob cb) {
+    if (DEBUG) {
+      System.out.println("senderForCompiledFrame");
+    }
+
+    //
+    // NOTE: some of this code is (unfortunately) duplicated  AARCH64CurrentFrameGuess
+    //
+
+    if (Assert.ASSERTS_ENABLED) {
+      Assert.that(map != null, "map must be set");
+    }
+
+    // frame owned by optimizing compiler
+    if (Assert.ASSERTS_ENABLED) {
+        Assert.that(cb.getFrameSize() >= 0, "must have non-zero frame size");
+    }
+    Address senderSP = getUnextendedSP().addOffsetTo(cb.getFrameSize());
+
+    // The return_address is always the word on the stack
+    Address senderPC = senderSP.getAddressAt(-1 * VM.getVM().getAddressSize());
+
+    // This is the saved value of FP which may or may not really be an FP.
+    // It is only an FP if the sender is an interpreter frame.
+    Address savedFPAddr = senderSP.addOffsetTo(- SENDER_SP_OFFSET * VM.getVM().getAddressSize());
+
+    if (map.getUpdateMap()) {
+      // Tell GC to use argument oopmaps for some runtime stubs that need it.
+      // For C1, the runtime stub might not have oop maps, so set this flag
+      // outside of update_register_map.
+      map.setIncludeArgumentOops(cb.callerMustGCArguments());
+
+      if (cb.getOopMaps() != null) {
+        ImmutableOopMapSet.updateRegisterMap(this, cb, map, true);
+      }
+
+      // Since the prolog does the save and restore of FP there is no oopmap
+      // for it so we must fill in its location as if there was an oopmap entry
+      // since if our caller was compiled code there could be live jvm state in it.
+      updateMapWithSavedLink(map, savedFPAddr);
+    }
+
+    return new AARCH64Frame(senderSP, savedFPAddr.getAddressAt(0), senderPC);
+  }
+
+  protected boolean hasSenderPD() {
+    return true;
+  }
+
+  public long frameSize() {
+    return (getSenderSP().minus(getSP()) / VM.getVM().getAddressSize());
+  }
+
+    public Address getLink() {
+        try {
+            if (DEBUG) {
+                System.out.println("Reading link at " + addressOfStackSlot(LINK_OFFSET)
+                        + " = " + addressOfStackSlot(LINK_OFFSET).getAddressAt(0));
+            }
+            return addressOfStackSlot(LINK_OFFSET).getAddressAt(0);
+        } catch (Exception e) {
+            if (DEBUG)
+                System.out.println("Returning null");
+            return null;
+        }
+    }
+
+  // FIXME: not implementable yet
+  //inline void      frame::set_link(intptr_t* addr)  { *(intptr_t **)addr_at(link_offset) = addr; }
+
+  public Address getUnextendedSP() { return raw_unextendedSP; }
+
+  // Return address:
+  public Address getSenderPCAddr() { return addressOfStackSlot(RETURN_ADDR_OFFSET); }
+  public Address getSenderPC()     { return getSenderPCAddr().getAddressAt(0);      }
+
+  // return address of param, zero origin index.
+  public Address getNativeParamAddr(int idx) {
+    return addressOfStackSlot(NATIVE_FRAME_INITIAL_PARAM_OFFSET + idx);
+  }
+
+  public Address getSenderSP()     { return addressOfStackSlot(SENDER_SP_OFFSET); }
+
+  public Address addressOfInterpreterFrameLocals() {
+    return addressOfStackSlot(INTERPRETER_FRAME_LOCALS_OFFSET);
+  }
+
+  private Address addressOfInterpreterFrameBCX() {
+    return addressOfStackSlot(INTERPRETER_FRAME_BCX_OFFSET);
+  }
+
+  public int getInterpreterFrameBCI() {
+    // FIXME: this is not atomic with respect to GC and is unsuitable
+    // for use in a non-debugging, or reflective, system. Need to
+    // figure out how to express this.
+    Address bcp = addressOfInterpreterFrameBCX().getAddressAt(0);
+    Address methodHandle = addressOfInterpreterFrameMethod().getAddressAt(0);
+    Method method = (Method)Metadata.instantiateWrapperFor(methodHandle);
+    return bcpToBci(bcp, method);
+  }
+
+  public Address addressOfInterpreterFrameMDX() {
+    return addressOfStackSlot(INTERPRETER_FRAME_MDX_OFFSET);
+  }
+
+  // FIXME
+  //inline int frame::interpreter_frame_monitor_size() {
+  //  return BasicObjectLock::size();
+  //}
+
+  // expression stack
+  // (the max_stack arguments are used by the GC; see class FrameClosure)
+
+  public Address addressOfInterpreterFrameExpressionStack() {
+    Address monitorEnd = interpreterFrameMonitorEnd().address();
+    return monitorEnd.addOffsetTo(-1 * VM.getVM().getAddressSize());
+  }
+
+  public int getInterpreterFrameExpressionStackDirection() { return -1; }
+
+  // top of expression stack
+  public Address addressOfInterpreterFrameTOS() {
+    return getSP();
+  }
+
+  /** Expression stack from top down */
+  public Address addressOfInterpreterFrameTOSAt(int slot) {
+    return addressOfInterpreterFrameTOS().addOffsetTo(slot * VM.getVM().getAddressSize());
+  }
+
+  public Address getInterpreterFrameSenderSP() {
+    if (Assert.ASSERTS_ENABLED) {
+      Assert.that(isInterpretedFrame(), "interpreted frame expected");
+    }
+    return addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0);
+  }
+
+  // Monitors
+  public BasicObjectLock interpreterFrameMonitorBegin() {
+    return new BasicObjectLock(addressOfStackSlot(INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET));
+  }
+
+  public BasicObjectLock interpreterFrameMonitorEnd() {
+    Address result = addressOfStackSlot(INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET).getAddressAt(0);
+    if (Assert.ASSERTS_ENABLED) {
+      // make sure the pointer points inside the frame
+      Assert.that(AddressOps.gt(getFP(), result), "result must <  than frame pointer");
+      Assert.that(AddressOps.lte(getSP(), result), "result must >= than stack pointer");
+    }
+    return new BasicObjectLock(result);
+  }
+
+  public int interpreterFrameMonitorSize() {
+    return BasicObjectLock.size();
+  }
+
+  // Method
+  public Address addressOfInterpreterFrameMethod() {
+    return addressOfStackSlot(INTERPRETER_FRAME_METHOD_OFFSET);
+  }
+
+  // Constant pool cache
+  public Address addressOfInterpreterFrameCPCache() {
+    return addressOfStackSlot(INTERPRETER_FRAME_CACHE_OFFSET);
+  }
+
+  // Entry frames
+  public JavaCallWrapper getEntryFrameCallWrapper() {
+    return new AARCH64JavaCallWrapper(addressOfStackSlot(ENTRY_FRAME_CALL_WRAPPER_OFFSET).getAddressAt(0));
+  }
+
+  protected Address addressOfSavedOopResult() {
+    // offset is 2 for compiler2 and 3 for compiler1
+    return getSP().addOffsetTo((VM.getVM().isClientCompiler() ? 2 : 3) *
+                               VM.getVM().getAddressSize());
+  }
+
+  protected Address addressOfSavedReceiver() {
+    return getSP().addOffsetTo(-4 * VM.getVM().getAddressSize());
+  }
+
+  private void dumpStack() {
+    for (Address addr = getSP().addOffsetTo(-4 * VM.getVM().getAddressSize());
+         AddressOps.lt(addr, getSP());
+         addr = addr.addOffsetTo(VM.getVM().getAddressSize())) {
+      System.out.println(addr + ": " + addr.getAddressAt(0));
+    }
+    System.out.println("-----------------------");
+    for (Address addr = getSP();
+         AddressOps.lte(addr, getSP().addOffsetTo(20 * VM.getVM().getAddressSize()));
+         addr = addr.addOffsetTo(VM.getVM().getAddressSize())) {
+      System.out.println(addr + ": " + addr.getAddressAt(0));
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/aarch64/AARCH64JavaCallWrapper.java	Thu Jun 25 09:48:50 2015 -0700
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Red Hat Inc.
+ * 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.
+ *
+ */
+
+package sun.jvm.hotspot.runtime.aarch64;
+
+import java.util.*;
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.types.*;
+import sun.jvm.hotspot.runtime.*;
+
+public class AARCH64JavaCallWrapper extends JavaCallWrapper {
+  private static AddressField lastJavaFPField;
+
+  static {
+    VM.registerVMInitializedObserver(new Observer() {
+        public void update(Observable o, Object data) {
+          initialize(VM.getVM().getTypeDataBase());
+        }
+      });
+  }
+
+  private static synchronized void initialize(TypeDataBase db) {
+    Type type = db.lookupType("JavaFrameAnchor");
+
+    lastJavaFPField  = type.getAddressField("_last_Java_fp");
+  }
+
+  public AARCH64JavaCallWrapper(Address addr) {
+    super(addr);
+  }
+
+  public Address getLastJavaFP() {
+    return lastJavaFPField.getValue(addr.addOffsetTo(anchorField.getOffset()));
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/aarch64/AARCH64RegisterMap.java	Thu Jun 25 09:48:50 2015 -0700
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Red Hat Inc.
+ * 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.
+ *
+ */
+
+package sun.jvm.hotspot.runtime.aarch64;
+
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.runtime.*;
+
+public class AARCH64RegisterMap extends RegisterMap {
+
+  /** This is the only public constructor */
+  public AARCH64RegisterMap(JavaThread thread, boolean updateMap) {
+    super(thread, updateMap);
+  }
+
+  protected AARCH64RegisterMap(RegisterMap map) {
+    super(map);
+  }
+
+  public Object clone() {
+    AARCH64RegisterMap retval = new AARCH64RegisterMap(this);
+    return retval;
+  }
+
+  // no PD state to clear or copy:
+  protected void clearPD() {}
+  protected void initializePD() {}
+  protected void initializeFromPD(RegisterMap map) {}
+  protected Address getLocationPD(VMReg reg) { return null; }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/linux_aarch64/LinuxAARCH64JavaThreadPDAccess.java	Thu Jun 25 09:48:50 2015 -0700
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Red Hat Inc.
+ * 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.
+ *
+ */
+
+package sun.jvm.hotspot.runtime.linux_aarch64;
+
+import java.io.*;
+import java.util.*;
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.debugger.aarch64.*;
+import sun.jvm.hotspot.runtime.*;
+import sun.jvm.hotspot.runtime.aarch64.*;
+import sun.jvm.hotspot.types.*;
+import sun.jvm.hotspot.utilities.*;
+
+public class LinuxAARCH64JavaThreadPDAccess implements JavaThreadPDAccess {
+  private static AddressField  lastJavaFPField;
+  private static AddressField  osThreadField;
+
+  // Field from OSThread
+  private static CIntegerField osThreadThreadIDField;
+
+  // This is currently unneeded but is being kept in case we change
+  // the currentFrameGuess algorithm
+  private static final long GUESS_SCAN_RANGE = 128 * 1024;
+
+  static {
+    VM.registerVMInitializedObserver(new Observer() {
+        public void update(Observable o, Object data) {
+          initialize(VM.getVM().getTypeDataBase());
+        }
+      });
+  }
+
+  private static synchronized void initialize(TypeDataBase db) {
+    Type type = db.lookupType("JavaThread");
+    osThreadField           = type.getAddressField("_osthread");
+
+    Type anchorType = db.lookupType("JavaFrameAnchor");
+    lastJavaFPField         = anchorType.getAddressField("_last_Java_fp");
+
+    Type osThreadType = db.lookupType("OSThread");
+    osThreadThreadIDField   = osThreadType.getCIntegerField("_thread_id");
+  }
+
+  public Address getLastJavaFP(Address addr) {
+    return lastJavaFPField.getValue(addr.addOffsetTo(sun.jvm.hotspot.runtime.JavaThread.getAnchorField().getOffset()));
+  }
+
+  public Address getLastJavaPC(Address addr) {
+    return null;
+  }
+
+  public Address getBaseOfStackPointer(Address addr) {
+    return null;
+  }
+
+  public Frame getLastFramePD(JavaThread thread, Address addr) {
+    Address fp = thread.getLastJavaFP();
+    if (fp == null) {
+      return null; // no information
+    }
+    return new AARCH64Frame(thread.getLastJavaSP(), fp);
+  }
+
+  public RegisterMap newRegisterMap(JavaThread thread, boolean updateMap) {
+    return new AARCH64RegisterMap(thread, updateMap);
+  }
+
+  public Frame getCurrentFrameGuess(JavaThread thread, Address addr) {
+    ThreadProxy t = getThreadProxy(addr);
+    AARCH64ThreadContext context = (AARCH64ThreadContext) t.getContext();
+    AARCH64CurrentFrameGuess guesser = new AARCH64CurrentFrameGuess(context, thread);
+    if (!guesser.run(GUESS_SCAN_RANGE)) {
+      return null;
+    }
+    if (guesser.getPC() == null) {
+      return new AARCH64Frame(guesser.getSP(), guesser.getFP());
+    } else {
+      return new AARCH64Frame(guesser.getSP(), guesser.getFP(), guesser.getPC());
+    }
+  }
+
+  public void printThreadIDOn(Address addr, PrintStream tty) {
+    tty.print(getThreadProxy(addr));
+  }
+
+  public void printInfoOn(Address threadAddr, PrintStream tty) {
+    tty.print("Thread id: ");
+    printThreadIDOn(threadAddr, tty);
+//    tty.println("\nPostJavaState: " + getPostJavaState(threadAddr));
+  }
+
+  public Address getLastSP(Address addr) {
+    ThreadProxy t = getThreadProxy(addr);
+    AARCH64ThreadContext context = (AARCH64ThreadContext) t.getContext();
+    return context.getRegisterAsAddress(AARCH64ThreadContext.SP);
+  }
+
+  public ThreadProxy getThreadProxy(Address addr) {
+    // Addr is the address of the JavaThread.
+    // Fetch the OSThread (for now and for simplicity, not making a
+    // separate "OSThread" class in this package)
+    Address osThreadAddr = osThreadField.getValue(addr);
+    // Get the address of the _thread_id from the OSThread
+    Address threadIdAddr = osThreadAddr.addOffsetTo(osThreadThreadIDField.getOffset());
+
+    JVMDebugger debugger = VM.getVM().getDebugger();
+    return debugger.getThreadForIdentifierAddress(threadIdAddr);
+  }
+}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/AltPlatformInfo.java	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/AltPlatformInfo.java	Thu Jun 25 09:48:50 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, 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
@@ -25,7 +25,10 @@
 package sun.jvm.hotspot.utilities;
 
 public interface AltPlatformInfo {
+
   // Additional cpu types can be tested via this interface
+  public boolean knownCPU(String cpu);
 
-  public boolean knownCPU(String cpu);
-}
\ No newline at end of file
+  // Mangle a cpu name if necessary
+  public String getCPU(String cpu);
+}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java	Thu Jun 25 09:48:50 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, 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
@@ -52,27 +52,54 @@
     }
   }
 
-  /* Returns "sparc" for SPARC based platforms and "x86" for x86 based
-     platforms. Otherwise returns the value of os.arch.  If the value
-     is not recognized as supported, an exception is thrown instead. */
+  public static boolean knownCPU(String cpu) {
+    final String[] KNOWN =
+        new String[] {"i386", "x86", "x86_64", "amd64", "sparc", "sparcv9", "ppc64", "aarch64"};
+
+    for(String s : KNOWN) {
+      if(s.equals(cpu))
+        return true;
+    }
+
+    return false;
+  }
+
+  /* Returns "sparc" for SPARC based platforms "x86" for x86 based
+     platforms and x86_64 for 64bit x86 based platform. Otherwise
+     returns the value of os.arch. If the value is not recognized as supported,
+     an exception is thrown instead. */
+
   public static String getCPU() throws UnsupportedPlatformException {
     String cpu = System.getProperty("os.arch");
-    if (cpu.equals("i386") || cpu.equals("x86")) {
+
+    // Let any additional CPU mangling fire first
+    try {
+      Class pic = Class.forName("sun.jvm.hotspot.utilities.PlatformInfoClosed");
+      AltPlatformInfo api = (AltPlatformInfo) pic.newInstance();
+      if (api.knownCPU(cpu)) {
+        return api.getCPU(cpu);
+      }
+    } catch (Exception e) {
+       // Ignored
+    }
+
+    // Check that CPU is supported
+    if (!knownCPU(cpu)) {
+       throw new UnsupportedPlatformException("CPU type " + cpu + " not yet supported");
+    }
+
+    // Tweeks
+    if (cpu.equals("i386"))
       return "x86";
-    } else if (cpu.equals("sparc") || cpu.equals("sparcv9")) {
+
+    if (cpu.equals("sparcv9"))
       return "sparc";
-    } else if (cpu.equals("ia64") || cpu.equals("amd64") || cpu.equals("x86_64") || cpu.equals("ppc64") || cpu.equals("aarch64")) {
-      return cpu;
-    } else {
-      try {
-        Class pic = Class.forName("sun.jvm.hotspot.utilities.PlatformInfoClosed");
-        AltPlatformInfo api = (AltPlatformInfo)pic.newInstance();
-        if (api.knownCPU(cpu)) {
-          return cpu;
-        }
-      } catch (Exception e) {}
-      throw new UnsupportedPlatformException("CPU type " + cpu + " not yet supported");
-    }
+
+    if (cpu.equals("x86_64"))
+      return "amd64";
+
+    return cpu;
+
   }
 
   // this main is invoked from Makefile to make platform specific agent Makefile(s).
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/PointerLocation.java	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/PointerLocation.java	Thu Jun 25 09:48:50 2015 -0700
@@ -84,11 +84,11 @@
   }
 
   public boolean isInNewGen() {
-    return ((gen != null) && (gen.level() == 0));
+    return ((gen != null) && (gen == ((GenCollectedHeap)heap).getGen(0)));
   }
 
   public boolean isInOldGen() {
-    return ((gen != null) && (gen.level() == 1));
+    return ((gen != null) && (gen == ((GenCollectedHeap)heap).getGen(1)));
   }
 
   public boolean inOtherGen() {
@@ -207,8 +207,6 @@
           tty.print("In new generation ");
         } else if (isInOldGen()) {
           tty.print("In old generation ");
-        } else if (gen != null) {
-          tty.print("In Generation " + getGeneration().level());
         } else {
           tty.print("In unknown section of Java heap");
         }
--- a/hotspot/make/bsd/makefiles/dtrace.make	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/make/bsd/makefiles/dtrace.make	Thu Jun 25 09:48:50 2015 -0700
@@ -263,14 +263,19 @@
 $(DtraceOutDir):
 	mkdir $(DtraceOutDir)
 
+# When building using a devkit, dtrace cannot find the correct preprocessor so
+# we run it explicitly before runing dtrace.
 $(DtraceOutDir)/hotspot.h: $(DTRACE_COMMON_SRCDIR)/hotspot.d | $(DtraceOutDir)
-	$(QUIETLY) $(DTRACE_PROG) $(DTRACE_OPTS) -C -I. -h -o $@ -s $(DTRACE_COMMON_SRCDIR)/hotspot.d
+	$(QUIETLY) $(CC) -E $(DTRACE_OPTS) -I. -x c $(DTRACE_COMMON_SRCDIR)/hotspot.d > $(DtraceOutDir)/hotspot.d
+	$(QUIETLY) $(DTRACE_PROG) -h -o $@ -s $(DtraceOutDir)/hotspot.d
 
 $(DtraceOutDir)/hotspot_jni.h: $(DTRACE_COMMON_SRCDIR)/hotspot_jni.d | $(DtraceOutDir)
-	$(QUIETLY) $(DTRACE_PROG) $(DTRACE_OPTS) -C -I. -h -o $@ -s $(DTRACE_COMMON_SRCDIR)/hotspot_jni.d
+	$(QUIETLY) $(CC) -E $(DTRACE_OPTS) -I. -x c $(DTRACE_COMMON_SRCDIR)/hotspot_jni.d > $(DtraceOutDir)/hotspot_jni.d
+	$(QUIETLY) $(DTRACE_PROG) -h -o $@ -s $(DtraceOutDir)/hotspot_jni.d
 
 $(DtraceOutDir)/hs_private.h: $(DTRACE_COMMON_SRCDIR)/hs_private.d | $(DtraceOutDir)
-	$(QUIETLY) $(DTRACE_PROG) $(DTRACE_OPTS) -C -I. -h -o $@ -s $(DTRACE_COMMON_SRCDIR)/hs_private.d
+	$(QUIETLY) $(CC) -E $(DTRACE_OPTS) -I. -x c $(DTRACE_COMMON_SRCDIR)/hs_private.d > $(DtraceOutDir)/hs_private.d
+	$(QUIETLY) $(DTRACE_PROG) -h -o $@ -s $(DtraceOutDir)/hs_private.d
 
 dtrace_gen_headers: $(DtraceOutDir)/hotspot.h $(DtraceOutDir)/hotspot_jni.h $(DtraceOutDir)/hs_private.h 
 
--- a/hotspot/make/bsd/makefiles/universal.gmk	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/make/bsd/makefiles/universal.gmk	Thu Jun 25 09:48:50 2015 -0700
@@ -56,13 +56,14 @@
 universalize: $(UNIVERSAL_LIPO_LIST) $(UNIVERSAL_COPY_LIST)
 	$(RM) -r $(EXPORT_PATH)/lib/{i386,amd64}
 
+LIPO ?= lipo
 
 # Package built libraries in a universal binary
 $(UNIVERSAL_LIPO_LIST):
 	BUILT_LIPO_FILES="`find $(EXPORT_LIB_DIR)/{i386,amd64}/$(subst $(EXPORT_LIB_DIR)/,,$@) 2>/dev/null`" || test $$? = "1"; \
 	if [ -n "$${BUILT_LIPO_FILES}" ]; then \
 	  $(MKDIR) -p $(shell dirname $@); \
-	  lipo -create -output $@ $${BUILT_LIPO_FILES}; \
+	  $(LIPO) -create -output $@ $${BUILT_LIPO_FILES}; \
 	fi
 
 
--- a/hotspot/make/sa.files	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/make/sa.files	Thu Jun 25 09:48:50 2015 -0700
@@ -44,6 +44,7 @@
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/compiler/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/amd64/*.java \
+$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/aarch64/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/bsd/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/bsd/amd64/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/bsd/x86/*.java \
@@ -55,6 +56,7 @@
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/amd64/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/ia64/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/ppc64/*.java \
+$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/aarch64/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/x86/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/sparc/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/posix/*.java \
@@ -63,6 +65,7 @@
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/proc/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/proc/amd64/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/proc/ppc64/*.java \
+$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/proc/aarch64/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/proc/sparc/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/proc/x86/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/remote/*.java \
@@ -70,6 +73,7 @@
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/remote/ppc64/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/remote/sparc/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/remote/x86/*.java \
+$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/remote/aarch64/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/sparc/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/win32/coff/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/windbg/*.java \
@@ -92,11 +96,13 @@
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/prims/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/amd64/*.java \
+$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/aarch64/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/bsd/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/bsd_amd64/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/bsd_x86/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/linux/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/linux_amd64/*.java \
+$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/linux_aarch64/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/linux_x86/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/linux_sparc/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/linux_ppc64/*.java \
--- a/hotspot/src/cpu/aarch64/vm/frame_aarch64.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/cpu/aarch64/vm/frame_aarch64.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2014, Red Hat Inc. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -526,16 +526,6 @@
   return frame(sender_sp(), link(), sender_pc());
 }
 
-bool frame::interpreter_frame_equals_unpacked_fp(intptr_t* fp) {
-  assert(is_interpreted_frame(), "must be interpreter frame");
-  Method* method = interpreter_frame_method();
-  // When unpacking an optimized frame the frame pointer is
-  // adjusted with:
-  int diff = (method->max_locals() - method->size_of_parameters()) *
-             Interpreter::stackElementWords;
-  return _fp == (fp - diff);
-}
-
 bool frame::is_interpreted_frame_valid(JavaThread* thread) const {
 // QQQ
 #ifdef CC_INTERP
--- a/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2014, Red Hat Inc. All rights reserved.
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Red Hat Inc. 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
@@ -84,7 +84,7 @@
 
 #ifdef BUILTIN_SIM
 #define UseBuiltinSim           true
-#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct) \
+#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct, range, constraint) \
                                                                         \
   product(bool, NotifySimulator, UseBuiltinSim,                         \
          "tell the AArch64 sim where we are in method code")            \
@@ -112,7 +112,7 @@
 #define NotifySimulator         false
 #define UseSimulatorCache       false
 #define DisableBCCheck          true
-#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct) \
+#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct, range, constraint) \
                                                                         \
   product(bool, NearCpool, true,                                        \
          "constant pool is close to instructions")                      \
--- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -2888,41 +2888,40 @@
   cmp(src1, rscratch1);
 }
 
-void MacroAssembler::store_check(Register obj) {
-  // Does a store check for the oop in register obj. The content of
-  // register obj is destroyed afterwards.
-  store_check_part_1(obj);
-  store_check_part_2(obj);
-}
-
 void MacroAssembler::store_check(Register obj, Address dst) {
   store_check(obj);
 }
 
-
-// split the store check operation so that other instructions can be scheduled inbetween
-void MacroAssembler::store_check_part_1(Register obj) {
-  BarrierSet* bs = Universe::heap()->barrier_set();
-  assert(bs->kind() == BarrierSet::CardTableModRef, "Wrong barrier set kind");
-  lsr(obj, obj, CardTableModRefBS::card_shift);
-}
-
-void MacroAssembler::store_check_part_2(Register obj) {
+void MacroAssembler::store_check(Register obj) {
+  // Does a store check for the oop in register obj. The content of
+  // register obj is destroyed afterwards.
+
   BarrierSet* bs = Universe::heap()->barrier_set();
   assert(bs->kind() == BarrierSet::CardTableModRef, "Wrong barrier set kind");
-  CardTableModRefBS* ct = (CardTableModRefBS*)bs;
+
+  CardTableModRefBS* ct = barrier_set_cast<CardTableModRefBS>(bs);
   assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code");
 
-  // The calculation for byte_map_base is as follows:
-  // byte_map_base = _byte_map - (uintptr_t(low_bound) >> card_shift);
-  // So this essentially converts an address to a displacement and
-  // it will never need to be relocated.
-
-  // FIXME: It's not likely that disp will fit into an offset so we
-  // don't bother to check, but it could save an instruction.
-  intptr_t disp = (intptr_t) ct->byte_map_base;
-  mov(rscratch1, disp);
-  strb(zr, Address(obj, rscratch1));
+  lsr(obj, obj, CardTableModRefBS::card_shift);
+
+  assert(CardTableModRefBS::dirty_card_val() == 0, "must be");
+
+  {
+    ExternalAddress cardtable((address) ct->byte_map_base);
+    unsigned long offset;
+    adrp(rscratch1, cardtable, offset);
+    assert(offset == 0, "byte_map_base is misaligned");
+  }
+
+  if (UseCondCardMark) {
+    Label L_already_dirty;
+    ldrb(rscratch2,  Address(obj, rscratch1));
+    cbz(rscratch2, L_already_dirty);
+    strb(zr, Address(obj, rscratch1));
+    bind(L_already_dirty);
+  } else {
+    strb(zr, Address(obj, rscratch1));
+  }
 }
 
 void MacroAssembler::load_klass(Register dst, Register src) {
--- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -756,10 +756,6 @@
 
 #endif // INCLUDE_ALL_GCS
 
-  // split store_check(Register obj) to enhance instruction interleaving
-  void store_check_part_1(Register obj);
-  void store_check_part_2(Register obj);
-
   // oop manipulations
   void load_klass(Register dst, Register src);
   void store_klass(Register dst, Register src);
--- a/hotspot/src/cpu/ppc/vm/globals_ppc.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/cpu/ppc/vm/globals_ppc.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -63,7 +63,7 @@
 define_pd_global(uintx, TypeProfileLevel, 111);
 
 // Platform dependent flag handling: flags only defined on this platform.
-#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct)  \
+#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct, range, constraint)  \
                                                                             \
   /* Load poll address from thread. This is used to implement per-thread */ \
   /* safepoints on platforms != IA64. */                                    \
--- a/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -510,7 +510,8 @@
 
 void VM_Version::determine_features() {
 #if defined(ABI_ELFv2)
-  const int code_size = (num_features+1+2*7)*BytesPerInstWord; // TODO(asmundak): calculation is incorrect.
+  // 1 InstWord per call for the blr instruction.
+  const int code_size = (num_features+1+2*1)*BytesPerInstWord;
 #else
   // 7 InstWords for each call (function descriptor + blr instruction).
   const int code_size = (num_features+1+2*7)*BytesPerInstWord;
@@ -545,7 +546,8 @@
   a->popcntw(R7, R5);                          // code[6]  -> popcntw
   a->fcfids(F3, F4);                           // code[7]  -> fcfids
   a->vand(VR0, VR0, VR0);                      // code[8]  -> vand
-  a->lqarx_unchecked(R7, R3_ARG1, R4_ARG2, 1); // code[9]  -> lqarx_m
+  // arg0 of lqarx must be an even register, (arg1 + arg2) must be a multiple of 16
+  a->lqarx_unchecked(R6, R3_ARG1, R4_ARG2, 1); // code[9]  -> lqarx_m
   a->vcipher(VR0, VR1, VR2);                   // code[10] -> vcipher
   a->vpmsumb(VR0, VR1, VR2);                   // code[11] -> vpmsumb
   a->tcheck(0);                                // code[12] -> tcheck
@@ -577,7 +579,8 @@
 
   // Execute code. Illegal instructions will be replaced by 0 in the signal handler.
   VM_Version::_is_determine_features_test_running = true;
-  (*test)((address)mid_of_test_area, (uint64_t)0);
+  // We must align the first argument to 16 bytes because of the lqarx check.
+  (*test)((address)align_size_up((intptr_t)mid_of_test_area, 16), (uint64_t)0);
   VM_Version::_is_determine_features_test_running = false;
 
   // determine which instructions are legal.
@@ -619,12 +622,12 @@
   MacroAssembler* a = new MacroAssembler(&cb);
 
   // Emit code.
-  uint64_t (*get_dscr)() = (uint64_t(*)())(void *)a->emit_fd();
+  uint64_t (*get_dscr)() = (uint64_t(*)())(void *)a->function_entry();
   uint32_t *code = (uint32_t *)a->pc();
   a->mfdscr(R3);
   a->blr();
 
-  void (*set_dscr)(long) = (void(*)(long))(void *)a->emit_fd();
+  void (*set_dscr)(long) = (void(*)(long))(void *)a->function_entry();
   a->mtdscr(R3);
   a->blr();
 
--- a/hotspot/src/cpu/sparc/vm/frame_sparc.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/cpu/sparc/vm/frame_sparc.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, 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
@@ -599,12 +599,6 @@
   return next_younger_sp_or_null(valid_sp, sp) != NULL;
 }
 
-
-bool frame::interpreter_frame_equals_unpacked_fp(intptr_t* fp) {
-  assert(is_interpreted_frame(), "must be interpreter frame");
-  return this->fp() == fp;
-}
-
 bool frame::is_interpreted_frame_valid(JavaThread* thread) const {
 #ifdef CC_INTERP
   // Is there anything to do?
--- a/hotspot/src/cpu/sparc/vm/globals_sparc.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/cpu/sparc/vm/globals_sparc.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -81,7 +81,7 @@
 
 define_pd_global(uintx, TypeProfileLevel, 111);
 
-#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct) \
+#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct, range, constraint) \
                                                                             \
   product(intx, UseVIS, 99,                                                 \
           "Highest supported VIS instructions set on Sparc")                \
--- a/hotspot/src/cpu/x86/vm/frame_x86.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/cpu/x86/vm/frame_x86.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -524,17 +524,6 @@
   return frame(sender_sp(), link(), sender_pc());
 }
 
-
-bool frame::interpreter_frame_equals_unpacked_fp(intptr_t* fp) {
-  assert(is_interpreted_frame(), "must be interpreter frame");
-  Method* method = interpreter_frame_method();
-  // When unpacking an optimized frame the frame pointer is
-  // adjusted with:
-  int diff = (method->max_locals() - method->size_of_parameters()) *
-             Interpreter::stackElementWords;
-  return _fp == (fp - diff);
-}
-
 bool frame::is_interpreted_frame_valid(JavaThread* thread) const {
 // QQQ
 #ifdef CC_INTERP
--- a/hotspot/src/cpu/x86/vm/globals_x86.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/cpu/x86/vm/globals_x86.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -84,7 +84,7 @@
 
 define_pd_global(bool, PreserveFramePointer, false);
 
-#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct) \
+#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct, range, constraint) \
                                                                             \
   develop(bool, IEEEPrecision, true,                                        \
           "Enables IEEE precision (for INTEL only)")                        \
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -4260,31 +4260,24 @@
 //////////////////////////////////////////////////////////////////////////////////
 
 
+void MacroAssembler::store_check(Register obj, Address dst) {
+  store_check(obj);
+}
+
 void MacroAssembler::store_check(Register obj) {
   // Does a store check for the oop in register obj. The content of
   // register obj is destroyed afterwards.
-  store_check_part_1(obj);
-  store_check_part_2(obj);
-}
-
-void MacroAssembler::store_check(Register obj, Address dst) {
-  store_check(obj);
-}
-
-
-// split the store check operation so that other instructions can be scheduled inbetween
-void MacroAssembler::store_check_part_1(Register obj) {
+
   BarrierSet* bs = Universe::heap()->barrier_set();
   assert(bs->kind() == BarrierSet::CardTableModRef, "Wrong barrier set kind");
-  shrptr(obj, CardTableModRefBS::card_shift);
-}
-
-void MacroAssembler::store_check_part_2(Register obj) {
-  BarrierSet* bs = Universe::heap()->barrier_set();
-  assert(bs->kind() == BarrierSet::CardTableModRef, "Wrong barrier set kind");
+
   CardTableModRefBS* ct = barrier_set_cast<CardTableModRefBS>(bs);
   assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code");
 
+  shrptr(obj, CardTableModRefBS::card_shift);
+
+  Address card_addr;
+
   // The calculation for byte_map_base is as follows:
   // byte_map_base = _byte_map - (uintptr_t(low_bound) >> card_shift);
   // So this essentially converts an address to a displacement and it will
@@ -4292,8 +4285,7 @@
   // large for a 32bit displacement.
   intptr_t disp = (intptr_t) ct->byte_map_base;
   if (is_simm32(disp)) {
-    Address cardtable(noreg, obj, Address::times_1, disp);
-    movb(cardtable, 0);
+    card_addr = Address(noreg, obj, Address::times_1, disp);
   } else {
     // By doing it as an ExternalAddress 'disp' could be converted to a rip-relative
     // displacement and done in a single instruction given favorable mapping and a
@@ -4301,7 +4293,21 @@
     // entry and that entry is not properly handled by the relocation code.
     AddressLiteral cardtable((address)ct->byte_map_base, relocInfo::none);
     Address index(noreg, obj, Address::times_1);
-    movb(as_Address(ArrayAddress(cardtable, index)), 0);
+    card_addr = as_Address(ArrayAddress(cardtable, index));
+  }
+
+  int dirty = CardTableModRefBS::dirty_card_val();
+  if (UseCondCardMark) {
+    Label L_already_dirty;
+    if (UseConcMarkSweepGC) {
+      membar(Assembler::StoreLoad);
+    }
+    cmpb(card_addr, dirty);
+    jcc(Assembler::equal, L_already_dirty);
+    movb(card_addr, dirty);
+    bind(L_already_dirty);
+  } else {
+    movb(card_addr, dirty);
   }
 }
 
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -315,10 +315,6 @@
 
 #endif // INCLUDE_ALL_GCS
 
-  // split store_check(Register obj) to enhance instruction interleaving
-  void store_check_part_1(Register obj);
-  void store_check_part_2(Register obj);
-
   // C 'boolean' to Java boolean: x == 0 ? 0 : 1
   void c2bool(Register x);
 
--- a/hotspot/src/cpu/zero/vm/globals_zero.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/cpu/zero/vm/globals_zero.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -63,7 +63,8 @@
 
 define_pd_global(bool, PreserveFramePointer, false);
 
-#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct)  \
+#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct, range, constraint)  \
+                                                                            \
   product(bool, UseFastEmptyMethods, true,                                  \
           "Use fast method entry code for empty methods")                   \
                                                                             \
--- a/hotspot/src/os/aix/vm/decoder_aix.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/os/aix/vm/decoder_aix.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
  * Copyright 2013 SAP AG. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -38,8 +38,8 @@
 
   virtual bool demangle(const char* symbol, char* buf, int buflen) { return false; } // demangled by getFuncName
 
-  virtual bool decode(address addr, char* buf, int buflen, int* offset, const char* modulepath) {
-    return (::getFuncName((codeptr_t)addr, buf, buflen, offset, 0, 0, 0) == 0);
+  virtual bool decode(address addr, char* buf, int buflen, int* offset, const char* modulepath, bool demangle) {
+    return (::getFuncName((codeptr_t)addr, buf, buflen, offset, 0, 0, 0, demangle) == 0);
   }
   virtual bool decode(address addr, char *buf, int buflen, int* offset, const void *base) {
     ShouldNotReachHere();
--- a/hotspot/src/os/aix/vm/globals_aix.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/os/aix/vm/globals_aix.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -29,7 +29,7 @@
 //
 // Defines Aix specific flags. They are not available on other platforms.
 //
-#define RUNTIME_OS_FLAGS(develop, develop_pd, product, product_pd, diagnostic, notproduct) \
+#define RUNTIME_OS_FLAGS(develop, develop_pd, product, product_pd, diagnostic, notproduct, range, constraint) \
                                                                                     \
   /* Use 64K pages for virtual memory (shmat). */                                   \
   product(bool, Use64KPages, true,                                                  \
--- a/hotspot/src/os/aix/vm/os_aix.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/os/aix/vm/os_aix.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -1439,7 +1439,8 @@
 }
 
 bool os::dll_address_to_function_name(address addr, char *buf,
-                                      int buflen, int *offset) {
+                                      int buflen, int *offset,
+                                      bool demangle) {
   if (offset) {
     *offset = -1;
   }
@@ -1454,7 +1455,7 @@
   }
 
   // Go through Decoder::decode to call getFuncName which reads the name from the traceback table.
-  return Decoder::decode(addr, buf, buflen, offset);
+  return Decoder::decode(addr, buf, buflen, offset, demangle);
 }
 
 static int getModuleName(codeptr_t pc,                    // [in] program counter
@@ -1653,7 +1654,7 @@
   }
 }
 
-void os::pd_print_cpu_info(outputStream* st) {
+void os::pd_print_cpu_info(outputStream* st, char* buf, size_t buflen) {
   // cpu
   st->print("CPU:");
   st->print("total %d", os::processor_count());
@@ -3761,10 +3762,6 @@
   return fetcher.result();
 }
 
-// Not neede on Aix.
-// int os::Aix::safe_cond_timedwait(pthread_cond_t *_cond, pthread_mutex_t *_mutex, const struct timespec *_abstime) {
-// }
-
 ////////////////////////////////////////////////////////////////////////////////
 // debug support
 
--- a/hotspot/src/os/aix/vm/porting_aix.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/os/aix/vm/porting_aix.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -114,7 +114,8 @@
     int* p_displacement,             // [out] optional: displacement (-1 if not available)
     const struct tbtable** p_tb,     // [out] optional: ptr to traceback table to get further
                                      //                 information (NULL if not available)
-    char* p_errmsg, size_t errmsglen // [out] optional: user provided buffer for error messages
+    char* p_errmsg, size_t errmsglen,// [out] optional: user provided buffer for error messages
+    bool demangle                    // [in] whether to demangle the name
   ) {
   struct tbtable* tb = 0;
   unsigned int searchcount = 0;
@@ -216,15 +217,17 @@
       p_name[0] = '\0';
 
       // If it is a C++ name, try and demangle it using the Demangle interface (see demangle.h).
-      char* rest;
-      Name* const name = Demangle(buf, rest);
-      if (name) {
-        const char* const demangled_name = name->Text();
-        if (demangled_name) {
-          strncpy(p_name, demangled_name, namelen-1);
-          p_name[namelen-1] = '\0';
+      if (demangle) {
+        char* rest;
+        Name* const name = Demangle(buf, rest);
+        if (name) {
+          const char* const demangled_name = name->Text();
+          if (demangled_name) {
+            strncpy(p_name, demangled_name, namelen-1);
+            p_name[namelen-1] = '\0';
+          }
+          delete name;
         }
-        delete name;
       }
 
       // Fallback: if demangling did not work, just provide the unmangled name.
@@ -325,7 +328,7 @@
       int displacement = 0;
 
       if (getFuncName((codeptr_t) p, funcname, sizeof(funcname), &displacement,
-                      NULL, NULL, 0) == 0) {
+                      NULL, NULL, 0, true /* demangle */) == 0) {
         if (funcname[0] != '\0') {
           const char* const interned = dladdr_fixed_strings.intern(funcname);
           info->dli_sname = interned;
--- a/hotspot/src/os/aix/vm/porting_aix.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/os/aix/vm/porting_aix.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -87,7 +87,8 @@
       char* p_name, size_t namelen,    // [out] optional: user provided buffer for the function name
       int* p_displacement,             // [out] optional: displacement
       const struct tbtable** p_tb,     // [out] optional: ptr to traceback table to get further information
-      char* p_errmsg, size_t errmsglen // [out] optional: user provided buffer for error messages
+      char* p_errmsg, size_t errmsglen,// [out] optional: user provided buffer for error messages
+      bool demangle = true             // [in] whether to demangle the name
     );
 
 // -------------------------------------------------------------------------
--- a/hotspot/src/os/bsd/vm/decoder_machO.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/os/bsd/vm/decoder_machO.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2015, 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
@@ -42,7 +42,7 @@
   virtual bool decode(address pc, char* buf, int buflen, int* offset,
                       const void* base);
   virtual bool decode(address pc, char* buf, int buflen, int* offset,
-                      const char* module_path = NULL) {
+                      const char* module_path, bool demangle) {
     ShouldNotReachHere();
     return false;
   }
--- a/hotspot/src/os/bsd/vm/globals_bsd.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/os/bsd/vm/globals_bsd.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, 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
@@ -28,19 +28,20 @@
 //
 // Defines Bsd specific flags. They are not available on other platforms.
 //
-#define RUNTIME_OS_FLAGS(develop, develop_pd, product, product_pd, diagnostic, notproduct) \
-  product(bool, UseOprofile, false,                                     \
-        "enable support for Oprofile profiler")                         \
-                                                                        \
-  product(bool, UseBsdPosixThreadCPUClocks, true,                     \
-          "enable fast Bsd Posix clocks where available")             \
-/*  NB: The default value of UseBsdPosixThreadCPUClocks may be        \
-    overridden in Arguments::parse_each_vm_init_arg.  */                \
-                                                                        \
-  product(bool, UseHugeTLBFS, false,                                    \
-          "Use MAP_HUGETLB for large pages")                            \
-                                                                        \
-  product(bool, UseSHM, false,                                          \
+#define RUNTIME_OS_FLAGS(develop, develop_pd, product, product_pd, diagnostic, notproduct, range, constraint) \
+                                                                                \
+  product(bool, UseOprofile, false,                                             \
+        "enable support for Oprofile profiler")                                 \
+                                                                                \
+  /*  NB: The default value of UseBsdPosixThreadCPUClocks may be  */            \
+  /*  overridden in Arguments::parse_each_vm_init_arg.            */            \
+  product(bool, UseBsdPosixThreadCPUClocks, true,                               \
+          "enable fast Bsd Posix clocks where available")                       \
+                                                                                \
+  product(bool, UseHugeTLBFS, false,                                            \
+          "Use MAP_HUGETLB for large pages")                                    \
+                                                                                \
+  product(bool, UseSHM, false,                                                  \
           "Use SYSV shared memory for large pages")
 
 //
--- a/hotspot/src/os/bsd/vm/os_bsd.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/os/bsd/vm/os_bsd.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -637,11 +637,6 @@
 //////////////////////////////////////////////////////////////////////////////
 // create new thread
 
-// check if it's safe to start a new thread
-static bool _thread_safety_check(Thread* thread) {
-  return true;
-}
-
 #ifdef __APPLE__
 // library handle for calling objc_registerThreadWithCollector()
 // without static linking to the libobjc library
@@ -681,15 +676,6 @@
   OSThread* osthread = thread->osthread();
   Monitor* sync = osthread->startThread_lock();
 
-  // non floating stack BsdThreads needs extra check, see above
-  if (!_thread_safety_check(thread)) {
-    // notify parent thread
-    MutexLockerEx ml(sync, Mutex::_no_safepoint_check_flag);
-    osthread->set_state(ZOMBIE);
-    sync->notify_all();
-    return NULL;
-  }
-
   osthread->set_thread_id(os::Bsd::gettid());
 
 #ifdef __APPLE__
@@ -1339,7 +1325,8 @@
 #define MACH_MAXSYMLEN 256
 
 bool os::dll_address_to_function_name(address addr, char *buf,
-                                      int buflen, int *offset) {
+                                      int buflen, int *offset,
+                                      bool demangle) {
   // buf is not optional, but offset is optional
   assert(buf != NULL, "sanity check");
 
@@ -1349,7 +1336,7 @@
   if (dladdr((void*)addr, &dlinfo) != 0) {
     // see if we have a matching symbol
     if (dlinfo.dli_saddr != NULL && dlinfo.dli_sname != NULL) {
-      if (!Decoder::demangle(dlinfo.dli_sname, buf, buflen)) {
+      if (!(demangle && Decoder::demangle(dlinfo.dli_sname, buf, buflen))) {
         jio_snprintf(buf, buflen, "%s", dlinfo.dli_sname);
       }
       if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr;
@@ -1358,15 +1345,16 @@
     // no matching symbol so try for just file info
     if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != NULL) {
       if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase),
-                          buf, buflen, offset, dlinfo.dli_fname)) {
+                          buf, buflen, offset, dlinfo.dli_fname, demangle)) {
         return true;
       }
     }
 
     // Handle non-dynamic manually:
     if (dlinfo.dli_fbase != NULL &&
-        Decoder::decode(addr, localbuf, MACH_MAXSYMLEN, offset, dlinfo.dli_fbase)) {
-      if (!Decoder::demangle(localbuf, buf, buflen)) {
+        Decoder::decode(addr, localbuf, MACH_MAXSYMLEN, offset,
+                        dlinfo.dli_fbase)) {
+      if (!(demangle && Decoder::demangle(localbuf, buf, buflen))) {
         jio_snprintf(buf, buflen, "%s", localbuf);
       }
       return true;
@@ -1706,7 +1694,7 @@
   os::Posix::print_load_average(st);
 }
 
-void os::pd_print_cpu_info(outputStream* st) {
+void os::pd_print_cpu_info(outputStream* st, char* buf, size_t buflen) {
   // Nothing to do for now.
 }
 
@@ -2276,8 +2264,6 @@
   return os::uncommit_memory(addr, size);
 }
 
-static address _highest_vm_reserved_address = NULL;
-
 // If 'fixed' is true, anon_mmap() will attempt to reserve anonymous memory
 // at 'requested_addr'. If there are existing memory mappings at the same
 // location, however, they will be overwritten. If 'fixed' is false,
@@ -2300,23 +2286,9 @@
   addr = (char*)::mmap(requested_addr, bytes, PROT_NONE,
                        flags, -1, 0);
 
-  if (addr != MAP_FAILED) {
-    // anon_mmap() should only get called during VM initialization,
-    // don't need lock (actually we can skip locking even it can be called
-    // from multiple threads, because _highest_vm_reserved_address is just a
-    // hint about the upper limit of non-stack memory regions.)
-    if ((address)addr + bytes > _highest_vm_reserved_address) {
-      _highest_vm_reserved_address = (address)addr + bytes;
-    }
-  }
-
   return addr == MAP_FAILED ? NULL : addr;
 }
 
-// Don't update _highest_vm_reserved_address, because there might be memory
-// regions above addr + size. If so, releasing a memory region only creates
-// a hole in the address space, it doesn't help prevent heap-stack collision.
-//
 static int anon_munmap(char * addr, size_t size) {
   return ::munmap(addr, size) == 0;
 }
@@ -2490,15 +2462,7 @@
   assert(bytes % os::vm_page_size() == 0, "reserving unexpected size block");
 
   // Repeatedly allocate blocks until the block is allocated at the
-  // right spot. Give up after max_tries. Note that reserve_memory() will
-  // automatically update _highest_vm_reserved_address if the call is
-  // successful. The variable tracks the highest memory address every reserved
-  // by JVM. It is used to detect heap-stack collision if running with
-  // fixed-stack BsdThreads. Because here we may attempt to reserve more
-  // space than needed, it could confuse the collision detecting code. To
-  // solve the problem, save current _highest_vm_reserved_address and
-  // calculate the correct value before return.
-  address old_highest = _highest_vm_reserved_address;
+  // right spot.
 
   // Bsd mmap allows caller to pass an address as hint; give it a try first,
   // if kernel honors the hint then we can return immediately.
@@ -2552,10 +2516,8 @@
   }
 
   if (i < max_tries) {
-    _highest_vm_reserved_address = MAX2(old_highest, (address)requested_addr + bytes);
     return requested_addr;
   } else {
-    _highest_vm_reserved_address = old_highest;
     return NULL;
   }
 }
@@ -3715,12 +3677,6 @@
   return fetcher.result();
 }
 
-int os::Bsd::safe_cond_timedwait(pthread_cond_t *_cond,
-                                 pthread_mutex_t *_mutex,
-                                 const struct timespec *_abstime) {
-  return pthread_cond_timedwait(_cond, _mutex, _abstime);
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // debug support
 
@@ -4286,7 +4242,7 @@
   // In that case, we should propagate the notify to another waiter.
 
   while (_Event < 0) {
-    status = os::Bsd::safe_cond_timedwait(_cond, _mutex, &abst);
+    status = pthread_cond_timedwait(_cond, _mutex, &abst);
     if (status != 0 && WorkAroundNPTLTimedWaitHang) {
       pthread_cond_destroy(_cond);
       pthread_cond_init(_cond, NULL);
@@ -4492,7 +4448,7 @@
   if (time == 0) {
     status = pthread_cond_wait(_cond, _mutex);
   } else {
-    status = os::Bsd::safe_cond_timedwait(_cond, _mutex, &absTime);
+    status = pthread_cond_timedwait(_cond, _mutex, &absTime);
     if (status != 0 && WorkAroundNPTLTimedWaitHang) {
       pthread_cond_destroy(_cond);
       pthread_cond_init(_cond, NULL);
--- a/hotspot/src/os/bsd/vm/os_bsd.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/os/bsd/vm/os_bsd.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -30,9 +30,6 @@
 // Information about the protection of the page at address '0' on this os.
 static bool zero_page_read_protected() { return true; }
 
-// pthread_getattr_np comes with BsdThreads-0.9-7 on RedHat 7.1
-typedef int (*pthread_getattr_func_type)(pthread_t, pthread_attr_t *);
-
 #ifdef __APPLE__
 // Mac OS X doesn't support clock_gettime. Stub out the type, it is
 // unused
@@ -145,9 +142,6 @@
 
   // none present
 
-  // BsdThreads work-around for 6292965
-  static int safe_cond_timedwait(pthread_cond_t *_cond, pthread_mutex_t *_mutex, const struct timespec *_abstime);
-
  private:
   typedef int (*sched_getcpu_func_t)(void);
   typedef int (*numa_node_to_cpus_func_t)(int node, unsigned long *buffer, int bufferlen);
--- a/hotspot/src/os/linux/vm/globals_linux.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/os/linux/vm/globals_linux.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, 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
@@ -28,14 +28,15 @@
 //
 // Defines Linux specific flags. They are not available on other platforms.
 //
-#define RUNTIME_OS_FLAGS(develop, develop_pd, product, product_pd, diagnostic, notproduct) \
+#define RUNTIME_OS_FLAGS(develop, develop_pd, product, product_pd, diagnostic, notproduct, range, constraint) \
+                                                                        \
   product(bool, UseOprofile, false,                                     \
         "enable support for Oprofile profiler")                         \
                                                                         \
+  /*  NB: The default value of UseLinuxPosixThreadCPUClocks may be   */ \
+  /* overridden in Arguments::parse_each_vm_init_arg.                */ \
   product(bool, UseLinuxPosixThreadCPUClocks, true,                     \
           "enable fast Linux Posix clocks where available")             \
-/*  NB: The default value of UseLinuxPosixThreadCPUClocks may be        \
-    overridden in Arguments::parse_each_vm_init_arg.  */                \
                                                                         \
   product(bool, UseHugeTLBFS, false,                                    \
           "Use MAP_HUGETLB for large pages")                            \
--- a/hotspot/src/os/linux/vm/os_linux.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/os/linux/vm/os_linux.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -135,8 +135,6 @@
 pthread_t os::Linux::_main_thread;
 int os::Linux::_page_size = -1;
 const int os::Linux::_vm_default_page_size = (8 * K);
-bool os::Linux::_is_floating_stack = false;
-bool os::Linux::_is_NPTL = false;
 bool os::Linux::_supports_fast_thread_cpu_time = false;
 const char * os::Linux::_glibc_version = NULL;
 const char * os::Linux::_libpthread_version = NULL;
@@ -150,8 +148,6 @@
 static sigset_t check_signal_done;
 static bool check_signals = true;
 
-static pid_t _initial_pid = 0;
-
 // Signal number used to suspend/resume a thread
 
 // do not use any signal number less than SIGSEGV, see 4355769
@@ -223,18 +219,10 @@
 //
 // Returns the kernel thread id of the currently running thread. Kernel
 // thread id is used to access /proc.
-//
-// (Note that getpid() on LinuxThreads returns kernel thread id too; but
-// on NPTL, it returns the same pid for all threads, as required by POSIX.)
-//
 pid_t os::Linux::gettid() {
   int rslt = syscall(SYS_gettid);
-  if (rslt == -1) {
-    // old kernel, no NPTL support
-    return getpid();
-  } else {
-    return (pid_t)rslt;
-  }
+  assert(rslt != -1, "must be."); // old linuxthreads implementation?
+  return (pid_t)rslt;
 }
 
 // Most versions of linux have a bug where the number of processors are
@@ -508,68 +496,48 @@
 // detecting pthread library
 
 void os::Linux::libpthread_init() {
-  // Save glibc and pthread version strings. Note that _CS_GNU_LIBC_VERSION
-  // and _CS_GNU_LIBPTHREAD_VERSION are supported in glibc >= 2.3.2. Use a
-  // generic name for earlier versions.
-  // Define macros here so we can build HotSpot on old systems.
-#ifndef _CS_GNU_LIBC_VERSION
-  #define _CS_GNU_LIBC_VERSION 2
-#endif
-#ifndef _CS_GNU_LIBPTHREAD_VERSION
-  #define _CS_GNU_LIBPTHREAD_VERSION 3
+  // Save glibc and pthread version strings.
+#if !defined(_CS_GNU_LIBC_VERSION) || \
+    !defined(_CS_GNU_LIBPTHREAD_VERSION)
+  #error "glibc too old (< 2.3.2)"
 #endif
 
   size_t n = confstr(_CS_GNU_LIBC_VERSION, NULL, 0);
-  if (n > 0) {
-    char *str = (char *)malloc(n, mtInternal);
-    confstr(_CS_GNU_LIBC_VERSION, str, n);
-    os::Linux::set_glibc_version(str);
-  } else {
-    // _CS_GNU_LIBC_VERSION is not supported, try gnu_get_libc_version()
-    static char _gnu_libc_version[32];
-    jio_snprintf(_gnu_libc_version, sizeof(_gnu_libc_version),
-                 "glibc %s %s", gnu_get_libc_version(), gnu_get_libc_release());
-    os::Linux::set_glibc_version(_gnu_libc_version);
-  }
+  assert(n > 0, "cannot retrieve glibc version");
+  char *str = (char *)malloc(n, mtInternal);
+  confstr(_CS_GNU_LIBC_VERSION, str, n);
+  os::Linux::set_glibc_version(str);
 
   n = confstr(_CS_GNU_LIBPTHREAD_VERSION, NULL, 0);
-  if (n > 0) {
-    char *str = (char *)malloc(n, mtInternal);
-    confstr(_CS_GNU_LIBPTHREAD_VERSION, str, n);
-    // Vanilla RH-9 (glibc 2.3.2) has a bug that confstr() always tells
-    // us "NPTL-0.29" even we are running with LinuxThreads. Check if this
-    // is the case. LinuxThreads has a hard limit on max number of threads.
-    // So sysconf(_SC_THREAD_THREADS_MAX) will return a positive value.
-    // On the other hand, NPTL does not have such a limit, sysconf()
-    // will return -1 and errno is not changed. Check if it is really NPTL.
-    if (strcmp(os::Linux::glibc_version(), "glibc 2.3.2") == 0 &&
-        strstr(str, "NPTL") &&
-        sysconf(_SC_THREAD_THREADS_MAX) > 0) {
-      free(str);
-      os::Linux::set_libpthread_version("linuxthreads");
-    } else {
-      os::Linux::set_libpthread_version(str);
-    }
-  } else {
-    // glibc before 2.3.2 only has LinuxThreads.
-    os::Linux::set_libpthread_version("linuxthreads");
-  }
-
-  if (strstr(libpthread_version(), "NPTL")) {
-    os::Linux::set_is_NPTL();
-  } else {
-    os::Linux::set_is_LinuxThreads();
-  }
-
-  // LinuxThreads have two flavors: floating-stack mode, which allows variable
-  // stack size; and fixed-stack mode. NPTL is always floating-stack.
-  if (os::Linux::is_NPTL() || os::Linux::supports_variable_stack_size()) {
-    os::Linux::set_is_floating_stack();
-  }
+  assert(n > 0, "cannot retrieve pthread version");
+  str = (char *)malloc(n, mtInternal);
+  confstr(_CS_GNU_LIBPTHREAD_VERSION, str, n);
+  os::Linux::set_libpthread_version(str);
 }
 
 /////////////////////////////////////////////////////////////////////////////
-// thread stack
+// thread stack expansion
+
+// os::Linux::manually_expand_stack() takes care of expanding the thread
+// stack. Note that this is normally not needed: pthread stacks allocate
+// thread stack using mmap() without MAP_NORESERVE, so the stack is already
+// committed. Therefore it is not necessary to expand the stack manually.
+//
+// Manually expanding the stack was historically needed on LinuxThreads
+// thread stacks, which were allocated with mmap(MAP_GROWSDOWN). Nowadays
+// it is kept to deal with very rare corner cases:
+//
+// For one, user may run the VM on an own implementation of threads
+// whose stacks are - like the old LinuxThreads - implemented using
+// mmap(MAP_GROWSDOWN).
+//
+// Also, this coding may be needed if the VM is running on the primordial
+// thread. Normally we avoid running on the primordial thread; however,
+// user may still invoke the VM on the primordial thread.
+//
+// The following historical comment describes the details about running
+// on a thread stack allocated with mmap(MAP_GROWSDOWN):
+
 
 // Force Linux kernel to expand current thread stack. If "bottom" is close
 // to the stack guard, caller should block all signals.
@@ -593,10 +561,7 @@
 //   stack overflow detection.
 //
 //   Newer version of LinuxThreads (since glibc-2.2, or, RH-7.x) and NPTL do
-//   not use this flag. However, the stack of initial thread is not created
-//   by pthread, it is still MAP_GROWSDOWN. Also it's possible (though
-//   unlikely) that user code can create a thread with MAP_GROWSDOWN stack
-//   and then attach the thread to JVM.
+//   not use MAP_GROWSDOWN.
 //
 // To get around the problem and allow stack banging on Linux, we need to
 // manually expand thread stack after receiving the SIGSEGV.
@@ -671,45 +636,6 @@
 //////////////////////////////////////////////////////////////////////////////
 // create new thread
 
-static address highest_vm_reserved_address();
-
-// check if it's safe to start a new thread
-static bool _thread_safety_check(Thread* thread) {
-  if (os::Linux::is_LinuxThreads() && !os::Linux::is_floating_stack()) {
-    // Fixed stack LinuxThreads (SuSE Linux/x86, and some versions of Redhat)
-    //   Heap is mmap'ed at lower end of memory space. Thread stacks are
-    //   allocated (MAP_FIXED) from high address space. Every thread stack
-    //   occupies a fixed size slot (usually 2Mbytes, but user can change
-    //   it to other values if they rebuild LinuxThreads).
-    //
-    // Problem with MAP_FIXED is that mmap() can still succeed even part of
-    // the memory region has already been mmap'ed. That means if we have too
-    // many threads and/or very large heap, eventually thread stack will
-    // collide with heap.
-    //
-    // Here we try to prevent heap/stack collision by comparing current
-    // stack bottom with the highest address that has been mmap'ed by JVM
-    // plus a safety margin for memory maps created by native code.
-    //
-    // This feature can be disabled by setting ThreadSafetyMargin to 0
-    //
-    if (ThreadSafetyMargin > 0) {
-      address stack_bottom = os::current_stack_base() - os::current_stack_size();
-
-      // not safe if our stack extends below the safety margin
-      return stack_bottom - ThreadSafetyMargin >= highest_vm_reserved_address();
-    } else {
-      return true;
-    }
-  } else {
-    // Floating stack LinuxThreads or NPTL:
-    //   Unlike fixed stack LinuxThreads, thread stacks are not MAP_FIXED. When
-    //   there's not enough space left, pthread_create() will fail. If we come
-    //   here, that means enough space has been reserved for stack.
-    return true;
-  }
-}
-
 // Thread start routine for all newly created threads
 static void *java_start(Thread *thread) {
   // Try to randomize the cache line index of hot stack frames.
@@ -726,15 +652,6 @@
   OSThread* osthread = thread->osthread();
   Monitor* sync = osthread->startThread_lock();
 
-  // non floating stack LinuxThreads needs extra check, see above
-  if (!_thread_safety_check(thread)) {
-    // notify parent thread
-    MutexLockerEx ml(sync, Mutex::_no_safepoint_check_flag);
-    osthread->set_state(ZOMBIE);
-    sync->notify_all();
-    return NULL;
-  }
-
   // thread_id is kernel thread id (similar to Solaris LWP id)
   osthread->set_thread_id(os::Linux::gettid());
 
@@ -833,12 +750,6 @@
   ThreadState state;
 
   {
-    // Serialize thread creation if we are running with fixed stack LinuxThreads
-    bool lock = os::Linux::is_LinuxThreads() && !os::Linux::is_floating_stack();
-    if (lock) {
-      os::Linux::createThread_lock()->lock_without_safepoint_check();
-    }
-
     pthread_t tid;
     int ret = pthread_create(&tid, &attr, (void* (*)(void*)) java_start, thread);
 
@@ -851,7 +762,6 @@
       // Need to clean up stuff we've allocated so far
       thread->set_osthread(NULL);
       delete osthread;
-      if (lock) os::Linux::createThread_lock()->unlock();
       return false;
     }
 
@@ -866,10 +776,6 @@
         sync_with_child->wait(Mutex::_no_safepoint_check_flag);
       }
     }
-
-    if (lock) {
-      os::Linux::createThread_lock()->unlock();
-    }
   }
 
   // Aborted due to thread limit being reached
@@ -1497,7 +1403,6 @@
 
 // Die immediately, no exit hook, no abort hook, no cleanup.
 void os::die() {
-  // _exit() on LinuxThreads only kills current thread
   ::abort();
 }
 
@@ -1520,24 +1425,7 @@
 
 intx os::current_thread_id() { return (intx)pthread_self(); }
 int os::current_process_id() {
-
-  // Under the old linux thread library, linux gives each thread
-  // its own process id. Because of this each thread will return
-  // a different pid if this method were to return the result
-  // of getpid(2). Linux provides no api that returns the pid
-  // of the launcher thread for the vm. This implementation
-  // returns a unique pid, the pid of the launcher thread
-  // that starts the vm 'process'.
-
-  // Under the NPTL, getpid() returns the same pid as the
-  // launcher thread rather than a unique pid per thread.
-  // Use gettid() if you want the old pre NPTL behaviour.
-
-  // if you are looking for the result of a call to getpid() that
-  // returns a unique pid for the calling thread, then look at the
-  // OSThread::thread_id() method in osThread_linux.hpp file
-
-  return (int)(_initial_pid ? _initial_pid : getpid());
+  return ::getpid();
 }
 
 // DLL functions
@@ -1623,7 +1511,8 @@
 }
 
 bool os::dll_address_to_function_name(address addr, char *buf,
-                                      int buflen, int *offset) {
+                                      int buflen, int *offset,
+                                      bool demangle) {
   // buf is not optional, but offset is optional
   assert(buf != NULL, "sanity check");
 
@@ -1632,7 +1521,7 @@
   if (dladdr((void*)addr, &dlinfo) != 0) {
     // see if we have a matching symbol
     if (dlinfo.dli_saddr != NULL && dlinfo.dli_sname != NULL) {
-      if (!Decoder::demangle(dlinfo.dli_sname, buf, buflen)) {
+      if (!(demangle && Decoder::demangle(dlinfo.dli_sname, buf, buflen))) {
         jio_snprintf(buf, buflen, "%s", dlinfo.dli_sname);
       }
       if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr;
@@ -1641,7 +1530,7 @@
     // no matching symbol so try for just file info
     if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != NULL) {
       if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase),
-                          buf, buflen, offset, dlinfo.dli_fname)) {
+                          buf, buflen, offset, dlinfo.dli_fname, demangle)) {
         return true;
       }
     }
@@ -2183,9 +2072,6 @@
   st->print("libc:");
   st->print("%s ", os::Linux::glibc_version());
   st->print("%s ", os::Linux::libpthread_version());
-  if (os::Linux::is_LinuxThreads()) {
-    st->print("(%s stack)", os::Linux::is_floating_stack() ? "floating" : "fixed");
-  }
   st->cr();
 }
 
@@ -2215,12 +2101,52 @@
   st->cr();
 }
 
-void os::pd_print_cpu_info(outputStream* st) {
-  st->print("\n/proc/cpuinfo:\n");
-  if (!_print_ascii_file("/proc/cpuinfo", st)) {
-    st->print("  <Not Available>");
-  }
-  st->cr();
+// Print the first "model name" line and the first "flags" line
+// that we find and nothing more. We assume "model name" comes
+// before "flags" so if we find a second "model name", then the
+// "flags" field is considered missing.
+static bool print_model_name_and_flags(outputStream* st, char* buf, size_t buflen) {
+#if defined(IA32) || defined(AMD64)
+  // Other platforms have less repetitive cpuinfo files
+  FILE *fp = fopen("/proc/cpuinfo", "r");
+  if (fp) {
+    while (!feof(fp)) {
+      if (fgets(buf, buflen, fp)) {
+        // Assume model name comes before flags
+        bool model_name_printed = false;
+        if (strstr(buf, "model name") != NULL) {
+          if (!model_name_printed) {
+            st->print_raw("\nCPU Model and flags from /proc/cpuinfo:\n");
+            st->print_raw(buf);
+            model_name_printed = true;
+          } else {
+            // model name printed but not flags?  Odd, just return
+            fclose(fp);
+            return true;
+          }
+        }
+        // print the flags line too
+        if (strstr(buf, "flags") != NULL) {
+          st->print_raw(buf);
+          fclose(fp);
+          return true;
+        }
+      }
+    }
+    fclose(fp);
+  }
+#endif // x86 platforms
+  return false;
+}
+
+void os::pd_print_cpu_info(outputStream* st, char* buf, size_t buflen) {
+  // Only print the model name if the platform provides this as a summary
+  if (!print_model_name_and_flags(st, buf, buflen)) {
+    st->print("\n/proc/cpuinfo:\n");
+    if (!_print_ascii_file("/proc/cpuinfo", st)) {
+      st->print_cr("  <Not Available>");
+    }
+  }
 }
 
 void os::print_siginfo(outputStream* st, void* siginfo) {
@@ -3044,8 +2970,6 @@
   return os::uncommit_memory(addr, size);
 }
 
-static address _highest_vm_reserved_address = NULL;
-
 // If 'fixed' is true, anon_mmap() will attempt to reserve anonymous memory
 // at 'requested_addr'. If there are existing memory mappings at the same
 // location, however, they will be overwritten. If 'fixed' is false,
@@ -3068,23 +2992,9 @@
   addr = (char*)::mmap(requested_addr, bytes, PROT_NONE,
                        flags, -1, 0);
 
-  if (addr != MAP_FAILED) {
-    // anon_mmap() should only get called during VM initialization,
-    // don't need lock (actually we can skip locking even it can be called
-    // from multiple threads, because _highest_vm_reserved_address is just a
-    // hint about the upper limit of non-stack memory regions.)
-    if ((address)addr + bytes > _highest_vm_reserved_address) {
-      _highest_vm_reserved_address = (address)addr + bytes;
-    }
-  }
-
   return addr == MAP_FAILED ? NULL : addr;
 }
 
-// Don't update _highest_vm_reserved_address, because there might be memory
-// regions above addr + size. If so, releasing a memory region only creates
-// a hole in the address space, it doesn't help prevent heap-stack collision.
-//
 static int anon_munmap(char * addr, size_t size) {
   return ::munmap(addr, size) == 0;
 }
@@ -3098,10 +3008,6 @@
   return anon_munmap(addr, size);
 }
 
-static address highest_vm_reserved_address() {
-  return _highest_vm_reserved_address;
-}
-
 static bool linux_mprotect(char* addr, size_t size, int prot) {
   // Linux wants the mprotect address argument to be page aligned.
   char* bottom = (char*)align_size_down((intptr_t)addr, os::Linux::page_size());
@@ -3718,15 +3624,7 @@
   assert(bytes % os::vm_page_size() == 0, "reserving unexpected size block");
 
   // Repeatedly allocate blocks until the block is allocated at the
-  // right spot. Give up after max_tries. Note that reserve_memory() will
-  // automatically update _highest_vm_reserved_address if the call is
-  // successful. The variable tracks the highest memory address every reserved
-  // by JVM. It is used to detect heap-stack collision if running with
-  // fixed-stack LinuxThreads. Because here we may attempt to reserve more
-  // space than needed, it could confuse the collision detecting code. To
-  // solve the problem, save current _highest_vm_reserved_address and
-  // calculate the correct value before return.
-  address old_highest = _highest_vm_reserved_address;
+  // right spot.
 
   // Linux mmap allows caller to pass an address as hint; give it a try first,
   // if kernel honors the hint then we can return immediately.
@@ -3780,10 +3678,8 @@
   }
 
   if (i < max_tries) {
-    _highest_vm_reserved_address = MAX2(old_highest, (address)requested_addr + bytes);
     return requested_addr;
   } else {
-    _highest_vm_reserved_address = old_highest;
     return NULL;
   }
 }
@@ -4627,16 +4523,6 @@
   char dummy;   // used to get a guess on initial stack address
 //  first_hrtime = gethrtime();
 
-  // With LinuxThreads the JavaMain thread pid (primordial thread)
-  // is different than the pid of the java launcher thread.
-  // So, on Linux, the launcher thread pid is passed to the VM
-  // via the sun.java.launcher.pid property.
-  // Use this property instead of getpid() if it was correctly passed.
-  // See bug 6351349.
-  pid_t java_launcher_pid = (pid_t) Arguments::sun_java_launcher_pid();
-
-  _initial_pid = (java_launcher_pid > 0) ? java_launcher_pid : getpid();
-
   clock_tics_per_sec = sysconf(_SC_CLK_TCK);
 
   init_random(1234567);
@@ -4769,9 +4655,8 @@
 
   Linux::libpthread_init();
   if (PrintMiscellaneous && (Verbose || WizardMode)) {
-    tty->print_cr("[HotSpot is running with %s, %s(%s)]\n",
-                  Linux::glibc_version(), Linux::libpthread_version(),
-                  Linux::is_floating_stack() ? "floating stack" : "fixed stack");
+    tty->print_cr("[HotSpot is running with %s, %s]\n",
+                  Linux::glibc_version(), Linux::libpthread_version());
   }
 
   if (UseNUMA) {
@@ -4946,22 +4831,6 @@
   return fetcher.result();
 }
 
-int os::Linux::safe_cond_timedwait(pthread_cond_t *_cond,
-                                   pthread_mutex_t *_mutex,
-                                   const struct timespec *_abstime) {
-  if (is_NPTL()) {
-    return pthread_cond_timedwait(_cond, _mutex, _abstime);
-  } else {
-    // 6292965: LinuxThreads pthread_cond_timedwait() resets FPU control
-    // word back to default 64bit precision if condvar is signaled. Java
-    // wants 53bit precision.  Save and restore current value.
-    int fpu = get_fpu_control_word();
-    int status = pthread_cond_timedwait(_cond, _mutex, _abstime);
-    set_fpu_control_word(fpu);
-    return status;
-  }
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // debug support
 
@@ -5585,7 +5454,7 @@
   // In that case, we should propagate the notify to another waiter.
 
   while (_Event < 0) {
-    status = os::Linux::safe_cond_timedwait(_cond, _mutex, &abst);
+    status = pthread_cond_timedwait(_cond, _mutex, &abst);
     if (status != 0 && WorkAroundNPTLTimedWaitHang) {
       pthread_cond_destroy(_cond);
       pthread_cond_init(_cond, os::Linux::condAttr());
@@ -5813,7 +5682,7 @@
     status = pthread_cond_wait(&_cond[_cur_index], _mutex);
   } else {
     _cur_index = isAbsolute ? ABS_INDEX : REL_INDEX;
-    status = os::Linux::safe_cond_timedwait(&_cond[_cur_index], _mutex, &absTime);
+    status = pthread_cond_timedwait(&_cond[_cur_index], _mutex, &absTime);
     if (status != 0 && WorkAroundNPTLTimedWaitHang) {
       pthread_cond_destroy(&_cond[_cur_index]);
       pthread_cond_init(&_cond[_cur_index], isAbsolute ? NULL : os::Linux::condAttr());
--- a/hotspot/src/os/linux/vm/os_linux.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/os/linux/vm/os_linux.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, 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
@@ -27,9 +27,6 @@
 
 // Linux_OS defines the interface to Linux operating systems
 
-// pthread_getattr_np comes with LinuxThreads-0.9-7 on RedHat 7.1
-typedef int (*pthread_getattr_func_type)(pthread_t, pthread_attr_t *);
-
 // Information about the protection of the page at address '0' on this os.
 static bool zero_page_read_protected() { return true; }
 
@@ -63,8 +60,6 @@
   static const char *_glibc_version;
   static const char *_libpthread_version;
 
-  static bool _is_floating_stack;
-  static bool _is_NPTL;
   static bool _supports_fast_thread_cpu_time;
 
   static GrowableArray<int>* _cpu_to_node;
@@ -90,10 +85,6 @@
 
   static bool supports_variable_stack_size();
 
-  static void set_is_NPTL()                   { _is_NPTL = true;  }
-  static void set_is_LinuxThreads()           { _is_NPTL = false; }
-  static void set_is_floating_stack()         { _is_floating_stack = true; }
-
   static void rebuild_cpu_to_node_map();
   static GrowableArray<int>* cpu_to_node()    { return _cpu_to_node; }
 
@@ -178,14 +169,6 @@
   static const char *glibc_version()          { return _glibc_version; }
   static const char *libpthread_version()     { return _libpthread_version; }
 
-  // NPTL or LinuxThreads?
-  static bool is_LinuxThreads()               { return !_is_NPTL; }
-  static bool is_NPTL()                       { return _is_NPTL;  }
-
-  // NPTL is always floating stack. LinuxThreads could be using floating
-  // stack or fixed stack.
-  static bool is_floating_stack()             { return _is_floating_stack; }
-
   static void libpthread_init();
   static bool libnuma_init();
   static void* libnuma_dlsym(void* handle, const char* name);
@@ -234,9 +217,6 @@
 
   // none present
 
-  // LinuxThreads work-around for 6292965
-  static int safe_cond_timedwait(pthread_cond_t *_cond, pthread_mutex_t *_mutex, const struct timespec *_abstime);
-
  private:
   typedef int (*sched_getcpu_func_t)(void);
   typedef int (*numa_node_to_cpus_func_t)(int node, unsigned long *buffer, int bufferlen);
--- a/hotspot/src/os/solaris/vm/globals_solaris.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/os/solaris/vm/globals_solaris.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, 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
@@ -28,7 +28,7 @@
 //
 // Defines Solaris specific flags. They are not available on other platforms.
 //
-#define RUNTIME_OS_FLAGS(develop, develop_pd, product, product_pd, diagnostic, notproduct) \
+#define RUNTIME_OS_FLAGS(develop, develop_pd, product, product_pd, diagnostic, notproduct, range, constraint) \
                                                                                \
   product(bool, UseExtendedFileIO, true,                                       \
           "Enable workaround for limitations of stdio FILE structure")
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -1627,7 +1627,8 @@
 static dladdr1_func_type dladdr1_func = NULL;
 
 bool os::dll_address_to_function_name(address addr, char *buf,
-                                      int buflen, int * offset) {
+                                      int buflen, int * offset,
+                                      bool demangle) {
   // buf is not optional, but offset is optional
   assert(buf != NULL, "sanity check");
 
@@ -1655,7 +1656,7 @@
       if (dlinfo.dli_saddr != NULL &&
           (char *)dlinfo.dli_saddr + info->st_size > (char *)addr) {
         if (dlinfo.dli_sname != NULL) {
-          if (!Decoder::demangle(dlinfo.dli_sname, buf, buflen)) {
+          if (!(demangle && Decoder::demangle(dlinfo.dli_sname, buf, buflen))) {
             jio_snprintf(buf, buflen, "%s", dlinfo.dli_sname);
           }
           if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr;
@@ -1665,7 +1666,7 @@
       // no matching symbol so try for just file info
       if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != NULL) {
         if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase),
-                            buf, buflen, offset, dlinfo.dli_fname)) {
+                            buf, buflen, offset, dlinfo.dli_fname, demangle)) {
           return true;
         }
       }
@@ -1679,7 +1680,7 @@
   if (dladdr((void *)addr, &dlinfo) != 0) {
     // see if we have a matching symbol
     if (dlinfo.dli_saddr != NULL && dlinfo.dli_sname != NULL) {
-      if (!Decoder::demangle(dlinfo.dli_sname, buf, buflen)) {
+      if (!(demangle && Decoder::demangle(dlinfo.dli_sname, buf, buflen))) {
         jio_snprintf(buf, buflen, dlinfo.dli_sname);
       }
       if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr;
@@ -1688,7 +1689,7 @@
     // no matching symbol so try for just file info
     if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != NULL) {
       if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase),
-                          buf, buflen, offset, dlinfo.dli_fname)) {
+                          buf, buflen, offset, dlinfo.dli_fname, demangle)) {
         return true;
       }
     }
@@ -1996,7 +1997,7 @@
   return status;
 }
 
-void os::pd_print_cpu_info(outputStream* st) {
+void os::pd_print_cpu_info(outputStream* st, char* buf, size_t buflen) {
   // Nothing to do for now.
 }
 
--- a/hotspot/src/os/windows/vm/decoder_windows.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/os/windows/vm/decoder_windows.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, 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
@@ -162,7 +162,7 @@
      // current function and comparing the result
      address addr = (address)Decoder::demangle;
      char buf[MAX_PATH];
-     if (decode(addr, buf, sizeof(buf), NULL)) {
+     if (decode(addr, buf, sizeof(buf), NULL, NULL, true /* demangle */)) {
        _can_decode_in_vm = !strcmp(buf, "Decoder::demangle");
      }
   }
@@ -187,7 +187,7 @@
 }
 
 
-bool WindowsDecoder::decode(address addr, char *buf, int buflen, int* offset, const char* modulepath)  {
+bool WindowsDecoder::decode(address addr, char *buf, int buflen, int* offset, const char* modulepath, bool demangle_name)  {
   if (_pfnSymGetSymFromAddr64 != NULL) {
     PIMAGEHLP_SYMBOL64 pSymbol;
     char symbolInfo[MAX_PATH + sizeof(IMAGEHLP_SYMBOL64)];
@@ -197,7 +197,7 @@
     DWORD64 displacement;
     if (_pfnSymGetSymFromAddr64(::GetCurrentProcess(), (DWORD64)addr, &displacement, pSymbol)) {
       if (buf != NULL) {
-        if (demangle(pSymbol->Name, buf, buflen)) {
+        if (!(demangle_name && demangle(pSymbol->Name, buf, buflen))) {
           jio_snprintf(buf, buflen, "%s", pSymbol->Name);
         }
       }
--- a/hotspot/src/os/windows/vm/decoder_windows.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/os/windows/vm/decoder_windows.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2015, 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
@@ -60,7 +60,7 @@
 
   bool can_decode_C_frame_in_vm() const;
   bool demangle(const char* symbol, char *buf, int buflen);
-  bool decode(address addr, char *buf, int buflen, int* offset, const char* modulepath = NULL);
+  bool decode(address addr, char *buf, int buflen, int* offset, const char* modulepath, bool demangle);
   bool decode(address addr, char *buf, int buflen, int* offset, const void* base) {
     ShouldNotReachHere();
     return false;
--- a/hotspot/src/os/windows/vm/globals_windows.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/os/windows/vm/globals_windows.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, 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
@@ -28,8 +28,7 @@
 //
 // Defines Windows specific flags. They are not available on other platforms.
 //
-#define RUNTIME_OS_FLAGS(develop, develop_pd, product, product_pd,       \
-                         diagnostic, notproduct)                         \
+#define RUNTIME_OS_FLAGS(develop, develop_pd, product, product_pd, diagnostic, notproduct, range, constraint) \
                                                                          \
   product(bool, UseUTCFileTimestamp, true,                               \
           "Adjust the timestamp returned from stat() to be UTC")
--- a/hotspot/src/os/windows/vm/os_windows.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/os/windows/vm/os_windows.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -1369,11 +1369,12 @@
 }
 
 bool os::dll_address_to_function_name(address addr, char *buf,
-                                      int buflen, int *offset) {
+                                      int buflen, int *offset,
+                                      bool demangle) {
   // buf is not optional, but offset is optional
   assert(buf != NULL, "sanity check");
 
-  if (Decoder::decode(addr, buf, buflen, offset)) {
+  if (Decoder::decode(addr, buf, buflen, offset, demangle)) {
     return true;
   }
   if (offset != NULL)  *offset  = -1;
@@ -1732,7 +1733,7 @@
   st->cr();
 }
 
-void os::pd_print_cpu_info(outputStream* st) {
+void os::pd_print_cpu_info(outputStream* st, char* buf, size_t buflen) {
   // Nothing to do for now.
 }
 
--- a/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -10,7 +10,7 @@
  * 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 hat
+ * 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
--- a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, 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
@@ -619,53 +619,14 @@
 
 #ifdef AMD64
 size_t os::Linux::min_stack_allowed  = 64 * K;
-
-// amd64: pthread on amd64 is always in floating stack mode
-bool os::Linux::supports_variable_stack_size() {  return true; }
 #else
 size_t os::Linux::min_stack_allowed  =  (48 DEBUG_ONLY(+4))*K;
-
-#ifdef __GNUC__
-#define GET_GS() ({int gs; __asm__ volatile("movw %%gs, %w0":"=q"(gs)); gs&0xffff;})
-#endif
-
-// Test if pthread library can support variable thread stack size. LinuxThreads
-// in fixed stack mode allocates 2M fixed slot for each thread. LinuxThreads
-// in floating stack mode and NPTL support variable stack size.
-bool os::Linux::supports_variable_stack_size() {
-  if (os::Linux::is_NPTL()) {
-     // NPTL, yes
-     return true;
+#endif // AMD64
 
-  } else {
-    // Note: We can't control default stack size when creating a thread.
-    // If we use non-default stack size (pthread_attr_setstacksize), both
-    // floating stack and non-floating stack LinuxThreads will return the
-    // same value. This makes it impossible to implement this function by
-    // detecting thread stack size directly.
-    //
-    // An alternative approach is to check %gs. Fixed-stack LinuxThreads
-    // do not use %gs, so its value is 0. Floating-stack LinuxThreads use
-    // %gs (either as LDT selector or GDT selector, depending on kernel)
-    // to access thread specific data.
-    //
-    // Note that %gs is a reserved glibc register since early 2001, so
-    // applications are not allowed to change its value (Ulrich Drepper from
-    // Redhat confirmed that all known offenders have been modified to use
-    // either %fs or TSD). In the worst case scenario, when VM is embedded in
-    // a native application that plays with %gs, we might see non-zero %gs
-    // even LinuxThreads is running in fixed stack mode. As the result, we'll
-    // return true and skip _thread_safety_check(), so we may not be able to
-    // detect stack-heap collisions. But otherwise it's harmless.
-    //
-#ifdef __GNUC__
-    return (GET_GS() != 0);
-#else
-    return false;
-#endif
-  }
+// Test if pthread library can support variable thread stack size.
+bool os::Linux::supports_variable_stack_size() {
+  return true;
 }
-#endif // AMD64
 
 // return default stack size for thr_type
 size_t os::Linux::default_stack_size(os::ThreadType thr_type) {
--- a/hotspot/src/os_cpu/linux_x86/vm/threadLS_linux_x86.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/os_cpu/linux_x86/vm/threadLS_linux_x86.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, 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
@@ -40,8 +40,7 @@
 // actual memory pages are committed on demand.
 //
 // If an application creates and destroys a lot of threads, usually the
-// stack space freed by a thread will soon get reused by new thread
-// (this is especially true in NPTL or LinuxThreads in fixed-stack mode).
+// stack space freed by a thread will soon get reused by new thread.
 // No memory page in _sp_map is wasted.
 //
 // However, it's still possible that we might end up populating &
--- a/hotspot/src/share/tools/ProjectCreator/WinGammaPlatformVC10.java	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/tools/ProjectCreator/WinGammaPlatformVC10.java	Thu Jun 25 09:48:50 2015 -0700
@@ -363,9 +363,6 @@
 
         // Set /On option
         addAttr(rv, "Optimization", opt);
-        // Set /FR option.
-        addAttr(rv, "BrowseInformation", "true");
-        addAttr(rv, "BrowseInformationFile", "$(IntDir)");
         // Set /MD option.
         addAttr(rv, "RuntimeLibrary", "MultiThreadedDLL");
         // Set /Oy- option
--- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -1619,6 +1619,9 @@
   LIR_Opr dirty = LIR_OprFact::intConst(CardTableModRefBS::dirty_card_val());
   if (UseCondCardMark) {
     LIR_Opr cur_value = new_register(T_INT);
+    if (UseConcMarkSweepGC) {
+      __ membar_storeload();
+    }
     __ move(card_addr, cur_value);
 
     LabelObj* L_already_dirty = new LabelObj();
--- a/hotspot/src/share/vm/c1/c1_globals.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/c1/c1_globals.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, 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
@@ -25,4 +25,4 @@
 #include "precompiled.hpp"
 #include "c1/c1_globals.hpp"
 
-C1_FLAGS(MATERIALIZE_DEVELOPER_FLAG, MATERIALIZE_PD_DEVELOPER_FLAG, MATERIALIZE_PRODUCT_FLAG, MATERIALIZE_PD_PRODUCT_FLAG, MATERIALIZE_DIAGNOSTIC_FLAG, MATERIALIZE_NOTPRODUCT_FLAG)
+C1_FLAGS(MATERIALIZE_DEVELOPER_FLAG, MATERIALIZE_PD_DEVELOPER_FLAG, MATERIALIZE_PRODUCT_FLAG, MATERIALIZE_PD_PRODUCT_FLAG, MATERIALIZE_DIAGNOSTIC_FLAG, MATERIALIZE_NOTPRODUCT_FLAG, IGNORE_RANGE, IGNORE_CONSTRAINT)
--- a/hotspot/src/share/vm/c1/c1_globals.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/c1/c1_globals.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, 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
@@ -60,7 +60,7 @@
 //
 // Defines all global flags used by the client compiler.
 //
-#define C1_FLAGS(develop, develop_pd, product, product_pd, diagnostic, notproduct) \
+#define C1_FLAGS(develop, develop_pd, product, product_pd, diagnostic, notproduct, range, constraint) \
                                                                             \
   /* Printing */                                                            \
   notproduct(bool, PrintC1Statistics, false,                                \
@@ -148,6 +148,7 @@
                                                                             \
   product(intx, ValueMapInitialSize, 11,                                    \
           "Initial size of a value map")                                    \
+          range(1, NOT_LP64(1*K) LP64_ONLY(32*K))                           \
                                                                             \
   product(intx, ValueMapMaxLoopSize, 8,                                     \
           "maximum size of a loop optimized by global value numbering")     \
@@ -191,6 +192,7 @@
                                                                             \
   develop(intx, NestedInliningSizeRatio, 90,                                \
           "Percentage of prev. allowed inline size in recursive inlining")  \
+          range(0, 100)                                                     \
                                                                             \
   notproduct(bool, PrintIRWithLIR, false,                                   \
           "Print IR instructions with generated LIR")                       \
@@ -338,10 +340,15 @@
   diagnostic(bool, C1PatchInvokeDynamic, true,                              \
              "Patch invokedynamic appendix not known at compile time")      \
                                                                             \
-
-
 // Read default values for c1 globals
 
-C1_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_NOTPRODUCT_FLAG)
+C1_FLAGS(DECLARE_DEVELOPER_FLAG, \
+         DECLARE_PD_DEVELOPER_FLAG, \
+         DECLARE_PRODUCT_FLAG, \
+         DECLARE_PD_PRODUCT_FLAG, \
+         DECLARE_DIAGNOSTIC_FLAG, \
+         DECLARE_NOTPRODUCT_FLAG, \
+         IGNORE_RANGE, \
+         IGNORE_CONSTRAINT)
 
 #endif // SHARE_VM_C1_C1_GLOBALS_HPP
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -949,8 +949,7 @@
         assert(runtime_visible_annotations != NULL, "null visible annotations");
         parse_annotations(runtime_visible_annotations,
                           runtime_visible_annotations_length,
-                          parsed_annotations,
-                          CHECK);
+                          parsed_annotations);
         cfs->skip_u1(runtime_visible_annotations_length, CHECK);
       } else if (attribute_name == vmSymbols::tag_runtime_invisible_annotations()) {
         if (runtime_invisible_annotations_exists) {
@@ -1643,7 +1642,6 @@
     index = skip_annotation(buffer, limit, index);
     break;
   default:
-    assert(false, "annotation tag");
     return limit;  //  bad tag byte
   }
   return index;
@@ -1651,8 +1649,7 @@
 
 // Sift through annotations, looking for those significant to the VM:
 void ClassFileParser::parse_annotations(u1* buffer, int limit,
-                                        ClassFileParser::AnnotationCollector* coll,
-                                        TRAPS) {
+                                        ClassFileParser::AnnotationCollector* coll) {
   // annotations := do(nann:u2) {annotation}
   int index = 0;
   if ((index += 2) >= limit)  return;  // read nann
@@ -2286,8 +2283,7 @@
         runtime_visible_annotations = cfs->get_u1_buffer();
         assert(runtime_visible_annotations != NULL, "null visible annotations");
         parse_annotations(runtime_visible_annotations,
-            runtime_visible_annotations_length, &parsed_annotations,
-            CHECK_(nullHandle));
+            runtime_visible_annotations_length, &parsed_annotations);
         cfs->skip_u1(runtime_visible_annotations_length, CHECK_(nullHandle));
       } else if (method_attribute_name == vmSymbols::tag_runtime_invisible_annotations()) {
         if (runtime_invisible_annotations_exists) {
@@ -2951,8 +2947,7 @@
         assert(runtime_visible_annotations != NULL, "null visible annotations");
         parse_annotations(runtime_visible_annotations,
                           runtime_visible_annotations_length,
-                          parsed_annotations,
-                          CHECK);
+                          parsed_annotations);
         cfs->skip_u1(runtime_visible_annotations_length, CHECK);
       } else if (tag == vmSymbols::tag_runtime_invisible_annotations()) {
         if (runtime_invisible_annotations_exists) {
--- a/hotspot/src/share/vm/classfile/classFileParser.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/classfile/classFileParser.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -295,8 +295,7 @@
   int skip_annotation_value(u1* buffer, int limit, int index);
   void parse_annotations(u1* buffer, int limit,
                          /* Results (currently, only one result is supported): */
-                         AnnotationCollector* result,
-                         TRAPS);
+                         AnnotationCollector* result);
 
   // Final setup
   unsigned int compute_oop_map_count(instanceKlassHandle super,
--- a/hotspot/src/share/vm/classfile/compactHashtable.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/classfile/compactHashtable.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -25,6 +25,7 @@
 #include "precompiled.hpp"
 #include "classfile/javaClasses.hpp"
 #include "memory/metaspaceShared.hpp"
+#include "prims/jvm.h"
 #include "utilities/numberSeq.hpp"
 #include <sys/stat.h>
 
@@ -32,11 +33,11 @@
 //
 // The compact hash table writer implementations
 //
-CompactHashtableWriter::CompactHashtableWriter(const char* table_name,
+CompactHashtableWriter::CompactHashtableWriter(int table_type,
                                                int num_entries,
                                                CompactHashtableStats* stats) {
   assert(DumpSharedSpaces, "dump-time only");
-  _table_name = table_name;
+  _type = table_type;
   _num_entries = num_entries;
   _num_buckets = number_of_buckets(_num_entries);
   _buckets = NEW_C_HEAP_ARRAY(Entry*, _num_buckets, mtSymbol);
@@ -99,7 +100,7 @@
                                           NumberSeq* summary) {
   int index;
   juint* compact_table = p;
-  // Find the start of the buckets, skip the compact_bucket_infos table
+  // Compute the start of the buckets, include the compact_bucket_infos table
   // and the table end offset.
   juint offset = _num_buckets + 1;
   *first_bucket = compact_table + offset;
@@ -130,10 +131,17 @@
 // Write the compact table's entries
 juint* CompactHashtableWriter::dump_buckets(juint* compact_table, juint* p,
                                             NumberSeq* summary) {
-  uintx base_address = uintx(MetaspaceShared::shared_rs()->base());
-  uintx max_delta    = uintx(MetaspaceShared::shared_rs()->size());
-  assert(max_delta <= 0x7fffffff, "range check");
+  uintx base_address = 0;
+  uintx max_delta = 0;
   int num_compact_buckets = 0;
+  if (_type == CompactHashtable<Symbol*, char>::_symbol_table) {
+    base_address = uintx(MetaspaceShared::shared_rs()->base());
+    max_delta    = uintx(MetaspaceShared::shared_rs()->size());
+    assert(max_delta <= 0x7fffffff, "range check");
+  } else {
+    assert((_type == CompactHashtable<oop, char>::_string_table), "unknown table");
+    assert(UseCompressedOops, "UseCompressedOops is required");
+  }
 
   assert(p != NULL, "sanity");
   for (int index = 0; index < _num_buckets; index++) {
@@ -148,12 +156,16 @@
     for (Entry* tent = _buckets[index]; tent;
          tent = tent->next()) {
       if (bucket_type == REGULAR_BUCKET_TYPE) {
-        *p++ = juint(tent->hash()); // write symbol hash
+        *p++ = juint(tent->hash()); // write entry hash
       }
-      uintx deltax = uintx(tent->value()) - base_address;
-      assert(deltax < max_delta, "range check");
-      juint delta = juint(deltax);
-      *p++ = delta; // write symbol offset
+      if (_type == CompactHashtable<Symbol*, char>::_symbol_table) {
+        uintx deltax = uintx(tent->value()) - base_address;
+        assert(deltax < max_delta, "range check");
+        juint delta = juint(deltax);
+        *p++ = delta; // write entry offset
+      } else {
+        *p++ = oopDesc::encode_heap_oop(tent->string());
+      }
       count ++;
     }
     assert(count == _bucket_sizes[index], "sanity");
@@ -174,6 +186,10 @@
 
   uintx base_address = uintx(MetaspaceShared::shared_rs()->base());
 
+  // Now write the following at the beginning of the table:
+  //      base_address (uintx)
+  //      num_entries  (juint)
+  //      num_buckets  (juint)
   *p++ = high(base_address);
   *p++ = low (base_address); // base address
   *p++ = _num_entries;  // number of entries in the table
@@ -191,7 +207,8 @@
     if (_num_entries > 0) {
       avg_cost = double(_required_bytes)/double(_num_entries);
     }
-    tty->print_cr("Shared %s table stats -------- base: " PTR_FORMAT, _table_name, (intptr_t)base_address);
+    tty->print_cr("Shared %s table stats -------- base: " PTR_FORMAT,
+                  table_name(), (intptr_t)base_address);
     tty->print_cr("Number of entries       : %9d", _num_entries);
     tty->print_cr("Total bytes used        : %9d", (int)((*top) - old_top));
     tty->print_cr("Average bytes per entry : %9.3f", avg_cost);
@@ -202,12 +219,24 @@
   }
 }
 
+const char* CompactHashtableWriter::table_name() {
+  switch (_type) {
+  case CompactHashtable<Symbol*, char>::_symbol_table: return "symbol";
+  case CompactHashtable<oop, char>::_string_table: return "string";
+  default:
+    ;
+  }
+  return "unknown";
+}
+
 /////////////////////////////////////////////////////////////
 //
 // The CompactHashtable implementation
 //
-template <class T, class N> const char* CompactHashtable<T, N>::init(const char* buffer) {
+template <class T, class N> const char* CompactHashtable<T, N>::init(
+                           CompactHashtableType type, const char* buffer) {
   assert(!DumpSharedSpaces, "run-time only");
+  _type = type;
   juint*p = (juint*)buffer;
   juint upper = *p++;
   juint lower = *p++;
@@ -245,8 +274,34 @@
   }
 }
 
+template <class T, class N> void CompactHashtable<T, N>::oops_do(OopClosure* f) {
+  assert(!DumpSharedSpaces, "run-time only");
+  assert(_type == _string_table || _bucket_count == 0, "sanity");
+  for (juint i = 0; i < _bucket_count; i ++) {
+    juint bucket_info = _buckets[i];
+    juint bucket_offset = BUCKET_OFFSET(bucket_info);
+    int   bucket_type = BUCKET_TYPE(bucket_info);
+    juint* bucket = _buckets + bucket_offset;
+    juint* bucket_end = _buckets;
+
+    narrowOop o;
+    if (bucket_type == COMPACT_BUCKET_TYPE) {
+      o = (narrowOop)bucket[0];
+      f->do_oop(&o);
+    } else {
+      bucket_end += BUCKET_OFFSET(_buckets[i + 1]);
+      while (bucket < bucket_end) {
+        o = (narrowOop)bucket[1];
+        f->do_oop(&o);
+        bucket += 2;
+      }
+    }
+  }
+}
+
 // Explicitly instantiate these types
 template class CompactHashtable<Symbol*, char>;
+template class CompactHashtable<oop, char>;
 
 #ifndef O_BINARY       // if defined (Win32) use binary files.
 #define O_BINARY 0     // otherwise do nothing.
@@ -273,6 +328,8 @@
   _p = _base;
   _end = _base + st.st_size;
   _filename = filename;
+  _prefix_type = Unknown;
+  _line_no = 1;
 }
 
 HashtableTextDump::~HashtableTextDump() {
@@ -286,9 +343,11 @@
   vm_exit_during_initialization(err, msg);
 }
 
-void HashtableTextDump::corrupted(const char *p) {
-  char info[60];
-  sprintf(info, "corrupted at pos %d", (int)(p - _base));
+void HashtableTextDump::corrupted(const char *p, const char* msg) {
+  char info[100];
+  jio_snprintf(info, sizeof(info),
+               "%s. Corrupted at line %d (file pos %d)",
+               msg, _line_no, (int)(p - _base));
   quit(info, _filename);
 }
 
@@ -298,8 +357,9 @@
   } else if (_p[0] == '\n') {
     _p += 1;
   } else {
-    corrupted(_p);
+    corrupted(_p, "Unexpected character");
   }
+  _line_no ++;
   return true;
 }
 
@@ -328,26 +388,60 @@
   skip_newline();
 }
 
+void HashtableTextDump::scan_prefix_type() {
+  _p ++;
+  if (strncmp(_p, "SECTION: String", 15) == 0) {
+    _p += 15;
+    _prefix_type = StringPrefix;
+  } else if (strncmp(_p, "SECTION: Symbol", 15) == 0) {
+    _p += 15;
+    _prefix_type = SymbolPrefix;
+  } else {
+    _prefix_type = Unknown;
+  }
+  skip_newline();
+}
 
-int HashtableTextDump::scan_prefix() {
+int HashtableTextDump::scan_prefix(int* utf8_length) {
+  if (*_p == '@') {
+    scan_prefix_type();
+  }
+
+  switch (_prefix_type) {
+  case SymbolPrefix:
+    *utf8_length = scan_symbol_prefix(); break;
+  case StringPrefix:
+    *utf8_length = scan_string_prefix(); break;
+  default:
+    tty->print_cr("Shared input data type: Unknown.");
+    corrupted(_p, "Unknown data type");
+  }
+
+  return _prefix_type;
+}
+
+int HashtableTextDump::scan_string_prefix() {
   // Expect /[0-9]+: /
-  int utf8_length = get_num(':');
+  int utf8_length;
+  get_num(':', &utf8_length);
   if (*_p != ' ') {
-    corrupted(_p);
+    corrupted(_p, "Wrong prefix format for string");
   }
   _p++;
   return utf8_length;
 }
 
-int HashtableTextDump::scan_prefix2() {
+int HashtableTextDump::scan_symbol_prefix() {
   // Expect /[0-9]+ (-|)[0-9]+: /
-  int utf8_length = get_num(' ');
-  if (*_p == '-') {
-    _p++;
+  int utf8_length;
+  get_num(' ', &utf8_length);
+    if (*_p == '-') {
+     _p++;
   }
-  (void)get_num(':');
+  int ref_num;
+  (void)get_num(':', &ref_num);
   if (*_p != ' ') {
-    corrupted(_p);
+    corrupted(_p, "Wrong prefix format for symbol");
   }
   _p++;
   return utf8_length;
@@ -408,7 +502,7 @@
       case 'r':  *to++ = '\r'; break;
       case '\\': *to++ = '\\'; break;
       default:
-        ShouldNotReachHere();
+        corrupted(_p, "Unsupported character");
       }
     }
   }
--- a/hotspot/src/share/vm/classfile/compactHashtable.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/classfile/compactHashtable.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -28,6 +28,7 @@
 #include "classfile/stringTable.hpp"
 #include "classfile/symbolTable.hpp"
 #include "memory/allocation.inline.hpp"
+#include "oops/oop.inline.hpp"
 #include "oops/symbol.hpp"
 #include "services/diagnosticCommand.hpp"
 #include "utilities/hashtable.hpp"
@@ -49,7 +50,7 @@
 // the compact table to the shared archive.
 //
 // At dump time, the CompactHashtableWriter obtains all entries from the
-// symbol table and adds them to a new temporary hash table. The hash
+// symbol/string table and adds them to a new temporary hash table. The hash
 // table size (number of buckets) is calculated using
 // '(num_entries + bucket_size - 1) / bucket_size'. The default bucket
 // size is 4 and can be changed by -XX:SharedSymbolTableBucketSize option.
@@ -57,14 +58,14 @@
 // faster lookup. It also has relatively small number of empty buckets and
 // good distribution of the entries.
 //
-// We use a simple hash function (symbol_hash % num_bucket) for the table.
+// We use a simple hash function (hash % num_bucket) for the table.
 // The new table is compacted when written out. Please see comments
 // above the CompactHashtable class for the table layout detail. The bucket
 // offsets are written to the archive as part of the compact table. The
 // bucket offset is encoded in the low 30-bit (0-29) and the bucket type
 // (regular or compact) are encoded in bit[31, 30]. For buckets with more
-// than one entry, both symbol hash and symbol offset are written to the
-// table. For buckets with only one entry, only the symbol offset is written
+// than one entry, both hash and entry offset are written to the
+// table. For buckets with only one entry, only the entry offset is written
 // to the table and the buckets are tagged as compact in their type bits.
 // Buckets without entry are skipped from the table. Their offsets are
 // still written out for faster lookup.
@@ -78,6 +79,7 @@
 
   public:
     Entry(unsigned int hash, Symbol *symbol) : _next(NULL), _hash(hash), _literal(symbol) {}
+    Entry(unsigned int hash, oop string)     : _next(NULL), _hash(hash), _literal(string) {}
 
     void *value() {
       return _literal;
@@ -85,6 +87,9 @@
     Symbol *symbol() {
       return (Symbol*)_literal;
     }
+    oop string() {
+      return (oop)_literal;
+    }
     unsigned int hash() {
       return _hash;
     }
@@ -95,7 +100,7 @@
 private:
   static int number_of_buckets(int num_entries);
 
-  const char* _table_name;
+  int _type;
   int _num_entries;
   int _num_buckets;
   juint* _bucket_sizes;
@@ -105,7 +110,7 @@
 
 public:
   // This is called at dump-time only
-  CompactHashtableWriter(const char* table_name, int num_entries, CompactHashtableStats* stats);
+  CompactHashtableWriter(int table_type, int num_entries, CompactHashtableStats* stats);
   ~CompactHashtableWriter();
 
   int get_required_bytes() {
@@ -116,6 +121,10 @@
     add(hash, new Entry(hash, symbol));
   }
 
+  void add(unsigned int hash, oop string) {
+    add(hash, new Entry(hash, string));
+  }
+
 private:
   void add(unsigned int hash, Entry* entry);
   juint* dump_table(juint* p, juint** first_bucket, NumberSeq* summary);
@@ -123,6 +132,7 @@
 
 public:
   void dump(char** top, char* end);
+  const char* table_name();
 };
 
 #define REGULAR_BUCKET_TYPE       0
@@ -136,23 +146,23 @@
 
 /////////////////////////////////////////////////////////////////////////////
 //
-// CompactHashtable is used to stored the CDS archive's symbol table. Used
+// CompactHashtable is used to stored the CDS archive's symbol/string table. Used
 // at runtime only to access the compact table from the archive.
 //
 // Because these tables are read-only (no entries can be added/deleted) at run-time
 // and tend to have large number of entries, we try to minimize the footprint
 // cost per entry.
 //
-// Layout of compact symbol table in the shared archive:
+// Layout of compact table in the shared archive:
 //
 //   uintx base_address;
-//   juint num_symbols;
+//   juint num_entries;
 //   juint num_buckets;
 //   juint bucket_infos[num_buckets+1]; // bit[31,30]: type; bit[29-0]: offset
 //   juint table[]
 //
 // -----------------------------------
-// | base_address  | num_symbols     |
+// | base_address  | num_entries     |
 // |---------------------------------|
 // | num_buckets   | bucket_info0    |
 // |---------------------------------|
@@ -177,9 +187,13 @@
 // compact buckets have '01' in their highest 2-bit, and regular buckets have
 // '00' in their highest 2-bit.
 //
-// For normal buckets, each symbol's entry is 8 bytes in the table[]:
-//   juint hash;    /* symbol hash */
-//   juint offset;  /* Symbol* sym = (Symbol*)(base_address + offset) */
+// For normal buckets, each entry is 8 bytes in the table[]:
+//   juint hash;    /* symbol/string hash */
+//   union {
+//     juint offset;  /* Symbol* sym = (Symbol*)(base_address + offset) */
+//     narrowOop str; /* String narrowOop encoding */
+//   }
+//
 //
 // For compact buckets, each entry has only the 4-byte 'offset' in the table[].
 //
@@ -189,19 +203,41 @@
 //
 template <class T, class N> class CompactHashtable VALUE_OBJ_CLASS_SPEC {
   friend class VMStructs;
+
+ public:
+  enum CompactHashtableType {
+    _symbol_table = 0,
+    _string_table = 1
+  };
+
+private:
+  CompactHashtableType _type;
   uintx  _base_address;
   juint  _entry_count;
   juint  _bucket_count;
   juint  _table_end_offset;
   juint* _buckets;
 
-  inline bool equals(T entry, const char* name, int len) {
-    if (entry->equals(name, len)) {
-      assert(entry->refcount() == -1, "must be shared");
-      return true;
-    } else {
-      return false;
+  inline Symbol* lookup_entry(CompactHashtable<Symbol*, char>* const t,
+                              juint* addr, const char* name, int len) {
+    Symbol* sym = (Symbol*)((void*)(_base_address + *addr));
+    if (sym->equals(name, len)) {
+      assert(sym->refcount() == -1, "must be shared");
+      return sym;
     }
+
+    return NULL;
+  }
+
+  inline oop lookup_entry(CompactHashtable<oop, char>* const t,
+                        juint* addr, const char* name, int len) {
+    narrowOop obj = (narrowOop)(*addr);
+    oop string = oopDesc::decode_heap_oop(obj);
+    if (java_lang_String::equals(string, (jchar*)name, len)) {
+      return string;
+    }
+
+    return NULL;
   }
 
 public:
@@ -211,7 +247,14 @@
     _table_end_offset = 0;
     _buckets = 0;
   }
-  const char* init(const char *buffer);
+  const char* init(CompactHashtableType type, const char *buffer);
+
+  void reset() {
+    _entry_count = 0;
+    _bucket_count = 0;
+    _table_end_offset = 0;
+    _buckets = 0;
+  }
 
   // Lookup an entry from the compact table
   inline T lookup(const N* name, unsigned int hash, int len) {
@@ -225,23 +268,22 @@
       juint* bucket_end = _buckets;
 
       if (bucket_type == COMPACT_BUCKET_TYPE) {
-        // the compact bucket has one entry with symbol offset only
-        T entry = (T)((void*)(_base_address + bucket[0]));
-        if (equals(entry, name, len)) {
-          return entry;
+        // the compact bucket has one entry with entry offset only
+        T res = lookup_entry(this, &bucket[0], name, len);
+        if (res != NULL) {
+          return res;
         }
       } else {
         // This is a regular bucket, which has more than one
-        // entries. Each entry is a pair of symbol (hash, offset).
+        // entries. Each entry is a pair of entry (hash, offset).
         // Seek until the end of the bucket.
         bucket_end += BUCKET_OFFSET(_buckets[index + 1]);
         while (bucket < bucket_end) {
           unsigned int h = (unsigned int)(bucket[0]);
           if (h == hash) {
-            juint offset = bucket[1];
-            T entry = (T)((void*)(_base_address + offset));
-            if (equals(entry, name, len)) {
-              return entry;
+            T res = lookup_entry(this, &bucket[1], name, len);
+            if (res != NULL) {
+              return res;
             }
           }
           bucket += 2;
@@ -253,12 +295,15 @@
 
   // iterate over symbols
   void symbols_do(SymbolClosure *cl);
+
+  // iterate over strings
+  void oops_do(OopClosure* f);
 };
 
 ////////////////////////////////////////////////////////////////////////
 //
 // Read/Write the contents of a hashtable textual dump (created by
-// SymbolTable::dump).
+// SymbolTable::dump and StringTable::dump).
 // Because the dump file may be big (hundred of MB in extreme cases),
 // we use mmap for fast access when reading it.
 //
@@ -269,21 +314,29 @@
   const char* _end;
   const char* _filename;
   size_t      _size;
+  int         _prefix_type;
+  int         _line_no;
 public:
   HashtableTextDump(const char* filename);
   ~HashtableTextDump();
 
+  enum {
+    SymbolPrefix = 1 << 0,
+    StringPrefix = 1 << 1,
+    Unknown = 1 << 2
+  };
+
   void quit(const char* err, const char* msg);
 
   inline int remain() {
     return (int)(_end - _p);
   }
 
-  void corrupted(const char *p);
+  void corrupted(const char *p, const char *msg);
 
   inline void corrupted_if(bool cond) {
     if (cond) {
-      corrupted(_p);
+      corrupted(_p, NULL);
     }
   }
 
@@ -292,7 +345,7 @@
   void skip_past(char c);
   void check_version(const char* ver);
 
-  inline int get_num(char delim) {
+  inline bool get_num(char delim, int *utf8_length) {
     const char* p   = _p;
     const char* end = _end;
     int num = 0;
@@ -303,18 +356,22 @@
         num = num * 10 + (c - '0');
       } else if (c == delim) {
         _p = p;
-        return num;
+        *utf8_length = num;
+        return true;
       } else {
-        corrupted(p-1);
+        // Not [0-9], not 'delim'
+        return false;
       }
     }
-    corrupted(_end);
+    corrupted(_end, "Incorrect format");
     ShouldNotReachHere();
-    return 0;
+    return false;
   }
 
-  int scan_prefix();
-  int scan_prefix2();
+  void scan_prefix_type();
+  int scan_prefix(int* utf8_length);
+  int scan_string_prefix();
+  int scan_symbol_prefix();
 
   jchar unescape(const char* from, const char* end, int count);
   void get_utf8(char* utf8_buffer, int utf8_length);
--- a/hotspot/src/share/vm/classfile/javaClasses.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/classfile/javaClasses.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -118,6 +118,10 @@
     return hash_offset;
   }
 
+  static void set_value_raw(oop string, typeArrayOop buffer) {
+    assert(initialized, "Must be initialized");
+    string->obj_field_put_raw(value_offset, buffer);
+  }
   static void set_value(oop string, typeArrayOop buffer) {
     assert(initialized && (value_offset > 0), "Must be initialized");
     string->obj_field_put(value_offset, (oop)buffer);
@@ -210,6 +214,7 @@
   // Debugging
   static void print(oop java_string, outputStream* st);
   friend class JavaClasses;
+  friend class StringTable;
 };
 
 
--- a/hotspot/src/share/vm/classfile/stringTable.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/classfile/stringTable.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -38,6 +38,7 @@
 #include "utilities/hashtable.inline.hpp"
 #include "utilities/macros.hpp"
 #if INCLUDE_ALL_GCS
+#include "gc/g1/g1CollectedHeap.hpp"
 #include "gc/g1/g1SATBCardTableModRefBS.hpp"
 #include "gc/g1/g1StringDedup.hpp"
 #endif
@@ -87,19 +88,28 @@
 
 // --------------------------------------------------------------------------
 StringTable* StringTable::_the_table = NULL;
-
+bool StringTable::_ignore_shared_strings = false;
 bool StringTable::_needs_rehashing = false;
 
 volatile int StringTable::_parallel_claimed_idx = 0;
 
+CompactHashtable<oop, char> StringTable::_shared_table;
+
 // Pick hashing algorithm
 unsigned int StringTable::hash_string(const jchar* s, int len) {
   return use_alternate_hashcode() ? AltHashing::murmur3_32(seed(), s, len) :
                                     java_lang_String::hash_code(s, len);
 }
 
-oop StringTable::lookup(int index, jchar* name,
-                        int len, unsigned int hash) {
+oop StringTable::lookup_shared(jchar* name, int len) {
+  // java_lang_String::hash_code() was used to compute hash values in the shared table. Don't
+  // use the hash value from StringTable::hash_string() as it might use alternate hashcode.
+  return _shared_table.lookup((const char*)name,
+                              java_lang_String::hash_code(name, len), len);
+}
+
+oop StringTable::lookup_in_main_table(int index, jchar* name,
+                                int len, unsigned int hash) {
   int count = 0;
   for (HashtableEntry<oop, mtSymbol>* l = bucket(index); l != NULL; l = l->next()) {
     count++;
@@ -140,7 +150,8 @@
   // Since look-up was done lock-free, we need to check if another
   // thread beat us in the race to insert the symbol.
 
-  oop test = lookup(index, name, len, hashValue); // calls lookup(u1*, int)
+  // No need to lookup the shared table from here since the caller (intern()) already did
+  oop test = lookup_in_main_table(index, name, len, hashValue); // calls lookup(u1*, int)
   if (test != NULL) {
     // Entry already added
     return test;
@@ -172,9 +183,14 @@
 }
 
 oop StringTable::lookup(jchar* name, int len) {
+  oop string = lookup_shared(name, len);
+  if (string != NULL) {
+    return string;
+  }
+
   unsigned int hash = hash_string(name, len);
   int index = the_table()->hash_to_index(hash);
-  oop string = the_table()->lookup(index, name, len, hash);
+  string = the_table()->lookup_in_main_table(index, name, len, hash);
 
   ensure_string_alive(string);
 
@@ -184,9 +200,14 @@
 
 oop StringTable::intern(Handle string_or_null, jchar* name,
                         int len, TRAPS) {
+  oop found_string = lookup_shared(name, len);
+  if (found_string != NULL) {
+    return found_string;
+  }
+
   unsigned int hashValue = hash_string(name, len);
   int index = the_table()->hash_to_index(hashValue);
-  oop found_string = the_table()->lookup(index, name, len, hashValue);
+  found_string = the_table()->lookup_in_main_table(index, name, len, hashValue);
 
   // Found
   if (found_string != NULL) {
@@ -611,3 +632,131 @@
     return 0;
   }
 }
+
+// Sharing
+bool StringTable::copy_shared_string(GrowableArray<MemRegion> *string_space,
+                                     CompactHashtableWriter* ch_table) {
+#if INCLUDE_CDS && INCLUDE_ALL_GCS && defined(_LP64) && !defined(_WINDOWS)
+  assert(UseG1GC, "Only support G1 GC");
+  assert(UseCompressedOops && UseCompressedClassPointers,
+         "Only support UseCompressedOops and UseCompressedClassPointers enabled");
+
+  Thread* THREAD = Thread::current();
+  G1CollectedHeap::heap()->begin_archive_alloc_range();
+  for (int i = 0; i < the_table()->table_size(); ++i) {
+    HashtableEntry<oop, mtSymbol>* bucket = the_table()->bucket(i);
+    for ( ; bucket != NULL; bucket = bucket->next()) {
+      oop s = bucket->literal();
+      unsigned int hash = java_lang_String::hash_code(s);
+      if (hash == 0) {
+        continue;
+      }
+
+      // allocate the new 'value' array first
+      typeArrayOop v = java_lang_String::value(s);
+      int v_len = v->size();
+      typeArrayOop new_v;
+      if (G1CollectedHeap::heap()->is_archive_alloc_too_large(v_len)) {
+        continue; // skip the current String. The 'value' array is too large to handle
+      } else {
+        new_v = (typeArrayOop)G1CollectedHeap::heap()->archive_mem_allocate(v_len);
+        if (new_v == NULL) {
+          return false; // allocation failed
+        }
+      }
+      // now allocate the new String object
+      int s_len = s->size();
+      oop new_s = (oop)G1CollectedHeap::heap()->archive_mem_allocate(s_len);
+      if (new_s == NULL) {
+        return false;
+      }
+
+      s->identity_hash();
+      v->identity_hash();
+
+      // copy the objects' data
+      Copy::aligned_disjoint_words((HeapWord*)s, (HeapWord*)new_s, s_len);
+      Copy::aligned_disjoint_words((HeapWord*)v, (HeapWord*)new_v, v_len);
+
+      // adjust the pointer to the 'value' field in the new String oop. Also pre-compute and set the
+      // 'hash' field. That avoids "write" to the shared strings at runtime by the deduplication process.
+      java_lang_String::set_value_raw(new_s, new_v);
+      if (java_lang_String::hash(new_s) == 0) {
+        java_lang_String::set_hash(new_s, hash);
+      }
+
+      // add to the compact table
+      ch_table->add(hash, new_s);
+    }
+  }
+
+  G1CollectedHeap::heap()->end_archive_alloc_range(string_space, os::vm_allocation_granularity());
+  assert(string_space->length() <= 2, "sanity");
+#endif
+  return true;
+}
+
+bool StringTable::copy_compact_table(char** top, char *end, GrowableArray<MemRegion> *string_space,
+                                     size_t* space_size) {
+#if INCLUDE_CDS && defined(_LP64) && !defined(_WINDOWS)
+  if (!(UseG1GC && UseCompressedOops && UseCompressedClassPointers)) {
+    if (PrintSharedSpaces) {
+      tty->print_cr("Shared strings are excluded from the archive as UseG1GC, "
+                    "UseCompressedOops and UseCompressedClassPointers are required.");
+    }
+    return true;
+  }
+
+  CompactHashtableWriter ch_table(CompactHashtable<oop, char>::_string_table,
+                                  the_table()->number_of_entries(),
+                                  &MetaspaceShared::stats()->string);
+
+  // Copy the interned strings into the "string space" within the java heap
+  if (!copy_shared_string(string_space, &ch_table)) {
+    return false;
+  }
+
+  for (int i = 0; i < string_space->length(); i++) {
+    *space_size += string_space->at(i).byte_size();
+  }
+
+  // Now dump the compact table
+  if (*top + ch_table.get_required_bytes() > end) {
+    // not enough space left
+    return false;
+  }
+  ch_table.dump(top, end);
+  *top = (char*)align_pointer_up(*top, sizeof(void*));
+
+#endif
+  return true;
+}
+
+void StringTable::shared_oops_do(OopClosure* f) {
+#if INCLUDE_CDS && defined(_LP64) && !defined(_WINDOWS)
+  _shared_table.oops_do(f);
+#endif
+}
+
+const char* StringTable::init_shared_table(FileMapInfo *mapinfo, char *buffer) {
+#if INCLUDE_CDS && defined(_LP64) && !defined(_WINDOWS)
+  if (mapinfo->space_capacity(MetaspaceShared::first_string) == 0) {
+    // no shared string data
+    return buffer;
+  }
+
+  // initialize the shared table
+  juint *p = (juint*)buffer;
+  const char* end = _shared_table.init(
+          CompactHashtable<oop, char>::_string_table, (char*)p);
+  const char* aligned_end = (const char*)align_pointer_up(end, sizeof(void*));
+
+  if (_ignore_shared_strings) {
+    _shared_table.reset();
+  }
+
+  return aligned_end;
+#endif
+
+  return buffer;
+}
--- a/hotspot/src/share/vm/classfile/stringTable.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/classfile/stringTable.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, 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
@@ -28,6 +28,10 @@
 #include "memory/allocation.inline.hpp"
 #include "utilities/hashtable.hpp"
 
+template <class T, class N> class CompactHashtable;
+class CompactHashtableWriter;
+class FileMapInfo;
+
 class StringTable : public RehashableHashtable<oop, mtSymbol> {
   friend class VMStructs;
   friend class Symbol;
@@ -36,6 +40,10 @@
   // The string table
   static StringTable* _the_table;
 
+  // Shared string table
+  static CompactHashtable<oop, char> _shared_table;
+  static bool _ignore_shared_strings;
+
   // Set if one bucket is out of balance due to hash algorithm deficiency
   static bool _needs_rehashing;
 
@@ -46,7 +54,8 @@
   oop basic_add(int index, Handle string_or_null, jchar* name, int len,
                 unsigned int hashValue, TRAPS);
 
-  oop lookup(int index, jchar* chars, int length, unsigned int hashValue);
+  oop lookup_in_main_table(int index, jchar* chars, int length, unsigned int hashValue);
+  static oop lookup_shared(jchar* name, int len);
 
   // Apply the give oop closure to the entries to the buckets
   // in the range [start_idx, end_idx).
@@ -141,12 +150,14 @@
   static int verify_and_compare_entries();
 
   // Sharing
-  static void copy_buckets(char** top, char*end) {
-    the_table()->Hashtable<oop, mtSymbol>::copy_buckets(top, end);
-  }
-  static void copy_table(char** top, char*end) {
-    the_table()->Hashtable<oop, mtSymbol>::copy_table(top, end);
-  }
+  static void ignore_shared_strings(bool v) { _ignore_shared_strings = v; }
+  static bool shared_string_ignored()       { return _ignore_shared_strings; }
+  static void shared_oops_do(OopClosure* f);
+  static bool copy_shared_string(GrowableArray<MemRegion> *string_space,
+                                 CompactHashtableWriter* ch_table);
+  static bool copy_compact_table(char** top, char* end, GrowableArray<MemRegion> *string_space,
+                                 size_t* space_size);
+  static const char* init_shared_table(FileMapInfo *mapinfo, char* buffer);
   static void reverse() {
     the_table()->Hashtable<oop, mtSymbol>::reverse();
   }
--- a/hotspot/src/share/vm/classfile/symbolTable.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/classfile/symbolTable.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -539,7 +539,8 @@
 
 bool SymbolTable::copy_compact_table(char** top, char*end) {
 #if INCLUDE_CDS
-  CompactHashtableWriter ch_table("symbol", the_table()->number_of_entries(),
+  CompactHashtableWriter ch_table(CompactHashtable<Symbol*, char>::_symbol_table,
+                                  the_table()->number_of_entries(),
                                   &MetaspaceShared::stats()->symbol);
   if (*top + ch_table.get_required_bytes() > end) {
     // not enough space left
@@ -556,7 +557,6 @@
     }
   }
 
-  char* old_top = *top;
   ch_table.dump(top, end);
 
   *top = (char*)align_pointer_up(*top, sizeof(void*));
@@ -565,7 +565,8 @@
 }
 
 const char* SymbolTable::init_shared_table(const char* buffer) {
-  const char* end = _shared_table.init(buffer);
+  const char* end = _shared_table.init(
+          CompactHashtable<Symbol*, char>::_symbol_table, buffer);
   return (const char*)align_pointer_up(end, sizeof(void*));
 }
 
--- a/hotspot/src/share/vm/code/codeCache.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/code/codeCache.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -190,7 +190,12 @@
   static void set_needs_cache_clean(bool v)           { _needs_cache_clean = v;    }
   static void clear_inline_caches();                  // clear all inline caches
 
-  // Returns the CodeBlobType for nmethods of the given compilation level
+  // Returns the CodeBlobType for the given nmethod
+  static int get_code_blob_type(nmethod* nm) {
+    return get_code_heap(nm)->code_blob_type();
+  }
+
+  // Returns the CodeBlobType for the given compilation level
   static int get_code_blob_type(int comp_level) {
     if (comp_level == CompLevel_none ||
         comp_level == CompLevel_simple ||
@@ -287,7 +292,7 @@
       // Iterate over all CodeBlobs
       _code_blob_type = CodeBlobType::All;
     } else if (nm != NULL) {
-      _code_blob_type = CodeCache::get_code_blob_type(nm->comp_level());
+      _code_blob_type = CodeCache::get_code_blob_type(nm);
     } else {
       // Only iterate over method code heaps, starting with non-profiled
       _code_blob_type = CodeBlobType::MethodNonProfiled;
--- a/hotspot/src/share/vm/code/nmethod.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/code/nmethod.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -1421,7 +1421,7 @@
   Events::log(JavaThread::current(), "flushing nmethod " INTPTR_FORMAT, this);
   if (PrintMethodFlushing) {
     tty->print_cr("*flushing nmethod %3d/" INTPTR_FORMAT ". Live blobs:" UINT32_FORMAT "/Free CodeCache:" SIZE_FORMAT "Kb",
-        _compile_id, this, CodeCache::nof_blobs(), CodeCache::unallocated_capacity(CodeCache::get_code_blob_type(_comp_level))/1024);
+        _compile_id, this, CodeCache::nof_blobs(), CodeCache::unallocated_capacity(CodeCache::get_code_blob_type(this))/1024);
   }
 
   // We need to deallocate any ExceptionCache data.
--- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -190,10 +190,10 @@
 };
 
 ConcurrentMarkSweepGeneration::ConcurrentMarkSweepGeneration(
-     ReservedSpace rs, size_t initial_byte_size, int level,
+     ReservedSpace rs, size_t initial_byte_size,
      CardTableRS* ct, bool use_adaptive_freelists,
      FreeBlockDictionary<FreeChunk>::DictionaryChoice dictionaryChoice) :
-  CardGeneration(rs, initial_byte_size, level, ct),
+  CardGeneration(rs, initial_byte_size, ct),
   _dilatation_factor(((double)MinChunkSize)/((double)(CollectedHeap::min_fill_size()))),
   _did_compact(false)
 {
@@ -285,9 +285,9 @@
     _ref_processor =
       new ReferenceProcessor(_span,                               // span
                              (ParallelGCThreads > 1) && ParallelRefProcEnabled, // mt processing
-                             (int) ParallelGCThreads,             // mt processing degree
+                             ParallelGCThreads,                   // mt processing degree
                              _cmsGen->refs_discovery_is_mt(),     // mt discovery
-                             (int) MAX2(ConcGCThreads, ParallelGCThreads), // mt discovery degree
+                             MAX2(ConcGCThreads, ParallelGCThreads), // mt discovery degree
                              _cmsGen->refs_discovery_is_atomic(), // discovery is not atomic
                              &_is_alive_closure);                 // closure for liveness info
     // Initialize the _ref_processor field of CMSGen
@@ -562,7 +562,7 @@
   // are not shared with parallel scavenge (ParNew).
   {
     uint i;
-    uint num_queues = (uint) MAX2(ParallelGCThreads, ConcGCThreads);
+    uint num_queues = MAX2(ParallelGCThreads, ConcGCThreads);
 
     if ((CMSParallelRemarkEnabled || CMSConcurrentMTEnabled
          || ParallelRefProcEnabled)
@@ -682,12 +682,17 @@
 void ConcurrentMarkSweepGeneration::printOccupancy(const char *s) {
   GenCollectedHeap* gch = GenCollectedHeap::heap();
   if (PrintGCDetails) {
+    // I didn't want to change the logging when removing the level concept,
+    // but I guess this logging could say "old" or something instead of "1".
+    assert(gch->is_old_gen(this),
+           "The CMS generation should be the old generation");
+    uint level = 1;
     if (Verbose) {
-      gclog_or_tty->print("[%d %s-%s: "SIZE_FORMAT"("SIZE_FORMAT")]",
-        level(), short_name(), s, used(), capacity());
+      gclog_or_tty->print("[%u %s-%s: "SIZE_FORMAT"("SIZE_FORMAT")]",
+        level, short_name(), s, used(), capacity());
     } else {
-      gclog_or_tty->print("[%d %s-%s: "SIZE_FORMAT"K("SIZE_FORMAT"K)]",
-        level(), short_name(), s, used() / K, capacity() / K);
+      gclog_or_tty->print("[%u %s-%s: "SIZE_FORMAT"K("SIZE_FORMAT"K)]",
+        level, short_name(), s, used() / K, capacity() / K);
     }
   }
   if (Verbose) {
@@ -797,27 +802,22 @@
       gclog_or_tty->print_cr("\nFrom compute_new_size: ");
       gclog_or_tty->print_cr("  Free fraction %f", free_percentage);
       gclog_or_tty->print_cr("  Desired free fraction %f",
-        desired_free_percentage);
+              desired_free_percentage);
       gclog_or_tty->print_cr("  Maximum free fraction %f",
-        maximum_free_percentage);
+              maximum_free_percentage);
       gclog_or_tty->print_cr("  Capacity "SIZE_FORMAT, capacity()/1000);
       gclog_or_tty->print_cr("  Desired capacity "SIZE_FORMAT,
-        desired_capacity/1000);
-      int prev_level = level() - 1;
-      if (prev_level >= 0) {
-        size_t prev_size = 0;
-        GenCollectedHeap* gch = GenCollectedHeap::heap();
-        Generation* prev_gen = gch->young_gen();
-        prev_size = prev_gen->capacity();
-          gclog_or_tty->print_cr("  Younger gen size "SIZE_FORMAT,
-                                 prev_size/1000);
-      }
+              desired_capacity/1000);
+      GenCollectedHeap* gch = GenCollectedHeap::heap();
+      assert(gch->is_old_gen(this), "The CMS generation should always be the old generation");
+      size_t young_size = gch->young_gen()->capacity();
+      gclog_or_tty->print_cr("  Young gen size " SIZE_FORMAT, young_size / 1000);
       gclog_or_tty->print_cr("  unsafe_max_alloc_nogc "SIZE_FORMAT,
-        unsafe_max_alloc_nogc()/1000);
+              unsafe_max_alloc_nogc()/1000);
       gclog_or_tty->print_cr("  contiguous available "SIZE_FORMAT,
-        contiguous_available()/1000);
+              contiguous_available()/1000);
       gclog_or_tty->print_cr("  Expand by "SIZE_FORMAT" (bytes)",
-        expand_bytes);
+              expand_bytes);
     }
     // safe if expansion fails
     expand_for_gc_cause(expand_bytes, 0, CMSExpansionCause::_satisfy_free_ratio);
@@ -1650,8 +1650,7 @@
                                             _intra_sweep_estimate.padded_average());
   }
 
-  GenMarkSweep::invoke_at_safepoint(_cmsGen->level(),
-    ref_processor(), clear_all_soft_refs);
+  GenMarkSweep::invoke_at_safepoint(ref_processor(), clear_all_soft_refs);
   #ifdef ASSERT
     CompactibleFreeListSpace* cms_space = _cmsGen->cmsSpace();
     size_t free_size = cms_space->free();
@@ -2432,7 +2431,7 @@
     StrongRootsScope srs(1);
 
     gch->gen_process_roots(&srs,
-                           _cmsGen->level(),
+                           GenCollectedHeap::OldGen,
                            true,   // younger gens are roots
                            GenCollectedHeap::ScanningOption(roots_scanning_options()),
                            should_unload_classes(),
@@ -2504,7 +2503,7 @@
     StrongRootsScope srs(1);
 
     gch->gen_process_roots(&srs,
-                           _cmsGen->level(),
+                           GenCollectedHeap::OldGen,
                            true,   // younger gens are roots
                            GenCollectedHeap::ScanningOption(roots_scanning_options()),
                            should_unload_classes(),
@@ -3031,7 +3030,7 @@
       StrongRootsScope srs(1);
 
       gch->gen_process_roots(&srs,
-                             _cmsGen->level(),
+                             GenCollectedHeap::OldGen,
                              true,   // younger gens are roots
                              GenCollectedHeap::ScanningOption(roots_scanning_options()),
                              should_unload_classes(),
@@ -4282,15 +4281,12 @@
       FlagSetting fl(gch->_is_gc_active, false);
       NOT_PRODUCT(GCTraceTime t("Scavenge-Before-Remark",
         PrintGCDetails && Verbose, true, _gc_timer_cm, _gc_tracer_cm->gc_id());)
-      int level = _cmsGen->level() - 1;
-      if (level >= 0) {
-        gch->do_collection(true,        // full (i.e. force, see below)
-                           false,       // !clear_all_soft_refs
-                           0,           // size
-                           false,       // is_tlab
-                           level        // max_level
-                          );
-      }
+      gch->do_collection(true,                      // full (i.e. force, see below)
+                         false,                     // !clear_all_soft_refs
+                         0,                         // size
+                         false,                     // is_tlab
+                         GenCollectedHeap::YoungGen // type
+        );
     }
     FreelistLocker x(this);
     MutexLockerEx y(bitMapLock(),
@@ -4464,7 +4460,7 @@
   CLDToOopClosure cld_closure(&par_mri_cl, true);
 
   gch->gen_process_roots(_strong_roots_scope,
-                         _collector->_cmsGen->level(),
+                         GenCollectedHeap::OldGen,
                          false,     // yg was scanned above
                          GenCollectedHeap::ScanningOption(_collector->CMSCollector::roots_scanning_options()),
                          _collector->should_unload_classes(),
@@ -4603,7 +4599,7 @@
   _timer.reset();
   _timer.start();
   gch->gen_process_roots(_strong_roots_scope,
-                         _collector->_cmsGen->level(),
+                         GenCollectedHeap::OldGen,
                          false,     // yg was scanned above
                          GenCollectedHeap::ScanningOption(_collector->CMSCollector::roots_scanning_options()),
                          _collector->should_unload_classes(),
@@ -5184,7 +5180,7 @@
     StrongRootsScope srs(1);
 
     gch->gen_process_roots(&srs,
-                           _cmsGen->level(),
+                           GenCollectedHeap::OldGen,
                            true,  // younger gens as roots
                            GenCollectedHeap::ScanningOption(roots_scanning_options()),
                            should_unload_classes(),
@@ -5322,8 +5318,8 @@
    _bit_map(bit_map),
    _work_queue(work_queue),
    _mark_and_push(collector, span, bit_map, work_queue),
-   _low_water_mark(MIN2((uint)(work_queue->max_elems()/4),
-                        (uint)(CMSWorkQueueDrainThreshold * ParallelGCThreads)))
+   _low_water_mark(MIN2((work_queue->max_elems()/4),
+                        ((uint)CMSWorkQueueDrainThreshold * ParallelGCThreads)))
 { }
 
 // . see if we can share work_queues with ParNew? XXX
@@ -5648,11 +5644,12 @@
   return _cmsSpace->find_chunk_at_end();
 }
 
-void ConcurrentMarkSweepGeneration::update_gc_stats(int current_level,
+void ConcurrentMarkSweepGeneration::update_gc_stats(Generation* current_generation,
                                                     bool full) {
-  // The next lower level has been collected.  Gather any statistics
+  // If the young generation has been collected, gather any statistics
   // that are of interest at this point.
-  if (!full && (current_level + 1) == level()) {
+  bool current_is_young = GenCollectedHeap::heap()->is_young_gen(current_generation);
+  if (!full && current_is_young) {
     // Gather statistics on the young generation collection.
     collector()->stats().record_gc0_end(used());
   }
@@ -6251,8 +6248,8 @@
   _span(span),
   _bit_map(bit_map),
   _work_queue(work_queue),
-  _low_water_mark(MIN2((uint)(work_queue->max_elems()/4),
-                       (uint)(CMSWorkQueueDrainThreshold * ParallelGCThreads))),
+  _low_water_mark(MIN2((work_queue->max_elems()/4),
+                       ((uint)CMSWorkQueueDrainThreshold * ParallelGCThreads))),
   _par_pushAndMarkClosure(collector, span, rp, bit_map, work_queue)
 {
   _ref_processor = rp;
--- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -1063,7 +1063,7 @@
   void shrink_free_list_by(size_t bytes);
 
   // Update statistics for GC
-  virtual void update_gc_stats(int level, bool full);
+  virtual void update_gc_stats(Generation* current_generation, bool full);
 
   // Maximum available space in the generation (including uncommitted)
   // space.
@@ -1079,7 +1079,7 @@
 
  public:
   ConcurrentMarkSweepGeneration(ReservedSpace rs, size_t initial_byte_size,
-                                int level, CardTableRS* ct,
+                                CardTableRS* ct,
                                 bool use_adaptive_freelists,
                                 FreeBlockDictionary<FreeChunk>::DictionaryChoice);
 
--- a/hotspot/src/share/vm/gc/cms/parCardTableModRefBS.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/cms/parCardTableModRefBS.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -42,7 +42,7 @@
                                                              uint n_threads) {
   assert(n_threads > 0, "expected n_threads > 0");
   assert(n_threads <= ParallelGCThreads,
-         err_msg("n_threads: %u > ParallelGCThreads: " UINTX_FORMAT, n_threads, ParallelGCThreads));
+         err_msg("n_threads: %u > ParallelGCThreads: %u", n_threads, ParallelGCThreads));
 
   // Make sure the LNC array is valid for the space.
   jbyte**   lowest_non_clean;
--- a/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -62,25 +62,25 @@
 #pragma warning( disable:4355 ) // 'this' : used in base member initializer list
 #endif
 ParScanThreadState::ParScanThreadState(Space* to_space_,
-                                       ParNewGeneration* gen_,
+                                       ParNewGeneration* young_gen_,
                                        Generation* old_gen_,
                                        int thread_num_,
                                        ObjToScanQueueSet* work_queue_set_,
                                        Stack<oop, mtGC>* overflow_stacks_,
                                        size_t desired_plab_sz_,
                                        ParallelTaskTerminator& term_) :
-  _to_space(to_space_), _old_gen(old_gen_), _young_gen(gen_), _thread_num(thread_num_),
+  _to_space(to_space_), _old_gen(old_gen_), _young_gen(young_gen_), _thread_num(thread_num_),
   _work_queue(work_queue_set_->queue(thread_num_)), _to_space_full(false),
   _overflow_stack(overflow_stacks_ ? overflow_stacks_ + thread_num_ : NULL),
   _ageTable(false), // false ==> not the global age table, no perf data.
   _to_space_alloc_buffer(desired_plab_sz_),
-  _to_space_closure(gen_, this), _old_gen_closure(gen_, this),
-  _to_space_root_closure(gen_, this), _old_gen_root_closure(gen_, this),
-  _older_gen_closure(gen_, this),
+  _to_space_closure(young_gen_, this), _old_gen_closure(young_gen_, this),
+  _to_space_root_closure(young_gen_, this), _old_gen_root_closure(young_gen_, this),
+  _older_gen_closure(young_gen_, this),
   _evacuate_followers(this, &_to_space_closure, &_old_gen_closure,
-                      &_to_space_root_closure, gen_, &_old_gen_root_closure,
+                      &_to_space_root_closure, young_gen_, &_old_gen_root_closure,
                       work_queue_set_, &term_),
-  _is_alive_closure(gen_), _scan_weak_ref_closure(gen_, this),
+  _is_alive_closure(young_gen_), _scan_weak_ref_closure(young_gen_, this),
   _keep_alive_closure(&_scan_weak_ref_closure),
   _strong_roots_time(0.0), _term_time(0.0)
 {
@@ -481,7 +481,6 @@
                                ParScanThreadState* par_scan_state) :
   OopsInKlassOrGenClosure(g), _par_scan_state(par_scan_state), _g(g)
 {
-  assert(_g->level() == 0, "Optimized for youngest generation");
   _boundary = _g->reserved().end();
 }
 
@@ -566,11 +565,11 @@
   par_scan_state()->end_term_time();
 }
 
-ParNewGenTask::ParNewGenTask(ParNewGeneration* gen, Generation* old_gen,
+ParNewGenTask::ParNewGenTask(ParNewGeneration* young_gen, Generation* old_gen,
                              HeapWord* young_old_boundary, ParScanThreadStateSet* state_set,
                              StrongRootsScope* strong_roots_scope) :
     AbstractGangTask("ParNewGeneration collection"),
-    _gen(gen), _old_gen(old_gen),
+    _young_gen(young_gen), _old_gen(old_gen),
     _young_old_boundary(young_old_boundary),
     _state_set(state_set),
     _strong_roots_scope(strong_roots_scope)
@@ -596,7 +595,7 @@
 
   par_scan_state.start_strong_roots();
   gch->gen_process_roots(_strong_roots_scope,
-                         _gen->level(),
+                         GenCollectedHeap::YoungGen,
                          true,  // Process younger gens, if any,
                                 // as strong roots.
                          GenCollectedHeap::SO_ScavengeCodeCache,
@@ -616,8 +615,8 @@
 #pragma warning( disable:4355 ) // 'this' : used in base member initializer list
 #endif
 ParNewGeneration::
-ParNewGeneration(ReservedSpace rs, size_t initial_byte_size, int level)
-  : DefNewGeneration(rs, initial_byte_size, level, "PCopy"),
+ParNewGeneration(ReservedSpace rs, size_t initial_byte_size)
+  : DefNewGeneration(rs, initial_byte_size, "PCopy"),
   _overflow_list(NULL),
   _is_alive_closure(this),
   _plab_stats(YoungPLABSize, PLABWeight)
@@ -752,7 +751,7 @@
 private:
   virtual void work(uint worker_id);
 private:
-  ParNewGeneration&      _gen;
+  ParNewGeneration&      _young_gen;
   ProcessTask&           _task;
   Generation&            _old_gen;
   HeapWord*              _young_old_boundary;
@@ -760,12 +759,12 @@
 };
 
 ParNewRefProcTaskProxy::ParNewRefProcTaskProxy(ProcessTask& task,
-                                               ParNewGeneration& gen,
+                                               ParNewGeneration& young_gen,
                                                Generation& old_gen,
                                                HeapWord* young_old_boundary,
                                                ParScanThreadStateSet& state_set)
   : AbstractGangTask("ParNewGeneration parallel reference processing"),
-    _gen(gen),
+    _young_gen(young_gen),
     _task(task),
     _old_gen(old_gen),
     _young_old_boundary(young_old_boundary),
@@ -806,12 +805,12 @@
   GenCollectedHeap* gch = GenCollectedHeap::heap();
   FlexibleWorkGang* workers = gch->workers();
   assert(workers != NULL, "Need parallel worker threads.");
-  _state_set.reset(workers->active_workers(), _generation.promotion_failed());
-  ParNewRefProcTaskProxy rp_task(task, _generation, *_generation.next_gen(),
-                                 _generation.reserved().end(), _state_set);
+  _state_set.reset(workers->active_workers(), _young_gen.promotion_failed());
+  ParNewRefProcTaskProxy rp_task(task, _young_gen, _old_gen,
+                                 _young_gen.reserved().end(), _state_set);
   workers->run_task(&rp_task);
   _state_set.reset(0 /* bad value in debug if not reset */,
-                   _generation.promotion_failed());
+                   _young_gen.promotion_failed());
 }
 
 void ParNewRefProcTaskExecutor::execute(EnqueueTask& task)
@@ -835,10 +834,10 @@
   ScanClosure(g, gc_barrier) {}
 
 EvacuateFollowersClosureGeneral::
-EvacuateFollowersClosureGeneral(GenCollectedHeap* gch, int level,
+EvacuateFollowersClosureGeneral(GenCollectedHeap* gch,
                                 OopsInGenClosure* cur,
                                 OopsInGenClosure* older) :
-  _gch(gch), _level(level),
+  _gch(gch),
   _scan_cur_or_nonheap(cur), _scan_older(older)
 {}
 
@@ -846,10 +845,10 @@
   do {
     // Beware: this call will lead to closure applications via virtual
     // calls.
-    _gch->oop_since_save_marks_iterate(_level,
+    _gch->oop_since_save_marks_iterate(GenCollectedHeap::YoungGen,
                                        _scan_cur_or_nonheap,
                                        _scan_older);
-  } while (!_gch->no_allocs_since_save_marks(_level));
+  } while (!_gch->no_allocs_since_save_marks(true /* include_young */));
 }
 
 
@@ -972,14 +971,14 @@
   ScanClosure               scan_without_gc_barrier(this, false);
   ScanClosureWithParBarrier scan_with_gc_barrier(this, true);
   set_promo_failure_scan_stack_closure(&scan_without_gc_barrier);
-  EvacuateFollowersClosureGeneral evacuate_followers(gch, _level,
+  EvacuateFollowersClosureGeneral evacuate_followers(gch,
     &scan_without_gc_barrier, &scan_with_gc_barrier);
   rp->setup_policy(clear_all_soft_refs);
   // Can  the mt_degree be set later (at run_task() time would be best)?
   rp->set_active_mt_degree(active_workers);
   ReferenceProcessorStats stats;
   if (rp->processing_is_mt()) {
-    ParNewRefProcTaskExecutor task_executor(*this, thread_state_set);
+    ParNewRefProcTaskExecutor task_executor(*this, *_old_gen, thread_state_set);
     stats = rp->process_discovered_references(&is_alive, &keep_alive,
                                               &evacuate_followers, &task_executor,
                                               _gc_timer, _gc_tracer.gc_id());
@@ -1045,7 +1044,7 @@
 
   rp->set_enqueuing_is_done(true);
   if (rp->processing_is_mt()) {
-    ParNewRefProcTaskExecutor task_executor(*this, thread_state_set);
+    ParNewRefProcTaskExecutor task_executor(*this, *_old_gen, thread_state_set);
     rp->enqueue_discovered_references(&task_executor);
   } else {
     rp->enqueue_discovered_references(NULL);
@@ -1349,7 +1348,7 @@
   oop prefix = cast_to_oop(Atomic::xchg_ptr(BUSY, &_overflow_list));
   // Trim off a prefix of at most objsFromOverflow items
   Thread* tid = Thread::current();
-  size_t spin_count = (size_t)ParallelGCThreads;
+  size_t spin_count = ParallelGCThreads;
   size_t sleep_time_millis = MAX2((size_t)1, objsFromOverflow/100);
   for (size_t spin = 0; prefix == BUSY && spin < spin_count; spin++) {
     // someone grabbed it before we did ...
@@ -1466,9 +1465,9 @@
     _ref_processor =
       new ReferenceProcessor(_reserved,                  // span
                              ParallelRefProcEnabled && (ParallelGCThreads > 1), // mt processing
-                             (uint) ParallelGCThreads,   // mt processing degree
+                             ParallelGCThreads,          // mt processing degree
                              refs_discovery_is_mt(),     // mt discovery
-                             (uint) ParallelGCThreads,   // mt discovery degree
+                             ParallelGCThreads,          // mt discovery degree
                              refs_discovery_is_atomic(), // atomic_discovery
                              NULL);                      // is_alive_non_header
   }
--- a/hotspot/src/share/vm/gc/cms/parNewGeneration.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/cms/parNewGeneration.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -234,14 +234,14 @@
 
 class ParNewGenTask: public AbstractGangTask {
  private:
-  ParNewGeneration*            _gen;
+  ParNewGeneration*            _young_gen;
   Generation*                  _old_gen;
   HeapWord*                    _young_old_boundary;
   class ParScanThreadStateSet* _state_set;
   StrongRootsScope*            _strong_roots_scope;
 
 public:
-  ParNewGenTask(ParNewGeneration*      gen,
+  ParNewGenTask(ParNewGeneration*      young_gen,
                 Generation*            old_gen,
                 HeapWord*              young_old_boundary,
                 ParScanThreadStateSet* state_set,
@@ -264,11 +264,10 @@
 class EvacuateFollowersClosureGeneral: public VoidClosure {
  private:
   GenCollectedHeap* _gch;
-  int               _level;
   OopsInGenClosure* _scan_cur_or_nonheap;
   OopsInGenClosure* _scan_older;
  public:
-  EvacuateFollowersClosureGeneral(GenCollectedHeap* gch, int level,
+  EvacuateFollowersClosureGeneral(GenCollectedHeap* gch,
                                   OopsInGenClosure* cur,
                                   OopsInGenClosure* older);
   virtual void do_void();
@@ -288,12 +287,14 @@
 // Implements AbstractRefProcTaskExecutor for ParNew.
 class ParNewRefProcTaskExecutor: public AbstractRefProcTaskExecutor {
  private:
-  ParNewGeneration&      _generation;
+  ParNewGeneration&      _young_gen;
+  Generation&            _old_gen;
   ParScanThreadStateSet& _state_set;
  public:
-  ParNewRefProcTaskExecutor(ParNewGeneration& generation,
+  ParNewRefProcTaskExecutor(ParNewGeneration& young_gen,
+                            Generation& old_gen,
                             ParScanThreadStateSet& state_set)
-    : _generation(generation), _state_set(state_set)
+    : _young_gen(young_gen), _old_gen(old_gen), _state_set(state_set)
   { }
 
   // Executes a task using worker threads.
@@ -353,7 +354,7 @@
   void set_survivor_overflow(bool v) { _survivor_overflow = v; }
 
  public:
-  ParNewGeneration(ReservedSpace rs, size_t initial_byte_size, int level);
+  ParNewGeneration(ReservedSpace rs, size_t initial_byte_size);
 
   ~ParNewGeneration() {
     for (uint i = 0; i < ParallelGCThreads; i++)
--- a/hotspot/src/share/vm/gc/cms/parOopClosures.inline.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/cms/parOopClosures.inline.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -72,7 +72,7 @@
                                         bool root_scan) {
   assert((!GenCollectedHeap::heap()->is_in_reserved(p) ||
           generation()->is_in_reserved(p))
-         && (generation()->level() == 0 || gc_barrier),
+         && (GenCollectedHeap::heap()->is_young_gen(generation()) || gc_barrier),
          "The gen must be right, and we must be doing the barrier "
          "in older generations.");
   T heap_oop = oopDesc::load_heap_oop(p);
--- a/hotspot/src/share/vm/gc/cms/vmCMSOperations.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/cms/vmCMSOperations.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -198,8 +198,7 @@
     assert(SafepointSynchronize::is_at_safepoint(),
       "We can only be executing this arm of if at a safepoint");
     GCCauseSetter gccs(gch, _gc_cause);
-    gch->do_full_collection(gch->must_clear_all_soft_refs(),
-                            0 /* collect only youngest gen */);
+    gch->do_full_collection(gch->must_clear_all_soft_refs(), GenCollectedHeap::YoungGen);
   } // Else no need for a foreground young gc
   assert((_gc_count_before < gch->total_collections()) ||
          (GC_locker::is_active() /* gc may have been skipped */
--- a/hotspot/src/share/vm/gc/g1/collectionSetChooser.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/collectionSetChooser.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -107,7 +107,8 @@
     HeapRegion *curr = regions_at(index++);
     guarantee(curr != NULL, "Regions in _regions array cannot be NULL");
     guarantee(!curr->is_young(), "should not be young!");
-    guarantee(!curr->is_humongous(), "should not be humongous!");
+    guarantee(!curr->is_pinned(),
+              err_msg("Pinned region should not be in collection set (index %u)", curr->hrm_index()));
     if (prev != NULL) {
       guarantee(order_regions(prev, curr) != 1,
                 err_msg("GC eff prev: %1.4f GC eff curr: %1.4f",
@@ -149,8 +150,8 @@
 
 
 void CollectionSetChooser::add_region(HeapRegion* hr) {
-  assert(!hr->is_humongous(),
-         "Humongous regions shouldn't be added to the collection set");
+  assert(!hr->is_pinned(),
+         err_msg("Pinned region shouldn't be added to the collection set (index %u)", hr->hrm_index()));
   assert(!hr->is_young(), "should not be young!");
   _regions.append(hr);
   _length++;
--- a/hotspot/src/share/vm/gc/g1/collectionSetChooser.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/collectionSetChooser.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -103,13 +103,12 @@
   void sort_regions();
 
   // Determine whether to add the given region to the CSet chooser or
-  // not. Currently, we skip humongous regions (we never add them to
-  // the CSet, we only reclaim them during cleanup) and regions whose
-  // live bytes are over the threshold.
+  // not. Currently, we skip pinned regions and regions whose live
+  // bytes are over the threshold. Humongous regions may be reclaimed during cleanup.
   bool should_add(HeapRegion* hr) {
     assert(hr->is_marked(), "pre-condition");
     assert(!hr->is_young(), "should never consider young regions");
-    return !hr->is_humongous() &&
+    return !hr->is_pinned() &&
             hr->live_bytes() < _region_live_threshold_bytes;
   }
 
--- a/hotspot/src/share/vm/gc/g1/concurrentMark.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/concurrentMark.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -30,6 +30,7 @@
 #include "gc/g1/concurrentMarkThread.inline.hpp"
 #include "gc/g1/g1CollectedHeap.inline.hpp"
 #include "gc/g1/g1CollectorPolicy.hpp"
+#include "gc/g1/g1CollectorState.hpp"
 #include "gc/g1/g1ErgoVerbose.hpp"
 #include "gc/g1/g1Log.hpp"
 #include "gc/g1/g1OopClosures.inline.hpp"
@@ -177,7 +178,7 @@
       // will have them as guarantees at the beginning / end of the bitmap
       // clearing to get some checking in the product.
       assert(!_may_yield || _cm->cmThread()->during_cycle(), "invariant");
-      assert(!_may_yield || !G1CollectedHeap::heap()->mark_in_progress(), "invariant");
+      assert(!_may_yield || !G1CollectedHeap::heap()->collector_state()->mark_in_progress(), "invariant");
     }
 
     return false;
@@ -518,7 +519,7 @@
   _markStack(this),
   // _finger set in set_non_marking_state
 
-  _max_worker_id((uint)ParallelGCThreads),
+  _max_worker_id(ParallelGCThreads),
   // _active_tasks set in set_non_marking_state
   // _tasks set inside the constructor
   _task_queues(new CMTaskQueueSet((int) _max_worker_id)),
@@ -579,8 +580,8 @@
   _root_regions.init(_g1h, this);
 
   if (ConcGCThreads > ParallelGCThreads) {
-    warning("Can't have more ConcGCThreads (" UINTX_FORMAT ") "
-            "than ParallelGCThreads (" UINTX_FORMAT ").",
+    warning("Can't have more ConcGCThreads (%u) "
+            "than ParallelGCThreads (%u).",
             ConcGCThreads, ParallelGCThreads);
     return;
   }
@@ -604,20 +605,20 @@
     double sleep_factor =
                        (1.0 - marking_task_overhead) / marking_task_overhead;
 
-    FLAG_SET_ERGO(uintx, ConcGCThreads, (uint) marking_thread_num);
+    FLAG_SET_ERGO(uint, ConcGCThreads, (uint) marking_thread_num);
     _sleep_factor             = sleep_factor;
     _marking_task_overhead    = marking_task_overhead;
   } else {
     // Calculate the number of parallel marking threads by scaling
     // the number of parallel GC threads.
-    uint marking_thread_num = scale_parallel_threads((uint) ParallelGCThreads);
-    FLAG_SET_ERGO(uintx, ConcGCThreads, marking_thread_num);
+    uint marking_thread_num = scale_parallel_threads(ParallelGCThreads);
+    FLAG_SET_ERGO(uint, ConcGCThreads, marking_thread_num);
     _sleep_factor             = 0.0;
     _marking_task_overhead    = 1.0;
   }
 
   assert(ConcGCThreads > 0, "Should have been set");
-  _parallel_marking_threads = (uint) ConcGCThreads;
+  _parallel_marking_threads = ConcGCThreads;
   _max_parallel_marking_threads = _parallel_marking_threads;
 
   if (parallel_marking_threads() > 1) {
@@ -830,7 +831,7 @@
   // marking bitmap and getting it ready for the next cycle. During
   // this time no other cycle can start. So, let's make sure that this
   // is the case.
-  guarantee(!g1h->mark_in_progress(), "invariant");
+  guarantee(!g1h->collector_state()->mark_in_progress(), "invariant");
 
   ClearBitmapHRClosure cl(this, _nextMarkBitMap, true /* may_yield */);
   ParClearNextMarkBitmapTask task(&cl, parallel_marking_threads(), true);
@@ -844,7 +845,7 @@
 
   // Repeat the asserts from above.
   guarantee(cmThread()->during_cycle(), "invariant");
-  guarantee(!g1h->mark_in_progress(), "invariant");
+  guarantee(!g1h->collector_state()->mark_in_progress(), "invariant");
 }
 
 class CheckBitmapClearHRClosure : public HeapRegionClosure {
@@ -1178,6 +1179,8 @@
 };
 
 void ConcurrentMark::scanRootRegions() {
+  double scan_start = os::elapsedTime();
+
   // Start of concurrent marking.
   ClassLoaderDataGraph::clear_claimed_marks();
 
@@ -1185,6 +1188,11 @@
   // at least one root region to scan. So, if it's false, we
   // should not attempt to do any further work.
   if (root_regions()->scan_in_progress()) {
+    if (G1Log::fine()) {
+      gclog_or_tty->gclog_stamp(concurrent_gc_id());
+      gclog_or_tty->print_cr("[GC concurrent-root-region-scan-start]");
+    }
+
     _parallel_marking_threads = calc_parallel_marking_threads();
     assert(parallel_marking_threads() <= max_parallel_marking_threads(),
            "Maximum number of marking threads exceeded");
@@ -1194,6 +1202,11 @@
     _parallel_workers->set_active_workers(active_workers);
     _parallel_workers->run_task(&task);
 
+    if (G1Log::fine()) {
+      gclog_or_tty->gclog_stamp(concurrent_gc_id());
+      gclog_or_tty->print_cr("[GC concurrent-root-region-scan-end, %1.7lf secs]", os::elapsedTime() - scan_start);
+    }
+
     // It's possible that has_aborted() is true here without actually
     // aborting the survivor scan earlier. This is OK as it's
     // mainly used for sanity checking.
@@ -1254,7 +1267,7 @@
 
   // If a full collection has happened, we shouldn't do this.
   if (has_aborted()) {
-    g1h->set_marking_complete(); // So bitmap clearing isn't confused
+    g1h->collector_state()->set_mark_in_progress(false); // So bitmap clearing isn't confused
     return;
   }
 
@@ -1783,7 +1796,7 @@
   const HeapRegionSetCount& humongous_regions_removed() { return _humongous_regions_removed; }
 
   bool doHeapRegion(HeapRegion *hr) {
-    if (hr->is_continues_humongous()) {
+    if (hr->is_continues_humongous() || hr->is_archive()) {
       return false;
     }
     // We use a claim value of zero here because all regions
@@ -1888,7 +1901,7 @@
 
   // If a full collection has happened, we shouldn't do this.
   if (has_aborted()) {
-    g1h->set_marking_complete(); // So bitmap clearing isn't confused
+    g1h->collector_state()->set_mark_in_progress(false); // So bitmap clearing isn't confused
     return;
   }
 
@@ -1934,7 +1947,7 @@
   }
 
   size_t start_used_bytes = g1h->used();
-  g1h->set_marking_complete();
+  g1h->collector_state()->set_mark_in_progress(false);
 
   double count_end = os::elapsedTime();
   double this_final_counting_time = (count_end - start);
@@ -2756,7 +2769,7 @@
 
 void ConcurrentMark::verify_no_cset_oops() {
   assert(SafepointSynchronize::is_at_safepoint(), "should be at a safepoint");
-  if (!G1CollectedHeap::heap()->mark_in_progress()) {
+  if (!G1CollectedHeap::heap()->collector_state()->mark_in_progress()) {
     return;
   }
 
@@ -2992,6 +3005,11 @@
 
 // abandon current marking iteration due to a Full GC
 void ConcurrentMark::abort() {
+  if (!cmThread()->during_cycle() || _has_aborted) {
+    // We haven't started a concurrent cycle or we have already aborted it. No need to do anything.
+    return;
+  }
+
   // Clear all marks in the next bitmap for the next marking cycle. This will allow us to skip the next
   // concurrent bitmap clearing.
   _nextMarkBitMap->clearAll();
@@ -3009,12 +3027,8 @@
   }
   _first_overflow_barrier_sync.abort();
   _second_overflow_barrier_sync.abort();
-  const GCId& gc_id = _g1h->gc_tracer_cm()->gc_id();
-  if (!gc_id.is_undefined()) {
-    // We can do multiple full GCs before ConcurrentMarkThread::run() gets a chance
-    // to detect that it was aborted. Only keep track of the first GC id that we aborted.
-    _aborted_gc_id = gc_id;
-   }
+  _aborted_gc_id = _g1h->gc_tracer_cm()->gc_id();
+  assert(!_aborted_gc_id.is_undefined(), "ConcurrentMark::abort() executed more than once?");
   _has_aborted = true;
 
   SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set();
--- a/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -78,7 +78,19 @@
   }
 };
 
-
+// We want to avoid that the logging from the concurrent thread is mixed
+// with the logging from a STW GC. So, if necessary join the STS to ensure
+// that the logging is done either before or after the STW logging.
+void ConcurrentMarkThread::cm_log(bool doit, bool join_sts, const char* fmt, ...) {
+  if (doit) {
+    SuspendibleThreadSetJoiner sts_joiner(join_sts);
+    va_list args;
+    va_start(args, fmt);
+    gclog_or_tty->gclog_stamp(cm()->concurrent_gc_id());
+    gclog_or_tty->vprint_cr(fmt, args);
+    va_end(args);
+  }
+}
 
 void ConcurrentMarkThread::run() {
   initialize_in_thread();
@@ -110,28 +122,12 @@
       // without the root regions have been scanned which would be a
       // correctness issue.
 
-      double scan_start = os::elapsedTime();
       if (!cm()->has_aborted()) {
-        if (G1Log::fine()) {
-          gclog_or_tty->gclog_stamp(cm()->concurrent_gc_id());
-          gclog_or_tty->print_cr("[GC concurrent-root-region-scan-start]");
-        }
-
         _cm->scanRootRegions();
-
-        double scan_end = os::elapsedTime();
-        if (G1Log::fine()) {
-          gclog_or_tty->gclog_stamp(cm()->concurrent_gc_id());
-          gclog_or_tty->print_cr("[GC concurrent-root-region-scan-end, %1.7lf secs]",
-                                 scan_end - scan_start);
-        }
       }
 
       double mark_start_sec = os::elapsedTime();
-      if (G1Log::fine()) {
-        gclog_or_tty->gclog_stamp(cm()->concurrent_gc_id());
-        gclog_or_tty->print_cr("[GC concurrent-mark-start]");
-      }
+      cm_log(G1Log::fine(), true, "[GC concurrent-mark-start]");
 
       int iter = 0;
       do {
@@ -151,25 +147,15 @@
             os::sleep(current_thread, sleep_time_ms, false);
           }
 
-          if (G1Log::fine()) {
-            gclog_or_tty->gclog_stamp(cm()->concurrent_gc_id());
-            gclog_or_tty->print_cr("[GC concurrent-mark-end, %1.7lf secs]",
-                                      mark_end_sec - mark_start_sec);
-          }
+          cm_log(G1Log::fine(), true, "[GC concurrent-mark-end, %1.7lf secs]", mark_end_sec - mark_start_sec);
 
           CMCheckpointRootsFinalClosure final_cl(_cm);
           VM_CGC_Operation op(&final_cl, "GC remark", true /* needs_pll */);
           VMThread::execute(&op);
         }
         if (cm()->restart_for_overflow()) {
-          if (G1TraceMarkStackOverflow) {
-            gclog_or_tty->print_cr("Restarting conc marking because of MS overflow "
-                                   "in remark (restart #%d).", iter);
-          }
-          if (G1Log::fine()) {
-            gclog_or_tty->gclog_stamp(cm()->concurrent_gc_id());
-            gclog_or_tty->print_cr("[GC concurrent-mark-restart-for-overflow]");
-          }
+          cm_log(G1TraceMarkStackOverflow, true, "Restarting conc marking because of MS overflow in remark (restart #%d).", iter);
+          cm_log(G1Log::fine(), true, "[GC concurrent-mark-restart-for-overflow]");
         }
       } while (cm()->restart_for_overflow());
 
@@ -194,7 +180,7 @@
         // We don't want to update the marking status if a GC pause
         // is already underway.
         SuspendibleThreadSetJoiner sts_join;
-        g1h->set_marking_complete();
+        g1h->collector_state()->set_mark_in_progress(false);
       }
 
       // Check if cleanup set the free_regions_coming flag. If it
@@ -209,10 +195,7 @@
         // reclaimed by cleanup.
 
         double cleanup_start_sec = os::elapsedTime();
-        if (G1Log::fine()) {
-          gclog_or_tty->gclog_stamp(cm()->concurrent_gc_id());
-          gclog_or_tty->print_cr("[GC concurrent-cleanup-start]");
-        }
+        cm_log(G1Log::fine(), true, "[GC concurrent-cleanup-start]");
 
         // Now do the concurrent cleanup operation.
         _cm->completeCleanup();
@@ -229,11 +212,7 @@
         g1h->reset_free_regions_coming();
 
         double cleanup_end_sec = os::elapsedTime();
-        if (G1Log::fine()) {
-          gclog_or_tty->gclog_stamp(cm()->concurrent_gc_id());
-          gclog_or_tty->print_cr("[GC concurrent-cleanup-end, %1.7lf secs]",
-                                 cleanup_end_sec - cleanup_start_sec);
-        }
+        cm_log(G1Log::fine(), true, "[GC concurrent-cleanup-end, %1.7lf secs]", cleanup_end_sec - cleanup_start_sec);
       }
       guarantee(cm()->cleanup_list_is_empty(),
                 "at this point there should be no regions on the cleanup list");
@@ -266,13 +245,8 @@
         SuspendibleThreadSetJoiner sts_join;
         if (!cm()->has_aborted()) {
           g1_policy->record_concurrent_mark_cleanup_completed();
-        }
-      }
-
-      if (cm()->has_aborted()) {
-        if (G1Log::fine()) {
-          gclog_or_tty->gclog_stamp(cm()->concurrent_gc_id());
-          gclog_or_tty->print_cr("[GC concurrent-mark-abort]");
+        } else {
+          cm_log(G1Log::fine(), false, "[GC concurrent-mark-abort]");
         }
       }
 
--- a/hotspot/src/share/vm/gc/g1/concurrentMarkThread.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/concurrentMarkThread.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -40,6 +40,7 @@
   double _vtime_accum;  // Accumulated virtual time.
 
   double _vtime_mark_accum;
+  void cm_log(bool doit, bool join_sts, const char* fmt, ...) ATTRIBUTE_PRINTF(4, 5);
 
  public:
   virtual void run();
--- a/hotspot/src/share/vm/gc/g1/g1Allocator.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1Allocator.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -26,6 +26,7 @@
 #include "gc/g1/g1Allocator.hpp"
 #include "gc/g1/g1CollectedHeap.inline.hpp"
 #include "gc/g1/g1CollectorPolicy.hpp"
+#include "gc/g1/g1MarkSweep.hpp"
 #include "gc/g1/heapRegion.inline.hpp"
 #include "gc/g1/heapRegionSet.inline.hpp"
 
@@ -44,6 +45,8 @@
                                             HeapRegion** retained_old) {
   HeapRegion* retained_region = *retained_old;
   *retained_old = NULL;
+  assert(retained_region == NULL || !retained_region->is_archive(),
+         err_msg("Archive region should not be alloc region (index %u)", retained_region->hrm_index()));
 
   // We will discard the current GC alloc region if:
   // a) it's in the collection set (it can happen!),
@@ -65,7 +68,7 @@
     // we allocate to in the region sets. We'll re-add it later, when
     // it's retired again.
     _g1h->_old_set.remove(retained_region);
-    bool during_im = _g1h->g1_policy()->during_initial_mark_pause();
+    bool during_im = _g1h->collector_state()->during_initial_mark_pause();
     retained_region->note_start_of_copying(during_im);
     old->set(retained_region);
     _g1h->_hr_printer.reuse(retained_region);
@@ -168,3 +171,153 @@
     }
   }
 }
+
+G1ArchiveAllocator* G1ArchiveAllocator::create_allocator(G1CollectedHeap* g1h) {
+  // Create the archive allocator, and also enable archive object checking
+  // in mark-sweep, since we will be creating archive regions.
+  G1ArchiveAllocator* result =  new G1ArchiveAllocator(g1h);
+  G1MarkSweep::enable_archive_object_check();
+  return result;
+}
+
+bool G1ArchiveAllocator::alloc_new_region() {
+  // Allocate the highest free region in the reserved heap,
+  // and add it to our list of allocated regions. It is marked
+  // archive and added to the old set.
+  HeapRegion* hr = _g1h->alloc_highest_free_region();
+  if (hr == NULL) {
+    return false;
+  }
+  assert(hr->is_empty(), err_msg("expected empty region (index %u)", hr->hrm_index()));
+  hr->set_archive();
+  _g1h->_old_set.add(hr);
+  _g1h->_hr_printer.alloc(hr, G1HRPrinter::Archive);
+  _allocated_regions.append(hr);
+  _allocation_region = hr;
+
+  // Set up _bottom and _max to begin allocating in the lowest
+  // min_region_size'd chunk of the allocated G1 region.
+  _bottom = hr->bottom();
+  _max = _bottom + HeapRegion::min_region_size_in_words();
+
+  // Tell mark-sweep that objects in this region are not to be marked.
+  G1MarkSweep::mark_range_archive(MemRegion(_bottom, HeapRegion::GrainWords));
+
+  // Since we've modified the old set, call update_sizes.
+  _g1h->g1mm()->update_sizes();
+  return true;
+}
+
+HeapWord* G1ArchiveAllocator::archive_mem_allocate(size_t word_size) {
+  assert(word_size != 0, "size must not be zero");
+  if (_allocation_region == NULL) {
+    if (!alloc_new_region()) {
+      return NULL;
+    }
+  }
+  HeapWord* old_top = _allocation_region->top();
+  assert(_bottom >= _allocation_region->bottom(),
+         err_msg("inconsistent allocation state: " PTR_FORMAT " < " PTR_FORMAT,
+                 p2i(_bottom), p2i(_allocation_region->bottom())));
+  assert(_max <= _allocation_region->end(),
+         err_msg("inconsistent allocation state: " PTR_FORMAT " > " PTR_FORMAT,
+                 p2i(_max), p2i(_allocation_region->end())));
+  assert(_bottom <= old_top && old_top <= _max,
+         err_msg("inconsistent allocation state: expected "
+                 PTR_FORMAT " <= " PTR_FORMAT " <= " PTR_FORMAT,
+                 p2i(_bottom), p2i(old_top), p2i(_max)));
+
+  // Allocate the next word_size words in the current allocation chunk.
+  // If allocation would cross the _max boundary, insert a filler and begin
+  // at the base of the next min_region_size'd chunk. Also advance to the next
+  // chunk if we don't yet cross the boundary, but the remainder would be too
+  // small to fill.
+  HeapWord* new_top = old_top + word_size;
+  size_t remainder = pointer_delta(_max, new_top);
+  if ((new_top > _max) ||
+      ((new_top < _max) && (remainder < CollectedHeap::min_fill_size()))) {
+    if (old_top != _max) {
+      size_t fill_size = pointer_delta(_max, old_top);
+      CollectedHeap::fill_with_object(old_top, fill_size);
+      _summary_bytes_used += fill_size * HeapWordSize;
+    }
+    _allocation_region->set_top(_max);
+    old_top = _bottom = _max;
+
+    // Check if we've just used up the last min_region_size'd chunk
+    // in the current region, and if so, allocate a new one.
+    if (_bottom != _allocation_region->end()) {
+      _max = _bottom + HeapRegion::min_region_size_in_words();
+    } else {
+      if (!alloc_new_region()) {
+        return NULL;
+      }
+      old_top = _allocation_region->bottom();
+    }
+  }
+  _allocation_region->set_top(old_top + word_size);
+  _summary_bytes_used += word_size * HeapWordSize;
+
+  return old_top;
+}
+
+void G1ArchiveAllocator::complete_archive(GrowableArray<MemRegion>* ranges,
+                                          size_t end_alignment_in_bytes) {
+  assert((end_alignment_in_bytes >> LogHeapWordSize) < HeapRegion::min_region_size_in_words(),
+          err_msg("alignment " SIZE_FORMAT " too large", end_alignment_in_bytes));
+  assert(is_size_aligned(end_alignment_in_bytes, HeapWordSize),
+         err_msg("alignment " SIZE_FORMAT " is not HeapWord (%u) aligned", end_alignment_in_bytes, HeapWordSize));
+
+  // If we've allocated nothing, simply return.
+  if (_allocation_region == NULL) {
+    return;
+  }
+
+  // If an end alignment was requested, insert filler objects.
+  if (end_alignment_in_bytes != 0) {
+    HeapWord* currtop = _allocation_region->top();
+    HeapWord* newtop = (HeapWord*)align_pointer_up(currtop, end_alignment_in_bytes);
+    size_t fill_size = pointer_delta(newtop, currtop);
+    if (fill_size != 0) {
+      if (fill_size < CollectedHeap::min_fill_size()) {
+        // If the required fill is smaller than we can represent,
+        // bump up to the next aligned address. We know we won't exceed the current
+        // region boundary because the max supported alignment is smaller than the min
+        // region size, and because the allocation code never leaves space smaller than
+        // the min_fill_size at the top of the current allocation region.
+        newtop = (HeapWord*)align_pointer_up(currtop + CollectedHeap::min_fill_size(),
+                                             end_alignment_in_bytes);
+        fill_size = pointer_delta(newtop, currtop);
+      }
+      HeapWord* fill = archive_mem_allocate(fill_size);
+      CollectedHeap::fill_with_objects(fill, fill_size);
+    }
+  }
+
+  // Loop through the allocated regions, and create MemRegions summarizing
+  // the allocated address range, combining contiguous ranges. Add the
+  // MemRegions to the GrowableArray provided by the caller.
+  int index = _allocated_regions.length() - 1;
+  assert(_allocated_regions.at(index) == _allocation_region,
+         err_msg("expected region %u at end of array, found %u",
+                 _allocation_region->hrm_index(), _allocated_regions.at(index)->hrm_index()));
+  HeapWord* base_address = _allocation_region->bottom();
+  HeapWord* top = base_address;
+
+  while (index >= 0) {
+    HeapRegion* next = _allocated_regions.at(index);
+    HeapWord* new_base = next->bottom();
+    HeapWord* new_top = next->top();
+    if (new_base != top) {
+      ranges->append(MemRegion(base_address, pointer_delta(top, base_address)));
+      base_address = new_base;
+    }
+    top = new_top;
+    index = index - 1;
+  }
+
+  assert(top != base_address, err_msg("zero-sized range, address " PTR_FORMAT, p2i(base_address)));
+  ranges->append(MemRegion(base_address, pointer_delta(top, base_address)));
+  _allocated_regions.clear();
+  _allocation_region = NULL;
+};
--- a/hotspot/src/share/vm/gc/g1/g1Allocator.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1Allocator.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -227,7 +227,7 @@
                           size_t word_sz,
                           AllocationContext_t context) {
     G1PLAB* buffer = alloc_buffer(dest, context);
-    if (_survivor_alignment_bytes == 0) {
+    if (_survivor_alignment_bytes == 0 || !dest.is_young()) {
       return buffer->allocate(word_sz);
     } else {
       return buffer->allocate_aligned(word_sz, _survivor_alignment_bytes);
@@ -269,4 +269,72 @@
   virtual void waste(size_t& wasted, size_t& undo_wasted);
 };
 
+// G1ArchiveAllocator is used to allocate memory in archive
+// regions. Such regions are not modifiable by GC, being neither
+// scavenged nor compacted, or even marked in the object header.
+// They can contain no pointers to non-archive heap regions,
+class G1ArchiveAllocator : public CHeapObj<mtGC> {
+
+protected:
+  G1CollectedHeap* _g1h;
+
+  // The current allocation region
+  HeapRegion* _allocation_region;
+
+  // Regions allocated for the current archive range.
+  GrowableArray<HeapRegion*> _allocated_regions;
+
+  // The number of bytes used in the current range.
+  size_t _summary_bytes_used;
+
+  // Current allocation window within the current region.
+  HeapWord* _bottom;
+  HeapWord* _top;
+  HeapWord* _max;
+
+  // Allocate a new region for this archive allocator.
+  // Allocation is from the top of the reserved heap downward.
+  bool alloc_new_region();
+
+public:
+  G1ArchiveAllocator(G1CollectedHeap* g1h) :
+    _g1h(g1h),
+    _allocation_region(NULL),
+    _allocated_regions((ResourceObj::set_allocation_type((address) &_allocated_regions,
+                                                         ResourceObj::C_HEAP),
+                        2), true /* C_Heap */),
+    _summary_bytes_used(0),
+    _bottom(NULL),
+    _top(NULL),
+    _max(NULL) { }
+
+  virtual ~G1ArchiveAllocator() {
+    assert(_allocation_region == NULL, "_allocation_region not NULL");
+  }
+
+  static G1ArchiveAllocator* create_allocator(G1CollectedHeap* g1h);
+
+  // Allocate memory for an individual object.
+  HeapWord* archive_mem_allocate(size_t word_size);
+
+  // Return the memory ranges used in the current archive, after
+  // aligning to the requested alignment.
+  void complete_archive(GrowableArray<MemRegion>* ranges,
+                        size_t end_alignment_in_bytes);
+
+  // The number of bytes allocated by this allocator.
+  size_t used() {
+    return _summary_bytes_used;
+  }
+
+  // Clear the count of bytes allocated in prior G1 regions. This
+  // must be done when recalculate_use is used to reset the counter
+  // for the generic allocator, since it counts bytes in all G1
+  // regions, including those still associated with this allocator.
+  void clear_used() {
+    _summary_bytes_used = 0;
+  }
+
+};
+
 #endif // SHARE_VM_GC_G1_G1ALLOCATOR_HPP
--- a/hotspot/src/share/vm/gc/g1/g1BiasedArray.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1BiasedArray.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -26,6 +26,7 @@
 #define SHARE_VM_GC_G1_G1BIASEDARRAY_HPP
 
 #include "memory/allocation.hpp"
+#include "memory/memRegion.hpp"
 #include "utilities/debug.hpp"
 
 // Implements the common base functionality for arrays that contain provisions
@@ -128,6 +129,14 @@
     return biased_base()[biased_index];
   }
 
+  // Return the index of the element of the given array that covers the given
+  // word in the heap.
+  idx_t get_index_by_address(HeapWord* value) const {
+    idx_t biased_index = ((uintptr_t)value) >> this->shift_by();
+    this->verify_biased_index(biased_index);
+    return biased_index - _bias;
+  }
+
   // Set the value of the array entry that corresponds to the given array.
   void set_by_address(HeapWord * address, T value) {
     idx_t biased_index = ((uintptr_t)address) >> this->shift_by();
@@ -135,6 +144,18 @@
     biased_base()[biased_index] = value;
   }
 
+  // Set the value of all array entries that correspond to addresses
+  // in the specified MemRegion.
+  void set_by_address(MemRegion range, T value) {
+    idx_t biased_start = ((uintptr_t)range.start()) >> this->shift_by();
+    idx_t biased_last = ((uintptr_t)range.last()) >> this->shift_by();
+    this->verify_biased_index(biased_start);
+    this->verify_biased_index(biased_last);
+    for (idx_t i = biased_start; i <= biased_last; i++) {
+      biased_base()[i] = value;
+    }
+  }
+
 protected:
   // Returns the address of the element the given address maps to
   T* address_mapped_to(HeapWord* address) {
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -34,6 +34,7 @@
 #include "gc/g1/g1AllocRegion.inline.hpp"
 #include "gc/g1/g1CollectedHeap.inline.hpp"
 #include "gc/g1/g1CollectorPolicy.hpp"
+#include "gc/g1/g1CollectorState.hpp"
 #include "gc/g1/g1ErgoVerbose.hpp"
 #include "gc/g1/g1EvacFailure.hpp"
 #include "gc/g1/g1GCPhaseTimes.hpp"
@@ -404,7 +405,7 @@
 // can move in an incremental collection.
 bool G1CollectedHeap::is_scavengable(const void* p) {
   HeapRegion* hr = heap_region_containing(p);
-  return !hr->is_humongous();
+  return !hr->is_pinned();
 }
 
 // Private methods.
@@ -907,6 +908,207 @@
   return NULL;
 }
 
+void G1CollectedHeap::begin_archive_alloc_range() {
+  assert_at_safepoint(true /* should_be_vm_thread */);
+  if (_archive_allocator == NULL) {
+    _archive_allocator = G1ArchiveAllocator::create_allocator(this);
+  }
+}
+
+bool G1CollectedHeap::is_archive_alloc_too_large(size_t word_size) {
+  // Allocations in archive regions cannot be of a size that would be considered
+  // humongous even for a minimum-sized region, because G1 region sizes/boundaries
+  // may be different at archive-restore time.
+  return word_size >= humongous_threshold_for(HeapRegion::min_region_size_in_words());
+}
+
+HeapWord* G1CollectedHeap::archive_mem_allocate(size_t word_size) {
+  assert_at_safepoint(true /* should_be_vm_thread */);
+  assert(_archive_allocator != NULL, "_archive_allocator not initialized");
+  if (is_archive_alloc_too_large(word_size)) {
+    return NULL;
+  }
+  return _archive_allocator->archive_mem_allocate(word_size);
+}
+
+void G1CollectedHeap::end_archive_alloc_range(GrowableArray<MemRegion>* ranges,
+                                              size_t end_alignment_in_bytes) {
+  assert_at_safepoint(true /* should_be_vm_thread */);
+  assert(_archive_allocator != NULL, "_archive_allocator not initialized");
+
+  // Call complete_archive to do the real work, filling in the MemRegion
+  // array with the archive regions.
+  _archive_allocator->complete_archive(ranges, end_alignment_in_bytes);
+  delete _archive_allocator;
+  _archive_allocator = NULL;
+}
+
+bool G1CollectedHeap::check_archive_addresses(MemRegion* ranges, size_t count) {
+  assert(ranges != NULL, "MemRegion array NULL");
+  assert(count != 0, "No MemRegions provided");
+  MemRegion reserved = _hrm.reserved();
+  for (size_t i = 0; i < count; i++) {
+    if (!reserved.contains(ranges[i].start()) || !reserved.contains(ranges[i].last())) {
+      return false;
+    }
+  }
+  return true;
+}
+
+bool G1CollectedHeap::alloc_archive_regions(MemRegion* ranges, size_t count) {
+  assert(ranges != NULL, "MemRegion array NULL");
+  assert(count != 0, "No MemRegions provided");
+  MutexLockerEx x(Heap_lock);
+
+  MemRegion reserved = _hrm.reserved();
+  HeapWord* prev_last_addr = NULL;
+  HeapRegion* prev_last_region = NULL;
+
+  // Temporarily disable pretouching of heap pages. This interface is used
+  // when mmap'ing archived heap data in, so pre-touching is wasted.
+  FlagSetting fs(AlwaysPreTouch, false);
+
+  // Enable archive object checking in G1MarkSweep. We have to let it know
+  // about each archive range, so that objects in those ranges aren't marked.
+  G1MarkSweep::enable_archive_object_check();
+
+  // For each specified MemRegion range, allocate the corresponding G1
+  // regions and mark them as archive regions. We expect the ranges in
+  // ascending starting address order, without overlap.
+  for (size_t i = 0; i < count; i++) {
+    MemRegion curr_range = ranges[i];
+    HeapWord* start_address = curr_range.start();
+    size_t word_size = curr_range.word_size();
+    HeapWord* last_address = curr_range.last();
+    size_t commits = 0;
+
+    guarantee(reserved.contains(start_address) && reserved.contains(last_address),
+              err_msg("MemRegion outside of heap [" PTR_FORMAT ", " PTR_FORMAT "]",
+              p2i(start_address), p2i(last_address)));
+    guarantee(start_address > prev_last_addr,
+              err_msg("Ranges not in ascending order: " PTR_FORMAT " <= " PTR_FORMAT ,
+              p2i(start_address), p2i(prev_last_addr)));
+    prev_last_addr = last_address;
+
+    // Check for ranges that start in the same G1 region in which the previous
+    // range ended, and adjust the start address so we don't try to allocate
+    // the same region again. If the current range is entirely within that
+    // region, skip it, just adjusting the recorded top.
+    HeapRegion* start_region = _hrm.addr_to_region(start_address);
+    if ((prev_last_region != NULL) && (start_region == prev_last_region)) {
+      start_address = start_region->end();
+      if (start_address > last_address) {
+        _allocator->increase_used(word_size * HeapWordSize);
+        start_region->set_top(last_address + 1);
+        continue;
+      }
+      start_region->set_top(start_address);
+      curr_range = MemRegion(start_address, last_address + 1);
+      start_region = _hrm.addr_to_region(start_address);
+    }
+
+    // Perform the actual region allocation, exiting if it fails.
+    // Then note how much new space we have allocated.
+    if (!_hrm.allocate_containing_regions(curr_range, &commits)) {
+      return false;
+    }
+    _allocator->increase_used(word_size * HeapWordSize);
+    if (commits != 0) {
+      ergo_verbose1(ErgoHeapSizing,
+                    "attempt heap expansion",
+                    ergo_format_reason("allocate archive regions")
+                    ergo_format_byte("total size"),
+                    HeapRegion::GrainWords * HeapWordSize * commits);
+    }
+
+    // Mark each G1 region touched by the range as archive, add it to the old set,
+    // and set the allocation context and top.
+    HeapRegion* curr_region = _hrm.addr_to_region(start_address);
+    HeapRegion* last_region = _hrm.addr_to_region(last_address);
+    prev_last_region = last_region;
+
+    while (curr_region != NULL) {
+      assert(curr_region->is_empty() && !curr_region->is_pinned(),
+             err_msg("Region already in use (index %u)", curr_region->hrm_index()));
+      _hr_printer.alloc(curr_region, G1HRPrinter::Archive);
+      curr_region->set_allocation_context(AllocationContext::system());
+      curr_region->set_archive();
+      _old_set.add(curr_region);
+      if (curr_region != last_region) {
+        curr_region->set_top(curr_region->end());
+        curr_region = _hrm.next_region_in_heap(curr_region);
+      } else {
+        curr_region->set_top(last_address + 1);
+        curr_region = NULL;
+      }
+    }
+
+    // Notify mark-sweep of the archive range.
+    G1MarkSweep::mark_range_archive(curr_range);
+  }
+  return true;
+}
+
+void G1CollectedHeap::fill_archive_regions(MemRegion* ranges, size_t count) {
+  assert(ranges != NULL, "MemRegion array NULL");
+  assert(count != 0, "No MemRegions provided");
+  MemRegion reserved = _hrm.reserved();
+  HeapWord *prev_last_addr = NULL;
+  HeapRegion* prev_last_region = NULL;
+
+  // For each MemRegion, create filler objects, if needed, in the G1 regions
+  // that contain the address range. The address range actually within the
+  // MemRegion will not be modified. That is assumed to have been initialized
+  // elsewhere, probably via an mmap of archived heap data.
+  MutexLockerEx x(Heap_lock);
+  for (size_t i = 0; i < count; i++) {
+    HeapWord* start_address = ranges[i].start();
+    HeapWord* last_address = ranges[i].last();
+
+    assert(reserved.contains(start_address) && reserved.contains(last_address),
+           err_msg("MemRegion outside of heap [" PTR_FORMAT ", " PTR_FORMAT "]",
+                   p2i(start_address), p2i(last_address)));
+    assert(start_address > prev_last_addr,
+           err_msg("Ranges not in ascending order: " PTR_FORMAT " <= " PTR_FORMAT ,
+                   p2i(start_address), p2i(prev_last_addr)));
+
+    HeapRegion* start_region = _hrm.addr_to_region(start_address);
+    HeapRegion* last_region = _hrm.addr_to_region(last_address);
+    HeapWord* bottom_address = start_region->bottom();
+
+    // Check for a range beginning in the same region in which the
+    // previous one ended.
+    if (start_region == prev_last_region) {
+      bottom_address = prev_last_addr + 1;
+    }
+
+    // Verify that the regions were all marked as archive regions by
+    // alloc_archive_regions.
+    HeapRegion* curr_region = start_region;
+    while (curr_region != NULL) {
+      guarantee(curr_region->is_archive(),
+                err_msg("Expected archive region at index %u", curr_region->hrm_index()));
+      if (curr_region != last_region) {
+        curr_region = _hrm.next_region_in_heap(curr_region);
+      } else {
+        curr_region = NULL;
+      }
+    }
+
+    prev_last_addr = last_address;
+    prev_last_region = last_region;
+
+    // Fill the memory below the allocated range with dummy object(s),
+    // if the region bottom does not match the range start, or if the previous
+    // range ended within the same G1 region, and there is a gap.
+    if (start_address != bottom_address) {
+      size_t fill_size = pointer_delta(start_address, bottom_address);
+      G1CollectedHeap::fill_with_objects(bottom_address, fill_size);
+      _allocator->increase_used(fill_size * HeapWordSize);
+    }
+  }
+}
+
 HeapWord* G1CollectedHeap::attempt_allocation_humongous(size_t word_size,
                                                         uint* gc_count_before_ret,
                                                         uint* gclocker_retry_count_ret) {
@@ -1039,7 +1241,7 @@
   } else {
     HeapWord* result = humongous_obj_allocate(word_size, context);
     if (result != NULL && g1_policy()->need_to_start_conc_mark("STW humongous allocation")) {
-      g1_policy()->set_initiate_conc_mark_if_possible();
+      collector_state()->set_initiate_conc_mark_if_possible(true);
     }
     return result;
   }
@@ -1131,6 +1333,8 @@
       }
     } else if (hr->is_continues_humongous()) {
       _hr_printer->post_compaction(hr, G1HRPrinter::ContinuesHumongous);
+    } else if (hr->is_archive()) {
+      _hr_printer->post_compaction(hr, G1HRPrinter::Archive);
     } else if (hr->is_old()) {
       _hr_printer->post_compaction(hr, G1HRPrinter::Old);
     } else {
@@ -1250,7 +1454,7 @@
       g1_policy()->stop_incremental_cset_building();
 
       tear_down_region_sets(false /* free_list_only */);
-      g1_policy()->set_gcs_are_young(true);
+      collector_state()->set_gcs_are_young(true);
 
       // See the comments in g1CollectedHeap.hpp and
       // G1CollectedHeap::ref_processing_init() about
@@ -1714,16 +1918,15 @@
   _ref_processor_stw(NULL),
   _bot_shared(NULL),
   _evac_failure_scan_stack(NULL),
-  _mark_in_progress(false),
   _cg1r(NULL),
   _g1mm(NULL),
   _refine_cte_cl(NULL),
-  _full_collection(false),
   _secondary_free_list("Secondary Free List", new SecondaryFreeRegionListMtSafeChecker()),
   _old_set("Old Set", false /* humongous */, new OldRegionSetMtSafeChecker()),
   _humongous_set("Master Humongous Set", true /* humongous */, new HumongousRegionSetMtSafeChecker()),
   _humongous_reclaim_candidates(),
   _has_humongous_reclaim_candidates(false),
+  _archive_allocator(NULL),
   _free_regions_coming(false),
   _young_list(new YoungList(this)),
   _gc_time_stamp(0),
@@ -1733,7 +1936,6 @@
   _surviving_young_words(NULL),
   _old_marking_cycles_started(0),
   _old_marking_cycles_completed(0),
-  _concurrent_cycle_started(false),
   _heap_summary_sent(false),
   _in_cset_fast_test(),
   _dirty_cards_region_list(NULL),
@@ -1750,9 +1952,13 @@
   _workers->initialize_workers();
 
   _allocator = G1Allocator::create_allocator(this);
-  _humongous_object_threshold_in_words = HeapRegion::GrainWords / 2;
-
-  int n_queues = (int)ParallelGCThreads;
+  _humongous_object_threshold_in_words = humongous_threshold_for(HeapRegion::GrainWords);
+
+  // Override the default _filler_array_max_size so that no humongous filler
+  // objects are created.
+  _filler_array_max_size = _humongous_object_threshold_in_words;
+
+  uint n_queues = ParallelGCThreads;
   _task_queues = new RefToScanQueueSet(n_queues);
 
   uint n_rem_sets = HeapRegionRemSet::num_par_rem_sets();
@@ -1762,7 +1968,7 @@
   _worker_cset_start_region_time_stamp = NEW_C_HEAP_ARRAY(uint, n_queues, mtGC);
   _evacuation_failed_info_array = NEW_C_HEAP_ARRAY(EvacuationFailedInfo, n_queues, mtGC);
 
-  for (int i = 0; i < n_queues; i++) {
+  for (uint i = 0; i < n_queues; i++) {
     RefToScanQueue* q = new RefToScanQueue();
     q->initialize();
     _task_queues->register_queue(i, q);
@@ -2064,11 +2270,11 @@
     new ReferenceProcessor(mr,    // span
                            ParallelRefProcEnabled && (ParallelGCThreads > 1),
                                 // mt processing
-                           (uint) ParallelGCThreads,
+                           ParallelGCThreads,
                                 // degree of mt processing
                            (ParallelGCThreads > 1) || (ConcGCThreads > 1),
                                 // mt discovery
-                           (uint) MAX2(ParallelGCThreads, ConcGCThreads),
+                           MAX2(ParallelGCThreads, ConcGCThreads),
                                 // degree of mt discovery
                            false,
                                 // Reference discovery is not atomic
@@ -2081,11 +2287,11 @@
     new ReferenceProcessor(mr,    // span
                            ParallelRefProcEnabled && (ParallelGCThreads > 1),
                                 // mt processing
-                           (uint) ParallelGCThreads,
+                           ParallelGCThreads,
                                 // degree of mt processing
                            (ParallelGCThreads > 1),
                                 // mt discovery
-                           (uint) ParallelGCThreads,
+                           ParallelGCThreads,
                                 // degree of mt discovery
                            true,
                                 // Reference discovery is atomic
@@ -2165,7 +2371,11 @@
 
 // Computes the sum of the storage used by the various regions.
 size_t G1CollectedHeap::used() const {
-  return _allocator->used();
+  size_t result = _allocator->used();
+  if (_archive_allocator != NULL) {
+    result += _archive_allocator->used();
+  }
+  return result;
 }
 
 size_t G1CollectedHeap::used_unlocked() const {
@@ -2288,7 +2498,7 @@
 }
 
 void G1CollectedHeap::register_concurrent_cycle_start(const Ticks& start_time) {
-  _concurrent_cycle_started = true;
+  collector_state()->set_concurrent_cycle_started(true);
   _gc_timer_cm->register_gc_start(start_time);
 
   _gc_tracer_cm->report_gc_start(gc_cause(), _gc_timer_cm->gc_start());
@@ -2296,7 +2506,7 @@
 }
 
 void G1CollectedHeap::register_concurrent_cycle_end() {
-  if (_concurrent_cycle_started) {
+  if (collector_state()->concurrent_cycle_started()) {
     if (_cm->has_aborted()) {
       _gc_tracer_cm->report_concurrent_mode_failure();
     }
@@ -2305,13 +2515,13 @@
     _gc_tracer_cm->report_gc_end(_gc_timer_cm->gc_end(), _gc_timer_cm->time_partitions());
 
     // Clear state variables to prepare for the next concurrent cycle.
-    _concurrent_cycle_started = false;
+     collector_state()->set_concurrent_cycle_started(false);
     _heap_summary_sent = false;
   }
 }
 
 void G1CollectedHeap::trace_heap_after_concurrent_cycle() {
-  if (_concurrent_cycle_started) {
+  if (collector_state()->concurrent_cycle_started()) {
     // This function can be called when:
     //  the cleanup pause is run
     //  the concurrent cycle is aborted before the cleanup pause.
@@ -2325,22 +2535,6 @@
   }
 }
 
-G1YCType G1CollectedHeap::yc_type() {
-  bool is_young = g1_policy()->gcs_are_young();
-  bool is_initial_mark = g1_policy()->during_initial_mark_pause();
-  bool is_during_mark = mark_in_progress();
-
-  if (is_initial_mark) {
-    return InitialMark;
-  } else if (is_during_mark) {
-    return DuringMark;
-  } else if (is_young) {
-    return Normal;
-  } else {
-    return Mixed;
-  }
-}
-
 void G1CollectedHeap::collect(GCCause::Cause cause) {
   assert_heap_not_locked();
 
@@ -2594,7 +2788,7 @@
 
 HeapRegion* G1CollectedHeap::next_compaction_region(const HeapRegion* from) const {
   HeapRegion* result = _hrm.next_region_in_heap(from);
-  while (result != NULL && result->is_humongous()) {
+  while (result != NULL && result->is_pinned()) {
     result = _hrm.next_region_in_heap(result);
   }
   return result;
@@ -2902,6 +3096,31 @@
   size_t live_bytes() { return _live_bytes; }
 };
 
+class VerifyArchiveOopClosure: public OopClosure {
+public:
+  VerifyArchiveOopClosure(HeapRegion *hr) { }
+  void do_oop(narrowOop *p) { do_oop_work(p); }
+  void do_oop(      oop *p) { do_oop_work(p); }
+
+  template <class T> void do_oop_work(T *p) {
+    oop obj = oopDesc::load_decode_heap_oop(p);
+    guarantee(obj == NULL || G1MarkSweep::in_archive_range(obj),
+              err_msg("Archive object at " PTR_FORMAT " references a non-archive object at " PTR_FORMAT,
+                      p2i(p), p2i(obj)));
+  }
+};
+
+class VerifyArchiveRegionClosure: public ObjectClosure {
+public:
+  VerifyArchiveRegionClosure(HeapRegion *hr) { }
+  // Verify that all object pointers are to archive regions.
+  void do_object(oop o) {
+    VerifyArchiveOopClosure checkOop(NULL);
+    assert(o != NULL, "Should not be here for NULL oops");
+    o->oop_iterate_no_header(&checkOop);
+  }
+};
+
 class VerifyRegionClosure: public HeapRegionClosure {
 private:
   bool             _par;
@@ -2921,6 +3140,13 @@
   }
 
   bool doHeapRegion(HeapRegion* r) {
+    // For archive regions, verify there are no heap pointers to
+    // non-pinned regions. For all others, verify liveness info.
+    if (r->is_archive()) {
+      VerifyArchiveRegionClosure verify_oop_pointers(r);
+      r->object_iterate(&verify_oop_pointers);
+      return true;
+    }
     if (!r->is_continues_humongous()) {
       bool failures = false;
       r->verify(_vo, &failures);
@@ -3105,7 +3331,7 @@
   switch (vo) {
   case VerifyOption_G1UsePrevMarking: return is_obj_dead(obj, hr);
   case VerifyOption_G1UseNextMarking: return is_obj_ill(obj, hr);
-  case VerifyOption_G1UseMarkWord:    return !obj->is_gc_marked();
+  case VerifyOption_G1UseMarkWord:    return !obj->is_gc_marked() && !hr->is_archive();
   default:                            ShouldNotReachHere();
   }
   return false; // keep some compilers happy
@@ -3116,7 +3342,10 @@
   switch (vo) {
   case VerifyOption_G1UsePrevMarking: return is_obj_dead(obj);
   case VerifyOption_G1UseNextMarking: return is_obj_ill(obj);
-  case VerifyOption_G1UseMarkWord:    return !obj->is_gc_marked();
+  case VerifyOption_G1UseMarkWord: {
+    HeapRegion* hr = _hrm.addr_to_region((HeapWord*)obj);
+    return !obj->is_gc_marked() && !hr->is_archive();
+  }
   default:                            ShouldNotReachHere();
   }
   return false; // keep some compilers happy
@@ -3149,7 +3378,7 @@
   st->cr();
   st->print_cr("Heap Regions: (Y=young(eden), SU=young(survivor), "
                "HS=humongous(starts), HC=humongous(continues), "
-               "CS=collection set, F=free, TS=gc time stamp, "
+               "CS=collection set, F=free, A=archive, TS=gc time stamp, "
                "PTAMS=previous top-at-mark-start, "
                "NTAMS=next top-at-mark-start)");
   PrintRegionClosure blk(st);
@@ -3251,6 +3480,28 @@
 }
 #endif // PRODUCT
 
+G1HeapSummary G1CollectedHeap::create_g1_heap_summary() {
+  YoungList* young_list = heap()->young_list();
+
+  size_t eden_used_bytes = young_list->eden_used_bytes();
+  size_t survivor_used_bytes = young_list->survivor_used_bytes();
+
+  size_t eden_capacity_bytes =
+    (g1_policy()->young_list_target_length() * HeapRegion::GrainBytes) - survivor_used_bytes;
+
+  VirtualSpaceSummary heap_summary = create_heap_space_summary();
+  return G1HeapSummary(heap_summary, used(), eden_used_bytes, eden_capacity_bytes, survivor_used_bytes);
+}
+
+void G1CollectedHeap::trace_heap(GCWhen::Type when, const GCTracer* gc_tracer) {
+  const G1HeapSummary& heap_summary = create_g1_heap_summary();
+  gc_tracer->report_gc_heap_summary(when, heap_summary);
+
+  const MetaspaceSummary& metaspace_summary = create_metaspace_summary();
+  gc_tracer->report_metaspace_summary(when, metaspace_summary);
+}
+
+
 G1CollectedHeap* G1CollectedHeap::heap() {
   CollectedHeap* heap = Universe::heap();
   assert(heap != NULL, "Uninitialized access to G1CollectedHeap::heap()");
@@ -3587,8 +3838,8 @@
   gclog_or_tty->gclog_stamp(_gc_tracer_stw->gc_id());
 
   GCCauseString gc_cause_str = GCCauseString("GC pause", gc_cause())
-    .append(g1_policy()->gcs_are_young() ? "(young)" : "(mixed)")
-    .append(g1_policy()->during_initial_mark_pause() ? " (initial-mark)" : "");
+    .append(collector_state()->gcs_are_young() ? "(young)" : "(mixed)")
+    .append(collector_state()->during_initial_mark_pause() ? " (initial-mark)" : "");
 
   gclog_or_tty->print("[%s", (const char*)gc_cause_str);
 }
@@ -3616,6 +3867,21 @@
   gclog_or_tty->flush();
 }
 
+void G1CollectedHeap::wait_for_root_region_scanning() {
+  double scan_wait_start = os::elapsedTime();
+  // We have to wait until the CM threads finish scanning the
+  // root regions as it's the only way to ensure that all the
+  // objects on them have been correctly scanned before we start
+  // moving them during the GC.
+  bool waited = _cm->root_regions()->wait_until_scan_finished();
+  double wait_time_ms = 0.0;
+  if (waited) {
+    double scan_wait_end = os::elapsedTime();
+    wait_time_ms = (scan_wait_end - scan_wait_start) * 1000.0;
+  }
+  g1_policy()->phase_times()->record_root_region_scan_wait_time(wait_time_ms);
+}
+
 bool
 G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
   assert_at_safepoint(true /* should_be_vm_thread */);
@@ -3632,6 +3898,8 @@
   SvcGCMarker sgcm(SvcGCMarker::MINOR);
   ResourceMark rm;
 
+  wait_for_root_region_scanning();
+
   G1Log::update_level();
   print_heap_before_gc();
   trace_heap_before_gc(_gc_tracer_stw);
@@ -3645,29 +3913,29 @@
   g1_policy()->decide_on_conc_mark_initiation();
 
   // We do not allow initial-mark to be piggy-backed on a mixed GC.
-  assert(!g1_policy()->during_initial_mark_pause() ||
-          g1_policy()->gcs_are_young(), "sanity");
+  assert(!collector_state()->during_initial_mark_pause() ||
+          collector_state()->gcs_are_young(), "sanity");
 
   // We also do not allow mixed GCs during marking.
-  assert(!mark_in_progress() || g1_policy()->gcs_are_young(), "sanity");
+  assert(!collector_state()->mark_in_progress() || collector_state()->gcs_are_young(), "sanity");
 
   // Record whether this pause is an initial mark. When the current
   // thread has completed its logging output and it's safe to signal
   // the CM thread, the flag's value in the policy has been reset.
-  bool should_start_conc_mark = g1_policy()->during_initial_mark_pause();
+  bool should_start_conc_mark = collector_state()->during_initial_mark_pause();
 
   // Inner scope for scope based logging, timers, and stats collection
   {
     EvacuationInfo evacuation_info;
 
-    if (g1_policy()->during_initial_mark_pause()) {
+    if (collector_state()->during_initial_mark_pause()) {
       // We are about to start a marking cycle, so we increment the
       // full collection counter.
       increment_old_marking_cycles_started();
       register_concurrent_cycle_start(_gc_timer_stw->gc_start());
     }
 
-    _gc_tracer_stw->report_yc_type(yc_type());
+    _gc_tracer_stw->report_yc_type(collector_state()->yc_type());
 
     TraceCPUTime tcpu(G1Log::finer(), true, gclog_or_tty);
 
@@ -3677,7 +3945,7 @@
     workers()->set_active_workers(active_workers);
 
     double pause_start_sec = os::elapsedTime();
-    g1_policy()->phase_times()->note_gc_start(active_workers, mark_in_progress());
+    g1_policy()->phase_times()->note_gc_start(active_workers, collector_state()->mark_in_progress());
     log_gc_header();
 
     TraceCollectorStats tcs(g1mm()->incremental_collection_counters());
@@ -3753,25 +4021,12 @@
 
         g1_policy()->record_collection_pause_start(sample_start_time_sec);
 
-        double scan_wait_start = os::elapsedTime();
-        // We have to wait until the CM threads finish scanning the
-        // root regions as it's the only way to ensure that all the
-        // objects on them have been correctly scanned before we start
-        // moving them during the GC.
-        bool waited = _cm->root_regions()->wait_until_scan_finished();
-        double wait_time_ms = 0.0;
-        if (waited) {
-          double scan_wait_end = os::elapsedTime();
-          wait_time_ms = (scan_wait_end - scan_wait_start) * 1000.0;
-        }
-        g1_policy()->phase_times()->record_root_region_scan_wait_time(wait_time_ms);
-
 #if YOUNG_LIST_VERBOSE
         gclog_or_tty->print_cr("\nAfter recording pause start.\nYoung_list:");
         _young_list->print();
 #endif // YOUNG_LIST_VERBOSE
 
-        if (g1_policy()->during_initial_mark_pause()) {
+        if (collector_state()->during_initial_mark_pause()) {
           concurrent_mark()->checkpointRootsInitialPre();
         }
 
@@ -3848,6 +4103,9 @@
 
         if (evacuation_failed()) {
           _allocator->set_used(recalculate_used());
+          if (_archive_allocator != NULL) {
+            _archive_allocator->clear_used();
+          }
           for (uint i = 0; i < ParallelGCThreads; i++) {
             if (_evacuation_failed_info_array[i].has_failed()) {
               _gc_tracer_stw->report_evacuation_failed(_evacuation_failed_info_array[i]);
@@ -3859,12 +4117,12 @@
           _allocator->increase_used(g1_policy()->bytes_copied_during_gc());
         }
 
-        if (g1_policy()->during_initial_mark_pause()) {
+        if (collector_state()->during_initial_mark_pause()) {
           // We have to do this before we notify the CM threads that
           // they can start working to make sure that all the
           // appropriate initialization is done on the CM object.
           concurrent_mark()->checkpointRootsInitialPost();
-          set_marking_started();
+          collector_state()->set_mark_in_progress(true);
           // Note that we don't actually trigger the CM thread at
           // this point. We do that later when we're sure that
           // the current thread has completed its logging output.
@@ -4343,7 +4601,7 @@
 
       pss.set_evac_failure_closure(&evac_failure_cl);
 
-      bool only_young = _g1h->g1_policy()->gcs_are_young();
+      bool only_young = _g1h->collector_state()->gcs_are_young();
 
       // Non-IM young GC.
       G1ParCopyClosure<G1BarrierNone, G1MarkNone>             scan_only_root_cl(_g1h, &pss, rp);
@@ -4369,7 +4627,7 @@
 
       bool trace_metadata = false;
 
-      if (_g1h->g1_policy()->during_initial_mark_pause()) {
+      if (_g1h->collector_state()->during_initial_mark_pause()) {
         // We also need to mark copied objects.
         strong_root_cl = &scan_mark_root_cl;
         strong_cld_cl  = &scan_mark_cld_cl;
@@ -5021,7 +5279,7 @@
 
     OopClosure*                    copy_non_heap_cl = &only_copy_non_heap_cl;
 
-    if (_g1h->g1_policy()->during_initial_mark_pause()) {
+    if (_g1h->collector_state()->during_initial_mark_pause()) {
       // We also need to mark copied objects.
       copy_non_heap_cl = &copy_mark_non_heap_cl;
     }
@@ -5122,7 +5380,7 @@
 
     OopClosure*                    copy_non_heap_cl = &only_copy_non_heap_cl;
 
-    if (_g1h->g1_policy()->during_initial_mark_pause()) {
+    if (_g1h->collector_state()->during_initial_mark_pause()) {
       // We also need to mark copied objects.
       copy_non_heap_cl = &copy_mark_non_heap_cl;
     }
@@ -5234,7 +5492,7 @@
 
   OopClosure*                    copy_non_heap_cl = &only_copy_non_heap_cl;
 
-  if (g1_policy()->during_initial_mark_pause()) {
+  if (collector_state()->during_initial_mark_pause()) {
     // We also need to mark copied objects.
     copy_non_heap_cl = &copy_mark_non_heap_cl;
   }
@@ -5342,7 +5600,7 @@
     G1RootProcessor root_processor(this, n_workers);
     G1ParTask g1_par_task(this, _task_queues, &root_processor, n_workers);
     // InitialMark needs claim bits to keep track of the marked-through CLDs.
-    if (g1_policy()->during_initial_mark_pause()) {
+    if (collector_state()->during_initial_mark_pause()) {
       ClassLoaderDataGraph::clear_claimed_marks();
     }
 
@@ -5598,7 +5856,7 @@
   // We reset mark_in_progress() before we reset _cmThread->in_progress() and in this window
   // we do the clearing of the next bitmap concurrently. Thus, we can not verify the bitmap
   // if we happen to be in that state.
-  if (mark_in_progress() || !_cmThread->in_progress()) {
+  if (collector_state()->mark_in_progress() || !_cmThread->in_progress()) {
     res_n = verify_no_bits_over_tams("next", next_bitmap, ntams, end);
   }
   if (!res_p || !res_n) {
@@ -6169,13 +6427,18 @@
       assert(!r->is_young(), "we should not come across young regions");
 
       if (r->is_humongous()) {
-        // We ignore humongous regions, we left the humongous set unchanged
+        // We ignore humongous regions. We left the humongous set unchanged.
       } else {
         // Objects that were compacted would have ended up on regions
-        // that were previously old or free.
+        // that were previously old or free.  Archive regions (which are
+        // old) will not have been touched.
         assert(r->is_free() || r->is_old(), "invariant");
-        // We now consider them old, so register as such.
-        r->set_old();
+        // We now consider them old, so register as such. Leave
+        // archive regions set that way, however, while still adding
+        // them to the old set.
+        if (!r->is_archive()) {
+          r->set_old();
+        }
         _old_set->add(r);
       }
       _total_used += r->used();
@@ -6201,6 +6464,9 @@
 
   if (!free_list_only) {
     _allocator->set_used(cl.total_used());
+    if (_archive_allocator != NULL) {
+      _archive_allocator->clear_used();
+    }
   }
   assert(_allocator->used_unlocked() == recalculate_used(),
          err_msg("inconsistent _allocator->used_unlocked(), "
@@ -6279,7 +6545,7 @@
         _hr_printer.alloc(new_alloc_region, G1HRPrinter::Old);
         check_bitmaps("Old Region Allocation", new_alloc_region);
       }
-      bool during_im = g1_policy()->during_initial_mark_pause();
+      bool during_im = collector_state()->during_initial_mark_pause();
       new_alloc_region->note_start_of_copying(during_im);
       return new_alloc_region;
     }
@@ -6290,7 +6556,7 @@
 void G1CollectedHeap::retire_gc_alloc_region(HeapRegion* alloc_region,
                                              size_t allocated_bytes,
                                              InCSetState dest) {
-  bool during_im = g1_policy()->during_initial_mark_pause();
+  bool during_im = collector_state()->during_initial_mark_pause();
   alloc_region->note_end_of_copying(during_im);
   g1_policy()->record_bytes_copied_during_gc(allocated_bytes);
   if (dest.is_young()) {
@@ -6301,6 +6567,25 @@
   _hr_printer.retire(alloc_region);
 }
 
+HeapRegion* G1CollectedHeap::alloc_highest_free_region() {
+  bool expanded = false;
+  uint index = _hrm.find_highest_free(&expanded);
+
+  if (index != G1_NO_HRM_INDEX) {
+    if (expanded) {
+      ergo_verbose1(ErgoHeapSizing,
+                    "attempt heap expansion",
+                    ergo_format_reason("requested address range outside heap bounds")
+                    ergo_format_byte("region size"),
+                    HeapRegion::GrainWords * HeapWordSize);
+    }
+    _hrm.allocate_free_regions_starting_at(index, 1);
+    return region_at(index);
+  }
+  return NULL;
+}
+
+
 // Heap region set verification
 
 class VerifyRegionListsClosure : public HeapRegionClosure {
@@ -6337,6 +6622,9 @@
       assert(hr->containing_set() == _old_set, err_msg("Heap region %u is old but not in the old set.", hr->hrm_index()));
       _old_count.increment(1u, hr->capacity());
     } else {
+      // There are no other valid region types. Check for one invalid
+      // one we can identify: pinned without old or humongous set.
+      assert(!hr->is_pinned(), err_msg("Heap region %u is pinned but not old (archive) or humongous.", hr->hrm_index()));
       ShouldNotReachHere();
     }
     return false;
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -31,6 +31,7 @@
 #include "gc/g1/g1AllocationContext.hpp"
 #include "gc/g1/g1Allocator.hpp"
 #include "gc/g1/g1BiasedArray.hpp"
+#include "gc/g1/g1CollectorState.hpp"
 #include "gc/g1/g1HRPrinter.hpp"
 #include "gc/g1/g1InCSetState.hpp"
 #include "gc/g1/g1MonitoringSupport.hpp"
@@ -187,6 +188,7 @@
   friend class SurvivorGCAllocRegion;
   friend class OldGCAllocRegion;
   friend class G1Allocator;
+  friend class G1ArchiveAllocator;
 
   // Closures used in implementation.
   friend class G1ParScanThreadState;
@@ -249,6 +251,9 @@
   // Class that handles the different kinds of allocations.
   G1Allocator* _allocator;
 
+  // Class that handles archive allocation ranges.
+  G1ArchiveAllocator* _archive_allocator;
+
   // Statistics for each allocation context
   AllocationContextStats _allocation_context_stats;
 
@@ -328,6 +333,9 @@
   // (d) cause == _g1_humongous_allocation
   bool should_do_concurrent_full_gc(GCCause::Cause cause);
 
+  // indicates whether we are in young or mixed GC mode
+  G1CollectorState _collector_state;
+
   // Keeps track of how many "old marking cycles" (i.e., Full GCs or
   // concurrent cycles) we have started.
   volatile uint _old_marking_cycles_started;
@@ -336,7 +344,6 @@
   // concurrent cycles) we have completed.
   volatile uint _old_marking_cycles_completed;
 
-  bool _concurrent_cycle_started;
   bool _heap_summary_sent;
 
   // This is a non-product method that is helpful for testing. It is
@@ -367,6 +374,8 @@
   void log_gc_header();
   void log_gc_footer(double pause_time_sec);
 
+  void trace_heap(GCWhen::Type when, const GCTracer* tracer);
+
   // These are macros so that, if the assert fires, we get the correct
   // line number, file, etc.
 
@@ -571,6 +580,10 @@
   void retire_gc_alloc_region(HeapRegion* alloc_region,
                               size_t allocated_bytes, InCSetState dest);
 
+  // Allocate the highest free region in the reserved heap. This will commit
+  // regions as necessary.
+  HeapRegion* alloc_highest_free_region();
+
   // - if explicit_gc is true, the GC is for a System.gc() or a heap
   //   inspection request and should collect the entire heap
   // - if clear_all_soft_refs is true, all soft references should be
@@ -701,8 +714,6 @@
   void register_concurrent_cycle_end();
   void trace_heap_after_concurrent_cycle();
 
-  G1YCType yc_type();
-
   G1HRPrinter* hr_printer() { return &_hr_printer; }
 
   // Frees a non-humongous region by initializing its contents and
@@ -728,6 +739,44 @@
   void free_humongous_region(HeapRegion* hr,
                              FreeRegionList* free_list,
                              bool par);
+
+  // Facility for allocating in 'archive' regions in high heap memory and
+  // recording the allocated ranges. These should all be called from the
+  // VM thread at safepoints, without the heap lock held. They can be used
+  // to create and archive a set of heap regions which can be mapped at the
+  // same fixed addresses in a subsequent JVM invocation.
+  void begin_archive_alloc_range();
+
+  // Check if the requested size would be too large for an archive allocation.
+  bool is_archive_alloc_too_large(size_t word_size);
+
+  // Allocate memory of the requested size from the archive region. This will
+  // return NULL if the size is too large or if no memory is available. It
+  // does not trigger a garbage collection.
+  HeapWord* archive_mem_allocate(size_t word_size);
+
+  // Optionally aligns the end address and returns the allocated ranges in
+  // an array of MemRegions in order of ascending addresses.
+  void end_archive_alloc_range(GrowableArray<MemRegion>* ranges,
+                               size_t end_alignment_in_bytes = 0);
+
+  // Facility for allocating a fixed range within the heap and marking
+  // the containing regions as 'archive'. For use at JVM init time, when the
+  // caller may mmap archived heap data at the specified range(s).
+  // Verify that the MemRegions specified in the argument array are within the
+  // reserved heap.
+  bool check_archive_addresses(MemRegion* range, size_t count);
+
+  // Commit the appropriate G1 regions containing the specified MemRegions
+  // and mark them as 'archive' regions. The regions in the array must be
+  // non-overlapping and in order of ascending address.
+  bool alloc_archive_regions(MemRegion* range, size_t count);
+
+  // Insert any required filler objects in the G1 regions around the specified
+  // ranges to make the regions parseable. This must be called after
+  // alloc_archive_regions, and after class loading has occurred.
+  void fill_archive_regions(MemRegion* range, size_t count);
+
 protected:
 
   // Shrink the garbage-first heap by at most the given size (in bytes!).
@@ -756,6 +805,8 @@
                                 bool*          succeeded,
                                 GCCause::Cause gc_cause);
 
+  void wait_for_root_region_scanning();
+
   // The guts of the incremental collection pause, executed by the vm
   // thread. It returns false if it is unable to do the collection due
   // to the GC locker being active, true otherwise
@@ -791,7 +842,6 @@
   // The concurrent marker (and the thread it runs in.)
   ConcurrentMark* _cm;
   ConcurrentMarkThread* _cmThread;
-  bool _mark_in_progress;
 
   // The concurrent refiner.
   ConcurrentG1Refine* _cg1r;
@@ -1019,6 +1069,8 @@
     return CollectedHeap::G1CollectedHeap;
   }
 
+  G1CollectorState* collector_state() { return &_collector_state; }
+
   // The current policy object for the collector.
   G1CollectorPolicy* g1_policy() const { return _g1_policy; }
 
@@ -1391,6 +1443,11 @@
     return word_size > _humongous_object_threshold_in_words;
   }
 
+  // Returns the humongous threshold for a specific region size
+  static size_t humongous_threshold_for(size_t region_size) {
+    return (region_size / 2);
+  }
+
   // Update mod union table with the set of dirty cards.
   void updateModUnion();
 
@@ -1399,17 +1456,6 @@
   // bits.
   void markModUnionRange(MemRegion mr);
 
-  // Records the fact that a marking phase is no longer in progress.
-  void set_marking_complete() {
-    _mark_in_progress = false;
-  }
-  void set_marking_started() {
-    _mark_in_progress = true;
-  }
-  bool mark_in_progress() {
-    return _mark_in_progress;
-  }
-
   // Print the maximum heap capacity.
   virtual size_t max_capacity() const;
 
@@ -1448,21 +1494,23 @@
 
   // Determine if an object is dead, given the object and also
   // the region to which the object belongs. An object is dead
-  // iff a) it was not allocated since the last mark and b) it
-  // is not marked.
+  // iff a) it was not allocated since the last mark, b) it
+  // is not marked, and c) it is not in an archive region.
   bool is_obj_dead(const oop obj, const HeapRegion* hr) const {
     return
       !hr->obj_allocated_since_prev_marking(obj) &&
-      !isMarkedPrev(obj);
+      !isMarkedPrev(obj) &&
+      !hr->is_archive();
   }
 
   // This function returns true when an object has been
   // around since the previous marking and hasn't yet
-  // been marked during this marking.
+  // been marked during this marking, and is not in an archive region.
   bool is_obj_ill(const oop obj, const HeapRegion* hr) const {
     return
       !hr->obj_allocated_since_next_marking(obj) &&
-      !isMarkedNext(obj);
+      !isMarkedNext(obj) &&
+      !hr->is_archive();
   }
 
   // Determine if an object is dead, given only the object itself.
@@ -1522,14 +1570,6 @@
   void redirty_logged_cards();
   // Verification
 
-  // The following is just to alert the verification code
-  // that a full collection has occurred and that the
-  // remembered sets are no longer up to date.
-  bool _full_collection;
-  void set_full_collection() { _full_collection = true;}
-  void clear_full_collection() {_full_collection = false;}
-  bool full_collection() {return _full_collection;}
-
   // Perform any cleanup actions necessary before allowing a verification.
   virtual void prepare_for_verify();
 
@@ -1565,6 +1605,8 @@
   bool is_obj_dead_cond(const oop obj,
                         const VerifyOption vo) const;
 
+  G1HeapSummary create_g1_heap_summary();
+
   // Printing
 
   virtual void print_on(outputStream* st) const;
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -29,6 +29,7 @@
 #include "gc/g1/g1AllocRegion.inline.hpp"
 #include "gc/g1/g1CollectedHeap.hpp"
 #include "gc/g1/g1CollectorPolicy.hpp"
+#include "gc/g1/g1CollectorState.hpp"
 #include "gc/g1/g1SATBCardTableModRefBS.hpp"
 #include "gc/g1/heapRegionManager.inline.hpp"
 #include "gc/g1/heapRegionSet.inline.hpp"
@@ -288,9 +289,9 @@
     _evacuation_failure_alot_for_current_gc = (elapsed_gcs >= G1EvacuationFailureALotInterval);
 
     // Now check if G1EvacuationFailureALot is enabled for the current GC type.
-    const bool gcs_are_young = g1_policy()->gcs_are_young();
-    const bool during_im = g1_policy()->during_initial_mark_pause();
-    const bool during_marking = mark_in_progress();
+    const bool gcs_are_young = collector_state()->gcs_are_young();
+    const bool during_im = collector_state()->during_initial_mark_pause();
+    const bool during_marking = collector_state()->mark_in_progress();
 
     _evacuation_failure_alot_for_current_gc &=
       evacuation_failure_alot_for_gc_type(gcs_are_young,
--- a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -107,22 +107,11 @@
 
   _pause_time_target_ms((double) MaxGCPauseMillis),
 
-  _gcs_are_young(true),
-
-  _during_marking(false),
-  _in_marking_window(false),
-  _in_marking_window_im(false),
-
   _recent_prev_end_times_for_all_gcs_sec(
                                 new TruncatedSeq(NumPrevPausesForHeuristics)),
 
   _recent_avg_pause_time_ratio(0.0),
 
-  _initiate_conc_mark_if_possible(false),
-  _during_initial_mark_pause(false),
-  _last_young_gc(false),
-  _last_gc_was_young(false),
-
   _eden_used_bytes_before_gc(0),
   _survivor_used_bytes_before_gc(0),
   _heap_used_bytes_before_gc(0),
@@ -334,6 +323,8 @@
   }
 }
 
+G1CollectorState* G1CollectorPolicy::collector_state() { return _g1->collector_state(); }
+
 G1YoungGenSizer::G1YoungGenSizer() : _sizer_kind(SizerDefaults), _adaptive_size(true),
         _min_desired_young_length(0), _max_desired_young_length(0) {
   if (FLAG_IS_CMDLINE(NewRatio)) {
@@ -552,7 +543,7 @@
 
   uint young_list_target_length = 0;
   if (adaptive_young_list_length()) {
-    if (gcs_are_young()) {
+    if (collector_state()->gcs_are_young()) {
       young_list_target_length =
                         calculate_young_list_target_length(rs_lengths,
                                                            base_min_length,
@@ -594,7 +585,7 @@
                                                      uint desired_min_length,
                                                      uint desired_max_length) {
   assert(adaptive_young_list_length(), "pre-condition");
-  assert(gcs_are_young(), "only call this for young GCs");
+  assert(collector_state()->gcs_are_young(), "only call this for young GCs");
 
   // In case some edge-condition makes the desired max length too small...
   if (desired_max_length <= desired_min_length) {
@@ -697,7 +688,7 @@
   for (HeapRegion * r = _recorded_survivor_head;
        r != NULL && r != _recorded_survivor_tail->get_next_young_region();
        r = r->get_next_young_region()) {
-    survivor_regions_evac_time += predict_region_elapsed_time_ms(r, gcs_are_young());
+    survivor_regions_evac_time += predict_region_elapsed_time_ms(r, collector_state()->gcs_are_young());
   }
   return survivor_regions_evac_time;
 }
@@ -782,7 +773,7 @@
   _full_collection_start_sec = os::elapsedTime();
   record_heap_size_info_at_start(true /* full */);
   // Release the future to-space so that it is available for compaction into.
-  _g1->set_full_collection();
+  collector_state()->set_full_collection(true);
 }
 
 void G1CollectorPolicy::record_full_collection_end() {
@@ -796,16 +787,16 @@
 
   update_recent_gc_times(end_sec, full_gc_time_ms);
 
-  _g1->clear_full_collection();
+  collector_state()->set_full_collection(false);
 
   // "Nuke" the heuristics that control the young/mixed GC
   // transitions and make sure we start with young GCs after the Full GC.
-  set_gcs_are_young(true);
-  _last_young_gc = false;
-  clear_initiate_conc_mark_if_possible();
-  clear_during_initial_mark_pause();
-  _in_marking_window = false;
-  _in_marking_window_im = false;
+  collector_state()->set_gcs_are_young(true);
+  collector_state()->set_last_young_gc(false);
+  collector_state()->set_initiate_conc_mark_if_possible(false);
+  collector_state()->set_during_initial_mark_pause(false);
+  collector_state()->set_in_marking_window(false);
+  collector_state()->set_in_marking_window_im(false);
 
   _short_lived_surv_rate_group->start_adding_regions();
   // also call this on any additional surv rate groups
@@ -845,7 +836,7 @@
   _collection_set_bytes_used_before = 0;
   _bytes_copied_during_gc = 0;
 
-  _last_gc_was_young = false;
+  collector_state()->set_last_gc_was_young(false);
 
   // do that for any other surv rate groups
   _short_lived_surv_rate_group->stop_adding_regions();
@@ -856,15 +847,15 @@
 
 void G1CollectorPolicy::record_concurrent_mark_init_end(double
                                                    mark_init_elapsed_time_ms) {
-  _during_marking = true;
-  assert(!initiate_conc_mark_if_possible(), "we should have cleared it by now");
-  clear_during_initial_mark_pause();
+  collector_state()->set_during_marking(true);
+  assert(!collector_state()->initiate_conc_mark_if_possible(), "we should have cleared it by now");
+  collector_state()->set_during_initial_mark_pause(false);
   _cur_mark_stop_world_time_ms = mark_init_elapsed_time_ms;
 }
 
 void G1CollectorPolicy::record_concurrent_mark_remark_start() {
   _mark_remark_start_sec = os::elapsedTime();
-  _during_marking = false;
+  collector_state()->set_during_marking(false);
 }
 
 void G1CollectorPolicy::record_concurrent_mark_remark_end() {
@@ -882,8 +873,8 @@
 }
 
 void G1CollectorPolicy::record_concurrent_mark_cleanup_completed() {
-  _last_young_gc = true;
-  _in_marking_window = false;
+  collector_state()->set_last_young_gc(true);
+  collector_state()->set_in_marking_window(false);
 }
 
 void G1CollectorPolicy::record_concurrent_pause() {
@@ -904,7 +895,7 @@
   size_t alloc_byte_size = alloc_word_size * HeapWordSize;
 
   if ((cur_used_bytes + alloc_byte_size) > marking_initiating_used_threshold) {
-    if (gcs_are_young() && !_last_young_gc) {
+    if (collector_state()->gcs_are_young() && !collector_state()->last_young_gc()) {
       ergo_verbose5(ErgoConcCycles,
         "request concurrent cycle initiation",
         ergo_format_reason("occupancy higher than threshold")
@@ -959,14 +950,14 @@
   }
 #endif // PRODUCT
 
-  last_pause_included_initial_mark = during_initial_mark_pause();
+  last_pause_included_initial_mark = collector_state()->during_initial_mark_pause();
   if (last_pause_included_initial_mark) {
     record_concurrent_mark_init_end(0.0);
   } else if (need_to_start_conc_mark("end of GC")) {
     // Note: this might have already been set, if during the last
     // pause we decided to start a cycle but at the beginning of
     // this pause we decided to postpone it. That's OK.
-    set_initiate_conc_mark_if_possible();
+    collector_state()->set_initiate_conc_mark_if_possible(true);
   }
 
   _mmu_tracker->add_pause(end_time_sec - pause_time_ms/1000.0,
@@ -1028,37 +1019,37 @@
     }
   }
 
-  bool new_in_marking_window = _in_marking_window;
+  bool new_in_marking_window = collector_state()->in_marking_window();
   bool new_in_marking_window_im = false;
   if (last_pause_included_initial_mark) {
     new_in_marking_window = true;
     new_in_marking_window_im = true;
   }
 
-  if (_last_young_gc) {
+  if (collector_state()->last_young_gc()) {
     // This is supposed to to be the "last young GC" before we start
     // doing mixed GCs. Here we decide whether to start mixed GCs or not.
 
     if (!last_pause_included_initial_mark) {
       if (next_gc_should_be_mixed("start mixed GCs",
                                   "do not start mixed GCs")) {
-        set_gcs_are_young(false);
+        collector_state()->set_gcs_are_young(false);
       }
     } else {
       ergo_verbose0(ErgoMixedGCs,
                     "do not start mixed GCs",
                     ergo_format_reason("concurrent cycle is about to start"));
     }
-    _last_young_gc = false;
+    collector_state()->set_last_young_gc(false);
   }
 
-  if (!_last_gc_was_young) {
+  if (!collector_state()->last_gc_was_young()) {
     // This is a mixed GC. Here we decide whether to continue doing
     // mixed GCs or not.
 
     if (!next_gc_should_be_mixed("continue mixed GCs",
                                  "do not continue mixed GCs")) {
-      set_gcs_are_young(true);
+      collector_state()->set_gcs_are_young(true);
     }
   }
 
@@ -1077,7 +1068,7 @@
     double cost_per_entry_ms = 0.0;
     if (cards_scanned > 10) {
       cost_per_entry_ms = phase_times()->average_time_ms(G1GCPhaseTimes::ScanRS) / (double) cards_scanned;
-      if (_last_gc_was_young) {
+      if (collector_state()->last_gc_was_young()) {
         _cost_per_entry_ms_seq->add(cost_per_entry_ms);
       } else {
         _mixed_cost_per_entry_ms_seq->add(cost_per_entry_ms);
@@ -1087,7 +1078,7 @@
     if (_max_rs_lengths > 0) {
       double cards_per_entry_ratio =
         (double) cards_scanned / (double) _max_rs_lengths;
-      if (_last_gc_was_young) {
+      if (collector_state()->last_gc_was_young()) {
         _young_cards_per_entry_ratio_seq->add(cards_per_entry_ratio);
       } else {
         _mixed_cards_per_entry_ratio_seq->add(cards_per_entry_ratio);
@@ -1119,7 +1110,7 @@
 
     if (copied_bytes > 0) {
       cost_per_byte_ms = phase_times()->average_time_ms(G1GCPhaseTimes::ObjCopy) / (double) copied_bytes;
-      if (_in_marking_window) {
+      if (collector_state()->in_marking_window()) {
         _cost_per_byte_ms_during_cm_seq->add(cost_per_byte_ms);
       } else {
         _cost_per_byte_ms_seq->add(cost_per_byte_ms);
@@ -1162,8 +1153,8 @@
     _rs_lengths_seq->add((double) _max_rs_lengths);
   }
 
-  _in_marking_window = new_in_marking_window;
-  _in_marking_window_im = new_in_marking_window_im;
+  collector_state()->set_in_marking_window(new_in_marking_window);
+  collector_state()->set_in_marking_window_im(new_in_marking_window_im);
   _free_regions_at_end_of_collection = _g1->num_free_regions();
   update_young_list_target_length();
 
@@ -1301,7 +1292,7 @@
 G1CollectorPolicy::predict_base_elapsed_time_ms(size_t pending_cards) {
   size_t rs_length = predict_rs_length_diff();
   size_t card_num;
-  if (gcs_are_young()) {
+  if (collector_state()->gcs_are_young()) {
     card_num = predict_young_card_num(rs_length);
   } else {
     card_num = predict_non_young_card_num(rs_length);
@@ -1467,7 +1458,7 @@
                   ergo_format_reason("requested by GC cause")
                   ergo_format_str("GC cause"),
                   GCCause::to_string(gc_cause));
-    set_initiate_conc_mark_if_possible();
+    collector_state()->set_initiate_conc_mark_if_possible(true);
     return true;
   } else {
     ergo_verbose1(ErgoConcCycles,
@@ -1484,13 +1475,13 @@
   // We are about to decide on whether this pause will be an
   // initial-mark pause.
 
-  // First, during_initial_mark_pause() should not be already set. We
+  // First, collector_state()->during_initial_mark_pause() should not be already set. We
   // will set it here if we have to. However, it should be cleared by
   // the end of the pause (it's only set for the duration of an
   // initial-mark pause).
-  assert(!during_initial_mark_pause(), "pre-condition");
+  assert(!collector_state()->during_initial_mark_pause(), "pre-condition");
 
-  if (initiate_conc_mark_if_possible()) {
+  if (collector_state()->initiate_conc_mark_if_possible()) {
     // We had noticed on a previous pause that the heap occupancy has
     // gone over the initiating threshold and we should start a
     // concurrent marking cycle. So we might initiate one.
@@ -1501,10 +1492,10 @@
       // it has completed the last one. So we can go ahead and
       // initiate a new cycle.
 
-      set_during_initial_mark_pause();
+      collector_state()->set_during_initial_mark_pause(true);
       // We do not allow mixed GCs during marking.
-      if (!gcs_are_young()) {
-        set_gcs_are_young(true);
+      if (!collector_state()->gcs_are_young()) {
+        collector_state()->set_gcs_are_young(true);
         ergo_verbose0(ErgoMixedGCs,
                       "end mixed GCs",
                       ergo_format_reason("concurrent cycle is about to start"));
@@ -1512,7 +1503,7 @@
 
       // And we can now clear initiate_conc_mark_if_possible() as
       // we've already acted on it.
-      clear_initiate_conc_mark_if_possible();
+      collector_state()->set_initiate_conc_mark_if_possible(false);
 
       ergo_verbose0(ErgoConcCycles,
                   "initiate concurrent cycle",
@@ -1686,7 +1677,7 @@
   // retiring the current allocation region) or a concurrent
   // refine thread (RSet sampling).
 
-  double region_elapsed_time_ms = predict_region_elapsed_time_ms(hr, gcs_are_young());
+  double region_elapsed_time_ms = predict_region_elapsed_time_ms(hr, collector_state()->gcs_are_young());
   size_t used_bytes = hr->used();
   _inc_cset_recorded_rs_lengths += rs_length;
   _inc_cset_predicted_elapsed_time_ms += region_elapsed_time_ms;
@@ -1721,7 +1712,7 @@
   _inc_cset_recorded_rs_lengths_diffs += rs_lengths_diff;
 
   double old_elapsed_time_ms = hr->predicted_elapsed_time_ms();
-  double new_region_elapsed_time_ms = predict_region_elapsed_time_ms(hr, gcs_are_young());
+  double new_region_elapsed_time_ms = predict_region_elapsed_time_ms(hr, collector_state()->gcs_are_young());
   double elapsed_ms_diff = new_region_elapsed_time_ms - old_elapsed_time_ms;
   _inc_cset_predicted_elapsed_time_ms_diffs += elapsed_ms_diff;
 
@@ -1914,9 +1905,9 @@
                 ergo_format_ms("target pause time"),
                 _pending_cards, base_time_ms, time_remaining_ms, target_pause_time_ms);
 
-  _last_gc_was_young = gcs_are_young() ? true : false;
+  collector_state()->set_last_gc_was_young(collector_state()->gcs_are_young());
 
-  if (_last_gc_was_young) {
+  if (collector_state()->last_gc_was_young()) {
     _trace_young_gen_time_data.increment_young_collection_count();
   } else {
     _trace_young_gen_time_data.increment_mixed_collection_count();
@@ -1967,7 +1958,7 @@
   // Set the start of the non-young choice time.
   double non_young_start_time_sec = young_end_time_sec;
 
-  if (!gcs_are_young()) {
+  if (!collector_state()->gcs_are_young()) {
     CollectionSetChooser* cset_chooser = _collectionSetChooser;
     cset_chooser->verify();
     const uint min_old_cset_length = calc_min_old_cset_length();
@@ -2013,7 +2004,7 @@
         break;
       }
 
-      double predicted_time_ms = predict_region_elapsed_time_ms(hr, gcs_are_young());
+      double predicted_time_ms = predict_region_elapsed_time_ms(hr, collector_state()->gcs_are_young());
       if (check_time_remaining) {
         if (predicted_time_ms > time_remaining_ms) {
           // Too expensive for the current CSet.
--- a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -27,6 +27,7 @@
 
 #include "gc/g1/collectionSetChooser.hpp"
 #include "gc/g1/g1Allocator.hpp"
+#include "gc/g1/g1CollectorState.hpp"
 #include "gc/g1/g1MMUTracker.hpp"
 #include "gc/shared/collectorPolicy.hpp"
 
@@ -193,9 +194,6 @@
 
   double _stop_world_start;
 
-  // indicates whether we are in young or mixed GC mode
-  bool _gcs_are_young;
-
   uint _young_list_target_length;
   uint _young_list_fixed_length;
 
@@ -203,12 +201,6 @@
   // locker is active. This should be >= _young_list_target_length;
   uint _young_list_max_length;
 
-  bool _last_gc_was_young;
-
-  bool _during_marking;
-  bool _in_marking_window;
-  bool _in_marking_window_im;
-
   SurvRateGroup* _short_lived_surv_rate_group;
   SurvRateGroup* _survivor_surv_rate_group;
   // add here any more surv rate groups
@@ -218,10 +210,6 @@
   double _reserve_factor;
   uint   _reserve_regions;
 
-  bool during_marking() {
-    return _during_marking;
-  }
-
   enum PredictionConstants {
     TruncatedSeqLength = 10
   };
@@ -363,7 +351,7 @@
   }
 
   double predict_rs_scan_time_ms(size_t card_num) {
-    if (gcs_are_young()) {
+    if (collector_state()->gcs_are_young()) {
       return (double) card_num * get_new_prediction(_cost_per_entry_ms_seq);
     } else {
       return predict_mixed_rs_scan_time_ms(card_num);
@@ -390,7 +378,7 @@
   }
 
   double predict_object_copy_time_ms(size_t bytes_to_copy) {
-    if (_in_marking_window && !_in_marking_window_im) {
+    if (collector_state()->during_concurrent_mark()) {
       return predict_object_copy_time_ms_during_cm(bytes_to_copy);
     } else {
       return (double) bytes_to_copy *
@@ -428,7 +416,7 @@
   double predict_survivor_regions_evac_time();
 
   void cset_regions_freed() {
-    bool propagate = _last_gc_was_young && !_in_marking_window;
+    bool propagate = collector_state()->should_propagate();
     _short_lived_surv_rate_group->all_surviving_words_recorded(propagate);
     _survivor_surv_rate_group->all_surviving_words_recorded(propagate);
     // also call it on any more surv rate groups
@@ -552,33 +540,6 @@
     return _recent_avg_pause_time_ratio;
   }
 
-  // At the end of a pause we check the heap occupancy and we decide
-  // whether we will start a marking cycle during the next pause. If
-  // we decide that we want to do that, we will set this parameter to
-  // true. So, this parameter will stay true between the end of a
-  // pause and the beginning of a subsequent pause (not necessarily
-  // the next one, see the comments on the next field) when we decide
-  // that we will indeed start a marking cycle and do the initial-mark
-  // work.
-  volatile bool _initiate_conc_mark_if_possible;
-
-  // If initiate_conc_mark_if_possible() is set at the beginning of a
-  // pause, it is a suggestion that the pause should start a marking
-  // cycle by doing the initial-mark work. However, it is possible
-  // that the concurrent marking thread is still finishing up the
-  // previous marking cycle (e.g., clearing the next marking
-  // bitmap). If that is the case we cannot start a new cycle and
-  // we'll have to wait for the concurrent marking thread to finish
-  // what it is doing. In this case we will postpone the marking cycle
-  // initiation decision for the next pause. When we eventually decide
-  // to start a cycle, we will set _during_initial_mark_pause which
-  // will stay true until the end of the initial-mark pause and it's
-  // the condition that indicates that a pause is doing the
-  // initial-mark work.
-  volatile bool _during_initial_mark_pause;
-
-  bool _last_young_gc;
-
   // This set of variables tracks the collector efficiency, in order to
   // determine whether we should initiate a new marking.
   double _cur_mark_stop_world_time_ms;
@@ -647,6 +608,8 @@
     return CollectorPolicy::G1CollectorPolicyKind;
   }
 
+  G1CollectorState* collector_state();
+
   G1GCPhaseTimes* phase_times() const { return _phase_times; }
 
   // Check the current value of the young list RSet lengths and
@@ -786,14 +749,6 @@
   void print_collection_set(HeapRegion* list_head, outputStream* st);
 #endif // !PRODUCT
 
-  bool initiate_conc_mark_if_possible()       { return _initiate_conc_mark_if_possible;  }
-  void set_initiate_conc_mark_if_possible()   { _initiate_conc_mark_if_possible = true;  }
-  void clear_initiate_conc_mark_if_possible() { _initiate_conc_mark_if_possible = false; }
-
-  bool during_initial_mark_pause()      { return _during_initial_mark_pause;  }
-  void set_during_initial_mark_pause()  { _during_initial_mark_pause = true;  }
-  void clear_during_initial_mark_pause(){ _during_initial_mark_pause = false; }
-
   // This sets the initiate_conc_mark_if_possible() flag to start a
   // new cycle, as long as we are not already in one. It's best if it
   // is called during a safepoint when the test whether a cycle is in
@@ -837,13 +792,6 @@
     return _young_list_max_length;
   }
 
-  bool gcs_are_young() {
-    return _gcs_are_young;
-  }
-  void set_gcs_are_young(bool gcs_are_young) {
-    _gcs_are_young = gcs_are_young;
-  }
-
   bool adaptive_young_list_length() {
     return _young_gen_sizer->adaptive_young_list_length();
   }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/g1/g1CollectorState.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2015, 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.
+ *
+ */
+
+#ifndef SHARE_VM_GC_G1_G1COLLECTORSTATE_HPP
+#define SHARE_VM_GC_G1_G1COLLECTORSTATE_HPP
+
+#include "utilities/globalDefinitions.hpp"
+#include "gc/g1/g1YCTypes.hpp"
+
+// Various state variables that indicate
+// the phase of the G1 collection.
+class G1CollectorState VALUE_OBJ_CLASS_SPEC {
+  // Indicates whether we are in "full young" or "mixed" GC mode.
+  bool _gcs_are_young;
+  // Was the last GC "young"?
+  bool _last_gc_was_young;
+  // Is this the "last young GC" before we start doing mixed GCs?
+  // Set after a concurrent mark has completed.
+  bool _last_young_gc;
+
+  // If initiate_conc_mark_if_possible() is set at the beginning of a
+  // pause, it is a suggestion that the pause should start a marking
+  // cycle by doing the initial-mark work. However, it is possible
+  // that the concurrent marking thread is still finishing up the
+  // previous marking cycle (e.g., clearing the next marking
+  // bitmap). If that is the case we cannot start a new cycle and
+  // we'll have to wait for the concurrent marking thread to finish
+  // what it is doing. In this case we will postpone the marking cycle
+  // initiation decision for the next pause. When we eventually decide
+  // to start a cycle, we will set _during_initial_mark_pause which
+  // will stay true until the end of the initial-mark pause and it's
+  // the condition that indicates that a pause is doing the
+  // initial-mark work.
+  volatile bool _during_initial_mark_pause;
+
+  // At the end of a pause we check the heap occupancy and we decide
+  // whether we will start a marking cycle during the next pause. If
+  // we decide that we want to do that, we will set this parameter to
+  // true. So, this parameter will stay true between the end of a
+  // pause and the beginning of a subsequent pause (not necessarily
+  // the next one, see the comments on the next field) when we decide
+  // that we will indeed start a marking cycle and do the initial-mark
+  // work.
+  volatile bool _initiate_conc_mark_if_possible;
+
+  // NOTE: if some of these are synonyms for others,
+  // the redundant fields should be eliminated. XXX
+  bool _during_marking;
+  bool _mark_in_progress;
+  bool _in_marking_window;
+  bool _in_marking_window_im;
+
+  bool _concurrent_cycle_started;
+  bool _full_collection;
+
+  public:
+    G1CollectorState() :
+      _gcs_are_young(true),
+      _last_gc_was_young(false),
+      _last_young_gc(false),
+
+      _during_initial_mark_pause(false),
+      _initiate_conc_mark_if_possible(false),
+
+      _during_marking(false),
+      _mark_in_progress(false),
+      _in_marking_window(false),
+      _in_marking_window_im(false),
+      _concurrent_cycle_started(false),
+      _full_collection(false) {}
+
+  // Setters
+  void set_gcs_are_young(bool v) { _gcs_are_young = v; }
+  void set_last_gc_was_young(bool v) { _last_gc_was_young = v; }
+  void set_last_young_gc(bool v) { _last_young_gc = v; }
+  void set_during_initial_mark_pause(bool v) { _during_initial_mark_pause = v; }
+  void set_initiate_conc_mark_if_possible(bool v) { _initiate_conc_mark_if_possible = v; }
+  void set_during_marking(bool v) { _during_marking = v; }
+  void set_mark_in_progress(bool v) { _mark_in_progress = v; }
+  void set_in_marking_window(bool v) { _in_marking_window = v; }
+  void set_in_marking_window_im(bool v) { _in_marking_window_im = v; }
+  void set_concurrent_cycle_started(bool v) { _concurrent_cycle_started = v; }
+  void set_full_collection(bool v) { _full_collection = v; }
+
+  // Getters
+  bool gcs_are_young() { return _gcs_are_young; }
+  bool last_gc_was_young() { return _last_gc_was_young; }
+  bool last_young_gc() { return _last_young_gc; }
+  bool during_initial_mark_pause() { return _during_initial_mark_pause; }
+  bool initiate_conc_mark_if_possible() { return _initiate_conc_mark_if_possible; }
+  bool during_marking() { return _during_marking; }
+  bool mark_in_progress() { return _mark_in_progress; }
+  bool in_marking_window() { return _in_marking_window; }
+  bool in_marking_window_im() { return _in_marking_window_im; }
+  bool concurrent_cycle_started() { return _concurrent_cycle_started; }
+  bool full_collection() { return _full_collection; }
+
+  // Composite booleans (clients worry about flickering)
+  bool during_concurrent_mark() {
+    return (_in_marking_window && !_in_marking_window_im);
+  }
+
+  bool should_propagate() { // XXX should have a more suitable state name or abstraction for this
+    return (_last_young_gc && !_in_marking_window);
+  }
+
+  G1YCType yc_type() {
+    if (during_initial_mark_pause()) {
+      return InitialMark;
+    } else if (mark_in_progress()) {
+      return DuringMark;
+    } else if (gcs_are_young()) {
+      return Normal;
+    } else {
+      return Mixed;
+    }
+  }
+};
+
+#endif /* SHARE_VM_GC_G1_G1COLLECTORSTATE_HPP */
--- a/hotspot/src/share/vm/gc/g1/g1EvacFailure.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1EvacFailure.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -26,6 +26,7 @@
 #include "gc/g1/concurrentMark.inline.hpp"
 #include "gc/g1/dirtyCardQueue.hpp"
 #include "gc/g1/g1CollectedHeap.inline.hpp"
+#include "gc/g1/g1CollectorState.hpp"
 #include "gc/g1/g1EvacFailure.hpp"
 #include "gc/g1/g1OopClosures.inline.hpp"
 #include "gc/g1/g1_globals.hpp"
@@ -186,10 +187,10 @@
   }
 
   bool doHeapRegion(HeapRegion *hr) {
-    bool during_initial_mark = _g1h->g1_policy()->during_initial_mark_pause();
-    bool during_conc_mark = _g1h->mark_in_progress();
+    bool during_initial_mark = _g1h->collector_state()->during_initial_mark_pause();
+    bool during_conc_mark = _g1h->collector_state()->mark_in_progress();
 
-    assert(!hr->is_humongous(), "sanity");
+    assert(!hr->is_pinned(), err_msg("Unexpected pinned region at index %u", hr->hrm_index()));
     assert(hr->in_collection_set(), "bad CS");
 
     if (_hrclaimer->claim_region(hr->hrm_index())) {
--- a/hotspot/src/share/vm/gc/g1/g1HRPrinter.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1HRPrinter.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -54,6 +54,7 @@
     case SingleHumongous:    return "SingleH";
     case StartsHumongous:    return "StartsH";
     case ContinuesHumongous: return "ContinuesH";
+    case Archive:            return "Archive";
     default:                 ShouldNotReachHere();
   }
   // trying to keep the Windows compiler happy
--- a/hotspot/src/share/vm/gc/g1/g1HRPrinter.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1HRPrinter.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -52,7 +52,8 @@
     Old,
     SingleHumongous,
     StartsHumongous,
-    ContinuesHumongous
+    ContinuesHumongous,
+    Archive
   } RegionType;
 
   typedef enum {
--- a/hotspot/src/share/vm/gc/g1/g1MarkSweep.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1MarkSweep.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -57,6 +57,9 @@
 
 class HeapRegion;
 
+bool G1MarkSweep::_archive_check_enabled = false;
+G1ArchiveRegionMap G1MarkSweep::_archive_region_map;
+
 void G1MarkSweep::invoke_at_safepoint(ReferenceProcessor* rp,
                                       bool clear_all_softrefs) {
   assert(SafepointSynchronize::is_at_safepoint(), "must be at a safepoint");
@@ -212,7 +215,7 @@
         // point all the oops to the new location
         MarkSweep::adjust_pointers(obj);
       }
-    } else {
+    } else if (!r->is_pinned()) {
       // This really ought to be "as_CompactibleSpace"...
       r->adjust_pointers();
     }
@@ -275,7 +278,7 @@
         }
         hr->reset_during_compaction();
       }
-    } else {
+    } else if (!hr->is_pinned()) {
       hr->compact();
     }
     return false;
@@ -298,6 +301,26 @@
 
 }
 
+void G1MarkSweep::enable_archive_object_check() {
+  assert(!_archive_check_enabled, "archive range check already enabled");
+  _archive_check_enabled = true;
+  size_t length = Universe::heap()->max_capacity();
+  _archive_region_map.initialize((HeapWord*)Universe::heap()->base(),
+                                 (HeapWord*)Universe::heap()->base() + length,
+                                 HeapRegion::GrainBytes);
+}
+
+void G1MarkSweep::mark_range_archive(MemRegion range) {
+  assert(_archive_check_enabled, "archive range check not enabled");
+  _archive_region_map.set_by_address(range, true);
+}
+
+bool G1MarkSweep::in_archive_range(oop object) {
+  // This is the out-of-line part of is_archive_object test, done separately
+  // to avoid additional performance impact when the check is not enabled.
+  return _archive_region_map.get_by_address((HeapWord*)object);
+}
+
 void G1MarkSweep::prepare_compaction_work(G1PrepareCompactClosure* blk) {
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
   g1h->heap_region_iterate(blk);
@@ -357,7 +380,7 @@
     } else {
       assert(hr->is_continues_humongous(), "Invalid humongous.");
     }
-  } else {
+  } else if (!hr->is_pinned()) {
     prepare_for_compaction(hr, hr->end());
   }
   return false;
--- a/hotspot/src/share/vm/gc/g1/g1MarkSweep.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1MarkSweep.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -44,6 +44,7 @@
 //
 // Class unloading will only occur when a full gc is invoked.
 class G1PrepareCompactClosure;
+class G1ArchiveRegionMap;
 
 class G1MarkSweep : AllStatic {
  public:
@@ -54,7 +55,22 @@
   static STWGCTimer* gc_timer() { return GenMarkSweep::_gc_timer; }
   static SerialOldTracer* gc_tracer() { return GenMarkSweep::_gc_tracer; }
 
+  // Create the _archive_region_map which is used to identify archive objects.
+  static void enable_archive_object_check();
+
+  // Mark the regions containing the specified address range as archive regions.
+  static void mark_range_archive(MemRegion range);
+
+  // Check if an object is in an archive region using the _archive_region_map.
+  static bool in_archive_range(oop object);
+
+  // Check if archive object checking is enabled, to avoid calling in_archive_range
+  // unnecessarily.
+  static bool archive_check_enabled() { return G1MarkSweep::_archive_check_enabled; }
+
  private:
+  static bool _archive_check_enabled;
+  static G1ArchiveRegionMap  _archive_region_map;
 
   // Mark live objects
   static void mark_sweep_phase1(bool& marked_for_deopt,
@@ -93,4 +109,12 @@
   bool doHeapRegion(HeapRegion* hr);
 };
 
+// G1ArchiveRegionMap is a boolean array used to mark G1 regions as
+// archive regions.  This allows a quick check for whether an object
+// should not be marked because it is in an archive region.
+class G1ArchiveRegionMap : public G1BiasedMappedArray<bool> {
+protected:
+  bool default_value() const { return false; }
+};
+
 #endif // SHARE_VM_GC_G1_G1MARKSWEEP_HPP
--- a/hotspot/src/share/vm/gc/g1/g1OopClosures.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1OopClosures.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -51,7 +51,7 @@
   _worker_id = par_scan_state->queue_num();
 
   assert(_worker_id < ParallelGCThreads,
-         err_msg("The given worker id %u must be less than the number of threads " UINTX_FORMAT, _worker_id, ParallelGCThreads));
+         err_msg("The given worker id %u must be less than the number of threads %u", _worker_id, ParallelGCThreads));
 }
 
 // Generate G1 specialized oop_oop_iterate functions.
--- a/hotspot/src/share/vm/gc/g1/g1RemSet.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1RemSet.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -627,7 +627,7 @@
 void G1RemSet::prepare_for_verify() {
   if (G1HRRSFlushLogBuffersOnVerify &&
       (VerifyBeforeGC || VerifyAfterGC)
-      &&  (!_g1->full_collection() || G1VerifyRSetsDuringFullGC)) {
+      &&  (!_g1->collector_state()->full_collection() || G1VerifyRSetsDuringFullGC)) {
     cleanupHRRS();
     _g1->set_refine_cte_cl_concurrency(false);
     if (SafepointSynchronize::is_at_safepoint()) {
--- a/hotspot/src/share/vm/gc/g1/g1RootProcessor.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1RootProcessor.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -30,6 +30,7 @@
 #include "gc/g1/bufferingOopClosure.hpp"
 #include "gc/g1/g1CollectedHeap.inline.hpp"
 #include "gc/g1/g1CollectorPolicy.hpp"
+#include "gc/g1/g1CollectorState.hpp"
 #include "gc/g1/g1GCPhaseTimes.hpp"
 #include "gc/g1/g1RemSet.inline.hpp"
 #include "gc/g1/g1RootProcessor.hpp"
@@ -199,7 +200,7 @@
   // as implicitly live).
   {
     G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::SATBFiltering, worker_i);
-    if (!_process_strong_tasks->is_task_claimed(G1RP_PS_filter_satb_buffers) && _g1h->mark_in_progress()) {
+    if (!_process_strong_tasks->is_task_claimed(G1RP_PS_filter_satb_buffers) && _g1h->collector_state()->mark_in_progress()) {
       JavaThread::satb_mark_queue_set().filter_thread_buffers();
     }
   }
--- a/hotspot/src/share/vm/gc/g1/g1StringDedupThread.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1StringDedupThread.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -23,12 +23,14 @@
  */
 
 #include "precompiled.hpp"
+#include "classfile/stringTable.hpp"
 #include "gc/g1/g1Log.hpp"
 #include "gc/g1/g1StringDedup.hpp"
 #include "gc/g1/g1StringDedupQueue.hpp"
 #include "gc/g1/g1StringDedupTable.hpp"
 #include "gc/g1/g1StringDedupThread.hpp"
 #include "gc/g1/suspendibleThreadSet.hpp"
+#include "oops/oop.inline.hpp"
 #include "runtime/atomic.inline.hpp"
 
 G1StringDedupThread* G1StringDedupThread::_thread = NULL;
@@ -55,11 +57,36 @@
   return _thread;
 }
 
+class G1StringDedupSharedClosure: public OopClosure {
+ private:
+  G1StringDedupStat& _stat;
+
+ public:
+  G1StringDedupSharedClosure(G1StringDedupStat& stat) : _stat(stat) {}
+
+  virtual void do_oop(oop* p) { ShouldNotReachHere(); }
+  virtual void do_oop(narrowOop* p) {
+    oop java_string = oopDesc::load_decode_heap_oop(p);
+    G1StringDedupTable::deduplicate(java_string, _stat);
+  }
+};
+
+// The CDS archive does not include the string dedupication table. Only the string
+// table is saved in the archive. The shared strings from CDS archive need to be
+// added to the string dedupication table before deduplication occurs. That is
+// done in the begining of the G1StringDedupThread (see G1StringDedupThread::run()
+// below).
+void G1StringDedupThread::deduplicate_shared_strings(G1StringDedupStat& stat) {
+  G1StringDedupSharedClosure sharedStringDedup(stat);
+  StringTable::shared_oops_do(&sharedStringDedup);
+}
+
 void G1StringDedupThread::run() {
   G1StringDedupStat total_stat;
 
   initialize_in_thread();
   wait_for_universe_init();
+  deduplicate_shared_strings(total_stat);
 
   // Main loop
   for (;;) {
--- a/hotspot/src/share/vm/gc/g1/g1StringDedupThread.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1StringDedupThread.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -52,6 +52,8 @@
   static G1StringDedupThread* thread();
 
   virtual void run();
+
+  void deduplicate_shared_strings(G1StringDedupStat& stat);
 };
 
 #endif // SHARE_VM_GC_G1_G1STRINGDEDUPTHREAD_HPP
--- a/hotspot/src/share/vm/gc/g1/g1_globals.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1_globals.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -25,8 +25,14 @@
 #include "precompiled.hpp"
 #include "gc/g1/g1_globals.hpp"
 
-G1_FLAGS(MATERIALIZE_DEVELOPER_FLAG, MATERIALIZE_PD_DEVELOPER_FLAG, \
-         MATERIALIZE_PRODUCT_FLAG, MATERIALIZE_PD_PRODUCT_FLAG,     \
-         MATERIALIZE_DIAGNOSTIC_FLAG, MATERIALIZE_EXPERIMENTAL_FLAG, \
+G1_FLAGS(MATERIALIZE_DEVELOPER_FLAG, \
+         MATERIALIZE_PD_DEVELOPER_FLAG, \
+         MATERIALIZE_PRODUCT_FLAG, \
+         MATERIALIZE_PD_PRODUCT_FLAG,     \
+         MATERIALIZE_DIAGNOSTIC_FLAG, \
+         MATERIALIZE_EXPERIMENTAL_FLAG, \
          MATERIALIZE_NOTPRODUCT_FLAG,  \
-         MATERIALIZE_MANAGEABLE_FLAG, MATERIALIZE_PRODUCT_RW_FLAG)
+         MATERIALIZE_MANAGEABLE_FLAG, \
+         MATERIALIZE_PRODUCT_RW_FLAG, \
+         IGNORE_RANGE, \
+         IGNORE_CONSTRAINT)
--- a/hotspot/src/share/vm/gc/g1/g1_globals.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1_globals.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -30,16 +30,19 @@
 // Defines all globals flags used by the garbage-first compiler.
 //
 
-#define G1_FLAGS(develop, develop_pd, product, product_pd, diagnostic, experimental, notproduct, manageable, product_rw) \
+#define G1_FLAGS(develop, develop_pd, product, product_pd, diagnostic, experimental, notproduct, manageable, product_rw, range, constraint) \
                                                                             \
   product(uintx, G1ConfidencePercent, 50,                                   \
           "Confidence level for MMU/pause predictions")                     \
+          range(0, 100)                                                     \
                                                                             \
   develop(intx, G1MarkingOverheadPercent, 0,                                \
           "Overhead of concurrent marking")                                 \
+          range(0, 100)                                                     \
                                                                             \
   develop(intx, G1MarkingVerboseLevel, 0,                                   \
           "Level (0-4) of verboseness of the marking code")                 \
+          range(0, 4)                                                       \
                                                                             \
   develop(bool, G1TraceMarkStackOverflow, false,                            \
           "If true, extra debugging code for CM restart for ovflw.")        \
@@ -68,10 +71,12 @@
   product(double, G1ConcMarkStepDurationMillis, 10.0,                       \
           "Target duration of individual concurrent marking steps "         \
           "in milliseconds.")                                               \
+          range(1.0, (double)max_uintx)                                     \
                                                                             \
   product(intx, G1RefProcDrainInterval, 10,                                 \
           "The number of discovered reference objects to process before "   \
           "draining concurrent marking work queues.")                       \
+          range(1, max_intx)                                                \
                                                                             \
   experimental(bool, G1UseConcMarkReferenceProcessing, true,                \
           "If true, enable reference discovery during concurrent "          \
@@ -89,9 +94,11 @@
           "the percentage of retained entries is over this threshold "      \
           "the buffer will be enqueued for processing. A value of 0 "       \
           "specifies that mutator threads should not do such filtering.")   \
+          range(0, 100)                                                     \
                                                                             \
   experimental(intx, G1ExpandByPercentOfAvailable, 20,                      \
           "When expanding, % of uncommitted space to claim.")               \
+          range(0, 100)                                                     \
                                                                             \
   develop(bool, G1RSBarrierRegionFilter, true,                              \
           "If true, generate region filtering code in RS barrier")          \
@@ -138,9 +145,11 @@
                                                                             \
   product(size_t, G1ConcRSLogCacheSize, 10,                                 \
           "Log base 2 of the length of conc RS hot-card cache.")            \
+          range(0, 27)                                                      \
                                                                             \
   product(uintx, G1ConcRSHotCardLimit, 4,                                   \
           "The threshold that defines (>=) a hot card.")                    \
+          range(0, max_jubyte)                                              \
                                                                             \
   develop(intx, G1RSetRegionEntriesBase, 256,                               \
           "Max number of regions in a fine-grain table per MB.")            \
@@ -183,6 +192,7 @@
   product(uintx, G1ReservePercent, 10,                                      \
           "It determines the minimum reserve we should have in the heap "   \
           "to minimize the probability of promotion failure.")              \
+          range(0, 100)                                                     \
                                                                             \
   diagnostic(bool, G1PrintHeapRegions, false,                               \
           "If set G1 will print information on which regions are being "    \
@@ -238,22 +248,27 @@
           "The number of times we'll force an overflow during "             \
           "concurrent marking")                                             \
                                                                             \
+  experimental(uintx, G1MaxNewSizePercent, 60,                              \
+          "Percentage (0-100) of the heap size to use as default "          \
+          " maximum young gen size.")                                       \
+          range(0, 100)                                                     \
+          constraint(G1MaxNewSizePercentConstraintFunc)                     \
+                                                                            \
   experimental(uintx, G1NewSizePercent, 5,                                  \
           "Percentage (0-100) of the heap size to use as default "          \
           "minimum young gen size.")                                        \
-                                                                            \
-  experimental(uintx, G1MaxNewSizePercent, 60,                              \
-          "Percentage (0-100) of the heap size to use as default "          \
-          " maximum young gen size.")                                       \
+          constraint(G1NewSizePercentConstraintFunc)                        \
                                                                             \
   experimental(uintx, G1MixedGCLiveThresholdPercent, 85,                    \
           "Threshold for regions to be considered for inclusion in the "    \
           "collection set of mixed GCs. "                                   \
           "Regions with live bytes exceeding this will not be collected.")  \
+          range(0, 100)                                                     \
                                                                             \
   product(uintx, G1HeapWastePercent, 5,                                     \
           "Amount of space, expressed as a percentage of the heap size, "   \
           "that G1 is willing not to collect to avoid expensive GCs.")      \
+          range(0, 100)                                                     \
                                                                             \
   product(uintx, G1MixedGCCountTarget, 8,                                   \
           "The target number of mixed GCs after a marking cycle.")          \
@@ -272,6 +287,7 @@
   experimental(uintx, G1OldCSetRegionThresholdPercent, 10,                  \
           "An upper bound for the number of old CSet regions expressed "    \
           "as a percentage of the heap size.")                              \
+          range(0, 100)                                                     \
                                                                             \
   experimental(ccstr, G1LogLevel, NULL,                                     \
           "Log level for G1 logging: fine, finer, finest")                  \
@@ -314,6 +330,16 @@
   develop(bool, G1VerifyBitmaps, false,                                     \
           "Verifies the consistency of the marking bitmaps")
 
-G1_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_EXPERIMENTAL_FLAG, DECLARE_NOTPRODUCT_FLAG, DECLARE_MANAGEABLE_FLAG, DECLARE_PRODUCT_RW_FLAG)
+G1_FLAGS(DECLARE_DEVELOPER_FLAG, \
+         DECLARE_PD_DEVELOPER_FLAG, \
+         DECLARE_PRODUCT_FLAG, \
+         DECLARE_PD_PRODUCT_FLAG, \
+         DECLARE_DIAGNOSTIC_FLAG, \
+         DECLARE_EXPERIMENTAL_FLAG, \
+         DECLARE_NOTPRODUCT_FLAG, \
+         DECLARE_MANAGEABLE_FLAG, \
+         DECLARE_PRODUCT_RW_FLAG, \
+         IGNORE_RANGE, \
+         IGNORE_CONSTRAINT)
 
 #endif // SHARE_VM_GC_G1_G1_GLOBALS_HPP
--- a/hotspot/src/share/vm/gc/g1/heapRegion.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/heapRegion.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -103,6 +103,10 @@
   return HeapRegionBounds::max_size();
 }
 
+size_t HeapRegion::min_region_size_in_words() {
+  return HeapRegionBounds::min_size() >> LogHeapWordSize;
+}
+
 void HeapRegion::setup_heap_region_size(size_t initial_heap_size, size_t max_heap_size) {
   size_t region_size = G1HeapRegionSize;
   if (FLAG_IS_DEFAULT(G1HeapRegionSize)) {
@@ -711,12 +715,12 @@
         _n_failures++;
       }
 
-      if (!_g1h->full_collection() || G1VerifyRSetsDuringFullGC) {
+      if (!_g1h->collector_state()->full_collection() || G1VerifyRSetsDuringFullGC) {
         HeapRegion* from = _g1h->heap_region_containing((HeapWord*)p);
         HeapRegion* to   = _g1h->heap_region_containing(obj);
         if (from != NULL && to != NULL &&
             from != to &&
-            !to->is_humongous()) {
+            !to->is_pinned()) {
           jbyte cv_obj = *_bs->byte_for_const(_containing_obj);
           jbyte cv_field = *_bs->byte_for_const(p);
           const jbyte dirty = CardTableModRefBS::dirty_card_val();
--- a/hotspot/src/share/vm/gc/g1/heapRegion.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/heapRegion.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -331,6 +331,7 @@
   }
 
   static size_t max_region_size();
+  static size_t min_region_size_in_words();
 
   // It sets up the heap region size (GrainBytes / GrainWords), as
   // well as other related fields that are based on the heap region
@@ -417,6 +418,15 @@
 
   bool is_old() const { return _type.is_old(); }
 
+  // A pinned region contains objects which are not moved by garbage collections.
+  // Humongous regions and archive regions are pinned.
+  bool is_pinned() const { return _type.is_pinned(); }
+
+  // An archive region is a pinned region, also tagged as old, which
+  // should not be marked during mark/sweep. This allows the address
+  // space to be shared by JVM instances.
+  bool is_archive() const { return _type.is_archive(); }
+
   // For a humongous region, region in which it starts.
   HeapRegion* humongous_start_region() const {
     return _humongous_start_region;
@@ -670,6 +680,8 @@
 
   void set_old() { _type.set_old(); }
 
+  void set_archive() { _type.set_archive(); }
+
   // Determine if an object has been allocated since the last
   // mark performed by the collector. This returns true iff the object
   // is within the unmarked area of the region.
--- a/hotspot/src/share/vm/gc/g1/heapRegionManager.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/heapRegionManager.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -278,6 +278,55 @@
   return num_regions;
 }
 
+uint HeapRegionManager::find_highest_free(bool* expanded) {
+  // Loop downwards from the highest region index, looking for an
+  // entry which is either free or not yet committed.  If not yet
+  // committed, expand_at that index.
+  uint curr = max_length() - 1;
+  while (true) {
+    HeapRegion *hr = _regions.get_by_index(curr);
+    if (hr == NULL) {
+      uint res = expand_at(curr, 1);
+      if (res == 1) {
+        *expanded = true;
+        return curr;
+      }
+    } else {
+      if (hr->is_free()) {
+        *expanded = false;
+        return curr;
+      }
+    }
+    if (curr == 0) {
+      return G1_NO_HRM_INDEX;
+    }
+    curr--;
+  }
+}
+
+bool HeapRegionManager::allocate_containing_regions(MemRegion range, size_t* commit_count) {
+  size_t commits = 0;
+  uint start_index = (uint)_regions.get_index_by_address(range.start());
+  uint last_index = (uint)_regions.get_index_by_address(range.last());
+
+  // Ensure that each G1 region in the range is free, returning false if not.
+  // Commit those that are not yet available, and keep count.
+  for (uint curr_index = start_index; curr_index <= last_index; curr_index++) {
+    if (!is_available(curr_index)) {
+      commits++;
+      expand_at(curr_index, 1);
+    }
+    HeapRegion* curr_region  = _regions.get_by_index(curr_index);
+    if (!curr_region->is_free()) {
+      return false;
+    }
+  }
+
+  allocate_free_regions_starting_at(start_index, (last_index - start_index) + 1);
+  *commit_count = commits;
+  return true;
+}
+
 void HeapRegionManager::par_iterate(HeapRegionClosure* blk, uint worker_id, HeapRegionClaimer* hrclaimer, bool concurrent) const {
   const uint start_index = hrclaimer->start_region_for_worker(worker_id);
 
--- a/hotspot/src/share/vm/gc/g1/heapRegionManager.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/heapRegionManager.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -221,6 +221,16 @@
 
   HeapRegion* next_region_in_heap(const HeapRegion* r) const;
 
+  // Find the highest free or uncommitted region in the reserved heap,
+  // and if uncommitted, commit it. If none are available, return G1_NO_HRM_INDEX.
+  // Set the 'expanded' boolean true if a new region was committed.
+  uint find_highest_free(bool* expanded);
+
+  // Allocate the regions that contain the address range specified, committing the
+  // regions if necessary. Return false if any of the regions is already committed
+  // and not free, and return the number of regions newly committed in commit_count.
+  bool allocate_containing_regions(MemRegion range, size_t* commit_count);
+
   // Apply blk->doHeapRegion() on all committed regions in address order,
   // terminating the iteration early if doHeapRegion() returns true.
   void iterate(HeapRegionClosure* blk) const;
--- a/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -817,7 +817,7 @@
 // This can be done by either mutator threads together with the
 // concurrent refinement threads or GC threads.
 uint HeapRegionRemSet::num_par_rem_sets() {
-  return MAX2(DirtyCardQueueSet::num_par_ids() + ConcurrentG1Refine::thread_num(), (uint)ParallelGCThreads);
+  return MAX2(DirtyCardQueueSet::num_par_ids() + ConcurrentG1Refine::thread_num(), ParallelGCThreads);
 }
 
 HeapRegionRemSet::HeapRegionRemSet(G1BlockOffsetSharedArray* bosa,
--- a/hotspot/src/share/vm/gc/g1/heapRegionSet.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/heapRegionSet.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -42,7 +42,8 @@
   assert(hr->is_humongous() == regions_humongous(), err_msg("Wrong humongous state for region %u and set %s", hr->hrm_index(), name()));
   assert(hr->is_free() == regions_free(), err_msg("Wrong free state for region %u and set %s", hr->hrm_index(), name()));
   assert(!hr->is_free() || hr->is_empty(), err_msg("Free region %u is not empty for set %s", hr->hrm_index(), name()));
-  assert(!hr->is_empty() || hr->is_free(), err_msg("Empty region %u is not free for set %s", hr->hrm_index(), name()));
+  assert(!hr->is_empty() || hr->is_free() || hr->is_archive(),
+         err_msg("Empty region %u is not free or archive for set %s", hr->hrm_index(), name()));
   assert(hr->rem_set()->verify_ready_for_par_iteration(), err_msg("Wrong iteration state %u", hr->hrm_index()));
 }
 #endif
--- a/hotspot/src/share/vm/gc/g1/heapRegionType.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/heapRegionType.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -33,6 +33,7 @@
     case StartsHumongousTag:
     case ContinuesHumongousTag:
     case OldTag:
+    case ArchiveTag:
       return true;
   }
   return false;
@@ -47,6 +48,7 @@
     case StartsHumongousTag:    return "HUMS";
     case ContinuesHumongousTag: return "HUMC";
     case OldTag:                return "OLD";
+    case ArchiveTag:            return "ARC";
   }
   ShouldNotReachHere();
   // keep some compilers happy
@@ -62,6 +64,7 @@
     case StartsHumongousTag:    return "HS";
     case ContinuesHumongousTag: return "HC";
     case OldTag:                return "O";
+    case ArchiveTag:            return "A";
   }
   ShouldNotReachHere();
   // keep some compilers happy
--- a/hotspot/src/share/vm/gc/g1/heapRegionType.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/heapRegionType.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -44,15 +44,18 @@
   //
   // 0000 0 [ 0] Free
   //
-  // 0001 0      Young Mask
+  // 0001 0 [ 2] Young Mask
   // 0001 0 [ 2] Eden
   // 0001 1 [ 3] Survivor
   //
-  // 0010 0      Humongous Mask
-  // 0010 0 [ 4] Starts Humongous
-  // 0010 1 [ 5] Continues Humongous
+  // 0010 0 [ 4] Humongous Mask
+  // 0100 0 [ 8] Pinned Mask
+  // 0110 0 [12] Starts Humongous
+  // 0110 1 [13] Continues Humongous
   //
-  // 01000 [ 8] Old
+  // 1000 0 [16] Old Mask
+  //
+  // 1100 0 [24] Archive
   typedef enum {
     FreeTag               = 0,
 
@@ -61,10 +64,14 @@
     SurvTag               = YoungMask + 1,
 
     HumongousMask         = 4,
-    StartsHumongousTag    = HumongousMask,
-    ContinuesHumongousTag = HumongousMask + 1,
+    PinnedMask            = 8,
+    StartsHumongousTag    = HumongousMask | PinnedMask,
+    ContinuesHumongousTag = HumongousMask | PinnedMask + 1,
 
-    OldTag                = 8
+    OldMask               = 16,
+    OldTag                = OldMask,
+
+    ArchiveTag            = PinnedMask | OldMask
   } Tag;
 
   volatile Tag _tag;
@@ -108,7 +115,13 @@
   bool is_starts_humongous()    const { return get() == StartsHumongousTag;    }
   bool is_continues_humongous() const { return get() == ContinuesHumongousTag; }
 
-  bool is_old() const { return get() == OldTag; }
+  bool is_archive() const { return get() == ArchiveTag; }
+
+  // is_old regions may or may not also be pinned
+  bool is_old() const { return (get() & OldMask) != 0; }
+
+  // is_pinned regions may be archive or humongous
+  bool is_pinned() const { return (get() & PinnedMask) != 0; }
 
   // Setters
 
@@ -123,6 +136,8 @@
 
   void set_old() { set(OldTag); }
 
+  void set_archive() { set_from(ArchiveTag, FreeTag); }
+
   // Misc
 
   const char* get_str() const;
--- a/hotspot/src/share/vm/gc/parallel/gcTaskManager.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/parallel/gcTaskManager.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -484,12 +484,12 @@
 
   assert(!all_workers_active() || active_workers() == ParallelGCThreads,
          err_msg("all_workers_active() is  incorrect: "
-                 "active %d  ParallelGCThreads " UINTX_FORMAT, active_workers(),
+                 "active %d  ParallelGCThreads %u", active_workers(),
                  ParallelGCThreads));
   if (TraceDynamicGCThreads) {
     gclog_or_tty->print_cr("GCTaskManager::set_active_gang(): "
                            "all_workers_active()  %d  workers %d  "
-                           "active  %d  ParallelGCThreads " UINTX_FORMAT,
+                           "active  %d  ParallelGCThreads %u",
                            all_workers_active(), workers(),  active_workers(),
                            ParallelGCThreads);
   }
--- a/hotspot/src/share/vm/gc/parallel/pcTasks.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/parallel/pcTasks.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -255,7 +255,7 @@
     which_stack_index = which;
     assert(manager->active_workers() == ParallelGCThreads,
            err_msg("all_workers_active has been incorrectly set: "
-                   " active %d  ParallelGCThreads " UINTX_FORMAT, manager->active_workers(),
+                   " active %d  ParallelGCThreads %u", manager->active_workers(),
                    ParallelGCThreads));
   } else {
     which_stack_index = ParCompactionManager::pop_recycled_stack_index();
@@ -334,7 +334,7 @@
     which_stack_index = which;
     assert(manager->active_workers() == ParallelGCThreads,
            err_msg("all_workers_active has been incorrectly set: "
-                   " active %d  ParallelGCThreads " UINTX_FORMAT, manager->active_workers(),
+                   " active %d  ParallelGCThreads %u", manager->active_workers(),
                    ParallelGCThreads));
   } else {
     which_stack_index = stack_index();
--- a/hotspot/src/share/vm/gc/parallel/psAdaptiveSizePolicy.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/parallel/psAdaptiveSizePolicy.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -1304,7 +1304,7 @@
     size_t survived_guess = survived + promoted;
     _avg_survived->sample(survived_guess);
   }
-  avg_promoted()->sample(promoted + _avg_pretenured->padded_average());
+  avg_promoted()->sample(promoted);
 
   if (PrintAdaptiveSizePolicy) {
     gclog_or_tty->print_cr(
--- a/hotspot/src/share/vm/gc/parallel/psCompactionManager.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/parallel/psCompactionManager.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -170,8 +170,8 @@
 }
 
 ParCompactionManager*
-ParCompactionManager::gc_thread_compaction_manager(int index) {
-  assert(index >= 0 && index < (int)ParallelGCThreads, "index out of range");
+ParCompactionManager::gc_thread_compaction_manager(uint index) {
+  assert(index < ParallelGCThreads, "index out of range");
   assert(_manager_array != NULL, "Sanity");
   return _manager_array[index];
 }
--- a/hotspot/src/share/vm/gc/parallel/psCompactionManager.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/parallel/psCompactionManager.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -133,7 +133,7 @@
   RegionTaskQueue* region_stack()                { return _region_stack; }
   void set_region_stack(RegionTaskQueue* v)       { _region_stack = v; }
 
-  inline static ParCompactionManager* manager_array(int index);
+  inline static ParCompactionManager* manager_array(uint index);
 
   inline static RegionTaskQueue* region_list(int index) {
     return _region_list[index];
@@ -177,7 +177,7 @@
   void follow_class_loader(ClassLoaderData* klass);
 
   // Access function for compaction managers
-  static ParCompactionManager* gc_thread_compaction_manager(int index);
+  static ParCompactionManager* gc_thread_compaction_manager(uint index);
 
   static bool steal(int queue_num, int* seed, oop& t);
   static bool steal_objarray(int queue_num, int* seed, ObjArrayTask& t);
@@ -229,10 +229,9 @@
   };
 };
 
-inline ParCompactionManager* ParCompactionManager::manager_array(int index) {
+inline ParCompactionManager* ParCompactionManager::manager_array(uint index) {
   assert(_manager_array != NULL, "access of NULL manager_array");
-  assert(index >= 0 && index <= (int)ParallelGCThreads,
-    "out of range manager_array access");
+  assert(index <= ParallelGCThreads, "out of range manager_array access");
   return _manager_array[index];
 }
 
--- a/hotspot/src/share/vm/gc/parallel/psOldGen.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/parallel/psOldGen.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -199,7 +199,7 @@
   // Allocations in the old generation need to be reported
   if (res != NULL) {
     ParallelScavengeHeap* heap = ParallelScavengeHeap::heap();
-    heap->size_policy()->tenured_allocation(word_size);
+    heap->size_policy()->tenured_allocation(word_size * HeapWordSize);
   }
 
   return res;
--- a/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -832,10 +832,10 @@
   _ref_processor =
     new ReferenceProcessor(mr,            // span
                            ParallelRefProcEnabled && (ParallelGCThreads > 1), // mt processing
-                           (uint) ParallelGCThreads, // mt processing degree
-                           true,          // mt discovery
-                           (uint) ParallelGCThreads, // mt discovery degree
-                           true,          // atomic_discovery
+                           ParallelGCThreads, // mt processing degree
+                           true,              // mt discovery
+                           ParallelGCThreads, // mt discovery degree
+                           true,              // atomic_discovery
                            &_is_alive_closure); // non-header is alive closure
   _counters = new CollectorCounters("PSParallelCompact", 1);
 
--- a/hotspot/src/share/vm/gc/parallel/psPromotionManager.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/parallel/psPromotionManager.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -75,8 +75,8 @@
   return PSScavenge::should_scavenge(p, check_to_space);
 }
 
-PSPromotionManager* PSPromotionManager::gc_thread_promotion_manager(int index) {
-  assert(index >= 0 && index < (int)ParallelGCThreads, "index out of range");
+PSPromotionManager* PSPromotionManager::gc_thread_promotion_manager(uint index) {
+  assert(index < ParallelGCThreads, "index out of range");
   assert(_manager_array != NULL, "Sanity");
   return &_manager_array[index];
 }
--- a/hotspot/src/share/vm/gc/parallel/psPromotionManager.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/parallel/psPromotionManager.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -90,7 +90,7 @@
   static PSOldGen* old_gen()         { return _old_gen; }
   static MutableSpace* young_space() { return _young_space; }
 
-  inline static PSPromotionManager* manager_array(int index);
+  inline static PSPromotionManager* manager_array(uint index);
   template <class T> inline void claim_or_forward_internal_depth(T* p);
 
   // On the task queues we push reference locations as well as
@@ -154,7 +154,7 @@
   static void pre_scavenge();
   static bool post_scavenge(YoungGCTracer& gc_tracer);
 
-  static PSPromotionManager* gc_thread_promotion_manager(int index);
+  static PSPromotionManager* gc_thread_promotion_manager(uint index);
   static PSPromotionManager* vm_thread_promotion_manager();
 
   static bool steal_depth(int queue_num, int* seed, StarTask& t);
--- a/hotspot/src/share/vm/gc/parallel/psPromotionManager.inline.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/parallel/psPromotionManager.inline.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -33,9 +33,9 @@
 #include "gc/shared/taskqueue.inline.hpp"
 #include "oops/oop.inline.hpp"
 
-inline PSPromotionManager* PSPromotionManager::manager_array(int index) {
+inline PSPromotionManager* PSPromotionManager::manager_array(uint index) {
   assert(_manager_array != NULL, "access of NULL manager_array");
-  assert(index >= 0 && index <= (int)ParallelGCThreads, "out of range manager_array access");
+  assert(index <= ParallelGCThreads, "out of range manager_array access");
   return &_manager_array[index];
 }
 
--- a/hotspot/src/share/vm/gc/parallel/psScavenge.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/parallel/psScavenge.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -845,9 +845,9 @@
   _ref_processor =
     new ReferenceProcessor(mr,                         // span
                            ParallelRefProcEnabled && (ParallelGCThreads > 1), // mt processing
-                           (uint) ParallelGCThreads,   // mt processing degree
+                           ParallelGCThreads,          // mt processing degree
                            true,                       // mt discovery
-                           (uint) ParallelGCThreads,   // mt discovery degree
+                           ParallelGCThreads,          // mt discovery degree
                            true,                       // atomic_discovery
                            NULL);                      // header provides liveness info
 
--- a/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -58,11 +58,13 @@
 
 // Methods of protected closure types.
 
-DefNewGeneration::IsAliveClosure::IsAliveClosure(Generation* g) : _g(g) {
-  assert(g->level() == 0, "Optimized for youngest gen.");
+DefNewGeneration::IsAliveClosure::IsAliveClosure(Generation* young_gen) : _young_gen(young_gen) {
+  assert(_young_gen->kind() == Generation::ParNew ||
+         _young_gen->kind() == Generation::DefNew, "Expected the young generation here");
 }
+
 bool DefNewGeneration::IsAliveClosure::do_object_b(oop p) {
-  return (HeapWord*)p >= _g->reserved().end() || p->is_forwarded();
+  return (HeapWord*)p >= _young_gen->reserved().end() || p->is_forwarded();
 }
 
 DefNewGeneration::KeepAliveClosure::
@@ -85,39 +87,38 @@
 void DefNewGeneration::FastKeepAliveClosure::do_oop(narrowOop* p) { DefNewGeneration::FastKeepAliveClosure::do_oop_work(p); }
 
 DefNewGeneration::EvacuateFollowersClosure::
-EvacuateFollowersClosure(GenCollectedHeap* gch, int level,
-                         ScanClosure* cur, ScanClosure* older) :
-  _gch(gch), _level(level),
-  _scan_cur_or_nonheap(cur), _scan_older(older)
+EvacuateFollowersClosure(GenCollectedHeap* gch,
+                         ScanClosure* cur,
+                         ScanClosure* older) :
+  _gch(gch), _scan_cur_or_nonheap(cur), _scan_older(older)
 {}
 
 void DefNewGeneration::EvacuateFollowersClosure::do_void() {
   do {
-    _gch->oop_since_save_marks_iterate(_level, _scan_cur_or_nonheap,
-                                       _scan_older);
-  } while (!_gch->no_allocs_since_save_marks(_level));
+    _gch->oop_since_save_marks_iterate(GenCollectedHeap::YoungGen, _scan_cur_or_nonheap, _scan_older);
+  } while (!_gch->no_allocs_since_save_marks(GenCollectedHeap::YoungGen));
 }
 
 DefNewGeneration::FastEvacuateFollowersClosure::
-FastEvacuateFollowersClosure(GenCollectedHeap* gch, int level,
-                             DefNewGeneration* gen,
-                             FastScanClosure* cur, FastScanClosure* older) :
-  _gch(gch), _level(level), _gen(gen),
-  _scan_cur_or_nonheap(cur), _scan_older(older)
-{}
+FastEvacuateFollowersClosure(GenCollectedHeap* gch,
+                             FastScanClosure* cur,
+                             FastScanClosure* older) :
+  _gch(gch), _scan_cur_or_nonheap(cur), _scan_older(older)
+{
+  assert(_gch->young_gen()->kind() == Generation::DefNew, "Generation should be DefNew");
+  _gen = (DefNewGeneration*)_gch->young_gen();
+}
 
 void DefNewGeneration::FastEvacuateFollowersClosure::do_void() {
   do {
-    _gch->oop_since_save_marks_iterate(_level, _scan_cur_or_nonheap,
-                                       _scan_older);
-  } while (!_gch->no_allocs_since_save_marks(_level));
+    _gch->oop_since_save_marks_iterate(GenCollectedHeap::YoungGen, _scan_cur_or_nonheap, _scan_older);
+  } while (!_gch->no_allocs_since_save_marks(GenCollectedHeap::YoungGen));
   guarantee(_gen->promo_failure_scan_is_complete(), "Failed to finish scan");
 }
 
 ScanClosure::ScanClosure(DefNewGeneration* g, bool gc_barrier) :
     OopsInKlassOrGenClosure(g), _g(g), _gc_barrier(gc_barrier)
 {
-  assert(_g->level() == 0, "Optimized for youngest generation");
   _boundary = _g->reserved().end();
 }
 
@@ -127,7 +128,6 @@
 FastScanClosure::FastScanClosure(DefNewGeneration* g, bool gc_barrier) :
     OopsInKlassOrGenClosure(g), _g(g), _gc_barrier(gc_barrier)
 {
-  assert(_g->level() == 0, "Optimized for youngest generation");
   _boundary = _g->reserved().end();
 }
 
@@ -168,7 +168,6 @@
 ScanWeakRefClosure::ScanWeakRefClosure(DefNewGeneration* g) :
   _g(g)
 {
-  assert(_g->level() == 0, "Optimized for youngest generation");
   _boundary = _g->reserved().end();
 }
 
@@ -186,9 +185,8 @@
 
 DefNewGeneration::DefNewGeneration(ReservedSpace rs,
                                    size_t initial_size,
-                                   int level,
                                    const char* policy)
-  : Generation(rs, initial_size, level),
+  : Generation(rs, initial_size),
     _promo_failure_drain_in_progress(false),
     _should_allocate_from_space(false)
 {
@@ -372,22 +370,18 @@
   return success;
 }
 
-
 void DefNewGeneration::compute_new_size() {
-  // This is called after a gc that includes the following generation
-  // (which is required to exist.)  So from-space will normally be empty.
+  // This is called after a GC that includes the old generation, so from-space
+  // will normally be empty.
   // Note that we check both spaces, since if scavenge failed they revert roles.
-  // If not we bail out (otherwise we would have to relocate the objects)
+  // If not we bail out (otherwise we would have to relocate the objects).
   if (!from()->is_empty() || !to()->is_empty()) {
     return;
   }
 
-  int next_level = level() + 1;
   GenCollectedHeap* gch = GenCollectedHeap::heap();
-  assert(next_level == 1, "DefNewGeneration must be a young gen");
 
-  Generation* old_gen = gch->old_gen();
-  size_t old_size = old_gen->capacity();
+  size_t old_size = gch->old_gen()->capacity();
   size_t new_size_before = _virtual_space.committed_size();
   size_t min_new_size = spec()->init_size();
   size_t max_new_size = reserved().byte_size();
@@ -603,7 +597,7 @@
 
   gch->rem_set()->prepare_for_younger_refs_iterate(false);
 
-  assert(gch->no_allocs_since_save_marks(0),
+  assert(gch->no_allocs_since_save_marks(GenCollectedHeap::YoungGen),
          "save marks have not been newly set.");
 
   // Not very pretty.
@@ -619,11 +613,11 @@
                                            false);
 
   set_promo_failure_scan_stack_closure(&fsc_with_no_gc_barrier);
-  FastEvacuateFollowersClosure evacuate_followers(gch, _level, this,
+  FastEvacuateFollowersClosure evacuate_followers(gch,
                                                   &fsc_with_no_gc_barrier,
                                                   &fsc_with_gc_barrier);
 
-  assert(gch->no_allocs_since_save_marks(0),
+  assert(gch->no_allocs_since_save_marks(GenCollectedHeap::YoungGen),
          "save marks have not been newly set.");
 
   {
@@ -633,7 +627,7 @@
     StrongRootsScope srs(0);
 
     gch->gen_process_roots(&srs,
-                           _level,
+                           GenCollectedHeap::YoungGen,
                            true,  // Process younger gens, if any,
                                   // as strong roots.
                            GenCollectedHeap::SO_ScavengeCodeCache,
@@ -870,8 +864,10 @@
 
 void DefNewGeneration::contribute_scratch(ScratchBlock*& list, Generation* requestor,
                                          size_t max_alloc_words) {
-  if (requestor == this || _promotion_failed) return;
-  assert(requestor->level() > level(), "DefNewGeneration must be youngest");
+  if (requestor == this || _promotion_failed) {
+    return;
+  }
+  assert(GenCollectedHeap::heap()->is_old_gen(requestor), "We should not call our own generation");
 
   /* $$$ Assert this?  "trace" is a "MarkSweep" function so that's not appropriate.
   if (to_space->top() > to_space->bottom()) {
--- a/hotspot/src/share/vm/gc/serial/defNewGeneration.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/serial/defNewGeneration.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -154,9 +154,9 @@
 
  public:  // was "protected" but caused compile error on win32
   class IsAliveClosure: public BoolObjectClosure {
-    Generation* _g;
+    Generation* _young_gen;
   public:
-    IsAliveClosure(Generation* g);
+    IsAliveClosure(Generation* young_gen);
     bool do_object_b(oop p);
   };
 
@@ -183,31 +183,28 @@
 
   class EvacuateFollowersClosure: public VoidClosure {
     GenCollectedHeap* _gch;
-    int _level;
     ScanClosure* _scan_cur_or_nonheap;
     ScanClosure* _scan_older;
   public:
-    EvacuateFollowersClosure(GenCollectedHeap* gch, int level,
+    EvacuateFollowersClosure(GenCollectedHeap* gch,
                              ScanClosure* cur, ScanClosure* older);
     void do_void();
   };
 
   class FastEvacuateFollowersClosure: public VoidClosure {
     GenCollectedHeap* _gch;
-    int _level;
     DefNewGeneration* _gen;
     FastScanClosure* _scan_cur_or_nonheap;
     FastScanClosure* _scan_older;
   public:
-    FastEvacuateFollowersClosure(GenCollectedHeap* gch, int level,
-                                 DefNewGeneration* gen,
+    FastEvacuateFollowersClosure(GenCollectedHeap* gch,
                                  FastScanClosure* cur,
                                  FastScanClosure* older);
     void do_void();
   };
 
  public:
-  DefNewGeneration(ReservedSpace rs, size_t initial_byte_size, int level,
+  DefNewGeneration(ReservedSpace rs, size_t initial_byte_size,
                    const char* policy="Copy");
 
   virtual void ref_processor_init();
--- a/hotspot/src/share/vm/gc/serial/genMarkSweep.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/serial/genMarkSweep.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -36,6 +36,7 @@
 #include "gc/shared/gcTrace.hpp"
 #include "gc/shared/gcTraceTime.hpp"
 #include "gc/shared/genCollectedHeap.hpp"
+#include "gc/shared/generation.hpp"
 #include "gc/shared/genOopClosures.inline.hpp"
 #include "gc/shared/modRefBarrierSet.hpp"
 #include "gc/shared/referencePolicy.hpp"
@@ -53,8 +54,7 @@
 #include "utilities/events.hpp"
 #include "utilities/stack.inline.hpp"
 
-void GenMarkSweep::invoke_at_safepoint(int level, ReferenceProcessor* rp, bool clear_all_softrefs) {
-  guarantee(level == 1, "We always collect both old and young.");
+void GenMarkSweep::invoke_at_safepoint(ReferenceProcessor* rp, bool clear_all_softrefs) {
   assert(SafepointSynchronize::is_at_safepoint(), "must be at a safepoint");
 
   GenCollectedHeap* gch = GenCollectedHeap::heap();
@@ -87,11 +87,11 @@
   // Capture used regions for each generation that will be
   // subject to collection, so that card table adjustments can
   // be made intelligently (see clear / invalidate further below).
-  gch->save_used_regions(level);
+  gch->save_used_regions();
 
   allocate_stacks();
 
-  mark_sweep_phase1(level, clear_all_softrefs);
+  mark_sweep_phase1(clear_all_softrefs);
 
   mark_sweep_phase2();
 
@@ -99,7 +99,7 @@
   COMPILER2_PRESENT(assert(DerivedPointerTable::is_active(), "Sanity"));
   COMPILER2_PRESENT(DerivedPointerTable::set_active(false));
 
-  mark_sweep_phase3(level);
+  mark_sweep_phase3();
 
   mark_sweep_phase4();
 
@@ -184,8 +184,7 @@
   _objarray_stack.clear(true);
 }
 
-void GenMarkSweep::mark_sweep_phase1(int level,
-                                     bool clear_all_softrefs) {
+void GenMarkSweep::mark_sweep_phase1(bool clear_all_softrefs) {
   // Recursively traverse all live objects and mark them
   GCTraceTime tm("phase 1", PrintGC && Verbose, true, _gc_timer, _gc_tracer->gc_id());
 
@@ -195,7 +194,6 @@
   // use OopsInGenClosure constructor which takes a generation,
   // as the Universe has not been created when the static constructors
   // are run.
-  assert(level == 1, "We don't use mark-sweep on young generations");
   follow_root_closure.set_orig_generation(gch->old_gen());
 
   // Need new claim bits before marking starts.
@@ -205,10 +203,10 @@
     StrongRootsScope srs(1);
 
     gch->gen_process_roots(&srs,
-                           level,
+                           GenCollectedHeap::OldGen,
                            false, // Younger gens are not roots.
                            GenCollectedHeap::SO_None,
-                           GenCollectedHeap::StrongRootsOnly,
+                           ClassUnloading,
                            &follow_root_closure,
                            &follow_root_closure,
                            &follow_cld_closure);
@@ -273,7 +271,7 @@
   }
 };
 
-void GenMarkSweep::mark_sweep_phase3(int level) {
+void GenMarkSweep::mark_sweep_phase3() {
   GenCollectedHeap* gch = GenCollectedHeap::heap();
 
   // Adjust the pointers to reflect the new locations
@@ -286,14 +284,13 @@
   // use OopsInGenClosure constructor which takes a generation,
   // as the Universe has not been created when the static constructors
   // are run.
-  assert(level == 1, "We don't use mark-sweep on young generations.");
   adjust_pointer_closure.set_orig_generation(gch->old_gen());
 
   {
     StrongRootsScope srs(1);
 
     gch->gen_process_roots(&srs,
-                           level,
+                           GenCollectedHeap::OldGen,
                            false, // Younger gens are not roots.
                            GenCollectedHeap::SO_AllCodeCache,
                            GenCollectedHeap::StrongAndWeakRoots,
--- a/hotspot/src/share/vm/gc/serial/genMarkSweep.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/serial/genMarkSweep.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -31,17 +31,16 @@
   friend class VM_MarkSweep;
   friend class G1MarkSweep;
  public:
-  static void invoke_at_safepoint(int level, ReferenceProcessor* rp,
-                                  bool clear_all_softrefs);
+  static void invoke_at_safepoint(ReferenceProcessor* rp, bool clear_all_softrefs);
 
  private:
 
   // Mark live objects
-  static void mark_sweep_phase1(int level, bool clear_all_softrefs);
+  static void mark_sweep_phase1(bool clear_all_softrefs);
   // Calculate new addresses
   static void mark_sweep_phase2();
   // Update pointers
-  static void mark_sweep_phase3(int level);
+  static void mark_sweep_phase3();
   // Move objects to new positions
   static void mark_sweep_phase4();
 
--- a/hotspot/src/share/vm/gc/serial/markSweep.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/serial/markSweep.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -313,7 +313,7 @@
 
 MarkSweep::IsAliveClosure   MarkSweep::is_alive;
 
-bool MarkSweep::IsAliveClosure::do_object_b(oop p) { return p->is_gc_marked(); }
+bool MarkSweep::IsAliveClosure::do_object_b(oop p) { return p->is_gc_marked() || is_archive_object(p); }
 
 MarkSweep::KeepAliveClosure MarkSweep::keep_alive;
 
--- a/hotspot/src/share/vm/gc/serial/markSweep.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/serial/markSweep.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -147,6 +147,9 @@
   // Reference Processing
   static ReferenceProcessor* const ref_processor() { return _ref_processor; }
 
+  // Archive Object handling
+  static inline bool is_archive_object(oop object);
+
   static STWGCTimer* gc_timer() { return _gc_timer; }
   static SerialOldTracer* gc_tracer() { return _gc_tracer; }
 
--- a/hotspot/src/share/vm/gc/serial/markSweep.inline.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/serial/markSweep.inline.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -37,6 +37,7 @@
 #include "utilities/stack.inline.hpp"
 #if INCLUDE_ALL_GCS
 #include "gc/g1/g1StringDedup.hpp"
+#include "gc/g1/g1MarkSweep.hpp"
 #endif // INCLUDE_ALL_GCS
 
 inline void MarkSweep::mark_object(oop obj) {
@@ -57,6 +58,15 @@
   }
 }
 
+inline bool MarkSweep::is_archive_object(oop object) {
+#if INCLUDE_ALL_GCS
+  return (G1MarkSweep::archive_check_enabled() &&
+          G1MarkSweep::in_archive_range(object));
+#else
+  return false;
+#endif
+}
+
 inline void MarkSweep::follow_klass(Klass* klass) {
   oop op = klass->klass_holder();
   MarkSweep::mark_and_push(&op);
@@ -74,7 +84,8 @@
   T heap_oop = oopDesc::load_heap_oop(p);
   if (!oopDesc::is_null(heap_oop)) {
     oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
-    if (!obj->mark()->is_marked()) {
+    if (!obj->mark()->is_marked() &&
+        !is_archive_object(obj)) {
       mark_object(obj);
       follow_object(obj);
     }
@@ -87,7 +98,8 @@
   T heap_oop = oopDesc::load_heap_oop(p);
   if (!oopDesc::is_null(heap_oop)) {
     oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
-    if (!obj->mark()->is_marked()) {
+    if (!obj->mark()->is_marked() &&
+        !is_archive_object(obj)) {
       mark_object(obj);
       _marking_stack.push(obj);
     }
@@ -111,15 +123,18 @@
     assert(Universe::heap()->is_in(obj), "should be in heap");
 
     oop new_obj = oop(obj->mark()->decode_pointer());
-    assert(new_obj != NULL ||                         // is forwarding ptr?
+    assert(is_archive_object(obj) ||                  // no forwarding of archive objects
+           new_obj != NULL ||                         // is forwarding ptr?
            obj->mark() == markOopDesc::prototype() || // not gc marked?
            (UseBiasedLocking && obj->mark()->has_bias_pattern()),
-                                                      // not gc marked?
+           // not gc marked?
            "should be forwarded");
     if (new_obj != NULL) {
-      assert(Universe::heap()->is_in_reserved(new_obj),
-             "should be in object space");
-      oopDesc::encode_store_heap_oop_not_null(p, new_obj);
+      if (!is_archive_object(obj)) {
+        assert(Universe::heap()->is_in_reserved(new_obj),
+              "should be in object space");
+        oopDesc::encode_store_heap_oop_not_null(p, new_obj);
+      }
     }
   }
 }
--- a/hotspot/src/share/vm/gc/serial/tenuredGeneration.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/serial/tenuredGeneration.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -41,9 +41,9 @@
 #endif
 
 TenuredGeneration::TenuredGeneration(ReservedSpace rs,
-                                     size_t initial_byte_size, int level,
+                                     size_t initial_byte_size,
                                      GenRemSet* remset) :
-  CardGeneration(rs, initial_byte_size, level, remset)
+  CardGeneration(rs, initial_byte_size, remset)
 {
   HeapWord* bottom = (HeapWord*) _virtual_space.low();
   HeapWord* end    = (HeapWord*) _virtual_space.high();
@@ -134,11 +134,12 @@
          " capacity: " SIZE_FORMAT, used(), used_after_gc, capacity()));
 }
 
-void TenuredGeneration::update_gc_stats(int current_level,
+void TenuredGeneration::update_gc_stats(Generation* current_generation,
                                         bool full) {
-  // If the next lower level(s) has been collected, gather any statistics
+  // If the young generation has been collected, gather any statistics
   // that are of interest at this point.
-  if (!full && (current_level + 1) == level()) {
+  bool current_is_young = GenCollectedHeap::heap()->is_young_gen(current_generation);
+  if (!full && current_is_young) {
     // Calculate size of data promoted from the younger generations
     // before doing the collection.
     size_t used_before_gc = used();
@@ -192,7 +193,7 @@
   SerialOldTracer* gc_tracer = GenMarkSweep::gc_tracer();
   gc_tracer->report_gc_start(gch->gc_cause(), gc_timer->gc_start());
 
-  GenMarkSweep::invoke_at_safepoint(_level, ref_processor(), clear_all_soft_refs);
+  GenMarkSweep::invoke_at_safepoint(ref_processor(), clear_all_soft_refs);
 
   gc_timer->register_gc_end();
 
--- a/hotspot/src/share/vm/gc/serial/tenuredGeneration.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/serial/tenuredGeneration.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -55,8 +55,9 @@
 
   void assert_correct_size_change_locking();
  public:
-  TenuredGeneration(ReservedSpace rs, size_t initial_byte_size,
-                               int level, GenRemSet* remset);
+  TenuredGeneration(ReservedSpace rs,
+                    size_t initial_byte_size,
+                    GenRemSet* remset);
 
   Generation::Name kind() { return Generation::MarkSweepCompact; }
 
@@ -120,7 +121,7 @@
 
   // Statistics
 
-  virtual void update_gc_stats(int level, bool full);
+  virtual void update_gc_stats(Generation* current_generation, bool full);
 
   virtual bool promotion_attempt_is_safe(size_t max_promoted_in_bytes) const;
 
--- a/hotspot/src/share/vm/gc/shared/cardGeneration.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/shared/cardGeneration.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -35,10 +35,10 @@
 #include "memory/memRegion.hpp"
 #include "runtime/java.hpp"
 
-CardGeneration::CardGeneration(ReservedSpace rs, size_t initial_byte_size,
-                               int level,
+CardGeneration::CardGeneration(ReservedSpace rs,
+                               size_t initial_byte_size,
                                GenRemSet* remset) :
-  Generation(rs, initial_byte_size, level), _rs(remset),
+  Generation(rs, initial_byte_size), _rs(remset),
   _shrink_factor(0), _min_heap_delta_bytes(), _capacity_at_prologue(),
   _used_at_prologue()
 {
--- a/hotspot/src/share/vm/gc/shared/cardGeneration.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/shared/cardGeneration.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -52,8 +52,7 @@
   size_t _capacity_at_prologue;
   size_t _used_at_prologue;
 
-  CardGeneration(ReservedSpace rs, size_t initial_byte_size, int level,
-                 GenRemSet* remset);
+  CardGeneration(ReservedSpace rs, size_t initial_byte_size, GenRemSet* remset);
 
   virtual void assert_correct_size_change_locking() = 0;
 
--- a/hotspot/src/share/vm/gc/shared/cardTableRS.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/shared/cardTableRS.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -104,7 +104,9 @@
 void CardTableRS::younger_refs_iterate(Generation* g,
                                        OopsInGenClosure* blk,
                                        uint n_threads) {
-  _last_cur_val_in_gen[g->level()+1] = cur_youngergen_card_val();
+  // The indexing in this array is slightly odd. We want to access
+  // the old generation record here, which is at index 2.
+  _last_cur_val_in_gen[2] = cur_youngergen_card_val();
   g->younger_refs_iterate(blk, n_threads);
 }
 
@@ -300,7 +302,8 @@
 }
 
 void CardTableRS::clear_into_younger(Generation* old_gen) {
-  assert(old_gen->level() == 1, "Should only be called for the old generation");
+  assert(GenCollectedHeap::heap()->is_old_gen(old_gen),
+         "Should only be called for the old generation");
   // The card tables for the youngest gen need never be cleared.
   // There's a bit of subtlety in the clear() and invalidate()
   // methods that we exploit here and in invalidate_or_clear()
@@ -311,7 +314,8 @@
 }
 
 void CardTableRS::invalidate_or_clear(Generation* old_gen) {
-  assert(old_gen->level() == 1, "Should only be called for the old generation");
+  assert(GenCollectedHeap::heap()->is_old_gen(old_gen),
+         "Should only be called for the old generation");
   // Invalidate the cards for the currently occupied part of
   // the old generation and clear the cards for the
   // unoccupied part of the generation (if any, making use
@@ -377,7 +381,9 @@
   VerifyCTGenClosure(CardTableRS* ct) : _ct(ct) {}
   void do_generation(Generation* gen) {
     // Skip the youngest generation.
-    if (gen->level() == 0) return;
+    if (GenCollectedHeap::heap()->is_young_gen(gen)) {
+      return;
+    }
     // Normally, we're interested in pointers to younger generations.
     VerifyCTSpaceClosure blk(_ct, gen->reserved().start());
     gen->space_iterate(&blk, true);
--- a/hotspot/src/share/vm/gc/shared/cardTableRS.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/shared/cardTableRS.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -76,9 +76,8 @@
 
   // An array that contains, for each generation, the card table value last
   // used as the current value for a younger_refs_do iteration of that
-  // portion of the table.  (The perm gen is index 0; other gens are at
-  // their level plus 1.  They youngest gen is in the table, but will
-  // always have the value "clean_card".)
+  // portion of the table. The perm gen is index 0. The young gen is index 1,
+  // but will always have the value "clean_card". The old gen is index 2.
   jbyte* _last_cur_val_in_gen;
 
   jbyte _cur_youngergen_card_val;
--- a/hotspot/src/share/vm/gc/shared/collectedHeap.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/shared/collectedHeap.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -88,9 +88,6 @@
   static int       _fire_out_of_memory_count;
 #endif
 
-  // Used for filler objects (static, but initialized in ctor).
-  static size_t _filler_array_max_size;
-
   GCHeapLog* _gc_heap_log;
 
   // Used in support of ReduceInitialCardMarks; only consulted if COMPILER2 is being used
@@ -102,6 +99,9 @@
   BarrierSet* _barrier_set;
   bool _is_gc_active;
 
+  // Used for filler objects (static, but initialized in ctor).
+  static size_t _filler_array_max_size;
+
   unsigned int _total_collections;          // ... started
   unsigned int _total_full_collections;     // ... started
   NOT_PRODUCT(volatile size_t _promotion_failure_alot_count;)
--- a/hotspot/src/share/vm/gc/shared/collectorPolicy.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/shared/collectorPolicy.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -746,11 +746,11 @@
     return result;   // Could be null if we are out of space.
   } else if (!gch->incremental_collection_will_fail(false /* don't consult_young */)) {
     // Do an incremental collection.
-    gch->do_collection(false            /* full */,
-                       false            /* clear_all_soft_refs */,
-                       size             /* size */,
-                       is_tlab          /* is_tlab */,
-                       number_of_generations() - 1 /* max_level */);
+    gch->do_collection(false,                     // full
+                       false,                     // clear_all_soft_refs
+                       size,                      // size
+                       is_tlab,                   // is_tlab
+                       GenCollectedHeap::OldGen); // max_generation
   } else {
     if (Verbose && PrintGCDetails) {
       gclog_or_tty->print(" :: Trying full because partial may fail :: ");
@@ -759,11 +759,11 @@
     // for the original code and why this has been simplified
     // with from-space allocation criteria modified and
     // such allocation moved out of the safepoint path.
-    gch->do_collection(true             /* full */,
-                       false            /* clear_all_soft_refs */,
-                       size             /* size */,
-                       is_tlab          /* is_tlab */,
-                       number_of_generations() - 1 /* max_level */);
+    gch->do_collection(true,                      // full
+                       false,                     // clear_all_soft_refs
+                       size,                      // size
+                       is_tlab,                   // is_tlab
+                       GenCollectedHeap::OldGen); // max_generation
   }
 
   result = gch->attempt_allocation(size, is_tlab, false /*first_only*/);
@@ -787,11 +787,11 @@
   {
     UIntXFlagSetting flag_change(MarkSweepAlwaysCompactCount, 1); // Make sure the heap is fully compacted
 
-    gch->do_collection(true             /* full */,
-                       true             /* clear_all_soft_refs */,
-                       size             /* size */,
-                       is_tlab          /* is_tlab */,
-                       number_of_generations() - 1 /* max_level */);
+    gch->do_collection(true,                      // full
+                       true,                      // clear_all_soft_refs
+                       size,                      // size
+                       is_tlab,                   // is_tlab
+                       GenCollectedHeap::OldGen); // max_generation
   }
 
   result = gch->attempt_allocation(size, is_tlab, false /* first_only */);
--- a/hotspot/src/share/vm/gc/shared/collectorPolicy.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/shared/collectorPolicy.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -261,8 +261,6 @@
   size_t initial_old_size()   { return _initial_old_size; }
   size_t max_old_size()       { return _max_old_size; }
 
-  int number_of_generations() { return 2; }
-
   GenerationSpec* young_gen_spec() const {
     assert(_young_gen_spec != NULL, "_young_gen_spec should have been initialized");
     return _young_gen_spec;
--- a/hotspot/src/share/vm/gc/shared/gcHeapSummary.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/shared/gcHeapSummary.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -78,11 +78,13 @@
 
 class GCHeapSummary;
 class PSHeapSummary;
+class G1HeapSummary;
 
 class GCHeapSummaryVisitor {
  public:
   virtual void visit(const GCHeapSummary* heap_summary) const = 0;
   virtual void visit(const PSHeapSummary* heap_summary) const {}
+  virtual void visit(const G1HeapSummary* heap_summary) const {}
 };
 
 class GCHeapSummary : public StackObj {
@@ -125,6 +127,22 @@
    }
 };
 
+class G1HeapSummary : public GCHeapSummary {
+  size_t  _edenUsed;
+  size_t  _edenCapacity;
+  size_t  _survivorUsed;
+ public:
+   G1HeapSummary(VirtualSpaceSummary& heap_space, size_t heap_used, size_t edenUsed, size_t edenCapacity, size_t survivorUsed) :
+       GCHeapSummary(heap_space, heap_used), _edenUsed(edenUsed), _edenCapacity(edenCapacity), _survivorUsed(survivorUsed) { }
+   const size_t edenUsed() const { return _edenUsed; }
+   const size_t edenCapacity() const { return _edenCapacity; }
+   const size_t survivorUsed() const { return _survivorUsed; }
+
+   virtual void accept(GCHeapSummaryVisitor* visitor) const {
+     visitor->visit(this);
+   }
+};
+
 class MetaspaceSummary : public StackObj {
   size_t _capacity_until_GC;
   MetaspaceSizes _meta_space;
--- a/hotspot/src/share/vm/gc/shared/gcTrace.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/shared/gcTrace.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -44,6 +44,7 @@
 class MetaspaceChunkFreeListSummary;
 class MetaspaceSummary;
 class PSHeapSummary;
+class G1HeapSummary;
 class ReferenceProcessorStats;
 class TimePartitions;
 class BoolObjectClosure;
--- a/hotspot/src/share/vm/gc/shared/gcTraceSend.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/shared/gcTraceSend.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -263,6 +263,20 @@
     }
   }
 
+  void visit(const G1HeapSummary* g1_heap_summary) const {
+    visit((GCHeapSummary*)g1_heap_summary);
+
+    EventG1HeapSummary e;
+    if (e.should_commit()) {
+      e.set_gcId(_gc_id.id());
+      e.set_when((u1)_when);
+      e.set_edenUsedSize(g1_heap_summary->edenUsed());
+      e.set_edenTotalSize(g1_heap_summary->edenCapacity());
+      e.set_survivorUsedSize(g1_heap_summary->survivorUsed());
+      e.commit();
+    }
+  }
+
   void visit(const PSHeapSummary* ps_heap_summary) const {
     visit((GCHeapSummary*)ps_heap_summary);
 
--- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -127,11 +127,11 @@
   set_barrier_set(rem_set()->bs());
 
   ReservedSpace young_rs = heap_rs.first_part(gen_policy()->young_gen_spec()->max_size(), false, false);
-  _young_gen = gen_policy()->young_gen_spec()->init(young_rs, 0, rem_set());
+  _young_gen = gen_policy()->young_gen_spec()->init(young_rs, rem_set());
   heap_rs = heap_rs.last_part(gen_policy()->young_gen_spec()->max_size());
 
   ReservedSpace old_rs = heap_rs.first_part(gen_policy()->old_gen_spec()->max_size(), false, false);
-  _old_gen = gen_policy()->old_gen_spec()->init(old_rs, 1, rem_set());
+  _old_gen = gen_policy()->old_gen_spec()->init(old_rs, rem_set());
   clear_incremental_collection_failed();
 
 #if INCLUDE_ALL_GCS
@@ -202,12 +202,8 @@
   return _young_gen->used() + _old_gen->used();
 }
 
-// Save the "used_region" for generations level and lower.
-void GenCollectedHeap::save_used_regions(int level) {
-  assert(level == 0 || level == 1, "Illegal level parameter");
-  if (level == 1) {
-    _old_gen->save_used_region();
-  }
+void GenCollectedHeap::save_used_regions() {
+  _old_gen->save_used_region();
   _young_gen->save_used_region();
 }
 
@@ -337,8 +333,16 @@
   record_gen_tops_before_GC();
 
   if (PrintGC && Verbose) {
-    gclog_or_tty->print("level=%d invoke=%d size=" SIZE_FORMAT,
-                        gen->level(),
+    // I didn't want to change the logging when removing the level concept,
+    // but I guess this logging could say young/old or something instead of 0/1.
+    uint level;
+    if (heap()->is_young_gen(gen)) {
+      level = 0;
+    } else {
+      level = 1;
+    }
+    gclog_or_tty->print("level=%u invoke=%d size=" SIZE_FORMAT,
+                        level,
                         gen->stat_record()->invocations,
                         size * HeapWordSize);
   }
@@ -399,7 +403,7 @@
 
   gen->stat_record()->accumulated_time.stop();
 
-  update_gc_stats(gen->level(), full);
+  update_gc_stats(gen, full);
 
   if (run_verification && VerifyAfterGC) {
     HandleMark hm;  // Discard invalid handles created during verification
@@ -412,11 +416,11 @@
   }
 }
 
-void GenCollectedHeap::do_collection(bool   full,
-                                     bool   clear_all_soft_refs,
-                                     size_t size,
-                                     bool   is_tlab,
-                                     int    max_level) {
+void GenCollectedHeap::do_collection(bool           full,
+                                     bool           clear_all_soft_refs,
+                                     size_t         size,
+                                     bool           is_tlab,
+                                     GenerationType max_generation) {
   ResourceMark rm;
   DEBUG_ONLY(Thread* my_thread = Thread::current();)
 
@@ -444,7 +448,7 @@
   {
     FlagSetting fl(_is_gc_active, true);
 
-    bool complete = full && (max_level == 1 /* old */);
+    bool complete = full && (max_generation == OldGen);
     const char* gc_cause_prefix = complete ? "Full GC" : "GC";
     TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
     // The PrintGCDetails logging starts before we have incremented the GC id. We will do that later
@@ -458,9 +462,8 @@
     bool run_verification = total_collections() >= VerifyGCStartAt;
 
     bool prepared_for_verification = false;
-    int max_level_collected = 0;
-    bool old_collects_young = (max_level == 1) &&
-                              full &&
+    bool collected_old = false;
+    bool old_collects_young = complete &&
                               _old_gen->full_collects_younger_generations();
     if (!old_collects_young &&
         _young_gen->should_collect(full, size, is_tlab)) {
@@ -487,7 +490,7 @@
 
     bool must_restore_marks_for_biased_locking = false;
 
-    if (max_level == 1 && _old_gen->should_collect(full, size, is_tlab)) {
+    if (max_generation == OldGen && _old_gen->should_collect(full, size, is_tlab)) {
       if (!complete) {
         // The full_collections increment was missed above.
         increment_total_full_collections();
@@ -510,13 +513,13 @@
                          true);
 
       must_restore_marks_for_biased_locking = true;
-      max_level_collected = 1;
+      collected_old = true;
     }
 
     // Update "complete" boolean wrt what actually transpired --
     // for instance, a promotion failure could have led to
     // a whole heap collection.
-    complete = complete || (max_level_collected == 1 /* old */);
+    complete = complete || collected_old;
 
     if (complete) { // We did a "major" collection
       // FIXME: See comment at pre_full_gc_dump call
@@ -533,7 +536,7 @@
     }
 
     // Adjust generation sizes.
-    if (max_level_collected == 1 /* old */) {
+    if (collected_old) {
       _old_gen->compute_new_size();
     }
     _young_gen->compute_new_size();
@@ -661,11 +664,10 @@
     DEBUG_ONLY(CodeBlobToOopClosure assert_code_is_non_scavengable(&assert_is_non_scavengable_closure, !CodeBlobToOopClosure::FixRelocations));
     DEBUG_ONLY(CodeCache::asserted_non_scavengable_nmethods_do(&assert_code_is_non_scavengable));
   }
-
 }
 
 void GenCollectedHeap::gen_process_roots(StrongRootsScope* scope,
-                                         int level,
+                                         GenerationType type,
                                          bool younger_gens_as_roots,
                                          ScanningOption so,
                                          bool only_strong_roots,
@@ -675,7 +677,7 @@
   const bool is_adjust_phase = !only_strong_roots && !younger_gens_as_roots;
 
   bool is_moving_collection = false;
-  if (level == 0 || is_adjust_phase) {
+  if (type == YoungGen || is_adjust_phase) {
     // young collections are always moving
     is_moving_collection = true;
   }
@@ -691,7 +693,7 @@
 
   if (younger_gens_as_roots) {
     if (!_process_strong_tasks->is_task_claimed(GCH_PS_younger_gens)) {
-      if (level == 1) {
+      if (type == OldGen) {
         not_older_gens->set_generation(_young_gen);
         _young_gen->oop_iterate(not_older_gens);
       }
@@ -699,8 +701,8 @@
     }
   }
   // When collection is parallel, all threads get to cooperate to do
-  // older-gen scanning.
-  if (level == 0) {
+  // old generation scanning.
+  if (type == YoungGen) {
     older_gens->set_generation(_old_gen);
     rem_set()->younger_refs_iterate(_old_gen, older_gens, scope->n_threads());
     older_gens->reset_generation();
@@ -724,10 +726,10 @@
 
 #define GCH_SINCE_SAVE_MARKS_ITERATE_DEFN(OopClosureType, nv_suffix)    \
 void GenCollectedHeap::                                                 \
-oop_since_save_marks_iterate(int level,                                 \
+oop_since_save_marks_iterate(GenerationType gen,                        \
                              OopClosureType* cur,                       \
                              OopClosureType* older) {                   \
-  if (level == 0) {                                                     \
+  if (gen == YoungGen) {                              \
     _young_gen->oop_since_save_marks_iterate##nv_suffix(cur);           \
     _old_gen->oop_since_save_marks_iterate##nv_suffix(older);           \
   } else {                                                              \
@@ -739,8 +741,8 @@
 
 #undef GCH_SINCE_SAVE_MARKS_ITERATE_DEFN
 
-bool GenCollectedHeap::no_allocs_since_save_marks(int level) {
-  if (level == 0 && !_young_gen->no_allocs_since_save_marks()) {
+bool GenCollectedHeap::no_allocs_since_save_marks(bool include_young) {
+  if (include_young && !_young_gen->no_allocs_since_save_marks()) {
     return false;
   }
   return _old_gen->no_allocs_since_save_marks();
@@ -770,47 +772,47 @@
 #endif // INCLUDE_ALL_GCS
   } else if (cause == GCCause::_wb_young_gc) {
     // minor collection for WhiteBox API
-    collect(cause, 0 /* young */);
+    collect(cause, YoungGen);
   } else {
 #ifdef ASSERT
   if (cause == GCCause::_scavenge_alot) {
     // minor collection only
-    collect(cause, 0 /* young */);
+    collect(cause, YoungGen);
   } else {
     // Stop-the-world full collection
-    collect(cause, 1 /* old */);
+    collect(cause, OldGen);
   }
 #else
     // Stop-the-world full collection
-    collect(cause, 1 /* old */);
+    collect(cause, OldGen);
 #endif
   }
 }
 
-void GenCollectedHeap::collect(GCCause::Cause cause, int max_level) {
+void GenCollectedHeap::collect(GCCause::Cause cause, GenerationType max_generation) {
   // The caller doesn't have the Heap_lock
   assert(!Heap_lock->owned_by_self(), "this thread should not own the Heap_lock");
   MutexLocker ml(Heap_lock);
-  collect_locked(cause, max_level);
+  collect_locked(cause, max_generation);
 }
 
 void GenCollectedHeap::collect_locked(GCCause::Cause cause) {
   // The caller has the Heap_lock
   assert(Heap_lock->owned_by_self(), "this thread should own the Heap_lock");
-  collect_locked(cause, 1 /* old */);
+  collect_locked(cause, OldGen);
 }
 
 // this is the private collection interface
 // The Heap_lock is expected to be held on entry.
 
-void GenCollectedHeap::collect_locked(GCCause::Cause cause, int max_level) {
+void GenCollectedHeap::collect_locked(GCCause::Cause cause, GenerationType max_generation) {
   // Read the GC count while holding the Heap_lock
   unsigned int gc_count_before      = total_collections();
   unsigned int full_gc_count_before = total_full_collections();
   {
     MutexUnlocker mu(Heap_lock);  // give up heap lock, execute gets it back
     VM_GenCollectFull op(gc_count_before, full_gc_count_before,
-                         cause, max_level);
+                         cause, max_generation);
     VMThread::execute(&op);
   }
 }
@@ -853,39 +855,39 @@
 #endif // INCLUDE_ALL_GCS
 
 void GenCollectedHeap::do_full_collection(bool clear_all_soft_refs) {
-   do_full_collection(clear_all_soft_refs, 1 /* old */);
+   do_full_collection(clear_all_soft_refs, OldGen);
 }
 
 void GenCollectedHeap::do_full_collection(bool clear_all_soft_refs,
-                                          int max_level) {
-  int local_max_level;
+                                          GenerationType last_generation) {
+  GenerationType local_last_generation;
   if (!incremental_collection_will_fail(false /* don't consult_young */) &&
       gc_cause() == GCCause::_gc_locker) {
-    local_max_level = 0;
+    local_last_generation = YoungGen;
   } else {
-    local_max_level = max_level;
+    local_last_generation = last_generation;
   }
 
-  do_collection(true                 /* full */,
-                clear_all_soft_refs  /* clear_all_soft_refs */,
-                0                    /* size */,
-                false                /* is_tlab */,
-                local_max_level      /* max_level */);
+  do_collection(true,                   // full
+                clear_all_soft_refs,    // clear_all_soft_refs
+                0,                      // size
+                false,                  // is_tlab
+                local_last_generation); // last_generation
   // Hack XXX FIX ME !!!
   // A scavenge may not have been attempted, or may have
   // been attempted and failed, because the old gen was too full
-  if (local_max_level == 0 && gc_cause() == GCCause::_gc_locker &&
+  if (local_last_generation == YoungGen && gc_cause() == GCCause::_gc_locker &&
       incremental_collection_will_fail(false /* don't consult_young */)) {
     if (PrintGCDetails) {
       gclog_or_tty->print_cr("GC locker: Trying a full collection "
                              "because scavenge failed");
     }
     // This time allow the old gen to be collected as well
-    do_collection(true                 /* full */,
-                  clear_all_soft_refs  /* clear_all_soft_refs */,
-                  0                    /* size */,
-                  false                /* is_tlab */,
-                  1  /* old */         /* max_level */);
+    do_collection(true,                // full
+                  clear_all_soft_refs, // clear_all_soft_refs
+                  0,                   // size
+                  false,               // is_tlab
+                  OldGen);             // last_generation
   }
 }
 
@@ -1108,12 +1110,8 @@
   _young_gen->prepare_for_compaction(&cp);
 }
 
-GCStats* GenCollectedHeap::gc_stats(int level) const {
-  if (level == 0) {
-    return _young_gen->gc_stats();
-  } else {
-    return _old_gen->gc_stats();
-  }
+GCStats* GenCollectedHeap::gc_stats(Generation* gen) const {
+  return gen->gc_stats();
 }
 
 void GenCollectedHeap::verify(bool silent, VerifyOption option /* ignored */) {
@@ -1283,7 +1281,7 @@
 oop GenCollectedHeap::handle_failed_promotion(Generation* old_gen,
                                               oop obj,
                                               size_t obj_size) {
-  guarantee(old_gen->level() == 1, "We only get here with an old generation");
+  guarantee(old_gen == _old_gen, "We only get here with an old generation");
   assert(obj_size == (size_t)obj->size(), "bad obj_size passed in");
   HeapWord* result = NULL;
 
--- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -55,6 +55,11 @@
 public:
   friend class VM_PopulateDumpSharedSpace;
 
+  enum GenerationType {
+    YoungGen,
+    OldGen
+  };
+
 private:
   Generation* _young_gen;
   Generation* _old_gen;
@@ -95,11 +100,11 @@
 
   // Helper function for two callbacks below.
   // Considers collection of the first max_level+1 generations.
-  void do_collection(bool   full,
-                     bool   clear_all_soft_refs,
-                     size_t size,
-                     bool   is_tlab,
-                     int    max_level);
+  void do_collection(bool           full,
+                     bool           clear_all_soft_refs,
+                     size_t         size,
+                     bool           is_tlab,
+                     GenerationType max_generation);
 
   // Callback from VM_GenCollectForAllocation operation.
   // This function does everything necessary/possible to satisfy an
@@ -110,7 +115,7 @@
   // Callback from VM_GenCollectFull operation.
   // Perform a full collection of the first max_level+1 generations.
   virtual void do_full_collection(bool clear_all_soft_refs);
-  void do_full_collection(bool clear_all_soft_refs, int max_level);
+  void do_full_collection(bool clear_all_soft_refs, GenerationType max_generation);
 
   // Does the "cause" of GC indicate that
   // we absolutely __must__ clear soft refs?
@@ -121,7 +126,7 @@
 
   FlexibleWorkGang* workers() const { return _workers; }
 
-  GCStats* gc_stats(int level) const;
+  GCStats* gc_stats(Generation* generation) const;
 
   // Returns JNI_OK on success
   virtual jint initialize();
@@ -142,6 +147,9 @@
   Generation* young_gen() const { return _young_gen; }
   Generation* old_gen()   const { return _old_gen; }
 
+  bool is_young_gen(const Generation* gen) const { return gen == _young_gen; }
+  bool is_old_gen(const Generation* gen) const { return gen == _old_gen; }
+
   // The generational collector policy.
   GenCollectorPolicy* gen_policy() const { return _gen_policy; }
 
@@ -160,8 +168,8 @@
   size_t capacity() const;
   size_t used() const;
 
-  // Save the "used_region" for generations level and lower.
-  void save_used_regions(int level);
+  // Save the "used_region" for both generations.
+  void save_used_regions();
 
   size_t max_capacity() const;
 
@@ -182,9 +190,9 @@
   // The same as above but assume that the caller holds the Heap_lock.
   void collect_locked(GCCause::Cause cause);
 
-  // Perform a full collection of the first max_level+1 generations.
+  // Perform a full collection of generations up to and including max_generation.
   // Mostly used for testing purposes. Caller does not hold the Heap_lock on entry.
-  void collect(GCCause::Cause cause, int max_level);
+  void collect(GCCause::Cause cause, GenerationType max_generation);
 
   // Returns "TRUE" iff "p" points into the committed areas of the heap.
   // The methods is_in(), is_in_closed_subset() and is_in_youngest() may
@@ -314,10 +322,8 @@
   }
 
   // Update the gc statistics for each generation.
-  // "level" is the level of the latest collection.
-  void update_gc_stats(int current_level, bool full) {
-    _young_gen->update_gc_stats(current_level, full);
-    _old_gen->update_gc_stats(current_level, full);
+  void update_gc_stats(Generation* current_generation, bool full) {
+    _old_gen->update_gc_stats(current_generation, full);
   }
 
   bool no_gc_in_progress() { return !is_gc_active(); }
@@ -365,8 +371,8 @@
   static GenCollectedHeap* heap();
 
   // Invoke the "do_oop" method of one of the closures "not_older_gens"
-  // or "older_gens" on root locations for the generation at
-  // "level".  (The "older_gens" closure is used for scanning references
+  // or "older_gens" on root locations for the generations depending on
+  // the type.  (The "older_gens" closure is used for scanning references
   // from older generations; "not_older_gens" is used everywhere else.)
   // If "younger_gens_as_roots" is false, younger generations are
   // not scanned as roots; in this case, the caller must be arranging to
@@ -396,7 +402,7 @@
   static const bool StrongRootsOnly    = true;
 
   void gen_process_roots(StrongRootsScope* scope,
-                         int level,
+                         GenerationType type,
                          bool younger_gens_as_roots,
                          ScanningOption so,
                          bool only_strong_roots,
@@ -420,7 +426,7 @@
   // applied to references in the generation at "level", and the "older"
   // closure to older generations.
 #define GCH_SINCE_SAVE_MARKS_ITERATE_DECL(OopClosureType, nv_suffix)    \
-  void oop_since_save_marks_iterate(int level,                          \
+  void oop_since_save_marks_iterate(GenerationType start_gen,           \
                                     OopClosureType* cur,                \
                                     OopClosureType* older);
 
@@ -428,21 +434,17 @@
 
 #undef GCH_SINCE_SAVE_MARKS_ITERATE_DECL
 
-  // Returns "true" iff no allocations have occurred in any generation at
-  // "level" or above since the last
+  // Returns "true" iff no allocations have occurred since the last
   // call to "save_marks".
-  bool no_allocs_since_save_marks(int level);
+  bool no_allocs_since_save_marks(bool include_young);
 
   // Returns true if an incremental collection is likely to fail.
   // We optionally consult the young gen, if asked to do so;
   // otherwise we base our answer on whether the previous incremental
   // collection attempt failed with no corrective action as of yet.
   bool incremental_collection_will_fail(bool consult_young) {
-    // Assumes a 2-generation system; the first disjunct remembers if an
-    // incremental collection failed, even when we thought (second disjunct)
-    // that it would not.
-    assert(heap()->collector_policy()->is_generation_policy(),
-           "the following definition may not be suitable for an n(>2)-generation system");
+    // The first disjunct remembers if an incremental collection failed, even
+    // when we thought (second disjunct) that it would not.
     return incremental_collection_failed() ||
            (consult_young && !_young_gen->collection_attempt_is_safe());
   }
@@ -482,10 +484,10 @@
   // iterating over spaces.
   void prepare_for_compaction();
 
-  // Perform a full collection of the first max_level+1 generations.
+  // Perform a full collection of the generations up to and including max_generation.
   // This is the low level interface used by the public versions of
   // collect() and collect_locked(). Caller holds the Heap_lock on entry.
-  void collect_locked(GCCause::Cause cause, int max_level);
+  void collect_locked(GCCause::Cause cause, GenerationType max_generation);
 
   // Returns success or failure.
   bool create_cms_collector();
--- a/hotspot/src/share/vm/gc/shared/generation.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/shared/generation.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -42,8 +42,7 @@
 #include "utilities/copy.hpp"
 #include "utilities/events.hpp"
 
-Generation::Generation(ReservedSpace rs, size_t initial_size, int level) :
-  _level(level),
+Generation::Generation(ReservedSpace rs, size_t initial_size) :
   _ref_processor(NULL) {
   if (!_virtual_space.initialize(rs, initial_size)) {
     vm_exit_during_initialization("Could not reserve enough space for "
@@ -61,8 +60,10 @@
 
 GenerationSpec* Generation::spec() {
   GenCollectedHeap* gch = GenCollectedHeap::heap();
-  assert(level() == 0 || level() == 1, "Bad gen level");
-  return level() == 0 ? gch->gen_policy()->young_gen_spec() : gch->gen_policy()->old_gen_spec();
+  if (gch->is_young_gen(this)) {
+    return gch->gen_policy()->young_gen_spec();
+  }
+  return gch->gen_policy()->old_gen_spec();
 }
 
 size_t Generation::max_capacity() const {
@@ -111,9 +112,17 @@
 void Generation::print_summary_info_on(outputStream* st) {
   StatRecord* sr = stat_record();
   double time = sr->accumulated_time.seconds();
+  // I didn't want to change the logging when removing the level concept,
+  // but I guess this logging could say young/old or something instead of 0/1.
+  uint level;
+  if (GenCollectedHeap::heap()->is_young_gen(this)) {
+    level = 0;
+  } else {
+    level = 1;
+  }
   st->print_cr("[Accumulated GC generation %d time %3.7f secs, "
-               "%d GC's, avg GC time %3.7f]",
-               level(), time, sr->invocations,
+               "%u GC's, avg GC time %3.7f]",
+               level, time, sr->invocations,
                sr->invocations > 0 ? time / sr->invocations : 0.0);
 }
 
@@ -149,25 +158,14 @@
   return blk.sp != NULL;
 }
 
-Generation* Generation::next_gen() const {
-  GenCollectedHeap* gch = GenCollectedHeap::heap();
-  if (level() == 0) {
-    return gch->old_gen();
-  } else {
-    return NULL;
-  }
-}
-
 size_t Generation::max_contiguous_available() const {
   // The largest number of contiguous free words in this or any higher generation.
-  size_t max = 0;
-  for (const Generation* gen = this; gen != NULL; gen = gen->next_gen()) {
-    size_t avail = gen->contiguous_available();
-    if (avail > max) {
-      max = avail;
-    }
+  size_t avail = contiguous_available();
+  size_t old_avail = 0;
+  if (GenCollectedHeap::heap()->is_young_gen(this)) {
+    old_avail = GenCollectedHeap::heap()->old_gen()->contiguous_available();
   }
-  return max;
+  return MAX2(avail, old_avail);
 }
 
 bool Generation::promotion_attempt_is_safe(size_t max_promotion_in_bytes) const {
--- a/hotspot/src/share/vm/gc/shared/generation.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/shared/generation.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -98,9 +98,6 @@
   // Memory area reserved for generation
   VirtualSpace _virtual_space;
 
-  // Level in the generation hierarchy.
-  int _level;
-
   // ("Weak") Reference processing support
   ReferenceProcessor* _ref_processor;
 
@@ -110,12 +107,8 @@
   // Statistics for garbage collection
   GCStats* _gc_stats;
 
-  // Returns the next generation in the configuration, or else NULL if this
-  // is the highest generation.
-  Generation* next_gen() const;
-
   // Initialize the generation.
-  Generation(ReservedSpace rs, size_t initial_byte_size, int level);
+  Generation(ReservedSpace rs, size_t initial_byte_size);
 
   // Apply "cl->do_oop" to (the address of) (exactly) all the ref fields in
   // "sp" that point into younger generations.
@@ -409,15 +402,14 @@
     _time_of_last_gc = now;
   }
 
-  // Generations may keep statistics about collection.  This
-  // method updates those statistics.  current_level is
-  // the level of the collection that has most recently
-  // occurred.  This allows the generation to decide what
-  // statistics are valid to collect.  For example, the
-  // generation can decide to gather the amount of promoted data
-  // if the collection of the younger generations has completed.
+  // Generations may keep statistics about collection. This method
+  // updates those statistics. current_generation is the generation
+  // that was most recently collected. This allows the generation to
+  // decide what statistics are valid to collect. For example, the
+  // generation can decide to gather the amount of promoted data if
+  // the collection of the younger generations has completed.
   GCStats* gc_stats() const { return _gc_stats; }
-  virtual void update_gc_stats(int current_level, bool full) {}
+  virtual void update_gc_stats(Generation* current_generation, bool full) {}
 
   // Mark sweep support phase2
   virtual void prepare_for_compaction(CompactPoint* cp);
@@ -502,8 +494,6 @@
   virtual const char* name() const = 0;
   virtual const char* short_name() const = 0;
 
-  int level() const { return _level; }
-
   // Reference Processing accessor
   ReferenceProcessor* const ref_processor() { return _ref_processor; }
 
--- a/hotspot/src/share/vm/gc/shared/generationSpec.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/shared/generationSpec.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -36,18 +36,17 @@
 #include "gc/cms/parNewGeneration.hpp"
 #endif // INCLUDE_ALL_GCS
 
-Generation* GenerationSpec::init(ReservedSpace rs, int level,
-                                 GenRemSet* remset) {
+Generation* GenerationSpec::init(ReservedSpace rs, GenRemSet* remset) {
   switch (name()) {
     case Generation::DefNew:
-      return new DefNewGeneration(rs, init_size(), level);
+      return new DefNewGeneration(rs, init_size());
 
     case Generation::MarkSweepCompact:
-      return new TenuredGeneration(rs, init_size(), level, remset);
+      return new TenuredGeneration(rs, init_size(), remset);
 
 #if INCLUDE_ALL_GCS
     case Generation::ParNew:
-      return new ParNewGeneration(rs, init_size(), level);
+      return new ParNewGeneration(rs, init_size());
 
     case Generation::ConcurrentMarkSweep: {
       assert(UseConcMarkSweepGC, "UseConcMarkSweepGC should be set");
@@ -61,7 +60,7 @@
 
       ConcurrentMarkSweepGeneration* g = NULL;
       g = new ConcurrentMarkSweepGeneration(rs,
-                 init_size(), level, ctrs, UseCMSAdaptiveFreeLists,
+                 init_size(), ctrs, UseCMSAdaptiveFreeLists,
                  (FreeBlockDictionary<FreeChunk>::DictionaryChoice)CMSDictionaryChoice);
 
       g->initialize_performance_counters();
--- a/hotspot/src/share/vm/gc/shared/generationSpec.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/shared/generationSpec.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -45,7 +45,7 @@
     _max_size(align_size_up(max_size, alignment))
   { }
 
-  Generation* init(ReservedSpace rs, int level, GenRemSet* remset);
+  Generation* init(ReservedSpace rs, GenRemSet* remset);
 
   // Accessors
   Generation::Name name()        const { return _name; }
--- a/hotspot/src/share/vm/gc/shared/vmGCOperations.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/shared/vmGCOperations.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -184,7 +184,7 @@
 
   GenCollectedHeap* gch = GenCollectedHeap::heap();
   GCCauseSetter gccs(gch, _gc_cause);
-  gch->do_full_collection(gch->must_clear_all_soft_refs(), _max_level);
+  gch->do_full_collection(gch->must_clear_all_soft_refs(), _max_generation);
 }
 
 // Returns true iff concurrent GCs unloads metadata.
@@ -197,7 +197,7 @@
 
   if (UseG1GC && ClassUnloadingWithConcurrentMark) {
     G1CollectedHeap* g1h = G1CollectedHeap::heap();
-    g1h->g1_policy()->set_initiate_conc_mark_if_possible();
+    g1h->g1_policy()->collector_state()->set_initiate_conc_mark_if_possible(true);
 
     GCCauseSetter x(g1h, _gc_cause);
 
--- a/hotspot/src/share/vm/gc/shared/vmGCOperations.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/gc/shared/vmGCOperations.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -26,6 +26,7 @@
 #define SHARE_VM_GC_SHARED_VMGCOPERATIONS_HPP
 
 #include "gc/shared/collectedHeap.hpp"
+#include "gc/shared/genCollectedHeap.hpp"
 #include "memory/heapInspection.hpp"
 #include "prims/jvmtiExport.hpp"
 #include "runtime/handles.hpp"
@@ -193,14 +194,14 @@
 // GenCollectedHeap heap.
 class VM_GenCollectFull: public VM_GC_Operation {
  private:
-  int _max_level;
+  GenCollectedHeap::GenerationType _max_generation;
  public:
   VM_GenCollectFull(uint gc_count_before,
                     uint full_gc_count_before,
                     GCCause::Cause gc_cause,
-                    int max_level)
+                    GenCollectedHeap::GenerationType max_generation)
     : VM_GC_Operation(gc_count_before, gc_cause, full_gc_count_before, true /* full */),
-      _max_level(max_level) { }
+      _max_generation(max_generation) { }
   ~VM_GenCollectFull() {}
   virtual VMOp_Type type() const { return VMOp_GenCollectFull; }
   virtual void doit();
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -26,6 +26,7 @@
 #include "classfile/javaClasses.inline.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "classfile/vmSymbols.hpp"
+#include "code/codeCache.hpp"
 #include "compiler/compileBroker.hpp"
 #include "compiler/disassembler.hpp"
 #include "gc/shared/collectedHeap.hpp"
@@ -309,6 +310,8 @@
   Handle exception = get_preinitialized_exception(
                                  SystemDictionary::StackOverflowError_klass(),
                                  CHECK);
+  // Increment counter for hs_err file reporting
+  Atomic::inc(&Exceptions::_stack_overflow_errors);
   THROW_HANDLE(exception);
 IRT_END
 
@@ -1127,6 +1130,14 @@
 
 // Implementation of SignatureHandlerLibrary
 
+#ifndef SHARING_FAST_NATIVE_FINGERPRINTS
+// Dummy definition (else normalization method is defined in CPU
+// dependant code)
+uint64_t InterpreterRuntime::normalize_fast_native_fingerprint(uint64_t fingerprint) {
+  return fingerprint;
+}
+#endif
+
 address SignatureHandlerLibrary::set_handler_blob() {
   BufferBlob* handler_blob = BufferBlob::create("native signature handlers", blob_size);
   if (handler_blob == NULL) {
@@ -1182,6 +1193,8 @@
       initialize();
       // lookup method signature's fingerprint
       uint64_t fingerprint = Fingerprinter(method).fingerprint();
+      // allow CPU dependant code to optimize the fingerprints for the fast handler
+      fingerprint = InterpreterRuntime::normalize_fast_native_fingerprint(fingerprint);
       handler_index = _fingerprints->find(fingerprint);
       // create handler if necessary
       if (handler_index < 0) {
@@ -1207,13 +1220,18 @@
                           buffer.insts_size());
             Disassembler::decode(handler, handler + buffer.insts_size());
 #ifndef PRODUCT
-            tty->print_cr(" --- associated result handler ---");
             address rh_begin = Interpreter::result_handler(method()->result_type());
-            address rh_end = rh_begin;
-            while (*(int*)rh_end != 0) {
-              rh_end += sizeof(int);
+            if (CodeCache::contains(rh_begin)) {
+              // else it might be special platform dependent values
+              tty->print_cr(" --- associated result handler ---");
+              address rh_end = rh_begin;
+              while (*(int*)rh_end != 0) {
+                rh_end += sizeof(int);
+              }
+              Disassembler::decode(rh_begin, rh_end);
+            } else {
+              tty->print_cr(" associated result handler: " PTR_FORMAT, p2i(rh_begin));
             }
-            Disassembler::decode(rh_begin, rh_end);
 #endif
           }
           // add handler to library
@@ -1225,13 +1243,13 @@
         }
       }
       // Set handler under SignatureHandlerLibrary_lock
-    if (handler_index < 0) {
-      // use generic signature handler
-      method->set_signature_handler(Interpreter::slow_signature_handler());
-    } else {
-      // set handler
-      method->set_signature_handler(_handlers->at(handler_index));
-    }
+      if (handler_index < 0) {
+        // use generic signature handler
+        method->set_signature_handler(Interpreter::slow_signature_handler());
+      } else {
+        // set handler
+        method->set_signature_handler(_handlers->at(handler_index));
+      }
     } else {
       CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops());
       // use generic signature handler
@@ -1248,9 +1266,11 @@
     // have to protect this read access here with the same mutex as well!
     MutexLocker mu(SignatureHandlerLibrary_lock);
     if (_handlers != NULL) {
-    handler_index = _handlers->find(method->signature_handler());
-    fingerprint_index = _fingerprints->find(Fingerprinter(method).fingerprint());
-  }
+      handler_index = _handlers->find(method->signature_handler());
+      uint64_t fingerprint = Fingerprinter(method).fingerprint();
+      fingerprint = InterpreterRuntime::normalize_fast_native_fingerprint(fingerprint);
+      fingerprint_index = _fingerprints->find(fingerprint);
+    }
   }
   assert(method->signature_handler() == Interpreter::slow_signature_handler() ||
          handler_index == fingerprint_index, "sanity check");
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -183,6 +183,8 @@
 # include "interpreterRT_aarch64.hpp"
 #endif
 
+  // optional normalization of fingerprints to reduce the number of adapters
+  static uint64_t normalize_fast_native_fingerprint(uint64_t fingerprint);
 
   // Interpreter's frequency counter overflow
   static nmethod* frequency_counter_overflow(JavaThread* thread, address branch_bcp);
--- a/hotspot/src/share/vm/interpreter/templateInterpreter.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/interpreter/templateInterpreter.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, 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
@@ -102,7 +102,6 @@
   static address    _throw_ArrayStoreException_entry;
   static address    _throw_ArithmeticException_entry;
   static address    _throw_ClassCastException_entry;
-  static address    _throw_WrongMethodType_entry;
   static address    _throw_NullPointerException_entry;
   static address    _throw_exception_entry;
 
@@ -148,7 +147,6 @@
   static address    remove_activation_entry()                   { return _remove_activation_entry; }
   static address    throw_exception_entry()                     { return _throw_exception_entry; }
   static address    throw_ArithmeticException_entry()           { return _throw_ArithmeticException_entry; }
-  static address    throw_WrongMethodType_entry()               { return _throw_WrongMethodType_entry; }
   static address    throw_NullPointerException_entry()          { return _throw_NullPointerException_entry; }
   static address    throw_StackOverflowError_entry()            { return _throw_StackOverflowError_entry; }
 
--- a/hotspot/src/share/vm/memory/filemap.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/memory/filemap.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -28,10 +28,14 @@
 #include "classfile/symbolTable.hpp"
 #include "classfile/systemDictionaryShared.hpp"
 #include "classfile/altHashing.hpp"
+#if INCLUDE_ALL_GCS
+#include "gc/g1/g1CollectedHeap.hpp"
+#endif
 #include "memory/filemap.hpp"
 #include "memory/metadataFactory.hpp"
 #include "memory/oopFactory.hpp"
 #include "oops/objArrayOop.hpp"
+#include "prims/jvmtiExport.hpp"
 #include "runtime/arguments.hpp"
 #include "runtime/java.hpp"
 #include "runtime/os.hpp"
@@ -165,6 +169,11 @@
   _version = _current_version;
   _alignment = alignment;
   _obj_alignment = ObjectAlignmentInBytes;
+  _narrow_oop_mode = Universe::narrow_oop_mode();
+  _narrow_oop_shift = Universe::narrow_oop_shift();
+  _max_heap_size = MaxHeapSize;
+  _narrow_klass_base = Universe::narrow_klass_base();
+  _narrow_klass_shift = Universe::narrow_klass_shift();
   _classpath_entry_table_size = mapinfo->_classpath_entry_table_size;
   _classpath_entry_table = mapinfo->_classpath_entry_table;
   _classpath_entry_size = mapinfo->_classpath_entry_size;
@@ -440,7 +449,16 @@
   } else {
     si->_file_offset = _file_offset;
   }
-  si->_base = base;
+  if (MetaspaceShared::is_string_region(region)) {
+    assert((base - (char*)Universe::narrow_oop_base()) % HeapWordSize == 0, "Sanity");
+    if (base != NULL) {
+      si->_addr._offset = (intx)oopDesc::encode_heap_oop_not_null((oop)base);
+    } else {
+      si->_addr._offset = 0;
+    }
+  } else {
+    si->_addr._base = base;
+  }
   si->_used = size;
   si->_capacity = capacity;
   si->_read_only = read_only;
@@ -449,6 +467,38 @@
   write_bytes_aligned(base, (int)size);
 }
 
+// Write the string space. The string space contains one or multiple GC(G1) regions.
+// When the total string space size is smaller than one GC region of the dump time,
+// only one string region is used for shared strings.
+//
+// If the total string space size is bigger than one GC region, there would be more
+// than one GC regions allocated for shared strings. The first/bottom GC region might
+// be a partial GC region with the empty portion at the higher address within that region.
+// The non-empty portion of the first region is written into the archive as one string
+// region. The rest are consecutive full GC regions if they exist, which can be written
+// out in one chunk as another string region.
+void FileMapInfo::write_string_regions(GrowableArray<MemRegion> *regions) {
+  for (int i = MetaspaceShared::first_string;
+           i < MetaspaceShared::first_string + MetaspaceShared::max_strings; i++) {
+    char* start = NULL;
+    size_t size = 0;
+    if (regions->is_nonempty()) {
+      if (i == MetaspaceShared::first_string) {
+        MemRegion first = regions->first();
+        start = (char*)first.start();
+        size = first.byte_size();
+      } else {
+        int len = regions->length();
+        if (len > 1) {
+          start = (char*)regions->at(1).start();
+          size = (char*)regions->at(len - 1).end() - start;
+        }
+      }
+    }
+    write_region(i, start, size, size, false, false);
+  }
+}
+
 
 // Dump bytes to file -- at the current file position.
 
@@ -513,7 +563,8 @@
 // JVM/TI RedefineClasses() support:
 // Remap the shared readonly space to shared readwrite, private.
 bool FileMapInfo::remap_shared_readonly_as_readwrite() {
-  struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[0];
+  int idx = 0;
+  struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[idx];
   if (!si->_read_only) {
     // the space is already readwrite so we are done
     return true;
@@ -523,15 +574,16 @@
   if (!open_for_read()) {
     return false;
   }
+  char *addr = _header->region_addr(idx);
   char *base = os::remap_memory(_fd, _full_path, si->_file_offset,
-                                si->_base, size, false /* !read_only */,
+                                addr, size, false /* !read_only */,
                                 si->_allow_exec);
   close();
   if (base == NULL) {
     fail_continue("Unable to remap shared readonly space (errno=%d).", errno);
     return false;
   }
-  if (base != si->_base) {
+  if (base != addr) {
     fail_continue("Unable to remap shared readonly space at required address.");
     return false;
   }
@@ -542,7 +594,7 @@
 // Map the whole region at once, assumed to be allocated contiguously.
 ReservedSpace FileMapInfo::reserve_shared_memory() {
   struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[0];
-  char* requested_addr = si->_base;
+  char* requested_addr = _header->region_addr(0);
 
   size_t size = FileMapInfo::shared_spaces_size();
 
@@ -560,20 +612,27 @@
 }
 
 // Memory map a region in the address space.
-static const char* shared_region_name[] = { "ReadOnly", "ReadWrite", "MiscData", "MiscCode"};
+static const char* shared_region_name[] = { "ReadOnly", "ReadWrite", "MiscData", "MiscCode",
+                                            "String1", "String2" };
 
 char* FileMapInfo::map_region(int i) {
+  assert(!MetaspaceShared::is_string_region(i), "sanity");
   struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[i];
   size_t used = si->_used;
   size_t alignment = os::vm_allocation_granularity();
   size_t size = align_size_up(used, alignment);
-  char *requested_addr = si->_base;
+  char *requested_addr = _header->region_addr(i);
+
+  // If a tool agent is in use (debugging enabled), we must map the address space RW
+  if (JvmtiExport::can_modify_any_class() || JvmtiExport::can_walk_any_space()) {
+    si->_read_only = false;
+  }
 
   // map the contents of the CDS archive in this memory
   char *base = os::map_memory(_fd, _full_path, si->_file_offset,
                               requested_addr, size, si->_read_only,
                               si->_allow_exec);
-  if (base == NULL || base != si->_base) {
+  if (base == NULL || base != requested_addr) {
     fail_continue("Unable to map %s shared space at required address.", shared_region_name[i]);
     return NULL;
   }
@@ -582,15 +641,132 @@
   // in method FileMapInfo::reserve_shared_memory(), which is not called on Windows.
   MemTracker::record_virtual_memory_type((address)base, mtClassShared);
 #endif
+
   return base;
 }
 
+static MemRegion *string_ranges = NULL;
+static int num_ranges = 0;
+bool FileMapInfo::map_string_regions() {
+#if INCLUDE_ALL_GCS
+  if (UseG1GC && UseCompressedOops && UseCompressedClassPointers) {
+    // Check that all the narrow oop and klass encodings match the archive
+    if (narrow_oop_mode() != Universe::narrow_oop_mode() ||
+        narrow_oop_shift() != Universe::narrow_oop_shift() ||
+        narrow_klass_base() != Universe::narrow_klass_base() ||
+        narrow_klass_shift() != Universe::narrow_klass_shift()) {
+      if (PrintSharedSpaces && _header->_space[MetaspaceShared::first_string]._used > 0) {
+        tty->print_cr("Shared string data from the CDS archive is being ignored. "
+                     "The current CompressedOops/CompressedClassPointers encoding differs from "
+                     "that archived due to heap size change. The archive was dumped using max heap "
+                     "size %dM.", max_heap_size()/M);
+      }
+    } else {
+      string_ranges = new MemRegion[MetaspaceShared::max_strings];
+      struct FileMapInfo::FileMapHeader::space_info* si;
+
+      for (int i = MetaspaceShared::first_string;
+               i < MetaspaceShared::first_string + MetaspaceShared::max_strings; i++) {
+        si = &_header->_space[i];
+        size_t used = si->_used;
+        if (used > 0) {
+          size_t size = used;
+          char* requested_addr = (char*)((void*)oopDesc::decode_heap_oop_not_null(
+                                                 (narrowOop)si->_addr._offset));
+          string_ranges[num_ranges] = MemRegion((HeapWord*)requested_addr, size / HeapWordSize);
+          num_ranges ++;
+        }
+      }
+
+      if (num_ranges == 0) {
+        StringTable::ignore_shared_strings(true);
+        return true; // no shared string data
+      }
+
+      // Check that ranges are within the java heap
+      if (!G1CollectedHeap::heap()->check_archive_addresses(string_ranges, num_ranges)) {
+        fail_continue("Unable to allocate shared string space: range is not "
+                      "within java heap.");
+        return false;
+      }
+
+      // allocate from java heap
+      if (!G1CollectedHeap::heap()->alloc_archive_regions(string_ranges, num_ranges)) {
+        fail_continue("Unable to allocate shared string space: range is "
+                      "already in use.");
+        return false;
+      }
+
+      // Map the string data. No need to call MemTracker::record_virtual_memory_type()
+      // for mapped string regions as they are part of the reserved java heap, which
+      // is already recorded.
+      for (int i = 0; i < num_ranges; i++) {
+        si = &_header->_space[MetaspaceShared::first_string + i];
+        char* addr = (char*)string_ranges[i].start();
+        char* base = os::map_memory(_fd, _full_path, si->_file_offset,
+                                    addr, string_ranges[i].byte_size(), si->_read_only,
+                                    si->_allow_exec);
+        if (base == NULL || base != addr) {
+          fail_continue("Unable to map shared string space at required address.");
+          return false;
+        }
+      }
+
+      if (!verify_string_regions()) {
+        fail_continue("Shared string regions are corrupt");
+        return false;
+      }
+
+      // the shared string data is mapped successfully
+      return true;
+    }
+  } else {
+    if (PrintSharedSpaces && _header->_space[MetaspaceShared::first_string]._used > 0) {
+      tty->print_cr("Shared string data from the CDS archive is being ignored. UseG1GC, "
+                    "UseCompressedOops and UseCompressedClassPointers are required.");
+    }
+  }
+
+  // if we get here, the shared string data is not mapped
+  assert(string_ranges == NULL && num_ranges == 0, "sanity");
+  StringTable::ignore_shared_strings(true);
+#endif
+  return true;
+}
+
+bool FileMapInfo::verify_string_regions() {
+  for (int i = MetaspaceShared::first_string;
+           i < MetaspaceShared::first_string + MetaspaceShared::max_strings; i++) {
+    if (!verify_region_checksum(i)) {
+      return false;
+    }
+  }
+  return true;
+}
+
+void FileMapInfo::fixup_string_regions() {
+  // If any string regions were found, call the fill routine to make them parseable.
+  // Note that string_ranges may be non-NULL even if no ranges were found.
+  if (num_ranges != 0) {
+    assert(string_ranges != NULL, "Null string_ranges array with non-zero count");
+    G1CollectedHeap::heap()->fill_archive_regions(string_ranges, num_ranges);
+  }
+}
+
 bool FileMapInfo::verify_region_checksum(int i) {
   if (!VerifySharedSpaces) {
     return true;
   }
-  const char* buf = _header->_space[i]._base;
+
   size_t sz = _header->_space[i]._used;
+
+  if (sz == 0) {
+    return true; // no data
+  }
+  if (MetaspaceShared::is_string_region(i) && StringTable::shared_string_ignored()) {
+    return true; // shared string data are not mapped
+  }
+  const char* buf = _header->region_addr(i);
   int crc = ClassLoader::crc32(0, buf, (jint)sz);
   if (crc != _header->_space[i]._crc) {
     fail_continue("Checksum verification failed.");
@@ -602,14 +778,36 @@
 // Unmap a memory region in the address space.
 
 void FileMapInfo::unmap_region(int i) {
+  assert(!MetaspaceShared::is_string_region(i), "sanity");
   struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[i];
   size_t used = si->_used;
   size_t size = align_size_up(used, os::vm_allocation_granularity());
-  if (!os::unmap_memory(si->_base, size)) {
+
+  if (used == 0) {
+    return;
+  }
+
+  char* addr = _header->region_addr(i);
+  if (!os::unmap_memory(addr, size)) {
     fail_stop("Unable to unmap shared space.");
   }
 }
 
+void FileMapInfo::unmap_string_regions() {
+  for (int i = MetaspaceShared::first_string;
+           i < MetaspaceShared::first_string + MetaspaceShared::max_strings; i++) {
+    struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[i];
+    size_t used = si->_used;
+    if (used > 0) {
+      size_t size = align_size_up(used, os::vm_allocation_granularity());
+      char* addr = (char*)((void*)oopDesc::decode_heap_oop_not_null(
+                                             (narrowOop)si->_addr._offset));
+      if (!os::unmap_memory(addr, size)) {
+        fail_stop("Unable to unmap shared space.");
+      }
+    }
+  }
+}
 
 void FileMapInfo::assert_mark(bool check) {
   if (!check) {
@@ -637,11 +835,6 @@
 bool FileMapInfo::initialize() {
   assert(UseSharedSpaces, "UseSharedSpaces expected.");
 
-  if (JvmtiExport::can_modify_any_class() || JvmtiExport::can_walk_any_space()) {
-    fail_continue("Tool agent requires sharing to be disabled.");
-    return false;
-  }
-
   if (!open_for_read()) {
     return false;
   }
@@ -658,6 +851,15 @@
   return true;
 }
 
+char* FileMapInfo::FileMapHeader::region_addr(int idx) {
+  if (MetaspaceShared::is_string_region(idx)) {
+    return (char*)((void*)oopDesc::decode_heap_oop_not_null(
+              (narrowOop)_space[idx]._addr._offset));
+  } else {
+    return _space[idx]._addr._base;
+  }
+}
+
 int FileMapInfo::FileMapHeader::compute_crc() {
   char* header = data();
   // start computing from the field after _crc
@@ -729,8 +931,12 @@
 // True if the p is within the mapped shared space, otherwise, false.
 bool FileMapInfo::is_in_shared_space(const void* p) {
   for (int i = 0; i < MetaspaceShared::n_regions; i++) {
-    if (p >= _header->_space[i]._base &&
-        p < _header->_space[i]._base + _header->_space[i]._used) {
+    char *base;
+    if (MetaspaceShared::is_string_region(i) && _header->_space[i]._used == 0) {
+      continue;
+    }
+    base = _header->region_addr(i);
+    if (p >= base && p < base + _header->_space[i]._used) {
       return true;
     }
   }
@@ -742,9 +948,10 @@
   gclog_or_tty->print_cr("Shared Spaces:");
   for (int i = 0; i < MetaspaceShared::n_regions; i++) {
     struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[i];
+    char *base = _header->region_addr(i);
     gclog_or_tty->print("  %s " INTPTR_FORMAT "-" INTPTR_FORMAT,
                         shared_region_name[i],
-                        si->_base, si->_base + si->_used);
+                        base, base + si->_used);
   }
 }
 
@@ -753,12 +960,14 @@
   FileMapInfo *map_info = FileMapInfo::current_info();
   if (map_info) {
     map_info->fail_continue("%s", msg);
-    for (int i = 0; i < MetaspaceShared::n_regions; i++) {
-      if (map_info->_header->_space[i]._base != NULL) {
+    for (int i = 0; i < MetaspaceShared::num_non_strings; i++) {
+      char *addr = map_info->_header->region_addr(i);
+      if (addr != NULL && !MetaspaceShared::is_string_region(i)) {
         map_info->unmap_region(i);
-        map_info->_header->_space[i]._base = NULL;
+        map_info->_header->_space[i]._addr._base = NULL;
       }
     }
+    map_info->unmap_string_regions();
   } else if (DumpSharedSpaces) {
     fail_stop("%s", msg);
   }
--- a/hotspot/src/share/vm/memory/filemap.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/memory/filemap.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, 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
@@ -94,11 +94,20 @@
     int    _version;                  // (from enum, above.)
     size_t _alignment;                // how shared archive should be aligned
     int    _obj_alignment;            // value of ObjectAlignmentInBytes
+    int    _narrow_oop_shift;         // compressed oop encoding shift
+    uintx  _max_heap_size;            // java max heap size during dumping
+    Universe::NARROW_OOP_MODE _narrow_oop_mode; // compressed oop encoding mode
+    int     _narrow_klass_shift;      // save narrow klass base and shift
+    address _narrow_klass_base;
 
     struct space_info {
       int    _crc;           // crc checksum of the current space
       size_t _file_offset;   // sizeof(this) rounded to vm page size
-      char*  _base;          // copy-on-write base address
+      union {
+        char*  _base;        // copy-on-write base address
+        intx   _offset;      // offset from the compressed oop encoding base, only used
+                             // by string space
+      } _addr;
       size_t _capacity;      // for validity checking
       size_t _used;          // for setting space top on read
       bool   _read_only;     // read only space?
@@ -138,6 +147,8 @@
     size_t _classpath_entry_size;
     SharedClassPathEntry* _classpath_entry_table;
 
+    char* region_addr(int idx);
+
     virtual bool validate();
     virtual void populate(FileMapInfo* info, size_t alignment);
     int compute_crc();
@@ -166,8 +177,12 @@
   void   invalidate();
   int    version()                    { return _header->_version; }
   size_t alignment()                  { return _header->_alignment; }
+  Universe::NARROW_OOP_MODE narrow_oop_mode() { return _header->_narrow_oop_mode; }
+  int    narrow_oop_shift()           { return _header->_narrow_oop_shift; }
+  uintx  max_heap_size()              { return _header->_max_heap_size; }
+  address narrow_klass_base() const   { return _header->_narrow_klass_base; }
+  int     narrow_klass_shift() const  { return _header->_narrow_klass_shift; }
   size_t space_capacity(int i)        { return _header->_space[i]._capacity; }
-  char*  region_base(int i)           { return _header->_space[i]._base; }
   struct FileMapHeader* header()      { return _header; }
 
   static FileMapInfo* current_info() {
@@ -185,10 +200,15 @@
   void  write_space(int i, Metaspace* space, bool read_only);
   void  write_region(int region, char* base, size_t size,
                      size_t capacity, bool read_only, bool allow_exec);
+  void  write_string_regions(GrowableArray<MemRegion> *regions);
   void  write_bytes(const void* buffer, int count);
   void  write_bytes_aligned(const void* buffer, int count);
   char* map_region(int i);
+  bool  map_string_regions();
+  bool  verify_string_regions();
+  void  fixup_string_regions();
   void  unmap_region(int i);
+  void  unmap_string_regions();
   bool  verify_region_checksum(int i);
   void  close();
   bool  is_open() { return _file_open; }
--- a/hotspot/src/share/vm/memory/metaspace.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/memory/metaspace.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -2423,7 +2423,9 @@
  * will be made to allocate a small chunk.
  */
 MetaWord* SpaceManager::get_small_chunk_and_allocate(size_t word_size) {
-  if (word_size + Metachunk::overhead() > small_chunk_size()) {
+  size_t raw_word_size = get_raw_word_size(word_size);
+
+  if (raw_word_size + Metachunk::overhead() > small_chunk_size()) {
     return NULL;
   }
 
@@ -2438,9 +2440,9 @@
     // Add chunk to the in-use chunk list and do an allocation from it.
     // Add to this manager's list of chunks in use.
     add_chunk(chunk, false);
-    mem = chunk->allocate(word_size);
-
-    inc_used_metrics(word_size);
+    mem = chunk->allocate(raw_word_size);
+
+    inc_used_metrics(raw_word_size);
 
     // Track metaspace memory usage statistic.
     track_metaspace_memory_usage();
@@ -3132,10 +3134,21 @@
   initialize_class_space(metaspace_rs);
 
   if (PrintCompressedOopsMode || (PrintMiscellaneous && Verbose)) {
-    gclog_or_tty->print_cr("Narrow klass base: " PTR_FORMAT ", Narrow klass shift: %d",
-                            p2i(Universe::narrow_klass_base()), Universe::narrow_klass_shift());
-    gclog_or_tty->print_cr("Compressed class space size: " SIZE_FORMAT " Address: " PTR_FORMAT " Req Addr: " PTR_FORMAT,
-                           compressed_class_space_size(), p2i(metaspace_rs.base()), p2i(requested_addr));
+    print_compressed_class_space(gclog_or_tty, requested_addr);
+  }
+}
+
+void Metaspace::print_compressed_class_space(outputStream* st, const char* requested_addr) {
+  st->print_cr("Narrow klass base: " PTR_FORMAT ", Narrow klass shift: %d",
+               p2i(Universe::narrow_klass_base()), Universe::narrow_klass_shift());
+  if (_class_space_list != NULL) {
+    address base = (address)_class_space_list->current_virtual_space()->bottom();
+    st->print("Compressed class space size: " SIZE_FORMAT " Address: " PTR_FORMAT,
+                 compressed_class_space_size(), p2i(base));
+    if (requested_addr != 0) {
+      st->print(" Req Addr: " PTR_FORMAT, p2i(requested_addr));
+    }
+    st->cr();
   }
 }
 
@@ -3282,12 +3295,12 @@
 #endif // _LP64
 #endif // INCLUDE_CDS
   } else {
-#if INCLUDE_CDS
     // If using shared space, open the file that contains the shared space
     // and map in the memory before initializing the rest of metaspace (so
     // the addresses don't conflict)
     address cds_address = NULL;
     if (UseSharedSpaces) {
+#if INCLUDE_CDS
       FileMapInfo* mapinfo = new FileMapInfo();
 
       // Open the shared archive file, read and validate the header. If
@@ -3296,27 +3309,30 @@
       // Map in spaces now also
       if (mapinfo->initialize() && MetaspaceShared::map_shared_spaces(mapinfo)) {
         cds_total = FileMapInfo::shared_spaces_size();
-        cds_address = (address)mapinfo->region_base(0);
+        cds_address = (address)mapinfo->header()->region_addr(0);
+#ifdef _LP64
+        if (using_class_space()) {
+          char* cds_end = (char*)(cds_address + cds_total);
+          cds_end = (char *)align_ptr_up(cds_end, _reserve_alignment);
+          // If UseCompressedClassPointers is set then allocate the metaspace area
+          // above the heap and above the CDS area (if it exists).
+          allocate_metaspace_compressed_klass_ptrs(cds_end, cds_address);
+          // Map the shared string space after compressed pointers
+          // because it relies on compressed class pointers setting to work
+          mapinfo->map_string_regions();
+        }
+#endif // _LP64
       } else {
         assert(!mapinfo->is_open() && !UseSharedSpaces,
                "archive file not closed or shared spaces not disabled.");
       }
+#endif // INCLUDE_CDS
     }
-#endif // INCLUDE_CDS
+
 #ifdef _LP64
-    // If UseCompressedClassPointers is set then allocate the metaspace area
-    // above the heap and above the CDS area (if it exists).
-    if (using_class_space()) {
-      if (UseSharedSpaces) {
-#if INCLUDE_CDS
-        char* cds_end = (char*)(cds_address + cds_total);
-        cds_end = (char *)align_ptr_up(cds_end, _reserve_alignment);
-        allocate_metaspace_compressed_klass_ptrs(cds_end, cds_address);
-#endif
-      } else {
-        char* base = (char*)align_ptr_up(Universe::heap()->reserved_region().end(), _reserve_alignment);
-        allocate_metaspace_compressed_klass_ptrs(base, 0);
-      }
+    if (!UseSharedSpaces && using_class_space()) {
+      char* base = (char*)align_ptr_up(Universe::heap()->reserved_region().end(), _reserve_alignment);
+      allocate_metaspace_compressed_klass_ptrs(base, 0);
     }
 #endif // _LP64
 
--- a/hotspot/src/share/vm/memory/metaspace.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/memory/metaspace.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -254,6 +254,8 @@
   // Debugging support
   void verify();
 
+  static void print_compressed_class_space(outputStream* st, const char* requested_addr = 0);
+
   class AllocRecordClosure :  public StackObj {
   public:
     virtual void doit(address ptr, MetaspaceObj::Type type, int byte_size) = 0;
--- a/hotspot/src/share/vm/memory/metaspaceShared.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/memory/metaspaceShared.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -422,6 +422,8 @@
   GrowableArray<Klass*> *_class_promote_order;
   VirtualSpace _md_vs;
   VirtualSpace _mc_vs;
+  CompactHashtableWriter* _string_cht;
+  GrowableArray<MemRegion> *_string_regions;
 
 public:
   VM_PopulateDumpSharedSpace(ClassLoaderData* loader_data,
@@ -540,7 +542,7 @@
 
   NOT_PRODUCT(SystemDictionary::verify();)
 
-  // Copy the the symbol table, and the system dictionary to the shared
+  // Copy the the symbol table, string table, and the system dictionary to the shared
   // space in usable form.  Copy the hashtable
   // buckets first [read-write], then copy the linked lists of entries
   // [read-only].
@@ -548,6 +550,15 @@
   NOT_PRODUCT(SymbolTable::verify());
   handle_misc_data_space_failure(SymbolTable::copy_compact_table(&md_top, md_end));
 
+  size_t ss_bytes = 0;
+  char* ss_low;
+  // The string space has maximum two regions. See FileMapInfo::write_string_regions() for details.
+  _string_regions = new GrowableArray<MemRegion>(2);
+  NOT_PRODUCT(StringTable::verify());
+  handle_misc_data_space_failure(StringTable::copy_compact_table(&md_top, md_end, _string_regions,
+                                                                 &ss_bytes));
+  ss_low = _string_regions->is_empty() ? NULL : (char*)_string_regions->first().start();
+
   SystemDictionary::reverse();
   SystemDictionary::copy_buckets(&md_top, md_end);
 
@@ -576,7 +587,8 @@
   const size_t rw_alloced = rw_space->capacity_bytes_slow(Metaspace::NonClassType);
   const size_t md_alloced = md_end-md_low;
   const size_t mc_alloced = mc_end-mc_low;
-  const size_t total_alloced = ro_alloced + rw_alloced + md_alloced + mc_alloced;
+  const size_t total_alloced = ro_alloced + rw_alloced + md_alloced + mc_alloced
+                             + ss_bytes;
 
   // Occupied size of each space.
   const size_t ro_bytes = ro_space->used_bytes_slow(Metaspace::NonClassType);
@@ -585,11 +597,12 @@
   const size_t mc_bytes = size_t(mc_top - mc_low);
 
   // Percent of total size
-  const size_t total_bytes = ro_bytes + rw_bytes + md_bytes + mc_bytes;
+  const size_t total_bytes = ro_bytes + rw_bytes + md_bytes + mc_bytes + ss_bytes;
   const double ro_t_perc = ro_bytes / double(total_bytes) * 100.0;
   const double rw_t_perc = rw_bytes / double(total_bytes) * 100.0;
   const double md_t_perc = md_bytes / double(total_bytes) * 100.0;
   const double mc_t_perc = mc_bytes / double(total_bytes) * 100.0;
+  const double ss_t_perc = ss_bytes / double(total_bytes) * 100.0;
 
   // Percent of fullness of each space
   const double ro_u_perc = ro_bytes / double(ro_alloced) * 100.0;
@@ -602,6 +615,7 @@
   tty->print_cr(fmt_space, "rw", rw_bytes, rw_t_perc, rw_alloced, rw_u_perc, rw_space->bottom());
   tty->print_cr(fmt_space, "md", md_bytes, md_t_perc, md_alloced, md_u_perc, md_low);
   tty->print_cr(fmt_space, "mc", mc_bytes, mc_t_perc, mc_alloced, mc_u_perc, mc_low);
+  tty->print_cr(fmt_space, "st", ss_bytes, ss_t_perc, ss_bytes, 100.0, ss_low);
   tty->print_cr("total   : %9d [100.0%% of total] out of %9d bytes [%4.1f%% used]",
                  total_bytes, total_alloced, total_u_perc);
 
@@ -631,6 +645,7 @@
                         pointer_delta(mc_top, _mc_vs.low(), sizeof(char)),
                         SharedMiscCodeSize,
                         true, true);
+  mapinfo->write_string_regions(_string_regions);
 
   // Pass 2 - write data.
   mapinfo->open_for_write();
@@ -646,6 +661,8 @@
                         pointer_delta(mc_top, _mc_vs.low(), sizeof(char)),
                         SharedMiscCodeSize,
                         true, true);
+  mapinfo->write_string_regions(_string_regions);
+
   mapinfo->close();
 
   memmove(vtbl_list, saved_vtbl, vtbl_list_size * sizeof(void*));
@@ -942,6 +959,11 @@
   return UseSharedSpaces && FileMapInfo::current_info()->is_in_shared_space(p);
 }
 
+bool MetaspaceShared::is_string_region(int idx) {
+  return (idx >= MetaspaceShared::first_string &&
+          idx < MetaspaceShared::first_string + MetaspaceShared::max_strings);
+}
+
 void MetaspaceShared::print_shared_spaces() {
   if (UseSharedSpaces) {
     FileMapInfo::current_info()->print_shared_spaces();
@@ -972,13 +994,13 @@
 
   // Map each shared region
   if ((_ro_base = mapinfo->map_region(ro)) != NULL &&
-       mapinfo->verify_region_checksum(ro) &&
+      mapinfo->verify_region_checksum(ro) &&
       (_rw_base = mapinfo->map_region(rw)) != NULL &&
-       mapinfo->verify_region_checksum(rw) &&
+      mapinfo->verify_region_checksum(rw) &&
       (_md_base = mapinfo->map_region(md)) != NULL &&
-       mapinfo->verify_region_checksum(md) &&
+      mapinfo->verify_region_checksum(md) &&
       (_mc_base = mapinfo->map_region(mc)) != NULL &&
-       mapinfo->verify_region_checksum(mc) &&
+      mapinfo->verify_region_checksum(mc) &&
       (image_alignment == (size_t)max_alignment()) &&
       mapinfo->validate_classpath_entry_table()) {
     // Success (no need to do anything)
@@ -1011,7 +1033,7 @@
 void MetaspaceShared::initialize_shared_spaces() {
   FileMapInfo *mapinfo = FileMapInfo::current_info();
 
-  char* buffer = mapinfo->region_base(md);
+  char* buffer = mapinfo->header()->region_addr(md);
 
   // Skip over (reserve space for) a list of addresses of C++ vtables
   // for Klass objects.  They get filled in later.
@@ -1027,13 +1049,16 @@
   buffer += sizeof(intptr_t);
   buffer += vtable_size;
 
-  // Create the shared symbol table using the bucket array at this spot in the
+  // Create the shared symbol table using the compact table at this spot in the
   // misc data space. (Todo: move this to read-only space. Currently
   // this is mapped copy-on-write but will never be written into).
 
   buffer = (char*)SymbolTable::init_shared_table(buffer);
   SymbolTable::create_table();
 
+  // Create the shared string table using the compact table
+  buffer = (char*)StringTable::init_shared_table(mapinfo, buffer);
+
   // Create the shared dictionary using the bucket array at this spot in
   // the misc data space.  Since the shared dictionary table is never
   // modified, this region (of mapped pages) will be (effectively, if
@@ -1100,6 +1125,11 @@
   }
 }
 
+void MetaspaceShared::fixup_shared_string_regions() {
+  FileMapInfo *mapinfo = FileMapInfo::current_info();
+  mapinfo->fixup_string_regions();
+}
+
 // JVM/TI RedefineClasses() support:
 bool MetaspaceShared::remap_shared_readonly_as_readwrite() {
   assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
--- a/hotspot/src/share/vm/memory/metaspaceShared.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/memory/metaspaceShared.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -53,6 +53,7 @@
     memset(this, 0, sizeof(*this));
   }
   CompactHashtableStats symbol;
+  CompactHashtableStats string;
 };
 
 // Class Data Sharing Support
@@ -90,7 +91,10 @@
     rw = 1,  // read-write shared space in the heap
     md = 2,  // miscellaneous data for initializing tables, etc.
     mc = 3,  // miscellaneous code - vtable replacement.
-    n_regions = 4
+    max_strings = 2, // max number of string regions in string space
+    num_non_strings = 4, // number of non-string regions
+    first_string = num_non_strings, // index of first string region
+    n_regions = max_strings + num_non_strings // total number of regions
   };
 
   // Accessor functions to save shared space created for metadata, which has
@@ -124,10 +128,13 @@
   }
   static bool map_shared_spaces(FileMapInfo* mapinfo) NOT_CDS_RETURN_(false);
   static void initialize_shared_spaces() NOT_CDS_RETURN;
+  static void fixup_shared_string_regions() NOT_CDS_RETURN;
 
   // Return true if given address is in the mapped shared space.
   static bool is_in_shared_space(const void* p) NOT_CDS_RETURN_(false);
 
+  static bool is_string_region(int idx) NOT_CDS_RETURN_(false);
+
   static void generate_vtable_methods(void** vtbl_list,
                                       void** vtable,
                                       char** md_top, char* md_end,
--- a/hotspot/src/share/vm/memory/universe.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/memory/universe.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -311,6 +311,7 @@
              SystemDictionary::Cloneable_klass(), "u3");
       assert(_the_array_interfaces_array->at(1) ==
              SystemDictionary::Serializable_klass(), "u3");
+      MetaspaceShared::fixup_shared_string_regions();
     } else {
       // Set up shared interfaces array.  (Do this before supers are set up.)
       _the_array_interfaces_array->at_put(0, SystemDictionary::Cloneable_klass());
@@ -754,7 +755,7 @@
     Universe::set_narrow_ptrs_base(Universe::narrow_oop_base());
 
     if (PrintCompressedOopsMode || (PrintMiscellaneous && Verbose)) {
-      Universe::print_compressed_oops_mode();
+      Universe::print_compressed_oops_mode(tty);
     }
 
     // Tell tests in which mode we run.
@@ -781,27 +782,24 @@
   return JNI_OK;
 }
 
-void Universe::print_compressed_oops_mode() {
-  tty->cr();
-  tty->print("heap address: " PTR_FORMAT ", size: " SIZE_FORMAT " MB",
+void Universe::print_compressed_oops_mode(outputStream* st) {
+  st->print("heap address: " PTR_FORMAT ", size: " SIZE_FORMAT " MB",
               p2i(Universe::heap()->base()), Universe::heap()->reserved_region().byte_size()/M);
 
-  tty->print(", Compressed Oops mode: %s", narrow_oop_mode_to_string(narrow_oop_mode()));
+  st->print(", Compressed Oops mode: %s", narrow_oop_mode_to_string(narrow_oop_mode()));
 
   if (Universe::narrow_oop_base() != 0) {
-    tty->print(": " PTR_FORMAT, p2i(Universe::narrow_oop_base()));
+    st->print(": " PTR_FORMAT, p2i(Universe::narrow_oop_base()));
   }
 
   if (Universe::narrow_oop_shift() != 0) {
-    tty->print(", Oop shift amount: %d", Universe::narrow_oop_shift());
+    st->print(", Oop shift amount: %d", Universe::narrow_oop_shift());
   }
 
   if (!Universe::narrow_oop_use_implicit_null_checks()) {
-    tty->print(", no protected page in front of the heap");
+    st->print(", no protected page in front of the heap");
   }
-
-  tty->cr();
-  tty->cr();
+  st->cr();
 }
 
 ReservedSpace Universe::reserve_heap(size_t heap_size, size_t alignment) {
--- a/hotspot/src/share/vm/memory/universe.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/memory/universe.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -398,7 +398,7 @@
   static void     set_narrow_ptrs_base(address a)         { _narrow_ptrs_base = a; }
   static address  narrow_ptrs_base()                      { return _narrow_ptrs_base; }
 
-  static void     print_compressed_oops_mode();
+  static void     print_compressed_oops_mode(outputStream* st);
 
   // this is set in vm_version on sparc (and then reset in universe afaict)
   static void     set_narrow_oop_shift(int shift)         {
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -381,6 +381,9 @@
     if (!constants()->is_shared()) {
       MetadataFactory::free_metadata(loader_data, constants());
     }
+    // Delete any cached resolution errors for the constant pool
+    SystemDictionary::delete_resolution_error(constants());
+
     set_constants(NULL);
   }
 
--- a/hotspot/src/share/vm/opto/c2_globals.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/opto/c2_globals.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, 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
@@ -25,4 +25,12 @@
 #include "precompiled.hpp"
 #include "opto/c2_globals.hpp"
 
-C2_FLAGS(MATERIALIZE_DEVELOPER_FLAG, MATERIALIZE_PD_DEVELOPER_FLAG, MATERIALIZE_PRODUCT_FLAG, MATERIALIZE_PD_PRODUCT_FLAG, MATERIALIZE_DIAGNOSTIC_FLAG, MATERIALIZE_EXPERIMENTAL_FLAG, MATERIALIZE_NOTPRODUCT_FLAG)
+C2_FLAGS(MATERIALIZE_DEVELOPER_FLAG, \
+         MATERIALIZE_PD_DEVELOPER_FLAG, \
+         MATERIALIZE_PRODUCT_FLAG, \
+         MATERIALIZE_PD_PRODUCT_FLAG, \
+         MATERIALIZE_DIAGNOSTIC_FLAG, \
+         MATERIALIZE_EXPERIMENTAL_FLAG, \
+         MATERIALIZE_NOTPRODUCT_FLAG, \
+         IGNORE_RANGE, \
+         IGNORE_CONSTRAINT)
--- a/hotspot/src/share/vm/opto/c2_globals.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/opto/c2_globals.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, 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
@@ -61,7 +61,7 @@
 // Defines all globals flags used by the server compiler.
 //
 
-#define C2_FLAGS(develop, develop_pd, product, product_pd, diagnostic, experimental, notproduct) \
+#define C2_FLAGS(develop, develop_pd, product, product_pd, diagnostic, experimental, notproduct, range, constraint) \
                                                                             \
   develop(bool, StressLCM, false,                                           \
           "Randomize instruction scheduling in LCM")                        \
@@ -94,7 +94,8 @@
           "in generated code (in bytes)")                                   \
                                                                             \
   product(intx, MaxLoopPad, (OptoLoopAlignment-1),                          \
-          "Align a loop if padding size in bytes is less or equal to this value") \
+          "Align a loop if padding size in bytes is less or equal to this " \
+          "value")                                                          \
                                                                             \
   product(intx, MaxVectorSize, 64,                                          \
           "Max vector size in bytes, "                                      \
@@ -108,6 +109,7 @@
                                                                             \
   notproduct(intx, IndexSetWatch, 0,                                        \
           "Trace all operations on this IndexSet (-1 means all, 0 none)")   \
+          range(-1, 0)                                                      \
                                                                             \
   develop(intx, OptoNodeListSize, 4,                                        \
           "Starting allocation size of Node_List data structures")          \
@@ -368,6 +370,7 @@
           "System-wide value, 0=nothing is printed, 3=all details printed. "\
           "Level of detail of printouts can be set on a per-method level "  \
           "as well by using CompileCommand=option.")                        \
+          range(0, 3)                                                       \
                                                                             \
   develop(intx, PrintIdealGraphPort, 4444,                                  \
           "Ideal graph printer to network port")                            \
@@ -389,13 +392,16 @@
           "Insert memory barrier after arraycopy call")                     \
                                                                             \
   develop(bool, SubsumeLoads, true,                                         \
-          "Attempt to compile while subsuming loads into machine instructions.") \
+          "Attempt to compile while subsuming loads into machine "          \
+          "instructions.")                                                  \
                                                                             \
   develop(bool, StressRecompilation, false,                                 \
-          "Recompile each compiled method without subsuming loads or escape analysis.") \
+          "Recompile each compiled method without subsuming loads "         \
+          "or escape analysis.")                                            \
                                                                             \
   develop(intx, ImplicitNullCheckThreshold, 3,                              \
-          "Don't do implicit null checks if NPE's in a method exceeds limit") \
+          "Don't do implicit null checks if NPE's in a method exceeds "     \
+          "limit")                                                          \
                                                                             \
   product(intx, LoopOptsCount, 43,                                          \
           "Set level of loop optimization for tier 1 compiles")             \
@@ -541,15 +547,16 @@
           "Use edge frequencies to drive block ordering")                   \
                                                                             \
   product(intx, BlockLayoutMinDiamondPercentage, 20,                        \
-          "Miniumum %% of a successor (predecessor) for which block layout "\
-          "a will allow a fork (join) in a single chain")                   \
+          "Miniumum %% of a successor (predecessor) for which block "       \
+          "layout a will allow a fork (join) in a single chain")            \
+          range(0, 100)                                                     \
                                                                             \
   product(bool, BlockLayoutRotateLoops, true,                               \
           "Allow back branches to be fall throughs in the block layour")    \
                                                                             \
   develop(bool, InlineReflectionGetCallerClass, true,                       \
-          "inline sun.reflect.Reflection.getCallerClass(), known to be part "\
-          "of base library DLL")                                            \
+          "inline sun.reflect.Reflection.getCallerClass(), known to be "    \
+          "part of base library DLL")                                       \
                                                                             \
   develop(bool, InlineObjectCopy, true,                                     \
           "inline Object.clone and Arrays.copyOf[Range] intrinsics")        \
@@ -611,6 +618,7 @@
                                                                             \
   product(intx, TypeProfileMajorReceiverPercent, 90,                        \
           "% of major receiver type to all profiled receivers")             \
+          range(0, 100)                                                     \
                                                                             \
   diagnostic(bool, PrintIntrinsics, false,                                  \
           "prints attempted and successful inlining of intrinsics")         \
@@ -650,6 +658,8 @@
   product(intx, AliasLevel,     3,                                          \
           "0 for no aliasing, 1 for oop/field/static/array split, "         \
           "2 for class split, 3 for unique instances")                      \
+          range(0, 3)                                                       \
+          constraint(AliasLevelConstraintFunc)                              \
                                                                             \
   develop(bool, VerifyAliases, false,                                       \
           "perform extra checks on the results of alias analysis")          \
@@ -696,6 +706,14 @@
   develop(bool, StressArrayCopyMacroNode, false,                            \
           "Perform ArrayCopy load/store replacement during IGVN only")
 
-C2_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_EXPERIMENTAL_FLAG, DECLARE_NOTPRODUCT_FLAG)
+C2_FLAGS(DECLARE_DEVELOPER_FLAG, \
+         DECLARE_PD_DEVELOPER_FLAG, \
+         DECLARE_PRODUCT_FLAG, \
+         DECLARE_PD_PRODUCT_FLAG, \
+         DECLARE_DIAGNOSTIC_FLAG, \
+         DECLARE_EXPERIMENTAL_FLAG, \
+         DECLARE_NOTPRODUCT_FLAG, \
+         IGNORE_RANGE, \
+         IGNORE_CONSTRAINT)
 
 #endif // SHARE_VM_OPTO_C2_GLOBALS_HPP
--- a/hotspot/src/share/vm/opto/graphKit.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/opto/graphKit.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -3803,6 +3803,11 @@
   Node*   zero = __ ConI(0); // Dirty card value
   BasicType bt = T_BYTE;
 
+  if (UseConcMarkSweepGC && UseCondCardMark) {
+    insert_mem_bar(Op_MemBarVolatile);   // StoreLoad barrier
+    __ sync_kit(this);
+  }
+
   if (UseCondCardMark) {
     // The classic GC reference write barrier is typically implemented
     // as a store into the global card mark table.  Unfortunately
--- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -4089,9 +4089,6 @@
     mnt->adjust_method_entries(the_class(), &trace_name_printed);
   }
 
-  // Fix Resolution Error table also to remove old constant pools
-  SystemDictionary::delete_resolution_error(old_constants);
-
   if (the_class->oop_map_cache() != NULL) {
     // Flush references to any obsolete methods from the oop map cache
     // so that obsolete methods are not pinned.
--- a/hotspot/src/share/vm/prims/whitebox.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/prims/whitebox.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -31,6 +31,7 @@
 #include "code/codeCache.hpp"
 #include "jvmtifiles/jvmtiEnv.hpp"
 #include "memory/metadataFactory.hpp"
+#include "memory/metaspaceShared.hpp"
 #include "memory/universe.hpp"
 #include "oops/oop.inline.hpp"
 #include "prims/wbtestmethods/parserTests.hpp"
@@ -89,6 +90,10 @@
   return os::vm_page_size();
 WB_END
 
+WB_ENTRY(jlong, WB_GetVMAllocationGranularity(JNIEnv* env, jobject o))
+  return os::vm_allocation_granularity();
+WB_END
+
 WB_ENTRY(jlong, WB_GetVMLargePageSize(JNIEnv* env, jobject o))
   return os::large_page_size();
 WB_END
@@ -630,27 +635,27 @@
 WB_END
 
 template <typename T>
-static bool GetVMFlag(JavaThread* thread, JNIEnv* env, jstring name, T* value, bool (*TAt)(const char*, T*, bool, bool)) {
+static bool GetVMFlag(JavaThread* thread, JNIEnv* env, jstring name, T* value, Flag::Error (*TAt)(const char*, T*, bool, bool)) {
   if (name == NULL) {
     return false;
   }
   ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
   const char* flag_name = env->GetStringUTFChars(name, NULL);
-  bool result = (*TAt)(flag_name, value, true, true);
+  Flag::Error result = (*TAt)(flag_name, value, true, true);
   env->ReleaseStringUTFChars(name, flag_name);
-  return result;
+  return (result == Flag::SUCCESS);
 }
 
 template <typename T>
-static bool SetVMFlag(JavaThread* thread, JNIEnv* env, jstring name, T* value, bool (*TAtPut)(const char*, T*, Flag::Flags)) {
+static bool SetVMFlag(JavaThread* thread, JNIEnv* env, jstring name, T* value, Flag::Error (*TAtPut)(const char*, T*, Flag::Flags)) {
   if (name == NULL) {
     return false;
   }
   ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
   const char* flag_name = env->GetStringUTFChars(name, NULL);
-  bool result = (*TAtPut)(flag_name, value, Flag::INTERNAL);
+  Flag::Error result = (*TAtPut)(flag_name, value, Flag::INTERNAL);
   env->ReleaseStringUTFChars(name, flag_name);
-  return result;
+  return (result == Flag::SUCCESS);
 }
 
 template <typename T>
@@ -1207,6 +1212,15 @@
   return NULL;
 WB_END
 
+WB_ENTRY(jboolean, WB_IsShared(JNIEnv* env, jobject wb, jobject obj))
+  oop obj_oop = JNIHandles::resolve(obj);
+  return MetaspaceShared::is_in_shared_space((void*)obj_oop);
+WB_END
+
+WB_ENTRY(jboolean, WB_AreSharedStringsIgnored(JNIEnv* env))
+  return StringTable::shared_string_ignored();
+WB_END
+
 //Some convenience methods to deal with objects from java
 int WhiteBox::offset_for_field(const char* field_name, oop object,
     Symbol* signature_symbol) {
@@ -1291,13 +1305,14 @@
 #define CC (char*)
 
 static JNINativeMethod methods[] = {
-  {CC"getObjectAddress0",   CC"(Ljava/lang/Object;)J", (void*)&WB_GetObjectAddress  },
-  {CC"getObjectSize0",      CC"(Ljava/lang/Object;)J", (void*)&WB_GetObjectSize     },
-  {CC"isObjectInOldGen0",   CC"(Ljava/lang/Object;)Z", (void*)&WB_isObjectInOldGen  },
-  {CC"getHeapOopSize",     CC"()I",                   (void*)&WB_GetHeapOopSize    },
-  {CC"getVMPageSize",      CC"()I",                   (void*)&WB_GetVMPageSize     },
-  {CC"getVMLargePageSize", CC"()J",                   (void*)&WB_GetVMLargePageSize},
-  {CC"isClassAlive0",      CC"(Ljava/lang/String;)Z", (void*)&WB_IsClassAlive      },
+  {CC"getObjectAddress0",                CC"(Ljava/lang/Object;)J", (void*)&WB_GetObjectAddress  },
+  {CC"getObjectSize0",                   CC"(Ljava/lang/Object;)J", (void*)&WB_GetObjectSize     },
+  {CC"isObjectInOldGen0",                CC"(Ljava/lang/Object;)Z", (void*)&WB_isObjectInOldGen  },
+  {CC"getHeapOopSize",                   CC"()I",                   (void*)&WB_GetHeapOopSize    },
+  {CC"getVMPageSize",                    CC"()I",                   (void*)&WB_GetVMPageSize     },
+  {CC"getVMAllocationGranularity",       CC"()J",                   (void*)&WB_GetVMAllocationGranularity },
+  {CC"getVMLargePageSize",               CC"()J",                   (void*)&WB_GetVMLargePageSize},
+  {CC"isClassAlive0",                    CC"(Ljava/lang/String;)Z", (void*)&WB_IsClassAlive      },
   {CC"parseCommandLine0",
       CC"(Ljava/lang/String;C[Lsun/hotspot/parser/DiagnosticCommand;)[Ljava/lang/Object;",
       (void*) &WB_ParseCommandLine
@@ -1431,6 +1446,8 @@
   {CC"getMethodStringOption",
       CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/String;",
                                                       (void*)&WB_GetMethodStringOption},
+  {CC"isShared",           CC"(Ljava/lang/Object;)Z", (void*)&WB_IsShared },
+  {CC"areSharedStringsIgnored",           CC"()Z",    (void*)&WB_AreSharedStringsIgnored },
 };
 
 #undef CC
--- a/hotspot/src/share/vm/runtime/arguments.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/runtime/arguments.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -38,6 +38,9 @@
 #include "prims/jvmtiExport.hpp"
 #include "runtime/arguments.hpp"
 #include "runtime/arguments_ext.hpp"
+#include "runtime/commandLineFlagConstraintList.hpp"
+#include "runtime/commandLineFlagRangeList.hpp"
+#include "runtime/globals.hpp"
 #include "runtime/globals_extension.hpp"
 #include "runtime/java.hpp"
 #include "runtime/os.hpp"
@@ -187,7 +190,6 @@
 
 // Initialize system properties key and value.
 void Arguments::init_system_properties() {
-
   PropertyList_add(&_system_properties, new SystemProperty("java.vm.specification.name",
                                                                  "Java Virtual Machine Specification",  false));
   PropertyList_add(&_system_properties, new SystemProperty("java.vm.version", VM_Version::vm_release(),  false));
@@ -215,8 +217,7 @@
   os::init_system_properties_values();
 }
 
-
-  // Update/Initialize System properties after JDK version number is known
+// Update/Initialize System properties after JDK version number is known
 void Arguments::init_version_specific_system_properties() {
   enum { bufsz = 16 };
   char buffer[bufsz];
@@ -273,6 +274,7 @@
   { "UseCompilerSafepoints",         JDK_Version::jdk(9), JDK_Version::jdk(10) },
   { "AdaptiveSizePausePolicy",       JDK_Version::jdk(9), JDK_Version::jdk(10) },
   { "ParallelGCRetainPLAB",          JDK_Version::jdk(9), JDK_Version::jdk(10) },
+  { "ThreadSafetyMargin",            JDK_Version::jdk(9), JDK_Version::jdk(10) },
   { NULL, JDK_Version(0), JDK_Version(0) }
 };
 
@@ -569,7 +571,11 @@
 }
 
 static bool set_bool_flag(char* name, bool value, Flag::Flags origin) {
-  return CommandLineFlags::boolAtPut(name, &value, origin);
+  if (CommandLineFlags::boolAtPut(name, &value, origin) == Flag::SUCCESS) {
+    return true;
+  } else {
+    return false;
+  }
 }
 
 static bool set_fp_numeric_flag(char* name, char* value, Flag::Flags origin) {
@@ -578,7 +584,7 @@
     return false;
   }
 
-  if (CommandLineFlags::doubleAtPut(name, &v, origin)) {
+  if (CommandLineFlags::doubleAtPut(name, &v, origin) == Flag::SUCCESS) {
     return true;
   }
   return false;
@@ -591,7 +597,7 @@
   bool is_neg = false;
   // Check the sign first since atomull() parses only unsigned values.
   if (*value == '-') {
-    if (!CommandLineFlags::intxAt(name, &intx_v) && !CommandLineFlags::intAt(name, &int_v)) {
+    if ((CommandLineFlags::intxAt(name, &intx_v) != Flag::SUCCESS) && (CommandLineFlags::intAt(name, &int_v) != Flag::SUCCESS)) {
       return false;
     }
     value++;
@@ -604,37 +610,37 @@
   if (is_neg) {
     int_v = -int_v;
   }
-  if (CommandLineFlags::intAtPut(name, &int_v, origin)) {
+  if (CommandLineFlags::intAtPut(name, &int_v, origin) == Flag::SUCCESS) {
     return true;
   }
   uint uint_v = (uint) v;
-  if (!is_neg && CommandLineFlags::uintAtPut(name, &uint_v, origin)) {
+  if (!is_neg && CommandLineFlags::uintAtPut(name, &uint_v, origin) == Flag::SUCCESS) {
     return true;
   }
   intx_v = (intx) v;
   if (is_neg) {
     intx_v = -intx_v;
   }
-  if (CommandLineFlags::intxAtPut(name, &intx_v, origin)) {
+  if (CommandLineFlags::intxAtPut(name, &intx_v, origin) == Flag::SUCCESS) {
     return true;
   }
   uintx uintx_v = (uintx) v;
-  if (!is_neg && CommandLineFlags::uintxAtPut(name, &uintx_v, origin)) {
+  if (!is_neg && (CommandLineFlags::uintxAtPut(name, &uintx_v, origin) == Flag::SUCCESS)) {
     return true;
   }
   uint64_t uint64_t_v = (uint64_t) v;
-  if (!is_neg && CommandLineFlags::uint64_tAtPut(name, &uint64_t_v, origin)) {
+  if (!is_neg && (CommandLineFlags::uint64_tAtPut(name, &uint64_t_v, origin) == Flag::SUCCESS)) {
     return true;
   }
   size_t size_t_v = (size_t) v;
-  if (!is_neg && CommandLineFlags::size_tAtPut(name, &size_t_v, origin)) {
+  if (!is_neg && (CommandLineFlags::size_tAtPut(name, &size_t_v, origin) == Flag::SUCCESS)) {
     return true;
   }
   return false;
 }
 
 static bool set_string_flag(char* name, const char* value, Flag::Flags origin) {
-  if (!CommandLineFlags::ccstrAtPut(name, &value, origin))  return false;
+  if (CommandLineFlags::ccstrAtPut(name, &value, origin) != Flag::SUCCESS) return false;
   // Contract:  CommandLineFlags always returns a pointer that needs freeing.
   FREE_C_HEAP_ARRAY(char, value);
   return true;
@@ -642,7 +648,7 @@
 
 static bool append_to_string_flag(char* name, const char* new_value, Flag::Flags origin) {
   const char* old_value = "";
-  if (!CommandLineFlags::ccstrAt(name, &old_value))  return false;
+  if (CommandLineFlags::ccstrAt(name, &old_value) != Flag::SUCCESS) return false;
   size_t old_len = old_value != NULL ? strlen(old_value) : 0;
   size_t new_len = strlen(new_value);
   const char* value;
@@ -1384,10 +1390,16 @@
   if (!FLAG_IS_DEFAULT(OldPLABSize) || !FLAG_IS_DEFAULT(OldPLABWeight)) {
     CFLS_LAB::modify_initialization(OldPLABSize, OldPLABWeight);
   }
+
+  if (!ClassUnloading) {
+    FLAG_SET_CMDLINE(bool, CMSClassUnloadingEnabled, false);
+    FLAG_SET_CMDLINE(bool, ExplicitGCInvokesConcurrentAndUnloadsClasses, false);
+  }
+
   if (PrintGCDetails && Verbose) {
     tty->print_cr("MarkStackSize: %uk  MarkStackSizeMax: %uk",
       (unsigned int) (MarkStackSize / K), (uint) (MarkStackSizeMax / K));
-    tty->print_cr("ConcGCThreads: %u", (uint) ConcGCThreads);
+    tty->print_cr("ConcGCThreads: %u", ConcGCThreads);
   }
 }
 #endif // INCLUDE_ALL_GCS
@@ -1407,61 +1419,16 @@
   // Oop encoding heap max
   OopEncodingHeapMax = (uint64_t(max_juint) + 1) << LogMinObjAlignmentInBytes;
 
+  if (SurvivorAlignmentInBytes == 0) {
+    SurvivorAlignmentInBytes = ObjectAlignmentInBytes;
+  }
+
 #if INCLUDE_ALL_GCS
   // Set CMS global values
   CompactibleFreeListSpace::set_cms_values();
 #endif // INCLUDE_ALL_GCS
 }
 
-bool verify_object_alignment() {
-  // Object alignment.
-  if (!is_power_of_2(ObjectAlignmentInBytes)) {
-    jio_fprintf(defaultStream::error_stream(),
-                "error: ObjectAlignmentInBytes=%d must be power of 2\n",
-                (int)ObjectAlignmentInBytes);
-    return false;
-  }
-  if ((int)ObjectAlignmentInBytes < BytesPerLong) {
-    jio_fprintf(defaultStream::error_stream(),
-                "error: ObjectAlignmentInBytes=%d must be greater or equal %d\n",
-                (int)ObjectAlignmentInBytes, BytesPerLong);
-    return false;
-  }
-  // It does not make sense to have big object alignment
-  // since a space lost due to alignment will be greater
-  // then a saved space from compressed oops.
-  if ((int)ObjectAlignmentInBytes > 256) {
-    jio_fprintf(defaultStream::error_stream(),
-                "error: ObjectAlignmentInBytes=%d must not be greater than 256\n",
-                (int)ObjectAlignmentInBytes);
-    return false;
-  }
-  // In case page size is very small.
-  if ((int)ObjectAlignmentInBytes >= os::vm_page_size()) {
-    jio_fprintf(defaultStream::error_stream(),
-                "error: ObjectAlignmentInBytes=%d must be less than page size %d\n",
-                (int)ObjectAlignmentInBytes, os::vm_page_size());
-    return false;
-  }
-  if(SurvivorAlignmentInBytes == 0) {
-    SurvivorAlignmentInBytes = ObjectAlignmentInBytes;
-  } else {
-    if (!is_power_of_2(SurvivorAlignmentInBytes)) {
-      jio_fprintf(defaultStream::error_stream(),
-            "error: SurvivorAlignmentInBytes=%d must be power of 2\n",
-            (int)SurvivorAlignmentInBytes);
-      return false;
-    }
-    if (SurvivorAlignmentInBytes < ObjectAlignmentInBytes) {
-      jio_fprintf(defaultStream::error_stream(),
-          "error: SurvivorAlignmentInBytes=%d must be greater than ObjectAlignmentInBytes=%d \n",
-          (int)SurvivorAlignmentInBytes, (int)ObjectAlignmentInBytes);
-      return false;
-    }
-  }
-  return true;
-}
-
 size_t Arguments::max_heap_for_compressed_oops() {
   // Avoid sign flip.
   assert(OopEncodingHeapMax > (uint64_t)os::vm_page_size(), "Unusual page size");
@@ -1568,7 +1535,11 @@
     if (should_auto_select_low_pause_collector()) {
       FLAG_SET_ERGO(bool, UseConcMarkSweepGC, true);
     } else {
+#if defined(JAVASE_EMBEDDED)
       FLAG_SET_ERGO(bool, UseParallelGC, true);
+#else
+      FLAG_SET_ERGO(bool, UseG1GC, true);
+#endif
     }
   } else {
     FLAG_SET_ERGO(bool, UseSerialGC, true);
@@ -1705,7 +1676,7 @@
   if (PrintGCDetails && Verbose) {
     tty->print_cr("MarkStackSize: %uk  MarkStackSizeMax: %uk",
       (unsigned int) (MarkStackSize / K), (uint) (MarkStackSizeMax / K));
-    tty->print_cr("ConcGCThreads: %u", (uint) ConcGCThreads);
+    tty->print_cr("ConcGCThreads: %u", ConcGCThreads);
   }
 }
 
@@ -1944,42 +1915,6 @@
 //===========================================================================================================
 // Parsing of main arguments
 
-bool Arguments::verify_interval(uintx val, uintx min,
-                                uintx max, const char* name) {
-  // Returns true iff value is in the inclusive interval [min..max]
-  // false, otherwise.
-  if (val >= min && val <= max) {
-    return true;
-  }
-  jio_fprintf(defaultStream::error_stream(),
-              "%s of " UINTX_FORMAT " is invalid; must be between " UINTX_FORMAT
-              " and " UINTX_FORMAT "\n",
-              name, val, min, max);
-  return false;
-}
-
-bool Arguments::verify_min_value(intx val, intx min, const char* name) {
-  // Returns true if given value is at least specified min threshold
-  // false, otherwise.
-  if (val >= min ) {
-      return true;
-  }
-  jio_fprintf(defaultStream::error_stream(),
-              "%s of " INTX_FORMAT " is invalid; must be at least " INTX_FORMAT "\n",
-              name, val, min);
-  return false;
-}
-
-bool Arguments::verify_percentage(uintx value, const char* name) {
-  if (is_percentage(value)) {
-    return true;
-  }
-  jio_fprintf(defaultStream::error_stream(),
-              "%s of " UINTX_FORMAT " is invalid; must be between 0 and 100\n",
-              name, value);
-  return false;
-}
-
 // check if do gclog rotation
 // +UseGCLogFileRotation is a must,
 // no gc log rotation when log file not supplied or
@@ -1996,9 +1931,10 @@
   }
 
   if (UseGCLogFileRotation && (GCLogFileSize != 0) && (GCLogFileSize < 8*K)) {
-    FLAG_SET_CMDLINE(size_t, GCLogFileSize, 8*K);
-    jio_fprintf(defaultStream::output_stream(),
+    if (FLAG_SET_CMDLINE(size_t, GCLogFileSize, 8*K) == Flag::SUCCESS) {
+      jio_fprintf(defaultStream::output_stream(),
                 "GCLogFileSize changed to minimum 8K\n");
+    }
   }
 }
 
@@ -2047,38 +1983,6 @@
   return count_p < 2 && count_t < 2;
 }
 
-bool Arguments::verify_MinHeapFreeRatio(FormatBuffer<80>& err_msg, uintx min_heap_free_ratio) {
-  if (!is_percentage(min_heap_free_ratio)) {
-    err_msg.print("MinHeapFreeRatio must have a value between 0 and 100");
-    return false;
-  }
-  if (min_heap_free_ratio > MaxHeapFreeRatio) {
-    err_msg.print("MinHeapFreeRatio (" UINTX_FORMAT ") must be less than or "
-                  "equal to MaxHeapFreeRatio (" UINTX_FORMAT ")", min_heap_free_ratio,
-                  MaxHeapFreeRatio);
-    return false;
-  }
-  // This does not set the flag itself, but stores the value in a safe place for later usage.
-  _min_heap_free_ratio = min_heap_free_ratio;
-  return true;
-}
-
-bool Arguments::verify_MaxHeapFreeRatio(FormatBuffer<80>& err_msg, uintx max_heap_free_ratio) {
-  if (!is_percentage(max_heap_free_ratio)) {
-    err_msg.print("MaxHeapFreeRatio must have a value between 0 and 100");
-    return false;
-  }
-  if (max_heap_free_ratio < MinHeapFreeRatio) {
-    err_msg.print("MaxHeapFreeRatio (" UINTX_FORMAT ") must be greater than or "
-                  "equal to MinHeapFreeRatio (" UINTX_FORMAT ")", max_heap_free_ratio,
-                  MinHeapFreeRatio);
-    return false;
-  }
-  // This does not set the flag itself, but stores the value in a safe place for later usage.
-  _max_heap_free_ratio = max_heap_free_ratio;
-  return true;
-}
-
 // Check consistency of GC selection
 bool Arguments::check_gc_consistency() {
   check_gclog_consistency();
@@ -2126,17 +2030,6 @@
   }
 }
 
-// Check stack pages settings
-bool Arguments::check_stack_pages()
-{
-  bool status = true;
-  status = status && verify_min_value(StackYellowPages, 1, "StackYellowPages");
-  status = status && verify_min_value(StackRedPages, 1, "StackRedPages");
-  // greater stack shadow pages can't generate instruction to bang stack
-  status = status && verify_interval(StackShadowPages, 1, 50, "StackShadowPages");
-  return status;
-}
-
 // Check the consistency of vm_init_args
 bool Arguments::check_vm_args_consistency() {
   // Method for adding checks for flag consistency.
@@ -2153,50 +2046,6 @@
     status = false;
   }
 
-  status = status && verify_interval(AdaptiveSizePolicyWeight, 0, 100,
-                              "AdaptiveSizePolicyWeight");
-  status = status && verify_percentage(ThresholdTolerance, "ThresholdTolerance");
-
-  // Divide by bucket size to prevent a large size from causing rollover when
-  // calculating amount of memory needed to be allocated for the String table.
-  status = status && verify_interval(StringTableSize, minimumStringTableSize,
-    (max_uintx / StringTable::bucket_size()), "StringTable size");
-
-  status = status && verify_interval(SymbolTableSize, minimumSymbolTableSize,
-    (max_uintx / SymbolTable::bucket_size()), "SymbolTable size");
-
-  {
-    // Using "else if" below to avoid printing two error messages if min > max.
-    // This will also prevent us from reporting both min>100 and max>100 at the
-    // same time, but that is less annoying than printing two identical errors IMHO.
-    FormatBuffer<80> err_msg("%s","");
-    if (!verify_MinHeapFreeRatio(err_msg, MinHeapFreeRatio)) {
-      jio_fprintf(defaultStream::error_stream(), "%s\n", err_msg.buffer());
-      status = false;
-    } else if (!verify_MaxHeapFreeRatio(err_msg, MaxHeapFreeRatio)) {
-      jio_fprintf(defaultStream::error_stream(), "%s\n", err_msg.buffer());
-      status = false;
-    }
-  }
-
-  // Min/MaxMetaspaceFreeRatio
-  status = status && verify_percentage(MinMetaspaceFreeRatio, "MinMetaspaceFreeRatio");
-  status = status && verify_percentage(MaxMetaspaceFreeRatio, "MaxMetaspaceFreeRatio");
-
-  if (MinMetaspaceFreeRatio > MaxMetaspaceFreeRatio) {
-    jio_fprintf(defaultStream::error_stream(),
-                "MinMetaspaceFreeRatio (%s" UINTX_FORMAT ") must be less than or "
-                "equal to MaxMetaspaceFreeRatio (%s" UINTX_FORMAT ")\n",
-                FLAG_IS_DEFAULT(MinMetaspaceFreeRatio) ? "Default: " : "",
-                MinMetaspaceFreeRatio,
-                FLAG_IS_DEFAULT(MaxMetaspaceFreeRatio) ? "Default: " : "",
-                MaxMetaspaceFreeRatio);
-    status = false;
-  }
-
-  // Trying to keep 100% free is not practical
-  MinMetaspaceFreeRatio = MIN2(MinMetaspaceFreeRatio, (uintx) 99);
-
   if (FullGCALot && FLAG_IS_DEFAULT(MarkSweepAlwaysCompactCount)) {
     MarkSweepAlwaysCompactCount = 1;  // Move objects every gc.
   }
@@ -2204,10 +2053,14 @@
   if (UseParallelOldGC && ParallelOldGCSplitALot) {
     // Settings to encourage splitting.
     if (!FLAG_IS_CMDLINE(NewRatio)) {
-      FLAG_SET_CMDLINE(uintx, NewRatio, 2);
+      if (FLAG_SET_CMDLINE(uintx, NewRatio, 2) != Flag::SUCCESS) {
+        status = false;
+      }
     }
     if (!FLAG_IS_CMDLINE(ScavengeBeforeFullGC)) {
-      FLAG_SET_CMDLINE(bool, ScavengeBeforeFullGC, false);
+      if (FLAG_SET_CMDLINE(bool, ScavengeBeforeFullGC, false) != Flag::SUCCESS) {
+        status = false;
+      }
     }
   }
 
@@ -2215,18 +2068,12 @@
     FLAG_SET_DEFAULT(ScavengeBeforeFullGC, false);
   }
 
-  status = status && verify_percentage(GCHeapFreeLimit, "GCHeapFreeLimit");
-  status = status && verify_percentage(GCTimeLimit, "GCTimeLimit");
   if (GCTimeLimit == 100) {
     // Turn off gc-overhead-limit-exceeded checks
     FLAG_SET_DEFAULT(UseGCOverheadLimit, false);
   }
 
   status = status && check_gc_consistency();
-  status = status && check_stack_pages();
-
-  status = status && verify_percentage(CMSIncrementalSafetyFactor,
-                                    "CMSIncrementalSafetyFactor");
 
   // CMS space iteration, which FLSVerifyAllHeapreferences entails,
   // insists that we hold the requisite locks so that the iteration is
@@ -2260,132 +2107,6 @@
     status = false;
   }
 
-  status = status && verify_min_value(ParGCArrayScanChunk, 1, "ParGCArrayScanChunk");
-
-#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(G1ConfidencePercent, "G1ConfidencePercent");
-    status = status && verify_percentage(InitiatingHeapOccupancyPercent,
-                                         "InitiatingHeapOccupancyPercent");
-    status = status && verify_min_value(G1RefProcDrainInterval, 1,
-                                        "G1RefProcDrainInterval");
-    status = status && verify_min_value((intx)G1ConcMarkStepDurationMillis, 1,
-                                        "G1ConcMarkStepDurationMillis");
-    status = status && verify_interval(G1ConcRSHotCardLimit, 0, max_jubyte,
-                                       "G1ConcRSHotCardLimit");
-    status = status && verify_interval(G1ConcRSLogCacheSize, 0, 27,
-                                       "G1ConcRSLogCacheSize");
-    status = status && verify_interval(StringDeduplicationAgeThreshold, 1, markOopDesc::max_age,
-                                       "StringDeduplicationAgeThreshold");
-  }
-  if (UseConcMarkSweepGC) {
-    status = status && verify_min_value(CMSOldPLABNumRefills, 1, "CMSOldPLABNumRefills");
-    status = status && verify_min_value(CMSOldPLABToleranceFactor, 1, "CMSOldPLABToleranceFactor");
-    status = status && verify_min_value(CMSOldPLABMax, 1, "CMSOldPLABMax");
-    status = status && verify_interval(CMSOldPLABMin, 1, CMSOldPLABMax, "CMSOldPLABMin");
-
-    status = status && verify_min_value(CMSYoungGenPerWorker, 1, "CMSYoungGenPerWorker");
-
-    status = status && verify_min_value(CMSSamplingGrain, 1, "CMSSamplingGrain");
-    status = status && verify_interval(CMS_SweepWeight, 0, 100, "CMS_SweepWeight");
-    status = status && verify_interval(CMS_FLSWeight, 0, 100, "CMS_FLSWeight");
-
-    status = status && verify_interval(FLSCoalescePolicy, 0, 4, "FLSCoalescePolicy");
-
-    status = status && verify_min_value(CMSRescanMultiple, 1, "CMSRescanMultiple");
-    status = status && verify_min_value(CMSConcMarkMultiple, 1, "CMSConcMarkMultiple");
-
-    status = status && verify_interval(CMSPrecleanIter, 0, 9, "CMSPrecleanIter");
-    status = status && verify_min_value(CMSPrecleanDenominator, 1, "CMSPrecleanDenominator");
-    status = status && verify_interval(CMSPrecleanNumerator, 0, CMSPrecleanDenominator - 1, "CMSPrecleanNumerator");
-
-    status = status && verify_percentage(CMSBootstrapOccupancy, "CMSBootstrapOccupancy");
-
-    status = status && verify_min_value(CMSPrecleanThreshold, 100, "CMSPrecleanThreshold");
-
-    status = status && verify_percentage(CMSScheduleRemarkEdenPenetration, "CMSScheduleRemarkEdenPenetration");
-    status = status && verify_min_value(CMSScheduleRemarkSamplingRatio, 1, "CMSScheduleRemarkSamplingRatio");
-    status = status && verify_min_value(CMSBitMapYieldQuantum, 1, "CMSBitMapYieldQuantum");
-    status = status && verify_percentage(CMSTriggerRatio, "CMSTriggerRatio");
-    status = status && verify_percentage(CMSIsTooFullPercentage, "CMSIsTooFullPercentage");
-  }
-
-  if (UseParallelGC || UseParallelOldGC) {
-    status = status && verify_interval(ParallelOldDeadWoodLimiterMean, 0, 100, "ParallelOldDeadWoodLimiterMean");
-    status = status && verify_interval(ParallelOldDeadWoodLimiterStdDev, 0, 100, "ParallelOldDeadWoodLimiterStdDev");
-
-    status = status && verify_percentage(YoungGenerationSizeIncrement, "YoungGenerationSizeIncrement");
-    status = status && verify_percentage(TenuredGenerationSizeIncrement, "TenuredGenerationSizeIncrement");
-
-    status = status && verify_min_value(YoungGenerationSizeSupplementDecay, 1, "YoungGenerationSizeSupplementDecay");
-    status = status && verify_min_value(TenuredGenerationSizeSupplementDecay, 1, "TenuredGenerationSizeSupplementDecay");
-
-    status = status && verify_min_value(ParGCCardsPerStrideChunk, 1, "ParGCCardsPerStrideChunk");
-
-    status = status && verify_min_value(ParallelOldGCSplitInterval, 0, "ParallelOldGCSplitInterval");
-  }
-#endif // INCLUDE_ALL_GCS
-
-  status = status && verify_interval(RefDiscoveryPolicy,
-                                     ReferenceProcessor::DiscoveryPolicyMin,
-                                     ReferenceProcessor::DiscoveryPolicyMax,
-                                     "RefDiscoveryPolicy");
-
-  // Limit the lower bound of this flag to 1 as it is used in a division
-  // expression.
-  status = status && verify_interval(TLABWasteTargetPercent,
-                                     1, 100, "TLABWasteTargetPercent");
-
-  status = status && verify_object_alignment();
-
-  status = status && verify_interval(CompressedClassSpaceSize, 1*M, 3*G,
-                                      "CompressedClassSpaceSize");
-
-  status = status && verify_interval(MarkStackSizeMax,
-                                  1, (max_jint - 1), "MarkStackSizeMax");
-  status = status && verify_interval(NUMAChunkResizeWeight, 0, 100, "NUMAChunkResizeWeight");
-
-  status = status && verify_min_value(LogEventsBufferEntries, 1, "LogEventsBufferEntries");
-
-  status = status && verify_min_value(HeapSizePerGCThread, (size_t) os::vm_page_size(), "HeapSizePerGCThread");
-
-  status = status && verify_min_value(GCTaskTimeStampEntries, 1, "GCTaskTimeStampEntries");
-
-  status = status && verify_percentage(ParallelGCBufferWastePct, "ParallelGCBufferWastePct");
-  status = status && verify_interval(TargetPLABWastePct, 1, 100, "TargetPLABWastePct");
-
-  status = status && verify_min_value(ParGCStridesPerThread, 1, "ParGCStridesPerThread");
-
-  status = status && verify_min_value(MinRAMFraction, 1, "MinRAMFraction");
-  status = status && verify_min_value(InitialRAMFraction, 1, "InitialRAMFraction");
-  status = status && verify_min_value(MaxRAMFraction, 1, "MaxRAMFraction");
-  status = status && verify_min_value(DefaultMaxRAMFraction, 1, "DefaultMaxRAMFraction");
-
-  status = status && verify_interval(AdaptiveTimeWeight, 0, 100, "AdaptiveTimeWeight");
-  status = status && verify_min_value(AdaptiveSizeDecrementScaleFactor, 1, "AdaptiveSizeDecrementScaleFactor");
-
-  status = status && verify_interval(TLABAllocationWeight, 0, 100, "TLABAllocationWeight");
-  status = status && verify_min_value(MinTLABSize, 1, "MinTLABSize");
-  status = status && verify_min_value(TLABRefillWasteFraction, 1, "TLABRefillWasteFraction");
-
-  status = status && verify_percentage(YoungGenerationSizeSupplement, "YoungGenerationSizeSupplement");
-  status = status && verify_percentage(TenuredGenerationSizeSupplement, "TenuredGenerationSizeSupplement");
-
-  status = status && verify_interval(MaxTenuringThreshold, 0, markOopDesc::max_age + 1, "MaxTenuringThreshold");
-  status = status && verify_interval(InitialTenuringThreshold, 0, MaxTenuringThreshold, "InitialTenuringThreshold");
-  status = status && verify_percentage(TargetSurvivorRatio, "TargetSurvivorRatio");
-  status = status && verify_percentage(MarkSweepDeadRatio, "MarkSweepDeadRatio");
-
-  status = status && verify_min_value(MarkSweepAlwaysCompactCount, 1, "MarkSweepAlwaysCompactCount");
-#ifdef COMPILER1
-  status = status && verify_min_value(ValueMapInitialSize, 1, "ValueMapInitialSize");
-#endif
-  status = status && verify_min_value(HeapSearchSteps, 1, "HeapSearchSteps");
-
   if (PrintNMTStatistics) {
 #if INCLUDE_NMT
     if (MemTracker::tracking_level() == NMT_off) {
@@ -2397,26 +2118,6 @@
 #endif
   }
 
-  // Need to limit the extent of the padding to reasonable size.
-  // 8K is well beyond the reasonable HW cache line size, even with the
-  // aggressive prefetching, while still leaving the room for segregating
-  // among the distinct pages.
-  if (ContendedPaddingWidth < 0 || ContendedPaddingWidth > 8192) {
-    jio_fprintf(defaultStream::error_stream(),
-                "ContendedPaddingWidth=" INTX_FORMAT " must be in between %d and %d\n",
-                ContendedPaddingWidth, 0, 8192);
-    status = false;
-  }
-
-  // Need to enforce the padding not to break the existing field alignments.
-  // It is sufficient to check against the largest type size.
-  if ((ContendedPaddingWidth % BytesPerLong) != 0) {
-    jio_fprintf(defaultStream::error_stream(),
-                "ContendedPaddingWidth=" INTX_FORMAT " must be a multiple of %d\n",
-                ContendedPaddingWidth, BytesPerLong);
-    status = false;
-  }
-
   // Check lower bounds of the code cache
   // Template Interpreter code is approximately 3X larger in debug builds.
   uint min_code_cache_size = CodeCacheMinimumUseSpace DEBUG_ONLY(* 3);
@@ -2455,17 +2156,9 @@
     status = false;
   }
 
-  status &= verify_interval(NmethodSweepActivity, 0, 2000, "NmethodSweepActivity");
-  status &= verify_interval(CodeCacheMinBlockLength, 1, 100, "CodeCacheMinBlockLength");
-  status &= verify_interval(CodeCacheSegmentSize, 1, 1024, "CodeCacheSegmentSize");
-  status &= verify_interval(StartAggressiveSweepingAt, 0, 100, "StartAggressiveSweepingAt");
-
-
   int min_number_of_compiler_threads = get_min_number_of_compiler_threads();
   // The default CICompilerCount's value is CI_COMPILER_COUNT.
   assert(min_number_of_compiler_threads <= CI_COMPILER_COUNT, "minimum should be less or equal default number");
-  // Check the minimum number of compiler threads
-  status &=verify_min_value(CICompilerCount, min_number_of_compiler_threads, "CICompilerCount");
 
   if (!FLAG_IS_DEFAULT(CICompilerCount) && !FLAG_IS_DEFAULT(CICompilerCountPerCPU) && CICompilerCountPerCPU) {
     warning("The VM option CICompilerCountPerCPU overrides CICompilerCount.");
@@ -2658,12 +2351,20 @@
     // -verbose:[class/gc/jni]
     if (match_option(option, "-verbose", &tail)) {
       if (!strcmp(tail, ":class") || !strcmp(tail, "")) {
-        FLAG_SET_CMDLINE(bool, TraceClassLoading, true);
-        FLAG_SET_CMDLINE(bool, TraceClassUnloading, true);
+        if (FLAG_SET_CMDLINE(bool, TraceClassLoading, true) != Flag::SUCCESS) {
+          return JNI_EINVAL;
+        }
+        if (FLAG_SET_CMDLINE(bool, TraceClassUnloading, true) != Flag::SUCCESS) {
+          return JNI_EINVAL;
+        }
       } else if (!strcmp(tail, ":gc")) {
-        FLAG_SET_CMDLINE(bool, PrintGC, true);
+        if (FLAG_SET_CMDLINE(bool, PrintGC, true) != Flag::SUCCESS) {
+          return JNI_EINVAL;
+        }
       } else if (!strcmp(tail, ":jni")) {
-        FLAG_SET_CMDLINE(bool, PrintJNIResolving, true);
+        if (FLAG_SET_CMDLINE(bool, PrintJNIResolving, true) != Flag::SUCCESS) {
+          return JNI_EINVAL;
+        }
       }
     // -da / -ea / -disableassertions / -enableassertions
     // These accept an optional class/package name separated by a colon, e.g.,
@@ -2750,16 +2451,24 @@
 #endif // !INCLUDE_JVMTI
     // -Xnoclassgc
     } else if (match_option(option, "-Xnoclassgc")) {
-      FLAG_SET_CMDLINE(bool, ClassUnloading, false);
+      if (FLAG_SET_CMDLINE(bool, ClassUnloading, false) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
     // -Xconcgc
     } else if (match_option(option, "-Xconcgc")) {
-      FLAG_SET_CMDLINE(bool, UseConcMarkSweepGC, true);
+      if (FLAG_SET_CMDLINE(bool, UseConcMarkSweepGC, true) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
     // -Xnoconcgc
     } else if (match_option(option, "-Xnoconcgc")) {
-      FLAG_SET_CMDLINE(bool, UseConcMarkSweepGC, false);
+      if (FLAG_SET_CMDLINE(bool, UseConcMarkSweepGC, false) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
     // -Xbatch
     } else if (match_option(option, "-Xbatch")) {
-      FLAG_SET_CMDLINE(bool, BackgroundCompilation, false);
+      if (FLAG_SET_CMDLINE(bool, BackgroundCompilation, false) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
     // -Xmn for compatibility with other JVM vendors
     } else if (match_option(option, "-Xmn", &tail)) {
       julong long_initial_young_size = 0;
@@ -2770,8 +2479,12 @@
         describe_range_error(errcode);
         return JNI_EINVAL;
       }
-      FLAG_SET_CMDLINE(size_t, MaxNewSize, (size_t)long_initial_young_size);
-      FLAG_SET_CMDLINE(size_t, NewSize, (size_t)long_initial_young_size);
+      if (FLAG_SET_CMDLINE(size_t, MaxNewSize, (size_t)long_initial_young_size) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
+      if (FLAG_SET_CMDLINE(size_t, NewSize, (size_t)long_initial_young_size) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
     // -Xms
     } else if (match_option(option, "-Xms", &tail)) {
       julong long_initial_heap_size = 0;
@@ -2786,7 +2499,9 @@
       set_min_heap_size((size_t)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(size_t, InitialHeapSize, (size_t)long_initial_heap_size);
+      if (FLAG_SET_CMDLINE(size_t, InitialHeapSize, (size_t)long_initial_heap_size) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
     // -Xmx
     } else if (match_option(option, "-Xmx", &tail) || match_option(option, "-XX:MaxHeapSize=", &tail)) {
       julong long_max_heap_size = 0;
@@ -2797,30 +2512,36 @@
         describe_range_error(errcode);
         return JNI_EINVAL;
       }
-      FLAG_SET_CMDLINE(size_t, MaxHeapSize, (size_t)long_max_heap_size);
+      if (FLAG_SET_CMDLINE(size_t, MaxHeapSize, (size_t)long_max_heap_size) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
     // Xmaxf
     } else if (match_option(option, "-Xmaxf", &tail)) {
       char* err;
       int maxf = (int)(strtod(tail, &err) * 100);
-      if (*err != '\0' || *tail == '\0' || maxf < 0 || maxf > 100) {
+      if (*err != '\0' || *tail == '\0') {
         jio_fprintf(defaultStream::error_stream(),
                     "Bad max heap free percentage size: %s\n",
                     option->optionString);
         return JNI_EINVAL;
       } else {
-        FLAG_SET_CMDLINE(uintx, MaxHeapFreeRatio, maxf);
+        if (FLAG_SET_CMDLINE(uintx, MaxHeapFreeRatio, maxf) != Flag::SUCCESS) {
+            return JNI_EINVAL;
+        }
       }
     // Xminf
     } else if (match_option(option, "-Xminf", &tail)) {
       char* err;
       int minf = (int)(strtod(tail, &err) * 100);
-      if (*err != '\0' || *tail == '\0' || minf < 0 || minf > 100) {
+      if (*err != '\0' || *tail == '\0') {
         jio_fprintf(defaultStream::error_stream(),
                     "Bad min heap free percentage size: %s\n",
                     option->optionString);
         return JNI_EINVAL;
       } else {
-        FLAG_SET_CMDLINE(uintx, MinHeapFreeRatio, minf);
+        if (FLAG_SET_CMDLINE(uintx, MinHeapFreeRatio, minf) != Flag::SUCCESS) {
+          return JNI_EINVAL;
+        }
       }
     // -Xss
     } else if (match_option(option, "-Xss", &tail)) {
@@ -2833,8 +2554,10 @@
         return JNI_EINVAL;
       }
       // Internally track ThreadStackSize in units of 1024 bytes.
-      FLAG_SET_CMDLINE(intx, ThreadStackSize,
-                              round_to((int)long_ThreadStackSize, K) / K);
+      if (FLAG_SET_CMDLINE(intx, ThreadStackSize,
+                       round_to((int)long_ThreadStackSize, K) / K) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
     // -Xoss
     } else if (match_option(option, "-Xoss", &tail)) {
           // HotSpot does not have separate native and Java stacks, ignore silently for compatibility
@@ -2847,7 +2570,9 @@
                    os::vm_page_size()/K);
         return JNI_EINVAL;
       }
-      FLAG_SET_CMDLINE(uintx, CodeCacheExpansionSize, (uintx)long_CodeCacheExpansionSize);
+      if (FLAG_SET_CMDLINE(uintx, CodeCacheExpansionSize, (uintx)long_CodeCacheExpansionSize) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
     } else if (match_option(option, "-Xmaxjitcodesize", &tail) ||
                match_option(option, "-XX:ReservedCodeCacheSize=", &tail)) {
       julong long_ReservedCodeCacheSize = 0;
@@ -2858,7 +2583,9 @@
                     "Invalid maximum code cache size: %s.\n", option->optionString);
         return JNI_EINVAL;
       }
-      FLAG_SET_CMDLINE(uintx, ReservedCodeCacheSize, (uintx)long_ReservedCodeCacheSize);
+      if (FLAG_SET_CMDLINE(uintx, ReservedCodeCacheSize, (uintx)long_ReservedCodeCacheSize) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
       // -XX:NonNMethodCodeHeapSize=
     } else if (match_option(option, "-XX:NonNMethodCodeHeapSize=", &tail)) {
       julong long_NonNMethodCodeHeapSize = 0;
@@ -2869,7 +2596,9 @@
                     "Invalid maximum non-nmethod code heap size: %s.\n", option->optionString);
         return JNI_EINVAL;
       }
-      FLAG_SET_CMDLINE(uintx, NonNMethodCodeHeapSize, (uintx)long_NonNMethodCodeHeapSize);
+      if (FLAG_SET_CMDLINE(uintx, NonNMethodCodeHeapSize, (uintx)long_NonNMethodCodeHeapSize) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
       // -XX:ProfiledCodeHeapSize=
     } else if (match_option(option, "-XX:ProfiledCodeHeapSize=", &tail)) {
       julong long_ProfiledCodeHeapSize = 0;
@@ -2880,7 +2609,9 @@
                     "Invalid maximum profiled code heap size: %s.\n", option->optionString);
         return JNI_EINVAL;
       }
-      FLAG_SET_CMDLINE(uintx, ProfiledCodeHeapSize, (uintx)long_ProfiledCodeHeapSize);
+      if (FLAG_SET_CMDLINE(uintx, ProfiledCodeHeapSize, (uintx)long_ProfiledCodeHeapSize) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
       // -XX:NonProfiledCodeHeapSizee=
     } else if (match_option(option, "-XX:NonProfiledCodeHeapSize=", &tail)) {
       julong long_NonProfiledCodeHeapSize = 0;
@@ -2891,17 +2622,9 @@
                     "Invalid maximum non-profiled code heap size: %s.\n", option->optionString);
         return JNI_EINVAL;
       }
-      FLAG_SET_CMDLINE(uintx, NonProfiledCodeHeapSize, (uintx)long_NonProfiledCodeHeapSize);
-      //-XX:IncreaseFirstTierCompileThresholdAt=
-    } else if (match_option(option, "-XX:IncreaseFirstTierCompileThresholdAt=", &tail)) {
-        uintx uint_IncreaseFirstTierCompileThresholdAt = 0;
-        if (!parse_uintx(tail, &uint_IncreaseFirstTierCompileThresholdAt, 0) || uint_IncreaseFirstTierCompileThresholdAt > 99) {
-          jio_fprintf(defaultStream::error_stream(),
-                      "Invalid value for IncreaseFirstTierCompileThresholdAt: %s. Should be between 0 and 99.\n",
-                      option->optionString);
-          return JNI_EINVAL;
-        }
-        FLAG_SET_CMDLINE(uintx, IncreaseFirstTierCompileThresholdAt, (uintx)uint_IncreaseFirstTierCompileThresholdAt);
+      if (FLAG_SET_CMDLINE(uintx, NonProfiledCodeHeapSize, (uintx)long_NonProfiledCodeHeapSize) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
     // -green
     } else if (match_option(option, "-green")) {
       jio_fprintf(defaultStream::error_stream(),
@@ -2916,10 +2639,14 @@
     // -Xrs
     } else if (match_option(option, "-Xrs")) {
           // Classic/EVM option, new functionality
-      FLAG_SET_CMDLINE(bool, ReduceSignalUsage, true);
+      if (FLAG_SET_CMDLINE(bool, ReduceSignalUsage, true) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
     } else if (match_option(option, "-Xusealtsigs")) {
           // change default internal VM signals used - lower case for back compat
-      FLAG_SET_CMDLINE(bool, UseAltSigs, true);
+      if (FLAG_SET_CMDLINE(bool, UseAltSigs, true) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
     // -Xoptimize
     } else if (match_option(option, "-Xoptimize")) {
           // EVM option, ignore silently for compatibility
@@ -2934,11 +2661,21 @@
 #endif // INCLUDE_FPROF
     // -Xconcurrentio
     } else if (match_option(option, "-Xconcurrentio")) {
-      FLAG_SET_CMDLINE(bool, UseLWPSynchronization, true);
-      FLAG_SET_CMDLINE(bool, BackgroundCompilation, false);
-      FLAG_SET_CMDLINE(intx, DeferThrSuspendLoopCount, 1);
-      FLAG_SET_CMDLINE(bool, UseTLAB, false);
-      FLAG_SET_CMDLINE(size_t, NewSizeThreadIncrease, 16 * K);  // 20Kb per thread added to new generation
+      if (FLAG_SET_CMDLINE(bool, UseLWPSynchronization, true) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
+      if (FLAG_SET_CMDLINE(bool, BackgroundCompilation, false) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
+      if (FLAG_SET_CMDLINE(intx, DeferThrSuspendLoopCount, 1) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
+      if (FLAG_SET_CMDLINE(bool, UseTLAB, false) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
+      if (FLAG_SET_CMDLINE(size_t, NewSizeThreadIncrease, 16 * K) != Flag::SUCCESS) {  // 20Kb per thread added to new generation
+        return JNI_EINVAL;
+      }
 
       // -Xinternalversion
     } else if (match_option(option, "-Xinternalversion")) {
@@ -2976,7 +2713,9 @@
       // Out of the box management support
       if (match_option(option, "-Dcom.sun.management", &tail)) {
 #if INCLUDE_MANAGEMENT
-        FLAG_SET_CMDLINE(bool, ManagementServer, true);
+        if (FLAG_SET_CMDLINE(bool, ManagementServer, true) != Flag::SUCCESS) {
+          return JNI_EINVAL;
+        }
 #else
         jio_fprintf(defaultStream::output_stream(),
           "-Dcom.sun.management is not supported in this VM.\n");
@@ -2995,31 +2734,57 @@
           set_mode_flags(_comp);
     // -Xshare:dump
     } else if (match_option(option, "-Xshare:dump")) {
-      FLAG_SET_CMDLINE(bool, DumpSharedSpaces, true);
+      if (FLAG_SET_CMDLINE(bool, DumpSharedSpaces, true) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
       set_mode_flags(_int);     // Prevent compilation, which creates objects
     // -Xshare:on
     } else if (match_option(option, "-Xshare:on")) {
-      FLAG_SET_CMDLINE(bool, UseSharedSpaces, true);
-      FLAG_SET_CMDLINE(bool, RequireSharedSpaces, true);
+      if (FLAG_SET_CMDLINE(bool, UseSharedSpaces, true) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
+      if (FLAG_SET_CMDLINE(bool, RequireSharedSpaces, true) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
     // -Xshare:auto
     } else if (match_option(option, "-Xshare:auto")) {
-      FLAG_SET_CMDLINE(bool, UseSharedSpaces, true);
-      FLAG_SET_CMDLINE(bool, RequireSharedSpaces, false);
+      if (FLAG_SET_CMDLINE(bool, UseSharedSpaces, true) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
+      if (FLAG_SET_CMDLINE(bool, RequireSharedSpaces, false) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
     // -Xshare:off
     } else if (match_option(option, "-Xshare:off")) {
-      FLAG_SET_CMDLINE(bool, UseSharedSpaces, false);
-      FLAG_SET_CMDLINE(bool, RequireSharedSpaces, false);
+      if (FLAG_SET_CMDLINE(bool, UseSharedSpaces, false) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
+      if (FLAG_SET_CMDLINE(bool, RequireSharedSpaces, false) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
     // -Xverify
     } else if (match_option(option, "-Xverify", &tail)) {
       if (strcmp(tail, ":all") == 0 || strcmp(tail, "") == 0) {
-        FLAG_SET_CMDLINE(bool, BytecodeVerificationLocal, true);
-        FLAG_SET_CMDLINE(bool, BytecodeVerificationRemote, true);
+        if (FLAG_SET_CMDLINE(bool, BytecodeVerificationLocal, true) != Flag::SUCCESS) {
+          return JNI_EINVAL;
+        }
+        if (FLAG_SET_CMDLINE(bool, BytecodeVerificationRemote, true) != Flag::SUCCESS) {
+          return JNI_EINVAL;
+        }
       } else if (strcmp(tail, ":remote") == 0) {
-        FLAG_SET_CMDLINE(bool, BytecodeVerificationLocal, false);
-        FLAG_SET_CMDLINE(bool, BytecodeVerificationRemote, true);
+        if (FLAG_SET_CMDLINE(bool, BytecodeVerificationLocal, false) != Flag::SUCCESS) {
+          return JNI_EINVAL;
+        }
+        if (FLAG_SET_CMDLINE(bool, BytecodeVerificationRemote, true) != Flag::SUCCESS) {
+          return JNI_EINVAL;
+        }
       } else if (strcmp(tail, ":none") == 0) {
-        FLAG_SET_CMDLINE(bool, BytecodeVerificationLocal, false);
-        FLAG_SET_CMDLINE(bool, BytecodeVerificationRemote, false);
+        if (FLAG_SET_CMDLINE(bool, BytecodeVerificationLocal, false) != Flag::SUCCESS) {
+          return JNI_EINVAL;
+        }
+        if (FLAG_SET_CMDLINE(bool, BytecodeVerificationRemote, false) != Flag::SUCCESS) {
+          return JNI_EINVAL;
+        }
       } else if (is_bad_option(option, args->ignoreUnrecognized, "verification")) {
         return JNI_EINVAL;
       }
@@ -3044,9 +2809,12 @@
                   "Note %%p or %%t can only be used once\n", _gc_log_filename);
         return JNI_EINVAL;
       }
-      FLAG_SET_CMDLINE(bool, PrintGC, true);
-      FLAG_SET_CMDLINE(bool, PrintGCTimeStamps, true);
-
+      if (FLAG_SET_CMDLINE(bool, PrintGC, true) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
+      if (FLAG_SET_CMDLINE(bool, PrintGCTimeStamps, true) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
     // JNI hooks
     } else if (match_option(option, "-Xcheck", &tail)) {
       if (!strcmp(tail, ":jni")) {
@@ -3098,16 +2866,24 @@
       initHeapSize = limit_by_allocatable_memory(initHeapSize);
 
       if (FLAG_IS_DEFAULT(MaxHeapSize)) {
-         FLAG_SET_CMDLINE(size_t, MaxHeapSize, initHeapSize);
-         FLAG_SET_CMDLINE(size_t, InitialHeapSize, initHeapSize);
+         if (FLAG_SET_CMDLINE(size_t, MaxHeapSize, initHeapSize) != Flag::SUCCESS) {
+           return JNI_EINVAL;
+         }
+         if (FLAG_SET_CMDLINE(size_t, InitialHeapSize, initHeapSize) != Flag::SUCCESS) {
+           return JNI_EINVAL;
+         }
          // Currently the minimum size and the initial heap sizes are the same.
          set_min_heap_size(initHeapSize);
       }
       if (FLAG_IS_DEFAULT(NewSize)) {
          // Make the young generation 3/8ths of the total heap.
-         FLAG_SET_CMDLINE(size_t, NewSize,
-                                ((julong)MaxHeapSize / (julong)8) * (julong)3);
-         FLAG_SET_CMDLINE(size_t, MaxNewSize, NewSize);
+         if (FLAG_SET_CMDLINE(size_t, NewSize,
+                                ((julong)MaxHeapSize / (julong)8) * (julong)3) != Flag::SUCCESS) {
+           return JNI_EINVAL;
+         }
+         if (FLAG_SET_CMDLINE(size_t, MaxNewSize, NewSize) != Flag::SUCCESS) {
+           return JNI_EINVAL;
+         }
       }
 
 #if !defined(_ALLBSD_SOURCE) && !defined(AIX)  // UseLargePages is not yet supported on BSD and AIX.
@@ -3115,14 +2891,22 @@
 #endif
 
       // Increase some data structure sizes for efficiency
-      FLAG_SET_CMDLINE(size_t, BaseFootPrintEstimate, MaxHeapSize);
-      FLAG_SET_CMDLINE(bool, ResizeTLAB, false);
-      FLAG_SET_CMDLINE(size_t, TLABSize, 256*K);
+      if (FLAG_SET_CMDLINE(size_t, BaseFootPrintEstimate, MaxHeapSize) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
+      if (FLAG_SET_CMDLINE(bool, ResizeTLAB, false) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
+      if (FLAG_SET_CMDLINE(size_t, TLABSize, 256*K) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
 
       // See the OldPLABSize comment below, but replace 'after promotion'
       // with 'after copying'.  YoungPLABSize is the size of the survivor
       // space per-gc-thread buffers.  The default is 4kw.
-      FLAG_SET_CMDLINE(size_t, YoungPLABSize, 256*K);      // Note: this is in words
+      if (FLAG_SET_CMDLINE(size_t, YoungPLABSize, 256*K) != Flag::SUCCESS) {      // Note: this is in words
+        return JNI_EINVAL;
+      }
 
       // OldPLABSize is the size of the buffers in the old gen that
       // UseParallelGC uses to promote live data that doesn't fit in the
@@ -3137,62 +2921,111 @@
       // locality.  A minor effect may be that larger PLABs reduce the
       // number of PLAB allocation events during gc.  The value of 8kw
       // was arrived at by experimenting with specjbb.
-      FLAG_SET_CMDLINE(size_t, OldPLABSize, 8*K);  // Note: this is in words
+      if (FLAG_SET_CMDLINE(size_t, OldPLABSize, 8*K) != Flag::SUCCESS) {  // Note: this is in words
+        return JNI_EINVAL;
+      }
 
       // Enable parallel GC and adaptive generation sizing
-      FLAG_SET_CMDLINE(bool, UseParallelGC, true);
+      if (FLAG_SET_CMDLINE(bool, UseParallelGC, true) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
       FLAG_SET_DEFAULT(ParallelGCThreads,
                        Abstract_VM_Version::parallel_worker_threads());
 
       // Encourage steady state memory management
-      FLAG_SET_CMDLINE(uintx, ThresholdTolerance, 100);
+      if (FLAG_SET_CMDLINE(uintx, ThresholdTolerance, 100) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
 
       // This appears to improve mutator locality
-      FLAG_SET_CMDLINE(bool, ScavengeBeforeFullGC, false);
+      if (FLAG_SET_CMDLINE(bool, ScavengeBeforeFullGC, false) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
 
       // Get around early Solaris scheduling bug
       // (affinity vs other jobs on system)
       // but disallow DR and offlining (5008695).
-      FLAG_SET_CMDLINE(bool, BindGCTaskThreadsToCPUs, true);
+      if (FLAG_SET_CMDLINE(bool, BindGCTaskThreadsToCPUs, true) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
 
     // Need to keep consistency of MaxTenuringThreshold and AlwaysTenure/NeverTenure;
     // and the last option wins.
     } else if (match_option(option, "-XX:+NeverTenure")) {
-      FLAG_SET_CMDLINE(bool, NeverTenure, true);
-      FLAG_SET_CMDLINE(bool, AlwaysTenure, false);
-      FLAG_SET_CMDLINE(uintx, MaxTenuringThreshold, markOopDesc::max_age + 1);
+      if (FLAG_SET_CMDLINE(bool, NeverTenure, true) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
+      if (FLAG_SET_CMDLINE(bool, AlwaysTenure, false) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
+      if (FLAG_SET_CMDLINE(uintx, MaxTenuringThreshold, markOopDesc::max_age + 1) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
     } else if (match_option(option, "-XX:+AlwaysTenure")) {
-      FLAG_SET_CMDLINE(bool, NeverTenure, false);
-      FLAG_SET_CMDLINE(bool, AlwaysTenure, true);
-      FLAG_SET_CMDLINE(uintx, MaxTenuringThreshold, 0);
+      if (FLAG_SET_CMDLINE(bool, NeverTenure, false) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
+      if (FLAG_SET_CMDLINE(bool, AlwaysTenure, true) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
+      if (FLAG_SET_CMDLINE(uintx, MaxTenuringThreshold, 0) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
     } else if (match_option(option, "-XX:MaxTenuringThreshold=", &tail)) {
       uintx max_tenuring_thresh = 0;
-      if(!parse_uintx(tail, &max_tenuring_thresh, 0)) {
+      if (!parse_uintx(tail, &max_tenuring_thresh, 0)) {
         jio_fprintf(defaultStream::error_stream(),
-          "Improperly specified VM option 'MaxTenuringThreshold=%s'\n", tail);
+                    "Improperly specified VM option \'MaxTenuringThreshold=%s\'\n", tail);
         return JNI_EINVAL;
       }
-      FLAG_SET_CMDLINE(uintx, MaxTenuringThreshold, max_tenuring_thresh);
+
+      if (FLAG_SET_CMDLINE(uintx, MaxTenuringThreshold, max_tenuring_thresh) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
 
       if (MaxTenuringThreshold == 0) {
-        FLAG_SET_CMDLINE(bool, NeverTenure, false);
-        FLAG_SET_CMDLINE(bool, AlwaysTenure, true);
+        if (FLAG_SET_CMDLINE(bool, NeverTenure, false) != Flag::SUCCESS) {
+          return JNI_EINVAL;
+        }
+        if (FLAG_SET_CMDLINE(bool, AlwaysTenure, true) != Flag::SUCCESS) {
+          return JNI_EINVAL;
+        }
       } else {
-        FLAG_SET_CMDLINE(bool, NeverTenure, false);
-        FLAG_SET_CMDLINE(bool, AlwaysTenure, false);
+        if (FLAG_SET_CMDLINE(bool, NeverTenure, false) != Flag::SUCCESS) {
+          return JNI_EINVAL;
+        }
+        if (FLAG_SET_CMDLINE(bool, AlwaysTenure, false) != Flag::SUCCESS) {
+          return JNI_EINVAL;
+        }
       }
     } else if (match_option(option, "-XX:+DisplayVMOutputToStderr")) {
-      FLAG_SET_CMDLINE(bool, DisplayVMOutputToStdout, false);
-      FLAG_SET_CMDLINE(bool, DisplayVMOutputToStderr, true);
+      if (FLAG_SET_CMDLINE(bool, DisplayVMOutputToStdout, false) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
+      if (FLAG_SET_CMDLINE(bool, DisplayVMOutputToStderr, true) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
     } else if (match_option(option, "-XX:+DisplayVMOutputToStdout")) {
-      FLAG_SET_CMDLINE(bool, DisplayVMOutputToStderr, false);
-      FLAG_SET_CMDLINE(bool, DisplayVMOutputToStdout, true);
+      if (FLAG_SET_CMDLINE(bool, DisplayVMOutputToStderr, false) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
+      if (FLAG_SET_CMDLINE(bool, DisplayVMOutputToStdout, true) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
     } else if (match_option(option, "-XX:+ExtendedDTraceProbes")) {
 #if defined(DTRACE_ENABLED)
-      FLAG_SET_CMDLINE(bool, ExtendedDTraceProbes, true);
-      FLAG_SET_CMDLINE(bool, DTraceMethodProbes, true);
-      FLAG_SET_CMDLINE(bool, DTraceAllocProbes, true);
-      FLAG_SET_CMDLINE(bool, DTraceMonitorProbes, true);
+      if (FLAG_SET_CMDLINE(bool, ExtendedDTraceProbes, true) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
+      if (FLAG_SET_CMDLINE(bool, DTraceMethodProbes, true) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
+      if (FLAG_SET_CMDLINE(bool, DTraceAllocProbes, true) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
+      if (FLAG_SET_CMDLINE(bool, DTraceMonitorProbes, true) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
 #else // defined(DTRACE_ENABLED)
       jio_fprintf(defaultStream::error_stream(),
                   "ExtendedDTraceProbes flag is not applicable for this configuration\n");
@@ -3200,9 +3033,13 @@
 #endif // defined(DTRACE_ENABLED)
 #ifdef ASSERT
     } else if (match_option(option, "-XX:+FullGCALot")) {
-      FLAG_SET_CMDLINE(bool, FullGCALot, true);
+      if (FLAG_SET_CMDLINE(bool, FullGCALot, true) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
       // disable scavenge before parallel mark-compact
-      FLAG_SET_CMDLINE(bool, ScavengeBeforeFullGC, false);
+      if (FLAG_SET_CMDLINE(bool, ScavengeBeforeFullGC, false) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
 #endif
     } else if (match_option(option, "-XX:CMSMarkStackSize=", &tail) ||
                match_option(option, "-XX:G1MarkStackSize=", &tail)) {
@@ -3217,7 +3054,9 @@
       jio_fprintf(defaultStream::error_stream(),
         "Please use -XX:MarkStackSize in place of "
         "-XX:CMSMarkStackSize or -XX:G1MarkStackSize in the future\n");
-      FLAG_SET_CMDLINE(size_t, MarkStackSize, stack_size);
+      if (FLAG_SET_CMDLINE(size_t, MarkStackSize, stack_size) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
     } else if (match_option(option, "-XX:CMSMarkStackSizeMax=", &tail)) {
       julong max_stack_size = 0;
       ArgsRange errcode = parse_memory_size(tail, &max_stack_size, 1);
@@ -3231,7 +3070,9 @@
       jio_fprintf(defaultStream::error_stream(),
          "Please use -XX:MarkStackSizeMax in place of "
          "-XX:CMSMarkStackSizeMax in the future\n");
-      FLAG_SET_CMDLINE(size_t, MarkStackSizeMax, max_stack_size);
+      if (FLAG_SET_CMDLINE(size_t, MarkStackSizeMax, max_stack_size) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
     } else if (match_option(option, "-XX:ParallelMarkingThreads=", &tail) ||
                match_option(option, "-XX:ParallelCMSThreads=", &tail)) {
       uintx conc_threads = 0;
@@ -3243,7 +3084,9 @@
       jio_fprintf(defaultStream::error_stream(),
         "Please use -XX:ConcGCThreads in place of "
         "-XX:ParallelMarkingThreads or -XX:ParallelCMSThreads in the future\n");
-      FLAG_SET_CMDLINE(uintx, ConcGCThreads, conc_threads);
+      if (FLAG_SET_CMDLINE(uint, ConcGCThreads, conc_threads) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
     } else if (match_option(option, "-XX:MaxDirectMemorySize=", &tail)) {
       julong max_direct_memory_size = 0;
       ArgsRange errcode = parse_memory_size(tail, &max_direct_memory_size, 0);
@@ -3254,7 +3097,9 @@
         describe_range_error(errcode);
         return JNI_EINVAL;
       }
-      FLAG_SET_CMDLINE(size_t, MaxDirectMemorySize, max_direct_memory_size);
+      if (FLAG_SET_CMDLINE(size_t, MaxDirectMemorySize, max_direct_memory_size) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
 #if !INCLUDE_MANAGEMENT
     } else if (match_option(option, "-XX:+ManagementServer")) {
         jio_fprintf(defaultStream::error_stream(),
@@ -3263,11 +3108,15 @@
 #endif // INCLUDE_MANAGEMENT
     // CreateMinidumpOnCrash is removed, and replaced by CreateCoredumpOnCrash
     } else if (match_option(option, "-XX:+CreateMinidumpOnCrash")) {
-      FLAG_SET_CMDLINE(bool, CreateCoredumpOnCrash, true);
+      if (FLAG_SET_CMDLINE(bool, CreateCoredumpOnCrash, true) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
       jio_fprintf(defaultStream::output_stream(),
           "CreateMinidumpOnCrash is replaced by CreateCoredumpOnCrash: CreateCoredumpOnCrash is on\n");
     } else if (match_option(option, "-XX:-CreateMinidumpOnCrash")) {
-      FLAG_SET_CMDLINE(bool, CreateCoredumpOnCrash, false);
+      if (FLAG_SET_CMDLINE(bool, CreateCoredumpOnCrash, false) != Flag::SUCCESS) {
+        return JNI_EINVAL;
+      }
       jio_fprintf(defaultStream::output_stream(),
           "CreateMinidumpOnCrash is replaced by CreateCoredumpOnCrash: CreateCoredumpOnCrash is off\n");
     } else if (match_option(option, "-XX:", &tail)) { // -XX:xxxx
@@ -3287,9 +3136,15 @@
   //   -Xshare:on
   //   -XX:+TraceClassPaths
   if (PrintSharedArchiveAndExit) {
-    FLAG_SET_CMDLINE(bool, UseSharedSpaces, true);
-    FLAG_SET_CMDLINE(bool, RequireSharedSpaces, true);
-    FLAG_SET_CMDLINE(bool, TraceClassPaths, true);
+    if (FLAG_SET_CMDLINE(bool, UseSharedSpaces, true) != Flag::SUCCESS) {
+      return JNI_EINVAL;
+    }
+    if (FLAG_SET_CMDLINE(bool, RequireSharedSpaces, true) != Flag::SUCCESS) {
+      return JNI_EINVAL;
+    }
+    if (FLAG_SET_CMDLINE(bool, TraceClassPaths, true) != Flag::SUCCESS) {
+      return JNI_EINVAL;
+    }
   }
 
   // Change the default value for flags  which have different default values
@@ -3696,6 +3551,10 @@
 
 jint Arguments::parse(const JavaVMInitArgs* args) {
 
+  // Initialize ranges and constraints
+  CommandLineFlagRangeList::init();
+  CommandLineFlagConstraintList::init();
+
   // Remaining part of option string
   const char* tail;
 
@@ -4030,6 +3889,15 @@
   return JNI_OK;
 }
 
+// Any custom code post the final range and constraint check
+// can be done here. We pass a flag that specifies whether
+// the check passed successfully
+void Arguments::post_final_range_and_constraint_check(bool check_passed) {
+  // This does not set the flag itself, but stores the value in a safe place for later usage.
+  _min_heap_free_ratio = MinHeapFreeRatio;
+  _max_heap_free_ratio = MaxHeapFreeRatio;
+}
+
 int Arguments::PropertyList_count(SystemProperty* pl) {
   int count = 0;
   while(pl != NULL) {
--- a/hotspot/src/share/vm/runtime/arguments.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/runtime/arguments.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -328,7 +328,6 @@
 
   // Tiered
   static void set_tiered_flags();
-  static int  get_min_number_of_compiler_threads();
   // CMS/ParNew garbage collectors
   static void set_parnew_gc_flags();
   static void set_cms_and_parnew_gc_flags();
@@ -384,14 +383,6 @@
     return is_bad_option(option, ignore, NULL);
   }
 
-  static bool is_percentage(uintx val) {
-    return val <= 100;
-  }
-
-  static bool verify_interval(uintx val, uintx min,
-                              uintx max, const char* name);
-  static bool verify_min_value(intx val, intx min, const char* name);
-  static bool verify_percentage(uintx value, const char* name);
   static void describe_range_error(ArgsRange errcode);
   static ArgsRange check_memory_size(julong size, julong min_size);
   static ArgsRange parse_memory_size(const char* s, julong* long_arg,
@@ -447,6 +438,9 @@
   static char*  SharedArchivePath;
 
  public:
+  // Tiered
+  static int  get_min_number_of_compiler_threads();
+
   // Scale compile thresholds
   // Returns threshold scaled with CompileThresholdScaling
   static intx scaled_compile_threshold(intx threshold, double scale);
@@ -465,26 +459,18 @@
   static jint apply_ergo();
   // Adjusts the arguments after the OS have adjusted the arguments
   static jint adjust_after_os();
+  // Set any arguments that need to be set after the final range and constraint check
+  static void post_final_range_and_constraint_check(bool check_passed);
 
   static void set_gc_specific_flags();
   static inline bool gc_selected(); // whether a gc has been selected
   static void select_gc_ergonomically();
 
-  // Verifies that the given value will fit as a MinHeapFreeRatio. If not, an error
-  // message is returned in the provided buffer.
-  static bool verify_MinHeapFreeRatio(FormatBuffer<80>& err_msg, uintx min_heap_free_ratio);
-
-  // Verifies that the given value will fit as a MaxHeapFreeRatio. If not, an error
-  // message is returned in the provided buffer.
-  static bool verify_MaxHeapFreeRatio(FormatBuffer<80>& err_msg, uintx max_heap_free_ratio);
-
   // Check for consistency in the selection of the garbage collector.
   static bool check_gc_consistency();        // Check user-selected gc
   static void check_deprecated_gc_flags();
   // Check consistency or otherwise of VM argument settings
   static bool check_vm_args_consistency();
-  // Check stack pages settings
-  static bool check_stack_pages();
   // Used by os_solaris
   static bool process_settings_file(const char* file_name, bool should_exist, jboolean ignore_unrecognized);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 2015, 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 "classfile/stringTable.hpp"
+#include "classfile/symbolTable.hpp"
+#include "gc/shared/referenceProcessor.hpp"
+#include "runtime/arguments.hpp"
+#include "runtime/commandLineFlagConstraintList.hpp"
+#include "runtime/commandLineFlagConstraintsCompiler.hpp"
+#include "runtime/commandLineFlagConstraintsGC.hpp"
+#include "runtime/commandLineFlagConstraintsRuntime.hpp"
+#include "runtime/os.hpp"
+#include "utilities/macros.hpp"
+
+class CommandLineFlagConstraint_bool : public CommandLineFlagConstraint {
+  CommandLineFlagConstraintFunc_bool _constraint;
+
+public:
+  // the "name" argument must be a string literal
+  CommandLineFlagConstraint_bool(const char* name, CommandLineFlagConstraintFunc_bool func) : CommandLineFlagConstraint(name) {
+    _constraint=func;
+  }
+
+  Flag::Error apply_bool(bool* value, bool verbose) {
+    return _constraint(verbose, value);
+  }
+};
+
+class CommandLineFlagConstraint_int : public CommandLineFlagConstraint {
+  CommandLineFlagConstraintFunc_int _constraint;
+
+public:
+  // the "name" argument must be a string literal
+  CommandLineFlagConstraint_int(const char* name, CommandLineFlagConstraintFunc_int func) : CommandLineFlagConstraint(name) {
+    _constraint=func;
+  }
+
+  Flag::Error apply_int(int* value, bool verbose) {
+    return _constraint(verbose, value);
+  }
+};
+
+class CommandLineFlagConstraint_intx : public CommandLineFlagConstraint {
+  CommandLineFlagConstraintFunc_intx _constraint;
+
+public:
+  // the "name" argument must be a string literal
+  CommandLineFlagConstraint_intx(const char* name, CommandLineFlagConstraintFunc_intx func) : CommandLineFlagConstraint(name) {
+    _constraint=func;
+  }
+
+  Flag::Error apply_intx(intx* value, bool verbose) {
+    return _constraint(verbose, value);
+  }
+};
+
+class CommandLineFlagConstraint_uint : public CommandLineFlagConstraint {
+  CommandLineFlagConstraintFunc_uint _constraint;
+
+public:
+  // the "name" argument must be a string literal
+  CommandLineFlagConstraint_uint(const char* name, CommandLineFlagConstraintFunc_uint func) : CommandLineFlagConstraint(name) {
+    _constraint=func;
+  }
+
+  Flag::Error apply_uint(uint* value, bool verbose) {
+    return _constraint(verbose, value);
+  }
+};
+
+class CommandLineFlagConstraint_uintx : public CommandLineFlagConstraint {
+  CommandLineFlagConstraintFunc_uintx _constraint;
+
+public:
+  // the "name" argument must be a string literal
+  CommandLineFlagConstraint_uintx(const char* name, CommandLineFlagConstraintFunc_uintx func) : CommandLineFlagConstraint(name) {
+    _constraint=func;
+  }
+
+  Flag::Error apply_uintx(uintx* value, bool verbose) {
+    return _constraint(verbose, value);
+  }
+};
+
+class CommandLineFlagConstraint_uint64_t : public CommandLineFlagConstraint {
+  CommandLineFlagConstraintFunc_uint64_t _constraint;
+
+public:
+  // the "name" argument must be a string literal
+  CommandLineFlagConstraint_uint64_t(const char* name, CommandLineFlagConstraintFunc_uint64_t func) : CommandLineFlagConstraint(name) {
+    _constraint=func;
+  }
+
+  Flag::Error apply_uint64_t(uint64_t* value, bool verbose) {
+    return _constraint(verbose, value);
+  }
+};
+
+class CommandLineFlagConstraint_size_t : public CommandLineFlagConstraint {
+  CommandLineFlagConstraintFunc_size_t _constraint;
+
+public:
+  // the "name" argument must be a string literal
+  CommandLineFlagConstraint_size_t(const char* name, CommandLineFlagConstraintFunc_size_t func) : CommandLineFlagConstraint(name) {
+    _constraint=func;
+  }
+
+  Flag::Error apply_size_t(size_t* value, bool verbose) {
+    return _constraint(verbose, value);
+  }
+};
+
+class CommandLineFlagConstraint_double : public CommandLineFlagConstraint {
+  CommandLineFlagConstraintFunc_double _constraint;
+
+public:
+  // the "name" argument must be a string literal
+  CommandLineFlagConstraint_double(const char* name, CommandLineFlagConstraintFunc_double func) : CommandLineFlagConstraint(name) {
+    _constraint=func;
+  }
+
+  Flag::Error apply_double(double* value, bool verbose) {
+    return _constraint(verbose, value);
+  }
+};
+
+// No constraint emitting
+void emit_constraint_no(...)                          { /* NOP */ }
+
+// No constraint emitting if function argument is NOT provided
+void emit_constraint_bool(const char* /*name*/)       { /* NOP */ }
+void emit_constraint_ccstr(const char* /*name*/)      { /* NOP */ }
+void emit_constraint_ccstrlist(const char* /*name*/)  { /* NOP */ }
+void emit_constraint_int(const char* /*name*/)        { /* NOP */ }
+void emit_constraint_intx(const char* /*name*/)       { /* NOP */ }
+void emit_constraint_uint(const char* /*name*/)       { /* NOP */ }
+void emit_constraint_uintx(const char* /*name*/)      { /* NOP */ }
+void emit_constraint_uint64_t(const char* /*name*/)   { /* NOP */ }
+void emit_constraint_size_t(const char* /*name*/)     { /* NOP */ }
+void emit_constraint_double(const char* /*name*/)     { /* NOP */ }
+
+// CommandLineFlagConstraint emitting code functions if function argument is provided
+void emit_constraint_bool(const char* name, CommandLineFlagConstraintFunc_bool func) {
+  CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_bool(name, func));
+}
+void emit_constraint_int(const char* name, CommandLineFlagConstraintFunc_int func) {
+  CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_int(name, func));
+}
+void emit_constraint_intx(const char* name, CommandLineFlagConstraintFunc_intx func) {
+  CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_intx(name, func));
+}
+void emit_constraint_uint(const char* name, CommandLineFlagConstraintFunc_uint func) {
+  CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_uint(name, func));
+}
+void emit_constraint_uintx(const char* name, CommandLineFlagConstraintFunc_uintx func) {
+  CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_uintx(name, func));
+}
+void emit_constraint_uint64_t(const char* name, CommandLineFlagConstraintFunc_uint64_t func) {
+  CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_uint64_t(name, func));
+}
+void emit_constraint_size_t(const char* name, CommandLineFlagConstraintFunc_size_t func) {
+  CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_size_t(name, func));
+}
+void emit_constraint_double(const char* name, CommandLineFlagConstraintFunc_double func) {
+  CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_double(name, func));
+}
+
+// Generate code to call emit_constraint_xxx function
+#define EMIT_CONSTRAINT_PRODUCT_FLAG(type, name, value, doc)      ); emit_constraint_##type(#name
+#define EMIT_CONSTRAINT_COMMERCIAL_FLAG(type, name, value, doc)   ); emit_constraint_##type(#name
+#define EMIT_CONSTRAINT_DIAGNOSTIC_FLAG(type, name, value, doc)   ); emit_constraint_##type(#name
+#define EMIT_CONSTRAINT_EXPERIMENTAL_FLAG(type, name, value, doc) ); emit_constraint_##type(#name
+#define EMIT_CONSTRAINT_MANAGEABLE_FLAG(type, name, value, doc)   ); emit_constraint_##type(#name
+#define EMIT_CONSTRAINT_PRODUCT_RW_FLAG(type, name, value, doc)   ); emit_constraint_##type(#name
+#define EMIT_CONSTRAINT_PD_PRODUCT_FLAG(type, name, doc)          ); emit_constraint_##type(#name
+#define EMIT_CONSTRAINT_DEVELOPER_FLAG(type, name, value, doc)    ); emit_constraint_##type(#name
+#define EMIT_CONSTRAINT_PD_DEVELOPER_FLAG(type, name, doc)        ); emit_constraint_##type(#name
+#define EMIT_CONSTRAINT_NOTPRODUCT_FLAG(type, name, value, doc)   ); emit_constraint_##type(#name
+#define EMIT_CONSTRAINT_LP64_PRODUCT_FLAG(type, name, value, doc) ); emit_constraint_##type(#name
+
+// Generate func argument to pass into emit_constraint_xxx functions
+#define EMIT_CONSTRAINT_CHECK(func)                               , func
+
+// the "name" argument must be a string literal
+#define INITIAL_CONTRAINTS_SIZE 16
+GrowableArray<CommandLineFlagConstraint*>* CommandLineFlagConstraintList::_constraints = NULL;
+
+// Check the ranges of all flags that have them or print them out and exit if requested
+void CommandLineFlagConstraintList::init(void) {
+
+  _constraints = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<CommandLineFlagConstraint*>(INITIAL_CONTRAINTS_SIZE, true);
+
+  emit_constraint_no(NULL RUNTIME_FLAGS(EMIT_CONSTRAINT_DEVELOPER_FLAG,
+                                        EMIT_CONSTRAINT_PD_DEVELOPER_FLAG,
+                                        EMIT_CONSTRAINT_PRODUCT_FLAG,
+                                        EMIT_CONSTRAINT_PD_PRODUCT_FLAG,
+                                        EMIT_CONSTRAINT_DIAGNOSTIC_FLAG,
+                                        EMIT_CONSTRAINT_EXPERIMENTAL_FLAG,
+                                        EMIT_CONSTRAINT_NOTPRODUCT_FLAG,
+                                        EMIT_CONSTRAINT_MANAGEABLE_FLAG,
+                                        EMIT_CONSTRAINT_PRODUCT_RW_FLAG,
+                                        EMIT_CONSTRAINT_LP64_PRODUCT_FLAG,
+                                        IGNORE_RANGE,
+                                        EMIT_CONSTRAINT_CHECK));
+
+  EMIT_CONSTRAINTS_FOR_GLOBALS_EXT
+
+  emit_constraint_no(NULL ARCH_FLAGS(EMIT_CONSTRAINT_DEVELOPER_FLAG,
+                                     EMIT_CONSTRAINT_PRODUCT_FLAG,
+                                     EMIT_CONSTRAINT_DIAGNOSTIC_FLAG,
+                                     EMIT_CONSTRAINT_EXPERIMENTAL_FLAG,
+                                     EMIT_CONSTRAINT_NOTPRODUCT_FLAG,
+                                     IGNORE_RANGE,
+                                     EMIT_CONSTRAINT_CHECK));
+
+#ifdef COMPILER1
+  emit_constraint_no(NULL C1_FLAGS(EMIT_CONSTRAINT_DEVELOPER_FLAG,
+                                   EMIT_CONSTRAINT_PD_DEVELOPER_FLAG,
+                                   EMIT_CONSTRAINT_PRODUCT_FLAG,
+                                   EMIT_CONSTRAINT_PD_PRODUCT_FLAG,
+                                   EMIT_CONSTRAINT_DIAGNOSTIC_FLAG,
+                                   EMIT_CONSTRAINT_NOTPRODUCT_FLAG,
+                                   IGNORE_RANGE,
+                                   EMIT_CONSTRAINT_CHECK));
+#endif // COMPILER1
+
+#ifdef COMPILER2
+  emit_constraint_no(NULL C2_FLAGS(EMIT_CONSTRAINT_DEVELOPER_FLAG,
+                                   EMIT_CONSTRAINT_PD_DEVELOPER_FLAG,
+                                   EMIT_CONSTRAINT_PRODUCT_FLAG,
+                                   EMIT_CONSTRAINT_PD_PRODUCT_FLAG,
+                                   EMIT_CONSTRAINT_DIAGNOSTIC_FLAG,
+                                   EMIT_CONSTRAINT_EXPERIMENTAL_FLAG,
+                                   EMIT_CONSTRAINT_NOTPRODUCT_FLAG,
+                                   IGNORE_RANGE,
+                                   EMIT_CONSTRAINT_CHECK));
+#endif // COMPILER2
+
+#ifndef INCLUDE_ALL_GCS
+  emit_constraint_no(NULL G1_FLAGS(EMIT_CONSTRAINT_DEVELOPER_FLAG,
+                                   EMIT_CONSTRAINT_PD_DEVELOPER_FLAG,
+                                   EMIT_CONSTRAINT_PRODUCT_FLAG,
+                                   EMIT_CONSTRAINT_PD_PRODUCT_FLAG,
+                                   EMIT_CONSTRAINT_DIAGNOSTIC_FLAG,
+                                   EMIT_CONSTRAINT_EXPERIMENTAL_FLAG,
+                                   EMIT_CONSTRAINT_NOTPRODUCT_FLAG,
+                                   EMIT_CONSTRAINT_MANAGEABLE_FLAG,
+                                   EMIT_CONSTRAINT_PRODUCT_RW_FLAG,
+                                   IGNORE_RANGE,
+                                   EMIT_CONSTRAINT_CHECK));
+#endif // INCLUDE_ALL_GCS
+}
+
+CommandLineFlagConstraint* CommandLineFlagConstraintList::find(const char* name) {
+  CommandLineFlagConstraint* found = NULL;
+  for (int i=0; i<length(); i++) {
+    CommandLineFlagConstraint* constraint = at(i);
+    if (strcmp(constraint->name(), name) == 0) {
+      found = constraint;
+      break;
+    }
+  }
+  return found;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2015, 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.
+ *
+ */
+
+#ifndef SHARE_VM_RUNTIME_COMMANDLINEFLAGCONSTRAINTLIST_HPP
+#define SHARE_VM_RUNTIME_COMMANDLINEFLAGCONSTRAINTLIST_HPP
+
+#include "runtime/globals.hpp"
+#include "utilities/growableArray.hpp"
+
+/*
+ * Here we have a mechanism for extracting constraints (as custom functions) for flags,
+ * which otherwise can not be expressed via simple range check, specified in flag macro tables.
+ *
+ * An example of a constraint is "flag1 < flag2" where both flag1 and flag2 can change.
+ *
+ * See runtime "runtime/commandLineFlagConstraintsCompiler.hpp",
+ * "runtime/commandLineFlagConstraintsGC.hpp" and
+ * "runtime/commandLineFlagConstraintsRuntime.hpp" for the functions themselves.
+ */
+
+typedef Flag::Error (*CommandLineFlagConstraintFunc_bool)(bool verbose, bool* value);
+typedef Flag::Error (*CommandLineFlagConstraintFunc_int)(bool verbose, int* value);
+typedef Flag::Error (*CommandLineFlagConstraintFunc_intx)(bool verbose, intx* value);
+typedef Flag::Error (*CommandLineFlagConstraintFunc_uint)(bool verbose, uint* value);
+typedef Flag::Error (*CommandLineFlagConstraintFunc_uintx)(bool verbose, uintx* value);
+typedef Flag::Error (*CommandLineFlagConstraintFunc_uint64_t)(bool verbose, uint64_t* value);
+typedef Flag::Error (*CommandLineFlagConstraintFunc_size_t)(bool verbose, size_t* value);
+typedef Flag::Error (*CommandLineFlagConstraintFunc_double)(bool verbose, double* value);
+
+class CommandLineFlagConstraint : public CHeapObj<mtInternal> {
+private:
+  const char* _name;
+public:
+  // the "name" argument must be a string literal
+  CommandLineFlagConstraint(const char* name) { _name=name; };
+  ~CommandLineFlagConstraint() {};
+  const char* name() { return _name; }
+  virtual Flag::Error apply_bool(bool* value, bool verbose = true) { ShouldNotReachHere(); return Flag::ERR_OTHER; };
+  virtual Flag::Error apply_int(int* value, bool verbose = true) { ShouldNotReachHere(); return Flag::ERR_OTHER; };
+  virtual Flag::Error apply_intx(intx* value, bool verbose = true) { ShouldNotReachHere(); return Flag::ERR_OTHER; };
+  virtual Flag::Error apply_uint(uint* value, bool verbose = true) { ShouldNotReachHere(); return Flag::ERR_OTHER; };
+  virtual Flag::Error apply_uintx(uintx* value, bool verbose = true) { ShouldNotReachHere(); return Flag::ERR_OTHER; };
+  virtual Flag::Error apply_uint64_t(uint64_t* value, bool verbose = true) { ShouldNotReachHere(); return Flag::ERR_OTHER; };
+  virtual Flag::Error apply_size_t(size_t* value, bool verbose = true) { ShouldNotReachHere(); return Flag::ERR_OTHER; };
+  virtual Flag::Error apply_double(double* value, bool verbose = true) { ShouldNotReachHere(); return Flag::ERR_OTHER; };
+};
+
+class CommandLineFlagConstraintList : public AllStatic {
+private:
+  static GrowableArray<CommandLineFlagConstraint*>* _constraints;
+public:
+  static void init();
+  static int length() { return (_constraints != NULL) ? _constraints->length() : 0; }
+  static CommandLineFlagConstraint* at(int i) { return (_constraints != NULL) ? _constraints->at(i) : NULL; }
+  static CommandLineFlagConstraint* find(const char* name);
+  static void add(CommandLineFlagConstraint* constraint) { _constraints->append(constraint); }
+};
+
+#endif /* SHARE_VM_RUNTIME_COMMANDLINEFLAGCONSTRAINTLIST_HPP */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2015, 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 "runtime/arguments.hpp"
+#include "runtime/commandLineFlagConstraintsCompiler.hpp"
+#include "runtime/globals.hpp"
+#include "utilities/defaultStream.hpp"
+
+Flag::Error AliasLevelConstraintFunc(bool verbose, intx* value) {
+  if (CommandLineFlags::finishedInitializing() == true) {
+    if ((*value <= 1) && (Arguments::mode() == Arguments::_comp)) {
+      if (verbose == true) {
+        jio_fprintf(defaultStream::error_stream(),
+                  "AliasLevel (" INTX_FORMAT ") is not compatible "
+                  "with -Xcomp \n",
+                  *value);
+      }
+      return Flag::VIOLATES_CONSTRAINT;
+    }
+  }
+  return Flag::SUCCESS;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2015, 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.
+ *
+ */
+
+#ifndef SHARE_VM_RUNTIME_COMMANDLINEFLAGCONSTRAINTSCOMPILER_HPP
+#define SHARE_VM_RUNTIME_COMMANDLINEFLAGCONSTRAINTSCOMPILER_HPP
+
+#include "runtime/globals.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+/*
+ * Here we have compiler arguments constraints functions, which are called automatically
+ * whenever flag's value changes. If the constraint fails the function should return
+ * an appropriate error value.
+ */
+
+Flag::Error AliasLevelConstraintFunc(bool verbose, intx* value);
+
+#endif /* SHARE_VM_RUNTIME_COMMANDLINEFLAGCONSTRAINTSCOMPILER_HPP */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2015, 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 "runtime/arguments.hpp"
+#include "runtime/commandLineFlagConstraintsGC.hpp"
+#include "runtime/globals.hpp"
+#include "utilities/defaultStream.hpp"
+
+#if INCLUDE_ALL_GCS
+#include "gc/g1/g1_globals.hpp"
+#endif // INCLUDE_ALL_GCS
+#ifdef COMPILER1
+#include "c1/c1_globals.hpp"
+#endif // COMPILER1
+#ifdef COMPILER2
+#include "opto/c2_globals.hpp"
+#endif // COMPILER2
+
+Flag::Error MinHeapFreeRatioConstraintFunc(bool verbose, uintx* value) {
+  if ((CommandLineFlags::finishedInitializing()) && (*value > MaxHeapFreeRatio)) {
+    if (verbose == true) {
+      jio_fprintf(defaultStream::error_stream(),
+                  "MinHeapFreeRatio (" UINTX_FORMAT ") must be less than or "
+                  "equal to MaxHeapFreeRatio (" UINTX_FORMAT ")\n",
+                  *value, MaxHeapFreeRatio);
+    }
+    return Flag::VIOLATES_CONSTRAINT;
+  } else {
+    return Flag::SUCCESS;
+  }
+}
+
+Flag::Error MaxHeapFreeRatioConstraintFunc(bool verbose, uintx* value) {
+  if ((CommandLineFlags::finishedInitializing()) && (*value < MinHeapFreeRatio)) {
+    if (verbose == true) {
+      jio_fprintf(defaultStream::error_stream(),
+                  "MaxHeapFreeRatio (" UINTX_FORMAT ") must be greater than or "
+                  "equal to MinHeapFreeRatio (" UINTX_FORMAT ")\n",
+                  *value, MinHeapFreeRatio);
+    }
+    return Flag::VIOLATES_CONSTRAINT;
+  } else {
+    return Flag::SUCCESS;
+  }
+}
+
+Flag::Error MinMetaspaceFreeRatioConstraintFunc(bool verbose, uintx* value) {
+  if ((CommandLineFlags::finishedInitializing()) && (*value > MaxMetaspaceFreeRatio)) {
+    if (verbose == true) {
+      jio_fprintf(defaultStream::error_stream(),
+                  "MinMetaspaceFreeRatio (" UINTX_FORMAT ") must be less than or "
+                  "equal to MaxMetaspaceFreeRatio (" UINTX_FORMAT ")\n",
+                  *value, MaxMetaspaceFreeRatio);
+    }
+    return Flag::VIOLATES_CONSTRAINT;
+  } else {
+    return Flag::SUCCESS;
+  }
+}
+
+Flag::Error MaxMetaspaceFreeRatioConstraintFunc(bool verbose, uintx* value) {
+  if ((CommandLineFlags::finishedInitializing()) && (*value < MinMetaspaceFreeRatio)) {
+    if (verbose == true) {
+      jio_fprintf(defaultStream::error_stream(),
+                  "MaxMetaspaceFreeRatio (" UINTX_FORMAT ") must be greater than or "
+                  "equal to MinMetaspaceFreeRatio (" UINTX_FORMAT ")\n",
+                  *value, MinMetaspaceFreeRatio);
+    }
+    return Flag::VIOLATES_CONSTRAINT;
+  } else {
+    return Flag::SUCCESS;
+  }
+}
+
+// GC workaround for "-XX:+UseConcMarkSweepGC"
+// which sets InitialTenuringThreshold to 7 but leaves MaxTenuringThreshold remaining at 6
+// and therefore would invalidate the constraint
+#define UseConcMarkSweepGCWorkaroundIfNeeded(initial, max) { \
+  if ((initial == 7) && (max == 6)) { \
+    return Flag::SUCCESS; \
+  } \
+}
+
+Flag::Error InitialTenuringThresholdConstraintFunc(bool verbose, uintx* value) {
+  UseConcMarkSweepGCWorkaroundIfNeeded(*value, MaxTenuringThreshold);
+
+  if ((CommandLineFlags::finishedInitializing()) && (*value > MaxTenuringThreshold)) {
+    if (verbose == true) {
+      jio_fprintf(defaultStream::error_stream(),
+                  "InitialTenuringThreshold (" UINTX_FORMAT ") must be less than or "
+                  "equal to MaxTenuringThreshold (" UINTX_FORMAT ")\n",
+                  *value, MaxTenuringThreshold);
+    }
+    return Flag::VIOLATES_CONSTRAINT;
+  } else {
+    return Flag::SUCCESS;
+  }
+}
+
+Flag::Error MaxTenuringThresholdConstraintFunc(bool verbose, uintx* value) {
+  UseConcMarkSweepGCWorkaroundIfNeeded(InitialTenuringThreshold, *value);
+
+  if ((CommandLineFlags::finishedInitializing()) && (*value < InitialTenuringThreshold)) {
+    if (verbose == true) {
+      jio_fprintf(defaultStream::error_stream(),
+                  "MaxTenuringThreshold (" UINTX_FORMAT ") must be greater than or "
+                  "equal to InitialTenuringThreshold (" UINTX_FORMAT ")\n",
+                  *value, InitialTenuringThreshold);
+    }
+    return Flag::VIOLATES_CONSTRAINT;
+  } else {
+    return Flag::SUCCESS;
+  }
+}
+
+#if INCLUDE_ALL_GCS
+
+Flag::Error G1NewSizePercentConstraintFunc(bool verbose, uintx* value) {
+  if ((CommandLineFlags::finishedInitializing()) && (*value > G1MaxNewSizePercent)) {
+    if (verbose == true) {
+      jio_fprintf(defaultStream::error_stream(),
+                  "G1NewSizePercent (" UINTX_FORMAT ") must be less than or "
+                  "equal to G1MaxNewSizePercent (" UINTX_FORMAT ")\n",
+                  *value, G1MaxNewSizePercent);
+    }
+    return Flag::VIOLATES_CONSTRAINT;
+  } else {
+    return Flag::SUCCESS;
+  }
+}
+
+Flag::Error G1MaxNewSizePercentConstraintFunc(bool verbose, uintx* value) {
+  if ((CommandLineFlags::finishedInitializing()) && (*value < G1NewSizePercent)) {
+    if (verbose == true) {
+      jio_fprintf(defaultStream::error_stream(),
+                  "G1MaxNewSizePercent (" UINTX_FORMAT ") must be greater than or "
+                  "equal to G1NewSizePercent (" UINTX_FORMAT ")\n",
+                  *value, G1NewSizePercent);
+    }
+    return Flag::VIOLATES_CONSTRAINT;
+  } else {
+    return Flag::SUCCESS;
+  }
+}
+
+#endif // INCLUDE_ALL_GCS
+
+Flag::Error CMSOldPLABMinConstraintFunc(bool verbose, size_t* value) {
+  if ((CommandLineFlags::finishedInitializing()) && (*value > CMSOldPLABMax)) {
+    if (verbose == true) {
+      jio_fprintf(defaultStream::error_stream(),
+                  "CMSOldPLABMin (" SIZE_FORMAT ") must be less than or "
+                  "equal to CMSOldPLABMax (" SIZE_FORMAT ")\n",
+                  *value, CMSOldPLABMax);
+    }
+    return Flag::VIOLATES_CONSTRAINT;
+  } else {
+    return Flag::SUCCESS;
+  }
+}
+
+Flag::Error CMSPrecleanDenominatorConstraintFunc(bool verbose, uintx* value) {
+  if ((CommandLineFlags::finishedInitializing()) && (*value <= CMSPrecleanNumerator)) {
+    if (verbose == true) {
+      jio_fprintf(defaultStream::error_stream(),
+                  "CMSPrecleanDenominator (" UINTX_FORMAT ") must be strickly greater than "
+                  "CMSPrecleanNumerator (" UINTX_FORMAT ")\n",
+                  *value, CMSPrecleanNumerator);
+    }
+    return Flag::VIOLATES_CONSTRAINT;
+  } else {
+    return Flag::SUCCESS;
+  }
+}
+
+Flag::Error CMSPrecleanNumeratorConstraintFunc(bool verbose, uintx* value) {
+  if ((CommandLineFlags::finishedInitializing()) && (*value > (CMSPrecleanDenominator - 1))) {
+    if (verbose == true) {
+      jio_fprintf(defaultStream::error_stream(),
+                  "CMSPrecleanNumerator (" UINTX_FORMAT ") must be less than or "
+                  "equal to CMSPrecleanDenominator - 1 (" UINTX_FORMAT ")\n", *value,
+                  CMSPrecleanDenominator - 1);
+    }
+    return Flag::VIOLATES_CONSTRAINT;
+  } else {
+    return Flag::SUCCESS;
+  }
+}
+
+Flag::Error SurvivorAlignmentInBytesConstraintFunc(bool verbose, intx* value) {
+  if (CommandLineFlags::finishedInitializing()) {
+    if (*value != 0) {
+      if (!is_power_of_2(*value)) {
+        if (verbose == true) {
+          jio_fprintf(defaultStream::error_stream(),
+                    "SurvivorAlignmentInBytes (" INTX_FORMAT ") must be power of 2\n",
+                    *value);
+        }
+        return Flag::VIOLATES_CONSTRAINT;
+      }
+      if (*value < ObjectAlignmentInBytes) {
+        if (verbose == true) {
+          jio_fprintf(defaultStream::error_stream(),
+                    "SurvivorAlignmentInBytes (" INTX_FORMAT ") must be greater than or "
+                    "equal to ObjectAlignmentInBytes (" INTX_FORMAT ") \n",
+                    *value, ObjectAlignmentInBytes);
+        }
+        return Flag::VIOLATES_CONSTRAINT;
+      }
+    }
+  }
+  return Flag::SUCCESS;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2015, 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.
+ *
+ */
+
+#ifndef SHARE_VM_RUNTIME_COMMANDLINEFLAGCONSTRAINTSGC_HPP
+#define SHARE_VM_RUNTIME_COMMANDLINEFLAGCONSTRAINTSGC_HPP
+
+#include "runtime/globals.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+/*
+ * Here we have GC arguments constraints functions, which are called automatically
+ * whenever flag's value changes. If the constraint fails the function should return
+ * an appropriate error value.
+ */
+
+Flag::Error MinHeapFreeRatioConstraintFunc(bool verbose, uintx* value);
+Flag::Error MaxHeapFreeRatioConstraintFunc(bool verbose, uintx* value);
+
+Flag::Error MinMetaspaceFreeRatioConstraintFunc(bool verbose, uintx* value);
+Flag::Error MaxMetaspaceFreeRatioConstraintFunc(bool verbose, uintx* value);
+
+Flag::Error InitialTenuringThresholdConstraintFunc(bool verbose, uintx* value);
+Flag::Error MaxTenuringThresholdConstraintFunc(bool verbose, uintx* value);
+
+#if INCLUDE_ALL_GCS
+Flag::Error G1NewSizePercentConstraintFunc(bool verbose, uintx* value);
+Flag::Error G1MaxNewSizePercentConstraintFunc(bool verbose, uintx* value);
+#endif // INCLUDE_ALL_GCS
+
+Flag::Error CMSOldPLABMinConstraintFunc(bool verbose, size_t* value);
+
+Flag::Error CMSPrecleanDenominatorConstraintFunc(bool verbose, uintx* value);
+Flag::Error CMSPrecleanNumeratorConstraintFunc(bool verbose, uintx* value);
+
+Flag::Error SurvivorAlignmentInBytesConstraintFunc(bool verbose, intx* value);
+
+#endif /* SHARE_VM_RUNTIME_COMMANDLINEFLAGCONSTRAINTSGC_HPP */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsRuntime.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2015, 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 "runtime/arguments.hpp"
+#include "runtime/commandLineFlagConstraintsRuntime.hpp"
+#include "runtime/globals.hpp"
+#include "utilities/defaultStream.hpp"
+
+Flag::Error ObjectAlignmentInBytesConstraintFunc(bool verbose, intx* value) {
+  if (!is_power_of_2(*value)) {
+    if (verbose == true) {
+      jio_fprintf(defaultStream::error_stream(),
+                "ObjectAlignmentInBytes=" INTX_FORMAT " must be power of 2\n",
+                *value);
+    }
+    return Flag::VIOLATES_CONSTRAINT;
+  }
+  // In case page size is very small.
+  if (*value >= (intx)os::vm_page_size()) {
+    if (verbose == true) {
+      jio_fprintf(defaultStream::error_stream(),
+                "ObjectAlignmentInBytes=" INTX_FORMAT " must be less than page size " INTX_FORMAT "\n",
+                *value, (intx)os::vm_page_size());
+    }
+    return Flag::VIOLATES_CONSTRAINT;
+  }
+  return Flag::SUCCESS;
+}
+
+// Need to enforce the padding not to break the existing field alignments.
+// It is sufficient to check against the largest type size.
+Flag::Error ContendedPaddingWidthConstraintFunc(bool verbose, intx* value) {
+  if ((*value != 0) && ((*value % BytesPerLong) != 0)) {
+    if (verbose == true) {
+      jio_fprintf(defaultStream::error_stream(),
+                "ContendedPaddingWidth=" INTX_FORMAT " must be a multiple of %d\n",
+                *value, BytesPerLong);
+    }
+    return Flag::VIOLATES_CONSTRAINT;
+  } else {
+    return Flag::SUCCESS;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsRuntime.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015, 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.
+ *
+ */
+
+#ifndef SHARE_VM_RUNTIME_COMMANDLINEFLAGCONSTRAINTSRUNTIME_HPP
+#define SHARE_VM_RUNTIME_COMMANDLINEFLAGCONSTRAINTSRUNTIME_HPP
+
+#include "runtime/globals.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+/*
+ * Here we have runtime arguments constraints functions, which are called automatically
+ * whenever flag's value changes. If the constraint fails the function should return
+ * an appropriate error value.
+ */
+
+Flag::Error ObjectAlignmentInBytesConstraintFunc(bool verbose, intx* value);
+
+Flag::Error ContendedPaddingWidthConstraintFunc(bool verbose, intx* value);
+
+#endif /* SHARE_VM_RUNTIME_COMMANDLINEFLAGCONSTRAINTSRUNTIME_HPP */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/runtime/commandLineFlagRangeList.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -0,0 +1,367 @@
+/*
+ * Copyright (c) 2015, 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 "classfile/stringTable.hpp"
+#include "classfile/symbolTable.hpp"
+#include "gc/shared/referenceProcessor.hpp"
+#include "runtime/arguments.hpp"
+#include "runtime/commandLineFlagRangeList.hpp"
+#include "runtime/os.hpp"
+#include "utilities/defaultStream.hpp"
+#include "utilities/macros.hpp"
+
+class CommandLineFlagRange_int : public CommandLineFlagRange {
+  int _min;
+  int _max;
+
+public:
+  // the "name" argument must be a string literal
+  CommandLineFlagRange_int(const char* name, int min, int max) : CommandLineFlagRange(name) {
+    _min=min, _max=max;
+  }
+
+  Flag::Error check_int(int value, bool verbose = true) {
+    if ((value < _min) || (value > _max)) {
+      if (verbose == true) {
+        jio_fprintf(defaultStream::error_stream(),
+                    "int %s=%d is outside the allowed range [ %d ... %d ]\n",
+                    name(), value, _min, _max);
+      }
+      return Flag::OUT_OF_BOUNDS;
+    } else {
+      return Flag::SUCCESS;
+    }
+  }
+
+  void print(outputStream* st) {
+    st->print("[ %-25d ... %25d ]", _min, _max);
+  }
+};
+
+class CommandLineFlagRange_intx : public CommandLineFlagRange {
+  intx _min;
+  intx _max;
+
+public:
+  // the "name" argument must be a string literal
+  CommandLineFlagRange_intx(const char* name, intx min, intx max) : CommandLineFlagRange(name) {
+    _min=min, _max=max;
+  }
+
+  Flag::Error check_intx(intx value, bool verbose = true) {
+    if ((value < _min) || (value > _max)) {
+      if (verbose == true) {
+        jio_fprintf(defaultStream::error_stream(),
+                    "intx %s=" INTX_FORMAT " is outside the allowed range [ " INTX_FORMAT " ... " INTX_FORMAT " ]\n",
+                    name(), value, _min, _max);
+      }
+      return Flag::OUT_OF_BOUNDS;
+    } else {
+      return Flag::SUCCESS;
+    }
+  }
+
+  void print(outputStream* st) {
+    st->print("[ "INTX_FORMAT_W(-25)" ... "INTX_FORMAT_W(25)" ]", _min, _max);
+  }
+};
+
+class CommandLineFlagRange_uint : public CommandLineFlagRange {
+  uint _min;
+  uint _max;
+
+public:
+  // the "name" argument must be a string literal
+  CommandLineFlagRange_uint(const char* name, uint min, uint max) : CommandLineFlagRange(name) {
+    _min=min, _max=max;
+  }
+
+  Flag::Error check_uint(uint value, bool verbose = true) {
+    if ((value < _min) || (value > _max)) {
+      if (verbose == true) {
+        jio_fprintf(defaultStream::error_stream(),
+                    "uintx %s=%u is outside the allowed range [ %u ... %u ]\n",
+                    name(), value, _min, _max);
+      }
+      return Flag::OUT_OF_BOUNDS;
+    } else {
+      return Flag::SUCCESS;
+    }
+  }
+
+  void print(outputStream* st) {
+    st->print("[ %-25u ... %25u ]", _min, _max);
+  }
+};
+
+class CommandLineFlagRange_uintx : public CommandLineFlagRange {
+  uintx _min;
+  uintx _max;
+
+public:
+  // the "name" argument must be a string literal
+  CommandLineFlagRange_uintx(const char* name, uintx min, uintx max) : CommandLineFlagRange(name) {
+    _min=min, _max=max;
+  }
+
+  Flag::Error check_uintx(uintx value, bool verbose = true) {
+    if ((value < _min) || (value > _max)) {
+      if (verbose == true) {
+        jio_fprintf(defaultStream::error_stream(),
+                    "uintx %s=" UINTX_FORMAT " is outside the allowed range [ " UINTX_FORMAT " ... " UINTX_FORMAT " ]\n",
+                    name(), value, _min, _max);
+      }
+      return Flag::OUT_OF_BOUNDS;
+    } else {
+      return Flag::SUCCESS;
+    }
+  }
+
+  void print(outputStream* st) {
+    st->print("[ "UINTX_FORMAT_W(-25)" ... "UINTX_FORMAT_W(25)" ]", _min, _max);
+  }
+};
+
+class CommandLineFlagRange_uint64_t : public CommandLineFlagRange {
+  uint64_t _min;
+  uint64_t _max;
+
+public:
+  // the "name" argument must be a string literal
+  CommandLineFlagRange_uint64_t(const char* name, uint64_t min, uint64_t max) : CommandLineFlagRange(name) {
+    _min=min, _max=max;
+  }
+
+  Flag::Error check_uint64_t(uint64_t value, bool verbose = true) {
+    if ((value < _min) || (value > _max)) {
+      if (verbose == true) {
+        jio_fprintf(defaultStream::error_stream(),
+                    "uint64_t %s=" UINT64_FORMAT " is outside the allowed range [ " UINT64_FORMAT " ... " UINT64_FORMAT " ]\n",
+                    name(), value, _min, _max);
+      }
+      return Flag::OUT_OF_BOUNDS;
+    } else {
+      return Flag::SUCCESS;
+    }
+  }
+
+  void print(outputStream* st) {
+    st->print("[ "UINT64_FORMAT_W(-25)" ... "UINT64_FORMAT_W(25)" ]", _min, _max);
+  }
+};
+
+class CommandLineFlagRange_size_t : public CommandLineFlagRange {
+  size_t _min;
+  size_t _max;
+
+public:
+  // the "name" argument must be a string literal
+  CommandLineFlagRange_size_t(const char* name, size_t min, size_t max) : CommandLineFlagRange(name) {
+    _min=min, _max=max;
+  }
+
+  Flag::Error check_size_t(size_t value, bool verbose = true) {
+    if ((value < _min) || (value > _max)) {
+      if (verbose == true) {
+        jio_fprintf(defaultStream::error_stream(),
+                    "size_t %s=" SIZE_FORMAT " is outside the allowed range [ " SIZE_FORMAT " ... " SIZE_FORMAT " ]\n",
+                    name(), value, _min, _max);
+      }
+      return Flag::OUT_OF_BOUNDS;
+    } else {
+      return Flag::SUCCESS;
+    }
+  }
+
+  void print(outputStream* st) {
+    st->print("[ "SIZE_FORMAT_W(-25)" ... "SIZE_FORMAT_W(25)" ]", _min, _max);
+  }
+};
+
+class CommandLineFlagRange_double : public CommandLineFlagRange {
+  double _min;
+  double _max;
+
+public:
+  // the "name" argument must be a string literal
+  CommandLineFlagRange_double(const char* name, double min, double max) : CommandLineFlagRange(name) {
+    _min=min, _max=max;
+  }
+
+  Flag::Error check_double(double value, bool verbose = true) {
+    if ((value < _min) || (value > _max)) {
+      if (verbose == true) {
+        jio_fprintf(defaultStream::error_stream(),
+                    "double %s=%f is outside the allowed range [ %f ... %f ]\n",
+                    name(), value, _min, _max);
+      }
+      return Flag::OUT_OF_BOUNDS;
+    } else {
+      return Flag::SUCCESS;
+    }
+  }
+
+  void print(outputStream* st) {
+    st->print("[ %-25.3f ... %25.3f ]", _min, _max);
+  }
+};
+
+// No constraint emitting
+void emit_range_no(...)                         { /* NOP */ }
+
+// No constraint emitting if function argument is NOT provided
+void emit_range_bool(const char* /*name*/)      { /* NOP */ }
+void emit_range_ccstr(const char* /*name*/)     { /* NOP */ }
+void emit_range_ccstrlist(const char* /*name*/) { /* NOP */ }
+void emit_range_int(const char* /*name*/)       { /* NOP */ }
+void emit_range_intx(const char* /*name*/)      { /* NOP */ }
+void emit_range_uint(const char* /*name*/)      { /* NOP */ }
+void emit_range_uintx(const char* /*name*/)     { /* NOP */ }
+void emit_range_uint64_t(const char* /*name*/)  { /* NOP */ }
+void emit_range_size_t(const char* /*name*/)    { /* NOP */ }
+void emit_range_double(const char* /*name*/)    { /* NOP */ }
+
+// CommandLineFlagRange emitting code functions if range arguments are provided
+void emit_range_intx(const char* name, intx min, intx max) {
+  CommandLineFlagRangeList::add(new CommandLineFlagRange_intx(name, min, max));
+}
+void emit_range_uintx(const char* name, uintx min, uintx max) {
+  CommandLineFlagRangeList::add(new CommandLineFlagRange_uintx(name, min, max));
+}
+void emit_range_uint64_t(const char* name, uint64_t min, uint64_t max) {
+  CommandLineFlagRangeList::add(new CommandLineFlagRange_uint64_t(name, min, max));
+}
+void emit_range_size_t(const char* name, size_t min, size_t max) {
+  CommandLineFlagRangeList::add(new CommandLineFlagRange_size_t(name, min, max));
+}
+void emit_range_double(const char* name, double min, double max) {
+  CommandLineFlagRangeList::add(new CommandLineFlagRange_double(name, min, max));
+}
+
+// Generate code to call emit_range_xxx function
+#define EMIT_RANGE_PRODUCT_FLAG(type, name, value, doc)      ); emit_range_##type(#name
+#define EMIT_RANGE_COMMERCIAL_FLAG(type, name, value, doc)   ); emit_range_##type(#name
+#define EMIT_RANGE_DIAGNOSTIC_FLAG(type, name, value, doc)   ); emit_range_##type(#name
+#define EMIT_RANGE_EXPERIMENTAL_FLAG(type, name, value, doc) ); emit_range_##type(#name
+#define EMIT_RANGE_MANAGEABLE_FLAG(type, name, value, doc)   ); emit_range_##type(#name
+#define EMIT_RANGE_PRODUCT_RW_FLAG(type, name, value, doc)   ); emit_range_##type(#name
+#define EMIT_RANGE_PD_PRODUCT_FLAG(type, name, doc)          ); emit_range_##type(#name
+#define EMIT_RANGE_DEVELOPER_FLAG(type, name, value, doc)    ); emit_range_##type(#name
+#define EMIT_RANGE_PD_DEVELOPER_FLAG(type, name, doc)        ); emit_range_##type(#name
+#define EMIT_RANGE_NOTPRODUCT_FLAG(type, name, value, doc)   ); emit_range_##type(#name
+#define EMIT_RANGE_LP64_PRODUCT_FLAG(type, name, value, doc) ); emit_range_##type(#name
+
+// Generate func argument to pass into emit_range_xxx functions
+#define EMIT_RANGE_CHECK(a, b)                               , a, b
+
+#define INITIAL_RANGES_SIZE 128
+GrowableArray<CommandLineFlagRange*>* CommandLineFlagRangeList::_ranges = NULL;
+
+// Check the ranges of all flags that have them
+void CommandLineFlagRangeList::init(void) {
+
+  _ranges = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<CommandLineFlagRange*>(INITIAL_RANGES_SIZE, true);
+
+  emit_range_no(NULL RUNTIME_FLAGS(EMIT_RANGE_DEVELOPER_FLAG,
+                                   EMIT_RANGE_PD_DEVELOPER_FLAG,
+                                   EMIT_RANGE_PRODUCT_FLAG,
+                                   EMIT_RANGE_PD_PRODUCT_FLAG,
+                                   EMIT_RANGE_DIAGNOSTIC_FLAG,
+                                   EMIT_RANGE_EXPERIMENTAL_FLAG,
+                                   EMIT_RANGE_NOTPRODUCT_FLAG,
+                                   EMIT_RANGE_MANAGEABLE_FLAG,
+                                   EMIT_RANGE_PRODUCT_RW_FLAG,
+                                   EMIT_RANGE_LP64_PRODUCT_FLAG,
+                                   EMIT_RANGE_CHECK,
+                                   IGNORE_CONSTRAINT) );
+
+  EMIT_RANGES_FOR_GLOBALS_EXT
+
+  emit_range_no(NULL ARCH_FLAGS(EMIT_RANGE_DEVELOPER_FLAG,
+                                     EMIT_RANGE_PRODUCT_FLAG,
+                                     EMIT_RANGE_DIAGNOSTIC_FLAG,
+                                     EMIT_RANGE_EXPERIMENTAL_FLAG,
+                                     EMIT_RANGE_NOTPRODUCT_FLAG,
+                                     EMIT_RANGE_CHECK,
+                                     IGNORE_CONSTRAINT));
+
+#ifdef COMPILER1
+  emit_range_no(NULL C1_FLAGS(EMIT_RANGE_DEVELOPER_FLAG,
+                                   EMIT_RANGE_PD_DEVELOPER_FLAG,
+                                   EMIT_RANGE_PRODUCT_FLAG,
+                                   EMIT_RANGE_PD_PRODUCT_FLAG,
+                                   EMIT_RANGE_DIAGNOSTIC_FLAG,
+                                   EMIT_RANGE_NOTPRODUCT_FLAG,
+                                   EMIT_RANGE_CHECK,
+                                   IGNORE_CONSTRAINT));
+#endif // COMPILER1
+
+#ifdef COMPILER2
+  emit_range_no(NULL C2_FLAGS(EMIT_RANGE_DEVELOPER_FLAG,
+                                   EMIT_RANGE_PD_DEVELOPER_FLAG,
+                                   EMIT_RANGE_PRODUCT_FLAG,
+                                   EMIT_RANGE_PD_PRODUCT_FLAG,
+                                   EMIT_RANGE_DIAGNOSTIC_FLAG,
+                                   EMIT_RANGE_EXPERIMENTAL_FLAG,
+                                   EMIT_RANGE_NOTPRODUCT_FLAG,
+                                   EMIT_RANGE_CHECK,
+                                   IGNORE_CONSTRAINT));
+#endif // COMPILER2
+
+#if INCLUDE_ALL_GCS
+  emit_range_no(NULL G1_FLAGS(EMIT_RANGE_DEVELOPER_FLAG,
+                                   EMIT_RANGE_PD_DEVELOPER_FLAG,
+                                   EMIT_RANGE_PRODUCT_FLAG,
+                                   EMIT_RANGE_PD_PRODUCT_FLAG,
+                                   EMIT_RANGE_DIAGNOSTIC_FLAG,
+                                   EMIT_RANGE_EXPERIMENTAL_FLAG,
+                                   EMIT_RANGE_NOTPRODUCT_FLAG,
+                                   EMIT_RANGE_MANAGEABLE_FLAG,
+                                   EMIT_RANGE_PRODUCT_RW_FLAG,
+                                   EMIT_RANGE_CHECK,
+                                   IGNORE_CONSTRAINT));
+#endif // INCLUDE_ALL_GCS
+}
+
+CommandLineFlagRange* CommandLineFlagRangeList::find(const char* name) {
+  CommandLineFlagRange* found = NULL;
+  for (int i=0; i<length(); i++) {
+    CommandLineFlagRange* range = at(i);
+    if (strcmp(range->name(), name) == 0) {
+      found = range;
+      break;
+    }
+  }
+  return found;
+}
+
+void CommandLineFlagRangeList::print(const char* name, outputStream* st, bool unspecified) {
+  CommandLineFlagRange* range = CommandLineFlagRangeList::find(name);
+  if (range != NULL) {
+    range->print(st);
+  } else if (unspecified == true) {
+    st->print("[                           ...                           ]");
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/runtime/commandLineFlagRangeList.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2015, 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.
+ *
+ */
+
+#ifndef SHARE_VM_RUNTIME_COMMANDLINEFLAGRANGELIST_HPP
+#define SHARE_VM_RUNTIME_COMMANDLINEFLAGRANGELIST_HPP
+
+#include "runtime/globals.hpp"
+#include "utilities/growableArray.hpp"
+
+/*
+ * Here we have a mechanism for extracting ranges specified in flag macro tables.
+ *
+ * The specified ranges are used to verify that flags have valid values.
+ *
+ * An example of a range is "min <= flag <= max". Both "min" and "max" must be
+ * constant and can not change. If either "min" or "max" can change,
+ * then we need to use constraint instead.
+ */
+
+class CommandLineFlagRange : public CHeapObj<mtInternal> {
+private:
+  const char* _name;
+public:
+  // the "name" argument must be a string literal
+  CommandLineFlagRange(const char* name) { _name=name; }
+  ~CommandLineFlagRange() {}
+  const char* name() { return _name; }
+  virtual Flag::Error check_int(int value, bool verbose = true) { ShouldNotReachHere(); return Flag::ERR_OTHER; }
+  virtual Flag::Error check_intx(intx value, bool verbose = true) { ShouldNotReachHere(); return Flag::ERR_OTHER; }
+  virtual Flag::Error check_uint(uint value, bool verbose = true) { ShouldNotReachHere(); return Flag::ERR_OTHER; }
+  virtual Flag::Error check_uintx(uintx value, bool verbose = true) { ShouldNotReachHere(); return Flag::ERR_OTHER; }
+  virtual Flag::Error check_uint64_t(uint64_t value, bool verbose = true) { ShouldNotReachHere(); return Flag::ERR_OTHER; }
+  virtual Flag::Error check_size_t(size_t value, bool verbose = true) { ShouldNotReachHere(); return Flag::ERR_OTHER; }
+  virtual Flag::Error check_double(double value, bool verbose = true) { ShouldNotReachHere(); return Flag::ERR_OTHER; }
+  virtual void print(outputStream* st) { ; }
+};
+
+class CommandLineFlagRangeList : public AllStatic {
+  static GrowableArray<CommandLineFlagRange*>* _ranges;
+public:
+  static void init();
+  static void add_globals_ext();
+  static int length() { return (_ranges != NULL) ? _ranges->length() : 0; }
+  static CommandLineFlagRange* at(int i) { return (_ranges != NULL) ? _ranges->at(i) : NULL; }
+  static CommandLineFlagRange* find(const char* name);
+  static void add(CommandLineFlagRange* range) { _ranges->append(range); }
+  static void print(const char* name, outputStream* st, bool unspecified = false);
+};
+
+#endif // SHARE_VM_RUNTIME_COMMANDLINEFLAGRANGELIST_HPP
--- a/hotspot/src/share/vm/runtime/frame.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/runtime/frame.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -307,11 +307,6 @@
 
   void interpreter_frame_verify_monitor(BasicObjectLock* value) const;
 
-  // Tells whether the current interpreter_frame frame pointer
-  // corresponds to the old compiled/deoptimized fp
-  // The receiver used to be a top level frame
-  bool interpreter_frame_equals_unpacked_fp(intptr_t* fp);
-
   // Return/result value from this interpreter frame
   // If the method return type is T_OBJECT or T_ARRAY populates oop_result
   // For other (non-T_VOID) the appropriate field in the jvalue is populated
--- a/hotspot/src/share/vm/runtime/globals.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/runtime/globals.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -28,7 +28,10 @@
 #include "runtime/arguments.hpp"
 #include "runtime/globals.hpp"
 #include "runtime/globals_extension.hpp"
+#include "runtime/commandLineFlagConstraintList.hpp"
+#include "runtime/commandLineFlagRangeList.hpp"
 #include "runtime/os.hpp"
+#include "runtime/sharedRuntime.hpp"
 #include "trace/tracing.hpp"
 #include "utilities/macros.hpp"
 #include "utilities/ostream.hpp"
@@ -48,24 +51,38 @@
 
 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
 
-RUNTIME_FLAGS(MATERIALIZE_DEVELOPER_FLAG, MATERIALIZE_PD_DEVELOPER_FLAG, \
-              MATERIALIZE_PRODUCT_FLAG, MATERIALIZE_PD_PRODUCT_FLAG, \
-              MATERIALIZE_DIAGNOSTIC_FLAG, MATERIALIZE_EXPERIMENTAL_FLAG, \
+RUNTIME_FLAGS(MATERIALIZE_DEVELOPER_FLAG, \
+              MATERIALIZE_PD_DEVELOPER_FLAG, \
+              MATERIALIZE_PRODUCT_FLAG, \
+              MATERIALIZE_PD_PRODUCT_FLAG, \
+              MATERIALIZE_DIAGNOSTIC_FLAG, \
+              MATERIALIZE_EXPERIMENTAL_FLAG, \
               MATERIALIZE_NOTPRODUCT_FLAG, \
-              MATERIALIZE_MANAGEABLE_FLAG, MATERIALIZE_PRODUCT_RW_FLAG, \
-              MATERIALIZE_LP64_PRODUCT_FLAG)
+              MATERIALIZE_MANAGEABLE_FLAG, \
+              MATERIALIZE_PRODUCT_RW_FLAG, \
+              MATERIALIZE_LP64_PRODUCT_FLAG, \
+              IGNORE_RANGE, \
+              IGNORE_CONSTRAINT)
 
-RUNTIME_OS_FLAGS(MATERIALIZE_DEVELOPER_FLAG, MATERIALIZE_PD_DEVELOPER_FLAG, \
-                 MATERIALIZE_PRODUCT_FLAG, MATERIALIZE_PD_PRODUCT_FLAG, \
-                 MATERIALIZE_DIAGNOSTIC_FLAG, MATERIALIZE_NOTPRODUCT_FLAG)
+RUNTIME_OS_FLAGS(MATERIALIZE_DEVELOPER_FLAG, \
+                 MATERIALIZE_PD_DEVELOPER_FLAG, \
+                 MATERIALIZE_PRODUCT_FLAG, \
+                 MATERIALIZE_PD_PRODUCT_FLAG, \
+                 MATERIALIZE_DIAGNOSTIC_FLAG, \
+                 MATERIALIZE_NOTPRODUCT_FLAG, \
+                 IGNORE_RANGE, \
+                 IGNORE_CONSTRAINT)
 
-ARCH_FLAGS(MATERIALIZE_DEVELOPER_FLAG, MATERIALIZE_PRODUCT_FLAG, \
-           MATERIALIZE_DIAGNOSTIC_FLAG, MATERIALIZE_EXPERIMENTAL_FLAG, \
-           MATERIALIZE_NOTPRODUCT_FLAG)
+ARCH_FLAGS(MATERIALIZE_DEVELOPER_FLAG, \
+           MATERIALIZE_PRODUCT_FLAG, \
+           MATERIALIZE_DIAGNOSTIC_FLAG, \
+           MATERIALIZE_EXPERIMENTAL_FLAG, \
+           MATERIALIZE_NOTPRODUCT_FLAG, \
+           IGNORE_RANGE, \
+           IGNORE_CONSTRAINT)
 
 MATERIALIZE_FLAGS_EXT
 
-
 static bool is_product_build() {
 #ifdef PRODUCT
   return true;
@@ -331,69 +348,86 @@
 #define FORMAT_BUFFER_LEN 16
 
 PRAGMA_FORMAT_NONLITERAL_IGNORED_EXTERNAL
-void Flag::print_on(outputStream* st, bool withComments) {
+void Flag::print_on(outputStream* st, bool withComments, bool printRanges) {
   // Don't print notproduct and develop flags in a product build.
   if (is_constant_in_binary()) {
     return;
   }
 
-  st->print("%9s %-40s %c= ", _type, _name, (!is_default() ? ':' : ' '));
+  if (!printRanges) {
+
+    st->print("%9s %-40s %c= ", _type, _name, (!is_default() ? ':' : ' '));
 
-  if (is_bool()) {
-    st->print("%-16s", get_bool() ? "true" : "false");
-  }
-  if (is_int()) {
-    st->print("%-16d", get_int());
-  }
-  if (is_uint()) {
-    st->print("%-16u", get_uint());
-  }
-  if (is_intx()) {
-    st->print("%-16ld", get_intx());
-  }
-  if (is_uintx()) {
-    st->print("%-16lu", get_uintx());
-  }
-  if (is_uint64_t()) {
-    st->print("%-16lu", get_uint64_t());
-  }
-  if (is_size_t()) {
-    st->print(SIZE_FORMAT_W(-16), get_size_t());
-  }
-  if (is_double()) {
-    st->print("%-16f", get_double());
+    if (is_bool()) {
+      st->print("%-16s", get_bool() ? "true" : "false");
+    } else if (is_int()) {
+      st->print("%-16d", get_int());
+    } else if (is_uint()) {
+      st->print("%-16u", get_uint());
+    } else if (is_intx()) {
+      st->print("%-16ld", get_intx());
+    } else if (is_uintx()) {
+      st->print("%-16lu", get_uintx());
+    } else if (is_uint64_t()) {
+      st->print("%-16lu", get_uint64_t());
+    } else if (is_size_t()) {
+      st->print(SIZE_FORMAT_W(-16), get_size_t());
+    } else if (is_double()) {
+      st->print("%-16f", get_double());
+    } else if (is_ccstr()) {
+      const char* cp = get_ccstr();
+      if (cp != NULL) {
+        const char* eol;
+        while ((eol = strchr(cp, '\n')) != NULL) {
+          char format_buffer[FORMAT_BUFFER_LEN];
+          size_t llen = pointer_delta(eol, cp, sizeof(char));
+          jio_snprintf(format_buffer, FORMAT_BUFFER_LEN,
+                       "%%." SIZE_FORMAT "s", llen);
+          PRAGMA_DIAG_PUSH
+          PRAGMA_FORMAT_NONLITERAL_IGNORED_INTERNAL
+          st->print(format_buffer, cp);
+          PRAGMA_DIAG_POP
+          st->cr();
+          cp = eol+1;
+          st->print("%5s %-35s += ", "", _name);
+        }
+        st->print("%-16s", cp);
+      }
+      else st->print("%-16s", "");
+    }
+
+    st->print("%-20s", " ");
+    print_kind(st);
+
+#ifndef PRODUCT
+    if (withComments) {
+      st->print("%s", _doc);
+    }
+#endif
+
+    st->cr();
+
+  } else if (!is_bool() && !is_ccstr()) {
+
+    if (printRanges) {
+
+      st->print("%9s %-50s ", _type, _name);
+
+      CommandLineFlagRangeList::print(_name, st, true);
+
+      st->print(" %-20s", " ");
+      print_kind(st);
+
+#ifndef PRODUCT
+      if (withComments) {
+        st->print("%s", _doc);
+      }
+#endif
+
+      st->cr();
+
+    }
   }
-  if (is_ccstr()) {
-    const char* cp = get_ccstr();
-    if (cp != NULL) {
-      const char* eol;
-      while ((eol = strchr(cp, '\n')) != NULL) {
-        char format_buffer[FORMAT_BUFFER_LEN];
-        size_t llen = pointer_delta(eol, cp, sizeof(char));
-        jio_snprintf(format_buffer, FORMAT_BUFFER_LEN,
-            "%%." SIZE_FORMAT "s", llen);
-PRAGMA_DIAG_PUSH
-PRAGMA_FORMAT_NONLITERAL_IGNORED_INTERNAL
-        st->print(format_buffer, cp);
-PRAGMA_DIAG_POP
-        st->cr();
-        cp = eol+1;
-        st->print("%5s %-35s += ", "", _name);
-      }
-      st->print("%-16s", cp);
-    }
-    else st->print("%-16s", "");
-  }
-
-  st->print("%-20s", " ");
-  print_kind(st);
-
-  if (withComments) {
-#ifndef PRODUCT
-    st->print("%s", _doc);
-#endif
-  }
-  st->cr();
 }
 
 void Flag::print_kind(outputStream* st) {
@@ -531,21 +565,75 @@
 #define SHARK_NOTPRODUCT_FLAG_STRUCT(    type, name, value, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_SHARK | Flag::KIND_NOT_PRODUCT) },
 
 static Flag flagTable[] = {
- RUNTIME_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, RUNTIME_PD_DEVELOP_FLAG_STRUCT, RUNTIME_PRODUCT_FLAG_STRUCT, RUNTIME_PD_PRODUCT_FLAG_STRUCT, RUNTIME_DIAGNOSTIC_FLAG_STRUCT, RUNTIME_EXPERIMENTAL_FLAG_STRUCT, RUNTIME_NOTPRODUCT_FLAG_STRUCT, RUNTIME_MANAGEABLE_FLAG_STRUCT, RUNTIME_PRODUCT_RW_FLAG_STRUCT, RUNTIME_LP64_PRODUCT_FLAG_STRUCT)
- RUNTIME_OS_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, RUNTIME_PD_DEVELOP_FLAG_STRUCT, RUNTIME_PRODUCT_FLAG_STRUCT, RUNTIME_PD_PRODUCT_FLAG_STRUCT, RUNTIME_DIAGNOSTIC_FLAG_STRUCT, RUNTIME_NOTPRODUCT_FLAG_STRUCT)
+ RUNTIME_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, \
+               RUNTIME_PD_DEVELOP_FLAG_STRUCT, \
+               RUNTIME_PRODUCT_FLAG_STRUCT, \
+               RUNTIME_PD_PRODUCT_FLAG_STRUCT, \
+               RUNTIME_DIAGNOSTIC_FLAG_STRUCT, \
+               RUNTIME_EXPERIMENTAL_FLAG_STRUCT, \
+               RUNTIME_NOTPRODUCT_FLAG_STRUCT, \
+               RUNTIME_MANAGEABLE_FLAG_STRUCT, \
+               RUNTIME_PRODUCT_RW_FLAG_STRUCT, \
+               RUNTIME_LP64_PRODUCT_FLAG_STRUCT, \
+               IGNORE_RANGE, \
+               IGNORE_CONSTRAINT)
+ RUNTIME_OS_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, \
+                  RUNTIME_PD_DEVELOP_FLAG_STRUCT, \
+                  RUNTIME_PRODUCT_FLAG_STRUCT, \
+                  RUNTIME_PD_PRODUCT_FLAG_STRUCT, \
+                  RUNTIME_DIAGNOSTIC_FLAG_STRUCT, \
+                  RUNTIME_NOTPRODUCT_FLAG_STRUCT, \
+                  IGNORE_RANGE, \
+                  IGNORE_CONSTRAINT)
 #if INCLUDE_ALL_GCS
- G1_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, RUNTIME_PD_DEVELOP_FLAG_STRUCT, RUNTIME_PRODUCT_FLAG_STRUCT, RUNTIME_PD_PRODUCT_FLAG_STRUCT, RUNTIME_DIAGNOSTIC_FLAG_STRUCT, RUNTIME_EXPERIMENTAL_FLAG_STRUCT, RUNTIME_NOTPRODUCT_FLAG_STRUCT, RUNTIME_MANAGEABLE_FLAG_STRUCT, RUNTIME_PRODUCT_RW_FLAG_STRUCT)
+ G1_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, \
+          RUNTIME_PD_DEVELOP_FLAG_STRUCT, \
+          RUNTIME_PRODUCT_FLAG_STRUCT, \
+          RUNTIME_PD_PRODUCT_FLAG_STRUCT, \
+          RUNTIME_DIAGNOSTIC_FLAG_STRUCT, \
+          RUNTIME_EXPERIMENTAL_FLAG_STRUCT, \
+          RUNTIME_NOTPRODUCT_FLAG_STRUCT, \
+          RUNTIME_MANAGEABLE_FLAG_STRUCT, \
+          RUNTIME_PRODUCT_RW_FLAG_STRUCT, \
+          IGNORE_RANGE, \
+          IGNORE_CONSTRAINT)
 #endif // INCLUDE_ALL_GCS
 #ifdef COMPILER1
- C1_FLAGS(C1_DEVELOP_FLAG_STRUCT, C1_PD_DEVELOP_FLAG_STRUCT, C1_PRODUCT_FLAG_STRUCT, C1_PD_PRODUCT_FLAG_STRUCT, C1_DIAGNOSTIC_FLAG_STRUCT, C1_NOTPRODUCT_FLAG_STRUCT)
-#endif
+ C1_FLAGS(C1_DEVELOP_FLAG_STRUCT, \
+          C1_PD_DEVELOP_FLAG_STRUCT, \
+          C1_PRODUCT_FLAG_STRUCT, \
+          C1_PD_PRODUCT_FLAG_STRUCT, \
+          C1_DIAGNOSTIC_FLAG_STRUCT, \
+          C1_NOTPRODUCT_FLAG_STRUCT, \
+          IGNORE_RANGE, \
+          IGNORE_CONSTRAINT)
+#endif // COMPILER1
 #ifdef COMPILER2
- C2_FLAGS(C2_DEVELOP_FLAG_STRUCT, C2_PD_DEVELOP_FLAG_STRUCT, C2_PRODUCT_FLAG_STRUCT, C2_PD_PRODUCT_FLAG_STRUCT, C2_DIAGNOSTIC_FLAG_STRUCT, C2_EXPERIMENTAL_FLAG_STRUCT, C2_NOTPRODUCT_FLAG_STRUCT)
-#endif
+ C2_FLAGS(C2_DEVELOP_FLAG_STRUCT, \
+          C2_PD_DEVELOP_FLAG_STRUCT, \
+          C2_PRODUCT_FLAG_STRUCT, \
+          C2_PD_PRODUCT_FLAG_STRUCT, \
+          C2_DIAGNOSTIC_FLAG_STRUCT, \
+          C2_EXPERIMENTAL_FLAG_STRUCT, \
+          C2_NOTPRODUCT_FLAG_STRUCT, \
+          IGNORE_RANGE, \
+          IGNORE_CONSTRAINT)
+#endif // COMPILER2
 #ifdef SHARK
- SHARK_FLAGS(SHARK_DEVELOP_FLAG_STRUCT, SHARK_PD_DEVELOP_FLAG_STRUCT, SHARK_PRODUCT_FLAG_STRUCT, SHARK_PD_PRODUCT_FLAG_STRUCT, SHARK_DIAGNOSTIC_FLAG_STRUCT, SHARK_NOTPRODUCT_FLAG_STRUCT)
-#endif
- ARCH_FLAGS(ARCH_DEVELOP_FLAG_STRUCT, ARCH_PRODUCT_FLAG_STRUCT, ARCH_DIAGNOSTIC_FLAG_STRUCT, ARCH_EXPERIMENTAL_FLAG_STRUCT, ARCH_NOTPRODUCT_FLAG_STRUCT)
+ SHARK_FLAGS(SHARK_DEVELOP_FLAG_STRUCT, \
+             SHARK_PD_DEVELOP_FLAG_STRUCT, \
+             SHARK_PRODUCT_FLAG_STRUCT, \
+             SHARK_PD_PRODUCT_FLAG_STRUCT, \
+             SHARK_DIAGNOSTIC_FLAG_STRUCT, \
+             SHARK_NOTPRODUCT_FLAG_STRUCT)
+#endif // SHARK
+ ARCH_FLAGS(ARCH_DEVELOP_FLAG_STRUCT, \
+            ARCH_PRODUCT_FLAG_STRUCT, \
+            ARCH_DIAGNOSTIC_FLAG_STRUCT, \
+            ARCH_EXPERIMENTAL_FLAG_STRUCT, \
+            ARCH_NOTPRODUCT_FLAG_STRUCT, \
+            IGNORE_RANGE, \
+            IGNORE_CONSTRAINT)
  FLAGTABLE_EXT
  {0, NULL, NULL}
 };
@@ -566,7 +654,7 @@
       // Found a matching entry.
       // Don't report notproduct and develop flags in product builds.
       if (current->is_constant_in_binary()) {
-        return (return_flag == true ? current : NULL);
+        return (return_flag ? current : NULL);
       }
       // Report locked flags only if allowed.
       if (!(current->is_unlocked() || current->is_unlocker())) {
@@ -661,8 +749,7 @@
 }
 
 template<class E, class T>
-static void trace_flag_changed(const char* name, const T old_value, const T new_value, const Flag::Flags origin)
-{
+static void trace_flag_changed(const char* name, const T old_value, const T new_value, const Flag::Flags origin) {
   E e;
   e.set_name(name);
   e.set_old_value(old_value);
@@ -671,242 +758,395 @@
   e.commit();
 }
 
-bool CommandLineFlags::boolAt(const char* name, size_t len, bool* value, bool allow_locked, bool return_flag) {
-  Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
-  if (result == NULL) return false;
-  if (!result->is_bool()) return false;
-  *value = result->get_bool();
-  return true;
+static Flag::Error get_status_error(Flag::Error status_range, Flag::Error status_constraint) {
+  if (status_range != Flag::SUCCESS) {
+    return status_range;
+  } else if (status_constraint != Flag::SUCCESS) {
+    return status_constraint;
+  } else {
+    return Flag::SUCCESS;
+  }
 }
 
-bool CommandLineFlags::boolAtPut(const char* name, size_t len, bool* value, Flag::Flags origin) {
+static Flag::Error apply_constraint_and_check_range_bool(const char* name, bool* new_value, bool verbose = true) {
+  Flag::Error status = Flag::SUCCESS;
+  CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find(name);
+  if (constraint != NULL) {
+    status = constraint->apply_bool(new_value, verbose);
+  }
+  return status;
+}
+
+Flag::Error CommandLineFlags::boolAt(const char* name, size_t len, bool* value, bool allow_locked, bool return_flag) {
+  Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
+  if (result == NULL) return Flag::INVALID_FLAG;
+  if (!result->is_bool()) return Flag::WRONG_FORMAT;
+  *value = result->get_bool();
+  return Flag::SUCCESS;
+}
+
+Flag::Error CommandLineFlags::boolAtPut(const char* name, size_t len, bool* value, Flag::Flags origin) {
   Flag* result = Flag::find_flag(name, len);
-  if (result == NULL) return false;
-  if (!result->is_bool()) return false;
+  if (result == NULL) return Flag::INVALID_FLAG;
+  if (!result->is_bool()) return Flag::WRONG_FORMAT;
+  Flag::Error check = apply_constraint_and_check_range_bool(name, value, !CommandLineFlags::finishedInitializing());
+  if (check != Flag::SUCCESS) return check;
   bool old_value = result->get_bool();
   trace_flag_changed<EventBooleanFlagChanged, bool>(name, old_value, *value, origin);
   result->set_bool(*value);
   *value = old_value;
   result->set_origin(origin);
-  return true;
+  return Flag::SUCCESS;
 }
 
-void CommandLineFlagsEx::boolAtPut(CommandLineFlagWithType flag, bool value, Flag::Flags origin) {
+Flag::Error CommandLineFlagsEx::boolAtPut(CommandLineFlagWithType flag, bool value, Flag::Flags origin) {
   Flag* faddr = address_of_flag(flag);
   guarantee(faddr != NULL && faddr->is_bool(), "wrong flag type");
+  Flag::Error check = apply_constraint_and_check_range_bool(faddr->_name, &value);
+  if (check != Flag::SUCCESS) return check;
   trace_flag_changed<EventBooleanFlagChanged, bool>(faddr->_name, faddr->get_bool(), value, origin);
   faddr->set_bool(value);
   faddr->set_origin(origin);
+  return Flag::SUCCESS;
 }
 
-bool CommandLineFlags::intAt(const char* name, size_t len, int* value, bool allow_locked, bool return_flag) {
-  Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
-  if (result == NULL) return false;
-  if (!result->is_int()) return false;
-  *value = result->get_int();
-  return true;
+static Flag::Error apply_constraint_and_check_range_int(const char* name, int* new_value, bool verbose = true) {
+  Flag::Error range_status = Flag::SUCCESS;
+  CommandLineFlagRange* range = CommandLineFlagRangeList::find(name);
+  if (range != NULL) {
+    range_status = range->check_int(*new_value, verbose);
+  }
+  Flag::Error constraint_status = Flag::SUCCESS;
+  CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find(name);
+  if (constraint != NULL) {
+    constraint_status = constraint->apply_int(new_value, verbose);
+  }
+  return get_status_error(range_status, constraint_status);
 }
 
-bool CommandLineFlags::intAtPut(const char* name, size_t len, int* value, Flag::Flags origin) {
+Flag::Error CommandLineFlags::intAt(const char* name, size_t len, int* value, bool allow_locked, bool return_flag) {
+  Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
+  if (result == NULL) return Flag::INVALID_FLAG;
+  if (!result->is_int()) return Flag::WRONG_FORMAT;
+  *value = result->get_int();
+  return Flag::SUCCESS;
+}
+
+Flag::Error CommandLineFlags::intAtPut(const char* name, size_t len, int* value, Flag::Flags origin) {
   Flag* result = Flag::find_flag(name, len);
-  if (result == NULL) return false;
-  if (!result->is_int()) return false;
+  if (result == NULL) return Flag::INVALID_FLAG;
+  if (!result->is_int()) return Flag::WRONG_FORMAT;
+  Flag::Error check = apply_constraint_and_check_range_int(name, value, !CommandLineFlags::finishedInitializing());
+  if (check != Flag::SUCCESS) return check;
   int old_value = result->get_int();
   trace_flag_changed<EventIntFlagChanged, s4>(name, old_value, *value, origin);
   result->set_int(*value);
   *value = old_value;
   result->set_origin(origin);
-  return true;
+  return Flag::SUCCESS;
 }
 
-void CommandLineFlagsEx::intAtPut(CommandLineFlagWithType flag, int value, Flag::Flags origin) {
+Flag::Error CommandLineFlagsEx::intAtPut(CommandLineFlagWithType flag, int value, Flag::Flags origin) {
   Flag* faddr = address_of_flag(flag);
   guarantee(faddr != NULL && faddr->is_int(), "wrong flag type");
   trace_flag_changed<EventIntFlagChanged, s4>(faddr->_name, faddr->get_int(), value, origin);
   faddr->set_int(value);
   faddr->set_origin(origin);
+  return Flag::SUCCESS;
 }
 
-bool CommandLineFlags::uintAt(const char* name, size_t len, uint* value, bool allow_locked, bool return_flag) {
-  Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
-  if (result == NULL) return false;
-  if (!result->is_uint()) return false;
-  *value = result->get_uint();
-  return true;
+static Flag::Error apply_constraint_and_check_range_uint(const char* name, uint* new_value, bool verbose = true) {
+  Flag::Error range_status = Flag::SUCCESS;
+  CommandLineFlagRange* range = CommandLineFlagRangeList::find(name);
+  if (range != NULL) {
+    range_status = range->check_uint(*new_value, verbose);
+  }
+  Flag::Error constraint_status = Flag::SUCCESS;
+  CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find(name);
+  if (constraint != NULL) {
+    constraint_status = constraint->apply_uint(new_value, verbose);
+  }
+  return get_status_error(range_status, constraint_status);
 }
 
-bool CommandLineFlags::uintAtPut(const char* name, size_t len, uint* value, Flag::Flags origin) {
+Flag::Error CommandLineFlags::uintAt(const char* name, size_t len, uint* value, bool allow_locked, bool return_flag) {
+  Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
+  if (result == NULL) return Flag::INVALID_FLAG;
+  if (!result->is_uint()) return Flag::WRONG_FORMAT;
+  *value = result->get_uint();
+  return Flag::SUCCESS;
+}
+
+Flag::Error CommandLineFlags::uintAtPut(const char* name, size_t len, uint* value, Flag::Flags origin) {
   Flag* result = Flag::find_flag(name, len);
-  if (result == NULL) return false;
-  if (!result->is_uint()) return false;
+  if (result == NULL) return Flag::INVALID_FLAG;
+  if (!result->is_uint()) return Flag::WRONG_FORMAT;
+  Flag::Error check = apply_constraint_and_check_range_uint(name, value, !CommandLineFlags::finishedInitializing());
+  if (check != Flag::SUCCESS) return check;
   uint old_value = result->get_uint();
   trace_flag_changed<EventUnsignedIntFlagChanged, u4>(name, old_value, *value, origin);
   result->set_uint(*value);
   *value = old_value;
   result->set_origin(origin);
-  return true;
+  return Flag::SUCCESS;
 }
 
-void CommandLineFlagsEx::uintAtPut(CommandLineFlagWithType flag, uint value, Flag::Flags origin) {
+Flag::Error CommandLineFlagsEx::uintAtPut(CommandLineFlagWithType flag, uint value, Flag::Flags origin) {
   Flag* faddr = address_of_flag(flag);
   guarantee(faddr != NULL && faddr->is_uint(), "wrong flag type");
   trace_flag_changed<EventUnsignedIntFlagChanged, u4>(faddr->_name, faddr->get_uint(), value, origin);
   faddr->set_uint(value);
   faddr->set_origin(origin);
+  return Flag::SUCCESS;
+}
+
+Flag::Error CommandLineFlags::intxAt(const char* name, size_t len, intx* value, bool allow_locked, bool return_flag) {
+  Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
+  if (result == NULL) return Flag::INVALID_FLAG;
+  if (!result->is_intx()) return Flag::WRONG_FORMAT;
+  *value = result->get_intx();
+  return Flag::SUCCESS;
 }
 
-bool CommandLineFlags::intxAt(const char* name, size_t len, intx* value, bool allow_locked, bool return_flag) {
-  Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
-  if (result == NULL) return false;
-  if (!result->is_intx()) return false;
-  *value = result->get_intx();
-  return true;
+static Flag::Error apply_constraint_and_check_range_intx(const char* name, intx* new_value, bool verbose = true) {
+  Flag::Error range_status = Flag::SUCCESS;
+  CommandLineFlagRange* range = CommandLineFlagRangeList::find(name);
+  if (range != NULL) {
+    range_status = range->check_intx(*new_value, verbose);
+  }
+  Flag::Error constraint_status = Flag::SUCCESS;
+  CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find(name);
+  if (constraint != NULL) {
+    constraint_status = constraint->apply_intx(new_value, verbose);
+  }
+  return get_status_error(range_status, constraint_status);
 }
 
-bool CommandLineFlags::intxAtPut(const char* name, size_t len, intx* value, Flag::Flags origin) {
+Flag::Error CommandLineFlags::intxAtPut(const char* name, size_t len, intx* value, Flag::Flags origin) {
   Flag* result = Flag::find_flag(name, len);
-  if (result == NULL) return false;
-  if (!result->is_intx()) return false;
+  if (result == NULL) return Flag::INVALID_FLAG;
+  if (!result->is_intx()) return Flag::WRONG_FORMAT;
+  Flag::Error check = apply_constraint_and_check_range_intx(name, value, !CommandLineFlags::finishedInitializing());
+  if (check != Flag::SUCCESS) return check;
   intx old_value = result->get_intx();
-  trace_flag_changed<EventLongFlagChanged, s8>(name, old_value, *value, origin);
+  trace_flag_changed<EventLongFlagChanged, intx>(name, old_value, *value, origin);
   result->set_intx(*value);
   *value = old_value;
   result->set_origin(origin);
-  return true;
+  return Flag::SUCCESS;
 }
 
-void CommandLineFlagsEx::intxAtPut(CommandLineFlagWithType flag, intx value, Flag::Flags origin) {
+Flag::Error CommandLineFlagsEx::intxAtPut(CommandLineFlagWithType flag, intx value, Flag::Flags origin) {
   Flag* faddr = address_of_flag(flag);
   guarantee(faddr != NULL && faddr->is_intx(), "wrong flag type");
-  trace_flag_changed<EventLongFlagChanged, s8>(faddr->_name, faddr->get_intx(), value, origin);
+  Flag::Error check = apply_constraint_and_check_range_intx(faddr->_name, &value);
+  if (check != Flag::SUCCESS) return check;
+  trace_flag_changed<EventLongFlagChanged, intx>(faddr->_name, faddr->get_intx(), value, origin);
   faddr->set_intx(value);
   faddr->set_origin(origin);
+  return Flag::SUCCESS;
 }
 
-bool CommandLineFlags::uintxAt(const char* name, size_t len, uintx* value, bool allow_locked, bool return_flag) {
+Flag::Error CommandLineFlags::uintxAt(const char* name, size_t len, uintx* value, bool allow_locked, bool return_flag) {
   Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
-  if (result == NULL) return false;
-  if (!result->is_uintx()) return false;
+  if (result == NULL) return Flag::INVALID_FLAG;
+  if (!result->is_uintx()) return Flag::WRONG_FORMAT;
   *value = result->get_uintx();
-  return true;
+  return Flag::SUCCESS;
 }
 
-bool CommandLineFlags::uintxAtPut(const char* name, size_t len, uintx* value, Flag::Flags origin) {
+static Flag::Error apply_constraint_and_check_range_uintx(const char* name, uintx* new_value, bool verbose = true) {
+  Flag::Error range_status = Flag::SUCCESS;
+  CommandLineFlagRange* range = CommandLineFlagRangeList::find(name);
+  if (range != NULL) {
+    range_status = range->check_uintx(*new_value, verbose);
+  }
+  Flag::Error constraint_status = Flag::SUCCESS;
+  CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find(name);
+  if (constraint != NULL) {
+    constraint_status = constraint->apply_uintx(new_value, verbose);
+  }
+  return get_status_error(range_status, constraint_status);
+}
+
+Flag::Error CommandLineFlags::uintxAtPut(const char* name, size_t len, uintx* value, Flag::Flags origin) {
   Flag* result = Flag::find_flag(name, len);
-  if (result == NULL) return false;
-  if (!result->is_uintx()) return false;
+  if (result == NULL) return Flag::INVALID_FLAG;
+  if (!result->is_uintx()) return Flag::WRONG_FORMAT;
+  Flag::Error check = apply_constraint_and_check_range_uintx(name, value, !CommandLineFlags::finishedInitializing());
+  if (check != Flag::SUCCESS) return check;
   uintx old_value = result->get_uintx();
   trace_flag_changed<EventUnsignedLongFlagChanged, u8>(name, old_value, *value, origin);
   result->set_uintx(*value);
   *value = old_value;
   result->set_origin(origin);
-  return true;
+  return Flag::SUCCESS;
 }
 
-void CommandLineFlagsEx::uintxAtPut(CommandLineFlagWithType flag, uintx value, Flag::Flags origin) {
+Flag::Error CommandLineFlagsEx::uintxAtPut(CommandLineFlagWithType flag, uintx value, Flag::Flags origin) {
   Flag* faddr = address_of_flag(flag);
   guarantee(faddr != NULL && faddr->is_uintx(), "wrong flag type");
+  Flag::Error check = apply_constraint_and_check_range_uintx(faddr->_name, &value);
+  if (check != Flag::SUCCESS) return check;
   trace_flag_changed<EventUnsignedLongFlagChanged, u8>(faddr->_name, faddr->get_uintx(), value, origin);
   faddr->set_uintx(value);
   faddr->set_origin(origin);
+  return Flag::SUCCESS;
+}
+
+Flag::Error CommandLineFlags::uint64_tAt(const char* name, size_t len, uint64_t* value, bool allow_locked, bool return_flag) {
+  Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
+  if (result == NULL) return Flag::INVALID_FLAG;
+  if (!result->is_uint64_t()) return Flag::WRONG_FORMAT;
+  *value = result->get_uint64_t();
+  return Flag::SUCCESS;
 }
 
-bool CommandLineFlags::uint64_tAt(const char* name, size_t len, uint64_t* value, bool allow_locked, bool return_flag) {
-  Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
-  if (result == NULL) return false;
-  if (!result->is_uint64_t()) return false;
-  *value = result->get_uint64_t();
-  return true;
+static Flag::Error apply_constraint_and_check_range_uint64_t(const char* name, uint64_t* new_value, bool verbose = true) {
+  Flag::Error range_status = Flag::SUCCESS;
+  CommandLineFlagRange* range = CommandLineFlagRangeList::find(name);
+  if (range != NULL) {
+    range_status = range->check_uint64_t(*new_value, verbose);
+  }
+  Flag::Error constraint_status = Flag::SUCCESS;
+  CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find(name);
+  if (constraint != NULL) {
+    constraint_status = constraint->apply_uint64_t(new_value, verbose);
+  }
+  return get_status_error(range_status, constraint_status);
 }
 
-bool CommandLineFlags::uint64_tAtPut(const char* name, size_t len, uint64_t* value, Flag::Flags origin) {
+Flag::Error CommandLineFlags::uint64_tAtPut(const char* name, size_t len, uint64_t* value, Flag::Flags origin) {
   Flag* result = Flag::find_flag(name, len);
-  if (result == NULL) return false;
-  if (!result->is_uint64_t()) return false;
+  if (result == NULL) return Flag::INVALID_FLAG;
+  if (!result->is_uint64_t()) return Flag::WRONG_FORMAT;
+  Flag::Error check = apply_constraint_and_check_range_uint64_t(name, value, !CommandLineFlags::finishedInitializing());
+  if (check != Flag::SUCCESS) return check;
   uint64_t old_value = result->get_uint64_t();
   trace_flag_changed<EventUnsignedLongFlagChanged, u8>(name, old_value, *value, origin);
   result->set_uint64_t(*value);
   *value = old_value;
   result->set_origin(origin);
-  return true;
+  return Flag::SUCCESS;
 }
 
-void CommandLineFlagsEx::uint64_tAtPut(CommandLineFlagWithType flag, uint64_t value, Flag::Flags origin) {
+Flag::Error CommandLineFlagsEx::uint64_tAtPut(CommandLineFlagWithType flag, uint64_t value, Flag::Flags origin) {
   Flag* faddr = address_of_flag(flag);
   guarantee(faddr != NULL && faddr->is_uint64_t(), "wrong flag type");
+  Flag::Error check = apply_constraint_and_check_range_uint64_t(faddr->_name, &value);
+  if (check != Flag::SUCCESS) return check;
   trace_flag_changed<EventUnsignedLongFlagChanged, u8>(faddr->_name, faddr->get_uint64_t(), value, origin);
   faddr->set_uint64_t(value);
   faddr->set_origin(origin);
+  return Flag::SUCCESS;
+}
+
+Flag::Error CommandLineFlags::size_tAt(const char* name, size_t len, size_t* value, bool allow_locked, bool return_flag) {
+  Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
+  if (result == NULL) return Flag::INVALID_FLAG;
+  if (!result->is_size_t()) return Flag::WRONG_FORMAT;
+  *value = result->get_size_t();
+  return Flag::SUCCESS;
 }
 
-bool CommandLineFlags::size_tAt(const char* name, size_t len, size_t* value, bool allow_locked, bool return_flag) {
-  Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
-  if (result == NULL) return false;
-  if (!result->is_size_t()) return false;
-  *value = result->get_size_t();
-  return true;
+static Flag::Error apply_constraint_and_check_range_size_t(const char* name, size_t* new_value, bool verbose = true) {
+  Flag::Error range_status = Flag::SUCCESS;
+  CommandLineFlagRange* range = CommandLineFlagRangeList::find(name);
+  if (range != NULL) {
+    range_status = range->check_size_t(*new_value, verbose);
+  }
+  Flag::Error constraint_status = Flag::SUCCESS;
+  CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find(name);
+  if (constraint != NULL) {
+    constraint_status = constraint->apply_size_t(new_value, verbose);
+  }
+  return get_status_error(range_status, constraint_status);
 }
 
-bool CommandLineFlags::size_tAtPut(const char* name, size_t len, size_t* value, Flag::Flags origin) {
+Flag::Error CommandLineFlags::size_tAtPut(const char* name, size_t len, size_t* value, Flag::Flags origin) {
   Flag* result = Flag::find_flag(name, len);
-  if (result == NULL) return false;
-  if (!result->is_size_t()) return false;
+  if (result == NULL) return Flag::INVALID_FLAG;
+  if (!result->is_size_t()) return Flag::WRONG_FORMAT;
+  Flag::Error check = apply_constraint_and_check_range_size_t(name, value, !CommandLineFlags::finishedInitializing());
+  if (check != Flag::SUCCESS) return check;
   size_t old_value = result->get_size_t();
   trace_flag_changed<EventUnsignedLongFlagChanged, u8>(name, old_value, *value, origin);
   result->set_size_t(*value);
   *value = old_value;
   result->set_origin(origin);
-  return true;
+  return Flag::SUCCESS;
 }
 
-void CommandLineFlagsEx::size_tAtPut(CommandLineFlagWithType flag, size_t value, Flag::Flags origin) {
+Flag::Error CommandLineFlagsEx::size_tAtPut(CommandLineFlagWithType flag, size_t value, Flag::Flags origin) {
   Flag* faddr = address_of_flag(flag);
   guarantee(faddr != NULL && faddr->is_size_t(), "wrong flag type");
+  Flag::Error check = apply_constraint_and_check_range_size_t(faddr->_name, &value);
+  if (check != Flag::SUCCESS) return check;
   trace_flag_changed<EventUnsignedLongFlagChanged, u8>(faddr->_name, faddr->get_size_t(), value, origin);
   faddr->set_size_t(value);
   faddr->set_origin(origin);
+  return Flag::SUCCESS;
+}
+
+Flag::Error CommandLineFlags::doubleAt(const char* name, size_t len, double* value, bool allow_locked, bool return_flag) {
+  Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
+  if (result == NULL) return Flag::INVALID_FLAG;
+  if (!result->is_double()) return Flag::WRONG_FORMAT;
+  *value = result->get_double();
+  return Flag::SUCCESS;
 }
 
-bool CommandLineFlags::doubleAt(const char* name, size_t len, double* value, bool allow_locked, bool return_flag) {
-  Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
-  if (result == NULL) return false;
-  if (!result->is_double()) return false;
-  *value = result->get_double();
-  return true;
+static Flag::Error apply_constraint_and_check_range_double(const char* name, double* new_value, bool verbose = true) {
+  Flag::Error range_status = Flag::SUCCESS;
+  CommandLineFlagRange* range = CommandLineFlagRangeList::find(name);
+  if (range != NULL) {
+    range_status = range->check_double(*new_value, verbose);
+  }
+  Flag::Error constraint_status = Flag::SUCCESS;
+  CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find(name);
+  if (constraint != NULL) {
+    constraint_status = constraint->apply_double(new_value, verbose);
+  }
+  return get_status_error(range_status, constraint_status);
 }
 
-bool CommandLineFlags::doubleAtPut(const char* name, size_t len, double* value, Flag::Flags origin) {
+Flag::Error CommandLineFlags::doubleAtPut(const char* name, size_t len, double* value, Flag::Flags origin) {
   Flag* result = Flag::find_flag(name, len);
-  if (result == NULL) return false;
-  if (!result->is_double()) return false;
+  if (result == NULL) return Flag::INVALID_FLAG;
+  if (!result->is_double()) return Flag::WRONG_FORMAT;
+  Flag::Error check = apply_constraint_and_check_range_double(name, value, !CommandLineFlags::finishedInitializing());
+  if (check != Flag::SUCCESS) return check;
   double old_value = result->get_double();
   trace_flag_changed<EventDoubleFlagChanged, double>(name, old_value, *value, origin);
   result->set_double(*value);
   *value = old_value;
   result->set_origin(origin);
-  return true;
+  return Flag::SUCCESS;
 }
 
-void CommandLineFlagsEx::doubleAtPut(CommandLineFlagWithType flag, double value, Flag::Flags origin) {
+Flag::Error CommandLineFlagsEx::doubleAtPut(CommandLineFlagWithType flag, double value, Flag::Flags origin) {
   Flag* faddr = address_of_flag(flag);
   guarantee(faddr != NULL && faddr->is_double(), "wrong flag type");
+  Flag::Error check = apply_constraint_and_check_range_double(faddr->_name, &value, !CommandLineFlags::finishedInitializing());
+  if (check != Flag::SUCCESS) return check;
   trace_flag_changed<EventDoubleFlagChanged, double>(faddr->_name, faddr->get_double(), value, origin);
   faddr->set_double(value);
   faddr->set_origin(origin);
+  return Flag::SUCCESS;
 }
 
-bool CommandLineFlags::ccstrAt(const char* name, size_t len, ccstr* value, bool allow_locked, bool return_flag) {
+Flag::Error CommandLineFlags::ccstrAt(const char* name, size_t len, ccstr* value, bool allow_locked, bool return_flag) {
   Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
-  if (result == NULL) return false;
-  if (!result->is_ccstr()) return false;
+  if (result == NULL) return Flag::INVALID_FLAG;
+  if (!result->is_ccstr()) return Flag::WRONG_FORMAT;
   *value = result->get_ccstr();
-  return true;
+  return Flag::SUCCESS;
 }
 
-bool CommandLineFlags::ccstrAtPut(const char* name, size_t len, ccstr* value, Flag::Flags origin) {
+Flag::Error CommandLineFlags::ccstrAtPut(const char* name, size_t len, ccstr* value, Flag::Flags origin) {
   Flag* result = Flag::find_flag(name, len);
-  if (result == NULL) return false;
-  if (!result->is_ccstr()) return false;
+  if (result == NULL) return Flag::INVALID_FLAG;
+  if (!result->is_ccstr()) return Flag::WRONG_FORMAT;
   ccstr old_value = result->get_ccstr();
   trace_flag_changed<EventStringFlagChanged, const char*>(name, old_value, *value, origin);
   char* new_value = NULL;
@@ -920,10 +1160,10 @@
   }
   *value = old_value;
   result->set_origin(origin);
-  return true;
+  return Flag::SUCCESS;
 }
 
-void CommandLineFlagsEx::ccstrAtPut(CommandLineFlagWithType flag, ccstr value, Flag::Flags origin) {
+Flag::Error CommandLineFlagsEx::ccstrAtPut(CommandLineFlagWithType flag, ccstr value, Flag::Flags origin) {
   Flag* faddr = address_of_flag(flag);
   guarantee(faddr != NULL && faddr->is_ccstr(), "wrong flag type");
   ccstr old_value = faddr->get_ccstr();
@@ -935,6 +1175,7 @@
     FREE_C_HEAP_ARRAY(char, old_value);
   }
   faddr->set_origin(origin);
+  return Flag::SUCCESS;
 }
 
 extern "C" {
@@ -969,16 +1210,140 @@
   FREE_C_HEAP_ARRAY(Flag*, array);
 }
 
+bool CommandLineFlags::_finished_initializing = false;
+
+bool CommandLineFlags::check_all_ranges_and_constraints() {
+
+//#define PRINT_RANGES_AND_CONSTRAINTS_SIZES
+#ifdef PRINT_RANGES_AND_CONSTRAINTS_SIZES
+  {
+    size_t size_ranges = sizeof(CommandLineFlagRangeList);
+    for (int i=0; i<CommandLineFlagRangeList::length(); i++) {
+      size_ranges += sizeof(CommandLineFlagRange);
+      CommandLineFlagRange* range = CommandLineFlagRangeList::at(i);
+      const char* name = range->name();
+      Flag* flag = Flag::find_flag(name, strlen(name), true, true);
+      if (flag->is_intx()) {
+        size_ranges += 2*sizeof(intx);
+        size_ranges += sizeof(CommandLineFlagRange*);
+      } else if (flag->is_uintx()) {
+        size_ranges += 2*sizeof(uintx);
+        size_ranges += sizeof(CommandLineFlagRange*);
+      } else if (flag->is_uint64_t()) {
+        size_ranges += 2*sizeof(uint64_t);
+        size_ranges += sizeof(CommandLineFlagRange*);
+      } else if (flag->is_size_t()) {
+        size_ranges += 2*sizeof(size_t);
+        size_ranges += sizeof(CommandLineFlagRange*);
+      } else if (flag->is_double()) {
+        size_ranges += 2*sizeof(double);
+        size_ranges += sizeof(CommandLineFlagRange*);
+      }
+    }
+    fprintf(stderr, "Size of %d ranges: "SIZE_FORMAT" bytes\n",
+            CommandLineFlagRangeList::length(), size_ranges);
+  }
+  {
+    size_t size_constraints = sizeof(CommandLineFlagConstraintList);
+    for (int i=0; i<CommandLineFlagConstraintList::length(); i++) {
+      size_constraints += sizeof(CommandLineFlagConstraint);
+      CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::at(i);
+      const char* name = constraint->name();
+      Flag* flag = Flag::find_flag(name, strlen(name), true, true);
+      if (flag->is_bool()) {
+        size_constraints += sizeof(CommandLineFlagConstraintFunc_bool);
+        size_constraints += sizeof(CommandLineFlagConstraint*);
+      } else if (flag->is_intx()) {
+        size_constraints += sizeof(CommandLineFlagConstraintFunc_intx);
+        size_constraints += sizeof(CommandLineFlagConstraint*);
+      } else if (flag->is_uintx()) {
+        size_constraints += sizeof(CommandLineFlagConstraintFunc_uintx);
+        size_constraints += sizeof(CommandLineFlagConstraint*);
+      } else if (flag->is_uint64_t()) {
+        size_constraints += sizeof(CommandLineFlagConstraintFunc_uint64_t);
+        size_constraints += sizeof(CommandLineFlagConstraint*);
+      } else if (flag->is_size_t()) {
+        size_constraints += sizeof(CommandLineFlagConstraintFunc_size_t);
+        size_constraints += sizeof(CommandLineFlagConstraint*);
+      } else if (flag->is_double()) {
+        size_constraints += sizeof(CommandLineFlagConstraintFunc_double);
+        size_constraints += sizeof(CommandLineFlagConstraint*);
+      }
+    }
+    fprintf(stderr, "Size of %d constraints: "SIZE_FORMAT" bytes\n",
+            CommandLineFlagConstraintList::length(), size_constraints);
+  }
+#endif // PRINT_RANGES_AND_CONSTRAINTS_SIZES
+
+  _finished_initializing = true;
+
+  bool status = true;
+  for (int i=0; i<CommandLineFlagRangeList::length(); i++) {
+    CommandLineFlagRange* range = CommandLineFlagRangeList::at(i);
+    const char* name = range->name();
+    Flag* flag = Flag::find_flag(name, strlen(name), true, true);
+    if (flag != NULL) {
+      if (flag->is_intx()) {
+        intx value = flag->get_intx();
+        if (range->check_intx(value, true) != Flag::SUCCESS) status = false;
+      } else if (flag->is_uintx()) {
+        uintx value = flag->get_uintx();
+        if (range->check_uintx(value, true) != Flag::SUCCESS) status = false;
+      } else if (flag->is_uint64_t()) {
+        uint64_t value = flag->get_uint64_t();
+        if (range->check_uint64_t(value, true) != Flag::SUCCESS) status = false;
+      } else if (flag->is_size_t()) {
+        size_t value = flag->get_size_t();
+        if (range->check_size_t(value, true) != Flag::SUCCESS) status = false;
+      } else if (flag->is_double()) {
+        double value = flag->get_double();
+        if (range->check_double(value, true) != Flag::SUCCESS) status = false;
+      }
+    }
+  }
+  for (int i=0; i<CommandLineFlagConstraintList::length(); i++) {
+    CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::at(i);
+    const char*name = constraint->name();
+    Flag* flag = Flag::find_flag(name, strlen(name), true, true);
+    if (flag != NULL) {
+      if (flag->is_bool()) {
+        bool value = flag->get_bool();
+        if (constraint->apply_bool(&value, true) != Flag::SUCCESS) status = false;
+      } else if (flag->is_intx()) {
+        intx value = flag->get_intx();
+        if (constraint->apply_intx(&value, true) != Flag::SUCCESS) status = false;
+      } else if (flag->is_uintx()) {
+        uintx value = flag->get_uintx();
+        if (constraint->apply_uintx(&value, true) != Flag::SUCCESS) status = false;
+      } else if (flag->is_uint64_t()) {
+        uint64_t value = flag->get_uint64_t();
+        if (constraint->apply_uint64_t(&value, true) != Flag::SUCCESS) status = false;
+      } else if (flag->is_size_t()) {
+        size_t value = flag->get_size_t();
+        if (constraint->apply_size_t(&value, true) != Flag::SUCCESS) status = false;
+      } else if (flag->is_double()) {
+        double value = flag->get_double();
+        if (constraint->apply_double(&value, true) != Flag::SUCCESS) status = false;
+      }
+    }
+  }
+
+  Arguments::post_final_range_and_constraint_check(status);
+
+  return status;
+}
+
 #ifndef PRODUCT
 
-
 void CommandLineFlags::verify() {
   assert(Arguments::check_vm_args_consistency(), "Some flag settings conflict");
 }
 
 #endif // PRODUCT
 
-void CommandLineFlags::printFlags(outputStream* out, bool withComments) {
+#define ONLY_PRINT_PRODUCT_FLAGS
+
+void CommandLineFlags::printFlags(outputStream* out, bool withComments, bool printRanges) {
   // Print the flags sorted by name
   // note: this method is called before the thread structure is in place
   //       which means resource allocation cannot be used.
@@ -994,10 +1359,18 @@
   qsort(array, length, sizeof(Flag*), compare_flags);
 
   // Print
-  out->print_cr("[Global flags]");
+  if (!printRanges) {
+    out->print_cr("[Global flags]");
+  } else {
+    out->print_cr("[Global flags ranges]");
+  }
+
   for (size_t i = 0; i < length; i++) {
     if (array[i]->is_unlocked()) {
-      array[i]->print_on(out, withComments);
+#ifdef ONLY_PRINT_PRODUCT_FLAGS
+      if (!array[i]->is_notproduct() && !array[i]->is_develop())
+#endif // ONLY_PRINT_PRODUCT_FLAGS
+      array[i]->print_on(out, withComments, printRanges);
     }
   }
   FREE_C_HEAP_ARRAY(Flag*, array);
--- a/hotspot/src/share/vm/runtime/globals.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/runtime/globals.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -258,6 +258,27 @@
     KIND_MASK = ~VALUE_ORIGIN_MASK
   };
 
+  enum Error {
+    // no error
+    SUCCESS = 0,
+    // flag name is missing
+    MISSING_NAME,
+    // flag value is missing
+    MISSING_VALUE,
+    // error parsing the textual form of the value
+    WRONG_FORMAT,
+    // flag is not writeable
+    NON_WRITABLE,
+    // flag value is outside of its bounds
+    OUT_OF_BOUNDS,
+    // flag value violates its constraint
+    VIOLATES_CONSTRAINT,
+    // there is no flag with the given name
+    INVALID_FLAG,
+    // other, unspecified error related to setting the flag
+    ERR_OTHER
+  };
+
   const char* _type;
   const char* _name;
   void* _addr;
@@ -270,6 +291,7 @@
   // number of flags
   static size_t numFlags;
 
+  static Flag* find_flag(const char* name) { return find_flag(name, strlen(name), true, true); };
   static Flag* find_flag(const char* name, size_t length, bool allow_locked = false, bool return_flag = false);
   static Flag* fuzzy_match(const char* name, size_t length, bool allow_locked = false);
 
@@ -345,9 +367,24 @@
   void get_locked_message(char*, int) const;
   void get_locked_message_ext(char*, int) const;
 
-  void print_on(outputStream* st, bool withComments = false );
+  // printRanges will print out flags type, name and range values as expected by -XX:+PrintFlagsRanges
+  void print_on(outputStream* st, bool withComments = false, bool printRanges = false);
   void print_kind(outputStream* st);
   void print_as_flag(outputStream* st);
+
+  static const char* flag_error_str(Flag::Error error) {
+    switch (error) {
+      case Flag::MISSING_NAME: return "MISSING_NAME";
+      case Flag::MISSING_VALUE: return "MISSING_VALUE";
+      case Flag::NON_WRITABLE: return "NON_WRITABLE";
+      case Flag::OUT_OF_BOUNDS: return "OUT_OF_BOUNDS";
+      case Flag::VIOLATES_CONSTRAINT: return "VIOLATES_CONSTRAINT";
+      case Flag::INVALID_FLAG: return "INVALID_FLAG";
+      case Flag::ERR_OTHER: return "ERR_OTHER";
+      case Flag::SUCCESS: return "SUCCESS";
+      default: return "NULL";
+    }
+  }
 };
 
 // debug flags control various aspects of the VM and are global accessible
@@ -413,59 +450,67 @@
 
 
 class CommandLineFlags {
- public:
-  static bool boolAt(const char* name, size_t len, bool* value, bool allow_locked = false, bool return_flag = false);
-  static bool boolAt(const char* name, bool* value, bool allow_locked = false, bool return_flag = false)      { return boolAt(name, strlen(name), value, allow_locked, return_flag); }
-  static bool boolAtPut(const char* name, size_t len, bool* value, Flag::Flags origin);
-  static bool boolAtPut(const char* name, bool* value, Flag::Flags origin)   { return boolAtPut(name, strlen(name), value, origin); }
+  static bool _finished_initializing;
+public:
+  static Flag::Error boolAt(const char* name, size_t len, bool* value, bool allow_locked = false, bool return_flag = false);
+  static Flag::Error boolAt(const char* name, bool* value, bool allow_locked = false, bool return_flag = false)      { return boolAt(name, strlen(name), value, allow_locked, return_flag); }
+  static Flag::Error boolAtPut(const char* name, size_t len, bool* value, Flag::Flags origin);
+  static Flag::Error boolAtPut(const char* name, bool* value, Flag::Flags origin)   { return boolAtPut(name, strlen(name), value, origin); }
 
-  static bool intAt(const char* name, size_t len, int* value, bool allow_locked = false, bool return_flag = false);
-  static bool intAt(const char* name, int* value, bool allow_locked = false, bool return_flag = false)      { return intAt(name, strlen(name), value, allow_locked, return_flag); }
-  static bool intAtPut(const char* name, size_t len, int* value, Flag::Flags origin);
-  static bool intAtPut(const char* name, int* value, Flag::Flags origin)   { return intAtPut(name, strlen(name), value, origin); }
+  static Flag::Error intAt(const char* name, size_t len, int* value, bool allow_locked = false, bool return_flag = false);
+  static Flag::Error intAt(const char* name, int* value, bool allow_locked = false, bool return_flag = false)      { return intAt(name, strlen(name), value, allow_locked, return_flag); }
+  static Flag::Error intAtPut(const char* name, size_t len, int* value, Flag::Flags origin);
+  static Flag::Error intAtPut(const char* name, int* value, Flag::Flags origin)   { return intAtPut(name, strlen(name), value, origin); }
 
-  static bool uintAt(const char* name, size_t len, uint* value, bool allow_locked = false, bool return_flag = false);
-  static bool uintAt(const char* name, uint* value, bool allow_locked = false, bool return_flag = false)      { return uintAt(name, strlen(name), value, allow_locked, return_flag); }
-  static bool uintAtPut(const char* name, size_t len, uint* value, Flag::Flags origin);
-  static bool uintAtPut(const char* name, uint* value, Flag::Flags origin)   { return uintAtPut(name, strlen(name), value, origin); }
+  static Flag::Error uintAt(const char* name, size_t len, uint* value, bool allow_locked = false, bool return_flag = false);
+  static Flag::Error uintAt(const char* name, uint* value, bool allow_locked = false, bool return_flag = false)      { return uintAt(name, strlen(name), value, allow_locked, return_flag); }
+  static Flag::Error uintAtPut(const char* name, size_t len, uint* value, Flag::Flags origin);
+  static Flag::Error uintAtPut(const char* name, uint* value, Flag::Flags origin)   { return uintAtPut(name, strlen(name), value, origin); }
 
-  static bool intxAt(const char* name, size_t len, intx* value, bool allow_locked = false, bool return_flag = false);
-  static bool intxAt(const char* name, intx* value, bool allow_locked = false, bool return_flag = false)      { return intxAt(name, strlen(name), value, allow_locked, return_flag); }
-  static bool intxAtPut(const char* name, size_t len, intx* value, Flag::Flags origin);
-  static bool intxAtPut(const char* name, intx* value, Flag::Flags origin)   { return intxAtPut(name, strlen(name), value, origin); }
+  static Flag::Error intxAt(const char* name, size_t len, intx* value, bool allow_locked = false, bool return_flag = false);
+  static Flag::Error intxAt(const char* name, intx* value, bool allow_locked = false, bool return_flag = false)      { return intxAt(name, strlen(name), value, allow_locked, return_flag); }
+  static Flag::Error intxAtPut(const char* name, size_t len, intx* value, Flag::Flags origin);
+  static Flag::Error intxAtPut(const char* name, intx* value, Flag::Flags origin)   { return intxAtPut(name, strlen(name), value, origin); }
 
-  static bool uintxAt(const char* name, size_t len, uintx* value, bool allow_locked = false, bool return_flag = false);
-  static bool uintxAt(const char* name, uintx* value, bool allow_locked = false, bool return_flag = false)    { return uintxAt(name, strlen(name), value, allow_locked, return_flag); }
-  static bool uintxAtPut(const char* name, size_t len, uintx* value, Flag::Flags origin);
-  static bool uintxAtPut(const char* name, uintx* value, Flag::Flags origin) { return uintxAtPut(name, strlen(name), value, origin); }
+  static Flag::Error uintxAt(const char* name, size_t len, uintx* value, bool allow_locked = false, bool return_flag = false);
+  static Flag::Error uintxAt(const char* name, uintx* value, bool allow_locked = false, bool return_flag = false)    { return uintxAt(name, strlen(name), value, allow_locked, return_flag); }
+  static Flag::Error uintxAtPut(const char* name, size_t len, uintx* value, Flag::Flags origin);
+  static Flag::Error uintxAtPut(const char* name, uintx* value, Flag::Flags origin) { return uintxAtPut(name, strlen(name), value, origin); }
 
-  static bool size_tAt(const char* name, size_t len, size_t* value, bool allow_locked = false, bool return_flag = false);
-  static bool size_tAt(const char* name, size_t* value, bool allow_locked = false, bool return_flag = false)    { return size_tAt(name, strlen(name), value, allow_locked, return_flag); }
-  static bool size_tAtPut(const char* name, size_t len, size_t* value, Flag::Flags origin);
-  static bool size_tAtPut(const char* name, size_t* value, Flag::Flags origin) { return size_tAtPut(name, strlen(name), value, origin); }
+  static Flag::Error size_tAt(const char* name, size_t len, size_t* value, bool allow_locked = false, bool return_flag = false);
+  static Flag::Error size_tAt(const char* name, size_t* value, bool allow_locked = false, bool return_flag = false)    { return size_tAt(name, strlen(name), value, allow_locked, return_flag); }
+  static Flag::Error size_tAtPut(const char* name, size_t len, size_t* value, Flag::Flags origin);
+  static Flag::Error size_tAtPut(const char* name, size_t* value, Flag::Flags origin) { return size_tAtPut(name, strlen(name), value, origin); }
 
-  static bool uint64_tAt(const char* name, size_t len, uint64_t* value, bool allow_locked = false, bool return_flag = false);
-  static bool uint64_tAt(const char* name, uint64_t* value, bool allow_locked = false, bool return_flag = false) { return uint64_tAt(name, strlen(name), value, allow_locked, return_flag); }
-  static bool uint64_tAtPut(const char* name, size_t len, uint64_t* value, Flag::Flags origin);
-  static bool uint64_tAtPut(const char* name, uint64_t* value, Flag::Flags origin) { return uint64_tAtPut(name, strlen(name), value, origin); }
+  static Flag::Error uint64_tAt(const char* name, size_t len, uint64_t* value, bool allow_locked = false, bool return_flag = false);
+  static Flag::Error uint64_tAt(const char* name, uint64_t* value, bool allow_locked = false, bool return_flag = false) { return uint64_tAt(name, strlen(name), value, allow_locked, return_flag); }
+  static Flag::Error uint64_tAtPut(const char* name, size_t len, uint64_t* value, Flag::Flags origin);
+  static Flag::Error uint64_tAtPut(const char* name, uint64_t* value, Flag::Flags origin) { return uint64_tAtPut(name, strlen(name), value, origin); }
 
-  static bool doubleAt(const char* name, size_t len, double* value, bool allow_locked = false, bool return_flag = false);
-  static bool doubleAt(const char* name, double* value, bool allow_locked = false, bool return_flag = false)    { return doubleAt(name, strlen(name), value, allow_locked, return_flag); }
-  static bool doubleAtPut(const char* name, size_t len, double* value, Flag::Flags origin);
-  static bool doubleAtPut(const char* name, double* value, Flag::Flags origin) { return doubleAtPut(name, strlen(name), value, origin); }
+  static Flag::Error doubleAt(const char* name, size_t len, double* value, bool allow_locked = false, bool return_flag = false);
+  static Flag::Error doubleAt(const char* name, double* value, bool allow_locked = false, bool return_flag = false)    { return doubleAt(name, strlen(name), value, allow_locked, return_flag); }
+  static Flag::Error doubleAtPut(const char* name, size_t len, double* value, Flag::Flags origin);
+  static Flag::Error doubleAtPut(const char* name, double* value, Flag::Flags origin) { return doubleAtPut(name, strlen(name), value, origin); }
 
-  static bool ccstrAt(const char* name, size_t len, ccstr* value, bool allow_locked = false, bool return_flag = false);
-  static bool ccstrAt(const char* name, ccstr* value, bool allow_locked = false, bool return_flag = false)    { return ccstrAt(name, strlen(name), value, allow_locked, return_flag); }
+  static Flag::Error ccstrAt(const char* name, size_t len, ccstr* value, bool allow_locked = false, bool return_flag = false);
+  static Flag::Error ccstrAt(const char* name, ccstr* value, bool allow_locked = false, bool return_flag = false)    { return ccstrAt(name, strlen(name), value, allow_locked, return_flag); }
   // Contract:  Flag will make private copy of the incoming value.
   // Outgoing value is always malloc-ed, and caller MUST call free.
-  static bool ccstrAtPut(const char* name, size_t len, ccstr* value, Flag::Flags origin);
-  static bool ccstrAtPut(const char* name, ccstr* value, Flag::Flags origin) { return ccstrAtPut(name, strlen(name), value, origin); }
+  static Flag::Error ccstrAtPut(const char* name, size_t len, ccstr* value, Flag::Flags origin);
+  static Flag::Error ccstrAtPut(const char* name, ccstr* value, Flag::Flags origin) { return ccstrAtPut(name, strlen(name), value, origin); }
 
   // Returns false if name is not a command line flag.
   static bool wasSetOnCmdline(const char* name, bool* value);
   static void printSetFlags(outputStream* out);
 
-  static void printFlags(outputStream* out, bool withComments);
+  // printRanges will print out flags type, name and range values as expected by -XX:+PrintFlagsRanges
+  static void printFlags(outputStream* out, bool withComments, bool printRanges = false);
+
+  // Returns true if all flags have their final values set (ready for ranges and constraint check)
+  static bool finishedInitializing() { return _finished_initializing; }
+
+  // Check the final values of all flags for ranges and constraints
+  static bool check_all_ranges_and_constraints();
 
   static void verify() PRODUCT_RETURN;
 };
@@ -559,8 +604,15 @@
 //
 // Note that when there is a need to support develop flags to be writeable,
 // it can be done in the same way as product_rw.
+//
+// range is a macro that will expand to min and max arguments for range
+//    checking code if provided - see commandLineFlagRangeList.hpp
+//
+// constraint is a macro that will expand to custom function call
+//    for constraint checking if provided - see commandLineFlagConstraintList.hpp
+//
 
-#define RUNTIME_FLAGS(develop, develop_pd, product, product_pd, diagnostic, experimental, notproduct, manageable, product_rw, lp64_product) \
+#define RUNTIME_FLAGS(develop, develop_pd, product, product_pd, diagnostic, experimental, notproduct, manageable, product_rw, lp64_product, range, constraint) \
                                                                             \
   lp64_product(bool, UseCompressedOops, false,                              \
           "Use 32-bit object references in 64-bit VM. "                     \
@@ -580,19 +632,22 @@
           "Heap allocation steps through preferred address regions to find" \
           " where it can allocate the heap. Number of steps to take per "   \
           "region.")                                                        \
+          range(1, max_uintx)                                               \
                                                                             \
   diagnostic(bool, PrintCompressedOopsMode, false,                          \
           "Print compressed oops base address and encoding mode")           \
                                                                             \
   lp64_product(intx, ObjectAlignmentInBytes, 8,                             \
           "Default object alignment in bytes, 8 is minimum")                \
+          range(8, 256)                                                     \
+          constraint(ObjectAlignmentInBytesConstraintFunc)                  \
                                                                             \
   product(bool, AssumeMP, false,                                            \
           "Instruct the VM to assume multiple processors are available")    \
                                                                             \
-  /* UseMembar is theoretically a temp flag used for memory barrier         \
-   * removal testing.  It was supposed to be removed before FCS but has     \
-   * been re-added (see 6401008) */                                         \
+  /* UseMembar is theoretically a temp flag used for memory barrier      */ \
+  /* removal testing.  It was supposed to be removed before FCS but has  */ \
+  /* been re-added (see 6401008)                                         */ \
   product_pd(bool, UseMembar,                                               \
           "(Unstable) Issues membars on thread state transitions")          \
                                                                             \
@@ -649,6 +704,7 @@
           "Percentage (0-100) used to weight the current sample when "      \
           "computing exponentially decaying average for "                   \
           "AdaptiveNUMAChunkSizing")                                        \
+          range(0, 100)                                                     \
                                                                             \
   product(size_t, NUMASpaceResizeRate, 1*G,                                 \
           "Do not reallocate more than this amount per collection")         \
@@ -841,7 +897,7 @@
           "Die upon failure to reach safepoint (see SafepointTimeout)")     \
                                                                             \
   /* 50 retries * (5 * current_retry_count) millis = ~6.375 seconds */      \
-  /* typically, at most a few retries are needed */                         \
+  /* typically, at most a few retries are needed                    */      \
   product(intx, SuspendRetryCount, 50,                                      \
           "Maximum retry count for an external suspend request")            \
                                                                             \
@@ -862,6 +918,7 @@
                                                                             \
   diagnostic(uintx, LogEventsBufferEntries, 10,                             \
           "Number of ring buffer event logs")                               \
+          range(1, NOT_LP64(1*K) LP64_ONLY(1*M))                            \
                                                                             \
   product(bool, BytecodeVerificationRemote, true,                           \
           "Enable the Java bytecode verifier for remote classes")           \
@@ -1034,6 +1091,7 @@
           "0: do not allow scavengable oops in the code cache; "            \
           "1: allow scavenging from the code cache; "                       \
           "2: emit as many constants as the compiler can see")              \
+          range(0, 2)                                                       \
                                                                             \
   product(bool, AlwaysRestoreFPU, false,                                    \
           "Restore the FPU control word after every JNI call (expensive)")  \
@@ -1307,8 +1365,10 @@
           "Use SSE2 MOVQ instruction for Arraycopy")                        \
                                                                             \
   product(intx, FieldsAllocationStyle, 1,                                   \
-          "0 - type based with oops first, 1 - with oops last, "            \
+          "0 - type based with oops first, "                                \
+          "1 - with oops last, "                                            \
           "2 - oops in super and sub classes are together")                 \
+          range(0, 2)                                                       \
                                                                             \
   product(bool, CompactFields, true,                                        \
           "Allocate nonstatic fields in gaps between previous fields")      \
@@ -1316,8 +1376,14 @@
   notproduct(bool, PrintFieldLayout, false,                                 \
           "Print field layout for each class")                              \
                                                                             \
+  /* Need to limit the extent of the padding to reasonable size.          */\
+  /* 8K is well beyond the reasonable HW cache line size, even with       */\
+  /* aggressive prefetching, while still leaving the room for segregating */\
+  /* among the distinct pages.                                            */\
   product(intx, ContendedPaddingWidth, 128,                                 \
           "How many bytes to pad the fields/classes marked @Contended with")\
+          range(0, 8192)                                                    \
+          constraint(ContendedPaddingWidthConstraintFunc)                   \
                                                                             \
   product(bool, EnableContended, true,                                      \
           "Enable @Contended annotation support")                           \
@@ -1365,7 +1431,7 @@
                                                                             \
   /* This option can change an EMCP method into an obsolete method. */      \
   /* This can affect tests that except specific methods to be EMCP. */      \
-  /* This option should be used with caution. */                            \
+  /* This option should be used with caution.                       */      \
   product(bool, StressLdcRewrite, false,                                    \
           "Force ldc -> ldc_w rewrite during RedefineClasses")              \
                                                                             \
@@ -1479,12 +1545,14 @@
   product(uintx, ParallelOldDeadWoodLimiterMean, 50,                        \
           "The mean used by the parallel compact dead wood "                \
           "limiter (a number between 0-100)")                               \
+          range(0, 100)                                                     \
                                                                             \
   product(uintx, ParallelOldDeadWoodLimiterStdDev, 80,                      \
           "The standard deviation used by the parallel compact dead wood "  \
           "limiter (a number between 0-100)")                               \
-                                                                            \
-  product(uintx, ParallelGCThreads, 0,                                      \
+          range(0, 100)                                                     \
+                                                                            \
+  product(uint, ParallelGCThreads, 0,                                       \
           "Number of parallel threads parallel gc will use")                \
                                                                             \
   product(bool, UseDynamicNumberOfGCThreads, false,                         \
@@ -1498,6 +1566,7 @@
   product(size_t, HeapSizePerGCThread, ScaleForWordSize(64*M),              \
           "Size of heap (bytes) per GC thread used in calculating the "     \
           "number of GC threads")                                           \
+          range((uintx)os::vm_page_size(), max_uintx)                       \
                                                                             \
   product(bool, TraceDynamicGCThreads, false,                               \
           "Trace the dynamic GC thread usage")                              \
@@ -1508,8 +1577,9 @@
                                                                             \
   develop(uintx, ParallelOldGCSplitInterval, 3,                             \
           "How often to provoke splitting a young gen space")               \
-                                                                            \
-  product(uintx, ConcGCThreads, 0,                                          \
+          range(0, max_uintx)                                               \
+                                                                            \
+  product(uint, ConcGCThreads, 0,                                           \
           "Number of threads concurrent gc will use")                       \
                                                                             \
   product(size_t, YoungPLABSize, 4096,                                      \
@@ -1521,6 +1591,7 @@
                                                                             \
   product(uintx, GCTaskTimeStampEntries, 200,                               \
           "Number of time stamp entries per gc worker thread")              \
+          range(1, max_uintx)                                               \
                                                                             \
   product(bool, AlwaysTenure, false,                                        \
           "Always tenure objects in eden (ParallelGC only)")                \
@@ -1554,6 +1625,7 @@
   product(uintx, GCLockerEdenExpansionPercent, 5,                           \
           "How much the GC can expand the eden by while the GC locker "     \
           "is active (as a percentage)")                                    \
+          range(0, 100)                                                     \
                                                                             \
   diagnostic(uintx, GCLockerRetryAllocationCount, 2,                        \
           "Number of times to retry allocations when "                      \
@@ -1579,14 +1651,17 @@
                                                                             \
   product(uintx, ParallelGCBufferWastePct, 10,                              \
           "Wasted fraction of parallel allocation buffer")                  \
+          range(0, 100)                                                     \
                                                                             \
   product(uintx, TargetPLABWastePct, 10,                                    \
           "Target wasted space in last buffer as percent of overall "       \
           "allocation")                                                     \
+          range(1, 100)                                                     \
                                                                             \
   product(uintx, PLABWeight, 75,                                            \
           "Percentage (0-100) used to weight the current sample when "      \
           "computing exponentially decaying average for ResizePLAB")        \
+          range(0, 100)                                                     \
                                                                             \
   product(bool, ResizePLAB, true,                                           \
           "Dynamically resize (survivor space) promotion LAB's")            \
@@ -1597,6 +1672,7 @@
   product(intx, ParGCArrayScanChunk, 50,                                    \
           "Scan a subset of object array and push remainder, if array is "  \
           "bigger than this")                                               \
+          range(1, max_intx)                                                \
                                                                             \
   product(bool, ParGCUseLocalOverflow, false,                               \
           "Instead of a global overflow list, use local overflow stacks")   \
@@ -1618,15 +1694,18 @@
   diagnostic(uintx, ParGCStridesPerThread, 2,                               \
           "The number of strides per worker thread that we divide up the "  \
           "card table scanning work into")                                  \
+          range(1, max_uintx)                                               \
                                                                             \
   diagnostic(intx, ParGCCardsPerStrideChunk, 256,                           \
           "The number of cards in each chunk of the parallel chunks used "  \
           "during card table scanning")                                     \
+          range(1, max_intx)                                                \
                                                                             \
   product(uintx, OldPLABWeight, 50,                                         \
           "Percentage (0-100) used to weight the current sample when "      \
           "computing exponentially decaying average for resizing "          \
           "OldPLABSize")                                                    \
+          range(0, 100)                                                     \
                                                                             \
   product(bool, ResizeOldPLAB, true,                                        \
           "Dynamically resize (old gen) promotion LAB's")                   \
@@ -1634,17 +1713,21 @@
   product(bool, PrintOldPLAB, false,                                        \
           "Print (old gen) promotion LAB's sizing decisions")               \
                                                                             \
+  product(size_t, CMSOldPLABMax, 1024,                                      \
+          "Maximum size of CMS gen promotion LAB caches per worker "        \
+          "per block size")                                                 \
+          range(1, max_uintx)                                               \
+                                                                            \
   product(size_t, CMSOldPLABMin, 16,                                        \
           "Minimum size of CMS gen promotion LAB caches per worker "        \
           "per block size")                                                 \
-                                                                            \
-  product(size_t, CMSOldPLABMax, 1024,                                      \
-          "Maximum size of CMS gen promotion LAB caches per worker "        \
-          "per block size")                                                 \
+          range(1, max_uintx)                                               \
+          constraint(CMSOldPLABMinConstraintFunc)                           \
                                                                             \
   product(uintx, CMSOldPLABNumRefills, 4,                                   \
           "Nominal number of refills of CMS gen promotion LAB cache "       \
           "per worker per block size")                                      \
+          range(1, max_uintx)                                               \
                                                                             \
   product(bool, CMSOldPLABResizeQuicker, false,                             \
           "React on-the-fly during a scavenge to a sudden "                 \
@@ -1653,6 +1736,7 @@
   product(uintx, CMSOldPLABToleranceFactor, 4,                              \
           "The tolerance of the phase-change detector for on-the-fly "      \
           "PLAB resizing during a scavenge")                                \
+          range(1, max_uintx)                                               \
                                                                             \
   product(uintx, CMSOldPLABReactivityFactor, 2,                             \
           "The gain in the feedback loop for on-the-fly PLAB resizing "     \
@@ -1664,19 +1748,23 @@
   product_pd(size_t, CMSYoungGenPerWorker,                                  \
           "The maximum size of young gen chosen by default per GC worker "  \
           "thread available")                                               \
+          range(1, max_uintx)                                               \
                                                                             \
   product(uintx, CMSIncrementalSafetyFactor, 10,                            \
           "Percentage (0-100) used to add conservatism when computing the " \
           "duty cycle")                                                     \
+          range(0, 100)                                                     \
                                                                             \
   product(uintx, CMSExpAvgFactor, 50,                                       \
           "Percentage (0-100) used to weight the current sample when "      \
           "computing exponential averages for CMS statistics")              \
+          range(0, 100)                                                     \
                                                                             \
   product(uintx, CMS_FLSWeight, 75,                                         \
           "Percentage (0-100) used to weight the current sample when "      \
           "computing exponentially decaying averages for CMS FLS "          \
           "statistics")                                                     \
+          range(0, 100)                                                     \
                                                                             \
   product(uintx, CMS_FLSPadding, 1,                                         \
           "The multiple of deviation from mean to use for buffering "       \
@@ -1685,6 +1773,7 @@
   product(uintx, FLSCoalescePolicy, 2,                                      \
           "CMS: aggressiveness level for coalescing, increasing "           \
           "from 0 to 4")                                                    \
+          range(0, 4)                                                       \
                                                                             \
   product(bool, FLSAlwaysCoalesceLarge, false,                              \
           "CMS: larger free blocks are always available for coalescing")    \
@@ -1718,6 +1807,7 @@
           "Percentage (0-100) used to weight the current sample when "      \
           "computing exponentially decaying average for inter-sweep "       \
           "duration")                                                       \
+          range(0, 100)                                                     \
                                                                             \
   product(uintx, CMS_SweepPadding, 1,                                       \
           "The multiple of deviation from mean to use for buffering "       \
@@ -1758,6 +1848,7 @@
                                                                             \
   product(size_t, MarkStackSizeMax, NOT_LP64(4*M) LP64_ONLY(512*M),         \
           "Maximum size of marking stack")                                  \
+          range(1, (max_jint - 1))                                          \
                                                                             \
   notproduct(bool, CMSMarkStackOverflowALot, false,                         \
           "Simulate frequent marking stack / work queue overflow")          \
@@ -1781,9 +1872,11 @@
                                                                             \
   product(size_t, CMSRescanMultiple, 32,                                    \
           "Size (in cards) of CMS parallel rescan task")                    \
+          range(1, max_uintx)                                               \
                                                                             \
   product(size_t, CMSConcMarkMultiple, 32,                                  \
           "Size (in cards) of CMS concurrent MT marking task")              \
+          range(1, max_uintx)                                               \
                                                                             \
   product(bool, CMSAbortSemantics, false,                                   \
           "Whether abort-on-overflow semantics is implemented")             \
@@ -1819,14 +1912,19 @@
                                                                             \
   product(uintx, CMSPrecleanIter, 3,                                        \
           "Maximum number of precleaning iteration passes")                 \
+          range(0, 9)                                                       \
+                                                                            \
+  product(uintx, CMSPrecleanDenominator, 3,                                 \
+          "CMSPrecleanNumerator:CMSPrecleanDenominator yields convergence " \
+          "ratio")                                                          \
+          range(1, max_uintx)                                               \
+          constraint(CMSPrecleanDenominatorConstraintFunc)                  \
                                                                             \
   product(uintx, CMSPrecleanNumerator, 2,                                   \
           "CMSPrecleanNumerator:CMSPrecleanDenominator yields convergence " \
           "ratio")                                                          \
-                                                                            \
-  product(uintx, CMSPrecleanDenominator, 3,                                 \
-          "CMSPrecleanNumerator:CMSPrecleanDenominator yields convergence " \
-          "ratio")                                                          \
+          range(0, max_uintx-1)                                             \
+          constraint(CMSPrecleanNumeratorConstraintFunc)                    \
                                                                             \
   product(bool, CMSPrecleanRefLists1, true,                                 \
           "Preclean ref lists during (initial) preclean phase")             \
@@ -1842,12 +1940,14 @@
                                                                             \
   product(uintx, CMSPrecleanThreshold, 1000,                                \
           "Do not iterate again if number of dirty cards is less than this")\
+          range(100, max_uintx)                                             \
                                                                             \
   product(bool, CMSCleanOnEnter, true,                                      \
           "Clean-on-enter optimization for reducing number of dirty cards") \
                                                                             \
   product(uintx, CMSRemarkVerifyVariant, 1,                                 \
           "Choose variant (1,2) of verification following remark")          \
+          range(1, 2)                                                       \
                                                                             \
   product(size_t, CMSScheduleRemarkEdenSizeThreshold, 2*M,                  \
           "If Eden size is below this, do not try to schedule remark")      \
@@ -1855,14 +1955,17 @@
   product(uintx, CMSScheduleRemarkEdenPenetration, 50,                      \
           "The Eden occupancy percentage (0-100) at which "                 \
           "to try and schedule remark pause")                               \
+          range(0, 100)                                                     \
                                                                             \
   product(uintx, CMSScheduleRemarkSamplingRatio, 5,                         \
           "Start sampling eden top at least before young gen "              \
           "occupancy reaches 1/<ratio> of the size at which "               \
           "we plan to schedule remark")                                     \
+          range(1, max_uintx)                                               \
                                                                             \
   product(uintx, CMSSamplingGrain, 16*K,                                    \
           "The minimum distance between eden samples for CMS (see above)")  \
+          range(1, max_uintx)                                               \
                                                                             \
   product(bool, CMSScavengeBeforeRemark, false,                             \
           "Attempt scavenge before the CMS remark step")                    \
@@ -1886,6 +1989,7 @@
   product(size_t, CMSBitMapYieldQuantum, 10*M,                              \
           "Bitmap operations should process at most this many bits "        \
           "between yields")                                                 \
+          range(1, max_uintx)                                               \
                                                                             \
   product(bool, CMSDumpAtPromotionFailure, false,                           \
           "Dump useful information about the state of the CMS old "         \
@@ -1925,6 +2029,8 @@
   product(intx, RefDiscoveryPolicy, 0,                                      \
           "Select type of reference discovery policy: "                     \
           "reference-based(0) or referent-based(1)")                        \
+          range(ReferenceProcessor::DiscoveryPolicyMin,                     \
+                ReferenceProcessor::DiscoveryPolicyMax)                     \
                                                                             \
   product(bool, ParallelRefProcEnabled, false,                              \
           "Enable parallel reference processing whenever possible")         \
@@ -1935,14 +2041,17 @@
   product(uintx, CMSTriggerRatio, 80,                                       \
           "Percentage of MinHeapFreeRatio in CMS generation that is "       \
           "allocated before a CMS collection cycle commences")              \
+          range(0, 100)                                                     \
                                                                             \
   product(uintx, CMSBootstrapOccupancy, 50,                                 \
           "Percentage CMS generation occupancy at which to "                \
           "initiate CMS collection for bootstrapping collection stats")     \
+          range(0, 100)                                                     \
                                                                             \
   product(intx, CMSInitiatingOccupancyFraction, -1,                         \
           "Percentage CMS generation occupancy to start a CMS collection "  \
           "cycle. A negative value means that CMSTriggerRatio is used")     \
+          range(min_intx, 100)                                              \
                                                                             \
   product(uintx, InitiatingHeapOccupancyPercent, 45,                        \
           "Percentage of the (entire) heap occupancy to start a "           \
@@ -1950,10 +2059,12 @@
           "concurrent GC cycle based on the occupancy of the entire heap, " \
           "not just one of the generations (e.g., G1). A value of 0 "       \
           "denotes 'do constant GC cycles'.")                               \
+          range(0, 100)                                                     \
                                                                             \
   manageable(intx, CMSTriggerInterval, -1,                                  \
           "Commence a CMS collection cycle (at least) every so many "       \
           "milliseconds (0 permanently, -1 disabled)")                      \
+          range(-1, max_intx)                                               \
                                                                             \
   product(bool, UseCMSInitiatingOccupancyOnly, false,                       \
           "Only use occupancy as a criterion for starting a CMS collection")\
@@ -1961,6 +2072,7 @@
   product(uintx, CMSIsTooFullPercentage, 98,                                \
           "An absolute ceiling above which CMS will always consider the "   \
           "unloading of classes when class unloading is enabled")           \
+          range(0, 100)                                                     \
                                                                             \
   develop(bool, CMSTestInFreeList, false,                                   \
           "Check if the coalesced range is already in the "                 \
@@ -2070,17 +2182,21 @@
   product(uintx, MaxRAMFraction, 4,                                         \
           "Maximum fraction (1/n) of real memory used for maximum heap "    \
           "size")                                                           \
+          range(1, max_uintx)                                               \
                                                                             \
   product(uintx, DefaultMaxRAMFraction, 4,                                  \
           "Maximum fraction (1/n) of real memory used for maximum heap "    \
           "size; deprecated: to be renamed to MaxRAMFraction")              \
+          range(1, max_uintx)                                               \
                                                                             \
   product(uintx, MinRAMFraction, 2,                                         \
           "Minimum fraction (1/n) of real memory used for maximum heap "    \
           "size on systems with small physical memory size")                \
+          range(1, max_uintx)                                               \
                                                                             \
   product(uintx, InitialRAMFraction, 64,                                    \
           "Fraction (1/n) of real memory used for initial heap size")       \
+          range(1, max_uintx)                                               \
                                                                             \
   develop(uintx, MaxVirtMemFraction, 2,                                     \
           "Maximum fraction (1/n) of virtual memory used for ergonomically "\
@@ -2139,9 +2255,11 @@
                                                                             \
   product(uintx, AdaptiveSizePolicyWeight, 10,                              \
           "Weight given to exponential resizing, between 0 and 100")        \
+          range(0, 100)                                                     \
                                                                             \
   product(uintx, AdaptiveTimeWeight,       25,                              \
           "Weight given to time in adaptive policy, between 0 and 100")     \
+          range(0, 100)                                                     \
                                                                             \
   product(uintx, PausePadding, 1,                                           \
           "How much buffer to keep for pause time")                         \
@@ -2154,6 +2272,7 @@
                                                                             \
   product(uintx, ThresholdTolerance, 10,                                    \
           "Allowed collection cost difference between generations")         \
+          range(0, 100)                                                     \
                                                                             \
   product(uintx, AdaptiveSizePolicyCollectionCostMargin, 50,                \
           "If collection costs are within margin, reduce both by full "     \
@@ -2161,21 +2280,27 @@
                                                                             \
   product(uintx, YoungGenerationSizeIncrement, 20,                          \
           "Adaptive size percentage change in young generation")            \
+          range(0, 100)                                                     \
                                                                             \
   product(uintx, YoungGenerationSizeSupplement, 80,                         \
           "Supplement to YoungedGenerationSizeIncrement used at startup")   \
+          range(0, 100)                                                     \
                                                                             \
   product(uintx, YoungGenerationSizeSupplementDecay, 8,                     \
           "Decay factor to YoungedGenerationSizeSupplement")                \
+          range(1, max_uintx)                                               \
                                                                             \
   product(uintx, TenuredGenerationSizeIncrement, 20,                        \
           "Adaptive size percentage change in tenured generation")          \
+          range(0, 100)                                                     \
                                                                             \
   product(uintx, TenuredGenerationSizeSupplement, 80,                       \
           "Supplement to TenuredGenerationSizeIncrement used at startup")   \
+          range(0, 100)                                                     \
                                                                             \
   product(uintx, TenuredGenerationSizeSupplementDecay, 2,                   \
           "Decay factor to TenuredGenerationSizeIncrement")                 \
+          range(1, max_uintx)                                               \
                                                                             \
   product(uintx, MaxGCPauseMillis, max_uintx,                               \
           "Adaptive size policy maximum GC pause time goal in millisecond, "\
@@ -2193,6 +2318,7 @@
                                                                             \
   product(uintx, AdaptiveSizeDecrementScaleFactor, 4,                       \
           "Adaptive size scale down factor for shrinking")                  \
+          range(1, max_uintx)                                               \
                                                                             \
   product(bool, UseAdaptiveSizeDecayMajorGCCost, true,                      \
           "Adaptive size decays the major cost for long major intervals")   \
@@ -2216,10 +2342,12 @@
   product(uintx, GCTimeLimit, 98,                                           \
           "Limit of the proportion of time spent in GC before "             \
           "an OutOfMemoryError is thrown (used with GCHeapFreeLimit)")      \
+          range(0, 100)                                                     \
                                                                             \
   product(uintx, GCHeapFreeLimit, 2,                                        \
           "Minimum percentage of free space after a full GC before an "     \
           "OutOfMemoryError is thrown (used with GCTimeLimit)")             \
+          range(0, 100)                                                     \
                                                                             \
   develop(uintx, AdaptiveSizePolicyGCTimeLimitThreshold, 5,                 \
           "Number of consecutive collections before gc time limit fires")   \
@@ -2504,11 +2632,16 @@
                                                                             \
   /* compiler */                                                            \
                                                                             \
+  /* notice: the max range value here is max_jint, not max_intx  */         \
+  /* because of overflow issue                                   */         \
   product(intx, CICompilerCount, CI_COMPILER_COUNT,                         \
           "Number of compiler threads to run")                              \
+          range((intx)Arguments::get_min_number_of_compiler_threads(),      \
+                max_jint)                                                   \
                                                                             \
   product(intx, CompilationPolicyChoice, 0,                                 \
           "which compilation policy (0-3)")                                 \
+          range(0, 3)                                                       \
                                                                             \
   develop(bool, UseStackBanging, true,                                      \
           "use stack banging for stack overflow checks (required for "      \
@@ -2625,6 +2758,9 @@
           "Print all VM flags with default values and descriptions and "    \
           "exit")                                                           \
                                                                             \
+  product(bool, PrintFlagsRanges, false,                                    \
+          "Print VM flags and their ranges and exit VM")                    \
+                                                                            \
   diagnostic(bool, SerializeVMOutput, true,                                 \
           "Use a mutex to serialize output to tty and LogFile")             \
                                                                             \
@@ -2863,6 +2999,7 @@
   product(intx, ProfileMaturityPercentage, 20,                              \
           "number of method invocations/branches (expressed as % of "       \
           "CompileThreshold) before using the method's profile")            \
+          range(0, 100)                                                     \
                                                                             \
   diagnostic(bool, PrintMethodData, false,                                  \
           "Print the results of +ProfileInterpreter at end of run")         \
@@ -2923,6 +3060,7 @@
           "1 = prefetch instructions for each allocation, "                 \
           "2 = use TLAB watermark to gate allocation prefetch, "            \
           "3 = use BIS instruction on Sparc for allocation prefetch")       \
+          range(0, 3)                                                       \
                                                                             \
   product(intx,  AllocatePrefetchDistance, -1,                              \
           "Distance to prefetch ahead of allocation pointer")               \
@@ -2969,6 +3107,7 @@
   product(intx, NmethodSweepActivity, 10,                                   \
           "Removes cold nmethods from code cache if > 0. Higher values "    \
           "result in more aggressive sweeping")                             \
+          range(0, 2000)                                                    \
                                                                             \
   notproduct(bool, LogSweeper, false,                                       \
           "Keep a ring buffer of sweeper activity")                         \
@@ -3097,15 +3236,18 @@
                                                                             \
   product(intx, PerMethodRecompilationCutoff, 400,                          \
           "After recompiling N times, stay in the interpreter (-1=>'Inf')") \
+          range(-1, max_intx)                                               \
                                                                             \
   product(intx, PerBytecodeRecompilationCutoff, 200,                        \
           "Per-BCI limit on repeated recompilation (-1=>'Inf')")            \
+          range(-1, max_intx)                                               \
                                                                             \
   product(intx, PerMethodTrapLimit,  100,                                   \
           "Limit on traps (of one kind) in a method (includes inlines)")    \
                                                                             \
   experimental(intx, PerMethodSpecTrapLimit,  5000,                         \
-          "Limit on speculative traps (of one kind) in a method (includes inlines)") \
+          "Limit on speculative traps (of one kind) in a method "           \
+          "(includes inlines)")                                             \
                                                                             \
   product(intx, PerBytecodeTrapLimit,  4,                                   \
           "Limit on traps (of one kind) at a particular BCI")               \
@@ -3158,15 +3300,21 @@
                                                                             \
   product(size_t, MinTLABSize, 2*K,                                         \
           "Minimum allowed TLAB size (in bytes)")                           \
+          range(1, max_uintx)                                               \
                                                                             \
   product(uintx, TLABAllocationWeight, 35,                                  \
           "Allocation averaging weight")                                    \
-                                                                            \
+          range(0, 100)                                                     \
+                                                                            \
+  /* Limit the lower bound of this flag to 1 as it is used  */              \
+  /* in a division expression.                              */              \
   product(uintx, TLABWasteTargetPercent, 1,                                 \
           "Percentage of Eden that can be wasted")                          \
+          range(1, 100)                                                     \
                                                                             \
   product(uintx, TLABRefillWasteFraction,    64,                            \
           "Maximum TLAB waste at a refill (internal fragmentation)")        \
+          range(1, max_uintx)                                               \
                                                                             \
   product(uintx, TLABWasteIncrement,    4,                                  \
           "Increment allowed waste at slow allocation")                     \
@@ -3190,16 +3338,21 @@
   product(size_t, CompressedClassSpaceSize, 1*G,                            \
           "Maximum size of class area in Metaspace when compressed "        \
           "class pointers are used")                                        \
+          range(1*M, 3*G)                                                   \
                                                                             \
   manageable(uintx, MinHeapFreeRatio, 40,                                   \
           "The minimum percentage of heap free after GC to avoid expansion."\
           " For most GCs this applies to the old generation. In G1 and"     \
           " ParallelGC it applies to the whole heap.")                      \
+          range(0, 100)                                                     \
+          constraint(MinHeapFreeRatioConstraintFunc)                        \
                                                                             \
   manageable(uintx, MaxHeapFreeRatio, 70,                                   \
           "The maximum percentage of heap free after GC to avoid shrinking."\
           " For most GCs this applies to the old generation. In G1 and"     \
           " ParallelGC it applies to the whole heap.")                      \
+          range(0, 100)                                                     \
+          constraint(MaxHeapFreeRatioConstraintFunc)                        \
                                                                             \
   product(intx, SoftRefLRUPolicyMSPerMB, 1000,                              \
           "Number of milliseconds per MB of free space in the heap")        \
@@ -3210,13 +3363,17 @@
   product(size_t, MinMetaspaceExpansion, ScaleForWordSize(256*K),           \
           "The minimum expansion of Metaspace (in bytes)")                  \
                                                                             \
+  product(uintx, MaxMetaspaceFreeRatio,    70,                              \
+          "The maximum percentage of Metaspace free after GC to avoid "     \
+          "shrinking")                                                      \
+          range(0, 100)                                                     \
+          constraint(MaxMetaspaceFreeRatioConstraintFunc)                   \
+                                                                            \
   product(uintx, MinMetaspaceFreeRatio,    40,                              \
           "The minimum percentage of Metaspace free after GC to avoid "     \
           "expansion")                                                      \
-                                                                            \
-  product(uintx, MaxMetaspaceFreeRatio,    70,                              \
-          "The maximum percentage of Metaspace free after GC to avoid "     \
-          "shrinking")                                                      \
+          range(0, 99)                                                      \
+          constraint(MinMetaspaceFreeRatioConstraintFunc)                   \
                                                                             \
   product(size_t, MaxMetaspaceExpansion, ScaleForWordSize(4*M),             \
           "The maximum expansion of Metaspace without full GC (in bytes)")  \
@@ -3233,12 +3390,17 @@
                                                                             \
   product(uintx, MaxTenuringThreshold,    15,                               \
           "Maximum value for tenuring threshold")                           \
+          range(0, markOopDesc::max_age + 1)                                \
+          constraint(MaxTenuringThresholdConstraintFunc)                    \
                                                                             \
   product(uintx, InitialTenuringThreshold,    7,                            \
           "Initial value for tenuring threshold")                           \
+          range(0, markOopDesc::max_age + 1)                                \
+          constraint(InitialTenuringThresholdConstraintFunc)                \
                                                                             \
   product(uintx, TargetSurvivorRatio,    50,                                \
           "Desired percentage of survivor space used after scavenge")       \
+          range(0, 100)                                                     \
                                                                             \
   product(uintx, MarkSweepDeadRatio,     5,                                 \
           "Percentage (0-100) of the old gen allowed as dead wood. "        \
@@ -3249,10 +3411,12 @@
           "generation and treats this as the maximum value when the heap "  \
           "is either completely full or completely empty.  Par compact "    \
           "also has a smaller default value; see arguments.cpp.")           \
+          range(0, 100)                                                     \
                                                                             \
   product(uintx, MarkSweepAlwaysCompactCount,     4,                        \
           "How often should we fully compact the heap (ignoring the dead "  \
           "space parameters)")                                              \
+          range(1, max_uintx)                                               \
                                                                             \
   product(intx, PrintCMSStatistics, 0,                                      \
           "Statistics for CMS")                                             \
@@ -3292,13 +3456,17 @@
   /* stack parameters */                                                    \
   product_pd(intx, StackYellowPages,                                        \
           "Number of yellow zone (recoverable overflows) pages")            \
+          range(1, max_intx)                                                \
                                                                             \
   product_pd(intx, StackRedPages,                                           \
           "Number of red zone (unrecoverable overflows) pages")             \
-                                                                            \
+          range(1, max_intx)                                                \
+                                                                            \
+  /* greater stack shadow pages can't generate instruction to bang stack */ \
   product_pd(intx, StackShadowPages,                                        \
           "Number of shadow zone (for overflow checking) pages "            \
           "this should exceed the depth of the VM and native call stack")   \
+          range(1, 50)                                                      \
                                                                             \
   product_pd(intx, ThreadStackSize,                                         \
           "Thread Stack Size (in Kbytes)")                                  \
@@ -3312,16 +3480,12 @@
   develop_pd(size_t, JVMInvokeMethodSlack,                                  \
           "Stack space (bytes) required for JVM_InvokeMethod to complete")  \
                                                                             \
-  product(size_t, ThreadSafetyMargin, 50*M,                                 \
-          "Thread safety margin is used on fixed-stack LinuxThreads (on "   \
-          "Linux/x86 only) to prevent heap-stack collision. Set to 0 to "   \
-          "disable this feature")                                           \
-                                                                            \
-  /* code cache parameters */                                               \
+  /* code cache parameters                                    */            \
   /* ppc64/tiered compilation has large code-entry alignment. */            \
   develop(uintx, CodeCacheSegmentSize, 64 PPC64_ONLY(+64) NOT_PPC64(TIERED_ONLY(+64)),\
           "Code cache segment size (in bytes) - smallest unit of "          \
           "allocation")                                                     \
+          range(1, 1024)                                                    \
                                                                             \
   develop_pd(intx, CodeEntryAlignment,                                      \
           "Code entry alignment for generated code (in bytes)")             \
@@ -3355,6 +3519,7 @@
                                                                             \
   develop_pd(uintx, CodeCacheMinBlockLength,                                \
           "Minimum number of segments in a code cache block")               \
+          range(1, 100)                                                     \
                                                                             \
   notproduct(bool, ExitOnFullCodeCache, false,                              \
           "Exit the VM if we fill the code cache")                          \
@@ -3366,6 +3531,7 @@
           "Start aggressive sweeping if X[%] of the code cache is free."    \
           "Segmented code cache: X[%] of the non-profiled heap."            \
           "Non-segmented code cache: X[%] of the total code cache")         \
+          range(0, 100)                                                     \
                                                                             \
   /* interpreter debugging */                                               \
   develop(intx, BinarySwitchThreshold, 5,                                   \
@@ -3426,6 +3592,7 @@
           "2 - treat class initializers for application classes as empty; " \
           "3 - allow all class initializers to run during bootstrap but "   \
           "    pretend they are empty after starting replay")               \
+          range(0, 3)                                                       \
                                                                             \
   develop(bool, ReplayIgnoreInitErrors, false,                              \
           "Ignore exceptions thrown during initialization for replay")      \
@@ -3470,6 +3637,7 @@
           "    used with care, as sometimes it can cause performance       "\
           "    degradation in the application and/or the entire system. On "\
           "    Linux this policy requires root privilege.")                 \
+          range(0, 1)                                                       \
                                                                             \
   product(bool, ThreadPriorityVerbose, false,                               \
           "Print priority changes")                                         \
@@ -3653,6 +3821,7 @@
   product(uintx, IncreaseFirstTierCompileThresholdAt, 50,                   \
           "Increase the compile threshold for C1 compilation if the code "  \
           "cache is filled by the specified percentage")                    \
+          range(0, 99)                                                      \
                                                                             \
   product(intx, TieredRateUpdateMinTime, 1,                                 \
           "Minimum rate sampling interval (in milliseconds)")               \
@@ -3673,6 +3842,7 @@
   product(intx, InterpreterProfilePercentage, 33,                           \
           "NON_TIERED number of method invocations/branches (expressed as " \
           "% of CompileThreshold) before profiling in the interpreter")     \
+          range(0, 100)                                                     \
                                                                             \
   develop(intx, MaxRecompilationSearchLength,    10,                        \
           "The maximum number of frames to inspect when searching for "     \
@@ -3752,6 +3922,7 @@
   product(intx, UnguardOnExecutionViolation, 0,                             \
           "Unguard page and retry on no-execute fault (Win32 only) "        \
           "0=off, 1=conservative, 2=aggressive")                            \
+          range(0, 2)                                                       \
                                                                             \
   /* Serviceability Support */                                              \
                                                                             \
@@ -3872,9 +4043,11 @@
                                                                             \
   product(uintx, StringTableSize, defaultStringTableSize,                   \
           "Number of buckets in the interned String table")                 \
+          range(minimumStringTableSize, 111*defaultStringTableSize)         \
                                                                             \
   experimental(uintx, SymbolTableSize, defaultSymbolTableSize,              \
           "Number of buckets in the JVM internal Symbol table")             \
+          range(minimumSymbolTableSize, 111*defaultSymbolTableSize)         \
                                                                             \
   product(bool, UseStringDeduplication, false,                              \
           "Use string deduplication")                                       \
@@ -3885,6 +4058,7 @@
   product(uintx, StringDeduplicationAgeThreshold, 3,                        \
           "A string must reach this age (or be promoted to an old region) " \
           "to be considered for deduplication")                             \
+          range(1, markOopDesc::max_age)                                    \
                                                                             \
   diagnostic(bool, StringDeduplicationResizeALot, false,                    \
           "Force table resize every time the table is scanned")             \
@@ -3906,6 +4080,7 @@
                                                                             \
   experimental(intx, SurvivorAlignmentInBytes, 0,                           \
            "Default survivor space alignment in bytes")                     \
+           constraint(SurvivorAlignmentInBytesConstraintFunc)               \
                                                                             \
   product(bool , AllowNonVirtualCalls, false,                               \
           "Obey the ACC_SUPER flag and allow invokenonvirtual calls")       \
@@ -3963,7 +4138,7 @@
 #define DECLARE_DEVELOPER_FLAG(type, name, value, doc)    extern "C" type name;
 #define DECLARE_PD_DEVELOPER_FLAG(type, name, doc)        extern "C" type name;
 #define DECLARE_NOTPRODUCT_FLAG(type, name, value, doc)   extern "C" type name;
-#endif
+#endif // PRODUCT
 // Special LP64 flags, product only needed for now.
 #ifdef _LP64
 #define DECLARE_LP64_PRODUCT_FLAG(type, name, value, doc) extern "C" type name;
@@ -3986,18 +4161,47 @@
 #define MATERIALIZE_DEVELOPER_FLAG(type, name, value, doc)    type name = value;
 #define MATERIALIZE_PD_DEVELOPER_FLAG(type, name, doc)        type name = pd_##name;
 #define MATERIALIZE_NOTPRODUCT_FLAG(type, name, value, doc)   type name = value;
-#endif
+#endif // PRODUCT
 #ifdef _LP64
 #define MATERIALIZE_LP64_PRODUCT_FLAG(type, name, value, doc) type name = value;
 #else
 #define MATERIALIZE_LP64_PRODUCT_FLAG(type, name, value, doc) /* flag is constant */
 #endif // _LP64
 
-RUNTIME_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_EXPERIMENTAL_FLAG, DECLARE_NOTPRODUCT_FLAG, DECLARE_MANAGEABLE_FLAG, DECLARE_PRODUCT_RW_FLAG, DECLARE_LP64_PRODUCT_FLAG)
+// Only materialize src code for range checking when required, ignore otherwise
+#define IGNORE_RANGE(a, b)
+// Only materialize src code for contraint checking when required, ignore otherwise
+#define IGNORE_CONSTRAINT(func)
 
-RUNTIME_OS_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_NOTPRODUCT_FLAG)
+RUNTIME_FLAGS(DECLARE_DEVELOPER_FLAG, \
+              DECLARE_PD_DEVELOPER_FLAG, \
+              DECLARE_PRODUCT_FLAG, \
+              DECLARE_PD_PRODUCT_FLAG, \
+              DECLARE_DIAGNOSTIC_FLAG, \
+              DECLARE_EXPERIMENTAL_FLAG, \
+              DECLARE_NOTPRODUCT_FLAG, \
+              DECLARE_MANAGEABLE_FLAG, \
+              DECLARE_PRODUCT_RW_FLAG, \
+              DECLARE_LP64_PRODUCT_FLAG, \
+              IGNORE_RANGE, \
+              IGNORE_CONSTRAINT)
 
-ARCH_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_EXPERIMENTAL_FLAG, DECLARE_NOTPRODUCT_FLAG)
+RUNTIME_OS_FLAGS(DECLARE_DEVELOPER_FLAG, \
+                 DECLARE_PD_DEVELOPER_FLAG, \
+                 DECLARE_PRODUCT_FLAG, \
+                 DECLARE_PD_PRODUCT_FLAG, \
+                 DECLARE_DIAGNOSTIC_FLAG, \
+                 DECLARE_NOTPRODUCT_FLAG, \
+                 IGNORE_RANGE, \
+                 IGNORE_CONSTRAINT)
+
+ARCH_FLAGS(DECLARE_DEVELOPER_FLAG, \
+           DECLARE_PRODUCT_FLAG, \
+           DECLARE_DIAGNOSTIC_FLAG, \
+           DECLARE_EXPERIMENTAL_FLAG, \
+           DECLARE_NOTPRODUCT_FLAG, \
+           IGNORE_RANGE, \
+           IGNORE_CONSTRAINT)
 
 // Extensions
 
--- a/hotspot/src/share/vm/runtime/globals_extension.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/runtime/globals_extension.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, 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
@@ -72,18 +72,67 @@
 #define ARCH_NOTPRODUCT_FLAG_MEMBER(type, name, value, doc)      FLAG_MEMBER(name),
 
 typedef enum {
- RUNTIME_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER, RUNTIME_PD_DEVELOP_FLAG_MEMBER, RUNTIME_PRODUCT_FLAG_MEMBER, RUNTIME_PD_PRODUCT_FLAG_MEMBER, RUNTIME_DIAGNOSTIC_FLAG_MEMBER, RUNTIME_EXPERIMENTAL_FLAG_MEMBER, RUNTIME_NOTPRODUCT_FLAG_MEMBER, RUNTIME_MANAGEABLE_FLAG_MEMBER, RUNTIME_PRODUCT_RW_FLAG_MEMBER, RUNTIME_LP64_PRODUCT_FLAG_MEMBER)
- RUNTIME_OS_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER, RUNTIME_PD_DEVELOP_FLAG_MEMBER, RUNTIME_PRODUCT_FLAG_MEMBER, RUNTIME_PD_PRODUCT_FLAG_MEMBER, RUNTIME_DIAGNOSTIC_FLAG_MEMBER, RUNTIME_NOTPRODUCT_FLAG_MEMBER)
+ RUNTIME_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER, \
+               RUNTIME_PD_DEVELOP_FLAG_MEMBER, \
+               RUNTIME_PRODUCT_FLAG_MEMBER, \
+               RUNTIME_PD_PRODUCT_FLAG_MEMBER, \
+               RUNTIME_DIAGNOSTIC_FLAG_MEMBER, \
+               RUNTIME_EXPERIMENTAL_FLAG_MEMBER, \
+               RUNTIME_NOTPRODUCT_FLAG_MEMBER, \
+               RUNTIME_MANAGEABLE_FLAG_MEMBER, \
+               RUNTIME_PRODUCT_RW_FLAG_MEMBER, \
+               RUNTIME_LP64_PRODUCT_FLAG_MEMBER, \
+               IGNORE_RANGE, \
+               IGNORE_CONSTRAINT)
+ RUNTIME_OS_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER, \
+                  RUNTIME_PD_DEVELOP_FLAG_MEMBER, \
+                  RUNTIME_PRODUCT_FLAG_MEMBER, \
+                  RUNTIME_PD_PRODUCT_FLAG_MEMBER, \
+                  RUNTIME_DIAGNOSTIC_FLAG_MEMBER, \
+                  RUNTIME_NOTPRODUCT_FLAG_MEMBER, \
+                  IGNORE_RANGE, \
+                  IGNORE_CONSTRAINT)
 #if INCLUDE_ALL_GCS
- G1_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER, RUNTIME_PD_DEVELOP_FLAG_MEMBER, RUNTIME_PRODUCT_FLAG_MEMBER, RUNTIME_PD_PRODUCT_FLAG_MEMBER, RUNTIME_DIAGNOSTIC_FLAG_MEMBER, RUNTIME_EXPERIMENTAL_FLAG_MEMBER, RUNTIME_NOTPRODUCT_FLAG_MEMBER, RUNTIME_MANAGEABLE_FLAG_MEMBER, RUNTIME_PRODUCT_RW_FLAG_MEMBER)
+ G1_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER, \
+          RUNTIME_PD_DEVELOP_FLAG_MEMBER, \
+          RUNTIME_PRODUCT_FLAG_MEMBER, \
+          RUNTIME_PD_PRODUCT_FLAG_MEMBER, \
+          RUNTIME_DIAGNOSTIC_FLAG_MEMBER, \
+          RUNTIME_EXPERIMENTAL_FLAG_MEMBER, \
+          RUNTIME_NOTPRODUCT_FLAG_MEMBER, \
+          RUNTIME_MANAGEABLE_FLAG_MEMBER, \
+          RUNTIME_PRODUCT_RW_FLAG_MEMBER, \
+          IGNORE_RANGE, \
+          IGNORE_CONSTRAINT)
 #endif // INCLUDE_ALL_GCS
 #ifdef COMPILER1
- C1_FLAGS(C1_DEVELOP_FLAG_MEMBER, C1_PD_DEVELOP_FLAG_MEMBER, C1_PRODUCT_FLAG_MEMBER, C1_PD_PRODUCT_FLAG_MEMBER, C1_DIAGNOSTIC_FLAG_MEMBER, C1_NOTPRODUCT_FLAG_MEMBER)
+ C1_FLAGS(C1_DEVELOP_FLAG_MEMBER, \
+          C1_PD_DEVELOP_FLAG_MEMBER, \
+          C1_PRODUCT_FLAG_MEMBER, \
+          C1_PD_PRODUCT_FLAG_MEMBER, \
+          C1_DIAGNOSTIC_FLAG_MEMBER, \
+          C1_NOTPRODUCT_FLAG_MEMBER, \
+          IGNORE_RANGE, \
+          IGNORE_CONSTRAINT)
 #endif
 #ifdef COMPILER2
- C2_FLAGS(C2_DEVELOP_FLAG_MEMBER, C2_PD_DEVELOP_FLAG_MEMBER, C2_PRODUCT_FLAG_MEMBER, C2_PD_PRODUCT_FLAG_MEMBER, C2_DIAGNOSTIC_FLAG_MEMBER, C2_EXPERIMENTAL_FLAG_MEMBER, C2_NOTPRODUCT_FLAG_MEMBER)
+ C2_FLAGS(C2_DEVELOP_FLAG_MEMBER, \
+          C2_PD_DEVELOP_FLAG_MEMBER, \
+          C2_PRODUCT_FLAG_MEMBER, \
+          C2_PD_PRODUCT_FLAG_MEMBER, \
+          C2_DIAGNOSTIC_FLAG_MEMBER, \
+          C2_EXPERIMENTAL_FLAG_MEMBER, \
+          C2_NOTPRODUCT_FLAG_MEMBER, \
+          IGNORE_RANGE, \
+          IGNORE_CONSTRAINT)
 #endif
- ARCH_FLAGS(ARCH_DEVELOP_FLAG_MEMBER, ARCH_PRODUCT_FLAG_MEMBER, ARCH_DIAGNOSTIC_FLAG_MEMBER, ARCH_EXPERIMENTAL_FLAG_MEMBER, ARCH_NOTPRODUCT_FLAG_MEMBER)
+ ARCH_FLAGS(ARCH_DEVELOP_FLAG_MEMBER, \
+            ARCH_PRODUCT_FLAG_MEMBER, \
+            ARCH_DIAGNOSTIC_FLAG_MEMBER, \
+            ARCH_EXPERIMENTAL_FLAG_MEMBER, \
+            ARCH_NOTPRODUCT_FLAG_MEMBER, \
+            IGNORE_RANGE, \
+            IGNORE_CONSTRAINT)
  COMMANDLINEFLAG_EXT
  NUM_CommandLineFlag
 } CommandLineFlag;
@@ -139,13 +188,17 @@
                RUNTIME_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE,
                RUNTIME_MANAGEABLE_FLAG_MEMBER_WITH_TYPE,
                RUNTIME_PRODUCT_RW_FLAG_MEMBER_WITH_TYPE,
-               RUNTIME_LP64_PRODUCT_FLAG_MEMBER_WITH_TYPE)
+               RUNTIME_LP64_PRODUCT_FLAG_MEMBER_WITH_TYPE,
+               IGNORE_RANGE,
+               IGNORE_CONSTRAINT)
  RUNTIME_OS_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER_WITH_TYPE,
                   RUNTIME_PD_DEVELOP_FLAG_MEMBER_WITH_TYPE,
                   RUNTIME_PRODUCT_FLAG_MEMBER_WITH_TYPE,
                   RUNTIME_PD_PRODUCT_FLAG_MEMBER_WITH_TYPE,
                   RUNTIME_DIAGNOSTIC_FLAG_MEMBER_WITH_TYPE,
-                  RUNTIME_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE)
+                  RUNTIME_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE,
+                  IGNORE_RANGE,
+                  IGNORE_CONSTRAINT)
 #if INCLUDE_ALL_GCS
  G1_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER_WITH_TYPE,
           RUNTIME_PD_DEVELOP_FLAG_MEMBER_WITH_TYPE,
@@ -155,7 +208,9 @@
           RUNTIME_EXPERIMENTAL_FLAG_MEMBER_WITH_TYPE,
           RUNTIME_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE,
           RUNTIME_MANAGEABLE_FLAG_MEMBER_WITH_TYPE,
-          RUNTIME_PRODUCT_RW_FLAG_MEMBER_WITH_TYPE)
+          RUNTIME_PRODUCT_RW_FLAG_MEMBER_WITH_TYPE,
+          IGNORE_RANGE,
+          IGNORE_CONSTRAINT)
 #endif // INCLUDE_ALL_GCS
 #ifdef COMPILER1
  C1_FLAGS(C1_DEVELOP_FLAG_MEMBER_WITH_TYPE,
@@ -163,7 +218,9 @@
           C1_PRODUCT_FLAG_MEMBER_WITH_TYPE,
           C1_PD_PRODUCT_FLAG_MEMBER_WITH_TYPE,
           C1_DIAGNOSTIC_FLAG_MEMBER_WITH_TYPE,
-          C1_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE)
+          C1_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE,
+          IGNORE_RANGE,
+          IGNORE_CONSTRAINT)
 #endif
 #ifdef COMPILER2
  C2_FLAGS(C2_DEVELOP_FLAG_MEMBER_WITH_TYPE,
@@ -172,13 +229,17 @@
           C2_PD_PRODUCT_FLAG_MEMBER_WITH_TYPE,
           C2_DIAGNOSTIC_FLAG_MEMBER_WITH_TYPE,
           C2_EXPERIMENTAL_FLAG_MEMBER_WITH_TYPE,
-          C2_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE)
+          C2_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE,
+          IGNORE_RANGE,
+          IGNORE_CONSTRAINT)
 #endif
  ARCH_FLAGS(ARCH_DEVELOP_FLAG_MEMBER_WITH_TYPE,
           ARCH_PRODUCT_FLAG_MEMBER_WITH_TYPE,
           ARCH_DIAGNOSTIC_FLAG_MEMBER_WITH_TYPE,
           ARCH_EXPERIMENTAL_FLAG_MEMBER_WITH_TYPE,
-          ARCH_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE)
+          ARCH_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE,
+          IGNORE_RANGE,
+          IGNORE_CONSTRAINT)
  COMMANDLINEFLAGWITHTYPE_EXT
  NUM_CommandLineFlagWithType
 } CommandLineFlagWithType;
@@ -196,16 +257,16 @@
 // of a circular dependency on the enum definition.
 class CommandLineFlagsEx : CommandLineFlags {
  public:
-  static void boolAtPut(CommandLineFlagWithType flag, bool value, Flag::Flags origin);
-  static void intAtPut(CommandLineFlagWithType flag, int value, Flag::Flags origin);
-  static void uintAtPut(CommandLineFlagWithType flag, uint value, Flag::Flags origin);
-  static void intxAtPut(CommandLineFlagWithType flag, intx value, Flag::Flags origin);
-  static void uintxAtPut(CommandLineFlagWithType flag, uintx value, Flag::Flags origin);
-  static void uint64_tAtPut(CommandLineFlagWithType flag, uint64_t value, Flag::Flags origin);
-  static void size_tAtPut(CommandLineFlagWithType flag, size_t value, Flag::Flags origin);
-  static void doubleAtPut(CommandLineFlagWithType flag, double value, Flag::Flags origin);
+  static Flag::Error boolAtPut(CommandLineFlagWithType flag, bool value, Flag::Flags origin);
+  static Flag::Error intAtPut(CommandLineFlagWithType flag, int value, Flag::Flags origin);
+  static Flag::Error uintAtPut(CommandLineFlagWithType flag, uint value, Flag::Flags origin);
+  static Flag::Error intxAtPut(CommandLineFlagWithType flag, intx value, Flag::Flags origin);
+  static Flag::Error uintxAtPut(CommandLineFlagWithType flag, uintx value, Flag::Flags origin);
+  static Flag::Error uint64_tAtPut(CommandLineFlagWithType flag, uint64_t value, Flag::Flags origin);
+  static Flag::Error size_tAtPut(CommandLineFlagWithType flag, size_t value, Flag::Flags origin);
+  static Flag::Error doubleAtPut(CommandLineFlagWithType flag, double value, Flag::Flags origin);
   // Contract:  Flag will make private copy of the incoming value
-  static void ccstrAtPut(CommandLineFlagWithType flag, ccstr value, Flag::Flags origin);
+  static Flag::Error ccstrAtPut(CommandLineFlagWithType flag, ccstr value, Flag::Flags origin);
 
   static bool is_default(CommandLineFlag flag);
   static bool is_ergo(CommandLineFlag flag);
--- a/hotspot/src/share/vm/runtime/init.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/runtime/init.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -29,6 +29,7 @@
 #include "interpreter/bytecodes.hpp"
 #include "memory/universe.hpp"
 #include "prims/methodHandles.hpp"
+#include "runtime/globals.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/icache.hpp"
 #include "runtime/init.hpp"
@@ -141,8 +142,8 @@
 
   // All the flags that get adjusted by VM_Version_init and os::init_2
   // have been set so dump the flags now.
-  if (PrintFlagsFinal) {
-    CommandLineFlags::printFlags(tty, false);
+  if (PrintFlagsFinal || PrintFlagsRanges) {
+    CommandLineFlags::printFlags(tty, false, PrintFlagsRanges);
   }
 
   return JNI_OK;
--- a/hotspot/src/share/vm/runtime/os.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/runtime/os.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -670,8 +670,8 @@
   }
   // always move the block
   void* ptr = os::malloc(size, memflags, stack);
-  if (PrintMalloc) {
-    tty->print_cr("os::remalloc " SIZE_FORMAT " bytes, " PTR_FORMAT " --> " PTR_FORMAT, size, memblock, ptr);
+  if (PrintMalloc && tty != NULL) {
+    tty->print_cr("os::realloc " SIZE_FORMAT " bytes, " PTR_FORMAT " --> " PTR_FORMAT, size, memblock, ptr);
   }
   // Copy to new memory if malloc didn't fail
   if ( ptr != NULL ) {
@@ -832,7 +832,7 @@
   }
 }
 
-void os::print_cpu_info(outputStream* st) {
+void os::print_cpu_info(outputStream* st, char* buf, size_t buflen) {
   // cpu
   st->print("CPU:");
   st->print("total %d", os::processor_count());
@@ -840,10 +840,10 @@
   // st->print("(active %d)", os::active_processor_count());
   st->print(" %s", VM_Version::cpu_features());
   st->cr();
-  pd_print_cpu_info(st);
+  pd_print_cpu_info(st, buf, buflen);
 }
 
-void os::print_date_and_time(outputStream *st) {
+void os::print_date_and_time(outputStream *st, char* buf, size_t buflen) {
   const int secs_per_day  = 86400;
   const int secs_per_hour = 3600;
   const int secs_per_min  = 60;
@@ -852,6 +852,12 @@
   (void)time(&tloc);
   st->print("time: %s", ctime(&tloc));  // ctime adds newline.
 
+  struct tm tz;
+  if (localtime_pd(&tloc, &tz) != NULL) {
+    ::strftime(buf, buflen, "%Z", &tz);
+    st->print_cr("timezone: %s", buf);
+  }
+
   double t = os::elapsedTime();
   // NOTE: It tends to crash after a SEGV if we want to printf("%f",...) in
   //       Linux. Must be a bug in glibc ? Workaround is to round "t" to int
--- a/hotspot/src/share/vm/runtime/os.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/runtime/os.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -539,7 +539,8 @@
   // If function name is not found, buf[0] is set to '\0' and offset is
   // set to -1 (if offset is non-NULL).
   static bool dll_address_to_function_name(address addr, char* buf,
-                                           int buflen, int* offset);
+                                           int buflen, int* offset,
+                                           bool demangle = true);
 
   // Locate DLL/DSO. On success, full path of the library is copied to
   // buf, and offset is optionally set to be the distance between addr
@@ -587,8 +588,8 @@
   // Output format may be different on different platforms.
   static void print_os_info(outputStream* st);
   static void print_os_info_brief(outputStream* st);
-  static void print_cpu_info(outputStream* st);
-  static void pd_print_cpu_info(outputStream* st);
+  static void print_cpu_info(outputStream* st, char* buf, size_t buflen);
+  static void pd_print_cpu_info(outputStream* st, char* buf, size_t buflen);
   static void print_memory_info(outputStream* st);
   static void print_dll_info(outputStream* st);
   static void print_environment_variables(outputStream* st, const char** env_list);
@@ -596,7 +597,7 @@
   static void print_register_info(outputStream* st, void* context);
   static void print_siginfo(outputStream* st, void* siginfo);
   static void print_signal_handlers(outputStream* st, char* buf, size_t buflen);
-  static void print_date_and_time(outputStream* st);
+  static void print_date_and_time(outputStream* st, char* buf, size_t buflen);
 
   static void print_location(outputStream* st, intptr_t x, bool verbose = false);
   static size_t lasterror(char *buf, size_t len);
--- a/hotspot/src/share/vm/runtime/os_ext.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/runtime/os_ext.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2015 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
@@ -25,7 +25,10 @@
 #ifndef SHARE_VM_RUNTIME_OS_EXT_HPP
 #define SHARE_VM_RUNTIME_OS_EXT_HPP
 
- public:
+#define EMIT_RANGES_FOR_GLOBALS_EXT // NOP
+#define EMIT_CONSTRAINTS_FOR_GLOBALS_EXT // NOP
+
+public:
   static void init_globals_ext() {} // Run from init_globals().
                                     // See os.hpp/cpp and init.cpp.
 
--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -732,6 +732,8 @@
   if (StackTraceInThrowable) {
     java_lang_Throwable::fill_in_stack_trace(exception);
   }
+  // Increment counter for hs_err file reporting
+  Atomic::inc(&Exceptions::_stack_overflow_errors);
   throw_and_post_jvmti_exception(thread, exception);
 JRT_END
 
@@ -2333,15 +2335,6 @@
   // and a single writer: this could be fixed if it becomes a
   // problem).
 
-  // Get the address of the ic_miss handlers before we grab the
-  // AdapterHandlerLibrary_lock. This fixes bug 6236259 which
-  // was caused by the initialization of the stubs happening
-  // while we held the lock and then notifying jvmti while
-  // holding it. This just forces the initialization to be a little
-  // earlier.
-  address ic_miss = SharedRuntime::get_ic_miss_stub();
-  assert(ic_miss != NULL, "must have handler");
-
   ResourceMark rm;
 
   NOT_PRODUCT(int insts_size);
--- a/hotspot/src/share/vm/runtime/signature.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/runtime/signature.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, 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
@@ -63,6 +63,8 @@
   // Fingerprinter.
   enum {
     static_feature_size    = 1,
+    is_static_bit          = 1,
+
     result_feature_size    = 4,
     result_feature_mask    = 0xF,
     parameter_feature_size = 4,
@@ -114,6 +116,15 @@
   // Object types (begin indexes the first character of the entry, end indexes the first character after the entry)
   virtual void do_object(int begin, int end) = 0;
   virtual void do_array (int begin, int end) = 0;
+
+  static bool is_static(uint64_t fingerprint) {
+    assert(fingerprint != (uint64_t)CONST64(-1), "invalid fingerprint");
+    return fingerprint & is_static_bit;
+  }
+  static BasicType return_type(uint64_t fingerprint) {
+    assert(fingerprint != (uint64_t)CONST64(-1), "invalid fingerprint");
+    return (BasicType) ((fingerprint >> static_feature_size) & result_feature_mask);
+  }
 };
 
 
--- a/hotspot/src/share/vm/runtime/stubCodeGenerator.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/runtime/stubCodeGenerator.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -96,7 +96,7 @@
       toprint[toprint_len++] = cdesc;
       if (cdesc == _first_stub) { saw_first = true; break; }
     }
-    assert(saw_first, "must get both first & last");
+    assert(toprint_len == 0 || saw_first, "must get both first & last");
     // Print in reverse order:
     qsort(toprint, toprint_len, sizeof(toprint[0]), compare_cdesc);
     for (int i = 0; i < toprint_len; i++) {
--- a/hotspot/src/share/vm/runtime/sweeper.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/runtime/sweeper.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -678,7 +678,7 @@
       // ReservedCodeCacheSize
       int reset_val = hotness_counter_reset_val();
       int time_since_reset = reset_val - nm->hotness_counter();
-      int code_blob_type = (CodeCache::get_code_blob_type(nm->comp_level()));
+      int code_blob_type = CodeCache::get_code_blob_type(nm);
       double threshold = -reset_val + (CodeCache::reverse_free_ratio(code_blob_type) * NmethodSweepActivity);
       // The less free space in the code cache we have - the bigger reverse_free_ratio() is.
       // I.e., 'threshold' increases with lower available space in the code cache and a higher
--- a/hotspot/src/share/vm/runtime/synchronizer.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/runtime/synchronizer.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "classfile/vmSymbols.hpp"
+#include "memory/metaspaceShared.hpp"
 #include "memory/padded.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/markOop.hpp"
@@ -638,11 +639,11 @@
 
   // hashCode() is a heap mutator ...
   // Relaxing assertion for bug 6320749.
-  assert(Universe::verify_in_progress() ||
+  assert(Universe::verify_in_progress() || DumpSharedSpaces ||
          !SafepointSynchronize::is_at_safepoint(), "invariant");
-  assert(Universe::verify_in_progress() ||
+  assert(Universe::verify_in_progress() || DumpSharedSpaces ||
          Self->is_Java_thread() , "invariant");
-  assert(Universe::verify_in_progress() ||
+  assert(Universe::verify_in_progress() || DumpSharedSpaces ||
          ((JavaThread *)Self)->thread_state() != _thread_blocked, "invariant");
 
   ObjectMonitor* monitor = NULL;
--- a/hotspot/src/share/vm/runtime/thread.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/runtime/thread.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -54,6 +54,7 @@
 #include "runtime/deoptimization.hpp"
 #include "runtime/fprofiler.hpp"
 #include "runtime/frame.inline.hpp"
+#include "runtime/globals.hpp"
 #include "runtime/init.hpp"
 #include "runtime/interfaceSupport.hpp"
 #include "runtime/java.hpp"
@@ -3273,6 +3274,9 @@
 jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
   extern void JDK_Version_init();
 
+  // Preinitialize version info.
+  VM_Version::early_initialize();
+
   // Check version
   if (!is_supported_jni_version(args->version)) return JNI_EVERSION;
 
@@ -3303,6 +3307,11 @@
   jint ergo_result = Arguments::apply_ergo();
   if (ergo_result != JNI_OK) return ergo_result;
 
+  // Final check of all arguments after ergonomics which may change values.
+  if (!CommandLineFlags::check_all_ranges_and_constraints()) {
+    return JNI_EINVAL;
+  }
+
   if (PauseAtStartup) {
     os::pause();
   }
--- a/hotspot/src/share/vm/runtime/timer.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/runtime/timer.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, 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
@@ -59,7 +59,7 @@
 }
 
 jlong elapsedTimer::milliseconds() const {
-  return TimeHelper::counter_to_millis(_counter);
+  return (jlong)TimeHelper::counter_to_millis(_counter);
 }
 
 jlong elapsedTimer::active_ticks() const {
@@ -89,7 +89,7 @@
 jlong TimeStamp::milliseconds() const {
   assert(is_updated(), "must not be clear");
   jlong new_count = os::elapsed_counter();
-  return TimeHelper::counter_to_millis(new_count - _counter);
+  return (jlong)TimeHelper::counter_to_millis(new_count - _counter);
 }
 
 jlong TimeStamp::ticks_since_update() const {
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -545,7 +545,6 @@
                                                                                                                                      \
   nonstatic_field(Generation,                  _reserved,                                     MemRegion)                             \
   nonstatic_field(Generation,                  _virtual_space,                                VirtualSpace)                          \
-  nonstatic_field(Generation,                  _level,                                        int)                                   \
   nonstatic_field(Generation,                  _stat_record,                                  Generation::StatRecord)                \
                                                                                                                                      \
   nonstatic_field(Generation::StatRecord,      invocations,                                   int)                                   \
--- a/hotspot/src/share/vm/runtime/vm_version.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/runtime/vm_version.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -280,7 +280,8 @@
 
 #ifndef PRODUCT
   if (PrintMiscellaneous && Verbose) {
-    os::print_cpu_info(tty);
+    char buf[512];
+    os::print_cpu_info(tty, buf, sizeof(buf));
   }
 #endif
 }
--- a/hotspot/src/share/vm/runtime/vm_version.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/runtime/vm_version.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -58,6 +58,13 @@
  public:
   static void initialize();
 
+  // This allows for early initialization of VM_Version information
+  // that may be needed later in the initialization sequence but before
+  // full VM_Version initialization is possible. It can not depend on any
+  // other part of the VM being initialized when called. Platforms that
+  // need to specialize this define VM_Version::early_initialize().
+  static void early_initialize() { }
+
   // Name
   static const char* vm_name();
   // Vendor
--- a/hotspot/src/share/vm/services/attachListener.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/services/attachListener.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -243,8 +243,8 @@
   FormatBuffer<80> err_msg("%s", "");
 
   int ret = WriteableFlags::set_flag(op->arg(0), op->arg(1), Flag::ATTACH_ON_DEMAND, err_msg);
-  if (ret != WriteableFlags::SUCCESS) {
-    if (ret == WriteableFlags::NON_WRITABLE) {
+  if (ret != Flag::SUCCESS) {
+    if (ret == Flag::NON_WRITABLE) {
       // if the flag is not manageable try to change it through
       // the platform dependent implementation
       return AttachListener::pd_set_flag(op, out);
--- a/hotspot/src/share/vm/services/classLoadingService.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/services/classLoadingService.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, 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
@@ -32,6 +32,7 @@
 #include "services/memoryService.hpp"
 #include "utilities/dtrace.hpp"
 #include "utilities/macros.hpp"
+#include "utilities/defaultStream.hpp"
 
 #ifdef DTRACE_ENABLED
 
@@ -176,13 +177,12 @@
   return class_size * oopSize;
 }
 
-
 bool ClassLoadingService::set_verbose(bool verbose) {
   MutexLocker m(Management_lock);
 
   // verbose will be set to the previous value
-  bool succeed = CommandLineFlags::boolAtPut((char*)"TraceClassLoading", &verbose, Flag::MANAGEMENT);
-  assert(succeed, "Setting TraceClassLoading flag fails");
+  Flag::Error error = CommandLineFlags::boolAtPut("TraceClassLoading", &verbose, Flag::MANAGEMENT);
+  assert(error==Flag::SUCCESS, err_msg("Setting TraceClassLoading flag failed with error %s", Flag::flag_error_str(error)));
   reset_trace_class_unloading();
 
   return verbose;
@@ -192,8 +192,8 @@
 void ClassLoadingService::reset_trace_class_unloading() {
   assert(Management_lock->owned_by_self(), "Must own the Management_lock");
   bool value = MemoryService::get_verbose() || ClassLoadingService::get_verbose();
-  bool succeed = CommandLineFlags::boolAtPut((char*)"TraceClassUnloading", &value, Flag::MANAGEMENT);
-  assert(succeed, "Setting TraceClassUnLoading flag fails");
+  Flag::Error error = CommandLineFlags::boolAtPut("TraceClassUnloading", &value, Flag::MANAGEMENT);
+  assert(error==Flag::SUCCESS, err_msg("Setting TraceClassUnLoading flag failed with error %s", Flag::flag_error_str(error)));
 }
 
 GrowableArray<KlassHandle>* LoadedClassesEnumerator::_loaded_classes = NULL;
--- a/hotspot/src/share/vm/services/diagnosticCommand.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -27,6 +27,7 @@
 #include "classfile/compactHashtable.hpp"
 #include "gc/shared/vmGCOperations.hpp"
 #include "oops/oop.inline.hpp"
+#include "runtime/globals.hpp"
 #include "runtime/javaCalls.hpp"
 #include "runtime/os.hpp"
 #include "services/diagnosticArgument.hpp"
@@ -221,7 +222,7 @@
   FormatBuffer<80> err_msg("%s", "");
   int ret = WriteableFlags::set_flag(_flag.value(), val, Flag::MANAGEMENT, err_msg);
 
-  if (ret != WriteableFlags::SUCCESS) {
+  if (ret != Flag::SUCCESS) {
     output()->print_cr("%s", err_msg.buffer());
   }
 }
--- a/hotspot/src/share/vm/services/management.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/services/management.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -1703,8 +1703,8 @@
   FormatBuffer<80> err_msg("%s", "");
   int succeed = WriteableFlags::set_flag(name, new_value, Flag::MANAGEMENT, err_msg);
 
-  if (succeed != WriteableFlags::SUCCESS) {
-    if (succeed == WriteableFlags::MISSING_VALUE) {
+  if (succeed != Flag::SUCCESS) {
+    if (succeed == Flag::MISSING_VALUE) {
       // missing value causes NPE to be thrown
       THROW(vmSymbols::java_lang_NullPointerException());
     } else {
@@ -1713,7 +1713,7 @@
                 err_msg.buffer());
     }
   }
-  assert(succeed == WriteableFlags::SUCCESS, "Setting flag should succeed");
+  assert(succeed == Flag::SUCCESS, "Setting flag should succeed");
 JVM_END
 
 class ThreadTimesClosure: public ThreadClosure {
--- a/hotspot/src/share/vm/services/memoryService.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/services/memoryService.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -127,7 +127,6 @@
 
   assert(policy->is_generation_policy(), "Only support two generations");
   GenCollectorPolicy* gen_policy = policy->as_generation_policy();
-  guarantee(gen_policy->number_of_generations() == 2, "Only support two-generation heap");
   if (gen_policy != NULL) {
     Generation::Name kind = gen_policy->young_gen_spec()->name();
     switch (kind) {
@@ -518,8 +517,8 @@
 bool MemoryService::set_verbose(bool verbose) {
   MutexLocker m(Management_lock);
   // verbose will be set to the previous value
-  bool succeed = CommandLineFlags::boolAtPut((char*)"PrintGC", &verbose, Flag::MANAGEMENT);
-  assert(succeed, "Setting PrintGC flag fails");
+  Flag::Error error = CommandLineFlags::boolAtPut("PrintGC", &verbose, Flag::MANAGEMENT);
+  assert(error==Flag::SUCCESS, err_msg("Setting PrintGC flag failed with error %s", Flag::flag_error_str(error)));
   ClassLoadingService::reset_trace_class_unloading();
 
   return verbose;
--- a/hotspot/src/share/vm/services/virtualMemoryTracker.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/services/virtualMemoryTracker.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, 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
@@ -347,6 +347,13 @@
         return true;
       }
 
+      // Mapped CDS string region.
+      // The string region(s) is part of the java heap.
+      if (reserved_rgn->flag() == mtJavaHeap) {
+        assert(reserved_rgn->contain_region(base_addr, size), "Reserved heap region should contain this mapping region");
+        return true;
+      }
+
       ShouldNotReachHere();
       return false;
     }
--- a/hotspot/src/share/vm/services/writeableFlags.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/services/writeableFlags.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -25,129 +25,200 @@
 #include "precompiled.hpp"
 #include "classfile/javaClasses.hpp"
 #include "runtime/arguments.hpp"
+#include "runtime/commandLineFlagRangeList.hpp"
 #include "runtime/java.hpp"
 #include "runtime/jniHandles.hpp"
 #include "services/writeableFlags.hpp"
 
+#define TEMP_BUF_SIZE 80
+
+static void buffer_concat(char* buffer, const char* src) {
+  strncat(buffer, src, TEMP_BUF_SIZE - 1 - strlen(buffer));
+}
+
+static void print_flag_error_message_bounds(const char* name, char* buffer) {
+  CommandLineFlagRange* range = CommandLineFlagRangeList::find(name);
+  if (range != NULL) {
+    buffer_concat(buffer, "must have value in range ");
+
+    stringStream stream;
+    range->print(&stream);
+    const char* range_string = stream.as_string();
+    size_t j = strlen(buffer);
+    for (size_t i=0; j<TEMP_BUF_SIZE-1; i++) {
+      if (range_string[i] == '\0') {
+        break;
+      } else if (range_string[i] != ' ') {
+        buffer[j] = range_string[i];
+        j++;
+      }
+    }
+    buffer[j] = '\0';
+  }
+}
+
+PRAGMA_FORMAT_NONLITERAL_IGNORED_EXTERNAL
+static void print_flag_error_message_if_needed(Flag::Error error, const char* name, FormatBuffer<80>& err_msg) {
+  if (error == Flag::SUCCESS) {
+    return;
+  }
+
+  char buffer[TEMP_BUF_SIZE] = {'\0'};
+  if ((error != Flag::MISSING_NAME) && (name != NULL)) {
+    buffer_concat(buffer, name);
+    buffer_concat(buffer, " error: ");
+  } else {
+    buffer_concat(buffer, "Error: ");
+  }
+  switch (error) {
+    case Flag::MISSING_NAME:
+      buffer_concat(buffer, "flag name is missing."); break;
+    case Flag::MISSING_VALUE:
+      buffer_concat(buffer, "parsing the textual form of the value."); break;
+    case Flag::NON_WRITABLE:
+      buffer_concat(buffer, "flag is not writeable."); break;
+    case Flag::OUT_OF_BOUNDS:
+      print_flag_error_message_bounds(name, buffer); break;
+    case Flag::VIOLATES_CONSTRAINT:
+      buffer_concat(buffer, "value violates its flag's constraint."); break;
+    case Flag::INVALID_FLAG:
+      buffer_concat(buffer, "there is no flag with the given name."); break;
+    case Flag::ERR_OTHER:
+      buffer_concat(buffer, "other, unspecified error related to setting the flag."); break;
+    case Flag::SUCCESS:
+      break;
+  }
+
+  PRAGMA_DIAG_PUSH
+  PRAGMA_FORMAT_NONLITERAL_IGNORED_INTERNAL
+  err_msg.print(buffer);
+  PRAGMA_DIAG_POP
+}
+
 // set a boolean global flag
-int WriteableFlags::set_bool_flag(const char* name, const char* arg, Flag::Flags origin, FormatBuffer<80>& err_msg) {
+Flag::Error WriteableFlags::set_bool_flag(const char* name, const char* arg, Flag::Flags origin, FormatBuffer<80>& err_msg) {
   int value = true;
 
   if (sscanf(arg, "%d", &value)) {
     return set_bool_flag(name, value != 0, origin, err_msg);
   }
   err_msg.print("flag value must be a boolean (1 or 0)");
-  return WRONG_FORMAT;
+  return Flag::WRONG_FORMAT;
 }
 
-int WriteableFlags::set_bool_flag(const char* name, bool value, Flag::Flags origin, FormatBuffer<80>& err_msg) {
-  return CommandLineFlags::boolAtPut((char*)name, &value, origin) ? SUCCESS : ERR_OTHER;
+Flag::Error WriteableFlags::set_bool_flag(const char* name, bool value, Flag::Flags origin, FormatBuffer<80>& err_msg) {
+  Flag::Error err = CommandLineFlags::boolAtPut(name, &value, origin);
+  print_flag_error_message_if_needed(err, name, err_msg);
+  return err;
 }
 
 // set a int global flag
-int WriteableFlags::set_int_flag(const char* name, const char* arg, Flag::Flags origin, FormatBuffer<80>& err_msg) {
+Flag::Error WriteableFlags::set_int_flag(const char* name, const char* arg, Flag::Flags origin, FormatBuffer<80>& err_msg) {
   int value;
 
   if (sscanf(arg, "%d", &value)) {
     return set_int_flag(name, value, origin, err_msg);
   }
   err_msg.print("flag value must be an integer");
-  return WRONG_FORMAT;
+  return Flag::WRONG_FORMAT;
 }
 
-int WriteableFlags::set_int_flag(const char* name, int value, Flag::Flags origin, FormatBuffer<80>& err_msg) {
-  return CommandLineFlags::intAtPut((char*)name, &value, origin) ? SUCCESS : ERR_OTHER;
+Flag::Error WriteableFlags::set_int_flag(const char* name, int value, Flag::Flags origin, FormatBuffer<80>& err_msg) {
+  Flag::Error err = CommandLineFlags::intAtPut(name, &value, origin);
+  print_flag_error_message_if_needed(err, name, err_msg);
+  return err;
 }
 
 // set a uint global flag
-int WriteableFlags::set_uint_flag(const char* name, const char* arg, Flag::Flags origin, FormatBuffer<80>& err_msg) {
+Flag::Error WriteableFlags::set_uint_flag(const char* name, const char* arg, Flag::Flags origin, FormatBuffer<80>& err_msg) {
   uint value;
 
   if (sscanf(arg, "%u", &value)) {
     return set_uint_flag(name, value, origin, err_msg);
   }
   err_msg.print("flag value must be an unsigned integer");
-  return WRONG_FORMAT;
+  return Flag::WRONG_FORMAT;
 }
 
-int WriteableFlags::set_uint_flag(const char* name, uint value, Flag::Flags origin, FormatBuffer<80>& err_msg) {
-  return CommandLineFlags::uintAtPut((char*)name, &value, origin) ? SUCCESS : ERR_OTHER;
+Flag::Error WriteableFlags::set_uint_flag(const char* name, uint value, Flag::Flags origin, FormatBuffer<80>& err_msg) {
+  Flag::Error err = CommandLineFlags::uintAtPut(name, &value, origin);
+  print_flag_error_message_if_needed(err, name, err_msg);
+  return err;
 }
 
 // set a intx global flag
-int WriteableFlags::set_intx_flag(const char* name, const char* arg, Flag::Flags origin, FormatBuffer<80>& err_msg) {
+Flag::Error WriteableFlags::set_intx_flag(const char* name, const char* arg, Flag::Flags origin, FormatBuffer<80>& err_msg) {
   intx value;
 
   if (sscanf(arg, INTX_FORMAT, &value)) {
     return set_intx_flag(name, value, origin, err_msg);
   }
   err_msg.print("flag value must be an integer");
-  return WRONG_FORMAT;
+  return Flag::WRONG_FORMAT;
 }
 
-int WriteableFlags::set_intx_flag(const char* name, intx value, Flag::Flags origin, FormatBuffer<80>& err_msg) {
-  return CommandLineFlags::intxAtPut((char*)name, &value, origin) ? SUCCESS : ERR_OTHER;
+Flag::Error WriteableFlags::set_intx_flag(const char* name, intx value, Flag::Flags origin, FormatBuffer<80>& err_msg) {
+  Flag::Error err = CommandLineFlags::intxAtPut(name, &value, origin);
+  print_flag_error_message_if_needed(err, name, err_msg);
+  return err;
 }
 
 // set a uintx global flag
-int WriteableFlags::set_uintx_flag(const char* name, const char* arg, Flag::Flags origin, FormatBuffer<80>& err_msg) {
+Flag::Error WriteableFlags::set_uintx_flag(const char* name, const char* arg, Flag::Flags origin, FormatBuffer<80>& err_msg) {
   uintx value;
 
   if (sscanf(arg, UINTX_FORMAT, &value)) {
     return set_uintx_flag(name, value, origin, err_msg);
   }
   err_msg.print("flag value must be an unsigned integer");
-  return WRONG_FORMAT;
+  return Flag::WRONG_FORMAT;
 }
 
-int WriteableFlags::set_uintx_flag(const char* name, uintx value, Flag::Flags origin, FormatBuffer<80>& err_msg) {
-  if (strncmp(name, "MaxHeapFreeRatio", 17) == 0) {
-      if (!Arguments::verify_MaxHeapFreeRatio(err_msg, value)) {
-        return OUT_OF_BOUNDS;
-      }
-    } else if (strncmp(name, "MinHeapFreeRatio", 17) == 0) {
-      if (!Arguments::verify_MinHeapFreeRatio(err_msg, value)) {
-        return OUT_OF_BOUNDS;
-      }
-    }
-    return CommandLineFlags::uintxAtPut((char*)name, &value, origin) ? SUCCESS : ERR_OTHER;
+Flag::Error WriteableFlags::set_uintx_flag(const char* name, uintx value, Flag::Flags origin, FormatBuffer<80>& err_msg) {
+  Flag::Error err = CommandLineFlags::uintxAtPut(name, &value, origin);
+  print_flag_error_message_if_needed(err, name, err_msg);
+  return err;
 }
 
 // set a uint64_t global flag
-int WriteableFlags::set_uint64_t_flag(const char* name, const char* arg, Flag::Flags origin, FormatBuffer<80>& err_msg) {
+Flag::Error WriteableFlags::set_uint64_t_flag(const char* name, const char* arg, Flag::Flags origin, FormatBuffer<80>& err_msg) {
   uint64_t value;
 
   if (sscanf(arg, UINT64_FORMAT, &value)) {
     return set_uint64_t_flag(name, value, origin, err_msg);
   }
   err_msg.print("flag value must be an unsigned 64-bit integer");
-  return WRONG_FORMAT;
+  return Flag::WRONG_FORMAT;
 }
 
-int WriteableFlags::set_uint64_t_flag(const char* name, uint64_t value, Flag::Flags origin, FormatBuffer<80>& err_msg) {
-  return CommandLineFlags::uint64_tAtPut((char*)name, &value, origin) ? SUCCESS : ERR_OTHER;
+Flag::Error WriteableFlags::set_uint64_t_flag(const char* name, uint64_t value, Flag::Flags origin, FormatBuffer<80>& err_msg) {
+  Flag::Error err = CommandLineFlags::uint64_tAtPut(name, &value, origin);
+  print_flag_error_message_if_needed(err, name, err_msg);
+  return err;
 }
 
 // set a size_t global flag
-int WriteableFlags::set_size_t_flag(const char* name, const char* arg, Flag::Flags origin, FormatBuffer<80>& err_msg) {
+Flag::Error WriteableFlags::set_size_t_flag(const char* name, const char* arg, Flag::Flags origin, FormatBuffer<80>& err_msg) {
   size_t value;
 
   if (sscanf(arg, SIZE_FORMAT, &value)) {
     return set_size_t_flag(name, value, origin, err_msg);
   }
   err_msg.print("flag value must be an unsigned integer");
-  return WRONG_FORMAT;
+  return Flag::WRONG_FORMAT;
 }
 
-int WriteableFlags::set_size_t_flag(const char* name, size_t value, Flag::Flags origin, FormatBuffer<80>& err_msg) {
-  return CommandLineFlags::size_tAtPut((char*)name, &value, origin) ? SUCCESS : ERR_OTHER;
+Flag::Error WriteableFlags::set_size_t_flag(const char* name, size_t value, Flag::Flags origin, FormatBuffer<80>& err_msg) {
+  Flag::Error err = CommandLineFlags::size_tAtPut(name, &value, origin);
+  print_flag_error_message_if_needed(err, name, err_msg);
+  return err;
 }
 
 // set a string global flag using value from AttachOperation
-int WriteableFlags::set_ccstr_flag(const char* name, const char* arg, Flag::Flags origin, FormatBuffer<80>& err_msg) {
-  bool res = CommandLineFlags::ccstrAtPut((char*)name, &arg, origin);
-
-  return res? SUCCESS : ERR_OTHER;
+Flag::Error WriteableFlags::set_ccstr_flag(const char* name, const char* value, Flag::Flags origin, FormatBuffer<80>& err_msg) {
+  Flag::Error err = CommandLineFlags::ccstrAtPut((char*)name, &value, origin);
+  print_flag_error_message_if_needed(err, name, err_msg);
+  return err;
 }
 
 /* sets a writeable flag to the provided value
@@ -155,7 +226,7 @@
  * - return status is one of the WriteableFlags::err enum values
  * - an eventual error message will be generated to the provided err_msg buffer
  */
-int WriteableFlags::set_flag(const char* flag_name, const char* flag_value, Flag::Flags origin, FormatBuffer<80>& err_msg) {
+Flag::Error WriteableFlags::set_flag(const char* flag_name, const char* flag_value, Flag::Flags origin, FormatBuffer<80>& err_msg) {
   return set_flag(flag_name, &flag_value, set_flag_from_char, origin, err_msg);
 }
 
@@ -164,19 +235,19 @@
  * - return status is one of the WriteableFlags::err enum values
  * - an eventual error message will be generated to the provided err_msg buffer
  */
-int WriteableFlags::set_flag(const char* flag_name, jvalue flag_value, Flag::Flags origin, FormatBuffer<80>& err_msg) {
+Flag::Error WriteableFlags::set_flag(const char* flag_name, jvalue flag_value, Flag::Flags origin, FormatBuffer<80>& err_msg) {
   return set_flag(flag_name, &flag_value, set_flag_from_jvalue, origin, err_msg);
 }
 
 // a writeable flag setter accepting either 'jvalue' or 'char *' values
-int WriteableFlags::set_flag(const char* name, const void* value, int(*setter)(Flag*,const void*,Flag::Flags,FormatBuffer<80>&), Flag::Flags origin, FormatBuffer<80>& err_msg) {
+Flag::Error WriteableFlags::set_flag(const char* name, const void* value, Flag::Error(*setter)(Flag*,const void*,Flag::Flags,FormatBuffer<80>&), Flag::Flags origin, FormatBuffer<80>& err_msg) {
   if (name == NULL) {
     err_msg.print("flag name is missing");
-    return MISSING_NAME;
+    return Flag::MISSING_NAME;
   }
   if (value == NULL) {
     err_msg.print("flag value is missing");
-    return MISSING_VALUE;
+    return Flag::MISSING_VALUE;
   }
 
   Flag* f = Flag::find_flag((char*)name, strlen(name));
@@ -186,20 +257,20 @@
       return setter(f, value, origin, err_msg);
     } else {
       err_msg.print("only 'writeable' flags can be set");
-      return NON_WRITABLE;
+      return Flag::NON_WRITABLE;
     }
   }
 
   err_msg.print("flag %s does not exist", name);
-  return INVALID_FLAG;
+  return Flag::INVALID_FLAG;
 }
 
 // a writeable flag setter accepting 'char *' values
-int WriteableFlags::set_flag_from_char(Flag* f, const void* value, Flag::Flags origin, FormatBuffer<80>& err_msg) {
+Flag::Error WriteableFlags::set_flag_from_char(Flag* f, const void* value, Flag::Flags origin, FormatBuffer<80>& err_msg) {
   char* flag_value = *(char**)value;
   if (flag_value == NULL) {
     err_msg.print("flag value is missing");
-    return MISSING_VALUE;
+    return Flag::MISSING_VALUE;
   }
   if (f->is_bool()) {
     return set_bool_flag(f->_name, flag_value, origin, err_msg);
@@ -220,11 +291,11 @@
   } else {
     ShouldNotReachHere();
   }
-  return ERR_OTHER;
+  return Flag::ERR_OTHER;
 }
 
 // a writeable flag setter accepting 'jvalue' values
-int WriteableFlags::set_flag_from_jvalue(Flag* f, const void* value, Flag::Flags origin, FormatBuffer<80>& err_msg) {
+Flag::Error WriteableFlags::set_flag_from_jvalue(Flag* f, const void* value, Flag::Flags origin, FormatBuffer<80>& err_msg) {
   jvalue new_value = *(jvalue*)value;
   if (f->is_bool()) {
     bool bvalue = (new_value.z == JNI_TRUE ? true : false);
@@ -251,17 +322,16 @@
     oop str = JNIHandles::resolve_external_guard(new_value.l);
     if (str == NULL) {
       err_msg.print("flag value is missing");
-      return MISSING_VALUE;
+      return Flag::MISSING_VALUE;
     }
     ccstr svalue = java_lang_String::as_utf8_string(str);
-    int ret = WriteableFlags::set_ccstr_flag(f->_name, svalue, origin, err_msg);
-    if (ret != SUCCESS) {
+    Flag::Error ret = WriteableFlags::set_ccstr_flag(f->_name, svalue, origin, err_msg);
+    if (ret != Flag::SUCCESS) {
       FREE_C_HEAP_ARRAY(char, svalue);
     }
     return ret;
   } else {
     ShouldNotReachHere();
   }
-  return ERR_OTHER;
+  return Flag::ERR_OTHER;
 }
-
--- a/hotspot/src/share/vm/services/writeableFlags.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/services/writeableFlags.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -26,64 +26,44 @@
 #define SHARE_VM_SERVICES_WRITEABLEFLAG_HPP
 
 class WriteableFlags : AllStatic {
-public:
-  enum error {
-    // no error
-    SUCCESS,
-    // flag name is missing
-    MISSING_NAME,
-    // flag value is missing
-    MISSING_VALUE,
-    // error parsing the textual form of the value
-    WRONG_FORMAT,
-    // flag is not writeable
-    NON_WRITABLE,
-    // flag value is outside of its bounds
-    OUT_OF_BOUNDS,
-    // there is no flag with the given name
-    INVALID_FLAG,
-    // other, unspecified error related to setting the flag
-    ERR_OTHER
-  } err;
-
 private:
   // a writeable flag setter accepting either 'jvalue' or 'char *' values
-  static int set_flag(const char* name, const void* value, int(*setter)(Flag*, const void*, Flag::Flags, FormatBuffer<80>&), Flag::Flags origin, FormatBuffer<80>& err_msg);
+  static Flag::Error set_flag(const char* name, const void* value, Flag::Error(*setter)(Flag*, const void*, Flag::Flags, FormatBuffer<80>&), Flag::Flags origin, FormatBuffer<80>& err_msg);
   // a writeable flag setter accepting 'char *' values
-  static int set_flag_from_char(Flag* f, const void* value, Flag::Flags origin, FormatBuffer<80>& err_msg);
+  static Flag::Error set_flag_from_char(Flag* f, const void* value, Flag::Flags origin, FormatBuffer<80>& err_msg);
   // a writeable flag setter accepting 'jvalue' values
-  static int set_flag_from_jvalue(Flag* f, const void* value, Flag::Flags origin, FormatBuffer<80>& err_msg);
+  static Flag::Error set_flag_from_jvalue(Flag* f, const void* value, Flag::Flags origin, FormatBuffer<80>& err_msg);
 
   // set a boolean global flag
-  static int set_bool_flag(const char* name, const char* value, Flag::Flags origin, FormatBuffer<80>& err_msg);
+  static Flag::Error set_bool_flag(const char* name, const char* value, Flag::Flags origin, FormatBuffer<80>& err_msg);
   // set a int global flag
-  static int set_int_flag(const char* name, const char* value, Flag::Flags origin, FormatBuffer<80>& err_msg);
+  static Flag::Error set_int_flag(const char* name, const char* value, Flag::Flags origin, FormatBuffer<80>& err_msg);
   // set a uint global flag
-  static int set_uint_flag(const char* name, const char* value, Flag::Flags origin, FormatBuffer<80>& err_msg);
+  static Flag::Error set_uint_flag(const char* name, const char* value, Flag::Flags origin, FormatBuffer<80>& err_msg);
   // set a intx global flag
-  static int set_intx_flag(const char* name, const char* value, Flag::Flags origin, FormatBuffer<80>& err_msg);
+  static Flag::Error set_intx_flag(const char* name, const char* value, Flag::Flags origin, FormatBuffer<80>& err_msg);
   // set a uintx global flag
-  static int set_uintx_flag(const char* name, const char* value, Flag::Flags origin, FormatBuffer<80>& err_msg);
+  static Flag::Error set_uintx_flag(const char* name, const char* value, Flag::Flags origin, FormatBuffer<80>& err_msg);
   // set a uint64_t global flag
-  static int set_uint64_t_flag(const char* name, const char* value, Flag::Flags origin, FormatBuffer<80>& err_msg);
+  static Flag::Error set_uint64_t_flag(const char* name, const char* value, Flag::Flags origin, FormatBuffer<80>& err_msg);
   // set a size_t global flag using value from AttachOperation
-  static int set_size_t_flag(const char* name, const char* value, Flag::Flags origin, FormatBuffer<80>& err_msg);
+  static Flag::Error set_size_t_flag(const char* name, const char* value, Flag::Flags origin, FormatBuffer<80>& err_msg);
   // set a boolean global flag
-  static int set_bool_flag(const char* name, bool value, Flag::Flags origin, FormatBuffer<80>& err_msg);
+  static Flag::Error set_bool_flag(const char* name, bool value, Flag::Flags origin, FormatBuffer<80>& err_msg);
   // set a int global flag
-  static int set_int_flag(const char* name, int value, Flag::Flags origin, FormatBuffer<80>& err_msg);
+  static Flag::Error set_int_flag(const char* name, int value, Flag::Flags origin, FormatBuffer<80>& err_msg);
   // set a uint global flag
-  static int set_uint_flag(const char* name, uint value, Flag::Flags origin, FormatBuffer<80>& err_msg);
+  static Flag::Error set_uint_flag(const char* name, uint value, Flag::Flags origin, FormatBuffer<80>& err_msg);
   // set a intx global flag
-  static int set_intx_flag(const char* name, intx value, Flag::Flags origin, FormatBuffer<80>& err_msg);
+  static Flag::Error set_intx_flag(const char* name, intx value, Flag::Flags origin, FormatBuffer<80>& err_msg);
   // set a uintx global flag
-  static int set_uintx_flag(const char* name, uintx value, Flag::Flags origin, FormatBuffer<80>& err_msg);
+  static Flag::Error set_uintx_flag(const char* name, uintx value, Flag::Flags origin, FormatBuffer<80>& err_msg);
   // set a uint64_t global flag
-  static int set_uint64_t_flag(const char* name, uint64_t value, Flag::Flags origin, FormatBuffer<80>& err_msg);
+  static Flag::Error set_uint64_t_flag(const char* name, uint64_t value, Flag::Flags origin, FormatBuffer<80>& err_msg);
   // set a size_t global flag using value from AttachOperation
-  static int set_size_t_flag(const char* name, size_t value, Flag::Flags origin, FormatBuffer<80>& err_msg);
+  static Flag::Error set_size_t_flag(const char* name, size_t value, Flag::Flags origin, FormatBuffer<80>& err_msg);
   // set a string global flag
-  static int set_ccstr_flag(const char* name, const char* value, Flag::Flags origin, FormatBuffer<80>& err_msg);
+  static Flag::Error set_ccstr_flag(const char* name, const char* value, Flag::Flags origin, FormatBuffer<80>& err_msg);
 
 public:
   /* sets a writeable flag to the provided value
@@ -91,15 +71,14 @@
    * - return status is one of the WriteableFlags::err enum values
    * - an eventual error message will be generated to the provided err_msg buffer
    */
-  static int set_flag(const char* flag_name, const char* flag_value, Flag::Flags origin, FormatBuffer<80>& err_msg);
+  static Flag::Error set_flag(const char* flag_name, const char* flag_value, Flag::Flags origin, FormatBuffer<80>& err_msg);
 
   /* sets a writeable flag to the provided value
    *
    * - return status is one of the WriteableFlags::err enum values
    * - an eventual error message will be generated to the provided err_msg buffer
    */
-  static int set_flag(const char* flag_name, jvalue flag_value, Flag::Flags origin, FormatBuffer<80>& err_msg);
+  static Flag::Error set_flag(const char* flag_name, jvalue flag_value, Flag::Flags origin, FormatBuffer<80>& err_msg);
 };
 
 #endif /* SHARE_VM_SERVICES_WRITEABLEFLAG_HPP */
-
--- a/hotspot/src/share/vm/trace/trace.xml	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/trace/trace.xml	Thu Jun 25 09:48:50 2015 -0700
@@ -264,6 +264,15 @@
       <structvalue type="ObjectSpace" field="toSpace" label="To Space"/>
     </event>
 
+    <event id="G1HeapSummary" path="vm/gc/heap/g1_summary" label="G1 Heap Summary" is_instant="true">
+      <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
+      <value type="GCWHEN" field="when" label="When" />
+
+      <value type="BYTES64" field="edenUsedSize" label="Eden Used Size" />
+      <value type="BYTES64" field="edenTotalSize" label="Eden Total Size" />
+      <value type="BYTES64" field="survivorUsedSize" label="Survivor Used Size" />
+    </event>
+
     <event id="GCGarbageCollection" path="vm/gc/collector/garbage_collection" label="Garbage Collection"
            description="Garbage collection performed by the JVM">
       <value type="UINT" field="gcId"  label="GC ID" relation="GC_ID" />
--- a/hotspot/src/share/vm/utilities/debug.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/utilities/debug.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -770,3 +770,31 @@
 }
 
 #endif // !PRODUCT
+
+//////////////////////////////////////////////////////////////////////////////
+// Test multiple STATIC_ASSERT forms in various scopes.
+
+#ifndef PRODUCT
+
+// namespace scope
+STATIC_ASSERT(true);
+STATIC_ASSERT(true);
+STATIC_ASSERT(1 == 1);
+STATIC_ASSERT(0 == 0);
+
+void test_multiple_static_assert_forms_in_function_scope() {
+  STATIC_ASSERT(true);
+  STATIC_ASSERT(true);
+  STATIC_ASSERT(0 == 0);
+  STATIC_ASSERT(1 == 1);
+}
+
+// class scope
+struct TestMultipleStaticAssertFormsInClassScope {
+  STATIC_ASSERT(true);
+  STATIC_ASSERT(true);
+  STATIC_ASSERT(0 == 0);
+  STATIC_ASSERT(1 == 1);
+};
+
+#endif // !PRODUCT
--- a/hotspot/src/share/vm/utilities/debug.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/utilities/debug.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -223,7 +223,8 @@
 template<> struct STATIC_ASSERT_FAILURE<true> { enum { value = 1 }; };
 
 #define STATIC_ASSERT(Cond) \
-  typedef char STATIC_ASSERT_DUMMY_TYPE[ STATIC_ASSERT_FAILURE< (Cond) >::value ]
+  typedef char PASTE_TOKENS(STATIC_ASSERT_DUMMY_TYPE_, __LINE__)[ \
+    STATIC_ASSERT_FAILURE< (Cond) >::value ]
 
 // out of shared space reporting
 enum SharedSpaceType {
--- a/hotspot/src/share/vm/utilities/decoder.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/utilities/decoder.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, 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
@@ -102,7 +102,7 @@
   return _shared_decoder_lock;
 }
 
-bool Decoder::decode(address addr, char* buf, int buflen, int* offset, const char* modulepath) {
+bool Decoder::decode(address addr, char* buf, int buflen, int* offset, const char* modulepath, bool demangle) {
   assert(_shared_decoder_lock != NULL, "Just check");
   bool error_handling_thread = os::current_thread_id() == VMError::first_error_tid;
   MutexLockerEx locker(error_handling_thread ? NULL : _shared_decoder_lock, true);
@@ -110,7 +110,7 @@
     get_error_handler_instance(): get_shared_instance();
   assert(decoder != NULL, "null decoder");
 
-  return decoder->decode(addr, buf, buflen, offset, modulepath);
+  return decoder->decode(addr, buf, buflen, offset, modulepath, demangle);
 }
 
 bool Decoder::decode(address addr, char* buf, int buflen, int* offset, const void* base) {
--- a/hotspot/src/share/vm/utilities/decoder.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/utilities/decoder.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, 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
@@ -46,8 +46,12 @@
 
   // decode an pc address to corresponding function name and an offset from the beginning of
   // the function
+  //
+  // Note: the 'base' variant does not demangle names. The
+  // demangling that was done systematically in the 'modulepath' variant
+  // is now optional.
   virtual bool decode(address pc, char* buf, int buflen, int* offset,
-    const char* modulepath = NULL) = 0;
+                      const char* modulepath = NULL, bool demangle = true) = 0;
   virtual bool decode(address pc, char* buf, int buflen, int* offset, const void* base) = 0;
 
   // demangle a C++ symbol
@@ -81,7 +85,7 @@
   ~NullDecoder() {};
 
   virtual bool decode(address pc, char* buf, int buflen, int* offset,
-    const char* modulepath = NULL) {
+                      const char* modulepath, bool demangle) {
     return false;
   }
 
@@ -101,7 +105,10 @@
 
 class Decoder : AllStatic {
 public:
-  static bool decode(address pc, char* buf, int buflen, int* offset, const char* modulepath = NULL);
+  static bool decode(address pc, char* buf, int buflen, int* offset, const char* modulepath = NULL, bool demangle = true);
+  static bool decode(address pc, char* buf, int buflen, int* offset, bool demangle) {
+    return decode(pc, buf, buflen, offset, (const char*) NULL, demangle);
+  }
   static bool decode(address pc, char* buf, int buflen, int* offset, const void* base);
   static bool demangle(const char* symbol, char* buf, int buflen);
   static bool can_decode_C_frame_in_vm();
--- a/hotspot/src/share/vm/utilities/decoder_elf.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/utilities/decoder_elf.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2015, 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
@@ -34,7 +34,7 @@
   }
 }
 
-bool ElfDecoder::decode(address addr, char *buf, int buflen, int* offset, const char* filepath) {
+bool ElfDecoder::decode(address addr, char *buf, int buflen, int* offset, const char* filepath, bool demangle_name) {
   assert(filepath, "null file path");
   assert(buf != NULL && buflen > 0, "Invalid buffer");
   if (has_error()) return false;
@@ -46,7 +46,7 @@
   if (!file->decode(addr, buf, buflen, offset)) {
     return false;
   }
-  if (buf[0] != '\0') {
+  if (demangle_name && (buf[0] != '\0')) {
     demangle(buf, buf, buflen);
   }
   return true;
--- a/hotspot/src/share/vm/utilities/decoder_elf.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/utilities/decoder_elf.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2015, 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
@@ -42,7 +42,7 @@
   bool can_decode_C_frame_in_vm() const { return true; }
 
   bool demangle(const char* symbol, char *buf, int buflen);
-  bool decode(address addr, char *buf, int buflen, int* offset, const char* filepath = NULL);
+  bool decode(address addr, char *buf, int buflen, int* offset, const char* filepath, bool demangle);
   bool decode(address addr, char *buf, int buflen, int* offset, const void *base) {
     ShouldNotReachHere();
     return false;
--- a/hotspot/src/share/vm/utilities/exceptions.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/utilities/exceptions.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, 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
@@ -154,15 +154,21 @@
     return;
   }
 
+  if (h_exception->is_a(SystemDictionary::OutOfMemoryError_klass())) {
+    count_out_of_memory_exceptions(h_exception);
+  }
+
   assert(h_exception->is_a(SystemDictionary::Throwable_klass()), "exception is not a subclass of java/lang/Throwable");
 
   // set the pending exception
   thread->set_pending_exception(h_exception(), file, line);
 
   // vm log
-  Events::log_exception(thread, "Exception <%s%s%s> (" INTPTR_FORMAT ") thrown at [%s, line %d]",
-                        h_exception->print_value_string(), message ? ": " : "", message ? message : "",
-                        (address)h_exception(), file, line);
+  if (LogEvents){
+    Events::log_exception(thread, "Exception <%s%s%s> (" INTPTR_FORMAT ") thrown at [%s, line %d]",
+                          h_exception->print_value_string(), message ? ": " : "", message ? message : "",
+                          (address)h_exception(), file, line);
+  }
 }
 
 
@@ -228,6 +234,8 @@
     if (StackTraceInThrowable) {
       java_lang_Throwable::fill_in_stack_trace(exception, method());
     }
+    // Increment counter for hs_err file reporting
+    Atomic::inc(&Exceptions::_stack_overflow_errors);
   } else {
     // if prior exception, throw that one instead
     exception = Handle(THREAD, THREAD->pending_exception());
@@ -404,6 +412,44 @@
                                    h_prot, to_utf8_safe);
 }
 
+
+// Exception counting for hs_err file
+volatile int Exceptions::_stack_overflow_errors = 0;
+volatile int Exceptions::_out_of_memory_error_java_heap_errors = 0;
+volatile int Exceptions::_out_of_memory_error_metaspace_errors = 0;
+volatile int Exceptions::_out_of_memory_error_class_metaspace_errors = 0;
+
+void Exceptions::count_out_of_memory_exceptions(Handle exception) {
+  if (exception() == Universe::out_of_memory_error_metaspace()) {
+     Atomic::inc(&_out_of_memory_error_metaspace_errors);
+  } else if (exception() == Universe::out_of_memory_error_class_metaspace()) {
+     Atomic::inc(&_out_of_memory_error_class_metaspace_errors);
+  } else {
+     // everything else reported as java heap OOM
+     Atomic::inc(&_out_of_memory_error_java_heap_errors);
+  }
+}
+
+void print_oom_count(outputStream* st, const char *err, int count) {
+  if (count > 0) {
+    st->print_cr("OutOfMemoryError %s=%d", err, count);
+  }
+}
+
+bool Exceptions::has_exception_counts() {
+  return (_stack_overflow_errors + _out_of_memory_error_java_heap_errors +
+         _out_of_memory_error_metaspace_errors + _out_of_memory_error_class_metaspace_errors) > 0;
+}
+
+void Exceptions::print_exception_counts_on_error(outputStream* st) {
+  print_oom_count(st, "java_heap_errors", _out_of_memory_error_java_heap_errors);
+  print_oom_count(st, "metaspace_errors", _out_of_memory_error_metaspace_errors);
+  print_oom_count(st, "class_metaspace_errors", _out_of_memory_error_class_metaspace_errors);
+  if (_stack_overflow_errors > 0) {
+    st->print_cr("StackOverflowErrors=%d", _stack_overflow_errors);
+  }
+}
+
 // Implementation of ExceptionMark
 
 ExceptionMark::ExceptionMark(Thread*& thread) {
--- a/hotspot/src/share/vm/utilities/exceptions.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/utilities/exceptions.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, 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
@@ -102,6 +102,11 @@
 class Exceptions {
   static bool special_exception(Thread *thread, const char* file, int line, Handle exception);
   static bool special_exception(Thread* thread, const char* file, int line, Symbol* name, const char* message);
+
+  // Count out of memory errors that are interesting in error diagnosis
+  static volatile int _out_of_memory_error_java_heap_errors;
+  static volatile int _out_of_memory_error_metaspace_errors;
+  static volatile int _out_of_memory_error_class_metaspace_errors;
  public:
   // this enum is defined to indicate whether it is safe to
   // ignore the encoding scheme of the original message string.
@@ -160,6 +165,14 @@
 
   static void throw_stack_overflow_exception(Thread* thread, const char* file, int line, methodHandle method);
 
+  // Exception counting for error files of interesting exceptions that may have
+  // caused a problem for the jvm
+  static volatile int _stack_overflow_errors;
+
+  static bool has_exception_counts();
+  static void count_out_of_memory_exceptions(Handle exception);
+  static void print_exception_counts_on_error(outputStream* st);
+
   // for AbortVMOnException flag
   NOT_PRODUCT(static void debug_check_abort(Handle exception, const char* message = NULL);)
   NOT_PRODUCT(static void debug_check_abort(const char *value_string, const char* message = NULL);)
--- a/hotspot/src/share/vm/utilities/macros.hpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/utilities/macros.hpp	Thu Jun 25 09:48:50 2015 -0700
@@ -34,6 +34,15 @@
 // Makes a string of the macro expansion of a
 #define XSTR(a) STR(a)
 
+// Apply pre-processor token pasting to the expansions of x and y.
+// The token pasting operator (##) prevents its arguments from being
+// expanded.  This macro allows expansion of its arguments before the
+// concatenation is performed.  Note: One auxilliary level ought to be
+// sufficient, but two are used because of bugs in some preprocesors.
+#define PASTE_TOKENS(x, y) PASTE_TOKENS_AUX(x, y)
+#define PASTE_TOKENS_AUX(x, y) PASTE_TOKENS_AUX2(x, y)
+#define PASTE_TOKENS_AUX2(x, y) x ## y
+
 // -DINCLUDE_<something>=0 | 1 can be specified on the command line to include
 // or exclude functionality.
 
--- a/hotspot/src/share/vm/utilities/vmError.cpp	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/src/share/vm/utilities/vmError.cpp	Thu Jun 25 09:48:50 2015 -0700
@@ -714,6 +714,24 @@
        st->cr();
      }
 
+  STEP(182, "(printing number of OutOfMemoryError and StackOverflow exceptions)")
+
+     if (_verbose && Exceptions::has_exception_counts()) {
+       st->print_cr("OutOfMemory and StackOverflow Exception counts:");
+       Exceptions::print_exception_counts_on_error(st);
+       st->cr();
+     }
+
+  STEP(185, "(printing compressed oops mode")
+
+     if (_verbose && UseCompressedOops) {
+       Universe::print_compressed_oops_mode(st);
+       if (UseCompressedClassPointers) {
+         Metaspace::print_compressed_class_space(st);
+       }
+       st->cr();
+     }
+
   STEP(190, "(printing heap information)" )
 
      if (_verbose && Universe::is_fully_initialized()) {
@@ -798,7 +816,7 @@
 
   STEP(250, "(printing CPU info)" )
      if (_verbose) {
-       os::print_cpu_info(st);
+       os::print_cpu_info(st, buf, sizeof(buf));
        st->cr();
      }
 
@@ -819,7 +837,7 @@
   STEP(280, "(printing date and time)" )
 
      if (_verbose) {
-       os::print_date_and_time(st);
+       os::print_date_and_time(st, buf, sizeof(buf));
        st->cr();
      }
 
--- a/hotspot/test/TEST.groups	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/test/TEST.groups	Thu Jun 25 09:48:50 2015 -0700
@@ -245,97 +245,6 @@
   gc/whitebox/TestConcMarkCycleWB.java \
   gc/arguments/TestG1ConcRefinementThreads.java
 
-# All tests that explicitly set the serial GC
-#
-needs_serialgc = \
-  gc/TestSystemGC.java \
-  gc/arguments/TestAlignmentToUseLargePages.java \
-  gc/arguments/TestMaxNewSize.java \
-  gc/arguments/TestSerialHeapSizeFlags.java \
-  gc/arguments/TestUseCompressedOopsErgo.java \
-  gc/serial/HeapChangeLogging.java \
-  gc/metaspace/TestMetaspacePerfCounters.java \
-  gc/metaspace/TestPerfCountersAndMemoryPools.java \
-  gc/startup_warnings/TestSerialGC.java 
-
-# All tests that explicitly set the parallel GC
-#
-needs_parallelgc = \
-  gc/TestSystemGC.java \
-  gc/arguments/TestAlignmentToUseLargePages.java \
-  gc/arguments/TestMaxNewSize.java \
-  gc/arguments/TestMinInitialErgonomics.java \
-  gc/arguments/TestParallelGCThreads.java \
-  gc/arguments/TestUseCompressedOopsErgo.java \
-  gc/ergonomics/TestDynamicNumberOfGCThreads.java
-  gc/metaspace/TestMetaspacePerfCounters.java \
-  gc/parallel/ \
-  gc/startup_warnings/TestParallelGC.java \
-  gc/startup_warnings/TestParallelScavengeSerialOld.java
-
-# All tests that explicitly set the CMS GC
-#
-needs_cmsgc = \
-  gc/6581734/Test6581734.java \
-  gc/TestSystemGC.java \
-  gc/arguments/TestAlignmentToUseLargePages.java \
-  gc/arguments/TestCMSHeapSizeFlags.java \
-  gc/arguments/TestMaxNewSize.java \
-  gc/arguments/TestParallelGCThreads.java \
-  gc/arguments/TestUseCompressedOopsErgo.java \
-  gc/class_unloading/TestCMSClassUnloadingEnabledHWM.java \
-  gc/cms/ \
-  gc/ergonomics/TestDynamicNumberOfGCThreads.java
-  gc/startup_warnings/TestCMS.java \
-  gc/startup_warnings/TestDefNewCMS.java \
-  gc/startup_warnings/TestParNewCMS.java
-
-# All tests that explicitly set some GC
-#
-needs_gc = \
-  :needs_g1gc \
-  :needs_serialgc \
-  :needs_parallelgc \
-  :needs_cmsgc
-
-# All tests that do not set any GC explicitly
-#
-not_needs_gc = \
-  :jdk \
- -:needs_gc
-
-# All tests that could be executed with the G1 GC without VM flags conflict
-#
-applicable_g1gc = \
-  :jdk \
- -:needs_serialgc \
- -:needs_parallelgc \
- -:needs_cmsgc
-
-# All tests that could be executed with the serial GC without VM flags conflict
-#
-applicable_serialgc = \
-  :jdk \
- -:needs_g1gc \
- -:needs_parallelgc \
- -:needs_cmsgc
-
-# All tests that could be executed with the parallel GC without VM flags conflict
-#
-applicable_parallelgc = \
-  :jdk \
- -:needs_g1gc \
- -:needs_serialgc \
- -:needs_cmsgc
-
-# All tests that could be executed with the CMS GC without VM flags conflict
-#
-applicable_cmsgc = \
-  :jdk \
- -:needs_g1gc \
- -:needs_serialgc \
- -:needs_parallelgc
-
 hotspot_native_sanity = \
   native_sanity
 
@@ -420,6 +329,7 @@
  -runtime/SharedArchiveFile/DefaultUseWithClient.java \
  -runtime/Thread/CancellableThreadTest.java \
  -runtime/7158988/FieldMonitor.java \
+ -runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java \
   sanity/ \
   testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java
 
--- a/hotspot/test/compiler/c2/7200264/Test7200264.sh	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/test/compiler/c2/7200264/Test7200264.sh	Thu Jun 25 09:48:50 2015 -0700
@@ -1,6 +1,6 @@
 #!/bin/sh
 # 
-# Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2012, 2015, 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
@@ -55,7 +55,8 @@
 cp ${TESTSRC}${FS}TestIntVect.java .
 ${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} -d . TestIntVect.java
 
-${TESTJAVA}${FS}bin${FS}java ${TESTOPTS} -Xbatch -XX:-TieredCompilation -XX:CICompilerCount=1 -XX:+PrintCompilation -XX:+TraceNewVectors TestIntVect > test.out 2>&1
+# CICompilerCount must be at least 2 with -TieredCompilation
+${TESTJAVA}${FS}bin${FS}java ${TESTOPTS} -Xbatch -XX:-TieredCompilation -XX:CICompilerCount=2 -XX:+PrintCompilation -XX:+TraceNewVectors TestIntVect > test.out 2>&1
 
 COUNT=`grep AddVI test.out | wc -l | awk '{print $1}'`
 if [ $COUNT -lt 4 ]
--- a/hotspot/test/compiler/startup/NumCompilerThreadsCheck.java	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/test/compiler/startup/NumCompilerThreadsCheck.java	Thu Jun 25 09:48:50 2015 -0700
@@ -37,7 +37,7 @@
     ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:CICompilerCount=-1");
     OutputAnalyzer out = new OutputAnalyzer(pb.start());
 
-    String expectedOutput = "CICompilerCount of -1 is invalid";
+    String expectedOutput = "outside the allowed range";
     out.shouldContain(expectedOutput);
 
     if (Platform.isZero()) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/CondCardMark/Basic.java	Thu Jun 25 09:48:50 2015 -0700
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2014, 2015, 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 8076987
+ * @bug 8078438
+ * @summary Verify UseCondCardMark works
+ * @library /testlibrary /../../test/lib
+ * @build Basic
+ * @run main/othervm -Xint Basic
+ * @run main/othervm -Xint -XX:+UseCondCardMark Basic
+ * @run main/othervm -XX:TieredStopAtLevel=1 Basic
+ * @run main/othervm -XX:TieredStopAtLevel=1 -XX:+UseCondCardMark Basic
+ * @run main/othervm -XX:TieredStopAtLevel=4 Basic
+ * @run main/othervm -XX:TieredStopAtLevel=4 -XX:+UseCondCardMark Basic
+ * @run main/othervm -XX:-TieredCompilation Basic
+ * @run main/othervm -XX:-TieredCompilation -XX:+UseCondCardMark Basic
+*/
+public class Basic {
+
+    static volatile MyObject sink;
+
+    public static void main(String args[]) {
+        final int COUNT = 10000000;
+        for (int c = 0; c < COUNT; c++) {
+             MyObject o = new MyObject();
+             o.x = c;
+             doStore(o);
+        }
+
+        if (sink.x != COUNT-1) {
+             throw new IllegalStateException("Failed");
+        }
+    }
+
+    public static void doStore(MyObject o) {
+        sink = o;
+    }
+
+    static class MyObject {
+        int x;
+    }
+
+}
--- a/hotspot/test/gc/arguments/TestHeapFreeRatio.java	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/test/gc/arguments/TestHeapFreeRatio.java	Thu Jun 25 09:48:50 2015 -0700
@@ -40,6 +40,7 @@
     VALID,
     MIN_INVALID,
     MAX_INVALID,
+    OUT_OF_RANGE,
     COMBINATION_INVALID
   }
 
@@ -65,8 +66,13 @@
       output.shouldContain("Error");
       output.shouldHaveExitValue(1);
       break;
+    case OUT_OF_RANGE:
+      output.shouldContain("outside the allowed range");
+      output.shouldContain("Error");
+      output.shouldHaveExitValue(1);
+      break;
     case COMBINATION_INVALID:
-      output.shouldContain("must be less than or equal to MaxHeapFreeRatio");
+      output.shouldContain("must be greater than or equal to MinHeapFreeRatio");
       output.shouldContain("Error");
       output.shouldHaveExitValue(1);
       break;
@@ -82,23 +88,24 @@
     testMinMaxFreeRatio(  ".1",  ".5", Validation.VALID);
     testMinMaxFreeRatio( "0.5", "0.5", Validation.VALID);
 
-    testMinMaxFreeRatio("-0.1", "0.5", Validation.MIN_INVALID);
-    testMinMaxFreeRatio( "1.1", "0.5", Validation.MIN_INVALID);
     testMinMaxFreeRatio("=0.1", "0.5", Validation.MIN_INVALID);
     testMinMaxFreeRatio("0.1f", "0.5", Validation.MIN_INVALID);
     testMinMaxFreeRatio(
                      "INVALID", "0.5", Validation.MIN_INVALID);
-    testMinMaxFreeRatio(
-                  "2147483647", "0.5", Validation.MIN_INVALID);
 
-    testMinMaxFreeRatio( "0.1", "-0.5", Validation.MAX_INVALID);
-    testMinMaxFreeRatio( "0.1",  "1.5", Validation.MAX_INVALID);
     testMinMaxFreeRatio( "0.1", "0.5f", Validation.MAX_INVALID);
     testMinMaxFreeRatio( "0.1", "=0.5", Validation.MAX_INVALID);
     testMinMaxFreeRatio(
                      "0.1",  "INVALID", Validation.MAX_INVALID);
+
+    testMinMaxFreeRatio("-0.1", "0.5", Validation.OUT_OF_RANGE);
+    testMinMaxFreeRatio( "1.1", "0.5", Validation.OUT_OF_RANGE);
     testMinMaxFreeRatio(
-                   "0.1", "2147483647", Validation.MAX_INVALID);
+                  "2147483647", "0.5", Validation.OUT_OF_RANGE);
+    testMinMaxFreeRatio( "0.1", "-0.5", Validation.OUT_OF_RANGE);
+    testMinMaxFreeRatio( "0.1",  "1.5", Validation.OUT_OF_RANGE);
+    testMinMaxFreeRatio(
+                   "0.1", "2147483647", Validation.OUT_OF_RANGE);
 
     testMinMaxFreeRatio( "0.5",  "0.1", Validation.COMBINATION_INVALID);
     testMinMaxFreeRatio(  ".5",  ".10", Validation.COMBINATION_INVALID);
--- a/hotspot/test/gc/arguments/TestParallelGCThreads.java	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/test/gc/arguments/TestParallelGCThreads.java	Thu Jun 25 09:48:50 2015 -0700
@@ -24,7 +24,7 @@
 /*
  * @test TestParallelGCThreads
  * @key gc
- * @bug 8059527
+ * @bug 8059527 8081382
  * @summary Tests argument processing for ParallelGCThreads
  * @library /testlibrary
  * @modules java.base/sun.misc
@@ -37,7 +37,38 @@
 public class TestParallelGCThreads {
 
   public static void main(String args[]) throws Exception {
+    testFlags();
+    testDefaultValue();
+  }
 
+  private static final String flagName = "ParallelGCThreads";
+
+  // uint ParallelGCThreads = 23 {product}
+  private static final String printFlagsFinalPattern = " *uint *" + flagName + " *:?= *(\\d+) *\\{product\\} *";
+
+  public static void testDefaultValue()  throws Exception {
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+      "-XX:+UnlockExperimentalVMOptions", "-XX:+PrintFlagsFinal", "-version");
+
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    String value = output.firstMatch(printFlagsFinalPattern, 1);
+
+    try {
+      Asserts.assertNotNull(value, "Couldn't find uint flag " + flagName);
+
+      Long longValue = new Long(value);
+
+      // Sanity check that we got a non-zero value.
+      Asserts.assertNotEquals(longValue, "0");
+
+      output.shouldHaveExitValue(0);
+    } catch (Exception e) {
+      System.err.println(output.getOutput());
+      throw e;
+    }
+  }
+
+  public static void testFlags() throws Exception {
     // For each parallel collector (G1, Parallel, ParNew/CMS)
     for (String gc : new String[] {"G1", "Parallel", "ConcMarkSweep"}) {
 
@@ -54,6 +85,15 @@
         Asserts.assertEQ(count, i, "Specifying ParallelGCThreads=" + i + " for " + gc + "GC does not set the thread count properly!");
       }
     }
+
+    // 4294967295 == (unsigned int) -1
+    // So setting ParallelGCThreads=4294967295 should give back 4294967295
+    // and setting ParallelGCThreads=4294967296 should give back 0. (SerialGC is ok with ParallelGCThreads=0)
+    for (long i = 4294967295L; i <= 4294967296L; i++) {
+      String[] flags = new String[] {"-XX:+UseSerialGC", "-XX:ParallelGCThreads=" + i, "-XX:+PrintFlagsFinal", "-version"};
+      long count = getParallelGCThreadCount(flags);
+      Asserts.assertEQ(count, i % 4294967296L, "Specifying ParallelGCThreads=" + i + " does not set the thread count properly!");
+    }
   }
 
   public static long getParallelGCThreadCount(String flags[]) throws Exception {
--- a/hotspot/test/gc/arguments/TestSelectDefaultGC.java	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/test/gc/arguments/TestSelectDefaultGC.java	Thu Jun 25 09:48:50 2015 -0700
@@ -36,11 +36,6 @@
 import java.util.regex.*;
 
 public class TestSelectDefaultGC {
-    public static boolean versionStringContains(OutputAnalyzer output, String pattern) {
-        Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(output.getStderr());
-        return matcher.find();
-    }
-
     public static void assertVMOption(OutputAnalyzer output, String option, boolean value) {
         output.shouldMatch(" " + option + " .*=.* " + value + " ");
     }
@@ -51,14 +46,18 @@
         OutputAnalyzer output = new OutputAnalyzer(pb.start());
         output.shouldHaveExitValue(0);
 
-        boolean isServerVM = versionStringContains(output, "Server VM");
+        boolean isServerVM = Platform.isServer();
+        boolean isEmbeddedVM = Platform.isEmbedded();
 
         // Verify GC selection
-        assertVMOption(output, "UseParallelGC",      isServerVM);
-        assertVMOption(output, "UseParallelOldGC",   isServerVM);
+        // G1 is default for non-embedded server VMs
+        assertVMOption(output, "UseG1GC",            isServerVM && !isEmbeddedVM);
+        // Parallel is default for embedded server VMs
+        assertVMOption(output, "UseParallelGC",      isServerVM && isEmbeddedVM);
+        assertVMOption(output, "UseParallelOldGC",   isServerVM && isEmbeddedVM);
+        // Serial is default for non-server VMs
         assertVMOption(output, "UseSerialGC",        !isServerVM);
         assertVMOption(output, "UseConcMarkSweepGC", false);
-        assertVMOption(output, "UseG1GC",            false);
         assertVMOption(output, "UseParNewGC",        false);
     }
 }
--- a/hotspot/test/gc/arguments/TestSurvivorAlignmentInBytesOption.java	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/test/gc/arguments/TestSurvivorAlignmentInBytesOption.java	Thu Jun 25 09:48:50 2015 -0700
@@ -45,9 +45,9 @@
         String optionIsExperimental
                 = CommandLineOptionTest.getExperimentalOptionErrorMessage(
                 optionName);
-        String valueIsTooSmall= ".*SurvivorAlignmentInBytes=.*must be greater"
-                + " than ObjectAlignmentInBytes.*";
-        String mustBePowerOf2 = ".*SurvivorAlignmentInBytes=.*must be "
+        String valueIsTooSmall= ".*SurvivorAlignmentInBytes.*must be greater"
+                + " than or equal to ObjectAlignmentInBytes.*";
+        String mustBePowerOf2 = ".*SurvivorAlignmentInBytes.*must be "
                 + "power of 2.*";
 
         // Verify that without -XX:+UnlockExperimentalVMOptions usage of
--- a/hotspot/test/gc/g1/TestLargePageUseForAuxMemory.java	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/test/gc/g1/TestLargePageUseForAuxMemory.java	Thu Jun 25 09:48:50 2015 -0700
@@ -24,25 +24,28 @@
 /*
  * @test TestLargePageUseForAuxMemory.java
  * @summary Test that auxiliary data structures are allocated using large pages if available.
- * @bug 8058354
+ * @bug 8058354 8079208
  * @key gc
  * @library /testlibrary /../../test/lib
  * @requires (vm.gc=="G1" | vm.gc=="null")
  * @build jdk.test.lib.* sun.hotspot.WhiteBox
  * @build TestLargePageUseForAuxMemory
- * @ignore 8079208
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
  * @run main/othervm -Xbootclasspath/a:. -XX:+UseG1GC -XX:+WhiteBoxAPI -XX:+IgnoreUnrecognizedVMOptions -XX:+UseLargePages TestLargePageUseForAuxMemory
  */
 
+import java.lang.Math;
+
 import jdk.test.lib.*;
+import jdk.test.lib.Asserts;
 import sun.hotspot.WhiteBox;
 
 public class TestLargePageUseForAuxMemory {
-    static final int HEAP_REGION_SIZE = 4 * 1024 * 1024;
+    static final long HEAP_REGION_SIZE = 1 * 1024 * 1024;
     static long largePageSize;
     static long smallPageSize;
+    static long allocGranularity;
 
     static void checkSmallTables(OutputAnalyzer output, long expectedPageSize) throws Exception {
         output.shouldContain("G1 'Block offset table': pg_sz=" + expectedPageSize);
@@ -54,16 +57,18 @@
         output.shouldContain("G1 'Next Bitmap': pg_sz=" + expectedPageSize);
     }
 
-    static void testVM(long heapsize, boolean cardsShouldUseLargePages, boolean bitmapShouldUseLargePages) throws Exception {
+    static void testVM(String what, long heapsize, boolean cardsShouldUseLargePages, boolean bitmapShouldUseLargePages) throws Exception {
+        System.out.println(what + " heapsize " + heapsize + " card table should use large pages " + cardsShouldUseLargePages + " " +
+                           "bitmaps should use large pages " + bitmapShouldUseLargePages);
         ProcessBuilder pb;
         // Test with large page enabled.
         pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
                                                    "-XX:G1HeapRegionSize=" + HEAP_REGION_SIZE,
-                                                   "-Xms" + 10 * HEAP_REGION_SIZE,
+                                                   "-Xms" + heapsize,
                                                    "-Xmx" + heapsize,
                                                    "-XX:+TracePageSizes",
                                                    "-XX:+UseLargePages",
-                                                   "-XX:+IgnoreUnrecognizedVMOptions",  // there is on ObjectAlignmentInBytes in 32 bit builds
+                                                   "-XX:+IgnoreUnrecognizedVMOptions",  // there is no ObjectAlignmentInBytes in 32 bit builds
                                                    "-XX:ObjectAlignmentInBytes=8",
                                                    "-version");
 
@@ -75,11 +80,11 @@
         // Test with large page disabled.
         pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
                                                    "-XX:G1HeapRegionSize=" + HEAP_REGION_SIZE,
-                                                   "-Xms" + 10 * HEAP_REGION_SIZE,
+                                                   "-Xms" + heapsize,
                                                    "-Xmx" + heapsize,
                                                    "-XX:+TracePageSizes",
                                                    "-XX:-UseLargePages",
-                                                   "-XX:+IgnoreUnrecognizedVMOptions",  // there is on ObjectAlignmentInBytes in 32 bit builds
+                                                   "-XX:+IgnoreUnrecognizedVMOptions",  // there is no ObjectAlignmentInBytes in 32 bit builds
                                                    "-XX:ObjectAlignmentInBytes=8",
                                                    "-version");
 
@@ -98,6 +103,7 @@
         WhiteBox wb = WhiteBox.getWhiteBox();
         smallPageSize = wb.getVMPageSize();
         largePageSize = wb.getVMLargePageSize();
+        allocGranularity = wb.getVMAllocationGranularity();
 
         if (largePageSize == 0) {
             System.out.println("Skip tests because large page support does not seem to be available on this platform.");
@@ -112,20 +118,26 @@
             final int cardSize = 512;
 
             final long heapSizeForCardTableUsingLargePages = largePageSize * cardSize;
+            final long heapSizeDiffForCardTable = Math.max(Math.max(allocGranularity * cardSize, HEAP_REGION_SIZE), largePageSize);
 
-            testVM(heapSizeForCardTableUsingLargePages, true, true);
-            testVM(heapSizeForCardTableUsingLargePages + HEAP_REGION_SIZE, true, true);
-            testVM(heapSizeForCardTableUsingLargePages - HEAP_REGION_SIZE, false, true);
+            Asserts.assertGT(heapSizeForCardTableUsingLargePages, heapSizeDiffForCardTable,
+                             "To test we would require to use an invalid heap size");
+            testVM("case1: card table and bitmap use large pages (barely)", heapSizeForCardTableUsingLargePages, true, true);
+            testVM("case2: card table and bitmap use large pages (extra slack)", heapSizeForCardTableUsingLargePages + heapSizeDiffForCardTable, true, true);
+            testVM("case3: only bitmap uses large pages (barely not)", heapSizeForCardTableUsingLargePages - heapSizeDiffForCardTable, false, true);
         }
 
         // Minimum heap requirement to get large pages for bitmaps is 128M heap. This seems okay to test
         // everywhere.
         final int bitmapTranslationFactor = 8 * 8; // ObjectAlignmentInBytes * BitsPerByte
         final long heapSizeForBitmapUsingLargePages = largePageSize * bitmapTranslationFactor;
+        final long heapSizeDiffForBitmap = Math.max(Math.max(allocGranularity * bitmapTranslationFactor, HEAP_REGION_SIZE), largePageSize);
 
-        testVM(heapSizeForBitmapUsingLargePages, false, true);
-        testVM(heapSizeForBitmapUsingLargePages + HEAP_REGION_SIZE, false, true);
-        testVM(heapSizeForBitmapUsingLargePages - HEAP_REGION_SIZE, false, false);
+        Asserts.assertGT(heapSizeForBitmapUsingLargePages, heapSizeDiffForBitmap,
+                         "To test we would require to use an invalid heap size");
+
+        testVM("case4: only bitmap uses large pages (barely)", heapSizeForBitmapUsingLargePages, false, true);
+        testVM("case5: only bitmap uses large pages (extra slack)", heapSizeForBitmapUsingLargePages + heapSizeDiffForBitmap, false, true);
+        testVM("case6: nothing uses large pages (barely not)", heapSizeForBitmapUsingLargePages - heapSizeDiffForBitmap, false, false);
     }
 }
-
--- a/hotspot/test/gc/g1/TestStringDeduplicationTools.java	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/test/gc/g1/TestStringDeduplicationTools.java	Thu Jun 25 09:48:50 2015 -0700
@@ -412,16 +412,14 @@
         output = DeduplicationTest.run(SmallNumberOfStrings,
                                        TooLowAgeThreshold,
                                        YoungGC);
-        output.shouldContain("StringDeduplicationAgeThreshold of " + TooLowAgeThreshold +
-                             " is invalid; must be between " + MinAgeThreshold + " and " + MaxAgeThreshold);
+        output.shouldContain("outside the allowed range");
         output.shouldHaveExitValue(1);
 
         // Test with too high age threshold
         output = DeduplicationTest.run(SmallNumberOfStrings,
                                        TooHighAgeThreshold,
                                        YoungGC);
-        output.shouldContain("StringDeduplicationAgeThreshold of " + TooHighAgeThreshold +
-                             " is invalid; must be between " + MinAgeThreshold + " and " + MaxAgeThreshold);
+        output.shouldContain("outside the allowed range");
         output.shouldHaveExitValue(1);
     }
 
--- a/hotspot/test/gc/survivorAlignment/TestAllocationInEden.java	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/test/gc/survivorAlignment/TestAllocationInEden.java	Thu Jun 25 09:48:50 2015 -0700
@@ -35,42 +35,42 @@
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m
  *                   -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions
- *                   -XX:SurvivorAlignmentInBytes=32 -XX:-UseTLAB
+ *                   -XX:SurvivorAlignmentInBytes=32 -XX:-UseTLAB -XX:-ResizePLAB
  *                   -XX:OldSize=128m -XX:MaxHeapSize=192m
  *                   -XX:-ExplicitGCInvokesConcurrent
  *                   TestAllocationInEden 10m 9 EDEN
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m
  *                   -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions
- *                   -XX:SurvivorAlignmentInBytes=32 -XX:-UseTLAB
+ *                   -XX:SurvivorAlignmentInBytes=32 -XX:-UseTLAB -XX:-ResizePLAB
  *                   -XX:OldSize=128m -XX:MaxHeapSize=192m
  *                   -XX:-ExplicitGCInvokesConcurrent
  *                   TestAllocationInEden 10m 47 EDEN
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m
  *                   -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions
- *                   -XX:SurvivorAlignmentInBytes=64 -XX:-UseTLAB
+ *                   -XX:SurvivorAlignmentInBytes=64 -XX:-UseTLAB -XX:-ResizePLAB
  *                   -XX:OldSize=128m  -XX:MaxHeapSize=192m
  *                   -XX:-ExplicitGCInvokesConcurrent
  *                   TestAllocationInEden 10m 9 EDEN
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m
  *                   -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions
- *                   -XX:SurvivorAlignmentInBytes=64 -XX:-UseTLAB
+ *                   -XX:SurvivorAlignmentInBytes=64 -XX:-UseTLAB -XX:-ResizePLAB
  *                   -XX:OldSize=128m  -XX:MaxHeapSize=192m
  *                   -XX:-ExplicitGCInvokesConcurrent
  *                   TestAllocationInEden 10m 87 EDEN
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m
  *                   -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions
- *                   -XX:SurvivorAlignmentInBytes=128 -XX:-UseTLAB
+ *                   -XX:SurvivorAlignmentInBytes=128 -XX:-UseTLAB -XX:-ResizePLAB
  *                   -XX:OldSize=128m -XX:MaxHeapSize=192m
  *                   -XX:-ExplicitGCInvokesConcurrent
  *                   TestAllocationInEden 10m 9 EDEN
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m
  *                   -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions
- *                   -XX:SurvivorAlignmentInBytes=128 -XX:-UseTLAB
+ *                   -XX:SurvivorAlignmentInBytes=128 -XX:-UseTLAB -XX:-ResizePLAB
  *                   -XX:OldSize=128m -XX:MaxHeapSize=192m
  *                   -XX:-ExplicitGCInvokesConcurrent
  *                   TestAllocationInEden 10m 147 EDEN
--- a/hotspot/test/gc/survivorAlignment/TestPromotionFromEdenToTenured.java	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/test/gc/survivorAlignment/TestPromotionFromEdenToTenured.java	Thu Jun 25 09:48:50 2015 -0700
@@ -36,42 +36,42 @@
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m
  *                   -XX:OldSize=32m -XX:MaxHeapSize=96m -XX:SurvivorRatio=1
- *                   -XX:-ExplicitGCInvokesConcurrent
+ *                   -XX:-ExplicitGCInvokesConcurrent -XX:-ResizePLAB
  *                   -XX:+UnlockExperimentalVMOptions
  *                   -XX:SurvivorAlignmentInBytes=32
  *                   TestPromotionFromEdenToTenured 10m 9 TENURED
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m
  *                   -XX:OldSize=32m -XX:MaxHeapSize=96m -XX:SurvivorRatio=1
- *                   -XX:-ExplicitGCInvokesConcurrent
+ *                   -XX:-ExplicitGCInvokesConcurrent -XX:-ResizePLAB
  *                   -XX:+UnlockExperimentalVMOptions
  *                   -XX:SurvivorAlignmentInBytes=32
  *                   TestPromotionFromEdenToTenured 10m 47 TENURED
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m
  *                   -XX:OldSize=32m  -XX:MaxHeapSize=96m
- *                   -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent
+ *                   -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent -XX:-ResizePLAB
  *                   -XX:+UnlockExperimentalVMOptions
  *                   -XX:SurvivorAlignmentInBytes=64
  *                   TestPromotionFromEdenToTenured 10m 9 TENURED
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m
  *                   -XX:OldSize=32m -XX:MaxHeapSize=128m
- *                   -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent
+ *                   -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent -XX:-ResizePLAB
  *                   -XX:+UnlockExperimentalVMOptions
  *                   -XX:SurvivorAlignmentInBytes=64
  *                   TestPromotionFromEdenToTenured 10m 87 TENURED
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m
  *                   -XX:OldSize=32M -XX:MaxHeapSize=96m -XX:SurvivorRatio=1
- *                   -XX:-ExplicitGCInvokesConcurrent
+ *                   -XX:-ExplicitGCInvokesConcurrent -XX:-ResizePLAB
  *                   -XX:+UnlockExperimentalVMOptions
  *                   -XX:SurvivorAlignmentInBytes=128
  *                   TestPromotionFromEdenToTenured 10m 9 TENURED
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m
  *                   -XX:OldSize=32m -XX:MaxHeapSize=96m -XX:SurvivorRatio=1
- *                   -XX:-ExplicitGCInvokesConcurrent
+ *                   -XX:-ExplicitGCInvokesConcurrent -XX:-ResizePLAB
  *                   -XX:+UnlockExperimentalVMOptions
  *                   -XX:SurvivorAlignmentInBytes=128
  *                   TestPromotionFromEdenToTenured 10m 147 TENURED
--- a/hotspot/test/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterFullGC.java	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/test/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterFullGC.java	Thu Jun 25 09:48:50 2015 -0700
@@ -36,13 +36,13 @@
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m
  *                   -XX:OldSize=32m -XX:MaxHeapSize=160m
- *                   -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent
+ *                   -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent -XX:-ResizePLAB
  *                   -XX:+UnlockExperimentalVMOptions
  *                   -XX:SurvivorAlignmentInBytes=32
  *                   TestPromotionFromSurvivorToTenuredAfterFullGC 10m 9 TENURED
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m
- *                   -XX:OldSize=32m -XX:MaxHeapSize=160m
+ *                   -XX:OldSize=32m -XX:MaxHeapSize=160m -XX:-ResizePLAB
  *                   -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent
  *                   -XX:+UnlockExperimentalVMOptions
  *                   -XX:SurvivorAlignmentInBytes=32
@@ -51,14 +51,14 @@
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:NewSize=200m -XX:MaxNewSize=200m
  *                   -XX:OldSize=32m -XX:MaxHeapSize=232m
- *                   -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent
+ *                   -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent -XX:-ResizePLAB
  *                   -XX:+UnlockExperimentalVMOptions
  *                   -XX:SurvivorAlignmentInBytes=64
  *                   TestPromotionFromSurvivorToTenuredAfterFullGC 10m 9 TENURED
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m
  *                   -XX:OldSize=32m -XX:MaxHeapSize=160m
- *                   -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent
+ *                   -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent -XX:-ResizePLAB
  *                   -XX:+UnlockExperimentalVMOptions
  *                   -XX:SurvivorAlignmentInBytes=64
  *                   TestPromotionFromSurvivorToTenuredAfterFullGC 20m 87
@@ -66,7 +66,7 @@
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:NewSize=256m -XX:MaxNewSize=256m
  *                   -XX:OldSize=32M -XX:MaxHeapSize=288m
- *                   -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent
+ *                   -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent -XX:-ResizePLAB
  *                   -XX:+UnlockExperimentalVMOptions
  *                   -XX:SurvivorAlignmentInBytes=128
  *                    TestPromotionFromSurvivorToTenuredAfterFullGC 10m 9
@@ -74,7 +74,7 @@
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m
  *                   -XX:OldSize=32m -XX:MaxHeapSize=160m
- *                   -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent
+ *                   -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent -XX:-ResizePLAB
  *                   -XX:+UnlockExperimentalVMOptions
  *                   -XX:SurvivorAlignmentInBytes=128
  *                   TestPromotionFromSurvivorToTenuredAfterFullGC 20m 147
--- a/hotspot/test/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterMinorGC.java	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/test/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterMinorGC.java	Thu Jun 25 09:48:50 2015 -0700
@@ -36,7 +36,7 @@
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m
- *                   -XX:OldSize=32M -XX:MaxHeapSize=160m -XX:SurvivorRatio=1
+ *                   -XX:OldSize=32M -XX:MaxHeapSize=160m -XX:SurvivorRatio=1 -XX:-ResizePLAB
  *                   -XX:-ExplicitGCInvokesConcurrent
  *                   -XX:+UnlockExperimentalVMOptions
  *                   -XX:SurvivorAlignmentInBytes=32
@@ -44,7 +44,7 @@
  *                   TENURED
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m
- *                   -XX:OldSize=32M -XX:MaxHeapSize=160m -XX:SurvivorRatio=1
+ *                   -XX:OldSize=32M -XX:MaxHeapSize=160m -XX:SurvivorRatio=1 -XX:-ResizePLAB
  *                   -XX:-ExplicitGCInvokesConcurrent
  *                   -XX:+UnlockExperimentalVMOptions
  *                   -XX:SurvivorAlignmentInBytes=32
@@ -52,7 +52,7 @@
  *                   TENURED
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:NewSize=200m -XX:MaxNewSize=200m
- *                   -XX:OldSize=32M -XX:MaxHeapSize=232m -XX:SurvivorRatio=1
+ *                   -XX:OldSize=32M -XX:MaxHeapSize=232m -XX:SurvivorRatio=1 -XX:-ResizePLAB
  *                   -XX:-ExplicitGCInvokesConcurrent
  *                   -XX:+UnlockExperimentalVMOptions
  *                   -XX:SurvivorAlignmentInBytes=64
@@ -60,7 +60,7 @@
  *                   TENURED
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m
- *                   -XX:OldSize=32M -XX:MaxHeapSize=160m -XX:SurvivorRatio=1
+ *                   -XX:OldSize=32M -XX:MaxHeapSize=160m -XX:SurvivorRatio=1 -XX:-ResizePLAB
  *                   -XX:-ExplicitGCInvokesConcurrent
  *                   -XX:+UnlockExperimentalVMOptions
  *                   -XX:SurvivorAlignmentInBytes=64
@@ -68,7 +68,7 @@
  *                   TENURED
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:NewSize=256m -XX:MaxNewSize=256m
- *                   -XX:OldSize=32M -XX:MaxHeapSize=288m -XX:SurvivorRatio=1
+ *                   -XX:OldSize=32M -XX:MaxHeapSize=288m -XX:SurvivorRatio=1 -XX:-ResizePLAB
  *                   -XX:-ExplicitGCInvokesConcurrent
  *                   -XX:+UnlockExperimentalVMOptions
  *                   -XX:SurvivorAlignmentInBytes=128
@@ -76,7 +76,7 @@
  *                    TENURED
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m
- *                   -XX:OldSize=32M -XX:MaxHeapSize=160m -XX:SurvivorRatio=1
+ *                   -XX:OldSize=32M -XX:MaxHeapSize=160m -XX:SurvivorRatio=1 -XX:-ResizePLAB
  *                   -XX:-ExplicitGCInvokesConcurrent
  *                   -XX:+UnlockExperimentalVMOptions
  *                   -XX:SurvivorAlignmentInBytes=128
--- a/hotspot/test/gc/survivorAlignment/TestPromotionToSurvivor.java	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/test/gc/survivorAlignment/TestPromotionToSurvivor.java	Thu Jun 25 09:48:50 2015 -0700
@@ -37,37 +37,37 @@
  *                   -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m
  *                   -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions
  *                   -XX:SurvivorAlignmentInBytes=32 -XX:OldSize=128m
- *                   -XX:MaxHeapSize=256m -XX:-ExplicitGCInvokesConcurrent
+ *                   -XX:MaxHeapSize=256m -XX:-ExplicitGCInvokesConcurrent -XX:-ResizePLAB
  *                   TestPromotionToSurvivor 10m 9 SURVIVOR
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m
  *                   -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions
  *                   -XX:SurvivorAlignmentInBytes=32 -XX:OldSize=128m
- *                   -XX:MaxHeapSize=256m -XX:-ExplicitGCInvokesConcurrent
+ *                   -XX:MaxHeapSize=256m -XX:-ExplicitGCInvokesConcurrent -XX:-ResizePLAB
  *                   TestPromotionToSurvivor 20m 47 SURVIVOR
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m
  *                   -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions
  *                   -XX:SurvivorAlignmentInBytes=64 -XX:OldSize=128m
- *                   -XX:MaxHeapSize=256m -XX:-ExplicitGCInvokesConcurrent
+ *                   -XX:MaxHeapSize=256m -XX:-ExplicitGCInvokesConcurrent -XX:-ResizePLAB
  *                   TestPromotionToSurvivor 8m 9 SURVIVOR
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m
  *                   -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions
  *                   -XX:SurvivorAlignmentInBytes=64 -XX:OldSize=128m
- *                   -XX:MaxHeapSize=256m -XX:-ExplicitGCInvokesConcurrent
+ *                   -XX:MaxHeapSize=256m -XX:-ExplicitGCInvokesConcurrent -XX:-ResizePLAB
  *                   TestPromotionToSurvivor 20m 87 SURVIVOR
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:NewSize=256m -XX:MaxNewSize=256m
  *                   -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions
  *                   -XX:SurvivorAlignmentInBytes=128 -XX:OldSize=128m
- *                   -XX:MaxHeapSize=384m  -XX:-ExplicitGCInvokesConcurrent
+ *                   -XX:MaxHeapSize=384m  -XX:-ExplicitGCInvokesConcurrent -XX:-ResizePLAB
  *                   TestPromotionToSurvivor 10m 9 SURVIVOR
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m
  *                   -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions
  *                   -XX:SurvivorAlignmentInBytes=128 -XX:OldSize=128m
- *                   -XX:MaxHeapSize=256m -XX:-ExplicitGCInvokesConcurrent
+ *                   -XX:MaxHeapSize=256m -XX:-ExplicitGCInvokesConcurrent -XX:-ResizePLAB
  *                   TestPromotionToSurvivor 20m 147 SURVIVOR
  */
 public class TestPromotionToSurvivor {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/CommandLine/OptionsValidation/TestJcmdOutput.java	Thu Jun 25 09:48:50 2015 -0700
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2015, 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
+ * @summary Verify jcmd error message for out-of-range value and for
+ *          value which is not allowed by constraint. Also check that
+ *          jcmd does not print an error message to the target process output.
+ * @library /testlibrary
+ * @modules java.base/sun.misc
+ *          java.management
+ *          jdk.management
+ * @run main TestJcmdOutput
+ */
+
+import jdk.test.lib.Asserts;
+import jdk.test.lib.DynamicVMOption;
+import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.ProcessTools;
+import jdk.test.lib.dcmd.PidJcmdExecutor;
+
+public class TestJcmdOutput {
+
+    /* Message printed by jcmd for value which is out-of-range */
+    static final String JCMD_OUT_OF_RANGE_MESSAGE = "error: must have value in range";
+    /* Message printed by jcmd for value which is not allowed by constraint */
+    static final String JCMD_CONSTRAINT_MESSAGE = "value violates its flag's constraint";
+
+    public static void main(String[] args) throws Exception {
+        OutputAnalyzer output;
+
+        System.out.println("Verify jcmd error message and that jcmd does not write errors to the target process output");
+        output = new OutputAnalyzer((ProcessTools.createJavaProcessBuilder(
+                "-Dtest.jdk=" + System.getProperty("test.jdk"),
+                "-XX:MinHeapFreeRatio=20", "-XX:MaxHeapFreeRatio=80", runJcmd.class.getName())).start());
+
+        output.shouldHaveExitValue(0);
+        /* Verify that jcmd not print error message to the target process output */
+        output.shouldNotContain(JCMD_OUT_OF_RANGE_MESSAGE);
+        output.shouldNotContain(JCMD_CONSTRAINT_MESSAGE);
+    }
+
+    public static class runJcmd {
+
+        public static void main(String[] args) throws Exception {
+            int minHeapFreeRatio = new Integer((new DynamicVMOption("MinHeapFreeRatio")).getValue());
+            int maxHeapFreeRatio = new Integer((new DynamicVMOption("MaxHeapFreeRatio")).getValue());
+            PidJcmdExecutor executor = new PidJcmdExecutor();
+
+            Asserts.assertGT(minHeapFreeRatio, 0, "MinHeapFreeRatio must be greater than 0");
+            Asserts.assertLT(maxHeapFreeRatio, 100, "MaxHeapFreeRatio must be less than 100");
+
+            /* Check out-of-range values */
+            executor.execute("VM.set_flag MinHeapFreeRatio -1", true).shouldContain(JCMD_OUT_OF_RANGE_MESSAGE);
+            executor.execute("VM.set_flag MaxHeapFreeRatio 101", true).shouldContain(JCMD_OUT_OF_RANGE_MESSAGE);
+
+            /* Check values which not allowed by constraint */
+            executor.execute(
+                    String.format("VM.set_flag MinHeapFreeRatio %d", maxHeapFreeRatio + 1), true)
+                    .shouldContain(JCMD_CONSTRAINT_MESSAGE);
+            executor.execute(
+                    String.format("VM.set_flag MaxHeapFreeRatio %d", minHeapFreeRatio - 1), true)
+                    .shouldContain(JCMD_CONSTRAINT_MESSAGE);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java	Thu Jun 25 09:48:50 2015 -0700
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2015, 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
+ * @summary Test VM Options with ranges
+ * @library /testlibrary /runtime/CommandLine/OptionsValidation/common
+ * @modules java.base/sun.misc
+ *          java.management
+ *          jdk.attach
+ *          jdk.management/sun.tools.attach
+ * @run main/othervm/timeout=600 TestOptionsWithRanges
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import jdk.test.lib.Asserts;
+import optionsvalidation.JVMOption;
+import optionsvalidation.JVMOptionsUtils;
+
+public class TestOptionsWithRanges {
+
+    public static void main(String[] args) throws Exception {
+        int failedTests;
+        Map<String, JVMOption> allOptionsAsMap = JVMOptionsUtils.getOptionsWithRangeAsMap();
+        List<JVMOption> allOptions;
+
+        /*
+         * Remove CICompilerCount from testing because currently it can hang system
+         */
+        allOptionsAsMap.remove("CICompilerCount");
+
+        allOptions = new ArrayList<>(allOptionsAsMap.values());
+
+        Asserts.assertGT(allOptions.size(), 0, "Options with ranges not found!");
+
+        System.out.println("Parsed " + allOptions.size() + " options with ranges. Start test!");
+
+        failedTests = JVMOptionsUtils.runCommandLineTests(allOptions);
+
+        Asserts.assertEQ(failedTests, 0,
+                String.format("%d tests failed! %s", failedTests, JVMOptionsUtils.getMessageWithFailures()));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRangesDynamic.java	Thu Jun 25 09:48:50 2015 -0700
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2015, 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
+ * @summary Test writeable VM Options with ranges.
+ * @library /testlibrary /runtime/CommandLine/OptionsValidation/common
+ * @modules java.base/sun.misc
+ *          java.management
+ *          jdk.attach
+ *          jdk.management/sun.tools.attach
+ * @run main/othervm -XX:MinHeapFreeRatio=0 -XX:MaxHeapFreeRatio=100 TestOptionsWithRangesDynamic
+ */
+
+import java.util.List;
+import jdk.test.lib.Asserts;
+import optionsvalidation.JVMOption;
+import optionsvalidation.JVMOptionsUtils;
+
+public class TestOptionsWithRangesDynamic {
+
+    public static void main(String[] args) throws Exception {
+        int failedTests;
+        List<JVMOption> allWriteableOptions;
+
+        /* Get only writeable options */
+        allWriteableOptions = JVMOptionsUtils.getOptionsWithRange(origin -> (origin.contains("manageable") || origin.contains("rw")));
+
+        Asserts.assertGT(allWriteableOptions.size(), 0, "Options with ranges not found!");
+
+        System.out.println("Test " + allWriteableOptions.size() + " writeable options with ranges. Start test!");
+
+        failedTests = JVMOptionsUtils.runDynamicTests(allWriteableOptions);
+
+        failedTests += JVMOptionsUtils.runJcmdTests(allWriteableOptions);
+
+        failedTests += JVMOptionsUtils.runAttachTests(allWriteableOptions);
+
+        Asserts.assertEQ(failedTests, 0,
+                String.format("%d tests failed! %s", failedTests, JVMOptionsUtils.getMessageWithFailures()));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/DoubleJVMOption.java	Thu Jun 25 09:48:50 2015 -0700
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+package optionsvalidation;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class DoubleJVMOption extends JVMOption {
+
+    /**
+     * Additional double values to test
+     */
+    private static final double ADDITIONAL_TEST_DOUBLE_NEGATIVE = -1.5;
+    private static final double ADDITIONAL_TEST_DOUBLE_ZERO = 0.0;
+    private static final double ADDITIONAL_TEST_DOUBLE_POSITIVE = 1.75;
+
+    /**
+     * Mininum option value
+     */
+    private double min;
+    /**
+     * Maximum option value
+     */
+    private double max;
+
+    /**
+     * Initialize double option with passed name
+     *
+     * @param name name of the option
+     */
+    DoubleJVMOption(String name) {
+        this.name = name;
+        min = Double.MIN_VALUE;
+        max = Double.MAX_VALUE;
+    }
+
+    /**
+     * Initialize double option with passed name, min and max values
+     *
+     * @param name name of the option
+     * @param min minimum value of the option
+     * @param max maximum value of the option
+     */
+    public DoubleJVMOption(String name, double min, double max) {
+        this(name);
+        this.min = min;
+        this.max = max;
+    }
+
+    /**
+     * Set new minimum option value
+     *
+     * @param min new minimum value
+     */
+    @Override
+    void setMin(String min) {
+        this.min = new Double(min);
+    }
+
+    /**
+     * Get string with minimum value of the option
+     *
+     * @return string with minimum value of the option
+     */
+    @Override
+    String getMin() {
+        return formatValue(min);
+    }
+
+    /**
+     * Set new maximum option value
+     *
+     * @param max new maximum value
+     */
+    @Override
+    void setMax(String max) {
+        this.max = new Double(max);
+    }
+
+    /**
+     * Get string with maximum value of the option
+     *
+     * @return string with maximum value of the option
+     */
+    @Override
+    String getMax() {
+        return formatValue(max);
+    }
+
+    private String formatValue(double value) {
+        return String.format("%f", value);
+    }
+
+    /**
+     * Return list of strings with valid option values which used for testing
+     * using jcmd, attach and etc.
+     *
+     * @return list of strings which contain valid values for option
+     */
+    @Override
+    protected List<String> getValidValues() {
+        List<String> validValues = new ArrayList<>();
+
+        validValues.add(formatValue(min));
+        validValues.add(formatValue(max));
+
+        if ((Double.compare(min, ADDITIONAL_TEST_DOUBLE_NEGATIVE) < 0)
+                && (Double.compare(max, ADDITIONAL_TEST_DOUBLE_NEGATIVE) > 0)) {
+            validValues.add(formatValue(ADDITIONAL_TEST_DOUBLE_NEGATIVE));
+        }
+
+        if ((Double.compare(min, ADDITIONAL_TEST_DOUBLE_ZERO) < 0)
+                && (Double.compare(max, ADDITIONAL_TEST_DOUBLE_ZERO) > 0)) {
+            validValues.add(formatValue(ADDITIONAL_TEST_DOUBLE_ZERO));
+        }
+
+        if ((Double.compare(min, ADDITIONAL_TEST_DOUBLE_POSITIVE) < 0)
+                && (Double.compare(max, ADDITIONAL_TEST_DOUBLE_POSITIVE) > 0)) {
+            validValues.add(formatValue(ADDITIONAL_TEST_DOUBLE_POSITIVE));
+        }
+
+        return validValues;
+    }
+
+    /**
+     * Return list of strings with invalid option values which used for testing
+     * using jcmd, attach and etc.
+     *
+     * @return list of strings which contain invalid values for option
+     */
+    @Override
+    protected List<String> getInvalidValues() {
+        List<String> invalidValues = new ArrayList<>();
+
+        if (withRange) {
+            /* Return invalid values only for options which have defined range in VM */
+            if (Double.compare(min, Double.MIN_VALUE) != 0) {
+                if ((Double.compare(min, 0.0) > 0)
+                        && (Double.isNaN(min * 0.999) == false)) {
+                    invalidValues.add(formatValue(min * 0.999));
+                } else if ((Double.compare(min, 0.0) < 0)
+                        && (Double.isNaN(min * 1.001) == false)) {
+                    invalidValues.add(formatValue(min * 1.001));
+                }
+            }
+
+            if (Double.compare(max, Double.MAX_VALUE) != 0) {
+                if ((Double.compare(max, 0.0) > 0)
+                        && (Double.isNaN(max * 1.001) == false)) {
+                    invalidValues.add(formatValue(max * 1.001));
+                } else if ((Double.compare(max, 0.0) < 0)
+                        && (Double.isNaN(max * 0.999) == false)) {
+                    invalidValues.add(formatValue(max * 0.999));
+                }
+            }
+        }
+
+        return invalidValues;
+    }
+
+    /**
+     * Return expected error message for option with value "value" when it used
+     * on command line with passed value
+     *
+     * @param value option value
+     * @return expected error message
+     */
+    @Override
+    protected String getErrorMessageCommandLine(String value) {
+        String errorMsg;
+
+        if (withRange) {
+            /* Option have defined range in VM */
+            errorMsg = "is outside the allowed range";
+        } else {
+            errorMsg = "";
+        }
+
+        return errorMsg;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/IntJVMOption.java	Thu Jun 25 09:48:50 2015 -0700
@@ -0,0 +1,309 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+package optionsvalidation;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import jdk.test.lib.Platform;
+
+public class IntJVMOption extends JVMOption {
+
+    private static final BigInteger MIN_LONG;
+    private static final BigInteger MAX_LONG;
+    private static final BigInteger MAX_UNSIGNED_LONG;
+    private static final BigInteger MAX_UNSIGNED_LONG_64;
+    private static final BigInteger MINUS_ONE = new BigInteger("-1");
+    private static final BigInteger TWO = new BigInteger("2");
+    private static final BigInteger MIN_4_BYTE_INT = new BigInteger("-2147483648");
+    private static final BigInteger MAX_4_BYTE_INT = new BigInteger("2147483647");
+    private static final BigInteger MAX_4_BYTE_INT_PLUS_ONE = new BigInteger("2147483648");
+    private static final BigInteger MAX_4_BYTE_UNSIGNED_INT = new BigInteger("4294967295");
+    private static final BigInteger MAX_4_BYTE_UNSIGNED_INT_PLUS_ONE = new BigInteger("4294967296");
+
+    /**
+     * Mininum option value
+     */
+    private BigInteger min;
+
+    /**
+     * Maximum option value
+     */
+    private BigInteger max;
+
+    /**
+     * Option type: intx, uintx, size_t or uint64_t
+     */
+    private String type;
+
+    /**
+     * Is this value signed or unsigned
+     */
+    private boolean unsigned;
+
+    /**
+     * Is this 32 bit type
+     */
+    private boolean is32Bit = false;
+
+    /**
+     * Is this value 64 bit unsigned
+     */
+    private boolean uint64 = false;
+
+    static {
+        if (Platform.is32bit()) {
+            MIN_LONG = new BigInteger(String.valueOf(Integer.MIN_VALUE));
+            MAX_LONG = new BigInteger(String.valueOf(Integer.MAX_VALUE));
+            MAX_UNSIGNED_LONG = MAX_LONG.multiply(TWO).add(BigInteger.ONE);
+        } else {
+            MIN_LONG = new BigInteger(String.valueOf(Long.MIN_VALUE));
+            MAX_LONG = new BigInteger(String.valueOf(Long.MAX_VALUE));
+            MAX_UNSIGNED_LONG = MAX_LONG.multiply(TWO).add(BigInteger.ONE);
+        }
+
+        MAX_UNSIGNED_LONG_64 = (new BigInteger(String.valueOf(Long.MAX_VALUE)))
+                .multiply(TWO).add(BigInteger.ONE);
+    }
+
+    private IntJVMOption() {
+        type = "";
+    }
+
+    /**
+     * Initialize new integer option with given type. Type can be: INTX -
+     * integer signed option UINTX - unsigned integer option UINT64_T - unsigned
+     * 64 bit integer option
+     *
+     * @param name name of the option
+     * @param type type of the option
+     */
+    IntJVMOption(String name, String type) {
+        this.name = name;
+        this.type = type;
+
+        switch (type) {
+            case "uint64_t":
+                unsigned = true;
+                uint64 = true;
+                max = MAX_UNSIGNED_LONG_64;
+                break;
+            case "uintx":
+            case "size_t":
+                unsigned = true;
+                max = MAX_UNSIGNED_LONG;
+                break;
+            case "uint":
+                unsigned = true;
+                is32Bit = true;
+                max = MAX_4_BYTE_UNSIGNED_INT;
+                break;
+            case "int":
+                min = MIN_4_BYTE_INT;
+                max = MAX_4_BYTE_INT;
+                is32Bit = true;
+                break;
+            default:
+                min = MIN_LONG;
+                max = MAX_LONG;
+                break;
+        }
+
+        if (unsigned) {
+            min = BigInteger.ZERO;
+        }
+    }
+
+    /**
+     * Initialize integer option with passed name, min and max values. Min and
+     * max are string because they can be very big, bigger than long.
+     *
+     * @param name name of the option
+     * @param min minimum value of the option
+     * @param max maximum value of the option
+     */
+    public IntJVMOption(String name, String min, String max) {
+        this();
+        this.name = name;
+        this.min = new BigInteger(min);
+        this.max = new BigInteger(max);
+    }
+
+    /**
+     * Set new minimum option value
+     *
+     * @param min new minimum value
+     */
+    @Override
+    void setMin(String min) {
+        this.min = new BigInteger(min);
+    }
+
+    /**
+     * Get string with minimum value of the option
+     *
+     * @return string with minimum value of the option
+     */
+    @Override
+    String getMin() {
+        return min.toString();
+    }
+
+    /**
+     * Set new maximum option value
+     *
+     * @param max new maximum value
+     */
+    @Override
+    void setMax(String max) {
+        this.max = new BigInteger(max);
+    }
+
+    /**
+     * Get string with maximum value of the option
+     *
+     * @return string with maximum value of the option
+     */
+    @Override
+    String getMax() {
+        return max.toString();
+    }
+
+    /**
+     * Return list of strings with valid option values which used for testing
+     * using jcmd, attach and etc.
+     *
+     * @return list of strings which contain valid values for option
+     */
+    @Override
+    protected List<String> getValidValues() {
+        List<String> validValues = new ArrayList<>();
+
+        validValues.add(min.toString());
+        validValues.add(max.toString());
+
+        if ((min.compareTo(MINUS_ONE) == -1) && (max.compareTo(MINUS_ONE) == 1)) {
+            /*
+             * Add -1 as valid value if min is less than -1 and max is greater than -1
+             */
+            validValues.add("-1");
+        }
+
+        if ((min.compareTo(BigInteger.ZERO) == -1) && (max.compareTo(BigInteger.ZERO) == 1)) {
+            /*
+             * Add 0 as valid value if min is less than 0 and max is greater than 0
+             */
+            validValues.add("0");
+        }
+        if ((min.compareTo(BigInteger.ONE) == -1) && (max.compareTo(BigInteger.ONE) == 1)) {
+            /*
+             * Add 1 as valid value if min is less than 1 and max is greater than 1
+             */
+            validValues.add("1");
+        }
+
+        if (max.compareTo(MAX_4_BYTE_INT_PLUS_ONE) == 1) {
+            /*
+             * Check for overflow when flag is assigned to the
+             * 4 byte int variable
+             */
+            validValues.add(MAX_4_BYTE_INT_PLUS_ONE.toString());
+        }
+
+        if (max.compareTo(MAX_4_BYTE_UNSIGNED_INT_PLUS_ONE) == 1) {
+            /*
+             * Check for overflow when flag is assigned to the
+             * 4 byte unsigned int variable
+             */
+            validValues.add(MAX_4_BYTE_UNSIGNED_INT_PLUS_ONE.toString());
+        }
+
+        return validValues;
+    }
+
+    /**
+     * Return list of strings with invalid option values which used for testing
+     * using jcmd, attach and etc.
+     *
+     * @return list of strings which contain invalid values for option
+     */
+    @Override
+    protected List<String> getInvalidValues() {
+        List<String> invalidValues = new ArrayList<>();
+
+        if (withRange) {
+            /* Return invalid values only for options which have defined range in VM */
+            if ((is32Bit && min.compareTo(MIN_4_BYTE_INT) != 0)
+                    || (!is32Bit && min.compareTo(MIN_LONG) != 0)) {
+                invalidValues.add(min.subtract(BigInteger.ONE).toString());
+            }
+
+            if (!unsigned
+                    && ((is32Bit && (max.compareTo(MAX_4_BYTE_INT) != 0))
+                    || (!is32Bit && (max.compareTo(MAX_LONG) != 0)))) {
+                invalidValues.add(max.add(BigInteger.ONE).toString());
+            }
+
+            if (unsigned
+                    && ((is32Bit && (max.compareTo(MAX_4_BYTE_UNSIGNED_INT) != 0))
+                    || (!is32Bit && !uint64 && (max.compareTo(MAX_UNSIGNED_LONG) != 0))
+                    || (uint64 && (max.compareTo(MAX_UNSIGNED_LONG_64) != 0)))) {
+                invalidValues.add(max.add(BigInteger.ONE).toString());
+            }
+        }
+
+        return invalidValues;
+    }
+
+    /**
+     * Return expected error message for option with value "value" when it used
+     * on command line with passed value
+     *
+     * @param value Option value
+     * @return expected error message
+     */
+    @Override
+    protected String getErrorMessageCommandLine(String value) {
+        String errorMsg;
+
+        if (withRange) {
+            /* Option have defined range in VM */
+            if (unsigned && ((new BigInteger(value)).compareTo(BigInteger.ZERO) < 0)) {
+                /*
+                 * Special case for unsigned options with lower range equal to 0. If
+                 * passed value is negative then error will be caught earlier for
+                 * such options. Thus use different error message.
+                 */
+                errorMsg = String.format("Improperly specified VM option '%s=%s'", name, value);
+            } else {
+                errorMsg = String.format("%s %s=%s is outside the allowed range [ %s ... %s ]",
+                        type, name, value, min.toString(), max.toString());
+            }
+        } else {
+            errorMsg = "";
+        }
+
+        return errorMsg;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOption.java	Thu Jun 25 09:48:50 2015 -0700
@@ -0,0 +1,477 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+package optionsvalidation;
+
+import com.sun.tools.attach.VirtualMachine;
+import com.sun.tools.attach.AttachOperationFailedException;
+import java.util.ArrayList;
+import java.util.List;
+import jdk.test.lib.DynamicVMOption;
+import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.ProcessTools;
+import jdk.test.lib.dcmd.CommandExecutor;
+import jdk.test.lib.dcmd.JMXExecutor;
+import sun.tools.attach.HotSpotVirtualMachine;
+
+import static optionsvalidation.JVMOptionsUtils.failedMessage;
+import static optionsvalidation.JVMOptionsUtils.printOutputContent;
+import static optionsvalidation.JVMOptionsUtils.VMType;
+
+public abstract class JVMOption {
+
+    /**
+     * Executor for JCMD
+     */
+    private final static CommandExecutor executor = new JMXExecutor();
+
+    /**
+     * Name of the tested parameter
+     */
+    protected String name;
+
+    /**
+     * Range is defined for option inside VM
+     */
+    protected boolean withRange;
+
+    /**
+     * Prepend string which added before testing option to the command line
+     */
+    private final List<String> prepend;
+    private final StringBuilder prependString;
+
+    protected JVMOption() {
+        this.prepend = new ArrayList<>();
+        prependString = new StringBuilder();
+        withRange = false;
+    }
+
+    /**
+     * Create JVM Option with given type and name.
+     *
+     * @param type type: "intx", "size_t", "uintx", "uint64_t" or "double"
+     * @param name name of the option
+     * @return created JVMOption
+     */
+    static JVMOption createVMOption(String type, String name) {
+        JVMOption parameter;
+
+        switch (type) {
+            case "int":
+            case "intx":
+            case "size_t":
+            case "uint":
+            case "uintx":
+            case "uint64_t":
+                parameter = new IntJVMOption(name, type);
+                break;
+            case "double":
+                parameter = new DoubleJVMOption(name);
+                break;
+            default:
+                throw new Error("Expected only \"int\", \"intx\", \"size_t\", "
+                        + "\"uint\", \"uintx\", \"uint64_t\", or \"double\" "
+                        + "option types! Got " + type + " type!");
+        }
+
+        return parameter;
+    }
+
+    /**
+     * Add passed options to the prepend options of the option. Prepend options
+     * will be added before testing option to the command line.
+     *
+     * @param options array of prepend options
+     */
+    public final void addPrepend(String... options) {
+        String toAdd;
+
+        for (String option : options) {
+            if (option.startsWith("-")) {
+                toAdd = option;
+            } else {
+                /* Add "-" before parameter name */
+                toAdd = "-" + option;
+
+            }
+            prepend.add(toAdd);
+            prependString.append(toAdd).append(" ");
+        }
+    }
+
+    /**
+     * Get name of the option
+     *
+     * @return name of the option
+     */
+    final String getName() {
+        return name;
+    }
+
+    /**
+     * Mark this option as option which range is defined inside VM
+     */
+    final void optionWithRange() {
+        withRange = true;
+    }
+
+    /**
+     * Set new minimum option value
+     *
+     * @param min new minimum value
+     */
+    abstract void setMin(String min);
+
+    /**
+     * Get string with minimum value of the option
+     *
+     * @return string with minimum value of the option
+     */
+    abstract String getMin();
+
+    /**
+     * Set new maximum option value
+     *
+     * @param max new maximum value
+     */
+    abstract void setMax(String min);
+
+    /**
+     * Get string with maximum value of the option
+     *
+     * @return string with maximum value of the option
+     */
+    abstract String getMax();
+
+    /**
+     * Return list of strings with valid option values which used for testing
+     * using jcmd, attach and etc.
+     *
+     * @return list of strings which contain valid values for option
+     */
+    protected abstract List<String> getValidValues();
+
+    /**
+     * Return list of strings with invalid option values which used for testing
+     * using jcmd, attach and etc.
+     *
+     * @return list of strings which contain invalid values for option
+     */
+    protected abstract List<String> getInvalidValues();
+
+    /**
+     * Return expected error message for option with value "value" when it used
+     * on command line with passed value
+     *
+     * @param value option value
+     * @return expected error message
+     */
+    protected abstract String getErrorMessageCommandLine(String value);
+
+    /**
+     * Testing writeable option using DynamicVMOption isValidValue and
+     * isInvalidValue methods
+     *
+     * @return number of failed tests
+     */
+    public int testDynamic() {
+        DynamicVMOption option = new DynamicVMOption(name);
+        int failedTests = 0;
+        String origValue;
+
+        if (option.isWriteable()) {
+
+            System.out.println("Testing " + name + " option dynamically by DynamicVMOption");
+
+            origValue = option.getValue();
+
+            for (String value : getValidValues()) {
+                if (!option.isValidValue(value)) {
+                    failedMessage(String.format("Option %s: Valid value \"%s\" is invalid", name, value));
+                    failedTests++;
+                }
+            }
+
+            for (String value : getInvalidValues()) {
+                if (option.isValidValue(value)) {
+                    failedMessage(String.format("Option %s: Invalid value \"%s\" is valid", name, value));
+                    failedTests++;
+                }
+            }
+
+            option.setValue(origValue);
+        }
+
+        return failedTests;
+    }
+
+    /**
+     * Testing writeable option using Jcmd
+     *
+     * @return number of failed tests
+     */
+    public int testJcmd() {
+        DynamicVMOption option = new DynamicVMOption(name);
+        int failedTests = 0;
+        OutputAnalyzer out;
+        String origValue;
+
+        if (option.isWriteable()) {
+
+            System.out.println("Testing " + name + " option dynamically by jcmd");
+
+            origValue = option.getValue();
+
+            for (String value : getValidValues()) {
+                out = executor.execute(String.format("VM.set_flag %s %s", name, value), true);
+
+                if (out.getOutput().contains(name + " error")) {
+                    failedMessage(String.format("Option %s: Can not change "
+                            + "option to valid value \"%s\" via jcmd", name, value));
+                    printOutputContent(out);
+                    failedTests++;
+                }
+            }
+
+            for (String value : getInvalidValues()) {
+                out = executor.execute(String.format("VM.set_flag %s %s", name, value), true);
+
+                if (!out.getOutput().contains(name + " error")) {
+                    failedMessage(String.format("Option %s: Error not reported for "
+                            + "option when it chagned to invalid value \"%s\" via jcmd", name, value));
+                    printOutputContent(out);
+                    failedTests++;
+                }
+            }
+
+            option.setValue(origValue);
+        }
+
+        return failedTests;
+    }
+
+    private boolean setFlagAttach(HotSpotVirtualMachine vm, String flagName, String flagValue) throws Exception {
+        boolean result;
+
+        try {
+            vm.setFlag(flagName, flagValue);
+            result = true;
+        } catch (AttachOperationFailedException e) {
+            result = false;
+        }
+
+        return result;
+    }
+
+    /**
+     * Testing writeable option using attach method
+     *
+     * @return number of failed tests
+     * @throws Exception if an error occurred while attaching to the target JVM
+     */
+    public int testAttach() throws Exception {
+        DynamicVMOption option = new DynamicVMOption(name);
+        int failedTests = 0;
+        String origValue;
+
+        if (option.isWriteable()) {
+
+            System.out.println("Testing " + name + " option dynamically via attach");
+
+            origValue = option.getValue();
+
+            HotSpotVirtualMachine vm = (HotSpotVirtualMachine) VirtualMachine.attach(String.valueOf(ProcessTools.getProcessId()));
+
+            for (String value : getValidValues()) {
+                if (!setFlagAttach(vm, name, value)) {
+                    failedMessage(String.format("Option %s: Can not change option to valid value \"%s\" via attach", name, value));
+                    failedTests++;
+                }
+            }
+
+            for (String value : getInvalidValues()) {
+                if (setFlagAttach(vm, name, value)) {
+                    failedMessage(String.format("Option %s: Option changed to invalid value \"%s\" via attach", name, value));
+                    failedTests++;
+                }
+            }
+
+            vm.detach();
+
+            option.setValue(origValue);
+        }
+
+        return failedTests;
+    }
+
+    /**
+     * Run java with passed parameter and check the result depending on the
+     * 'valid' parameter
+     *
+     * @param param tested parameter passed to the JVM
+     * @param valid indicates whether the JVM should fail or not
+     * @return true - if test passed
+     * @throws Exception if java process can not be started
+     */
+    private boolean runJavaWithParam(String optionValue, boolean valid) throws Exception {
+        int exitCode;
+        boolean result = true;
+        String value = optionValue.substring(optionValue.lastIndexOf("=") + 1);
+        String fullOptionString = prependString.toString() + optionValue;
+        List<String> runJava = new ArrayList<>();
+        OutputAnalyzer out;
+
+        if (VMType != null) {
+            runJava.add(VMType);
+        }
+        runJava.addAll(prepend);
+        runJava.add(optionValue);
+        runJava.add(JVMOptionsUtils.class.getName());
+
+        out = new OutputAnalyzer(ProcessTools.createJavaProcessBuilder(runJava.toArray(new String[0])).start());
+
+        exitCode = out.getExitValue();
+
+        if (out.getOutput().contains("A fatal error has been detected by the Java Runtime Environment")) {
+            /* Always consider "fatal error" in output as fail */
+            failedMessage(name, fullOptionString, valid, "JVM output reports a fatal error. JVM exited with code " + exitCode + "!");
+            printOutputContent(out);
+            result = false;
+        } else if (valid == true) {
+            if ((exitCode != 0) && (exitCode != 1)) {
+                failedMessage(name, fullOptionString, valid, "JVM exited with unexpected error code = " + exitCode);
+                printOutputContent(out);
+                result = false;
+            } else if ((exitCode == 1) && (out.getOutput().isEmpty() == true)) {
+                failedMessage(name, fullOptionString, valid, "JVM exited with error(exitcode == 1)"
+                        + ", but with empty stdout and stderr. Description of error is needed!");
+                result = false;
+            } else if (out.getOutput().contains("is outside the allowed range")) {
+                failedMessage(name, fullOptionString, valid, "JVM output contains \"is outside the allowed range\"");
+                printOutputContent(out);
+                result = false;
+            }
+        } else {
+            // valid == false
+            if (exitCode == 0) {
+                failedMessage(name, fullOptionString, valid, "JVM successfully exit");
+                result = false;
+            } else if (exitCode != 1) {
+                failedMessage(name, fullOptionString, valid, "JVM exited with code "
+                        + exitCode + " which not equal to 1");
+                result = false;
+            } else if (!out.getOutput().contains(getErrorMessageCommandLine(value))) {
+                failedMessage(name, fullOptionString, valid, "JVM output does not contain "
+                        + "expected output \"" + getErrorMessageCommandLine(value) + "\"");
+                printOutputContent(out);
+                result = false;
+            }
+        }
+
+        System.out.println("");
+
+        return result;
+    }
+
+    /**
+     * Construct option string with passed value
+     *
+     * @param value parameter value
+     * @return string containing option with passed value
+     */
+    private String constructOption(String value) {
+        return "-XX:" + name + "=" + value;
+    }
+
+    /**
+     * Return list of strings which contain options with valid values which can
+     * be used for testing on command line
+     *
+     * @return list of strings which contain options with valid values
+     */
+    private List<String> getValidCommandLineOptions() {
+        List<String> validParameters = new ArrayList<>();
+
+        for (String value : getValidValues()) {
+            validParameters.add(constructOption(value));
+        }
+
+        return validParameters;
+    }
+
+    /**
+     * Return list of strings which contain options with invalid values which
+     * can be used for testing on command line
+     *
+     * @return list of strings which contain options with invalid values
+     */
+    private List<String> getInvalidCommandLineOptions() {
+        List<String> invalidParameters = new ArrayList<>();
+
+        for (String value : getInvalidValues()) {
+            invalidParameters.add(constructOption(value));
+        }
+
+        return invalidParameters;
+    }
+
+    /**
+     * Perform test of the parameter. Call java with valid option values and
+     * with invalid option values.
+     *
+     * @return number of failed tests
+     * @throws Exception if java process can not be started
+     */
+    public int testCommandLine() throws Exception {
+        ProcessBuilder pb;
+        int failed = 0;
+        List<String> optionValuesList;
+
+        optionValuesList = getValidCommandLineOptions();
+
+        if (optionValuesList.isEmpty() != true) {
+            System.out.println("Testing valid " + name + " values.");
+            for (String optionValid : optionValuesList) {
+                if (runJavaWithParam(optionValid, true) == false) {
+                    failed++;
+                }
+            }
+        }
+
+        optionValuesList = getInvalidCommandLineOptions();
+
+        if (optionValuesList.isEmpty() != true) {
+            System.out.println("Testing invalid " + name + " values.");
+
+            for (String optionInvalid : optionValuesList) {
+                if (runJavaWithParam(optionInvalid, false) == false) {
+                    failed++;
+                }
+            }
+        }
+
+        /* return number of failed tests for this option */
+        return failed;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOptionsUtils.java	Thu Jun 25 09:48:50 2015 -0700
@@ -0,0 +1,450 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+package optionsvalidation;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.StringTokenizer;
+import java.util.function.Predicate;
+import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.Platform;
+import jdk.test.lib.ProcessTools;
+
+public class JVMOptionsUtils {
+
+    /* Java option which print options with ranges */
+    private static final String PRINT_FLAGS_RANGES = "-XX:+PrintFlagsRanges";
+
+    /* StringBuilder to accumulate failed message */
+    private static final StringBuilder finalFailedMessage = new StringBuilder();
+
+    /* Used to start the JVM with the same type as current */
+    static String VMType;
+
+    static {
+        if (Platform.isServer()) {
+            VMType = "-server";
+        } else if (Platform.isClient()) {
+            VMType = "-client";
+        } else if (Platform.isMinimal()) {
+            VMType = "-minimal";
+        } else if (Platform.isGraal()) {
+            VMType = "-graal";
+        } else {
+            VMType = null;
+        }
+    }
+
+    /**
+     * Add dependency for option depending on it's name. E.g. enable G1 GC for
+     * G1 options or add prepend options to not hit constraints.
+     *
+     * @param option option
+     */
+    private static void addNameDependency(JVMOption option) {
+        String name = option.getName();
+
+        if (name.startsWith("G1")) {
+            option.addPrepend("-XX:+UseG1GC");
+        }
+
+        if (name.startsWith("CMS")) {
+            option.addPrepend("-XX:+UseConcMarkSweepGC");
+        }
+
+        switch (name) {
+            case "MinHeapFreeRatio":
+                option.addPrepend("-XX:MaxHeapFreeRatio=100");
+                break;
+            case "MaxHeapFreeRatio":
+                option.addPrepend("-XX:MinHeapFreeRatio=0");
+                break;
+            case "MinMetaspaceFreeRatio":
+                option.addPrepend("-XX:MaxMetaspaceFreeRatio=100");
+                break;
+            case "MaxMetaspaceFreeRatio":
+                option.addPrepend("-XX:MinMetaspaceFreeRatio=0");
+                break;
+            case "CMSOldPLABMin":
+                option.addPrepend("-XX:CMSOldPLABMax=" + option.getMax());
+                break;
+            case "CMSOldPLABMax":
+                option.addPrepend("-XX:CMSOldPLABMin=" + option.getMin());
+                break;
+            case "CMSPrecleanNumerator":
+                option.addPrepend("-XX:CMSPrecleanDenominator=" + option.getMax());
+                break;
+            case "CMSPrecleanDenominator":
+                option.addPrepend("-XX:CMSPrecleanNumerator=" + ((new Integer(option.getMin())) - 1));
+                break;
+            case "InitialTenuringThreshold":
+                option.addPrepend("-XX:MaxTenuringThreshold=" + option.getMax());
+                break;
+            default:
+                /* Do nothing */
+                break;
+        }
+
+    }
+
+    /**
+     * Add dependency for option depending on it's type. E.g. run the JVM in
+     * compilation mode for compiler options.
+     *
+     * @param option option
+     * @param type type of the option
+     */
+    private static void addTypeDependency(JVMOption option, String type) {
+        if (type.contains("C1") || type.contains("C2")) {
+            /* Run in compiler mode for compiler flags */
+            option.addPrepend("-Xcomp");
+        }
+    }
+
+    /**
+     * Parse JVM Options. Get input from "inputReader". Parse using
+     * "-XX:+PrintFlagsRanges" output format.
+     *
+     * @param inputReader input data for parsing
+     * @param withRanges true if needed options with defined ranges inside JVM
+     * @param acceptOrigin predicate for option origins. Origins can be
+     * "product", "diagnostic" etc. Accept option only if acceptOrigin evaluates
+     * to true.
+     * @return map from option name to the JVMOption object
+     * @throws IOException if an error occurred while reading the data
+     */
+    private static Map<String, JVMOption> getJVMOptions(Reader inputReader,
+            boolean withRanges, Predicate<String> acceptOrigin) throws IOException {
+        BufferedReader reader = new BufferedReader(inputReader);
+        String type;
+        String line;
+        String token;
+        String name;
+        StringTokenizer st;
+        JVMOption option;
+        Map<String, JVMOption> allOptions = new LinkedHashMap<>();
+
+        // Skip first line
+        line = reader.readLine();
+
+        while ((line = reader.readLine()) != null) {
+            /*
+             * Parse option from following line:
+             * <type> <name> [ <min, optional> ... <max, optional> ] {<origin>}
+             */
+            st = new StringTokenizer(line);
+
+            type = st.nextToken();
+
+            name = st.nextToken();
+
+            option = JVMOption.createVMOption(type, name);
+
+            /* Skip '[' */
+            token = st.nextToken();
+
+            /* Read min range or "..." if range is absent */
+            token = st.nextToken();
+
+            if (token.equals("...") == false) {
+                if (!withRanges) {
+                    /*
+                     * Option have range, but asked for options without
+                     * ranges => skip it
+                     */
+                    continue;
+                }
+
+                /* Mark this option as option which range is defined in VM */
+                option.optionWithRange();
+
+                option.setMin(token);
+
+                /* Read "..." and skip it */
+                token = st.nextToken();
+
+                /* Get max value */
+                token = st.nextToken();
+                option.setMax(token);
+            } else if (withRanges) {
+                /*
+                 * Option not have range, but asked for options with
+                 * ranges => skip it
+                 */
+                continue;
+            }
+
+            /* Skip ']' */
+            token = st.nextToken();
+
+            /* Read origin of the option */
+            token = st.nextToken();
+
+            while (st.hasMoreTokens()) {
+                token += st.nextToken();
+            };
+            token = token.substring(1, token.indexOf("}"));
+
+            if (acceptOrigin.test(token)) {
+                addTypeDependency(option, token);
+                addNameDependency(option);
+
+                allOptions.put(name, option);
+            }
+        }
+
+        return allOptions;
+    }
+
+    static void failedMessage(String optionName, String value, boolean valid, String message) {
+        String temp;
+
+        if (valid) {
+            temp = "valid";
+        } else {
+            temp = "invalid";
+        }
+
+        failedMessage(String.format("Error processing option %s with %s value '%s'! %s",
+                optionName, temp, value, message));
+    }
+
+    static void failedMessage(String message) {
+        System.err.println("TEST FAILED: " + message);
+        finalFailedMessage.append(String.format("(%s)%n", message));
+    }
+
+    static void printOutputContent(OutputAnalyzer output) {
+        System.err.println(String.format("stdout content[%s]", output.getStdout()));
+        System.err.println(String.format("stderr content[%s]%n", output.getStderr()));
+    }
+
+    /**
+     * Return string with accumulated failure messages
+     *
+     * @return string with accumulated failure messages
+     */
+    public static String getMessageWithFailures() {
+        return finalFailedMessage.toString();
+    }
+
+    /**
+     * Run command line tests for options passed in the list
+     *
+     * @param options list of options to test
+     * @return number of failed tests
+     * @throws Exception if java process can not be started
+     */
+    public static int runCommandLineTests(List<? extends JVMOption> options) throws Exception {
+        int failed = 0;
+
+        for (JVMOption option : options) {
+            failed += option.testCommandLine();
+        }
+
+        return failed;
+    }
+
+    /**
+     * Test passed options using DynamicVMOption isValidValue and isInvalidValue
+     * methods. Only tests writeable options.
+     *
+     * @param options list of options to test
+     * @return number of failed tests
+     */
+    public static int runDynamicTests(List<? extends JVMOption> options) {
+        int failed = 0;
+
+        for (JVMOption option : options) {
+            failed += option.testDynamic();
+        }
+
+        return failed;
+    }
+
+    /**
+     * Test passed options using Jcmd. Only tests writeable options.
+     *
+     * @param options list of options to test
+     * @return number of failed tests
+     */
+    public static int runJcmdTests(List<? extends JVMOption> options) {
+        int failed = 0;
+
+        for (JVMOption option : options) {
+            failed += option.testJcmd();
+        }
+
+        return failed;
+    }
+
+    /**
+     * Test passed option using attach method. Only tests writeable options.
+     *
+     * @param options list of options to test
+     * @return number of failed tests
+     * @throws Exception if an error occurred while attaching to the target JVM
+     */
+    public static int runAttachTests(List<? extends JVMOption> options) throws Exception {
+        int failed = 0;
+
+        for (JVMOption option : options) {
+            failed += option.testAttach();
+        }
+
+        return failed;
+    }
+
+    /**
+     * Get JVM options as map. Can return options with defined ranges or options
+     * without range depending on "withRanges" argument. "acceptOrigin"
+     * predicate can be used to filter option origin.
+     *
+     * @param withRanges true if needed options with defined ranges inside JVM
+     * @param acceptOrigin predicate for option origins. Origins can be
+     * "product", "diagnostic" etc. Accept option only if acceptOrigin evaluates
+     * to true.
+     * @param additionalArgs additional arguments to the Java process which ran
+     * with "-XX:+PrintFlagsRanges"
+     * @return map from option name to the JVMOption object
+     * @throws Exception if a new process can not be created or an error
+     * occurred while reading the data
+     */
+    public static Map<String, JVMOption> getOptionsAsMap(boolean withRanges, Predicate<String> acceptOrigin,
+            String... additionalArgs) throws Exception {
+        Map<String, JVMOption> result;
+        Process p;
+        List<String> runJava = new ArrayList<>();
+
+        if (additionalArgs.length > 0) {
+            runJava.addAll(Arrays.asList(additionalArgs));
+        }
+
+        if (VMType != null) {
+            runJava.add(VMType);
+        }
+        runJava.add(PRINT_FLAGS_RANGES);
+        runJava.add("-version");
+
+        p = ProcessTools.createJavaProcessBuilder(runJava.toArray(new String[0])).start();
+
+        result = getJVMOptions(new InputStreamReader(p.getInputStream()), withRanges, acceptOrigin);
+
+        p.waitFor();
+
+        return result;
+    }
+
+    /**
+     * Get JVM options as list. Can return options with defined ranges or
+     * options without range depending on "withRanges" argument. "acceptOrigin"
+     * predicate can be used to filter option origin.
+     *
+     * @param withRanges true if needed options with defined ranges inside JVM
+     * @param acceptOrigin predicate for option origins. Origins can be
+     * "product", "diagnostic" etc. Accept option only if acceptOrigin evaluates
+     * to true.
+     * @param additionalArgs additional arguments to the Java process which ran
+     * with "-XX:+PrintFlagsRanges"
+     * @return List of options
+     * @throws Exception if a new process can not be created or an error
+     * occurred while reading the data
+     */
+    public static List<JVMOption> getOptions(boolean withRanges, Predicate<String> acceptOrigin,
+            String... additionalArgs) throws Exception {
+        return new ArrayList<>(getOptionsAsMap(withRanges, acceptOrigin, additionalArgs).values());
+    }
+
+    /**
+     * Get JVM options with ranges as list. "acceptOrigin" predicate can be used
+     * to filter option origin.
+     *
+     * @param acceptOrigin predicate for option origins. Origins can be
+     * "product", "diagnostic" etc. Accept option only if acceptOrigin evaluates
+     * to true.
+     * @param additionalArgs additional arguments to the Java process which ran
+     * with "-XX:+PrintFlagsRanges"
+     * @return List of options
+     * @throws Exception if a new process can not be created or an error
+     * occurred while reading the data
+     */
+    public static List<JVMOption> getOptionsWithRange(Predicate<String> acceptOrigin, String... additionalArgs) throws Exception {
+        return getOptions(true, acceptOrigin, additionalArgs);
+    }
+
+    /**
+     * Get JVM options with ranges as list.
+     *
+     * @param additionalArgs additional arguments to the Java process which ran
+     * with "-XX:+PrintFlagsRanges"
+     * @return list of options
+     * @throws Exception if a new process can not be created or an error
+     * occurred while reading the data
+     */
+    public static List<JVMOption> getOptionsWithRange(String... additionalArgs) throws Exception {
+        return getOptionsWithRange(origin -> true, additionalArgs);
+    }
+
+    /**
+     * Get JVM options with range as map. "acceptOrigin" predicate can be used
+     * to filter option origin.
+     *
+     * @param acceptOrigin predicate for option origins. Origins can be
+     * "product", "diagnostic" etc. Accept option only if acceptOrigin evaluates
+     * to true.
+     * @param additionalArgs additional arguments to the Java process which ran
+     * with "-XX:+PrintFlagsRanges"
+     * @return Map from option name to the JVMOption object
+     * @throws Exception if a new process can not be created or an error
+     * occurred while reading the data
+     */
+    public static Map<String, JVMOption> getOptionsWithRangeAsMap(Predicate<String> acceptOrigin, String... additionalArgs) throws Exception {
+        return getOptionsAsMap(true, acceptOrigin, additionalArgs);
+    }
+
+    /**
+     * Get JVM options with range as map
+     *
+     * @param additionalArgs additional arguments to the Java process which ran
+     * with "-XX:+PrintFlagsRanges"
+     * @return map from option name to the JVMOption object
+     * @throws Exception if a new process can not be created or an error
+     * occurred while reading the data
+     */
+    public static Map<String, JVMOption> getOptionsWithRangeAsMap(String... additionalArgs) throws Exception {
+        return getOptionsWithRangeAsMap(origin -> true, additionalArgs);
+    }
+
+    /* Simple method to test that java start-up. Used for testing options. */
+    public static void main(String[] args) {
+        System.out.print("Java start-up!");
+    }
+}
--- a/hotspot/test/runtime/CompressedOops/CompressedClassSpaceSize.java	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/test/runtime/CompressedOops/CompressedClassSpaceSize.java	Thu Jun 25 09:48:50 2015 -0700
@@ -42,7 +42,7 @@
             pb = ProcessTools.createJavaProcessBuilder("-XX:CompressedClassSpaceSize=0",
                                                        "-version");
             output = new OutputAnalyzer(pb.start());
-            output.shouldContain("CompressedClassSpaceSize of 0 is invalid")
+            output.shouldContain("outside the allowed range")
                   .shouldHaveExitValue(1);
 
             // Invalid size of -1 should be handled correctly
@@ -57,7 +57,7 @@
             pb = ProcessTools.createJavaProcessBuilder("-XX:CompressedClassSpaceSize=4g",
                                                        "-version");
             output = new OutputAnalyzer(pb.start());
-            output.shouldContain("CompressedClassSpaceSize of 4294967296 is invalid")
+            output.shouldContain("outside the allowed range")
                   .shouldHaveExitValue(1);
 
 
--- a/hotspot/test/runtime/CompressedOops/ObjectAlignment.java	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/test/runtime/CompressedOops/ObjectAlignment.java	Thu Jun 25 09:48:50 2015 -0700
@@ -39,21 +39,22 @@
         if (Platform.is64bit()) {
             // Minimum alignment should be 8
             testObjectAlignment(4)
-                .shouldContain("error: ObjectAlignmentInBytes=4 must be greater or equal 8")
+                .shouldContain("outside the allowed range")
                 .shouldHaveExitValue(1);
 
             // Alignment has to be a power of 2
             testObjectAlignment(9)
-                .shouldContain("error: ObjectAlignmentInBytes=9 must be power of 2")
+                .shouldContain("must be power of 2")
                 .shouldHaveExitValue(1);
 
             testObjectAlignment(-1)
-                .shouldContain("error: ObjectAlignmentInBytes=-1 must be power of 2")
+                .shouldContain("must be power of 2")
+                .shouldContain("outside the allowed range")
                 .shouldHaveExitValue(1);
 
             // Maximum alignment allowed is 256
             testObjectAlignment(512)
-                .shouldContain("error: ObjectAlignmentInBytes=512 must not be greater than 256")
+                .shouldContain("outside the allowed range")
                 .shouldHaveExitValue(1);
 
             // Valid alignments should work
@@ -74,4 +75,4 @@
                                                                   "-version");
         return new OutputAnalyzer(pb.start());
     }
-}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/RedefineTests/RedefineRunningMethodsWithResolutionErrors.java	Thu Jun 25 09:48:50 2015 -0700
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2014, 2015, 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 8076110
+ * @summary Redefine running methods that have cached resolution errors
+ * @library /testlibrary
+ * @modules java.instrument
+ *          java.base/jdk.internal.org.objectweb.asm
+ * @build RedefineClassHelper
+ * @run main RedefineClassHelper
+ * @run main/othervm -javaagent:redefineagent.jar -XX:TraceRedefineClasses=0x600 RedefineRunningMethodsWithResolutionErrors
+ */
+
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.internal.org.objectweb.asm.Label;
+import jdk.internal.org.objectweb.asm.MethodVisitor;
+import jdk.internal.org.objectweb.asm.Opcodes;
+
+import java.lang.reflect.InvocationTargetException;
+
+public class RedefineRunningMethodsWithResolutionErrors extends ClassLoader implements Opcodes {
+
+    @Override
+    protected Class<?> findClass(String name) throws ClassNotFoundException {
+        if (name.equals("C")) {
+            byte[] b = loadC(false);
+            return defineClass(name, b, 0, b.length);
+        } else {
+            return super.findClass(name);
+        }
+    }
+
+    private static byte[] loadC(boolean redefine) {
+        ClassWriter cw = new ClassWriter(0);
+
+        cw.visit(52, ACC_SUPER | ACC_PUBLIC, "C", null, "java/lang/Object", null);
+        {
+            MethodVisitor mv;
+
+            mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "m", "()V", null, null);
+            mv.visitCode();
+
+            // First time we run we will:
+            // 1) Cache resolution errors
+            // 2) Redefine the class / method
+            // 3) Try to read the resolution errors that were cached
+            //
+            // The redefined method will never run, throw error to be sure
+            if (redefine) {
+                createThrowRuntimeExceptionCode(mv, "The redefined method was called");
+            } else {
+                createMethodBody(mv);
+            }
+            mv.visitMaxs(3, 0);
+            mv.visitEnd();
+        }
+        cw.visitEnd();
+        return cw.toByteArray();
+    }
+
+    private static void createMethodBody(MethodVisitor mv) {
+        Label classExists = new Label();
+
+        // Cache resolution errors
+        createLoadNonExistentClassCode(mv, classExists);
+
+        // Redefine our own class and method
+        mv.visitMethodInsn(INVOKESTATIC, "RedefineRunningMethodsWithResolutionErrors", "redefine", "()V");
+
+        // Provoke the same error again to make sure the resolution error cache works
+        createLoadNonExistentClassCode(mv, classExists);
+
+        // Test passed
+        mv.visitInsn(RETURN);
+
+        mv.visitFrame(F_SAME, 0, new Object[0], 0, new Object[0]);
+        mv.visitLabel(classExists);
+
+        createThrowRuntimeExceptionCode(mv, "Loaded class that shouldn't exist (\"NonExistentClass\")");
+    }
+
+    private static void createLoadNonExistentClassCode(MethodVisitor mv, Label classExists) {
+        Label tryLoadBegin = new Label();
+        Label tryLoadEnd = new Label();
+        Label catchLoadBlock = new Label();
+        mv.visitTryCatchBlock(tryLoadBegin, tryLoadEnd, catchLoadBlock, "java/lang/NoClassDefFoundError");
+
+        // Try to load a class that does not exist to provoke resolution errors
+        mv.visitLabel(tryLoadBegin);
+        mv.visitMethodInsn(INVOKESTATIC, "NonExistentClass", "nonExistentMethod", "()V");
+        mv.visitLabel(tryLoadEnd);
+
+        // No NoClassDefFoundError means NonExistentClass existed, which shouldn't happen
+        mv.visitJumpInsn(GOTO, classExists);
+
+        mv.visitFrame(F_SAME1, 0, new Object[0], 1, new Object[] { "java/lang/NoClassDefFoundError" });
+        mv.visitLabel(catchLoadBlock);
+
+        // Ignore the expected NoClassDefFoundError
+        mv.visitInsn(POP);
+    }
+
+    private static void createThrowRuntimeExceptionCode(MethodVisitor mv, String msg) {
+        mv.visitTypeInsn(NEW, "java/lang/RuntimeException");
+        mv.visitInsn(DUP);
+        mv.visitLdcInsn(msg);
+        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/RuntimeException", "<init>", "(Ljava/lang/String;)V");
+        mv.visitInsn(ATHROW);
+    }
+
+    private static Class<?> c;
+
+    public static void redefine() throws Exception {
+        RedefineClassHelper.redefineClass(c, loadC(true));
+    }
+
+    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
+        c = Class.forName("C", true, new RedefineRunningMethodsWithResolutionErrors());
+        c.getMethod("m").invoke(null);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/classFileParserBug/AnnotationTag.java	Thu Jun 25 09:48:50 2015 -0700
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015, 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 8042041
+ * @summary Fuzzy-ed RuntimeVisibleAnnotations causes assertion
+ * @compile badAnnotTag.jcod
+ * @run main AnnotationTag
+ */
+
+// Test that a bad element_tag in an element_value of a RuntimeVisibileAnnotation
+// attribute is ignored.
+public class AnnotationTag {
+    public static void main(String args[]) throws Throwable {
+
+        System.out.println("Regression test for bug 8042041");
+        try {
+            Class newClass = Class.forName("badAnnotTag");
+        } catch (java.lang.Throwable e) {
+            throw new RuntimeException(
+                "Unexpected exception: " + e.getMessage());
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/classFileParserBug/badAnnotTag.jcod	Thu Jun 25 09:48:50 2015 -0700
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2015, 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.
+ *
+ */
+
+// This class contains a bad element_tag in an element_value structure for a
+// RuntimeVisibleAnnotation at line 91.  The bad element tag should be ignored
+// by the class file parser.
+class badAnnotTag {
+  0xCAFEBABE;
+  0; // minor version
+  52; // version
+  [19] { // Constant Pool
+    ; // first element is empty
+    class #16; // #1     at 0x0A
+    class #17; // #2     at 0x0D
+    class #18; // #3     at 0x10
+    Utf8 "value"; // #4     at 0x13
+    Utf8 "()Ljava/lang/String;"; // #5     at 0x1B
+    Utf8 "SourceFile"; // #6     at 0x32
+    Utf8 "badAnnotTag.java"; // #7     at 0x3F
+    Utf8 "RuntimeVisibleAnnotations"; // #8     at 0x50
+    Utf8 "Ljava/lang/annotation/Target;"; // #9     at 0x6C
+    Utf8 "Ljava/lang/annotation/ElementType;"; // #10     at 0x8C
+    Utf8 "TYPE_USE"; // #11     at 0xB1
+    Utf8 "TYPE_PARAMETER"; // #12     at 0xBC
+    Utf8 "Ljava/lang/annotation/Retention;"; // #13     at 0xCD
+    Utf8 "Ljava/lang/annotation/RetentionPolicy;"; // #14     at 0xF0
+    Utf8 "RUNTIME"; // #15     at 0x0119
+    Utf8 "badAnnotTag"; // #16     at 0x0123
+    Utf8 "java/lang/Object"; // #17     at 0x0127
+    Utf8 "java/lang/annotation/Annotation"; // #18     at 0x013A
+  } // Constant Pool
+
+  0x2600; // access
+  #1;// this_cpx
+  #2;// super_cpx
+
+  [1] { // Interfaces
+    #3;
+  } // Interfaces
+
+  [0] { // fields
+  } // fields
+
+  [1] { // methods
+    { // Member at 0x016A
+      0x0401; // access
+      #4; // name_cpx
+      #5; // sig_cpx
+      [0] { // Attributes
+      } // Attributes
+    } // Member
+  } // methods
+
+  [2] { // Attributes
+    Attr(#6, 2) { // SourceFile at 0x0174
+      #7;
+    } // end SourceFile
+    ;
+    Attr(#8, 32) { // RuntimeVisibleAnnotations at 0x017C
+      [2] { // annotations
+        {  //  annotation
+          #9;
+          [1] { // element_value_pairs
+            {  //  element value pair
+              #4;
+              {  //  element_value
+                '[';
+                [2] { // array_value
+                  {  //  element_value
+                    'd'; // * illegal value *, correct value is 'e'
+                    {  //  enum_const_value
+                      #10;
+                      #11;
+                    }  //  enum_const_value
+                  }  //  element_value
+                  ;
+                  {  //  element_value
+                    'e';
+                    {  //  enum_const_value
+                      #10;
+                      #12;
+                    }  //  enum_const_value
+                  }  //  element_value
+                }  //  array_value
+              }  //  element_value
+            }  //  element value pair
+          }  //  element_value_pairs
+        }  //  annotation
+        ;
+        {  //  annotation
+          #13;
+          [1] { // element_value_pairs
+            {  //  element value pair
+              #4;
+              {  //  element_value
+                'e';
+                {  //  enum_const_value
+                  #14;
+                  #15;
+                }  //  enum_const_value
+              }  //  element_value
+            }  //  element value pair
+          }  //  element_value_pairs
+        }  //  annotation
+      }
+    } // end RuntimeVisibleAnnotations
+  } // Attributes
+} // end class badAnnotTag
--- a/hotspot/test/runtime/contended/Options.java	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/test/runtime/contended/Options.java	Thu Jun 25 09:48:50 2015 -0700
@@ -42,19 +42,19 @@
         pb = ProcessTools.createJavaProcessBuilder("-XX:ContendedPaddingWidth=-128", "-version");
         output = new OutputAnalyzer(pb.start());
         output.shouldContain("ContendedPaddingWidth");
-        output.shouldContain("must be in between");
+        output.shouldContain("outside the allowed range");
         output.shouldHaveExitValue(1);
 
         pb = ProcessTools.createJavaProcessBuilder("-XX:ContendedPaddingWidth=-8", "-version");
         output = new OutputAnalyzer(pb.start());
         output.shouldContain("ContendedPaddingWidth");
-        output.shouldContain("must be in between");
+        output.shouldContain("outside the allowed range");
         output.shouldHaveExitValue(1);
 
         pb = ProcessTools.createJavaProcessBuilder("-XX:ContendedPaddingWidth=-1", "-version");
         output = new OutputAnalyzer(pb.start());
         output.shouldContain("ContendedPaddingWidth");
-        output.shouldContain("must be in between");
+        output.shouldContain("outside the allowed range");
         output.shouldContain("must be a multiple of 8");
         output.shouldHaveExitValue(1);
 
@@ -89,17 +89,16 @@
         pb = ProcessTools.createJavaProcessBuilder("-XX:ContendedPaddingWidth=8193", "-version");
         output = new OutputAnalyzer(pb.start());
         output.shouldContain("ContendedPaddingWidth");
-        output.shouldContain("must be in between");
+        output.shouldContain("outside the allowed range");
         output.shouldContain("must be a multiple of 8");
         output.shouldHaveExitValue(1);
 
         pb = ProcessTools.createJavaProcessBuilder("-XX:ContendedPaddingWidth=8200", "-version"); // 8192+8 = 8200
         output = new OutputAnalyzer(pb.start());
         output.shouldContain("ContendedPaddingWidth");
-        output.shouldContain("must be in between");
+        output.shouldContain("outside the allowed range");
         output.shouldHaveExitValue(1);
 
    }
 
 }
-
--- a/hotspot/test/serviceability/attach/AttachSetGetFlag.java	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/test/serviceability/attach/AttachSetGetFlag.java	Thu Jun 25 09:48:50 2015 -0700
@@ -61,6 +61,9 @@
     // Since it is not manageable, we can't test the setFlag functionality.
     testGetFlag("ArrayAllocatorMallocLimit", "128");
     // testSetFlag("ArrayAllocatorMallocLimit", "64", "128");
+
+    // Test a uint flag.
+    testGetFlag("ParallelGCThreads", "10");
   }
 
   public static ProcessBuilder runTarget(String flagName, String flagValue) throws Exception {
--- a/hotspot/test/serviceability/sa/TestClassLoaderStats.java	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/test/serviceability/sa/TestClassLoaderStats.java	Thu Jun 25 09:48:50 2015 -0700
@@ -21,9 +21,13 @@
  * questions.
  */
 
+import java.util.ArrayList;
+import java.util.List;
+
 import jdk.test.lib.Platform;
 import jdk.test.lib.ProcessTools;
 import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.Utils;
 import jdk.test.lib.apps.LingeredApp;
 
 /*
@@ -44,7 +48,10 @@
 
         LingeredApp app = null;
         try {
-            app = LingeredApp.startApp();
+            List<String> vmArgs = new ArrayList<String>();
+            vmArgs.add("-XX:+UsePerfData");
+            vmArgs.addAll(Utils.getVmOptions());
+            app = LingeredApp.startApp(vmArgs);
 
             System.out.println("Attaching sun.jvm.hotspot.tools.ClassLoaderStats to " + app.getPid());
             ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(
@@ -61,7 +68,7 @@
             output.stderrShouldNotMatch("[E|e]xception");
             output.stderrShouldNotMatch("[E|e]rror");
         } finally {
-            app.stopApp();
+            LingeredApp.stopApp(app);
         }
     }
 
--- a/hotspot/test/serviceability/sa/TestStackTrace.java	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/test/serviceability/sa/TestStackTrace.java	Thu Jun 25 09:48:50 2015 -0700
@@ -21,9 +21,13 @@
  * questions.
  */
 
+import java.util.ArrayList;
+import java.util.List;
+
 import jdk.test.lib.OutputAnalyzer;
 import jdk.test.lib.Platform;
 import jdk.test.lib.ProcessTools;
+import jdk.test.lib.Utils;
 import jdk.test.lib.apps.LingeredApp;
 
 /*
@@ -44,7 +48,10 @@
 
         LingeredApp app = null;
         try {
-            app = LingeredApp.startApp();
+            List<String> vmArgs = new ArrayList<String>();
+            vmArgs.add("-XX:+UsePerfData");
+            vmArgs.addAll(Utils.getVmOptions());
+            app = LingeredApp.startApp(vmArgs);
 
             System.out.println("Attaching sun.jvm.hotspot.tools.StackTrace to " + app.getPid());
             ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(
@@ -59,7 +66,7 @@
             output.stderrShouldNotMatch("[E|e]xception");
             output.stderrShouldNotMatch("[E|e]rror");
         } finally {
-            app.stopApp();
+            LingeredApp.stopApp(app);
         }
      }
 
--- a/hotspot/test/serviceability/sa/jmap-hashcode/Test8028623.java	Wed Jun 24 09:13:12 2015 +0200
+++ b/hotspot/test/serviceability/sa/jmap-hashcode/Test8028623.java	Thu Jun 25 09:48:50 2015 -0700
@@ -21,6 +21,13 @@
  * questions.
  */
 
+import jdk.test.lib.JDKToolLauncher;
+import jdk.test.lib.OutputBuffer;
+import jdk.test.lib.Platform;
+import jdk.test.lib.ProcessTools;
+
+import java.io.File;
+
 /*
  * @test
  * @bug 8028623
@@ -32,16 +39,8 @@
  *          jdk.jvmstat/sun.jvmstat.monitor
  * @build jdk.test.lib.*
  * @compile -encoding utf8 Test8028623.java
- * @run main Test8028623
+ * @run main/othervm -XX:+UsePerfData Test8028623
  */
-
-import jdk.test.lib.JDKToolLauncher;
-import jdk.test.lib.OutputBuffer;
-import jdk.test.lib.Platform;
-import jdk.test.lib.ProcessTools;
-
-import java.io.File;
-
 public class Test8028623 {
 
   public static int \u00CB = 1;