changeset 12614:43139c588ea4 jdk-9+156

Merge
author jwilhelm
date Sat, 04 Feb 2017 03:29:40 +0100
parents 34706140c7ff bb5efb0bc34a
children c22bf83dad09 e64d5880a8be
files src/cpu/aarch64/vm/globals_aarch64.hpp src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassCollector.java src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp src/share/vm/runtime/arguments.cpp src/share/vm/services/diagnosticCommand.cpp test/compiler/aot/cli/jaotc/ClasspathOptionTest.java test/compiler/aot/fingerprint/CDSDumper.java test/compiler/aot/fingerprint/CDSRunner.java test/compiler/aot/fingerprint/SelfChanged.java test/compiler/aot/fingerprint/SelfChangedCDS.java test/compiler/aot/fingerprint/SuperChanged.java test/compiler/c2/cr7200264/Test7200264.sh test/compiler/jvmci/compilerToVM/CanInlineMethodTest.java
diffstat 309 files changed, 5550 insertions(+), 2674 deletions(-) [+]
line wrap: on
line diff
--- a/make/ide/CreateVSProject.gmk	Fri Feb 03 15:20:05 2017 +0100
+++ b/make/ide/CreateVSProject.gmk	Sat Feb 04 03:29:40 2017 +0100
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2016, 2017, 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
@@ -121,7 +121,7 @@
       -buildBase $(call FixPath, $(IDE_OUTPUTDIR)/vs-output) \
       -buildSpace $(call FixPath, $(IDE_OUTPUTDIR)) \
       -makeBinary $(call FixPath, $(MAKE)) \
-      -makeOutput $(call FixPath, $(HOTSPOT_OUTPUTDIR)/variant-%f/libjvm) \
+      -makeOutput $(call FixPath, $(JDK_OUTPUTDIR)/bin/server) \
       -absoluteInclude $(call FixPath, $(HOTSPOT_OUTPUTDIR)/variant-server/gensrc) \
       -absoluteSrcInclude $(call FixPath, $(HOTSPOT_OUTPUTDIR)/variant-server/gensrc) \
       $(EXTRACTED_DEFINES_client) \
--- a/make/src/classes/build/tools/projectcreator/WinGammaPlatformVC10.java	Fri Feb 03 15:20:05 2017 +0100
+++ b/make/src/classes/build/tools/projectcreator/WinGammaPlatformVC10.java	Sat Feb 04 03:29:40 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2017, 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
@@ -114,8 +114,8 @@
             tag(cfg, "CodeAnalysisRuleAssemblies");
         }
         for (BuildConfig cfg : allConfigs) {
-            tagData(cfg, "NMakeBuildCommandLine", cfg.get("MakeBinary") + " -f ../../Makefile import-hotspot LOG=info");
-            tagData(cfg, "NMakeReBuildCommandLine", cfg.get("MakeBinary") + " -f ../../Makefile clean-hotspot import-hotspot LOG=info");
+            tagData(cfg, "NMakeBuildCommandLine", cfg.get("MakeBinary") + " -f ../../Makefile hotspot LOG=info");
+            tagData(cfg, "NMakeReBuildCommandLine", cfg.get("MakeBinary") + " -f ../../Makefile clean-hotspot hotspot LOG=info");
             tagData(cfg, "NMakeCleanCommandLine", cfg.get("MakeBinary") + " -f ../../Makefile clean-hotspot LOG=info");
             tagData(cfg, "NMakeOutput", cfg.get("MakeOutput") + Util.sep + "jvm.dll");
             tagData(cfg, "NMakePreprocessorDefinitions", Util.join(";", cfg.getDefines()));
--- a/make/symbols/symbols-unix	Fri Feb 03 15:20:05 2017 +0100
+++ b/make/symbols/symbols-unix	Sat Feb 04 03:29:40 2017 +0100
@@ -192,4 +192,3 @@
 JVM_AddReadsModule
 JVM_DefineModule
 JVM_SetBootLoaderUnnamedModule
-JVM_GetModuleByPackageName
--- a/src/cpu/aarch64/vm/aarch64.ad	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/cpu/aarch64/vm/aarch64.ad	Sat Feb 04 03:29:40 2017 +0100
@@ -1042,8 +1042,10 @@
   bool is_card_mark_membar(const MemBarNode *barrier);
   bool is_CAS(int opcode);
 
-  MemBarNode *leading_to_trailing(MemBarNode *leading);
-  MemBarNode *card_mark_to_leading(const MemBarNode *barrier);
+  MemBarNode *leading_to_normal(MemBarNode *leading);
+  MemBarNode *normal_to_leading(const MemBarNode *barrier);
+  MemBarNode *card_mark_to_trailing(const MemBarNode *barrier);
+  MemBarNode *trailing_to_card_mark(const MemBarNode *trailing);
   MemBarNode *trailing_to_leading(const MemBarNode *trailing);
 
   // predicates controlling emit of ldr<x>/ldar<x> and associated dmb
@@ -1420,28 +1422,23 @@
   // leading MemBarRelease and a trailing MemBarVolatile as follows
   //
   //   MemBarRelease
-  //  {    ||        } -- optional
+  //  {      ||      } -- optional
   //  {MemBarCPUOrder}
-  //       ||       \\
-  //       ||     StoreX[mo_release]
-  //       | \ Bot    / ???
-  //       | MergeMem
-  //       | /
+  //         ||     \\
+  //         ||     StoreX[mo_release]
+  //         | \     /
+  //         | MergeMem
+  //         | /
   //   MemBarVolatile
   //
   // where
   //  || and \\ represent Ctl and Mem feeds via Proj nodes
   //  | \ and / indicate further routing of the Ctl and Mem feeds
   //
-  // Note that the memory feed from the CPUOrder membar to the
-  // MergeMem node is an AliasIdxBot slice while the feed from the
-  // StoreX is for a slice determined by the type of value being
-  // written.
-  //
-  // the diagram above shows the graph we see for non-object stores.
-  // for a volatile Object store (StoreN/P) we may see other nodes
-  // below the leading membar because of the need for a GC pre- or
-  // post-write barrier.
+  // this is the graph we see for non-object stores. however, for a
+  // volatile Object store (StoreN/P) we may see other nodes below the
+  // leading membar because of the need for a GC pre- or post-write
+  // barrier.
   //
   // with most GC configurations we with see this simple variant which
   // includes a post-write barrier card mark.
@@ -1449,7 +1446,7 @@
   //   MemBarRelease______________________________
   //         ||    \\               Ctl \        \\
   //         ||    StoreN/P[mo_release] CastP2X  StoreB/CM
-  //         | \ Bot  / oop                 . . .  /
+  //         | \     /                       . . .  /
   //         | MergeMem
   //         | /
   //         ||      /
@@ -1459,142 +1456,152 @@
   // the object address to an int used to compute the card offset) and
   // Ctl+Mem to a StoreB node (which does the actual card mark).
   //
-  // n.b. a StoreCM node is only ever used when CMS (with or without
-  // CondCardMark) or G1 is configured. This abstract instruction
-  // differs from a normal card mark write (StoreB) because it implies
-  // a requirement to order visibility of the card mark (StoreCM)
-  // after that of the object put (StoreP/N) using a StoreStore memory
-  // barrier. Note that this is /not/ a requirement to order the
-  // instructions in the generated code (that is already guaranteed by
-  // the order of memory dependencies). Rather it is a requirement to
-  // ensure visibility order which only applies on architectures like
-  // AArch64 which do not implement TSO. This ordering is required for
-  // both non-volatile and volatile puts.
-  //
-  // That implies that we need to translate a StoreCM using the
-  // sequence
+  // n.b. a StoreCM node will only appear in this configuration when
+  // using CMS. StoreCM differs from a normal card mark write (StoreB)
+  // because it implies a requirement to order visibility of the card
+  // mark (StoreCM) relative to the object put (StoreP/N) using a
+  // StoreStore memory barrier (arguably this ought to be represented
+  // explicitly in the ideal graph but that is not how it works). This
+  // ordering is required for both non-volatile and volatile
+  // puts. Normally that means we need to translate a StoreCM using
+  // the sequence
   //
   //   dmb ishst
   //   stlrb
   //
-  // This dmb cannot be omitted even when the associated StoreX or
-  // CompareAndSwapX is implemented using stlr. However, as described
-  // below there are circumstances where a specific GC configuration
-  // requires a stronger barrier in which case it can be omitted.
-  // 
-  // With the Serial or Parallel GC using +CondCardMark the card mark
-  // is performed conditionally on it currently being unmarked in
-  // which case the volatile put graph looks slightly different
+  // However, in the case of a volatile put if we can recognise this
+  // configuration and plant an stlr for the object write then we can
+  // omit the dmb and just plant an strb since visibility of the stlr
+  // is ordered before visibility of subsequent stores. StoreCM nodes
+  // also arise when using G1 or using CMS with conditional card
+  // marking. In these cases (as we shall see) we don't need to insert
+  // the dmb when translating StoreCM because there is already an
+  // intervening StoreLoad barrier between it and the StoreP/N.
+  //
+  // It is also possible to perform the card mark conditionally on it
+  // currently being unmarked in which case the volatile put graph
+  // will look slightly different
   //
   //   MemBarRelease____________________________________________
   //         ||    \\               Ctl \     Ctl \     \\  Mem \
   //         ||    StoreN/P[mo_release] CastP2X   If   LoadB     |
-  //         | \ Bot / oop                          \            |
+  //         | \     /                              \            |
   //         | MergeMem                            . . .      StoreB
   //         | /                                                /
   //         ||     /
   //   MemBarVolatile
   //
-  // It is worth noting at this stage that all the above
+  // It is worth noting at this stage that both the above
   // configurations can be uniquely identified by checking that the
   // memory flow includes the following subgraph:
   //
   //   MemBarRelease
   //  {MemBarCPUOrder}
-  //      |  \      . . .
-  //      |  StoreX[mo_release]  . . .
-  //  Bot |   / oop
-  //     MergeMem
-  //      |
+  //          |  \      . . .
+  //          |  StoreX[mo_release]  . . .
+  //          |   /
+  //         MergeMem
+  //          |
   //   MemBarVolatile
   //
-  // This is referred to as a *normal* volatile store subgraph. It can
-  // easily be detected starting from any candidate MemBarRelease,
-  // StoreX[mo_release] or MemBarVolatile node.
-  //
-  // A small variation on this normal case occurs for an unsafe CAS
-  // operation. The basic memory flow subgraph for a non-object CAS is
-  // as follows
+  // This is referred to as a *normal* subgraph. It can easily be
+  // detected starting from any candidate MemBarRelease,
+  // StoreX[mo_release] or MemBarVolatile.
+  //
+  // A simple variation on this normal case occurs for an unsafe CAS
+  // operation. The basic graph for a non-object CAS is
   //
   //   MemBarRelease
   //         ||
   //   MemBarCPUOrder
-  //          |     \\   . . .
-  //          |     CompareAndSwapX
-  //          |       |
-  //      Bot |     SCMemProj
-  //           \     / Bot
-  //           MergeMem
-  //           /
+  //         ||     \\   . . .
+  //         ||     CompareAndSwapX
+  //         ||       |
+  //         ||     SCMemProj
+  //         | \     /
+  //         | MergeMem
+  //         | /
   //   MemBarCPUOrder
   //         ||
   //   MemBarAcquire
   //
   // The same basic variations on this arrangement (mutatis mutandis)
-  // occur when a card mark is introduced. i.e. the CPUOrder MemBar
-  // feeds the extra CastP2X, LoadB etc nodes but the above memory
-  // flow subgraph is still present.
-  // 
-  // This is referred to as a *normal* CAS subgraph. It can easily be
-  // detected starting from any candidate MemBarRelease,
-  // StoreX[mo_release] or MemBarAcquire node.
-  //
-  // The code below uses two helper predicates, leading_to_trailing
-  // and trailing_to_leading to identify these normal graphs, one
-  // validating the layout starting from the top membar and searching
-  // down and the other validating the layout starting from the lower
-  // membar and searching up.
-  //
-  // There are two special case GC configurations when the simple
-  // normal graphs above may not be generated: when using G1 (which
-  // always employs a conditional card mark); and when using CMS with
-  // conditional card marking (+CondCardMark) configured. These GCs
-  // are both concurrent rather than stop-the world GCs. So they
-  // introduce extra Ctl+Mem flow into the graph between the leading
-  // and trailing membar nodes, in particular enforcing stronger
-  // memory serialisation beween the object put and the corresponding
-  // conditional card mark. CMS employs a post-write GC barrier while
-  // G1 employs both a pre- and post-write GC barrier.
-  //
-  // The post-write barrier subgraph for these configurations includes
-  // a MemBarVolatile node -- referred to as a card mark membar --
-  // which is needed to order the card write (StoreCM) operation in
-  // the barrier, the preceding StoreX (or CompareAndSwapX) and Store
-  // operations performed by GC threads i.e. a card mark membar
-  // constitutes a StoreLoad barrier hence must be translated to a dmb
-  // ish (whether or not it sits inside a volatile store sequence).
-  //
-  // Of course, the use of the dmb ish for the card mark membar also
-  // implies theat the StoreCM which follows can omit the dmb ishst
-  // instruction. The necessary visibility ordering will already be
-  // guaranteed by the dmb ish. In sum, the dmb ishst instruction only
-  // needs to be generated for as part of the StoreCM sequence with GC
-  // configuration +CMS -CondCardMark.
-  // 
-  // Of course all these extra barrier nodes may well be absent --
-  // they are only inserted for object puts. Their potential presence
-  // significantly complicates the task of identifying whether a
-  // MemBarRelease, StoreX[mo_release], MemBarVolatile or
-  // MemBarAcquire forms part of a volatile put or CAS when using
-  // these GC configurations (see below) and also complicates the
-  // decision as to how to translate a MemBarVolatile and StoreCM.
-  //
-  // So, thjis means that a card mark MemBarVolatile occurring in the
-  // post-barrier graph it needs to be distinguished from a normal
-  // trailing MemBarVolatile. Resolving this is straightforward: a
-  // card mark MemBarVolatile always projects a Mem feed to a StoreCM
-  // node and that is a unique marker
+  // occur when a card mark is introduced. i.e. we se the same basic
+  // shape but the StoreP/N is replaced with CompareAndSawpP/N and the
+  // tail of the graph is a pair comprising a MemBarCPUOrder +
+  // MemBarAcquire.
+  //
+  // So, in the case of a CAS the normal graph has the variant form
+  //
+  //   MemBarRelease
+  //   MemBarCPUOrder
+  //          |   \      . . .
+  //          |  CompareAndSwapX  . . .
+  //          |    |
+  //          |   SCMemProj
+  //          |   /  . . .
+  //         MergeMem
+  //          |
+  //   MemBarCPUOrder
+  //   MemBarAcquire
+  //
+  // This graph can also easily be detected starting from any
+  // candidate MemBarRelease, CompareAndSwapX or MemBarAcquire.
+  //
+  // the code below uses two helper predicates, leading_to_normal and
+  // normal_to_leading to identify these normal graphs, one validating
+  // the layout starting from the top membar and searching down and
+  // the other validating the layout starting from the lower membar
+  // and searching up.
+  //
+  // There are two special case GC configurations when a normal graph
+  // may not be generated: when using G1 (which always employs a
+  // conditional card mark); and when using CMS with conditional card
+  // marking configured. These GCs are both concurrent rather than
+  // stop-the world GCs. So they introduce extra Ctl+Mem flow into the
+  // graph between the leading and trailing membar nodes, in
+  // particular enforcing stronger memory serialisation beween the
+  // object put and the corresponding conditional card mark. CMS
+  // employs a post-write GC barrier while G1 employs both a pre- and
+  // post-write GC barrier. Of course the extra nodes may be absent --
+  // they are only inserted for object puts. This significantly
+  // complicates the task of identifying whether a MemBarRelease,
+  // StoreX[mo_release] or MemBarVolatile forms part of a volatile put
+  // when using these GC configurations (see below). It adds similar
+  // complexity to the task of identifying whether a MemBarRelease,
+  // CompareAndSwapX or MemBarAcquire forms part of a CAS.
+  //
+  // In both cases the post-write subtree includes an auxiliary
+  // MemBarVolatile (StoreLoad barrier) separating the object put and
+  // the read of the corresponding card. This poses two additional
+  // problems.
+  //
+  // Firstly, a card mark MemBarVolatile needs to be distinguished
+  // from a normal trailing MemBarVolatile. Resolving this first
+  // problem is straightforward: a card mark MemBarVolatile always
+  // projects a Mem feed to a StoreCM node and that is a unique marker
   //
   //      MemBarVolatile (card mark)
   //       C |    \     . . .
   //         |   StoreCM   . . .
   //       . . .
   //
-  // Returning to the task of translating the object put and the
-  // leading/trailing membar nodes: what do the node graphs look like
-  // for these 2 special cases? and how can we determine the status of
-  // a MemBarRelease, StoreX[mo_release] or MemBarVolatile in both
-  // normal and non-normal cases?
+  // The second problem is how the code generator is to translate the
+  // card mark barrier? It always needs to be translated to a "dmb
+  // ish" instruction whether or not it occurs as part of a volatile
+  // put. A StoreLoad barrier is needed after the object put to ensure
+  // i) visibility to GC threads of the object put and ii) visibility
+  // to the mutator thread of any card clearing write by a GC
+  // thread. Clearly a normal store (str) will not guarantee this
+  // ordering but neither will a releasing store (stlr). The latter
+  // guarantees that the object put is visible but does not guarantee
+  // that writes by other threads have also been observed.
+  //
+  // So, returning to the task of translating the object put and the
+  // leading/trailing membar nodes: what do the non-normal node graph
+  // look like for these 2 special cases? and how can we determine the
+  // status of a MemBarRelease, StoreX[mo_release] or MemBarVolatile
+  // in both normal and non-normal cases?
   //
   // A CMS GC post-barrier wraps its card write (StoreCM) inside an If
   // which selects conditonal execution based on the value loaded
@@ -1605,117 +1612,91 @@
   // which looks like this
   //
   //   MemBarRelease
-  //   MemBarCPUOrder_(leading)____________________
-  //     C |  | M \       \\               M |   C \
-  //       |  |    \    StoreN/P[mo_release] |  CastP2X
-  //       |  | Bot \    / oop      \        |
-  //       |  |    MergeMem          \      / 
-  //       |  |      /                |    /
-  //     MemBarVolatile (card mark)   |   /
-  //     C |  ||    M |               |  /
-  //       | LoadB    | Bot       oop | / Bot
-  //       |   |      |              / /
-  //       | Cmp      |\            / /
-  //       | /        | \          / /
-  //       If         |  \        / /
-  //       | \        |   \      / /
-  // IfFalse  IfTrue  |    \    / /
-  //       \     / \  |    |   / /
-  //        \   / StoreCM  |  / /
-  //         \ /      \   /  / /
-  //        Region     Phi  / /
-  //          | \   Raw |  / /
-  //          |  . . .  | / /
+  //   MemBarCPUOrder_(leading)__________________
+  //     C |    M \       \\                   C \
+  //       |       \    StoreN/P[mo_release]  CastP2X
+  //       |    Bot \    /
+  //       |       MergeMem
+  //       |         /
+  //      MemBarVolatile (card mark)
+  //     C |  ||    M |
+  //       | LoadB    |
+  //       |   |      |
+  //       | Cmp      |\
+  //       | /        | \
+  //       If         |  \
+  //       | \        |   \
+  // IfFalse  IfTrue  |    \
+  //       \     / \  |     \
+  //        \   / StoreCM    |
+  //         \ /      |      |
+  //        Region   . . .   |
+  //          | \           /
+  //          |  . . .  \  / Bot
   //          |       MergeMem
-  //          |           |
+  //          |          |
   //        MemBarVolatile (trailing)
   //
-  // Notice that there are two MergeMem nodes below the leading
-  // membar. The first MergeMem merges the AliasIdxBot Mem slice from
-  // the leading membar and the oopptr Mem slice from the Store into
-  // the card mark membar. The trailing MergeMem merges the
-  // AliasIdxBot Mem slice from the leading membar, the AliasIdxRaw
-  // slice from the StoreCM and an oop slice from the StoreN/P node
-  // into the trailing membar (n.b. the raw slice proceeds via a Phi
-  // associated with the If region).
-  //
-  // So, in the case of CMS + CondCardMark the volatile object store
-  // graph still includes a normal volatile store subgraph from the
-  // leading membar to the trailing membar. However, it also contains
-  // the same shape memory flow to the card mark membar. The two flows
-  // can be distinguished by testing whether or not the downstream
-  // membar is a card mark membar.
-  //
-  // The graph for a CAS also varies with CMS + CondCardMark, in
-  // particular employing a control feed from the CompareAndSwapX node
-  // through a CmpI and If to the card mark membar and StoreCM which
-  // updates the associated card. This avoids executing the card mark
-  // if the CAS fails. However, it can be seen from the diagram below
-  // that the presence of the barrier does not alter the normal CAS
-  // memory subgraph where the leading membar feeds a CompareAndSwapX,
-  // an SCMemProj, a MergeMem then a final trailing MemBarCPUOrder and
-  // MemBarAcquire pair.
+  // The first MergeMem merges the AliasIdxBot Mem slice from the
+  // leading membar and the oopptr Mem slice from the Store into the
+  // card mark membar. The trailing MergeMem merges the AliasIdxBot
+  // Mem slice from the card mark membar and the AliasIdxRaw slice
+  // from the StoreCM into the trailing membar (n.b. the latter
+  // proceeds via a Phi associated with the If region).
+  //
+  // The graph for a CAS varies slightly, the obvious difference being
+  // that the StoreN/P node is replaced by a CompareAndSwapP/N node
+  // and the trailing MemBarVolatile by a MemBarCPUOrder +
+  // MemBarAcquire pair. The other important difference is that the
+  // CompareAndSwap node's SCMemProj is not merged into the card mark
+  // membar - it still feeds the trailing MergeMem. This also means
+  // that the card mark membar receives its Mem feed directly from the
+  // leading membar rather than via a MergeMem.
   //
   //   MemBarRelease
-  //   MemBarCPUOrder__(leading)_______________________
-  //   C /  M |                        \\            C \
-  //  . . .   | Bot                CompareAndSwapN/P   CastP2X
-  //          |                  C /  M |
-  //          |                 CmpI    |
-  //          |                  /      |
-  //          |               . . .     |
-  //          |              IfTrue     |
-  //          |              /          |
-  //       MemBarVolatile (card mark)   |
-  //        C |  ||    M |              |
-  //          | LoadB    | Bot   ______/|
-  //          |   |      |      /       |
-  //          | Cmp      |     /      SCMemProj
-  //          | /        |    /         |
-  //          If         |   /         /
-  //          | \        |  /         / Bot
-  //     IfFalse  IfTrue | /         /
-  //          |   / \   / / prec    /
-  //   . . .  |  /  StoreCM        /
-  //        \ | /      | raw      /
-  //        Region    . . .      /
-  //           | \              /
-  //           |   . . .   \    / Bot
-  //           |        MergeMem
-  //           |          /
-  //         MemBarCPUOrder
-  //         MemBarAcquire (trailing)
+  //   MemBarCPUOrder__(leading)_________________________
+  //       ||                       \\                 C \
+  //   MemBarVolatile (card mark)  CompareAndSwapN/P  CastP2X
+  //     C |  ||    M |              |
+  //       | LoadB    |       ______/|
+  //       |   |      |      /       |
+  //       | Cmp      |     /      SCMemProj
+  //       | /        |    /         |
+  //       If         |   /         /
+  //       | \        |  /         /
+  // IfFalse  IfTrue  | /         /
+  //       \     / \  |/ prec    /
+  //        \   / StoreCM       /
+  //         \ /      |        /
+  //        Region   . . .    /
+  //          | \            /
+  //          |  . . .  \   / Bot
+  //          |       MergeMem
+  //          |          |
+  //        MemBarCPUOrder
+  //        MemBarAcquire (trailing)
   //
   // This has a slightly different memory subgraph to the one seen
-  // previously but the core of it has a similar memory flow to the
-  // CAS normal subgraph:
+  // previously but the core of it is the same as for the CAS normal
+  // sungraph
   //
   //   MemBarRelease
   //   MemBarCPUOrder____
-  //         |          \      . . .
-  //         |       CompareAndSwapX  . . .
-  //         |       C /  M |
-  //         |      CmpI    |
-  //         |       /      |
-  //         |      . .    /
-  //     Bot |   IfTrue   /
-  //         |   /       /
-  //    MemBarVolatile  /
-  //         | ...     /
-  //      StoreCM ... /
-  //         |       / 
-  //       . . .  SCMemProj
-  //      Raw \    / Bot
-  //        MergeMem
-  //           |
+  //      ||             \      . . .
+  //   MemBarVolatile  CompareAndSwapX  . . .
+  //      |  \            |
+  //        . . .   SCMemProj
+  //          |     /  . . .
+  //         MergeMem
+  //          |
   //   MemBarCPUOrder
   //   MemBarAcquire
   //
-  // The G1 graph for a volatile object put is a lot more complicated.
-  // Nodes inserted on behalf of G1 may comprise: a pre-write graph
-  // which adds the old value to the SATB queue; the releasing store
-  // itself; and, finally, a post-write graph which performs a card
-  // mark.
+  //
+  // G1 is quite a lot more complicated. The nodes inserted on behalf
+  // of G1 may comprise: a pre-write graph which adds the old value to
+  // the SATB queue; the releasing store itself; and, finally, a
+  // post-write graph which performs a card mark.
   //
   // The pre-write graph may be omitted, but only when the put is
   // writing to a newly allocated (young gen) object and then only if
@@ -1753,60 +1734,25 @@
   //       | CastP2X | StoreN/P[mo_release] |
   //       |         |         |            |
   //     C |       M |       M |          M |
-  //        \        | Raw     | oop       / Bot
+  //        \        |         |           /
   //                  . . .
   //          (post write subtree elided)
   //                    . . .
   //             C \         M /
   //         MemBarVolatile (trailing)
   //
-  // Note that the three memory feeds into the post-write tree are an
-  // AliasRawIdx slice associated with the writes in the pre-write
-  // tree, an oop type slice from the StoreX specific to the type of
-  // the volatile field and the AliasBotIdx slice emanating from the
-  // leading membar.
-  //
   // n.b. the LoadB in this subgraph is not the card read -- it's a
   // read of the SATB queue active flag.
   //
-  // The CAS graph is once again a variant of the above with a
-  // CompareAndSwapX node and SCMemProj in place of the StoreX.  The
-  // value from the CompareAndSwapX node is fed into the post-write
-  // graph aling with the AliasIdxRaw feed from the pre-barrier and
-  // the AliasIdxBot feeds from the leading membar and the ScMemProj.
-  //
-  //  MemBarRelease (leading)____________
-  //     C |  ||  M \   M \    M \  M \ . . .
-  //       | LoadB   \  LoadL  LoadN   \
-  //       | /        \                 \
-  //       If         |\                 \
-  //       | \        | \                 \
-  //  IfFalse  IfTrue |  \                 \
-  //       |     |    |   \                 \
-  //       |     If   |    \                 |
-  //       |     |          \                |
-  //       |                 \               |
-  //       |    . . .         \              |
-  //       | /       | /       \             |
-  //      Region  Phi[M]        \            |
-  //       | \       |           \           |
-  //       |  \_____ |            |          |
-  //     C | C \     |            |          |
-  //       | CastP2X |     CompareAndSwapX   |
-  //       |         |   res |     |         |
-  //     C |       M |       |  SCMemProj  M |
-  //        \        | Raw   |     | Bot    / Bot
-  //                  . . .
-  //          (post write subtree elided)
-  //                    . . .
-  //             C \         M /
-  //         MemBarVolatile (trailing)
+  // Once again the CAS graph is a minor variant on the above with the
+  // expected substitutions of CompareAndSawpX for StoreN/P and
+  // MemBarCPUOrder + MemBarAcquire for trailing MemBarVolatile.
   //
   // The G1 post-write subtree is also optional, this time when the
   // new value being written is either null or can be identified as a
   // newly allocated (young gen) object with no intervening control
   // flow. The latter cannot happen but the former may, in which case
-  // the card mark membar is omitted and the memory feeds from the
+  // the card mark membar is omitted and the memory feeds form the
   // leading membar and the SToreN/P are merged direct into the
   // trailing membar as per the normal subgraph. So, the only special
   // case which arises is when the post-write subgraph is generated.
@@ -1828,106 +1774,94 @@
   //
   //                (pre-write subtree elided)
   //        . . .                  . . .    . . .  . . .
-  //        C |               M |    M |    M |
-  //       Region            Phi[M] StoreN    |
-  //          |            Raw  |  oop |  Bot |
-  //         / \_______         |\     |\     |\
-  //      C / C \      . . .    | \    | \    | \
-  //       If   CastP2X . . .   |  \   |  \   |  \
-  //       / \                  |   \  |   \  |   \
-  //      /   \                 |    \ |    \ |    \
-  // IfFalse IfTrue             |      |      |     \
-  //   |       |                 \     |     /       |
-  //   |       If                 \    | \  /   \    |
-  //   |      / \                  \   |   /     \   |
-  //   |     /   \                  \  |  / \     |  |
-  //   | IfFalse IfTrue           MergeMem   \    |  |
-  //   |  . . .    / \                 |      \   |  |
-  //   |          /   \                |       |  |  |
-  //   |     IfFalse IfTrue            |       |  |  |
-  //   |      . . .    |               |       |  |  |
-  //   |               If             /        |  |  |
-  //   |               / \           /         |  |  |
-  //   |              /   \         /          |  |  |
-  //   |         IfFalse IfTrue    /           |  |  |
-  //   |           . . .   |      /            |  |  |
-  //   |                    \    /             |  |  |
-  //   |                     \  /              |  |  |
-  //   |         MemBarVolatile__(card mark  ) |  |  |
-  //   |              ||   C |     \           |  |  |
-  //   |             LoadB   If     |         /   |  |
-  //   |                    / \ Raw |        /   /  /
-  //   |                   . . .    |       /   /  /
-  //   |                        \   |      /   /  /
-  //   |                        StoreCM   /   /  /
-  //   |                           |     /   /  /
-  //   |                            . . .   /  /
-  //   |                                   /  /
-  //   |   . . .                          /  /
-  //   |    |             | /            /  /
-  //   |    |           Phi[M] /        /  /
-  //   |    |             |   /        /  /
-  //   |    |             |  /        /  /
-  //   |  Region  . . .  Phi[M]      /  /
-  //   |    |             |         /  /
-  //    \   |             |        /  /
-  //     \  | . . .       |       /  /
-  //      \ |             |      /  /
-  //      Region         Phi[M] /  /
-  //        |               \  /  /
-  //         \             MergeMem
-  //          \            /
-  //          MemBarVolatile
-  //
-  // As with CMS + CondCardMark the first MergeMem merges the
-  // AliasIdxBot Mem slice from the leading membar and the oopptr Mem
-  // slice from the Store into the card mark membar. However, in this
-  // case it may also merge an AliasRawIdx mem slice from the pre
-  // barrier write.
-  //
-  // The trailing MergeMem merges an AliasIdxBot Mem slice from the
-  // leading membar with an oop slice from the StoreN and an
-  // AliasRawIdx slice from the post barrier writes. In this case the
-  // AliasIdxRaw Mem slice is merged through a series of Phi nodes
-  // which combine feeds from the If regions in the post barrier
-  // subgraph.
-  //
-  // So, for G1 the same characteristic subgraph arises as for CMS +
-  // CondCardMark. There is a normal subgraph feeding the card mark
-  // membar and a normal subgraph feeding the trailing membar.
-  //
-  // The CAS graph when using G1GC also includes an optional
-  // post-write subgraph. It is very similar to the above graph except
-  // for a few details.
-  // 
-  // - The control flow is gated by an additonal If which tests the
-  // result from the CompareAndSwapX node
-  // 
-  //  - The MergeMem which feeds the card mark membar only merges the
-  // AliasIdxBot slice from the leading membar and the AliasIdxRaw
-  // slice from the pre-barrier. It does not merge the SCMemProj
-  // AliasIdxBot slice. So, this subgraph does not look like the
-  // normal CAS subgraph.
-  //
-  // - The MergeMem which feeds the trailing membar merges the
-  // AliasIdxBot slice from the leading membar, the AliasIdxRaw slice
-  // from the post-barrier and the SCMemProj AliasIdxBot slice i.e. it
-  // has two AliasIdxBot input slices. However, this subgraph does
-  // still look like the normal CAS subgraph.
-  //
-  // So, the upshot is:
-  //
-  // In all cases a volatile put graph will include a *normal*
-  // volatile store subgraph betwen the leading membar and the
-  // trailing membar. It may also include a normal volatile store
-  // subgraph betwen the leading membar and the card mark membar.
-  //
-  // In all cases a CAS graph will contain a unique normal CAS graph
-  // feeding the trailing membar.
-  //
-  // In all cases where there is a card mark membar (either as part of
-  // a volatile object put or CAS) it will be fed by a MergeMem whose
-  // AliasIdxBot slice feed will be a leading membar.
+  //        C |                    M |     M |    M |
+  //       Region                  Phi[M] StoreN    |
+  //          |                     / \      |      |
+  //         / \_______            /   \     |      |
+  //      C / C \      . . .            \    |      |
+  //       If   CastP2X . . .            |   |      |
+  //       / \                           |   |      |
+  //      /   \                          |   |      |
+  // IfFalse IfTrue                      |   |      |
+  //   |       |                         |   |     /|
+  //   |       If                        |   |    / |
+  //   |      / \                        |   |   /  |
+  //   |     /   \                        \  |  /   |
+  //   | IfFalse IfTrue                   MergeMem  |
+  //   |  . . .    / \                       /      |
+  //   |          /   \                     /       |
+  //   |     IfFalse IfTrue                /        |
+  //   |      . . .    |                  /         |
+  //   |               If                /          |
+  //   |               / \              /           |
+  //   |              /   \            /            |
+  //   |         IfFalse IfTrue       /             |
+  //   |           . . .   |         /              |
+  //   |                    \       /               |
+  //   |                     \     /                |
+  //   |             MemBarVolatile__(card mark)    |
+  //   |                ||   C |  M \  M \          |
+  //   |               LoadB   If    |    |         |
+  //   |                      / \    |    |         |
+  //   |                     . . .   |    |         |
+  //   |                          \  |    |        /
+  //   |                        StoreCM   |       /
+  //   |                          . . .   |      /
+  //   |                        _________/      /
+  //   |                       /  _____________/
+  //   |   . . .       . . .  |  /            /
+  //   |    |                 | /   _________/
+  //   |    |               Phi[M] /        /
+  //   |    |                 |   /        /
+  //   |    |                 |  /        /
+  //   |  Region  . . .     Phi[M]  _____/
+  //   |    /                 |    /
+  //   |                      |   /
+  //   | . . .   . . .        |  /
+  //   | /                    | /
+  // Region           |  |  Phi[M]
+  //   |              |  |  / Bot
+  //    \            MergeMem
+  //     \            /
+  //     MemBarVolatile
+  //
+  // As with CMS the initial MergeMem merges the AliasIdxBot Mem slice
+  // from the leading membar and the oopptr Mem slice from the Store
+  // into the card mark membar i.e. the memory flow to the card mark
+  // membar still looks like a normal graph.
+  //
+  // The trailing MergeMem merges an AliasIdxBot Mem slice with other
+  // Mem slices (from the StoreCM and other card mark queue stores).
+  // However in this case the AliasIdxBot Mem slice does not come
+  // direct from the card mark membar. It is merged through a series
+  // of Phi nodes. These are needed to merge the AliasIdxBot Mem flow
+  // from the leading membar with the Mem feed from the card mark
+  // membar. Each Phi corresponds to one of the Ifs which may skip
+  // around the card mark membar. So when the If implementing the NULL
+  // value check has been elided the total number of Phis is 2
+  // otherwise it is 3.
+  //
+  // The CAS graph when using G1GC also includes a pre-write subgraph
+  // and an optional post-write subgraph. Teh sam evarioations are
+  // introduced as for CMS with conditional card marking i.e. the
+  // StoreP/N is swapped for a CompareAndSwapP/N, the tariling
+  // MemBarVolatile for a MemBarCPUOrder + MemBarAcquire pair and the
+  // Mem feed from the CompareAndSwapP/N includes a precedence
+  // dependency feed to the StoreCM and a feed via an SCMemProj to the
+  // trailing membar. So, as before the configuration includes the
+  // normal CAS graph as a subgraph of the memory flow.
+  //
+  // So, the upshot is that in all cases the volatile put graph will
+  // include a *normal* memory subgraph betwen the leading membar and
+  // its child membar, either a volatile put graph (including a
+  // releasing StoreX) or a CAS graph (including a CompareAndSwapX).
+  // When that child is not a card mark membar then it marks the end
+  // of the volatile put or CAS subgraph. If the child is a card mark
+  // membar then the normal subgraph will form part of a volatile put
+  // subgraph if and only if the child feeds an AliasIdxBot Mem feed
+  // to a trailing barrier via a MergeMem. That feed is either direct
+  // (for CMS) or via 2 or 3 Phi nodes merging the leading barrier
+  // memory flow (for G1).
   //
   // The predicates controlling generation of instructions for store
   // and barrier nodes employ a few simple helper functions (described
@@ -1971,24 +1905,24 @@
   }
 
 
-  // leading_to_trailing
+  // leading_to_normal
   //
   //graph traversal helper which detects the normal case Mem feed from
   // a release membar (or, optionally, its cpuorder child) to a
   // dependent volatile membar i.e. it ensures that one or other of
   // the following Mem flow subgraph is present.
   //
-  //   MemBarRelease {leading}
-  //   {MemBarCPUOrder} {optional}
-  //     Bot |  \      . . .
-  //         |  StoreN/P[mo_release]  . . .
-  //         |   /
-  //        MergeMem
-  //         |
-  //   MemBarVolatile {not card mark}
-  //
-  //   MemBarRelease {leading}
-  //   {MemBarCPUOrder} {optional}
+  //   MemBarRelease
+  //   MemBarCPUOrder {leading}
+  //          |  \      . . .
+  //          |  StoreN/P[mo_release]  . . .
+  //          |   /
+  //         MergeMem
+  //          |
+  //   MemBarVolatile {trailing or card mark}
+  //
+  //   MemBarRelease
+  //   MemBarCPUOrder {leading}
   //      |       \      . . .
   //      |     CompareAndSwapX  . . .
   //               |
@@ -1999,23 +1933,6 @@
   //    MemBarCPUOrder
   //    MemBarAcquire {trailing}
   //
-  // the predicate needs to be capable of distinguishing the following
-  // volatile put graph which may arises when a GC post barrier
-  // inserts a card mark membar
-  //
-  //   MemBarRelease {leading}
-  //   {MemBarCPUOrder}__
-  //     Bot |   \       \
-  //         |   StoreN/P \
-  //         |    / \     |
-  //        MergeMem \    |
-  //         |        \   |
-  //   MemBarVolatile  \  |
-  //    {card mark}     \ |
-  //                  MergeMem
-  //                      |
-  // {not card mark} MemBarVolatile
-  //
   // if the correct configuration is present returns the trailing
   // membar otherwise NULL.
   //
@@ -2026,7 +1943,7 @@
   // the returned value may be a card mark or trailing membar
   //
 
-  MemBarNode *leading_to_trailing(MemBarNode *leading)
+  MemBarNode *leading_to_normal(MemBarNode *leading)
   {
     assert((leading->Opcode() == Op_MemBarRelease ||
 	    leading->Opcode() == Op_MemBarCPUOrder),
@@ -2043,21 +1960,15 @@
     StoreNode * st = NULL;
     LoadStoreNode *cas = NULL;
     MergeMemNode *mm = NULL;
-    MergeMemNode *mm2 = NULL;
 
     for (DUIterator_Fast imax, i = mem->fast_outs(imax); i < imax; i++) {
       x = mem->fast_out(i);
       if (x->is_MergeMem()) {
 	if (mm != NULL) {
-	  if (mm2 != NULL) {
-	  // should not see more than 2 merge mems
-	    return NULL;
-	  } else {
-	    mm2 = x->as_MergeMem();
-	  }
-	} else {
-	  mm = x->as_MergeMem();
+	  return NULL;
 	}
+	// two merge mems is one too many
+	mm = x->as_MergeMem();
       } else if (x->is_Store() && x->as_Store()->is_release() && x->Opcode() != Op_StoreCM) {
 	// two releasing stores/CAS nodes is one too many
 	if (st != NULL || cas != NULL) {
@@ -2077,13 +1988,13 @@
       return NULL;
     }
 
-    // must have at least one merge if we also have st
+    // must have a merge if we also have st
     if (st && !mm) {
       return NULL;
     }
 
+    Node *y = NULL;
     if (cas) {
-      Node *y = NULL;
       // look for an SCMemProj
       for (DUIterator_Fast imax, i = cas->fast_outs(imax); i < imax; i++) {
 	x = cas->fast_out(i);
@@ -2103,29 +2014,10 @@
 	  break;
 	}
       }
-      if (mm == NULL) {
+      if (mm == NULL)
 	return NULL;
-      }
-      MemBarNode *mbar = NULL;
-      // ensure the merge feeds a trailing membar cpuorder + acquire pair
-      for (DUIterator_Fast imax, i = mm->fast_outs(imax); i < imax; i++) {
-	x = mm->fast_out(i);
-	if (x->is_MemBar()) {
-	  int opcode = x->Opcode();
-	  if (opcode == Op_MemBarCPUOrder) {
-	    MemBarNode *z =  x->as_MemBar();
-	    z = child_membar(z);
-	    if (z != NULL && z->Opcode() == Op_MemBarAcquire) {
-	      mbar = z;
-	    }
-	  }
-	  break;
-	}
-      }
-      return mbar;
     } else {
-      Node *y = NULL;
-      // ensure the store feeds the first mergemem;
+      // ensure the store feeds the existing mergemem;
       for (DUIterator_Fast imax, i = st->fast_outs(imax); i < imax; i++) {
 	if (st->fast_out(i) == mm) {
 	  y = st;
@@ -2135,89 +2027,55 @@
       if (y == NULL) {
 	return NULL;
       }
-      if (mm2 != NULL) {
-	// ensure the store feeds the second mergemem;
-	y = NULL;
-	for (DUIterator_Fast imax, i = st->fast_outs(imax); i < imax; i++) {
-	  if (st->fast_out(i) == mm2) {
-	    y = st;
+    }
+
+    MemBarNode *mbar = NULL;
+    // ensure the merge feeds to the expected type of membar
+    for (DUIterator_Fast imax, i = mm->fast_outs(imax); i < imax; i++) {
+      x = mm->fast_out(i);
+      if (x->is_MemBar()) {
+	int opcode = x->Opcode();
+	if (opcode == Op_MemBarVolatile && st) {
+	  mbar = x->as_MemBar();
+	} else if (cas && opcode == Op_MemBarCPUOrder) {
+	  MemBarNode *y =  x->as_MemBar();
+	  y = child_membar(y);
+	  if (y != NULL && y->Opcode() == Op_MemBarAcquire) {
+	    mbar = y;
 	  }
 	}
-	if (y == NULL) {
-	  return NULL;
-	}
+	break;
       }
-
-      MemBarNode *mbar = NULL;
-      // ensure the first mergemem feeds a volatile membar
-      for (DUIterator_Fast imax, i = mm->fast_outs(imax); i < imax; i++) {
-	x = mm->fast_out(i);
-	if (x->is_MemBar()) {
-	  int opcode = x->Opcode();
-	  if (opcode == Op_MemBarVolatile) {
-	    mbar = x->as_MemBar();
-	  }
-	  break;
-	}
-      }
-      if (mm2 == NULL) {
-	// this is our only option for a trailing membar
-	return mbar;
-      }
-      // ensure the second mergemem feeds a volatile membar
-      MemBarNode *mbar2 = NULL;
-      for (DUIterator_Fast imax, i = mm2->fast_outs(imax); i < imax; i++) {
-	x = mm2->fast_out(i);
-	if (x->is_MemBar()) {
-	  int opcode = x->Opcode();
-	  if (opcode == Op_MemBarVolatile) {
-	    mbar2 = x->as_MemBar();
-	  }
-	  break;
-	}
-      }
-      // if we have two merge mems we must have two volatile membars
-      if (mbar == NULL || mbar2 == NULL) {
-	return NULL;
-      }
-      // return the trailing membar
-      if (is_card_mark_membar(mbar2)) {
-	return mbar;
-      } else {
-	if (is_card_mark_membar(mbar)) {
-	  return mbar2;
-	} else {
-	  return NULL;
-	}
-      }
-    }
-  }
-
-  // trailing_to_leading
+    }
+
+    return mbar;
+  }
+
+  // normal_to_leading
   //
   // graph traversal helper which detects the normal case Mem feed
-  // from a trailing membar to a preceding release membar (optionally
-  // its cpuorder child) i.e. it ensures that one or other of the
-  // following Mem flow subgraphs is present.
-  //
-  //   MemBarRelease {leading}
-  //   MemBarCPUOrder {optional}
-  //    | Bot |  \      . . .
-  //    |     |  StoreN/P[mo_release]  . . .
-  //    |     |   /
-  //    |    MergeMem
-  //    |     |
-  //   MemBarVolatile {not card mark}
-  //
-  //   MemBarRelease {leading}
-  //   MemBarCPUOrder {optional}
+  // from either a card mark or a trailing membar to a preceding
+  // release membar (optionally its cpuorder child) i.e. it ensures
+  // that one or other of the following Mem flow subgraphs is present.
+  //
+  //   MemBarRelease
+  //   MemBarCPUOrder {leading}
+  //          |  \      . . .
+  //          |  StoreN/P[mo_release]  . . .
+  //          |   /
+  //         MergeMem
+  //          |
+  //   MemBarVolatile {card mark or trailing}
+  //
+  //   MemBarRelease
+  //   MemBarCPUOrder {leading}
   //      |       \      . . .
   //      |     CompareAndSwapX  . . .
   //               |
   //     . . .    SCMemProj
   //           \   |
   //      |    MergeMem
-  //      |       |
+  //      |        /
   //    MemBarCPUOrder
   //    MemBarAcquire {trailing}
   //
@@ -2227,20 +2085,15 @@
   // if the configuration is present returns the cpuorder member for
   // preference or when absent the release membar otherwise NULL.
   //
-  // n.b. the input membar is expected to be a MemBarVolatile or
-  // MemBarAcquire. if it is a MemBarVolatile it must *not* be a card
-  // mark membar.
-
-  MemBarNode *trailing_to_leading(const MemBarNode *barrier)
+  // n.b. the input membar is expected to be a MemBarVolatile but
+  // need not be a card mark membar.
+
+  MemBarNode *normal_to_leading(const MemBarNode *barrier)
   {
     // input must be a volatile membar
     assert((barrier->Opcode() == Op_MemBarVolatile ||
 	    barrier->Opcode() == Op_MemBarAcquire),
 	   "expecting a volatile or an acquire membar");
-
-    assert((barrier->Opcode() != Op_MemBarVolatile) ||
-	   !is_card_mark_membar(barrier),
-	   "not expecting a card mark membar");
     Node *x;
     bool is_cas = barrier->Opcode() == Op_MemBarAcquire;
 
@@ -2353,35 +2206,169 @@
     return NULL;
   }
 
-  // card_mark_to_leading
-  //
-  // graph traversal helper which traverses from a card mark volatile
-  // membar to a leading membar i.e. it ensures that the following Mem
-  // flow subgraph is present.
-  //
-  //    MemBarRelease {leading}
-  //   {MemBarCPUOrder} {optional}
-  //         |   . . .
+  // card_mark_to_trailing
+  //
+  // graph traversal helper which detects extra, non-normal Mem feed
+  // from a card mark volatile membar to a trailing membar i.e. it
+  // ensures that one of the following three GC post-write Mem flow
+  // subgraphs is present.
+  //
+  // 1)
+  //     . . .
+  //       |
+  //   MemBarVolatile (card mark)
+  //      |          |
+  //      |        StoreCM
+  //      |          |
+  //      |        . . .
+  //  Bot |  /
+  //   MergeMem
+  //      |
+  //      |
+  //    MemBarVolatile {trailing}
+  //
+  // 2)
+  //   MemBarRelease/CPUOrder (leading)
+  //    |
+  //    |
+  //    |\       . . .
+  //    | \        |
+  //    |  \  MemBarVolatile (card mark)
+  //    |   \   |     |
+  //     \   \  |   StoreCM    . . .
+  //      \   \ |
+  //       \  Phi
+  //        \ /
+  //        Phi  . . .
   //     Bot |   /
-  //      MergeMem
+  //       MergeMem
   //         |
-  //     MemBarVolatile (card mark)
-  //        |     \
-  //      . . .   StoreCM
-  //
-  // if the configuration is present returns the cpuorder member for
-  // preference or when absent the release membar otherwise NULL.
-  //
-  // n.b. the input membar is expected to be a MemBarVolatile amd must
-  // be a card mark membar.
-
-  MemBarNode *card_mark_to_leading(const MemBarNode *barrier)
+  //    MemBarVolatile {trailing}
+  //
+  //
+  // 3)
+  //   MemBarRelease/CPUOrder (leading)
+  //    |
+  //    |\
+  //    | \
+  //    |  \      . . .
+  //    |   \       |
+  //    |\   \  MemBarVolatile (card mark)
+  //    | \   \   |     |
+  //    |  \   \  |   StoreCM    . . .
+  //    |   \   \ |
+  //     \   \  Phi
+  //      \   \ /
+  //       \  Phi
+  //        \ /
+  //        Phi  . . .
+  //     Bot |   /
+  //       MergeMem
+  //         |
+  //         |
+  //    MemBarVolatile {trailing}
+  //
+  // configuration 1 is only valid if UseConcMarkSweepGC &&
+  // UseCondCardMark
+  //
+  // configurations 2 and 3 are only valid if UseG1GC.
+  //
+  // if a valid configuration is present returns the trailing membar
+  // otherwise NULL.
+  //
+  // n.b. the supplied membar is expected to be a card mark
+  // MemBarVolatile i.e. the caller must ensure the input node has the
+  // correct operand and feeds Mem to a StoreCM node
+
+  MemBarNode *card_mark_to_trailing(const MemBarNode *barrier)
   {
     // input must be a card mark volatile membar
     assert(is_card_mark_membar(barrier), "expecting a card mark membar");
 
+    Node *feed = barrier->proj_out(TypeFunc::Memory);
+    Node *x;
+    MergeMemNode *mm = NULL;
+
+    const int MAX_PHIS = 3;	// max phis we will search through
+    int phicount = 0; 		// current search count
+
+    bool retry_feed = true;
+    while (retry_feed) {
+      // see if we have a direct MergeMem feed
+      for (DUIterator_Fast imax, i = feed->fast_outs(imax); i < imax; i++) {
+	x = feed->fast_out(i);
+	// the correct Phi will be merging a Bot memory slice
+	if (x->is_MergeMem()) {
+	  mm = x->as_MergeMem();
+	  break;
+	}
+      }
+      if (mm) {
+	retry_feed = false;
+      } else if (UseG1GC & phicount++ < MAX_PHIS) {
+	// the barrier may feed indirectly via one or two Phi nodes
+	PhiNode *phi = NULL;
+	for (DUIterator_Fast imax, i = feed->fast_outs(imax); i < imax; i++) {
+	  x = feed->fast_out(i);
+	  // the correct Phi will be merging a Bot memory slice
+	  if (x->is_Phi() && x->adr_type() == TypePtr::BOTTOM) {
+	    phi = x->as_Phi();
+	    break;
+	  }
+	}
+	if (!phi) {
+	  return NULL;
+	}
+	// look for another merge below this phi
+	feed = phi;
+      } else {
+	// couldn't find a merge
+	return NULL;
+      }
+    }
+
+    // sanity check this feed turns up as the expected slice
+    assert(mm->as_MergeMem()->in(Compile::AliasIdxBot) == feed, "expecting membar to feed AliasIdxBot slice to Merge");
+
+    MemBarNode *trailing = NULL;
+    // be sure we have a trailing membar the merge
+    for (DUIterator_Fast imax, i = mm->fast_outs(imax); i < imax; i++) {
+      x = mm->fast_out(i);
+      if (x->is_MemBar() && x->Opcode() == Op_MemBarVolatile) {
+	trailing = x->as_MemBar();
+	break;
+      }
+    }
+
+    return trailing;
+  }
+
+  // trailing_to_card_mark
+  //
+  // graph traversal helper which detects extra, non-normal Mem feed
+  // from a trailing volatile membar to a preceding card mark volatile
+  // membar i.e. it identifies whether one of the three possible extra
+  // GC post-write Mem flow subgraphs is present
+  //
+  // this predicate checks for the same flow as the previous predicate
+  // but starting from the bottom rather than the top.
+  //
+  // if the configuration is present returns the card mark membar
+  // otherwise NULL
+  //
+  // n.b. the supplied membar is expected to be a trailing
+  // MemBarVolatile i.e. the caller must ensure the input node has the
+  // correct opcode
+
+  MemBarNode *trailing_to_card_mark(const MemBarNode *trailing)
+  {
+    assert(trailing->Opcode() == Op_MemBarVolatile,
+	   "expecting a volatile membar");
+    assert(!is_card_mark_membar(trailing),
+	   "not expecting a card mark membar");
+
     // the Mem feed to the membar should be a merge
-    Node *x = barrier->in(TypeFunc::Memory);
+    Node *x = trailing->in(TypeFunc::Memory);
     if (!x->is_MergeMem()) {
       return NULL;
     }
@@ -2389,19 +2376,117 @@
     MergeMemNode *mm = x->as_MergeMem();
 
     x = mm->in(Compile::AliasIdxBot);
-
+    // with G1 we may possibly see a Phi or two before we see a Memory
+    // Proj from the card mark membar
+
+    const int MAX_PHIS = 3;	// max phis we will search through
+    int phicount = 0; 		// current search count
+
+    bool retry_feed = !x->is_Proj();
+
+    while (retry_feed) {
+      if (UseG1GC && x->is_Phi() && phicount++ < MAX_PHIS) {
+	PhiNode *phi = x->as_Phi();
+	ProjNode *proj = NULL;
+	PhiNode *nextphi = NULL;
+	bool found_leading = false;
+	for (uint i = 1; i < phi->req(); i++) {
+	  x = phi->in(i);
+	  if (x->is_Phi()) {
+	    nextphi = x->as_Phi();
+	  } else if (x->is_Proj()) {
+	    int opcode = x->in(0)->Opcode();
+	    if (opcode == Op_MemBarVolatile) {
+	      proj = x->as_Proj();
+	    } else if (opcode == Op_MemBarRelease ||
+		       opcode == Op_MemBarCPUOrder) {
+	      // probably a leading membar
+	      found_leading = true;
+	    }
+	  }
+	}
+	// if we found a correct looking proj then retry from there
+	// otherwise we must see a leading and a phi or this the
+	// wrong config
+	if (proj != NULL) {
+	  x = proj;
+	  retry_feed = false;
+	} else if (found_leading && nextphi != NULL) {
+	  // retry from this phi to check phi2
+	  x = nextphi;
+	} else {
+	  // not what we were looking for
+	  return NULL;
+	}
+      } else {
+	return NULL;
+      }
+    }
+    // the proj has to come from the card mark membar
+    x = x->in(0);
     if (!x->is_MemBar()) {
       return NULL;
     }
 
-    MemBarNode *leading = x->as_MemBar();
-
-    if (leading_membar(leading)) {
+    MemBarNode *card_mark_membar = x->as_MemBar();
+
+    if (!is_card_mark_membar(card_mark_membar)) {
+      return NULL;
+    }
+
+    return card_mark_membar;
+  }
+
+  // trailing_to_leading
+  //
+  // graph traversal helper which checks the Mem flow up the graph
+  // from a (non-card mark) trailing membar attempting to locate and
+  // return an associated leading membar. it first looks for a
+  // subgraph in the normal configuration (relying on helper
+  // normal_to_leading). failing that it then looks for one of the
+  // possible post-write card mark subgraphs linking the trailing node
+  // to a the card mark membar (relying on helper
+  // trailing_to_card_mark), and then checks that the card mark membar
+  // is fed by a leading membar (once again relying on auxiliary
+  // predicate normal_to_leading).
+  //
+  // if the configuration is valid returns the cpuorder member for
+  // preference or when absent the release membar otherwise NULL.
+  //
+  // n.b. the input membar is expected to be either a volatile or
+  // acquire membar but in the former case must *not* be a card mark
+  // membar.
+
+  MemBarNode *trailing_to_leading(const MemBarNode *trailing)
+  {
+    assert((trailing->Opcode() == Op_MemBarAcquire ||
+	    trailing->Opcode() == Op_MemBarVolatile),
+	   "expecting an acquire or volatile membar");
+    assert((trailing->Opcode() != Op_MemBarVolatile ||
+	    !is_card_mark_membar(trailing)),
+	   "not expecting a card mark membar");
+
+    MemBarNode *leading = normal_to_leading(trailing);
+
+    if (leading) {
       return leading;
     }
 
-    return NULL;
-  }
+    // nothing more to do if this is an acquire
+    if (trailing->Opcode() == Op_MemBarAcquire) {
+      return NULL;
+    }
+
+    MemBarNode *card_mark_membar = trailing_to_card_mark(trailing);
+
+    if (!card_mark_membar) {
+      return NULL;
+    }
+
+    return normal_to_leading(card_mark_membar);
+  }
+
+  // predicates controlling emit of ldr<x>/ldar<x> and associated dmb
 
 bool unnecessary_acquire(const Node *barrier)
 {
@@ -2617,8 +2702,19 @@
   }
 
   // must start with a normal feed
-  MemBarNode *trailing = leading_to_trailing(barrier);
-
+  MemBarNode *child_barrier = leading_to_normal(barrier);
+
+  if (!child_barrier) {
+    return false;
+  }
+
+  if (!is_card_mark_membar(child_barrier)) {
+    // this is the trailing membar and we are done
+    return true;
+  }
+
+  // must be sure this card mark feeds a trailing membar
+  MemBarNode *trailing = card_mark_to_trailing(child_barrier);
   return (trailing != NULL);
 }
 
@@ -2640,7 +2736,7 @@
   }
 
   // ok, if it's not a card mark then we still need to check if it is
-  // a trailing membar of a volatile put graph.
+  // a trailing membar of a volatile put hgraph.
 
   return (trailing_to_leading(mbvol) != NULL);
 }
@@ -2690,9 +2786,20 @@
   }
 
   // does this lead a normal subgraph?
-  MemBarNode *trailing = leading_to_trailing(barrier);
-
-  return (trailing != NULL);
+  MemBarNode *mbvol = leading_to_normal(barrier);
+
+  if (!mbvol) {
+    return false;
+  }
+
+  // all done unless this is a card mark
+  if (!is_card_mark_membar(mbvol)) {
+    return true;
+  }
+
+  // we found a card mark -- just make sure we have a trailing barrier
+
+  return (card_mark_to_trailing(mbvol) != NULL);
 }
 
 // predicate controlling translation of CAS
@@ -2734,7 +2841,7 @@
 	  "CAS not fed by cpuorder+release membar pair!");
 
   // does this lead a normal subgraph?
-  MemBarNode *mbar = leading_to_trailing(barrier);
+  MemBarNode *mbar = leading_to_normal(barrier);
 
   assert(mbar != NULL, "CAS not embedded in normal graph!");
 
@@ -2755,27 +2862,48 @@
 
   // we only ever need to generate a dmb ishst between an object put
   // and the associated card mark when we are using CMS without
-  // conditional card marking. Any other occurence will happen when
-  // performing a card mark using CMS with conditional card marking or
-  // G1. In those cases the preceding MamBarVolatile will be
-  // translated to a dmb ish which guarantes visibility of the
-  // preceding StoreN/P before this StoreCM
+  // conditional card marking
 
   if (!UseConcMarkSweepGC || UseCondCardMark) {
     return true;
   }
 
-  // if we are implementing volatile puts using barriers then we must
-  // insert the dmb ishst
+  // if we are implementing volatile puts using barriers then the
+  // object put as an str so we must insert the dmb ishst
 
   if (UseBarriersForVolatile) {
     return false;
   }
 
-  // we must be using CMS with conditional card marking so we ahve to
-  // generate the StoreStore
-
-  return false;
+  // we can omit the dmb ishst if this StoreCM is part of a volatile
+  // put because in thta case the put will be implemented by stlr
+  //
+  // we need to check for a normal subgraph feeding this StoreCM.
+  // that means the StoreCM must be fed Memory from a leading membar,
+  // either a MemBarRelease or its dependent MemBarCPUOrder, and the
+  // leading membar must be part of a normal subgraph
+
+  Node *x = storecm->in(StoreNode::Memory);
+
+  if (!x->is_Proj()) {
+    return false;
+  }
+
+  x = x->in(0);
+
+  if (!x->is_MemBar()) {
+    return false;
+  }
+
+  MemBarNode *leading = x->as_MemBar();
+
+  // reject invalid candidates
+  if (!leading_membar(leading)) {
+    return false;
+  }
+
+  // we can omit the StoreStore if it is the head of a normal subgraph
+  return (leading_to_normal(leading) != NULL);
 }
 
 
@@ -3008,6 +3136,10 @@
     __ notify(Assembler::method_reentry);
   }
 
+  if (StackReservedPages > 0 && C->has_reserved_stack_access()) {
+    __ reserved_stack_check();
+  }
+
   if (do_polling() && C->is_method_compilation()) {
     __ read_polling_page(rscratch1, os::get_polling_page(), relocInfo::poll_return_type);
   }
@@ -9862,7 +9994,7 @@
 // END This section of the file is automatically generated. Do not edit --------------
 // ---------------------------------------------------------------------
 
-instruct get_and_setI(indirect mem, iRegINoSp newv, iRegI prev) %{
+instruct get_and_setI(indirect mem, iRegI newv, iRegINoSp prev) %{
   match(Set prev (GetAndSetI mem newv));
   format %{ "atomic_xchgw  $prev, $newv, [$mem]" %}
   ins_encode %{
@@ -9871,7 +10003,7 @@
   ins_pipe(pipe_serial);
 %}
 
-instruct get_and_setL(indirect mem, iRegLNoSp newv, iRegL prev) %{
+instruct get_and_setL(indirect mem, iRegL newv, iRegLNoSp prev) %{
   match(Set prev (GetAndSetL mem newv));
   format %{ "atomic_xchg  $prev, $newv, [$mem]" %}
   ins_encode %{
@@ -9880,7 +10012,7 @@
   ins_pipe(pipe_serial);
 %}
 
-instruct get_and_setN(indirect mem, iRegNNoSp newv, iRegI prev) %{
+instruct get_and_setN(indirect mem, iRegN newv, iRegINoSp prev) %{
   match(Set prev (GetAndSetN mem newv));
   format %{ "atomic_xchgw $prev, $newv, [$mem]" %}
   ins_encode %{
@@ -9889,7 +10021,7 @@
   ins_pipe(pipe_serial);
 %}
 
-instruct get_and_setP(indirect mem, iRegPNoSp newv, iRegP prev) %{
+instruct get_and_setP(indirect mem, iRegP newv, iRegPNoSp prev) %{
   match(Set prev (GetAndSetP mem newv));
   format %{ "atomic_xchg  $prev, $newv, [$mem]" %}
   ins_encode %{
--- a/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -532,8 +532,14 @@
 
 void LIR_Assembler::return_op(LIR_Opr result) {
   assert(result->is_illegal() || !result->is_single_cpu() || result->as_register() == r0, "word returns are in r0,");
+
   // Pop the stack before the safepoint code
   __ remove_frame(initial_frame_size_in_bytes());
+
+  if (StackReservedPages > 0 && compilation()->has_reserved_stack_access()) {
+    __ reserved_stack_check();
+  }
+
   address polling_page(os::get_polling_page());
   __ read_polling_page(rscratch1, polling_page, relocInfo::poll_return_type);
   __ ret(lr);
--- a/src/cpu/aarch64/vm/c1_Runtime1_aarch64.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/cpu/aarch64/vm/c1_Runtime1_aarch64.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2014, Red Hat Inc. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -1179,6 +1179,15 @@
         Label done;
         Label runtime;
 
+        // Is marking still active?
+        if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
+          __ ldrw(tmp, in_progress);
+        } else {
+          assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
+          __ ldrb(tmp, in_progress);
+        }
+        __ cbzw(tmp, done);
+
         // Can we store original value in the thread's buffer?
         __ ldr(tmp, queue_index);
         __ cbz(tmp, runtime);
--- a/src/cpu/aarch64/vm/frame_aarch64.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/cpu/aarch64/vm/frame_aarch64.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -375,7 +375,8 @@
   fr._unextended_sp = unextended_sp;
 
   address original_pc = nm->get_original_pc(&fr);
-  assert(nm->insts_contains(original_pc), "original PC must be in nmethod");
+  assert(nm->insts_contains_inclusive(original_pc),
+         "original PC must be in the main code section of the the compiled method (or must be immediately following it)");
 }
 #endif
 
@@ -629,6 +630,7 @@
     DESCRIBE_FP_OFFSET(interpreter_frame_last_sp);
     DESCRIBE_FP_OFFSET(interpreter_frame_method);
     DESCRIBE_FP_OFFSET(interpreter_frame_mdp);
+    DESCRIBE_FP_OFFSET(interpreter_frame_mirror);
     DESCRIBE_FP_OFFSET(interpreter_frame_cache);
     DESCRIBE_FP_OFFSET(interpreter_frame_locals);
     DESCRIBE_FP_OFFSET(interpreter_frame_bcp);
--- a/src/cpu/aarch64/vm/frame_aarch64.hpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/cpu/aarch64/vm/frame_aarch64.hpp	Sat Feb 04 03:29:40 2017 +0100
@@ -46,6 +46,9 @@
 //    [pointer to locals     ]                   = locals()             locals_offset
 //    [constant pool cache   ]                   = cache()              cache_offset
 
+//    [klass of method       ]                   = mirror()             mirror_offset
+//    [padding               ]
+
 //    [methodData            ]                   = mdp()                mdx_offset
 //    [methodOop             ]                   = method()             method_offset
 
--- a/src/cpu/aarch64/vm/frame_aarch64.inline.hpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/cpu/aarch64/vm/frame_aarch64.inline.hpp	Sat Feb 04 03:29:40 2017 +0100
@@ -82,7 +82,8 @@
   address original_pc = CompiledMethod::get_deopt_original_pc(this);
   if (original_pc != NULL) {
     _pc = original_pc;
-    assert(((CompiledMethod*)_cb)->insts_contains(_pc), "original PC must be in CompiledMethod");
+    assert(_cb->as_compiled_method()->insts_contains_inclusive(_pc),
+           "original PC must be in the main code section of the the compiled method (or must be immediately following it)");
     _deopt_state = is_deoptimized;
   } else {
     _deopt_state = not_deoptimized;
--- a/src/cpu/aarch64/vm/globalDefinitions_aarch64.hpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/cpu/aarch64/vm/globalDefinitions_aarch64.hpp	Sat Feb 04 03:29:40 2017 +0100
@@ -53,4 +53,6 @@
 // evidence that it's worth doing.
 #define DEOPTIMIZE_WHEN_PATCHING
 
+#define SUPPORT_RESERVED_STACK_AREA
+
 #endif // CPU_AARCH64_VM_GLOBALDEFINITIONS_AARCH64_HPP
--- a/src/cpu/aarch64/vm/globals_aarch64.hpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/cpu/aarch64/vm/globals_aarch64.hpp	Sat Feb 04 03:29:40 2017 +0100
@@ -50,7 +50,7 @@
 // stack if compiled for unix and LP64. To pass stack overflow tests we need
 // 20 shadow pages.
 #define DEFAULT_STACK_SHADOW_PAGES (20 DEBUG_ONLY(+5))
-#define DEFAULT_STACK_RESERVED_PAGES (0)
+#define DEFAULT_STACK_RESERVED_PAGES (1)
 
 #define MIN_STACK_YELLOW_PAGES DEFAULT_STACK_YELLOW_PAGES
 #define MIN_STACK_RED_PAGES    DEFAULT_STACK_RED_PAGES
--- a/src/cpu/aarch64/vm/interp_masm_aarch64.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/cpu/aarch64/vm/interp_masm_aarch64.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -619,6 +619,22 @@
   // get sender esp
   ldr(esp,
       Address(rfp, frame::interpreter_frame_sender_sp_offset * wordSize));
+  if (StackReservedPages > 0) {
+    // testing if reserved zone needs to be re-enabled
+    Label no_reserved_zone_enabling;
+
+    ldr(rscratch1, Address(rthread, JavaThread::reserved_stack_activation_offset()));
+    cmp(esp, rscratch1);
+    br(Assembler::LS, no_reserved_zone_enabling);
+
+    call_VM_leaf(
+      CAST_FROM_FN_PTR(address, SharedRuntime::enable_stack_reserved_zone), rthread);
+    call_VM(noreg, CAST_FROM_FN_PTR(address,
+                   InterpreterRuntime::throw_delayed_StackOverflowError));
+    should_not_reach_here();
+
+    bind(no_reserved_zone_enabling);
+  }
   // remove frame anchor
   leave();
   // If we're returning to interpreted code we will shortly be
--- a/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -402,6 +402,30 @@
   }
 }
 
+void MacroAssembler::reserved_stack_check() {
+    // testing if reserved zone needs to be enabled
+    Label no_reserved_zone_enabling;
+
+    ldr(rscratch1, Address(rthread, JavaThread::reserved_stack_activation_offset()));
+    cmp(sp, rscratch1);
+    br(Assembler::LO, no_reserved_zone_enabling);
+
+    enter();   // LR and FP are live.
+    lea(rscratch1, CAST_FROM_FN_PTR(address, SharedRuntime::enable_stack_reserved_zone));
+    mov(c_rarg0, rthread);
+    blr(rscratch1);
+    leave();
+
+    // We have already removed our own frame.
+    // throw_delayed_StackOverflowError will think that it's been
+    // called by our caller.
+    lea(rscratch1, RuntimeAddress(StubRoutines::throw_delayed_StackOverflowError_entry()));
+    br(rscratch1);
+    should_not_reach_here();
+
+    bind(no_reserved_zone_enabling);
+}
+
 int MacroAssembler::biased_locking_enter(Register lock_reg,
                                          Register obj_reg,
                                          Register swap_reg,
--- a/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp	Sat Feb 04 03:29:40 2017 +0100
@@ -957,6 +957,9 @@
   // stack overflow + shadow pages.  Also, clobbers tmp
   void bang_stack_size(Register size, Register tmp);
 
+  // Check for reserved stack access in method being exited (for JIT)
+  void reserved_stack_check();
+
   virtual RegisterOrConstant delayed_value_impl(intptr_t* delayed_value_addr,
                                                 Register tmp,
                                                 int offset);
--- a/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -4676,8 +4676,11 @@
     StubRoutines::_throw_StackOverflowError_entry =
       generate_throw_exception("StackOverflowError throw_exception",
                                CAST_FROM_FN_PTR(address,
-                                                SharedRuntime::
-                                                throw_StackOverflowError));
+                                                SharedRuntime::throw_StackOverflowError));
+    StubRoutines::_throw_delayed_StackOverflowError_entry =
+      generate_throw_exception("delayed StackOverflowError throw_exception",
+                               CAST_FROM_FN_PTR(address,
+                                                SharedRuntime::throw_delayed_StackOverflowError));
     if (UseCRC32Intrinsics) {
       // set table address before stub generation which use it
       StubRoutines::_crc_table_adr = (address)StubRoutines::aarch64::_crc_table;
--- a/src/cpu/arm/vm/c1_Runtime1_arm.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/cpu/arm/vm/c1_Runtime1_arm.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2017, 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
@@ -551,6 +551,8 @@
         const Register r_index_1    = R1;
         const Register r_buffer_2   = R2;
 
+        Address queue_active(Rthread, in_bytes(JavaThread::satb_mark_queue_offset() +
+                                               SATBMarkQueue::byte_offset_of_active()));
         Address queue_index(Rthread, in_bytes(JavaThread::satb_mark_queue_offset() +
                                               SATBMarkQueue::byte_offset_of_index()));
         Address buffer(Rthread, in_bytes(JavaThread::satb_mark_queue_offset() +
@@ -559,6 +561,11 @@
         Label done;
         Label runtime;
 
+        // Is marking still active?
+        assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
+        __ ldrb(R1, queue_active);
+        __ cbz(R1, done);
+
         __ ldr(r_index_1, queue_index);
         __ ldr(r_pre_val_0, Address(SP, nb_saved_regs*wordSize));
         __ ldr(r_buffer_2, buffer);
--- a/src/cpu/arm/vm/frame_arm.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/cpu/arm/vm/frame_arm.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -364,7 +364,8 @@
   fr._unextended_sp = unextended_sp;
 
   address original_pc = nm->get_original_pc(&fr);
-  assert(nm->insts_contains(original_pc), "original PC must be in nmethod");
+  assert(nm->insts_contains_inclusive(original_pc),
+         "original PC must be in the main code section of the the compiled method (or must be immediately following it)");
   assert(nm->is_method_handle_return(original_pc) == is_method_handle_return, "must be");
 }
 #endif
--- a/src/cpu/arm/vm/frame_arm.inline.hpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/cpu/arm/vm/frame_arm.inline.hpp	Sat Feb 04 03:29:40 2017 +0100
@@ -75,7 +75,8 @@
   address original_pc = CompiledMethod::get_deopt_original_pc(this);
   if (original_pc != NULL) {
     _pc = original_pc;
-    assert(_cb->as_compiled_method()->insts_contains(_pc), "original PC must be in CompiledMethod");
+    assert(_cb->as_compiled_method()->insts_contains_inclusive(_pc),
+           "original PC must be in the main code section of the the compiled method (or must be immediately following it)");
     _deopt_state = is_deoptimized;
   } else {
     _deopt_state = not_deoptimized;
--- a/src/cpu/ppc/vm/c1_Runtime1_ppc.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/cpu/ppc/vm/c1_Runtime1_ppc.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2012, 2015 SAP SE. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -741,7 +741,10 @@
         Register tmp  = R14;
         Register tmp2 = R15;
 
-        Label refill, restart;
+        Label refill, restart, marking_not_active;
+        int satb_q_active_byte_offset =
+          in_bytes(JavaThread::satb_mark_queue_offset() +
+                   SATBMarkQueue::byte_offset_of_active());
         int satb_q_index_byte_offset =
           in_bytes(JavaThread::satb_mark_queue_offset() +
                    SATBMarkQueue::byte_offset_of_index());
@@ -753,6 +756,16 @@
         __ std(tmp, -16, R1_SP);
         __ std(tmp2, -24, R1_SP);
 
+        // Is marking still active?
+        if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
+          __ lwz(tmp, satb_q_active_byte_offset, R16_thread);
+        } else {
+          assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
+          __ lbz(tmp, satb_q_active_byte_offset, R16_thread);
+        }
+        __ cmpdi(CCR0, tmp, 0);
+        __ beq(CCR0, marking_not_active);
+
         __ bind(restart);
         // Load the index into the SATB buffer. SATBMarkQueue::_index is a
         // size_t so ld_ptr is appropriate.
@@ -769,6 +782,7 @@
         __ std(tmp, satb_q_index_byte_offset, R16_thread);
         __ stdx(pre_val, tmp2, tmp); // [_buf + index] := <address_of_card>
 
+        __ bind(marking_not_active);
         // Restore temp registers and return-from-leaf.
         __ ld(tmp2, -24, R1_SP);
         __ ld(tmp, -16, R1_SP);
--- a/src/cpu/ppc/vm/macroAssembler_ppc.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/cpu/ppc/vm/macroAssembler_ppc.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -2569,7 +2569,7 @@
 }
 
 // Spin and retry if lock is busy.
-// inputs: box_Reg (monitor address)
+// inputs: owner_addr_Reg (monitor address)
 //       : retry_count_Reg
 // output: retry_count_Reg decremented by 1
 // CTR is killed
@@ -2577,15 +2577,22 @@
   Label SpinLoop, doneRetry;
   addic_(retry_count_Reg, retry_count_Reg, -1);
   blt(CCR0, doneRetry);
-  li(R0, RTMSpinLoopCount);
-  mtctr(R0);
+
+  if (RTMSpinLoopCount > 1) {
+    li(R0, RTMSpinLoopCount);
+    mtctr(R0);
+  }
 
   bind(SpinLoop);
   smt_yield(); // Can't use waitrsv(). No permission (SIGILL).
-  bdz(retryLabel);
-  ld(R0, 0, owner_addr_Reg);
-  cmpdi(CCR0, R0, 0);
-  bne(CCR0, SpinLoop);
+
+  if (RTMSpinLoopCount > 1) {
+    bdz(retryLabel);
+    ld(R0, 0, owner_addr_Reg);
+    cmpdi(CCR0, R0, 0);
+    bne(CCR0, SpinLoop);
+  }
+
   b(retryLabel);
 
   bind(doneRetry);
--- a/src/cpu/ppc/vm/vm_version_ppc.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/cpu/ppc/vm/vm_version_ppc.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -327,7 +327,10 @@
       warning("RTMAbortRatio must be in the range 0 to 100, resetting it to 50");
       FLAG_SET_DEFAULT(RTMAbortRatio, 50);
     }
-    guarantee(RTMSpinLoopCount > 0, "unsupported");
+    if (RTMSpinLoopCount < 0) {
+      warning("RTMSpinLoopCount must not be a negative value, resetting it to 0");
+      FLAG_SET_DEFAULT(RTMSpinLoopCount, 0);
+    }
 #else
     // Only C2 does RTM locking optimization.
     // Can't continue because UseRTMLocking affects UseBiasedLocking flag
--- a/src/cpu/s390/vm/c1_LIRAssembler_s390.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/cpu/s390/vm/c1_LIRAssembler_s390.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -1105,16 +1105,16 @@
       }
     case T_FLOAT :
       if (short_disp) {
-                    __ z_ste(from->as_float_reg(),  disp_value, disp_reg, dest);
+        __ z_ste(from->as_float_reg(),  disp_value, disp_reg, dest);
       } else {
-                    __ z_stey(from->as_float_reg(), disp_value, disp_reg, dest);
+        __ z_stey(from->as_float_reg(), disp_value, disp_reg, dest);
       }
       break;
     case T_DOUBLE:
       if (short_disp) {
-                    __ z_std(from->as_double_reg(),  disp_value, disp_reg, dest);
+        __ z_std(from->as_double_reg(),  disp_value, disp_reg, dest);
       } else {
-                    __ z_stdy(from->as_double_reg(), disp_value, disp_reg, dest);
+        __ z_stdy(from->as_double_reg(), disp_value, disp_reg, dest);
       }
       break;
     default: ShouldNotReachHere();
@@ -1148,6 +1148,10 @@
     __ restore_return_pc();
   }
 
+  if (StackReservedPages > 0 && compilation()->has_reserved_stack_access()) {
+    __ reserved_stack_check(Z_R14);
+  }
+
   // We need to mark the code position where the load from the safepoint
   // polling page was emitted as relocInfo::poll_return_type here.
   __ relocate(relocInfo::poll_return_type);
--- a/src/cpu/s390/vm/c1_Runtime1_s390.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/cpu/s390/vm/c1_Runtime1_s390.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017 Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2016 SAP SE. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -784,7 +784,10 @@
         Register tmp  = Z_R6; // Must be non-volatile because it is used to save pre_val.
         Register tmp2 = Z_R7;
 
-        Label refill, restart;
+        Label refill, restart, marking_not_active;
+        int satb_q_active_byte_offset =
+          in_bytes(JavaThread::satb_mark_queue_offset() +
+                   SATBMarkQueue::byte_offset_of_active());
         int satb_q_index_byte_offset =
           in_bytes(JavaThread::satb_mark_queue_offset() +
                    SATBMarkQueue::byte_offset_of_index());
@@ -796,6 +799,15 @@
         __ z_stg(tmp,  0*BytesPerWord + FrameMap::first_available_sp_in_frame, Z_SP);
         __ z_stg(tmp2, 1*BytesPerWord + FrameMap::first_available_sp_in_frame, Z_SP);
 
+        // Is marking still active?
+        if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
+          __ load_and_test_int(tmp, Address(Z_thread, satb_q_active_byte_offset));
+        } else {
+          assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
+          __ load_and_test_byte(tmp, Address(Z_thread, satb_q_active_byte_offset));
+        }
+        __ z_bre(marking_not_active); // Activity indicator is zero, so there is no marking going on currently.
+
         __ bind(restart);
         // Load the index into the SATB buffer. SATBMarkQueue::_index is a
         // size_t so ld_ptr is appropriate.
@@ -810,6 +822,7 @@
         __ z_stg(pre_val, 0, tmp, tmp2); // [_buf + index] := <address_of_card>
         __ z_stg(tmp, satb_q_index_byte_offset, Z_thread);
 
+        __ bind(marking_not_active);
         // Restore tmp registers (see assertion in G1PreBarrierStub::emit_code()).
         __ z_lg(tmp,  0*BytesPerWord + FrameMap::first_available_sp_in_frame, Z_SP);
         __ z_lg(tmp2, 1*BytesPerWord + FrameMap::first_available_sp_in_frame, Z_SP);
--- a/src/cpu/s390/vm/globalDefinitions_s390.hpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/cpu/s390/vm/globalDefinitions_s390.hpp	Sat Feb 04 03:29:40 2017 +0100
@@ -52,4 +52,6 @@
 // The expected size in bytes of a cache line, used to pad data structures.
 #define DEFAULT_CACHE_LINE_SIZE 256
 
+#define SUPPORT_RESERVED_STACK_AREA
+
 #endif // CPU_S390_VM_GLOBALDEFINITIONS_S390_HPP
--- a/src/cpu/s390/vm/globals_s390.hpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/cpu/s390/vm/globals_s390.hpp	Sat Feb 04 03:29:40 2017 +0100
@@ -56,7 +56,7 @@
 // Java_java_net_SocketOutputStream_socketWrite0() uses a 64k buffer on the
 // stack. To pass stack overflow tests we need 20 shadow pages.
 #define DEFAULT_STACK_SHADOW_PAGES   (20 DEBUG_ONLY(+2))
-#define DEFAULT_STACK_RESERVED_PAGES (0)
+#define DEFAULT_STACK_RESERVED_PAGES (1)
 
 #define MIN_STACK_YELLOW_PAGES     DEFAULT_STACK_YELLOW_PAGES
 #define MIN_STACK_RED_PAGES        DEFAULT_STACK_RED_PAGES
--- a/src/cpu/s390/vm/interp_masm_s390.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/cpu/s390/vm/interp_masm_s390.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -860,16 +860,39 @@
                                                   bool throw_monitor_exception,
                                                   bool install_monitor_exception,
                                                   bool notify_jvmti) {
-
+  BLOCK_COMMENT("remove_activation {");
   unlock_if_synchronized_method(state, throw_monitor_exception, install_monitor_exception);
 
   // Save result (push state before jvmti call and pop it afterwards) and notify jvmti.
   notify_method_exit(false, state, notify_jvmti ? NotifyJVMTI : SkipNotifyJVMTI);
 
+  if (StackReservedPages > 0) {
+    BLOCK_COMMENT("reserved_stack_check:");
+    // Test if reserved zone needs to be enabled.
+    Label no_reserved_zone_enabling;
+
+    // Compare frame pointers. There is no good stack pointer, as with stack
+    // frame compression we can get different SPs when we do calls. A subsequent
+    // call could have a smaller SP, so that this compare succeeds for an
+    // inner call of the method annotated with ReservedStack.
+    z_lg(Z_R0, Address(Z_SP, (intptr_t)_z_abi(callers_sp)));
+    z_clg(Z_R0, Address(Z_thread, JavaThread::reserved_stack_activation_offset())); // Compare with frame pointer in memory.
+    z_brl(no_reserved_zone_enabling);
+
+    // Enable reserved zone again, throw stack overflow exception.
+    call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::enable_stack_reserved_zone), Z_thread);
+    call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_delayed_StackOverflowError));
+
+    should_not_reach_here();
+
+    bind(no_reserved_zone_enabling);
+  }
+
   verify_oop(Z_tos, state);
   verify_thread();
 
   pop_interpreter_frame(return_pc, Z_ARG2, Z_ARG3);
+  BLOCK_COMMENT("} remove_activation");
 }
 
 // lock object
--- a/src/cpu/s390/vm/macroAssembler_s390.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/cpu/s390/vm/macroAssembler_s390.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -2666,6 +2666,32 @@
   }
 }
 
+void MacroAssembler::reserved_stack_check(Register return_pc) {
+  // Test if reserved zone needs to be enabled.
+  Label no_reserved_zone_enabling;
+  assert(return_pc == Z_R14, "Return pc must be in R14 before z_br() to StackOverflow stub.");
+  BLOCK_COMMENT("reserved_stack_check {");
+
+  z_clg(Z_SP, Address(Z_thread, JavaThread::reserved_stack_activation_offset()));
+  z_brl(no_reserved_zone_enabling);
+
+  // Enable reserved zone again, throw stack overflow exception.
+  save_return_pc();
+  push_frame_abi160(0);
+  call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::enable_stack_reserved_zone), Z_thread);
+  pop_frame();
+  restore_return_pc();
+
+  load_const_optimized(Z_R1, StubRoutines::throw_delayed_StackOverflowError_entry());
+  // Don't use call() or z_basr(), they will invalidate Z_R14 which contains the return pc.
+  z_br(Z_R1);
+
+  should_not_reach_here();
+
+  bind(no_reserved_zone_enabling);
+  BLOCK_COMMENT("} reserved_stack_check");
+}
+
 // Defines obj, preserves var_size_in_bytes, okay for t2 == var_size_in_bytes.
 void MacroAssembler::tlab_allocate(Register obj,
                                    Register var_size_in_bytes,
--- a/src/cpu/s390/vm/macroAssembler_s390.hpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/cpu/s390/vm/macroAssembler_s390.hpp	Sat Feb 04 03:29:40 2017 +0100
@@ -627,6 +627,11 @@
   // Stack overflow checking
   void bang_stack_with_offset(int offset);
 
+  // Check for reserved stack access in method being exited. If the reserved
+  // stack area was accessed, protect it again and throw StackOverflowError.
+  // Uses Z_R1.
+  void reserved_stack_check(Register return_pc);
+
   // Atomics
   // -- none?
 
--- a/src/cpu/s390/vm/s390.ad	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/cpu/s390/vm/s390.ad	Sat Feb 04 03:29:40 2017 +0100
@@ -909,15 +909,8 @@
   // If this does safepoint polling, then do it here.
   bool need_polling = do_polling() && C->is_method_compilation();
 
-  // Touch the polling page.
-  // Part 1: get the page's address.
-  if (need_polling) {
-    AddressLiteral pp(os::get_polling_page());
-    __ load_const_optimized(Z_R1_scratch, pp);
-  }
-
   // Pop frame, restore return_pc, and all stuff needed by interpreter.
-  // Pop frame by add insted of load (a penny saved is a penny got :-).
+  // Pop frame by add instead of load (a penny saved is a penny got :-).
   int frame_size_in_bytes = Assembler::align((C->frame_slots() << LogBytesPerInt), frame::alignment_in_bytes);
   int retPC_offset        = frame_size_in_bytes + _z_abi16(return_pc);
   if (Displacement::is_validDisp(retPC_offset)) {
@@ -928,9 +921,14 @@
     __ restore_return_pc();
   }
 
-  // Touch the polling page,
-  // part 2: touch the page now.
+  if (StackReservedPages > 0 && C->has_reserved_stack_access()) {
+    __ reserved_stack_check(Z_R14);
+  }
+
+  // Touch the polling page.
   if (need_polling) {
+    AddressLiteral pp(os::get_polling_page());
+    __ load_const_optimized(Z_R1_scratch, pp);
     // We need to mark the code position where the load from the safepoint
     // polling page was emitted as relocInfo::poll_return_type here.
     __ relocate(relocInfo::poll_return_type);
@@ -939,7 +937,7 @@
 }
 
 uint MachEpilogNode::size(PhaseRegAlloc *ra_) const {
-  // variable size. determine dynamically.
+  // Variable size. determine dynamically.
   return MachNode::size(ra_);
 }
 
--- a/src/cpu/s390/vm/stubGenerator_s390.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/cpu/s390/vm/stubGenerator_s390.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -2433,13 +2433,12 @@
     StubRoutines::_throw_StackOverflowError_entry          =
       generate_throw_exception("StackOverflowError throw_exception",
                                CAST_FROM_FN_PTR(address, SharedRuntime::throw_StackOverflowError), false);
+    StubRoutines::_throw_delayed_StackOverflowError_entry  =
+      generate_throw_exception("delayed StackOverflowError throw_exception",
+                               CAST_FROM_FN_PTR(address, SharedRuntime::throw_delayed_StackOverflowError), false);
 
     //----------------------------------------------------------------------
     // Entry points that are platform specific.
-    // Build this early so it's available for the interpreter.
-    StubRoutines::_throw_StackOverflowError_entry          =
-      generate_throw_exception("StackOverflowError throw_exception",
-                               CAST_FROM_FN_PTR(address, SharedRuntime::throw_StackOverflowError), false);
 
     if (UseCRC32Intrinsics) {
       // We have no CRC32 table on z/Architecture.
--- a/src/cpu/s390/vm/templateInterpreterGenerator_s390.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/cpu/s390/vm/templateInterpreterGenerator_s390.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -1112,16 +1112,21 @@
   // top_frame_size = TOP_IJAVA_FRAME_ABI + max_stack + size of interpreter state
   __ add2reg(top_frame_size,
              frame::z_top_ijava_frame_abi_size +
-               frame::z_ijava_state_size +
-               frame::interpreter_frame_monitor_size() * wordSize,
+             frame::z_ijava_state_size +
+             frame::interpreter_frame_monitor_size() * wordSize,
              max_stack);
 
-  // Check if there's room for the new frame...
-  Register frame_size = max_stack; // Reuse the regiser for max_stack.
-  __ z_lgr(frame_size, Z_SP);
-  __ z_sgr(frame_size, sp_after_resize);
-  __ z_agr(frame_size, top_frame_size);
-  generate_stack_overflow_check(frame_size, fp/*tmp1*/);
+  if (!native_call) {
+    // Stack overflow check.
+    // Native calls don't need the stack size check since they have no
+    // expression stack and the arguments are already on the stack and
+    // we only add a handful of words to the stack.
+    Register frame_size = max_stack; // Reuse the regiser for max_stack.
+    __ z_lgr(frame_size, Z_SP);
+    __ z_sgr(frame_size, sp_after_resize);
+    __ z_agr(frame_size, top_frame_size);
+    generate_stack_overflow_check(frame_size, fp/*tmp1*/);
+  }
 
   DEBUG_ONLY(__ z_cg(Z_R14, _z_abi16(return_pc), Z_SP));
   __ asm_assert_eq("killed Z_R14", 0);
--- a/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, 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
@@ -694,6 +694,7 @@
 int LIR_Assembler::store(LIR_Opr from_reg, Register base, int offset, BasicType type, bool wide, bool unaligned) {
   int store_offset;
   if (!Assembler::is_simm13(offset + (type == T_LONG) ? wordSize : 0)) {
+    assert(base != O7, "destroying register");
     assert(!unaligned, "can't handle this");
     // for offsets larger than a simm13 we setup the offset in O7
     __ set(offset, O7);
@@ -712,9 +713,12 @@
       case T_LONG  :
 #ifdef _LP64
         if (unaligned || PatchALot) {
-          __ srax(from_reg->as_register_lo(), 32, O7);
+          // Don't use O7 here because it may be equal to 'base' (see LIR_Assembler::reg2mem)
+          assert(G3_scratch != base, "can't handle this");
+          assert(G3_scratch != from_reg->as_register_lo(), "can't handle this");
+          __ srax(from_reg->as_register_lo(), 32, G3_scratch);
           __ stw(from_reg->as_register_lo(), base, offset + lo_word_offset_in_bytes);
-          __ stw(O7,                         base, offset + hi_word_offset_in_bytes);
+          __ stw(G3_scratch,                 base, offset + hi_word_offset_in_bytes);
         } else {
           __ stx(from_reg->as_register_lo(), base, offset);
         }
@@ -821,7 +825,7 @@
       case T_SHORT : __ ldsh(base, offset, to_reg->as_register()); break;
       case T_INT   : __ ld(base, offset, to_reg->as_register()); break;
       case T_LONG  :
-        if (!unaligned) {
+        if (!unaligned && !PatchALot) {
 #ifdef _LP64
           __ ldx(base, offset, to_reg->as_register_lo());
 #else
@@ -1297,7 +1301,7 @@
       disp_reg = O7;
     }
   } else if (unaligned || PatchALot) {
-    __ add(src, addr->index()->as_register(), O7);
+    __ add(src, addr->index()->as_pointer_register(), O7);
     src = O7;
   } else {
     disp_reg = addr->index()->as_pointer_register();
@@ -1424,7 +1428,7 @@
       disp_reg = O7;
     }
   } else if (unaligned || PatchALot) {
-    __ add(src, addr->index()->as_register(), O7);
+    __ add(src, addr->index()->as_pointer_register(), O7);
     src = O7;
   } else {
     disp_reg = addr->index()->as_pointer_register();
--- a/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2017, 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
@@ -856,7 +856,9 @@
         Register tmp2 = G3_scratch;
 
         Label refill, restart;
-        bool with_frame = false; // I don't know if we can do with-frame.
+        int satb_q_active_byte_offset =
+          in_bytes(JavaThread::satb_mark_queue_offset() +
+                   SATBMarkQueue::byte_offset_of_active());
         int satb_q_index_byte_offset =
           in_bytes(JavaThread::satb_mark_queue_offset() +
                    SATBMarkQueue::byte_offset_of_index());
@@ -864,6 +866,17 @@
           in_bytes(JavaThread::satb_mark_queue_offset() +
                    SATBMarkQueue::byte_offset_of_buf());
 
+        // Is marking still active?
+        if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
+          __ ld(G2_thread, satb_q_active_byte_offset, tmp);
+        } else {
+          assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
+          __ ldsb(G2_thread, satb_q_active_byte_offset, tmp);
+        }
+        __ cmp_and_br_short(tmp, G0, Assembler::notEqual, Assembler::pt, restart);
+        __ retl();
+        __ delayed()->nop();
+
         __ bind(restart);
         // Load the index into the SATB buffer. SATBMarkQueue::_index is a
         // size_t so ld_ptr is appropriate
--- a/src/cpu/x86/vm/c1_Runtime1_x86.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/cpu/x86/vm/c1_Runtime1_x86.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2017, 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
@@ -1623,6 +1623,8 @@
 
         NOT_LP64(__ get_thread(thread);)
 
+        Address queue_active(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
+                                              SATBMarkQueue::byte_offset_of_active()));
         Address queue_index(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
                                              SATBMarkQueue::byte_offset_of_index()));
         Address buffer(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
@@ -1631,6 +1633,15 @@
         Label done;
         Label runtime;
 
+        // Is marking still active?
+        if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
+          __ cmpl(queue_active, 0);
+        } else {
+          assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
+          __ cmpb(queue_active, 0);
+        }
+        __ jcc(Assembler::equal, done);
+
         // Can we store original value in the thread's buffer?
 
         __ movptr(tmp, queue_index);
--- a/src/cpu/x86/vm/frame_x86.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/cpu/x86/vm/frame_x86.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -376,7 +376,8 @@
   fr._unextended_sp = unextended_sp;
 
   address original_pc = nm->get_original_pc(&fr);
-  assert(nm->insts_contains(original_pc), "original PC must be in CompiledMethod");
+  assert(nm->insts_contains_inclusive(original_pc),
+         "original PC must be in the main code section of the the compiled method (or must be immediately following it)");
 }
 #endif
 
--- a/src/cpu/x86/vm/frame_x86.inline.hpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/cpu/x86/vm/frame_x86.inline.hpp	Sat Feb 04 03:29:40 2017 +0100
@@ -75,7 +75,8 @@
   address original_pc = CompiledMethod::get_deopt_original_pc(this);
   if (original_pc != NULL) {
     _pc = original_pc;
-    assert(((CompiledMethod*)_cb)->insts_contains(_pc), "original PC must be in CompiledMethod");
+    assert(_cb->as_compiled_method()->insts_contains_inclusive(_pc),
+           "original PC must be in the main code section of the the compiled method (or must be immediately following it)");
     _deopt_state = is_deoptimized;
   } else {
     if (_cb->is_deoptimization_stub()) {
--- a/src/cpu/x86/vm/macroAssembler_x86.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/cpu/x86/vm/macroAssembler_x86.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -3499,12 +3499,12 @@
   }
 }
 
-void MacroAssembler::movdqu(XMMRegister dst, AddressLiteral src) {
+void MacroAssembler::movdqu(XMMRegister dst, AddressLiteral src, Register scratchReg) {
   if (reachable(src)) {
     movdqu(dst, as_Address(src));
   } else {
-    lea(rscratch1, src);
-    movdqu(dst, Address(rscratch1, 0));
+    lea(scratchReg, src);
+    movdqu(dst, Address(scratchReg, 0));
   }
 }
 
--- a/src/cpu/x86/vm/macroAssembler_x86.hpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/cpu/x86/vm/macroAssembler_x86.hpp	Sat Feb 04 03:29:40 2017 +0100
@@ -1085,7 +1085,7 @@
   void movdqu(Address     dst, XMMRegister src);
   void movdqu(XMMRegister dst, Address src);
   void movdqu(XMMRegister dst, XMMRegister src);
-  void movdqu(XMMRegister dst, AddressLiteral src);
+  void movdqu(XMMRegister dst, AddressLiteral src, Register scratchReg = rscratch1);
   // AVX Unaligned forms
   void vmovdqu(Address     dst, XMMRegister src);
   void vmovdqu(XMMRegister dst, Address src);
--- a/src/cpu/x86/vm/macroAssembler_x86_sha.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/cpu/x86/vm/macroAssembler_x86_sha.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -817,7 +817,7 @@
   movl(d, Address(CTX, 4*3));
   movl(e, Address(CTX, 4*4));
   movl(f, Address(CTX, 4*5));
-  movl(g, Address(CTX, 4*6));
+  // load g - r10 after it is used as scratch
   movl(h, Address(CTX, 4*7));
 
   pshuffle_byte_flip_mask_addr = pshuffle_byte_flip_mask;
@@ -825,6 +825,8 @@
   vmovdqu(SHUF_00BA, ExternalAddress(pshuffle_byte_flip_mask_addr + 32));     //[_SHUF_00BA wrt rip]
   vmovdqu(SHUF_DC00, ExternalAddress(pshuffle_byte_flip_mask_addr + 64));     //[_SHUF_DC00 wrt rip]
 
+  movl(g, Address(CTX, 4*6));
+
   movq(Address(rsp, _CTX), CTX);           // store
 
 bind(loop0);
@@ -977,7 +979,7 @@
   movl(d, Address(CTX, 4*3));   // 0xa54ff53a
   movl(e, Address(CTX, 4*4));   // 0x510e527f
   movl(f, Address(CTX, 4*5));   // 0x9b05688c
-  movl(g, Address(CTX, 4*6));   // 0x1f83d9ab
+  // load g - r10 after use as scratch
   movl(h, Address(CTX, 4*7));   // 0x5be0cd19
 
 
@@ -986,6 +988,8 @@
   vmovdqu(SHUF_00BA, ExternalAddress(pshuffle_byte_flip_mask_addr + 32));     //[_SHUF_00BA wrt rip]
   vmovdqu(SHUF_DC00, ExternalAddress(pshuffle_byte_flip_mask_addr + 64));     //[_SHUF_DC00 wrt rip]
 
+  movl(g, Address(CTX, 4*6));   // 0x1f83d9ab
+
   movq(Address(rsp, _CTX), CTX);
   jmpb(do_last_block);
 
@@ -1154,9 +1158,8 @@
       // Move to appropriate lanes for calculating w[16] and w[17]
       vperm2f128(xmm4, xmm0, xmm0, 0); //xmm4 = W[-16] + W[-7] + s0{ BABA }
 
-      address MASK_YMM_LO = StubRoutines::x86::pshuffle_byte_flip_mask_addr_sha512();
       //Move to appropriate lanes for calculating w[18] and w[19]
-      vpand(xmm0, xmm0, ExternalAddress(MASK_YMM_LO + 32), AVX_256bit); //xmm0 = W[-16] + W[-7] + s0{ DC00 }
+      vpand(xmm0, xmm0, xmm10, AVX_256bit); //xmm0 = W[-16] + W[-7] + s0{ DC00 }
       //Calculate w[16] and w[17] in both 128 bit lanes
       //Calculate sigma1 for w[16] and w[17] on both 128 bit lanes
       vperm2f128(xmm2, xmm7, xmm7, 17); //xmm2 = W[-2] {BABA}
@@ -1250,6 +1253,7 @@
 
     const XMMRegister& XFER = xmm0; // YTMP0
     const XMMRegister& BYTE_FLIP_MASK = xmm9; // ymm9
+    const XMMRegister& YMM_MASK_LO = xmm10; // ymm10
 #ifdef _WIN64
     const Register& INP = rcx; //1st arg
     const Register& CTX = rdx; //2nd arg
@@ -1368,11 +1372,14 @@
     movq(d, Address(CTX, 8 * 3));
     movq(e, Address(CTX, 8 * 4));
     movq(f, Address(CTX, 8 * 5));
-    movq(g, Address(CTX, 8 * 6));
+    // load g - r10 after it is used as scratch
     movq(h, Address(CTX, 8 * 7));
 
     pshuffle_byte_flip_mask_addr = pshuffle_byte_flip_mask_sha512;
     vmovdqu(BYTE_FLIP_MASK, ExternalAddress(pshuffle_byte_flip_mask_addr + 0)); //PSHUFFLE_BYTE_FLIP_MASK wrt rip
+    vmovdqu(YMM_MASK_LO, ExternalAddress(pshuffle_byte_flip_mask_addr + 32));
+
+    movq(g, Address(CTX, 8 * 6));
 
     bind(loop0);
     lea(TBL, ExternalAddress(K512_W));
--- a/src/cpu/x86/vm/stubGenerator_x86_64.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/cpu/x86/vm/stubGenerator_x86_64.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -3207,7 +3207,7 @@
     const Register len_reg     = c_rarg4;  // src len (must be multiple of blocksize 16)
 #else
     const Address  len_mem(rbp, 6 * wordSize);  // length is on stack on Win64
-    const Register len_reg     = r10;      // pick the first volatile windows register
+    const Register len_reg     = r11;      // pick the volatile windows register
 #endif
     const Register pos         = rax;
 
@@ -3404,7 +3404,7 @@
     const Register len_reg     = c_rarg4;  // src len (must be multiple of blocksize 16)
 #else
     const Address  len_mem(rbp, 6 * wordSize);  // length is on stack on Win64
-    const Register len_reg     = r10;      // pick the first volatile windows register
+    const Register len_reg     = r11;      // pick the volatile windows register
 #endif
     const Register pos         = rax;
 
@@ -3930,7 +3930,7 @@
 
     __ push(rbx); // Save RBX
     __ movdqu(xmm_curr_counter, Address(counter, 0x00)); // initialize counter with initial counter
-    __ movdqu(xmm_counter_shuf_mask, ExternalAddress(StubRoutines::x86::counter_shuffle_mask_addr()));
+    __ movdqu(xmm_counter_shuf_mask, ExternalAddress(StubRoutines::x86::counter_shuffle_mask_addr()), pos); // pos as scratch
     __ pshufb(xmm_curr_counter, xmm_counter_shuf_mask); //counter is shuffled
     __ movptr(pos, 0);
 
@@ -3953,7 +3953,7 @@
     __ movl(Address(used_addr, 0), used);
 
     // key length could be only {11, 13, 15} * 4 = {44, 52, 60}
-    __ movdqu(xmm_key_shuf_mask, ExternalAddress(StubRoutines::x86::key_shuffle_mask_addr()));
+    __ movdqu(xmm_key_shuf_mask, ExternalAddress(StubRoutines::x86::key_shuffle_mask_addr()), rbx); // rbx as scratch
     __ movl(rbx, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT)));
     __ cmpl(rbx, 52);
     __ jcc(Assembler::equal, L_multiBlock_loopTop[1]);
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java	Sat Feb 04 03:29:40 2017 +0100
@@ -37,6 +37,7 @@
 import jdk.tools.jaotc.binformat.Symbol.Kind;
 import jdk.tools.jaotc.binformat.elf.JELFRelocObject;
 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
+import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
 
 /**
  * A format-agnostic container class that holds various components of a binary.
@@ -257,9 +258,9 @@
      * prefix {@code prefix}. It also initializes internal code container, symbol table and
      * relocation tables.
      */
-    public BinaryContainer(GraalHotSpotVMConfig config, String jvmVersion) {
-        this.codeSegmentSize = config.codeSegmentSize;
-        this.codeEntryAlignment = config.codeEntryAlignment;
+    public BinaryContainer(GraalHotSpotVMConfig graalHotSpotVMConfig, GraphBuilderConfiguration graphBuilderConfig, String jvmVersion) {
+        this.codeSegmentSize = graalHotSpotVMConfig.codeSegmentSize;
+        this.codeEntryAlignment = graalHotSpotVMConfig.codeEntryAlignment;
 
         // read only, code
         codeContainer = new CodeContainer(".text", this);
@@ -289,30 +290,31 @@
 
         addGlobalSymbols();
 
-        recordConfiguration(config);
+        recordConfiguration(graalHotSpotVMConfig, graphBuilderConfig);
     }
 
-    private void recordConfiguration(GraalHotSpotVMConfig config) {
+    private void recordConfiguration(GraalHotSpotVMConfig graalHotSpotVMConfig, GraphBuilderConfiguration graphBuilderConfig) {
         // @formatter:off
-        boolean[] booleanFlags = { config.cAssertions, // Debug VM
-                                   config.useCompressedOops,
-                                   config.useCompressedClassPointers,
-                                   config.compactFields,
-                                   config.useG1GC,
-                                   config.useCMSGC,
-                                   config.useTLAB,
-                                   config.useBiasedLocking,
+        boolean[] booleanFlags = { graalHotSpotVMConfig.cAssertions, // Debug VM
+                                   graalHotSpotVMConfig.useCompressedOops,
+                                   graalHotSpotVMConfig.useCompressedClassPointers,
+                                   graalHotSpotVMConfig.compactFields,
+                                   graalHotSpotVMConfig.useG1GC,
+                                   graalHotSpotVMConfig.useCMSGC,
+                                   graalHotSpotVMConfig.useTLAB,
+                                   graalHotSpotVMConfig.useBiasedLocking,
                                    TieredAOT.getValue(),
-                                   config.enableContended,
-                                   config.restrictContended,
+                                   graalHotSpotVMConfig.enableContended,
+                                   graalHotSpotVMConfig.restrictContended,
+                                   graphBuilderConfig.omitAssertions()
         };
 
-        int[] intFlags         = { config.narrowOopShift,
-                                   config.narrowKlassShift,
-                                   config.contendedPaddingWidth,
-                                   config.fieldsAllocationStyle,
-                                   config.objectAlignment,
-                                   config.codeSegmentSize,
+        int[] intFlags         = { graalHotSpotVMConfig.getOopEncoding().shift,
+                                   graalHotSpotVMConfig.getKlassEncoding().shift,
+                                   graalHotSpotVMConfig.contendedPaddingWidth,
+                                   graalHotSpotVMConfig.fieldsAllocationStyle,
+                                   1 << graalHotSpotVMConfig.getOopEncoding().alignment,
+                                   graalHotSpotVMConfig.codeSegmentSize,
         };
         // @formatter:on
 
@@ -395,6 +397,10 @@
         return "_aot_narrow_klass_base_address";
     }
 
+    public String getNarrowOopBaseAddressSymbolName() {
+        return "_aot_narrow_oop_base_address";
+    }
+
     public String getLogOfHeapRegionGrainBytesSymbolName() {
         return "_aot_log_of_heap_region_grain_bytes";
     }
@@ -445,6 +451,7 @@
         createGotSymbol(getHeapTopAddressSymbolName());
         createGotSymbol(getHeapEndAddressSymbolName());
         createGotSymbol(getNarrowKlassBaseAddressSymbolName());
+        createGotSymbol(getNarrowOopBaseAddressSymbolName());
         createGotSymbol(getPollingPageSymbolName());
         createGotSymbol(getLogOfHeapRegionGrainBytesSymbolName());
         createGotSymbol(getInlineContiguousAllocationSupportedSymbolName());
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java	Sat Feb 04 03:29:40 2017 +0100
@@ -77,10 +77,14 @@
         this.filters = filters;
         providers = backend.getProviders();
         codeCache = providers.getCodeCache();
-        graphBuilderSuite = initGraphBuilderSuite(backend);
+        graphBuilderSuite = initGraphBuilderSuite(backend, main.options.compileWithAssertions);
         highTierContext = new HighTierContext(providers, graphBuilderSuite, OptimisticOptimizations.ALL);
     }
 
+    public PhaseSuite<HighTierContext> getGraphBuilderSuite() {
+        return graphBuilderSuite;
+    }
+
     private Suites getSuites() {
         // create suites every time, as we modify options for the compiler
         return backend.getSuites().getDefaultSuites();
@@ -146,14 +150,14 @@
         return backend.getRuntime().getVMConfig().cAssertions;
     }
 
-    private static PhaseSuite<HighTierContext> initGraphBuilderSuite(HotSpotBackend backend) {
+    private static PhaseSuite<HighTierContext> initGraphBuilderSuite(HotSpotBackend backend, boolean compileWithAssertions) {
         PhaseSuite<HighTierContext> graphBuilderSuite = backend.getSuites().getDefaultGraphBuilderSuite().copy();
         ListIterator<BasePhase<? super HighTierContext>> iterator = graphBuilderSuite.findPhase(GraphBuilderPhase.class);
         GraphBuilderConfiguration baseConfig = ((GraphBuilderPhase) iterator.previous()).getGraphBuilderConfig();
 
         // Use all default plugins.
         Plugins plugins = baseConfig.getPlugins();
-        GraphBuilderConfiguration aotConfig = GraphBuilderConfiguration.getDefault(plugins).withEagerResolving(true);
+        GraphBuilderConfiguration aotConfig = GraphBuilderConfiguration.getDefault(plugins).withEagerResolving(true).withOmitAssertions(!compileWithAssertions);
 
         iterator.next();
         iterator.remove();
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiledClass.java	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiledClass.java	Sat Feb 04 03:29:40 2017 +0100
@@ -293,12 +293,18 @@
             // Record methods holder
             methodInfo.addDependentKlassData(binaryContainer, resolvedJavaType);
             // Record inlinee classes
-            for (ResolvedJavaMethod m : methodInfo.getCompilationResult().getMethods()) {
-                methodInfo.addDependentKlassData(binaryContainer, (HotSpotResolvedObjectType) m.getDeclaringClass());
+            ResolvedJavaMethod[] inlinees = methodInfo.getCompilationResult().getMethods();
+            if (inlinees != null) {
+                for (ResolvedJavaMethod m : inlinees) {
+                    methodInfo.addDependentKlassData(binaryContainer, (HotSpotResolvedObjectType) m.getDeclaringClass());
+                }
             }
             // Record classes of fields that were accessed
-            for (ResolvedJavaField f : methodInfo.getCompilationResult().getFields()) {
-                methodInfo.addDependentKlassData(binaryContainer, (HotSpotResolvedObjectType) f.getDeclaringClass());
+            ResolvedJavaField[] fields = methodInfo.getCompilationResult().getFields();
+            if (fields != null) {
+                for (ResolvedJavaField f : fields) {
+                    methodInfo.addDependentKlassData(binaryContainer, (HotSpotResolvedObjectType) f.getDeclaringClass());
+                }
             }
         }
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/LoadedClass.java	Sat Feb 04 03:29:40 2017 +0100
@@ -0,0 +1,64 @@
+package jdk.tools.jaotc;/*
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+public class LoadedClass {
+    private final String name;
+    private final Class<?> clz;
+
+    public LoadedClass(String name, Class<?> clz) {
+        this.name = name;
+        this.clz = clz;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public Class<?> getLoadedClass() {
+        return clz;
+    }
+
+    @Override
+    public String toString() {
+        return name;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof LoadedClass)) return false;
+
+        LoadedClass that = (LoadedClass) o;
+
+        if (name != null ? !name.equals(that.name) : that.name != null) return false;
+        return clz != null ? clz.equals(that.clz) : that.clz == null;
+
+    }
+
+    @Override
+    public int hashCode() {
+        int result = name != null ? name.hashCode() : 0;
+        result = 31 * result + (clz != null ? clz.hashCode() : 0);
+        return result;
+    }
+}
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java	Sat Feb 04 03:29:40 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, 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
@@ -43,19 +43,31 @@
 import java.text.MessageFormat;
 import java.util.ArrayList;
 import java.util.Date;
+import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.ListIterator;
 import java.util.Set;
 import java.util.stream.Stream;
 
 import jdk.tools.jaotc.binformat.BinaryContainer;
 import jdk.tools.jaotc.binformat.ByteContainer;
-import jdk.tools.jaotc.collect.ClassCollector;
+import jdk.tools.jaotc.collect.*;
+import jdk.tools.jaotc.collect.classname.ClassNameSourceProvider;
+import jdk.tools.jaotc.collect.directory.DirectorySourceProvider;
+import jdk.tools.jaotc.collect.jar.JarSourceProvider;
+import jdk.tools.jaotc.collect.module.ModuleSourceProvider;
 import jdk.tools.jaotc.utils.Timer;
 
 import org.graalvm.compiler.api.runtime.GraalJVMCICompiler;
+import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
 import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
 import org.graalvm.compiler.hotspot.HotSpotHostBackend;
+import org.graalvm.compiler.java.GraphBuilderPhase;
+import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
+import org.graalvm.compiler.phases.BasePhase;
+import org.graalvm.compiler.phases.PhaseSuite;
+import org.graalvm.compiler.phases.tiers.HighTierContext;
 import org.graalvm.compiler.runtime.RuntimeProvider;
 
 import jdk.vm.ci.meta.MetaAccessProvider;
@@ -120,17 +132,7 @@
         abstract void process(Main task, String opt, String arg) throws BadArgs;
     }
 
-    static Option[] recognizedOptions = {new Option("  --module <name>            Module to compile", true, "--module") {
-        @Override
-        void process(Main task, String opt, String arg) {
-            task.options.module = arg;
-        }
-    }, new Option("  --module-path <path>       Specify where to find module to compile", true, "--module-path") {
-        @Override
-        void process(Main task, String opt, String arg) {
-            task.options.modulepath = arg;
-        }
-    }, new Option("  --output <file>            Output file name", true, "--output") {
+    static Option[] recognizedOptions = { new Option("  --output <file>            Output file name", true, "--output") {
         @Override
         void process(Main task, String opt, String arg) {
             String name = arg;
@@ -139,22 +141,48 @@
             }
             task.options.outputName = name;
         }
+    }, new Option("  --class-name <class names> List of classes to compile", true, "--class-name", "--classname") {
+        @Override
+        void process(Main task, String opt, String arg) {
+            task.options.files.addAll(ClassSearch.makeList(ClassNameSourceProvider.TYPE, arg));
+        }
+    }, new Option("  --jar <jarfiles>           List of jar files to compile", true, "--jar") {
+        @Override
+        void process(Main task, String opt, String arg) {
+            task.options.files.addAll(ClassSearch.makeList(JarSourceProvider.TYPE, arg));
+        }
+    }, new Option("  --module <modules>         List of modules to compile", true, "--module") {
+        @Override
+        void process(Main task, String opt, String arg) {
+            task.options.files.addAll(ClassSearch.makeList(ModuleSourceProvider.TYPE, arg));
+        }
+    }, new Option("  --directory <dirs>         List of directories where to search for files to compile", true, "--directory") {
+        @Override
+        void process(Main task, String opt, String arg) {
+            task.options.files.addAll(ClassSearch.makeList(DirectorySourceProvider.TYPE, arg));
+        }
+    }, new Option("  --search-path <dirs>       List of directories where to search for specified files", true, "--search-path") {
+        @Override
+        void process(Main task, String opt, String arg) {
+            String[] elements = arg.split(":");
+            task.options.searchPath.add(elements);
+        }
     }, new Option("  --compile-commands <file>  Name of file with compile commands", true, "--compile-commands") {
         @Override
         void process(Main task, String opt, String arg) {
             task.options.methodList = arg;
         }
-    }, new Option("  --compile-for-tiered       Generated profiling code for tiered compilation", false, "--compile-for-tiered") {
+    }, new Option("  --compile-for-tiered       Generate profiling code for tiered compilation", false, "--compile-for-tiered") {
         @Override
         void process(Main task, String opt, String arg) {
             TieredAOT.setValue(true);
         }
-    }, new Option("  --classpath <path>         Specify where to find user class files", true, "--classpath", "--class-path") {
+    }, new Option("  --compile-with-assertions  Compile with java assertions", false, "--compile-with-assertions") {
         @Override
         void process(Main task, String opt, String arg) {
-            task.options.classpath = arg;
+            task.options.compileWithAssertions = true;
         }
-    }, new Option("  --threads <number>         Number of compilation threads to be used", true, "--threads") {
+    }, new Option("  --compile-threads <number> Number of compilation threads to be used", true, "--compile-threads", "--threads") {
         @Override
         void process(Main task, String opt, String arg) {
             int threads = Integer.parseInt(arg);
@@ -213,27 +241,27 @@
     }};
 
     public static class Options {
-        public List<String> files = new LinkedList<>();
-        public String module = null;
-        public String modulepath = "modules";
+        public List<SearchFor> files = new LinkedList<>();
         public String outputName = "unnamed";
         public String methodList;
-        public String classpath = ".";
+        public List<ClassSource> sources = new ArrayList<>();
+        public SearchPath searchPath = new SearchPath();
 
         /**
          * We don't see scaling beyond 16 threads.
          */
         private static final int COMPILER_THREADS = 16;
 
-        int threads = Integer.min(COMPILER_THREADS, Runtime.getRuntime().availableProcessors());
+        public int threads = Integer.min(COMPILER_THREADS, Runtime.getRuntime().availableProcessors());
 
         public boolean ignoreClassLoadingErrors;
         public boolean exitOnError;
-        boolean info;
-        boolean verbose;
-        boolean debug;
-        boolean help;
-        boolean version;
+        public boolean info;
+        public boolean verbose;
+        public boolean debug;
+        public boolean help;
+        public boolean version;
+        public boolean compileWithAssertions;
     }
 
     /* package */final Options options = new Options();
@@ -275,7 +303,9 @@
 
             printlnInfo("Compiling " + options.outputName + "...");
             final long start = System.currentTimeMillis();
-            run();
+            if (!run()) {
+              return EXIT_ABNORMAL;
+            }
             final long end = System.currentTimeMillis();
             printlnInfo("Total time: " + (end - start) + " ms");
 
@@ -318,17 +348,34 @@
     }
 
     @SuppressWarnings("try")
-    private void run() throws Exception {
+    private boolean run() throws Exception {
         openLog();
 
         try {
             CompilationSpec compilationRestrictions = collectSpecifiedMethods();
 
-            Set<Class<?>> classesToCompile;
+            Set<Class<?>> classesToCompile = new HashSet<>();
 
             try (Timer t = new Timer(this, "")) {
-                ClassCollector collector = new ClassCollector(this.options, this);
-                classesToCompile = collector.collectClassesToCompile();
+                FileSupport fileSupport = new FileSupport();
+                ClassSearch lookup = new ClassSearch();
+                lookup.addProvider(new ModuleSourceProvider());
+                lookup.addProvider(new ClassNameSourceProvider(fileSupport));
+                lookup.addProvider(new JarSourceProvider());
+                lookup.addProvider(new DirectorySourceProvider(fileSupport));
+
+                List<LoadedClass> found = null;
+                try {
+                    found = lookup.search(options.files, options.searchPath);
+                } catch (InternalError e) {
+                    reportError(e);
+                    return false;
+                }
+
+                for (LoadedClass loadedClass : found) {
+                    classesToCompile.add(loadedClass.getLoadedClass());
+                }
+
                 printInfo(classesToCompile.size() + " classes found");
             }
 
@@ -356,6 +403,11 @@
             AOTCompiler compiler = new AOTCompiler(this, aotBackend, options.threads);
             classes = compiler.compileClasses(classes);
 
+            GraalHotSpotVMConfig graalHotSpotVMConfig = runtime.getVMConfig();
+            PhaseSuite<HighTierContext> graphBuilderSuite = aotBackend.getGraphBuilderSuite();
+            ListIterator<BasePhase<? super HighTierContext>> iterator = graphBuilderSuite.findPhase(GraphBuilderPhase.class);
+            GraphBuilderConfiguration graphBuilderConfig = ((GraphBuilderPhase) iterator.previous()).getGraphBuilderConfig();
+
             // Free memory!
             try (Timer t = options.verbose ? new Timer(this, "Freeing memory") : null) {
                 printMemoryUsage();
@@ -364,7 +416,7 @@
                 System.gc();
             }
 
-            BinaryContainer binaryContainer = new BinaryContainer(runtime.getVMConfig(), JVM_VERSION);
+            BinaryContainer binaryContainer = new BinaryContainer(graalHotSpotVMConfig, graphBuilderConfig, JVM_VERSION);
             DataBuilder dataBuilder = new DataBuilder(this, backend, classes, binaryContainer);
             dataBuilder.prepareData();
 
@@ -446,6 +498,7 @@
         } finally {
             closeLog();
         }
+        return true;
     }
 
     private void addMethods(AOTCompiledClass aotClass, ResolvedJavaMethod[] methods, CompilationSpec compilationRestrictions, GraalFilters filters) {
@@ -509,7 +562,7 @@
                     break;
                 }
             } else {
-                options.files.add(arg);
+                options.files.add(new SearchFor(arg));
             }
         }
     }
@@ -570,6 +623,12 @@
         log.flush();
     }
 
+    private void reportError(Throwable e) {
+        log.println("Error: " + e.getMessage());
+        e.printStackTrace(log);
+        log.flush();
+    }
+
     private void reportError(String key, Object... args) {
         printError(MessageFormat.format(key, args));
     }
@@ -580,17 +639,17 @@
     }
 
     private void showUsage() {
-        log.println("Usage: " + PROGNAME + " <options> list...");
+        log.println("Usage: " + PROGNAME + " <options> list");
         log.println("use --help for a list of possible options");
     }
 
     private void showHelp() {
-        log.println("Usage: " + PROGNAME + " <options> <--module name> | <list...>");
+        log.println("Usage: " + PROGNAME + " <options> list");
         log.println();
-        log.println("  list       A list of class files, jar files or directories which");
-        log.println("             contains class files.");
+        log.println("  list       A : separated list of class names, modules, jar files");
+        log.println("             or directories which contain class files.");
         log.println();
-        log.println("where possible options include:");
+        log.println("where options include:");
         for (Option o : recognizedOptions) {
             String name = o.aliases[0].substring(1); // there must always be at least one name
             name = name.charAt(0) == '-' ? name.substring(1) : name;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MarkId.java	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MarkId.java	Sat Feb 04 03:29:40 2017 +0100
@@ -48,6 +48,7 @@
     HEAP_TOP_ADDRESS("CodeInstaller::HEAP_TOP_ADDRESS"),
     HEAP_END_ADDRESS("CodeInstaller::HEAP_END_ADDRESS"),
     NARROW_KLASS_BASE_ADDRESS("CodeInstaller::NARROW_KLASS_BASE_ADDRESS"),
+    NARROW_OOP_BASE_ADDRESS("CodeInstaller::NARROW_OOP_BASE_ADDRESS"),
     CRC_TABLE_ADDRESS("CodeInstaller::CRC_TABLE_ADDRESS"),
     LOG_OF_HEAP_REGION_GRAIN_BYTES("CodeInstaller::LOG_OF_HEAP_REGION_GRAIN_BYTES"),
     INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED("CodeInstaller::INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED");
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MarkProcessor.java	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MarkProcessor.java	Sat Feb 04 03:29:40 2017 +0100
@@ -57,6 +57,7 @@
             case HEAP_TOP_ADDRESS:
             case HEAP_END_ADDRESS:
             case NARROW_KLASS_BASE_ADDRESS:
+            case NARROW_OOP_BASE_ADDRESS:
             case CRC_TABLE_ADDRESS:
             case LOG_OF_HEAP_REGION_GRAIN_BYTES:
             case INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED:
@@ -78,6 +79,9 @@
                     case NARROW_KLASS_BASE_ADDRESS:
                         vmSymbolName = binaryContainer.getNarrowKlassBaseAddressSymbolName();
                         break;
+                    case NARROW_OOP_BASE_ADDRESS:
+                        vmSymbolName = binaryContainer.getNarrowOopBaseAddressSymbolName();
+                        break;
                     case CRC_TABLE_ADDRESS:
                         vmSymbolName = binaryContainer.getCrcTableAddressSymbolName();
                         break;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassCollector.java	Fri Feb 03 15:20:05 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,332 +0,0 @@
-/*
- * Copyright (c) 2016, 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 jdk.tools.jaotc.collect;
-
-import jdk.tools.jaotc.LogPrinter;
-import jdk.tools.jaotc.Main;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.*;
-import java.nio.file.*;
-import java.nio.file.attribute.BasicFileAttributes;
-import java.util.*;
-
-import static java.nio.file.FileVisitResult.CONTINUE;
-
-public class ClassCollector {
-    private final Main.Options options;
-    private final LogPrinter log;
-
-    public ClassCollector(Main.Options options, LogPrinter log) {
-        this.options = options;
-        this.log = log;
-    }
-
-    /**
-     * Collect all class names passed by the user.
-     *
-     * @return array list of classes
-     */
-    public Set<Class<?>> collectClassesToCompile() {
-        Set<Class<?>> classes = new HashSet<>();
-        List<String> filesToScan = new LinkedList<>(options.files);
-
-        if (options.module != null) {
-            classes.addAll(scanModule(filesToScan));
-        }
-
-        classes.addAll(scanFiles(filesToScan));
-        return classes;
-    }
-
-    private Set<Class<?>> scanModule(List<String> filesToScan) {
-        String module = options.module;
-        // Search module in standard JDK installation.
-        Path dir = getModuleDirectory(options.modulepath, module);
-
-        if (Files.isDirectory(dir)) {
-            return loadFromModuleDirectory(dir);
-        } else {
-            findFilesToScan(filesToScan, module);
-            return new HashSet<>();
-        }
-    }
-
-    private Set<Class<?>> loadFromModuleDirectory(Path dir) {
-        log.printInfo("Scanning module: " + dir + " ...");
-        log.printlnVerbose(" "); // Break line
-
-        FileSystemFinder finder = new FileSystemFinder(dir, pathname -> entryIsClassFile(pathname.toString()));
-        Set<Class<?>> cls = loadWithClassLoader(() -> ClassLoader.getSystemClassLoader(), dir, finder);
-        log.printlnInfo(" " + cls.size() + " classes loaded.");
-        return cls;
-    }
-
-    private void findFilesToScan(List<String> filesToScan, String module) {
-        // Try to search regular directory, .jar or .class files
-        Path path = Paths.get(options.modulepath, module);
-
-        if (Files.isDirectory(path)) {
-            filesToScan.add(".");
-            options.classpath = path.toString();
-        } else if (path.endsWith(".jar") || path.endsWith(".class")) {
-            filesToScan.add(path.toString());
-        } else {
-            path = Paths.get(options.modulepath, module + ".jar");
-            if (Files.exists(path)) {
-                filesToScan.add(path.toString());
-            } else {
-                path = Paths.get(options.modulepath, module + ".class");
-                if (Files.exists(path)) {
-                    filesToScan.add(path.toString());
-                } else {
-                    throw new InternalError("Expecting a .class, .jar or directory: " + path);
-                }
-            }
-        }
-    }
-
-    private boolean entryIsClassFile(String entry) {
-        return entry.endsWith(".class") && !entry.endsWith("module-info.class");
-    }
-
-    private Set<Class<?>> scanFiles(List<String> filesToScan) {
-        Set<Class<?>> classes = new HashSet<>();
-        for (String fileName : filesToScan) {
-            Set<Class<?>> loaded = scanFile(fileName);
-            log.printlnInfo(" " + loaded.size() + " classes loaded.");
-            classes.addAll(loaded);
-        }
-        return classes;
-    }
-
-    interface ClassLoaderFactory {
-        ClassLoader create() throws IOException;
-    }
-
-    private Set<Class<?>> loadWithClassLoader(ClassLoaderFactory factory, Path root, FileSystemFinder finder) {
-        ClassLoader loader = null;
-        try {
-            loader = factory.create();
-            return loadClassFiles(root, finder, loader);
-        } catch (IOException e) {
-            throw new InternalError(e);
-        } finally {
-            if (loader instanceof AutoCloseable) {
-                try {
-                    ((AutoCloseable) loader).close();
-                } catch (Exception e) {
-                    throw new InternalError(e);
-                }
-            }
-        }
-    }
-
-    private Set<Class<?>> scanFile(String fileName) {
-        log.printInfo("Scanning: " + fileName + " ...");
-        log.printlnVerbose(" "); // Break line
-
-        if (fileName.endsWith(".jar")) {
-            return loadFromJarFile(fileName);
-        } else if (fileName.endsWith(".class")) {
-            Set<Class<?>> classes = new HashSet<>();
-            loadFromClassFile(fileName, classes);
-            return classes;
-        } else {
-            return scanClassPath(fileName);
-        }
-    }
-
-    private Set<Class<?>> loadFromJarFile(String fileName) {
-        FileSystem fs = makeFileSystem(fileName);
-        FileSystemFinder finder = new FileSystemFinder(fs.getPath("/"), pathname -> entryIsClassFile(pathname.toString()));
-        return loadWithClassLoader(() -> URLClassLoader.newInstance(buildUrls(fileName)), fs.getPath("/"), finder);
-    }
-
-    private void loadFromClassFile(String fileName, Set<Class<?>> classes) {
-        Class<?> result;
-        File file = new File(options.classpath);
-        try (URLClassLoader loader = URLClassLoader.newInstance(buildUrls(file))) {
-            result = loadClassFile(loader, fileName);
-        } catch (IOException e) {
-            throw new InternalError(e);
-        }
-        Class<?> c = result;
-        addClass(classes, fileName, c);
-    }
-
-    private Set<Class<?>> scanClassPath(String fileName) {
-        Path classPath = Paths.get(options.classpath);
-        if (!Files.exists(classPath)) {
-            throw new InternalError("Path does not exist: " + classPath);
-        }
-        if (!Files.isDirectory(classPath)) {
-            throw new InternalError("Path must be a directory: " + classPath);
-        }
-
-        // Combine class path and file name and see what it is.
-        Path combinedPath = Paths.get(options.classpath + File.separator + fileName);
-        if (combinedPath.endsWith(".class")) {
-            throw new InternalError("unimplemented");
-        } else if (Files.isDirectory(combinedPath)) {
-            return scanDirectory(classPath, combinedPath);
-        } else {
-            throw new InternalError("Expecting a .class, .jar or directory: " + fileName);
-        }
-    }
-
-    private FileSystem makeFileSystem(String fileName) {
-        try {
-            return FileSystems.newFileSystem(makeJarFileURI(fileName), new HashMap<>());
-        } catch (IOException e) {
-            throw new InternalError(e);
-        }
-    }
-
-    private URI makeJarFileURI(String fileName) {
-        try {
-            return new URI("jar:file:" + Paths.get(fileName).toAbsolutePath() + "!/");
-        } catch (URISyntaxException e) {
-            throw new InternalError(e);
-        }
-    }
-
-    private PathMatcher combine(PathMatcher m1, PathMatcher m2) {
-        return path -> m1.matches(path) && m2.matches(path);
-    }
-
-    private Set<Class<?>> scanDirectory(Path classPath, Path combinedPath) {
-        String dir = options.classpath;
-
-        FileSystem fileSystem = FileSystems.getDefault();
-        PathMatcher matcher = fileSystem.getPathMatcher("glob:" + "*.class");
-        FileSystemFinder finder = new FileSystemFinder(combinedPath,
-            combine(matcher, pathname -> entryIsClassFile(pathname.toString())));
-
-        File file = new File(dir);
-        try (URLClassLoader loader = URLClassLoader.newInstance(buildUrls(file))) {
-            return loadClassFiles(classPath, finder, loader);
-        } catch (IOException e) {
-            throw new InternalError(e);
-        }
-    }
-
-    private Set<Class<?>> loadClassFiles(Path root, FileSystemFinder finder, ClassLoader loader) {
-        Set<Class<?>> classes = new HashSet<>();
-        for (Path name : finder.done()) {
-            // Now relativize to the class path so we get the actual class names.
-            String entry = root.relativize(name).normalize().toString();
-            Class<?> c = loadClassFile(loader, entry);
-            addClass(classes, entry, c);
-        }
-        return classes;
-    }
-
-    private void addClass(Set<Class<?>> classes, String name, Class<?> c) {
-        if (c != null) {
-            classes.add(c);
-            log.printlnVerbose(" loaded " + name);
-        }
-    }
-
-    private URL[] buildUrls(String fileName) throws MalformedURLException {
-        return new URL[]{ new URL("jar:file:" + Paths.get(fileName).toAbsolutePath() + "!/") };
-    }
-
-    private URL[] buildUrls(File file) throws MalformedURLException {
-        return new URL[] {file.toURI().toURL() };
-    }
-
-    private Path getModuleDirectory(String modulepath, String module) {
-        FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
-        return fs.getPath(modulepath, module);
-    }
-
-    /**
-     * Loads a class with the given file name from the specified {@link URLClassLoader}.
-     */
-    private Class<?> loadClassFile(final ClassLoader loader, final String fileName) {
-        int start = 0;
-        if (fileName.startsWith("/")) {
-            start = 1;
-        }
-        String className = fileName.substring(start, fileName.length() - ".class".length());
-        className = className.replace('/', '.');
-        try {
-            return loader.loadClass(className);
-        } catch (Throwable e) {
-            // If we are running in JCK mode we ignore all exceptions.
-            if (options.ignoreClassLoadingErrors) {
-                log.printError(className + ": " + e);
-                return null;
-            }
-            throw new InternalError(e);
-        }
-    }
-
-    /**
-     * {@link FileVisitor} implementation to find class files recursively.
-     */
-    private static class FileSystemFinder extends SimpleFileVisitor<Path> {
-        private final ArrayList<Path> fileNames = new ArrayList<>();
-        private final PathMatcher filter;
-
-        FileSystemFinder(Path combinedPath, PathMatcher filter) {
-            this.filter = filter;
-            try {
-                Files.walkFileTree(combinedPath, this);
-            } catch (IOException e) {
-                throw new InternalError(e);
-            }
-        }
-
-        /**
-         * Compares the glob pattern against the file name.
-         */
-        void find(Path file) {
-            Path name = file.getFileName();
-            if (name != null && filter.matches(name)) {
-                fileNames.add(file);
-            }
-        }
-
-        List<Path> done() {
-            return fileNames;
-        }
-
-        @Override
-        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
-            find(file);
-            return CONTINUE;
-        }
-
-        @Override
-        public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
-            find(dir);
-            return CONTINUE;
-        }
-
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSearch.java	Sat Feb 04 03:29:40 2017 +0100
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2017, 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 jdk.tools.jaotc.collect;
+
+import jdk.tools.jaotc.LoadedClass;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ClassSearch {
+    private List<SourceProvider> providers = new ArrayList<>();
+
+    public void addProvider(SourceProvider provider) {
+        providers.add(provider);
+    }
+
+    public List<LoadedClass> search(List<SearchFor> search, SearchPath searchPath) {
+        List<LoadedClass> loaded = new ArrayList<>();
+
+        List<ClassSource> sources = new ArrayList<>();
+
+        for (SearchFor entry : search) {
+            sources.add(findSource(entry, searchPath));
+        }
+
+        for (ClassSource source : sources) {
+            source.eachClass((name, loader) -> loaded.add(loadClass(name, loader)));
+        }
+
+        return loaded;
+    }
+
+    private LoadedClass loadClass(String name, ClassLoader loader) {
+        try {
+            Class<?> clzz = loader.loadClass(name);
+            return new LoadedClass(name, clzz);
+        } catch (ClassNotFoundException e) {
+            throw new InternalError("Failed to load with: " + loader, e);
+        }
+    }
+
+    private ClassSource findSource(SearchFor searchFor, SearchPath searchPath) {
+        ClassSource found = null;
+
+        for (SourceProvider provider : providers) {
+            if (!searchFor.isUnknown() && !provider.supports(searchFor.getType())) {
+                continue;
+            }
+
+            ClassSource source = provider.findSource(searchFor.getName(), searchPath);
+            if (source != null) {
+                if (found != null) {
+                    throw new InternalError("Multiple possible sources: " + source + " and: " + found);
+                }
+                found = source;
+            }
+        }
+
+        if (found == null) {
+            throw new InternalError("Failed to find: " + searchFor.toString());
+        }
+        return found;
+    }
+
+    public static List<SearchFor> makeList(String type, String argument) {
+        List<SearchFor> list = new ArrayList<>();
+        String[] elements = argument.split(":");
+        for (String element : elements) {
+            list.add(new SearchFor(element, type));
+        }
+        return list;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSource.java	Sat Feb 04 03:29:40 2017 +0100
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2017, 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 jdk.tools.jaotc.collect;
+
+import java.nio.file.Path;
+import java.util.function.BiConsumer;
+
+public interface ClassSource {
+    static boolean pathIsClassFile(Path entry) {
+        String fileName = entry.getFileName().toString();
+        return fileName.endsWith(".class") && !fileName.endsWith("module-info.class");
+    }
+
+    static String makeClassName(Path path) {
+        String fileName = path.toString();
+
+        if (!fileName.endsWith(".class")) {
+            throw new IllegalArgumentException("File doesn't end with .class: '" + fileName + "'");
+        }
+
+        int start = 0;
+        if (fileName.startsWith("/")) {
+            start = 1;
+        }
+
+        String className = fileName.substring(start, fileName.length() - ".class".length());
+        className = className.replace('/', '.');
+        return className;
+    }
+
+    void eachClass(BiConsumer<String, ClassLoader> consumer);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/FileSupport.java	Sat Feb 04 03:29:40 2017 +0100
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2017, 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 jdk.tools.jaotc.collect;
+
+import java.io.IOException;
+import java.net.*;
+import java.nio.file.*;
+import java.util.HashMap;
+
+public class FileSupport {
+    public boolean exists(Path path)  {
+        return Files.exists(path);
+    }
+
+    public boolean isDirectory(Path path) {
+        return Files.isDirectory(path);
+    }
+
+    private FileSystem makeJarFileSystem(Path path) {
+        try {
+            return FileSystems.newFileSystem(makeJarFileURI(path), new HashMap<>());
+        } catch (IOException e) {
+            throw new InternalError(e);
+        }
+    }
+
+    private URI makeJarFileURI(Path path) {
+        try {
+            return new URI("jar:file:" + path.toAbsolutePath() + "!/");
+        } catch (URISyntaxException e) {
+            throw new InternalError(e);
+        }
+    }
+
+    public ClassLoader createClassLoader(Path path, ClassLoader parent) {
+        try {
+            return URLClassLoader.newInstance(buildUrls(path), parent);
+        } catch (MalformedURLException e) {
+            throw new InternalError(e);
+        }
+    }
+
+    public ClassLoader createClassLoader(Path path) throws MalformedURLException {
+        return URLClassLoader.newInstance(buildUrls(path));
+    }
+
+    private URL[] buildUrls(Path path) throws MalformedURLException {
+        return new URL[] { path.toUri().toURL() };
+    }
+
+    public Path getJarFileSystemRoot(Path jarFile) {
+        FileSystem fileSystem = makeJarFileSystem(jarFile);
+        return fileSystem.getPath("/");
+    }
+
+    public boolean isAbsolute(Path entry) {
+        return entry.isAbsolute();
+    }
+
+    public Path getSubDirectory(FileSystem fileSystem, Path root, Path path) throws IOException {
+        DirectoryStream<Path> paths = fileSystem.provider().newDirectoryStream(root,null);
+        for (Path entry : paths) {
+            Path relative = root.relativize(entry);
+            if (relative.equals(path)) {
+                return entry;
+            }
+        }
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/FileSystemFinder.java	Sat Feb 04 03:29:40 2017 +0100
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2017, 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 jdk.tools.jaotc.collect;
+
+import java.io.IOException;
+import java.nio.file.*;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import static java.nio.file.FileVisitResult.CONTINUE;
+
+/**
+ * {@link FileVisitor} implementation to find class files recursively.
+ */
+public class FileSystemFinder extends SimpleFileVisitor<Path> implements Iterable<Path> {
+    private final ArrayList<Path> fileNames = new ArrayList<>();
+    private final PathMatcher filter;
+
+    public FileSystemFinder(Path combinedPath, PathMatcher filter) {
+        this.filter = filter;
+        try {
+            Files.walkFileTree(combinedPath, this);
+        } catch (IOException e) {
+            throw new InternalError(e);
+        }
+    }
+
+    /**
+     * Compares the glob pattern against the file name.
+     */
+    private void find(Path file) {
+        Path name = file.getFileName();
+        if (name != null && filter.matches(name)) {
+            fileNames.add(file);
+        }
+    }
+
+    @Override
+    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
+        find(file);
+        return CONTINUE;
+    }
+
+    @Override
+    public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
+        find(dir);
+        return CONTINUE;
+    }
+
+
+    @Override
+    public Iterator<Path> iterator() {
+        return fileNames.iterator();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/SearchFor.java	Sat Feb 04 03:29:40 2017 +0100
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2017, 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 jdk.tools.jaotc.collect;
+
+public class SearchFor {
+    private final String name;
+    private final String type;
+
+    public SearchFor(String name) {
+        this(name, "unknown");
+    }
+
+    public SearchFor(String name, String type) {
+        this.name = name;
+        this.type = type;
+    }
+
+    public boolean isUnknown() {
+        return "unknown".equals(type);
+    }
+
+    public String getType() {
+        return this.type;
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    @Override
+    public String toString() {
+        return type + ":" + name;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/SearchPath.java	Sat Feb 04 03:29:40 2017 +0100
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2017, 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 jdk.tools.jaotc.collect;
+
+import java.nio.file.FileSystem;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+
+public class SearchPath {
+    private final List<Path> searchPaths = new ArrayList<>();
+    private final FileSupport fileSupport;
+
+    public SearchPath() {
+        this(new FileSupport());
+    }
+
+    public SearchPath(FileSupport fileSupport) {
+        this.fileSupport = fileSupport;
+    }
+
+    public Path find(FileSystem fileSystem, Path entry, String... defaults) {
+        if (isAbsolute(entry)) {
+            if (exists(entry)) {
+                return entry;
+            }
+            return null;
+        }
+
+        if (exists(entry)) {
+            return entry;
+        }
+
+        for (String searchPath : defaults) {
+            Path newPath = fileSystem.getPath(searchPath, entry.toString());
+            if (exists(newPath)) {
+                return newPath;
+            }
+        }
+
+        for (Path searchPath : searchPaths) {
+            Path newPath = fileSystem.getPath(searchPath.toString(), entry.toString());
+            if (exists(newPath)) {
+                return newPath;
+            }
+        }
+
+        return null;
+    }
+
+    private boolean isAbsolute(Path entry) {
+        return fileSupport.isAbsolute(entry);
+    }
+
+    private boolean exists(Path entry) {
+        return fileSupport.exists(entry);
+    }
+
+    public void add(String... paths) {
+        for (String name : paths) {
+            Path path = Paths.get(name);
+            searchPaths.add(path);
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/SourceProvider.java	Sat Feb 04 03:29:40 2017 +0100
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2017, 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 jdk.tools.jaotc.collect;
+
+public interface SourceProvider {
+    ClassSource findSource(String name, SearchPath searchPath);
+
+    boolean supports(String type);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/classname/ClassNameSource.java	Sat Feb 04 03:29:40 2017 +0100
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2017, 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 jdk.tools.jaotc.collect.classname;
+
+import jdk.tools.jaotc.collect.ClassSource;
+
+import java.util.function.BiConsumer;
+
+public class ClassNameSource implements ClassSource {
+    private final String name;
+    private final ClassLoader classLoader;
+
+    public ClassNameSource(String name, ClassLoader classLoader) {
+        this.name = name;
+        this.classLoader = classLoader;
+    }
+
+    @Override
+    public void eachClass(BiConsumer<String, ClassLoader> consumer) {
+        consumer.accept(name, classLoader);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/classname/ClassNameSourceProvider.java	Sat Feb 04 03:29:40 2017 +0100
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2017, 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 jdk.tools.jaotc.collect.classname;
+
+import jdk.tools.jaotc.collect.ClassSource;
+import jdk.tools.jaotc.collect.FileSupport;
+import jdk.tools.jaotc.collect.SearchPath;
+import jdk.tools.jaotc.collect.SourceProvider;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class ClassNameSourceProvider implements SourceProvider {
+    public final static String TYPE = "classname";
+    private final ClassLoader classLoader;
+
+    public ClassNameSourceProvider(FileSupport fileSupport) {
+        String classPath = System.getProperty("java.class.path");
+        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
+        if (classPath != null && !classPath.isEmpty()) {
+            classLoader = systemClassLoader;
+        } else {
+            Path path = Paths.get(".").toAbsolutePath();
+            classLoader = fileSupport.createClassLoader(path, systemClassLoader);
+        }
+    }
+
+    @Override
+    public ClassSource findSource(String name, SearchPath searchPath) {
+        try {
+            classLoader.loadClass(name);
+            return new ClassNameSource(name, classLoader);
+        } catch (ClassNotFoundException e) {
+            return null;
+        }
+    }
+
+    @Override
+    public boolean supports(String type) {
+        return TYPE.equals(type);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/directory/DirectorySource.java	Sat Feb 04 03:29:40 2017 +0100
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2017, 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 jdk.tools.jaotc.collect.directory;
+
+import jdk.tools.jaotc.collect.ClassSource;
+import jdk.tools.jaotc.collect.FileSystemFinder;
+
+import java.nio.file.Path;
+import java.util.function.BiConsumer;
+
+public class DirectorySource implements ClassSource {
+    private final Path directoryPath;
+    private final ClassLoader classLoader;
+
+    public DirectorySource(Path directoryPath, ClassLoader classLoader) {
+        this.directoryPath = directoryPath;
+        this.classLoader = classLoader;
+    }
+
+    @Override
+    public void eachClass(BiConsumer<String, ClassLoader> consumer) {
+        FileSystemFinder finder = new FileSystemFinder(directoryPath, ClassSource::pathIsClassFile);
+
+        for (Path path : finder) {
+            consumer.accept(ClassSource.makeClassName(directoryPath.relativize(path).normalize()), classLoader);
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "directory:" + directoryPath.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/directory/DirectorySourceProvider.java	Sat Feb 04 03:29:40 2017 +0100
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2017, 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 jdk.tools.jaotc.collect.directory;
+
+import jdk.tools.jaotc.collect.ClassSource;
+import jdk.tools.jaotc.collect.FileSupport;
+import jdk.tools.jaotc.collect.SearchPath;
+import jdk.tools.jaotc.collect.SourceProvider;
+
+import java.net.MalformedURLException;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+
+public class DirectorySourceProvider implements SourceProvider {
+    private final FileSupport fileSupport;
+    private final FileSystem fileSystem;
+    public final static String TYPE = "directory";
+
+    public DirectorySourceProvider(FileSupport fileSupport) {
+        this.fileSupport = fileSupport;
+        fileSystem = FileSystems.getDefault();
+    }
+
+    @Override
+    public ClassSource findSource(String name, SearchPath searchPath) {
+        Path directoryPath = fileSystem.getPath(name);
+
+        if (!fileSupport.exists(directoryPath)) {
+            return null;
+        }
+        if (!fileSupport.isDirectory(directoryPath)) {
+            return null;
+        }
+
+        try {
+            ClassLoader classLoader = fileSupport.createClassLoader(directoryPath);
+            return new DirectorySource(directoryPath, classLoader);
+        } catch (MalformedURLException e) {
+            return null;
+        }
+    }
+
+    @Override
+    public boolean supports(String type) {
+        return TYPE.equals(type);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/jar/JarFileSource.java	Sat Feb 04 03:29:40 2017 +0100
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2017, 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 jdk.tools.jaotc.collect.jar;
+
+import jdk.tools.jaotc.collect.ClassSource;
+import jdk.tools.jaotc.collect.FileSystemFinder;
+
+import java.nio.file.Path;
+import java.util.function.BiConsumer;
+
+public class JarFileSource implements ClassSource {
+    private final Path jarFile;
+    private final Path jarRootPath;
+    private final ClassLoader classLoader;
+
+
+    public JarFileSource(Path jarFile, Path jarRootPath, ClassLoader classLoader) {
+        this.jarFile = jarFile;
+        this.jarRootPath = jarRootPath;
+        this.classLoader = classLoader;
+    }
+
+    public void eachClass(BiConsumer<String, ClassLoader> consumer) {
+        FileSystemFinder finder = new FileSystemFinder(jarRootPath, ClassSource::pathIsClassFile);
+
+        for (Path path : finder) {
+            consumer.accept(ClassSource.makeClassName(jarRootPath.relativize(path).normalize()), classLoader);
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "jar:" + jarFile.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/jar/JarSourceProvider.java	Sat Feb 04 03:29:40 2017 +0100
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2017, 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 jdk.tools.jaotc.collect.jar;
+
+import jdk.tools.jaotc.collect.ClassSource;
+import jdk.tools.jaotc.collect.FileSupport;
+import jdk.tools.jaotc.collect.SearchPath;
+import jdk.tools.jaotc.collect.SourceProvider;
+
+import java.net.MalformedURLException;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+import java.nio.file.ProviderNotFoundException;
+
+public class JarSourceProvider implements SourceProvider {
+    private final FileSystem fileSystem;
+    private final FileSupport fileSupport;
+    public final static String TYPE = "jar";
+
+    public JarSourceProvider() {
+        this(new FileSupport());
+    }
+
+    public JarSourceProvider(FileSupport fileSupport) {
+        this.fileSupport = fileSupport;
+        fileSystem = FileSystems.getDefault();
+    }
+
+    @Override
+    public ClassSource findSource(String name, SearchPath searchPath) {
+        Path fileName = fileSystem.getPath(name);
+        Path jarFile = searchPath.find(fileSystem, fileName);
+
+        if (!validPath(jarFile)) {
+            return null;
+        }
+
+        return createSource(jarFile);
+    }
+
+    private ClassSource createSource(Path jarFile) {
+        try {
+            Path jarRootPath = fileSupport.getJarFileSystemRoot(jarFile);
+            if (jarRootPath == null) {
+                return null;
+            }
+            ClassLoader classLoader = fileSupport.createClassLoader(jarFile);
+            return new JarFileSource(jarFile, jarRootPath, classLoader);
+        } catch (ProviderNotFoundException | MalformedURLException e) {
+        }
+        return null;
+    }
+
+    @Override
+    public boolean supports(String type) {
+        return TYPE.equals(type);
+    }
+
+    private boolean validPath(Path jarFile) {
+        return jarFile != null && !fileSupport.isDirectory(jarFile);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/module/ModuleSource.java	Sat Feb 04 03:29:40 2017 +0100
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2017, 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 jdk.tools.jaotc.collect.module;
+
+import jdk.tools.jaotc.collect.ClassSource;
+import jdk.tools.jaotc.collect.FileSystemFinder;
+
+import java.nio.file.Path;
+import java.util.function.BiConsumer;
+
+public class ModuleSource implements ClassSource {
+    private final Path modulePath;
+    private final ClassLoader classLoader;
+
+    public ModuleSource(Path modulePath, ClassLoader classLoader) {
+        this.modulePath = modulePath;
+        this.classLoader = classLoader;
+    }
+
+    @Override
+    public void eachClass(BiConsumer<String, ClassLoader> consumer) {
+        FileSystemFinder finder = new FileSystemFinder(modulePath, ClassSource::pathIsClassFile);
+
+        for (Path path : finder) {
+            consumer.accept(ClassSource.makeClassName(modulePath.relativize(path).normalize()), classLoader);
+        }
+    }
+
+    public Path getModulePath() {
+        return modulePath;
+    }
+
+    @Override
+    public String toString() {
+        return "module:" + modulePath.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/module/ModuleSourceProvider.java	Sat Feb 04 03:29:40 2017 +0100
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2017, 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 jdk.tools.jaotc.collect.module;
+
+import jdk.tools.jaotc.collect.ClassSource;
+import jdk.tools.jaotc.collect.FileSupport;
+import jdk.tools.jaotc.collect.SearchPath;
+import jdk.tools.jaotc.collect.SourceProvider;
+
+import java.io.IOException;
+import java.net.URI;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+
+public class ModuleSourceProvider implements SourceProvider {
+    private final FileSystem fileSystem;
+    private final ClassLoader classLoader;
+    private final FileSupport fileSupport;
+    public final static String TYPE = "module";
+
+    public ModuleSourceProvider() {
+        this(FileSystems.getFileSystem(URI.create("jrt:/")), ClassLoader.getSystemClassLoader(), new FileSupport());
+    }
+
+    public ModuleSourceProvider(FileSystem fileSystem, ClassLoader classLoader, FileSupport fileSupport) {
+        this.fileSystem = fileSystem;
+        this.classLoader = classLoader;
+        this.fileSupport = fileSupport;
+    }
+
+    @Override
+    public ClassSource findSource(String name, SearchPath searchPath) {
+        Path path = fileSystem.getPath(name);
+        Path dir = fileSystem.getPath("modules");
+
+        if (dir == null || !fileSupport.isDirectory(dir)) {
+            return null;
+        }
+
+        Path found = findModuleDirectory(dir, path);
+
+        if (found == null) {
+            return null;
+        }
+
+        return new ModuleSource(found, classLoader);
+    }
+
+    private Path findModuleDirectory(Path root, Path path) {
+        try {
+            return fileSupport.getSubDirectory(fileSystem, root, path);
+        } catch (IOException e) {
+            throw new InternalError(e);
+        }
+    }
+
+    @Override
+    public boolean supports(String type) {
+        return TYPE.equals(type);
+    }
+}
--- a/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java	Sat Feb 04 03:29:40 2017 +0100
@@ -100,15 +100,19 @@
     native long getExceptionTableStart(HotSpotResolvedJavaMethodImpl method);
 
     /**
-     * Determines if {@code method} can be inlined. A method may not be inlinable for a number of
-     * reasons such as:
-     * <ul>
-     * <li>a CompileOracle directive may prevent inlining or compilation of methods</li>
-     * <li>the method may have a bytecode breakpoint set</li>
-     * <li>the method may have other bytecode features that require special handling by the VM</li>
-     * </ul>
+     * Determines whether {@code method} is currently compilable by the JVMCI compiler being used by
+     * the VM. This can return false if JVMCI compilation failed earlier for {@code method}, a
+     * breakpoint is currently set in {@code method} or {@code method} contains other bytecode
+     * features that require special handling by the VM.
      */
-    native boolean canInlineMethod(HotSpotResolvedJavaMethodImpl method);
+    native boolean isCompilable(HotSpotResolvedJavaMethodImpl method);
+
+    /**
+     * Determines if {@code method} is targeted by a VM directive (e.g.,
+     * {@code -XX:CompileCommand=dontinline,<pattern>}) or annotation (e.g.,
+     * {@code jdk.internal.vm.annotation.DontInline}) that specifies it should not be inlined.
+     */
+    native boolean hasNeverInlineDirective(HotSpotResolvedJavaMethodImpl method);
 
     /**
      * Determines if {@code method} should be inlined at any cost. This could be because:
--- a/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethod.java	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethod.java	Sat Feb 04 03:29:40 2017 +0100
@@ -50,13 +50,6 @@
     boolean isForceInline();
 
     /**
-     * Returns true if this method has a {@code DontInline} annotation.
-     *
-     * @return true if DontInline annotation present, false otherwise
-     */
-    boolean isDontInline();
-
-    /**
      * Returns true if this method has a {@code ReservedStackAccess} annotation.
      *
      * @return true if ReservedStackAccess annotation present, false otherwise
--- a/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java	Sat Feb 04 03:29:40 2017 +0100
@@ -299,15 +299,6 @@
     }
 
     /**
-     * Returns true if this method has a {@code DontInline} annotation.
-     *
-     * @return true if DontInline annotation present, false otherwise
-     */
-    public boolean isDontInline() {
-        return (getFlags() & config().methodFlagsDontInline) != 0;
-    }
-
-    /**
      * Returns true if this method has a {@code ReservedStackAccess} annotation.
      *
      * @return true if ReservedStackAccess annotation present, false otherwise
@@ -582,10 +573,15 @@
 
     @Override
     public boolean canBeInlined() {
-        if (isDontInline()) {
+        if (hasNeverInlineDirective()) {
             return false;
         }
-        return compilerToVM().canInlineMethod(this);
+        return compilerToVM().isCompilable(this);
+    }
+
+    @Override
+    public boolean hasNeverInlineDirective() {
+        return compilerToVM().hasNeverInlineDirective(this);
     }
 
     @Override
--- a/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaMethod.java	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaMethod.java	Sat Feb 04 03:29:40 2017 +0100
@@ -347,6 +347,13 @@
     boolean canBeInlined();
 
     /**
+     * Determines if this method is targeted by a VM directive (e.g.,
+     * {@code -XX:CompileCommand=dontinline,<pattern>}) or VM recognized annotation (e.g.,
+     * {@code jdk.internal.vm.annotation.DontInline}) that specifies it should not be inlined.
+     */
+    boolean hasNeverInlineDirective();
+
+    /**
      * Returns {@code true} if the inlining of this method should be forced.
      */
     boolean shouldBeInlined();
--- a/src/jdk.vm.compiler/.mx.graal/suite.py	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/jdk.vm.compiler/.mx.graal/suite.py	Sat Feb 04 03:29:40 2017 +0100
@@ -638,6 +638,7 @@
       "annotationProcessors" : [
         "GRAAL_NODEINFO_PROCESSOR",
         "GRAAL_REPLACEMENTS_VERIFIER",
+        "GRAAL_OPTIONS_PROCESSOR",
       ],
       "workingSets" : "Graal,Graph",
     },
--- a/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Debug.java	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Debug.java	Sat Feb 04 03:29:40 2017 +0100
@@ -116,6 +116,7 @@
     public static final int INFO_LOG_LEVEL = 2;
     public static final int VERBOSE_LOG_LEVEL = 3;
     public static final int DETAILED_LOG_LEVEL = 4;
+    public static final int VERY_DETAILED_LOG_LEVEL = 5;
 
     public static boolean isDumpEnabled(int dumpLevel) {
         return ENABLED && DebugScope.getInstance().isDumpEnabled(dumpLevel);
--- a/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java	Sat Feb 04 03:29:40 2017 +0100
@@ -267,10 +267,15 @@
 
             if (config.useCompressedClassPointers) {
                 Register register = r10;
-                AMD64HotSpotMove.decodeKlassPointer(asm, register, providers.getRegisters().getHeapBaseRegister(), src, config.getKlassEncoding());
-                if (config.narrowKlassBase != 0) {
-                    // The heap base register was destroyed above, so restore it
-                    asm.movq(providers.getRegisters().getHeapBaseRegister(), config.narrowOopBase);
+                AMD64HotSpotMove.decodeKlassPointer(crb, asm, register, providers.getRegisters().getHeapBaseRegister(), src, config);
+                if (GeneratePIC.getValue()) {
+                    asm.movq(providers.getRegisters().getHeapBaseRegister(), asm.getPlaceholder(-1));
+                    crb.recordMark(config.MARKID_NARROW_OOP_BASE_ADDRESS);
+                } else {
+                    if (config.narrowKlassBase != 0) {
+                        // The heap base register was destroyed above, so restore it
+                        asm.movq(providers.getRegisters().getHeapBaseRegister(), config.narrowOopBase);
+                    }
                 }
                 asm.cmpq(inlineCacheKlass, register);
             } else {
--- a/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMove.java	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMove.java	Sat Feb 04 03:29:40 2017 +0100
@@ -265,14 +265,21 @@
         }
     }
 
-    public static void decodeKlassPointer(AMD64MacroAssembler masm, Register register, Register scratch, AMD64Address address, CompressEncoding encoding) {
+    public static void decodeKlassPointer(CompilationResultBuilder crb, AMD64MacroAssembler masm, Register register, Register scratch, AMD64Address address, GraalHotSpotVMConfig config) {
+        CompressEncoding encoding = config.getKlassEncoding();
         masm.movl(register, address);
         if (encoding.shift != 0) {
             assert encoding.alignment == encoding.shift : "Decode algorithm is wrong";
             masm.shlq(register, encoding.alignment);
         }
-        if (encoding.base != 0) {
-            masm.movq(scratch, encoding.base);
+        if (GeneratePIC.getValue() || encoding.base != 0) {
+            if (GeneratePIC.getValue()) {
+                masm.movq(scratch, masm.getPlaceholder(-1));
+                crb.recordMark(config.MARKID_NARROW_KLASS_BASE_ADDRESS);
+            } else {
+                assert encoding.base != 0;
+                masm.movq(scratch, encoding.base);
+            }
             masm.addq(register, scratch);
         }
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/AOTGraalHotSpotVMConfig.java	Sat Feb 04 03:29:40 2017 +0100
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2017, 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 org.graalvm.compiler.hotspot;
+
+import jdk.vm.ci.hotspot.HotSpotVMConfigStore;
+
+public class AOTGraalHotSpotVMConfig extends GraalHotSpotVMConfig {
+    private final CompressEncoding aotOopEncoding;
+    private final CompressEncoding aotKlassEncoding;
+
+    public AOTGraalHotSpotVMConfig(HotSpotVMConfigStore store) {
+        super(store);
+        // In AOT, force the shift to be always equal to alignment therefore avoiding zero-shift.
+        CompressEncoding vmOopEncoding = super.getOopEncoding();
+        aotOopEncoding = new CompressEncoding(vmOopEncoding.base, vmOopEncoding.alignment, vmOopEncoding.alignment);
+        CompressEncoding vmKlassEncoding = super.getKlassEncoding();
+        aotKlassEncoding = new CompressEncoding(vmKlassEncoding.base, vmKlassEncoding.alignment, vmKlassEncoding.alignment);
+        assert check();
+    }
+
+    @Override
+    public CompressEncoding getOopEncoding() {
+        return aotOopEncoding;
+    }
+
+    @Override
+    public CompressEncoding getKlassEncoding() {
+        return aotKlassEncoding;
+    }
+}
--- a/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java	Sat Feb 04 03:29:40 2017 +0100
@@ -479,7 +479,6 @@
     public final int methodCompiledEntryOffset = getFieldOffset("Method::_from_compiled_entry", Integer.class, "address");
     public final int methodCodeOffset = getFieldOffset("Method::_code", Integer.class, isJDK8 ? "nmethod*" : "CompiledMethod*");
 
-    public final int methodFlagsJfrTowrite = getConstant("Method::_jfr_towrite", Integer.class);
     public final int methodFlagsCallerSensitive = getConstant("Method::_caller_sensitive", Integer.class);
     public final int methodFlagsForceInline = getConstant("Method::_force_inline", Integer.class);
     public final int methodFlagsDontInline = getConstant("Method::_dont_inline", Integer.class);
@@ -773,13 +772,14 @@
     public final int MARKID_HEAP_TOP_ADDRESS = getConstant("CodeInstaller::HEAP_TOP_ADDRESS", Integer.class, 17);
     public final int MARKID_HEAP_END_ADDRESS = getConstant("CodeInstaller::HEAP_END_ADDRESS", Integer.class, 18);
     public final int MARKID_NARROW_KLASS_BASE_ADDRESS = getConstant("CodeInstaller::NARROW_KLASS_BASE_ADDRESS", Integer.class, 19);
-    public final int MARKID_CRC_TABLE_ADDRESS = getConstant("CodeInstaller::CRC_TABLE_ADDRESS", Integer.class, 20);
-    public final int MARKID_LOG_OF_HEAP_REGION_GRAIN_BYTES = getConstant("CodeInstaller::LOG_OF_HEAP_REGION_GRAIN_BYTES", Integer.class, 21);
-    public final int MARKID_INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED = getConstant("CodeInstaller::INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED", Integer.class, 22);
+    public final int MARKID_NARROW_OOP_BASE_ADDRESS = getConstant("CodeInstaller::NARROW_OOP_BASE_ADDRESS", Integer.class, 20);
+    public final int MARKID_CRC_TABLE_ADDRESS = getConstant("CodeInstaller::CRC_TABLE_ADDRESS", Integer.class, 21);
+    public final int MARKID_LOG_OF_HEAP_REGION_GRAIN_BYTES = getConstant("CodeInstaller::LOG_OF_HEAP_REGION_GRAIN_BYTES", Integer.class, 22);
+    public final int MARKID_INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED = getConstant("CodeInstaller::INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED", Integer.class, 23);
 
     // Checkstyle: resume
 
-    private boolean check() {
+    protected boolean check() {
         for (Field f : getClass().getDeclaredFields()) {
             int modifiers = f.getModifiers();
             if (Modifier.isPublic(modifiers) && !Modifier.isStatic(modifiers)) {
--- a/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java	Sat Feb 04 03:29:40 2017 +0100
@@ -22,6 +22,7 @@
  */
 package org.graalvm.compiler.hotspot;
 
+import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
 import static org.graalvm.compiler.debug.GraalDebugConfig.areScopedGlobalMetricsEnabled;
 import static org.graalvm.compiler.debug.GraalDebugConfig.Options.DebugValueSummary;
 import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Dump;
@@ -99,7 +100,7 @@
     HotSpotGraalRuntime(HotSpotJVMCIRuntime jvmciRuntime, CompilerConfigurationFactory compilerConfigurationFactory) {
 
         HotSpotVMConfigStore store = jvmciRuntime.getConfigStore();
-        config = new GraalHotSpotVMConfig(store);
+        config = GeneratePIC.getValue() ? new AOTGraalHotSpotVMConfig(store) : new GraalHotSpotVMConfig(store);
         CompileTheWorldOptions.overrideWithNativeOptions(config);
 
         // Only set HotSpotPrintInlining if it still has its default value (false).
--- a/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotNodePlugin.java	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotNodePlugin.java	Sat Feb 04 03:29:40 2017 +0100
@@ -22,7 +22,6 @@
  */
 package org.graalvm.compiler.hotspot.meta;
 
-import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
 import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode;
 import static org.graalvm.compiler.hotspot.meta.HotSpotGraalConstantFieldProvider.FieldReadEnabledInImmutableCode;
 
@@ -112,11 +111,6 @@
                 return true;
             }
         }
-        if (GeneratePIC.getValue()) {
-            if (field.isSynthetic() && field.getName().startsWith("$assertionsDisabled")) {
-                return tryReadField(b, field, null);
-            }
-        }
         if (b.parsingIntrinsic() && wordOperationPlugin.handleLoadStaticField(b, field)) {
             return true;
         }
--- a/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java	Sat Feb 04 03:29:40 2017 +0100
@@ -1738,9 +1738,8 @@
             } else {
                 // Intrinsic was not applied: remove intrinsic guard
                 // and restore the original receiver node in the arguments array
-                for (Node node : graph.getNewNodes(intrinsicGuard.mark)) {
-                    GraphUtil.killCFG(node);
-                }
+                intrinsicGuard.lastInstr.setNext(null);
+                GraphUtil.removeNewNodes(graph, intrinsicGuard.mark);
                 lastInstr = intrinsicGuard.lastInstr;
                 args[0] = intrinsicGuard.receiver;
             }
--- a/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/SimplifyingGraphDecoder.java	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/SimplifyingGraphDecoder.java	Sat Feb 04 03:29:40 2017 +0100
@@ -153,9 +153,7 @@
         }
 
         for (Node node : methodScope.graph.getNewNodes(methodScope.methodStartMark)) {
-            if (!(node instanceof FixedNode) && node.hasNoUsages()) {
-                GraphUtil.killCFG(node);
-            }
+            GraphUtil.tryKillUnused(node);
         }
     }
 
--- a/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java	Sat Feb 04 03:29:40 2017 +0100
@@ -506,7 +506,7 @@
         for (Node successor : snapshot) {
             if (successor != null && successor.isAlive()) {
                 if (successor != survivingSuccessor) {
-                    GraphUtil.killCFG(successor, tool);
+                    GraphUtil.killCFG((FixedNode) successor, tool);
                 }
             }
         }
@@ -566,6 +566,9 @@
             reduceTrivialMerge(begin);
         } else { // convert to merge
             AbstractMergeNode merge = this.add(new MergeNode());
+            for (EndNode end : begin.forwardEnds()) {
+                merge.addForwardEnd(end);
+            }
             this.replaceFixedWithFixed(begin, merge);
         }
     }
@@ -576,7 +579,14 @@
         for (PhiNode phi : merge.phis().snapshot()) {
             assert phi.valueCount() == 1;
             ValueNode singleValue = phi.valueAt(0);
-            phi.replaceAtUsagesAndDelete(singleValue);
+            if (phi.hasUsages()) {
+                phi.replaceAtUsagesAndDelete(singleValue);
+            } else {
+                phi.safeDelete();
+                if (singleValue != null) {
+                    GraphUtil.tryKillUnused(singleValue);
+                }
+            }
         }
         // remove loop exits
         if (merge instanceof LoopBeginNode) {
--- a/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java	Sat Feb 04 03:29:40 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2017, 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
@@ -22,18 +22,30 @@
  */
 package org.graalvm.compiler.nodes.util;
 
+import static org.graalvm.compiler.graph.Graph.Options.VerifyGraalGraphEdges;
+import static org.graalvm.compiler.nodes.util.GraphUtil.Options.VerifyKillCFGUnusedNodes;
+
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Iterator;
+import java.util.Set;
 
 import org.graalvm.compiler.bytecode.Bytecode;
 import org.graalvm.compiler.code.SourceStackTraceBailoutException;
+import org.graalvm.compiler.core.common.CollectionsFactory;
 import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
+import org.graalvm.compiler.core.common.type.StampFactory;
+import org.graalvm.compiler.debug.Debug;
+import org.graalvm.compiler.graph.Graph;
 import org.graalvm.compiler.graph.Node;
+import org.graalvm.compiler.graph.NodeClass;
 import org.graalvm.compiler.graph.NodeWorkList;
+import org.graalvm.compiler.graph.Position;
 import org.graalvm.compiler.graph.iterators.NodeIterable;
 import org.graalvm.compiler.graph.spi.SimplifierTool;
+import org.graalvm.compiler.nodeinfo.InputType;
+import org.graalvm.compiler.nodeinfo.NodeInfo;
 import org.graalvm.compiler.nodes.AbstractBeginNode;
 import org.graalvm.compiler.nodes.AbstractEndNode;
 import org.graalvm.compiler.nodes.AbstractMergeNode;
@@ -48,11 +60,15 @@
 import org.graalvm.compiler.nodes.StateSplit;
 import org.graalvm.compiler.nodes.StructuredGraph;
 import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.calc.FloatingNode;
 import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
 import org.graalvm.compiler.nodes.spi.ArrayLengthProvider;
 import org.graalvm.compiler.nodes.spi.LimitedValueProxy;
 import org.graalvm.compiler.nodes.spi.LoweringProvider;
 import org.graalvm.compiler.nodes.spi.ValueProxy;
+import org.graalvm.compiler.options.Option;
+import org.graalvm.compiler.options.OptionType;
+import org.graalvm.compiler.options.OptionValue;
 
 import jdk.vm.ci.code.BailoutException;
 import jdk.vm.ci.code.BytecodePosition;
@@ -64,22 +80,78 @@
 
 public class GraphUtil {
 
-    public static void killCFG(Node node, SimplifierTool tool) {
-        NodeWorkList worklist = killCFG(node, tool, null);
-        if (worklist != null) {
-            for (Node successor : worklist) {
-                killCFG(successor, tool, worklist);
+    public static class Options {
+        @Option(help = "Verify that there are no new unused nodes when performing killCFG", type = OptionType.Debug)//
+        public static final OptionValue<Boolean> VerifyKillCFGUnusedNodes = new OptionValue<>(false);
+    }
+
+    @SuppressWarnings("try")
+    public static void killCFG(FixedNode node, SimplifierTool tool) {
+        try (Debug.Scope scope = Debug.scope("KillCFG", node)) {
+            Set<Node> unusedNodes = null;
+            Set<Node> unsafeNodes = null;
+            Graph.NodeEventScope nodeEventScope = null;
+            if (VerifyGraalGraphEdges.getValue()) {
+                unsafeNodes = collectUnsafeNodes(node.graph());
+            }
+            if (VerifyKillCFGUnusedNodes.getValue()) {
+                Set<Node> collectedUnusedNodes = unusedNodes = CollectionsFactory.newSet();
+                nodeEventScope = node.graph().trackNodeEvents(new Graph.NodeEventListener() {
+                    @Override
+                    public void event(Graph.NodeEvent e, Node n) {
+                        if (e == Graph.NodeEvent.ZERO_USAGES && isFloatingNode(n)) {
+                            collectedUnusedNodes.add(n);
+                        }
+                    }
+                });
+            }
+            Debug.dump(Debug.VERY_DETAILED_LOG_LEVEL, node.graph(), "Before killCFG %s", node);
+            NodeWorkList worklist = killCFG(node, tool, null);
+            if (worklist != null) {
+                for (Node n : worklist) {
+                    killCFG(n, tool, worklist);
+                }
+            }
+            if (VerifyGraalGraphEdges.getValue()) {
+                Set<Node> newUnsafeNodes = collectUnsafeNodes(node.graph());
+                newUnsafeNodes.removeAll(unsafeNodes);
+                assert newUnsafeNodes.isEmpty() : "New unsafe nodes: " + newUnsafeNodes;
+            }
+            if (VerifyKillCFGUnusedNodes.getValue()) {
+                nodeEventScope.close();
+                unusedNodes.removeIf(n -> n.isDeleted());
+                assert unusedNodes.isEmpty() : "New unused nodes: " + unusedNodes;
+            }
+        } catch (Throwable t) {
+            throw Debug.handle(t);
+        }
+    }
+
+    /**
+     * Collects all node in the graph which have non-optional inputs that are null.
+     */
+    private static Set<Node> collectUnsafeNodes(Graph graph) {
+        Set<Node> unsafeNodes = CollectionsFactory.newSet();
+        for (Node n : graph.getNodes()) {
+            for (Position pos : n.inputPositions()) {
+                Node input = pos.get(n);
+                if (input == null) {
+                    if (!pos.isInputOptional()) {
+                        unsafeNodes.add(n);
+                    }
+                }
             }
         }
+        return unsafeNodes;
     }
 
     private static NodeWorkList killCFG(Node node, SimplifierTool tool, NodeWorkList worklist) {
         NodeWorkList newWorklist = worklist;
-        // DebugScope.forceDump(node.graph(), "kill CFG %s", node);
         if (node instanceof FixedNode) {
             newWorklist = killCFGLinear((FixedNode) node, newWorklist, tool);
         } else {
-            propagateKill(node);
+            newWorklist = propagateKill(node, newWorklist);
+            Debug.dump(Debug.VERY_DETAILED_LOG_LEVEL, node.graph(), "killCFG (Floating) %s", node);
         }
         return newWorklist;
     }
@@ -93,19 +165,20 @@
             if (current instanceof AbstractEndNode) {
                 // We reached a control flow end.
                 AbstractEndNode end = (AbstractEndNode) current;
-                killEnd(end, tool);
+                newWorklist = killEnd(end, newWorklist, tool);
             } else if (current instanceof FixedWithNextNode) {
-                next = ((FixedWithNextNode) current).next();
+                // Node guaranteed to have a single successor
+                FixedWithNextNode fixedWithNext = (FixedWithNextNode) current;
+                assert fixedWithNext.successors().count() == 1 || fixedWithNext.successors().count() == 0;
+                assert fixedWithNext.successors().first() == fixedWithNext.next();
+                next = fixedWithNext.next();
             } else {
-                // Normal control flow node.
                 /*
                  * We do not take a successor snapshot because this iterator supports concurrent
                  * modifications as long as they do not change the size of the successor list. Not
                  * taking a snapshot allows us to see modifications to other branches that may
                  * happen while processing one branch.
                  */
-                // assert node.successors().count() > 1 || node.successors().count() == 0 :
-                // node.getClass();
                 Iterator<Node> successors = current.successors().iterator();
                 if (successors.hasNext()) {
                     Node first = successors.next();
@@ -126,100 +199,158 @@
                 }
             }
             current.replaceAtPredecessor(null);
-            propagateKill(current);
+            newWorklist = propagateKill(current, newWorklist);
+            Debug.dump(Debug.VERY_DETAILED_LOG_LEVEL, current.graph(), "killCFGLinear %s", current);
             current = next;
         }
+        Debug.dump(Debug.DETAILED_LOG_LEVEL, in.graph(), "killCFGLinear %s", in);
         return newWorklist;
     }
 
-    public static void killCFG(Node node) {
+    public static void killCFG(FixedNode node) {
         killCFG(node, null);
     }
 
-    private static void killEnd(AbstractEndNode end, SimplifierTool tool) {
+    /**
+     * Node type used temporarily while deleting loops.
+     *
+     * It is used as replacement for the loop {@link PhiNode PhiNodes} in order to break data-flow
+     * cycles before deleting the loop. The control-flow of the whole loop is killed before killing
+     * the poison node if they are still alive.
+     */
+    @NodeInfo(allowedUsageTypes = InputType.Unchecked)
+    private static final class PoisonNode extends FloatingNode {
+        public static final NodeClass<PoisonNode> TYPE = NodeClass.create(PoisonNode.class);
+
+        protected PoisonNode() {
+            super(TYPE, StampFactory.forVoid());
+        }
+    }
+
+    private static NodeWorkList killEnd(AbstractEndNode end, NodeWorkList worklist, SimplifierTool tool) {
+        NodeWorkList newWorklist = worklist;
         AbstractMergeNode merge = end.merge();
         if (merge != null) {
             merge.removeEnd(end);
             StructuredGraph graph = end.graph();
             if (merge instanceof LoopBeginNode && merge.forwardEndCount() == 0) {
                 // dead loop
-                for (PhiNode phi : merge.phis().snapshot()) {
-                    propagateKill(phi);
-                }
                 LoopBeginNode begin = (LoopBeginNode) merge;
                 // disconnect and delete loop ends & loop exits
                 for (LoopEndNode loopend : begin.loopEnds().snapshot()) {
                     loopend.predecessor().replaceFirstSuccessor(loopend, null);
                     loopend.safeDelete();
                 }
+                // clean unused proxies to avoid creating new unused nodes
+                for (LoopExitNode exit : begin.loopExits()) {
+                    for (ProxyNode vpn : exit.proxies().snapshot()) {
+                        tryKillUnused(vpn);
+                    }
+                }
                 begin.removeExits();
+                PoisonNode poison = null;
+                if (merge.phis().isNotEmpty()) {
+                    poison = graph.unique(new PoisonNode());
+                    for (PhiNode phi : merge.phis()) {
+                        phi.replaceAtUsages(poison);
+                    }
+                    for (PhiNode phi : merge.phis().snapshot()) {
+                        killWithUnusedFloatingInputs(phi);
+                    }
+                }
                 FixedNode loopBody = begin.next();
-                if (loopBody != null) { // for small infinite loops, the body may be killed while
-                                        // killing the loop ends
-                    killCFG(loopBody);
+                Debug.dump(Debug.VERY_DETAILED_LOG_LEVEL, end.graph(), "killEnd (Loop) %s after initial loop cleanup", end);
+                if (loopBody != null) {
+                    // for small infinite loops, the body may already be killed while killing the
+                    // LoopEnds
+                    newWorklist = killCFG(loopBody, tool, worklist);
                 }
+                FrameState frameState = begin.stateAfter();
                 begin.safeDelete();
+                if (frameState != null) {
+                    tryKillUnused(frameState);
+                }
+                if (poison != null && poison.isAlive()) {
+                    if (newWorklist == null) {
+                        newWorklist = graph.createNodeWorkList();
+                    }
+                    // drain the worklist to finish the loop before adding the poison
+                    for (Node n : newWorklist) {
+                        killCFG(n, tool, newWorklist);
+                    }
+                    if (poison.isAlive()) {
+                        newWorklist.add(poison);
+                    }
+                }
             } else if (merge instanceof LoopBeginNode && ((LoopBeginNode) merge).loopEnds().isEmpty()) {
                 // not a loop anymore
                 if (tool != null) {
-                    merge.phis().forEach(phi -> tool.addToWorkList(phi.usages()));
+                    for (PhiNode phi : merge.phis()) {
+                        tool.addToWorkList(phi.usages());
+                    }
                 }
                 graph.reduceDegenerateLoopBegin((LoopBeginNode) merge);
             } else if (merge.phiPredecessorCount() == 1) {
                 // not a merge anymore
                 if (tool != null) {
-                    merge.phis().forEach(phi -> tool.addToWorkList(phi.usages()));
+                    for (PhiNode phi : merge.phis()) {
+                        tool.addToWorkList(phi.usages());
+                    }
                 }
                 graph.reduceTrivialMerge(merge);
             }
         }
+        return newWorklist;
     }
 
     public static boolean isFloatingNode(Node n) {
         return !(n instanceof FixedNode);
     }
 
-    private static void propagateKill(Node node) {
+    private static NodeWorkList propagateKill(Node node, NodeWorkList workList) {
+        NodeWorkList newWorkList = workList;
         if (node != null && node.isAlive()) {
-            node.markDeleted();
-
-            for (Node in : node.inputs()) {
-                if (in.isAlive()) {
-                    in.removeUsage(node);
-                    if (in.hasNoUsages() && !(in instanceof FixedNode)) {
-                        killWithUnusedFloatingInputs(in);
+            for (Node usage : node.usages().snapshot()) {
+                assert usage.isAlive();
+                if (isFloatingNode(usage)) {
+                    boolean addUsage = false;
+                    if (usage instanceof PhiNode) {
+                        PhiNode phi = (PhiNode) usage;
+                        assert phi.merge() != null;
+                        if (phi.merge() == node) {
+                            // we reach the phi directly through he merge, queue it.
+                            addUsage = true;
+                        } else {
+                            // we reach it though a value
+                            assert phi.values().contains(node);
+                            // let that be handled when we reach the corresponding End node
+                        }
+                    } else {
+                        addUsage = true;
+                    }
+                    if (addUsage) {
+                        if (newWorkList == null) {
+                            newWorkList = node.graph().createNodeWorkList();
+                        }
+                        newWorkList.add(usage);
                     }
                 }
+                usage.replaceFirstInput(node, null);
             }
+            killWithUnusedFloatingInputs(node);
+        }
+        return newWorkList;
+    }
 
-            ArrayList<Node> usageToKill = null;
-            for (Node usage : node.usages()) {
-                if (usage.isAlive() && !(usage instanceof FixedNode)) {
-                    if (usageToKill == null) {
-                        usageToKill = new ArrayList<>();
-                    }
-                    usageToKill.add(usage);
-                }
-            }
-            if (usageToKill != null) {
-                for (Node usage : usageToKill) {
-                    if (usage.isAlive()) {
-                        if (usage instanceof PhiNode) {
-                            PhiNode phiNode = (PhiNode) usage;
-                            usage.replaceFirstInput(node, null);
-                            if (phiNode.merge() == null || !phiNode.hasValidInput()) {
-                                propagateKill(usage);
-                            }
-                        } else {
-                            propagateKill(usage);
-                        }
-                    }
-                }
-            }
-        }
+    private static boolean checkKill(Node node) {
+        node.assertTrue(node.isAlive(), "must be alive");
+        node.assertTrue(node.hasNoUsages(), "cannot kill node %s because of usages: %s", node, node.usages());
+        node.assertTrue(node.predecessor() == null, "cannot kill node %s because of predecessor: %s", node, node.predecessor());
+        return true;
     }
 
     public static void killWithUnusedFloatingInputs(Node node) {
+        assert checkKill(node);
         node.markDeleted();
         outer: for (Node in : node.inputs()) {
             if (in.isAlive()) {
@@ -227,7 +358,7 @@
                 if (in.hasNoUsages()) {
                     node.maybeNotifyZeroUsages(in);
                 }
-                if (!(in instanceof FixedNode)) {
+                if (isFloatingNode(in)) {
                     if (in.hasNoUsages()) {
                         killWithUnusedFloatingInputs(in);
                     } else if (in instanceof PhiNode) {
@@ -244,6 +375,35 @@
         }
     }
 
+    /**
+     * Removes all nodes created after the {@code mark}, assuming no "old" nodes point to "new"
+     * nodes.
+     */
+    public static void removeNewNodes(Graph graph, Graph.Mark mark) {
+        assert checkNoOldToNewEdges(graph, mark);
+        for (Node n : graph.getNewNodes(mark)) {
+            n.markDeleted();
+            for (Node in : n.inputs()) {
+                in.removeUsage(n);
+            }
+        }
+    }
+
+    private static boolean checkNoOldToNewEdges(Graph graph, Graph.Mark mark) {
+        for (Node old : graph.getNodes()) {
+            if (graph.isNew(mark, old)) {
+                break;
+            }
+            for (Node n : old.successors()) {
+                assert !graph.isNew(mark, n) : old + " -> " + n;
+            }
+            for (Node n : old.inputs()) {
+                assert !graph.isNew(mark, n) : old + " -> " + n;
+            }
+        }
+        return true;
+    }
+
     public static void removeFixedWithUnusedInputs(FixedWithNextNode fixed) {
         if (fixed instanceof StateSplit) {
             FrameState stateAfter = ((StateSplit) fixed).stateAfter();
@@ -688,8 +848,9 @@
 
         @Override
         public void deleteBranch(Node branch) {
-            branch.predecessor().replaceFirstSuccessor(branch, null);
-            GraphUtil.killCFG(branch, this);
+            FixedNode fixedBranch = (FixedNode) branch;
+            fixedBranch.predecessor().replaceFirstSuccessor(fixedBranch, null);
+            GraphUtil.killCFG(fixedBranch, this);
         }
 
         @Override
--- a/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/CanonicalizerPhase.java	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/CanonicalizerPhase.java	Sat Feb 04 03:29:40 2017 +0100
@@ -444,8 +444,9 @@
 
             @Override
             public void deleteBranch(Node branch) {
-                branch.predecessor().replaceFirstSuccessor(branch, null);
-                GraphUtil.killCFG(branch, this);
+                FixedNode fixedBranch = (FixedNode) branch;
+                fixedBranch.predecessor().replaceFirstSuccessor(fixedBranch, null);
+                GraphUtil.killCFG(fixedBranch, this);
             }
 
             @Override
--- a/src/os/aix/vm/os_aix.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/os/aix/vm/os_aix.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2016 SAP SE. All rights reserved.
+ * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017 SAP SE. 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
@@ -632,7 +632,6 @@
   sigaddset(&unblocked_sigs, SIGBUS);
   sigaddset(&unblocked_sigs, SIGFPE);
   sigaddset(&unblocked_sigs, SIGTRAP);
-  sigaddset(&unblocked_sigs, SIGDANGER);
   sigaddset(&unblocked_sigs, SR_signum);
 
   if (!ReduceSignalUsage) {
@@ -1553,6 +1552,8 @@
   print_signal_handler(st, SHUTDOWN3_SIGNAL , buf, buflen);
   print_signal_handler(st, BREAK_SIGNAL, buf, buflen);
   print_signal_handler(st, SIGTRAP, buf, buflen);
+  // We also want to know if someone else adds a SIGDANGER handler because
+  // that will interfere with OOM killling.
   print_signal_handler(st, SIGDANGER, buf, buflen);
 }
 
@@ -3156,7 +3157,6 @@
     set_signal_handler(SIGFPE, true);
     set_signal_handler(SIGTRAP, true);
     set_signal_handler(SIGXFSZ, true);
-    set_signal_handler(SIGDANGER, true);
 
     if (libjsig_is_loaded) {
       // Tell libjsig jvm finishes setting signal handlers.
@@ -3273,7 +3273,6 @@
   if (UseSIGTRAP) {
     DO_SIGNAL_CHECK(SIGTRAP);
   }
-  DO_SIGNAL_CHECK(SIGDANGER);
 
   // ReduceSignalUsage allows the user to override these handlers
   // see comments at the very top and jvm_solaris.h
--- a/src/os/windows/vm/os_windows.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/os/windows/vm/os_windows.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -778,6 +778,11 @@
   // is already attached to a debugger; debugger must observe
   // the exception below to show the correct name.
 
+  // If there is no debugger attached skip raising the exception
+  if (!IsDebuggerPresent()) {
+    return;
+  }
+
   const DWORD MS_VC_EXCEPTION = 0x406D1388;
   struct {
     DWORD dwType;     // must be 0x1000
--- a/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2016 SAP SE. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017 SAP SE. 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
@@ -258,13 +258,6 @@
     }
   }
 
-  // Handle SIGDANGER right away. AIX would raise SIGDANGER whenever available swap
-  // space falls below 30%. This is only a chance for the process to gracefully abort.
-  // We can't hope to proceed after SIGDANGER since SIGKILL tailgates.
-  if (sig == SIGDANGER) {
-    goto report_and_die;
-  }
-
   if (info == NULL || uc == NULL || thread == NULL && vmthread == NULL) {
     goto run_chained_handler;
   }
--- a/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -87,6 +87,7 @@
 #define SPELL_REG_FP "rbp"
 #else
 #define REG_FP 29
+#define REG_LR 30
 
 #define SPELL_REG_SP "sp"
 #define SPELL_REG_FP "x29"
@@ -182,6 +183,46 @@
   return frame(sp, fp, epc.pc());
 }
 
+bool os::Linux::get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr) {
+  address pc = (address) os::Linux::ucontext_get_pc(uc);
+  if (Interpreter::contains(pc)) {
+    // interpreter performs stack banging after the fixed frame header has
+    // been generated while the compilers perform it before. To maintain
+    // semantic consistency between interpreted and compiled frames, the
+    // method returns the Java sender of the current frame.
+    *fr = os::fetch_frame_from_context(uc);
+    if (!fr->is_first_java_frame()) {
+      assert(fr->safe_for_sender(thread), "Safety check");
+      *fr = fr->java_sender();
+    }
+  } else {
+    // more complex code with compiled code
+    assert(!Interpreter::contains(pc), "Interpreted methods should have been handled above");
+    CodeBlob* cb = CodeCache::find_blob(pc);
+    if (cb == NULL || !cb->is_nmethod() || cb->is_frame_complete_at(pc)) {
+      // Not sure where the pc points to, fallback to default
+      // stack overflow handling
+      return false;
+    } else {
+      // In compiled code, the stack banging is performed before LR
+      // has been saved in the frame.  LR is live, and SP and FP
+      // belong to the caller.
+      intptr_t* fp = os::Linux::ucontext_get_fp(uc);
+      intptr_t* sp = os::Linux::ucontext_get_sp(uc);
+      address pc = (address)(uc->uc_mcontext.regs[REG_LR]
+                         - NativeInstruction::instruction_size);
+      *fr = frame(sp, fp, pc);
+      if (!fr->is_java_frame()) {
+        assert(fr->safe_for_sender(thread), "Safety check");
+        assert(!fr->is_first_frame(), "Safety check");
+        *fr = fr->java_sender();
+      }
+    }
+  }
+  assert(fr->is_java_frame(), "Safety check");
+  return true;
+}
+
 // By default, gcc always saves frame pointer rfp on this stack. This
 // may get turned off by -fomit-frame-pointer.
 frame os::get_sender_for_C_frame(frame* fr) {
@@ -313,6 +354,24 @@
         if (thread->in_stack_yellow_reserved_zone(addr)) {
           thread->disable_stack_yellow_reserved_zone();
           if (thread->thread_state() == _thread_in_Java) {
+            if (thread->in_stack_reserved_zone(addr)) {
+              frame fr;
+              if (os::Linux::get_frame_at_stack_banging_point(thread, uc, &fr)) {
+                assert(fr.is_java_frame(), "Must be a Java frame");
+                frame activation =
+                  SharedRuntime::look_for_reserved_stack_annotated_method(thread, fr);
+                if (activation.sp() != NULL) {
+                  thread->disable_stack_reserved_zone();
+                  if (activation.is_interpreted_frame()) {
+                    thread->set_reserved_stack_activation((address)(
+                      activation.fp() + frame::interpreter_frame_initial_sp_offset));
+                  } else {
+                    thread->set_reserved_stack_activation((address)activation.unextended_sp());
+                  }
+                  return 1;
+                }
+              }
+            }
             // Throw a stack overflow exception.  Guard pages will be reenabled
             // while unwinding the stack.
             stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW);
--- a/src/os_cpu/linux_s390/vm/os_linux_s390.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/os_cpu/linux_s390/vm/os_linux_s390.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -144,6 +144,42 @@
   return frame(sp, epc.pc());
 }
 
+bool os::Linux::get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr) {
+  address pc = (address) os::Linux::ucontext_get_pc(uc);
+  if (Interpreter::contains(pc)) {
+    // Interpreter performs stack banging after the fixed frame header has
+    // been generated while the compilers perform it before. To maintain
+    // semantic consistency between interpreted and compiled frames, the
+    // method returns the Java sender of the current frame.
+    *fr = os::fetch_frame_from_context(uc);
+    if (!fr->is_first_java_frame()) {
+      assert(fr->safe_for_sender(thread), "Safety check");
+      *fr = fr->java_sender();
+    }
+  } else {
+    // More complex code with compiled code.
+    assert(!Interpreter::contains(pc), "Interpreted methods should have been handled above");
+    CodeBlob* cb = CodeCache::find_blob(pc);
+    if (cb == NULL || !cb->is_nmethod() || cb->is_frame_complete_at(pc)) {
+      // Not sure where the pc points to, fallback to default
+      // stack overflow handling. In compiled code, we bang before
+      // the frame is complete.
+      return false;
+    } else {
+      intptr_t* fp = os::Linux::ucontext_get_fp(uc);
+      intptr_t* sp = os::Linux::ucontext_get_sp(uc);
+      *fr = frame(sp, (address)*sp);
+      if (!fr->is_java_frame()) {
+        assert(fr->safe_for_sender(thread), "Safety check");
+        assert(!fr->is_first_frame(), "Safety check");
+        *fr = fr->java_sender();
+      }
+    }
+  }
+  assert(fr->is_java_frame(), "Safety check");
+  return true;
+}
+
 frame os::get_sender_for_C_frame(frame* fr) {
   if (*fr->sp() == 0) {
     // fr is the last C frame.
@@ -279,13 +315,31 @@
       if (thread->on_local_stack(addr)) {
         // stack overflow
         if (thread->in_stack_yellow_reserved_zone(addr)) {
-          thread->disable_stack_yellow_reserved_zone();
           if (thread->thread_state() == _thread_in_Java) {
+            if (thread->in_stack_reserved_zone(addr)) {
+              frame fr;
+              if (os::Linux::get_frame_at_stack_banging_point(thread, uc, &fr)) {
+                assert(fr.is_java_frame(), "Must be a Javac frame");
+                frame activation =
+                  SharedRuntime::look_for_reserved_stack_annotated_method(thread, fr);
+                if (activation.sp() != NULL) {
+                  thread->disable_stack_reserved_zone();
+                  if (activation.is_interpreted_frame()) {
+                    thread->set_reserved_stack_activation((address)activation.fp());
+                  } else {
+                    thread->set_reserved_stack_activation((address)activation.unextended_sp());
+                  }
+                  return 1;
+                }
+              }
+            }
             // Throw a stack overflow exception.
             // Guard pages will be reenabled while unwinding the stack.
+            thread->disable_stack_yellow_reserved_zone();
             stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW);
           } else {
             // Thread was in the vm or native code. Return and try to finish.
+            thread->disable_stack_yellow_reserved_zone();
             return 1;
           }
         } else if (thread->in_stack_red_zone(addr)) {
--- a/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -89,7 +89,10 @@
 // Minimum usable stack sizes required to get to user code. Space for
 // HotSpot guard pages is added later.
 #ifdef _LP64
-size_t os::Posix::_compiler_thread_min_stack_allowed = 202 * K;
+// The adlc generated method 'State::MachNodeGenerator(int)' used by the C2 compiler
+// threads requires a large stack with the Solaris Studio C++ compiler version 5.13
+// and product VM builds (debug builds require significantly less stack space).
+size_t os::Posix::_compiler_thread_min_stack_allowed = 325 * K;
 size_t os::Posix::_java_thread_min_stack_allowed = 48 * K;
 size_t os::Posix::_vm_internal_thread_min_stack_allowed = 224 * K;
 #else
--- a/src/share/vm/adlc/formssel.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/adlc/formssel.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -650,6 +650,7 @@
   if( strcmp(_matrule->_opType,"MemBarReleaseLock") == 0 ) return true;
   if( strcmp(_matrule->_opType,"MemBarAcquireLock") == 0 ) return true;
   if( strcmp(_matrule->_opType,"MemBarStoreStore") == 0 ) return true;
+  if( strcmp(_matrule->_opType,"MemBarVolatile") == 0 ) return true;
   if( strcmp(_matrule->_opType,"StoreFence") == 0 ) return true;
   if( strcmp(_matrule->_opType,"LoadFence") == 0 ) return true;
 
--- a/src/share/vm/aot/aotCodeHeap.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/aot/aotCodeHeap.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -25,6 +25,7 @@
 
 #include "aot/aotCodeHeap.hpp"
 #include "aot/aotLoader.hpp"
+#include "classfile/javaAssertions.hpp"
 #include "gc/g1/heapRegion.hpp"
 #include "gc/shared/gcLocker.hpp"
 #include "interpreter/abstractInterpreter.hpp"
@@ -294,6 +295,8 @@
     // When the AOT compiler compiles something big we fail to generate metadata
     // in CodeInstaller::gather_metadata. In that case the scopes_pcs_begin == scopes_pcs_end.
     // In all successful cases we always have 2 entries of scope pcs.
+    log_info(aot, class, resolve)("Failed to load %s (no metadata available)", mh->name_and_sig_as_C_string());
+    _code_to_aot[code_id]._state = invalid;
     return;
   }
 
@@ -536,6 +539,7 @@
     SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_heap_end_address", address, (heap->supports_inline_contig_alloc() ? heap->end_addr() : NULL));
     SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_polling_page", address, os::get_polling_page());
     SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_narrow_klass_base_address", address, Universe::narrow_klass_base());
+    SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_narrow_oop_base_address", address, Universe::narrow_oop_base());
     SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_log_of_heap_region_grain_bytes", int, HeapRegion::LogOfHRGrainBytes);
     SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_inline_contiguous_allocation_supported", bool, heap->supports_inline_contig_alloc());
     link_shared_runtime_symbols();
@@ -706,6 +710,12 @@
     return false;
   }
 
+  if (_lib->config()->_omitAssertions && JavaAssertions::enabled(kh->name()->as_C_string(), kh->class_loader() == NULL)) {
+    log_trace(aot, class, load)("class  %s  in  %s does not have java assertions in compiled code, but assertions are enabled for this execution.", kh->internal_name(), _lib->name());
+    sweep_dependent_methods(klass_data);
+    return false;
+  }
+
   NOT_PRODUCT( aot_klasses_found++; )
 
   log_trace(aot, class, load)("found  %s  in  %s for classloader %p tid=" INTPTR_FORMAT, kh->internal_name(), _lib->name(), kh->class_loader_data(), p2i(thread));
@@ -714,7 +724,7 @@
   // Set klass's Resolve (second) got cell.
   _metaspace_got[klass_data->_got_index] = kh();
 
-  // Initialize global symbols of the DSO to the correspondingVM symbol values.
+  // Initialize global symbols of the DSO to the corresponding VM symbol values.
   link_global_lib_symbols();
 
   int methods_offset = klass_data->_compiled_methods_offset;
--- a/src/share/vm/aot/aotCodeHeap.hpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/aot/aotCodeHeap.hpp	Sat Feb 04 03:29:40 2017 +0100
@@ -88,7 +88,7 @@
 } AOTHeader;
 
 typedef struct {
-  enum { CONFIG_SIZE = 11 + 7 * 4 };
+  enum { CONFIG_SIZE = 12 + 7 * 4 };
   int _config_size;
   int _narrowOopShift;
   int _narrowKlassShift;
@@ -108,6 +108,7 @@
   bool _tieredAOT;
   bool _enableContended;
   bool _restrictContended;
+  bool _omitAssertions;
 } AOTConfiguration;
 
 class AOTLib : public CHeapObj<mtCode> {
--- a/src/share/vm/c1/c1_GraphBuilder.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/c1/c1_GraphBuilder.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -3298,7 +3298,9 @@
   // for osr compile, bailout if some requirements are not fulfilled
   if (osr_bci != -1) {
     BlockBegin* osr_block = blm.bci2block()->at(osr_bci);
-    assert(osr_block->is_set(BlockBegin::was_visited_flag),"osr entry must have been visited for osr compile");
+    if (!osr_block->is_set(BlockBegin::was_visited_flag)) {
+      BAILOUT("osr entry must have been visited for osr compile");
+    }
 
     // check if osr entry point has empty stack - we cannot handle non-empty stacks at osr entry points
     if (!osr_block->state()->stack_is_empty()) {
--- a/src/share/vm/ci/bcEscapeAnalyzer.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/ci/bcEscapeAnalyzer.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -895,8 +895,32 @@
           ciMethod* target = s.get_method(ignored_will_link, &declared_signature);
           ciKlass*  holder = s.get_declared_method_holder();
           assert(declared_signature != NULL, "cannot be null");
-          // Push appendix argument, if one.
-          if (s.has_appendix()) {
+          // If the current bytecode has an attached appendix argument,
+          // push an unknown object to represent that argument. (Analysis
+          // of dynamic call sites, especially invokehandle calls, needs
+          // the appendix argument on the stack, in addition to "regular" arguments
+          // pushed onto the stack by bytecode instructions preceding the call.)
+          //
+          // The escape analyzer does _not_ use the ciBytecodeStream::has_appendix(s)
+          // method to determine whether the current bytecode has an appendix argument.
+          // The has_appendix() method obtains the appendix from the
+          // ConstantPoolCacheEntry::_f1 field, which can happen concurrently with
+          // resolution of dynamic call sites. Callees in the
+          // ciBytecodeStream::get_method() call above also access the _f1 field;
+          // interleaving the get_method() and has_appendix() calls in the current
+          // method with call site resolution can lead to an inconsistent view of
+          // the current method's argument count. In particular, some interleaving(s)
+          // can cause the method's argument count to not include the appendix, which
+          // then leads to stack over-/underflow in the escape analyzer.
+          //
+          // Instead of pushing the argument if has_appendix() is true, the escape analyzer
+          // pushes an appendix for all call sites targeted by invokedynamic and invokehandle
+          // instructions, except if the call site is the _invokeBasic intrinsic
+          // (that intrinsic is always targeted by an invokehandle instruction but does
+          // not have an appendix argument).
+          if (target->is_loaded() &&
+              Bytecodes::has_optional_appendix(s.cur_bc_raw()) &&
+              target->intrinsic_id() != vmIntrinsics::_invokeBasic) {
             state.apush(unknown_obj);
           }
           // Pass in raw bytecode because we need to see invokehandle instructions.
--- a/src/share/vm/ci/ciMethod.hpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/ci/ciMethod.hpp	Sat Feb 04 03:29:40 2017 +0100
@@ -136,15 +136,19 @@
     check_is_loaded();
     return _signature->size() + (_flags.is_static() ? 0 : 1);
   }
-  // Report the number of elements on stack when invoking this method.
-  // This is different than the regular arg_size because invokedynamic
-  // has an implicit receiver.
+  // Report the number of elements on stack when invoking the current method.
+  // If the method is loaded, arg_size() gives precise information about the
+  // number of stack elements (using the method's signature and its flags).
+  // However, if the method is not loaded, the number of stack elements must
+  // be determined differently, as the method's flags are not yet available.
+  // The invoke_arg_size() method assumes in that case that all bytecodes except
+  // invokestatic and invokedynamic have a receiver that is also pushed onto the
+  // stack by the caller of the current method.
   int invoke_arg_size(Bytecodes::Code code) const {
     if (is_loaded()) {
       return arg_size();
     } else {
       int arg_size = _signature->size();
-      // Add a receiver argument, maybe:
       if (code != Bytecodes::_invokestatic &&
           code != Bytecodes::_invokedynamic) {
         arg_size++;
--- a/src/share/vm/classfile/classLoader.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/classfile/classLoader.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -364,7 +364,12 @@
     if (verstr != NULL) {
       version = atoi(verstr);
       if (version < base_version || version > cur_ver) {
-        is_multi_ver = false;
+        // If the specified version is lower than the base version, the base
+        // entry will be used; if the version is higher than the current
+        // jdk version, the highest versioned entry will be used.
+        if (version < base_version) {
+          is_multi_ver = false;
+        }
         // print out warning, do not use assertion here since it will continue to look
         // for proper version.
         warning("JDK%d is not supported in multiple version jars", version);
--- a/src/share/vm/classfile/classLoaderData.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/classfile/classLoaderData.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -94,7 +94,7 @@
   _metaspace(NULL), _unloading(false), _klasses(NULL),
   _modules(NULL), _packages(NULL),
   _claimed(0), _jmethod_ids(NULL), _handles(NULL), _deallocate_list(NULL),
-  _next(NULL), _dependencies(dependencies), _shared_class_loader_id(-1),
+  _next(NULL), _dependencies(dependencies),
   _metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true,
                             Monitor::_safepoint_check_never)) {
   TRACE_INIT_ID(this);
--- a/src/share/vm/classfile/classLoaderData.hpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/classfile/classLoaderData.hpp	Sat Feb 04 03:29:40 2017 +0100
@@ -204,9 +204,6 @@
   // Support for walking class loader data objects
   ClassLoaderData* _next; /// Next loader_datas created
 
-  // CDS
-  int _shared_class_loader_id;
-
   // ReadOnly and ReadWrite metaspaces (static because only on the null
   // class loader for now).
   static Metaspace* _ro_metaspace;
@@ -338,15 +335,6 @@
   Metaspace* rw_metaspace();
   void initialize_shared_metaspaces();
 
-  int shared_class_loader_id() const {
-    return _shared_class_loader_id;
-  }
-  void set_shared_class_loader_id(int id) {
-    assert(id >= 0, "sanity");
-    assert(_shared_class_loader_id <0, "cannot be assigned more than once");
-    _shared_class_loader_id = id;
-  }
-
   TRACE_DEFINE_TRACE_ID_METHODS;
 };
 
--- a/src/share/vm/classfile/javaClasses.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/classfile/javaClasses.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -163,8 +163,8 @@
 
   Klass* k = SystemDictionary::String_klass();
   compute_offset(value_offset,           k, vmSymbols::value_name(),  vmSymbols::byte_array_signature());
-  compute_optional_offset(hash_offset,   k, vmSymbols::hash_name(),   vmSymbols::int_signature());
-  compute_optional_offset(coder_offset,  k, vmSymbols::coder_name(),  vmSymbols::byte_signature());
+  compute_offset(hash_offset,            k, vmSymbols::hash_name(),   vmSymbols::int_signature());
+  compute_offset(coder_offset,           k, vmSymbols::coder_name(),  vmSymbols::byte_signature());
 
   initialized = true;
 }
@@ -3977,12 +3977,8 @@
   // java.lang.String
 
   CHECK_OFFSET("java/lang/String", java_lang_String, value, "[B");
-  if (java_lang_String::has_hash_field()) {
-    CHECK_OFFSET("java/lang/String", java_lang_String, hash, "I");
-  }
-  if (java_lang_String::has_coder_field()) {
-    CHECK_OFFSET("java/lang/String", java_lang_String, coder, "B");
-  }
+  CHECK_OFFSET("java/lang/String", java_lang_String, hash, "I");
+  CHECK_OFFSET("java/lang/String", java_lang_String, coder, "B");
 
   // java.lang.Class
 
--- a/src/share/vm/classfile/javaClasses.hpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/classfile/javaClasses.hpp	Sat Feb 04 03:29:40 2017 +0100
@@ -81,15 +81,6 @@
   static Handle create_from_platform_dependent_str(const char* str, TRAPS);
   static Handle char_converter(Handle java_string, jchar from_char, jchar to_char, TRAPS);
 
-  static bool has_hash_field()  {
-    assert(initialized, "Must be initialized");
-    return (hash_offset > 0);
-  }
-  static bool has_coder_field()  {
-    assert(initialized, "Must be initialized");
-    return (coder_offset > 0);
-  }
-
   static void set_compact_strings(bool value);
 
   static int value_offset_in_bytes()  {
--- a/src/share/vm/classfile/javaClasses.inline.hpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/classfile/javaClasses.inline.hpp	Sat Feb 04 03:29:40 2017 +0100
@@ -30,10 +30,8 @@
 #include "oops/oopsHierarchy.hpp"
 
 void java_lang_String::set_coder(oop string, jbyte coder) {
-  assert(initialized, "Must be initialized");
-  if (coder_offset > 0) {
-    string->byte_field_put(coder_offset, coder);
-  }
+  assert(initialized && (coder_offset > 0), "Must be initialized");
+  string->byte_field_put(coder_offset, coder);
 }
 
 void java_lang_String::set_value_raw(oop string, typeArrayOop buffer) {
@@ -61,15 +59,11 @@
   return java_string->int_field(hash_offset);
 }
 bool java_lang_String::is_latin1(oop java_string) {
-  assert(initialized, "Must be initialized");
+  assert(initialized && (coder_offset > 0), "Must be initialized");
   assert(is_instance(java_string), "must be java_string");
-  if (coder_offset > 0) {
-    jbyte coder = java_string->byte_field(coder_offset);
-    assert(CompactStrings || coder == CODER_UTF16, "Must be UTF16 without CompactStrings");
-    return coder == CODER_LATIN1;
-  } else {
-    return false;
-  }
+  jbyte coder = java_string->byte_field(coder_offset);
+  assert(CompactStrings || coder == CODER_UTF16, "Must be UTF16 without CompactStrings");
+  return coder == CODER_LATIN1;
 }
 int java_lang_String::length(oop java_string) {
   assert(initialized, "Must be initialized");
--- a/src/share/vm/classfile/modules.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/classfile/modules.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+* Copyright (c) 2016, 2017, 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
@@ -39,8 +39,6 @@
 #include "logging/log.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/instanceKlass.hpp"
-#include "oops/objArrayKlass.hpp"
-#include "oops/objArrayOop.inline.hpp"
 #include "runtime/arguments.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/javaCalls.hpp"
@@ -48,17 +46,17 @@
 #include "utilities/stringUtils.hpp"
 #include "utilities/utf8.hpp"
 
-static bool verify_module_name(char *module_name) {
+static bool verify_module_name(const char *module_name) {
   if (module_name == NULL) return false;
   int len = (int)strlen(module_name);
   return (len > 0 && len <= Symbol::max_length());
 }
 
-bool Modules::verify_package_name(char *package_name) {
+bool Modules::verify_package_name(const char* package_name) {
   if (package_name == NULL) return false;
   int len = (int)strlen(package_name);
   return (len > 0 && len <= Symbol::max_length() &&
-    UTF8::is_legal_utf8((unsigned char *)package_name, len, false) &&
+    UTF8::is_legal_utf8((const unsigned char *)package_name, len, false) &&
     ClassFileParser::verify_unqualified_name(package_name, len,
     ClassFileParser::LegalClass));
 }
@@ -107,10 +105,8 @@
   return java_lang_reflect_Module::module_entry(module_h(), CHECK_NULL);
 }
 
-static PackageEntry* get_package_entry(ModuleEntry* module_entry, jstring package, TRAPS) {
+static PackageEntry* get_package_entry(ModuleEntry* module_entry, const char* package_name, TRAPS) {
   ResourceMark rm(THREAD);
-  if (package == NULL) return NULL;
-  const char *package_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package));
   if (package_name == NULL) return NULL;
   TempNewSymbol pkg_symbol = SymbolTable::new_symbol(package_name, CHECK_NULL);
   PackageEntryTable* package_entry_table = module_entry->loader_data()->packages();
@@ -139,7 +135,8 @@
 }
 
 static void define_javabase_module(jobject module, jstring version,
-                                   jstring location, jobjectArray packages, TRAPS) {
+                                   jstring location, const char* const* packages,
+                                   jsize num_packages, TRAPS) {
   ResourceMark rm(THREAD);
 
   Handle module_handle(THREAD, JNIHandles::resolve(module));
@@ -164,21 +161,12 @@
     }
   }
 
-  objArrayOop packages_oop = objArrayOop(JNIHandles::resolve(packages));
-  objArrayHandle packages_h(THREAD, packages_oop);
-  int num_packages = (packages_h == NULL ? 0 : packages_h->length());
 
   // Check that the list of packages has no duplicates and that the
   // packages are syntactically ok.
   GrowableArray<Symbol*>* pkg_list = new GrowableArray<Symbol*>(num_packages);
   for (int x = 0; x < num_packages; x++) {
-    oop string_obj = packages_h->obj_at(x);
-
-    if (string_obj == NULL || !string_obj->is_a(SystemDictionary::String_klass())) {
-      THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
-                "Bad package name for module: " JAVA_BASE_NAME);
-    }
-    char *package_name = java_lang_String::as_utf8_string(string_obj);
+    const char *package_name = packages[x];
     if (!Modules::verify_package_name(package_name)) {
       THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
                 err_msg("Invalid package name: %s for module: " JAVA_BASE_NAME, package_name));
@@ -239,7 +227,7 @@
     }
   }
   if (duplicate_javabase) {
-    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+    THROW_MSG(vmSymbols::java_lang_InternalError(),
               "Module " JAVA_BASE_NAME " is already defined");
   }
 
@@ -262,13 +250,39 @@
   }
 }
 
+// Caller needs ResourceMark.
+void throw_dup_pkg_exception(const char* module_name, PackageEntry* package, TRAPS) {
+  const char* package_name = package->name()->as_C_string();
+  if (package->module()->is_named()) {
+    THROW_MSG(vmSymbols::java_lang_IllegalStateException(),
+      err_msg("Package %s for module %s is already in another module, %s, defined to the class loader",
+              package_name, module_name, package->module()->name()->as_C_string()));
+  } else {
+    THROW_MSG(vmSymbols::java_lang_IllegalStateException(),
+      err_msg("Package %s for module %s is already in the unnamed module defined to the class loader",
+              package_name, module_name));
+  }
+}
+
 void Modules::define_module(jobject module, jstring version,
-                            jstring location, jobjectArray packages, TRAPS) {
+                            jstring location, const char* const* packages,
+                            jsize num_packages, TRAPS) {
   ResourceMark rm(THREAD);
 
   if (module == NULL) {
     THROW_MSG(vmSymbols::java_lang_NullPointerException(), "Null module object");
   }
+
+  if (num_packages < 0) {
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              "num_packages must be >= 0");
+  }
+
+  if (packages == NULL && num_packages > 0) {
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              "num_packages should be zero if packages is null");
+  }
+
   Handle module_handle(THREAD, JNIHandles::resolve(module));
   if (!java_lang_reflect_Module::is_instance(module_handle())) {
     THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
@@ -283,7 +297,7 @@
 
   // Special handling of java.base definition
   if (strcmp(module_name, JAVA_BASE_NAME) == 0) {
-    define_javabase_module(module, version, location, packages, CHECK);
+    define_javabase_module(module, version, location, packages, num_packages, CHECK);
     return;
   }
 
@@ -297,21 +311,11 @@
   }
   Handle h_loader = Handle(THREAD, loader);
 
-  objArrayOop packages_oop = objArrayOop(JNIHandles::resolve(packages));
-  objArrayHandle packages_h(THREAD, packages_oop);
-  int num_packages = (packages_h == NULL ? 0 : packages_h->length());
-
   // Check that the list of packages has no duplicates and that the
   // packages are syntactically ok.
   GrowableArray<Symbol*>* pkg_list = new GrowableArray<Symbol*>(num_packages);
   for (int x = 0; x < num_packages; x++) {
-    oop string_obj = packages_h->obj_at(x);
-
-    if (string_obj == NULL || !string_obj->is_a(SystemDictionary::String_klass())) {
-      THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
-                err_msg("Bad package name for module: %s", module_name));
-    }
-    char *package_name = java_lang_String::as_utf8_string(string_obj);
+    const char* package_name = packages[x];
     if (!verify_package_name(package_name)) {
       THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
                 err_msg("Invalid package name: %s for module: %s",
@@ -323,12 +327,15 @@
         !SystemDictionary::is_platform_class_loader(h_loader) &&
         strncmp(package_name, JAVAPKG, JAVAPKG_LEN) == 0) {
       const char* class_loader_name = SystemDictionary::loader_name(h_loader());
-      StringUtils::replace_no_expand(package_name, "/", ".");
+      size_t pkg_len = strlen(package_name);
+      char* pkg_name = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, pkg_len);
+      strncpy(pkg_name, package_name, pkg_len);
+      StringUtils::replace_no_expand(pkg_name, "/", ".");
       const char* msg_text1 = "Class loader (instance of): ";
       const char* msg_text2 = " tried to define prohibited package name: ";
-      size_t len = strlen(msg_text1) + strlen(class_loader_name) + strlen(msg_text2) + strlen(package_name) + 1;
+      size_t len = strlen(msg_text1) + strlen(class_loader_name) + strlen(msg_text2) + pkg_len + 1;
       char* message = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, len);
-      jio_snprintf(message, len, "%s%s%s%s", msg_text1, class_loader_name, msg_text2, package_name);
+      jio_snprintf(message, len, "%s%s%s%s", msg_text1, class_loader_name, msg_text2, pkg_name);
       THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), message);
     }
 
@@ -347,7 +354,6 @@
   // Create symbol* entry for module name.
   TempNewSymbol module_symbol = SymbolTable::new_symbol(module_name, CHECK);
 
-  int dupl_pkg_index = -1;
   bool dupl_modules = false;
 
   // Create symbol* entry for module version.
@@ -373,6 +379,7 @@
   assert(loader_data != NULL, "class loader data shouldn't be null");
 
   PackageEntryTable* package_table = NULL;
+  PackageEntry* existing_pkg = NULL;
   {
     MutexLocker ml(Module_lock, THREAD);
 
@@ -382,13 +389,12 @@
 
       // Check that none of the packages exist in the class loader's package table.
       for (int x = 0; x < pkg_list->length(); x++) {
-        if (package_table->lookup_only(pkg_list->at(x)) != NULL) {
+        existing_pkg = package_table->lookup_only(pkg_list->at(x));
+        if (existing_pkg != NULL) {
           // This could be because the module was already defined.  If so,
           // report that error instead of the package error.
           if (module_table->lookup_only(module_symbol) != NULL) {
             dupl_modules = true;
-          } else {
-            dupl_pkg_index = x;
           }
           break;
         }
@@ -396,9 +402,8 @@
     }  // if (num_packages > 0)...
 
     // Add the module and its packages.
-    if (!dupl_modules && dupl_pkg_index == -1) {
+    if (!dupl_modules && existing_pkg == NULL) {
       // Create the entry for this module in the class loader's module entry table.
-
       ModuleEntry* module_entry = module_table->locked_create_entry_or_null(module_handle, module_symbol,
                                     version_symbol, location_symbol, loader_data);
 
@@ -426,13 +431,10 @@
 
   // any errors ?
   if (dupl_modules) {
-     THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+     THROW_MSG(vmSymbols::java_lang_IllegalStateException(),
                err_msg("Module %s is already defined", module_name));
-  }
-  if (dupl_pkg_index != -1) {
-    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
-              err_msg("Package %s for module %s already exists for class loader",
-                      pkg_list->at(dupl_pkg_index)->as_C_string(), module_name));
+  } else if (existing_pkg != NULL) {
+      throw_dup_pkg_exception(module_name, existing_pkg, CHECK);
   }
 
   if (log_is_enabled(Debug, modules)) {
@@ -497,8 +499,8 @@
   java_lang_reflect_Module::set_module_entry(module_handle(), unnamed_module);
 }
 
-void Modules::add_module_exports(jobject from_module, jstring package, jobject to_module, TRAPS) {
-  if (package == NULL) {
+void Modules::add_module_exports(jobject from_module, const char* package_name, jobject to_module, TRAPS) {
+  if (package_name == NULL) {
     THROW_MSG(vmSymbols::java_lang_NullPointerException(),
               "package is null");
   }
@@ -526,10 +528,9 @@
     }
   }
 
-  PackageEntry *package_entry = get_package_entry(from_module_entry, package, CHECK);
+  PackageEntry *package_entry = get_package_entry(from_module_entry, package_name, CHECK);
   ResourceMark rm(THREAD);
   if (package_entry == NULL) {
-    const char *package_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package));
     THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
               err_msg("Package %s not found in from_module %s",
                       package_name != NULL ? package_name : "",
@@ -557,7 +558,7 @@
 }
 
 
-void Modules::add_module_exports_qualified(jobject from_module, jstring package,
+void Modules::add_module_exports_qualified(jobject from_module, const char* package,
                                            jobject to_module, TRAPS) {
   if (to_module == NULL) {
     THROW_MSG(vmSymbols::java_lang_NullPointerException(),
@@ -649,21 +650,15 @@
 }
 
 
-jobject Modules::get_module_by_package_name(jobject loader, jstring package, TRAPS) {
+jobject Modules::get_module_by_package_name(jobject loader, const char* package_name, TRAPS) {
   ResourceMark rm(THREAD);
   assert(ModuleEntryTable::javabase_defined(),
          "Attempt to call get_module_from_pkg before " JAVA_BASE_NAME " is defined");
 
-  if (NULL == package) {
+  if (package_name == NULL) {
     THROW_MSG_(vmSymbols::java_lang_NullPointerException(),
                "package is null", JNI_FALSE);
   }
-  const char* package_str =
-    java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package));
-  if (NULL == package_str) {
-    THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
-               "Invalid package", JNI_FALSE);
-  }
 
   Handle h_loader (THREAD, JNIHandles::resolve(loader));
   // Check that loader is a subclass of java.lang.ClassLoader.
@@ -672,7 +667,7 @@
                "Class loader is not a subclass of java.lang.ClassLoader", JNI_FALSE);
   }
 
-  if (strlen(package_str) == 0) {
+  if (strlen(package_name) == 0) {
     // Return the unnamed module
     ModuleEntryTable* module_table = get_module_entry_table(h_loader, CHECK_NULL);
     if (NULL == module_table) return NULL;
@@ -680,24 +675,24 @@
     return JNIHandles::make_local(THREAD, JNIHandles::resolve(unnamed_module->module()));
 
   } else {
-    TempNewSymbol package_sym = SymbolTable::new_symbol(package_str, CHECK_NULL);
+    TempNewSymbol package_sym = SymbolTable::new_symbol(package_name, CHECK_NULL);
     return get_module(package_sym, h_loader, CHECK_NULL);
   }
   return NULL;
 }
 
 
-jobject Modules::get_named_module(Handle h_loader, const char* package_str, TRAPS) {
+jobject Modules::get_named_module(Handle h_loader, const char* package_name, TRAPS) {
   assert(ModuleEntryTable::javabase_defined(),
          "Attempt to call get_named_module before " JAVA_BASE_NAME " is defined");
   assert(h_loader.is_null() || java_lang_ClassLoader::is_subclass(h_loader->klass()),
          "Class loader is not a subclass of java.lang.ClassLoader");
-  assert(package_str != NULL, "the package_str should not be NULL");
+  assert(package_name != NULL, "the package_name should not be NULL");
 
-  if (strlen(package_str) == 0) {
+  if (strlen(package_name) == 0) {
     return NULL;
   }
-  TempNewSymbol package_sym = SymbolTable::new_symbol(package_str, CHECK_NULL);
+  TempNewSymbol package_sym = SymbolTable::new_symbol(package_name, CHECK_NULL);
   const PackageEntry* const pkg_entry =
     get_package_entry_by_name(package_sym, h_loader, THREAD);
   const ModuleEntry* const module_entry = (pkg_entry != NULL ? pkg_entry->module() : NULL);
@@ -723,14 +718,14 @@
   return NULL;
 }
 
-void Modules::add_module_package(jobject module, jstring package, TRAPS) {
+void Modules::add_module_package(jobject module, const char* package_name, TRAPS) {
   ResourceMark rm(THREAD);
 
   if (module == NULL) {
     THROW_MSG(vmSymbols::java_lang_NullPointerException(),
               "module is null");
   }
-  if (package == NULL) {
+  if (package_name == NULL) {
     THROW_MSG(vmSymbols::java_lang_NullPointerException(),
               "package is null");
   }
@@ -743,11 +738,6 @@
     THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
               "module cannot be an unnamed module");
   }
-  char *package_name = java_lang_String::as_utf8_string(
-    JNIHandles::resolve_non_null(package));
-  if (package_name == NULL) {
-    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "Bad package");
-  }
   if (!verify_package_name(package_name)) {
     THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
               err_msg("Invalid package name: %s", package_name));
@@ -760,12 +750,15 @@
       !loader_data->is_platform_class_loader_data() &&
       strncmp(package_name, JAVAPKG, JAVAPKG_LEN) == 0) {
     const char* class_loader_name = SystemDictionary::loader_name(loader_data);
-    StringUtils::replace_no_expand(package_name, "/", ".");
+    size_t pkg_len = strlen(package_name);
+    char* pkg_name = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, pkg_len);
+    strncpy(pkg_name, package_name, pkg_len);
+    StringUtils::replace_no_expand(pkg_name, "/", ".");
     const char* msg_text1 = "Class loader (instance of): ";
     const char* msg_text2 = " tried to define prohibited package name: ";
-    size_t len = strlen(msg_text1) + strlen(class_loader_name) + strlen(msg_text2) + strlen(package_name) + 1;
+    size_t len = strlen(msg_text1) + strlen(class_loader_name) + strlen(msg_text2) + pkg_len + 1;
     char* message = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, len);
-    jio_snprintf(message, len, "%s%s%s%s", msg_text1, class_loader_name, msg_text2, package_name);
+    jio_snprintf(message, len, "%s%s%s%s", msg_text1, class_loader_name, msg_text2, pkg_name);
     THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), message);
   }
 
@@ -776,31 +769,29 @@
   PackageEntryTable* package_table = loader_data->packages();
   assert(package_table != NULL, "Missing package_table");
 
-  bool pkg_exists = false;
+  PackageEntry* existing_pkg = NULL;
   {
     MutexLocker ml(Module_lock, THREAD);
 
     // Check that the package does not exist in the class loader's package table.
-    if (!package_table->lookup_only(pkg_symbol)) {
+    existing_pkg = package_table->lookup_only(pkg_symbol);
+    if (existing_pkg == NULL) {
       PackageEntry* pkg = package_table->locked_create_entry_or_null(pkg_symbol, module_entry);
       assert(pkg != NULL, "Unable to create a module's package entry");
-    } else {
-      pkg_exists = true;
     }
   }
-  if (pkg_exists) {
-    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
-              err_msg("Package %s already exists for class loader", package_name));
+  if (existing_pkg != NULL) {
+    throw_dup_pkg_exception(module_entry->name()->as_C_string(), existing_pkg, CHECK);
   }
 }
 
 // Export package in module to all unnamed modules.
-void Modules::add_module_exports_to_all_unnamed(jobject module, jstring package, TRAPS) {
+void Modules::add_module_exports_to_all_unnamed(jobject module, const char* package_name, TRAPS) {
   if (module == NULL) {
     THROW_MSG(vmSymbols::java_lang_NullPointerException(),
               "module is null");
   }
-  if (package == NULL) {
+  if (package_name == NULL) {
     THROW_MSG(vmSymbols::java_lang_NullPointerException(),
               "package is null");
   }
@@ -811,10 +802,9 @@
   }
 
   if (module_entry->is_named()) { // No-op for unnamed module.
-    PackageEntry *package_entry = get_package_entry(module_entry, package, CHECK);
+    PackageEntry *package_entry = get_package_entry(module_entry, package_name, CHECK);
     ResourceMark rm(THREAD);
     if (package_entry == NULL) {
-      const char *package_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package));
       THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
                 err_msg("Package %s not found in module %s",
                         package_name != NULL ? package_name : "",
@@ -833,10 +823,7 @@
                        package_entry->name()->as_C_string(),
                        module_entry->name()->as_C_string());
 
-    // Mark package as exported to all unnamed modules, unless already
-    // unqualifiedly exported.
-    if (!package_entry->is_unqual_exported()) {
-      package_entry->set_is_exported_allUnnamed();
-    }
+    // Mark package as exported to all unnamed modules.
+    package_entry->set_is_exported_allUnnamed();
   }
 }
--- a/src/share/vm/classfile/modules.hpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/classfile/modules.hpp	Sat Feb 04 03:29:40 2017 +0100
@@ -48,9 +48,12 @@
   // * Packages contains a duplicate package name
   // * A package already exists in another module for this class loader
   // * Module is an unnamed module
+  // * num_packages is negative
+  // * num_packages is non-zero when packages is null
   //  NullPointerExceptions are thrown if module is null.
   static void define_module(jobject module, jstring version,
-                            jstring location, jobjectArray packages, TRAPS);
+                            jstring location, const char* const* packages,
+                            jsize num_packages, TRAPS);
 
   // Provides the java.lang.reflect.Module for the unnamed module defined
   // to the boot loader.
@@ -72,7 +75,7 @@
   // * Package is not syntactically correct
   // * Package is not defined for from_module's class loader
   // * Package is not in module from_module.
-  static void add_module_exports(jobject from_module, jstring package, jobject to_module, TRAPS);
+  static void add_module_exports(jobject from_module, const char* package, jobject to_module, TRAPS);
 
   // This does a qualified export of package in module from_module to module
   // to_module.  The format for the package name must use "/' not ".".
@@ -83,7 +86,7 @@
   // * Package is not syntactically correct
   // * Package is not defined for from_module's class loader
   // * Package is not in module from_module.
-  static void add_module_exports_qualified(jobject from_module, jstring package, jobject to_module, TRAPS);
+  static void add_module_exports_qualified(jobject from_module, const char* package, jobject to_module, TRAPS);
 
   // add_reads_module adds module to_module to the list of modules that from_module
   // can read.  If from_module is the same as to_module then this is a no-op.
@@ -102,7 +105,7 @@
   // NullPointerException is thrown if package is null.
   // IllegalArgumentException is thrown if loader is neither null nor a subtype of
   // java/lang/ClassLoader.
-  static jobject get_module_by_package_name(jobject loader, jstring package, TRAPS);
+  static jobject get_module_by_package_name(jobject loader, const char* package, TRAPS);
   static jobject get_named_module(Handle h_loader, const char* package, TRAPS);
 
   // If package is defined by loader, return the
@@ -116,16 +119,16 @@
   // * Module is unnamed
   // * Package is not syntactically correct
   // * Package is already defined for module's class loader.
-  static void add_module_package(jobject module, jstring package, TRAPS);
+  static void add_module_package(jobject module, const char* package, TRAPS);
 
   // Marks the specified package as exported to all unnamed modules.
   // If either module or package is null then NullPointerException is thrown.
   // If module or package is bad, or module is unnamed, or package is not in
   // module then IllegalArgumentException is thrown.
-  static void add_module_exports_to_all_unnamed(jobject module, jstring package, TRAPS);
+  static void add_module_exports_to_all_unnamed(jobject module, const char* package, TRAPS);
 
   // Return TRUE if package_name is syntactically valid, false otherwise.
-  static bool verify_package_name(char *package_name);
+  static bool verify_package_name(const char *package_name);
 
   // Return TRUE iff package is defined by loader
   static bool is_package_defined(Symbol* package_name, Handle h_loader, TRAPS);
--- a/src/share/vm/classfile/packageEntry.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/classfile/packageEntry.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, 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
@@ -37,8 +37,8 @@
 
 // Returns true if this package specifies m as a qualified export, including through an unnamed export
 bool PackageEntry::is_qexported_to(ModuleEntry* m) const {
+  assert(Module_lock->owned_by_self(), "should have the Module_lock");
   assert(m != NULL, "No module to lookup in this package's qualified exports list");
-  MutexLocker m1(Module_lock);
   if (is_exported_allUnnamed() && !m->is_named()) {
     return true;
   } else if (!has_qual_exports_list()) {
@@ -98,15 +98,8 @@
   }
 
   if (m == NULL) {
-    // NULL indicates the package is being unqualifiedly exported
-    if (has_qual_exports_list()) {
-      // Legit to transition a package from being qualifiedly exported
-      // to unqualified.  Clean up the qualified lists at the next
-      // safepoint.
-      _exported_pending_delete = _qualified_exports;
-    }
-
-    // Mark package as unqualifiedly exported
+    // NULL indicates the package is being unqualifiedly exported.  Clean up
+    // the qualified list at the next safepoint.
     set_unqual_exported();
 
   } else {
@@ -115,14 +108,19 @@
   }
 }
 
+// Set the package as exported to all unnamed modules unless the package is
+// already unqualifiedly exported.
 void PackageEntry::set_is_exported_allUnnamed() {
   MutexLocker m1(Module_lock);
   if (!is_unqual_exported()) {
-   _is_exported_allUnnamed = true;
+   _export_flags = PKG_EXP_ALLUNNAMED;
   }
 }
 
-// Remove dead module entries within the package's exported list.
+// Remove dead module entries within the package's exported list.  Note that
+// if all of the modules on the _qualified_exports get purged the list does not
+// get deleted.  This prevents the package from illegally transitioning from
+// exported to non-exported.
 void PackageEntry::purge_qualified_exports() {
   assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
   if (_must_walk_exports &&
@@ -160,18 +158,9 @@
 
 void PackageEntry::delete_qualified_exports() {
   assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
-  if (_exported_pending_delete != NULL) {
-    // If a transition occurred from qualified to unqualified, the _qualified_exports
-    // field should have been NULL'ed out.
-    assert(_qualified_exports == NULL, "Package's exported pending delete, exported list should not be active");
-    delete _exported_pending_delete;
-  }
-
   if (_qualified_exports != NULL) {
     delete _qualified_exports;
   }
-
-  _exported_pending_delete = NULL;
   _qualified_exports = NULL;
 }
 
@@ -314,6 +303,11 @@
   }
 }
 
+bool PackageEntry::exported_pending_delete() const {
+  assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
+  return (is_unqual_exported() && _qualified_exports != NULL);
+}
+
 // Remove dead entries from all packages' exported list
 void PackageEntryTable::purge_all_package_exports() {
   assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
@@ -344,13 +338,17 @@
   }
 }
 
+// This function may be called from debuggers so access private fields directly
+// to prevent triggering locking-related asserts that could result from calling
+// getter methods.
 void PackageEntry::print(outputStream* st) {
   ResourceMark rm;
   st->print_cr("package entry " PTR_FORMAT " name %s module %s classpath_index "
                INT32_FORMAT " is_exported_unqualified %d is_exported_allUnnamed %d " "next " PTR_FORMAT,
                p2i(this), name()->as_C_string(),
                (module()->is_named() ? module()->name()->as_C_string() : UNNAMED_MODULE),
-               _classpath_index, _is_exported_unqualified, _is_exported_allUnnamed, p2i(next()));
+               _classpath_index, _export_flags == PKG_EXP_UNQUALIFIED,
+               _export_flags == PKG_EXP_ALLUNNAMED, p2i(next()));
 }
 
 void PackageEntryTable::verify() {
--- a/src/share/vm/classfile/packageEntry.hpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/classfile/packageEntry.hpp	Sat Feb 04 03:29:40 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,8 +34,8 @@
 // A PackageEntry basically represents a Java package.  It contains:
 //   - Symbol* containing the package's name.
 //   - ModuleEntry* for this package's containing module.
-//   - a flag indicating if package is exported unqualifiedly
-//   - a flag indicating if this package is exported to all unnamed modules.
+//   - a field indicating if the package is exported unqualifiedly or to all
+//     unnamed modules.
 //   - a growable array containing other module entries that this
 //     package is exported to.
 //
@@ -44,9 +44,9 @@
 //   - qualified exports:   the package has been explicitly qualified to at least
 //                            one particular module or has been qualifiedly exported
 //                            to all unnamed modules.
-//                            Note: _is_exported_allUnnamed is a form of a qualified
-//                            export. It is equivalent to the package being
-//                            explicitly exported to all current and future unnamed modules.
+//                            Note: being exported to all unnamed is a form of a qualified
+//                            export. It is equivalent to the package being explicitly
+//                            exported to all current and future unnamed modules.
 //   - unqualified exports: the package is exported to all modules.
 //
 // A package can transition from:
@@ -56,21 +56,53 @@
 // A package cannot transition from:
 //   - being unqualifiedly exported, to exported qualifiedly to a specific module.
 //       This transition attempt is silently ignored in set_exported.
+//   - being qualifiedly exported to not exported.
+//       Because transitions are only allowed from less exposure to greater exposure,
+//       the transition from qualifiedly exported to not exported would be considered
+//       a backward direction.  Therefore the implementation considers a package as
+//       qualifiedly exported even if its export-list exists but is empty.
 //
 // The Mutex Module_lock is shared between ModuleEntry and PackageEntry, to lock either
 // data structure.
+
+// PKG_EXP_UNQUALIFIED and PKG_EXP_ALLUNNAMED indicate whether the package is
+// exported unqualifiedly or exported to all unnamed modules.  They are used to
+// set the value of _export_flags.  Field _export_flags and the _qualified_exports
+// list are used to determine a package's export state.
+// Valid states are:
+//
+//   1. Package is not exported
+//      _export_flags is zero and _qualified_exports is null
+//   2. Package is unqualifiedly exported
+//      _export_flags is set to PKG_EXP_UNQUALIFIED
+//      _qualified_exports may or may not be null depending on whether the package
+//        transitioned from qualifiedly exported to unqualifiedly exported.
+//   3. Package is qualifiedly exported
+//      _export_flags may be set to PKG_EXP_ALLUNNAMED if the package is also
+//        exported to all unnamed modules
+//      _qualified_exports will be non-null
+//   4. Package is exported to all unnamed modules
+//      _export_flags is set to PKG_EXP_ALLUNNAMED
+//      _qualified_exports may or may not be null depending on whether the package
+//        is also qualifiedly exported to one or more named modules.
+#define PKG_EXP_UNQUALIFIED  0x0001
+#define PKG_EXP_ALLUNNAMED   0x0002
+#define PKG_EXP_UNQUALIFIED_OR_ALL_UNAMED (PKG_EXP_UNQUALIFIED | PKG_EXP_ALLUNNAMED)
+
 class PackageEntry : public HashtableEntry<Symbol*, mtModule> {
 private:
   ModuleEntry* _module;
+  // Indicates if package is exported unqualifiedly or to all unnamed. Access to
+  // this field is protected by the Module_lock.
+  int _export_flags;
   // Used to indicate for packages with classes loaded by the boot loader that
   // a class in that package has been loaded.  And, for packages with classes
   // loaded by the boot loader from -Xbootclasspath/a in an unnamed module, it
   // indicates from which class path entry.
   s2 _classpath_index;
-  bool _is_exported_unqualified;
-  bool _is_exported_allUnnamed;
   bool _must_walk_exports;
-  GrowableArray<ModuleEntry*>* _exported_pending_delete; // transitioned from qualified to unqualified, delete at safepoint
+  // Contains list of modules this package is qualifiedly exported to.  Access
+  // to this list is protected by the Module_lock.
   GrowableArray<ModuleEntry*>* _qualified_exports;
   TRACE_DEFINE_TRACE_ID_FIELD;
 
@@ -80,17 +112,14 @@
 public:
   void init() {
     _module = NULL;
+    _export_flags = 0;
     _classpath_index = -1;
-    _is_exported_unqualified = false;
-    _is_exported_allUnnamed = false;
     _must_walk_exports = false;
-    _exported_pending_delete = NULL;
     _qualified_exports = NULL;
   }
 
   // package name
   Symbol*            name() const               { return literal(); }
-  void               set_name(Symbol* n)        { set_literal(n); }
 
   // the module containing the package definition
   ModuleEntry*       module() const             { return _module; }
@@ -98,37 +127,39 @@
 
   // package's export state
   bool is_exported() const { // qualifiedly or unqualifiedly exported
-      return (is_unqual_exported() || has_qual_exports_list() || is_exported_allUnnamed());
+    assert_locked_or_safepoint(Module_lock);
+    return ((_export_flags & PKG_EXP_UNQUALIFIED_OR_ALL_UNAMED) != 0) || has_qual_exports_list();
   }
   // Returns true if the package has any explicit qualified exports or is exported to all unnamed
   bool is_qual_exported() const {
+    assert_locked_or_safepoint(Module_lock);
     return (has_qual_exports_list() || is_exported_allUnnamed());
   }
-  // Returns true if there are any explicit qualified exports
+  // Returns true if there are any explicit qualified exports.  Note that even
+  // if the _qualified_exports list is now empty (because the modules that were
+  // on the list got gc-ed and deleted from the list) this method may still
+  // return true.
   bool has_qual_exports_list() const {
-    assert(!(_qualified_exports != NULL && _is_exported_unqualified),
-           "_qualified_exports set at same time as _is_exported_unqualified");
-    return (_qualified_exports != NULL);
+    assert_locked_or_safepoint(Module_lock);
+    return (!is_unqual_exported() && _qualified_exports != NULL);
   }
   bool is_exported_allUnnamed() const {
-    assert(!(_is_exported_allUnnamed && _is_exported_unqualified),
-           "_is_exported_allUnnamed set at same time as _is_exported_unqualified");
-    return _is_exported_allUnnamed;
+    assert_locked_or_safepoint(Module_lock);
+    return (_export_flags == PKG_EXP_ALLUNNAMED);
   }
   bool is_unqual_exported() const {
-    assert(!(_qualified_exports != NULL && _is_exported_unqualified),
-           "_qualified_exports set at same time as _is_exported_unqualified");
-    assert(!(_is_exported_allUnnamed && _is_exported_unqualified),
-           "_is_exported_allUnnamed set at same time as _is_exported_unqualified");
-    return _is_exported_unqualified;
+    assert_locked_or_safepoint(Module_lock);
+    return (_export_flags == PKG_EXP_UNQUALIFIED);
   }
+
+  // Explicitly set _export_flags to PKG_EXP_UNQUALIFIED and clear
+  // PKG_EXP_ALLUNNAMED, if it was set.
   void set_unqual_exported() {
     assert(Module_lock->owned_by_self(), "should have the Module_lock");
-    _is_exported_unqualified = true;
-    _is_exported_allUnnamed = false;
-    _qualified_exports = NULL;
+    _export_flags = PKG_EXP_UNQUALIFIED;
   }
-  bool exported_pending_delete() const     { return (_exported_pending_delete != NULL); }
+
+  bool exported_pending_delete() const;
 
   void set_exported(ModuleEntry* m);
 
--- a/src/share/vm/classfile/systemDictionaryShared.hpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/classfile/systemDictionaryShared.hpp	Sat Feb 04 03:29:40 2017 +0100
@@ -29,7 +29,6 @@
 #include "classfile/dictionary.hpp"
 
 class ClassFileStream;
-class SerializeClosure;
 
 class SystemDictionaryShared: public SystemDictionary {
 public:
@@ -79,8 +78,6 @@
     return NULL;
   }
 
-  static void serialize(SerializeClosure* soc) {}
-
   // The (non-application) CDS implementation supports only classes in the boot
   // class loader, which ensures that the verification constraints are the same
   // during archive creation time and runtime. Thus we can do the constraint checks
--- a/src/share/vm/code/codeCache.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/code/codeCache.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -149,16 +149,17 @@
   size_t total_size = non_nmethod_size + profiled_size + non_profiled_size;
   // Prepare error message
   const char* error = "Invalid code heap sizes";
-  err_msg message("NonNMethodCodeHeapSize (%zuK) + ProfiledCodeHeapSize (%zuK) + NonProfiledCodeHeapSize (%zuK) = %zuK",
+  err_msg message("NonNMethodCodeHeapSize (" SIZE_FORMAT "K) + ProfiledCodeHeapSize (" SIZE_FORMAT "K)"
+                  " + NonProfiledCodeHeapSize (" SIZE_FORMAT "K) = " SIZE_FORMAT "K",
           non_nmethod_size/K, profiled_size/K, non_profiled_size/K, total_size/K);
 
   if (total_size > cache_size) {
     // Some code heap sizes were explicitly set: total_size must be <= cache_size
-    message.append(" is greater than ReservedCodeCacheSize (%zuK).", cache_size/K);
+    message.append(" is greater than ReservedCodeCacheSize (" SIZE_FORMAT "K).", cache_size/K);
     vm_exit_during_initialization(error, message);
   } else if (all_set && total_size != cache_size) {
     // All code heap sizes were explicitly set: total_size must equal cache_size
-    message.append(" is not equal to ReservedCodeCacheSize (%zuK).", cache_size/K);
+    message.append(" is not equal to ReservedCodeCacheSize (" SIZE_FORMAT "K).", cache_size/K);
     vm_exit_during_initialization(error, message);
   }
 }
@@ -267,7 +268,7 @@
   uint min_code_cache_size = CodeCacheMinimumUseSpace DEBUG_ONLY(* 3);
   if (non_nmethod_size < (min_code_cache_size + code_buffers_size)) {
     vm_exit_during_initialization(err_msg(
-        "Not enough space in non-nmethod code heap to run VM: %zuK < %zuK",
+        "Not enough space in non-nmethod code heap to run VM: " SIZE_FORMAT "K < " SIZE_FORMAT "K",
         non_nmethod_size/K, (min_code_cache_size + code_buffers_size)/K));
   }
 
--- a/src/share/vm/code/compiledMethod.hpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/code/compiledMethod.hpp	Sat Feb 04 03:29:40 2017 +0100
@@ -250,7 +250,11 @@
 
   address insts_begin() const { return code_begin(); }
   address insts_end() const { return stub_begin(); }
+  // Returns true if a given address is in the 'insts' section. The method
+  // insts_contains_inclusive() is end-inclusive.
   bool insts_contains(address addr) const { return insts_begin() <= addr && addr < insts_end(); }
+  bool insts_contains_inclusive(address addr) const { return insts_begin() <= addr && addr <= insts_end(); }
+
   int insts_size() const { return insts_end() - insts_begin(); }
 
   virtual address consts_begin() const = 0;
--- a/src/share/vm/compiler/compilerDefinitions.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/compiler/compilerDefinitions.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -23,6 +23,8 @@
  */
 
 #include "precompiled.hpp"
+#include "runtime/globals.hpp"
+#include "runtime/globals_extension.hpp"
 #include "compiler/compilerDefinitions.hpp"
 
 const char* compilertype2name_tab[compiler_number_of_types] = {
@@ -32,3 +34,82 @@
   "jvmci",
   "shark"
 };
+
+#if defined(COMPILER2) || defined(SHARK)
+CompLevel  CompLevel_highest_tier      = CompLevel_full_optimization;  // pure C2 and tiered or JVMCI and tiered
+#elif defined(COMPILER1)
+CompLevel  CompLevel_highest_tier      = CompLevel_simple;             // pure C1 or JVMCI
+#else
+CompLevel  CompLevel_highest_tier      = CompLevel_none;
+#endif
+
+#if defined(TIERED)
+CompLevel  CompLevel_initial_compile   = CompLevel_full_profile;        // tiered
+#elif defined(COMPILER1) || INCLUDE_JVMCI
+CompLevel  CompLevel_initial_compile   = CompLevel_simple;              // pure C1 or JVMCI
+#elif defined(COMPILER2) || defined(SHARK)
+CompLevel  CompLevel_initial_compile   = CompLevel_full_optimization;   // pure C2
+#else
+CompLevel  CompLevel_initial_compile   = CompLevel_none;
+#endif
+
+#if defined(COMPILER2)
+CompMode  Compilation_mode             = CompMode_server;
+#elif defined(COMPILER1)
+CompMode  Compilation_mode             = CompMode_client;
+#else
+CompMode  Compilation_mode             = CompMode_none;
+#endif
+
+#ifdef TIERED
+void set_client_compilation_mode() {
+  Compilation_mode = CompMode_client;
+  CompLevel_highest_tier = CompLevel_simple;
+  CompLevel_initial_compile = CompLevel_simple;
+  FLAG_SET_ERGO(bool, TieredCompilation, false);
+  FLAG_SET_ERGO(bool, ProfileInterpreter, false);
+#if INCLUDE_JVMCI
+  FLAG_SET_ERGO(bool, EnableJVMCI, false);
+  FLAG_SET_ERGO(bool, UseJVMCICompiler, false);
+#endif
+#if INCLUDE_AOT
+  FLAG_SET_ERGO(bool, UseAOT, false);
+#endif
+  if (FLAG_IS_DEFAULT(NeverActAsServerClassMachine)) {
+    FLAG_SET_ERGO(bool, NeverActAsServerClassMachine, true);
+  }
+  if (FLAG_IS_DEFAULT(InitialCodeCacheSize)) {
+    FLAG_SET_ERGO(uintx, InitialCodeCacheSize, 160*K);
+  }
+  if (FLAG_IS_DEFAULT(ReservedCodeCacheSize)) {
+    FLAG_SET_ERGO(uintx, ReservedCodeCacheSize, 32*M);
+  }
+  if (FLAG_IS_DEFAULT(NonProfiledCodeHeapSize)) {
+    FLAG_SET_ERGO(uintx, NonProfiledCodeHeapSize, 27*M);
+  }
+  if (FLAG_IS_DEFAULT(ProfiledCodeHeapSize)) {
+    FLAG_SET_ERGO(uintx, ProfiledCodeHeapSize, 0);
+  }
+  if (FLAG_IS_DEFAULT(NonNMethodCodeHeapSize)) {
+    FLAG_SET_ERGO(uintx, NonNMethodCodeHeapSize, 5*M);
+  }
+  if (FLAG_IS_DEFAULT(CodeCacheExpansionSize)) {
+    FLAG_SET_ERGO(uintx, CodeCacheExpansionSize, 32*K);
+  }
+  if (FLAG_IS_DEFAULT(MetaspaceSize)) {
+    FLAG_SET_ERGO(size_t, MetaspaceSize, 12*M);
+  }
+  if (FLAG_IS_DEFAULT(MaxRAM)) {
+    FLAG_SET_ERGO(uint64_t, MaxRAM, 1ULL*G);
+  }
+  if (FLAG_IS_DEFAULT(CompileThreshold)) {
+    FLAG_SET_ERGO(intx, CompileThreshold, 1500);
+  }
+  if (FLAG_IS_DEFAULT(OnStackReplacePercentage)) {
+    FLAG_SET_ERGO(intx, OnStackReplacePercentage, 933);
+  }
+  if (FLAG_IS_DEFAULT(CICompilerCount)) {
+    FLAG_SET_ERGO(intx, CICompilerCount, 1);
+  }
+}
+#endif // TIERED
--- a/src/share/vm/compiler/compilerDefinitions.hpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/compiler/compilerDefinitions.hpp	Sat Feb 04 03:29:40 2017 +0100
@@ -54,27 +54,30 @@
   CompLevel_simple            = 1,         // C1
   CompLevel_limited_profile   = 2,         // C1, invocation & backedge counters
   CompLevel_full_profile      = 3,         // C1, invocation & backedge counters + mdo
-  CompLevel_full_optimization = 4,         // C2, Shark or JVMCI
+  CompLevel_full_optimization = 4          // C2, Shark or JVMCI
+};
 
-#if defined(COMPILER2) || defined(SHARK)
-  CompLevel_highest_tier      = CompLevel_full_optimization,  // pure C2 and tiered or JVMCI and tiered
-#elif defined(COMPILER1)
-  CompLevel_highest_tier      = CompLevel_simple,             // pure C1 or JVMCI
-#else
-  CompLevel_highest_tier      = CompLevel_none,
-#endif
+extern CompLevel CompLevel_highest_tier;
+extern CompLevel CompLevel_initial_compile;
 
-#if defined(TIERED)
-  CompLevel_initial_compile   = CompLevel_full_profile        // tiered
-#elif defined(COMPILER1) || INCLUDE_JVMCI
-  CompLevel_initial_compile   = CompLevel_simple              // pure C1 or JVMCI
-#elif defined(COMPILER2) || defined(SHARK)
-  CompLevel_initial_compile   = CompLevel_full_optimization   // pure C2
-#else
-  CompLevel_initial_compile   = CompLevel_none
-#endif
+enum CompMode {
+  CompMode_none = 0,
+  CompMode_client = 1,
+  CompMode_server = 2
 };
 
+extern CompMode Compilation_mode;
+
+inline bool is_server_compilation_mode_vm() {
+  return Compilation_mode == CompMode_server;
+}
+
+inline bool is_client_compilation_mode_vm() {
+  return Compilation_mode == CompMode_client;
+}
+
+extern void set_client_compilation_mode();
+
 inline bool is_c1_compile(int comp_level) {
   return comp_level > CompLevel_none && comp_level < CompLevel_full_optimization;
 }
--- a/src/share/vm/compiler/compilerDirectives.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/compiler/compilerDirectives.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -445,7 +445,9 @@
   _default_directives->_c1_store->EnableOption = true;
 #endif
 #ifdef COMPILER2
-  _default_directives->_c2_store->EnableOption = true;
+  if (is_server_compilation_mode_vm()) {
+    _default_directives->_c2_store->EnableOption = true;
+  }
 #endif
   assert(error_msg == NULL, "Must succeed.");
   push(_default_directives);
--- a/src/share/vm/compiler/compilerDirectives.hpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/compiler/compilerDirectives.hpp	Sat Feb 04 03:29:40 2017 +0100
@@ -60,13 +60,12 @@
     cflags(BlockLayoutByFrequency,  bool, BlockLayoutByFrequency,  BlockLayoutByFrequency) \
     cflags(PrintOptoAssembly,       bool, PrintOptoAssembly, PrintOptoAssembly) \
     cflags(PrintIntrinsics,         bool, PrintIntrinsics, PrintIntrinsics) \
-    cflags(TraceOptoPipelining,     bool, false, TraceOptoPipelining) \
-    cflags(TraceOptoOutput,         bool, false, TraceOptoOutput) \
+NOT_PRODUCT(cflags(TraceOptoPipelining, bool, TraceOptoPipelining, TraceOptoPipelining)) \
+NOT_PRODUCT(cflags(TraceOptoOutput,     bool, TraceOptoOutput, TraceOptoOutput)) \
     cflags(TraceSpilling,           bool, TraceSpilling, TraceSpilling) \
     cflags(Vectorize,               bool, false, Vectorize) \
     cflags(VectorizeDebug,         uintx, 0, VectorizeDebug) \
     cflags(CloneMapDebug,           bool, false, CloneMapDebug) \
-    cflags(DoReserveCopyInSuperWordDebug, bool, false, DoReserveCopyInSuperWordDebug) \
     cflags(IGVPrintLevel,           intx, PrintIdealGraphLevel, IGVPrintLevel) \
     cflags(MaxNodeLimit,            intx, MaxNodeLimit, MaxNodeLimit)
 #else
--- a/src/share/vm/gc/g1/g1BiasedArray.hpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/gc/g1/g1BiasedArray.hpp	Sat Feb 04 03:29:40 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, 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
@@ -69,12 +69,12 @@
   void initialize(HeapWord* bottom, HeapWord* end, size_t target_elem_size_in_bytes, size_t mapping_granularity_in_bytes) {
     assert(mapping_granularity_in_bytes > 0, "just checking");
     assert(is_power_of_2(mapping_granularity_in_bytes),
-           "mapping granularity must be power of 2, is %zd", mapping_granularity_in_bytes);
+           "mapping granularity must be power of 2, is " SIZE_FORMAT, mapping_granularity_in_bytes);
     assert((uintptr_t)bottom % mapping_granularity_in_bytes == 0,
-           "bottom mapping area address must be a multiple of mapping granularity %zd, is  " PTR_FORMAT,
+           "bottom mapping area address must be a multiple of mapping granularity " SIZE_FORMAT ", is  " PTR_FORMAT,
            mapping_granularity_in_bytes, p2i(bottom));
     assert((uintptr_t)end % mapping_granularity_in_bytes == 0,
-           "end mapping area address must be a multiple of mapping granularity %zd, is " PTR_FORMAT,
+           "end mapping area address must be a multiple of mapping granularity " SIZE_FORMAT ", is " PTR_FORMAT,
            mapping_granularity_in_bytes, p2i(end));
     size_t num_target_elems = pointer_delta(end, bottom, mapping_granularity_in_bytes);
     idx_t bias = (uintptr_t)bottom / mapping_granularity_in_bytes;
--- a/src/share/vm/gc/shared/collectedHeap.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/gc/shared/collectedHeap.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -233,7 +233,7 @@
   // Used for ReduceInitialCardMarks (when COMPILER2 is used);
   // otherwise remains unused.
 #if defined(COMPILER2) || INCLUDE_JVMCI
-  _defer_initial_card_mark =    ReduceInitialCardMarks && can_elide_tlab_store_barriers()
+  _defer_initial_card_mark = is_server_compilation_mode_vm() &&  ReduceInitialCardMarks && can_elide_tlab_store_barriers()
                              && (DeferInitialCardMark || card_mark_must_follow_store());
 #else
   assert(_defer_initial_card_mark == false, "Who would set it?");
--- a/src/share/vm/gc/shared/genCollectedHeap.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/gc/shared/genCollectedHeap.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -1209,7 +1209,7 @@
 #if defined(COMPILER2) || INCLUDE_JVMCI
   assert(DerivedPointerTable::is_empty(), "derived pointer present");
   size_t actual_gap = pointer_delta((HeapWord*) (max_uintx-3), *(end_addr()));
-  guarantee(actual_gap > (size_t)FastAllocateSizeLimit, "inline allocation wraps");
+  guarantee(is_client_compilation_mode_vm() || actual_gap > (size_t)FastAllocateSizeLimit, "inline allocation wraps");
 #endif /* COMPILER2 || INCLUDE_JVMCI */
 
   resize_all_tlabs();
--- a/src/share/vm/gc/shared/referenceProcessor.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/gc/shared/referenceProcessor.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -57,11 +57,11 @@
   java_lang_ref_SoftReference::set_clock(_soft_ref_timestamp_clock);
 
   _always_clear_soft_ref_policy = new AlwaysClearPolicy();
-#if defined(COMPILER2) || INCLUDE_JVMCI
-  _default_soft_ref_policy      = new LRUMaxHeapPolicy();
-#else
-  _default_soft_ref_policy      = new LRUCurrentHeapPolicy();
-#endif
+  if (is_server_compilation_mode_vm()) {
+    _default_soft_ref_policy = new LRUMaxHeapPolicy();
+  } else {
+    _default_soft_ref_policy = new LRUCurrentHeapPolicy();
+  }
   if (_always_clear_soft_ref_policy == NULL || _default_soft_ref_policy == NULL) {
     vm_exit_during_initialization("Could not allocate reference policy object");
   }
--- a/src/share/vm/gc/shared/threadLocalAllocBuffer.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/gc/shared/threadLocalAllocBuffer.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -233,9 +233,11 @@
   // If the C2 compiler is not present, no space is reserved.
 
   // +1 for rounding up to next cache line, +1 to be safe
-  int lines =  MAX2(AllocatePrefetchLines, AllocateInstancePrefetchLines) + 2;
-  _reserve_for_allocation_prefetch = (AllocatePrefetchDistance + AllocatePrefetchStepSize * lines) /
-                                     (int)HeapWordSize;
+  if (is_server_compilation_mode_vm()) {
+    int lines =  MAX2(AllocatePrefetchLines, AllocateInstancePrefetchLines) + 2;
+    _reserve_for_allocation_prefetch = (AllocatePrefetchDistance + AllocatePrefetchStepSize * lines) /
+                                       (int)HeapWordSize;
+  }
 #endif
 
   // During jvm startup, the main (primordial) thread is initialized
--- a/src/share/vm/interpreter/bytecode.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/interpreter/bytecode.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -112,7 +112,7 @@
 // Implementation of Bytecode_tableupswitch
 
 int Bytecode_tableswitch::dest_offset_at(int i) const {
-  return get_Java_u4_at(aligned_offset(1 + (3 + i)*jintSize));
+  return get_aligned_Java_u4_at(1 + (3 + i)*jintSize);
 }
 
 
--- a/src/share/vm/interpreter/bytecode.hpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/interpreter/bytecode.hpp	Sat Feb 04 03:29:40 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -45,11 +45,11 @@
   address addr_at            (int offset)        const     { return (address)_bcp + offset; }
   u_char byte_at(int offset) const               { return *addr_at(offset); }
   address aligned_addr_at    (int offset)        const     { return (address)round_to((intptr_t)addr_at(offset), jintSize); }
-  int     aligned_offset     (int offset)        const     { return aligned_addr_at(offset) - addr_at(0); }
 
   // Word access:
   int     get_Java_u2_at     (int offset)        const     { return Bytes::get_Java_u2(addr_at(offset)); }
   int     get_Java_u4_at     (int offset)        const     { return Bytes::get_Java_u4(addr_at(offset)); }
+  int     get_aligned_Java_u4_at(int offset)     const     { return Bytes::get_Java_u4(aligned_addr_at(offset)); }
   int     get_native_u2_at   (int offset)        const     { return Bytes::get_native_u2(addr_at(offset)); }
   int     get_native_u4_at   (int offset)        const     { return Bytes::get_native_u4(addr_at(offset)); }
 
@@ -150,8 +150,8 @@
   void verify() const PRODUCT_RETURN;
 
   // Attributes
-  int  default_offset() const                    { return get_Java_u4_at(aligned_offset(1 + 0*jintSize)); }
-  int  number_of_pairs() const                   { return get_Java_u4_at(aligned_offset(1 + 1*jintSize)); }
+  int  default_offset() const                    { return get_aligned_Java_u4_at(1 + 0*jintSize); }
+  int  number_of_pairs() const                   { return get_aligned_Java_u4_at(1 + 1*jintSize); }
   LookupswitchPair pair_at(int i) const          {
     assert(0 <= i && i < number_of_pairs(), "pair index out of bounds");
     return LookupswitchPair(aligned_addr_at(1 + (1 + i)*2*jintSize));
@@ -166,9 +166,9 @@
   void verify() const PRODUCT_RETURN;
 
   // Attributes
-  int  default_offset() const                    { return get_Java_u4_at(aligned_offset(1 + 0*jintSize)); }
-  int  low_key() const                           { return get_Java_u4_at(aligned_offset(1 + 1*jintSize)); }
-  int  high_key() const                          { return get_Java_u4_at(aligned_offset(1 + 2*jintSize)); }
+  int  default_offset() const                    { return get_aligned_Java_u4_at(1 + 0*jintSize); }
+  int  low_key() const                           { return get_aligned_Java_u4_at(1 + 1*jintSize); }
+  int  high_key() const                          { return get_aligned_Java_u4_at(1 + 2*jintSize); }
   int  dest_offset_at(int i) const;
   int  length()                                  { return high_key()-low_key()+1; }
 };
--- a/src/share/vm/jvmci/jvmciCodeInstaller.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/jvmci/jvmciCodeInstaller.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -554,7 +554,7 @@
   _constants = buffer.consts();
 
   initialize_fields(target(), JNIHandles::resolve(compiled_code_obj), CHECK_OK);
-  JVMCIEnv::CodeInstallResult result = initialize_buffer(buffer, CHECK_OK);
+  JVMCIEnv::CodeInstallResult result = initialize_buffer(buffer, false, CHECK_OK);
   if (result != JVMCIEnv::ok) {
     return result;
   }
@@ -587,7 +587,7 @@
   _constants = buffer.consts();
 
   initialize_fields(target(), JNIHandles::resolve(compiled_code_obj), CHECK_OK);
-  JVMCIEnv::CodeInstallResult result = initialize_buffer(buffer, CHECK_OK);
+  JVMCIEnv::CodeInstallResult result = initialize_buffer(buffer, true, CHECK_OK);
   if (result != JVMCIEnv::ok) {
     return result;
   }
@@ -726,7 +726,7 @@
 }
 
 // perform data and call relocation on the CodeBuffer
-JVMCIEnv::CodeInstallResult CodeInstaller::initialize_buffer(CodeBuffer& buffer, TRAPS) {
+JVMCIEnv::CodeInstallResult CodeInstaller::initialize_buffer(CodeBuffer& buffer, bool check_size, TRAPS) {
   HandleMark hm;
   objArrayHandle sites = this->sites();
   int locs_buffer_size = sites->length() * (relocInfo::length_limit + sizeof(relocInfo));
@@ -738,7 +738,7 @@
   int stubs_size = estimate_stubs_size(CHECK_OK);
   int total_size = round_to(_code_size, buffer.insts()->alignment()) + round_to(_constants_size, buffer.consts()->alignment()) + round_to(stubs_size, buffer.stubs()->alignment());
 
-  if (total_size > JVMCINMethodSizeLimit) {
+  if (check_size && total_size > JVMCINMethodSizeLimit) {
     return JVMCIEnv::code_too_large;
   }
 
@@ -1258,6 +1258,7 @@
       case HEAP_TOP_ADDRESS:
       case HEAP_END_ADDRESS:
       case NARROW_KLASS_BASE_ADDRESS:
+      case NARROW_OOP_BASE_ADDRESS:
       case CRC_TABLE_ADDRESS:
       case LOG_OF_HEAP_REGION_GRAIN_BYTES:
       case INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED:
--- a/src/share/vm/jvmci/jvmciCodeInstaller.hpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/jvmci/jvmciCodeInstaller.hpp	Sat Feb 04 03:29:40 2017 +0100
@@ -133,9 +133,10 @@
     HEAP_TOP_ADDRESS                       = 17,
     HEAP_END_ADDRESS                       = 18,
     NARROW_KLASS_BASE_ADDRESS              = 19,
-    CRC_TABLE_ADDRESS                      = 20,
-    LOG_OF_HEAP_REGION_GRAIN_BYTES         = 21,
-    INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED = 22,
+    NARROW_OOP_BASE_ADDRESS                = 20,
+    CRC_TABLE_ADDRESS                      = 21,
+    LOG_OF_HEAP_REGION_GRAIN_BYTES         = 22,
+    INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED = 23,
     INVOKE_INVALID                         = -1
   };
 
@@ -227,7 +228,7 @@
   int estimate_stubs_size(TRAPS);
 
   // perform data and call relocation on the CodeBuffer
-  JVMCIEnv::CodeInstallResult initialize_buffer(CodeBuffer& buffer, TRAPS);
+  JVMCIEnv::CodeInstallResult initialize_buffer(CodeBuffer& buffer, bool check_size, TRAPS);
 
   void assumption_NoFinalizableSubclass(Handle assumption);
   void assumption_ConcreteSubtype(Handle assumption);
--- a/src/share/vm/jvmci/jvmciCompilerToVM.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/jvmci/jvmciCompilerToVM.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -591,12 +591,16 @@
   return method->is_ignored_by_security_stack_walk();
 C2V_END
 
-C2V_VMENTRY(jboolean, canInlineMethod,(JNIEnv *, jobject, jobject jvmci_method))
+C2V_VMENTRY(jboolean, isCompilable,(JNIEnv *, jobject, jobject jvmci_method))
   methodHandle method = CompilerToVM::asMethod(jvmci_method);
-  // In hosted mode ignore the not_compilable flags since they are never set by
+  // Ignore the not_compilable flags in hosted mode since they are never set by
   // the JVMCI compiler.
-  bool is_compilable = UseJVMCICompiler ? !method->is_not_compilable(CompLevel_full_optimization) : true;
-  return is_compilable && !CompilerOracle::should_not_inline(method) && !method->dont_inline();
+  return UseJVMCICompiler || !method->is_not_compilable(CompLevel_full_optimization);
+C2V_END
+
+C2V_VMENTRY(jboolean, hasNeverInlineDirective,(JNIEnv *, jobject, jobject jvmci_method))
+  methodHandle method = CompilerToVM::asMethod(jvmci_method);
+  return CompilerOracle::should_not_inline(method) || method->dont_inline();
 C2V_END
 
 C2V_VMENTRY(jboolean, shouldInlineMethod,(JNIEnv *, jobject, jobject jvmci_method))
@@ -1591,7 +1595,8 @@
   {CC "getStackTraceElement",                         CC "(" HS_RESOLVED_METHOD "I)" STACK_TRACE_ELEMENT,                                   FN_PTR(getStackTraceElement)},
   {CC "methodIsIgnoredBySecurityStackWalk",           CC "(" HS_RESOLVED_METHOD ")Z",                                                       FN_PTR(methodIsIgnoredBySecurityStackWalk)},
   {CC "doNotInlineOrCompile",                         CC "(" HS_RESOLVED_METHOD ")V",                                                       FN_PTR(doNotInlineOrCompile)},
-  {CC "canInlineMethod",                              CC "(" HS_RESOLVED_METHOD ")Z",                                                       FN_PTR(canInlineMethod)},
+  {CC "isCompilable",                                 CC "(" HS_RESOLVED_METHOD ")Z",                                                       FN_PTR(isCompilable)},
+  {CC "hasNeverInlineDirective",                      CC "(" HS_RESOLVED_METHOD ")Z",                                                       FN_PTR(hasNeverInlineDirective)},
   {CC "shouldInlineMethod",                           CC "(" HS_RESOLVED_METHOD ")Z",                                                       FN_PTR(shouldInlineMethod)},
   {CC "lookupType",                                   CC "(" STRING CLASS "Z)" HS_RESOLVED_KLASS,                                           FN_PTR(lookupType)},
   {CC "lookupNameInPool",                             CC "(" HS_CONSTANT_POOL "I)" STRING,                                                  FN_PTR(lookupNameInPool)},
--- a/src/share/vm/jvmci/vmStructs_jvmci.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/jvmci/vmStructs_jvmci.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -429,6 +429,7 @@
   declare_constant(CodeInstaller::HEAP_TOP_ADDRESS)                       \
   declare_constant(CodeInstaller::HEAP_END_ADDRESS)                       \
   declare_constant(CodeInstaller::NARROW_KLASS_BASE_ADDRESS)              \
+  declare_constant(CodeInstaller::NARROW_OOP_BASE_ADDRESS)                \
   declare_constant(CodeInstaller::CRC_TABLE_ADDRESS)                      \
   declare_constant(CodeInstaller::LOG_OF_HEAP_REGION_GRAIN_BYTES)         \
   declare_constant(CodeInstaller::INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED) \
@@ -534,7 +535,6 @@
                                                                           \
   declare_constant(markOopDesc::no_hash)                                  \
                                                                           \
-  declare_constant(Method::_jfr_towrite)                                  \
   declare_constant(Method::_caller_sensitive)                             \
   declare_constant(Method::_force_inline)                                 \
   declare_constant(Method::_dont_inline)                                  \
--- a/src/share/vm/logging/logConfiguration.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/logging/logConfiguration.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -478,7 +478,7 @@
 
 void LogConfiguration::print_command_line_help(FILE* out) {
   jio_fprintf(out, "-Xlog Usage: -Xlog[:[what][:[output][:[decorators][:output-options]]]]\n"
-              "\t where 'what' is a combination of tags and levels on the form tag1[+tag2...][*][=level][,...]\n"
+              "\t where 'what' is a combination of tags and levels of the form tag1[+tag2...][*][=level][,...]\n"
               "\t Unless wildcard (*) is specified, only log messages tagged with exactly the tags specified will be matched.\n\n");
 
   jio_fprintf(out, "Available log levels:\n");
@@ -514,6 +514,14 @@
               " -Xlog:gc\n"
               "\t Log messages tagged with 'gc' tag using 'info' level to stdout, with default decorations.\n\n"
 
+              " -Xlog:gc,safepoint\n"
+              "\t Log messages tagged either with 'gc' or 'safepoint' tags, both using 'info' level, to stdout, with default decorations.\n"
+              "\t (Messages tagged with both 'gc' and 'safepoint' will not be logged.)\n\n"
+
+              " -Xlog:gc+ref=debug\n"
+              "\t Log messages tagged with both 'gc' and 'ref' tags, using 'debug' level, to stdout, with default decorations.\n"
+              "\t (Messages tagged only with one of the two tags will not be logged.)\n\n"
+
               " -Xlog:gc=debug:file=gc.txt:none\n"
               "\t Log messages tagged with 'gc' tag using 'debug' level to file 'gc.txt' with no decorations.\n\n"
 
--- a/src/share/vm/memory/metaspaceShared.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/memory/metaspaceShared.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -145,10 +145,6 @@
   StringTable::serialize(soc, string_space, space_size);
   soc->do_tag(--tag);
 
-  // Dump/restore the misc information for system dictionary
-  SystemDictionaryShared::serialize(soc);
-  soc->do_tag(--tag);
-
   soc->do_tag(666);
 }
 
--- a/src/share/vm/oops/instanceKlass.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/oops/instanceKlass.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -2139,8 +2139,6 @@
 }
 
 void InstanceKlass::release_C_heap_structures() {
-  assert(!this->is_shared(), "should not be called for a shared class");
-
   // Can't release the constant pool here because the constant pool can be
   // deallocated separately from the InstanceKlass for default methods and
   // redefine classes.
@@ -2191,7 +2189,7 @@
   }
 
   // deallocate the cached class file
-  if (_cached_class_file != NULL) {
+  if (_cached_class_file != NULL && !MetaspaceShared::is_in_shared_space(_cached_class_file)) {
     os::free(_cached_class_file);
     _cached_class_file = NULL;
   }
--- a/src/share/vm/oops/method.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/oops/method.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -85,7 +85,6 @@
   set_constMethod(xconst);
   set_access_flags(access_flags);
   set_intrinsic_id(vmIntrinsics::_none);
-  set_jfr_towrite(false);
   set_force_inline(false);
   set_hidden(false);
   set_dont_inline(false);
--- a/src/share/vm/oops/method.hpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/oops/method.hpp	Sat Feb 04 03:29:40 2017 +0100
@@ -75,18 +75,19 @@
 
   // Flags
   enum Flags {
-    _jfr_towrite           = 1 << 0,
-    _caller_sensitive      = 1 << 1,
-    _force_inline          = 1 << 2,
-    _dont_inline           = 1 << 3,
-    _hidden                = 1 << 4,
-    _has_injected_profile  = 1 << 5,
-    _running_emcp          = 1 << 6,
-    _intrinsic_candidate   = 1 << 7,
-    _reserved_stack_access = 1 << 8
+    _caller_sensitive      = 1 << 0,
+    _force_inline          = 1 << 1,
+    _dont_inline           = 1 << 2,
+    _hidden                = 1 << 3,
+    _has_injected_profile  = 1 << 4,
+    _running_emcp          = 1 << 5,
+    _intrinsic_candidate   = 1 << 6,
+    _reserved_stack_access = 1 << 7
   };
   mutable u2 _flags;
 
+  TRACE_DEFINE_FLAG;
+
 #ifndef PRODUCT
   int               _compiled_invocation_count;  // Number of nmethod invocations so far (for perf. debugging)
 #endif
@@ -833,13 +834,6 @@
   void init_intrinsic_id();     // updates from _none if a match
   static vmSymbols::SID klass_id_for_intrinsics(const Klass* holder);
 
-  bool jfr_towrite() const {
-    return (_flags & _jfr_towrite) != 0;
-  }
-  void set_jfr_towrite(bool x) const {
-    _flags = x ? (_flags | _jfr_towrite) : (_flags & ~_jfr_towrite);
-  }
-
   bool caller_sensitive() {
     return (_flags & _caller_sensitive) != 0;
   }
@@ -890,6 +884,8 @@
     _flags = x ? (_flags | _reserved_stack_access) : (_flags & ~_reserved_stack_access);
   }
 
+  TRACE_DEFINE_FLAG_ACCESSOR;
+
   ConstMethod::MethodType method_type() const {
       return _constMethod->method_type();
   }
--- a/src/share/vm/oops/methodData.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/oops/methodData.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -717,9 +717,9 @@
 }
 
 int MethodData::bytecode_cell_count(Bytecodes::Code code) {
-#if defined(COMPILER1) && !(defined(COMPILER2) || INCLUDE_JVMCI)
-  return no_profile_data;
-#else
+  if (is_client_compilation_mode_vm()) {
+    return no_profile_data;
+  }
   switch (code) {
   case Bytecodes::_checkcast:
   case Bytecodes::_instanceof:
@@ -778,7 +778,6 @@
     return variable_cell_count;
   }
   return no_profile_data;
-#endif
 }
 
 // Compute the size of the profiling information corresponding to
@@ -840,7 +839,9 @@
   case Bytecodes::_ifnonnull:
   case Bytecodes::_invokestatic:
 #ifdef COMPILER2
-    return UseTypeSpeculation;
+    if (is_server_compilation_mode_vm()) {
+      return UseTypeSpeculation;
+    }
 #endif
   default:
     return false;
@@ -942,9 +943,9 @@
 // the segment in bytes.
 int MethodData::initialize_data(BytecodeStream* stream,
                                        int data_index) {
-#if defined(COMPILER1) && !(defined(COMPILER2) || INCLUDE_JVMCI)
-  return 0;
-#else
+  if (is_client_compilation_mode_vm()) {
+    return 0;
+  }
   int cell_count = -1;
   int tag = DataLayout::no_tag;
   DataLayout* data_layout = data_layout_at(data_index);
@@ -1061,7 +1062,6 @@
     assert(!bytecode_has_profile(c), "agree w/ !BHP");
     return 0;
   }
-#endif
 }
 
 // Get the data at an arbitrary (sort of) data index.
--- a/src/share/vm/oops/methodData.hpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/oops/methodData.hpp	Sat Feb 04 03:29:40 2017 +0100
@@ -2183,7 +2183,7 @@
   uint _nof_overflow_traps;         // trap count, excluding _trap_hist
   union {
     intptr_t _align;
-    u1 _array[_trap_hist_limit];
+    u1 _array[JVMCI_ONLY(2 *) _trap_hist_limit];
   } _trap_hist;
 
   // Support for interprocedural escape analysis, from Thomas Kotzmann.
--- a/src/share/vm/opto/cfgnode.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/opto/cfgnode.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -2097,6 +2097,7 @@
   uint ideal_reg = _type->ideal_reg();
   assert( ideal_reg != Node::NotAMachineReg, "invalid type at Phi" );
   if( ideal_reg == 0 ) return RegMask::Empty;
+  assert(ideal_reg != Op_RegFlags, "flags register is not spillable");
   return *(Compile::current()->matcher()->idealreg2spillmask[ideal_reg]);
 }
 
--- a/src/share/vm/opto/coalesce.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/opto/coalesce.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -292,7 +292,14 @@
               // Copy any flags as well
               _phc.clone_projs(pred, pred->end_idx(), m, copy, _phc._lrg_map);
             } else {
-              const RegMask *rm = C->matcher()->idealreg2spillmask[m->ideal_reg()];
+              int ireg = m->ideal_reg();
+              if (ireg == 0 || ireg == Op_RegFlags) {
+                assert(false, "attempted to spill a non-spillable item: %d: %s, ireg = %d, spill_type: %s",
+                       m->_idx, m->Name(), ireg, MachSpillCopyNode::spill_type(MachSpillCopyNode::PhiInput));
+                C->record_method_not_compilable("attempted to spill a non-spillable item");
+                return;
+              }
+              const RegMask *rm = C->matcher()->idealreg2spillmask[ireg];
               copy = new MachSpillCopyNode(MachSpillCopyNode::PhiInput, m, *rm, *rm);
               // Find a good place to insert.  Kinda tricky, use a subroutine
               insert_copy_with_overlap(pred,copy,phi_name,src_name);
@@ -326,7 +333,14 @@
               b->insert_node(copy, l++);
               l += _phc.clone_projs(b, l, m, copy, _phc._lrg_map);
             } else {
-              const RegMask *rm = C->matcher()->idealreg2spillmask[m->ideal_reg()];
+              int ireg = m->ideal_reg();
+              if (ireg == 0 || ireg == Op_RegFlags) {
+                assert(false, "attempted to spill a non-spillable item: %d: %s, ireg = %d, spill_type: %s",
+                       m->_idx, m->Name(), ireg, MachSpillCopyNode::spill_type(MachSpillCopyNode::TwoAddress));
+                C->record_method_not_compilable("attempted to spill a non-spillable item");
+                return;
+              }
+              const RegMask *rm = C->matcher()->idealreg2spillmask[ireg];
               copy = new MachSpillCopyNode(MachSpillCopyNode::TwoAddress, m, *rm, *rm);
               // Insert the copy in the basic block, just before us
               b->insert_node(copy, l++);
@@ -373,7 +387,14 @@
               if( k < b->_num_succs )
                 continue;     // Live out; do not pre-split
               // Split the lrg at this use
-              const RegMask *rm = C->matcher()->idealreg2spillmask[inp->ideal_reg()];
+              int ireg = inp->ideal_reg();
+              if (ireg == 0 || ireg == Op_RegFlags) {
+                assert(false, "attempted to spill a non-spillable item: %d: %s, ireg = %d, spill_type: %s",
+                       inp->_idx, inp->Name(), ireg, MachSpillCopyNode::spill_type(MachSpillCopyNode::DebugUse));
+                C->record_method_not_compilable("attempted to spill a non-spillable item");
+                return;
+              }
+              const RegMask *rm = C->matcher()->idealreg2spillmask[ireg];
               Node* copy = new MachSpillCopyNode(MachSpillCopyNode::DebugUse, inp, *rm, *rm);
               // Insert the copy in the use-def chain
               n->set_req(inpidx, copy );
--- a/src/share/vm/opto/compile.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/opto/compile.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -971,7 +971,7 @@
     _java_calls(0),
     _inner_loops(0),
 #ifndef PRODUCT
-    _trace_opto_output(TraceOptoOutput),
+    _trace_opto_output(directive->TraceOptoOutputOption),
     _in_dump_cnt(0),
     _printer(NULL),
 #endif
--- a/src/share/vm/opto/graphKit.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/opto/graphKit.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -3152,19 +3152,6 @@
   return membar;
 }
 
-void GraphKit::insert_store_load_for_barrier() {
-  Node* mem = reset_memory();
-  MemBarNode* mb = MemBarNode::make(C, Op_MemBarVolatile, Compile::AliasIdxBot);
-  mb->init_req(TypeFunc::Control, control());
-  mb->init_req(TypeFunc::Memory, mem);
-  Node* membar = _gvn.transform(mb);
-  set_control(_gvn.transform(new ProjNode(membar, TypeFunc::Control)));
-  Node* newmem = _gvn.transform(new ProjNode(membar, TypeFunc::Memory));
-  set_all_memory(mem);
-  set_memory(newmem, Compile::AliasIdxRaw);
-}
-
-
 //------------------------------shared_lock------------------------------------
 // Emit locking code.
 FastLockNode* GraphKit::shared_lock(Node* obj) {
@@ -3854,7 +3841,7 @@
   BasicType bt = T_BYTE;
 
   if (UseConcMarkSweepGC && UseCondCardMark) {
-    insert_store_load_for_barrier();
+    insert_mem_bar(Op_MemBarVolatile);   // StoreLoad barrier
     __ sync_kit(this);
   }
 
@@ -4294,7 +4281,8 @@
 
         __ if_then(card_val, BoolTest::ne, young_card); {
           sync_kit(ideal);
-          insert_store_load_for_barrier();
+          // Use Op_MemBarVolatile to achieve the effect of a StoreLoad barrier.
+          insert_mem_bar(Op_MemBarVolatile, oop_store);
           __ sync_kit(this);
 
           Node* card_val_reload = __ load(__ ctrl(), card_adr, TypeInt::INT, T_BYTE, Compile::AliasIdxRaw);
@@ -4348,20 +4336,16 @@
 }
 
 Node* GraphKit::load_String_coder(Node* ctrl, Node* str) {
-  if (java_lang_String::has_coder_field()) {
-    if (!CompactStrings) {
-      return intcon(java_lang_String::CODER_UTF16);
-    }
-    int coder_offset = java_lang_String::coder_offset_in_bytes();
-    const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(),
-                                                       false, NULL, 0);
-    const TypePtr* coder_field_type = string_type->add_offset(coder_offset);
-    int coder_field_idx = C->get_alias_index(coder_field_type);
-    return make_load(ctrl, basic_plus_adr(str, str, coder_offset),
-                     TypeInt::BYTE, T_BYTE, coder_field_idx, MemNode::unordered);
-  } else {
-    return intcon(0); // false
+  if (!CompactStrings) {
+    return intcon(java_lang_String::CODER_UTF16);
   }
+  int coder_offset = java_lang_String::coder_offset_in_bytes();
+  const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(),
+                                                     false, NULL, 0);
+  const TypePtr* coder_field_type = string_type->add_offset(coder_offset);
+  int coder_field_idx = C->get_alias_index(coder_field_type);
+  return make_load(ctrl, basic_plus_adr(str, str, coder_offset),
+                   TypeInt::BYTE, T_BYTE, coder_field_idx, MemNode::unordered);
 }
 
 void GraphKit::store_String_value(Node* ctrl, Node* str, Node* value) {
--- a/src/share/vm/opto/graphKit.hpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/opto/graphKit.hpp	Sat Feb 04 03:29:40 2017 +0100
@@ -837,7 +837,6 @@
   int next_monitor();
   Node* insert_mem_bar(int opcode, Node* precedent = NULL);
   Node* insert_mem_bar_volatile(int opcode, int alias_idx, Node* precedent = NULL);
-  void insert_store_load_for_barrier();
   // Optional 'precedent' is appended as an extra edge, to force ordering.
   FastLockNode* shared_lock(Node* obj);
   void shared_unlock(Node* box, Node* obj);
--- a/src/share/vm/opto/library_call.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/opto/library_call.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -6335,7 +6335,7 @@
 
 //------------------------------get_key_start_from_aescrypt_object-----------------------
 Node * LibraryCallKit::get_key_start_from_aescrypt_object(Node *aescrypt_object) {
-#ifdef PPC64
+#if defined(PPC64) || defined(S390)
   // MixColumns for decryption can be reduced by preprocessing MixColumns with round keys.
   // Intel's extention is based on this optimization and AESCrypt generates round keys by preprocessing MixColumns.
   // However, ppc64 vncipher processes MixColumns and requires the same round keys with encryption.
--- a/src/share/vm/opto/machnode.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/opto/machnode.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -643,6 +643,7 @@
   }
 
   // Values outside the domain represent debug info
+  assert(in(idx)->ideal_reg() != Op_RegFlags, "flags register is not spillable");
   return *Compile::current()->matcher()->idealreg2spillmask[in(idx)->ideal_reg()];
 }
 
--- a/src/share/vm/opto/macro.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/opto/macro.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -426,7 +426,7 @@
 
 // Generate loads from source of the arraycopy for fields of
 // destination needed at a deoptimization point
-Node* PhaseMacroExpand::make_arraycopy_load(ArrayCopyNode* ac, intptr_t offset, Node* ctl, BasicType ft, const Type *ftype, AllocateNode *alloc) {
+Node* PhaseMacroExpand::make_arraycopy_load(ArrayCopyNode* ac, intptr_t offset, Node* ctl, Node* mem, BasicType ft, const Type *ftype, AllocateNode *alloc) {
   BasicType bt = ft;
   const Type *type = ftype;
   if (ft == T_NARROWOOP) {
@@ -438,8 +438,7 @@
     Node* base = ac->in(ArrayCopyNode::Src)->in(AddPNode::Base);
     Node* adr = _igvn.transform(new AddPNode(base, base, MakeConX(offset)));
     const TypePtr* adr_type = _igvn.type(base)->is_ptr()->add_offset(offset);
-    Node* m = ac->in(TypeFunc::Memory);
-    res = LoadNode::make(_igvn, ctl, m, adr, adr_type, type, bt, MemNode::unordered, LoadNode::Pinned);
+    res = LoadNode::make(_igvn, ctl, mem, adr, adr_type, type, bt, MemNode::unordered, LoadNode::Pinned);
   } else {
     if (ac->modifies(offset, offset, &_igvn, true)) {
       assert(ac->in(ArrayCopyNode::Dest) == alloc->result_cast(), "arraycopy destination should be allocation's result");
@@ -454,8 +453,7 @@
       Node* base = ac->in(ArrayCopyNode::Src);
       Node* adr = _igvn.transform(new AddPNode(base, base, off));
       const TypePtr* adr_type = _igvn.type(base)->is_ptr()->add_offset(offset);
-      Node* m = ac->in(TypeFunc::Memory);
-      res = LoadNode::make(_igvn, ctl, m, adr, adr_type, type, bt, MemNode::unordered, LoadNode::Pinned);
+      res = LoadNode::make(_igvn, ctl, mem, adr, adr_type, type, bt, MemNode::unordered, LoadNode::Pinned);
     }
   }
   if (res != NULL) {
@@ -544,7 +542,7 @@
         assert(false, "Object is not scalar replaceable if a LoadStore node accesses its field");
         return NULL;
       } else if (val->is_ArrayCopy()) {
-        Node* res = make_arraycopy_load(val->as_ArrayCopy(), offset, val->in(0), ft, phi_type, alloc);
+        Node* res = make_arraycopy_load(val->as_ArrayCopy(), offset, val->in(0), val->in(TypeFunc::Memory), ft, phi_type, alloc);
         if (res == NULL) {
           return NULL;
         }
@@ -657,11 +655,13 @@
       }
     } else if (mem->is_ArrayCopy()) {
       Node* ctl = mem->in(0);
+      Node* m = mem->in(TypeFunc::Memory);
       if (sfpt_ctl->is_Proj() && sfpt_ctl->as_Proj()->is_uncommon_trap_proj(Deoptimization::Reason_none)) {
         // pin the loads in the uncommon trap path
         ctl = sfpt_ctl;
+        m = sfpt_mem;
       }
-      return make_arraycopy_load(mem->as_ArrayCopy(), offset, ctl, ft, ftype, alloc);
+      return make_arraycopy_load(mem->as_ArrayCopy(), offset, ctl, m, ft, ftype, alloc);
     }
   }
   // Something go wrong.
--- a/src/share/vm/opto/macro.hpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/opto/macro.hpp	Sat Feb 04 03:29:40 2017 +0100
@@ -200,7 +200,7 @@
                             Node* old_eden_top, Node* new_eden_top,
                             Node* length);
 
-  Node* make_arraycopy_load(ArrayCopyNode* ac, intptr_t offset, Node* ctl, BasicType ft, const Type *ftype, AllocateNode *alloc);
+  Node* make_arraycopy_load(ArrayCopyNode* ac, intptr_t offset, Node* ctl, Node* mem, BasicType ft, const Type *ftype, AllocateNode *alloc);
 
 public:
   PhaseMacroExpand(PhaseIterGVN &igvn) : Phase(Macro_Expand), _igvn(igvn), _has_locks(false) {
--- a/src/share/vm/opto/matcher.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/opto/matcher.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -85,6 +85,7 @@
   idealreg2spillmask  [Op_VecX] = NULL;
   idealreg2spillmask  [Op_VecY] = NULL;
   idealreg2spillmask  [Op_VecZ] = NULL;
+  idealreg2spillmask  [Op_RegFlags] = NULL;
 
   idealreg2debugmask  [Op_RegI] = NULL;
   idealreg2debugmask  [Op_RegN] = NULL;
@@ -97,6 +98,7 @@
   idealreg2debugmask  [Op_VecX] = NULL;
   idealreg2debugmask  [Op_VecY] = NULL;
   idealreg2debugmask  [Op_VecZ] = NULL;
+  idealreg2debugmask  [Op_RegFlags] = NULL;
 
   idealreg2mhdebugmask[Op_RegI] = NULL;
   idealreg2mhdebugmask[Op_RegN] = NULL;
@@ -109,6 +111,7 @@
   idealreg2mhdebugmask[Op_VecX] = NULL;
   idealreg2mhdebugmask[Op_VecY] = NULL;
   idealreg2mhdebugmask[Op_VecZ] = NULL;
+  idealreg2mhdebugmask[Op_RegFlags] = NULL;
 
   debug_only(_mem_node = NULL;)   // Ideal memory node consumed by mach node
 }
--- a/src/share/vm/prims/jniCheck.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/prims/jniCheck.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -238,8 +238,8 @@
   size_t live_handles = handles->get_number_of_live_handles();
   if (live_handles > planned_capacity) {
     IN_VM(
-      tty->print_cr("WARNING: JNI local refs: %zu, exceeds capacity: %zu",
-          live_handles, planned_capacity);
+      tty->print_cr("WARNING: JNI local refs: " SIZE_FORMAT ", exceeds capacity: " SIZE_FORMAT,
+                    live_handles, planned_capacity);
       thr->print_stack();
     )
     // Complain just the once, reset to current + warn threshold
--- a/src/share/vm/prims/jvm.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/prims/jvm.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -1009,9 +1009,9 @@
 // Module support //////////////////////////////////////////////////////////////////////////////
 
 JVM_ENTRY(void, JVM_DefineModule(JNIEnv *env, jobject module, jboolean is_open, jstring version,
-                                 jstring location, jobjectArray packages))
+                                 jstring location, const char* const* packages, jsize num_packages))
   JVMWrapper("JVM_DefineModule");
-  Modules::define_module(module, version, location, packages, CHECK);
+  Modules::define_module(module, version, location, packages, num_packages, CHECK);
 JVM_END
 
 JVM_ENTRY(void, JVM_SetBootLoaderUnnamedModule(JNIEnv *env, jobject module))
@@ -1019,17 +1019,17 @@
   Modules::set_bootloader_unnamed_module(module, CHECK);
 JVM_END
 
-JVM_ENTRY(void, JVM_AddModuleExports(JNIEnv *env, jobject from_module, jstring package, jobject to_module))
+JVM_ENTRY(void, JVM_AddModuleExports(JNIEnv *env, jobject from_module, const char* package, jobject to_module))
   JVMWrapper("JVM_AddModuleExports");
   Modules::add_module_exports_qualified(from_module, package, to_module, CHECK);
 JVM_END
 
-JVM_ENTRY(void, JVM_AddModuleExportsToAllUnnamed(JNIEnv *env, jobject from_module, jstring package))
+JVM_ENTRY(void, JVM_AddModuleExportsToAllUnnamed(JNIEnv *env, jobject from_module, const char* package))
   JVMWrapper("JVM_AddModuleExportsToAllUnnamed");
   Modules::add_module_exports_to_all_unnamed(from_module, package, CHECK);
 JVM_END
 
-JVM_ENTRY(void, JVM_AddModuleExportsToAll(JNIEnv *env, jobject from_module, jstring package))
+JVM_ENTRY(void, JVM_AddModuleExportsToAll(JNIEnv *env, jobject from_module, const char* package))
   JVMWrapper("JVM_AddModuleExportsToAll");
   Modules::add_module_exports(from_module, package, NULL, CHECK);
 JVM_END
@@ -1039,16 +1039,11 @@
   Modules::add_reads_module(from_module, source_module, CHECK);
 JVM_END
 
-JVM_ENTRY (void, JVM_AddModulePackage(JNIEnv *env, jobject module, jstring package))
+JVM_ENTRY (void, JVM_AddModulePackage(JNIEnv *env, jobject module, const char* package))
   JVMWrapper("JVM_AddModulePackage");
   Modules::add_module_package(module, package, CHECK);
 JVM_END
 
-JVM_ENTRY (jobject, JVM_GetModuleByPackageName(JNIEnv *env, jobject loader, jstring package))
-  JVMWrapper("JVM_GetModuleByPackageName");
-  return Modules::get_module_by_package_name(loader, package, THREAD);
-JVM_END
-
 // Reflection support //////////////////////////////////////////////////////////////////////////////
 
 JVM_ENTRY(jstring, JVM_GetClassName(JNIEnv *env, jclass cls))
--- a/src/share/vm/prims/jvm.h	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/prims/jvm.h	Sat Feb 04 03:29:40 2017 +0100
@@ -412,30 +412,67 @@
  * Module support funcions
  */
 
+/*
+ * Define a module with the specified packages and bind the module to the
+ * given class loader.
+ *  module:       module to define
+ *  is_open:      specifies if module is open (currently ignored)
+ *  version:      the module version
+ *  location:     the module location
+ *  packages:     list of packages in the module
+ *  num_packages: number of packages in the module
+ */
 JNIEXPORT void JNICALL
 JVM_DefineModule(JNIEnv *env, jobject module, jboolean is_open, jstring version,
-                 jstring location, jobjectArray packages);
+                 jstring location, const char* const* packages, jsize num_packages);
 
+/*
+ * Set the boot loader's unnamed module.
+ *  module: boot loader's unnamed module
+ */
 JNIEXPORT void JNICALL
 JVM_SetBootLoaderUnnamedModule(JNIEnv *env, jobject module);
 
+/*
+ * Do a qualified export of a package.
+ *  from_module: module containing the package to export
+ *  package:     name of the package to export
+ *  to_module:   module to export the package to
+ */
 JNIEXPORT void JNICALL
-JVM_AddModuleExports(JNIEnv *env, jobject from_module, jstring package, jobject to_module);
+JVM_AddModuleExports(JNIEnv *env, jobject from_module, const char* package, jobject to_module);
 
+/*
+ * Do an export of a package to all unnamed modules.
+ *  from_module: module containing the package to export
+ *  package:     name of the package to export to all unnamed modules
+ */
 JNIEXPORT void JNICALL
-JVM_AddModuleExportsToAllUnnamed(JNIEnv *env, jobject from_module, jstring package);
+JVM_AddModuleExportsToAllUnnamed(JNIEnv *env, jobject from_module, const char* package);
 
+/*
+ * Do an unqualified export of a package.
+ *  from_module: module containing the package to export
+ *  package:     name of the package to export
+ */
 JNIEXPORT void JNICALL
-JVM_AddModuleExportsToAll(JNIEnv *env, jobject from_module, jstring package);
+JVM_AddModuleExportsToAll(JNIEnv *env, jobject from_module, const char* package);
 
+/*
+ * Add a module to the list of modules that a given module can read.
+ *  from_module:   module requesting read access
+ *  source_module: module that from_module wants to read
+ */
 JNIEXPORT void JNICALL
 JVM_AddReadsModule(JNIEnv *env, jobject from_module, jobject source_module);
 
+/*
+ * Add a package to a module.
+ *  module:  module that will contain the package
+ *  package: package to add to the module
+ */
 JNIEXPORT void JNICALL
-JVM_AddModulePackage(JNIEnv* env,  jobject module, jstring package);
-
-JNIEXPORT jobject JNICALL
-JVM_GetModuleByPackageName(JNIEnv* env, jobject loader, jstring package);
+JVM_AddModulePackage(JNIEnv* env,  jobject module, const char* package);
 
 /*
  * Reflection support functions
--- a/src/share/vm/prims/jvmti.xml	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/prims/jvmti.xml	Sat Feb 04 03:29:40 2017 +0100
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="ISO-8859-1"?>
 <?xml-stylesheet type="text/xsl" href="jvmti.xsl"?>
 <!--
- Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2002, 2017, 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
@@ -12864,11 +12864,13 @@
       If the capability has been added then the VM posts the event as early
       as possible. The VM is capable of executing bytecode but it may not have
       initialized to the point where it can load classes in modules other than
-      <code>java.base</code>. Agents that do load-time instrumentation in this
+      <code>java.base</code>, or even arbitrary classes in <code>java.base</code>.
+      Agents that do load-time instrumentation in this
       phase must take great care when instrumenting code that potentially
-      executes in this phase. Care should also be taken with JNI
-      <code>FindClass</code> as it may not be possible to load classes that are
-      not in the <code>java.base</code> module.
+      executes in this phase. Extreme care should also be taken with JNI
+      <code>FindClass</code> as it may not be possible to load classes and attempts
+      to do so may result in unpredictable behavior, maybe even stability issues
+      on some VM implementations.
       If the capability has not been added then the VM delays posting this
       event until it is capable of loading classes in modules other than
       <code>java.base</code> or the VM has completed its initialization.
--- a/src/share/vm/prims/jvmtiEnter.xsl	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/prims/jvmtiEnter.xsl	Sat Feb 04 03:29:40 2017 +0100
@@ -1246,7 +1246,7 @@
   <xsl:param name="name"/>
   <xsl:text> </xsl:text>
   <xsl:value-of select="$name"/>
-  <xsl:text>=0x%zx</xsl:text>
+  <xsl:text>=" SIZE_FORMAT_HEX "</xsl:text>
 </xsl:template>
 
 <xsl:template match="jfloat|jdouble" mode="traceInFormat">
--- a/src/share/vm/prims/whitebox.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/prims/whitebox.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -40,6 +40,8 @@
 #include "memory/universe.hpp"
 #include "memory/oopFactory.hpp"
 #include "oops/constantPool.hpp"
+#include "oops/objArrayKlass.hpp"
+#include "oops/objArrayOop.inline.hpp"
 #include "oops/oop.inline.hpp"
 #include "prims/wbtestmethods/parserTests.hpp"
 #include "prims/whitebox.hpp"
@@ -659,6 +661,9 @@
 WB_END
 
 WB_ENTRY(jboolean, WB_IsMethodCompilable(JNIEnv* env, jobject o, jobject method, jint comp_level, jboolean is_osr))
+  if (method == NULL || comp_level > MIN2((CompLevel) TieredStopAtLevel, CompLevel_highest_tier)) {
+    return false;
+  }
   jmethodID jmid = reflected_method_to_jmid(thread, env, method);
   CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
   MutexLockerEx mu(Compile_lock);
@@ -760,7 +765,7 @@
 
 bool WhiteBox::compile_method(Method* method, int comp_level, int bci, Thread* THREAD) {
   // Screen for unavailable/bad comp level or null method
-  if (method == NULL || comp_level > TieredStopAtLevel ||
+  if (method == NULL || comp_level > MIN2((CompLevel) TieredStopAtLevel, CompLevel_highest_tier) ||
       CompileBroker::compiler(comp_level) == NULL) {
     return false;
   }
@@ -1400,19 +1405,52 @@
 
 WB_ENTRY(void, WB_DefineModule(JNIEnv* env, jobject o, jobject module, jstring version, jstring location,
                                 jobjectArray packages))
-  Modules::define_module(module, version, location, packages, CHECK);
+  ResourceMark rm(THREAD);
+
+  objArrayOop packages_oop = objArrayOop(JNIHandles::resolve(packages));
+  objArrayHandle packages_h(THREAD, packages_oop);
+  int num_packages = (packages_h == NULL ? 0 : packages_h->length());
+
+  char** pkgs = NULL;
+  if (num_packages > 0) {
+    pkgs = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char*, num_packages);
+    for (int x = 0; x < num_packages; x++) {
+      oop pkg_str = packages_h->obj_at(x);
+      if (pkg_str == NULL || !pkg_str->is_a(SystemDictionary::String_klass())) {
+        THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+                  err_msg("Bad package name"));
+      }
+      pkgs[x] = java_lang_String::as_utf8_string(pkg_str);
+    }
+  }
+  Modules::define_module(module, version, location, (const char* const*)pkgs, num_packages, CHECK);
 WB_END
 
 WB_ENTRY(void, WB_AddModuleExports(JNIEnv* env, jobject o, jobject from_module, jstring package, jobject to_module))
-  Modules::add_module_exports_qualified(from_module, package, to_module, CHECK);
+  ResourceMark rm(THREAD);
+  char* package_name = NULL;
+  if (package != NULL) {
+      package_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package));
+  }
+  Modules::add_module_exports_qualified(from_module, package_name, to_module, CHECK);
 WB_END
 
 WB_ENTRY(void, WB_AddModuleExportsToAllUnnamed(JNIEnv* env, jobject o, jclass module, jstring package))
-  Modules::add_module_exports_to_all_unnamed(module, package, CHECK);
+  ResourceMark rm(THREAD);
+  char* package_name = NULL;
+  if (package != NULL) {
+      package_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package));
+  }
+  Modules::add_module_exports_to_all_unnamed(module, package_name, CHECK);
 WB_END
 
 WB_ENTRY(void, WB_AddModuleExportsToAll(JNIEnv* env, jobject o, jclass module, jstring package))
-  Modules::add_module_exports(module, package, NULL, CHECK);
+  ResourceMark rm(THREAD);
+  char* package_name = NULL;
+  if (package != NULL) {
+      package_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package));
+  }
+  Modules::add_module_exports(module, package_name, NULL, CHECK);
 WB_END
 
 WB_ENTRY(void, WB_AddReadsModule(JNIEnv* env, jobject o, jobject from_module, jobject source_module))
@@ -1420,11 +1458,21 @@
 WB_END
 
 WB_ENTRY(void, WB_AddModulePackage(JNIEnv* env, jobject o, jclass module, jstring package))
-  Modules::add_module_package(module, package, CHECK);
+  ResourceMark rm(THREAD);
+  char* package_name = NULL;
+  if (package != NULL) {
+      package_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package));
+  }
+  Modules::add_module_package(module, package_name, CHECK);
 WB_END
 
 WB_ENTRY(jobject, WB_GetModuleByPackageName(JNIEnv* env, jobject o, jobject loader, jstring package))
-  return Modules::get_module_by_package_name(loader, package, THREAD);
+  ResourceMark rm(THREAD);
+  char* package_name = NULL;
+  if (package != NULL) {
+      package_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package));
+  }
+  return Modules::get_module_by_package_name(loader, package_name, THREAD);
 WB_END
 
 WB_ENTRY(jlong, WB_IncMetaspaceCapacityUntilGC(JNIEnv* env, jobject wb, jlong inc))
--- a/src/share/vm/runtime/arguments.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/runtime/arguments.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -1819,6 +1819,25 @@
 #endif // INCLUDE_ALL_GCS
 }
 
+#ifdef TIERED
+bool Arguments::compilation_mode_selected() {
+ return !FLAG_IS_DEFAULT(TieredCompilation) || !FLAG_IS_DEFAULT(TieredStopAtLevel) ||
+        !FLAG_IS_DEFAULT(UseAOT) JVMCI_ONLY(|| !FLAG_IS_DEFAULT(EnableJVMCI) || !FLAG_IS_DEFAULT(UseJVMCICompiler));
+
+}
+
+void Arguments::select_compilation_mode_ergonomically() {
+#if defined(_WINDOWS) && !defined(_LP64)
+  if (FLAG_IS_DEFAULT(NeverActAsServerClassMachine)) {
+    FLAG_SET_ERGO(bool, NeverActAsServerClassMachine, true);
+  }
+#endif
+  if (NeverActAsServerClassMachine) {
+    set_client_compilation_mode();
+  }
+}
+#endif //TIERED
+
 void Arguments::select_gc_ergonomically() {
 #if INCLUDE_ALL_GCS
   if (os::is_server_class_machine()) {
@@ -1854,7 +1873,40 @@
   }
 }
 
+#if INCLUDE_JVMCI
+void Arguments::set_jvmci_specific_flags() {
+  if (UseJVMCICompiler) {
+    if (FLAG_IS_DEFAULT(TypeProfileWidth)) {
+      FLAG_SET_DEFAULT(TypeProfileWidth, 8);
+    }
+    if (FLAG_IS_DEFAULT(OnStackReplacePercentage)) {
+      FLAG_SET_DEFAULT(OnStackReplacePercentage, 933);
+    }
+    if (FLAG_IS_DEFAULT(ReservedCodeCacheSize)) {
+      FLAG_SET_DEFAULT(ReservedCodeCacheSize, 64*M);
+    }
+    if (FLAG_IS_DEFAULT(InitialCodeCacheSize)) {
+      FLAG_SET_DEFAULT(InitialCodeCacheSize, 16*M);
+    }
+    if (FLAG_IS_DEFAULT(MetaspaceSize)) {
+      FLAG_SET_DEFAULT(MetaspaceSize, 12*M);
+    }
+    if (FLAG_IS_DEFAULT(NewSizeThreadIncrease)) {
+      FLAG_SET_DEFAULT(NewSizeThreadIncrease, 4*K);
+    }
+    if (FLAG_IS_DEFAULT(TypeProfileLevel)) {
+      FLAG_SET_DEFAULT(TypeProfileLevel, 0);
+    }
+  }
+}
+#endif
+
 void Arguments::set_ergonomics_flags() {
+#ifdef TIERED
+  if (!compilation_mode_selected()) {
+    select_compilation_mode_ergonomically();
+  }
+#endif
   select_gc();
 
 #if defined(COMPILER2) || INCLUDE_JVMCI
@@ -1863,7 +1915,7 @@
   // server performance.  When -server is specified, keep the default off
   // unless it is asked for.  Future work: either add bytecode rewriting
   // at link time, or rewrite bytecodes in non-shared methods.
-  if (!DumpSharedSpaces && !RequireSharedSpaces &&
+  if (is_server_compilation_mode_vm() && !DumpSharedSpaces && !RequireSharedSpaces &&
       (FLAG_IS_DEFAULT(UseSharedSpaces) || !UseSharedSpaces)) {
     no_shared_spaces("COMPILER2 default: -Xshare:auto | off, have to manually setup to on.");
   }
@@ -2463,14 +2515,6 @@
       warning("forcing ScavengeRootsInCode non-zero because JVMCI is enabled");
       ScavengeRootsInCode = 1;
     }
-    if (FLAG_IS_DEFAULT(TypeProfileLevel)) {
-      TypeProfileLevel = 0;
-    }
-    if (UseJVMCICompiler) {
-      if (FLAG_IS_DEFAULT(TypeProfileWidth)) {
-        TypeProfileWidth = 8;
-      }
-    }
   }
 #endif
 
@@ -3691,6 +3735,12 @@
     return JNI_ERR;
   }
 
+#if INCLUDE_JVMCI
+  if (UseJVMCICompiler) {
+    Compilation_mode = CompMode_server;
+  }
+#endif
+
   return JNI_OK;
 }
 
@@ -3820,6 +3870,9 @@
     return JNI_ENOMEM;
   }
 
+  jio_fprintf(defaultStream::error_stream(),
+              "Picked up %s: %s\n", name, buffer);
+
   int retcode = parse_options_buffer(name, buffer, strlen(buffer), vm_args);
 
   os::free(buffer);
@@ -4420,6 +4473,10 @@
   // Set flags based on ergonomics.
   set_ergonomics_flags();
 
+#if INCLUDE_JVMCI
+  set_jvmci_specific_flags();
+#endif
+
   set_shared_spaces_flags();
 
   // Check the GC selections again.
@@ -4432,7 +4489,9 @@
   } else {
     int max_compilation_policy_choice = 1;
 #ifdef COMPILER2
-    max_compilation_policy_choice = 2;
+    if (is_server_compilation_mode_vm()) {
+      max_compilation_policy_choice = 2;
+    }
 #endif
     // Check if the policy is valid.
     if (CompilationPolicyChoice >= max_compilation_policy_choice) {
--- a/src/share/vm/runtime/arguments.hpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/runtime/arguments.hpp	Sat Feb 04 03:29:40 2017 +0100
@@ -455,6 +455,10 @@
   static intx _Tier3InvokeNotifyFreqLog;
   static intx _Tier4InvocationThreshold;
 
+  // Compilation mode.
+  static bool compilation_mode_selected();
+  static void select_compilation_mode_ergonomically();
+
   // Tiered
   static void set_tiered_flags();
   // CMS/ParNew garbage collectors
@@ -638,6 +642,7 @@
 #if INCLUDE_JVMCI
   // Check consistency of jvmci vm argument settings.
   static bool check_jvmci_args_consistency();
+  static void set_jvmci_specific_flags();
 #endif
   // Check for consistency in the selection of the garbage collector.
   static bool check_gc_consistency();        // Check user-selected gc
--- a/src/share/vm/runtime/compilationPolicy.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/runtime/compilationPolicy.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -238,31 +238,17 @@
 // Note: this policy is used ONLY if TieredCompilation is off.
 // compiler_count() behaves the following way:
 // - with TIERED build (with both COMPILER1 and COMPILER2 defined) it should return
-//   zero for the c1 compilation levels, hence the particular ordering of the
-//   statements.
-// - the same should happen when COMPILER2 is defined and COMPILER1 is not
-//   (server build without TIERED defined).
-// - if only COMPILER1 is defined (client build), zero should be returned for
-//   the c2 level.
+//   zero for the c1 compilation levels in server compilation mode runs
+//   and c2 compilation levels in client compilation mode runs.
+// - with COMPILER2 not defined it should return zero for c2 compilation levels.
+// - with COMPILER1 not defined it should return zero for c1 compilation levels.
 // - if neither is defined - always return zero.
 int NonTieredCompPolicy::compiler_count(CompLevel comp_level) {
   assert(!TieredCompilation, "This policy should not be used with TieredCompilation");
-#ifdef COMPILER2
-  if (is_c2_compile(comp_level)) {
+  if (COMPILER2_PRESENT(is_server_compilation_mode_vm() && is_c2_compile(comp_level) ||)
+      is_client_compilation_mode_vm() && is_c1_compile(comp_level)) {
     return _compiler_count;
-  } else {
-    return 0;
   }
-#endif
-
-#ifdef COMPILER1
-  if (is_c1_compile(comp_level)) {
-    return _compiler_count;
-  } else {
-    return 0;
-  }
-#endif
-
   return 0;
 }
 
--- a/src/share/vm/runtime/globals.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/runtime/globals.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -469,14 +469,18 @@
   }
 
   if (!printRanges) {
+    // Use some named constants to make code more readable.
+    const unsigned int nSpaces    = 10;
+    const unsigned int maxFlagLen = 40 + nSpaces;
+
     // The print below assumes that the flag name is 40 characters or less.
     // This works for most flags, but there are exceptions. Our longest flag
     // name right now is UseAdaptiveGenerationSizePolicyAtMajorCollection and
     // its minor collection buddy. These are 48 characters. We use a buffer of
-    // 10 spaces below to adjust the space between the flag value and the
+    // nSpaces spaces below to adjust the space between the flag value and the
     // column of flag type and origin that is printed in the end of the line.
-    char spaces[10 + 1] = "          ";
-    st->print("%9s %-40s = ", _type, _name);
+    char spaces[nSpaces + 1] = "          ";
+    st->print("%9s %-*s = ", _type, maxFlagLen-nSpaces, _name);
 
     if (is_bool()) {
       st->print("%-20s", get_bool() ? "true" : "false");
@@ -509,9 +513,12 @@
       }
       else st->print("%-20s", "");
     }
-    assert(strlen(_name) < 50, "Flag name is longer than expected");
-    spaces[50 - MAX2((size_t)40, strlen(_name))] = '\0';
-    st->print("%s", spaces);
+    // Make sure we do not punch a '\0' at a negative char array index.
+    unsigned int nameLen = (unsigned int)strlen(_name);
+    if (nameLen <= maxFlagLen) {
+      spaces[maxFlagLen - MAX2(maxFlagLen-nSpaces, nameLen)] = '\0';
+      st->print("%s", spaces);
+    }
     print_kind_and_origin(st);
 
 #ifndef PRODUCT
--- a/src/share/vm/runtime/os.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/runtime/os.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,7 @@
 #include "precompiled.hpp"
 #include "classfile/classLoader.hpp"
 #include "classfile/javaClasses.hpp"
+#include "classfile/moduleEntry.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "classfile/vmSymbols.hpp"
 #include "code/codeCache.hpp"
@@ -1229,7 +1230,7 @@
   FREE_C_HEAP_ARRAY(char, jimage);
 
   // check if developer build with exploded modules
-  char* base_classes = format_boot_path("%/modules/java.base", home, home_len, fileSep, pathSep);
+  char* base_classes = format_boot_path("%/modules/" JAVA_BASE_NAME, home, home_len, fileSep, pathSep);
   if (base_classes == NULL) return false;
   if (os::stat(base_classes, &st) == 0) {
     Arguments::set_sysclasspath(base_classes, false);
--- a/src/share/vm/runtime/reflection.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/runtime/reflection.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -534,22 +534,26 @@
     PackageEntry* package_to = new_class->package();
     assert(package_to != NULL, "can not obtain new_class' package");
 
-    // Once readability is established, if module_to exports T unqualifiedly,
-    // (to all modules), than whether module_from is in the unnamed module
-    // or not does not matter, access is allowed.
-    if (package_to->is_unqual_exported()) {
-      return ACCESS_OK;
-    }
+    {
+      MutexLocker m1(Module_lock);
 
-    // Access is allowed if both 1 & 2 hold:
-    //   1. Readability, module_from can read module_to (established above).
-    //   2. Either module_to exports T to module_from qualifiedly.
-    //      or
-    //      module_to exports T to all unnamed modules and module_from is unnamed.
-    //      or
-    //      module_to exports T unqualifiedly to all modules (checked above).
-    if (!package_to->is_qexported_to(module_from)) {
-      return TYPE_NOT_EXPORTED;
+      // Once readability is established, if module_to exports T unqualifiedly,
+      // (to all modules), than whether module_from is in the unnamed module
+      // or not does not matter, access is allowed.
+      if (package_to->is_unqual_exported()) {
+        return ACCESS_OK;
+      }
+
+      // Access is allowed if both 1 & 2 hold:
+      //   1. Readability, module_from can read module_to (established above).
+      //   2. Either module_to exports T to module_from qualifiedly.
+      //      or
+      //      module_to exports T to all unnamed modules and module_from is unnamed.
+      //      or
+      //      module_to exports T unqualifiedly to all modules (checked above).
+      if (!package_to->is_qexported_to(module_from)) {
+        return TYPE_NOT_EXPORTED;
+      }
     }
     return ACCESS_OK;
   }
--- a/src/share/vm/runtime/vframe_hp.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/runtime/vframe_hp.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -158,7 +158,7 @@
     deferred =  new(ResourceObj::C_HEAP, mtCompiler) GrowableArray<jvmtiDeferredLocalVariableSet*> (1, true);
     thread()->set_deferred_locals(deferred);
   }
-  deferred->push(new jvmtiDeferredLocalVariableSet(method(), bci(), fr().id()));
+  deferred->push(new jvmtiDeferredLocalVariableSet(method(), bci(), fr().id(), vframe_id()));
   assert(deferred->top()->id() == fr().id(), "Huh? Must match");
   deferred->top()->set_local_at(index, type, value);
 }
@@ -243,6 +243,7 @@
 compiledVFrame::compiledVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread, CompiledMethod* nm)
 : javaVFrame(fr, reg_map, thread) {
   _scope  = NULL;
+  _vframe_id = 0;
   // Compiled method (native stub or Java code)
   // native wrappers have no scope data, it is implied
   if (!nm->is_compiled() || !nm->as_compiled_method()->is_native_method()) {
@@ -250,9 +251,10 @@
   }
 }
 
-compiledVFrame::compiledVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread, ScopeDesc* scope)
+compiledVFrame::compiledVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread, ScopeDesc* scope, int vframe_id)
 : javaVFrame(fr, reg_map, thread) {
   _scope  = scope;
+  _vframe_id = vframe_id;
   guarantee(_scope != NULL, "scope must be present");
 }
 
@@ -316,14 +318,15 @@
   } else {
     return scope()->is_top()
       ? vframe::sender()
-      : new compiledVFrame(&f, register_map(), thread(), scope()->sender());
+      : new compiledVFrame(&f, register_map(), thread(), scope()->sender(), vframe_id() + 1);
   }
 }
 
-jvmtiDeferredLocalVariableSet::jvmtiDeferredLocalVariableSet(Method* method, int bci, intptr_t* id) {
+jvmtiDeferredLocalVariableSet::jvmtiDeferredLocalVariableSet(Method* method, int bci, intptr_t* id, int vframe_id) {
   _method = method;
   _bci = bci;
   _id = id;
+  _vframe_id = vframe_id;
   // Alway will need at least one, must be on C heap
   _locals = new(ResourceObj::C_HEAP, mtCompiler) GrowableArray<jvmtiDeferredLocalVariable*> (1, true);
 }
@@ -339,7 +342,11 @@
 bool jvmtiDeferredLocalVariableSet::matches(vframe* vf) {
   if (!vf->is_compiled_frame()) return false;
   compiledVFrame* cvf = (compiledVFrame*)vf;
-  return cvf->fr().id() == id() && cvf->method() == method() && cvf->bci() == bci();
+  if (cvf->fr().id() == id() && cvf->vframe_id() == vframe_id()) {
+    assert(cvf->method() == method() && cvf->bci() == bci(), "must agree");
+    return true;
+  }
+  return false;
 }
 
 void jvmtiDeferredLocalVariableSet::set_local_at(int idx, BasicType type, jvalue val) {
--- a/src/share/vm/runtime/vframe_hp.hpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/runtime/vframe_hp.hpp	Sat Feb 04 03:29:40 2017 +0100
@@ -36,6 +36,7 @@
   StackValueCollection*        locals()             const;
   StackValueCollection*        expressions()        const;
   GrowableArray<MonitorInfo*>* monitors()           const;
+  int                          vframe_id()          const { return _vframe_id; }
 
   void set_locals(StackValueCollection* values) const;
 
@@ -68,14 +69,14 @@
 
  protected:
   ScopeDesc* _scope;
-
+  int _vframe_id;
 
   //StackValue resolve(ScopeValue* sv) const;
   BasicLock* resolve_monitor_lock(Location location) const;
   StackValue *create_stack_value(ScopeValue *sv) const;
 
  private:
-  compiledVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread, ScopeDesc* scope);
+  compiledVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread, ScopeDesc* scope, int vframe_id);
 
 #ifndef PRODUCT
  public:
@@ -95,6 +96,7 @@
   Method* _method;
   int       _bci;
   intptr_t* _id;
+  int _vframe_id;
   GrowableArray<jvmtiDeferredLocalVariable*>* _locals;
 
  public:
@@ -102,6 +104,7 @@
   Method*                           method()         const  { return _method; }
   int                               bci()            const  { return _bci; }
   intptr_t*                         id()             const  { return _id; }
+  int                               vframe_id()      const  { return _vframe_id; }
   GrowableArray<jvmtiDeferredLocalVariable*>* locals()         const  { return _locals; }
   void                              set_local_at(int idx, BasicType typ, jvalue val);
 
@@ -111,7 +114,7 @@
   void                              oops_do(OopClosure* f);
 
   // constructor
-  jvmtiDeferredLocalVariableSet(Method* method, int bci, intptr_t* id);
+  jvmtiDeferredLocalVariableSet(Method* method, int bci, intptr_t* id, int vframe_id);
 
   // destructor
   ~jvmtiDeferredLocalVariableSet();
--- a/src/share/vm/runtime/vmStructs.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/runtime/vmStructs.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -2453,7 +2453,6 @@
   /* ConstMethod anon-enum */                                             \
   /********************************/                                      \
                                                                           \
-  declare_constant(Method::_jfr_towrite)                                  \
   declare_constant(Method::_caller_sensitive)                             \
   declare_constant(Method::_force_inline)                                 \
   declare_constant(Method::_dont_inline)                                  \
--- a/src/share/vm/runtime/vm_version.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/runtime/vm_version.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -131,19 +131,32 @@
       return UseSharedSpaces ? "interpreted mode, sharing" : "interpreted mode";
     case Arguments::_mixed:
       if (UseSharedSpaces) {
-          if (UseAOT) {
-            return "mixed mode, aot, sharing";
-          } else {
-            return "mixed mode, sharing";
-          }
+        if (UseAOT) {
+          return "mixed mode, aot, sharing";
+#ifdef TIERED
+        } else if(is_client_compilation_mode_vm()) {
+          return "mixed mode, emulated-client, sharing";
+#endif
+        } else {
+          return "mixed mode, sharing";
+         }
       } else {
         if (UseAOT) {
           return "mixed mode, aot";
+#ifdef TIERED
+        } else if(is_client_compilation_mode_vm()) {
+          return "mixed mode, emulated-client";
+#endif
         } else {
           return "mixed mode";
         }
       }
     case Arguments::_comp:
+#ifdef TIERED
+      if (is_client_compilation_mode_vm()) {
+         return UseSharedSpaces ? "compiled mode, emulated-client, sharing" : "compiled mode, emulated-client";
+      }
+#endif
       return UseSharedSpaces ? "compiled mode, sharing"    : "compiled mode";
   };
   ShouldNotReachHere();
--- a/src/share/vm/services/diagnosticCommand.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/services/diagnosticCommand.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -292,7 +292,7 @@
       char *opt = (char *)os::malloc(opt_len, mtInternal);
       if (opt == NULL) {
         output()->print_cr("JVMTI agent attach failed: "
-                           "Could not allocate %zu bytes for argument.",
+                           "Could not allocate " SIZE_FORMAT " bytes for argument.",
                            opt_len);
         return;
       }
--- a/src/share/vm/trace/traceMacros.hpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/trace/traceMacros.hpp	Sat Feb 04 03:29:40 2017 +0100
@@ -55,6 +55,8 @@
 #define TRACE_DEFINE_THREAD_ID_SIZE typedef int ___IGNORED_hs_trace_type6
 #define TRACE_DEFINE_THREAD_DATA_WRITER_OFFSET typedef int ___IGNORED_hs_trace_type7
 #define TRACE_THREAD_DATA_WRITER_OFFSET in_ByteSize(0); ShouldNotReachHere()
+#define TRACE_DEFINE_FLAG typedef int ___IGNORED_hs_trace_type8
+#define TRACE_DEFINE_FLAG_ACCESSOR typedef int ___IGNORED_hs_trace_type9
 #define TRACE_TEMPLATES(template)
 #define TRACE_INTRINSICS(do_intrinsic, do_class, do_name, do_signature, do_alias)
 
--- a/src/share/vm/utilities/copy.cpp	Fri Feb 03 15:20:05 2017 +0100
+++ b/src/share/vm/utilities/copy.cpp	Sat Feb 04 03:29:40 2017 +0100
@@ -214,7 +214,7 @@
     case 2: do_conjoint_swap<uint16_t,D>(src, dst, byte_count); break;
     case 4: do_conjoint_swap<uint32_t,D>(src, dst, byte_count); break;
     case 8: do_conjoint_swap<uint64_t,D>(src, dst, byte_count); break;
-    default: guarantee(false, "do_conjoint_swap: Invalid elem_size %zd\n", elem_size);
+    default: guarantee(false, "do_conjoint_swap: Invalid elem_size " SIZE_FORMAT "\n", elem_size);
     }
   }
 };
--- a/test/ProblemList.txt	Fri Feb 03 15:20:05 2017 +0100
+++ b/test/ProblemList.txt	Sat Feb 04 03:29:40 2017 +0100
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -55,7 +55,7 @@
 
 gc/g1/humongousObjects/objectGraphTest/TestObjectGraphAfterGC.java 8156755 generic-all
 gc/survivorAlignment/TestPromotionToSurvivor.java 8129886 generic-all
-gc/stress/TestStressG1Humongous.java 8171045 generic-all
+gc/g1/logging/TestG1LoggingFailure.java 8169634 generic-all
 
 #############################################################################
 
@@ -78,5 +78,7 @@
 
 # :hotspot_misc
 
+testlibrary_tests/ctw/JarDirTest.java 8172457 windows-all
+
 #############################################################################
 
--- a/test/TEST.ROOT	Fri Feb 03 15:20:05 2017 +0100
+++ b/test/TEST.ROOT	Sat Feb 04 03:29:40 2017 +0100
@@ -46,6 +46,8 @@
     vm.gc.Parallel \
     vm.gc.ConcMarkSweep \
     vm.jvmci \
+    vm.emulatedClient \
+    vm.cpu.features \
     vm.debug
 
 # Tests using jtreg 4.2 b04 features
--- a/test/compiler/aot/AotCompiler.java	Fri Feb 03 15:20:05 2017 +0100
+++ b/test/compiler/aot/AotCompiler.java	Sat Feb 04 03:29:40 2017 +0100
@@ -69,7 +69,7 @@
         extraopts.add("-classpath");
         extraopts.add(Utils.TEST_CLASS_PATH + File.pathSeparator + Utils.TEST_SRC);
         if (className != null && libName != null) {
-            OutputAnalyzer oa = launchCompiler(libName, className + ".class", extraopts, compileList);
+            OutputAnalyzer oa = launchCompiler(libName, className, extraopts, compileList);
             oa.shouldHaveExitValue(0);
         } else {
             printUsage();
@@ -93,12 +93,14 @@
             }
         }
         List<String> args = new ArrayList<>();
+        args.add("--compile-with-assertions");
         args.add("--output");
         args.add(libName);
         if (file != null) {
             args.add("--compile-commands");
             args.add(file.toString());
         }
+        args.add("--class-name");
         args.add(item);
         return launchJaotc(args, extraopts);
     }
--- a/test/compiler/aot/RecompilationTest.java	Fri Feb 03 15:20:05 2017 +0100
+++ b/test/compiler/aot/RecompilationTest.java	Sat Feb 04 03:29:40 2017 +0100
@@ -33,6 +33,7 @@
  * @run main compiler.aot.AotCompiler -libname libRecompilationTest1.so
  *     -class compiler.whitebox.SimpleTestCaseHelper
  *     -extraopt -Dgraal.TieredAOT=true -extraopt -Dgraal.ProfileSimpleMethods=true
+ *     -extraopt -Dgraal.ProbabilisticProfiling=false
  *     -extraopt -XX:+UnlockDiagnosticVMOptions -extraopt -XX:+WhiteBoxAPI -extraopt -Xbootclasspath/a:.
  *     -extraopt -XX:-UseCompressedOops
  *     -extraopt -XX:CompileCommand=dontinline,compiler.whitebox.SimpleTestCaseHelper::*
--- a/test/compiler/aot/cli/jaotc/ClasspathOptionTest.java	Fri Feb 03 15:20:05 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2016, 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
- * @library / /test/lib /testlibrary
- * @modules java.base/jdk.internal.misc
- * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
- * @build compiler.aot.cli.jaotc.ClasspathOptionTest
- * @run driver ClassFileInstaller compiler.aot.cli.jaotc.data.HelloWorldOne
- * @run driver compiler.aot.cli.jaotc.ClasspathOptionTest
- * @summary check jaotc can compile class from classpath
- */
-
-package compiler.aot.cli.jaotc;
-
-import compiler.aot.cli.jaotc.data.HelloWorldOne;
-import java.io.File;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import jdk.test.lib.Asserts;
-import jdk.test.lib.process.OutputAnalyzer;
-
-public class ClasspathOptionTest {
-    public static void main(String[] args) {
-        Path cp = Paths.get("testClasspath");
-        try {
-            Files.createDirectory(cp);
-            Files.move(Paths.get("compiler"), cp.resolve("compiler"));
-        } catch (IOException e) {
-            throw new Error("TESTBUG: can't create test data " + e, e);
-        }
-        OutputAnalyzer oa = JaotcTestHelper.compileLibrary("--classpath", cp.toString(),
-                JaotcTestHelper.getClassAotCompilationName(HelloWorldOne.class));
-        oa.shouldHaveExitValue(0);
-        File compiledLibrary = new File(JaotcTestHelper.DEFAULT_LIB_PATH);
-        Asserts.assertTrue(compiledLibrary.exists(), "Compiled library file missing");
-        Asserts.assertGT(compiledLibrary.length(), 0L, "Unexpected compiled library size");
-        JaotcTestHelper.checkLibraryUsage(HelloWorldOne.class.getName());
-    }
-}
--- a/test/compiler/aot/cli/jaotc/ClasspathOptionUnknownClassTest.java	Fri Feb 03 15:20:05 2017 +0100
+++ b/test/compiler/aot/cli/jaotc/ClasspathOptionUnknownClassTest.java	Sat Feb 04 03:29:40 2017 +0100
@@ -39,7 +39,7 @@
 
 public class ClasspathOptionUnknownClassTest {
     public static void main(String[] args) {
-        OutputAnalyzer oa = JaotcTestHelper.compileLibrary("HelloWorldOne.class");
+        OutputAnalyzer oa = JaotcTestHelper.compileLibrary("--class-name", "HelloWorldOne");
         Asserts.assertNE(oa.getExitValue(), 0, "Unexpected compilation exit code");
         File compiledLibrary = new File(JaotcTestHelper.DEFAULT_LIB_PATH);
         Asserts.assertFalse(compiledLibrary.exists(), "Compiler library unexpectedly exists");
--- a/test/compiler/aot/cli/jaotc/CompileClassTest.java	Fri Feb 03 15:20:05 2017 +0100
+++ b/test/compiler/aot/cli/jaotc/CompileClassTest.java	Sat Feb 04 03:29:40 2017 +0100
@@ -41,7 +41,7 @@
 
 public class CompileClassTest {
     public static void main(String[] args) {
-        OutputAnalyzer oa = JaotcTestHelper.compileLibrary(JaotcTestHelper
+        OutputAnalyzer oa = JaotcTestHelper.compileLibrary("--class-name", JaotcTestHelper
                 .getClassAotCompilationName(HelloWorldOne.class));
         oa.shouldHaveExitValue(0);
         File compiledLibrary = new File(JaotcTestHelper.DEFAULT_LIB_PATH);
--- a/test/compiler/aot/cli/jaotc/CompileDirectoryTest.java	Fri Feb 03 15:20:05 2017 +0100
+++ b/test/compiler/aot/cli/jaotc/CompileDirectoryTest.java	Sat Feb 04 03:29:40 2017 +0100
@@ -42,7 +42,7 @@
 
 public class CompileDirectoryTest {
     public static void main(String[] args) {
-        OutputAnalyzer oa =JaotcTestHelper.compileLibrary(".");
+        OutputAnalyzer oa =JaotcTestHelper.compileLibrary("--directory", ".");
         oa.shouldHaveExitValue(0);
         File compiledLibrary = new File(JaotcTestHelper.DEFAULT_LIB_PATH);
         Asserts.assertTrue(compiledLibrary.exists(), "Compiled library file missing");
--- a/test/compiler/aot/cli/jaotc/CompileJarTest.java	Fri Feb 03 15:20:05 2017 +0100
+++ b/test/compiler/aot/cli/jaotc/CompileJarTest.java	Sat Feb 04 03:29:40 2017 +0100
@@ -48,7 +48,7 @@
 
     public static void main(String[] args) {
         createJar();
-        OutputAnalyzer oa = JaotcTestHelper.compileLibrary(JAR_NAME);
+        OutputAnalyzer oa = JaotcTestHelper.compileLibrary("--jar", JAR_NAME);
         oa.shouldHaveExitValue(0);
         File compiledLibrary = new File(JaotcTestHelper.DEFAULT_LIB_PATH);
         Asserts.assertTrue(compiledLibrary.exists(), "Compiled library file missing");
--- a/test/compiler/aot/cli/jaotc/JaotcTestHelper.java	Fri Feb 03 15:20:05 2017 +0100
+++ b/test/compiler/aot/cli/jaotc/JaotcTestHelper.java	Sat Feb 04 03:29:40 2017 +0100
@@ -44,6 +44,7 @@
         for (String vmOpt : Utils.getTestJavaOpts()) {
             launcher.addVMArg(vmOpt);
         }
+        launcher.addToolArg("--compile-with-assertions");
         for (String arg : args) {
             launcher.addToolArg(arg);
         }
@@ -70,7 +71,11 @@
         }
     }
 
-    public static String getClassAotCompilationName(Class<?> classToCompile) {
+    public static String getClassAotCompilationFilename(Class<?> classToCompile) {
         return classToCompile.getName().replaceAll("\\.", File.separator) + ".class";
     }
+
+    public static String getClassAotCompilationName(Class<?> classToCompile) {
+        return classToCompile.getName();
+    }
 }
--- a/test/compiler/aot/cli/jaotc/ListOptionNotExistingTest.java	Fri Feb 03 15:20:05 2017 +0100
+++ b/test/compiler/aot/cli/jaotc/ListOptionNotExistingTest.java	Sat Feb 04 03:29:40 2017 +0100
@@ -45,7 +45,7 @@
 
     public static void main(String[] args) {
         OutputAnalyzer oa = JaotcTestHelper.compileLibrary("--compile-commands", "./notExisting.list",
-                COMPILE_ITEM);
+                "--class-name", COMPILE_ITEM);
         int exitCode = oa.getExitValue();
         Asserts.assertNE(exitCode, 0, "Unexpected compilation exit code");
         File compiledLibrary = new File(JaotcTestHelper.DEFAULT_LIB_PATH);
--- a/test/compiler/aot/cli/jaotc/ListOptionTest.java	Fri Feb 03 15:20:05 2017 +0100
+++ b/test/compiler/aot/cli/jaotc/ListOptionTest.java	Sat Feb 04 03:29:40 2017 +0100
@@ -66,7 +66,7 @@
             throw new Error("TESTBUG: can't write list file " + e, e);
         }
         OutputAnalyzer oa = JaotcTestHelper.compileLibrary("--compile-commands", COMPILE_COMMAND_FILE.toString(),
-                JaotcTestHelper.getClassAotCompilationName(HelloWorldOne.class));
+                "--class-name", JaotcTestHelper.getClassAotCompilationName(HelloWorldOne.class));
         oa.shouldHaveExitValue(0);
         File compiledLibrary = new File(JaotcTestHelper.DEFAULT_LIB_PATH);
         Asserts.assertTrue(compiledLibrary.exists(), "Compiled library file missing");
--- a/test/compiler/aot/cli/jaotc/ListOptionWrongFileTest.java	Fri Feb 03 15:20:05 2017 +0100
+++ b/test/compiler/aot/cli/jaotc/ListOptionWrongFileTest.java	Sat Feb 04 03:29:40 2017 +0100
@@ -49,12 +49,15 @@
     private static final String COMPILE_ITEM
             = JaotcTestHelper.getClassAotCompilationName(HelloWorldOne.class);
 
+    private static final String COMPILE_FILE
+            = JaotcTestHelper.getClassAotCompilationFilename(HelloWorldOne.class);
+
     public static void main(String[] args) {
         // expecting wrong file to be read but no compilation directive recognized, so, all compiled
-        OutputAnalyzer oa = JaotcTestHelper.compileLibrary("--compile-commands", COMPILE_ITEM, COMPILE_ITEM);
+        OutputAnalyzer oa = JaotcTestHelper.compileLibrary("--compile-commands", COMPILE_FILE, "--class-name", COMPILE_ITEM);
         oa.shouldHaveExitValue(0);
         File compiledLibrary = new File(JaotcTestHelper.DEFAULT_LIB_PATH);
-        Asserts.assertTrue(compiledLibrary.exists(), "Expecte compiler library to exist");
+        Asserts.assertTrue(compiledLibrary.exists(), "Expected compiler library to exist");
         JaotcTestHelper.checkLibraryUsage(HelloWorldOne.class.getName(), EXPECTED, null);
     }
 }
--- a/test/compiler/aot/fingerprint/CDSDumper.java	Fri Feb 03 15:20:05 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2016, 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 compiler.aot.fingerprint;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.PrintStream;
-
-import jdk.test.lib.process.OutputAnalyzer;
-import jdk.test.lib.process.ProcessTools;
-
-// Usage:
-// java CDSDumper <classpath> <classlist> <archive> <class1> <class2> ...
-public class CDSDumper {
-    public static void main(String[] args) throws Exception {
-        String classpath = args[0];
-        String classlist = args[1];
-        String archive = args[2];
-
-        // Prepare the classlist
-        FileOutputStream fos = new FileOutputStream(classlist);
-        PrintStream ps = new PrintStream(fos);
-
-        for (int i=3; i<args.length; i++) {
-            ps.println(args[i].replace('.', '/'));
-        }
-        ps.close();
-        fos.close();
-
-        // Dump the archive
-        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
-            "-XX:+UnlockCommercialFeatures",
-            "-XX:+UseAppCDS",
-            "-XX:+UnlockDiagnosticVMOptions",
-            "-cp", classpath,
-            "-XX:ExtraSharedClassListFile=" + classlist,
-            "-XX:SharedArchiveFile=" + archive,
-            "-Xshare:dump",
-            "-XX:+PrintSharedSpaces");
-
-        OutputAnalyzer output = new OutputAnalyzer(pb.start());
-        output.shouldContain("Loading classes to share");
-        output.shouldHaveExitValue(0);
-    }
-}
--- a/test/compiler/aot/fingerprint/CDSRunner.java	Fri Feb 03 15:20:05 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2016, 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 compiler.aot.fingerprint;
-
-import jdk.test.lib.process.OutputAnalyzer;
-import jdk.test.lib.process.ProcessTools;
-
-// Usage:
-// java CDSRunner <vmargs> <class> <args> ...
-public class CDSRunner {
-    public static void main(String[] args) throws Exception {
-        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(args);
-        OutputAnalyzer output = new OutputAnalyzer(pb.start());
-
-        System.out.println("[stdout = " + output.getStdout() + "]");
-        System.out.println("[stderr = " + output.getStderr() + "]");
-
-        output.shouldContain("PASSED");
-        output.shouldHaveExitValue(0);
-    }
-}
--- a/test/compiler/aot/fingerprint/SelfChanged.java	Fri Feb 03 15:20:05 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,130 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @summary AOT methods should be swept if a super class has changed.
- * @library /test/lib /
- * @modules java.base/jdk.internal.misc
- *          java.management
- * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
- * @build compiler.aot.fingerprint.SelfChanged
- *        compiler.aot.AotCompiler
- *
- * @run main
- *      compiler.aot.fingerprint.SelfChanged WRITE-UNMODIFIED-CLASS
- * @run main/othervm compiler.aot.AotCompiler -libname libSelfChanged.so
- *      -class compiler.aot.fingerprint.Blah
- *
- * @run main/othervm
- *      compiler.aot.fingerprint.SelfChanged TEST-UNMODIFIED
- * @run main/othervm -XX:+UseAOT -XX:+PrintAOT -XX:AOTLibrary=./libSelfChanged.so
- *      -Xlog:aot+class+fingerprint=trace -Xlog:aot+class+load=trace
- *      compiler.aot.fingerprint.SelfChanged TEST-UNMODIFIED
- *
- * @run main
- *      compiler.aot.fingerprint.SelfChanged WRITE-MODIFIED-CLASS
- * @run main
- *      compiler.aot.fingerprint.SelfChanged TEST-MODIFIED
- * @run main/othervm -XX:+UseAOT -XX:+PrintAOT -XX:AOTLibrary=./libSelfChanged.so
- *      -Xlog:aot+class+fingerprint=trace -Xlog:aot+class+load=trace
- *      compiler.aot.fingerprint.SelfChanged TEST-MODIFIED
- */
-
-package compiler.aot.fingerprint;
-
-import jdk.test.lib.Asserts;
-import jdk.test.lib.InMemoryJavaCompiler;
-
-import java.io.*;
-
-class Blah {
-    volatile int z;
-    int getX() {
-        for (z = 0; z < 10000; z++) {
-            if (z % 7 == 1) {
-                z += 2;
-            }
-        }
-        return 0;
-    }
-}
-
-public class SelfChanged {
-    public static void main(String args[]) throws Throwable {
-        Blah f = new Blah();
-        System.out.println("f.getX = " + f.getX());
-        switch (args[0]) {
-        case "WRITE-UNMODIFIED-CLASS":
-            compileClass(false);
-            break;
-        case "WRITE-MODIFIED-CLASS":
-            compileClass(true);
-            break;
-        case "TEST-UNMODIFIED":
-            Asserts.assertTrue(f.getX() == 0, "getX from unmodified Blah class should return 0");
-            break;
-        case "TEST-MODIFIED":
-            Asserts.assertTrue(f.getX() == 1, "getX from modified Blah class should return 1");
-            break;
-        default:
-            throw new RuntimeException("unexpected option: " + args[0]);
-        }
-    }
-
-    static void compileClass(boolean isModified) throws Throwable {
-        String src =
-               "package compiler.aot.fingerprint;"
-             + "public class Blah {"
-             + "    volatile int z;"
-             + "    int getX() {"
-             + "        for (z = 0; z < 10000; z++) {"
-             + "            if (z % 7 == 1) {"
-             + "                z += 2;"
-             + "            }"
-             + "        }"
-             + "        return " + ((isModified) ? "1" : "0") + ";"
-             + "    }"
-             + "    int getY() {return 255;}"
-
-            // The following is for the SelfChangedCDS.java test case. We always load an unmodified
-            // version of Blah from the CDS archive. However, we would load an AOT library that
-            // was compiled using a modified version of Blah. The getX method in this AOT library should
-            // not be used.
-
-            + "    public static void main(String args[]) {"
-             + "        Blah b = new Blah();"
-             + "        int n = b.getX();"
-             + "        if (n != 0) {"
-