Merge
authoramurillo
Fri, 31 Jul 2015 10:15:02 -0700
changeset 31997 a9f423dbab9e
parent 31945 eeea9adfd1e3 (current diff)
parent 31996 6c23ab90cbaa (diff)
child 31998 f057c3f8e4d2
child 32078 8757adb98184
child 32087 dcbcf15229a9
Merge
hotspot/agent/src/share/classes/sun/jvm/hotspot/gc/g1/G1Allocator.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/SAGetopt.java	Fri Jul 31 10:15:02 2015 -0700
@@ -0,0 +1,162 @@
+/*
+ * 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 sun.jvm.hotspot;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class SAGetopt {
+
+    private String[] _argv;
+
+    private int _optind;    // index in arguments array
+    private int _optopt;    // index within an argument
+    private String _optarg; // last option argument
+    private boolean _optreset; // special handling of first call
+
+    public SAGetopt(String[] args) {
+        _argv  = args;
+        _optind   = 0;
+        _optopt   = 1;
+        _optarg   = null;
+        _optreset = true;
+    }
+
+    public String getOptarg() {
+        return _optarg;
+    }
+
+    public int getOptind() {
+        return _optind;
+    }
+
+    private void extractOptarg(String opt) {
+        // Argument expected
+        if (_optind > _argv.length) {
+            throw new RuntimeException("Not enough arguments for '" + opt + "'");
+        }
+
+        if (! _argv[_optind].isEmpty() && _argv[_optind].charAt(0) == '-') {
+            throw new RuntimeException("Argument is expected for '" + opt + "'");
+        }
+
+        _optarg = _argv[_optind];
+        _optind += 1;
+    }
+
+    private String processLongOptions(String carg, String[] longOptStr) {
+        List<String> los = Arrays.asList(longOptStr);
+        String[] ca = carg.split("=", 2);
+
+        if (los.contains(ca[0])) {
+            if (ca.length > 1) {
+                throw new RuntimeException("Argument is not expected for '" + ca[0] + "'");
+            }
+            return carg;
+        }
+
+        if (los.contains(ca[0] + "=")) {
+            if (ca.length > 1) {
+                // GNU style options --file=name
+                _optarg = ca[1];
+            }
+            else {
+                // Mixed style options --file name
+                extractOptarg(ca[0]);
+            }
+
+            return ca[0];
+        }
+
+        throw new RuntimeException("Invalid option '" + ca[0] + "'");
+    }
+
+    public String next(String optStr, String[] longOptStr) {
+
+        if (_optind >= _argv.length || _argv[_optind] == null) {
+            // All arguments processed
+            return null;
+        }
+
+        String carg = _argv[_optind];
+        _optarg = null;
+
+        if (_optreset) {
+            // End of option batch like '-abc' reached, expect option to start from '-'
+
+            if (carg.isEmpty() || carg.charAt(0) != '-' || carg.equals("--")) {
+                // Stop processing on -- or first non-option argument;
+                return null;
+            }
+
+            if (carg.startsWith("--")) {
+                // Handle long options, it can't be combined so it's simple
+                if (longOptStr == null || longOptStr.length == 0) {
+                    // No long options expected, stop options processing
+                    return null;
+                }
+                ++ _optind;
+
+                // at this point carg contains at least one character besides --
+                carg = carg.substring(2);
+                return processLongOptions(carg, longOptStr);
+            }
+
+            if (optStr == null || optStr.length() == 0) {
+                // No short options
+                return null;
+            }
+
+            // At this point carg[0] contains '-'
+            _optreset = false;
+            _optopt = 1;
+        }
+
+        char ch = carg.charAt(_optopt);
+
+        // adjust pointer to next character
+        _optopt += 1;
+
+        // Okay, ready to process options like
+        // -abc -d bla -ef
+
+        int chIndex = optStr.indexOf(ch);
+        if (chIndex == -1) {
+            throw new RuntimeException("Invalid option '" + ch + "'");
+        }
+
+        if (_optopt >= carg.length()) {
+            _optind += 1;
+            _optreset = true;
+        }
+
+        if (chIndex < optStr.length()-1 && optStr.charAt(chIndex+1) == ':') {
+            // Argument expected
+            extractOptarg(String.valueOf(ch));
+        }
+
+        return String.valueOf(ch);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/SALauncher.java	Fri Jul 31 10:15:02 2015 -0700
@@ -0,0 +1,359 @@
+/*
+ * 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 sun.jvm.hotspot;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import sun.jvm.hotspot.tools.JStack;
+import sun.jvm.hotspot.tools.JMap;
+import sun.jvm.hotspot.tools.JInfo;
+
+public class SALauncher {
+
+    private static boolean launcherHelp() {
+        System.out.println("    clhsdb       \tcommand line debugger");
+        System.out.println("    hsdb         \tui debugger");
+        System.out.println("    jstack --help\tto get more information");
+        System.out.println("    jmap   --help\tto get more information");
+        System.out.println("    jinfo  --help\tto get more information");
+        return false;
+    }
+
+    private static boolean commonHelp() {
+        // --pid <pid>
+        // --exe <exe>
+        // --core <core>
+        System.out.println("    --exe\texecutable image name");
+        System.out.println("    --core\tpath to coredump");
+        System.out.println("    --pid\tpid of process to attach");
+        return false;
+    }
+
+    private static boolean jinfoHelp() {
+        // --flags -> -flags
+        // --sysprops -> -sysprops
+        System.out.println("    --flags\tto print VM flags");
+        System.out.println("    --sysprops\tto print Java System properties");
+        System.out.println("    <no option>\tto print both of the above");
+        return commonHelp();
+    }
+
+    private static boolean jmapHelp() {
+        // --heap -> -heap
+        // --binaryheap -> -heap:format=b
+        // --histo -> -histo
+        // --clstats -> -clstats
+        // --finalizerinfo -> -finalizerinfo
+
+        System.out.println("    <no option>\tto print same info as Solaris pmap");
+        System.out.println("    --heap\tto print java heap summary");
+        System.out.println("    --binaryheap\tto dump java heap in hprof binary format");
+        System.out.println("    --histo\tto print histogram of java object heap");
+        System.out.println("    --clstats\tto print class loader statistics");
+        System.out.println("    --finalizerinfo\tto print information on objects awaiting finalization");
+        return commonHelp();
+    }
+
+    private static boolean jstackHelp() {
+        // --locks -> -l
+        // --mixed -> -m
+        System.out.println("    --locks\tto print java.util.concurrent locks");
+        System.out.println("    --mixed\tto print both java and native frames (mixed mode)");
+        return commonHelp();
+    }
+
+    private static boolean toolHelp(String toolName) {
+        if (toolName.equals("jstack")) {
+            return jstackHelp();
+        }
+        if (toolName.equals("jinfo")) {
+            return jinfoHelp();
+        }
+        if (toolName.equals("jmap")) {
+            return jmapHelp();
+        }
+        if (toolName.equals("hsdb") || toolName.equals("clhsdb")) {
+            return commonHelp();
+        }
+        return launcherHelp();
+    }
+
+    private static void runCLHSDB(String[] oldArgs) {
+        SAGetopt sg = new SAGetopt(oldArgs);
+        String[] longOpts = {"exe=", "core=", "pid="};
+
+        ArrayList<String> newArgs = new ArrayList();
+        String exeORpid = null;
+        String core = null;
+        String s = null;
+
+        while((s = sg.next(null, longOpts)) != null) {
+            if (s.equals("exe")) {
+                exeORpid = sg.getOptarg();
+                continue;
+            }
+            if (s.equals("core")) {
+                core = sg.getOptarg();
+                continue;
+            }
+            if (s.equals("pid")) {
+                exeORpid = sg.getOptarg();
+                continue;
+            }
+        }
+
+        if (exeORpid != null) {
+            newArgs.add(exeORpid);
+            if (core != null) {
+                newArgs.add(core);
+            }
+        }
+        CLHSDB.main(newArgs.toArray(new String[newArgs.size()]));
+    }
+
+    private static void runHSDB(String[] oldArgs) {
+        SAGetopt sg = new SAGetopt(oldArgs);
+        String[] longOpts = {"exe=", "core=", "pid="};
+
+        ArrayList<String> newArgs = new ArrayList();
+        String exeORpid = null;
+        String core = null;
+        String s = null;
+
+        while((s = sg.next(null, longOpts)) != null) {
+            if (s.equals("exe")) {
+                exeORpid = sg.getOptarg();
+                continue;
+            }
+            if (s.equals("core")) {
+                core = sg.getOptarg();
+                continue;
+            }
+            if (s.equals("pid")) {
+                exeORpid = sg.getOptarg();
+                continue;
+            }
+        }
+
+        if (exeORpid != null) {
+            newArgs.add(exeORpid);
+            if (core != null) {
+                newArgs.add(core);
+            }
+        }
+        HSDB.main(newArgs.toArray(new String[newArgs.size()]));
+    }
+
+    private static void runJSTACK(String[] oldArgs) {
+        SAGetopt sg = new SAGetopt(oldArgs);
+        String[] longOpts = {"exe=", "core=", "pid=",
+                                 "mixed", "locks"};
+
+        ArrayList<String> newArgs = new ArrayList();
+        String exeORpid = null;
+        String core = null;
+        String s = null;
+
+        while((s = sg.next(null, longOpts)) != null) {
+            if (s.equals("exe")) {
+                exeORpid = sg.getOptarg();
+                continue;
+            }
+            if (s.equals("core")) {
+                core = sg.getOptarg();
+                continue;
+            }
+            if (s.equals("pid")) {
+                exeORpid = sg.getOptarg();
+                continue;
+            }
+            if (s.equals("mixed")) {
+                newArgs.add("-m");
+                continue;
+            }
+            if (s.equals("locks")) {
+                newArgs.add("-l");
+                continue;
+            }
+        }
+
+        if (exeORpid != null) {
+            newArgs.add(exeORpid);
+            if (core != null) {
+                newArgs.add(core);
+            }
+        }
+
+        JStack.main(newArgs.toArray(new String[newArgs.size()]));
+    }
+
+    private static void runJMAP(String[] oldArgs) {
+        SAGetopt sg = new SAGetopt(oldArgs);
+        String[] longOpts = {"exe=", "core=", "pid=",
+              "heap", "binaryheap", "histo", "clstats", "finalizerinfo"};
+
+        ArrayList<String> newArgs = new ArrayList();
+        String exeORpid = null;
+        String core = null;
+        String s = null;
+
+        while((s = sg.next(null, longOpts)) != null) {
+            if (s.equals("exe")) {
+                exeORpid = sg.getOptarg();
+                continue;
+            }
+            if (s.equals("core")) {
+                core = sg.getOptarg();
+                continue;
+            }
+            if (s.equals("pid")) {
+                exeORpid = sg.getOptarg();
+                continue;
+            }
+            if (s.equals("heap")) {
+                newArgs.add("-heap");
+                continue;
+            }
+            if (s.equals("binaryheap")) {
+                newArgs.add("-heap:format=b");
+                continue;
+            }
+            if (s.equals("histo")) {
+                newArgs.add("-histo");
+                continue;
+            }
+            if (s.equals("clstats")) {
+                newArgs.add("-clstats");
+                continue;
+            }
+            if (s.equals("finalizerinfo")) {
+                newArgs.add("-finalizerinfo");
+                continue;
+            }
+        }
+
+        if (exeORpid != null) {
+            newArgs.add(exeORpid);
+            if (core != null) {
+                newArgs.add(core);
+            }
+        }
+
+        JMap.main(newArgs.toArray(new String[newArgs.size()]));
+    }
+
+    private static void runJINFO(String[] oldArgs) {
+        SAGetopt sg = new SAGetopt(oldArgs);
+        String[] longOpts = {"exe=", "core=", "pid=",
+                                     "flags", "sysprops"};
+
+        ArrayList<String> newArgs = new ArrayList();
+        String exeORpid = null;
+        String core = null;
+        String s = null;
+
+        while((s = sg.next(null, longOpts)) != null) {
+            if (s.equals("exe")) {
+                exeORpid = sg.getOptarg();
+                continue;
+            }
+            if (s.equals("core")) {
+                core = sg.getOptarg();
+                continue;
+            }
+            if (s.equals("pid")) {
+                exeORpid = sg.getOptarg();
+                continue;
+            }
+            if (s.equals("flags")) {
+                newArgs.add("-flags");
+                continue;
+            }
+            if (s.equals("sysprops")) {
+                newArgs.add("-sysprops");
+                continue;
+            }
+        }
+
+        if (exeORpid != null) {
+            newArgs.add(exeORpid);
+            if (core != null) {
+                newArgs.add(core);
+            }
+        }
+
+        JInfo.main(newArgs.toArray(new String[newArgs.size()]));
+    }
+
+    public static void main(String[] args) {
+        // Provide a help
+        if (args.length == 0) {
+            launcherHelp();
+            return;
+        }
+        // No arguments imply help for jstack, jmap, jinfo but launch clhsdb and hsdb
+        if (args.length == 1 && !args[0].equals("clhsdb") && !args[0].equals("hsdb")) {
+            toolHelp(args[0]);
+            return;
+        }
+
+        for (String arg : args) {
+            if (arg.equals("-h") || arg.equals("-help") || arg.equals("--help")) {
+                toolHelp(args[0]);
+                return;
+            }
+        }
+
+        String[] oldArgs = Arrays.copyOfRange(args, 1, args.length);
+
+        // Run SA interactive mode
+        if (args[0].equals("clhsdb")) {
+            runCLHSDB(oldArgs);
+            return;
+        }
+
+        if (args[0].equals("hsdb")) {
+            runHSDB(oldArgs);
+            return;
+        }
+
+        // Run SA tmtools mode
+        if (args[0].equals("jstack")) {
+            runJSTACK(oldArgs);
+            return;
+        }
+
+        if (args[0].equals("jmap")) {
+            runJMAP(oldArgs);
+            return;
+        }
+
+        if (args[0].equals("jinfo")) {
+            runJINFO(oldArgs);
+            return;
+        }
+    }
+}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/aarch64/AARCH64ThreadContext.java	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/aarch64/AARCH64ThreadContext.java	Fri Jul 31 10:15:02 2015 -0700
@@ -37,6 +37,21 @@
 public abstract class AARCH64ThreadContext implements ThreadContext {
     // Taken from /usr/include/asm/sigcontext.h on Linux/AARCH64.
 
+    //  /*
+    //   * Signal context structure - contains all info to do with the state
+    //   * before the signal handler was invoked.
+    //   */
+    // struct sigcontext {
+    //         __u64 fault_address;
+    //         /* AArch64 registers */
+    //          __u64 regs[31];
+    //          __u64 sp;
+    //          __u64 pc;
+    //          __u64 pstate;
+    //          /* 4K reserved for FP/SIMD state and future expansion */
+    //          __u8 __reserved[4096] __attribute__((__aligned__(16)));
+    //  };
+
     // 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
@@ -78,8 +93,9 @@
     public static final int LR = 30;
     public static final int SP = 31;
     public static final int PC = 32;
+    public static final int PSTATE = 33;
 
-    public static final int NPRGREG = 33;
+    public static final int NPRGREG = 34;
 
     private long[] data;
 
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc/g1/G1Allocator.java	Wed Jul 05 20:44:11 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-package sun.jvm.hotspot.gc.g1;
-
-import java.util.Observable;
-import java.util.Observer;
-
-import sun.jvm.hotspot.debugger.Address;
-import sun.jvm.hotspot.runtime.VM;
-import sun.jvm.hotspot.runtime.VMObject;
-import sun.jvm.hotspot.types.CIntegerField;
-import sun.jvm.hotspot.types.Type;
-import sun.jvm.hotspot.types.TypeDataBase;
-
-public class G1Allocator extends VMObject {
-
-  //size_t _summary_bytes_used;
-  static private CIntegerField summaryBytesUsedField;
-
-  static {
-    VM.registerVMInitializedObserver(new Observer() {
-      public void update(Observable o, Object data) {
-        initialize(VM.getVM().getTypeDataBase());
-      }
-    });
-  }
-
-  static private synchronized void initialize(TypeDataBase db) {
-    Type type = db.lookupType("G1Allocator");
-
-    summaryBytesUsedField = type.getCIntegerField("_summary_bytes_used");
-  }
-
-  public long getSummaryBytes() {
-    return summaryBytesUsedField.getValue(addr);
-  }
-
-  public G1Allocator(Address addr) {
-    super(addr);
-
-  }
-}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc/g1/G1CollectedHeap.java	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc/g1/G1CollectedHeap.java	Fri Jul 31 10:15:02 2015 -0700
@@ -36,6 +36,7 @@
 import sun.jvm.hotspot.runtime.VM;
 import sun.jvm.hotspot.runtime.VMObjectFactory;
 import sun.jvm.hotspot.types.AddressField;
+import sun.jvm.hotspot.types.CIntegerField;
 import sun.jvm.hotspot.types.Type;
 import sun.jvm.hotspot.types.TypeDataBase;
 
@@ -46,8 +47,8 @@
     static private long hrmFieldOffset;
     // MemRegion _g1_reserved;
     static private long g1ReservedFieldOffset;
-    // G1Allocator* _allocator
-    static private AddressField g1Allocator;
+    // size_t _summary_bytes_used;
+    static private CIntegerField summaryBytesUsedField;
     // G1MonitoringSupport* _g1mm;
     static private AddressField g1mmField;
     // HeapRegionSet _old_set;
@@ -67,7 +68,7 @@
         Type type = db.lookupType("G1CollectedHeap");
 
         hrmFieldOffset = type.getField("_hrm").getOffset();
-        g1Allocator = type.getAddressField("_allocator");
+        summaryBytesUsedField = type.getCIntegerField("_summary_bytes_used");
         g1mmField = type.getAddressField("_g1mm");
         oldSetFieldOffset = type.getField("_old_set").getOffset();
         humongousSetFieldOffset = type.getField("_humongous_set").getOffset();
@@ -78,7 +79,7 @@
     }
 
     public long used() {
-        return allocator().getSummaryBytes();
+        return summaryBytesUsedField.getValue(addr);
     }
 
     public long n_regions() {
@@ -96,11 +97,6 @@
         return (G1MonitoringSupport) VMObjectFactory.newObject(G1MonitoringSupport.class, g1mmAddr);
     }
 
-    public G1Allocator allocator() {
-        Address g1AllocatorAddr = g1Allocator.getValue(addr);
-        return (G1Allocator) VMObjectFactory.newObject(G1Allocator.class, g1AllocatorAddr);
-    }
-
     public HeapRegionSetBase oldSet() {
         Address oldSetAddr = addr.addOffsetTo(oldSetFieldOffset);
         return (HeapRegionSetBase) VMObjectFactory.newObject(HeapRegionSetBase.class,
--- a/hotspot/src/cpu/aarch64/vm/aarch64.ad	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad	Fri Jul 31 10:15:02 2015 -0700
@@ -2167,8 +2167,12 @@
     return 0;            // Self copy, no move.
   }
 
+  bool is64 = (src_lo & 1) == 0 && src_lo + 1 == src_hi &&
+              (dst_lo & 1) == 0 && dst_lo + 1 == dst_hi;
+  int src_offset = ra_->reg2offset(src_lo);
+  int dst_offset = ra_->reg2offset(dst_lo);
+
   if (bottom_type()->isa_vect() != NULL) {
-    uint len = 4;
     uint ireg = ideal_reg();
     assert(ireg == Op_VecD || ireg == Op_VecX, "must be 64 bit or 128 bit vector");
     if (cbuf) {
@@ -2176,334 +2180,115 @@
       assert((src_lo_rc != rc_int && dst_lo_rc != rc_int), "sanity");
       if (src_lo_rc == rc_stack && dst_lo_rc == rc_stack) {
         // stack->stack
-        int src_offset = ra_->reg2offset(src_lo);
-        int dst_offset = ra_->reg2offset(dst_lo);
         assert((src_offset & 7) && (dst_offset & 7), "unaligned stack offset");
-        len = 8;
         if (ireg == Op_VecD) {
-          __ ldr(rscratch1, Address(sp, src_offset));
-          __ str(rscratch1, Address(sp, dst_offset));
+          __ unspill(rscratch1, true, src_offset);
+          __ spill(rscratch1, true, dst_offset);
         } else {
-          if (src_offset < 512) {
-            __ ldp(rscratch1, rscratch2, Address(sp, src_offset));
-          } else {
-            __ ldr(rscratch1, Address(sp, src_offset));
-            __ ldr(rscratch2, Address(sp, src_offset+4));
-            len += 4;
-          }
-          if (dst_offset < 512) {
-            __ stp(rscratch1, rscratch2, Address(sp, dst_offset));
-          } else {
-            __ str(rscratch1, Address(sp, dst_offset));
-            __ str(rscratch2, Address(sp, dst_offset+4));
-            len += 4;
-          }
+          __ spill_copy128(src_offset, dst_offset);
         }
       } else if (src_lo_rc == rc_float && dst_lo_rc == rc_float) {
-        __ orr(as_FloatRegister(Matcher::_regEncode[dst_lo]),
+        __ mov(as_FloatRegister(Matcher::_regEncode[dst_lo]),
                ireg == Op_VecD ? __ T8B : __ T16B,
-               as_FloatRegister(Matcher::_regEncode[src_lo]),
                as_FloatRegister(Matcher::_regEncode[src_lo]));
       } else if (src_lo_rc == rc_float && dst_lo_rc == rc_stack) {
-        __ str(as_FloatRegister(Matcher::_regEncode[src_lo]),
-               ireg == Op_VecD ? __ D : __ Q,
-               Address(sp, ra_->reg2offset(dst_lo)));
+        __ spill(as_FloatRegister(Matcher::_regEncode[src_lo]),
+                       ireg == Op_VecD ? __ D : __ Q,
+                       ra_->reg2offset(dst_lo));
       } else if (src_lo_rc == rc_stack && dst_lo_rc == rc_float) {
-        __ ldr(as_FloatRegister(Matcher::_regEncode[dst_lo]),
-               ireg == Op_VecD ? __ D : __ Q,
-               Address(sp, ra_->reg2offset(src_lo)));
+        __ unspill(as_FloatRegister(Matcher::_regEncode[dst_lo]),
+                       ireg == Op_VecD ? __ D : __ Q,
+                       ra_->reg2offset(src_lo));
       } else {
         ShouldNotReachHere();
       }
-    } else if (st) {
-      if (src_lo_rc == rc_stack && dst_lo_rc == rc_stack) {
-        // stack->stack
-        int src_offset = ra_->reg2offset(src_lo);
-        int dst_offset = ra_->reg2offset(dst_lo);
-        if (ireg == Op_VecD) {
-          st->print("ldr  rscratch1, [sp, #%d]", src_offset);
-          st->print("str  rscratch1, [sp, #%d]", dst_offset);
+    }
+  } else if (cbuf) {
+    MacroAssembler _masm(cbuf);
+    switch (src_lo_rc) {
+    case rc_int:
+      if (dst_lo_rc == rc_int) {  // gpr --> gpr copy
+        if (is64) {
+            __ mov(as_Register(Matcher::_regEncode[dst_lo]),
+                   as_Register(Matcher::_regEncode[src_lo]));
         } else {
-          if (src_offset < 512) {
-            st->print("ldp  rscratch1, rscratch2, [sp, #%d]", src_offset);
-          } else {
-            st->print("ldr  rscratch1, [sp, #%d]", src_offset);
-            st->print("\nldr  rscratch2, [sp, #%d]", src_offset+4);
-          }
-          if (dst_offset < 512) {
-            st->print("\nstp  rscratch1, rscratch2, [sp, #%d]", dst_offset);
-          } else {
-            st->print("\nstr  rscratch1, [sp, #%d]", dst_offset);
-            st->print("\nstr  rscratch2, [sp, #%d]", dst_offset+4);
-          }
-        }
-        st->print("\t# vector spill, stack to stack");
-      } else if (src_lo_rc == rc_float && dst_lo_rc == rc_float) {
-        st->print("mov  %s, %s\t# vector spill, reg to reg",
-                   Matcher::regName[dst_lo], Matcher::regName[src_lo]);
-      } else if (src_lo_rc == rc_float && dst_lo_rc == rc_stack) {
-        st->print("str  %s, [sp, #%d]\t# vector spill, reg to stack",
-                   Matcher::regName[src_lo], ra_->reg2offset(dst_lo));
-      } else if (src_lo_rc == rc_stack && dst_lo_rc == rc_float) {
-        st->print("ldr  %s, [sp, #%d]\t# vector spill, stack to reg",
-                   Matcher::regName[dst_lo], ra_->reg2offset(src_lo));
-      }
-    }
-    return len;
-  }
-
-  switch (src_lo_rc) {
-  case rc_int:
-    if (dst_lo_rc == rc_int) {  // gpr --> gpr copy
-      if (((src_lo & 1) == 0 && src_lo + 1 == src_hi) &&
-          (dst_lo & 1) == 0 && dst_lo + 1 == dst_hi) {
-          // 64 bit
-        if (cbuf) {
-          MacroAssembler _masm(cbuf);
-          __ mov(as_Register(Matcher::_regEncode[dst_lo]),
-                 as_Register(Matcher::_regEncode[src_lo]));
-        } else if (st) {
-          st->print("mov  %s, %s\t# shuffle",
-                    Matcher::regName[dst_lo],
-                    Matcher::regName[src_lo]);
-        }
-      } else {
-        // 32 bit
-        if (cbuf) {
-          MacroAssembler _masm(cbuf);
-          __ movw(as_Register(Matcher::_regEncode[dst_lo]),
-                  as_Register(Matcher::_regEncode[src_lo]));
-        } else if (st) {
-          st->print("movw  %s, %s\t# shuffle",
-                    Matcher::regName[dst_lo],
-                    Matcher::regName[src_lo]);
+            MacroAssembler _masm(cbuf);
+            __ movw(as_Register(Matcher::_regEncode[dst_lo]),
+                    as_Register(Matcher::_regEncode[src_lo]));
         }
-      }
-    } else if (dst_lo_rc == rc_float) { // gpr --> fpr copy
-      if (((src_lo & 1) == 0 && src_lo + 1 == src_hi) &&
-          (dst_lo & 1) == 0 && dst_lo + 1 == dst_hi) {
-          // 64 bit
-        if (cbuf) {
-          MacroAssembler _masm(cbuf);
-          __ fmovd(as_FloatRegister(Matcher::_regEncode[dst_lo]),
-                   as_Register(Matcher::_regEncode[src_lo]));
-        } else if (st) {
-          st->print("fmovd  %s, %s\t# shuffle",
-                    Matcher::regName[dst_lo],
-                    Matcher::regName[src_lo]);
-        }
-      } else {
-        // 32 bit
-        if (cbuf) {
-          MacroAssembler _masm(cbuf);
-          __ fmovs(as_FloatRegister(Matcher::_regEncode[dst_lo]),
-                   as_Register(Matcher::_regEncode[src_lo]));
-        } else if (st) {
-          st->print("fmovs  %s, %s\t# shuffle",
-                    Matcher::regName[dst_lo],
-                    Matcher::regName[src_lo]);
-        }
-      }
-    } else {                    // gpr --> stack spill
-      assert(dst_lo_rc == rc_stack, "spill to bad register class");
-      int dst_offset = ra_->reg2offset(dst_lo);
-      if (((src_lo & 1) == 0 && src_lo + 1 == src_hi) &&
-          (dst_lo & 1) == 0 && dst_lo + 1 == dst_hi) {
-          // 64 bit
-        if (cbuf) {
-          MacroAssembler _masm(cbuf);
-          __ str(as_Register(Matcher::_regEncode[src_lo]),
-                 Address(sp, dst_offset));
-        } else if (st) {
-          st->print("str  %s, [sp, #%d]\t# spill",
-                    Matcher::regName[src_lo],
-                    dst_offset);
-        }
-      } else {
-        // 32 bit
-        if (cbuf) {
-          MacroAssembler _masm(cbuf);
-          __ strw(as_Register(Matcher::_regEncode[src_lo]),
-                 Address(sp, dst_offset));
-        } else if (st) {
-          st->print("strw  %s, [sp, #%d]\t# spill",
-                    Matcher::regName[src_lo],
-                    dst_offset);
-        }
-      }
-    }
-    return 4;
-  case rc_float:
-    if (dst_lo_rc == rc_int) {  // fpr --> gpr copy
-      if (((src_lo & 1) == 0 && src_lo + 1 == src_hi) &&
-          (dst_lo & 1) == 0 && dst_lo + 1 == dst_hi) {
-          // 64 bit
-        if (cbuf) {
-          MacroAssembler _masm(cbuf);
-          __ fmovd(as_Register(Matcher::_regEncode[dst_lo]),
-                   as_FloatRegister(Matcher::_regEncode[src_lo]));
-        } else if (st) {
-          st->print("fmovd  %s, %s\t# shuffle",
-                    Matcher::regName[dst_lo],
-                    Matcher::regName[src_lo]);
+      } else if (dst_lo_rc == rc_float) { // gpr --> fpr copy
+        if (is64) {
+            __ fmovd(as_FloatRegister(Matcher::_regEncode[dst_lo]),
+                     as_Register(Matcher::_regEncode[src_lo]));
+        } else {
+            __ fmovs(as_FloatRegister(Matcher::_regEncode[dst_lo]),
+                     as_Register(Matcher::_regEncode[src_lo]));
         }
-      } else {
-        // 32 bit
-        if (cbuf) {
-          MacroAssembler _masm(cbuf);
-          __ fmovs(as_Register(Matcher::_regEncode[dst_lo]),
-                   as_FloatRegister(Matcher::_regEncode[src_lo]));
-        } else if (st) {
-          st->print("fmovs  %s, %s\t# shuffle",
-                    Matcher::regName[dst_lo],
-                    Matcher::regName[src_lo]);
-        }
-      }
-    } else if (dst_lo_rc == rc_float) { // fpr --> fpr copy
-      if (((src_lo & 1) == 0 && src_lo + 1 == src_hi) &&
-          (dst_lo & 1) == 0 && dst_lo + 1 == dst_hi) {
-          // 64 bit
-        if (cbuf) {
-          MacroAssembler _masm(cbuf);
-          __ fmovd(as_FloatRegister(Matcher::_regEncode[dst_lo]),
-                   as_FloatRegister(Matcher::_regEncode[src_lo]));
-        } else if (st) {
-          st->print("fmovd  %s, %s\t# shuffle",
-                    Matcher::regName[dst_lo],
-                    Matcher::regName[src_lo]);
-        }
-      } else {
-        // 32 bit
-        if (cbuf) {
-          MacroAssembler _masm(cbuf);
-          __ fmovs(as_FloatRegister(Matcher::_regEncode[dst_lo]),
-                   as_FloatRegister(Matcher::_regEncode[src_lo]));
-        } else if (st) {
-          st->print("fmovs  %s, %s\t# shuffle",
-                    Matcher::regName[dst_lo],
-                    Matcher::regName[src_lo]);
-        }
-      }
-    } else {                    // fpr --> stack spill
-      assert(dst_lo_rc == rc_stack, "spill to bad register class");
-      int dst_offset = ra_->reg2offset(dst_lo);
-      if (((src_lo & 1) == 0 && src_lo + 1 == src_hi) &&
-          (dst_lo & 1) == 0 && dst_lo + 1 == dst_hi) {
-          // 64 bit
-        if (cbuf) {
-          MacroAssembler _masm(cbuf);
-          __ strd(as_FloatRegister(Matcher::_regEncode[src_lo]),
-                 Address(sp, dst_offset));
-        } else if (st) {
-          st->print("strd  %s, [sp, #%d]\t# spill",
-                    Matcher::regName[src_lo],
-                    dst_offset);
-        }
-      } else {
-        // 32 bit
-        if (cbuf) {
-          MacroAssembler _masm(cbuf);
-          __ strs(as_FloatRegister(Matcher::_regEncode[src_lo]),
-                 Address(sp, dst_offset));
-        } else if (st) {
-          st->print("strs  %s, [sp, #%d]\t# spill",
-                    Matcher::regName[src_lo],
-                    dst_offset);
-        }
+      } else {                    // gpr --> stack spill
+        assert(dst_lo_rc == rc_stack, "spill to bad register class");
+        __ spill(as_Register(Matcher::_regEncode[src_lo]), is64, dst_offset);
       }
-    }
-    return 4;
-  case rc_stack:
-    int src_offset = ra_->reg2offset(src_lo);
-    if (dst_lo_rc == rc_int) {  // stack --> gpr load
-      if (((src_lo & 1) == 0 && src_lo + 1 == src_hi) &&
-          (dst_lo & 1) == 0 && dst_lo + 1 == dst_hi) {
-          // 64 bit
-        if (cbuf) {
-          MacroAssembler _masm(cbuf);
-          __ ldr(as_Register(Matcher::_regEncode[dst_lo]),
-                 Address(sp, src_offset));
-        } else if (st) {
-          st->print("ldr  %s, [sp, %d]\t# restore",
-                    Matcher::regName[dst_lo],
-                    src_offset);
+      break;
+    case rc_float:
+      if (dst_lo_rc == rc_int) {  // fpr --> gpr copy
+        if (is64) {
+            __ fmovd(as_Register(Matcher::_regEncode[dst_lo]),
+                     as_FloatRegister(Matcher::_regEncode[src_lo]));
+        } else {
+            __ fmovs(as_Register(Matcher::_regEncode[dst_lo]),
+                     as_FloatRegister(Matcher::_regEncode[src_lo]));
         }
-      } else {
-        // 32 bit
-        if (cbuf) {
-          MacroAssembler _masm(cbuf);
-          __ ldrw(as_Register(Matcher::_regEncode[dst_lo]),
-                  Address(sp, src_offset));
-        } else if (st) {
-          st->print("ldr  %s, [sp, %d]\t# restore",
-                    Matcher::regName[dst_lo],
-                   src_offset);
-        }
-      }
-      return 4;
-    } else if (dst_lo_rc == rc_float) { // stack --> fpr load
-      if (((src_lo & 1) == 0 && src_lo + 1 == src_hi) &&
-          (dst_lo & 1) == 0 && dst_lo + 1 == dst_hi) {
-          // 64 bit
-        if (cbuf) {
-          MacroAssembler _masm(cbuf);
-          __ ldrd(as_FloatRegister(Matcher::_regEncode[dst_lo]),
-                 Address(sp, src_offset));
-        } else if (st) {
-          st->print("ldrd  %s, [sp, %d]\t# restore",
-                    Matcher::regName[dst_lo],
-                    src_offset);
+      } else if (dst_lo_rc == rc_float) { // fpr --> fpr copy
+          if (cbuf) {
+            __ fmovd(as_FloatRegister(Matcher::_regEncode[dst_lo]),
+                     as_FloatRegister(Matcher::_regEncode[src_lo]));
+        } else {
+            __ fmovs(as_FloatRegister(Matcher::_regEncode[dst_lo]),
+                     as_FloatRegister(Matcher::_regEncode[src_lo]));
         }
-      } else {
-        // 32 bit
-        if (cbuf) {
-          MacroAssembler _masm(cbuf);
-          __ ldrs(as_FloatRegister(Matcher::_regEncode[dst_lo]),
-                  Address(sp, src_offset));
-        } else if (st) {
-          st->print("ldrs  %s, [sp, %d]\t# restore",
-                    Matcher::regName[dst_lo],
-                   src_offset);
-        }
+      } else {                    // fpr --> stack spill
+        assert(dst_lo_rc == rc_stack, "spill to bad register class");
+        __ spill(as_FloatRegister(Matcher::_regEncode[src_lo]),
+                 is64 ? __ D : __ S, dst_offset);
       }
-      return 4;
-    } else {                    // stack --> stack copy
-      assert(dst_lo_rc == rc_stack, "spill to bad register class");
-      int dst_offset = ra_->reg2offset(dst_lo);
-      if (((src_lo & 1) == 0 && src_lo + 1 == src_hi) &&
-          (dst_lo & 1) == 0 && dst_lo + 1 == dst_hi) {
-          // 64 bit
-        if (cbuf) {
-          MacroAssembler _masm(cbuf);
-          __ ldr(rscratch1, Address(sp, src_offset));
-          __ str(rscratch1, Address(sp, dst_offset));
-        } else if (st) {
-          st->print("ldr  rscratch1, [sp, %d]\t# mem-mem spill",
-                    src_offset);
-          st->print("\n\t");
-          st->print("str  rscratch1, [sp, %d]",
-                    dst_offset);
-        }
-      } else {
-        // 32 bit
-        if (cbuf) {
-          MacroAssembler _masm(cbuf);
-          __ ldrw(rscratch1, Address(sp, src_offset));
-          __ strw(rscratch1, Address(sp, dst_offset));
-        } else if (st) {
-          st->print("ldrw  rscratch1, [sp, %d]\t# mem-mem spill",
-                    src_offset);
-          st->print("\n\t");
-          st->print("strw  rscratch1, [sp, %d]",
-                    dst_offset);
-        }
+      break;
+    case rc_stack:
+      if (dst_lo_rc == rc_int) {  // stack --> gpr load
+        __ unspill(as_Register(Matcher::_regEncode[dst_lo]), is64, src_offset);
+      } else if (dst_lo_rc == rc_float) { // stack --> fpr load
+        __ unspill(as_FloatRegister(Matcher::_regEncode[dst_lo]),
+                   is64 ? __ D : __ S, src_offset);
+      } else {                    // stack --> stack copy
+        assert(dst_lo_rc == rc_stack, "spill to bad register class");
+        __ unspill(rscratch1, is64, src_offset);
+        __ spill(rscratch1, is64, dst_offset);
       }
-      return 8;
+      break;
+    default:
+      assert(false, "bad rc_class for spill");
+      ShouldNotReachHere();
     }
   }
 
-  assert(false," bad rc_class for spill ");
-  Unimplemented();
+  if (st) {
+    st->print("spill ");
+    if (src_lo_rc == rc_stack) {
+      st->print("[sp, #%d] -> ", ra_->reg2offset(src_lo));
+    } else {
+      st->print("%s -> ", Matcher::regName[src_lo]);
+    }
+    if (dst_lo_rc == rc_stack) {
+      st->print("[sp, #%d]", ra_->reg2offset(dst_lo));
+    } else {
+      st->print("%s", Matcher::regName[dst_lo]);
+    }
+    if (bottom_type()->isa_vect() != NULL) {
+      st->print("\t# vector spill size = %d", ideal_reg()==Op_VecD ? 64:128);
+    } else {
+      st->print("\t# spill size = %d", is64 ? 64:32);
+    }
+  }
+
   return 0;
 
 }
@@ -2522,7 +2307,7 @@
 }
 
 uint MachSpillCopyNode::size(PhaseRegAlloc *ra_) const {
-  return implementation(NULL, ra_, true, NULL);
+  return MachNode::size(ra_);
 }
 
 //=============================================================================
--- a/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp	Fri Jul 31 10:15:02 2015 -0700
@@ -1896,7 +1896,7 @@
  public:
 
   enum SIMD_Arrangement {
-       T8B, T16B, T4H, T8H, T2S, T4S, T1D, T2D
+       T8B, T16B, T4H, T8H, T2S, T4S, T1D, T2D, T1Q
   };
 
   enum SIMD_RegVariant {
@@ -2225,14 +2225,16 @@
     f(0b001111, 15, 10), rf(Vn, 5), rf(Xd, 0);
   }
 
-  // We do not handle the 1Q arrangement.
   void pmull(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, FloatRegister Vm, SIMD_Arrangement Tb) {
     starti;
-    assert(Ta == T8H && (Tb == T8B || Tb == T16B), "Invalid Size specifier");
-    f(0, 31), f(Tb & 1, 30), f(0b001110001, 29, 21), rf(Vm, 16), f(0b111000, 15, 10);
-    rf(Vn, 5), rf(Vd, 0);
+    assert((Ta == T1Q && (Tb == T1D || Tb == T2D)) ||
+           (Ta == T8H && (Tb == T8B || Tb == T16B)), "Invalid Size specifier");
+    int size = (Ta == T1Q) ? 0b11 : 0b00;
+    f(0, 31), f(Tb & 1, 30), f(0b001110, 29, 24), f(size, 23, 22);
+    f(1, 21), rf(Vm, 16), f(0b111000, 15, 10), rf(Vn, 5), rf(Vd, 0);
   }
   void pmull2(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, FloatRegister Vm, SIMD_Arrangement Tb) {
+    assert(Tb == T2D || Tb == T16B, "pmull2 assumes T2D or T16B as the second size specifier");
     pmull(Vd, Ta, Vn, Vm, Tb);
   }
 
@@ -2245,15 +2247,6 @@
     f(0b100001010010, 21, 10), rf(Vn, 5), rf(Vd, 0);
   }
 
-  void rev32(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn)
-  {
-    starti;
-    assert(T <= T8H, "must be one of T8B, T16B, T4H, T8H");
-    f(0, 31), f((int)T & 1, 30), f(0b101110, 29, 24);
-    f(T <= T16B ? 0b00 : 0b01, 23, 22), f(0b100000000010, 21, 10);
-    rf(Vn, 5), rf(Vd, 0);
-  }
-
   void dup(FloatRegister Vd, SIMD_Arrangement T, Register Xs)
   {
     starti;
@@ -2290,6 +2283,57 @@
 
 #undef INSN
 
+  // Table vector lookup
+#define INSN(NAME, op)                                                                                       \
+  void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, unsigned registers, FloatRegister Vm) {  \
+    starti;                                                                                                  \
+    assert(T == T8B || T == T16B, "invalid arrangement");                                                    \
+    assert(0 < registers && registers <= 4, "invalid number of registers");                                  \
+    f(0, 31), f((int)T & 1, 30), f(0b001110000, 29, 21), rf(Vm, 16), f(0, 15);                               \
+    f(registers - 1, 14, 13), f(op, 12),f(0b00, 11, 10), rf(Vn, 5), rf(Vd, 0);                               \
+  }
+
+  INSN(tbl, 0);
+  INSN(tbx, 1);
+
+#undef INSN
+
+#define INSN(NAME, U, opcode)                                                       \
+  void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn) {               \
+       starti;                                                                      \
+       assert((ASSERTION), MSG);                                                    \
+       f(0, 31), f((int)T & 1, 30), f(U, 29), f(0b01110, 28, 24);                   \
+       f((int)(T >> 1), 23, 22), f(0b10000, 21, 17), f(opcode, 16, 12);             \
+       f(0b10, 11, 10), rf(Vn, 5), rf(Vd, 0);                                       \
+ }
+
+#define MSG "invalid arrangement"
+
+#define ASSERTION (T == T8B || T == T16B || T == T4H || T == T8H || T == T2S || T == T4S)
+  INSN(rev64, 0, 0b00000);
+#undef ASSERTION
+
+#define ASSERTION (T == T8B || T == T16B || T == T4H || T == T8H)
+  INSN(rev32, 1, 0b00000);
+#undef ASSERTION
+
+#define ASSERTION (T == T8B || T == T16B)
+  INSN(rev16, 0, 0b00001);
+#undef ASSERTION
+
+#undef MSG
+
+#undef INSN
+
+void ext(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, FloatRegister Vm, int index)
+  {
+    starti;
+    assert(T == T8B || T == T16B, "invalid arrangement");
+    assert((T == T8B && index <= 0b0111) || (T == T16B && index <= 0b1111), "Invalid index value");
+    f(0, 31), f((int)T & 1, 30), f(0b101110000, 29, 21);
+    rf(Vm, 16), f(0, 15), f(index, 14, 11);
+    f(0, 10), rf(Vn, 5), rf(Vd, 0);
+  }
 
 /* Simulator extensions to the ISA
 
--- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp	Fri Jul 31 10:15:02 2015 -0700
@@ -2009,6 +2009,14 @@
   }
 }
 
+void MacroAssembler::sub(Register Rd, Register Rn, RegisterOrConstant decrement) {
+  if (decrement.is_register()) {
+    sub(Rd, Rn, decrement.as_register());
+  } else {
+    sub(Rd, Rn, decrement.as_constant());
+  }
+}
+
 void MacroAssembler::reinit_heapbase()
 {
   if (UseCompressedOops) {
@@ -2307,6 +2315,28 @@
   }
 }
 
+Address MacroAssembler::spill_address(int size, int offset, Register tmp)
+{
+  assert(offset >= 0, "spill to negative address?");
+  // Offset reachable ?
+  //   Not aligned - 9 bits signed offset
+  //   Aligned - 12 bits unsigned offset shifted
+  Register base = sp;
+  if ((offset & (size-1)) && offset >= (1<<8)) {
+    add(tmp, base, offset & ((1<<12)-1));
+    base = tmp;
+    offset &= -1<<12;
+  }
+
+  if (offset >= (1<<12) * size) {
+    add(tmp, base, offset & (((1<<12)-1)<<12));
+    base = tmp;
+    offset &= ~(((1<<12)-1)<<12);
+  }
+
+  return Address(base, offset);
+}
+
 /**
  * Multiply 64 bit by 64 bit first loop.
  */
--- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp	Fri Jul 31 10:15:02 2015 -0700
@@ -464,10 +464,21 @@
     mov(dst, (long)i);
   }
 
+  void mov(Register dst, RegisterOrConstant src) {
+    if (src.is_register())
+      mov(dst, src.as_register());
+    else
+      mov(dst, src.as_constant());
+  }
+
   void movptr(Register r, uintptr_t imm64);
 
   void mov(FloatRegister Vd, SIMD_Arrangement T, u_int32_t imm32);
 
+  void mov(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn) {
+    orr(Vd, T, Vn, Vn);
+  }
+
   // macro instructions for accessing and updating floating point
   // status register
   //
@@ -1045,6 +1056,7 @@
 
   void add(Register Rd, Register Rn, RegisterOrConstant increment);
   void addw(Register Rd, Register Rn, RegisterOrConstant increment);
+  void sub(Register Rd, Register Rn, RegisterOrConstant decrement);
 
   void adrp(Register reg1, const Address &dest, unsigned long &byte_offset);
 
@@ -1161,6 +1173,46 @@
   // Uses rscratch2.
   Address offsetted_address(Register r, Register r1, Address::extend ext,
                             int offset, int size);
+
+private:
+  // Returns an address on the stack which is reachable with a ldr/str of size
+  // Uses rscratch2 if the address is not directly reachable
+  Address spill_address(int size, int offset, Register tmp=rscratch2);
+
+public:
+  void spill(Register Rx, bool is64, int offset) {
+    if (is64) {
+      str(Rx, spill_address(8, offset));
+    } else {
+      strw(Rx, spill_address(4, offset));
+    }
+  }
+  void spill(FloatRegister Vx, SIMD_RegVariant T, int offset) {
+    str(Vx, T, spill_address(1 << (int)T, offset));
+  }
+  void unspill(Register Rx, bool is64, int offset) {
+    if (is64) {
+      ldr(Rx, spill_address(8, offset));
+    } else {
+      ldrw(Rx, spill_address(4, offset));
+    }
+  }
+  void unspill(FloatRegister Vx, SIMD_RegVariant T, int offset) {
+    ldr(Vx, T, spill_address(1 << (int)T, offset));
+  }
+  void spill_copy128(int src_offset, int dst_offset,
+                     Register tmp1=rscratch1, Register tmp2=rscratch2) {
+    if (src_offset < 512 && (src_offset & 7) == 0 &&
+        dst_offset < 512 && (dst_offset & 7) == 0) {
+      ldp(tmp1, tmp2, Address(sp, src_offset));
+      stp(tmp1, tmp2, Address(sp, dst_offset));
+    } else {
+      unspill(tmp1, true, src_offset);
+      spill(tmp1, true, dst_offset);
+      unspill(tmp1, true, src_offset+8);
+      spill(tmp1, true, dst_offset+8);
+    }
+  }
 };
 
 #ifdef ASSERT
--- a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp	Fri Jul 31 10:15:02 2015 -0700
@@ -120,10 +120,8 @@
   // we save r19-r28 which Java uses as scratch registers and C
   // expects to be callee-save
   //
-  // we don't save any FP registers since only v8-v15 are callee-save
-  // (strictly only the f and d components) and Java uses them as
-  // callee-save. v0-v7 are arg registers and C treats v16-v31 as
-  // volatile (as does Java?)
+  // we save the bottom 64 bits of each value stored in v8-v15; it is
+  // the responsibility of the caller to preserve larger values.
   //
   // so the stub frame looks like this when we enter Java code
   //
@@ -131,14 +129,14 @@
   //     [ argument word n      ]
   //      ...
   // -27 [ argument word 1      ]
-  // -26 [ saved d15            ] <--- sp_after_call
-  // -25 [ saved d14            ]
-  // -24 [ saved d13            ]
-  // -23 [ saved d12            ]
-  // -22 [ saved d11            ]
-  // -21 [ saved d10            ]
-  // -20 [ saved d9             ]
-  // -19 [ saved d8             ]
+  // -26 [ saved v15            ] <--- sp_after_call
+  // -25 [ saved v14            ]
+  // -24 [ saved v13            ]
+  // -23 [ saved v12            ]
+  // -22 [ saved v11            ]
+  // -21 [ saved v10            ]
+  // -20 [ saved v9             ]
+  // -19 [ saved v8             ]
   // -18 [ saved r28            ]
   // -17 [ saved r27            ]
   // -16 [ saved r26            ]
@@ -2437,6 +2435,137 @@
     return start;
   }
 
+  /**
+   *  Arguments:
+   *
+   *  Input:
+   *  c_rarg0   - current state address
+   *  c_rarg1   - H key address
+   *  c_rarg2   - data address
+   *  c_rarg3   - number of blocks
+   *
+   *  Output:
+   *  Updated state at c_rarg0
+   */
+  address generate_ghash_processBlocks() {
+    __ align(CodeEntryAlignment);
+    Label L_ghash_loop, L_exit;
+
+    StubCodeMark mark(this, "StubRoutines", "ghash_processBlocks");
+    address start = __ pc();
+
+    Register state   = c_rarg0;
+    Register subkeyH = c_rarg1;
+    Register data    = c_rarg2;
+    Register blocks  = c_rarg3;
+
+    FloatRegister vzr = v30;
+    __ eor(vzr, __ T16B, vzr, vzr); // zero register
+
+    __ mov(v26, __ T16B, 1);
+    __ mov(v27, __ T16B, 63);
+    __ mov(v28, __ T16B, 62);
+    __ mov(v29, __ T16B, 57);
+
+    __ ldrq(v6, Address(state));
+    __ ldrq(v16, Address(subkeyH));
+
+    __ ext(v0, __ T16B, v6, v6, 0x08);
+    __ ext(v1, __ T16B, v16, v16, 0x08);
+    __ eor(v16, __ T16B, v16, v1);
+
+    __ bind(L_ghash_loop);
+
+    __ ldrq(v2, Address(__ post(data, 0x10)));
+    __ rev64(v2, __ T16B, v2); // swap data
+
+    __ ext(v6, __ T16B, v0, v0, 0x08);
+    __ eor(v6, __ T16B, v6, v2);
+    __ ext(v2, __ T16B, v6, v6, 0x08);
+
+    __ pmull2(v7, __ T1Q, v2, v1, __ T2D);  // A1*B1
+    __ eor(v6, __ T16B, v6, v2);
+    __ pmull(v5,  __ T1Q, v2, v1, __ T1D);  // A0*B0
+    __ pmull(v20, __ T1Q, v6, v16, __ T1D);  // (A1 + A0)(B1 + B0)
+
+    __ ext(v21, __ T16B, v5, v7, 0x08);
+    __ eor(v18, __ T16B, v7, v5); // A1*B1 xor A0*B0
+    __ eor(v20, __ T16B, v20, v21);
+    __ eor(v20, __ T16B, v20, v18);
+
+    // Registers pair <v7:v5> holds the result of carry-less multiplication
+    __ ins(v7, __ D, v20, 0, 1);
+    __ ins(v5, __ D, v20, 1, 0);
+
+    // Result of the multiplication is shifted by one bit position
+    // [X3:X2:X1:X0] = [X3:X2:X1:X0] << 1
+    __ ushr(v18, __ T2D, v5, -63 & 63);
+    __ ins(v25, __ D, v18, 1, 0);
+    __ ins(v25, __ D, vzr, 0, 0);
+    __ ushl(v5, __ T2D, v5, v26);
+    __ orr(v5, __ T16B, v5, v25);
+
+    __ ushr(v19, __ T2D, v7, -63 & 63);
+    __ ins(v19, __ D, v19, 1, 0);
+    __ ins(v19, __ D, v18, 0, 1);
+    __ ushl(v7, __ T2D, v7, v26);
+    __ orr(v6, __ T16B, v7, v19);
+
+    __ ins(v24, __ D, v5, 0, 1);
+
+    // A = X0 << 63
+    __ ushl(v21, __ T2D, v5, v27);
+
+    // A = X0 << 62
+    __ ushl(v22, __ T2D, v5, v28);
+
+    // A = X0 << 57
+    __ ushl(v23, __ T2D, v5, v29);
+
+    // D = X1^A^B^C
+    __ eor(v21, __ T16B, v21, v22);
+    __ eor(v21, __ T16B, v21, v23);
+    __ eor(v21, __ T16B, v21, v24);
+    __ ins(v5, __ D, v21, 1, 0);
+
+    // [E1:E0] = [D:X0] >> 1
+    __ ushr(v20, __ T2D, v5, -1 & 63);
+    __ ushl(v18, __ T2D, v5, v27);
+    __ ext(v25, __ T16B, v18, vzr, 0x08);
+    __ orr(v19, __ T16B, v20, v25);
+
+    __ eor(v7, __ T16B, v5, v19);
+
+    // [F1:F0] = [D:X0] >> 2
+    __ ushr(v20, __ T2D, v5, -2 & 63);
+    __ ushl(v18, __ T2D, v5, v28);
+    __ ins(v25, __ D, v18, 0, 1);
+    __ orr(v19, __ T16B, v20, v25);
+
+    __ eor(v7, __ T16B, v7, v19);
+
+    // [G1:G0] = [D:X0] >> 7
+    __ ushr(v20, __ T2D, v5, -7 & 63);
+    __ ushl(v18, __ T2D, v5, v29);
+    __ ins(v25, __ D, v18, 0, 1);
+    __ orr(v19, __ T16B, v20, v25);
+
+    // [H1:H0] = [D^E1^F1^G1:X0^E0^F0^G0]
+    __ eor(v7, __ T16B, v7, v19);
+
+    // Result = [H1:H0]^[X3:X2]
+    __ eor(v0, __ T16B, v7, v6);
+
+    __ subs(blocks, blocks, 1);
+    __ cbnz(blocks, L_ghash_loop);
+
+    __ ext(v1, __ T16B, v0, v0, 0x08);
+    __ st1(v1, __ T16B, state);
+    __ ret(lr);
+
+    return start;
+  }
+
   // Continuation point for throwing of implicit exceptions that are
   // not handled in the current activation. Fabricates an exception
   // oop and initiates normal exception dispatching in this
@@ -2544,6 +2673,828 @@
     return stub->entry_point();
   }
 
+  class MontgomeryMultiplyGenerator : public MacroAssembler {
+
+    Register Pa_base, Pb_base, Pn_base, Pm_base, inv, Rlen, Ra, Rb, Rm, Rn,
+      Pa, Pb, Pn, Pm, Rhi_ab, Rlo_ab, Rhi_mn, Rlo_mn, t0, t1, t2, Ri, Rj;
+
+    RegSet _toSave;
+    bool _squaring;
+
+  public:
+    MontgomeryMultiplyGenerator (Assembler *as, bool squaring)
+      : MacroAssembler(as->code()), _squaring(squaring) {
+
+      // Register allocation
+
+      Register reg = c_rarg0;
+      Pa_base = reg;       // Argument registers
+      if (squaring)
+        Pb_base = Pa_base;
+      else
+        Pb_base = ++reg;
+      Pn_base = ++reg;
+      Rlen= ++reg;
+      inv = ++reg;
+      Pm_base = ++reg;
+
+                          // Working registers:
+      Ra =  ++reg;        // The current digit of a, b, n, and m.
+      Rb =  ++reg;
+      Rm =  ++reg;
+      Rn =  ++reg;
+
+      Pa =  ++reg;        // Pointers to the current/next digit of a, b, n, and m.
+      Pb =  ++reg;
+      Pm =  ++reg;
+      Pn =  ++reg;
+
+      t0 =  ++reg;        // Three registers which form a
+      t1 =  ++reg;        // triple-precision accumuator.
+      t2 =  ++reg;
+
+      Ri =  ++reg;        // Inner and outer loop indexes.
+      Rj =  ++reg;
+
+      Rhi_ab = ++reg;     // Product registers: low and high parts
+      Rlo_ab = ++reg;     // of a*b and m*n.
+      Rhi_mn = ++reg;
+      Rlo_mn = ++reg;
+
+      // r19 and up are callee-saved.
+      _toSave = RegSet::range(r19, reg) + Pm_base;
+    }
+
+  private:
+    void save_regs() {
+      push(_toSave, sp);
+    }
+
+    void restore_regs() {
+      pop(_toSave, sp);
+    }
+
+    template <typename T>
+    void unroll_2(Register count, T block) {
+      Label loop, end, odd;
+      tbnz(count, 0, odd);
+      cbz(count, end);
+      align(16);
+      bind(loop);
+      (this->*block)();
+      bind(odd);
+      (this->*block)();
+      subs(count, count, 2);
+      br(Assembler::GT, loop);
+      bind(end);
+    }
+
+    template <typename T>
+    void unroll_2(Register count, T block, Register d, Register s, Register tmp) {
+      Label loop, end, odd;
+      tbnz(count, 0, odd);
+      cbz(count, end);
+      align(16);
+      bind(loop);
+      (this->*block)(d, s, tmp);
+      bind(odd);
+      (this->*block)(d, s, tmp);
+      subs(count, count, 2);
+      br(Assembler::GT, loop);
+      bind(end);
+    }
+
+    void pre1(RegisterOrConstant i) {
+      block_comment("pre1");
+      // Pa = Pa_base;
+      // Pb = Pb_base + i;
+      // Pm = Pm_base;
+      // Pn = Pn_base + i;
+      // Ra = *Pa;
+      // Rb = *Pb;
+      // Rm = *Pm;
+      // Rn = *Pn;
+      ldr(Ra, Address(Pa_base));
+      ldr(Rb, Address(Pb_base, i, Address::uxtw(LogBytesPerWord)));
+      ldr(Rm, Address(Pm_base));
+      ldr(Rn, Address(Pn_base, i, Address::uxtw(LogBytesPerWord)));
+      lea(Pa, Address(Pa_base));
+      lea(Pb, Address(Pb_base, i, Address::uxtw(LogBytesPerWord)));
+      lea(Pm, Address(Pm_base));
+      lea(Pn, Address(Pn_base, i, Address::uxtw(LogBytesPerWord)));
+
+      // Zero the m*n result.
+      mov(Rhi_mn, zr);
+      mov(Rlo_mn, zr);
+    }
+
+    // The core multiply-accumulate step of a Montgomery
+    // multiplication.  The idea is to schedule operations as a
+    // pipeline so that instructions with long latencies (loads and
+    // multiplies) have time to complete before their results are
+    // used.  This most benefits in-order implementations of the
+    // architecture but out-of-order ones also benefit.
+    void step() {
+      block_comment("step");
+      // MACC(Ra, Rb, t0, t1, t2);
+      // Ra = *++Pa;
+      // Rb = *--Pb;
+      umulh(Rhi_ab, Ra, Rb);
+      mul(Rlo_ab, Ra, Rb);
+      ldr(Ra, pre(Pa, wordSize));
+      ldr(Rb, pre(Pb, -wordSize));
+      acc(Rhi_mn, Rlo_mn, t0, t1, t2); // The pending m*n from the
+                                       // previous iteration.
+      // MACC(Rm, Rn, t0, t1, t2);
+      // Rm = *++Pm;
+      // Rn = *--Pn;
+      umulh(Rhi_mn, Rm, Rn);
+      mul(Rlo_mn, Rm, Rn);
+      ldr(Rm, pre(Pm, wordSize));
+      ldr(Rn, pre(Pn, -wordSize));
+      acc(Rhi_ab, Rlo_ab, t0, t1, t2);
+    }
+
+    void post1() {
+      block_comment("post1");
+
+      // MACC(Ra, Rb, t0, t1, t2);
+      // Ra = *++Pa;
+      // Rb = *--Pb;
+      umulh(Rhi_ab, Ra, Rb);
+      mul(Rlo_ab, Ra, Rb);
+      acc(Rhi_mn, Rlo_mn, t0, t1, t2);  // The pending m*n
+      acc(Rhi_ab, Rlo_ab, t0, t1, t2);
+
+      // *Pm = Rm = t0 * inv;
+      mul(Rm, t0, inv);
+      str(Rm, Address(Pm));
+
+      // MACC(Rm, Rn, t0, t1, t2);
+      // t0 = t1; t1 = t2; t2 = 0;
+      umulh(Rhi_mn, Rm, Rn);
+
+#ifndef PRODUCT
+      // assert(m[i] * n[0] + t0 == 0, "broken Montgomery multiply");
+      {
+        mul(Rlo_mn, Rm, Rn);
+        add(Rlo_mn, t0, Rlo_mn);
+        Label ok;
+        cbz(Rlo_mn, ok); {
+          stop("broken Montgomery multiply");
+        } bind(ok);
+      }
+#endif
+      // We have very carefully set things up so that
+      // m[i]*n[0] + t0 == 0 (mod b), so we don't have to calculate
+      // the lower half of Rm * Rn because we know the result already:
+      // it must be -t0.  t0 + (-t0) must generate a carry iff
+      // t0 != 0.  So, rather than do a mul and an adds we just set
+      // the carry flag iff t0 is nonzero.
+      //
+      // mul(Rlo_mn, Rm, Rn);
+      // adds(zr, t0, Rlo_mn);
+      subs(zr, t0, 1); // Set carry iff t0 is nonzero
+      adcs(t0, t1, Rhi_mn);
+      adc(t1, t2, zr);
+      mov(t2, zr);
+    }
+
+    void pre2(RegisterOrConstant i, RegisterOrConstant len) {
+      block_comment("pre2");
+      // Pa = Pa_base + i-len;
+      // Pb = Pb_base + len;
+      // Pm = Pm_base + i-len;
+      // Pn = Pn_base + len;
+
+      if (i.is_register()) {
+        sub(Rj, i.as_register(), len);
+      } else {
+        mov(Rj, i.as_constant());
+        sub(Rj, Rj, len);
+      }
+      // Rj == i-len
+
+      lea(Pa, Address(Pa_base, Rj, Address::uxtw(LogBytesPerWord)));
+      lea(Pb, Address(Pb_base, len, Address::uxtw(LogBytesPerWord)));
+      lea(Pm, Address(Pm_base, Rj, Address::uxtw(LogBytesPerWord)));
+      lea(Pn, Address(Pn_base, len, Address::uxtw(LogBytesPerWord)));
+
+      // Ra = *++Pa;
+      // Rb = *--Pb;
+      // Rm = *++Pm;
+      // Rn = *--Pn;
+      ldr(Ra, pre(Pa, wordSize));
+      ldr(Rb, pre(Pb, -wordSize));
+      ldr(Rm, pre(Pm, wordSize));
+      ldr(Rn, pre(Pn, -wordSize));
+
+      mov(Rhi_mn, zr);
+      mov(Rlo_mn, zr);
+    }
+
+    void post2(RegisterOrConstant i, RegisterOrConstant len) {
+      block_comment("post2");
+      if (i.is_constant()) {
+        mov(Rj, i.as_constant()-len.as_constant());
+      } else {
+        sub(Rj, i.as_register(), len);
+      }
+
+      adds(t0, t0, Rlo_mn); // The pending m*n, low part
+
+      // As soon as we know the least significant digit of our result,
+      // store it.
+      // Pm_base[i-len] = t0;
+      str(t0, Address(Pm_base, Rj, Address::uxtw(LogBytesPerWord)));
+
+      // t0 = t1; t1 = t2; t2 = 0;
+      adcs(t0, t1, Rhi_mn); // The pending m*n, high part
+      adc(t1, t2, zr);
+      mov(t2, zr);
+    }
+
+    // A carry in t0 after Montgomery multiplication means that we
+    // should subtract multiples of n from our result in m.  We'll
+    // keep doing that until there is no carry.
+    void normalize(RegisterOrConstant len) {
+      block_comment("normalize");
+      // while (t0)
+      //   t0 = sub(Pm_base, Pn_base, t0, len);
+      Label loop, post, again;
+      Register cnt = t1, i = t2; // Re-use registers; we're done with them now
+      cbz(t0, post); {
+        bind(again); {
+          mov(i, zr);
+          mov(cnt, len);
+          ldr(Rm, Address(Pm_base, i, Address::uxtw(LogBytesPerWord)));
+          ldr(Rn, Address(Pn_base, i, Address::uxtw(LogBytesPerWord)));
+          subs(zr, zr, zr); // set carry flag, i.e. no borrow
+          align(16);
+          bind(loop); {
+            sbcs(Rm, Rm, Rn);
+            str(Rm, Address(Pm_base, i, Address::uxtw(LogBytesPerWord)));
+            add(i, i, 1);
+            ldr(Rm, Address(Pm_base, i, Address::uxtw(LogBytesPerWord)));
+            ldr(Rn, Address(Pn_base, i, Address::uxtw(LogBytesPerWord)));
+            sub(cnt, cnt, 1);
+          } cbnz(cnt, loop);
+          sbc(t0, t0, zr);
+        } cbnz(t0, again);
+      } bind(post);
+    }
+
+    // Move memory at s to d, reversing words.
+    //    Increments d to end of copied memory
+    //    Destroys tmp1, tmp2
+    //    Preserves len
+    //    Leaves s pointing to the address which was in d at start
+    void reverse(Register d, Register s, Register len, Register tmp1, Register tmp2) {
+      assert(tmp1 < r19 && tmp2 < r19, "register corruption");
+
+      lea(s, Address(s, len, Address::uxtw(LogBytesPerWord)));
+      mov(tmp1, len);
+      unroll_2(tmp1, &MontgomeryMultiplyGenerator::reverse1, d, s, tmp2);
+      sub(s, d, len, ext::uxtw, LogBytesPerWord);
+    }
+    // where
+    void reverse1(Register d, Register s, Register tmp) {
+      ldr(tmp, pre(s, -wordSize));
+      ror(tmp, tmp, 32);
+      str(tmp, post(d, wordSize));
+    }
+
+    void step_squaring() {
+      // An extra ACC
+      step();
+      acc(Rhi_ab, Rlo_ab, t0, t1, t2);
+    }
+
+    void last_squaring(RegisterOrConstant i) {
+      Label dont;
+      // if ((i & 1) == 0) {
+      tbnz(i.as_register(), 0, dont); {
+        // MACC(Ra, Rb, t0, t1, t2);
+        // Ra = *++Pa;
+        // Rb = *--Pb;
+        umulh(Rhi_ab, Ra, Rb);
+        mul(Rlo_ab, Ra, Rb);
+        acc(Rhi_ab, Rlo_ab, t0, t1, t2);
+      } bind(dont);
+    }
+
+    void extra_step_squaring() {
+      acc(Rhi_mn, Rlo_mn, t0, t1, t2);  // The pending m*n
+
+      // MACC(Rm, Rn, t0, t1, t2);
+      // Rm = *++Pm;
+      // Rn = *--Pn;
+      umulh(Rhi_mn, Rm, Rn);
+      mul(Rlo_mn, Rm, Rn);
+      ldr(Rm, pre(Pm, wordSize));
+      ldr(Rn, pre(Pn, -wordSize));
+    }
+
+    void post1_squaring() {
+      acc(Rhi_mn, Rlo_mn, t0, t1, t2);  // The pending m*n
+
+      // *Pm = Rm = t0 * inv;
+      mul(Rm, t0, inv);
+      str(Rm, Address(Pm));
+
+      // MACC(Rm, Rn, t0, t1, t2);
+      // t0 = t1; t1 = t2; t2 = 0;
+      umulh(Rhi_mn, Rm, Rn);
+
+#ifndef PRODUCT
+      // assert(m[i] * n[0] + t0 == 0, "broken Montgomery multiply");
+      {
+        mul(Rlo_mn, Rm, Rn);
+        add(Rlo_mn, t0, Rlo_mn);
+        Label ok;
+        cbz(Rlo_mn, ok); {
+          stop("broken Montgomery multiply");
+        } bind(ok);
+      }
+#endif
+      // We have very carefully set things up so that
+      // m[i]*n[0] + t0 == 0 (mod b), so we don't have to calculate
+      // the lower half of Rm * Rn because we know the result already:
+      // it must be -t0.  t0 + (-t0) must generate a carry iff
+      // t0 != 0.  So, rather than do a mul and an adds we just set
+      // the carry flag iff t0 is nonzero.
+      //
+      // mul(Rlo_mn, Rm, Rn);
+      // adds(zr, t0, Rlo_mn);
+      subs(zr, t0, 1); // Set carry iff t0 is nonzero
+      adcs(t0, t1, Rhi_mn);
+      adc(t1, t2, zr);
+      mov(t2, zr);
+    }
+
+    void acc(Register Rhi, Register Rlo,
+             Register t0, Register t1, Register t2) {
+      adds(t0, t0, Rlo);
+      adcs(t1, t1, Rhi);
+      adc(t2, t2, zr);
+    }
+
+  public:
+    /**
+     * Fast Montgomery multiplication.  The derivation of the
+     * algorithm is in A Cryptographic Library for the Motorola
+     * DSP56000, Dusse and Kaliski, Proc. EUROCRYPT 90, pp. 230-237.
+     *
+     * Arguments:
+     *
+     * Inputs for multiplication:
+     *   c_rarg0   - int array elements a
+     *   c_rarg1   - int array elements b
+     *   c_rarg2   - int array elements n (the modulus)
+     *   c_rarg3   - int length
+     *   c_rarg4   - int inv
+     *   c_rarg5   - int array elements m (the result)
+     *
+     * Inputs for squaring:
+     *   c_rarg0   - int array elements a
+     *   c_rarg1   - int array elements n (the modulus)
+     *   c_rarg2   - int length
+     *   c_rarg3   - int inv
+     *   c_rarg4   - int array elements m (the result)
+     *
+     */
+    address generate_multiply() {
+      Label argh, nothing;
+      bind(argh);
+      stop("MontgomeryMultiply total_allocation must be <= 8192");
+
+      align(CodeEntryAlignment);
+      address entry = pc();
+
+      cbzw(Rlen, nothing);
+
+      enter();
+
+      // Make room.
+      cmpw(Rlen, 512);
+      br(Assembler::HI, argh);
+      sub(Ra, sp, Rlen, ext::uxtw, exact_log2(4 * sizeof (jint)));
+      andr(sp, Ra, -2 * wordSize);
+
+      lsrw(Rlen, Rlen, 1);  // length in longwords = len/2
+
+      {
+        // Copy input args, reversing as we go.  We use Ra as a
+        // temporary variable.
+        reverse(Ra, Pa_base, Rlen, t0, t1);
+        if (!_squaring)
+          reverse(Ra, Pb_base, Rlen, t0, t1);
+        reverse(Ra, Pn_base, Rlen, t0, t1);
+      }
+
+      // Push all call-saved registers and also Pm_base which we'll need
+      // at the end.
+      save_regs();
+
+#ifndef PRODUCT
+      // assert(inv * n[0] == -1UL, "broken inverse in Montgomery multiply");
+      {
+        ldr(Rn, Address(Pn_base, 0));
+        mul(Rlo_mn, Rn, inv);
+        cmp(Rlo_mn, -1);
+        Label ok;
+        br(EQ, ok); {
+          stop("broken inverse in Montgomery multiply");
+        } bind(ok);
+      }
+#endif
+
+      mov(Pm_base, Ra);
+
+      mov(t0, zr);
+      mov(t1, zr);
+      mov(t2, zr);
+
+      block_comment("for (int i = 0; i < len; i++) {");
+      mov(Ri, zr); {
+        Label loop, end;
+        cmpw(Ri, Rlen);
+        br(Assembler::GE, end);
+
+        bind(loop);
+        pre1(Ri);
+
+        block_comment("  for (j = i; j; j--) {"); {
+          movw(Rj, Ri);
+          unroll_2(Rj, &MontgomeryMultiplyGenerator::step);
+        } block_comment("  } // j");
+
+        post1();
+        addw(Ri, Ri, 1);
+        cmpw(Ri, Rlen);
+        br(Assembler::LT, loop);
+        bind(end);
+        block_comment("} // i");
+      }
+
+      block_comment("for (int i = len; i < 2*len; i++) {");
+      mov(Ri, Rlen); {
+        Label loop, end;
+        cmpw(Ri, Rlen, Assembler::LSL, 1);
+        br(Assembler::GE, end);
+
+        bind(loop);
+        pre2(Ri, Rlen);
+
+        block_comment("  for (j = len*2-i-1; j; j--) {"); {
+          lslw(Rj, Rlen, 1);
+          subw(Rj, Rj, Ri);
+          subw(Rj, Rj, 1);
+          unroll_2(Rj, &MontgomeryMultiplyGenerator::step);
+        } block_comment("  } // j");
+
+        post2(Ri, Rlen);
+        addw(Ri, Ri, 1);
+        cmpw(Ri, Rlen, Assembler::LSL, 1);
+        br(Assembler::LT, loop);
+        bind(end);
+      }
+      block_comment("} // i");
+
+      normalize(Rlen);
+
+      mov(Ra, Pm_base);  // Save Pm_base in Ra
+      restore_regs();  // Restore caller's Pm_base
+
+      // Copy our result into caller's Pm_base
+      reverse(Pm_base, Ra, Rlen, t0, t1);
+
+      leave();
+      bind(nothing);
+      ret(lr);
+
+      return entry;
+    }
+    // In C, approximately:
+
+    // void
+    // montgomery_multiply(unsigned long Pa_base[], unsigned long Pb_base[],
+    //                     unsigned long Pn_base[], unsigned long Pm_base[],
+    //                     unsigned long inv, int len) {
+    //   unsigned long t0 = 0, t1 = 0, t2 = 0; // Triple-precision accumulator
+    //   unsigned long *Pa, *Pb, *Pn, *Pm;
+    //   unsigned long Ra, Rb, Rn, Rm;
+
+    //   int i;
+
+    //   assert(inv * Pn_base[0] == -1UL, "broken inverse in Montgomery multiply");
+
+    //   for (i = 0; i < len; i++) {
+    //     int j;
+
+    //     Pa = Pa_base;
+    //     Pb = Pb_base + i;
+    //     Pm = Pm_base;
+    //     Pn = Pn_base + i;
+
+    //     Ra = *Pa;
+    //     Rb = *Pb;
+    //     Rm = *Pm;
+    //     Rn = *Pn;
+
+    //     int iters = i;
+    //     for (j = 0; iters--; j++) {
+    //       assert(Ra == Pa_base[j] && Rb == Pb_base[i-j], "must be");
+    //       MACC(Ra, Rb, t0, t1, t2);
+    //       Ra = *++Pa;
+    //       Rb = *--Pb;
+    //       assert(Rm == Pm_base[j] && Rn == Pn_base[i-j], "must be");
+    //       MACC(Rm, Rn, t0, t1, t2);
+    //       Rm = *++Pm;
+    //       Rn = *--Pn;
+    //     }
+
+    //     assert(Ra == Pa_base[i] && Rb == Pb_base[0], "must be");
+    //     MACC(Ra, Rb, t0, t1, t2);
+    //     *Pm = Rm = t0 * inv;
+    //     assert(Rm == Pm_base[i] && Rn == Pn_base[0], "must be");
+    //     MACC(Rm, Rn, t0, t1, t2);
+
+    //     assert(t0 == 0, "broken Montgomery multiply");
+
+    //     t0 = t1; t1 = t2; t2 = 0;
+    //   }
+
+    //   for (i = len; i < 2*len; i++) {
+    //     int j;
+
+    //     Pa = Pa_base + i-len;
+    //     Pb = Pb_base + len;
+    //     Pm = Pm_base + i-len;
+    //     Pn = Pn_base + len;
+
+    //     Ra = *++Pa;
+    //     Rb = *--Pb;
+    //     Rm = *++Pm;
+    //     Rn = *--Pn;
+
+    //     int iters = len*2-i-1;
+    //     for (j = i-len+1; iters--; j++) {
+    //       assert(Ra == Pa_base[j] && Rb == Pb_base[i-j], "must be");
+    //       MACC(Ra, Rb, t0, t1, t2);
+    //       Ra = *++Pa;
+    //       Rb = *--Pb;
+    //       assert(Rm == Pm_base[j] && Rn == Pn_base[i-j], "must be");
+    //       MACC(Rm, Rn, t0, t1, t2);
+    //       Rm = *++Pm;
+    //       Rn = *--Pn;
+    //     }
+
+    //     Pm_base[i-len] = t0;
+    //     t0 = t1; t1 = t2; t2 = 0;
+    //   }
+
+    //   while (t0)
+    //     t0 = sub(Pm_base, Pn_base, t0, len);
+    // }
+
+    /**
+     * Fast Montgomery squaring.  This uses asymptotically 25% fewer
+     * multiplies than Montgomery multiplication so it should be up to
+     * 25% faster.  However, its loop control is more complex and it
+     * may actually run slower on some machines.
+     *
+     * Arguments:
+     *
+     * Inputs:
+     *   c_rarg0   - int array elements a
+     *   c_rarg1   - int array elements n (the modulus)
+     *   c_rarg2   - int length
+     *   c_rarg3   - int inv
+     *   c_rarg4   - int array elements m (the result)
+     *
+     */
+    address generate_square() {
+      Label argh;
+      bind(argh);
+      stop("MontgomeryMultiply total_allocation must be <= 8192");
+
+      align(CodeEntryAlignment);
+      address entry = pc();
+
+      enter();
+
+      // Make room.
+      cmpw(Rlen, 512);
+      br(Assembler::HI, argh);
+      sub(Ra, sp, Rlen, ext::uxtw, exact_log2(4 * sizeof (jint)));
+      andr(sp, Ra, -2 * wordSize);
+
+      lsrw(Rlen, Rlen, 1);  // length in longwords = len/2
+
+      {
+        // Copy input args, reversing as we go.  We use Ra as a
+        // temporary variable.
+        reverse(Ra, Pa_base, Rlen, t0, t1);
+        reverse(Ra, Pn_base, Rlen, t0, t1);
+      }
+
+      // Push all call-saved registers and also Pm_base which we'll need
+      // at the end.
+      save_regs();
+
+      mov(Pm_base, Ra);
+
+      mov(t0, zr);
+      mov(t1, zr);
+      mov(t2, zr);
+
+      block_comment("for (int i = 0; i < len; i++) {");
+      mov(Ri, zr); {
+        Label loop, end;
+        bind(loop);
+        cmp(Ri, Rlen);
+        br(Assembler::GE, end);
+
+        pre1(Ri);
+
+        block_comment("for (j = (i+1)/2; j; j--) {"); {
+          add(Rj, Ri, 1);
+          lsr(Rj, Rj, 1);
+          unroll_2(Rj, &MontgomeryMultiplyGenerator::step_squaring);
+        } block_comment("  } // j");
+
+        last_squaring(Ri);
+
+        block_comment("  for (j = i/2; j; j--) {"); {
+          lsr(Rj, Ri, 1);
+          unroll_2(Rj, &MontgomeryMultiplyGenerator::extra_step_squaring);
+        } block_comment("  } // j");
+
+        post1_squaring();
+        add(Ri, Ri, 1);
+        cmp(Ri, Rlen);
+        br(Assembler::LT, loop);
+
+        bind(end);
+        block_comment("} // i");
+      }
+
+      block_comment("for (int i = len; i < 2*len; i++) {");
+      mov(Ri, Rlen); {
+        Label loop, end;
+        bind(loop);
+        cmp(Ri, Rlen, Assembler::LSL, 1);
+        br(Assembler::GE, end);
+
+        pre2(Ri, Rlen);
+
+        block_comment("  for (j = (2*len-i-1)/2; j; j--) {"); {
+          lsl(Rj, Rlen, 1);
+          sub(Rj, Rj, Ri);
+          sub(Rj, Rj, 1);
+          lsr(Rj, Rj, 1);
+          unroll_2(Rj, &MontgomeryMultiplyGenerator::step_squaring);
+        } block_comment("  } // j");
+
+        last_squaring(Ri);
+
+        block_comment("  for (j = (2*len-i)/2; j; j--) {"); {
+          lsl(Rj, Rlen, 1);
+          sub(Rj, Rj, Ri);
+          lsr(Rj, Rj, 1);
+          unroll_2(Rj, &MontgomeryMultiplyGenerator::extra_step_squaring);
+        } block_comment("  } // j");
+
+        post2(Ri, Rlen);
+        add(Ri, Ri, 1);
+        cmp(Ri, Rlen, Assembler::LSL, 1);
+
+        br(Assembler::LT, loop);
+        bind(end);
+        block_comment("} // i");
+      }
+
+      normalize(Rlen);
+
+      mov(Ra, Pm_base);  // Save Pm_base in Ra
+      restore_regs();  // Restore caller's Pm_base
+
+      // Copy our result into caller's Pm_base
+      reverse(Pm_base, Ra, Rlen, t0, t1);
+
+      leave();
+      ret(lr);
+
+      return entry;
+    }
+    // In C, approximately:
+
+    // void
+    // montgomery_square(unsigned long Pa_base[], unsigned long Pn_base[],
+    //                   unsigned long Pm_base[], unsigned long inv, int len) {
+    //   unsigned long t0 = 0, t1 = 0, t2 = 0; // Triple-precision accumulator
+    //   unsigned long *Pa, *Pb, *Pn, *Pm;
+    //   unsigned long Ra, Rb, Rn, Rm;
+
+    //   int i;
+
+    //   assert(inv * Pn_base[0] == -1UL, "broken inverse in Montgomery multiply");
+
+    //   for (i = 0; i < len; i++) {
+    //     int j;
+
+    //     Pa = Pa_base;
+    //     Pb = Pa_base + i;
+    //     Pm = Pm_base;
+    //     Pn = Pn_base + i;
+
+    //     Ra = *Pa;
+    //     Rb = *Pb;
+    //     Rm = *Pm;
+    //     Rn = *Pn;
+
+    //     int iters = (i+1)/2;
+    //     for (j = 0; iters--; j++) {
+    //       assert(Ra == Pa_base[j] && Rb == Pa_base[i-j], "must be");
+    //       MACC2(Ra, Rb, t0, t1, t2);
+    //       Ra = *++Pa;
+    //       Rb = *--Pb;
+    //       assert(Rm == Pm_base[j] && Rn == Pn_base[i-j], "must be");
+    //       MACC(Rm, Rn, t0, t1, t2);
+    //       Rm = *++Pm;
+    //       Rn = *--Pn;
+    //     }
+    //     if ((i & 1) == 0) {
+    //       assert(Ra == Pa_base[j], "must be");
+    //       MACC(Ra, Ra, t0, t1, t2);
+    //     }
+    //     iters = i/2;
+    //     assert(iters == i-j, "must be");
+    //     for (; iters--; j++) {
+    //       assert(Rm == Pm_base[j] && Rn == Pn_base[i-j], "must be");
+    //       MACC(Rm, Rn, t0, t1, t2);
+    //       Rm = *++Pm;
+    //       Rn = *--Pn;
+    //     }
+
+    //     *Pm = Rm = t0 * inv;
+    //     assert(Rm == Pm_base[i] && Rn == Pn_base[0], "must be");
+    //     MACC(Rm, Rn, t0, t1, t2);
+
+    //     assert(t0 == 0, "broken Montgomery multiply");
+
+    //     t0 = t1; t1 = t2; t2 = 0;
+    //   }
+
+    //   for (i = len; i < 2*len; i++) {
+    //     int start = i-len+1;
+    //     int end = start + (len - start)/2;
+    //     int j;
+
+    //     Pa = Pa_base + i-len;
+    //     Pb = Pa_base + len;
+    //     Pm = Pm_base + i-len;
+    //     Pn = Pn_base + len;
+
+    //     Ra = *++Pa;
+    //     Rb = *--Pb;
+    //     Rm = *++Pm;
+    //     Rn = *--Pn;
+
+    //     int iters = (2*len-i-1)/2;
+    //     assert(iters == end-start, "must be");
+    //     for (j = start; iters--; j++) {
+    //       assert(Ra == Pa_base[j] && Rb == Pa_base[i-j], "must be");
+    //       MACC2(Ra, Rb, t0, t1, t2);
+    //       Ra = *++Pa;
+    //       Rb = *--Pb;
+    //       assert(Rm == Pm_base[j] && Rn == Pn_base[i-j], "must be");
+    //       MACC(Rm, Rn, t0, t1, t2);
+    //       Rm = *++Pm;
+    //       Rn = *--Pn;
+    //     }
+    //     if ((i & 1) == 0) {
+    //       assert(Ra == Pa_base[j], "must be");
+    //       MACC(Ra, Ra, t0, t1, t2);
+    //     }
+    //     iters =  (2*len-i)/2;
+    //     assert(iters == len-j, "must be");
+    //     for (; iters--; j++) {
+    //       assert(Rm == Pm_base[j] && Rn == Pn_base[i-j], "must be");
+    //       MACC(Rm, Rn, t0, t1, t2);
+    //       Rm = *++Pm;
+    //       Rn = *--Pn;
+    //     }
+    //     Pm_base[i-len] = t0;
+    //     t0 = t1; t1 = t2; t2 = 0;
+    //   }
+
+    //   while (t0)
+    //     t0 = sub(Pm_base, Pn_base, t0, len);
+    // }
+  };
+
   // Initialization
   void generate_initial() {
     // Generate initial stubs and initializes the entry points
@@ -2603,7 +3554,26 @@
       StubRoutines::_multiplyToLen = generate_multiplyToLen();
     }
 
+    if (UseMontgomeryMultiplyIntrinsic) {
+      StubCodeMark mark(this, "StubRoutines", "montgomeryMultiply");
+      MontgomeryMultiplyGenerator g(_masm, /*squaring*/false);
+      StubRoutines::_montgomeryMultiply = g.generate_multiply();
+    }
+
+    if (UseMontgomerySquareIntrinsic) {
+      StubCodeMark mark(this, "StubRoutines", "montgomerySquare");
+      MontgomeryMultiplyGenerator g(_masm, /*squaring*/true);
+      // We use generate_multiply() rather than generate_square()
+      // because it's faster for the sizes of modulus we care about.
+      StubRoutines::_montgomerySquare = g.generate_multiply();
+    }
+
 #ifndef BUILTIN_SIM
+    // generate GHASH intrinsics code
+    if (UseGHASHIntrinsics) {
+      StubRoutines::_ghash_processBlocks = generate_ghash_processBlocks();
+    }
+
     if (UseAESIntrinsics) {
       StubRoutines::_aescrypt_encryptBlock = generate_aescrypt_encryptBlock();
       StubRoutines::_aescrypt_decryptBlock = generate_aescrypt_decryptBlock();
--- a/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp	Fri Jul 31 10:15:02 2015 -0700
@@ -45,6 +45,10 @@
 #define HWCAP_AES   (1<<3)
 #endif
 
+#ifndef HWCAP_PMULL
+#define HWCAP_PMULL (1<<4)
+#endif
+
 #ifndef HWCAP_SHA1
 #define HWCAP_SHA1  (1<<5)
 #endif
@@ -190,11 +194,6 @@
     }
   }
 
-  if (UseGHASHIntrinsics) {
-    warning("GHASH intrinsics are not available on this CPU");
-    FLAG_SET_DEFAULT(UseGHASHIntrinsics, false);
-  }
-
   if (FLAG_IS_DEFAULT(UseCRC32Intrinsics)) {
     UseCRC32Intrinsics = true;
   }
@@ -232,7 +231,7 @@
     }
   } else if (UseSHA256Intrinsics) {
     warning("Intrinsics for SHA-224 and SHA-256 crypto hash functions not available on this CPU.");
-    FLAG_SET_DEFAULT(UseSHA1Intrinsics, false);
+    FLAG_SET_DEFAULT(UseSHA256Intrinsics, false);
   }
 
   if (UseSHA512Intrinsics) {
@@ -244,6 +243,15 @@
     FLAG_SET_DEFAULT(UseSHA, false);
   }
 
+  if (auxv & HWCAP_PMULL) {
+    if (FLAG_IS_DEFAULT(UseGHASHIntrinsics)) {
+      FLAG_SET_DEFAULT(UseGHASHIntrinsics, true);
+    }
+  } else if (UseGHASHIntrinsics) {
+    warning("GHASH intrinsics are not available on this CPU");
+    FLAG_SET_DEFAULT(UseGHASHIntrinsics, false);
+  }
+
   // This machine allows unaligned memory accesses
   if (FLAG_IS_DEFAULT(UseUnalignedAccesses)) {
     FLAG_SET_DEFAULT(UseUnalignedAccesses, true);
@@ -261,6 +269,13 @@
     UsePopCountInstruction = true;
   }
 
+  if (FLAG_IS_DEFAULT(UseMontgomeryMultiplyIntrinsic)) {
+    UseMontgomeryMultiplyIntrinsic = true;
+  }
+  if (FLAG_IS_DEFAULT(UseMontgomerySquareIntrinsic)) {
+    UseMontgomerySquareIntrinsic = true;
+  }
+
 #ifdef COMPILER2
   if (FLAG_IS_DEFAULT(OptoScheduling)) {
     OptoScheduling = true;
--- a/hotspot/src/os/aix/vm/os_aix.cpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/os/aix/vm/os_aix.cpp	Fri Jul 31 10:15:02 2015 -0700
@@ -1550,6 +1550,13 @@
   LoadedLibraries::print(st);
 }
 
+void os::get_summary_os_info(char* buf, size_t buflen) {
+  // There might be something more readable than uname results for AIX.
+  struct utsname name;
+  uname(&name);
+  snprintf(buf, buflen, "%s %s", name.release, name.version);
+}
+
 void os::print_os_info(outputStream* st) {
   st->print("OS:");
 
@@ -1654,6 +1661,17 @@
   }
 }
 
+// Get a string for the cpuinfo that is a summary of the cpu type
+void os::get_summary_cpu_info(char* buf, size_t buflen) {
+  // This looks good
+  os::Aix::cpuinfo_t ci;
+  if (os::Aix::get_cpuinfo(&ci)) {
+    strncpy(buf, ci.version, buflen);
+  } else {
+    strncpy(buf, "AIX", buflen);
+  }
+}
+
 void os::pd_print_cpu_info(outputStream* st, char* buf, size_t buflen) {
 }
 
--- a/hotspot/src/os/bsd/vm/os_bsd.cpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/os/bsd/vm/os_bsd.cpp	Fri Jul 31 10:15:02 2015 -0700
@@ -1600,24 +1600,6 @@
   return dlsym(handle, name);
 }
 
-
-static bool _print_ascii_file(const char* filename, outputStream* st) {
-  int fd = ::open(filename, O_RDONLY);
-  if (fd == -1) {
-    return false;
-  }
-
-  char buf[32];
-  int bytes;
-  while ((bytes = ::read(fd, buf, sizeof(buf))) > 0) {
-    st->print_raw(buf, bytes);
-  }
-
-  ::close(fd);
-
-  return true;
-}
-
 int _print_dll_info_cb(const char * name, address base_address, address top_address, void * param) {
   outputStream * out = (outputStream *) param;
   out->print_cr(PTR_FORMAT " \t%s", base_address, name);
@@ -1678,15 +1660,38 @@
 #endif
 }
 
+void os::get_summary_os_info(char* buf, size_t buflen) {
+  // These buffers are small because we want this to be brief
+  // and not use a lot of stack while generating the hs_err file.
+  char os[100];
+  size_t size = sizeof(os);
+  int mib_kern[] = { CTL_KERN, KERN_OSTYPE };
+  if (sysctl(mib_kern, 2, os, &size, NULL, 0) < 0) {
+#ifdef __APPLE__
+      strncpy(os, "Darwin", sizeof(os));
+#elif __OpenBSD__
+      strncpy(os, "OpenBSD", sizeof(os));
+#else
+      strncpy(os, "BSD", sizeof(os));
+#endif
+  }
+
+  char release[100];
+  size = sizeof(release);
+  int mib_release[] = { CTL_KERN, KERN_OSRELEASE };
+  if (sysctl(mib_release, 2, release, &size, NULL, 0) < 0) {
+      // if error, leave blank
+      strncpy(release, "", sizeof(release));
+  }
+  snprintf(buf, buflen, "%s %s", os, release);
+}
+
 void os::print_os_info_brief(outputStream* st) {
-  st->print("Bsd");
-
   os::Posix::print_uname_info(st);
 }
 
 void os::print_os_info(outputStream* st) {
   st->print("OS:");
-  st->print("Bsd");
 
   os::Posix::print_uname_info(st);
 
@@ -1699,6 +1704,33 @@
   // Nothing to do for now.
 }
 
+void os::get_summary_cpu_info(char* buf, size_t buflen) {
+  unsigned int mhz;
+  size_t size = sizeof(mhz);
+  int mib[] = { CTL_HW, HW_CPU_FREQ };
+  if (sysctl(mib, 2, &mhz, &size, NULL, 0) < 0) {
+    mhz = 1;  // looks like an error but can be divided by
+  } else {
+    mhz /= 1000000;  // reported in millions
+  }
+
+  char model[100];
+  size = sizeof(model);
+  int mib_model[] = { CTL_HW, HW_MODEL };
+  if (sysctl(mib_model, 2, model, &size, NULL, 0) < 0) {
+    strncpy(model, cpu_arch, sizeof(model));
+  }
+
+  char machine[100];
+  size = sizeof(machine);
+  int mib_machine[] = { CTL_HW, HW_MACHINE };
+  if (sysctl(mib_machine, 2, machine, &size, NULL, 0) < 0) {
+      strncpy(machine, "", sizeof(machine));
+  }
+
+  snprintf(buf, buflen, "%s %s %d MHz", model, machine, mhz);
+}
+
 void os::print_memory_info(outputStream* st) {
 
   st->print("Memory:");
@@ -1709,11 +1741,6 @@
   st->print("(" UINT64_FORMAT "k free)",
             os::available_memory() >> 10);
   st->cr();
-
-  // meminfo
-  st->print("\n/proc/meminfo:\n");
-  _print_ascii_file("/proc/meminfo", st);
-  st->cr();
 }
 
 void os::print_siginfo(outputStream* st, void* siginfo) {
--- a/hotspot/src/os/linux/vm/os_linux.cpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/os/linux/vm/os_linux.cpp	Fri Jul 31 10:15:02 2015 -0700
@@ -2043,31 +2043,96 @@
 // Searching for the debian_version file is the last resort.  It contains
 // an informative string like "6.0.6" or "wheezy/sid". Because of this
 // "Debian " is printed before the contents of the debian_version file.
+
+const char* distro_files[] = {
+  "/etc/oracle-release",
+  "/etc/mandriva-release",
+  "/etc/mandrake-release",
+  "/etc/sun-release",
+  "/etc/redhat-release",
+  "/etc/lsb-release",
+  "/etc/SuSE-release",
+  "/etc/turbolinux-release",
+  "/etc/gentoo-release",
+  "/etc/ltib-release",
+  "/etc/angstrom-version",
+  "/etc/system-release",
+  "/etc/os-release",
+  NULL };
+
 void os::Linux::print_distro_info(outputStream* st) {
-  if (!_print_ascii_file("/etc/oracle-release", st) &&
-      !_print_ascii_file("/etc/mandriva-release", st) &&
-      !_print_ascii_file("/etc/mandrake-release", st) &&
-      !_print_ascii_file("/etc/sun-release", st) &&
-      !_print_ascii_file("/etc/redhat-release", st) &&
-      !_print_ascii_file("/etc/lsb-release", st) &&
-      !_print_ascii_file("/etc/SuSE-release", st) &&
-      !_print_ascii_file("/etc/turbolinux-release", st) &&
-      !_print_ascii_file("/etc/gentoo-release", st) &&
-      !_print_ascii_file("/etc/ltib-release", st) &&
-      !_print_ascii_file("/etc/angstrom-version", st) &&
-      !_print_ascii_file("/etc/system-release", st) &&
-      !_print_ascii_file("/etc/os-release", st)) {
-
-    if (file_exists("/etc/debian_version")) {
-      st->print("Debian ");
-      _print_ascii_file("/etc/debian_version", st);
-    } else {
-      st->print("Linux");
+  for (int i = 0;; i++) {
+    const char* file = distro_files[i];
+    if (file == NULL) {
+      break;  // done
     }
+    // If file prints, we found it.
+    if (_print_ascii_file(file, st)) {
+      return;
+    }
+  }
+
+  if (file_exists("/etc/debian_version")) {
+    st->print("Debian ");
+    _print_ascii_file("/etc/debian_version", st);
+  } else {
+    st->print("Linux");
   }
   st->cr();
 }
 
+static void parse_os_info(char* distro, size_t length, const char* file) {
+  FILE* fp = fopen(file, "r");
+  if (fp != NULL) {
+    char buf[256];
+    // get last line of the file.
+    while (fgets(buf, sizeof(buf), fp)) { }
+    // Edit out extra stuff in expected ubuntu format
+    if (strstr(buf, "DISTRIB_DESCRIPTION=") != NULL) {
+      char* ptr = strstr(buf, "\"");  // the name is in quotes
+      if (ptr != NULL) {
+        ptr++; // go beyond first quote
+        char* nl = strchr(ptr, '\"');
+        if (nl != NULL) *nl = '\0';
+        strncpy(distro, ptr, length);
+      } else {
+        ptr = strstr(buf, "=");
+        ptr++; // go beyond equals then
+        char* nl = strchr(ptr, '\n');
+        if (nl != NULL) *nl = '\0';
+        strncpy(distro, ptr, length);
+      }
+    } else {
+      // if not in expected Ubuntu format, print out whole line minus \n
+      char* nl = strchr(buf, '\n');
+      if (nl != NULL) *nl = '\0';
+      strncpy(distro, buf, length);
+    }
+    // close distro file
+    fclose(fp);
+  }
+}
+
+void os::get_summary_os_info(char* buf, size_t buflen) {
+  for (int i = 0;; i++) {
+    const char* file = distro_files[i];
+    if (file == NULL) {
+      break; // ran out of distro_files
+    }
+    if (file_exists(file)) {
+      parse_os_info(buf, buflen, file);
+      return;
+    }
+  }
+  // special case for debian
+  if (file_exists("/etc/debian_version")) {
+    strncpy(buf, "Debian ", buflen);
+    parse_os_info(&buf[7], buflen-7, "/etc/debian_version");
+  } else {
+    strncpy(buf, "Linux", buflen);
+  }
+}
+
 void os::Linux::print_libversion_info(outputStream* st) {
   // libc, pthread
   st->print("libc:");
@@ -2150,6 +2215,48 @@
   }
 }
 
+const char* search_string = IA32_ONLY("model name") AMD64_ONLY("model name")
+                            IA64_ONLY("") SPARC_ONLY("cpu")
+                            ARM32_ONLY("Processor") PPC_ONLY("Processor") AARCH64_ONLY("Processor");
+
+// Parses the cpuinfo file for string representing the model name.
+void os::get_summary_cpu_info(char* cpuinfo, size_t length) {
+  FILE* fp = fopen("/proc/cpuinfo", "r");
+  if (fp != NULL) {
+    while (!feof(fp)) {
+      char buf[256];
+      if (fgets(buf, sizeof(buf), fp)) {
+        char* start = strstr(buf, search_string);
+        if (start != NULL) {
+          char *ptr = start + strlen(search_string);
+          char *end = buf + strlen(buf);
+          while (ptr != end) {
+             // skip whitespace and colon for the rest of the name.
+             if (*ptr != ' ' && *ptr != '\t' && *ptr != ':') {
+               break;
+             }
+             ptr++;
+          }
+          if (ptr != end) {
+            // reasonable string, get rid of newline and keep the rest
+            char* nl = strchr(buf, '\n');
+            if (nl != NULL) *nl = '\0';
+            strncpy(cpuinfo, ptr, length);
+            fclose(fp);
+            return;
+          }
+        }
+      }
+    }
+    fclose(fp);
+  }
+  // cpuinfo not found or parsing failed, just print generic string.  The entire
+  // /proc/cpuinfo file will be printed later in the file (or enough of it for x86)
+  strncpy(cpuinfo, IA32_ONLY("x86_32") AMD64_ONLY("x86_32")
+                   IA64_ONLY("IA64") SPARC_ONLY("sparcv9")
+                   ARM32_ONLY("ARM") PPC_ONLY("PPC64") AARCH64_ONLY("AArch64"), length);
+}
+
 void os::print_siginfo(outputStream* st, void* siginfo) {
   const siginfo_t* si = (const siginfo_t*)siginfo;
 
--- a/hotspot/src/os/posix/vm/os_posix.cpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/os/posix/vm/os_posix.cpp	Fri Jul 31 10:15:02 2015 -0700
@@ -236,6 +236,15 @@
   st->cr();
 }
 
+#ifndef PRODUCT
+bool os::get_host_name(char* buf, size_t buflen) {
+  struct utsname name;
+  uname(&name);
+  jio_snprintf(buf, buflen, "%s", name.nodename);
+  return true;
+}
+#endif // PRODUCT
+
 bool os::has_allocatable_memory_limit(julong* limit) {
   struct rlimit rlim;
   int getrlimit_res = getrlimit(RLIMIT_AS, &rlim);
@@ -1070,7 +1079,7 @@
   return ret == 0;
 }
 
-bool PosixSemaphore::timedwait(const struct timespec ts) {
+bool PosixSemaphore::timedwait(struct timespec ts) {
   while (true) {
     int result = sem_timedwait(&_semaphore, &ts);
     if (result == 0) {
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp	Fri Jul 31 10:15:02 2015 -0700
@@ -1971,6 +1971,26 @@
   st->cr();
 }
 
+void os::get_summary_os_info(char* buf, size_t buflen) {
+  strncpy(buf, "Solaris", buflen);  // default to plain solaris
+  FILE* fp = fopen("/etc/release", "r");
+  if (fp != NULL) {
+    char tmp[256];
+    // Only get the first line and chop out everything but the os name.
+    if (fgets(tmp, sizeof(tmp), fp)) {
+      char* ptr = tmp;
+      // skip past whitespace characters
+      while (*ptr != '\0' && (*ptr == ' ' || *ptr == '\t' || *ptr == '\n')) ptr++;
+      if (*ptr != '\0') {
+        char* nl = strchr(ptr, '\n');
+        if (nl != NULL) *nl = '\0';
+        strncpy(buf, ptr, buflen);
+      }
+    }
+    fclose(fp);
+  }
+}
+
 void os::Solaris::print_libversion_info(outputStream* st) {
   st->print("  (T2 libthread)");
   st->cr();
@@ -1998,6 +2018,22 @@
   return status;
 }
 
+void os::get_summary_cpu_info(char* buf, size_t buflen) {
+  // Get MHz with system call. We don't seem to already have this.
+  processor_info_t stats;
+  processorid_t id = getcpuid();
+  int clock = 0;
+  if (processor_info(id, &stats) != -1) {
+    clock = stats.pi_clock;  // pi_processor_type isn't more informative than below
+  }
+#ifdef AMD64
+  snprintf(buf, buflen, "x86 64 bit %d MHz", clock);
+#else
+  // must be sparc
+  snprintf(buf, buflen, "Sparcv9 64 bit %d MHz", clock);
+#endif
+}
+
 void os::pd_print_cpu_info(outputStream* st, char* buf, size_t buflen) {
   // Nothing to do for now.
 }
--- a/hotspot/src/os/windows/vm/os_windows.cpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/os/windows/vm/os_windows.cpp	Fri Jul 31 10:15:02 2015 -0700
@@ -1593,6 +1593,21 @@
   return result;
 }
 
+#ifndef PRODUCT
+bool os::get_host_name(char* buf, size_t buflen) {
+  DWORD size = (DWORD)buflen;
+  return (GetComputerNameEx(ComputerNameDnsHostname, buf, &size) == TRUE);
+}
+#endif // PRODUCT
+
+void os::get_summary_os_info(char* buf, size_t buflen) {
+  stringStream sst(buf, buflen);
+  os::win32::print_windows_version(&sst);
+  // chop off newline character
+  char* nl = strchr(buf, '\n');
+  if (nl != NULL) *nl = '\0';
+}
+
 void os::print_os_info_brief(outputStream* st) {
   os::print_os_info(st);
 }
@@ -1600,15 +1615,14 @@
 void os::print_os_info(outputStream* st) {
 #ifdef ASSERT
   char buffer[1024];
-  DWORD size = sizeof(buffer);
-  st->print(" HostName: ");
-  if (GetComputerNameEx(ComputerNameDnsHostname, buffer, &size)) {
-    st->print("%s", buffer);
+  st->print("HostName: ");
+  if (get_host_name(buffer, sizeof(buffer))) {
+    st->print("%s ", buffer);
   } else {
-    st->print("N/A");
+    st->print("N/A ");
   }
 #endif
-  st->print(" OS:");
+  st->print("OS:");
   os::win32::print_windows_version(st);
 }
 
@@ -1738,6 +1752,23 @@
   // Nothing to do for now.
 }
 
+void os::get_summary_cpu_info(char* buf, size_t buflen) {
+  HKEY key;
+  DWORD status = RegOpenKey(HKEY_LOCAL_MACHINE,
+               "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", &key);
+  if (status == ERROR_SUCCESS) {
+    DWORD size = (DWORD)buflen;
+    status = RegQueryValueEx(key, "ProcessorNameString", NULL, NULL, (byte*)buf, &size);
+    if (status != ERROR_SUCCESS) {
+        strncpy(buf, "## __CPU__", buflen);
+    }
+    RegCloseKey(key);
+  } else {
+    // Put generic cpu info to return
+    strncpy(buf, "## __CPU__", buflen);
+  }
+}
+
 void os::print_memory_info(outputStream* st) {
   st->print("Memory:");
   st->print(" %dk page", os::vm_page_size()>>10);
--- a/hotspot/src/share/vm/c1/c1_Compiler.cpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/c1/c1_Compiler.cpp	Fri Jul 31 10:15:02 2015 -0700
@@ -99,6 +99,164 @@
   return buffer_blob;
 }
 
+bool Compiler::is_intrinsic_supported(methodHandle method) {
+  vmIntrinsics::ID id = method->intrinsic_id();
+  assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
+
+  if (method->is_synchronized()) {
+    // C1 does not support intrinsification of synchronized methods.
+    return false;
+  }
+
+  switch (id) {
+  case vmIntrinsics::_compareAndSwapLong:
+    if (!VM_Version::supports_cx8()) return false;
+    break;
+  case vmIntrinsics::_getAndAddInt:
+    if (!VM_Version::supports_atomic_getadd4()) return false;
+    break;
+  case vmIntrinsics::_getAndAddLong:
+    if (!VM_Version::supports_atomic_getadd8()) return false;
+    break;
+  case vmIntrinsics::_getAndSetInt:
+    if (!VM_Version::supports_atomic_getset4()) return false;
+    break;
+  case vmIntrinsics::_getAndSetLong:
+    if (!VM_Version::supports_atomic_getset8()) return false;
+    break;
+  case vmIntrinsics::_getAndSetObject:
+#ifdef _LP64
+    if (!UseCompressedOops && !VM_Version::supports_atomic_getset8()) return false;
+    if (UseCompressedOops && !VM_Version::supports_atomic_getset4()) return false;
+#else
+    if (!VM_Version::supports_atomic_getset4()) return false;
+#endif
+    break;
+  case vmIntrinsics::_arraycopy:
+  case vmIntrinsics::_currentTimeMillis:
+  case vmIntrinsics::_nanoTime:
+  case vmIntrinsics::_Reference_get:
+    // Use the intrinsic version of Reference.get() so that the value in
+    // the referent field can be registered by the G1 pre-barrier code.
+    // Also to prevent commoning reads from this field across safepoint
+    // since GC can change its value.
+  case vmIntrinsics::_loadFence:
+  case vmIntrinsics::_storeFence:
+  case vmIntrinsics::_fullFence:
+  case vmIntrinsics::_floatToRawIntBits:
+  case vmIntrinsics::_intBitsToFloat:
+  case vmIntrinsics::_doubleToRawLongBits:
+  case vmIntrinsics::_longBitsToDouble:
+  case vmIntrinsics::_getClass:
+  case vmIntrinsics::_isInstance:
+  case vmIntrinsics::_currentThread:
+  case vmIntrinsics::_dabs:
+  case vmIntrinsics::_dsqrt:
+  case vmIntrinsics::_dsin:
+  case vmIntrinsics::_dcos:
+  case vmIntrinsics::_dtan:
+  case vmIntrinsics::_dlog:
+  case vmIntrinsics::_dlog10:
+  case vmIntrinsics::_dexp:
+  case vmIntrinsics::_dpow:
+  case vmIntrinsics::_getObject:
+  case vmIntrinsics::_getBoolean:
+  case vmIntrinsics::_getByte:
+  case vmIntrinsics::_getShort:
+  case vmIntrinsics::_getChar:
+  case vmIntrinsics::_getInt:
+  case vmIntrinsics::_getLong:
+  case vmIntrinsics::_getFloat:
+  case vmIntrinsics::_getDouble:
+  case vmIntrinsics::_putObject:
+  case vmIntrinsics::_putBoolean:
+  case vmIntrinsics::_putByte:
+  case vmIntrinsics::_putShort:
+  case vmIntrinsics::_putChar:
+  case vmIntrinsics::_putInt:
+  case vmIntrinsics::_putLong:
+  case vmIntrinsics::_putFloat:
+  case vmIntrinsics::_putDouble:
+  case vmIntrinsics::_getObjectVolatile:
+  case vmIntrinsics::_getBooleanVolatile:
+  case vmIntrinsics::_getByteVolatile:
+  case vmIntrinsics::_getShortVolatile:
+  case vmIntrinsics::_getCharVolatile:
+  case vmIntrinsics::_getIntVolatile:
+  case vmIntrinsics::_getLongVolatile:
+  case vmIntrinsics::_getFloatVolatile:
+  case vmIntrinsics::_getDoubleVolatile:
+  case vmIntrinsics::_putObjectVolatile:
+  case vmIntrinsics::_putBooleanVolatile:
+  case vmIntrinsics::_putByteVolatile:
+  case vmIntrinsics::_putShortVolatile:
+  case vmIntrinsics::_putCharVolatile:
+  case vmIntrinsics::_putIntVolatile:
+  case vmIntrinsics::_putLongVolatile:
+  case vmIntrinsics::_putFloatVolatile:
+  case vmIntrinsics::_putDoubleVolatile:
+  case vmIntrinsics::_getByte_raw:
+  case vmIntrinsics::_getShort_raw:
+  case vmIntrinsics::_getChar_raw:
+  case vmIntrinsics::_getInt_raw:
+  case vmIntrinsics::_getLong_raw:
+  case vmIntrinsics::_getFloat_raw:
+  case vmIntrinsics::_getDouble_raw:
+  case vmIntrinsics::_putByte_raw:
+  case vmIntrinsics::_putShort_raw:
+  case vmIntrinsics::_putChar_raw:
+  case vmIntrinsics::_putInt_raw:
+  case vmIntrinsics::_putLong_raw:
+  case vmIntrinsics::_putFloat_raw:
+  case vmIntrinsics::_putDouble_raw:
+  case vmIntrinsics::_putOrderedObject:
+  case vmIntrinsics::_putOrderedInt:
+  case vmIntrinsics::_putOrderedLong:
+  case vmIntrinsics::_getShortUnaligned:
+  case vmIntrinsics::_getCharUnaligned:
+  case vmIntrinsics::_getIntUnaligned:
+  case vmIntrinsics::_getLongUnaligned:
+  case vmIntrinsics::_putShortUnaligned:
+  case vmIntrinsics::_putCharUnaligned:
+  case vmIntrinsics::_putIntUnaligned:
+  case vmIntrinsics::_putLongUnaligned:
+  case vmIntrinsics::_checkIndex:
+  case vmIntrinsics::_updateCRC32:
+  case vmIntrinsics::_updateBytesCRC32:
+  case vmIntrinsics::_updateByteBufferCRC32:
+  case vmIntrinsics::_compareAndSwapInt:
+  case vmIntrinsics::_compareAndSwapObject:
+#ifdef TRACE_HAVE_INTRINSICS
+  case vmIntrinsics::_classID:
+  case vmIntrinsics::_threadID:
+  case vmIntrinsics::_counterTime:
+#endif
+    break;
+  default:
+    return false; // Intrinsics not on the previous list are not available.
+  }
+
+  return true;
+}
+
+bool Compiler::is_intrinsic_disabled_by_flag(methodHandle method) {
+  vmIntrinsics::ID id = method->intrinsic_id();
+  assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
+
+  if (vmIntrinsics::is_disabled_by_flags(id)) {
+    return true;
+  }
+
+  if (!InlineNatives && id != vmIntrinsics::_Reference_get) {
+    return true;
+  }
+
+  if (!InlineClassNatives && id == vmIntrinsics::_getClass) {
+    return true;
+  }
+
+  return false;
+}
 
 void Compiler::compile_method(ciEnv* env, ciMethod* method, int entry_bci) {
   BufferBlob* buffer_blob = CompilerThread::current()->get_buffer_blob();
@@ -117,3 +275,7 @@
 void Compiler::print_timers() {
   Compilation::print_timers();
 }
+
+bool Compiler::is_intrinsic_available(methodHandle method, methodHandle compilation_context) {
+  return is_intrinsic_supported(method) && !is_intrinsic_disabled_by_flag(method);
+}
--- a/hotspot/src/share/vm/c1/c1_Compiler.hpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/c1/c1_Compiler.hpp	Fri Jul 31 10:15:02 2015 -0700
@@ -55,6 +55,18 @@
   // Print compilation timers and statistics
   virtual void print_timers();
 
+  // Check the availability of an intrinsic for 'method' given a compilation context.
+  // The compilation context is needed to support per-method usage of the
+  // DisableIntrinsic flag. However, as C1 ignores the DisableIntrinsic flag, it
+  // ignores the compilation context.
+  virtual bool is_intrinsic_available(methodHandle method, methodHandle compilation_context);
+
+  // Check if the C1 compiler supports an intrinsic for 'method'.
+  virtual bool is_intrinsic_supported(methodHandle method);
+
+  // Processing of command-line flags specific to the C1 compiler.
+  virtual bool is_intrinsic_disabled_by_flag(methodHandle method);
+
   // Size of the code buffer
   static int code_buffer_size();
 };
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp	Fri Jul 31 10:15:02 2015 -0700
@@ -3372,231 +3372,85 @@
   return NULL;
 }
 
-
-bool GraphBuilder::try_inline_intrinsics(ciMethod* callee) {
-  if (callee->is_synchronized()) {
-    // We don't currently support any synchronized intrinsics
-    return false;
-  }
-
-  // callee seems like a good candidate
-  // determine id
+void GraphBuilder::build_graph_for_intrinsic(ciMethod* callee) {
   vmIntrinsics::ID id = callee->intrinsic_id();
-  if (!InlineNatives && id != vmIntrinsics::_Reference_get) {
-    // InlineNatives does not control Reference.get
-    INLINE_BAILOUT("intrinsic method inlining disabled");
+  assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
+
+  // Some intrinsics need special IR nodes.
+  switch(id) {
+  case vmIntrinsics::_getObject          : append_unsafe_get_obj(callee, T_OBJECT,  false); return;
+  case vmIntrinsics::_getBoolean         : append_unsafe_get_obj(callee, T_BOOLEAN, false); return;
+  case vmIntrinsics::_getByte            : append_unsafe_get_obj(callee, T_BYTE,    false); return;
+  case vmIntrinsics::_getShort           : append_unsafe_get_obj(callee, T_SHORT,   false); return;
+  case vmIntrinsics::_getChar            : append_unsafe_get_obj(callee, T_CHAR,    false); return;
+  case vmIntrinsics::_getInt             : append_unsafe_get_obj(callee, T_INT,     false); return;
+  case vmIntrinsics::_getLong            : append_unsafe_get_obj(callee, T_LONG,    false); return;
+  case vmIntrinsics::_getFloat           : append_unsafe_get_obj(callee, T_FLOAT,   false); return;
+  case vmIntrinsics::_getDouble          : append_unsafe_get_obj(callee, T_DOUBLE,  false); return;
+  case vmIntrinsics::_putObject          : append_unsafe_put_obj(callee, T_OBJECT,  false); return;
+  case vmIntrinsics::_putBoolean         : append_unsafe_put_obj(callee, T_BOOLEAN, false); return;
+  case vmIntrinsics::_putByte            : append_unsafe_put_obj(callee, T_BYTE,    false); return;
+  case vmIntrinsics::_putShort           : append_unsafe_put_obj(callee, T_SHORT,   false); return;
+  case vmIntrinsics::_putChar            : append_unsafe_put_obj(callee, T_CHAR,    false); return;
+  case vmIntrinsics::_putInt             : append_unsafe_put_obj(callee, T_INT,     false); return;
+  case vmIntrinsics::_putLong            : append_unsafe_put_obj(callee, T_LONG,    false); return;
+  case vmIntrinsics::_putFloat           : append_unsafe_put_obj(callee, T_FLOAT,   false); return;
+  case vmIntrinsics::_putDouble          : append_unsafe_put_obj(callee, T_DOUBLE,  false); return;
+  case vmIntrinsics::_getShortUnaligned  : append_unsafe_get_obj(callee, T_SHORT,   false); return;
+  case vmIntrinsics::_getCharUnaligned   : append_unsafe_get_obj(callee, T_CHAR,    false); return;
+  case vmIntrinsics::_getIntUnaligned    : append_unsafe_get_obj(callee, T_INT,     false); return;
+  case vmIntrinsics::_getLongUnaligned   : append_unsafe_get_obj(callee, T_LONG,    false); return;
+  case vmIntrinsics::_putShortUnaligned  : append_unsafe_put_obj(callee, T_SHORT,   false); return;
+  case vmIntrinsics::_putCharUnaligned   : append_unsafe_put_obj(callee, T_CHAR,    false); return;
+  case vmIntrinsics::_putIntUnaligned    : append_unsafe_put_obj(callee, T_INT,     false); return;
+  case vmIntrinsics::_putLongUnaligned   : append_unsafe_put_obj(callee, T_LONG,    false); return;
+  case vmIntrinsics::_getObjectVolatile  : append_unsafe_get_obj(callee, T_OBJECT,  true); return;
+  case vmIntrinsics::_getBooleanVolatile : append_unsafe_get_obj(callee, T_BOOLEAN, true); return;
+  case vmIntrinsics::_getByteVolatile    : append_unsafe_get_obj(callee, T_BYTE,    true); return;
+  case vmIntrinsics::_getShortVolatile   : append_unsafe_get_obj(callee, T_SHORT,   true); return;
+  case vmIntrinsics::_getCharVolatile    : append_unsafe_get_obj(callee, T_CHAR,    true); return;
+  case vmIntrinsics::_getIntVolatile     : append_unsafe_get_obj(callee, T_INT,     true); return;
+  case vmIntrinsics::_getLongVolatile    : append_unsafe_get_obj(callee, T_LONG,    true); return;
+  case vmIntrinsics::_getFloatVolatile   : append_unsafe_get_obj(callee, T_FLOAT,   true); return;
+  case vmIntrinsics::_getDoubleVolatile  : append_unsafe_get_obj(callee, T_DOUBLE,  true); return;
+  case vmIntrinsics::_putObjectVolatile  : append_unsafe_put_obj(callee, T_OBJECT,  true); return;
+  case vmIntrinsics::_putBooleanVolatile : append_unsafe_put_obj(callee, T_BOOLEAN, true); return;
+  case vmIntrinsics::_putByteVolatile    : append_unsafe_put_obj(callee, T_BYTE,    true); return;
+  case vmIntrinsics::_putShortVolatile   : append_unsafe_put_obj(callee, T_SHORT,   true); return;
+  case vmIntrinsics::_putCharVolatile    : append_unsafe_put_obj(callee, T_CHAR,    true); return;
+  case vmIntrinsics::_putIntVolatile     : append_unsafe_put_obj(callee, T_INT,     true); return;
+  case vmIntrinsics::_putLongVolatile    : append_unsafe_put_obj(callee, T_LONG,    true); return;
+  case vmIntrinsics::_putFloatVolatile   : append_unsafe_put_obj(callee, T_FLOAT,   true); return;
+  case vmIntrinsics::_putDoubleVolatile  : append_unsafe_put_obj(callee, T_DOUBLE,  true); return;
+  case vmIntrinsics::_getByte_raw        : append_unsafe_get_raw(callee, T_BYTE  ); return;
+  case vmIntrinsics::_getShort_raw       : append_unsafe_get_raw(callee, T_SHORT ); return;
+  case vmIntrinsics::_getChar_raw        : append_unsafe_get_raw(callee, T_CHAR  ); return;
+  case vmIntrinsics::_getInt_raw         : append_unsafe_get_raw(callee, T_INT   ); return;
+  case vmIntrinsics::_getLong_raw        : append_unsafe_get_raw(callee, T_LONG  ); return;
+  case vmIntrinsics::_getFloat_raw       : append_unsafe_get_raw(callee, T_FLOAT ); return;
+  case vmIntrinsics::_getDouble_raw      : append_unsafe_get_raw(callee, T_DOUBLE); return;
+  case vmIntrinsics::_putByte_raw        : append_unsafe_put_raw(callee, T_BYTE  ); return;
+  case vmIntrinsics::_putShort_raw       : append_unsafe_put_raw(callee, T_SHORT ); return;
+  case vmIntrinsics::_putChar_raw        : append_unsafe_put_raw(callee, T_CHAR  ); return;
+  case vmIntrinsics::_putInt_raw         : append_unsafe_put_raw(callee, T_INT   ); return;
+  case vmIntrinsics::_putLong_raw        : append_unsafe_put_raw(callee, T_LONG  ); return;
+  case vmIntrinsics::_putFloat_raw       : append_unsafe_put_raw(callee, T_FLOAT ); return;
+  case vmIntrinsics::_putDouble_raw      : append_unsafe_put_raw(callee, T_DOUBLE);  return;
+  case vmIntrinsics::_putOrderedObject   : append_unsafe_put_obj(callee, T_OBJECT,  true); return;
+  case vmIntrinsics::_putOrderedInt      : append_unsafe_put_obj(callee, T_INT,     true); return;
+  case vmIntrinsics::_putOrderedLong     : append_unsafe_put_obj(callee, T_LONG,    true); return;
+  case vmIntrinsics::_compareAndSwapLong:
+  case vmIntrinsics::_compareAndSwapInt:
+  case vmIntrinsics::_compareAndSwapObject: append_unsafe_CAS(callee); return;
+  case vmIntrinsics::_getAndAddInt:
+  case vmIntrinsics::_getAndAddLong      : append_unsafe_get_and_set_obj(callee, true); return;
+  case vmIntrinsics::_getAndSetInt       :
+  case vmIntrinsics::_getAndSetLong      :
+  case vmIntrinsics::_getAndSetObject    : append_unsafe_get_and_set_obj(callee, false); return;
+  default:
+    break;
   }
-  bool preserves_state = false;
-  bool cantrap = true;
-  switch (id) {
-    case vmIntrinsics::_arraycopy:
-      if (!InlineArrayCopy) return false;
-      break;
-
-#ifdef TRACE_HAVE_INTRINSICS
-    case vmIntrinsics::_classID:
-    case vmIntrinsics::_threadID:
-      preserves_state = true;
-      cantrap = true;
-      break;
-
-    case vmIntrinsics::_counterTime:
-      preserves_state = true;
-      cantrap = false;
-      break;
-#endif
-
-    case vmIntrinsics::_currentTimeMillis:
-    case vmIntrinsics::_nanoTime:
-      preserves_state = true;
-      cantrap = false;
-      break;
-
-    case vmIntrinsics::_floatToRawIntBits   :
-    case vmIntrinsics::_intBitsToFloat      :
-    case vmIntrinsics::_doubleToRawLongBits :
-    case vmIntrinsics::_longBitsToDouble    :
-      if (!InlineMathNatives) return false;
-      preserves_state = true;
-      cantrap = false;
-      break;
-
-    case vmIntrinsics::_getClass      :
-    case vmIntrinsics::_isInstance    :
-      if (!InlineClassNatives) return false;
-      preserves_state = true;
-      break;
-
-    case vmIntrinsics::_currentThread :
-      if (!InlineThreadNatives) return false;
-      preserves_state = true;
-      cantrap = false;
-      break;
-
-    case vmIntrinsics::_dabs          : // fall through
-    case vmIntrinsics::_dsqrt         : // fall through
-    case vmIntrinsics::_dsin          : // fall through
-    case vmIntrinsics::_dcos          : // fall through
-    case vmIntrinsics::_dtan          : // fall through
-    case vmIntrinsics::_dlog          : // fall through
-    case vmIntrinsics::_dlog10        : // fall through
-    case vmIntrinsics::_dexp          : // fall through
-    case vmIntrinsics::_dpow          : // fall through
-      if (!InlineMathNatives) return false;
-      cantrap = false;
-      preserves_state = true;
-      break;
-
-    // Use special nodes for Unsafe instructions so we can more easily
-    // perform an address-mode optimization on the raw variants
-    case vmIntrinsics::_getObject : return append_unsafe_get_obj(callee, T_OBJECT,  false);
-    case vmIntrinsics::_getBoolean: return append_unsafe_get_obj(callee, T_BOOLEAN, false);
-    case vmIntrinsics::_getByte   : return append_unsafe_get_obj(callee, T_BYTE,    false);
-    case vmIntrinsics::_getShort  : return append_unsafe_get_obj(callee, T_SHORT,   false);
-    case vmIntrinsics::_getChar   : return append_unsafe_get_obj(callee, T_CHAR,    false);
-    case vmIntrinsics::_getInt    : return append_unsafe_get_obj(callee, T_INT,     false);
-    case vmIntrinsics::_getLong   : return append_unsafe_get_obj(callee, T_LONG,    false);
-    case vmIntrinsics::_getFloat  : return append_unsafe_get_obj(callee, T_FLOAT,   false);
-    case vmIntrinsics::_getDouble : return append_unsafe_get_obj(callee, T_DOUBLE,  false);
-
-    case vmIntrinsics::_putObject : return append_unsafe_put_obj(callee, T_OBJECT,  false);
-    case vmIntrinsics::_putBoolean: return append_unsafe_put_obj(callee, T_BOOLEAN, false);
-    case vmIntrinsics::_putByte   : return append_unsafe_put_obj(callee, T_BYTE,    false);
-    case vmIntrinsics::_putShort  : return append_unsafe_put_obj(callee, T_SHORT,   false);
-    case vmIntrinsics::_putChar   : return append_unsafe_put_obj(callee, T_CHAR,    false);
-    case vmIntrinsics::_putInt    : return append_unsafe_put_obj(callee, T_INT,     false);
-    case vmIntrinsics::_putLong   : return append_unsafe_put_obj(callee, T_LONG,    false);
-    case vmIntrinsics::_putFloat  : return append_unsafe_put_obj(callee, T_FLOAT,   false);
-    case vmIntrinsics::_putDouble : return append_unsafe_put_obj(callee, T_DOUBLE,  false);
-
-    case vmIntrinsics::_getShortUnaligned  :
-      return UseUnalignedAccesses ? append_unsafe_get_obj(callee, T_SHORT,   false) : false;
-    case vmIntrinsics::_getCharUnaligned   :
-      return UseUnalignedAccesses ? append_unsafe_get_obj(callee, T_CHAR,    false) : false;
-    case vmIntrinsics::_getIntUnaligned    :
-      return UseUnalignedAccesses ? append_unsafe_get_obj(callee, T_INT,     false) : false;
-    case vmIntrinsics::_getLongUnaligned   :
-      return UseUnalignedAccesses ? append_unsafe_get_obj(callee, T_LONG,    false) : false;
-
-    case vmIntrinsics::_putShortUnaligned  :
-      return UseUnalignedAccesses ? append_unsafe_put_obj(callee, T_SHORT,   false) : false;
-    case vmIntrinsics::_putCharUnaligned   :
-      return UseUnalignedAccesses ? append_unsafe_put_obj(callee, T_CHAR,    false) : false;
-    case vmIntrinsics::_putIntUnaligned    :
-      return UseUnalignedAccesses ? append_unsafe_put_obj(callee, T_INT,     false) : false;
-    case vmIntrinsics::_putLongUnaligned   :
-      return UseUnalignedAccesses ? append_unsafe_put_obj(callee, T_LONG,    false) : false;
-
-    case vmIntrinsics::_getObjectVolatile : return append_unsafe_get_obj(callee, T_OBJECT,  true);
-    case vmIntrinsics::_getBooleanVolatile: return append_unsafe_get_obj(callee, T_BOOLEAN, true);
-    case vmIntrinsics::_getByteVolatile   : return append_unsafe_get_obj(callee, T_BYTE,    true);
-    case vmIntrinsics::_getShortVolatile  : return append_unsafe_get_obj(callee, T_SHORT,   true);
-    case vmIntrinsics::_getCharVolatile   : return append_unsafe_get_obj(callee, T_CHAR,    true);
-    case vmIntrinsics::_getIntVolatile    : return append_unsafe_get_obj(callee, T_INT,     true);
-    case vmIntrinsics::_getLongVolatile   : return append_unsafe_get_obj(callee, T_LONG,    true);
-    case vmIntrinsics::_getFloatVolatile  : return append_unsafe_get_obj(callee, T_FLOAT,   true);
-    case vmIntrinsics::_getDoubleVolatile : return append_unsafe_get_obj(callee, T_DOUBLE,  true);
-
-    case vmIntrinsics::_putObjectVolatile : return append_unsafe_put_obj(callee, T_OBJECT,  true);
-    case vmIntrinsics::_putBooleanVolatile: return append_unsafe_put_obj(callee, T_BOOLEAN, true);
-    case vmIntrinsics::_putByteVolatile   : return append_unsafe_put_obj(callee, T_BYTE,    true);
-    case vmIntrinsics::_putShortVolatile  : return append_unsafe_put_obj(callee, T_SHORT,   true);
-    case vmIntrinsics::_putCharVolatile   : return append_unsafe_put_obj(callee, T_CHAR,    true);
-    case vmIntrinsics::_putIntVolatile    : return append_unsafe_put_obj(callee, T_INT,     true);
-    case vmIntrinsics::_putLongVolatile   : return append_unsafe_put_obj(callee, T_LONG,    true);
-    case vmIntrinsics::_putFloatVolatile  : return append_unsafe_put_obj(callee, T_FLOAT,   true);
-    case vmIntrinsics::_putDoubleVolatile : return append_unsafe_put_obj(callee, T_DOUBLE,  true);
-
-    case vmIntrinsics::_getByte_raw   : return append_unsafe_get_raw(callee, T_BYTE);
-    case vmIntrinsics::_getShort_raw  : return append_unsafe_get_raw(callee, T_SHORT);
-    case vmIntrinsics::_getChar_raw   : return append_unsafe_get_raw(callee, T_CHAR);
-    case vmIntrinsics::_getInt_raw    : return append_unsafe_get_raw(callee, T_INT);
-    case vmIntrinsics::_getLong_raw   : return append_unsafe_get_raw(callee, T_LONG);
-    case vmIntrinsics::_getFloat_raw  : return append_unsafe_get_raw(callee, T_FLOAT);
-    case vmIntrinsics::_getDouble_raw : return append_unsafe_get_raw(callee, T_DOUBLE);
-
-    case vmIntrinsics::_putByte_raw   : return append_unsafe_put_raw(callee, T_BYTE);
-    case vmIntrinsics::_putShort_raw  : return append_unsafe_put_raw(callee, T_SHORT);
-    case vmIntrinsics::_putChar_raw   : return append_unsafe_put_raw(callee, T_CHAR);
-    case vmIntrinsics::_putInt_raw    : return append_unsafe_put_raw(callee, T_INT);
-    case vmIntrinsics::_putLong_raw   : return append_unsafe_put_raw(callee, T_LONG);
-    case vmIntrinsics::_putFloat_raw  : return append_unsafe_put_raw(callee, T_FLOAT);
-    case vmIntrinsics::_putDouble_raw : return append_unsafe_put_raw(callee, T_DOUBLE);
-
-    case vmIntrinsics::_checkIndex    :
-      if (!InlineNIOCheckIndex) return false;
-      preserves_state = true;
-      break;
-    case vmIntrinsics::_putOrderedObject : return append_unsafe_put_obj(callee, T_OBJECT,  true);
-    case vmIntrinsics::_putOrderedInt    : return append_unsafe_put_obj(callee, T_INT,     true);
-    case vmIntrinsics::_putOrderedLong   : return append_unsafe_put_obj(callee, T_LONG,    true);
-
-    case vmIntrinsics::_compareAndSwapLong:
-      if (!VM_Version::supports_cx8()) return false;
-      // fall through
-    case vmIntrinsics::_compareAndSwapInt:
-    case vmIntrinsics::_compareAndSwapObject:
-      append_unsafe_CAS(callee);
-      return true;
-
-    case vmIntrinsics::_getAndAddInt:
-      if (!VM_Version::supports_atomic_getadd4()) {
-        return false;
-      }
-      return append_unsafe_get_and_set_obj(callee, true);
-    case vmIntrinsics::_getAndAddLong:
-      if (!VM_Version::supports_atomic_getadd8()) {
-        return false;
-      }
-      return append_unsafe_get_and_set_obj(callee, true);
-    case vmIntrinsics::_getAndSetInt:
-      if (!VM_Version::supports_atomic_getset4()) {
-        return false;
-      }
-      return append_unsafe_get_and_set_obj(callee, false);
-    case vmIntrinsics::_getAndSetLong:
-      if (!VM_Version::supports_atomic_getset8()) {
-        return false;
-      }
-      return append_unsafe_get_and_set_obj(callee, false);
-    case vmIntrinsics::_getAndSetObject:
-#ifdef _LP64
-      if (!UseCompressedOops && !VM_Version::supports_atomic_getset8()) {
-        return false;
-      }
-      if (UseCompressedOops && !VM_Version::supports_atomic_getset4()) {
-        return false;
-      }
-#else
-      if (!VM_Version::supports_atomic_getset4()) {
-        return false;
-      }
-#endif
-      return append_unsafe_get_and_set_obj(callee, false);
-
-    case vmIntrinsics::_Reference_get:
-      // Use the intrinsic version of Reference.get() so that the value in
-      // the referent field can be registered by the G1 pre-barrier code.
-      // Also to prevent commoning reads from this field across safepoint
-      // since GC can change its value.
-      preserves_state = true;
-      break;
-
-    case vmIntrinsics::_updateCRC32:
-    case vmIntrinsics::_updateBytesCRC32:
-    case vmIntrinsics::_updateByteBufferCRC32:
-      if (!UseCRC32Intrinsics) return false;
-      cantrap = false;
-      preserves_state = true;
-      break;
-
-    case vmIntrinsics::_loadFence :
-    case vmIntrinsics::_storeFence:
-    case vmIntrinsics::_fullFence :
-      break;
-
-    default                       : return false; // do not inline
-  }
+
   // create intrinsic node
   const bool has_receiver = !callee->is_static();
   ValueType* result_type = as_ValueType(callee->return_type());
@@ -3621,8 +3475,10 @@
     }
   }
 
-  Intrinsic* result = new Intrinsic(result_type, id, args, has_receiver, state_before,
-                                    preserves_state, cantrap);
+  Intrinsic* result = new Intrinsic(result_type, callee->intrinsic_id(),
+                                    args, has_receiver, state_before,
+                                    vmIntrinsics::preserves_state(id),
+                                    vmIntrinsics::can_trap(id));
   // append instruction & push result
   Value value = append_split(result);
   if (result_type != voidType) push(result_type, value);
@@ -3630,8 +3486,22 @@
   if (callee != method() && profile_return() && result_type->is_object_kind()) {
     profile_return_type(result, callee);
   }
-
-  // done
+}
+
+bool GraphBuilder::try_inline_intrinsics(ciMethod* callee) {
+  // For calling is_intrinsic_available we need to transition to
+  // the '_thread_in_vm' state because is_intrinsic_available()
+  // does not accesses critical VM-internal data.
+  if (!_compilation->compiler()->is_intrinsic_available(callee->get_Method(), NULL)) {
+    if (!InlineNatives) {
+      // Return false and also set message that the inlining of
+      // intrinsics has been disabled in general.
+      INLINE_BAILOUT("intrinsic method inlining disabled");
+    } else {
+      return false;
+    }
+  }
+  build_graph_for_intrinsic(callee);
   return true;
 }
 
@@ -4224,58 +4094,46 @@
   _scope_data = scope_data()->parent();
 }
 
-bool GraphBuilder::append_unsafe_get_obj(ciMethod* callee, BasicType t, bool is_volatile) {
-  if (InlineUnsafeOps) {
-    Values* args = state()->pop_arguments(callee->arg_size());
-    null_check(args->at(0));
-    Instruction* offset = args->at(2);
+void GraphBuilder::append_unsafe_get_obj(ciMethod* callee, BasicType t, bool is_volatile) {
+  Values* args = state()->pop_arguments(callee->arg_size());
+  null_check(args->at(0));
+  Instruction* offset = args->at(2);
 #ifndef _LP64
-    offset = append(new Convert(Bytecodes::_l2i, offset, as_ValueType(T_INT)));
+  offset = append(new Convert(Bytecodes::_l2i, offset, as_ValueType(T_INT)));
 #endif
-    Instruction* op = append(new UnsafeGetObject(t, args->at(1), offset, is_volatile));
-    push(op->type(), op);
-    compilation()->set_has_unsafe_access(true);
-  }
-  return InlineUnsafeOps;
+  Instruction* op = append(new UnsafeGetObject(t, args->at(1), offset, is_volatile));
+  push(op->type(), op);
+  compilation()->set_has_unsafe_access(true);
 }
 
 
-bool GraphBuilder::append_unsafe_put_obj(ciMethod* callee, BasicType t, bool is_volatile) {
-  if (InlineUnsafeOps) {
-    Values* args = state()->pop_arguments(callee->arg_size());
-    null_check(args->at(0));
-    Instruction* offset = args->at(2);
+void GraphBuilder::append_unsafe_put_obj(ciMethod* callee, BasicType t, bool is_volatile) {
+  Values* args = state()->pop_arguments(callee->arg_size());
+  null_check(args->at(0));
+  Instruction* offset = args->at(2);
 #ifndef _LP64
-    offset = append(new Convert(Bytecodes::_l2i, offset, as_ValueType(T_INT)));
+  offset = append(new Convert(Bytecodes::_l2i, offset, as_ValueType(T_INT)));
 #endif
-    Instruction* op = append(new UnsafePutObject(t, args->at(1), offset, args->at(3), is_volatile));
-    compilation()->set_has_unsafe_access(true);
-    kill_all();
-  }
-  return InlineUnsafeOps;
+  Instruction* op = append(new UnsafePutObject(t, args->at(1), offset, args->at(3), is_volatile));
+  compilation()->set_has_unsafe_access(true);
+  kill_all();
 }
 
 
-bool GraphBuilder::append_unsafe_get_raw(ciMethod* callee, BasicType t) {
-  if (InlineUnsafeOps) {
-    Values* args = state()->pop_arguments(callee->arg_size());
-    null_check(args->at(0));
-    Instruction* op = append(new UnsafeGetRaw(t, args->at(1), false));
-    push(op->type(), op);
-    compilation()->set_has_unsafe_access(true);
-  }
-  return InlineUnsafeOps;
+void GraphBuilder::append_unsafe_get_raw(ciMethod* callee, BasicType t) {
+  Values* args = state()->pop_arguments(callee->arg_size());
+  null_check(args->at(0));
+  Instruction* op = append(new UnsafeGetRaw(t, args->at(1), false));
+  push(op->type(), op);
+  compilation()->set_has_unsafe_access(true);
 }
 
 
-bool GraphBuilder::append_unsafe_put_raw(ciMethod* callee, BasicType t) {
-  if (InlineUnsafeOps) {
-    Values* args = state()->pop_arguments(callee->arg_size());
-    null_check(args->at(0));
-    Instruction* op = append(new UnsafePutRaw(t, args->at(1), args->at(2)));
-    compilation()->set_has_unsafe_access(true);
-  }
-  return InlineUnsafeOps;
+void GraphBuilder::append_unsafe_put_raw(ciMethod* callee, BasicType t) {
+  Values* args = state()->pop_arguments(callee->arg_size());
+  null_check(args->at(0));
+  Instruction* op = append(new UnsafePutRaw(t, args->at(1), args->at(2)));
+  compilation()->set_has_unsafe_access(true);
 }
 
 
@@ -4352,21 +4210,18 @@
   }
 }
 
-bool GraphBuilder::append_unsafe_get_and_set_obj(ciMethod* callee, bool is_add) {
-  if (InlineUnsafeOps) {
-    Values* args = state()->pop_arguments(callee->arg_size());
-    BasicType t = callee->return_type()->basic_type();
-    null_check(args->at(0));
-    Instruction* offset = args->at(2);
+void GraphBuilder::append_unsafe_get_and_set_obj(ciMethod* callee, bool is_add) {
+  Values* args = state()->pop_arguments(callee->arg_size());
+  BasicType t = callee->return_type()->basic_type();
+  null_check(args->at(0));
+  Instruction* offset = args->at(2);
 #ifndef _LP64
-    offset = append(new Convert(Bytecodes::_l2i, offset, as_ValueType(T_INT)));
+  offset = append(new Convert(Bytecodes::_l2i, offset, as_ValueType(T_INT)));
 #endif
-    Instruction* op = append(new UnsafeGetAndSetObject(t, args->at(1), offset, args->at(3), is_add));
-    compilation()->set_has_unsafe_access(true);
-    kill_all();
-    push(op->type(), op);
-  }
-  return InlineUnsafeOps;
+  Instruction* op = append(new UnsafeGetAndSetObject(t, args->at(1), offset, args->at(3), is_add));
+  compilation()->set_has_unsafe_access(true);
+  kill_all();
+  push(op->type(), op);
 }
 
 #ifndef PRODUCT
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp	Fri Jul 31 10:15:02 2015 -0700
@@ -339,6 +339,8 @@
   void inline_sync_entry(Value lock, BlockBegin* sync_handler);
   void fill_sync_handler(Value lock, BlockBegin* sync_handler, bool default_handler = false);
 
+  void build_graph_for_intrinsic(ciMethod* callee);
+
   // inliners
   bool try_inline(           ciMethod* callee, bool holder_known, Bytecodes::Code bc = Bytecodes::_illegal, Value receiver = NULL);
   bool try_inline_intrinsics(ciMethod* callee);
@@ -364,12 +366,12 @@
   void pop_scope();
   void pop_scope_for_jsr();
 
-  bool append_unsafe_get_obj(ciMethod* callee, BasicType t, bool is_volatile);
-  bool append_unsafe_put_obj(ciMethod* callee, BasicType t, bool is_volatile);
-  bool append_unsafe_get_raw(ciMethod* callee, BasicType t);
-  bool append_unsafe_put_raw(ciMethod* callee, BasicType t);
+  void append_unsafe_get_obj(ciMethod* callee, BasicType t, bool is_volatile);
+  void append_unsafe_put_obj(ciMethod* callee, BasicType t, bool is_volatile);
+  void append_unsafe_get_raw(ciMethod* callee, BasicType t);
+  void append_unsafe_put_raw(ciMethod* callee, BasicType t);
   void append_unsafe_CAS(ciMethod* callee);
-  bool append_unsafe_get_and_set_obj(ciMethod* callee, bool is_add);
+  void append_unsafe_get_and_set_obj(ciMethod* callee, bool is_add);
 
   void print_inlining(ciMethod* callee, const char* msg = NULL, bool success = true);
 
--- a/hotspot/src/share/vm/c1/c1_ValueType.cpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/c1/c1_ValueType.cpp	Fri Jul 31 10:15:02 2015 -0700
@@ -153,7 +153,19 @@
     case T_FLOAT  : return new FloatConstant (value.as_float ());
     case T_DOUBLE : return new DoubleConstant(value.as_double());
     case T_ARRAY  : // fall through (ciConstant doesn't have an array accessor)
-    case T_OBJECT : return new ObjectConstant(value.as_object());
+    case T_OBJECT : {
+      // TODO: Common the code with GraphBuilder::load_constant?
+      ciObject* obj = value.as_object();
+      if (obj->is_null_object())
+        return objectNull;
+      if (obj->is_loaded()) {
+        if (obj->is_array())
+          return new ArrayConstant(obj->as_array());
+        else if (obj->is_instance())
+          return new InstanceConstant(obj->as_instance());
+      }
+      return new ObjectConstant(obj);
+    }
   }
   ShouldNotReachHere();
   return illegalType;
--- a/hotspot/src/share/vm/classfile/javaClasses.cpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/classfile/javaClasses.cpp	Fri Jul 31 10:15:02 2015 -0700
@@ -809,6 +809,22 @@
   return name;
 }
 
+// Returns the Java name for this Java mirror (Resource allocated)
+// See Klass::external_name().
+// For primitive type Java mirrors, its type name is returned.
+const char* java_lang_Class::as_external_name(oop java_class) {
+  assert(java_lang_Class::is_instance(java_class), "must be a Class object");
+  const char* name = NULL;
+  if (is_primitive(java_class)) {
+    name = type2name(primitive_type(java_class));
+  } else {
+    name = as_Klass(java_class)->external_name();
+  }
+  if (name == NULL) {
+    name = "<null>";
+  }
+  return name;
+}
 
 Klass* java_lang_Class::array_klass(oop java_class) {
   Klass* k = ((Klass*)java_class->metadata_field(_array_klass_offset));
@@ -1468,6 +1484,19 @@
 
 };
 
+Symbol* get_source_file_name(InstanceKlass* holder, int version) {
+  // Find the specific ik version that contains this source_file_name_index
+  // via the previous versions list, but use the current version's
+  // constant pool to look it up.  The previous version's index has been
+  // merged for the current constant pool.
+  InstanceKlass* ik = holder->get_klass_version(version);
+  // This version has been cleaned up.
+  if (ik == NULL) return NULL;
+  int source_file_name_index = ik->source_file_name_index();
+  return (source_file_name_index == 0) ?
+      (Symbol*)NULL : holder->constants()->symbol_at(source_file_name_index);
+}
+
 // Print stack trace element to resource allocated buffer
 char* java_lang_Throwable::print_stack_element_to_buffer(Handle mirror,
                                   int method_id, int version, int bci, int cpref) {
@@ -1484,17 +1513,11 @@
   char* method_name = sym->as_C_string();
   buf_len += (int)strlen(method_name);
 
-  // Use specific ik version as a holder since the mirror might
-  // refer to version that is now obsolete and no longer accessible
-  // via the previous versions list.
-  holder = holder->get_klass_version(version);
   char* source_file_name = NULL;
-  if (holder != NULL) {
-    Symbol* source = holder->source_file_name();
-    if (source != NULL) {
-      source_file_name = source->as_C_string();
-      buf_len += (int)strlen(source_file_name);
-    }
+  Symbol* source = get_source_file_name(holder, version);
+  if (source != NULL) {
+    source_file_name = source->as_C_string();
+    buf_len += (int)strlen(source_file_name);
   }
 
   // Allocate temporary buffer with extra space for formatting and line number
@@ -1909,12 +1932,7 @@
     java_lang_StackTraceElement::set_lineNumber(element(), -1);
   } else {
     // Fill in source file name and line number.
-    // Use specific ik version as a holder since the mirror might
-    // refer to version that is now obsolete and no longer accessible
-    // via the previous versions list.
-    holder = holder->get_klass_version(version);
-    assert(holder != NULL, "sanity check");
-    Symbol* source = holder->source_file_name();
+    Symbol* source = get_source_file_name(holder, version);
     if (ShowHiddenFrames && source == NULL)
       source = vmSymbols::unknown_class_name();
     oop filename = StringTable::intern(source, CHECK_0);
--- a/hotspot/src/share/vm/classfile/javaClasses.hpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/classfile/javaClasses.hpp	Fri Jul 31 10:15:02 2015 -0700
@@ -276,6 +276,7 @@
   }
   static Symbol* as_signature(oop java_class, bool intern_if_not_found, TRAPS);
   static void print_signature(oop java_class, outputStream *st);
+  static const char* as_external_name(oop java_class);
   // Testing
   static bool is_instance(oop obj);
 
--- a/hotspot/src/share/vm/classfile/verificationType.cpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/classfile/verificationType.cpp	Fri Jul 31 10:15:02 2015 -0700
@@ -86,7 +86,7 @@
     VerificationType comp_this = get_component(context, CHECK_false);
     VerificationType comp_from = from.get_component(context, CHECK_false);
     if (!comp_this.is_bogus() && !comp_from.is_bogus()) {
-      return comp_this.is_assignable_from(comp_from, context,
+      return comp_this.is_component_assignable_from(comp_from, context,
                                           from_field_is_protected, CHECK_false);
     }
   }
--- a/hotspot/src/share/vm/classfile/verificationType.hpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/classfile/verificationType.hpp	Fri Jul 31 10:15:02 2015 -0700
@@ -297,6 +297,26 @@
     }
   }
 
+  // Check to see if one array component type is assignable to another.
+  // Same as is_assignable_from() except int primitives must be identical.
+  bool is_component_assignable_from(
+      const VerificationType& from, ClassVerifier* context,
+      bool from_field_is_protected, TRAPS) const {
+    if (equals(from) || is_bogus()) {
+      return true;
+    } else {
+      switch(_u._data) {
+        case Boolean:
+        case Byte:
+        case Char:
+        case Short:
+          return false;
+        default:
+          return is_assignable_from(from, context, from_field_is_protected, CHECK_false);
+      }
+    }
+  }
+
   VerificationType get_component(ClassVerifier* context, TRAPS) const;
 
   int dimensions() const {
--- a/hotspot/src/share/vm/classfile/vmSymbols.cpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/classfile/vmSymbols.cpp	Fri Jul 31 10:15:02 2015 -0700
@@ -324,6 +324,319 @@
   return vmIntrinsics::_none;
 }
 
+bool vmIntrinsics::preserves_state(vmIntrinsics::ID id) {
+  assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
+  switch(id) {
+#ifdef TRACE_HAVE_INTRINSICS
+  case vmIntrinsics::_classID:
+  case vmIntrinsics::_threadID:
+  case vmIntrinsics::_counterTime:
+#endif
+  case vmIntrinsics::_currentTimeMillis:
+  case vmIntrinsics::_nanoTime:
+  case vmIntrinsics::_floatToRawIntBits:
+  case vmIntrinsics::_intBitsToFloat:
+  case vmIntrinsics::_doubleToRawLongBits:
+  case vmIntrinsics::_longBitsToDouble:
+  case vmIntrinsics::_getClass:
+  case vmIntrinsics::_isInstance:
+  case vmIntrinsics::_currentThread:
+  case vmIntrinsics::_dabs:
+  case vmIntrinsics::_dsqrt:
+  case vmIntrinsics::_dsin:
+  case vmIntrinsics::_dcos:
+  case vmIntrinsics::_dtan:
+  case vmIntrinsics::_dlog:
+  case vmIntrinsics::_dlog10:
+  case vmIntrinsics::_dexp:
+  case vmIntrinsics::_dpow:
+  case vmIntrinsics::_checkIndex:
+  case vmIntrinsics::_Reference_get:
+  case vmIntrinsics::_updateCRC32:
+  case vmIntrinsics::_updateBytesCRC32:
+  case vmIntrinsics::_updateByteBufferCRC32:
+    return true;
+  default:
+    return false;
+  }
+}
+
+bool vmIntrinsics::can_trap(vmIntrinsics::ID id) {
+  assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
+  switch(id) {
+#ifdef TRACE_HAVE_INTRINSICS
+  case vmIntrinsics::_counterTime:
+#endif
+  case vmIntrinsics::_currentTimeMillis:
+  case vmIntrinsics::_nanoTime:
+  case vmIntrinsics::_floatToRawIntBits:
+  case vmIntrinsics::_intBitsToFloat:
+  case vmIntrinsics::_doubleToRawLongBits:
+  case vmIntrinsics::_longBitsToDouble:
+  case vmIntrinsics::_currentThread:
+  case vmIntrinsics::_dabs:
+  case vmIntrinsics::_dsqrt:
+  case vmIntrinsics::_dsin:
+  case vmIntrinsics::_dcos:
+  case vmIntrinsics::_dtan:
+  case vmIntrinsics::_dlog:
+  case vmIntrinsics::_dlog10:
+  case vmIntrinsics::_dexp:
+  case vmIntrinsics::_dpow:
+  case vmIntrinsics::_updateCRC32:
+  case vmIntrinsics::_updateBytesCRC32:
+  case vmIntrinsics::_updateByteBufferCRC32:
+    return false;
+  default:
+    return true;
+  }
+}
+
+bool vmIntrinsics::does_virtual_dispatch(vmIntrinsics::ID id) {
+  assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
+  switch(id) {
+  case vmIntrinsics::_hashCode:
+  case vmIntrinsics::_clone:
+    return true;
+    break;
+  default:
+    return false;
+  }
+}
+
+int vmIntrinsics::predicates_needed(vmIntrinsics::ID id) {
+  assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
+  switch (id) {
+  case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt:
+  case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt:
+    return 1;
+  case vmIntrinsics::_digestBase_implCompressMB:
+    return 3;
+  default:
+    return 0;
+  }
+}
+
+bool vmIntrinsics::is_disabled_by_flags(vmIntrinsics::ID id) {
+  assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
+  switch (id) {
+  case vmIntrinsics::_isInstance:
+  case vmIntrinsics::_isAssignableFrom:
+  case vmIntrinsics::_getModifiers:
+  case vmIntrinsics::_isInterface:
+  case vmIntrinsics::_isArray:
+  case vmIntrinsics::_isPrimitive:
+  case vmIntrinsics::_getSuperclass:
+  case vmIntrinsics::_Class_cast:
+  case vmIntrinsics::_getLength:
+  case vmIntrinsics::_newArray:
+    if (!InlineClassNatives) return true;
+    break;
+  case vmIntrinsics::_currentThread:
+  case vmIntrinsics::_isInterrupted:
+    if (!InlineThreadNatives) return true;
+    break;
+  case vmIntrinsics::_floatToRawIntBits:
+  case vmIntrinsics::_intBitsToFloat:
+  case vmIntrinsics::_doubleToRawLongBits:
+  case vmIntrinsics::_longBitsToDouble:
+  case vmIntrinsics::_dabs:
+  case vmIntrinsics::_dsqrt:
+  case vmIntrinsics::_dsin:
+  case vmIntrinsics::_dcos:
+  case vmIntrinsics::_dtan:
+  case vmIntrinsics::_dlog:
+  case vmIntrinsics::_dexp:
+  case vmIntrinsics::_dpow:
+  case vmIntrinsics::_dlog10:
+  case vmIntrinsics::_datan2:
+  case vmIntrinsics::_min:
+  case vmIntrinsics::_max:
+  case vmIntrinsics::_floatToIntBits:
+  case vmIntrinsics::_doubleToLongBits:
+    if (!InlineMathNatives) return true;
+    break;
+  case vmIntrinsics::_arraycopy:
+    if (!InlineArrayCopy) return true;
+    break;
+  case vmIntrinsics::_updateCRC32:
+  case vmIntrinsics::_updateBytesCRC32:
+  case vmIntrinsics::_updateByteBufferCRC32:
+    if (!UseCRC32Intrinsics) return true;
+    break;
+  case vmIntrinsics::_getObject:
+  case vmIntrinsics::_getBoolean:
+  case vmIntrinsics::_getByte:
+  case vmIntrinsics::_getShort:
+  case vmIntrinsics::_getChar:
+  case vmIntrinsics::_getInt:
+  case vmIntrinsics::_getLong:
+  case vmIntrinsics::_getFloat:
+  case vmIntrinsics::_getDouble:
+  case vmIntrinsics::_putObject:
+  case vmIntrinsics::_putBoolean:
+  case vmIntrinsics::_putByte:
+  case vmIntrinsics::_putShort:
+  case vmIntrinsics::_putChar:
+  case vmIntrinsics::_putInt:
+  case vmIntrinsics::_putLong:
+  case vmIntrinsics::_putFloat:
+  case vmIntrinsics::_putDouble:
+  case vmIntrinsics::_getObjectVolatile:
+  case vmIntrinsics::_getBooleanVolatile:
+  case vmIntrinsics::_getByteVolatile:
+  case vmIntrinsics::_getShortVolatile:
+  case vmIntrinsics::_getCharVolatile:
+  case vmIntrinsics::_getIntVolatile:
+  case vmIntrinsics::_getLongVolatile:
+  case vmIntrinsics::_getFloatVolatile:
+  case vmIntrinsics::_getDoubleVolatile:
+  case vmIntrinsics::_putObjectVolatile:
+  case vmIntrinsics::_putBooleanVolatile:
+  case vmIntrinsics::_putByteVolatile:
+  case vmIntrinsics::_putShortVolatile:
+  case vmIntrinsics::_putCharVolatile:
+  case vmIntrinsics::_putIntVolatile:
+  case vmIntrinsics::_putLongVolatile:
+  case vmIntrinsics::_putFloatVolatile:
+  case vmIntrinsics::_putDoubleVolatile:
+  case vmIntrinsics::_getByte_raw:
+  case vmIntrinsics::_getShort_raw:
+  case vmIntrinsics::_getChar_raw:
+  case vmIntrinsics::_getInt_raw:
+  case vmIntrinsics::_getLong_raw:
+  case vmIntrinsics::_getFloat_raw:
+  case vmIntrinsics::_getDouble_raw:
+  case vmIntrinsics::_putByte_raw:
+  case vmIntrinsics::_putShort_raw:
+  case vmIntrinsics::_putChar_raw:
+  case vmIntrinsics::_putInt_raw:
+  case vmIntrinsics::_putLong_raw:
+  case vmIntrinsics::_putFloat_raw:
+  case vmIntrinsics::_putDouble_raw:
+  case vmIntrinsics::_putOrderedObject:
+  case vmIntrinsics::_putOrderedLong:
+  case vmIntrinsics::_putOrderedInt:
+  case vmIntrinsics::_getAndAddInt:
+  case vmIntrinsics::_getAndAddLong:
+  case vmIntrinsics::_getAndSetInt:
+  case vmIntrinsics::_getAndSetLong:
+  case vmIntrinsics::_getAndSetObject:
+    if (!InlineUnsafeOps) return true;
+    break;
+  case vmIntrinsics::_getShortUnaligned:
+  case vmIntrinsics::_getCharUnaligned:
+  case vmIntrinsics::_getIntUnaligned:
+  case vmIntrinsics::_getLongUnaligned:
+  case vmIntrinsics::_putShortUnaligned:
+  case vmIntrinsics::_putCharUnaligned:
+  case vmIntrinsics::_putIntUnaligned:
+  case vmIntrinsics::_putLongUnaligned:
+  case vmIntrinsics::_allocateInstance:
+  case vmIntrinsics::_getAddress_raw:
+  case vmIntrinsics::_putAddress_raw:
+    if (!InlineUnsafeOps || !UseUnalignedAccesses) return true;
+    break;
+  case vmIntrinsics::_hashCode:
+    if (!InlineObjectHash) return true;
+    break;
+  case vmIntrinsics::_aescrypt_encryptBlock:
+  case vmIntrinsics::_aescrypt_decryptBlock:
+    if (!UseAESIntrinsics) return true;
+    break;
+  case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt:
+  case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt:
+    if (!UseAESIntrinsics) return true;
+    break;
+  case vmIntrinsics::_sha_implCompress:
+    if (!UseSHA1Intrinsics) return true;
+    break;
+  case vmIntrinsics::_sha2_implCompress:
+    if (!UseSHA256Intrinsics) return true;
+    break;
+  case vmIntrinsics::_sha5_implCompress:
+    if (!UseSHA512Intrinsics) return true;
+    break;
+  case vmIntrinsics::_digestBase_implCompressMB:
+    if (!(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics)) return true;
+    break;
+  case vmIntrinsics::_ghash_processBlocks:
+    if (!UseGHASHIntrinsics) return true;
+    break;
+  case vmIntrinsics::_updateBytesCRC32C:
+  case vmIntrinsics::_updateDirectByteBufferCRC32C:
+    if (!UseCRC32CIntrinsics) return true;
+    break;
+  case vmIntrinsics::_copyMemory:
+    if (!InlineArrayCopy || !InlineUnsafeOps) return true;
+    break;
+#ifdef COMPILER1
+  case vmIntrinsics::_checkIndex:
+    if (!InlineNIOCheckIndex) return true;
+    break;
+#endif // COMPILER1
+#ifdef COMPILER2
+  case vmIntrinsics::_clone:
+  case vmIntrinsics::_copyOf:
+  case vmIntrinsics::_copyOfRange:
+    // These intrinsics use both the objectcopy and the arraycopy
+    // intrinsic mechanism.
+    if (!InlineObjectCopy || !InlineArrayCopy) return true;
+    break;
+  case vmIntrinsics::_compareTo:
+     if (!SpecialStringCompareTo) return true;
+     break;
+  case vmIntrinsics::_indexOf:
+    if (!SpecialStringIndexOf) return true;
+    break;
+  case vmIntrinsics::_equals:
+    if (!SpecialStringEquals) return true;
+    break;
+  case vmIntrinsics::_equalsC:
+    if (!SpecialArraysEquals) return true;
+    break;
+  case vmIntrinsics::_encodeISOArray:
+    if (!SpecialEncodeISOArray) return true;
+    break;
+  case vmIntrinsics::_getCallerClass:
+    if (!InlineReflectionGetCallerClass) return true;
+    break;
+  case vmIntrinsics::_multiplyToLen:
+      if (!UseMultiplyToLenIntrinsic) return true;
+      break;
+  case vmIntrinsics::_squareToLen:
+    if (!UseSquareToLenIntrinsic) return true;
+    break;
+  case vmIntrinsics::_mulAdd:
+    if (!UseMulAddIntrinsic) return true;
+    break;
+  case vmIntrinsics::_montgomeryMultiply:
+    if (!UseMontgomeryMultiplyIntrinsic) return true;
+    break;
+  case vmIntrinsics::_montgomerySquare:
+    if (!UseMontgomerySquareIntrinsic) return true;
+    break;
+  case vmIntrinsics::_addExactI:
+  case vmIntrinsics::_addExactL:
+  case vmIntrinsics::_decrementExactI:
+  case vmIntrinsics::_decrementExactL:
+  case vmIntrinsics::_incrementExactI:
+  case vmIntrinsics::_incrementExactL:
+  case vmIntrinsics::_multiplyExactI:
+  case vmIntrinsics::_multiplyExactL:
+  case vmIntrinsics::_negateExactI:
+  case vmIntrinsics::_negateExactL:
+  case vmIntrinsics::_subtractExactI:
+  case vmIntrinsics::_subtractExactL:
+    if (!UseMathExactIntrinsics || !InlineMathNatives) return true;
+    break;
+#endif // COMPILER2
+  default:
+    return false;
+  }
+
+  return false;
+}
 
 #define VM_INTRINSIC_INITIALIZE(id, klass, name, sig, flags) #id "\0"
 static const char* vm_intrinsic_name_bodies =
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp	Fri Jul 31 10:15:02 2015 -0700
@@ -1368,6 +1368,26 @@
 
   // Raw conversion:
   static ID for_raw_conversion(BasicType src, BasicType dest);
+
+  // The methods below provide information related to compiling intrinsics.
+
+  // (1) Information needed by the C1 compiler.
+
+  static bool preserves_state(vmIntrinsics::ID id);
+  static bool can_trap(vmIntrinsics::ID id);
+
+  // (2) Information needed by the C2 compiler.
+
+  // Returns true if the intrinsic for method 'method' will perform a virtual dispatch.
+  static bool does_virtual_dispatch(vmIntrinsics::ID id);
+  // A return value larger than 0 indicates that the intrinsic for method
+  // 'method' requires predicated logic.
+  static int predicates_needed(vmIntrinsics::ID id);
+
+  // Returns true if an intrinsic is disabled by command-line flags and
+  // false otherwise. Implements functionality common to the C1
+  // and the C2 compiler.
+  static bool is_disabled_by_flags(vmIntrinsics::ID id);
 };
 
 #endif // SHARE_VM_CLASSFILE_VMSYMBOLS_HPP
--- a/hotspot/src/share/vm/compiler/abstractCompiler.hpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/compiler/abstractCompiler.hpp	Fri Jul 31 10:15:02 2015 -0700
@@ -66,6 +66,58 @@
   virtual bool supports_osr   ()                 { return true; }
   virtual bool can_compile_method(methodHandle method)  { return true; }
 
+  // Determine if the current compiler provides an intrinsic
+  // for method 'method'. An intrinsic is available if:
+  //  - the intrinsic is enabled (by using the appropriate command-line flag) and
+  //  - the platform on which the VM is running supports the intrinsic
+  //    (i.e., the platform provides the instructions necessary for the compiler
+  //    to generate the intrinsic code).
+  //
+  // The second parameter, 'compilation_context', is needed to implement functionality
+  // related to the DisableIntrinsic command-line flag. The DisableIntrinsic flag can
+  // be used to prohibit the C2 compiler (but not the C1 compiler) to use an intrinsic.
+  // There are three ways to disable an intrinsic using the DisableIntrinsic flag:
+  //
+  // (1) -XX:DisableIntrinsic=_hashCode,_getClass
+  //     Disables intrinsification of _hashCode and _getClass globally
+  //     (i.e., the intrinsified version the methods will not be used at all).
+  // (2) -XX:CompileCommand=option,aClass::aMethod,ccstr,DisableIntrinsic,_hashCode
+  //     Disables intrinsification of _hashCode if it is called from
+  //     aClass::aMethod (but not for any other call site of _hashCode)
+  // (3) -XX:CompileCommand=option,java.lang.ref.Reference::get,ccstr,DisableIntrinsic,_Reference_get
+  //     Some methods are not compiled by C2. Instead, the C2 compiler
+  //     returns directly the intrinsified version of these methods.
+  //     The command above forces C2 to compile _Reference_get, but
+  //     allows using the intrinsified version of _Reference_get at all
+  //     other call sites.
+  //
+  // From the modes above, (1) disable intrinsics globally, (2) and (3)
+  // disable intrinsics on a per-method basis. In cases (2) and (3) the
+  // compilation context is aClass::aMethod and java.lang.ref.Reference::get,
+  // respectively.
+  virtual bool is_intrinsic_available(methodHandle method, methodHandle compilation_context) {
+    return false;
+  }
+
+  // Determines if an intrinsic is supported by the compiler, that is,
+  // the compiler provides the instructions necessary to generate
+  // the intrinsic code for method 'method'.
+  //
+  // The 'is_intrinsic_supported' method is a white list, that is,
+  // by default no intrinsics are supported by a compiler except
+  // the ones listed in the method. Overriding methods should conform
+  // to this behavior.
+  virtual bool is_intrinsic_supported(methodHandle method) {
+    return false;
+  }
+
+  // Implements compiler-specific processing of command-line flags.
+  // Processing of command-line flags common to all compilers is implemented
+  // in vmIntrinsicss::is_disabled_by_flag.
+  virtual bool is_intrinsic_disabled_by_flag(methodHandle method) {
+    return false;
+  }
+
   // Compiler type queries.
   bool is_c1()                                   { return _type == c1; }
   bool is_c2()                                   { return _type == c2; }
--- a/hotspot/src/share/vm/compiler/compileBroker.cpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/compiler/compileBroker.cpp	Fri Jul 31 10:15:02 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
@@ -345,6 +345,14 @@
   }
 }
 
+// RedefineClasses support
+void CompileTask::metadata_do(void f(Metadata*)) {
+  f(method());
+  if (hot_method() != NULL && hot_method() != method()) {
+    f(hot_method());
+  }
+}
+
 // ------------------------------------------------------------------
 // CompileTask::print_line_on_error
 //
@@ -660,6 +668,11 @@
  * Get the next CompileTask from a CompileQueue
  */
 CompileTask* CompileQueue::get() {
+  // save methods from RedefineClasses across safepoint
+  // across MethodCompileQueue_lock below.
+  methodHandle save_method;
+  methodHandle save_hot_method;
+
   MutexLocker locker(MethodCompileQueue_lock);
   // If _first is NULL we have no more compile jobs. There are two reasons for
   // having no compile jobs: First, we compiled everything we wanted. Second,
@@ -693,6 +706,12 @@
     No_Safepoint_Verifier nsv;
     task = CompilationPolicy::policy()->select_task(this);
   }
+
+  // Save method pointers across unlock safepoint.  The task is removed from
+  // the compilation queue, which is walked during RedefineClasses.
+  save_method = methodHandle(task->method());
+  save_hot_method = methodHandle(task->hot_method());
+
   remove(task);
   purge_stale_tasks(); // may temporarily release MCQ lock
   return task;
--- a/hotspot/src/share/vm/compiler/compileBroker.hpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/compiler/compileBroker.hpp	Fri Jul 31 10:15:02 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
@@ -80,6 +80,7 @@
 
   int          compile_id() const                { return _compile_id; }
   Method*      method() const                    { return _method; }
+  Method*      hot_method() const                { return _hot_method; }
   int          osr_bci() const                   { return _osr_bci; }
   bool         is_complete() const               { return _is_complete; }
   bool         is_blocking() const               { return _is_blocking; }
@@ -108,6 +109,9 @@
   bool         is_free() const                   { return _is_free; }
   void         set_is_free(bool val)             { _is_free = val; }
 
+  // RedefineClasses support
+  void         metadata_do(void f(Metadata*));
+
 private:
   static void  print_compilation_impl(outputStream* st, Method* method, int compile_id, int comp_level,
                                       bool is_osr_method = false, int osr_bci = -1, bool is_blocking = false,
--- a/hotspot/src/share/vm/gc/cms/parCardTableModRefBS.cpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/gc/cms/parCardTableModRefBS.cpp	Fri Jul 31 10:15:02 2015 -0700
@@ -36,10 +36,11 @@
 #include "runtime/orderAccess.inline.hpp"
 #include "runtime/vmThread.hpp"
 
-void CardTableModRefBS::non_clean_card_iterate_parallel_work(Space* sp, MemRegion mr,
-                                                             OopsInGenClosure* cl,
-                                                             CardTableRS* ct,
-                                                             uint n_threads) {
+void CardTableModRefBSForCTRS::
+non_clean_card_iterate_parallel_work(Space* sp, MemRegion mr,
+                                     OopsInGenClosure* cl,
+                                     CardTableRS* ct,
+                                     uint n_threads) {
   assert(n_threads > 0, "expected n_threads > 0");
   assert(n_threads <= ParallelGCThreads,
          err_msg("n_threads: %u > ParallelGCThreads: %u", n_threads, ParallelGCThreads));
@@ -81,7 +82,7 @@
 }
 
 void
-CardTableModRefBS::
+CardTableModRefBSForCTRS::
 process_stride(Space* sp,
                MemRegion used,
                jint stride, int n_strides,
@@ -170,7 +171,7 @@
 #endif
 
 void
-CardTableModRefBS::
+CardTableModRefBSForCTRS::
 process_chunk_boundaries(Space* sp,
                          DirtyCardToOopClosure* dcto_cl,
                          MemRegion chunk_mr,
@@ -426,7 +427,7 @@
 #undef NOISY
 
 void
-CardTableModRefBS::
+CardTableModRefBSForCTRS::
 get_LNC_array_for_space(Space* sp,
                         jbyte**& lowest_non_clean,
                         uintptr_t& lowest_non_clean_base_chunk_index,
--- a/hotspot/src/share/vm/gc/g1/concurrentMark.cpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/gc/g1/concurrentMark.cpp	Fri Jul 31 10:15:02 2015 -0700
@@ -403,14 +403,6 @@
   _saved_index = -1;
 }
 
-void CMMarkStack::oops_do(OopClosure* f) {
-  assert(_saved_index == _index,
-         err_msg("saved index: %d index: %d", _saved_index, _index));
-  for (int i = 0; i < _index; i += 1) {
-    f->do_oop(&_base[i]);
-  }
-}
-
 CMRootRegions::CMRootRegions() :
   _young_list(NULL), _cm(NULL), _scan_in_progress(false),
   _should_abort(false),  _next_survivor(NULL) { }
@@ -2717,53 +2709,26 @@
 }
 
 #ifndef PRODUCT
-enum VerifyNoCSetOopsPhase {
-  VerifyNoCSetOopsStack,
-  VerifyNoCSetOopsQueues
-};
-
-class VerifyNoCSetOopsClosure : public OopClosure, public ObjectClosure  {
+class VerifyNoCSetOops VALUE_OBJ_CLASS_SPEC {
 private:
   G1CollectedHeap* _g1h;
-  VerifyNoCSetOopsPhase _phase;
+  const char* _phase;
   int _info;
 
-  const char* phase_str() {
-    switch (_phase) {
-    case VerifyNoCSetOopsStack:         return "Stack";
-    case VerifyNoCSetOopsQueues:        return "Queue";
-    default:                            ShouldNotReachHere();
-    }
-    return NULL;
-  }
-
-  void do_object_work(oop obj) {
+public:
+  VerifyNoCSetOops(const char* phase, int info = -1) :
+    _g1h(G1CollectedHeap::heap()),
+    _phase(phase),
+    _info(info)
+  { }
+
+  void operator()(oop obj) const {
+    guarantee(obj->is_oop(),
+              err_msg("Non-oop " PTR_FORMAT ", phase: %s, info: %d",
+                      p2i(obj), _phase, _info));
     guarantee(!_g1h->obj_in_cs(obj),
               err_msg("obj: " PTR_FORMAT " in CSet, phase: %s, info: %d",
-                      p2i((void*) obj), phase_str(), _info));
-  }
-
-public:
-  VerifyNoCSetOopsClosure() : _g1h(G1CollectedHeap::heap()) { }
-
-  void set_phase(VerifyNoCSetOopsPhase phase, int info = -1) {
-    _phase = phase;
-    _info = info;
-  }
-
-  virtual void do_oop(oop* p) {
-    oop obj = oopDesc::load_decode_heap_oop(p);
-    do_object_work(obj);
-  }
-
-  virtual void do_oop(narrowOop* p) {
-    // We should not come across narrow oops while scanning marking
-    // stacks
-    ShouldNotReachHere();
-  }
-
-  virtual void do_object(oop obj) {
-    do_object_work(obj);
+                      p2i(obj), _phase, _info));
   }
 };
 
@@ -2773,17 +2738,13 @@
     return;
   }
 
-  VerifyNoCSetOopsClosure cl;
-
   // Verify entries on the global mark stack
-  cl.set_phase(VerifyNoCSetOopsStack);
-  _markStack.oops_do(&cl);
+  _markStack.iterate(VerifyNoCSetOops("Stack"));
 
   // Verify entries on the task queues
-  for (uint i = 0; i < _max_worker_id; i += 1) {
-    cl.set_phase(VerifyNoCSetOopsQueues, i);
+  for (uint i = 0; i < _max_worker_id; ++i) {
     CMTaskQueue* queue = _task_queues->queue(i);
-    queue->oops_do(&cl);
+    queue->iterate(VerifyNoCSetOops("Queue", i));
   }
 
   // Verify the global finger
@@ -2806,7 +2767,7 @@
 
   // Verify the task fingers
   assert(parallel_marking_threads() <= _max_worker_id, "sanity");
-  for (int i = 0; i < (int) parallel_marking_threads(); i += 1) {
+  for (uint i = 0; i < parallel_marking_threads(); ++i) {
     CMTask* task = _tasks[i];
     HeapWord* task_finger = task->finger();
     if (task_finger != NULL && task_finger < _heap_end) {
--- a/hotspot/src/share/vm/gc/g1/concurrentMark.hpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/gc/g1/concurrentMark.hpp	Fri Jul 31 10:15:02 2015 -0700
@@ -246,9 +246,10 @@
   // Make sure that we have not added any entries to the stack during GC.
   void note_end_of_gc();
 
-  // iterate over the oops in the mark stack, up to the bound recorded via
-  // the call above.
-  void oops_do(OopClosure* f);
+  // Apply fn to each oop in the mark stack, up to the bound recorded
+  // via one of the above "note" functions.  The mark stack must not
+  // be modified while iterating.
+  template<typename Fn> void iterate(Fn fn);
 };
 
 class ForceOverflowSettings VALUE_OBJ_CLASS_SPEC {
--- a/hotspot/src/share/vm/gc/g1/concurrentMark.inline.hpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/gc/g1/concurrentMark.inline.hpp	Fri Jul 31 10:15:02 2015 -0700
@@ -223,6 +223,15 @@
 
 #undef check_mark
 
+template<typename Fn>
+inline void CMMarkStack::iterate(Fn fn) {
+  assert(_saved_index == _index,
+         err_msg("saved index: %d index: %d", _saved_index, _index));
+  for (int i = 0; i < _index; ++i) {
+    fn(_base[i]);
+  }
+}
+
 inline void CMTask::push(oop obj) {
   HeapWord* objAddr = (HeapWord*) obj;
   assert(_g1h->is_in_g1_reserved(objAddr), "invariant");
--- a/hotspot/src/share/vm/gc/g1/g1Allocator.hpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1Allocator.hpp	Fri Jul 31 10:15:02 2015 -0700
@@ -39,13 +39,8 @@
 protected:
   G1CollectedHeap* _g1h;
 
-  // Outside of GC pauses, the number of bytes used in all regions other
-  // than the current allocation region.
-  size_t _summary_bytes_used;
-
 public:
-  G1Allocator(G1CollectedHeap* heap) :
-    _g1h(heap), _summary_bytes_used(0) { }
+  G1Allocator(G1CollectedHeap* heap) : _g1h(heap) { }
 
   static G1Allocator* create_allocator(G1CollectedHeap* g1h);
 
@@ -59,32 +54,13 @@
   virtual MutatorAllocRegion*    mutator_alloc_region(AllocationContext_t context) = 0;
   virtual SurvivorGCAllocRegion* survivor_gc_alloc_region(AllocationContext_t context) = 0;
   virtual OldGCAllocRegion*      old_gc_alloc_region(AllocationContext_t context) = 0;
-  virtual size_t                 used() = 0;
+  virtual size_t                 used_in_alloc_regions() = 0;
   virtual bool                   is_retained_old_region(HeapRegion* hr) = 0;
 
   void                           reuse_retained_old_region(EvacuationInfo& evacuation_info,
                                                            OldGCAllocRegion* old,
                                                            HeapRegion** retained);
 
-  size_t used_unlocked() const {
-    return _summary_bytes_used;
-  }
-
-  void increase_used(size_t bytes) {
-    _summary_bytes_used += bytes;
-  }
-
-  void decrease_used(size_t bytes) {
-    assert(_summary_bytes_used >= bytes,
-           err_msg("invariant: _summary_bytes_used: " SIZE_FORMAT " should be >= bytes: " SIZE_FORMAT,
-               _summary_bytes_used, bytes));
-    _summary_bytes_used -= bytes;
-  }
-
-  void set_used(size_t bytes) {
-    _summary_bytes_used = bytes;
-  }
-
   virtual HeapRegion* new_heap_region(uint hrs_index,
                                       G1BlockOffsetSharedArray* sharedOffsetArray,
                                       MemRegion mr) {
@@ -133,10 +109,10 @@
     return &_old_gc_alloc_region;
   }
 
-  virtual size_t used() {
+  virtual size_t used_in_alloc_regions() {
     assert(Heap_lock->owner() != NULL,
            "Should be owned on this thread's behalf.");
-    size_t result = _summary_bytes_used;
+    size_t result = 0;
 
     // Read only once in case it is set to NULL concurrently
     HeapRegion* hr = mutator_alloc_region(AllocationContext::current())->get();
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp	Fri Jul 31 10:15:02 2015 -0700
@@ -632,7 +632,7 @@
   check_bitmaps("Humongous Region Allocation", first_hr);
 
   assert(first_hr->used() == word_size * HeapWordSize, "invariant");
-  _allocator->increase_used(first_hr->used());
+  increase_used(first_hr->used());
   _humongous_set.add(first_hr);
 
   return new_obj;
@@ -998,7 +998,7 @@
     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);
+        increase_used(word_size * HeapWordSize);
         start_region->set_top(last_address + 1);
         continue;
       }
@@ -1012,7 +1012,7 @@
     if (!_hrm.allocate_containing_regions(curr_range, &commits)) {
       return false;
     }
-    _allocator->increase_used(word_size * HeapWordSize);
+    increase_used(word_size * HeapWordSize);
     if (commits != 0) {
       ergo_verbose1(ErgoHeapSizing,
                     "attempt heap expansion",
@@ -1104,7 +1104,7 @@
     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);
+      increase_used(fill_size * HeapWordSize);
     }
   }
 }
@@ -1917,7 +1917,6 @@
   _ref_processor_cm(NULL),
   _ref_processor_stw(NULL),
   _bot_shared(NULL),
-  _evac_failure_scan_stack(NULL),
   _cg1r(NULL),
   _g1mm(NULL),
   _refine_cte_cl(NULL),
@@ -1930,6 +1929,7 @@
   _free_regions_coming(false),
   _young_list(new YoungList(this)),
   _gc_time_stamp(0),
+  _summary_bytes_used(0),
   _survivor_plab_stats(YoungPLABSize, PLABWeight),
   _old_plab_stats(OldPLABSize, PLABWeight),
   _expand_heap_after_alloc_failure(true),
@@ -2204,6 +2204,11 @@
 
   G1StringDedup::initialize();
 
+  _preserved_objs = NEW_C_HEAP_ARRAY(OopAndMarkOopStack, ParallelGCThreads, mtGC);
+  for (uint i = 0; i < ParallelGCThreads; i++) {
+    new (&_preserved_objs[i]) OopAndMarkOopStack();
+  }
+
   return JNI_OK;
 }
 
@@ -2371,7 +2376,7 @@
 
 // Computes the sum of the storage used by the various regions.
 size_t G1CollectedHeap::used() const {
-  size_t result = _allocator->used();
+  size_t result = _summary_bytes_used + _allocator->used_in_alloc_regions();
   if (_archive_allocator != NULL) {
     result += _archive_allocator->used();
   }
@@ -2379,7 +2384,7 @@
 }
 
 size_t G1CollectedHeap::used_unlocked() const {
-  return _allocator->used_unlocked();
+  return _summary_bytes_used;
 }
 
 class SumUsedClosure: public HeapRegionClosure {
@@ -3376,7 +3381,7 @@
 
   // Print the per-region information.
   st->cr();
-  st->print_cr("Heap Regions: (Y=young(eden), SU=young(survivor), "
+  st->print_cr("Heap Regions: (E=young(eden), S=young(survivor), O=old, "
                "HS=humongous(starts), HC=humongous(continues), "
                "CS=collection set, F=free, A=archive, TS=gc time stamp, "
                "PTAMS=previous top-at-mark-start, "
@@ -4102,7 +4107,7 @@
         _young_list->reset_auxilary_lists();
 
         if (evacuation_failed()) {
-          _allocator->set_used(recalculate_used());
+          set_used(recalculate_used());
           if (_archive_allocator != NULL) {
             _archive_allocator->clear_used();
           }
@@ -4114,7 +4119,7 @@
         } else {
           // The "used" of the the collection set have already been subtracted
           // when they were freed.  Add in the bytes evacuated.
-          _allocator->increase_used(g1_policy()->bytes_copied_during_gc());
+          increase_used(g1_policy()->bytes_copied_during_gc());
         }
 
         if (collector_state()->during_initial_mark_pause()) {
@@ -4255,21 +4260,6 @@
   return true;
 }
 
-void G1CollectedHeap::init_for_evac_failure(OopsInHeapRegionClosure* cl) {
-  _drain_in_progress = false;
-  set_evac_failure_closure(cl);
-  _evac_failure_scan_stack = new (ResourceObj::C_HEAP, mtGC) GrowableArray<oop>(40, true);
-}
-
-void G1CollectedHeap::finalize_for_evac_failure() {
-  assert(_evac_failure_scan_stack != NULL &&
-         _evac_failure_scan_stack->length() == 0,
-         "Postcondition");
-  assert(!_drain_in_progress, "Postcondition");
-  delete _evac_failure_scan_stack;
-  _evac_failure_scan_stack = NULL;
-}
-
 void G1CollectedHeap::remove_self_forwarding_pointers() {
   double remove_self_forwards_start = os::elapsedTime();
 
@@ -4277,104 +4267,30 @@
   workers()->run_task(&rsfp_task);
 
   // Now restore saved marks, if any.
-  assert(_objs_with_preserved_marks.size() ==
-            _preserved_marks_of_objs.size(), "Both or none.");
-  while (!_objs_with_preserved_marks.is_empty()) {
-    oop obj = _objs_with_preserved_marks.pop();
-    markOop m = _preserved_marks_of_objs.pop();
-    obj->set_mark(m);
-  }
-  _objs_with_preserved_marks.clear(true);
-  _preserved_marks_of_objs.clear(true);
+  for (uint i = 0; i < ParallelGCThreads; i++) {
+    OopAndMarkOopStack& cur = _preserved_objs[i];
+    while (!cur.is_empty()) {
+      OopAndMarkOop elem = cur.pop();
+      elem.set_mark();
+    }
+    cur.clear(true);
+  }
 
   g1_policy()->phase_times()->record_evac_fail_remove_self_forwards((os::elapsedTime() - remove_self_forwards_start) * 1000.0);
 }
 
-void G1CollectedHeap::push_on_evac_failure_scan_stack(oop obj) {
-  _evac_failure_scan_stack->push(obj);
-}
-
-void G1CollectedHeap::drain_evac_failure_scan_stack() {
-  assert(_evac_failure_scan_stack != NULL, "precondition");
-
-  while (_evac_failure_scan_stack->length() > 0) {
-     oop obj = _evac_failure_scan_stack->pop();
-     _evac_failure_closure->set_region(heap_region_containing(obj));
-     obj->oop_iterate_backwards(_evac_failure_closure);
-  }
-}
-
-oop
-G1CollectedHeap::handle_evacuation_failure_par(G1ParScanThreadState* _par_scan_state,
-                                               oop old) {
-  assert(obj_in_cs(old),
-         err_msg("obj: " PTR_FORMAT " should still be in the CSet",
-                 p2i(old)));
-  markOop m = old->mark();
-  oop forward_ptr = old->forward_to_atomic(old);
-  if (forward_ptr == NULL) {
-    // Forward-to-self succeeded.
-    assert(_par_scan_state != NULL, "par scan state");
-    OopsInHeapRegionClosure* cl = _par_scan_state->evac_failure_closure();
-    uint queue_num = _par_scan_state->queue_num();
-
+void G1CollectedHeap::preserve_mark_during_evac_failure(uint queue_num, oop obj, markOop m) {
+  if (!_evacuation_failed) {
     _evacuation_failed = true;
-    _evacuation_failed_info_array[queue_num].register_copy_failure(old->size());
-    if (_evac_failure_closure != cl) {
-      MutexLockerEx x(EvacFailureStack_lock, Mutex::_no_safepoint_check_flag);
-      assert(!_drain_in_progress,
-             "Should only be true while someone holds the lock.");
-      // Set the global evac-failure closure to the current thread's.
-      assert(_evac_failure_closure == NULL, "Or locking has failed.");
-      set_evac_failure_closure(cl);
-      // Now do the common part.
-      handle_evacuation_failure_common(old, m);
-      // Reset to NULL.
-      set_evac_failure_closure(NULL);
-    } else {
-      // The lock is already held, and this is recursive.
-      assert(_drain_in_progress, "This should only be the recursive case.");
-      handle_evacuation_failure_common(old, m);
-    }
-    return old;
-  } else {
-    // Forward-to-self failed. Either someone else managed to allocate
-    // space for this object (old != forward_ptr) or they beat us in
-    // self-forwarding it (old == forward_ptr).
-    assert(old == forward_ptr || !obj_in_cs(forward_ptr),
-           err_msg("obj: " PTR_FORMAT " forwarded to: " PTR_FORMAT " "
-                   "should not be in the CSet",
-                   p2i(old), p2i(forward_ptr)));
-    return forward_ptr;
-  }
-}
-
-void G1CollectedHeap::handle_evacuation_failure_common(oop old, markOop m) {
-  preserve_mark_if_necessary(old, m);
-
-  HeapRegion* r = heap_region_containing(old);
-  if (!r->evacuation_failed()) {
-    r->set_evacuation_failed(true);
-    _hr_printer.evac_failure(r);
-  }
-
-  push_on_evac_failure_scan_stack(old);
-
-  if (!_drain_in_progress) {
-    // prevent recursion in copy_to_survivor_space()
-    _drain_in_progress = true;
-    drain_evac_failure_scan_stack();
-    _drain_in_progress = false;
-  }
-}
-
-void G1CollectedHeap::preserve_mark_if_necessary(oop obj, markOop m) {
-  assert(evacuation_failed(), "Oversaving!");
+  }
+
+  _evacuation_failed_info_array[queue_num].register_copy_failure(obj->size());
+
   // We want to call the "for_promotion_failure" version only in the
   // case of a promotion failure.
   if (m->must_be_preserved_for_promotion_failure(obj)) {
-    _objs_with_preserved_marks.push(obj);
-    _preserved_marks_of_objs.push(m);
+    OopAndMarkOop elem(obj, m);
+    _preserved_objs[queue_num].push(elem);
   }
 }
 
@@ -4450,14 +4366,7 @@
       mark_object(obj);
     }
   }
-
-  if (barrier == G1BarrierEvac) {
-    _par_scan_state->update_rs(_from, p, _worker_id);
-  }
-}
-
-template void G1ParCopyClosure<G1BarrierEvac, G1MarkNone>::do_oop_work(oop* p);
-template void G1ParCopyClosure<G1BarrierEvac, G1MarkNone>::do_oop_work(narrowOop* p);
+}
 
 class G1ParEvacuateFollowersClosure : public VoidClosure {
 protected:
@@ -4597,9 +4506,6 @@
       ReferenceProcessor*             rp = _g1h->ref_processor_stw();
 
       G1ParScanThreadState            pss(_g1h, worker_id, rp);
-      G1ParScanHeapEvacFailureClosure evac_failure_cl(_g1h, &pss, rp);
-
-      pss.set_evac_failure_closure(&evac_failure_cl);
 
       bool only_young = _g1h->collector_state()->gcs_are_young();
 
@@ -5269,9 +5175,6 @@
     G1STWIsAliveClosure is_alive(_g1h);
 
     G1ParScanThreadState            pss(_g1h, worker_id, NULL);
-    G1ParScanHeapEvacFailureClosure evac_failure_cl(_g1h, &pss, NULL);
-
-    pss.set_evac_failure_closure(&evac_failure_cl);
 
     G1ParScanExtRootClosure        only_copy_non_heap_cl(_g1h, &pss, NULL);
 
@@ -5368,10 +5271,6 @@
     HandleMark   hm;
 
     G1ParScanThreadState            pss(_g1h, worker_id, NULL);
-    G1ParScanHeapEvacFailureClosure evac_failure_cl(_g1h, &pss, NULL);
-
-    pss.set_evac_failure_closure(&evac_failure_cl);
-
     assert(pss.queue_is_empty(), "both queue and overflow should be empty");
 
     G1ParScanExtRootClosure        only_copy_non_heap_cl(_g1h, &pss, NULL);
@@ -5476,15 +5375,11 @@
 
   // Use only a single queue for this PSS.
   G1ParScanThreadState            pss(this, 0, NULL);
+  assert(pss.queue_is_empty(), "pre-condition");
 
   // We do not embed a reference processor in the copying/scanning
   // closures while we're actually processing the discovered
   // reference objects.
-  G1ParScanHeapEvacFailureClosure evac_failure_cl(this, &pss, NULL);
-
-  pss.set_evac_failure_closure(&evac_failure_cl);
-
-  assert(pss.queue_is_empty(), "pre-condition");
 
   G1ParScanExtRootClosure        only_copy_non_heap_cl(this, &pss, NULL);
 
@@ -5590,8 +5485,6 @@
 
   const uint n_workers = workers()->active_workers();
 
-  init_for_evac_failure(NULL);
-
   assert(dirty_card_queue_set().completed_buffers_num() == 0, "Should be empty");
   double start_par_time_sec = os::elapsedTime();
   double end_par_time_sec;
@@ -5655,8 +5548,6 @@
 
   purge_code_root_memory();
 
-  finalize_for_evac_failure();
-
   if (evacuation_failed()) {
     remove_self_forwarding_pointers();
 
@@ -5745,7 +5636,7 @@
 }
 
 void G1CollectedHeap::decrement_summary_bytes(size_t bytes) {
-  _allocator->decrease_used(bytes);
+  decrease_used(bytes);
 }
 
 class G1ParCleanupCTTask : public AbstractGangTask {
@@ -6395,6 +6286,21 @@
   _hrm.remove_all_free_regions();
 }
 
+void G1CollectedHeap::increase_used(size_t bytes) {
+  _summary_bytes_used += bytes;
+}
+
+void G1CollectedHeap::decrease_used(size_t bytes) {
+  assert(_summary_bytes_used >= bytes,
+         err_msg("invariant: _summary_bytes_used: " SIZE_FORMAT " should be >= bytes: " SIZE_FORMAT,
+                 _summary_bytes_used, bytes));
+  _summary_bytes_used -= bytes;
+}
+
+void G1CollectedHeap::set_used(size_t bytes) {
+  _summary_bytes_used = bytes;
+}
+
 class RebuildRegionSetsClosure : public HeapRegionClosure {
 private:
   bool            _free_list_only;
@@ -6463,15 +6369,15 @@
   heap_region_iterate(&cl);
 
   if (!free_list_only) {
-    _allocator->set_used(cl.total_used());
+    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(), "
+  assert(used_unlocked() == recalculate_used(),
+         err_msg("inconsistent used_unlocked(), "
                  "value: " SIZE_FORMAT " recalculated: " SIZE_FORMAT,
-                 _allocator->used_unlocked(), recalculate_used()));
+                 used_unlocked(), recalculate_used()));
 }
 
 void G1CollectedHeap::set_refine_cte_cl_concurrency(bool concurrent) {
@@ -6511,7 +6417,7 @@
   assert(alloc_region->is_eden(), "all mutator alloc regions should be eden");
 
   g1_policy()->add_region_to_incremental_cset_lhs(alloc_region);
-  _allocator->increase_used(allocated_bytes);
+  increase_used(allocated_bytes);
   _hr_printer.retire(alloc_region);
   // We update the eden sizes here, when the region is retired,
   // instead of when it's allocated, since this is the point that its
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp	Fri Jul 31 10:15:02 2015 -0700
@@ -251,6 +251,15 @@
   // Class that handles the different kinds of allocations.
   G1Allocator* _allocator;
 
+  // Outside of GC pauses, the number of bytes used in all regions other
+  // than the current allocation region(s).
+  size_t _summary_bytes_used;
+
+  void increase_used(size_t bytes);
+  void decrease_used(size_t bytes);
+
+  void set_used(size_t bytes);
+
   // Class that handles archive allocation ranges.
   G1ArchiveAllocator* _archive_allocator;
 
@@ -858,44 +867,27 @@
   // forwarding pointers to themselves.  Reset them.
   void remove_self_forwarding_pointers();
 
-  // Together, these store an object with a preserved mark, and its mark value.
-  Stack<oop, mtGC>     _objs_with_preserved_marks;
-  Stack<markOop, mtGC> _preserved_marks_of_objs;
+  struct OopAndMarkOop {
+   private:
+    oop _o;
+    markOop _m;
+   public:
+    OopAndMarkOop(oop obj, markOop m) : _o(obj), _m(m) {
+    }
+
+    void set_mark() {
+      _o->set_mark(_m);
+    }
+  };
+
+  typedef Stack<OopAndMarkOop,mtGC> OopAndMarkOopStack;
+  // Stores marks with the corresponding oop that we need to preserve during evacuation
+  // failure.
+  OopAndMarkOopStack*  _preserved_objs;
 
   // Preserve the mark of "obj", if necessary, in preparation for its mark
   // word being overwritten with a self-forwarding-pointer.
-  void preserve_mark_if_necessary(oop obj, markOop m);
-
-  // The stack of evac-failure objects left to be scanned.
-  GrowableArray<oop>*    _evac_failure_scan_stack;
-  // The closure to apply to evac-failure objects.
-
-  OopsInHeapRegionClosure* _evac_failure_closure;
-  // Set the field above.
-  void
-  set_evac_failure_closure(OopsInHeapRegionClosure* evac_failure_closure) {
-    _evac_failure_closure = evac_failure_closure;
-  }
-
-  // Push "obj" on the scan stack.
-  void push_on_evac_failure_scan_stack(oop obj);
-  // Process scan stack entries until the stack is empty.
-  void drain_evac_failure_scan_stack();
-  // True iff an invocation of "drain_scan_stack" is in progress; to
-  // prevent unnecessary recursion.
-  bool _drain_in_progress;
-
-  // Do any necessary initialization for evacuation-failure handling.
-  // "cl" is the closure that will be used to process evac-failure
-  // objects.
-  void init_for_evac_failure(OopsInHeapRegionClosure* cl);
-  // Do any necessary cleanup for evacuation-failure handling data
-  // structures.
-  void finalize_for_evac_failure();
-
-  // An attempt to evacuate "obj" has failed; take necessary steps.
-  oop handle_evacuation_failure_par(G1ParScanThreadState* _par_scan_state, oop obj);
-  void handle_evacuation_failure_common(oop obj, markOop m);
+  void preserve_mark_during_evac_failure(uint queue, oop obj, markOop m);
 
 #ifndef PRODUCT
   // Support for forcing evacuation failures. Analogous to
--- a/hotspot/src/share/vm/gc/g1/g1OopClosures.hpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1OopClosures.hpp	Fri Jul 31 10:15:02 2015 -0700
@@ -111,7 +111,6 @@
 
 enum G1Barrier {
   G1BarrierNone,
-  G1BarrierEvac,
   G1BarrierKlass
 };
 
@@ -148,8 +147,6 @@
 // We use a separate closure to handle references during evacuation
 // failure processing.
 
-typedef G1ParCopyClosure<G1BarrierEvac, G1MarkNone> G1ParScanHeapEvacFailureClosure;
-
 class FilterIntoCSClosure: public ExtendedOopClosure {
   G1CollectedHeap* _g1;
   OopClosure* _oc;
--- a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp	Fri Jul 31 10:15:02 2015 -0700
@@ -144,8 +144,6 @@
 #endif // ASSERT
 
 void G1ParScanThreadState::trim_queue() {
-  assert(_evac_failure_cl != NULL, "not set");
-
   StarTask ref;
   do {
     // Drain the overflow stack first, so other threads can steal.
@@ -222,7 +220,7 @@
       if (obj_ptr == NULL) {
         // This will either forward-to-self, or detect that someone else has
         // installed a forwarding pointer.
-        return _g1h->handle_evacuation_failure_par(this, old);
+        return handle_evacuation_failure_par(old, old_mark);
       }
     }
   }
@@ -236,7 +234,7 @@
     // Doing this after all the allocation attempts also tests the
     // undo_allocation() method too.
     _g1_par_allocator->undo_allocation(dest_state, obj_ptr, word_sz, context);
-    return _g1h->handle_evacuation_failure_par(this, old);
+    return handle_evacuation_failure_par(old, old_mark);
   }
 #endif // !PRODUCT
 
@@ -301,3 +299,36 @@
     return forward_ptr;
   }
 }
+
+oop G1ParScanThreadState::handle_evacuation_failure_par(oop old, markOop m) {
+  assert(_g1h->obj_in_cs(old),
+         err_msg("Object " PTR_FORMAT " should be in the CSet", p2i(old)));
+
+  oop forward_ptr = old->forward_to_atomic(old);
+  if (forward_ptr == NULL) {
+    // Forward-to-self succeeded. We are the "owner" of the object.
+    HeapRegion* r = _g1h->heap_region_containing(old);
+
+    if (!r->evacuation_failed()) {
+      r->set_evacuation_failed(true);
+     _g1h->hr_printer()->evac_failure(r);
+    }
+
+    _g1h->preserve_mark_during_evac_failure(_queue_num, old, m);
+
+    _scanner.set_region(r);
+    old->oop_iterate_backwards(&_scanner);
+
+    return old;
+  } else {
+    // Forward-to-self failed. Either someone else managed to allocate
+    // space for this object (old != forward_ptr) or they beat us in
+    // self-forwarding it (old == forward_ptr).
+    assert(old == forward_ptr || !_g1h->obj_in_cs(forward_ptr),
+           err_msg("Object " PTR_FORMAT " forwarded to: " PTR_FORMAT " "
+                   "should not be in the CSet",
+                   p2i(old), p2i(forward_ptr)));
+    return forward_ptr;
+  }
+}
+
--- a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.hpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.hpp	Fri Jul 31 10:15:02 2015 -0700
@@ -54,8 +54,6 @@
   uint              _tenuring_threshold;
   G1ParScanClosure  _scanner;
 
-  OopsInHeapRegionClosure*      _evac_failure_cl;
-
   int  _hash_seed;
   uint _queue_num;
 
@@ -114,12 +112,6 @@
     }
   }
 
-  void set_evac_failure_closure(OopsInHeapRegionClosure* evac_failure_cl) {
-    _evac_failure_cl = evac_failure_cl;
-  }
-
-  OopsInHeapRegionClosure* evac_failure_closure() { return _evac_failure_cl; }
-
   int* hash_seed() { return &_hash_seed; }
   uint queue_num() { return _queue_num; }
 
@@ -211,6 +203,9 @@
   void trim_queue();
 
   inline void steal_and_trim_queue(RefToScanQueueSet *task_queues);
+
+  // An attempt to evacuate "obj" has failed; take necessary steps.
+  oop handle_evacuation_failure_par(oop obj, markOop m);
 };
 
 #endif // SHARE_VM_GC_G1_G1PARSCANTHREADSTATE_HPP
--- a/hotspot/src/share/vm/gc/g1/g1_globals.hpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1_globals.hpp	Fri Jul 31 10:15:02 2015 -0700
@@ -252,12 +252,12 @@
           "Percentage (0-100) of the heap size to use as default "          \
           " maximum young gen size.")                                       \
           range(0, 100)                                                     \
-          constraint(G1MaxNewSizePercentConstraintFunc)                     \
+          constraint(G1MaxNewSizePercentConstraintFunc,AfterErgo)           \
                                                                             \
   experimental(uintx, G1NewSizePercent, 5,                                  \
           "Percentage (0-100) of the heap size to use as default "          \
           "minimum young gen size.")                                        \
-          constraint(G1NewSizePercentConstraintFunc)                        \
+          constraint(G1NewSizePercentConstraintFunc,AfterErgo)              \
                                                                             \
   experimental(uintx, G1MixedGCLiveThresholdPercent, 85,                    \
           "Threshold for regions to be considered for inclusion in the "    \
--- a/hotspot/src/share/vm/gc/g1/vmStructs_g1.hpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/gc/g1/vmStructs_g1.hpp	Fri Jul 31 10:15:02 2015 -0700
@@ -45,13 +45,11 @@
   nonstatic_field(HeapRegionManager, _regions,          G1HeapRegionTable)    \
   nonstatic_field(HeapRegionManager, _num_committed,    uint)                 \
                                                                               \
-  nonstatic_field(G1Allocator,     _summary_bytes_used, size_t)               \
-                                                                              \
+  nonstatic_field(G1CollectedHeap, _summary_bytes_used, size_t)               \
   nonstatic_field(G1CollectedHeap, _hrm,                HeapRegionManager)    \
   nonstatic_field(G1CollectedHeap, _g1mm,               G1MonitoringSupport*) \
   nonstatic_field(G1CollectedHeap, _old_set,            HeapRegionSetBase)    \
   nonstatic_field(G1CollectedHeap, _humongous_set,      HeapRegionSetBase)    \
-  nonstatic_field(G1CollectedHeap, _allocator,          G1Allocator*)         \
                                                                               \
   nonstatic_field(G1MonitoringSupport, _eden_committed,     size_t)           \
   nonstatic_field(G1MonitoringSupport, _eden_used,          size_t)           \
@@ -78,12 +76,10 @@
   declare_toplevel_type(HeapRegionSetBase)                                    \
   declare_toplevel_type(HeapRegionSetCount)                                   \
   declare_toplevel_type(G1MonitoringSupport)                                  \
-  declare_toplevel_type(G1Allocator)                                          \
                                                                               \
   declare_toplevel_type(G1CollectedHeap*)                                     \
   declare_toplevel_type(HeapRegion*)                                          \
   declare_toplevel_type(G1MonitoringSupport*)                                 \
-  declare_toplevel_type(G1Allocator*)                                         \
 
 
 #endif // SHARE_VM_GC_G1_VMSTRUCTS_G1_HPP
--- a/hotspot/src/share/vm/gc/parallel/cardTableExtension.cpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/gc/parallel/cardTableExtension.cpp	Fri Jul 31 10:15:02 2015 -0700
@@ -40,7 +40,6 @@
   PSYoungGen*         _young_gen;
   CardTableExtension* _card_table;
   HeapWord*           _unmarked_addr;
-  jbyte*              _unmarked_card;
 
  protected:
   template <class T> void do_oop_work(T* p) {
@@ -50,7 +49,6 @@
       // Don't overwrite the first missing card mark
       if (_unmarked_addr == NULL) {
         _unmarked_addr = (HeapWord*)p;
-        _unmarked_card = _card_table->byte_for(p);
       }
     }
   }
--- a/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp	Fri Jul 31 10:15:02 2015 -0700
@@ -623,7 +623,7 @@
   {
     // DefNew needs to run with n_threads == 0, to make sure the serial
     // version of the card table scanning code is used.
-    // See: CardTableModRefBS::non_clean_card_iterate_possibly_parallel.
+    // See: CardTableModRefBSForCTRS::non_clean_card_iterate_possibly_parallel.
     StrongRootsScope srs(0);
 
     gch->gen_process_roots(&srs,
--- a/hotspot/src/share/vm/gc/shared/cardTableModRefBS.cpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/gc/shared/cardTableModRefBS.cpp	Fri Jul 31 10:15:02 2015 -0700
@@ -24,22 +24,12 @@
 
 #include "precompiled.hpp"
 #include "gc/shared/cardTableModRefBS.inline.hpp"
-#include "gc/shared/cardTableRS.hpp"
 #include "gc/shared/collectedHeap.hpp"
 #include "gc/shared/genCollectedHeap.hpp"
-#include "gc/shared/space.hpp"
 #include "gc/shared/space.inline.hpp"
-#include "memory/allocation.inline.hpp"
-#include "memory/universe.hpp"
 #include "memory/virtualspace.hpp"
-#include "runtime/java.hpp"
-#include "runtime/mutexLocker.hpp"
 #include "services/memTracker.hpp"
 #include "utilities/macros.hpp"
-#ifdef COMPILER1
-#include "c1/c1_LIR.hpp"
-#include "c1/c1_LIRGenerator.hpp"
-#endif
 
 // This kind of "BarrierSet" allows a "CollectedHeap" to detect and
 // enumerate ref fields that have been modified (since the last
@@ -68,12 +58,7 @@
   _committed(NULL),
   _cur_covered_regions(0),
   _byte_map(NULL),
-  byte_map_base(NULL),
-  // LNC functionality
-  _lowest_non_clean(NULL),
-  _lowest_non_clean_chunk_size(NULL),
-  _lowest_non_clean_base_chunk_index(NULL),
-  _last_LNC_resizing_collection(NULL)
+  byte_map_base(NULL)
 {
   assert((uintptr_t(_whole_heap.start())  & (card_size - 1))  == 0, "heap must start at card boundary");
   assert((uintptr_t(_whole_heap.end()) & (card_size - 1))  == 0, "heap must end at card boundary");
@@ -130,25 +115,6 @@
                             !ExecMem, "card table last card");
   *guard_card = last_card;
 
-  _lowest_non_clean =
-    NEW_C_HEAP_ARRAY(CardArr, _max_covered_regions, mtGC);
-  _lowest_non_clean_chunk_size =
-    NEW_C_HEAP_ARRAY(size_t, _max_covered_regions, mtGC);
-  _lowest_non_clean_base_chunk_index =
-    NEW_C_HEAP_ARRAY(uintptr_t, _max_covered_regions, mtGC);
-  _last_LNC_resizing_collection =
-    NEW_C_HEAP_ARRAY(int, _max_covered_regions, mtGC);
-  if (_lowest_non_clean == NULL
-      || _lowest_non_clean_chunk_size == NULL
-      || _lowest_non_clean_base_chunk_index == NULL
-      || _last_LNC_resizing_collection == NULL)
-    vm_exit_during_initialization("couldn't allocate an LNC array.");
-  for (int i = 0; i < _max_covered_regions; i++) {
-    _lowest_non_clean[i] = NULL;
-    _lowest_non_clean_chunk_size[i] = 0;
-    _last_LNC_resizing_collection[i] = -1;
-  }
-
   if (TraceCardTableModRefBS) {
     gclog_or_tty->print_cr("CardTableModRefBS::CardTableModRefBS: ");
     gclog_or_tty->print_cr("  "
@@ -171,22 +137,6 @@
     delete[] _committed;
     _committed = NULL;
   }
-  if (_lowest_non_clean) {
-    FREE_C_HEAP_ARRAY(CardArr, _lowest_non_clean);
-    _lowest_non_clean = NULL;
-  }
-  if (_lowest_non_clean_chunk_size) {
-    FREE_C_HEAP_ARRAY(size_t, _lowest_non_clean_chunk_size);
-    _lowest_non_clean_chunk_size = NULL;
-  }
-  if (_lowest_non_clean_base_chunk_index) {
-    FREE_C_HEAP_ARRAY(uintptr_t, _lowest_non_clean_base_chunk_index);
-    _lowest_non_clean_base_chunk_index = NULL;
-  }
-  if (_last_LNC_resizing_collection) {
-    FREE_C_HEAP_ARRAY(int, _last_LNC_resizing_collection);
-    _last_LNC_resizing_collection = NULL;
-  }
 }
 
 int CardTableModRefBS::find_covering_region_by_base(HeapWord* base) {
@@ -437,32 +387,6 @@
 }
 
 
-void CardTableModRefBS::non_clean_card_iterate_possibly_parallel(Space* sp,
-                                                                 MemRegion mr,
-                                                                 OopsInGenClosure* cl,
-                                                                 CardTableRS* ct,
-                                                                 uint n_threads) {
-  if (!mr.is_empty()) {
-    if (n_threads > 0) {
-#if INCLUDE_ALL_GCS
-      non_clean_card_iterate_parallel_work(sp, mr, cl, ct, n_threads);
-#else  // INCLUDE_ALL_GCS
-      fatal("Parallel gc not supported here.");
-#endif // INCLUDE_ALL_GCS
-    } else {
-      // clear_cl finds contiguous dirty ranges of cards to process and clear.
-
-      // This is the single-threaded version used by DefNew.
-      const bool parallel = false;
-
-      DirtyCardToOopClosure* dcto_cl = sp->new_dcto_cl(cl, precision(), cl->gen_boundary(), parallel);
-      ClearNoncleanCardWrapper clear_cl(dcto_cl, ct, parallel);
-
-      clear_cl.do_MemRegion(mr);
-    }
-  }
-}
-
 void CardTableModRefBS::dirty_MemRegion(MemRegion mr) {
   assert((HeapWord*)align_size_down((uintptr_t)mr.start(), HeapWordSize) == mr.start(), "Unaligned start");
   assert((HeapWord*)align_size_up  ((uintptr_t)mr.end(),   HeapWordSize) == mr.end(),   "Unaligned end"  );
@@ -623,15 +547,3 @@
                p2i(_byte_map), p2i(_byte_map + _byte_map_size), p2i(byte_map_base));
 }
 
-bool CardTableModRefBSForCTRS::card_will_be_scanned(jbyte cv) {
-  return
-    CardTableModRefBS::card_will_be_scanned(cv) ||
-    _rs->is_prev_nonclean_card_val(cv);
-};
-
-bool CardTableModRefBSForCTRS::card_may_have_been_dirty(jbyte cv) {
-  return
-    cv != clean_card &&
-    (CardTableModRefBS::card_may_have_been_dirty(cv) ||
-     CardTableRS::youngergen_may_have_been_dirty(cv));
-};
--- a/hotspot/src/share/vm/gc/shared/cardTableModRefBS.hpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/gc/shared/cardTableModRefBS.hpp	Fri Jul 31 10:15:02 2015 -0700
@@ -40,23 +40,9 @@
 // Closures used to scan dirty cards should take these
 // considerations into account.
 
-class Generation;
-class OopsInGenClosure;
-class DirtyCardToOopClosure;
-class ClearNoncleanCardWrapper;
-class CardTableRS;
-
 class CardTableModRefBS: public ModRefBarrierSet {
   // Some classes get to look at some private stuff.
-  friend class BytecodeInterpreter;
   friend class VMStructs;
-  friend class CardTableRS;
-  friend class CheckForUnmarkedOops; // Needs access to raw card bytes.
-  friend class SharkBuilder;
-#ifndef PRODUCT
-  // For debugging.
-  friend class GuaranteeNotModClosure;
-#endif
  protected:
 
   enum CardValues {
@@ -75,24 +61,6 @@
   // a word's worth (row) of clean card values
   static const intptr_t clean_card_row = (intptr_t)(-1);
 
-  // dirty and precleaned are equivalent wrt younger_refs_iter.
-  static bool card_is_dirty_wrt_gen_iter(jbyte cv) {
-    return cv == dirty_card || cv == precleaned_card;
-  }
-
-  // Returns "true" iff the value "cv" will cause the card containing it
-  // to be scanned in the current traversal.  May be overridden by
-  // subtypes.
-  virtual bool card_will_be_scanned(jbyte cv) {
-    return CardTableModRefBS::card_is_dirty_wrt_gen_iter(cv);
-  }
-
-  // Returns "true" iff the value "cv" may have represented a dirty card at
-  // some point.
-  virtual bool card_may_have_been_dirty(jbyte cv) {
-    return card_is_dirty_wrt_gen_iter(cv);
-  }
-
   // The declaration order of these const fields is important; see the
   // constructor before changing.
   const MemRegion _whole_heap;       // the region covered by the card table
@@ -174,20 +142,6 @@
     return byte_for(p) + 1;
   }
 
-  // Iterate over the portion of the card-table which covers the given
-  // region mr in the given space and apply cl to any dirty sub-regions
-  // of mr. Clears the dirty cards as they are processed.
-  void non_clean_card_iterate_possibly_parallel(Space* sp, MemRegion mr,
-                                                OopsInGenClosure* cl, CardTableRS* ct,
-                                                uint n_threads);
-
- private:
-  // Work method used to implement non_clean_card_iterate_possibly_parallel()
-  // above in the parallel case.
-  void non_clean_card_iterate_parallel_work(Space* sp, MemRegion mr,
-                                            OopsInGenClosure* cl, CardTableRS* ct,
-                                            uint n_threads);
-
  protected:
   // Dirty the bytes corresponding to "mr" (not all of which must be
   // covered.)
@@ -197,65 +151,6 @@
   // all of which must be covered.)
   void clear_MemRegion(MemRegion mr);
 
-  // *** Support for parallel card scanning.
-
-  // This is an array, one element per covered region of the card table.
-  // Each entry is itself an array, with one element per chunk in the
-  // covered region.  Each entry of these arrays is the lowest non-clean
-  // card of the corresponding chunk containing part of an object from the
-  // previous chunk, or else NULL.
-  typedef jbyte*  CardPtr;
-  typedef CardPtr* CardArr;
-  CardArr* _lowest_non_clean;
-  size_t*  _lowest_non_clean_chunk_size;
-  uintptr_t* _lowest_non_clean_base_chunk_index;
-  int* _last_LNC_resizing_collection;
-
-  // Initializes "lowest_non_clean" to point to the array for the region
-  // covering "sp", and "lowest_non_clean_base_chunk_index" to the chunk
-  // index of the corresponding to the first element of that array.
-  // Ensures that these arrays are of sufficient size, allocating if necessary.
-  // May be called by several threads concurrently.
-  void get_LNC_array_for_space(Space* sp,
-                               jbyte**& lowest_non_clean,
-                               uintptr_t& lowest_non_clean_base_chunk_index,
-                               size_t& lowest_non_clean_chunk_size);
-
-  // Returns the number of chunks necessary to cover "mr".
-  size_t chunks_to_cover(MemRegion mr) {
-    return (size_t)(addr_to_chunk_index(mr.last()) -
-                    addr_to_chunk_index(mr.start()) + 1);
-  }
-
-  // Returns the index of the chunk in a stride which
-  // covers the given address.
-  uintptr_t addr_to_chunk_index(const void* addr) {
-    uintptr_t card = (uintptr_t) byte_for(addr);
-    return card / ParGCCardsPerStrideChunk;
-  }
-
-  // Apply cl, which must either itself apply dcto_cl or be dcto_cl,
-  // to the cards in the stride (of n_strides) within the given space.
-  void process_stride(Space* sp,
-                      MemRegion used,
-                      jint stride, int n_strides,
-                      OopsInGenClosure* cl,
-                      CardTableRS* ct,
-                      jbyte** lowest_non_clean,
-                      uintptr_t lowest_non_clean_base_chunk_index,
-                      size_t lowest_non_clean_chunk_size);
-
-  // Makes sure that chunk boundaries are handled appropriately, by
-  // adjusting the min_done of dcto_cl, and by using a special card-table
-  // value to indicate how min_done should be set.
-  void process_chunk_boundaries(Space* sp,
-                                DirtyCardToOopClosure* dcto_cl,
-                                MemRegion chunk_mr,
-                                MemRegion used,
-                                jbyte** lowest_non_clean,
-                                uintptr_t lowest_non_clean_base_chunk_index,
-                                size_t    lowest_non_clean_chunk_size);
-
 public:
   // Constants
   enum SomePublicConstants {
@@ -436,34 +331,5 @@
   static const BarrierSet::Name value = BarrierSet::CardTableModRef;
 };
 
-class CardTableRS;
-
-// A specialization for the CardTableRS gen rem set.
-class CardTableModRefBSForCTRS: public CardTableModRefBS {
-  CardTableRS* _rs;
-protected:
-  bool card_will_be_scanned(jbyte cv);
-  bool card_may_have_been_dirty(jbyte cv);
-public:
-  CardTableModRefBSForCTRS(MemRegion whole_heap) :
-    CardTableModRefBS(
-      whole_heap,
-      // Concrete tag should be BarrierSet::CardTableForRS.
-      // That will presently break things in a bunch of places though.
-      // The concrete tag is used as a dispatch key in many places, and
-      // CardTableForRS does not correctly dispatch in some of those
-      // uses. This will be addressed as part of a reorganization of the
-      // BarrierSet hierarchy.
-      BarrierSet::FakeRtti(BarrierSet::CardTableModRef, 0).add_tag(BarrierSet::CardTableForRS))
-    {}
-
-  void set_CTRS(CardTableRS* rs) { _rs = rs; }
-};
-
-template<>
-struct BarrierSet::GetName<CardTableModRefBSForCTRS> {
-  static const BarrierSet::Name value = BarrierSet::CardTableForRS;
-};
-
 
 #endif // SHARE_VM_GC_SHARED_CARDTABLEMODREFBS_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/shared/cardTableModRefBSForCTRS.cpp	Fri Jul 31 10:15:02 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.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc/shared/cardTableModRefBS.inline.hpp"
+#include "gc/shared/cardTableRS.hpp"
+#include "memory/allocation.inline.hpp"
+#include "gc/shared/space.inline.hpp"
+
+CardTableModRefBSForCTRS::CardTableModRefBSForCTRS(MemRegion whole_heap) :
+  CardTableModRefBS(
+    whole_heap,
+    // Concrete tag should be BarrierSet::CardTableForRS.
+    // That will presently break things in a bunch of places though.
+    // The concrete tag is used as a dispatch key in many places, and
+    // CardTableForRS does not correctly dispatch in some of those
+    // uses. This will be addressed as part of a reorganization of the
+    // BarrierSet hierarchy.
+    BarrierSet::FakeRtti(BarrierSet::CardTableModRef, 0).add_tag(BarrierSet::CardTableForRS)),
+  // LNC functionality
+  _lowest_non_clean(NULL),
+  _lowest_non_clean_chunk_size(NULL),
+  _lowest_non_clean_base_chunk_index(NULL),
+  _last_LNC_resizing_collection(NULL)
+{ }
+
+void CardTableModRefBSForCTRS::initialize() {
+  CardTableModRefBS::initialize();
+  _lowest_non_clean =
+    NEW_C_HEAP_ARRAY(CardArr, _max_covered_regions, mtGC);
+  _lowest_non_clean_chunk_size =
+    NEW_C_HEAP_ARRAY(size_t, _max_covered_regions, mtGC);
+  _lowest_non_clean_base_chunk_index =
+    NEW_C_HEAP_ARRAY(uintptr_t, _max_covered_regions, mtGC);
+  _last_LNC_resizing_collection =
+    NEW_C_HEAP_ARRAY(int, _max_covered_regions, mtGC);
+  if (_lowest_non_clean == NULL
+      || _lowest_non_clean_chunk_size == NULL
+      || _lowest_non_clean_base_chunk_index == NULL
+      || _last_LNC_resizing_collection == NULL)
+    vm_exit_during_initialization("couldn't allocate an LNC array.");
+  for (int i = 0; i < _max_covered_regions; i++) {
+    _lowest_non_clean[i] = NULL;
+    _lowest_non_clean_chunk_size[i] = 0;
+    _last_LNC_resizing_collection[i] = -1;
+  }
+}
+
+CardTableModRefBSForCTRS::~CardTableModRefBSForCTRS() {
+  if (_lowest_non_clean) {
+    FREE_C_HEAP_ARRAY(CardArr, _lowest_non_clean);
+    _lowest_non_clean = NULL;
+  }
+  if (_lowest_non_clean_chunk_size) {
+    FREE_C_HEAP_ARRAY(size_t, _lowest_non_clean_chunk_size);
+    _lowest_non_clean_chunk_size = NULL;
+  }
+  if (_lowest_non_clean_base_chunk_index) {
+    FREE_C_HEAP_ARRAY(uintptr_t, _lowest_non_clean_base_chunk_index);
+    _lowest_non_clean_base_chunk_index = NULL;
+  }
+  if (_last_LNC_resizing_collection) {
+    FREE_C_HEAP_ARRAY(int, _last_LNC_resizing_collection);
+    _last_LNC_resizing_collection = NULL;
+  }
+}
+
+bool CardTableModRefBSForCTRS::card_will_be_scanned(jbyte cv) {
+  return
+    card_is_dirty_wrt_gen_iter(cv) ||
+    _rs->is_prev_nonclean_card_val(cv);
+}
+
+bool CardTableModRefBSForCTRS::card_may_have_been_dirty(jbyte cv) {
+  return
+    cv != clean_card &&
+    (card_is_dirty_wrt_gen_iter(cv) ||
+     CardTableRS::youngergen_may_have_been_dirty(cv));
+}
+
+void CardTableModRefBSForCTRS::non_clean_card_iterate_possibly_parallel(
+  Space* sp,
+  MemRegion mr,
+  OopsInGenClosure* cl,
+  CardTableRS* ct,
+  uint n_threads)
+{
+  if (!mr.is_empty()) {
+    if (n_threads > 0) {
+#if INCLUDE_ALL_GCS
+      non_clean_card_iterate_parallel_work(sp, mr, cl, ct, n_threads);
+#else  // INCLUDE_ALL_GCS
+      fatal("Parallel gc not supported here.");
+#endif // INCLUDE_ALL_GCS
+    } else {
+      // clear_cl finds contiguous dirty ranges of cards to process and clear.
+
+      // This is the single-threaded version used by DefNew.
+      const bool parallel = false;
+
+      DirtyCardToOopClosure* dcto_cl = sp->new_dcto_cl(cl, precision(), cl->gen_boundary(), parallel);
+      ClearNoncleanCardWrapper clear_cl(dcto_cl, ct, parallel);
+
+      clear_cl.do_MemRegion(mr);
+    }
+  }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/shared/cardTableModRefBSForCTRS.hpp	Fri Jul 31 10:15:02 2015 -0700
@@ -0,0 +1,143 @@
+/*
+ * 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_SHARED_CARDTABLEMODREFBSFORCTRS_HPP
+#define SHARE_VM_GC_SHARED_CARDTABLEMODREFBSFORCTRS_HPP
+
+#include "gc/shared/cardTableModRefBS.hpp"
+
+class CardTableRS;
+class DirtyCardToOopClosure;
+class OopsInGenClosure;
+
+// A specialization for the CardTableRS gen rem set.
+class CardTableModRefBSForCTRS: public CardTableModRefBS {
+  friend class CardTableRS;
+
+public:
+  CardTableModRefBSForCTRS(MemRegion whole_heap);
+  ~CardTableModRefBSForCTRS();
+
+  virtual void initialize();
+
+  void set_CTRS(CardTableRS* rs) { _rs = rs; }
+
+private:
+  CardTableRS* _rs;
+
+  // *** Support for parallel card scanning.
+
+  // dirty and precleaned are equivalent wrt younger_refs_iter.
+  static bool card_is_dirty_wrt_gen_iter(jbyte cv) {
+    return cv == dirty_card || cv == precleaned_card;
+  }
+
+  // Returns "true" iff the value "cv" will cause the card containing it
+  // to be scanned in the current traversal.  May be overridden by
+  // subtypes.
+  bool card_will_be_scanned(jbyte cv);
+
+  // Returns "true" iff the value "cv" may have represented a dirty card at
+  // some point.
+  bool card_may_have_been_dirty(jbyte cv);
+
+  // Iterate over the portion of the card-table which covers the given
+  // region mr in the given space and apply cl to any dirty sub-regions
+  // of mr. Clears the dirty cards as they are processed.
+  void non_clean_card_iterate_possibly_parallel(Space* sp, MemRegion mr,
+                                                OopsInGenClosure* cl, CardTableRS* ct,
+                                                uint n_threads);
+
+  // Work method used to implement non_clean_card_iterate_possibly_parallel()
+  // above in the parallel case.
+  void non_clean_card_iterate_parallel_work(Space* sp, MemRegion mr,
+                                            OopsInGenClosure* cl, CardTableRS* ct,
+                                            uint n_threads);
+
+  // This is an array, one element per covered region of the card table.
+  // Each entry is itself an array, with one element per chunk in the
+  // covered region.  Each entry of these arrays is the lowest non-clean
+  // card of the corresponding chunk containing part of an object from the
+  // previous chunk, or else NULL.
+  typedef jbyte*  CardPtr;
+  typedef CardPtr* CardArr;
+  CardArr* _lowest_non_clean;
+  size_t*  _lowest_non_clean_chunk_size;
+  uintptr_t* _lowest_non_clean_base_chunk_index;
+  int* _last_LNC_resizing_collection;
+
+  // Initializes "lowest_non_clean" to point to the array for the region
+  // covering "sp", and "lowest_non_clean_base_chunk_index" to the chunk
+  // index of the corresponding to the first element of that array.
+  // Ensures that these arrays are of sufficient size, allocating if necessary.
+  // May be called by several threads concurrently.
+  void get_LNC_array_for_space(Space* sp,
+                               jbyte**& lowest_non_clean,
+                               uintptr_t& lowest_non_clean_base_chunk_index,
+                               size_t& lowest_non_clean_chunk_size);
+
+  // Returns the number of chunks necessary to cover "mr".
+  size_t chunks_to_cover(MemRegion mr) {
+    return (size_t)(addr_to_chunk_index(mr.last()) -
+                    addr_to_chunk_index(mr.start()) + 1);
+  }
+
+  // Returns the index of the chunk in a stride which
+  // covers the given address.
+  uintptr_t addr_to_chunk_index(const void* addr) {
+    uintptr_t card = (uintptr_t) byte_for(addr);
+    return card / ParGCCardsPerStrideChunk;
+  }
+
+  // Apply cl, which must either itself apply dcto_cl or be dcto_cl,
+  // to the cards in the stride (of n_strides) within the given space.
+  void process_stride(Space* sp,
+                      MemRegion used,
+                      jint stride, int n_strides,
+                      OopsInGenClosure* cl,
+                      CardTableRS* ct,
+                      jbyte** lowest_non_clean,
+                      uintptr_t lowest_non_clean_base_chunk_index,
+                      size_t lowest_non_clean_chunk_size);
+
+  // Makes sure that chunk boundaries are handled appropriately, by
+  // adjusting the min_done of dcto_cl, and by using a special card-table
+  // value to indicate how min_done should be set.
+  void process_chunk_boundaries(Space* sp,
+                                DirtyCardToOopClosure* dcto_cl,
+                                MemRegion chunk_mr,
+                                MemRegion used,
+                                jbyte** lowest_non_clean,
+                                uintptr_t lowest_non_clean_base_chunk_index,
+                                size_t    lowest_non_clean_chunk_size);
+
+};
+
+template<>
+struct BarrierSet::GetName<CardTableModRefBSForCTRS> {
+  static const BarrierSet::Name value = BarrierSet::CardTableForRS;
+};
+
+#endif // include guard
+
--- a/hotspot/src/share/vm/gc/shared/cardTableRS.cpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/gc/shared/cardTableRS.cpp	Fri Jul 31 10:15:02 2015 -0700
@@ -240,7 +240,7 @@
 // cur-younger-gen                ==> cur_younger_gen
 // cur_youngergen_and_prev_nonclean_card ==> no change.
 void CardTableRS::write_ref_field_gc_par(void* field, oop new_val) {
-  jbyte* entry = ct_bs()->byte_for(field);
+  jbyte* entry = _ct_bs->byte_for(field);
   do {
     jbyte entry_val = *entry;
     // We put this first because it's probably the most common case.
@@ -398,10 +398,10 @@
   jbyte* cur_entry = byte_for(used.start());
   jbyte* limit = byte_after(used.last());
   while (cur_entry < limit) {
-    if (*cur_entry == CardTableModRefBS::clean_card) {
+    if (*cur_entry == clean_card_val()) {
       jbyte* first_dirty = cur_entry+1;
       while (first_dirty < limit &&
-             *first_dirty == CardTableModRefBS::clean_card) {
+             *first_dirty == clean_card_val()) {
         first_dirty++;
       }
       // If the first object is a regular object, and it has a
@@ -418,7 +418,7 @@
               !boundary_obj->is_typeArray()) {
             guarantee(cur_entry > byte_for(used.start()),
                       "else boundary would be boundary_block");
-            if (*byte_for(boundary_block) != CardTableModRefBS::clean_card) {
+            if (*byte_for(boundary_block) != clean_card_val()) {
               begin = boundary_block + s->block_size(boundary_block);
               start_block = begin;
             }
--- a/hotspot/src/share/vm/gc/shared/cardTableRS.hpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/gc/shared/cardTableRS.hpp	Fri Jul 31 10:15:02 2015 -0700
@@ -25,7 +25,7 @@
 #ifndef SHARE_VM_GC_SHARED_CARDTABLERS_HPP
 #define SHARE_VM_GC_SHARED_CARDTABLERS_HPP
 
-#include "gc/shared/cardTableModRefBS.hpp"
+#include "gc/shared/cardTableModRefBSForCTRS.hpp"
 #include "gc/shared/genRemSet.hpp"
 #include "memory/memRegion.hpp"
 
@@ -42,16 +42,16 @@
   friend class ClearNoncleanCardWrapper;
 
   static jbyte clean_card_val() {
-    return CardTableModRefBS::clean_card;
+    return CardTableModRefBSForCTRS::clean_card;
   }
 
   static intptr_t clean_card_row() {
-    return CardTableModRefBS::clean_card_row;
+    return CardTableModRefBSForCTRS::clean_card_row;
   }
 
   static bool
   card_is_dirty_wrt_gen_iter(jbyte cv) {
-    return CardTableModRefBS::card_is_dirty_wrt_gen_iter(cv);
+    return CardTableModRefBSForCTRS::card_is_dirty_wrt_gen_iter(cv);
   }
 
   CardTableModRefBSForCTRS* _ct_bs;
@@ -61,17 +61,17 @@
   void verify_space(Space* s, HeapWord* gen_start);
 
   enum ExtendedCardValue {
-    youngergen_card   = CardTableModRefBS::CT_MR_BS_last_reserved + 1,
+    youngergen_card   = CardTableModRefBSForCTRS::CT_MR_BS_last_reserved + 1,
     // These are for parallel collection.
     // There are three P (parallel) youngergen card values.  In general, this
     // needs to be more than the number of generations (including the perm
     // gen) that might have younger_refs_do invoked on them separately.  So
     // if we add more gens, we have to add more values.
-    youngergenP1_card  = CardTableModRefBS::CT_MR_BS_last_reserved + 2,
-    youngergenP2_card  = CardTableModRefBS::CT_MR_BS_last_reserved + 3,
-    youngergenP3_card  = CardTableModRefBS::CT_MR_BS_last_reserved + 4,
+    youngergenP1_card  = CardTableModRefBSForCTRS::CT_MR_BS_last_reserved + 2,
+    youngergenP2_card  = CardTableModRefBSForCTRS::CT_MR_BS_last_reserved + 3,
+    youngergenP3_card  = CardTableModRefBSForCTRS::CT_MR_BS_last_reserved + 4,
     cur_youngergen_and_prev_nonclean_card =
-      CardTableModRefBS::CT_MR_BS_last_reserved + 5
+      CardTableModRefBSForCTRS::CT_MR_BS_last_reserved + 5
   };
 
   // An array that contains, for each generation, the card table value last
@@ -107,7 +107,7 @@
   // *** GenRemSet functions.
   CardTableRS* as_CardTableRS() { return this; }
 
-  CardTableModRefBS* ct_bs() { return _ct_bs; }
+  CardTableModRefBSForCTRS* ct_bs() { return _ct_bs; }
 
   // Override.
   void prepare_for_younger_refs_iterate(bool parallel);
@@ -147,7 +147,7 @@
   void invalidate_or_clear(Generation* old_gen);
 
   static uintx ct_max_alignment_constraint() {
-    return CardTableModRefBS::ct_max_alignment_constraint();
+    return CardTableModRefBSForCTRS::ct_max_alignment_constraint();
   }
 
   jbyte* byte_for(void* p)     { return _ct_bs->byte_for(p); }
--- a/hotspot/src/share/vm/gc/shared/taskqueue.hpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/gc/shared/taskqueue.hpp	Fri Jul 31 10:15:02 2015 -0700
@@ -295,8 +295,9 @@
   // Delete any resource associated with the queue.
   ~GenericTaskQueue();
 
-  // apply the closure to all elements in the task queue
-  void oops_do(OopClosure* f);
+  // Apply fn to each element in the task queue.  The queue must not
+  // be modified while iterating.
+  template<typename Fn> void iterate(Fn fn);
 
 private:
   // Element array.
--- a/hotspot/src/share/vm/gc/shared/taskqueue.inline.hpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/gc/shared/taskqueue.inline.hpp	Fri Jul 31 10:15:02 2015 -0700
@@ -259,20 +259,14 @@
 }
 
 template<class E, MEMFLAGS F, unsigned int N>
-inline void GenericTaskQueue<E, F, N>::oops_do(OopClosure* f) {
-  // tty->print_cr("START OopTaskQueue::oops_do");
+template<class Fn>
+inline void GenericTaskQueue<E, F, N>::iterate(Fn fn) {
   uint iters = size();
   uint index = _bottom;
   for (uint i = 0; i < iters; ++i) {
     index = decrement_index(index);
-    // tty->print_cr("  doing entry %d," INTPTR_T " -> " INTPTR_T,
-    //            index, &_elems[index], _elems[index]);
-    E* t = (E*)&_elems[index];      // cast away volatility
-    oop* p = (oop*)t;
-    assert((*t)->is_oop_or_null(), err_msg("Expected an oop or NULL at " PTR_FORMAT, p2i(*t)));
-    f->do_oop(p);
+    fn(const_cast<E&>(_elems[index])); // cast away volatility
   }
-  // tty->print_cr("END OopTaskQueue::oops_do");
 }
 
 
--- a/hotspot/src/share/vm/memory/universe.cpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/memory/universe.cpp	Fri Jul 31 10:15:02 2015 -0700
@@ -56,6 +56,7 @@
 #include "prims/jvmtiRedefineClassesTrace.hpp"
 #include "runtime/arguments.hpp"
 #include "runtime/atomic.inline.hpp"
+#include "runtime/commandLineFlagConstraintList.hpp"
 #include "runtime/deoptimization.hpp"
 #include "runtime/fprofiler.hpp"
 #include "runtime/handles.inline.hpp"
@@ -656,6 +657,11 @@
 
   Metaspace::global_initialize();
 
+  // Checks 'AfterMemoryInit' constraints.
+  if (!CommandLineFlagConstraintList::check_constraints(CommandLineFlagConstraint::AfterMemoryInit)) {
+    return JNI_EINVAL;
+  }
+
   // Create memory for metadata.  Must be after initializing heap for
   // DumpSharedSpaces.
   ClassLoaderData::init_null_class_loader_data();
--- a/hotspot/src/share/vm/oops/oop.hpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/oops/oop.hpp	Fri Jul 31 10:15:02 2015 -0700
@@ -200,7 +200,6 @@
 
   // Access to fields in a instanceOop through these methods.
   oop obj_field(int offset) const;
-  volatile oop obj_field_volatile(int offset) const;
   void obj_field_put(int offset, oop value);
   void obj_field_put_raw(int offset, oop value);
   void obj_field_put_volatile(int offset, oop value);
--- a/hotspot/src/share/vm/oops/oop.inline.hpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/oops/oop.inline.hpp	Fri Jul 31 10:15:02 2015 -0700
@@ -284,11 +284,7 @@
     load_decode_heap_oop(obj_field_addr<narrowOop>(offset)) :
     load_decode_heap_oop(obj_field_addr<oop>(offset));
 }
-inline volatile oop oopDesc::obj_field_volatile(int offset) const {
-  volatile oop value = obj_field(offset);
-  OrderAccess::acquire();
-  return value;
-}
+
 inline void oopDesc::obj_field_put(int offset, oop value) {
   UseCompressedOops ? oop_store(obj_field_addr<narrowOop>(offset), value) :
                       oop_store(obj_field_addr<oop>(offset),       value);
--- a/hotspot/src/share/vm/opto/c2_globals.hpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/opto/c2_globals.hpp	Fri Jul 31 10:15:02 2015 -0700
@@ -659,7 +659,7 @@
           "0 for no aliasing, 1 for oop/field/static/array split, "         \
           "2 for class split, 3 for unique instances")                      \
           range(0, 3)                                                       \
-          constraint(AliasLevelConstraintFunc)                              \
+          constraint(AliasLevelConstraintFunc,AfterErgo)                    \
                                                                             \
   develop(bool, VerifyAliases, false,                                       \
           "perform extra checks on the results of alias analysis")          \
--- a/hotspot/src/share/vm/opto/c2compiler.cpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/opto/c2compiler.cpp	Fri Jul 31 10:15:02 2015 -0700
@@ -79,7 +79,6 @@
   return OptoRuntime::generate(thread->env());
 }
 
-
 void C2Compiler::initialize() {
   // The first compiler thread that gets here will initialize the
   // small amount of global state (and runtime stubs) that C2 needs.
@@ -154,11 +153,361 @@
   }
 }
 
-
 void C2Compiler::print_timers() {
   Compile::print_timers();
 }
 
+bool C2Compiler::is_intrinsic_available(methodHandle method, methodHandle compilation_context) {
+  // Assume a non-virtual dispatch. A virtual dispatch is
+  // possible for only a limited set of available intrinsics whereas
+  // a non-virtual dispatch is possible for all available intrinsics.
+  return is_intrinsic_supported(method, false) &&
+         !is_intrinsic_disabled_by_flag(method, compilation_context);
+}
+
+bool C2Compiler::is_intrinsic_supported(methodHandle method, bool is_virtual) {
+  vmIntrinsics::ID id = method->intrinsic_id();
+  assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
+
+  if (id < vmIntrinsics::FIRST_ID || id >= vmIntrinsics::LAST_COMPILER_INLINE) {
+    return false;
+  }
+
+  // Only Object.hashCode and Object.clone intrinsics implement also a virtual
+  // dispatch because calling both methods is expensive but both methods are
+  // frequently overridden. All other intrinsics implement only a non-virtual
+  // dispatch.
+  if (is_virtual) {
+    switch (id) {
+    case vmIntrinsics::_hashCode:
+    case vmIntrinsics::_clone:
+      break;
+    default:
+      return false;
+    }
+  }
+
+  switch (id) {
+  case vmIntrinsics::_compareTo:
+    if (!Matcher::match_rule_supported(Op_StrComp)) return false;
+    break;
+  case vmIntrinsics::_equals:
+    if (!Matcher::match_rule_supported(Op_StrEquals)) return false;
+    break;
+  case vmIntrinsics::_equalsC:
+    if (!Matcher::match_rule_supported(Op_AryEq)) return false;
+    break;
+  case vmIntrinsics::_copyMemory:
+    if (StubRoutines::unsafe_arraycopy() == NULL) return false;
+    break;
+  case vmIntrinsics::_encodeISOArray:
+    if (!Matcher::match_rule_supported(Op_EncodeISOArray)) return false;
+    break;
+  case vmIntrinsics::_bitCount_i:
+    if (!Matcher::match_rule_supported(Op_PopCountI)) return false;
+    break;
+  case vmIntrinsics::_bitCount_l:
+    if (!Matcher::match_rule_supported(Op_PopCountL)) return false;
+    break;
+  case vmIntrinsics::_numberOfLeadingZeros_i:
+    if (!Matcher::match_rule_supported(Op_CountLeadingZerosI)) return false;
+    break;
+  case vmIntrinsics::_numberOfLeadingZeros_l:
+    if (!Matcher::match_rule_supported(Op_CountLeadingZerosL)) return false;
+    break;
+  case vmIntrinsics::_numberOfTrailingZeros_i:
+    if (!Matcher::match_rule_supported(Op_CountTrailingZerosI)) return false;
+    break;
+  case vmIntrinsics::_numberOfTrailingZeros_l:
+    if (!Matcher::match_rule_supported(Op_CountTrailingZerosL)) return false;
+    break;
+  case vmIntrinsics::_reverseBytes_c:
+    if (!Matcher::match_rule_supported(Op_ReverseBytesUS)) return false;
+    break;
+  case vmIntrinsics::_reverseBytes_s:
+    if (!Matcher::match_rule_supported(Op_ReverseBytesS)) return false;
+    break;
+  case vmIntrinsics::_reverseBytes_i:
+    if (!Matcher::match_rule_supported(Op_ReverseBytesI)) return false;
+    break;
+  case vmIntrinsics::_reverseBytes_l:
+    if (!Matcher::match_rule_supported(Op_ReverseBytesL)) return false;
+    break;
+  case vmIntrinsics::_compareAndSwapObject:
+#ifdef _LP64
+    if (!UseCompressedOops && !Matcher::match_rule_supported(Op_CompareAndSwapP)) return false;
+#endif
+    break;
+  case vmIntrinsics::_compareAndSwapLong:
+    if (!Matcher::match_rule_supported(Op_CompareAndSwapL)) return false;
+    break;
+  case vmIntrinsics::_getAndAddInt:
+    if (!Matcher::match_rule_supported(Op_GetAndAddI)) return false;
+    break;
+  case vmIntrinsics::_getAndAddLong:
+    if (!Matcher::match_rule_supported(Op_GetAndAddL)) return false;
+    break;
+  case vmIntrinsics::_getAndSetInt:
+    if (!Matcher::match_rule_supported(Op_GetAndSetI)) return false;
+    break;
+  case vmIntrinsics::_getAndSetLong:
+    if (!Matcher::match_rule_supported(Op_GetAndSetL)) return false;
+    break;
+  case vmIntrinsics::_getAndSetObject:
+#ifdef _LP64
+    if (!UseCompressedOops && !Matcher::match_rule_supported(Op_GetAndSetP)) return false;
+    if (UseCompressedOops && !Matcher::match_rule_supported(Op_GetAndSetN)) return false;
+    break;
+#else
+    if (!Matcher::match_rule_supported(Op_GetAndSetP)) return false;
+    break;
+#endif
+  case vmIntrinsics::_incrementExactI:
+  case vmIntrinsics::_addExactI:
+    if (!Matcher::match_rule_supported(Op_OverflowAddI)) return false;
+    break;
+  case vmIntrinsics::_incrementExactL:
+  case vmIntrinsics::_addExactL:
+    if (!Matcher::match_rule_supported(Op_OverflowAddL)) return false;
+    break;
+  case vmIntrinsics::_decrementExactI:
+  case vmIntrinsics::_subtractExactI:
+    if (!Matcher::match_rule_supported(Op_OverflowSubI)) return false;
+    break;
+  case vmIntrinsics::_decrementExactL:
+  case vmIntrinsics::_subtractExactL:
+    if (!Matcher::match_rule_supported(Op_OverflowSubL)) return false;
+    break;
+  case vmIntrinsics::_negateExactI:
+    if (!Matcher::match_rule_supported(Op_OverflowSubI)) return false;
+    break;
+  case vmIntrinsics::_negateExactL:
+    if (!Matcher::match_rule_supported(Op_OverflowSubL)) return false;
+    break;
+  case vmIntrinsics::_multiplyExactI:
+    if (!Matcher::match_rule_supported(Op_OverflowMulI)) return false;
+    break;
+  case vmIntrinsics::_multiplyExactL:
+    if (!Matcher::match_rule_supported(Op_OverflowMulL)) return false;
+    break;
+  case vmIntrinsics::_getCallerClass:
+    if (SystemDictionary::reflect_CallerSensitive_klass() == NULL) return false;
+    break;
+  case vmIntrinsics::_hashCode:
+  case vmIntrinsics::_identityHashCode:
+  case vmIntrinsics::_getClass:
+  case vmIntrinsics::_dsin:
+  case vmIntrinsics::_dcos:
+  case vmIntrinsics::_dtan:
+  case vmIntrinsics::_dabs:
+  case vmIntrinsics::_datan2:
+  case vmIntrinsics::_dsqrt:
+  case vmIntrinsics::_dexp:
+  case vmIntrinsics::_dlog:
+  case vmIntrinsics::_dlog10:
+  case vmIntrinsics::_dpow:
+  case vmIntrinsics::_min:
+  case vmIntrinsics::_max:
+  case vmIntrinsics::_arraycopy:
+  case vmIntrinsics::_indexOf:
+  case vmIntrinsics::_getObject:
+  case vmIntrinsics::_getBoolean:
+  case vmIntrinsics::_getByte:
+  case vmIntrinsics::_getShort:
+  case vmIntrinsics::_getChar:
+  case vmIntrinsics::_getInt:
+  case vmIntrinsics::_getLong:
+  case vmIntrinsics::_getFloat:
+  case vmIntrinsics::_getDouble:
+  case vmIntrinsics::_putObject:
+  case vmIntrinsics::_putBoolean:
+  case vmIntrinsics::_putByte:
+  case vmIntrinsics::_putShort:
+  case vmIntrinsics::_putChar:
+  case vmIntrinsics::_putInt:
+  case vmIntrinsics::_putLong:
+  case vmIntrinsics::_putFloat:
+  case vmIntrinsics::_putDouble:
+  case vmIntrinsics::_getByte_raw:
+  case vmIntrinsics::_getShort_raw:
+  case vmIntrinsics::_getChar_raw:
+  case vmIntrinsics::_getInt_raw:
+  case vmIntrinsics::_getLong_raw:
+  case vmIntrinsics::_getFloat_raw:
+  case vmIntrinsics::_getDouble_raw:
+  case vmIntrinsics::_getAddress_raw:
+  case vmIntrinsics::_putByte_raw:
+  case vmIntrinsics::_putShort_raw:
+  case vmIntrinsics::_putChar_raw:
+  case vmIntrinsics::_putInt_raw:
+  case vmIntrinsics::_putLong_raw:
+  case vmIntrinsics::_putFloat_raw:
+  case vmIntrinsics::_putDouble_raw:
+  case vmIntrinsics::_putAddress_raw:
+  case vmIntrinsics::_getObjectVolatile:
+  case vmIntrinsics::_getBooleanVolatile:
+  case vmIntrinsics::_getByteVolatile:
+  case vmIntrinsics::_getShortVolatile:
+  case vmIntrinsics::_getCharVolatile:
+  case vmIntrinsics::_getIntVolatile:
+  case vmIntrinsics::_getLongVolatile:
+  case vmIntrinsics::_getFloatVolatile:
+  case vmIntrinsics::_getDoubleVolatile:
+  case vmIntrinsics::_putObjectVolatile:
+  case vmIntrinsics::_putBooleanVolatile:
+  case vmIntrinsics::_putByteVolatile:
+  case vmIntrinsics::_putShortVolatile:
+  case vmIntrinsics::_putCharVolatile:
+  case vmIntrinsics::_putIntVolatile:
+  case vmIntrinsics::_putLongVolatile:
+  case vmIntrinsics::_putFloatVolatile:
+  case vmIntrinsics::_putDoubleVolatile:
+  case vmIntrinsics::_getShortUnaligned:
+  case vmIntrinsics::_getCharUnaligned:
+  case vmIntrinsics::_getIntUnaligned:
+  case vmIntrinsics::_getLongUnaligned:
+  case vmIntrinsics::_putShortUnaligned:
+  case vmIntrinsics::_putCharUnaligned:
+  case vmIntrinsics::_putIntUnaligned:
+  case vmIntrinsics::_putLongUnaligned:
+  case vmIntrinsics::_compareAndSwapInt:
+  case vmIntrinsics::_putOrderedObject:
+  case vmIntrinsics::_putOrderedInt:
+  case vmIntrinsics::_putOrderedLong:
+  case vmIntrinsics::_loadFence:
+  case vmIntrinsics::_storeFence:
+  case vmIntrinsics::_fullFence:
+  case vmIntrinsics::_currentThread:
+  case vmIntrinsics::_isInterrupted:
+#ifdef TRACE_HAVE_INTRINSICS
+  case vmIntrinsics::_classID:
+  case vmIntrinsics::_threadID:
+  case vmIntrinsics::_counterTime:
+#endif
+  case vmIntrinsics::_currentTimeMillis:
+  case vmIntrinsics::_nanoTime:
+  case vmIntrinsics::_allocateInstance:
+  case vmIntrinsics::_newArray:
+  case vmIntrinsics::_getLength:
+  case vmIntrinsics::_copyOf:
+  case vmIntrinsics::_copyOfRange:
+  case vmIntrinsics::_clone:
+  case vmIntrinsics::_isAssignableFrom:
+  case vmIntrinsics::_isInstance:
+  case vmIntrinsics::_getModifiers:
+  case vmIntrinsics::_isInterface:
+  case vmIntrinsics::_isArray:
+  case vmIntrinsics::_isPrimitive:
+  case vmIntrinsics::_getSuperclass:
+  case vmIntrinsics::_getClassAccessFlags:
+  case vmIntrinsics::_floatToRawIntBits:
+  case vmIntrinsics::_floatToIntBits:
+  case vmIntrinsics::_intBitsToFloat:
+  case vmIntrinsics::_doubleToRawLongBits:
+  case vmIntrinsics::_doubleToLongBits:
+  case vmIntrinsics::_longBitsToDouble:
+  case vmIntrinsics::_Reference_get:
+  case vmIntrinsics::_Class_cast:
+  case vmIntrinsics::_aescrypt_encryptBlock:
+  case vmIntrinsics::_aescrypt_decryptBlock:
+  case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt:
+  case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt:
+  case vmIntrinsics::_sha_implCompress:
+  case vmIntrinsics::_sha2_implCompress:
+  case vmIntrinsics::_sha5_implCompress:
+  case vmIntrinsics::_digestBase_implCompressMB:
+  case vmIntrinsics::_multiplyToLen:
+  case vmIntrinsics::_squareToLen:
+  case vmIntrinsics::_mulAdd:
+  case vmIntrinsics::_montgomeryMultiply:
+  case vmIntrinsics::_montgomerySquare:
+  case vmIntrinsics::_ghash_processBlocks:
+  case vmIntrinsics::_updateCRC32:
+  case vmIntrinsics::_updateBytesCRC32:
+  case vmIntrinsics::_updateByteBufferCRC32:
+  case vmIntrinsics::_updateBytesCRC32C:
+  case vmIntrinsics::_updateDirectByteBufferCRC32C:
+  case vmIntrinsics::_profileBoolean:
+  case vmIntrinsics::_isCompileConstant:
+    break;
+  default:
+    return false;
+  }
+  return true;
+}
+
+bool C2Compiler::is_intrinsic_disabled_by_flag(methodHandle method, methodHandle compilation_context) {
+  vmIntrinsics::ID id = method->intrinsic_id();
+  assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
+
+  if (vmIntrinsics::is_disabled_by_flags(method->intrinsic_id())) {
+    return true;
+  }
+
+  // Check if the intrinsic corresponding to 'method' has been disabled on
+  // the command line by using the DisableIntrinsic flag (either globally
+  // or on a per-method level, see src/share/vm/compiler/abstractCompiler.hpp
+  // for details).
+  // Usually, the compilation context is the caller of the method 'method'.
+  // The only case when for a non-recursive method 'method' the compilation context
+  // is not the caller of the 'method' (but it is the method itself) is
+  // java.lang.ref.Referene::get.
+  // For java.lang.ref.Reference::get, the intrinsic version is used
+  // instead of the C2-compiled version so that the value in the referent
+  // field can be registered by the G1 pre-barrier code. The intrinsified
+  // version of Reference::get also adds a memory barrier to prevent
+  // commoning reads from the referent field across safepoint since GC
+  // can change the referent field's value. See Compile::Compile()
+  // in src/share/vm/opto/compile.cpp for more details.
+  ccstr disable_intr = NULL;
+  if ((DisableIntrinsic[0] != '\0' && strstr(DisableIntrinsic, vmIntrinsics::name_at(id)) != NULL) ||
+      (!compilation_context.is_null() &&
+       CompilerOracle::has_option_value(compilation_context, "DisableIntrinsic", disable_intr) &&
+       strstr(disable_intr, vmIntrinsics::name_at(id)) != NULL)
+  ) {
+    return true;
+  }
+
+  // -XX:-InlineNatives disables nearly all intrinsics except the ones listed in
+  // the following switch statement.
+  if (!InlineNatives) {
+    switch (id) {
+    case vmIntrinsics::_indexOf:
+    case vmIntrinsics::_compareTo:
+    case vmIntrinsics::_equals:
+    case vmIntrinsics::_equalsC:
+    case vmIntrinsics::_getAndAddInt:
+    case vmIntrinsics::_getAndAddLong:
+    case vmIntrinsics::_getAndSetInt:
+    case vmIntrinsics::_getAndSetLong:
+    case vmIntrinsics::_getAndSetObject:
+    case vmIntrinsics::_loadFence:
+    case vmIntrinsics::_storeFence:
+    case vmIntrinsics::_fullFence:
+    case vmIntrinsics::_Reference_get:
+      break;
+    default:
+      return true;
+    }
+  }
+
+  if (!InlineUnsafeOps) {
+    switch (id) {
+    case vmIntrinsics::_loadFence:
+    case vmIntrinsics::_storeFence:
+    case vmIntrinsics::_fullFence:
+    case vmIntrinsics::_compareAndSwapObject:
+    case vmIntrinsics::_compareAndSwapLong:
+    case vmIntrinsics::_compareAndSwapInt:
+      return true;
+    default:
+      return false;
+    }
+  }
+
+  return false;
+}
+
 int C2Compiler::initial_code_buffer_size() {
   assert(SegmentedCodeCache, "Should be only used with a segmented code cache");
   return Compile::MAX_inst_size + Compile::MAX_locs_size + initial_const_capacity;
--- a/hotspot/src/share/vm/opto/c2compiler.hpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/opto/c2compiler.hpp	Fri Jul 31 10:15:02 2015 -0700
@@ -36,7 +36,6 @@
 
   // Name
   const char *name() { return "C2"; }
-
   void initialize();
 
   // Compilation entry point for methods
@@ -52,6 +51,26 @@
   // Print compilation timers and statistics
   void print_timers();
 
+  // Check the availability of an intrinsic for 'method' given a compilation context.
+  virtual bool is_intrinsic_available(methodHandle method, methodHandle compilation_context);
+
+  // Return true if the intrinsification of a method supported by the compiler
+  // assuming a non-virtual dispatch. Return false otherwise.
+  virtual bool is_intrinsic_supported(methodHandle method) {
+    return is_intrinsic_supported(method, false);
+  }
+
+  // Check if the compiler supports an intrinsic for 'method' given the
+  // the dispatch mode specified by the 'is_virtual' parameter.
+  virtual bool is_intrinsic_supported(methodHandle method, bool is_virtual);
+
+  // Processing of command-line flags specific to the C2 compiler.
+  virtual bool is_intrinsic_disabled_by_flag(methodHandle method) {
+    return is_intrinsic_disabled_by_flag(method, NULL);
+  }
+
+  virtual bool is_intrinsic_disabled_by_flag(methodHandle method, methodHandle compilation_context);
+
   // Initial size of the code buffer (may be increased at runtime)
   static int initial_code_buffer_size();
 };
--- a/hotspot/src/share/vm/opto/library_call.cpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/opto/library_call.cpp	Fri Jul 31 10:15:02 2015 -0700
@@ -31,6 +31,7 @@
 #include "oops/objArrayKlass.hpp"
 #include "opto/addnode.hpp"
 #include "opto/arraycopynode.hpp"
+#include "opto/c2compiler.hpp"
 #include "opto/callGenerator.hpp"
 #include "opto/castnode.hpp"
 #include "opto/cfgnode.hpp"
@@ -305,330 +306,40 @@
   bool inline_isCompileConstant();
 };
 
-
 //---------------------------make_vm_intrinsic----------------------------
 CallGenerator* Compile::make_vm_intrinsic(ciMethod* m, bool is_virtual) {
   vmIntrinsics::ID id = m->intrinsic_id();
   assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
 
-  ccstr disable_intr = NULL;
-
-  if ((DisableIntrinsic[0] != '\0'
-       && strstr(DisableIntrinsic, vmIntrinsics::name_at(id)) != NULL) ||
-      (method_has_option_value("DisableIntrinsic", disable_intr)
-       && strstr(disable_intr, vmIntrinsics::name_at(id)) != NULL)) {
-    // disabled by a user request on the command line:
-    // example: -XX:DisableIntrinsic=_hashCode,_getClass
-    return NULL;
-  }
-
   if (!m->is_loaded()) {
-    // do not attempt to inline unloaded methods
-    return NULL;
-  }
-
-  // Only a few intrinsics implement a virtual dispatch.
-  // They are expensive calls which are also frequently overridden.
-  if (is_virtual) {
-    switch (id) {
-    case vmIntrinsics::_hashCode:
-    case vmIntrinsics::_clone:
-      // OK, Object.hashCode and Object.clone intrinsics come in both flavors
-      break;
-    default:
-      return NULL;
-    }
-  }
-
-  // -XX:-InlineNatives disables nearly all intrinsics:
-  if (!InlineNatives) {
-    switch (id) {
-    case vmIntrinsics::_indexOf:
-    case vmIntrinsics::_compareTo:
-    case vmIntrinsics::_equals:
-    case vmIntrinsics::_equalsC:
-    case vmIntrinsics::_getAndAddInt:
-    case vmIntrinsics::_getAndAddLong:
-    case vmIntrinsics::_getAndSetInt:
-    case vmIntrinsics::_getAndSetLong:
-    case vmIntrinsics::_getAndSetObject:
-    case vmIntrinsics::_loadFence:
-    case vmIntrinsics::_storeFence:
-    case vmIntrinsics::_fullFence:
-      break;  // InlineNatives does not control String.compareTo
-    case vmIntrinsics::_Reference_get:
-      break;  // InlineNatives does not control Reference.get
-    default:
-      return NULL;
-    }
-  }
-
-  int predicates = 0;
-  bool does_virtual_dispatch = false;
-
-  switch (id) {
-  case vmIntrinsics::_compareTo:
-    if (!SpecialStringCompareTo)  return NULL;
-    if (!Matcher::match_rule_supported(Op_StrComp))  return NULL;
-    break;
-  case vmIntrinsics::_indexOf:
-    if (!SpecialStringIndexOf)  return NULL;
-    break;
-  case vmIntrinsics::_equals:
-    if (!SpecialStringEquals)  return NULL;
-    if (!Matcher::match_rule_supported(Op_StrEquals))  return NULL;
-    break;
-  case vmIntrinsics::_equalsC:
-    if (!SpecialArraysEquals)  return NULL;
-    if (!Matcher::match_rule_supported(Op_AryEq))  return NULL;
-    break;
-  case vmIntrinsics::_arraycopy:
-    if (!InlineArrayCopy)  return NULL;
-    break;
-  case vmIntrinsics::_copyMemory:
-    if (StubRoutines::unsafe_arraycopy() == NULL)  return NULL;
-    if (!InlineArrayCopy)  return NULL;
-    break;
-  case vmIntrinsics::_hashCode:
-    if (!InlineObjectHash)  return NULL;
-    does_virtual_dispatch = true;
-    break;
-  case vmIntrinsics::_clone:
-    does_virtual_dispatch = true;
-  case vmIntrinsics::_copyOf:
-  case vmIntrinsics::_copyOfRange:
-    if (!InlineObjectCopy)  return NULL;
-    // These also use the arraycopy intrinsic mechanism:
-    if (!InlineArrayCopy)  return NULL;
-    break;
-  case vmIntrinsics::_encodeISOArray:
-    if (!SpecialEncodeISOArray)  return NULL;
-    if (!Matcher::match_rule_supported(Op_EncodeISOArray))  return NULL;
-    break;
-  case vmIntrinsics::_checkIndex:
-    // We do not intrinsify this.  The optimizer does fine with it.
+    // Do not attempt to inline unloaded methods.
     return NULL;
-
-  case vmIntrinsics::_getCallerClass:
-    if (!InlineReflectionGetCallerClass)  return NULL;
-    if (SystemDictionary::reflect_CallerSensitive_klass() == NULL)  return NULL;
-    break;
-
-  case vmIntrinsics::_bitCount_i:
-    if (!Matcher::match_rule_supported(Op_PopCountI)) return NULL;
-    break;
-
-  case vmIntrinsics::_bitCount_l:
-    if (!Matcher::match_rule_supported(Op_PopCountL)) return NULL;
-    break;
-
-  case vmIntrinsics::_numberOfLeadingZeros_i:
-    if (!Matcher::match_rule_supported(Op_CountLeadingZerosI)) return NULL;
-    break;
-
-  case vmIntrinsics::_numberOfLeadingZeros_l:
-    if (!Matcher::match_rule_supported(Op_CountLeadingZerosL)) return NULL;
-    break;
-
-  case vmIntrinsics::_numberOfTrailingZeros_i:
-    if (!Matcher::match_rule_supported(Op_CountTrailingZerosI)) return NULL;
-    break;
-
-  case vmIntrinsics::_numberOfTrailingZeros_l:
-    if (!Matcher::match_rule_supported(Op_CountTrailingZerosL)) return NULL;
-    break;
-
-  case vmIntrinsics::_reverseBytes_c:
-    if (!Matcher::match_rule_supported(Op_ReverseBytesUS)) return NULL;
-    break;
-  case vmIntrinsics::_reverseBytes_s:
-    if (!Matcher::match_rule_supported(Op_ReverseBytesS))  return NULL;
-    break;
-  case vmIntrinsics::_reverseBytes_i:
-    if (!Matcher::match_rule_supported(Op_ReverseBytesI))  return NULL;
-    break;
-  case vmIntrinsics::_reverseBytes_l:
-    if (!Matcher::match_rule_supported(Op_ReverseBytesL))  return NULL;
-    break;
-
-  case vmIntrinsics::_Reference_get:
-    // Use the intrinsic version of Reference.get() so that the value in
-    // the referent field can be registered by the G1 pre-barrier code.
-    // Also add memory barrier to prevent commoning reads from this field
-    // across safepoint since GC can change it value.
-    break;
-
-  case vmIntrinsics::_compareAndSwapObject:
-#ifdef _LP64
-    if (!UseCompressedOops && !Matcher::match_rule_supported(Op_CompareAndSwapP)) return NULL;
-#endif
-    break;
-
-  case vmIntrinsics::_compareAndSwapLong:
-    if (!Matcher::match_rule_supported(Op_CompareAndSwapL)) return NULL;
-    break;
-
-  case vmIntrinsics::_getAndAddInt:
-    if (!Matcher::match_rule_supported(Op_GetAndAddI)) return NULL;
-    break;
-
-  case vmIntrinsics::_getAndAddLong:
-    if (!Matcher::match_rule_supported(Op_GetAndAddL)) return NULL;
-    break;
-
-  case vmIntrinsics::_getAndSetInt:
-    if (!Matcher::match_rule_supported(Op_GetAndSetI)) return NULL;
-    break;
-
-  case vmIntrinsics::_getAndSetLong:
-    if (!Matcher::match_rule_supported(Op_GetAndSetL)) return NULL;
-    break;
-
-  case vmIntrinsics::_getAndSetObject:
-#ifdef _LP64
-    if (!UseCompressedOops && !Matcher::match_rule_supported(Op_GetAndSetP)) return NULL;
-    if (UseCompressedOops && !Matcher::match_rule_supported(Op_GetAndSetN)) return NULL;
-    break;
-#else
-    if (!Matcher::match_rule_supported(Op_GetAndSetP)) return NULL;
-    break;
-#endif
-
-  case vmIntrinsics::_aescrypt_encryptBlock:
-  case vmIntrinsics::_aescrypt_decryptBlock:
-    if (!UseAESIntrinsics) return NULL;
-    break;
-
-  case vmIntrinsics::_multiplyToLen:
-    if (!UseMultiplyToLenIntrinsic) return NULL;
-    break;
-
-  case vmIntrinsics::_squareToLen:
-    if (!UseSquareToLenIntrinsic) return NULL;
-    break;
-
-  case vmIntrinsics::_mulAdd:
-    if (!UseMulAddIntrinsic) return NULL;
-    break;
-
-  case vmIntrinsics::_montgomeryMultiply:
-     if (!UseMontgomeryMultiplyIntrinsic) return NULL;
-    break;
-  case vmIntrinsics::_montgomerySquare:
-     if (!UseMontgomerySquareIntrinsic) return NULL;
-    break;
-
-  case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt:
-  case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt:
-    if (!UseAESIntrinsics) return NULL;
-    // these two require the predicated logic
-    predicates = 1;
-    break;
-
-  case vmIntrinsics::_sha_implCompress:
-    if (!UseSHA1Intrinsics) return NULL;
-    break;
-
-  case vmIntrinsics::_sha2_implCompress:
-    if (!UseSHA256Intrinsics) return NULL;
-    break;
-
-  case vmIntrinsics::_sha5_implCompress:
-    if (!UseSHA512Intrinsics) return NULL;
-    break;
-
-  case vmIntrinsics::_digestBase_implCompressMB:
-    if (!(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics)) return NULL;
-    predicates = 3;
-    break;
-
-  case vmIntrinsics::_ghash_processBlocks:
-    if (!UseGHASHIntrinsics) return NULL;
-    break;
-
-  case vmIntrinsics::_updateCRC32:
-  case vmIntrinsics::_updateBytesCRC32:
-  case vmIntrinsics::_updateByteBufferCRC32:
-    if (!UseCRC32Intrinsics) return NULL;
-    break;
-
-  case vmIntrinsics::_updateBytesCRC32C:
-  case vmIntrinsics::_updateDirectByteBufferCRC32C:
-    if (!UseCRC32CIntrinsics) return NULL;
-    break;
-
-  case vmIntrinsics::_incrementExactI:
-  case vmIntrinsics::_addExactI:
-    if (!Matcher::match_rule_supported(Op_OverflowAddI) || !UseMathExactIntrinsics) return NULL;
-    break;
-  case vmIntrinsics::_incrementExactL:
-  case vmIntrinsics::_addExactL:
-    if (!Matcher::match_rule_supported(Op_OverflowAddL) || !UseMathExactIntrinsics) return NULL;
-    break;
-  case vmIntrinsics::_decrementExactI:
-  case vmIntrinsics::_subtractExactI:
-    if (!Matcher::match_rule_supported(Op_OverflowSubI) || !UseMathExactIntrinsics) return NULL;
-    break;
-  case vmIntrinsics::_decrementExactL:
-  case vmIntrinsics::_subtractExactL:
-    if (!Matcher::match_rule_supported(Op_OverflowSubL) || !UseMathExactIntrinsics) return NULL;
-    break;
-  case vmIntrinsics::_negateExactI:
-    if (!Matcher::match_rule_supported(Op_OverflowSubI) || !UseMathExactIntrinsics) return NULL;
-    break;
-  case vmIntrinsics::_negateExactL:
-    if (!Matcher::match_rule_supported(Op_OverflowSubL) || !UseMathExactIntrinsics) return NULL;
-    break;
-  case vmIntrinsics::_multiplyExactI:
-    if (!Matcher::match_rule_supported(Op_OverflowMulI) || !UseMathExactIntrinsics) return NULL;
-    break;
-  case vmIntrinsics::_multiplyExactL:
-    if (!Matcher::match_rule_supported(Op_OverflowMulL) || !UseMathExactIntrinsics) return NULL;
-    break;
-
-  case vmIntrinsics::_getShortUnaligned:
-  case vmIntrinsics::_getCharUnaligned:
-  case vmIntrinsics::_getIntUnaligned:
-  case vmIntrinsics::_getLongUnaligned:
-  case vmIntrinsics::_putShortUnaligned:
-  case vmIntrinsics::_putCharUnaligned:
-  case vmIntrinsics::_putIntUnaligned:
-  case vmIntrinsics::_putLongUnaligned:
-    if (!UseUnalignedAccesses) return NULL;
-    break;
-
- default:
+  }
+
+  C2Compiler* compiler = (C2Compiler*)CompileBroker::compiler(CompLevel_full_optimization);
+  bool is_available = false;
+
+  {
+    // For calling is_intrinsic_supported and is_intrinsic_disabled_by_flag
+    // the compiler must transition to '_thread_in_vm' state because both
+    // methods access VM-internal data.
+    VM_ENTRY_MARK;
+    methodHandle mh(THREAD, m->get_Method());
+    methodHandle ct(THREAD, method()->get_Method());
+    is_available = compiler->is_intrinsic_supported(mh, is_virtual) &&
+                   !compiler->is_intrinsic_disabled_by_flag(mh, ct);
+  }
+
+  if (is_available) {
     assert(id <= vmIntrinsics::LAST_COMPILER_INLINE, "caller responsibility");
     assert(id != vmIntrinsics::_Object_init && id != vmIntrinsics::_invoke, "enum out of order?");
-    break;
-  }
-
-  // -XX:-InlineClassNatives disables natives from the Class class.
-  // The flag applies to all reflective calls, notably Array.newArray
-  // (visible to Java programmers as Array.newInstance).
-  if (m->holder()->name() == ciSymbol::java_lang_Class() ||
-      m->holder()->name() == ciSymbol::java_lang_reflect_Array()) {
-    if (!InlineClassNatives)  return NULL;
-  }
-
-  // -XX:-InlineThreadNatives disables natives from the Thread class.
-  if (m->holder()->name() == ciSymbol::java_lang_Thread()) {
-    if (!InlineThreadNatives)  return NULL;
-  }
-
-  // -XX:-InlineMathNatives disables natives from the Math,Float and Double classes.
-  if (m->holder()->name() == ciSymbol::java_lang_Math() ||
-      m->holder()->name() == ciSymbol::java_lang_Float() ||
-      m->holder()->name() == ciSymbol::java_lang_Double()) {
-    if (!InlineMathNatives)  return NULL;
-  }
-
-  // -XX:-InlineUnsafeOps disables natives from the Unsafe class.
-  if (m->holder()->name() == ciSymbol::sun_misc_Unsafe()) {
-    if (!InlineUnsafeOps)  return NULL;
-  }
-
-  return new LibraryIntrinsic(m, is_virtual, predicates, does_virtual_dispatch, (vmIntrinsics::ID) id);
+    return new LibraryIntrinsic(m, is_virtual,
+                                vmIntrinsics::predicates_needed(id),
+                                vmIntrinsics::does_virtual_dispatch(id),
+                                (vmIntrinsics::ID) id);
+  } else {
+    return NULL;
+  }
 }
 
 //----------------------register_library_intrinsics-----------------------
@@ -812,7 +523,6 @@
   case vmIntrinsics::_getLong:                  return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG,    !is_volatile);
   case vmIntrinsics::_getFloat:                 return inline_unsafe_access(!is_native_ptr, !is_store, T_FLOAT,   !is_volatile);
   case vmIntrinsics::_getDouble:                return inline_unsafe_access(!is_native_ptr, !is_store, T_DOUBLE,  !is_volatile);
-
   case vmIntrinsics::_putObject:                return inline_unsafe_access(!is_native_ptr,  is_store, T_OBJECT,  !is_volatile);
   case vmIntrinsics::_putBoolean:               return inline_unsafe_access(!is_native_ptr,  is_store, T_BOOLEAN, !is_volatile);
   case vmIntrinsics::_putByte:                  return inline_unsafe_access(!is_native_ptr,  is_store, T_BYTE,    !is_volatile);
--- a/hotspot/src/share/vm/prims/jvmtiTagMap.cpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/prims/jvmtiTagMap.cpp	Fri Jul 31 10:15:02 2015 -0700
@@ -2824,7 +2824,7 @@
   if (klass->oop_is_instance()) {
     InstanceKlass* ik = InstanceKlass::cast(klass);
 
-    // ignore the class if it's has been initialized yet
+    // Ignore the class if it hasn't been initialized yet
     if (!ik->is_linked()) {
       return true;
     }
--- a/hotspot/src/share/vm/prims/whitebox.cpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/prims/whitebox.cpp	Fri Jul 31 10:15:02 2015 -0700
@@ -528,6 +528,24 @@
   return mh->queued_for_compilation();
 WB_END
 
+WB_ENTRY(jboolean, WB_IsIntrinsicAvailable(JNIEnv* env, jobject o, jobject method, jobject compilation_context, jint compLevel))
+  if (compLevel < CompLevel_none || compLevel > CompLevel_highest_tier) {
+    return false; // Intrinsic is not available on a non-existent compilation level.
+  }
+  jmethodID method_id, compilation_context_id;
+  method_id = reflected_method_to_jmid(thread, env, method);
+  CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
+  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(method_id));
+  if (compilation_context != NULL) {
+    compilation_context_id = reflected_method_to_jmid(thread, env, compilation_context);
+    CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
+    methodHandle cch(THREAD, Method::checked_resolve_jmethod_id(compilation_context_id));
+    return CompileBroker::compiler(compLevel)->is_intrinsic_available(mh, cch);
+  } else {
+    return CompileBroker::compiler(compLevel)->is_intrinsic_available(mh, NULL);
+  }
+WB_END
+
 WB_ENTRY(jint, WB_GetMethodCompilationLevel(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
   jmethodID jmid = reflected_method_to_jmid(thread, env, method);
   CHECK_JNI_EXCEPTION_(env, CompLevel_none);
@@ -1477,14 +1495,17 @@
 #endif // INCLUDE_NMT
   {CC"deoptimizeFrames",   CC"(Z)I",                  (void*)&WB_DeoptimizeFrames  },
   {CC"deoptimizeAll",      CC"()V",                   (void*)&WB_DeoptimizeAll     },
-  {CC"deoptimizeMethod0",   CC"(Ljava/lang/reflect/Executable;Z)I",
-                                                      (void*)&WB_DeoptimizeMethod  },
+    {CC"deoptimizeMethod0",   CC"(Ljava/lang/reflect/Executable;Z)I",
+                                                        (void*)&WB_DeoptimizeMethod  },
   {CC"isMethodCompiled0",   CC"(Ljava/lang/reflect/Executable;Z)Z",
                                                       (void*)&WB_IsMethodCompiled  },
   {CC"isMethodCompilable0", CC"(Ljava/lang/reflect/Executable;IZ)Z",
                                                       (void*)&WB_IsMethodCompilable},
   {CC"isMethodQueuedForCompilation0",
       CC"(Ljava/lang/reflect/Executable;)Z",          (void*)&WB_IsMethodQueuedForCompilation},
+  {CC"isIntrinsicAvailable0",
+      CC"(Ljava/lang/reflect/Executable;Ljava/lang/reflect/Executable;I)Z",
+                                                      (void*)&WB_IsIntrinsicAvailable},
   {CC"makeMethodNotCompilable0",
       CC"(Ljava/lang/reflect/Executable;IZ)V",        (void*)&WB_MakeMethodNotCompilable},
   {CC"testSetDontInlineMethod0",
--- a/hotspot/src/share/vm/runtime/arguments.cpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/runtime/arguments.cpp	Fri Jul 31 10:15:02 2015 -0700
@@ -788,9 +788,11 @@
   st->print_cr("VM Arguments:");
   if (num_jvm_flags() > 0) {
     st->print("jvm_flags: "); print_jvm_flags_on(st);
+    st->cr();
   }
   if (num_jvm_args() > 0) {
     st->print("jvm_args: "); print_jvm_args_on(st);
+    st->cr();
   }
   st->print_cr("java_command: %s", java_command() ? java_command() : "<unknown>");
   if (_java_class_path != NULL) {
@@ -800,12 +802,32 @@
   st->print_cr("Launcher Type: %s", _sun_java_launcher);
 }
 
+void Arguments::print_summary_on(outputStream* st) {
+  // Print the command line.  Environment variables that are helpful for
+  // reproducing the problem are written later in the hs_err file.
+  // flags are from setting file
+  if (num_jvm_flags() > 0) {
+    st->print_raw("Settings File: ");
+    print_jvm_flags_on(st);
+    st->cr();
+  }
+  // args are the command line and environment variable arguments.
+  st->print_raw("Command Line: ");
+  if (num_jvm_args() > 0) {
+    print_jvm_args_on(st);
+  }
+  // this is the classfile and any arguments to the java program
+  if (java_command() != NULL) {
+    st->print("%s", java_command());
+  }
+  st->cr();
+}
+
 void Arguments::print_jvm_flags_on(outputStream* st) {
   if (_num_jvm_flags > 0) {
     for (int i=0; i < _num_jvm_flags; i++) {
       st->print("%s ", _jvm_flags_array[i]);
     }
-    st->cr();
   }
 }
 
@@ -814,7 +836,6 @@
     for (int i=0; i < _num_jvm_args; i++) {
       st->print("%s ", _jvm_args_array[i]);
     }
-    st->cr();
   }
 }
 
@@ -1205,32 +1226,6 @@
   }
 }
 
-/**
- * Returns the minimum number of compiler threads needed to run the JVM. The following
- * configurations are possible.
- *
- * 1) The JVM is build using an interpreter only. As a result, the minimum number of
- *    compiler threads is 0.
- * 2) The JVM is build using the compiler(s) and tiered compilation is disabled. As
- *    a result, either C1 or C2 is used, so the minimum number of compiler threads is 1.
- * 3) The JVM is build using the compiler(s) and tiered compilation is enabled. However,
- *    the option "TieredStopAtLevel < CompLevel_full_optimization". As a result, only
- *    C1 can be used, so the minimum number of compiler threads is 1.
- * 4) The JVM is build using the compilers and tiered compilation is enabled. The option
- *    'TieredStopAtLevel = CompLevel_full_optimization' (the default value). As a result,
- *    the minimum number of compiler threads is 2.
- */
-int Arguments::get_min_number_of_compiler_threads() {
-#if !defined(COMPILER1) && !defined(COMPILER2) && !defined(SHARK)
-  return 0;   // case 1
-#else
-  if (!TieredCompilation || (TieredStopAtLevel < CompLevel_full_optimization)) {
-    return 1; // case 2 or case 3
-  }
-  return 2;   // case 4 (tiered)
-#endif
-}
-
 #if INCLUDE_ALL_GCS
 static void disable_adaptive_size_policy(const char* collector_name) {
   if (UseAdaptiveSizePolicy) {
@@ -2178,10 +2173,6 @@
     status = false;
   }
 
-  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");
-
   if (!FLAG_IS_DEFAULT(CICompilerCount) && !FLAG_IS_DEFAULT(CICompilerCountPerCPU) && CICompilerCountPerCPU) {
     warning("The VM option CICompilerCountPerCPU overrides CICompilerCount.");
   }
@@ -3989,10 +3980,10 @@
   return JNI_OK;
 }
 
-// Any custom code post the final range and constraint check
+// Any custom code post the 'CommandLineFlagConstraint::AfterErgo' 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) {
+void Arguments::post_after_ergo_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;
--- a/hotspot/src/share/vm/runtime/arguments.hpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/runtime/arguments.hpp	Fri Jul 31 10:15:02 2015 -0700
@@ -445,9 +445,6 @@
   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);
@@ -466,8 +463,8 @@
   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);
+  // Set any arguments that need to be set after the 'CommandLineFlagConstraint::AfterErgo' constraint check
+  static void post_after_ergo_constraint_check(bool check_passed);
 
   static void set_gc_specific_flags();
   static inline bool gc_selected(); // whether a gc has been selected
@@ -495,6 +492,7 @@
 
   // print jvm_flags, jvm_args and java_command
   static void print_on(outputStream* st);
+  static void print_summary_on(outputStream* st);
 
   // convenient methods to obtain / print jvm_flags and jvm_args
   static const char* jvm_flags()           { return build_resource_string(_jvm_flags_array, _num_jvm_flags); }
--- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.cpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.cpp	Fri Jul 31 10:15:02 2015 -0700
@@ -39,7 +39,9 @@
 
 public:
   // the "name" argument must be a string literal
-  CommandLineFlagConstraint_bool(const char* name, CommandLineFlagConstraintFunc_bool func) : CommandLineFlagConstraint(name) {
+  CommandLineFlagConstraint_bool(const char* name,
+                                 CommandLineFlagConstraintFunc_bool func,
+                                 ConstraintType type) : CommandLineFlagConstraint(name, type) {
     _constraint=func;
   }
 
@@ -53,7 +55,9 @@
 
 public:
   // the "name" argument must be a string literal
-  CommandLineFlagConstraint_int(const char* name, CommandLineFlagConstraintFunc_int func) : CommandLineFlagConstraint(name) {
+  CommandLineFlagConstraint_int(const char* name,
+                                CommandLineFlagConstraintFunc_int func,
+                                ConstraintType type) : CommandLineFlagConstraint(name, type) {
     _constraint=func;
   }
 
@@ -67,7 +71,9 @@
 
 public:
   // the "name" argument must be a string literal
-  CommandLineFlagConstraint_intx(const char* name, CommandLineFlagConstraintFunc_intx func) : CommandLineFlagConstraint(name) {
+  CommandLineFlagConstraint_intx(const char* name,
+                                 CommandLineFlagConstraintFunc_intx func,
+                                 ConstraintType type) : CommandLineFlagConstraint(name, type) {
     _constraint=func;
   }
 
@@ -81,7 +87,9 @@
 
 public:
   // the "name" argument must be a string literal
-  CommandLineFlagConstraint_uint(const char* name, CommandLineFlagConstraintFunc_uint func) : CommandLineFlagConstraint(name) {
+  CommandLineFlagConstraint_uint(const char* name,
+                                 CommandLineFlagConstraintFunc_uint func,
+                                 ConstraintType type) : CommandLineFlagConstraint(name, type) {
     _constraint=func;
   }
 
@@ -95,7 +103,9 @@
 
 public:
   // the "name" argument must be a string literal
-  CommandLineFlagConstraint_uintx(const char* name, CommandLineFlagConstraintFunc_uintx func) : CommandLineFlagConstraint(name) {
+  CommandLineFlagConstraint_uintx(const char* name,
+                                  CommandLineFlagConstraintFunc_uintx func,
+                                  ConstraintType type) : CommandLineFlagConstraint(name, type) {
     _constraint=func;
   }
 
@@ -109,7 +119,9 @@
 
 public:
   // the "name" argument must be a string literal
-  CommandLineFlagConstraint_uint64_t(const char* name, CommandLineFlagConstraintFunc_uint64_t func) : CommandLineFlagConstraint(name) {
+  CommandLineFlagConstraint_uint64_t(const char* name,
+                                     CommandLineFlagConstraintFunc_uint64_t func,
+                                     ConstraintType type) : CommandLineFlagConstraint(name, type) {
     _constraint=func;
   }
 
@@ -123,7 +135,9 @@
 
 public:
   // the "name" argument must be a string literal
-  CommandLineFlagConstraint_size_t(const char* name, CommandLineFlagConstraintFunc_size_t func) : CommandLineFlagConstraint(name) {
+  CommandLineFlagConstraint_size_t(const char* name,
+                                   CommandLineFlagConstraintFunc_size_t func,
+                                   ConstraintType type) : CommandLineFlagConstraint(name, type) {
     _constraint=func;
   }
 
@@ -137,7 +151,9 @@
 
 public:
   // the "name" argument must be a string literal
-  CommandLineFlagConstraint_double(const char* name, CommandLineFlagConstraintFunc_double func) : CommandLineFlagConstraint(name) {
+  CommandLineFlagConstraint_double(const char* name,
+                                   CommandLineFlagConstraintFunc_double func,
+                                   ConstraintType type) : CommandLineFlagConstraint(name, type) {
     _constraint=func;
   }
 
@@ -162,29 +178,29 @@
 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_bool(const char* name, CommandLineFlagConstraintFunc_bool func, CommandLineFlagConstraint::ConstraintType type) {
+  CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_bool(name, func, type));
 }
-void emit_constraint_int(const char* name, CommandLineFlagConstraintFunc_int func) {
-  CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_int(name, func));
+void emit_constraint_int(const char* name, CommandLineFlagConstraintFunc_int func, CommandLineFlagConstraint::ConstraintType type) {
+  CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_int(name, func, type));
 }
-void emit_constraint_intx(const char* name, CommandLineFlagConstraintFunc_intx func) {
-  CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_intx(name, func));
+void emit_constraint_intx(const char* name, CommandLineFlagConstraintFunc_intx func, CommandLineFlagConstraint::ConstraintType type) {
+  CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_intx(name, func, type));
 }
-void emit_constraint_uint(const char* name, CommandLineFlagConstraintFunc_uint func) {
-  CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_uint(name, func));
+void emit_constraint_uint(const char* name, CommandLineFlagConstraintFunc_uint func, CommandLineFlagConstraint::ConstraintType type) {
+  CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_uint(name, func, type));
 }
-void emit_constraint_uintx(const char* name, CommandLineFlagConstraintFunc_uintx func) {
-  CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_uintx(name, func));
+void emit_constraint_uintx(const char* name, CommandLineFlagConstraintFunc_uintx func, CommandLineFlagConstraint::ConstraintType type) {
+  CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_uintx(name, func, type));
 }
-void emit_constraint_uint64_t(const char* name, CommandLineFlagConstraintFunc_uint64_t func) {
-  CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_uint64_t(name, func));
+void emit_constraint_uint64_t(const char* name, CommandLineFlagConstraintFunc_uint64_t func, CommandLineFlagConstraint::ConstraintType type) {
+  CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_uint64_t(name, func, type));
 }
-void emit_constraint_size_t(const char* name, CommandLineFlagConstraintFunc_size_t func) {
-  CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_size_t(name, func));
+void emit_constraint_size_t(const char* name, CommandLineFlagConstraintFunc_size_t func, CommandLineFlagConstraint::ConstraintType type) {
+  CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_size_t(name, func, type));
 }
-void emit_constraint_double(const char* name, CommandLineFlagConstraintFunc_double func) {
-  CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_double(name, func));
+void emit_constraint_double(const char* name, CommandLineFlagConstraintFunc_double func, CommandLineFlagConstraint::ConstraintType type) {
+  CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_double(name, func, type));
 }
 
 // Generate code to call emit_constraint_xxx function
@@ -201,16 +217,17 @@
 #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
+#define EMIT_CONSTRAINT_CHECK(func, type)                               , func, CommandLineFlagConstraint::type
 
 // the "name" argument must be a string literal
-#define INITIAL_CONTRAINTS_SIZE 16
+#define INITIAL_CONSTRAINTS_SIZE 16
 GrowableArray<CommandLineFlagConstraint*>* CommandLineFlagConstraintList::_constraints = NULL;
+CommandLineFlagConstraint::ConstraintType CommandLineFlagConstraintList::_validating_type = CommandLineFlagConstraint::AtParse;
 
 // 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);
+  _constraints = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<CommandLineFlagConstraint*>(INITIAL_CONSTRAINTS_SIZE, true);
 
   emit_constraint_no(NULL RUNTIME_FLAGS(EMIT_CONSTRAINT_DEVELOPER_FLAG,
                                         EMIT_CONSTRAINT_PD_DEVELOPER_FLAG,
@@ -273,14 +290,89 @@
 #endif // INCLUDE_ALL_GCS
 }
 
-CommandLineFlagConstraint* CommandLineFlagConstraintList::find(const char* name) {
+// Find constraints by name and return only if found constraint's type is equal or lower than current validating type.
+CommandLineFlagConstraint* CommandLineFlagConstraintList::find_if_needs_check(const char* name) {
   CommandLineFlagConstraint* found = NULL;
   for (int i=0; i<length(); i++) {
     CommandLineFlagConstraint* constraint = at(i);
-    if (strcmp(constraint->name(), name) == 0) {
+    if ((strcmp(constraint->name(), name) == 0) &&
+        (constraint->type() <= _validating_type)) {
       found = constraint;
       break;
     }
   }
   return found;
 }
+
+// Check constraints for specific constraint type.
+bool CommandLineFlagConstraintList::check_constraints(CommandLineFlagConstraint::ConstraintType type) {
+//#define PRINT_CONSTRAINTS_SIZES
+#ifdef PRINT_CONSTRAINTS_SIZES
+  {
+    size_t size_constraints = sizeof(CommandLineFlagConstraintList);
+    for (int i=0; i<length(); i++) {
+      size_constraints += sizeof(CommandLineFlagConstraint);
+      CommandLineFlagConstraint* constraint = 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",
+            length(), size_constraints);
+  }
+#endif // PRINT_CONSTRAINTS_SIZES
+
+  // Skip if we already checked.
+  if (type < _validating_type) {
+    return true;
+  }
+  _validating_type = type;
+
+  bool status = true;
+  for (int i=0; i<length(); i++) {
+    CommandLineFlagConstraint* constraint = at(i);
+    if (type != constraint->type()) continue;
+    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;
+      }
+    }
+  }
+  return status;
+}
--- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.hpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.hpp	Fri Jul 31 10:15:02 2015 -0700
@@ -49,13 +49,27 @@
 typedef Flag::Error (*CommandLineFlagConstraintFunc_double)(bool verbose, double* value);
 
 class CommandLineFlagConstraint : public CHeapObj<mtInternal> {
+public:
+  // During VM initialization, constraint validation will be done order of ConstraintType.
+  enum ConstraintType {
+    // Will be validated during argument processing (Arguments::parse_argument).
+    AtParse         = 0,
+    // Will be validated by CommandLineFlags::check_constraints_of_after_ergo().
+    AfterErgo      = 1,
+    // Will be validated by CommandLineFlags::check_constraints_of_after_memory_init().
+    AfterMemoryInit = 2
+  };
+
 private:
   const char* _name;
+  ConstraintType _validate_type;
+
 public:
   // the "name" argument must be a string literal
-  CommandLineFlagConstraint(const char* name) { _name=name; };
+  CommandLineFlagConstraint(const char* name, ConstraintType type) { _name=name; _validate_type=type; };
   ~CommandLineFlagConstraint() {};
-  const char* name() { return _name; }
+  const char* name() const { return _name; }
+  ConstraintType type() const { return _validate_type; }
   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; };
@@ -69,12 +83,17 @@
 class CommandLineFlagConstraintList : public AllStatic {
 private:
   static GrowableArray<CommandLineFlagConstraint*>* _constraints;
+  // Latest constraint validation type.
+  static CommandLineFlagConstraint::ConstraintType _validating_type;
 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 CommandLineFlagConstraint* find_if_needs_check(const char* name);
   static void add(CommandLineFlagConstraint* constraint) { _constraints->append(constraint); }
+  // True if 'AfterErgo' or later constraint functions are validated.
+  static bool validated_after_ergo() { return _validating_type >= CommandLineFlagConstraint::AfterErgo; };
+  static bool check_constraints(CommandLineFlagConstraint::ConstraintType type);
 };
 
 #endif /* SHARE_VM_RUNTIME_COMMANDLINEFLAGCONSTRAINTLIST_HPP */
--- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.cpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.cpp	Fri Jul 31 10:15:02 2015 -0700
@@ -29,16 +29,57 @@
 #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;
+  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;
+  } else {
+    return Flag::SUCCESS;
   }
-  return Flag::SUCCESS;
 }
+
+/**
+ * Validate the minimum number of compiler threads needed to run the
+ * JVM. The following configurations are possible.
+ *
+ * 1) The JVM is build using an interpreter only. As a result, the minimum number of
+ *    compiler threads is 0.
+ * 2) The JVM is build using the compiler(s) and tiered compilation is disabled. As
+ *    a result, either C1 or C2 is used, so the minimum number of compiler threads is 1.
+ * 3) The JVM is build using the compiler(s) and tiered compilation is enabled. However,
+ *    the option "TieredStopAtLevel < CompLevel_full_optimization". As a result, only
+ *    C1 can be used, so the minimum number of compiler threads is 1.
+ * 4) The JVM is build using the compilers and tiered compilation is enabled. The option
+ *    'TieredStopAtLevel = CompLevel_full_optimization' (the default value). As a result,
+ *    the minimum number of compiler threads is 2.
+ */
+Flag::Error CICompilerCountConstraintFunc(bool verbose, intx* value) {
+  int min_number_of_compiler_threads = 0;
+#if !defined(COMPILER1) && !defined(COMPILER2) && !defined(SHARK)
+  // case 1
+#else
+  if (!TieredCompilation || (TieredStopAtLevel < CompLevel_full_optimization)) {
+    min_number_of_compiler_threads = 1; // case 2 or case 3
+  } else {
+    min_number_of_compiler_threads = 2;   // case 4 (tiered)
+  }
+#endif
+
+  // 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");
+
+  if (*value < (intx)min_number_of_compiler_threads) {
+    if (verbose == true) {
+      jio_fprintf(defaultStream::error_stream(),
+                  "CICompilerCount=" INTX_FORMAT " must be at least %d \n",
+                  *value, min_number_of_compiler_threads);
+    }
+    return Flag::VIOLATES_CONSTRAINT;
+  } else {
+    return Flag::SUCCESS;
+  }
+}
--- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.hpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.hpp	Fri Jul 31 10:15:02 2015 -0700
@@ -36,4 +36,6 @@
 
 Flag::Error AliasLevelConstraintFunc(bool verbose, intx* value);
 
+Flag::Error CICompilerCountConstraintFunc(bool verbose, intx* value);
+
 #endif /* SHARE_VM_RUNTIME_COMMANDLINEFLAGCONSTRAINTSCOMPILER_HPP */
--- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.cpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.cpp	Fri Jul 31 10:15:02 2015 -0700
@@ -30,6 +30,9 @@
 
 #if INCLUDE_ALL_GCS
 #include "gc/g1/g1_globals.hpp"
+#include "gc/g1/heapRegionBounds.inline.hpp"
+#include "gc/parallel/parallelScavengeHeap.hpp"
+#include "gc/shared/plab.hpp"
 #endif // INCLUDE_ALL_GCS
 #ifdef COMPILER1
 #include "c1/c1_globals.hpp"
@@ -38,8 +41,49 @@
 #include "opto/c2_globals.hpp"
 #endif // COMPILER2
 
+static Flag::Error MinPLABSizeBounds(const char* name, bool verbose, size_t* value) {
+#if INCLUDE_ALL_GCS
+  if ((UseConcMarkSweepGC || UseG1GC) && (*value < PLAB::min_size())) {
+    if (verbose == true) {
+      jio_fprintf(defaultStream::error_stream(),
+                  "%s (" SIZE_FORMAT ") must be greater than "
+                  "ergonomic PLAB minimum size (" SIZE_FORMAT ")\n",
+                  name, *value, PLAB::min_size());
+    }
+    return Flag::VIOLATES_CONSTRAINT;
+  }
+#endif // INCLUDE_ALL_GCS
+  return Flag::SUCCESS;
+}
+
+static Flag::Error MaxPLABSizeBounds(const char* name, bool verbose, size_t* value) {
+#if INCLUDE_ALL_GCS
+  if ((UseConcMarkSweepGC || UseG1GC) && (*value > PLAB::max_size())) {
+    if (verbose == true) {
+      jio_fprintf(defaultStream::error_stream(),
+                  "%s (" SIZE_FORMAT ") must be less than "
+                  "ergonomic PLAB maximum size (" SIZE_FORMAT ")\n",
+                  name, *value, PLAB::max_size());
+    }
+    return Flag::VIOLATES_CONSTRAINT;
+  }
+#endif // INCLUDE_ALL_GCS
+  return Flag::SUCCESS;
+}
+
+static Flag::Error MinMaxPLABSizeBounds(const char* name, bool verbose, size_t* value) {
+  if (MinPLABSizeBounds(name, verbose, value) == Flag::SUCCESS) {
+    return MaxPLABSizeBounds(name, verbose, value);
+  }
+  return Flag::VIOLATES_CONSTRAINT;
+}
+
+Flag::Error YoungPLABSizeConstraintFunc(bool verbose, size_t* value) {
+  return MinMaxPLABSizeBounds("YoungPLABSize", verbose, value);
+}
+
 Flag::Error MinHeapFreeRatioConstraintFunc(bool verbose, uintx* value) {
-  if ((CommandLineFlags::finishedInitializing()) && (*value > MaxHeapFreeRatio)) {
+  if (*value > MaxHeapFreeRatio) {
     if (verbose == true) {
       jio_fprintf(defaultStream::error_stream(),
                   "MinHeapFreeRatio (" UINTX_FORMAT ") must be less than or "
@@ -53,7 +97,7 @@
 }
 
 Flag::Error MaxHeapFreeRatioConstraintFunc(bool verbose, uintx* value) {
-  if ((CommandLineFlags::finishedInitializing()) && (*value < MinHeapFreeRatio)) {
+  if (*value < MinHeapFreeRatio) {
     if (verbose == true) {
       jio_fprintf(defaultStream::error_stream(),
                   "MaxHeapFreeRatio (" UINTX_FORMAT ") must be greater than or "
@@ -67,7 +111,7 @@
 }
 
 Flag::Error MinMetaspaceFreeRatioConstraintFunc(bool verbose, uintx* value) {
-  if ((CommandLineFlags::finishedInitializing()) && (*value > MaxMetaspaceFreeRatio)) {
+  if (*value > MaxMetaspaceFreeRatio) {
     if (verbose == true) {
       jio_fprintf(defaultStream::error_stream(),
                   "MinMetaspaceFreeRatio (" UINTX_FORMAT ") must be less than or "
@@ -81,7 +125,7 @@
 }
 
 Flag::Error MaxMetaspaceFreeRatioConstraintFunc(bool verbose, uintx* value) {
-  if ((CommandLineFlags::finishedInitializing()) && (*value < MinMetaspaceFreeRatio)) {
+  if (*value < MinMetaspaceFreeRatio) {
     if (verbose == true) {
       jio_fprintf(defaultStream::error_stream(),
                   "MaxMetaspaceFreeRatio (" UINTX_FORMAT ") must be greater than or "
@@ -106,7 +150,7 @@
 Flag::Error InitialTenuringThresholdConstraintFunc(bool verbose, uintx* value) {
   UseConcMarkSweepGCWorkaroundIfNeeded(*value, MaxTenuringThreshold);
 
-  if ((CommandLineFlags::finishedInitializing()) && (*value > MaxTenuringThreshold)) {
+  if (*value > MaxTenuringThreshold) {
     if (verbose == true) {
       jio_fprintf(defaultStream::error_stream(),
                   "InitialTenuringThreshold (" UINTX_FORMAT ") must be less than or "
@@ -122,7 +166,7 @@
 Flag::Error MaxTenuringThresholdConstraintFunc(bool verbose, uintx* value) {
   UseConcMarkSweepGCWorkaroundIfNeeded(InitialTenuringThreshold, *value);
 
-  if ((CommandLineFlags::finishedInitializing()) && (*value < InitialTenuringThreshold)) {
+  if (*value < InitialTenuringThreshold) {
     if (verbose == true) {
       jio_fprintf(defaultStream::error_stream(),
                   "MaxTenuringThreshold (" UINTX_FORMAT ") must be greater than or "
@@ -136,9 +180,8 @@
 }
 
 #if INCLUDE_ALL_GCS
-
 Flag::Error G1NewSizePercentConstraintFunc(bool verbose, uintx* value) {
-  if ((CommandLineFlags::finishedInitializing()) && (*value > G1MaxNewSizePercent)) {
+  if (*value > G1MaxNewSizePercent) {
     if (verbose == true) {
       jio_fprintf(defaultStream::error_stream(),
                   "G1NewSizePercent (" UINTX_FORMAT ") must be less than or "
@@ -152,7 +195,7 @@
 }
 
 Flag::Error G1MaxNewSizePercentConstraintFunc(bool verbose, uintx* value) {
-  if ((CommandLineFlags::finishedInitializing()) && (*value < G1NewSizePercent)) {
+  if (*value < G1NewSizePercent) {
     if (verbose == true) {
       jio_fprintf(defaultStream::error_stream(),
                   "G1MaxNewSizePercent (" UINTX_FORMAT ") must be greater than or "
@@ -168,7 +211,7 @@
 #endif // INCLUDE_ALL_GCS
 
 Flag::Error CMSOldPLABMinConstraintFunc(bool verbose, size_t* value) {
-  if ((CommandLineFlags::finishedInitializing()) && (*value > CMSOldPLABMax)) {
+  if (*value > CMSOldPLABMax) {
     if (verbose == true) {
       jio_fprintf(defaultStream::error_stream(),
                   "CMSOldPLABMin (" SIZE_FORMAT ") must be less than or "
@@ -182,7 +225,7 @@
 }
 
 Flag::Error CMSPrecleanDenominatorConstraintFunc(bool verbose, uintx* value) {
-  if ((CommandLineFlags::finishedInitializing()) && (*value <= CMSPrecleanNumerator)) {
+  if (*value <= CMSPrecleanNumerator) {
     if (verbose == true) {
       jio_fprintf(defaultStream::error_stream(),
                   "CMSPrecleanDenominator (" UINTX_FORMAT ") must be strickly greater than "
@@ -196,7 +239,7 @@
 }
 
 Flag::Error CMSPrecleanNumeratorConstraintFunc(bool verbose, uintx* value) {
-  if ((CommandLineFlags::finishedInitializing()) && (*value > (CMSPrecleanDenominator - 1))) {
+  if (*value > (CMSPrecleanDenominator - 1)) {
     if (verbose == true) {
       jio_fprintf(defaultStream::error_stream(),
                   "CMSPrecleanNumerator (" UINTX_FORMAT ") must be less than or "
@@ -210,25 +253,23 @@
 }
 
 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 != 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);
       }
-      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::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;
--- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.hpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.hpp	Fri Jul 31 10:15:02 2015 -0700
@@ -34,6 +34,8 @@
  * an appropriate error value.
  */
 
+Flag::Error YoungPLABSizeConstraintFunc(bool verbose, size_t* value);
+
 Flag::Error MinHeapFreeRatioConstraintFunc(bool verbose, uintx* value);
 Flag::Error MaxHeapFreeRatioConstraintFunc(bool verbose, uintx* value);
 
--- a/hotspot/src/share/vm/runtime/commandLineFlagRangeList.cpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/runtime/commandLineFlagRangeList.cpp	Fri Jul 31 10:15:02 2015 -0700
@@ -365,3 +365,63 @@
     st->print("[                           ...                           ]");
   }
 }
+
+bool CommandLineFlagRangeList::check_ranges() {
+//#define PRINT_RANGES_SIZES
+#ifdef PRINT_RANGES_SIZES
+  {
+    size_t size_ranges = sizeof(CommandLineFlagRangeList);
+    for (int i=0; i<length(); i++) {
+      size_ranges += sizeof(CommandLineFlagRange);
+      CommandLineFlagRange* range = 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",
+            length(), size_ranges);
+  }
+#endif // PRINT_RANGES_SIZES
+
+  // Check ranges.
+  bool status = true;
+  for (int i=0; i<length(); i++) {
+    CommandLineFlagRange* range = 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;
+      }
+    }
+  }
+  return status;
+}
--- a/hotspot/src/share/vm/runtime/commandLineFlagRangeList.hpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/runtime/commandLineFlagRangeList.hpp	Fri Jul 31 10:15:02 2015 -0700
@@ -66,6 +66,8 @@
   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);
+  // Check the final values of all flags for ranges.
+  static bool check_ranges();
 };
 
 #endif // SHARE_VM_RUNTIME_COMMANDLINEFLAGRANGELIST_HPP
--- a/hotspot/src/share/vm/runtime/globals.cpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/runtime/globals.cpp	Fri Jul 31 10:15:02 2015 -0700
@@ -770,7 +770,7 @@
 
 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);
+  CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find_if_needs_check(name);
   if (constraint != NULL) {
     status = constraint->apply_bool(new_value, verbose);
   }
@@ -789,7 +789,7 @@
   Flag* result = Flag::find_flag(name, len);
   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());
+  Flag::Error check = apply_constraint_and_check_range_bool(name, value, !CommandLineFlagConstraintList::validated_after_ergo());
   if (check != Flag::SUCCESS) return check;
   bool old_value = result->get_bool();
   trace_flag_changed<EventBooleanFlagChanged, bool>(name, old_value, *value, origin);
@@ -817,7 +817,7 @@
     range_status = range->check_int(*new_value, verbose);
   }
   Flag::Error constraint_status = Flag::SUCCESS;
-  CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find(name);
+  CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find_if_needs_check(name);
   if (constraint != NULL) {
     constraint_status = constraint->apply_int(new_value, verbose);
   }
@@ -836,7 +836,7 @@
   Flag* result = Flag::find_flag(name, len);
   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());
+  Flag::Error check = apply_constraint_and_check_range_int(name, value, !CommandLineFlagConstraintList::validated_after_ergo());
   if (check != Flag::SUCCESS) return check;
   int old_value = result->get_int();
   trace_flag_changed<EventIntFlagChanged, s4>(name, old_value, *value, origin);
@@ -862,7 +862,7 @@
     range_status = range->check_uint(*new_value, verbose);
   }
   Flag::Error constraint_status = Flag::SUCCESS;
-  CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find(name);
+  CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find_if_needs_check(name);
   if (constraint != NULL) {
     constraint_status = constraint->apply_uint(new_value, verbose);
   }
@@ -881,7 +881,7 @@
   Flag* result = Flag::find_flag(name, len);
   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());
+  Flag::Error check = apply_constraint_and_check_range_uint(name, value, !CommandLineFlagConstraintList::validated_after_ergo());
   if (check != Flag::SUCCESS) return check;
   uint old_value = result->get_uint();
   trace_flag_changed<EventUnsignedIntFlagChanged, u4>(name, old_value, *value, origin);
@@ -915,7 +915,7 @@
     range_status = range->check_intx(*new_value, verbose);
   }
   Flag::Error constraint_status = Flag::SUCCESS;
-  CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find(name);
+  CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find_if_needs_check(name);
   if (constraint != NULL) {
     constraint_status = constraint->apply_intx(new_value, verbose);
   }
@@ -926,7 +926,7 @@
   Flag* result = Flag::find_flag(name, len);
   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());
+  Flag::Error check = apply_constraint_and_check_range_intx(name, value, !CommandLineFlagConstraintList::validated_after_ergo());
   if (check != Flag::SUCCESS) return check;
   intx old_value = result->get_intx();
   trace_flag_changed<EventLongFlagChanged, intx>(name, old_value, *value, origin);
@@ -962,7 +962,7 @@
     range_status = range->check_uintx(*new_value, verbose);
   }
   Flag::Error constraint_status = Flag::SUCCESS;
-  CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find(name);
+  CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find_if_needs_check(name);
   if (constraint != NULL) {
     constraint_status = constraint->apply_uintx(new_value, verbose);
   }
@@ -973,7 +973,7 @@
   Flag* result = Flag::find_flag(name, len);
   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());
+  Flag::Error check = apply_constraint_and_check_range_uintx(name, value, !CommandLineFlagConstraintList::validated_after_ergo());
   if (check != Flag::SUCCESS) return check;
   uintx old_value = result->get_uintx();
   trace_flag_changed<EventUnsignedLongFlagChanged, u8>(name, old_value, *value, origin);
@@ -1009,7 +1009,7 @@
     range_status = range->check_uint64_t(*new_value, verbose);
   }
   Flag::Error constraint_status = Flag::SUCCESS;
-  CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find(name);
+  CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find_if_needs_check(name);
   if (constraint != NULL) {
     constraint_status = constraint->apply_uint64_t(new_value, verbose);
   }
@@ -1020,7 +1020,7 @@
   Flag* result = Flag::find_flag(name, len);
   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());
+  Flag::Error check = apply_constraint_and_check_range_uint64_t(name, value, !CommandLineFlagConstraintList::validated_after_ergo());
   if (check != Flag::SUCCESS) return check;
   uint64_t old_value = result->get_uint64_t();
   trace_flag_changed<EventUnsignedLongFlagChanged, u8>(name, old_value, *value, origin);
@@ -1056,7 +1056,7 @@
     range_status = range->check_size_t(*new_value, verbose);
   }
   Flag::Error constraint_status = Flag::SUCCESS;
-  CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find(name);
+  CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find_if_needs_check(name);
   if (constraint != NULL) {
     constraint_status = constraint->apply_size_t(new_value, verbose);
   }
@@ -1067,7 +1067,7 @@
   Flag* result = Flag::find_flag(name, len);
   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());
+  Flag::Error check = apply_constraint_and_check_range_size_t(name, value, !CommandLineFlagConstraintList::validated_after_ergo());
   if (check != Flag::SUCCESS) return check;
   size_t old_value = result->get_size_t();
   trace_flag_changed<EventUnsignedLongFlagChanged, u8>(name, old_value, *value, origin);
@@ -1103,7 +1103,7 @@
     range_status = range->check_double(*new_value, verbose);
   }
   Flag::Error constraint_status = Flag::SUCCESS;
-  CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find(name);
+  CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find_if_needs_check(name);
   if (constraint != NULL) {
     constraint_status = constraint->apply_double(new_value, verbose);
   }
@@ -1114,7 +1114,7 @@
   Flag* result = Flag::find_flag(name, len);
   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());
+  Flag::Error check = apply_constraint_and_check_range_double(name, value, !CommandLineFlagConstraintList::validated_after_ergo());
   if (check != Flag::SUCCESS) return check;
   double old_value = result->get_double();
   trace_flag_changed<EventDoubleFlagChanged, double>(name, old_value, *value, origin);
@@ -1127,7 +1127,7 @@
 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());
+  Flag::Error check = apply_constraint_and_check_range_double(faddr->_name, &value);
   if (check != Flag::SUCCESS) return check;
   trace_flag_changed<EventDoubleFlagChanged, double>(faddr->_name, faddr->get_double(), value, origin);
   faddr->set_double(value);
@@ -1210,129 +1210,6 @@
   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() {
--- a/hotspot/src/share/vm/runtime/globals.hpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/runtime/globals.hpp	Fri Jul 31 10:15:02 2015 -0700
@@ -450,7 +450,6 @@
 
 
 class CommandLineFlags {
-  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); }
@@ -506,12 +505,6 @@
   // 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;
 };
 
@@ -640,7 +633,7 @@
   lp64_product(intx, ObjectAlignmentInBytes, 8,                             \
           "Default object alignment in bytes, 8 is minimum")                \
           range(8, 256)                                                     \
-          constraint(ObjectAlignmentInBytesConstraintFunc)                  \
+          constraint(ObjectAlignmentInBytesConstraintFunc,AtParse)          \
                                                                             \
   product(bool, AssumeMP, false,                                            \
           "Instruct the VM to assume multiple processors are available")    \
@@ -1286,7 +1279,7 @@
                                                                             \
   experimental(intx, SyncVerbose, 0, "(Unstable)")                          \
                                                                             \
-  product(bool, InlineNotify, true, "intrinsify subset of notify" )         \
+  diagnostic(bool, InlineNotify, true, "intrinsify subset of notify")       \
                                                                             \
   experimental(intx, ClearFPUAtPark, 0, "(Unsafe, Unstable)")               \
                                                                             \
@@ -1396,7 +1389,7 @@
   product(intx, ContendedPaddingWidth, 128,                                 \
           "How many bytes to pad the fields/classes marked @Contended with")\
           range(0, 8192)                                                    \
-          constraint(ContendedPaddingWidthConstraintFunc)                   \
+          constraint(ContendedPaddingWidthConstraintFunc,AtParse)           \
                                                                             \
   product(bool, EnableContended, true,                                      \
           "Enable @Contended annotation support")                           \
@@ -1597,6 +1590,7 @@
                                                                             \
   product(size_t, YoungPLABSize, 4096,                                      \
           "Size of young gen promotion LAB's (in HeapWords)")               \
+          constraint(YoungPLABSizeConstraintFunc,AfterMemoryInit)           \
                                                                             \
   product(size_t, OldPLABSize, 1024,                                        \
           "Size of old gen promotion LAB's (in HeapWords), or Number        \
@@ -1735,7 +1729,7 @@
           "Minimum size of CMS gen promotion LAB caches per worker "        \
           "per block size")                                                 \
           range(1, max_uintx)                                               \
-          constraint(CMSOldPLABMinConstraintFunc)                           \
+          constraint(CMSOldPLABMinConstraintFunc,AfterErgo)                 \
                                                                             \
   product(uintx, CMSOldPLABNumRefills, 4,                                   \
           "Nominal number of refills of CMS gen promotion LAB cache "       \
@@ -1931,13 +1925,13 @@
           "CMSPrecleanNumerator:CMSPrecleanDenominator yields convergence " \
           "ratio")                                                          \
           range(1, max_uintx)                                               \
-          constraint(CMSPrecleanDenominatorConstraintFunc)                  \
+          constraint(CMSPrecleanDenominatorConstraintFunc,AfterErgo)        \
                                                                             \
   product(uintx, CMSPrecleanNumerator, 2,                                   \
           "CMSPrecleanNumerator:CMSPrecleanDenominator yields convergence " \
           "ratio")                                                          \
           range(0, max_uintx-1)                                             \
-          constraint(CMSPrecleanNumeratorConstraintFunc)                    \
+          constraint(CMSPrecleanNumeratorConstraintFunc,AfterErgo)          \
                                                                             \
   product(bool, CMSPrecleanRefLists1, true,                                 \
           "Preclean ref lists during (initial) preclean phase")             \
@@ -2649,8 +2643,8 @@
   /* 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)                                                   \
+          range(0, max_jint)                                                \
+          constraint(CICompilerCountConstraintFunc, AtParse)                \
                                                                             \
   product(intx, CompilationPolicyChoice, 0,                                 \
           "which compilation policy (0-3)")                                 \
@@ -3361,14 +3355,14 @@
           " For most GCs this applies to the old generation. In G1 and"     \
           " ParallelGC it applies to the whole heap.")                      \
           range(0, 100)                                                     \
-          constraint(MinHeapFreeRatioConstraintFunc)                        \
+          constraint(MinHeapFreeRatioConstraintFunc,AfterErgo)              \
                                                                             \
   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)                        \
+          constraint(MaxHeapFreeRatioConstraintFunc,AfterErgo)              \
                                                                             \
   product(intx, SoftRefLRUPolicyMSPerMB, 1000,                              \
           "Number of milliseconds per MB of free space in the heap")        \
@@ -3383,13 +3377,13 @@
           "The maximum percentage of Metaspace free after GC to avoid "     \
           "shrinking")                                                      \
           range(0, 100)                                                     \
-          constraint(MaxMetaspaceFreeRatioConstraintFunc)                   \
+          constraint(MaxMetaspaceFreeRatioConstraintFunc,AfterErgo)         \
                                                                             \
   product(uintx, MinMetaspaceFreeRatio,    40,                              \
           "The minimum percentage of Metaspace free after GC to avoid "     \
           "expansion")                                                      \
           range(0, 99)                                                      \
-          constraint(MinMetaspaceFreeRatioConstraintFunc)                   \
+          constraint(MinMetaspaceFreeRatioConstraintFunc,AfterErgo)         \
                                                                             \
   product(size_t, MaxMetaspaceExpansion, ScaleForWordSize(4*M),             \
           "The maximum expansion of Metaspace without full GC (in bytes)")  \
@@ -3407,12 +3401,12 @@
   product(uintx, MaxTenuringThreshold,    15,                               \
           "Maximum value for tenuring threshold")                           \
           range(0, markOopDesc::max_age + 1)                                \
-          constraint(MaxTenuringThresholdConstraintFunc)                    \
+          constraint(MaxTenuringThresholdConstraintFunc,AfterErgo)          \
                                                                             \
   product(uintx, InitialTenuringThreshold,    7,                            \
           "Initial value for tenuring threshold")                           \
           range(0, markOopDesc::max_age + 1)                                \
-          constraint(InitialTenuringThresholdConstraintFunc)                \
+          constraint(InitialTenuringThresholdConstraintFunc,AfterErgo)      \
                                                                             \
   product(uintx, TargetSurvivorRatio,    50,                                \
           "Desired percentage of survivor space used after scavenge")       \
@@ -4090,7 +4084,7 @@
                                                                             \
   experimental(intx, SurvivorAlignmentInBytes, 0,                           \
            "Default survivor space alignment in bytes")                     \
-           constraint(SurvivorAlignmentInBytesConstraintFunc)               \
+           constraint(SurvivorAlignmentInBytesConstraintFunc,AfterErgo)     \
                                                                             \
   product(bool , AllowNonVirtualCalls, false,                               \
           "Obey the ACC_SUPER flag and allow invokenonvirtual calls")       \
@@ -4194,7 +4188,7 @@
 // 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)
+#define IGNORE_CONSTRAINT(func,type)
 
 RUNTIME_FLAGS(DECLARE_DEVELOPER_FLAG, \
               DECLARE_PD_DEVELOPER_FLAG, \
--- a/hotspot/src/share/vm/runtime/mutexLocker.cpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/runtime/mutexLocker.cpp	Fri Jul 31 10:15:02 2015 -0700
@@ -83,7 +83,6 @@
 Monitor* DirtyCardQ_CBL_mon           = NULL;
 Mutex*   Shared_DirtyCardQ_lock       = NULL;
 Mutex*   ParGCRareEvent_lock          = NULL;
-Mutex*   EvacFailureStack_lock        = NULL;
 Mutex*   DerivedPointerTableGC_lock   = NULL;
 Mutex*   Compile_lock                 = NULL;
 Monitor* MethodCompileQueue_lock      = NULL;
@@ -201,7 +200,6 @@
     def(OldSets_lock               , Mutex  , leaf     ,   true,  Monitor::_safepoint_check_never);
     def(RootRegionScan_lock        , Monitor, leaf     ,   true,  Monitor::_safepoint_check_never);
     def(MMUTracker_lock            , Mutex  , leaf     ,   true,  Monitor::_safepoint_check_never);
-    def(EvacFailureStack_lock      , Mutex  , nonleaf  ,   true,  Monitor::_safepoint_check_never);
 
     def(StringDedupQueue_lock      , Monitor, leaf,        true,  Monitor::_safepoint_check_never);
     def(StringDedupTable_lock      , Mutex  , leaf,        true,  Monitor::_safepoint_check_never);
--- a/hotspot/src/share/vm/runtime/mutexLocker.hpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/runtime/mutexLocker.hpp	Fri Jul 31 10:15:02 2015 -0700
@@ -87,7 +87,6 @@
                                                  // non-Java threads.
                                                  // (see option ExplicitGCInvokesConcurrent)
 extern Mutex*   ParGCRareEvent_lock;             // Synchronizes various (rare) parallel GC ops.
-extern Mutex*   EvacFailureStack_lock;           // guards the evac failure scan stack
 extern Mutex*   Compile_lock;                    // a lock held when Compilation is updating code (used to block CodeCache traversal, CHA updates, etc)
 extern Monitor* MethodCompileQueue_lock;         // a lock held when method compilations are enqueued, dequeued
 extern Monitor* CompileThread_lock;              // a lock held by compile threads during compilation system initialization
--- a/hotspot/src/share/vm/runtime/os.cpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/runtime/os.cpp	Fri Jul 31 10:15:02 2015 -0700
@@ -843,6 +843,28 @@
   pd_print_cpu_info(st, buf, buflen);
 }
 
+// Print a one line string summarizing the cpu, number of cores, memory, and operating system version
+void os::print_summary_info(outputStream* st, char* buf, size_t buflen) {
+  st->print("Host: ");
+#ifndef PRODUCT
+  if (get_host_name(buf, buflen)) {
+    st->print("%s, ", buf);
+  }
+#endif // PRODUCT
+  get_summary_cpu_info(buf, buflen);
+  st->print("%s, ", buf);
+  size_t mem = physical_memory()/G;
+  if (mem == 0) {  // for low memory systems
+    mem = physical_memory()/M;
+    st->print("%d cores, %dM, ", processor_count(), mem);
+  } else {
+    st->print("%d cores, %dG, ", processor_count(), mem);
+  }
+  get_summary_os_info(buf, buflen);
+  st->print_raw(buf);
+  st->cr();
+}
+
 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;
@@ -850,12 +872,19 @@
 
   time_t tloc;
   (void)time(&tloc);
-  st->print("time: %s", ctime(&tloc));  // ctime adds newline.
+  char* timestring = ctime(&tloc);  // ctime adds newline.
+  // edit out the newline
+  char* nl = strchr(timestring, '\n');
+  if (nl != NULL) {
+    *nl = '\0';
+  }
 
   struct tm tz;
   if (localtime_pd(&tloc, &tz) != NULL) {
     ::strftime(buf, buflen, "%Z", &tz);
-    st->print_cr("timezone: %s", buf);
+    st->print("Time: %s %s", timestring, buf);
+  } else {
+    st->print("Time: %s", timestring);
   }
 
   double t = os::elapsedTime();
@@ -872,7 +901,7 @@
   int elmins = (eltime - day_secs - hour_secs) / secs_per_min;
   int minute_secs = elmins * secs_per_min;
   int elsecs = (eltime - day_secs - hour_secs - minute_secs);
-  st->print_cr("elapsed time: %d seconds (%dd %dh %dm %ds)", eltime, eldays, elhours, elmins, elsecs);
+  st->print_cr(" elapsed time: %d seconds (%dd %dh %dm %ds)", eltime, eldays, elhours, elmins, elsecs);
 }
 
 // moved from debug.cpp (used to be find()) but still called from there
--- a/hotspot/src/share/vm/runtime/os.hpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/runtime/os.hpp	Fri Jul 31 10:15:02 2015 -0700
@@ -150,6 +150,11 @@
 
   static size_t page_size_for_region(size_t region_size, size_t min_pages, bool must_be_aligned);
 
+  // Get summary strings for system information in buffer provided
+  static bool  get_host_name(char* buf, size_t buflen) PRODUCT_RETURN_(return false;);  // true if available
+  static void  get_summary_cpu_info(char* buf, size_t buflen);
+  static void  get_summary_os_info(char* buf, size_t buflen);
+
  public:
   static void init(void);                      // Called before command line parsing
   static void init_before_ergo(void);          // Called after command line parsing
@@ -590,6 +595,7 @@
   static void print_os_info_brief(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_summary_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);
--- a/hotspot/src/share/vm/runtime/thread.cpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/runtime/thread.cpp	Fri Jul 31 10:15:02 2015 -0700
@@ -52,6 +52,8 @@
 #include "runtime/arguments.hpp"
 #include "runtime/atomic.inline.hpp"
 #include "runtime/biasedLocking.hpp"
+#include "runtime/commandLineFlagConstraintList.hpp"
+#include "runtime/commandLineFlagRangeList.hpp"
 #include "runtime/deoptimization.hpp"
 #include "runtime/fprofiler.hpp"
 #include "runtime/frame.inline.hpp"
@@ -2739,6 +2741,9 @@
     if (ct->env() != NULL) {
       ct->env()->metadata_do(f);
     }
+    if (ct->task() != NULL) {
+      ct->task()->metadata_do(f);
+    }
   }
 }
 
@@ -3319,8 +3324,15 @@
   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()) {
+  // Final check of all ranges after ergonomics which may change values.
+  if (!CommandLineFlagRangeList::check_ranges()) {
+    return JNI_EINVAL;
+  }
+
+  // Final check of all 'AfterErgo' constraints after ergonomics which may change values.
+  bool constraint_result = CommandLineFlagConstraintList::check_constraints(CommandLineFlagConstraint::AfterErgo);
+  Arguments::post_after_ergo_constraint_check(constraint_result);
+  if (!constraint_result) {
     return JNI_EINVAL;
   }
 
--- a/hotspot/src/share/vm/runtime/vframe.cpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/runtime/vframe.cpp	Fri Jul 31 10:15:02 2015 -0700
@@ -148,8 +148,7 @@
   if (obj.not_null()) {
     st->print("\t- %s <" INTPTR_FORMAT "> ", lock_state, (address)obj());
     if (obj->klass() == SystemDictionary::Class_klass()) {
-      Klass* target_klass = java_lang_Class::as_Klass(obj());
-      st->print_cr("(a java.lang.Class for %s)", InstanceKlass::cast(target_klass)->external_name());
+      st->print_cr("(a java.lang.Class for %s)", java_lang_Class::as_external_name(obj()));
     } else {
       Klass* k = obj->klass();
       st->print_cr("(a %s)", k->external_name());
--- a/hotspot/src/share/vm/services/heapDumper.cpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/services/heapDumper.cpp	Fri Jul 31 10:15:02 2015 -0700
@@ -899,6 +899,11 @@
   assert(klass->oop_is_instance(), "not an InstanceKlass");
   InstanceKlass* ik = (InstanceKlass*)klass;
 
+  // Ignore the class if it hasn't been initialized yet
+  if (!ik->is_linked()) {
+    return;
+  }
+
   writer->write_u1(HPROF_GC_CLASS_DUMP);
 
   // class ID
--- a/hotspot/src/share/vm/shark/sharkBuilder.cpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/shark/sharkBuilder.cpp	Fri Jul 31 10:15:02 2015 -0700
@@ -25,6 +25,8 @@
 
 #include "precompiled.hpp"
 #include "ci/ciMethod.hpp"
+#include "gc/shared/barrierSet.hpp"
+#include "gc/shared/cardTableModRefBS.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/method.hpp"
 #include "runtime/os.hpp"
@@ -442,7 +444,7 @@
     Unimplemented();
 
   CreateStore(
-    LLVMValue::jbyte_constant(CardTableModRefBS::dirty_card),
+    LLVMValue::jbyte_constant(CardTableModRefBS::dirty_card_val()),
     CreateIntToPtr(
       CreateAdd(
         LLVMValue::intptr_constant(
--- a/hotspot/src/share/vm/shark/sharkBuilder.hpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/shark/sharkBuilder.hpp	Fri Jul 31 10:15:02 2015 -0700
@@ -27,8 +27,6 @@
 #define SHARE_VM_SHARK_SHARKBUILDER_HPP
 
 #include "ci/ciType.hpp"
-#include "gc/shared/barrierSet.hpp"
-#include "gc/shared/cardTableModRefBS.hpp"
 #include "shark/llvmHeaders.hpp"
 #include "shark/llvmValue.hpp"
 #include "shark/sharkCodeBuffer.hpp"
@@ -38,6 +36,8 @@
 #include "utilities/debug.hpp"
 #include "utilities/sizes.hpp"
 
+class BarrierSet;
+
 class SharkBuilder : public llvm::IRBuilder<> {
   friend class SharkCompileInvariants;
 
--- a/hotspot/src/share/vm/utilities/vmError.cpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/utilities/vmError.cpp	Fri Jul 31 10:15:02 2015 -0700
@@ -306,6 +306,30 @@
 #endif // ZERO
 }
 
+void VMError::print_oom_reasons(outputStream* st) {
+  st->print_cr("# Possible reasons:");
+  st->print_cr("#   The system is out of physical RAM or swap space");
+  st->print_cr("#   In 32 bit mode, the process size limit was hit");
+  st->print_cr("# Possible solutions:");
+  st->print_cr("#   Reduce memory load on the system");
+  st->print_cr("#   Increase physical memory or swap space");
+  st->print_cr("#   Check if swap backing store is full");
+  st->print_cr("#   Use 64 bit Java on a 64 bit OS");
+  st->print_cr("#   Decrease Java heap size (-Xmx/-Xms)");
+  st->print_cr("#   Decrease number of Java threads");
+  st->print_cr("#   Decrease Java thread stack sizes (-Xss)");
+  st->print_cr("#   Set larger code cache with -XX:ReservedCodeCacheSize=");
+  st->print_cr("# This output file may be truncated or incomplete.");
+}
+
+const char* VMError::gc_mode() {
+  if (UseG1GC)            return "g1 gc";
+  if (UseParallelGC)      return "parallel gc";
+  if (UseConcMarkSweepGC) return "concurrent mark sweep gc";
+  if (UseSerialGC)        return "serial gc";
+  return "ERROR in GC mode";
+}
+
 // This is the main function to report a fatal error. Only one thread can
 // call this function, so we don't need to worry about MT-safety. But it's
 // possible that the error handler itself may crash or die on an internal
@@ -358,21 +382,21 @@
 
   // test secondary error handling. Test it twice, to test that resetting
   // error handler after a secondary crash works.
-  STEP(11, "(test secondary crash 1)")
+  STEP(20, "(test secondary crash 1)")
     if (_verbose && TestCrashInErrorHandler != 0) {
       st->print_cr("Will crash now (TestCrashInErrorHandler=%d)...",
         TestCrashInErrorHandler);
       controlled_crash(TestCrashInErrorHandler);
     }
 
-  STEP(12, "(test secondary crash 2)")
+  STEP(30, "(test secondary crash 2)")
     if (_verbose && TestCrashInErrorHandler != 0) {
       st->print_cr("Will crash now (TestCrashInErrorHandler=%d)...",
         TestCrashInErrorHandler);
       controlled_crash(TestCrashInErrorHandler);
     }
 
-  STEP(13, "(test safefetch in error handler)")
+  STEP(40, "(test safefetch in error handler)")
     // test whether it is safe to use SafeFetch32 in Crash Handler. Test twice
     // to test that resetting the signal handler works correctly.
     if (_verbose && TestSafeFetchInErrorHandler) {
@@ -393,7 +417,7 @@
     }
 #endif // PRODUCT
 
-  STEP(15, "(printing type of error)")
+  STEP(50, "(printing type of error)")
 
      switch(_id) {
        case OOM_MALLOC_ERROR:
@@ -418,19 +442,7 @@
          }
          // In error file give some solutions
          if (_verbose) {
-           st->print_cr("# Possible reasons:");
-           st->print_cr("#   The system is out of physical RAM or swap space");
-           st->print_cr("#   In 32 bit mode, the process size limit was hit");
-           st->print_cr("# Possible solutions:");
-           st->print_cr("#   Reduce memory load on the system");
-           st->print_cr("#   Increase physical memory or swap space");
-           st->print_cr("#   Check if swap backing store is full");
-           st->print_cr("#   Use 64 bit Java on a 64 bit OS");
-           st->print_cr("#   Decrease Java heap size (-Xmx/-Xms)");
-           st->print_cr("#   Decrease number of Java threads");
-           st->print_cr("#   Decrease Java thread stack sizes (-Xss)");
-           st->print_cr("#   Set larger code cache with -XX:ReservedCodeCacheSize=");
-           st->print_cr("# This output file may be truncated or incomplete.");
+           print_oom_reasons(st);
          } else {
            return;  // that's enough for the screen
          }
@@ -440,7 +452,7 @@
          break;
      }
 
-  STEP(20, "(printing exception/signal name)")
+  STEP(60, "(printing exception/signal name)")
 
      st->print_cr("#");
      st->print("#  ");
@@ -470,14 +482,14 @@
        }
      }
 
-  STEP(30, "(printing current thread and pid)")
+  STEP(70, "(printing current thread and pid)")
 
      // process id, thread id
      st->print(", pid=%d", os::current_process_id());
      st->print(", tid=" INTPTR_FORMAT, os::current_thread_id());
      st->cr();
 
-  STEP(40, "(printing error message)")
+  STEP(80, "(printing error message)")
 
      if (should_report_bug(_id)) {  // already printed the message.
        // error message
@@ -488,7 +500,7 @@
        }
     }
 
-  STEP(50, "(printing Java version string)")
+  STEP(90, "(printing Java version string)")
 
      // VM version
      st->print_cr("#");
@@ -498,15 +510,18 @@
      const char* runtime_version = JDK_Version::runtime_version() != NULL ?
                                   JDK_Version::runtime_version() : "";
      st->print_cr("# JRE version: %s (%s) (build %s)", runtime_name, buf, runtime_version);
-     st->print_cr("# Java VM: %s (%s %s %s %s)",
+     // This is the long version with some default settings added
+     st->print_cr("# Java VM: %s (%s, %s%s%s, %s, %s)",
                    Abstract_VM_Version::vm_name(),
                    Abstract_VM_Version::vm_release(),
                    Abstract_VM_Version::vm_info_string(),
-                   Abstract_VM_Version::vm_platform_string(),
-                   UseCompressedOops ? "compressed oops" : ""
+                   TieredCompilation ? ", tiered" : "",
+                   UseCompressedOops ? ", compressed oops" : "",
+                   gc_mode(),
+                   Abstract_VM_Version::vm_platform_string()
                  );
 
-  STEP(60, "(printing problematic frame)")
+  STEP(100, "(printing problematic frame)")
 
      // Print current frame if we have a context (i.e. it's a crash)
      if (_context) {
@@ -517,7 +532,8 @@
        st->cr();
        st->print_cr("#");
      }
-  STEP(63, "(printing core file information)")
+
+  STEP(110, "(printing core file information)")
     st->print("# ");
     if (CreateCoredumpOnCrash) {
       if (coredump_status) {
@@ -531,13 +547,42 @@
     st->cr();
     st->print_cr("#");
 
-  STEP(65, "(printing bug submit message)")
+  STEP(120, "(printing bug submit message)")
 
      if (should_report_bug(_id) && _verbose) {
        print_bug_submit_message(st, _thread);
      }
 
-  STEP(70, "(printing thread)" )
+  STEP(130, "(printing summary)" )
+
+     if (_verbose) {
+       st->cr();
+       st->print_cr("---------------  S U M M A R Y ------------");
+       st->cr();
+     }
+
+  STEP(140, "(printing VM option summary)" )
+
+     if (_verbose) {
+       // VM options
+       Arguments::print_summary_on(st);
+       st->cr();
+     }
+
+  STEP(150, "(printing summary machine and OS info)")
+
+     if (_verbose) {
+       os::print_summary_info(st, buf, sizeof(buf));
+     }
+
+
+  STEP(160, "(printing date and time)" )
+
+     if (_verbose) {
+       os::print_date_and_time(st, buf, sizeof(buf));
+     }
+
+  STEP(170, "(printing thread)" )
 
      if (_verbose) {
        st->cr();
@@ -545,7 +590,7 @@
        st->cr();
      }
 
-  STEP(80, "(printing current thread)" )
+  STEP(180, "(printing current thread)" )
 
      // current thread
      if (_verbose) {
@@ -559,31 +604,20 @@
        st->cr();
      }
 
-  STEP(90, "(printing siginfo)" )
+  STEP(190, "(printing current compile task)" )
 
-     // signal no, signal code, address that caused the fault
-     if (_verbose && _siginfo) {
-       os::print_siginfo(st, _siginfo);
-       st->cr();
+     if (_verbose && _thread && _thread->is_Compiler_thread()) {
+        CompilerThread* t = (CompilerThread*)_thread;
+        if (t->task()) {
+           st->cr();
+           st->print_cr("Current CompileTask:");
+           t->task()->print_line_on_error(st, buf, sizeof(buf));
+           st->cr();
+        }
      }
 
-  STEP(100, "(printing registers, top of stack, instructions near pc)")
 
-     // registers, top of stack, instructions near pc
-     if (_verbose && _context) {
-       os::print_context(st, _context);
-       st->cr();
-     }
-
-  STEP(105, "(printing register info)")
-
-     // decode register contents if possible
-     if (_verbose && _context && Universe::is_fully_initialized()) {
-       os::print_register_info(st, _context);
-       st->cr();
-     }
-
-  STEP(110, "(printing stack bounds)" )
+  STEP(200, "(printing stack bounds)" )
 
      if (_verbose) {
        st->print("Stack: ");
@@ -614,7 +648,7 @@
        st->cr();
      }
 
-  STEP(120, "(printing native stack)" )
+  STEP(210, "(printing native stack)" )
 
    if (_verbose) {
      if (os::platform_print_native_stack(st, _context, buf, sizeof(buf))) {
@@ -628,13 +662,13 @@
      }
    }
 
-  STEP(130, "(printing Java stack)" )
+  STEP(220, "(printing Java stack)" )
 
      if (_verbose && _thread && _thread->is_Java_thread()) {
        print_stack_trace(st, (JavaThread*)_thread, buf, sizeof(buf));
      }
 
-  STEP(135, "(printing target Java thread stack)" )
+  STEP(230, "(printing target Java thread stack)" )
 
      // printing Java thread stack trace if it is involved in GC crash
      if (_verbose && _thread && (_thread->is_Named_thread())) {
@@ -645,7 +679,32 @@
        }
      }
 
-  STEP(140, "(printing VM operation)" )
+  STEP(240, "(printing siginfo)" )
+
+     // signal no, signal code, address that caused the fault
+     if (_verbose && _siginfo) {
+       st->cr();
+       os::print_siginfo(st, _siginfo);
+       st->cr();
+     }
+
+  STEP(250, "(printing register info)")
+
+     // decode register contents if possible
+     if (_verbose && _context && Universe::is_fully_initialized()) {
+       os::print_register_info(st, _context);
+       st->cr();
+     }
+
+  STEP(260, "(printing registers, top of stack, instructions near pc)")
+
+     // registers, top of stack, instructions near pc
+     if (_verbose && _context) {
+       os::print_context(st, _context);
+       st->cr();
+     }
+
+  STEP(270, "(printing VM operation)" )
 
      if (_verbose && _thread && _thread->is_VM_thread()) {
         VMThread* t = (VMThread*)_thread;
@@ -657,19 +716,7 @@
         }
      }
 
-  STEP(150, "(printing current compile task)" )
-
-     if (_verbose && _thread && _thread->is_Compiler_thread()) {
-        CompilerThread* t = (CompilerThread*)_thread;
-        if (t->task()) {
-           st->cr();
-           st->print_cr("Current CompileTask:");
-           t->task()->print_line_on_error(st, buf, sizeof(buf));
-           st->cr();
-        }
-     }
-
-  STEP(160, "(printing process)" )
+  STEP(280, "(printing process)" )
 
      if (_verbose) {
        st->cr();
@@ -677,7 +724,7 @@
        st->cr();
      }
 
-  STEP(170, "(printing all threads)" )
+  STEP(290, "(printing all threads)" )
 
      // all threads
      if (_verbose && _thread) {
@@ -685,7 +732,7 @@
        st->cr();
      }
 
-  STEP(175, "(printing VM state)" )
+  STEP(300, "(printing VM state)" )
 
      if (_verbose) {
        // Safepoint state
@@ -707,7 +754,7 @@
        st->cr();
      }
 
-  STEP(180, "(printing owned locks on error)" )
+  STEP(310, "(printing owned locks on error)" )
 
      // mutexes/monitors that currently have an owner
      if (_verbose) {
@@ -715,7 +762,7 @@
        st->cr();
      }
 
-  STEP(182, "(printing number of OutOfMemoryError and StackOverflow exceptions)")
+  STEP(320, "(printing number of OutOfMemoryError and StackOverflow exceptions)")
 
      if (_verbose && Exceptions::has_exception_counts()) {
        st->print_cr("OutOfMemory and StackOverflow Exception counts:");
@@ -723,7 +770,7 @@
        st->cr();
      }
 
-  STEP(185, "(printing compressed oops mode")
+  STEP(330, "(printing compressed oops mode")
 
      if (_verbose && UseCompressedOops) {
        Universe::print_compressed_oops_mode(st);
@@ -733,7 +780,7 @@
        st->cr();
      }
 
-  STEP(190, "(printing heap information)" )
+  STEP(340, "(printing heap information)" )
 
      if (_verbose && Universe::is_fully_initialized()) {
        Universe::heap()->print_on_error(st);
@@ -743,7 +790,7 @@
        st->cr();
      }
 
-  STEP(195, "(printing code cache information)" )
+  STEP(350, "(printing code cache information)" )
 
      if (_verbose && Universe::is_fully_initialized()) {
        // print code cache information before vm abort
@@ -751,14 +798,14 @@
        st->cr();
      }
 
-  STEP(200, "(printing ring buffers)" )
+  STEP(360, "(printing ring buffers)" )
 
      if (_verbose) {
        Events::print_all(st);
        st->cr();
      }
 
-  STEP(205, "(printing dynamic libraries)" )
+  STEP(370, "(printing dynamic libraries)" )
 
      if (_verbose) {
        // dynamic libraries, or memory map
@@ -766,7 +813,7 @@
        st->cr();
      }
 
-  STEP(210, "(printing VM options)" )
+  STEP(380, "(printing VM options)" )
 
      if (_verbose) {
        // VM options
@@ -774,33 +821,33 @@
        st->cr();
      }
 
-  STEP(215, "(printing warning if internal testing API used)" )
+  STEP(390, "(printing warning if internal testing API used)" )
 
      if (WhiteBox::used()) {
        st->print_cr("Unsupported internal testing APIs have been used.");
        st->cr();
      }
 
-  STEP(220, "(printing environment variables)" )
+  STEP(400, "(printing all environment variables)" )
 
      if (_verbose) {
        os::print_environment_variables(st, env_list);
        st->cr();
      }
 
-  STEP(225, "(printing signal handlers)" )
+  STEP(410, "(printing signal handlers)" )
 
      if (_verbose) {
        os::print_signal_handlers(st, buf, sizeof(buf));
        st->cr();
      }
 
-  STEP(228, "(Native Memory Tracking)" )
+  STEP(420, "(Native Memory Tracking)" )
      if (_verbose) {
        MemTracker::error_report(st);
      }
 
-  STEP(230, "" )
+  STEP(430, "(printing system)" )
 
      if (_verbose) {
        st->cr();
@@ -808,48 +855,39 @@
        st->cr();
      }
 
-  STEP(240, "(printing OS information)" )
+  STEP(440, "(printing OS information)" )
 
      if (_verbose) {
        os::print_os_info(st);
        st->cr();
      }
 
-  STEP(250, "(printing CPU info)" )
+  STEP(450, "(printing CPU info)" )
      if (_verbose) {
        os::print_cpu_info(st, buf, sizeof(buf));
        st->cr();
      }
 
-  STEP(260, "(printing memory info)" )
+  STEP(460, "(printing memory info)" )
 
      if (_verbose) {
        os::print_memory_info(st);
        st->cr();
      }
 
-  STEP(270, "(printing internal vm info)" )
+  STEP(470, "(printing internal vm info)" )
 
      if (_verbose) {
        st->print_cr("vm_info: %s", Abstract_VM_Version::internal_vm_info_string());
        st->cr();
      }
 
-  STEP(280, "(printing date and time)" )
-
-     if (_verbose) {
-       os::print_date_and_time(st, buf, sizeof(buf));
-       st->cr();
-     }
-
-#ifndef PRODUCT
   // print a defined marker to show that error handling finished correctly.
-  STEP(290, "(printing end marker)" )
+  STEP(480, "(printing end marker)" )
 
      if (_verbose) {
        st->print_cr("END.");
      }
-#endif
 
   END
 
--- a/hotspot/src/share/vm/utilities/vmError.hpp	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/src/share/vm/utilities/vmError.hpp	Fri Jul 31 10:15:02 2015 -0700
@@ -89,6 +89,9 @@
   static void print_stack_trace(outputStream* st, JavaThread* jt,
                                 char* buf, int buflen, bool verbose = false);
 
+  static const char* gc_mode();
+  static void print_oom_reasons(outputStream* st);
+
   // accessor
   const char* message() const    { return _message; }
   const char* detail_msg() const { return _detail_msg; }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/arguments/CheckCICompilerCount.java	Fri Jul 31 10:15:02 2015 -0700
@@ -0,0 +1,135 @@
+/*
+ * 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.
+ */
+
+import jdk.test.lib.*;
+
+/*
+ * @test CheckCheckCICompilerCount
+ * @bug 8130858
+ * @summary Check that correct range of values for CICompilerCount are allowed depending on whether tiered is enabled or not
+ * @library /testlibrary
+ * @modules java.base/sun.misc
+ *          java.management
+ * @run main CheckCICompilerCount
+ */
+
+public class CheckCICompilerCount {
+    private static final String[][] NON_TIERED_ARGUMENTS = {
+        {
+            "-XX:-TieredCompilation",
+            "-XX:+PrintFlagsFinal",
+            "-XX:CICompilerCount=0",
+            "-version"
+        },
+        {
+            "-XX:-TieredCompilation",
+            "-XX:+PrintFlagsFinal",
+            "-XX:CICompilerCount=1",
+            "-version"
+        }
+    };
+
+    private static final String[][] NON_TIERED_EXPECTED_OUTPUTS = {
+        {
+            "CICompilerCount=0 must be at least 1",
+            "Improperly specified VM option 'CICompilerCount=0'"
+        },
+        {
+            "intx CICompilerCount                          := 1                                   {product}"
+        }
+    };
+
+    private static final int[] NON_TIERED_EXIT = {
+        1,
+        0
+    };
+
+    private static final String[][] TIERED_ARGUMENTS = {
+        {
+            "-XX:+TieredCompilation",
+            "-XX:+PrintFlagsFinal",
+            "-XX:CICompilerCount=1",
+            "-version"
+        },
+        {
+            "-XX:+TieredCompilation",
+            "-XX:+PrintFlagsFinal",
+            "-XX:CICompilerCount=2",
+            "-version"
+        }
+    };
+
+    private static final String[][] TIERED_EXPECTED_OUTPUTS = {
+        {
+            "CICompilerCount=1 must be at least 2",
+            "Improperly specified VM option 'CICompilerCount=1'"
+        },
+        {
+            "intx CICompilerCount                          := 2                                   {product}"
+        }
+    };
+
+    private static final int[] TIERED_EXIT = {
+        1,
+        0
+    };
+
+    private static void verifyValidOption(String[] arguments, String[] expected_outputs, int exit, boolean tiered) throws Exception {
+        ProcessBuilder pb;
+        OutputAnalyzer out;
+
+        pb = ProcessTools.createJavaProcessBuilder(arguments);
+        out = new OutputAnalyzer(pb.start());
+
+        try {
+            out.shouldHaveExitValue(exit);
+            for (String expected_output : expected_outputs) {
+                out.shouldContain(expected_output);
+            }
+        } catch (RuntimeException e) {
+            // Check if tiered compilation is available in this JVM
+            // Version. Throw exception only if it is available.
+            if (!(tiered && out.getOutput().contains("TieredCompilation is disabled in this release."))) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        if (NON_TIERED_ARGUMENTS.length != NON_TIERED_EXPECTED_OUTPUTS.length || NON_TIERED_ARGUMENTS.length != NON_TIERED_EXIT.length) {
+            throw new RuntimeException("Test is set up incorrectly: length of arguments, expected outputs and exit codes in non-tiered mode of operation do not match.");
+        }
+
+        if (TIERED_ARGUMENTS.length != TIERED_EXPECTED_OUTPUTS.length || TIERED_ARGUMENTS.length != TIERED_EXIT.length) {
+            throw new RuntimeException("Test is set up incorrectly: length of arguments, expected outputs and exit codes in tiered mode of operation do not match.");
+        }
+
+        for (int i = 0; i < NON_TIERED_ARGUMENTS.length; i++) {
+            verifyValidOption(NON_TIERED_ARGUMENTS[i], NON_TIERED_EXPECTED_OUTPUTS[i], NON_TIERED_EXIT[i], false);
+        }
+
+        for (int i = 0; i < TIERED_ARGUMENTS.length; i++) {
+            verifyValidOption(TIERED_ARGUMENTS[i], TIERED_EXPECTED_OUTPUTS[i], TIERED_EXIT[i], true);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/IntrinsicAvailableTest.java	Fri Jul 31 10:15:02 2015 -0700
@@ -0,0 +1,126 @@
+/*
+ * 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.
+ */
+import java.lang.reflect.Executable;
+import java.util.concurrent.Callable;
+import java.util.Objects;
+/*
+ * @test
+ * @bug 8130832
+ * @library /testlibrary /../../test/lib /compiler/whitebox /compiler/testlibrary
+ * @build IntrinsicAvailableTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:.
+ *                   -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI
+ *                   -XX:+UseCRC32Intrinsics
+ *                   IntrinsicAvailableTest
+ * @run main/othervm -Xbootclasspath/a:.
+ *                   -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI
+ *                   -XX:-UseCRC32Intrinsics
+ *                   IntrinsicAvailableTest
+ */
+public class IntrinsicAvailableTest extends CompilerWhiteBoxTest {
+    protected String VMName;
+
+    public IntrinsicAvailableTest(IntrinsicAvailableTestTestCase testCase) {
+        super(testCase);
+        VMName = System.getProperty("java.vm.name");
+    }
+
+    public static class IntrinsicAvailableTestTestCase implements TestCase {
+
+        public String name() {
+            return "IntrinsicAvailableTestTestCase";
+        }
+
+        public Executable getExecutable() {
+            // Using a single method to test the
+            // WhiteBox.isIntrinsicAvailable(Executable method, int compLevel)
+            // call for the compilation level corresponding to both the C1 and C2
+            // compiler keeps the current test simple.
+            //
+            // The tested method is java.util.zip.CRC32.update(int, int) because
+            // both C1 and C2 define an intrinsic for the method and
+            // the UseCRC32Intrinsics flag can be used to enable/disable
+            // intrinsification of the method in both product and fastdebug
+            // builds.
+            try {
+                return Class.forName("java.util.zip.CRC32").getDeclaredMethod("update", int.class, int.class);
+            } catch (NoSuchMethodException e) {
+                throw new RuntimeException("Test bug, method unavailable. " + e);
+            } catch (ClassNotFoundException e) {
+                throw new RuntimeException("Test bug, class unavailable. " + e);
+            }
+        }
+
+        public Callable<Integer> getCallable() {
+            return null;
+        }
+
+        public boolean isOsr() {
+            return false;
+        }
+
+    }
+
+    protected void checkIntrinsicForCompilationLevel(Executable method, int compLevel) throws Exception {
+        boolean intrinsicEnabled = Boolean.valueOf(getVMOption("UseCRC32Intrinsics"));
+        boolean intrinsicAvailable = WHITE_BOX.isIntrinsicAvailable(method,
+                                                                    compLevel);
+
+        String intrinsicEnabledMessage = intrinsicEnabled ? "enabled" : "disabled";
+        String intrinsicAvailableMessage = intrinsicAvailable ? "available" : "not available";
+
+        if (intrinsicEnabled == intrinsicAvailable) {
+            System.out.println("Expected result: intrinsic for java.util.zip.CRC32.update() is " +
+                               intrinsicEnabledMessage + " and intrinsic is " + intrinsicAvailableMessage +
+                               " at compilation level " + compLevel);
+        } else {
+            throw new RuntimeException("Unexpected result: intrinsic for java.util.zip.CRC32.update() is " +
+                                       intrinsicEnabledMessage + " but intrinsic is " + intrinsicAvailableMessage +
+                                       " at compilation level " + compLevel);
+        }
+    }
+
+    protected boolean isServerVM() {
+        return VMName.toLowerCase().contains("server");
+    }
+
+    public void test() throws Exception {
+        Executable intrinsicMethod = testCase.getExecutable();
+        if (isServerVM()) {
+            if (TIERED_COMPILATION) {
+                checkIntrinsicForCompilationLevel(intrinsicMethod, COMP_LEVEL_SIMPLE);
+            }
+            checkIntrinsicForCompilationLevel(intrinsicMethod, COMP_LEVEL_FULL_OPTIMIZATION);
+        } else {
+            checkIntrinsicForCompilationLevel(intrinsicMethod, COMP_LEVEL_SIMPLE);
+        }
+    }
+
+    public static void main(String args[]) throws Exception {
+        new IntrinsicAvailableTest(new IntrinsicAvailableTestTestCase()).test();
+    }
+}
--- a/hotspot/test/compiler/intrinsics/mathexact/sanity/IntrinsicBase.java	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/IntrinsicBase.java	Fri Jul 31 10:15:02 2015 -0700
@@ -67,7 +67,7 @@
                     compileAtLevel(CompilerWhiteBoxTest.COMP_LEVEL_SIMPLE);
                 }
 
-                if (!isIntrinsicSupported()) {
+                if (!isIntrinsicAvailable()) {
                     expectedIntrinsicCount = 0;
                 }
                 break;
@@ -114,7 +114,11 @@
         }
     }
 
-    protected abstract boolean isIntrinsicSupported();
+    // An intrinsic is available if:
+    // - the intrinsic is enabled (by using the appropriate command-line flag) and
+    // - the intrinsic is supported by the VM (i.e., the platform on which the VM is
+    //   running provides the instructions necessary for the VM to generate the intrinsic).
+    protected abstract boolean isIntrinsicAvailable();
 
     protected abstract String getIntrinsicId();
 
@@ -123,14 +127,20 @@
     }
 
     static class IntTest extends IntrinsicBase {
+
+        protected boolean isIntrinsicAvailable; // The tested intrinsic is available on the current platform.
+
         protected IntTest(MathIntrinsic.IntIntrinsic testCase) {
             super(testCase);
+            // Only the C2 compiler intrinsifies exact math methods
+            // so check if the intrinsics are available with C2.
+            isIntrinsicAvailable = WHITE_BOX.isIntrinsicAvailable(testCase.getTestMethod(),
+                                                                  COMP_LEVEL_FULL_OPTIMIZATION);
         }
 
         @Override
-        protected boolean isIntrinsicSupported() {
-            return isServerVM() && Boolean.valueOf(useMathExactIntrinsics)
-                && (Platform.isX86() || Platform.isX64() || Platform.isAArch64());
+        protected boolean isIntrinsicAvailable() {
+            return isIntrinsicAvailable;
         }
 
         @Override
@@ -140,14 +150,20 @@
     }
 
     static class LongTest extends IntrinsicBase {
+
+        protected boolean isIntrinsicAvailable; // The tested intrinsic is available on the current platform.
+
         protected LongTest(MathIntrinsic.LongIntrinsic testCase) {
             super(testCase);
+            // Only the C2 compiler intrinsifies exact math methods
+            // so check if the intrinsics are available with C2.
+            isIntrinsicAvailable = WHITE_BOX.isIntrinsicAvailable(testCase.getTestMethod(),
+                                                                  COMP_LEVEL_FULL_OPTIMIZATION);
         }
 
         @Override
-        protected boolean isIntrinsicSupported() {
-            return isServerVM() && Boolean.valueOf(useMathExactIntrinsics) &&
-                (Platform.isX64() || Platform.isPPC() || Platform.isAArch64());
+        protected boolean isIntrinsicAvailable() {
+            return isIntrinsicAvailable;
         }
 
         @Override
--- a/hotspot/test/compiler/intrinsics/mathexact/sanity/MathIntrinsic.java	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/MathIntrinsic.java	Fri Jul 31 10:15:02 2015 -0700
@@ -29,11 +29,21 @@
     enum IntIntrinsic implements CompilerWhiteBoxTest.TestCase {
         Add {
             @Override
+            Executable testMethod() throws NoSuchMethodException, ClassNotFoundException {
+                return Class.forName("java.lang.Math").getDeclaredMethod("addExact", int.class, int.class);
+            }
+
+            @Override
             Object execMathMethod() {
                 return intR = Math.addExact(int1, int2);
             }
         },
-        Subtract {
+       Subtract {
+            @Override
+            Executable testMethod() throws NoSuchMethodException, ClassNotFoundException {
+                return Class.forName("java.lang.Math").getDeclaredMethod("subtractExact", int.class, int.class);
+            }
+
             @Override
             Object execMathMethod() {
                 return intR = Math.subtractExact(int1, int2);
@@ -41,34 +51,66 @@
         },
         Multiply {
             @Override
+            Executable testMethod() throws NoSuchMethodException, ClassNotFoundException {
+                return Class.forName("java.lang.Math").getDeclaredMethod("multiplyExact", int.class, int.class);
+            }
+
+            @Override
             Object execMathMethod() {
                 return intR = Math.multiplyExact(int1, int2);
             }
         },
         Increment {
             @Override
+            Executable testMethod() throws NoSuchMethodException, ClassNotFoundException {
+                return Class.forName("java.lang.Math").getDeclaredMethod("incrementExact", int.class);
+            }
+
+            @Override
             Object execMathMethod() {
                 return intR = Math.incrementExact(int1);
             }
         },
         Decrement {
             @Override
+            Executable testMethod() throws NoSuchMethodException, ClassNotFoundException {
+                return Class.forName("java.lang.Math").getDeclaredMethod("decrementExact", int.class);
+            }
+
+            @Override
             Object execMathMethod() {
                 return intR = Math.decrementExact(int1);
             }
         },
         Negate {
             @Override
+            Executable testMethod() throws NoSuchMethodException, ClassNotFoundException {
+                return Class.forName("java.lang.Math").getDeclaredMethod("negateExact", int.class);
+            }
+
+            @Override
             Object execMathMethod() {
                 return intR = Math.negateExact(int1);
             }
         };
+
         protected int int1;
         protected int int2;
         protected int intR;
 
+        abstract Executable testMethod() throws NoSuchMethodException, ClassNotFoundException;
         abstract Object execMathMethod();
 
+        public Executable getTestMethod() {
+            try {
+                return testMethod();
+            } catch (NoSuchMethodException e) {
+                throw new RuntimeException("Test bug, no such method: " + e);
+            } catch (ClassNotFoundException e) {
+                throw new RuntimeException("Test bug, no such class: " + e);
+            }
+        }
+
         @Override
         public Executable getExecutable() {
             try {
@@ -93,36 +135,66 @@
     enum LongIntrinsic implements CompilerWhiteBoxTest.TestCase {
         Add {
             @Override
+            Executable testMethod() throws NoSuchMethodException, ClassNotFoundException {
+                return Class.forName("java.lang.Math").getDeclaredMethod("addExact", long.class, long.class);
+            }
+
+            @Override
             Object execMathMethod() {
                 return longR = Math.addExact(long1, long2);
             }
         },
         Subtract {
             @Override
+            Executable testMethod() throws NoSuchMethodException, ClassNotFoundException {
+                return Class.forName("java.lang.Math").getDeclaredMethod("subtractExact", long.class, long.class);
+            }
+
+            @Override
             Object execMathMethod() {
                 return longR = Math.subtractExact(long1, long2);
             }
         },
         Multiply {
             @Override
+            Executable testMethod() throws NoSuchMethodException, ClassNotFoundException {
+                return Class.forName("java.lang.Math").getDeclaredMethod("multiplyExact", long.class, long.class);
+            }
+
+            @Override
             Object execMathMethod() {
                 return longR = Math.multiplyExact(long1, long2);
             }
         },
         Increment {
             @Override
+            Executable testMethod() throws NoSuchMethodException, ClassNotFoundException {
+                return Class.forName("java.lang.Math").getDeclaredMethod("incrementExact", long.class);
+            }
+
+            @Override
             Object execMathMethod() {
                 return longR = Math.incrementExact(long1);
             }
         },
         Decrement {
             @Override
+            Executable testMethod() throws NoSuchMethodException, ClassNotFoundException {
+                return Class.forName("java.lang.Math").getDeclaredMethod("decrementExact", long.class);
+            }
+
+            @Override
             Object execMathMethod() {
                 return longR = Math.decrementExact(long1);
             }
         },
         Negate {
             @Override
+            Executable testMethod() throws NoSuchMethodException, ClassNotFoundException {
+                return Class.forName("java.lang.Math").getDeclaredMethod("negateExact", long.class);
+            }
+
+            @Override
             Object execMathMethod() {
                 return longR = Math.negateExact(long1);
             }
@@ -131,8 +203,19 @@
         protected long long2;
         protected long longR;
 
+        abstract Executable testMethod() throws NoSuchMethodException, ClassNotFoundException;
         abstract Object execMathMethod();
 
+        public Executable getTestMethod() {
+            try {
+                return testMethod();
+            } catch (NoSuchMethodException e) {
+                throw new RuntimeException("Test bug, no such method: " + e);
+            } catch (ClassNotFoundException e) {
+                throw new RuntimeException("Test bug, no such class: " + e);
+            }
+        }
+
         @Override
         public Executable getExecutable() {
             try {
--- a/hotspot/test/gc/g1/TestLargePageUseForAuxMemory.java	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/test/gc/g1/TestLargePageUseForAuxMemory.java	Fri Jul 31 10:15:02 2015 -0700
@@ -94,29 +94,47 @@
         output.shouldHaveExitValue(0);
     }
 
+    private static long gcd(long x, long y) {
+        while (x > 0) {
+            long t = x;
+            x = y % x;
+            y = t;
+        }
+        return y;
+    }
+
+    private static long lcm(long x, long y) {
+        return x * (y / gcd(x, y));
+    }
+
     public static void main(String[] args) throws Exception {
         if (!Platform.isDebugBuild()) {
             System.out.println("Skip tests on non-debug builds because the required option TracePageSizes is a debug-only option.");
             return;
         }
 
+        // Size that a single card covers.
+        final int cardSize = 512;
         WhiteBox wb = WhiteBox.getWhiteBox();
         smallPageSize = wb.getVMPageSize();
         largePageSize = wb.getVMLargePageSize();
         allocGranularity = wb.getVMAllocationGranularity();
+        final long heapAlignment = lcm(cardSize * smallPageSize, largePageSize);
 
         if (largePageSize == 0) {
             System.out.println("Skip tests because large page support does not seem to be available on this platform.");
             return;
         }
+        if (largePageSize == smallPageSize) {
+            System.out.println("Skip tests because large page support does not seem to be available on this platform." +
+                               "Small and large page size are the same.");
+            return;
+        }
 
         // To get large pages for the card table etc. we need at least a 1G heap (with 4k page size).
         // 32 bit systems will have problems reserving such an amount of contiguous space, so skip the
         // test there.
         if (!Platform.is32bit()) {
-            // Size that a single card covers.
-            final int cardSize = 512;
-
             final long heapSizeForCardTableUsingLargePages = largePageSize * cardSize;
             final long heapSizeDiffForCardTable = Math.max(Math.max(allocGranularity * cardSize, HEAP_REGION_SIZE), largePageSize);
 
@@ -131,7 +149,8 @@
         // 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);
+        final long heapSizeDiffForBitmap = Math.max(Math.max(allocGranularity * bitmapTranslationFactor, HEAP_REGION_SIZE),
+                                                    Math.max(largePageSize, heapAlignment));
 
         Asserts.assertGT(heapSizeForBitmapUsingLargePages, heapSizeDiffForBitmap,
                          "To test we would require to use an invalid heap size");
--- a/hotspot/test/runtime/CompressedOops/ObjectAlignment.java	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/test/runtime/CompressedOops/ObjectAlignment.java	Fri Jul 31 10:15:02 2015 -0700
@@ -48,7 +48,6 @@
                 .shouldHaveExitValue(1);
 
             testObjectAlignment(-1)
-                .shouldContain("must be power of 2")
                 .shouldContain("outside the allowed range")
                 .shouldHaveExitValue(1);
 
@@ -75,4 +74,4 @@
                                                                   "-version");
         return new OutputAnalyzer(pb.start());
     }
-}
\ No newline at end of file
+}
--- a/hotspot/test/runtime/ErrorHandling/CreateCoredumpOnCrash.java	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/test/runtime/ErrorHandling/CreateCoredumpOnCrash.java	Fri Jul 31 10:15:02 2015 -0700
@@ -38,7 +38,7 @@
 public class CreateCoredumpOnCrash {
     private static class Crasher {
         public static void main(String[] args) {
-            Utils.getUnsafe().getInt(0);
+            Utils.getUnsafe().putInt(0L, 0);
         }
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/RedefineTests/RedefineRunningMethodsWithBacktrace.java	Fri Jul 31 10:15:02 2015 -0700
@@ -0,0 +1,193 @@
+/*
+ * 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 8087315
+ * @summary Get old method's stack trace elements after GC
+ * @library /testlibrary
+ * @modules java.compiler
+ *          java.instrument
+ *          jdk.jartool/sun.tools.jar
+ * @build RedefineClassHelper
+ * @run main RedefineClassHelper
+ * @run main/othervm -javaagent:redefineagent.jar RedefineRunningMethodsWithBacktrace
+ */
+
+import static jdk.test.lib.Asserts.*;
+
+public class RedefineRunningMethodsWithBacktrace {
+
+    public static String newB =
+                "class RedefineRunningMethodsWithBacktrace$B {" +
+                "   static int count1 = 0;" +
+                "   static int count2 = 0;" +
+                "   public static volatile boolean stop = false;" +
+                "  static void localSleep() { " +
+                "    try{ " +
+                "      Thread.currentThread().sleep(10);" +
+                "    } catch(InterruptedException ie) { " +
+                "    } " +
+                " } " +
+                "   public static void infinite() { " +
+                "       System.out.println(\"infinite called\");" +
+                "   }" +
+                "   public static void throwable() { " +
+                "       throw new RuntimeException(\"throwable called\");" +
+                "   }" +
+                "}";
+
+    public static String evenNewerB =
+                "class RedefineRunningMethodsWithBacktrace$B {" +
+                "   static int count1 = 0;" +
+                "   static int count2 = 0;" +
+                "   public static volatile boolean stop = false;" +
+                "  static void localSleep() { " +
+                "    try{ " +
+                "      Thread.currentThread().sleep(1);" +
+                "    } catch(InterruptedException ie) { " +
+                "    } " +
+                " } " +
+                "   public static void infinite() { }" +
+                "   public static void throwable() { " +
+                "       throw new RuntimeException(\"throwable called\");" +
+                "   }" +
+                "}";
+
+    static class B {
+        static int count1 = 0;
+        static int count2 = 0;
+        public static volatile boolean stop = false;
+        static void localSleep() {
+            try {
+                Thread.currentThread().sleep(10);//sleep for 10 ms
+            } catch(InterruptedException ie) {
+            }
+        }
+
+        public static void infinite() {
+            while (!stop) { count1++; localSleep(); }
+        }
+        public static void throwable() {
+            // add some stuff to the original constant pool
+            String s1 = new String ("string1");
+            String s2 = new String ("string2");
+            String s3 = new String ("string3");
+            String s4 = new String ("string4");
+            String s5 = new String ("string5");
+            String s6 = new String ("string6");
+            String s7 = new String ("string7");
+            String s8 = new String ("string8");
+            String s9 = new String ("string9");
+            String s10 = new String ("string10");
+            String s11 = new String ("string11");
+            String s12 = new String ("string12");
+            String s13 = new String ("string13");
+            String s14 = new String ("string14");
+            String s15 = new String ("string15");
+            String s16 = new String ("string16");
+            String s17 = new String ("string17");
+            String s18 = new String ("string18");
+            String s19 = new String ("string19");
+            throw new RuntimeException("throwable called");
+        }
+    }
+
+    private static void touchRedefinedMethodInBacktrace(Throwable throwable) {
+        System.out.println("touchRedefinedMethodInBacktrace: ");
+        throwable.printStackTrace();  // this actually crashes with the bug in
+                                      // java_lang_StackTraceElement::create()
+
+        // Make sure that we can convert the backtrace, which is referring to
+        // the redefined method, to a  StrackTraceElement[] without crashing.
+        StackTraceElement[] stackTrace = throwable.getStackTrace();
+        for (int i = 0; i < stackTrace.length; i++) {
+            StackTraceElement frame = stackTrace[i];
+            assertNotNull(frame.getClassName(),
+              "\nTest failed: trace[" + i + "].getClassName() returned null");
+            assertNotNull(frame.getMethodName(),
+              "\nTest failed: trace[" + i + "].getMethodName() returned null");
+        }
+    }
+
+    private static Throwable getThrowableInB() {
+        Throwable t = null;
+        try {
+            B.throwable();
+        } catch (Exception e) {
+            t = e;
+            // Don't print here because Throwable will cache the constructed stacktrace
+            // e.printStackTrace();
+        }
+        return t;
+    }
+
+
+    public static void main(String[] args) throws Exception {
+
+        new Thread() {
+            public void run() {
+                B.infinite();
+            }
+        }.start();
+
+        Throwable t1 = getThrowableInB();
+
+        RedefineClassHelper.redefineClass(B.class, newB);
+
+        System.gc();
+
+        Throwable t2 = getThrowableInB();
+
+        B.infinite();
+
+        for (int i = 0; i < 20 ; i++) {
+            String s = new String("some garbage");
+            System.gc();
+        }
+
+        RedefineClassHelper.redefineClass(B.class, evenNewerB);
+        System.gc();
+
+        Throwable t3 = getThrowableInB();
+
+        for (int i = 0; i < 20 ; i++) {
+            B.infinite();
+            String s = new String("some garbage");
+            System.gc();
+        }
+
+        touchRedefinedMethodInBacktrace(t1);
+        touchRedefinedMethodInBacktrace(t2);
+        touchRedefinedMethodInBacktrace(t3);
+
+        // purge should clean everything up.
+        B.stop = true;
+
+        for (int i = 0; i < 20 ; i++) {
+            B.infinite();
+            String s = new String("some garbage");
+            System.gc();
+        }
+    }
+}
--- a/hotspot/test/runtime/contended/Options.java	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/test/runtime/contended/Options.java	Fri Jul 31 10:15:02 2015 -0700
@@ -55,7 +55,6 @@
         output = new OutputAnalyzer(pb.start());
         output.shouldContain("ContendedPaddingWidth");
         output.shouldContain("outside the allowed range");
-        output.shouldContain("must be a multiple of 8");
         output.shouldHaveExitValue(1);
 
         pb = ProcessTools.createJavaProcessBuilder("-XX:ContendedPaddingWidth=0", "-version");
@@ -90,7 +89,6 @@
         output = new OutputAnalyzer(pb.start());
         output.shouldContain("ContendedPaddingWidth");
         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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/verifier/PrimIntArray.java	Fri Jul 31 10:15:02 2015 -0700
@@ -0,0 +1,55 @@
+/*
+ * 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 8129895
+ * @summary Throw VerifyError when checking assignability of primitive arrays
+ * that are not identical.  For example, [I is not assignable to [B.
+ * @compile primArray.jasm
+ * @compile primArray49.jasm
+ * @run main/othervm -Xverify:all PrimIntArray
+ */
+
+// Test that an int[] is not assignable to byte[].
+public class PrimIntArray {
+
+    public static void main(String args[]) throws Throwable {
+        System.out.println("Regression test for bug 8129895");
+
+        try {
+            Class newClass = Class.forName("primArray");
+            throw new RuntimeException("Expected VerifyError exception not thrown with new verifier");
+        } catch (java.lang.VerifyError e) {
+            System.out.println("Test PrimIntArray passed with new verifier");
+        }
+
+        try {
+            Class newClass = Class.forName("primArray49");
+            throw new RuntimeException("Expected VerifyError exception not thrown by old verifier");
+        } catch (java.lang.VerifyError e) {
+            System.out.println("Test PrimIntArray passed with old verifier");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/verifier/primArray.jasm	Fri Jul 31 10:15:02 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.
+ *
+ */
+
+// Method castToByteArray() tries to return an array of ints when an array
+// of bytes is expected.
+super class primArray
+version 52:0
+{
+
+    public Method "<init>":"()V"
+    stack 1 locals 1
+    {
+        aload_0;
+        invokespecial Method java/lang/Object."<init>":"()V";
+        return;
+    }
+
+    public static Method castToByteArray:"([I)[B"
+        stack 1 locals 1
+    {
+        aload_0;
+        areturn;
+    }
+
+} // end Class primArray
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/verifier/primArray49.jasm	Fri Jul 31 10:15:02 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.
+ *
+ */
+
+// Method castToByteArray() tries to return an array of ints when an array
+// of bytes is expected.
+super class primArray49
+version 49:0
+{
+
+    public Method "<init>":"()V"
+    stack 1 locals 1
+    {
+        aload_0;
+        invokespecial Method java/lang/Object."<init>":"()V";
+        return;
+    }
+
+    public static Method castToByteArray:"([I)[B"
+        stack 1 locals 1
+    {
+        aload_0;
+        areturn;
+    }
+
+} // end Class primArray49
--- a/hotspot/test/serviceability/sa/TestStackTrace.java	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/test/serviceability/sa/TestStackTrace.java	Fri Jul 31 10:15:02 2015 -0700
@@ -34,7 +34,6 @@
  * @test
  * @library /../../test/lib/share/classes
  * @library /testlibrary
- * @ignore 8129971
  * @build jdk.test.lib.*
  * @build jdk.test.lib.apps.*
  * @run main TestStackTrace
--- a/hotspot/test/testlibrary/jdk/test/lib/InMemoryJavaCompiler.java	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/test/testlibrary/jdk/test/lib/InMemoryJavaCompiler.java	Fri Jul 31 10:15:02 2015 -0700
@@ -31,11 +31,9 @@
 import java.util.Arrays;
 
 import javax.tools.ForwardingJavaFileManager;
-import javax.tools.ForwardingJavaFileManager;
 import javax.tools.FileObject;
 import javax.tools.JavaCompiler;
 import javax.tools.JavaCompiler.CompilationTask;
-import javax.tools.JavaFileManager;
 import javax.tools.JavaFileObject;
 import javax.tools.JavaFileObject.Kind;
 import javax.tools.SimpleJavaFileObject;
--- a/hotspot/test/testlibrary/jdk/test/lib/Platform.java	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/test/testlibrary/jdk/test/lib/Platform.java	Fri Jul 31 10:15:02 2015 -0700
@@ -24,7 +24,6 @@
 package jdk.test.lib;
 
 import java.util.regex.Pattern;
-import jdk.test.lib.Utils;
 
 public class Platform {
     private static final String osName      = System.getProperty("os.name");
--- a/hotspot/test/testlibrary/jdk/test/lib/ProcessTools.java	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/test/testlibrary/jdk/test/lib/ProcessTools.java	Fri Jul 31 10:15:02 2015 -0700
@@ -27,8 +27,6 @@
 import java.io.IOException;
 import java.lang.management.ManagementFactory;
 import java.lang.management.RuntimeMXBean;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
--- a/hotspot/test/testlibrary/jdk/test/lib/Utils.java	Wed Jul 05 20:44:11 2017 +0200
+++ b/hotspot/test/testlibrary/jdk/test/lib/Utils.java	Fri Jul 31 10:15:02 2015 -0700
@@ -24,9 +24,6 @@
 package jdk.test.lib;
 
 import static jdk.test.lib.Asserts.assertTrue;
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileReader;
 import java.io.IOException;
 import java.lang.reflect.Field;
 import java.net.InetAddress;
@@ -58,12 +55,12 @@
     public static final String NEW_LINE = System.getProperty("line.separator");
 
     /**
-     * Returns the value of 'test.vm.opts'system property.
+     * Returns the value of 'test.vm.opts' system property.
      */
     public static final String VM_OPTIONS = System.getProperty("test.vm.opts", "").trim();
 
     /**
-     * Returns the value of 'test.java.opts'system property.
+     * Returns the value of 'test.java.opts' system property.
      */
     public static final String JAVA_OPTIONS = System.getProperty("test.java.opts", "").trim();
 
@@ -129,7 +126,7 @@
     /**
      * Returns the default JTReg arguments for a jvm running a test.
      * This is the combination of JTReg arguments test.vm.opts and test.java.opts.
-     * @return An array of options, or an empty array if no opptions.
+     * @return An array of options, or an empty array if no options.
      */
     public static String[] getTestJavaOpts() {
         List<String> opts = new ArrayList<String>();
@@ -276,7 +273,7 @@
      * 12254 /tmp/jdk8/tl/jdk/JTwork/classes/com/sun/tools/attach/Application.jar
      *
      * @param key A regular expression to search for.
-     * @return The found pid, or -1 if Enot found.
+     * @return The found pid, or -1 if not found.
      * @throws Exception If multiple matching jvms are found.
      */
     public static int tryFindJvmPid(String key) throws Throwable {
@@ -392,7 +389,7 @@
      * @param condition, a condition to wait for
      * @param timeout a time in milliseconds to wait for condition to be true
      * specifying -1 will wait forever
-     * @return condition value, to determine if wait was successfull
+     * @return condition value, to determine if wait was successful
      */
     public static final boolean waitForCondition(BooleanSupplier condition,
             long timeout) {
@@ -406,7 +403,7 @@
      * @param timeout a time in milliseconds to wait for condition to be true,
      * specifying -1 will wait forever
      * @param sleepTime a time to sleep value in milliseconds
-     * @return condition value, to determine if wait was successfull
+     * @return condition value, to determine if wait was successful
      */
     public static final boolean waitForCondition(BooleanSupplier condition,
             long timeout, long sleepTime) {