--- a/.hgtags Wed Mar 09 14:54:18 2016 +0100
+++ b/.hgtags Wed Mar 09 14:18:12 2016 +0100
@@ -350,3 +350,4 @@
db483b34fa7148d257a429acddbde9c13687dcae jdk-9+105
6c644cca3f3fc2763e2ff7d669849a75d34543ba jdk-9+106
1c076468bf7dad5b8f2ee5dcf66e2279caa3e208 jdk-9+107
+257b579d813201682931d6b42f0445ffe5b4210d jdk-9+108
--- a/.hgtags-top-repo Wed Mar 09 14:54:18 2016 +0100
+++ b/.hgtags-top-repo Wed Mar 09 14:18:12 2016 +0100
@@ -350,3 +350,4 @@
be58b02c11f90b88c67e4d0e2cb5e4cf2d9b3c57 jdk-9+105
54575d8783b3a39a2d710c28cda675d44261f9d9 jdk-9+106
4d65eba233a8730f913734a6804910b842d2cb54 jdk-9+107
+c7be2a78c31b3b6132f2f5e9e4b3d3bb1c20245c jdk-9+108
--- a/common/conf/jib-profiles.js Wed Mar 09 14:54:18 2016 +0100
+++ b/common/conf/jib-profiles.js Wed Mar 09 14:18:12 2016 +0100
@@ -311,6 +311,16 @@
labels: [ "open" ]
},
+ "linux-x86-open": {
+ target_os: mainProfiles["linux-x86"].target_os,
+ target_cpu: mainProfiles["linux-x86"].target_cpu,
+ dependencies: mainProfiles["linux-x86"].dependencies,
+ configure_args: concat(mainProfiles["linux-x86"].configure_args,
+ "--enable-openjdk-only"),
+ make_args: mainProfiles["linux-x86"].make_args,
+ labels: [ "open" ]
+ },
+
"solaris-x64-open": {
target_os: mainProfiles["solaris-x64"].target_os,
target_cpu: mainProfiles["solaris-x64"].target_cpu,
@@ -319,6 +329,16 @@
"--enable-openjdk-only"),
make_args: mainProfiles["solaris-x64"].make_args,
labels: [ "open" ]
+ },
+
+ "windows-x86-open": {
+ target_os: mainProfiles["windows-x86"].target_os,
+ target_cpu: mainProfiles["windows-x86"].target_cpu,
+ dependencies: mainProfiles["windows-x86"].dependencies,
+ configure_args: concat(mainProfiles["windows-x86"].configure_args,
+ "--enable-openjdk-only"),
+ make_args: mainProfiles["windows-x86"].make_args,
+ labels: [ "open" ]
}
};
profiles = concatObjects(profiles, jprtOpenProfiles);
--- a/corba/.hgtags Wed Mar 09 14:54:18 2016 +0100
+++ b/corba/.hgtags Wed Mar 09 14:18:12 2016 +0100
@@ -350,3 +350,4 @@
64006ae915b3aa85ac7e6fac679024d2da7fe526 jdk-9+105
8ec4f97943fe56f93e4621f622b56b7144c0181a jdk-9+106
49202432b69445164a42be7cbdf74ed5fce98157 jdk-9+107
+84f2862a25eb3232ff36c376b4e2bf2a83dfced3 jdk-9+108
--- a/hotspot/.hgtags Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/.hgtags Wed Mar 09 14:18:12 2016 +0100
@@ -510,3 +510,4 @@
266fa9bb5297bf02cb2a7b038b10a109817d2b48 jdk-9+105
7232de4c17c37f60aecec4f3191090bd3d41d334 jdk-9+106
c5146d4da417f76edfc43097d2e2ced042a65b4e jdk-9+107
+934f6793f5f7dca44f69b4559d525fa64b31840d jdk-9+108
--- a/hotspot/make/test/JtregNative.gmk Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/make/test/JtregNative.gmk Wed Mar 09 14:18:12 2016 +0100
@@ -48,6 +48,7 @@
$(HOTSPOT_TOPDIR)/test/runtime/SameObject \
$(HOTSPOT_TOPDIR)/test/compiler/floatingpoint/ \
$(HOTSPOT_TOPDIR)/test/compiler/calls \
+ $(HOTSPOT_TOPDIR)/test/compiler/native \
#
# Add conditional directories here when needed.
--- a/hotspot/src/cpu/aarch64/vm/aarch64.ad Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad Wed Mar 09 14:18:12 2016 +0100
@@ -1041,10 +1041,8 @@
bool is_card_mark_membar(const MemBarNode *barrier);
bool is_CAS(int opcode);
- 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 *leading_to_trailing(MemBarNode *leading);
+ MemBarNode *card_mark_to_leading(const MemBarNode *barrier);
MemBarNode *trailing_to_leading(const MemBarNode *trailing);
// predicates controlling emit of ldr<x>/ldar<x> and associated dmb
@@ -1418,23 +1416,28 @@
// leading MemBarRelease and a trailing MemBarVolatile as follows
//
// MemBarRelease
- // { || } -- optional
+ // { || } -- optional
// {MemBarCPUOrder}
- // || \\
- // || StoreX[mo_release]
- // | \ /
- // | MergeMem
- // | /
+ // || \\
+ // || StoreX[mo_release]
+ // | \ Bot / ???
+ // | MergeMem
+ // | /
// MemBarVolatile
//
// where
// || and \\ represent Ctl and Mem feeds via Proj nodes
// | \ and / indicate further routing of the Ctl and Mem feeds
//
- // 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.
+ // 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.
//
// with most GC configurations we with see this simple variant which
// includes a post-write barrier card mark.
@@ -1442,7 +1445,7 @@
// MemBarRelease______________________________
// || \\ Ctl \ \\
// || StoreN/P[mo_release] CastP2X StoreB/CM
- // | \ / . . . /
+ // | \ Bot / oop . . . /
// | MergeMem
// | /
// || /
@@ -1452,152 +1455,142 @@
// 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 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
+ // 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
//
// dmb ishst
// stlrb
//
- // 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
+ // 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
//
// MemBarRelease____________________________________________
// || \\ Ctl \ Ctl \ \\ Mem \
// || StoreN/P[mo_release] CastP2X If LoadB |
- // | \ / \ |
+ // | \ Bot / oop \ |
// | MergeMem . . . StoreB
// | / /
// || /
// MemBarVolatile
//
- // It is worth noting at this stage that both the above
+ // It is worth noting at this stage that all the above
// configurations can be uniquely identified by checking that the
// memory flow includes the following subgraph:
//
// MemBarRelease
// {MemBarCPUOrder}
- // | \ . . .
- // | StoreX[mo_release] . . .
- // | /
- // MergeMem
- // |
+ // | \ . . .
+ // | StoreX[mo_release] . . .
+ // Bot | / oop
+ // MergeMem
+ // |
// MemBarVolatile
//
- // 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
+ // 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
//
// MemBarRelease
// ||
// MemBarCPUOrder
- // || \\ . . .
- // || CompareAndSwapX
- // || |
- // || SCMemProj
- // | \ /
- // | MergeMem
- // | /
+ // | \\ . . .
+ // | CompareAndSwapX
+ // | |
+ // Bot | SCMemProj
+ // \ / Bot
+ // MergeMem
+ // /
// MemBarCPUOrder
// ||
// MemBarAcquire
//
// The same basic variations on this arrangement (mutatis mutandis)
- // 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
+ // 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
//
// MemBarVolatile (card mark)
// C | \ . . .
// | StoreCM . . .
// . . .
//
- // 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?
+ // 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?
//
// A CMS GC post-barrier wraps its card write (StoreCM) inside an If
// which selects conditonal execution based on the value loaded
@@ -1608,91 +1601,117 @@
// which looks like this
//
// MemBarRelease
- // 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
+ // 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 | / /
+ // | . . . | / /
// | MergeMem
- // | |
+ // | |
// MemBarVolatile (trailing)
//
- // 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.
+ // 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.
//
// MemBarRelease
- // 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)
+ // 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)
//
// This has a slightly different memory subgraph to the one seen
- // previously but the core of it is the same as for the CAS normal
- // sungraph
+ // previously but the core of it has a similar memory flow to the
+ // CAS normal subgraph:
//
// MemBarRelease
// MemBarCPUOrder____
- // || \ . . .
- // MemBarVolatile CompareAndSwapX . . .
- // | \ |
- // . . . SCMemProj
- // | / . . .
- // MergeMem
- // |
+ // | \ . . .
+ // | CompareAndSwapX . . .
+ // | C / M |
+ // | CmpI |
+ // | / |
+ // | . . /
+ // Bot | IfTrue /
+ // | / /
+ // MemBarVolatile /
+ // | ... /
+ // StoreCM ... /
+ // | /
+ // . . . SCMemProj
+ // Raw \ / Bot
+ // MergeMem
+ // |
// MemBarCPUOrder
// MemBarAcquire
//
- //
- // 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 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.
//
// 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
@@ -1730,25 +1749,60 @@
// | 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.
//
- // 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 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)
//
// 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 form the
+ // the card mark membar is omitted and the memory feeds from 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.
@@ -1770,94 +1824,106 @@
//
// (pre-write subtree elided)
// . . . . . . . . . . . .
- // 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).
+ // 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.
//
// The predicates controlling generation of instructions for store
// and barrier nodes employ a few simple helper functions (described
@@ -1878,24 +1944,24 @@
opcode == Op_CompareAndSwapP);
}
- // leading_to_normal
+ // leading_to_trailing
//
//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
- // MemBarCPUOrder {leading}
- // | \ . . .
- // | StoreN/P[mo_release] . . .
- // | /
- // MergeMem
- // |
- // MemBarVolatile {trailing or card mark}
- //
- // MemBarRelease
- // MemBarCPUOrder {leading}
+ // MemBarRelease {leading}
+ // {MemBarCPUOrder} {optional}
+ // Bot | \ . . .
+ // | StoreN/P[mo_release] . . .
+ // | /
+ // MergeMem
+ // |
+ // MemBarVolatile {not card mark}
+ //
+ // MemBarRelease {leading}
+ // {MemBarCPUOrder} {optional}
// | \ . . .
// | CompareAndSwapX . . .
// |
@@ -1906,6 +1972,23 @@
// 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.
//
@@ -1916,7 +1999,7 @@
// the returned value may be a card mark or trailing membar
//
- MemBarNode *leading_to_normal(MemBarNode *leading)
+ MemBarNode *leading_to_trailing(MemBarNode *leading)
{
assert((leading->Opcode() == Op_MemBarRelease ||
leading->Opcode() == Op_MemBarCPUOrder),
@@ -1933,15 +2016,21 @@
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) {
- return NULL;
+ if (mm2 != NULL) {
+ // should not see more than 2 merge mems
+ return NULL;
+ } else {
+ mm2 = x->as_MergeMem();
+ }
+ } else {
+ mm = x->as_MergeMem();
}
- // 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) {
@@ -1961,13 +2050,13 @@
return NULL;
}
- // must have a merge if we also have st
+ // must have at least one 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);
@@ -1987,10 +2076,29 @@
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 {
- // ensure the store feeds the existing mergemem;
+ Node *y = NULL;
+ // ensure the store feeds the first mergemem;
for (DUIterator_Fast imax, i = st->fast_outs(imax); i < imax; i++) {
if (st->fast_out(i) == mm) {
y = st;
@@ -2000,55 +2108,89 @@
if (y == NULL) {
return NULL;
}
- }
-
- 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 (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;
}
}
- break;
+ if (y == NULL) {
+ return NULL;
+ }
+ }
+
+ 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;
}
- }
-
- return mbar;
- }
-
- // normal_to_leading
+ // 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
//
// graph traversal helper which detects the normal case Mem feed
- // 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}
+ // 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}
// | \ . . .
// | CompareAndSwapX . . .
// |
// . . . SCMemProj
// \ |
// | MergeMem
- // | /
+ // | |
// MemBarCPUOrder
// MemBarAcquire {trailing}
//
@@ -2058,15 +2200,20 @@
// 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 but
- // need not be a card mark membar.
-
- MemBarNode *normal_to_leading(const MemBarNode *barrier)
+ // 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)
{
// 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;
@@ -2179,169 +2326,35 @@
return NULL;
}
- // 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 . . .
+ // 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}
+ // | . . .
// Bot | /
- // MergeMem
+ // MergeMem
// |
- // 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)
+ // 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)
{
// 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 = trailing->in(TypeFunc::Memory);
+ Node *x = barrier->in(TypeFunc::Memory);
if (!x->is_MergeMem()) {
return NULL;
}
@@ -2349,117 +2362,19 @@
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 *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) {
+ MemBarNode *leading = x->as_MemBar();
+
+ if (leading_membar(leading)) {
return leading;
}
- // 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
+ return NULL;
+ }
bool unnecessary_acquire(const Node *barrier)
{
@@ -2675,19 +2590,8 @@
}
// must start with a normal feed
- 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);
+ MemBarNode *trailing = leading_to_trailing(barrier);
+
return (trailing != NULL);
}
@@ -2709,7 +2613,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 hgraph.
+ // a trailing membar of a volatile put graph.
return (trailing_to_leading(mbvol) != NULL);
}
@@ -2759,20 +2663,9 @@
}
// does this lead a normal subgraph?
- 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);
+ MemBarNode *trailing = leading_to_trailing(barrier);
+
+ return (trailing != NULL);
}
// predicate controlling translation of CAS
@@ -2814,7 +2707,7 @@
"CAS not fed by cpuorder+release membar pair!");
// does this lead a normal subgraph?
- MemBarNode *mbar = leading_to_normal(barrier);
+ MemBarNode *mbar = leading_to_trailing(barrier);
assert(mbar != NULL, "CAS not embedded in normal graph!");
@@ -2835,48 +2728,27 @@
// 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
+ // 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
if (!UseConcMarkSweepGC || UseCondCardMark) {
return true;
}
- // if we are implementing volatile puts using barriers then the
- // object put as an str so we must insert the dmb ishst
+ // if we are implementing volatile puts using barriers then we must
+ // insert the dmb ishst
if (UseBarriersForVolatile) {
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);
+ // we must be using CMS with conditional card marking so we ahve to
+ // generate the StoreStore
+
+ return false;
}
@@ -13409,7 +13281,7 @@
__ fmovs($dst$$Register, as_FloatRegister($src$$reg));
%}
- ins_pipe(pipe_class_memory);
+ ins_pipe(fp_f2i);
%}
@@ -13427,7 +13299,7 @@
__ fmovs(as_FloatRegister($dst$$reg), $src$$Register);
%}
- ins_pipe(pipe_class_memory);
+ ins_pipe(fp_i2f);
%}
@@ -13445,7 +13317,7 @@
__ fmovd($dst$$Register, as_FloatRegister($src$$reg));
%}
- ins_pipe(pipe_class_memory);
+ ins_pipe(fp_d2l);
%}
@@ -13463,7 +13335,7 @@
__ fmovd(as_FloatRegister($dst$$reg), $src$$Register);
%}
- ins_pipe(pipe_class_memory);
+ ins_pipe(fp_l2d);
%}
@@ -14319,6 +14191,25 @@
ins_pipe(pipe_cmp_branch);
%}
+instruct cmpN_imm0_branch(cmpOp cmp, iRegN op1, immN0 op2, label labl, rFlagsReg cr) %{
+ match(If cmp (CmpN op1 op2));
+ predicate(n->in(1)->as_Bool()->_test._test == BoolTest::ne
+ || n->in(1)->as_Bool()->_test._test == BoolTest::eq);
+ effect(USE labl);
+
+ ins_cost(BRANCH_COST);
+ format %{ "cbw$cmp $op1, $labl" %}
+ ins_encode %{
+ Label* L = $labl$$label;
+ Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode;
+ if (cond == Assembler::EQ)
+ __ cbzw($op1$$Register, *L);
+ else
+ __ cbnzw($op1$$Register, *L);
+ %}
+ ins_pipe(pipe_cmp_branch);
+%}
+
instruct cmpP_narrowOop_imm0_branch(cmpOp cmp, iRegN oop, immP0 zero, label labl, rFlagsReg cr) %{
match(If cmp (CmpP (DecodeN oop) zero));
predicate(n->in(1)->as_Bool()->_test._test == BoolTest::ne
@@ -14911,19 +14802,19 @@
%}
instruct string_equals(iRegP_R1 str1, iRegP_R3 str2, iRegI_R4 cnt,
- iRegI_R0 result, iRegP_R10 tmp, rFlagsReg cr)
+ iRegI_R0 result, rFlagsReg cr)
%{
predicate(!CompactStrings);
match(Set result (StrEquals (Binary str1 str2) cnt));
- effect(KILL tmp, USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL cr);
-
- format %{ "String Equals $str1,$str2,$cnt -> $result // KILL $tmp" %}
+ effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL cr);
+
+ format %{ "String Equals $str1,$str2,$cnt -> $result" %}
ins_encode %{
// Count is in 8-bit bytes; non-Compact chars are 16 bits.
__ asrw($cnt$$Register, $cnt$$Register, 1);
- __ string_equals($str1$$Register, $str2$$Register,
- $cnt$$Register, $result$$Register,
- $tmp$$Register);
+ __ arrays_equals($str1$$Register, $str2$$Register,
+ $result$$Register, $cnt$$Register,
+ 2, /*is_string*/true);
%}
ins_pipe(pipe_class_memory);
%}
@@ -14937,9 +14828,10 @@
format %{ "Array Equals $ary1,ary2 -> $result // KILL $tmp" %}
ins_encode %{
- __ byte_arrays_equals($ary1$$Register, $ary2$$Register,
- $result$$Register, $tmp$$Register);
- %}
+ __ arrays_equals($ary1$$Register, $ary2$$Register,
+ $result$$Register, $tmp$$Register,
+ 1, /*is_string*/false);
+ %}
ins_pipe(pipe_class_memory);
%}
@@ -14952,12 +14844,14 @@
format %{ "Array Equals $ary1,ary2 -> $result // KILL $tmp" %}
ins_encode %{
- __ char_arrays_equals($ary1$$Register, $ary2$$Register,
- $result$$Register, $tmp$$Register);
+ __ arrays_equals($ary1$$Register, $ary2$$Register,
+ $result$$Register, $tmp$$Register,
+ 2, /*is_string*/false);
%}
ins_pipe(pipe_class_memory);
%}
+
// encode char[] to byte[] in ISO_8859_1
instruct encode_iso_array(iRegP_R2 src, iRegP_R1 dst, iRegI_R3 len,
vRegD_V0 Vtmp1, vRegD_V1 Vtmp2,
@@ -16608,7 +16502,7 @@
as_FloatRegister($src$$reg),
as_FloatRegister($shift$$reg));
%}
- ins_pipe(vshift64_imm);
+ ins_pipe(vshift64);
%}
instruct vsll4I(vecX dst, vecX src, vecX shift) %{
@@ -16622,7 +16516,7 @@
as_FloatRegister($src$$reg),
as_FloatRegister($shift$$reg));
%}
- ins_pipe(vshift128_imm);
+ ins_pipe(vshift128);
%}
instruct vsrl2I(vecD dst, vecD src, vecX shift) %{
@@ -16635,7 +16529,7 @@
as_FloatRegister($src$$reg),
as_FloatRegister($shift$$reg));
%}
- ins_pipe(vshift64_imm);
+ ins_pipe(vshift64);
%}
instruct vsrl4I(vecX dst, vecX src, vecX shift) %{
@@ -16648,7 +16542,7 @@
as_FloatRegister($src$$reg),
as_FloatRegister($shift$$reg));
%}
- ins_pipe(vshift128_imm);
+ ins_pipe(vshift128);
%}
instruct vsll2I_imm(vecD dst, vecD src, immI shift) %{
@@ -16766,7 +16660,7 @@
as_FloatRegister($src$$reg),
(int)$shift$$constant & 63);
%}
- ins_pipe(vshift128);
+ ins_pipe(vshift128_imm);
%}
instruct vsra2L_imm(vecX dst, vecX src, immI shift) %{
--- a/hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -74,7 +74,7 @@
void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset, TRAPS) {
address pc = _instructions->start() + pc_offset;
NativeInstruction* inst = nativeInstruction_at(pc);
- if (inst->is_adr_aligned()) {
+ if (inst->is_adr_aligned() || inst->is_ldr_literal()) {
address dest = _constants->start() + data_offset;
_instructions->relocate(pc, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS));
TRACE_jvmci_3("relocating at " PTR_FORMAT " (+%d) with destination at %d", p2i(pc), pc_offset, data_offset);
--- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -4481,224 +4481,125 @@
BLOCK_COMMENT("} string_compare");
}
-
-void MacroAssembler::string_equals(Register str1, Register str2,
- Register cnt, Register result,
- Register tmp1) {
- Label SAME_CHARS, DONE, SHORT_LOOP, SHORT_STRING,
- NEXT_WORD;
-
- const Register tmp2 = rscratch1;
- assert_different_registers(str1, str2, cnt, result, tmp1, tmp2, rscratch2);
-
- BLOCK_COMMENT("string_equals {");
-
- // Start by assuming that the strings are not equal.
- mov(result, zr);
-
- // A very short string
- cmpw(cnt, 4);
- br(Assembler::LT, SHORT_STRING);
-
- // Check if the strings start at the same location.
- cmp(str1, str2);
- br(Assembler::EQ, SAME_CHARS);
-
- // Compare longwords
- {
- subw(cnt, cnt, 4); // The last longword is a special case
-
- // Move both string pointers to the last longword of their
- // strings, negate the remaining count, and convert it to bytes.
- lea(str1, Address(str1, cnt, Address::uxtw(1)));
- lea(str2, Address(str2, cnt, Address::uxtw(1)));
- sub(cnt, zr, cnt, LSL, 1);
-
- // Loop, loading longwords and comparing them into rscratch2.
- bind(NEXT_WORD);
- ldr(tmp1, Address(str1, cnt));
- ldr(tmp2, Address(str2, cnt));
- adds(cnt, cnt, wordSize);
- eor(rscratch2, tmp1, tmp2);
- cbnz(rscratch2, DONE);
- br(Assembler::LT, NEXT_WORD);
-
- // Last longword. In the case where length == 4 we compare the
- // same longword twice, but that's still faster than another
- // conditional branch.
-
- ldr(tmp1, Address(str1));
- ldr(tmp2, Address(str2));
- eor(rscratch2, tmp1, tmp2);
- cbz(rscratch2, SAME_CHARS);
- b(DONE);
- }
-
- bind(SHORT_STRING);
- // Is the length zero?
- cbz(cnt, SAME_CHARS);
-
- bind(SHORT_LOOP);
- load_unsigned_short(tmp1, Address(post(str1, 2)));
- load_unsigned_short(tmp2, Address(post(str2, 2)));
- subw(tmp1, tmp1, tmp2);
- cbnz(tmp1, DONE);
- sub(cnt, cnt, 1);
- cbnz(cnt, SHORT_LOOP);
-
- // Strings are equal.
- bind(SAME_CHARS);
- mov(result, true);
-
- // That's it
- bind(DONE);
-
- BLOCK_COMMENT("} string_equals");
-}
-
-
-void MacroAssembler::byte_arrays_equals(Register ary1, Register ary2,
- Register result, Register tmp1)
+// Compare Strings or char/byte arrays.
+
+// is_string is true iff this is a string comparison.
+
+// For Strings we're passed the address of the first characters in a1
+// and a2 and the length in cnt1.
+
+// For byte and char arrays we're passed the arrays themselves and we
+// have to extract length fields and do null checks here.
+
+// elem_size is the element size in bytes: either 1 or 2.
+
+// There are two implementations. For arrays >= 8 bytes, all
+// comparisons (including the final one, which may overlap) are
+// performed 8 bytes at a time. For arrays < 8 bytes, we compare a
+// halfword, then a short, and then a byte.
+
+void MacroAssembler::arrays_equals(Register a1, Register a2,
+ Register result, Register cnt1,
+ int elem_size, bool is_string)
{
- Register cnt1 = rscratch1;
- Register cnt2 = rscratch2;
+ Label SAME, DONE, SHORT, NEXT_WORD, ONE;
+ Register tmp1 = rscratch1;
Register tmp2 = rscratch2;
-
- Label SAME, DIFFER, NEXT, TAIL07, TAIL03, TAIL01;
-
- int length_offset = arrayOopDesc::length_offset_in_bytes();
- int base_offset = arrayOopDesc::base_offset_in_bytes(T_BYTE);
-
- BLOCK_COMMENT("byte_arrays_equals {");
-
- // different until proven equal
- mov(result, false);
-
- // same array?
- cmp(ary1, ary2);
- br(Assembler::EQ, SAME);
-
- // ne if either null
- cbz(ary1, DIFFER);
- cbz(ary2, DIFFER);
-
- // lengths ne?
- ldrw(cnt1, Address(ary1, length_offset));
- ldrw(cnt2, Address(ary2, length_offset));
- cmp(cnt1, cnt2);
- br(Assembler::NE, DIFFER);
-
- lea(ary1, Address(ary1, base_offset));
- lea(ary2, Address(ary2, base_offset));
-
- subs(cnt1, cnt1, 8);
- br(LT, TAIL07);
-
- BIND(NEXT);
- ldr(tmp1, Address(post(ary1, 8)));
- ldr(tmp2, Address(post(ary2, 8)));
- subs(cnt1, cnt1, 8);
+ Register cnt2 = tmp2; // cnt2 only used in array length compare
+ int elem_per_word = wordSize/elem_size;
+ int log_elem_size = exact_log2(elem_size);
+ int length_offset = arrayOopDesc::length_offset_in_bytes();
+ int base_offset
+ = arrayOopDesc::base_offset_in_bytes(elem_size == 2 ? T_CHAR : T_BYTE);
+
+ assert(elem_size == 1 || elem_size == 2, "must be char or byte");
+ assert_different_registers(a1, a2, result, cnt1, rscratch1, rscratch2);
+
+ BLOCK_COMMENT(is_string ? "string_equals {" : "array_equals {");
+
+ mov(result, false);
+
+ if (!is_string) {
+ // if (a==a2)
+ // return true;
+ eor(rscratch1, a1, a2);
+ cbz(rscratch1, SAME);
+ // if (a==null || a2==null)
+ // return false;
+ cbz(a1, DONE);
+ cbz(a2, DONE);
+ // if (a1.length != a2.length)
+ // return false;
+ ldrw(cnt1, Address(a1, length_offset));
+ ldrw(cnt2, Address(a2, length_offset));
+ eorw(tmp1, cnt1, cnt2);
+ cbnzw(tmp1, DONE);
+
+ lea(a1, Address(a1, base_offset));
+ lea(a2, Address(a2, base_offset));
+ }
+
+ // Check for short strings, i.e. smaller than wordSize.
+ subs(cnt1, cnt1, elem_per_word);
+ br(Assembler::LT, SHORT);
+ // Main 8 byte comparison loop.
+ bind(NEXT_WORD); {
+ ldr(tmp1, Address(post(a1, wordSize)));
+ ldr(tmp2, Address(post(a2, wordSize)));
+ subs(cnt1, cnt1, elem_per_word);
eor(tmp1, tmp1, tmp2);
- cbnz(tmp1, DIFFER);
- br(GE, NEXT);
-
- BIND(TAIL07); // 0-7 bytes left, cnt1 = #bytes left - 4
- tst(cnt1, 0b100);
- br(EQ, TAIL03);
- ldrw(tmp1, Address(post(ary1, 4)));
- ldrw(tmp2, Address(post(ary2, 4)));
- cmp(tmp1, tmp2);
- br(NE, DIFFER);
-
- BIND(TAIL03); // 0-3 bytes left, cnt1 = #bytes left - 4
- tst(cnt1, 0b10);
- br(EQ, TAIL01);
- ldrh(tmp1, Address(post(ary1, 2)));
- ldrh(tmp2, Address(post(ary2, 2)));
- cmp(tmp1, tmp2);
- br(NE, DIFFER);
- BIND(TAIL01); // 0-1 byte left
- tst(cnt1, 0b01);
- br(EQ, SAME);
- ldrb(tmp1, ary1);
- ldrb(tmp2, ary2);
- cmp(tmp1, tmp2);
- br(NE, DIFFER);
-
- BIND(SAME);
- mov(result, true);
- BIND(DIFFER); // result already set
-
- BLOCK_COMMENT("} byte_arrays_equals");
+ cbnz(tmp1, DONE);
+ } br(GT, NEXT_WORD);
+ // Last longword. In the case where length == 4 we compare the
+ // same longword twice, but that's still faster than another
+ // conditional branch.
+ // cnt1 could be 0, -1, -2, -3, -4 for chars; -4 only happens when
+ // length == 4.
+ if (log_elem_size > 0)
+ lsl(cnt1, cnt1, log_elem_size);
+ ldr(tmp1, Address(a1, cnt1));
+ ldr(tmp2, Address(a2, cnt1));
+ eor(tmp1, tmp1, tmp2);
+ cbnz(tmp1, DONE);
+ b(SAME);
+
+ bind(SHORT);
+ Label TAIL03, TAIL01;
+
+ tbz(cnt1, 2 - log_elem_size, TAIL03); // 0-7 bytes left.
+ {
+ ldrw(tmp1, Address(post(a1, 4)));
+ ldrw(tmp2, Address(post(a2, 4)));
+ eorw(tmp1, tmp1, tmp2);
+ cbnzw(tmp1, DONE);
+ }
+ bind(TAIL03);
+ tbz(cnt1, 1 - log_elem_size, TAIL01); // 0-3 bytes left.
+ {
+ ldrh(tmp1, Address(post(a1, 2)));
+ ldrh(tmp2, Address(post(a2, 2)));
+ eorw(tmp1, tmp1, tmp2);
+ cbnzw(tmp1, DONE);
+ }
+ bind(TAIL01);
+ if (elem_size == 1) { // Only needed when comparing byte arrays.
+ tbz(cnt1, 0, SAME); // 0-1 bytes left.
+ {
+ ldrb(tmp1, a1);
+ ldrb(tmp2, a2);
+ eorw(tmp1, tmp1, tmp2);
+ cbnzw(tmp1, DONE);
+ }
+ }
+ // Arrays are equal.
+ bind(SAME);
+ mov(result, true);
+
+ // That's it.
+ bind(DONE);
+ BLOCK_COMMENT(is_string ? "} string_equals" : "} array_equals");
}
-// Compare char[] arrays aligned to 4 bytes
-void MacroAssembler::char_arrays_equals(Register ary1, Register ary2,
- Register result, Register tmp1)
-{
- Register cnt1 = rscratch1;
- Register cnt2 = rscratch2;
- Register tmp2 = rscratch2;
-
- Label SAME, DIFFER, NEXT, TAIL03, TAIL01;
-
- int length_offset = arrayOopDesc::length_offset_in_bytes();
- int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR);
-
- BLOCK_COMMENT("char_arrays_equals {");
-
- // different until proven equal
- mov(result, false);
-
- // same array?
- cmp(ary1, ary2);
- br(Assembler::EQ, SAME);
-
- // ne if either null
- cbz(ary1, DIFFER);
- cbz(ary2, DIFFER);
-
- // lengths ne?
- ldrw(cnt1, Address(ary1, length_offset));
- ldrw(cnt2, Address(ary2, length_offset));
- cmp(cnt1, cnt2);
- br(Assembler::NE, DIFFER);
-
- lea(ary1, Address(ary1, base_offset));
- lea(ary2, Address(ary2, base_offset));
-
- subs(cnt1, cnt1, 4);
- br(LT, TAIL03);
-
- BIND(NEXT);
- ldr(tmp1, Address(post(ary1, 8)));
- ldr(tmp2, Address(post(ary2, 8)));
- subs(cnt1, cnt1, 4);
- eor(tmp1, tmp1, tmp2);
- cbnz(tmp1, DIFFER);
- br(GE, NEXT);
-
- BIND(TAIL03); // 0-3 chars left, cnt1 = #chars left - 4
- tst(cnt1, 0b10);
- br(EQ, TAIL01);
- ldrw(tmp1, Address(post(ary1, 4)));
- ldrw(tmp2, Address(post(ary2, 4)));
- cmp(tmp1, tmp2);
- br(NE, DIFFER);
- BIND(TAIL01); // 0-1 chars left
- tst(cnt1, 0b01);
- br(EQ, SAME);
- ldrh(tmp1, ary1);
- ldrh(tmp2, ary2);
- cmp(tmp1, tmp2);
- br(NE, DIFFER);
-
- BIND(SAME);
- mov(result, true);
- BIND(DIFFER); // result already set
-
- BLOCK_COMMENT("} char_arrays_equals");
-}
// encode char[] to byte[] in ISO_8859_1
void MacroAssembler::encode_iso_array(Register src, Register dst,
--- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp Wed Mar 09 14:18:12 2016 +0100
@@ -1186,13 +1186,11 @@
void string_compare(Register str1, Register str2,
Register cnt1, Register cnt2, Register result,
Register tmp1);
- void string_equals(Register str1, Register str2,
- Register cnt, Register result,
- Register tmp1);
- void char_arrays_equals(Register ary1, Register ary2,
- Register result, Register tmp1);
- void byte_arrays_equals(Register ary1, Register ary2,
- Register result, Register tmp1);
+
+ void arrays_equals(Register a1, Register a2,
+ Register result, Register cnt1,
+ int elem_size, bool is_string);
+
void encode_iso_array(Register src, Register dst,
Register len, Register result,
FloatRegister Vtmp1, FloatRegister Vtmp2,
--- a/hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.hpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.hpp Wed Mar 09 14:18:12 2016 +0100
@@ -105,13 +105,20 @@
inline friend NativeInstruction* nativeInstruction_at(address address);
static bool is_adrp_at(address instr);
+
static bool is_ldr_literal_at(address instr);
+
+ bool is_ldr_literal() {
+ return is_ldr_literal_at(addr_at(0));
+ }
+
static bool is_ldrw_to_zr(address instr);
static bool is_call_at(address instr) {
const uint32_t insn = (*(uint32_t*)instr);
return (insn >> 26) == 0b100101;
}
+
bool is_call() {
return is_call_at(addr_at(0));
}
--- a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -163,30 +163,20 @@
sp_after_call_off = -26,
d15_off = -26,
- d14_off = -25,
d13_off = -24,
- d12_off = -23,
d11_off = -22,
- d10_off = -21,
d9_off = -20,
- d8_off = -19,
r28_off = -18,
- r27_off = -17,
r26_off = -16,
- r25_off = -15,
r24_off = -14,
- r23_off = -13,
r22_off = -12,
- r21_off = -11,
r20_off = -10,
- r19_off = -9,
call_wrapper_off = -8,
result_off = -7,
result_type_off = -6,
method_off = -5,
entry_point_off = -4,
- parameters_off = -3,
parameter_size_off = -2,
thread_off = -1,
fp_f = 0,
@@ -208,30 +198,20 @@
const Address result_type (rfp, result_type_off * wordSize);
const Address method (rfp, method_off * wordSize);
const Address entry_point (rfp, entry_point_off * wordSize);
- const Address parameters (rfp, parameters_off * wordSize);
const Address parameter_size(rfp, parameter_size_off * wordSize);
const Address thread (rfp, thread_off * wordSize);
const Address d15_save (rfp, d15_off * wordSize);
- const Address d14_save (rfp, d14_off * wordSize);
const Address d13_save (rfp, d13_off * wordSize);
- const Address d12_save (rfp, d12_off * wordSize);
const Address d11_save (rfp, d11_off * wordSize);
- const Address d10_save (rfp, d10_off * wordSize);
const Address d9_save (rfp, d9_off * wordSize);
- const Address d8_save (rfp, d8_off * wordSize);
const Address r28_save (rfp, r28_off * wordSize);
- const Address r27_save (rfp, r27_off * wordSize);
const Address r26_save (rfp, r26_off * wordSize);
- const Address r25_save (rfp, r25_off * wordSize);
const Address r24_save (rfp, r24_off * wordSize);
- const Address r23_save (rfp, r23_off * wordSize);
const Address r22_save (rfp, r22_off * wordSize);
- const Address r21_save (rfp, r21_off * wordSize);
const Address r20_save (rfp, r20_off * wordSize);
- const Address r19_save (rfp, r19_off * wordSize);
// stub code
@@ -254,31 +234,20 @@
// rthread because we want to sanity check rthread later
__ str(c_rarg7, thread);
__ strw(c_rarg6, parameter_size);
- __ str(c_rarg5, parameters);
- __ str(c_rarg4, entry_point);
- __ str(c_rarg3, method);
- __ str(c_rarg2, result_type);
- __ str(c_rarg1, result);
- __ str(c_rarg0, call_wrapper);
- __ str(r19, r19_save);
- __ str(r20, r20_save);
- __ str(r21, r21_save);
- __ str(r22, r22_save);
- __ str(r23, r23_save);
- __ str(r24, r24_save);
- __ str(r25, r25_save);
- __ str(r26, r26_save);
- __ str(r27, r27_save);
- __ str(r28, r28_save);
-
- __ strd(v8, d8_save);
- __ strd(v9, d9_save);
- __ strd(v10, d10_save);
- __ strd(v11, d11_save);
- __ strd(v12, d12_save);
- __ strd(v13, d13_save);
- __ strd(v14, d14_save);
- __ strd(v15, d15_save);
+ __ stp(c_rarg4, c_rarg5, entry_point);
+ __ stp(c_rarg2, c_rarg3, result_type);
+ __ stp(c_rarg0, c_rarg1, call_wrapper);
+
+ __ stp(r20, r19, r20_save);
+ __ stp(r22, r21, r22_save);
+ __ stp(r24, r23, r24_save);
+ __ stp(r26, r25, r26_save);
+ __ stp(r28, r27, r28_save);
+
+ __ stpd(v9, v8, d9_save);
+ __ stpd(v11, v10, d11_save);
+ __ stpd(v13, v12, d13_save);
+ __ stpd(v15, v14, d15_save);
// install Java thread in global register now we have saved
// whatever value it held
@@ -385,33 +354,22 @@
#endif
// restore callee-save registers
- __ ldrd(v15, d15_save);
- __ ldrd(v14, d14_save);
- __ ldrd(v13, d13_save);
- __ ldrd(v12, d12_save);
- __ ldrd(v11, d11_save);
- __ ldrd(v10, d10_save);
- __ ldrd(v9, d9_save);
- __ ldrd(v8, d8_save);
-
- __ ldr(r28, r28_save);
- __ ldr(r27, r27_save);
- __ ldr(r26, r26_save);
- __ ldr(r25, r25_save);
- __ ldr(r24, r24_save);
- __ ldr(r23, r23_save);
- __ ldr(r22, r22_save);
- __ ldr(r21, r21_save);
- __ ldr(r20, r20_save);
- __ ldr(r19, r19_save);
- __ ldr(c_rarg0, call_wrapper);
- __ ldr(c_rarg1, result);
+ __ ldpd(v15, v14, d15_save);
+ __ ldpd(v13, v12, d13_save);
+ __ ldpd(v11, v10, d11_save);
+ __ ldpd(v9, v8, d9_save);
+
+ __ ldp(r28, r27, r28_save);
+ __ ldp(r26, r25, r26_save);
+ __ ldp(r24, r23, r24_save);
+ __ ldp(r22, r21, r22_save);
+ __ ldp(r20, r19, r20_save);
+
+ __ ldp(c_rarg0, c_rarg1, call_wrapper);
__ ldrw(c_rarg2, result_type);
__ ldr(c_rarg3, method);
- __ ldr(c_rarg4, entry_point);
- __ ldr(c_rarg5, parameters);
- __ ldr(c_rarg6, parameter_size);
- __ ldr(c_rarg7, thread);
+ __ ldp(c_rarg4, c_rarg5, entry_point);
+ __ ldp(c_rarg6, c_rarg7, parameter_size);
#ifndef PRODUCT
// tell the simulator we are about to end Java execution
@@ -666,7 +624,7 @@
// count - element count
// tmp - scratch register
//
- // Destroy no registers!
+ // Destroy no registers except rscratch1 and rscratch2
//
void gen_write_ref_array_pre_barrier(Register addr, Register count, bool dest_uninitialized) {
BarrierSet* bs = Universe::heap()->barrier_set();
@@ -674,12 +632,13 @@
case BarrierSet::G1SATBCTLogging:
// With G1, don't generate the call if we statically know that the target in uninitialized
if (!dest_uninitialized) {
- __ push(RegSet::range(r0, r29), sp); // integer registers except lr & sp
+ __ push_call_clobbered_registers();
if (count == c_rarg0) {
if (addr == c_rarg1) {
// exactly backwards!!
- __ stp(c_rarg0, c_rarg1, __ pre(sp, -2 * wordSize));
- __ ldp(c_rarg1, c_rarg0, __ post(sp, -2 * wordSize));
+ __ mov(rscratch1, c_rarg0);
+ __ mov(c_rarg0, c_rarg1);
+ __ mov(c_rarg1, rscratch1);
} else {
__ mov(c_rarg1, count);
__ mov(c_rarg0, addr);
@@ -689,7 +648,7 @@
__ mov(c_rarg1, count);
}
__ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_pre), 2);
- __ pop(RegSet::range(r0, r29), sp); // integer registers except lr & sp }
+ __ pop_call_clobbered_registers();
break;
case BarrierSet::CardTableForRS:
case BarrierSet::CardTableExtension:
@@ -719,7 +678,7 @@
case BarrierSet::G1SATBCTLogging:
{
- __ push(RegSet::range(r0, r29), sp); // integer registers except lr & sp
+ __ push_call_clobbered_registers();
// must compute element count unless barrier set interface is changed (other platforms supply count)
assert_different_registers(start, end, scratch);
__ lea(scratch, Address(end, BytesPerHeapOop));
@@ -728,7 +687,7 @@
__ mov(c_rarg0, start);
__ mov(c_rarg1, scratch);
__ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_post), 2);
- __ pop(RegSet::range(r0, r29), sp); // integer registers except lr & sp }
+ __ pop_call_clobbered_registers();
}
break;
case BarrierSet::CardTableForRS:
@@ -1394,10 +1353,10 @@
// no-overlap entry point used by generate_conjoint_long_oop_copy().
//
address generate_disjoint_oop_copy(bool aligned, address *entry,
- const char *name, bool dest_uninitialized = false) {
+ const char *name, bool dest_uninitialized) {
const bool is_oop = true;
const size_t size = UseCompressedOops ? sizeof (jint) : sizeof (jlong);
- return generate_disjoint_copy(size, aligned, is_oop, entry, name);
+ return generate_disjoint_copy(size, aligned, is_oop, entry, name, dest_uninitialized);
}
// Arguments:
@@ -1412,10 +1371,11 @@
//
address generate_conjoint_oop_copy(bool aligned,
address nooverlap_target, address *entry,
- const char *name, bool dest_uninitialized = false) {
+ const char *name, bool dest_uninitialized) {
const bool is_oop = true;
const size_t size = UseCompressedOops ? sizeof (jint) : sizeof (jlong);
- return generate_conjoint_copy(size, aligned, is_oop, nooverlap_target, entry, name);
+ return generate_conjoint_copy(size, aligned, is_oop, nooverlap_target, entry,
+ name, dest_uninitialized);
}
@@ -1522,6 +1482,8 @@
}
#endif //ASSERT
+ gen_write_ref_array_pre_barrier(to, count, dest_uninitialized);
+
// save the original count
__ mov(count_save, count);
@@ -1988,9 +1950,11 @@
bool aligned = !UseCompressedOops;
StubRoutines::_arrayof_oop_disjoint_arraycopy
- = generate_disjoint_oop_copy(aligned, &entry, "arrayof_oop_disjoint_arraycopy");
+ = generate_disjoint_oop_copy(aligned, &entry, "arrayof_oop_disjoint_arraycopy",
+ /*dest_uninitialized*/false);
StubRoutines::_arrayof_oop_arraycopy
- = generate_conjoint_oop_copy(aligned, entry, &entry_oop_arraycopy, "arrayof_oop_arraycopy");
+ = generate_conjoint_oop_copy(aligned, entry, &entry_oop_arraycopy, "arrayof_oop_arraycopy",
+ /*dest_uninitialized*/false);
// Aligned versions without pre-barriers
StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit
= generate_disjoint_oop_copy(aligned, &entry, "arrayof_oop_disjoint_arraycopy_uninit",
--- a/hotspot/src/cpu/ppc/vm/globals_ppc.hpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/cpu/ppc/vm/globals_ppc.hpp Wed Mar 09 14:18:12 2016 +0100
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2015 SAP SE. All rights reserved.
+ * Copyright (c) 2012, 2016 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
@@ -74,8 +74,7 @@
define_pd_global(uintx, TypeProfileLevel, 111);
-// No performance work done here yet.
-define_pd_global(bool, CompactStrings, false);
+define_pd_global(bool, CompactStrings, true);
// Platform dependent flag handling: flags only defined on this platform.
#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct, range, constraint) \
--- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -45,6 +45,9 @@
#include "gc/g1/g1SATBCardTableModRefBS.hpp"
#include "gc/g1/heapRegion.hpp"
#endif // INCLUDE_ALL_GCS
+#ifdef COMPILER2
+#include "opto/intrinsicnode.hpp"
+#endif
#ifdef PRODUCT
#define BLOCK_COMMENT(str) // nothing
@@ -3168,6 +3171,553 @@
/////////////////////////////////////////// String intrinsics ////////////////////////////////////////////
+#ifdef COMPILER2
+// Intrinsics for CompactStrings
+
+// Compress char[] to byte[] by compressing 16 bytes at once.
+void MacroAssembler::string_compress_16(Register src, Register dst, Register cnt,
+ Register tmp1, Register tmp2, Register tmp3, Register tmp4, Register tmp5,
+ Label& Lfailure) {
+
+ const Register tmp0 = R0;
+ assert_different_registers(src, dst, cnt, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5);
+ Label Lloop, Lslow;
+
+ // Check if cnt >= 8 (= 16 bytes)
+ lis(tmp1, 0xFF); // tmp1 = 0x00FF00FF00FF00FF
+ srwi_(tmp2, cnt, 3);
+ beq(CCR0, Lslow);
+ ori(tmp1, tmp1, 0xFF);
+ rldimi(tmp1, tmp1, 32, 0);
+ mtctr(tmp2);
+
+ // 2x unrolled loop
+ bind(Lloop);
+ ld(tmp2, 0, src); // _0_1_2_3 (Big Endian)
+ ld(tmp4, 8, src); // _4_5_6_7
+
+ orr(tmp0, tmp2, tmp4);
+ rldicl(tmp3, tmp2, 6*8, 64-24); // _____1_2
+ rldimi(tmp2, tmp2, 2*8, 2*8); // _0_2_3_3
+ rldicl(tmp5, tmp4, 6*8, 64-24); // _____5_6
+ rldimi(tmp4, tmp4, 2*8, 2*8); // _4_6_7_7
+
+ andc_(tmp0, tmp0, tmp1);
+ bne(CCR0, Lfailure); // Not latin1.
+ addi(src, src, 16);
+
+ rlwimi(tmp3, tmp2, 0*8, 24, 31);// _____1_3
+ srdi(tmp2, tmp2, 3*8); // ____0_2_
+ rlwimi(tmp5, tmp4, 0*8, 24, 31);// _____5_7
+ srdi(tmp4, tmp4, 3*8); // ____4_6_
+
+ orr(tmp2, tmp2, tmp3); // ____0123
+ orr(tmp4, tmp4, tmp5); // ____4567
+
+ stw(tmp2, 0, dst);
+ stw(tmp4, 4, dst);
+ addi(dst, dst, 8);
+ bdnz(Lloop);
+
+ bind(Lslow); // Fallback to slow version
+}
+
+// Compress char[] to byte[]. cnt must be positive int.
+void MacroAssembler::string_compress(Register src, Register dst, Register cnt, Register tmp, Label& Lfailure) {
+ Label Lloop;
+ mtctr(cnt);
+
+ bind(Lloop);
+ lhz(tmp, 0, src);
+ cmplwi(CCR0, tmp, 0xff);
+ bgt(CCR0, Lfailure); // Not latin1.
+ addi(src, src, 2);
+ stb(tmp, 0, dst);
+ addi(dst, dst, 1);
+ bdnz(Lloop);
+}
+
+// Inflate byte[] to char[] by inflating 16 bytes at once.
+void MacroAssembler::string_inflate_16(Register src, Register dst, Register cnt,
+ Register tmp1, Register tmp2, Register tmp3, Register tmp4, Register tmp5) {
+ const Register tmp0 = R0;
+ assert_different_registers(src, dst, cnt, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5);
+ Label Lloop, Lslow;
+
+ // Check if cnt >= 8
+ srwi_(tmp2, cnt, 3);
+ beq(CCR0, Lslow);
+ lis(tmp1, 0xFF); // tmp1 = 0x00FF00FF
+ ori(tmp1, tmp1, 0xFF);
+ mtctr(tmp2);
+
+ // 2x unrolled loop
+ bind(Lloop);
+ lwz(tmp2, 0, src); // ____0123 (Big Endian)
+ lwz(tmp4, 4, src); // ____4567
+ addi(src, src, 8);
+
+ rldicl(tmp3, tmp2, 7*8, 64-8); // _______2
+ rlwimi(tmp2, tmp2, 3*8, 16, 23);// ____0113
+ rldicl(tmp5, tmp4, 7*8, 64-8); // _______6
+ rlwimi(tmp4, tmp4, 3*8, 16, 23);// ____4557
+
+ andc(tmp0, tmp2, tmp1); // ____0_1_
+ rlwimi(tmp2, tmp3, 2*8, 0, 23); // _____2_3
+ andc(tmp3, tmp4, tmp1); // ____4_5_
+ rlwimi(tmp4, tmp5, 2*8, 0, 23); // _____6_7
+
+ rldimi(tmp2, tmp0, 3*8, 0*8); // _0_1_2_3
+ rldimi(tmp4, tmp3, 3*8, 0*8); // _4_5_6_7
+
+ std(tmp2, 0, dst);
+ std(tmp4, 8, dst);
+ addi(dst, dst, 16);
+ bdnz(Lloop);
+
+ bind(Lslow); // Fallback to slow version
+}
+
+// Inflate byte[] to char[]. cnt must be positive int.
+void MacroAssembler::string_inflate(Register src, Register dst, Register cnt, Register tmp) {
+ Label Lloop;
+ mtctr(cnt);
+
+ bind(Lloop);
+ lbz(tmp, 0, src);
+ addi(src, src, 1);
+ sth(tmp, 0, dst);
+ addi(dst, dst, 2);
+ bdnz(Lloop);
+}
+
+void MacroAssembler::string_compare(Register str1, Register str2,
+ Register cnt1, Register cnt2,
+ Register tmp1, Register result, int ae) {
+ const Register tmp0 = R0,
+ diff = tmp1;
+
+ assert_different_registers(str1, str2, cnt1, cnt2, tmp0, tmp1, result);
+ Label Ldone, Lslow, Lloop, Lreturn_diff;
+
+ // Note: Making use of the fact that compareTo(a, b) == -compareTo(b, a)
+ // we interchange str1 and str2 in the UL case and negate the result.
+ // Like this, str1 is always latin1 encoded, except for the UU case.
+ // In addition, we need 0 (or sign which is 0) extend.
+
+ if (ae == StrIntrinsicNode::UU) {
+ srwi(cnt1, cnt1, 1);
+ } else {
+ clrldi(cnt1, cnt1, 32);
+ }
+
+ if (ae != StrIntrinsicNode::LL) {
+ srwi(cnt2, cnt2, 1);
+ } else {
+ clrldi(cnt2, cnt2, 32);
+ }
+
+ // See if the lengths are different, and calculate min in cnt1.
+ // Save diff in case we need it for a tie-breaker.
+ subf_(diff, cnt2, cnt1); // diff = cnt1 - cnt2
+ // if (diff > 0) { cnt1 = cnt2; }
+ if (VM_Version::has_isel()) {
+ isel(cnt1, CCR0, Assembler::greater, /*invert*/ false, cnt2);
+ } else {
+ Label Lskip;
+ blt(CCR0, Lskip);
+ mr(cnt1, cnt2);
+ bind(Lskip);
+ }
+
+ // Rename registers
+ Register chr1 = result;
+ Register chr2 = tmp0;
+
+ // Compare multiple characters in fast loop (only implemented for same encoding).
+ int stride1 = 8, stride2 = 8;
+ if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
+ int log2_chars_per_iter = (ae == StrIntrinsicNode::LL) ? 3 : 2;
+ Label Lfastloop, Lskipfast;
+
+ srwi_(tmp0, cnt1, log2_chars_per_iter);
+ beq(CCR0, Lskipfast);
+ rldicl(cnt2, cnt1, 0, 64 - log2_chars_per_iter); // Remaining characters.
+ li(cnt1, 1 << log2_chars_per_iter); // Initialize for failure case: Rescan characters from current iteration.
+ mtctr(tmp0);
+
+ bind(Lfastloop);
+ ld(chr1, 0, str1);
+ ld(chr2, 0, str2);
+ cmpd(CCR0, chr1, chr2);
+ bne(CCR0, Lslow);
+ addi(str1, str1, stride1);
+ addi(str2, str2, stride2);
+ bdnz(Lfastloop);
+ mr(cnt1, cnt2); // Remaining characters.
+ bind(Lskipfast);
+ }
+
+ // Loop which searches the first difference character by character.
+ cmpwi(CCR0, cnt1, 0);
+ beq(CCR0, Lreturn_diff);
+ bind(Lslow);
+ mtctr(cnt1);
+
+ switch (ae) {
+ case StrIntrinsicNode::LL: stride1 = 1; stride2 = 1; break;
+ case StrIntrinsicNode::UL: // fallthru (see comment above)
+ case StrIntrinsicNode::LU: stride1 = 1; stride2 = 2; break;
+ case StrIntrinsicNode::UU: stride1 = 2; stride2 = 2; break;
+ default: ShouldNotReachHere(); break;
+ }
+
+ bind(Lloop);
+ if (stride1 == 1) { lbz(chr1, 0, str1); } else { lhz(chr1, 0, str1); }
+ if (stride2 == 1) { lbz(chr2, 0, str2); } else { lhz(chr2, 0, str2); }
+ subf_(result, chr2, chr1); // result = chr1 - chr2
+ bne(CCR0, Ldone);
+ addi(str1, str1, stride1);
+ addi(str2, str2, stride2);
+ bdnz(Lloop);
+
+ // If strings are equal up to min length, return the length difference.
+ bind(Lreturn_diff);
+ mr(result, diff);
+
+ // Otherwise, return the difference between the first mismatched chars.
+ bind(Ldone);
+ if (ae == StrIntrinsicNode::UL) {
+ neg(result, result); // Negate result (see note above).
+ }
+}
+
+void MacroAssembler::array_equals(bool is_array_equ, Register ary1, Register ary2,
+ Register limit, Register tmp1, Register result, bool is_byte) {
+ const Register tmp0 = R0;
+ assert_different_registers(ary1, ary2, limit, tmp0, tmp1, result);
+ Label Ldone, Lskiploop, Lloop, Lfastloop, Lskipfast;
+ bool limit_needs_shift = false;
+
+ if (is_array_equ) {
+ const int length_offset = arrayOopDesc::length_offset_in_bytes();
+ const int base_offset = arrayOopDesc::base_offset_in_bytes(is_byte ? T_BYTE : T_CHAR);
+
+ // Return true if the same array.
+ cmpd(CCR0, ary1, ary2);
+ beq(CCR0, Lskiploop);
+
+ // Return false if one of them is NULL.
+ cmpdi(CCR0, ary1, 0);
+ cmpdi(CCR1, ary2, 0);
+ li(result, 0);
+ cror(CCR0, Assembler::equal, CCR1, Assembler::equal);
+ beq(CCR0, Ldone);
+
+ // Load the lengths of arrays.
+ lwz(limit, length_offset, ary1);
+ lwz(tmp0, length_offset, ary2);
+
+ // Return false if the two arrays are not equal length.
+ cmpw(CCR0, limit, tmp0);
+ bne(CCR0, Ldone);
+
+ // Load array addresses.
+ addi(ary1, ary1, base_offset);
+ addi(ary2, ary2, base_offset);
+ } else {
+ limit_needs_shift = !is_byte;
+ li(result, 0); // Assume not equal.
+ }
+
+ // Rename registers
+ Register chr1 = tmp0;
+ Register chr2 = tmp1;
+
+ // Compare 8 bytes per iteration in fast loop.
+ const int log2_chars_per_iter = is_byte ? 3 : 2;
+
+ srwi_(tmp0, limit, log2_chars_per_iter + (limit_needs_shift ? 1 : 0));
+ beq(CCR0, Lskipfast);
+ mtctr(tmp0);
+
+ bind(Lfastloop);
+ ld(chr1, 0, ary1);
+ ld(chr2, 0, ary2);
+ addi(ary1, ary1, 8);
+ addi(ary2, ary2, 8);
+ cmpd(CCR0, chr1, chr2);
+ bne(CCR0, Ldone);
+ bdnz(Lfastloop);
+
+ bind(Lskipfast);
+ rldicl_(limit, limit, limit_needs_shift ? 64 - 1 : 0, 64 - log2_chars_per_iter); // Remaining characters.
+ beq(CCR0, Lskiploop);
+ mtctr(limit);
+
+ // Character by character.
+ bind(Lloop);
+ if (is_byte) {
+ lbz(chr1, 0, ary1);
+ lbz(chr2, 0, ary2);
+ addi(ary1, ary1, 1);
+ addi(ary2, ary2, 1);
+ } else {
+ lhz(chr1, 0, ary1);
+ lhz(chr2, 0, ary2);
+ addi(ary1, ary1, 2);
+ addi(ary2, ary2, 2);
+ }
+ cmpw(CCR0, chr1, chr2);
+ bne(CCR0, Ldone);
+ bdnz(Lloop);
+
+ bind(Lskiploop);
+ li(result, 1); // All characters are equal.
+ bind(Ldone);
+}
+
+void MacroAssembler::string_indexof(Register result, Register haystack, Register haycnt,
+ Register needle, ciTypeArray* needle_values, Register needlecnt, int needlecntval,
+ Register tmp1, Register tmp2, Register tmp3, Register tmp4, int ae) {
+
+ // Ensure 0<needlecnt<=haycnt in ideal graph as prerequisite!
+ Label L_TooShort, L_Found, L_NotFound, L_End;
+ Register last_addr = haycnt, // Kill haycnt at the beginning.
+ addr = tmp1,
+ n_start = tmp2,
+ ch1 = tmp3,
+ ch2 = R0;
+
+ assert(ae != StrIntrinsicNode::LU, "Invalid encoding");
+ const int h_csize = (ae == StrIntrinsicNode::LL) ? 1 : 2;
+ const int n_csize = (ae == StrIntrinsicNode::UU) ? 2 : 1;
+
+ // **************************************************************************************************
+ // Prepare for main loop: optimized for needle count >=2, bail out otherwise.
+ // **************************************************************************************************
+
+ // Compute last haystack addr to use if no match gets found.
+ clrldi(haycnt, haycnt, 32); // Ensure positive int is valid as 64 bit value.
+ addi(addr, haystack, -h_csize); // Accesses use pre-increment.
+ if (needlecntval == 0) { // variable needlecnt
+ cmpwi(CCR6, needlecnt, 2);
+ clrldi(needlecnt, needlecnt, 32); // Ensure positive int is valid as 64 bit value.
+ blt(CCR6, L_TooShort); // Variable needlecnt: handle short needle separately.
+ }
+
+ if (n_csize == 2) { lwz(n_start, 0, needle); } else { lhz(n_start, 0, needle); } // Load first 2 characters of needle.
+
+ if (needlecntval == 0) { // variable needlecnt
+ subf(ch1, needlecnt, haycnt); // Last character index to compare is haycnt-needlecnt.
+ addi(needlecnt, needlecnt, -2); // Rest of needle.
+ } else { // constant needlecnt
+ guarantee(needlecntval != 1, "IndexOf with single-character needle must be handled separately");
+ assert((needlecntval & 0x7fff) == needlecntval, "wrong immediate");
+ addi(ch1, haycnt, -needlecntval); // Last character index to compare is haycnt-needlecnt.
+ if (needlecntval > 3) { li(needlecnt, needlecntval - 2); } // Rest of needle.
+ }
+
+ if (h_csize == 2) { slwi(ch1, ch1, 1); } // Scale to number of bytes.
+
+ if (ae ==StrIntrinsicNode::UL) {
+ srwi(tmp4, n_start, 1*8); // ___0
+ rlwimi(n_start, tmp4, 2*8, 0, 23); // _0_1
+ }
+
+ add(last_addr, haystack, ch1); // Point to last address to compare (haystack+2*(haycnt-needlecnt)).
+
+ // Main Loop (now we have at least 2 characters).
+ Label L_OuterLoop, L_InnerLoop, L_FinalCheck, L_Comp1, L_Comp2;
+ bind(L_OuterLoop); // Search for 1st 2 characters.
+ Register addr_diff = tmp4;
+ subf(addr_diff, addr, last_addr); // Difference between already checked address and last address to check.
+ addi(addr, addr, h_csize); // This is the new address we want to use for comparing.
+ srdi_(ch2, addr_diff, h_csize);
+ beq(CCR0, L_FinalCheck); // 2 characters left?
+ mtctr(ch2); // num of characters / 2
+ bind(L_InnerLoop); // Main work horse (2x unrolled search loop)
+ if (h_csize == 2) { // Load 2 characters of haystack (ignore alignment).
+ lwz(ch1, 0, addr);
+ lwz(ch2, 2, addr);
+ } else {
+ lhz(ch1, 0, addr);
+ lhz(ch2, 1, addr);
+ }
+ cmpw(CCR0, ch1, n_start); // Compare 2 characters (1 would be sufficient but try to reduce branches to CompLoop).
+ cmpw(CCR1, ch2, n_start);
+ beq(CCR0, L_Comp1); // Did we find the needle start?
+ beq(CCR1, L_Comp2);
+ addi(addr, addr, 2 * h_csize);
+ bdnz(L_InnerLoop);
+ bind(L_FinalCheck);
+ andi_(addr_diff, addr_diff, h_csize); // Remaining characters not covered by InnerLoop: (num of characters) & 1.
+ beq(CCR0, L_NotFound);
+ if (h_csize == 2) { lwz(ch1, 0, addr); } else { lhz(ch1, 0, addr); } // One position left at which we have to compare.
+ cmpw(CCR1, ch1, n_start);
+ beq(CCR1, L_Comp1);
+ bind(L_NotFound);
+ li(result, -1); // not found
+ b(L_End);
+
+ // **************************************************************************************************
+ // Special Case: unfortunately, the variable needle case can be called with needlecnt<2
+ // **************************************************************************************************
+ if (needlecntval == 0) { // We have to handle these cases separately.
+ Label L_OneCharLoop;
+ bind(L_TooShort);
+ mtctr(haycnt);
+ if (n_csize == 2) { lhz(n_start, 0, needle); } else { lbz(n_start, 0, needle); } // First character of needle
+ bind(L_OneCharLoop);
+ if (h_csize == 2) { lhzu(ch1, 2, addr); } else { lbzu(ch1, 1, addr); }
+ cmpw(CCR1, ch1, n_start);
+ beq(CCR1, L_Found); // Did we find the one character needle?
+ bdnz(L_OneCharLoop);
+ li(result, -1); // Not found.
+ b(L_End);
+ }
+
+ // **************************************************************************************************
+ // Regular Case Part II: compare rest of needle (first 2 characters have been compared already)
+ // **************************************************************************************************
+
+ // Compare the rest
+ bind(L_Comp2);
+ addi(addr, addr, h_csize); // First comparison has failed, 2nd one hit.
+ bind(L_Comp1); // Addr points to possible needle start.
+ if (needlecntval != 2) { // Const needlecnt==2?
+ if (needlecntval != 3) {
+ if (needlecntval == 0) { beq(CCR6, L_Found); } // Variable needlecnt==2?
+ Register n_ind = tmp4,
+ h_ind = n_ind;
+ li(n_ind, 2 * n_csize); // First 2 characters are already compared, use index 2.
+ mtctr(needlecnt); // Decremented by 2, still > 0.
+ Label L_CompLoop;
+ bind(L_CompLoop);
+ if (ae ==StrIntrinsicNode::UL) {
+ h_ind = ch1;
+ sldi(h_ind, n_ind, 1);
+ }
+ if (n_csize == 2) { lhzx(ch2, needle, n_ind); } else { lbzx(ch2, needle, n_ind); }
+ if (h_csize == 2) { lhzx(ch1, addr, h_ind); } else { lbzx(ch1, addr, h_ind); }
+ cmpw(CCR1, ch1, ch2);
+ bne(CCR1, L_OuterLoop);
+ addi(n_ind, n_ind, n_csize);
+ bdnz(L_CompLoop);
+ } else { // No loop required if there's only one needle character left.
+ if (n_csize == 2) { lhz(ch2, 2 * 2, needle); } else { lbz(ch2, 2 * 1, needle); }
+ if (h_csize == 2) { lhz(ch1, 2 * 2, addr); } else { lbz(ch1, 2 * 1, addr); }
+ cmpw(CCR1, ch1, ch2);
+ bne(CCR1, L_OuterLoop);
+ }
+ }
+ // Return index ...
+ bind(L_Found);
+ subf(result, haystack, addr); // relative to haystack, ...
+ if (h_csize == 2) { srdi(result, result, 1); } // in characters.
+ bind(L_End);
+} // string_indexof
+
+void MacroAssembler::string_indexof_char(Register result, Register haystack, Register haycnt,
+ Register needle, jchar needleChar, Register tmp1, Register tmp2, bool is_byte) {
+ assert_different_registers(haystack, haycnt, needle, tmp1, tmp2);
+
+ Label L_InnerLoop, L_FinalCheck, L_Found1, L_Found2, L_NotFound, L_End;
+ Register addr = tmp1,
+ ch1 = tmp2,
+ ch2 = R0;
+
+ const int h_csize = is_byte ? 1 : 2;
+
+//4:
+ srwi_(tmp2, haycnt, 1); // Shift right by exact_log2(UNROLL_FACTOR).
+ mr(addr, haystack);
+ beq(CCR0, L_FinalCheck);
+ mtctr(tmp2); // Move to count register.
+//8:
+ bind(L_InnerLoop); // Main work horse (2x unrolled search loop).
+ if (!is_byte) {
+ lhz(ch1, 0, addr);
+ lhz(ch2, 2, addr);
+ } else {
+ lbz(ch1, 0, addr);
+ lbz(ch2, 1, addr);
+ }
+ (needle != R0) ? cmpw(CCR0, ch1, needle) : cmplwi(CCR0, ch1, (unsigned int)needleChar);
+ (needle != R0) ? cmpw(CCR1, ch2, needle) : cmplwi(CCR1, ch2, (unsigned int)needleChar);
+ beq(CCR0, L_Found1); // Did we find the needle?
+ beq(CCR1, L_Found2);
+ addi(addr, addr, 2 * h_csize);
+ bdnz(L_InnerLoop);
+//16:
+ bind(L_FinalCheck);
+ andi_(R0, haycnt, 1);
+ beq(CCR0, L_NotFound);
+ if (!is_byte) { lhz(ch1, 0, addr); } else { lbz(ch1, 0, addr); } // One position left at which we have to compare.
+ (needle != R0) ? cmpw(CCR1, ch1, needle) : cmplwi(CCR1, ch1, (unsigned int)needleChar);
+ beq(CCR1, L_Found1);
+//21:
+ bind(L_NotFound);
+ li(result, -1); // Not found.
+ b(L_End);
+
+ bind(L_Found2);
+ addi(addr, addr, h_csize);
+//24:
+ bind(L_Found1); // Return index ...
+ subf(result, haystack, addr); // relative to haystack, ...
+ if (!is_byte) { srdi(result, result, 1); } // in characters.
+ bind(L_End);
+} // string_indexof_char
+
+
+void MacroAssembler::has_negatives(Register src, Register cnt, Register result,
+ Register tmp1, Register tmp2) {
+ const Register tmp0 = R0;
+ assert_different_registers(src, result, cnt, tmp0, tmp1, tmp2);
+ Label Lfastloop, Lslow, Lloop, Lnoneg, Ldone;
+
+ // Check if cnt >= 8 (= 16 bytes)
+ lis(tmp1, (int)(short)0x8080); // tmp1 = 0x8080808080808080
+ srwi_(tmp2, cnt, 4);
+ li(result, 1); // Assume there's a negative byte.
+ beq(CCR0, Lslow);
+ ori(tmp1, tmp1, 0x8080);
+ rldimi(tmp1, tmp1, 32, 0);
+ mtctr(tmp2);
+
+ // 2x unrolled loop
+ bind(Lfastloop);
+ ld(tmp2, 0, src);
+ ld(tmp0, 8, src);
+
+ orr(tmp0, tmp2, tmp0);
+
+ and_(tmp0, tmp0, tmp1);
+ bne(CCR0, Ldone); // Found negative byte.
+ addi(src, src, 16);
+
+ bdnz(Lfastloop);
+
+ bind(Lslow); // Fallback to slow version
+ rldicl_(tmp0, cnt, 0, 64-4);
+ beq(CCR0, Lnoneg);
+ mtctr(tmp0);
+ bind(Lloop);
+ lbz(tmp0, 0, src);
+ addi(src, src, 1);
+ andi_(tmp0, tmp0, 0x80);
+ bne(CCR0, Ldone); // Found negative byte.
+ bdnz(Lloop);
+ bind(Lnoneg);
+ li(result, 0);
+
+ bind(Ldone);
+}
+
+
+// Intrinsics for non-CompactStrings
+
// Search for a single jchar in an jchar[].
//
// Assumes that result differs from all other registers.
@@ -3613,6 +4163,8 @@
bind(Ldone_false);
}
+#endif // Compiler2
+
// Helpers for Intrinsic Emitters
//
// Revert the byte order of a 32bit value in a register
--- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp Wed Mar 09 14:18:12 2016 +0100
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2015 SAP SE. All rights reserved.
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016 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
@@ -679,6 +679,39 @@
void clear_memory_doubleword(Register base_ptr, Register cnt_dwords, Register tmp = R0);
+#ifdef COMPILER2
+ // Intrinsics for CompactStrings
+ // Compress char[] to byte[] by compressing 16 bytes at once.
+ void string_compress_16(Register src, Register dst, Register cnt,
+ Register tmp1, Register tmp2, Register tmp3, Register tmp4, Register tmp5,
+ Label& Lfailure);
+
+ // Compress char[] to byte[]. cnt must be positive int.
+ void string_compress(Register src, Register dst, Register cnt, Register tmp, Label& Lfailure);
+
+ // Inflate byte[] to char[] by inflating 16 bytes at once.
+ void string_inflate_16(Register src, Register dst, Register cnt,
+ Register tmp1, Register tmp2, Register tmp3, Register tmp4, Register tmp5);
+
+ // Inflate byte[] to char[]. cnt must be positive int.
+ void string_inflate(Register src, Register dst, Register cnt, Register tmp);
+
+ void string_compare(Register str1, Register str2, Register cnt1, Register cnt2,
+ Register tmp1, Register result, int ae);
+
+ void array_equals(bool is_array_equ, Register ary1, Register ary2,
+ Register limit, Register tmp1, Register result, bool is_byte);
+
+ void string_indexof(Register result, Register haystack, Register haycnt,
+ Register needle, ciTypeArray* needle_values, Register needlecnt, int needlecntval,
+ Register tmp1, Register tmp2, Register tmp3, Register tmp4, int ae);
+
+ void string_indexof_char(Register result, Register haystack, Register haycnt,
+ Register needle, jchar needleChar, Register tmp1, Register tmp2, bool is_byte);
+
+ void has_negatives(Register src, Register cnt, Register result, Register tmp1, Register tmp2);
+
+ // Intrinsics for non-CompactStrings
// Needle of length 1.
void string_indexof_1(Register result, Register haystack, Register haycnt,
Register needle, jchar needleChar,
@@ -694,6 +727,7 @@
Register tmp5_reg);
void char_arrays_equalsImm(Register str1_reg, Register str2_reg, int cntval, Register result_reg,
Register tmp1_reg, Register tmp2_reg);
+#endif
// Emitters for BigInteger.multiplyToLen intrinsic.
inline void multiply64(Register dest_hi, Register dest_lo,
--- a/hotspot/src/cpu/ppc/vm/ppc.ad Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/cpu/ppc/vm/ppc.ad Wed Mar 09 14:18:12 2016 +0100
@@ -1,6 +1,6 @@
//
// Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
-// Copyright (c) 2012, 2015 SAP SE. All rights reserved.
+// Copyright (c) 2012, 2016 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
@@ -2024,13 +2024,13 @@
return (UsePopCountInstruction && VM_Version::has_popcntw());
case Op_StrComp:
- return SpecialStringCompareTo && !CompactStrings;
+ return SpecialStringCompareTo;
case Op_StrEquals:
- return SpecialStringEquals && !CompactStrings;
+ return SpecialStringEquals;
case Op_StrIndexOf:
- return SpecialStringIndexOf && !CompactStrings;
+ return SpecialStringIndexOf;
case Op_StrIndexOfChar:
- return SpecialStringIndexOf && !CompactStrings;
+ return SpecialStringIndexOf;
}
return true; // Per default match rules are supported.
@@ -11022,6 +11022,584 @@
ins_pipe(pipe_class_default);
%}
+instruct string_compareL(rarg1RegP str1, rarg2RegP str2, rarg3RegI cnt1, rarg4RegI cnt2, iRegIdst result,
+ iRegIdst tmp, regCTR ctr, flagsRegCR0 cr0) %{
+ predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::LL);
+ match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
+ effect(TEMP_DEF result, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ctr, KILL cr0, TEMP tmp);
+ ins_cost(300);
+ format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result \t// KILL $tmp" %}
+ ins_encode %{
+ // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+ __ string_compare($str1$$Register, $str2$$Register,
+ $cnt1$$Register, $cnt2$$Register,
+ $tmp$$Register,
+ $result$$Register, StrIntrinsicNode::LL);
+ %}
+ ins_pipe(pipe_class_default);
+%}
+
+instruct string_compareU(rarg1RegP str1, rarg2RegP str2, rarg3RegI cnt1, rarg4RegI cnt2, iRegIdst result,
+ iRegIdst tmp, regCTR ctr, flagsRegCR0 cr0) %{
+ predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::UU);
+ match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
+ effect(TEMP_DEF result, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ctr, KILL cr0, TEMP tmp);
+ ins_cost(300);
+ format %{ "String Compare char[] $str1,$cnt1,$str2,$cnt2 -> $result \t// KILL $tmp" %}
+ ins_encode %{
+ // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+ __ string_compare($str1$$Register, $str2$$Register,
+ $cnt1$$Register, $cnt2$$Register,
+ $tmp$$Register,
+ $result$$Register, StrIntrinsicNode::UU);
+ %}
+ ins_pipe(pipe_class_default);
+%}
+
+instruct string_compareLU(rarg1RegP str1, rarg2RegP str2, rarg3RegI cnt1, rarg4RegI cnt2, iRegIdst result,
+ iRegIdst tmp, regCTR ctr, flagsRegCR0 cr0) %{
+ predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::LU);
+ match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
+ effect(TEMP_DEF result, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ctr, KILL cr0, TEMP tmp);
+ ins_cost(300);
+ format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result \t// KILL $tmp" %}
+ ins_encode %{
+ // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+ __ string_compare($str1$$Register, $str2$$Register,
+ $cnt1$$Register, $cnt2$$Register,
+ $tmp$$Register,
+ $result$$Register, StrIntrinsicNode::LU);
+ %}
+ ins_pipe(pipe_class_default);
+%}
+
+instruct string_compareUL(rarg1RegP str1, rarg2RegP str2, rarg3RegI cnt1, rarg4RegI cnt2, iRegIdst result,
+ iRegIdst tmp, regCTR ctr, flagsRegCR0 cr0) %{
+ predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::UL);
+ match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
+ effect(TEMP_DEF result, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ctr, KILL cr0, TEMP tmp);
+ ins_cost(300);
+ format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result \t// KILL $tmp" %}
+ ins_encode %{
+ // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+ __ string_compare($str2$$Register, $str1$$Register,
+ $cnt2$$Register, $cnt1$$Register,
+ $tmp$$Register,
+ $result$$Register, StrIntrinsicNode::UL);
+ %}
+ ins_pipe(pipe_class_default);
+%}
+
+instruct string_equalsL(rarg1RegP str1, rarg2RegP str2, rarg3RegI cnt, iRegIdst result,
+ iRegIdst tmp, regCTR ctr, flagsRegCR0 cr0) %{
+ predicate(((StrEqualsNode*)n)->encoding() == StrIntrinsicNode::LL);
+ match(Set result (StrEquals (Binary str1 str2) cnt));
+ effect(TEMP_DEF result, USE_KILL str1, USE_KILL str2, USE_KILL cnt, TEMP tmp, KILL ctr, KILL cr0);
+ ins_cost(300);
+ format %{ "String Equals byte[] $str1,$str2,$cnt -> $result \t// KILL $tmp" %}
+ ins_encode %{
+ // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+ __ array_equals(false, $str1$$Register, $str2$$Register,
+ $cnt$$Register, $tmp$$Register,
+ $result$$Register, true /* byte */);
+ %}
+ ins_pipe(pipe_class_default);
+%}
+
+instruct string_equalsU(rarg1RegP str1, rarg2RegP str2, rarg3RegI cnt, iRegIdst result,
+ iRegIdst tmp, regCTR ctr, flagsRegCR0 cr0) %{
+ predicate(((StrEqualsNode*)n)->encoding() == StrIntrinsicNode::UU);
+ match(Set result (StrEquals (Binary str1 str2) cnt));
+ effect(TEMP_DEF result, USE_KILL str1, USE_KILL str2, USE_KILL cnt, TEMP tmp, KILL ctr, KILL cr0);
+ ins_cost(300);
+ format %{ "String Equals char[] $str1,$str2,$cnt -> $result \t// KILL $tmp" %}
+ ins_encode %{
+ // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+ __ array_equals(false, $str1$$Register, $str2$$Register,
+ $cnt$$Register, $tmp$$Register,
+ $result$$Register, false /* byte */);
+ %}
+ ins_pipe(pipe_class_default);
+%}
+
+instruct array_equalsB(rarg1RegP ary1, rarg2RegP ary2, iRegIdst result,
+ iRegIdst tmp1, iRegIdst tmp2, regCTR ctr, flagsRegCR0 cr0, flagsRegCR0 cr1) %{
+ predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::LL);
+ match(Set result (AryEq ary1 ary2));
+ effect(TEMP_DEF result, USE_KILL ary1, USE_KILL ary2, TEMP tmp1, TEMP tmp2, KILL ctr, KILL cr0, KILL cr1);
+ ins_cost(300);
+ format %{ "Array Equals $ary1,$ary2 -> $result \t// KILL $tmp1,$tmp2" %}
+ ins_encode %{
+ // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+ __ array_equals(true, $ary1$$Register, $ary2$$Register,
+ $tmp1$$Register, $tmp2$$Register,
+ $result$$Register, true /* byte */);
+ %}
+ ins_pipe(pipe_class_default);
+%}
+
+instruct array_equalsC(rarg1RegP ary1, rarg2RegP ary2, iRegIdst result,
+ iRegIdst tmp1, iRegIdst tmp2, regCTR ctr, flagsRegCR0 cr0, flagsRegCR0 cr1) %{
+ predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU);
+ match(Set result (AryEq ary1 ary2));
+ effect(TEMP_DEF result, USE_KILL ary1, USE_KILL ary2, TEMP tmp1, TEMP tmp2, KILL ctr, KILL cr0, KILL cr1);
+ ins_cost(300);
+ format %{ "Array Equals $ary1,$ary2 -> $result \t// KILL $tmp1,$tmp2" %}
+ ins_encode %{
+ // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+ __ array_equals(true, $ary1$$Register, $ary2$$Register,
+ $tmp1$$Register, $tmp2$$Register,
+ $result$$Register, false /* byte */);
+ %}
+ ins_pipe(pipe_class_default);
+%}
+
+instruct indexOf_imm1_char_U(iRegIdst result, iRegPsrc haystack, iRegIsrc haycnt,
+ immP needleImm, immL offsetImm, immI_1 needlecntImm,
+ iRegIdst tmp1, iRegIdst tmp2,
+ flagsRegCR0 cr0, flagsRegCR1 cr1, regCTR ctr) %{
+ match(Set result (StrIndexOf (Binary haystack haycnt) (Binary (AddP needleImm offsetImm) needlecntImm)));
+ effect(TEMP tmp1, TEMP tmp2, KILL cr0, KILL cr1, KILL ctr);
+ // Required for EA: check if it is still a type_array.
+ predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU);
+ ins_cost(150);
+
+ format %{ "String IndexOf CSCL1 $haystack[0..$haycnt], $needleImm+$offsetImm[0..$needlecntImm]"
+ "-> $result \t// KILL $haycnt, $tmp1, $tmp2, $cr0, $cr1" %}
+
+ ins_encode %{
+ // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+ immPOper *needleOper = (immPOper *)$needleImm;
+ const TypeOopPtr *t = needleOper->type()->isa_oopptr();
+ ciTypeArray* needle_values = t->const_oop()->as_type_array(); // Pointer to live char *
+ jchar chr;
+#ifdef VM_LITTLE_ENDIAN
+ chr = (((jchar)(unsigned char)needle_values->element_value(1).as_byte()) << 8) |
+ ((jchar)(unsigned char)needle_values->element_value(0).as_byte());
+#else
+ chr = (((jchar)(unsigned char)needle_values->element_value(0).as_byte()) << 8) |
+ ((jchar)(unsigned char)needle_values->element_value(1).as_byte());
+#endif
+ __ string_indexof_char($result$$Register,
+ $haystack$$Register, $haycnt$$Register,
+ R0, chr,
+ $tmp1$$Register, $tmp2$$Register, false /*is_byte*/);
+ %}
+ ins_pipe(pipe_class_compare);
+%}
+
+instruct indexOf_imm1_char_L(iRegIdst result, iRegPsrc haystack, iRegIsrc haycnt,
+ immP needleImm, immL offsetImm, immI_1 needlecntImm,
+ iRegIdst tmp1, iRegIdst tmp2,
+ flagsRegCR0 cr0, flagsRegCR1 cr1, regCTR ctr) %{
+ match(Set result (StrIndexOf (Binary haystack haycnt) (Binary (AddP needleImm offsetImm) needlecntImm)));
+ effect(TEMP tmp1, TEMP tmp2, KILL cr0, KILL cr1, KILL ctr);
+ // Required for EA: check if it is still a type_array.
+ predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL);
+ ins_cost(150);
+
+ format %{ "String IndexOf CSCL1 $haystack[0..$haycnt], $needleImm+$offsetImm[0..$needlecntImm]"
+ "-> $result \t// KILL $haycnt, $tmp1, $tmp2, $cr0, $cr1" %}
+
+ ins_encode %{
+ // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+ immPOper *needleOper = (immPOper *)$needleImm;
+ const TypeOopPtr *t = needleOper->type()->isa_oopptr();
+ ciTypeArray* needle_values = t->const_oop()->as_type_array(); // Pointer to live char *
+ jchar chr = (jchar)needle_values->element_value(0).as_byte();
+ __ string_indexof_char($result$$Register,
+ $haystack$$Register, $haycnt$$Register,
+ R0, chr,
+ $tmp1$$Register, $tmp2$$Register, true /*is_byte*/);
+ %}
+ ins_pipe(pipe_class_compare);
+%}
+
+instruct indexOf_imm1_char_UL(iRegIdst result, iRegPsrc haystack, iRegIsrc haycnt,
+ immP needleImm, immL offsetImm, immI_1 needlecntImm,
+ iRegIdst tmp1, iRegIdst tmp2,
+ flagsRegCR0 cr0, flagsRegCR1 cr1, regCTR ctr) %{
+ match(Set result (StrIndexOf (Binary haystack haycnt) (Binary (AddP needleImm offsetImm) needlecntImm)));
+ effect(TEMP tmp1, TEMP tmp2, KILL cr0, KILL cr1, KILL ctr);
+ // Required for EA: check if it is still a type_array.
+ predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL);
+ ins_cost(150);
+
+ format %{ "String IndexOf CSCL1 $haystack[0..$haycnt], $needleImm+$offsetImm[0..$needlecntImm]"
+ "-> $result \t// KILL $haycnt, $tmp1, $tmp2, $cr0, $cr1" %}
+
+ ins_encode %{
+ // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+ immPOper *needleOper = (immPOper *)$needleImm;
+ const TypeOopPtr *t = needleOper->type()->isa_oopptr();
+ ciTypeArray* needle_values = t->const_oop()->as_type_array(); // Pointer to live char *
+ jchar chr = (jchar)needle_values->element_value(0).as_byte();
+ __ string_indexof_char($result$$Register,
+ $haystack$$Register, $haycnt$$Register,
+ R0, chr,
+ $tmp1$$Register, $tmp2$$Register, false /*is_byte*/);
+ %}
+ ins_pipe(pipe_class_compare);
+%}
+
+instruct indexOf_imm1_U(iRegIdst result, iRegPsrc haystack, iRegIsrc haycnt,
+ rscratch2RegP needle, immI_1 needlecntImm,
+ iRegIdst tmp1, iRegIdst tmp2,
+ flagsRegCR0 cr0, flagsRegCR1 cr1, regCTR ctr) %{
+ match(Set result (StrIndexOf (Binary haystack haycnt) (Binary needle needlecntImm)));
+ effect(USE_KILL needle, TEMP tmp1, TEMP tmp2, KILL cr0, KILL cr1, KILL ctr);
+ // Required for EA: check if it is still a type_array.
+ predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU &&
+ n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop() &&
+ n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop()->is_type_array());
+ ins_cost(180);
+
+ format %{ "String IndexOf SCL1 $haystack[0..$haycnt], $needle[0..$needlecntImm]"
+ " -> $result \t// KILL $haycnt, $needle, $tmp1, $tmp2, $cr0, $cr1" %}
+ ins_encode %{
+ // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+ Node *ndl = in(operand_index($needle)); // The node that defines needle.
+ ciTypeArray* needle_values = ndl->bottom_type()->is_aryptr()->const_oop()->as_type_array();
+ guarantee(needle_values, "sanity");
+ jchar chr;
+#ifdef VM_LITTLE_ENDIAN
+ chr = (((jchar)(unsigned char)needle_values->element_value(1).as_byte()) << 8) |
+ ((jchar)(unsigned char)needle_values->element_value(0).as_byte());
+#else
+ chr = (((jchar)(unsigned char)needle_values->element_value(0).as_byte()) << 8) |
+ ((jchar)(unsigned char)needle_values->element_value(1).as_byte());
+#endif
+ __ string_indexof_char($result$$Register,
+ $haystack$$Register, $haycnt$$Register,
+ R0, chr,
+ $tmp1$$Register, $tmp2$$Register, false /*is_byte*/);
+ %}
+ ins_pipe(pipe_class_compare);
+%}
+
+instruct indexOf_imm1_L(iRegIdst result, iRegPsrc haystack, iRegIsrc haycnt,
+ rscratch2RegP needle, immI_1 needlecntImm,
+ iRegIdst tmp1, iRegIdst tmp2,
+ flagsRegCR0 cr0, flagsRegCR1 cr1, regCTR ctr) %{
+ match(Set result (StrIndexOf (Binary haystack haycnt) (Binary needle needlecntImm)));
+ effect(USE_KILL needle, TEMP tmp1, TEMP tmp2, KILL cr0, KILL cr1, KILL ctr);
+ // Required for EA: check if it is still a type_array.
+ predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL &&
+ n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop() &&
+ n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop()->is_type_array());
+ ins_cost(180);
+
+ format %{ "String IndexOf SCL1 $haystack[0..$haycnt], $needle[0..$needlecntImm]"
+ " -> $result \t// KILL $haycnt, $needle, $tmp1, $tmp2, $cr0, $cr1" %}
+ ins_encode %{
+ // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+ Node *ndl = in(operand_index($needle)); // The node that defines needle.
+ ciTypeArray* needle_values = ndl->bottom_type()->is_aryptr()->const_oop()->as_type_array();
+ guarantee(needle_values, "sanity");
+ jchar chr = (jchar)needle_values->element_value(0).as_byte();
+ __ string_indexof_char($result$$Register,
+ $haystack$$Register, $haycnt$$Register,
+ R0, chr,
+ $tmp1$$Register, $tmp2$$Register, true /*is_byte*/);
+ %}
+ ins_pipe(pipe_class_compare);
+%}
+
+instruct indexOf_imm1_UL(iRegIdst result, iRegPsrc haystack, iRegIsrc haycnt,
+ rscratch2RegP needle, immI_1 needlecntImm,
+ iRegIdst tmp1, iRegIdst tmp2,
+ flagsRegCR0 cr0, flagsRegCR1 cr1, regCTR ctr) %{
+ match(Set result (StrIndexOf (Binary haystack haycnt) (Binary needle needlecntImm)));
+ effect(USE_KILL needle, TEMP tmp1, TEMP tmp2, KILL cr0, KILL cr1, KILL ctr);
+ // Required for EA: check if it is still a type_array.
+ predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL &&
+ n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop() &&
+ n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop()->is_type_array());
+ ins_cost(180);
+
+ format %{ "String IndexOf SCL1 $haystack[0..$haycnt], $needle[0..$needlecntImm]"
+ " -> $result \t// KILL $haycnt, $needle, $tmp1, $tmp2, $cr0, $cr1" %}
+ ins_encode %{
+ // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+ Node *ndl = in(operand_index($needle)); // The node that defines needle.
+ ciTypeArray* needle_values = ndl->bottom_type()->is_aryptr()->const_oop()->as_type_array();
+ guarantee(needle_values, "sanity");
+ jchar chr = (jchar)needle_values->element_value(0).as_byte();
+ __ string_indexof_char($result$$Register,
+ $haystack$$Register, $haycnt$$Register,
+ R0, chr,
+ $tmp1$$Register, $tmp2$$Register, false /*is_byte*/);
+ %}
+ ins_pipe(pipe_class_compare);
+%}
+
+instruct indexOfChar_U(iRegIdst result, iRegPsrc haystack, iRegIsrc haycnt,
+ iRegIsrc ch, iRegIdst tmp1, iRegIdst tmp2,
+ flagsRegCR0 cr0, flagsRegCR1 cr1, regCTR ctr) %{
+ match(Set result (StrIndexOfChar (Binary haystack haycnt) ch));
+ effect(TEMP tmp1, TEMP tmp2, KILL cr0, KILL cr1, KILL ctr);
+ predicate(CompactStrings);
+ ins_cost(180);
+
+ format %{ "String IndexOfChar $haystack[0..$haycnt], $ch"
+ " -> $result \t// KILL $haycnt, $tmp1, $tmp2, $cr0, $cr1" %}
+ ins_encode %{
+ // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+ __ string_indexof_char($result$$Register,
+ $haystack$$Register, $haycnt$$Register,
+ $ch$$Register, 0 /* this is not used if the character is already in a register */,
+ $tmp1$$Register, $tmp2$$Register, false /*is_byte*/);
+ %}
+ ins_pipe(pipe_class_compare);
+%}
+
+instruct indexOf_imm_U(iRegIdst result, iRegPsrc haystack, rscratch1RegI haycnt,
+ iRegPsrc needle, uimmI15 needlecntImm,
+ iRegIdst tmp1, iRegIdst tmp2, iRegIdst tmp3, iRegIdst tmp4, iRegIdst tmp5,
+ flagsRegCR0 cr0, flagsRegCR1 cr1, flagsRegCR6 cr6, regCTR ctr) %{
+ match(Set result (StrIndexOf (Binary haystack haycnt) (Binary needle needlecntImm)));
+ effect(USE_KILL haycnt, /* better: TDEF haycnt, */ TEMP_DEF result,
+ TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, KILL cr0, KILL cr1, KILL cr6, KILL ctr);
+ // Required for EA: check if it is still a type_array.
+ predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU &&
+ n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop() &&
+ n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop()->is_type_array());
+ ins_cost(250);
+
+ format %{ "String IndexOf SCL $haystack[0..$haycnt], $needle[0..$needlecntImm]"
+ " -> $result \t// KILL $haycnt, $tmp1, $tmp2, $tmp3, $tmp4, $tmp5, $cr0, $cr1" %}
+ ins_encode %{
+ // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+ Node *ndl = in(operand_index($needle)); // The node that defines needle.
+ ciTypeArray* needle_values = ndl->bottom_type()->is_aryptr()->const_oop()->as_type_array();
+
+ __ string_indexof($result$$Register,
+ $haystack$$Register, $haycnt$$Register,
+ $needle$$Register, needle_values, $tmp5$$Register, $needlecntImm$$constant,
+ $tmp1$$Register, $tmp2$$Register, $tmp3$$Register, $tmp4$$Register, StrIntrinsicNode::UU);
+ %}
+ ins_pipe(pipe_class_compare);
+%}
+
+instruct indexOf_imm_L(iRegIdst result, iRegPsrc haystack, rscratch1RegI haycnt,
+ iRegPsrc needle, uimmI15 needlecntImm,
+ iRegIdst tmp1, iRegIdst tmp2, iRegIdst tmp3, iRegIdst tmp4, iRegIdst tmp5,
+ flagsRegCR0 cr0, flagsRegCR1 cr1, flagsRegCR6 cr6, regCTR ctr) %{
+ match(Set result (StrIndexOf (Binary haystack haycnt) (Binary needle needlecntImm)));
+ effect(USE_KILL haycnt, /* better: TDEF haycnt, */ TEMP_DEF result,
+ TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, KILL cr0, KILL cr1, KILL cr6, KILL ctr);
+ // Required for EA: check if it is still a type_array.
+ predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL &&
+ n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop() &&
+ n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop()->is_type_array());
+ ins_cost(250);
+
+ format %{ "String IndexOf SCL $haystack[0..$haycnt], $needle[0..$needlecntImm]"
+ " -> $result \t// KILL $haycnt, $tmp1, $tmp2, $tmp3, $tmp4, $tmp5, $cr0, $cr1" %}
+ ins_encode %{
+ // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+ Node *ndl = in(operand_index($needle)); // The node that defines needle.
+ ciTypeArray* needle_values = ndl->bottom_type()->is_aryptr()->const_oop()->as_type_array();
+
+ __ string_indexof($result$$Register,
+ $haystack$$Register, $haycnt$$Register,
+ $needle$$Register, needle_values, $tmp5$$Register, $needlecntImm$$constant,
+ $tmp1$$Register, $tmp2$$Register, $tmp3$$Register, $tmp4$$Register, StrIntrinsicNode::LL);
+ %}
+ ins_pipe(pipe_class_compare);
+%}
+
+instruct indexOf_imm_UL(iRegIdst result, iRegPsrc haystack, rscratch1RegI haycnt,
+ iRegPsrc needle, uimmI15 needlecntImm,
+ iRegIdst tmp1, iRegIdst tmp2, iRegIdst tmp3, iRegIdst tmp4, iRegIdst tmp5,
+ flagsRegCR0 cr0, flagsRegCR1 cr1, flagsRegCR6 cr6, regCTR ctr) %{
+ match(Set result (StrIndexOf (Binary haystack haycnt) (Binary needle needlecntImm)));
+ effect(USE_KILL haycnt, /* better: TDEF haycnt, */ TEMP_DEF result,
+ TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, KILL cr0, KILL cr1, KILL cr6, KILL ctr);
+ // Required for EA: check if it is still a type_array.
+ predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL &&
+ n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop() &&
+ n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop()->is_type_array());
+ ins_cost(250);
+
+ format %{ "String IndexOf SCL $haystack[0..$haycnt], $needle[0..$needlecntImm]"
+ " -> $result \t// KILL $haycnt, $tmp1, $tmp2, $tmp3, $tmp4, $tmp5, $cr0, $cr1" %}
+ ins_encode %{
+ // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+ Node *ndl = in(operand_index($needle)); // The node that defines needle.
+ ciTypeArray* needle_values = ndl->bottom_type()->is_aryptr()->const_oop()->as_type_array();
+
+ __ string_indexof($result$$Register,
+ $haystack$$Register, $haycnt$$Register,
+ $needle$$Register, needle_values, $tmp5$$Register, $needlecntImm$$constant,
+ $tmp1$$Register, $tmp2$$Register, $tmp3$$Register, $tmp4$$Register, StrIntrinsicNode::UL);
+ %}
+ ins_pipe(pipe_class_compare);
+%}
+
+instruct indexOf_U(iRegIdst result, iRegPsrc haystack, rscratch1RegI haycnt, iRegPsrc needle, rscratch2RegI needlecnt,
+ iRegLdst tmp1, iRegLdst tmp2, iRegLdst tmp3, iRegLdst tmp4,
+ flagsRegCR0 cr0, flagsRegCR1 cr1, flagsRegCR6 cr6, regCTR ctr) %{
+ match(Set result (StrIndexOf (Binary haystack haycnt) (Binary needle needlecnt)));
+ effect(USE_KILL haycnt, USE_KILL needlecnt, /*better: TDEF haycnt, TDEF needlecnt,*/
+ TEMP_DEF result,
+ TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr0, KILL cr1, KILL cr6, KILL ctr);
+ predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU);
+ ins_cost(300);
+
+ format %{ "String IndexOf $haystack[0..$haycnt], $needle[0..$needlecnt]"
+ " -> $result \t// KILL $haycnt, $needlecnt, $tmp1, $tmp2, $tmp3, $tmp4, $cr0, $cr1" %}
+ ins_encode %{
+ // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+ __ string_indexof($result$$Register,
+ $haystack$$Register, $haycnt$$Register,
+ $needle$$Register, NULL, $needlecnt$$Register, 0, // needlecnt not constant.
+ $tmp1$$Register, $tmp2$$Register, $tmp3$$Register, $tmp4$$Register, StrIntrinsicNode::UU);
+ %}
+ ins_pipe(pipe_class_compare);
+%}
+
+instruct indexOf_L(iRegIdst result, iRegPsrc haystack, rscratch1RegI haycnt, iRegPsrc needle, rscratch2RegI needlecnt,
+ iRegLdst tmp1, iRegLdst tmp2, iRegLdst tmp3, iRegLdst tmp4,
+ flagsRegCR0 cr0, flagsRegCR1 cr1, flagsRegCR6 cr6, regCTR ctr) %{
+ match(Set result (StrIndexOf (Binary haystack haycnt) (Binary needle needlecnt)));
+ effect(USE_KILL haycnt, USE_KILL needlecnt, /*better: TDEF haycnt, TDEF needlecnt,*/
+ TEMP_DEF result,
+ TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr0, KILL cr1, KILL cr6, KILL ctr);
+ predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL);
+ ins_cost(300);
+
+ format %{ "String IndexOf $haystack[0..$haycnt], $needle[0..$needlecnt]"
+ " -> $result \t// KILL $haycnt, $needlecnt, $tmp1, $tmp2, $tmp3, $tmp4, $cr0, $cr1" %}
+ ins_encode %{
+ // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+ __ string_indexof($result$$Register,
+ $haystack$$Register, $haycnt$$Register,
+ $needle$$Register, NULL, $needlecnt$$Register, 0, // needlecnt not constant.
+ $tmp1$$Register, $tmp2$$Register, $tmp3$$Register, $tmp4$$Register, StrIntrinsicNode::LL);
+ %}
+ ins_pipe(pipe_class_compare);
+%}
+
+instruct indexOf_UL(iRegIdst result, iRegPsrc haystack, rscratch1RegI haycnt, iRegPsrc needle, rscratch2RegI needlecnt,
+ iRegLdst tmp1, iRegLdst tmp2, iRegLdst tmp3, iRegLdst tmp4,
+ flagsRegCR0 cr0, flagsRegCR1 cr1, flagsRegCR6 cr6, regCTR ctr) %{
+ match(Set result (StrIndexOf (Binary haystack haycnt) (Binary needle needlecnt)));
+ effect(USE_KILL haycnt, USE_KILL needlecnt, /*better: TDEF haycnt, TDEF needlecnt,*/
+ TEMP_DEF result,
+ TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr0, KILL cr1, KILL cr6, KILL ctr);
+ predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL);
+ ins_cost(300);
+
+ format %{ "String IndexOf $haystack[0..$haycnt], $needle[0..$needlecnt]"
+ " -> $result \t// KILL $haycnt, $needlecnt, $tmp1, $tmp2, $tmp3, $tmp4, $cr0, $cr1" %}
+ ins_encode %{
+ // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+ __ string_indexof($result$$Register,
+ $haystack$$Register, $haycnt$$Register,
+ $needle$$Register, NULL, $needlecnt$$Register, 0, // needlecnt not constant.
+ $tmp1$$Register, $tmp2$$Register, $tmp3$$Register, $tmp4$$Register, StrIntrinsicNode::UL);
+ %}
+ ins_pipe(pipe_class_compare);
+%}
+
+// char[] to byte[] compression
+instruct string_compress(rarg1RegP src, rarg2RegP dst, iRegIsrc len, iRegIdst result, iRegLdst tmp1,
+ iRegLdst tmp2, iRegLdst tmp3, iRegLdst tmp4, iRegLdst tmp5, regCTR ctr, flagsRegCR0 cr0) %{
+ match(Set result (StrCompressedCopy src (Binary dst len)));
+ effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5,
+ USE_KILL src, USE_KILL dst, KILL ctr, KILL cr0);
+ ins_cost(300);
+ format %{ "String Compress $src,$dst,$len -> $result \t// KILL $tmp1, $tmp2, $tmp3, $tmp4, $tmp5" %}
+ ins_encode %{
+ // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+ Label Lskip, Ldone;
+ __ li($result$$Register, 0);
+ __ string_compress_16($src$$Register, $dst$$Register, $len$$Register, $tmp1$$Register,
+ $tmp2$$Register, $tmp3$$Register, $tmp4$$Register, $tmp5$$Register, Ldone);
+ __ rldicl_($tmp1$$Register, $len$$Register, 0, 64-3); // Remaining characters.
+ __ beq(CCR0, Lskip);
+ __ string_compress($src$$Register, $dst$$Register, $tmp1$$Register, $tmp2$$Register, Ldone);
+ __ bind(Lskip);
+ __ mr($result$$Register, $len$$Register);
+ __ bind(Ldone);
+ %}
+ ins_pipe(pipe_class_default);
+%}
+
+// byte[] to char[] inflation
+instruct string_inflate(Universe dummy, rarg1RegP src, rarg2RegP dst, iRegIsrc len, iRegLdst tmp1,
+ iRegLdst tmp2, iRegLdst tmp3, iRegLdst tmp4, iRegLdst tmp5, regCTR ctr, flagsRegCR0 cr0) %{
+ match(Set dummy (StrInflatedCopy src (Binary dst len)));
+ effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, USE_KILL src, USE_KILL dst, KILL ctr, KILL cr0);
+ ins_cost(300);
+ format %{ "String Inflate $src,$dst,$len \t// KILL $tmp1, $tmp2, $tmp3, $tmp4, $tmp5" %}
+ ins_encode %{
+ // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+ Label Ldone;
+ __ string_inflate_16($src$$Register, $dst$$Register, $len$$Register, $tmp1$$Register,
+ $tmp2$$Register, $tmp3$$Register, $tmp4$$Register, $tmp5$$Register);
+ __ rldicl_($tmp1$$Register, $len$$Register, 0, 64-3); // Remaining characters.
+ __ beq(CCR0, Ldone);
+ __ string_inflate($src$$Register, $dst$$Register, $tmp1$$Register, $tmp2$$Register);
+ __ bind(Ldone);
+ %}
+ ins_pipe(pipe_class_default);
+%}
+
+// StringCoding.java intrinsics
+instruct has_negatives(rarg1RegP ary1, iRegIsrc len, iRegIdst result, iRegLdst tmp1, iRegLdst tmp2,
+ regCTR ctr, flagsRegCR0 cr0)
+%{
+ match(Set result (HasNegatives ary1 len));
+ effect(TEMP_DEF result, USE_KILL ary1, TEMP tmp1, TEMP tmp2, KILL ctr, KILL cr0);
+ ins_cost(300);
+ format %{ "has negatives byte[] $ary1,$len -> $result \t// KILL $tmp1, $tmp2" %}
+ ins_encode %{
+ // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+ __ has_negatives($ary1$$Register, $len$$Register, $result$$Register,
+ $tmp1$$Register, $tmp2$$Register);
+ %}
+ ins_pipe(pipe_class_default);
+%}
+
+// encode char[] to byte[] in ISO_8859_1
+instruct encode_iso_array(rarg1RegP src, rarg2RegP dst, iRegIsrc len, iRegIdst result, iRegLdst tmp1,
+ iRegLdst tmp2, iRegLdst tmp3, iRegLdst tmp4, iRegLdst tmp5, regCTR ctr, flagsRegCR0 cr0) %{
+ match(Set result (EncodeISOArray src (Binary dst len)));
+ effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5,
+ USE_KILL src, USE_KILL dst, KILL ctr, KILL cr0);
+ ins_cost(300);
+ format %{ "Encode array $src,$dst,$len -> $result \t// KILL $tmp1, $tmp2, $tmp3, $tmp4, $tmp5" %}
+ ins_encode %{
+ // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+ Label Lslow, Lfailure1, Lfailure2, Ldone;
+ __ string_compress_16($src$$Register, $dst$$Register, $len$$Register, $tmp1$$Register,
+ $tmp2$$Register, $tmp3$$Register, $tmp4$$Register, $tmp5$$Register, Lfailure1);
+ __ rldicl_($result$$Register, $len$$Register, 0, 64-3); // Remaining characters.
+ __ beq(CCR0, Ldone);
+ __ bind(Lslow);
+ __ string_compress($src$$Register, $dst$$Register, $result$$Register, $tmp2$$Register, Lfailure2);
+ __ li($result$$Register, 0);
+ __ b(Ldone);
+
+ __ bind(Lfailure1);
+ __ mr($result$$Register, $len$$Register);
+ __ mfctr($tmp1$$Register);
+ __ rldimi_($result$$Register, $tmp1$$Register, 3, 0); // Remaining characters.
+ __ beq(CCR0, Ldone);
+ __ b(Lslow);
+
+ __ bind(Lfailure2);
+ __ mfctr($result$$Register); // Remaining characters.
+
+ __ bind(Ldone);
+ __ subf($result$$Register, $result$$Register, $len$$Register);
+ %}
+ ins_pipe(pipe_class_default);
+%}
+
+
// String_IndexOf for needle of length 1.
//
// Match needle into immediate operands: no loadConP node needed. Saves one
@@ -11060,11 +11638,11 @@
if (java_lang_String::has_coder_field()) {
// New compact strings byte array strings
#ifdef VM_LITTLE_ENDIAN
- chr = (((jchar)needle_values->element_value(1).as_byte()) << 8) |
- (jchar)needle_values->element_value(0).as_byte();
+ chr = (((jchar)(unsigned char)needle_values->element_value(1).as_byte()) << 8) |
+ ((jchar)(unsigned char)needle_values->element_value(0).as_byte());
#else
- chr = (((jchar)needle_values->element_value(0).as_byte()) << 8) |
- (jchar)needle_values->element_value(1).as_byte();
+ chr = (((jchar)(unsigned char)needle_values->element_value(0).as_byte()) << 8) |
+ ((jchar)(unsigned char)needle_values->element_value(1).as_byte());
#endif
} else {
// Old char array strings
@@ -11115,11 +11693,11 @@
if (java_lang_String::has_coder_field()) {
// New compact strings byte array strings
#ifdef VM_LITTLE_ENDIAN
- chr = (((jchar)needle_values->element_value(1).as_byte()) << 8) |
- (jchar)needle_values->element_value(0).as_byte();
+ chr = (((jchar)(unsigned char)needle_values->element_value(1).as_byte()) << 8) |
+ ((jchar)(unsigned char)needle_values->element_value(0).as_byte());
#else
- chr = (((jchar)needle_values->element_value(0).as_byte()) << 8) |
- (jchar)needle_values->element_value(1).as_byte();
+ chr = (((jchar)(unsigned char)needle_values->element_value(0).as_byte()) << 8) |
+ ((jchar)(unsigned char)needle_values->element_value(1).as_byte());
#endif
} else {
// Old char array strings
@@ -11321,6 +11899,20 @@
%}
%}
+instruct minI_reg_reg_isel(iRegIdst dst, iRegIsrc src1, iRegIsrc src2, flagsRegCR0 cr0) %{
+ match(Set dst (MinI src1 src2));
+ effect(KILL cr0);
+ predicate(VM_Version::has_isel());
+ ins_cost(DEFAULT_COST*2);
+
+ ins_encode %{
+ // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+ __ cmpw(CCR0, $src1$$Register, $src2$$Register);
+ __ isel($dst$$Register, CCR0, Assembler::less, /*invert*/false, $src1$$Register, $src2$$Register);
+ %}
+ ins_pipe(pipe_class_default);
+%}
+
instruct maxI_reg_reg_Ex(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{
match(Set dst (MaxI src1 src2));
ins_cost(DEFAULT_COST*6);
@@ -11341,6 +11933,20 @@
%}
%}
+instruct maxI_reg_reg_isel(iRegIdst dst, iRegIsrc src1, iRegIsrc src2, flagsRegCR0 cr0) %{
+ match(Set dst (MaxI src1 src2));
+ effect(KILL cr0);
+ predicate(VM_Version::has_isel());
+ ins_cost(DEFAULT_COST*2);
+
+ ins_encode %{
+ // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+ __ cmpw(CCR0, $src1$$Register, $src2$$Register);
+ __ isel($dst$$Register, CCR0, Assembler::greater, /*invert*/false, $src1$$Register, $src2$$Register);
+ %}
+ ins_pipe(pipe_class_default);
+%}
+
//---------- Population Count Instructions ------------------------------------
// Popcnt for Power7.
--- a/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -2609,9 +2609,7 @@
* R5_ARG3 - int length (of buffer)
*
* scratch:
- * R6_ARG4 - crc table address
- * R7_ARG5 - tmp1
- * R8_ARG6 - tmp2
+ * R2, R6-R12
*
* Ouput:
* R3_RET - int crc result
@@ -2623,22 +2621,25 @@
address start = __ function_entry(); // Remember stub start address (is rtn value).
// arguments to kernel_crc32:
- Register crc = R3_ARG1; // Current checksum, preset by caller or result from previous call.
- Register data = R4_ARG2; // source byte array
- Register dataLen = R5_ARG3; // #bytes to process
- Register table = R6_ARG4; // crc table address
-
- Register t0 = R9; // work reg for kernel* emitters
- Register t1 = R10; // work reg for kernel* emitters
- Register t2 = R11; // work reg for kernel* emitters
- Register t3 = R12; // work reg for kernel* emitters
+ const Register crc = R3_ARG1; // Current checksum, preset by caller or result from previous call.
+ const Register data = R4_ARG2; // source byte array
+ const Register dataLen = R5_ARG3; // #bytes to process
+ const Register table = R6_ARG4; // crc table address
+
+ const Register t0 = R2;
+ const Register t1 = R7;
+ const Register t2 = R8;
+ const Register t3 = R9;
+ const Register tc0 = R10;
+ const Register tc1 = R11;
+ const Register tc2 = R12;
BLOCK_COMMENT("Stub body {");
assert_different_registers(crc, data, dataLen, table);
StubRoutines::ppc64::generate_load_crc_table_addr(_masm, table);
- __ kernel_crc32_1byte(crc, data, dataLen, table, t0, t1, t2, t3);
+ __ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3, tc0, tc1, tc2, table);
BLOCK_COMMENT("return");
__ mr_if_needed(R3_RET, crc); // Updated crc is function result. No copying required (R3_ARG1 == R3_RET).
--- a/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2015 SAP SE. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016 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
@@ -53,7 +53,7 @@
// If PowerArchitecturePPC64 hasn't been specified explicitly determine from features.
if (FLAG_IS_DEFAULT(PowerArchitecturePPC64)) {
- if (VM_Version::has_tcheck() && VM_Version::has_lqarx()) {
+ if (VM_Version::has_lqarx()) {
FLAG_SET_ERGO(uintx, PowerArchitecturePPC64, 8);
} else if (VM_Version::has_popcntw()) {
FLAG_SET_ERGO(uintx, PowerArchitecturePPC64, 7);
@@ -68,8 +68,7 @@
bool PowerArchitecturePPC64_ok = false;
switch (PowerArchitecturePPC64) {
- case 8: if (!VM_Version::has_tcheck() ) break;
- if (!VM_Version::has_lqarx() ) break;
+ case 8: if (!VM_Version::has_lqarx() ) break;
case 7: if (!VM_Version::has_popcntw()) break;
case 6: if (!VM_Version::has_cmpb() ) break;
case 5: if (!VM_Version::has_popcntb()) break;
@@ -80,7 +79,7 @@
UINTX_FORMAT " on this machine", PowerArchitecturePPC64);
// Power 8: Configure Data Stream Control Register.
- if (PowerArchitecturePPC64 >= 8) {
+ if (has_mfdscr()) {
config_dscr();
}
@@ -112,7 +111,7 @@
// Create and print feature-string.
char buf[(num_features+1) * 16]; // Max 16 chars per feature.
jio_snprintf(buf, sizeof(buf),
- "ppc64%s%s%s%s%s%s%s%s%s%s%s%s",
+ "ppc64%s%s%s%s%s%s%s%s%s%s%s%s%s",
(has_fsqrt() ? " fsqrt" : ""),
(has_isel() ? " isel" : ""),
(has_lxarxeh() ? " lxarxeh" : ""),
@@ -125,7 +124,8 @@
(has_lqarx() ? " lqarx" : ""),
(has_vcipher() ? " vcipher" : ""),
(has_vpmsumb() ? " vpmsumb" : ""),
- (has_tcheck() ? " tcheck" : "")
+ (has_tcheck() ? " tcheck" : ""),
+ (has_mfdscr() ? " mfdscr" : "")
// Make sure number of %s matches num_features!
);
_features_string = os::strdup(buf);
@@ -610,6 +610,7 @@
a->vcipher(VR0, VR1, VR2); // code[10] -> vcipher
a->vpmsumb(VR0, VR1, VR2); // code[11] -> vpmsumb
a->tcheck(0); // code[12] -> tcheck
+ a->mfdscr(R0); // code[13] -> mfdscr
a->blr();
// Emit function to set one cache line to zero. Emit function descriptor and get pointer to it.
@@ -657,6 +658,7 @@
if (code[feature_cntr++]) features |= vcipher_m;
if (code[feature_cntr++]) features |= vpmsumb_m;
if (code[feature_cntr++]) features |= tcheck_m;
+ if (code[feature_cntr++]) features |= mfdscr_m;
// Print the detection code.
if (PrintAssembly) {
@@ -670,8 +672,6 @@
// Power 8: Configure Data Stream Control Register.
void VM_Version::config_dscr() {
- assert(has_tcheck(), "Only execute on Power 8 or later!");
-
// 7 InstWords for each call (function descriptor + blr instruction).
const int code_size = (2+2*7)*BytesPerInstWord;
--- a/hotspot/src/cpu/ppc/vm/vm_version_ppc.hpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/cpu/ppc/vm/vm_version_ppc.hpp Wed Mar 09 14:18:12 2016 +0100
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2015 SAP SE. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016 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
@@ -45,6 +45,7 @@
vcipher,
vpmsumb,
tcheck,
+ mfdscr,
num_features // last entry to count features
};
enum Feature_Flag_Set {
@@ -62,6 +63,7 @@
vcipher_m = (1 << vcipher),
vpmsumb_m = (1 << vpmsumb),
tcheck_m = (1 << tcheck ),
+ mfdscr_m = (1 << mfdscr ),
all_features_m = (unsigned long)-1
};
@@ -94,6 +96,7 @@
static bool has_vcipher() { return (_features & vcipher_m) != 0; }
static bool has_vpmsumb() { return (_features & vpmsumb_m) != 0; }
static bool has_tcheck() { return (_features & tcheck_m) != 0; }
+ static bool has_mfdscr() { return (_features & mfdscr_m) != 0; }
// Assembler testing
static void allow_all();
--- a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -1349,9 +1349,12 @@
}
} else if (dst.first()->is_stack()) {
// reg to stack
- __ st_ptr(src.first()->as_Register(), SP, reg2offset(dst.first()) + STACK_BIAS);
+ // Some compilers (gcc) expect a clean 32 bit value on function entry
+ __ signx(src.first()->as_Register(), L5);
+ __ st_ptr(L5, SP, reg2offset(dst.first()) + STACK_BIAS);
} else {
- __ mov(src.first()->as_Register(), dst.first()->as_Register());
+ // Some compilers (gcc) expect a clean 32 bit value on function entry
+ __ signx(src.first()->as_Register(), dst.first()->as_Register());
}
}
--- a/hotspot/src/cpu/sparc/vm/sparc.ad Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/cpu/sparc/vm/sparc.ad Wed Mar 09 14:18:12 2016 +0100
@@ -948,28 +948,28 @@
}
#endif
- uint instr;
- instr = (Assembler::ldst_op << 30)
- | (dst_enc << 25)
- | (primary << 19)
- | (src1_enc << 14);
+ uint instr = (Assembler::ldst_op << 30)
+ | (dst_enc << 25)
+ | (primary << 19)
+ | (src1_enc << 14);
uint index = src2_enc;
int disp = disp32;
if (src1_enc == R_SP_enc || src1_enc == R_FP_enc) {
disp += STACK_BIAS;
- // Quick fix for JDK-8029668: check that stack offset fits, bailout if not
+ // Check that stack offset fits, load into O7 if not
if (!Assembler::is_simm13(disp)) {
- ra->C->record_method_not_compilable("unable to handle large constant offsets");
- return;
+ MacroAssembler _masm(&cbuf);
+ __ set(disp, O7);
+ if (index != R_G0_enc) {
+ __ add(O7, reg_to_register_object(index), O7);
+ }
+ index = R_O7_enc;
+ disp = 0;
}
}
- // We should have a compiler bailout here rather than a guarantee.
- // Better yet would be some mechanism to handle variable-size matches correctly.
- guarantee(Assembler::is_simm13(disp), "Do not match large constant offsets" );
-
if( disp == 0 ) {
// use reg-reg form
// bit 13 is already zero
@@ -983,7 +983,7 @@
cbuf.insts()->emit_int32(instr);
#ifdef ASSERT
- {
+ if (VerifyOops) {
MacroAssembler _masm(&cbuf);
if (is_verified_oop_base) {
__ verify_oop(reg_to_register_object(src1_enc));
@@ -1342,7 +1342,7 @@
// Figure out which register class each belongs in: rc_int, rc_float, rc_stack
enum RC { rc_bad, rc_int, rc_float, rc_stack };
static enum RC rc_class( OptoReg::Name reg ) {
- if( !OptoReg::is_valid(reg) ) return rc_bad;
+ if (!OptoReg::is_valid(reg)) return rc_bad;
if (OptoReg::is_stack(reg)) return rc_stack;
VMReg r = OptoReg::as_VMReg(reg);
if (r->is_Register()) return rc_int;
@@ -1350,66 +1350,79 @@
return rc_float;
}
-static int impl_helper(const MachNode* mach, CodeBuffer* cbuf, PhaseRegAlloc* ra, bool do_size, bool is_load, int offset, int reg, int opcode, const char *op_str, int size, outputStream* st ) {
+#ifndef PRODUCT
+ATTRIBUTE_PRINTF(2, 3)
+static void print_helper(outputStream* st, const char* format, ...) {
+ if (st->position() > 0) {
+ st->cr();
+ st->sp();
+ }
+ va_list ap;
+ va_start(ap, format);
+ st->vprint(format, ap);
+ va_end(ap);
+}
+#endif // !PRODUCT
+
+static void impl_helper(const MachNode* mach, CodeBuffer* cbuf, PhaseRegAlloc* ra, bool is_load, int offset, int reg, int opcode, const char *op_str, outputStream* st) {
if (cbuf) {
emit_form3_mem_reg(*cbuf, ra, mach, opcode, -1, R_SP_enc, offset, 0, Matcher::_regEncode[reg]);
}
#ifndef PRODUCT
- else if (!do_size) {
- if (size != 0) st->print("\n\t");
- if (is_load) st->print("%s [R_SP + #%d],R_%s\t! spill",op_str,offset,OptoReg::regname(reg));
- else st->print("%s R_%s,[R_SP + #%d]\t! spill",op_str,OptoReg::regname(reg),offset);
+ else {
+ if (is_load) {
+ print_helper(st, "%s [R_SP + #%d],R_%s\t! spill", op_str, offset, OptoReg::regname(reg));
+ } else {
+ print_helper(st, "%s R_%s,[R_SP + #%d]\t! spill", op_str, OptoReg::regname(reg), offset);
+ }
}
#endif
- return size+4;
}
-static int impl_mov_helper( CodeBuffer *cbuf, bool do_size, int src, int dst, int op1, int op2, const char *op_str, int size, outputStream* st ) {
- if( cbuf ) emit3( *cbuf, Assembler::arith_op, Matcher::_regEncode[dst], op1, 0, op2, Matcher::_regEncode[src] );
+static void impl_mov_helper(CodeBuffer *cbuf, int src, int dst, int op1, int op2, const char *op_str, outputStream* st) {
+ if (cbuf) {
+ emit3(*cbuf, Assembler::arith_op, Matcher::_regEncode[dst], op1, 0, op2, Matcher::_regEncode[src]);
+ }
#ifndef PRODUCT
- else if( !do_size ) {
- if( size != 0 ) st->print("\n\t");
- st->print("%s R_%s,R_%s\t! spill",op_str,OptoReg::regname(src),OptoReg::regname(dst));
+ else {
+ print_helper(st, "%s R_%s,R_%s\t! spill", op_str, OptoReg::regname(src), OptoReg::regname(dst));
}
#endif
- return size+4;
}
-uint MachSpillCopyNode::implementation( CodeBuffer *cbuf,
- PhaseRegAlloc *ra_,
- bool do_size,
- outputStream* st ) const {
+static void mach_spill_copy_implementation_helper(const MachNode* mach,
+ CodeBuffer *cbuf,
+ PhaseRegAlloc *ra_,
+ outputStream* st) {
// Get registers to move
- OptoReg::Name src_second = ra_->get_reg_second(in(1));
- OptoReg::Name src_first = ra_->get_reg_first(in(1));
- OptoReg::Name dst_second = ra_->get_reg_second(this );
- OptoReg::Name dst_first = ra_->get_reg_first(this );
+ OptoReg::Name src_second = ra_->get_reg_second(mach->in(1));
+ OptoReg::Name src_first = ra_->get_reg_first(mach->in(1));
+ OptoReg::Name dst_second = ra_->get_reg_second(mach);
+ OptoReg::Name dst_first = ra_->get_reg_first(mach);
enum RC src_second_rc = rc_class(src_second);
- enum RC src_first_rc = rc_class(src_first);
+ enum RC src_first_rc = rc_class(src_first);
enum RC dst_second_rc = rc_class(dst_second);
- enum RC dst_first_rc = rc_class(dst_first);
-
- assert( OptoReg::is_valid(src_first) && OptoReg::is_valid(dst_first), "must move at least 1 register" );
-
- // Generate spill code!
- int size = 0;
-
- if( src_first == dst_first && src_second == dst_second )
- return size; // Self copy, no move
+ enum RC dst_first_rc = rc_class(dst_first);
+
+ assert(OptoReg::is_valid(src_first) && OptoReg::is_valid(dst_first), "must move at least 1 register");
+
+ if (src_first == dst_first && src_second == dst_second) {
+ return; // Self copy, no move
+ }
// --------------------------------------
// Check for mem-mem move. Load into unused float registers and fall into
// the float-store case.
- if( src_first_rc == rc_stack && dst_first_rc == rc_stack ) {
+ if (src_first_rc == rc_stack && dst_first_rc == rc_stack) {
int offset = ra_->reg2offset(src_first);
// Further check for aligned-adjacent pair, so we can use a double load
- if( (src_first&1)==0 && src_first+1 == src_second ) {
+ if ((src_first&1) == 0 && src_first+1 == src_second) {
src_second = OptoReg::Name(R_F31_num);
src_second_rc = rc_float;
- size = impl_helper(this,cbuf,ra_,do_size,true,offset,R_F30_num,Assembler::lddf_op3,"LDDF",size, st);
+ impl_helper(mach, cbuf, ra_, true, offset, R_F30_num, Assembler::lddf_op3, "LDDF", st);
} else {
- size = impl_helper(this,cbuf,ra_,do_size,true,offset,R_F30_num,Assembler::ldf_op3 ,"LDF ",size, st);
+ impl_helper(mach, cbuf, ra_, true, offset, R_F30_num, Assembler::ldf_op3, "LDF ", st);
}
src_first = OptoReg::Name(R_F30_num);
src_first_rc = rc_float;
@@ -1417,7 +1430,7 @@
if( src_second_rc == rc_stack && dst_second_rc == rc_stack ) {
int offset = ra_->reg2offset(src_second);
- size = impl_helper(this,cbuf,ra_,do_size,true,offset,R_F31_num,Assembler::ldf_op3,"LDF ",size, st);
+ impl_helper(mach, cbuf, ra_, true, offset, R_F31_num, Assembler::ldf_op3, "LDF ", st);
src_second = OptoReg::Name(R_F31_num);
src_second_rc = rc_float;
}
@@ -1427,36 +1440,38 @@
if (src_first_rc == rc_float && dst_first_rc == rc_int && UseVIS < 3) {
int offset = frame::register_save_words*wordSize;
if (cbuf) {
- emit3_simm13( *cbuf, Assembler::arith_op, R_SP_enc, Assembler::sub_op3, R_SP_enc, 16 );
- impl_helper(this,cbuf,ra_,do_size,false,offset,src_first,Assembler::stf_op3 ,"STF ",size, st);
- impl_helper(this,cbuf,ra_,do_size,true ,offset,dst_first,Assembler::lduw_op3,"LDUW",size, st);
- emit3_simm13( *cbuf, Assembler::arith_op, R_SP_enc, Assembler::add_op3, R_SP_enc, 16 );
+ emit3_simm13(*cbuf, Assembler::arith_op, R_SP_enc, Assembler::sub_op3, R_SP_enc, 16);
+ impl_helper(mach, cbuf, ra_, false, offset, src_first, Assembler::stf_op3, "STF ", st);
+ impl_helper(mach, cbuf, ra_, true, offset, dst_first, Assembler::lduw_op3, "LDUW", st);
+ emit3_simm13(*cbuf, Assembler::arith_op, R_SP_enc, Assembler::add_op3, R_SP_enc, 16);
}
#ifndef PRODUCT
- else if (!do_size) {
- if (size != 0) st->print("\n\t");
- st->print( "SUB R_SP,16,R_SP\n");
- impl_helper(this,cbuf,ra_,do_size,false,offset,src_first,Assembler::stf_op3 ,"STF ",size, st);
- impl_helper(this,cbuf,ra_,do_size,true ,offset,dst_first,Assembler::lduw_op3,"LDUW",size, st);
- st->print("\tADD R_SP,16,R_SP\n");
+ else {
+ print_helper(st, "SUB R_SP,16,R_SP");
+ impl_helper(mach, cbuf, ra_, false, offset, src_first, Assembler::stf_op3, "STF ", st);
+ impl_helper(mach, cbuf, ra_, true, offset, dst_first, Assembler::lduw_op3, "LDUW", st);
+ print_helper(st, "ADD R_SP,16,R_SP");
}
#endif
- size += 16;
}
// Check for float->int copy on T4
if (src_first_rc == rc_float && dst_first_rc == rc_int && UseVIS >= 3) {
// Further check for aligned-adjacent pair, so we can use a double move
- if ((src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second)
- return impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::mftoi_op3,Assembler::mdtox_opf,"MOVDTOX",size, st);
- size = impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::mftoi_op3,Assembler::mstouw_opf,"MOVSTOUW",size, st);
+ if ((src_first & 1) == 0 && src_first + 1 == src_second && (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
+ impl_mov_helper(cbuf, src_first, dst_first, Assembler::mftoi_op3, Assembler::mdtox_opf, "MOVDTOX", st);
+ return;
+ }
+ impl_mov_helper(cbuf, src_first, dst_first, Assembler::mftoi_op3, Assembler::mstouw_opf, "MOVSTOUW", st);
}
// Check for int->float copy on T4
if (src_first_rc == rc_int && dst_first_rc == rc_float && UseVIS >= 3) {
// Further check for aligned-adjacent pair, so we can use a double move
- if ((src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second)
- return impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::mftoi_op3,Assembler::mxtod_opf,"MOVXTOD",size, st);
- size = impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::mftoi_op3,Assembler::mwtos_opf,"MOVWTOS",size, st);
+ if ((src_first & 1) == 0 && src_first + 1 == src_second && (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
+ impl_mov_helper(cbuf, src_first, dst_first, Assembler::mftoi_op3, Assembler::mxtod_opf, "MOVXTOD", st);
+ return;
+ }
+ impl_mov_helper(cbuf, src_first, dst_first, Assembler::mftoi_op3, Assembler::mwtos_opf, "MOVWTOS", st);
}
// --------------------------------------
@@ -1466,10 +1481,10 @@
// there. Misaligned sources only come from native-long-returns (handled
// special below).
#ifndef _LP64
- if( src_first_rc == rc_int && // source is already big-endian
+ if (src_first_rc == rc_int && // source is already big-endian
src_second_rc != rc_bad && // 64-bit move
- ((dst_first&1)!=0 || dst_second != dst_first+1) ) { // misaligned dst
- assert( (src_first&1)==0 && src_second == src_first+1, "source must be aligned" );
+ ((dst_first & 1) != 0 || dst_second != dst_first + 1)) { // misaligned dst
+ assert((src_first & 1) == 0 && src_second == src_first + 1, "source must be aligned");
// Do the big-endian flop.
OptoReg::Name tmp = dst_first ; dst_first = dst_second ; dst_second = tmp ;
enum RC tmp_rc = dst_first_rc; dst_first_rc = dst_second_rc; dst_second_rc = tmp_rc;
@@ -1478,30 +1493,28 @@
// --------------------------------------
// Check for integer reg-reg copy
- if( src_first_rc == rc_int && dst_first_rc == rc_int ) {
+ if (src_first_rc == rc_int && dst_first_rc == rc_int) {
#ifndef _LP64
- if( src_first == R_O0_num && src_second == R_O1_num ) { // Check for the evil O0/O1 native long-return case
+ if (src_first == R_O0_num && src_second == R_O1_num) { // Check for the evil O0/O1 native long-return case
// Note: The _first and _second suffixes refer to the addresses of the the 2 halves of the 64-bit value
// as stored in memory. On a big-endian machine like SPARC, this means that the _second
// operand contains the least significant word of the 64-bit value and vice versa.
OptoReg::Name tmp = OptoReg::Name(R_O7_num);
- assert( (dst_first&1)==0 && dst_second == dst_first+1, "return a native O0/O1 long to an aligned-adjacent 64-bit reg" );
+ assert((dst_first & 1) == 0 && dst_second == dst_first + 1, "return a native O0/O1 long to an aligned-adjacent 64-bit reg" );
// Shift O0 left in-place, zero-extend O1, then OR them into the dst
- if( cbuf ) {
- emit3_simm13( *cbuf, Assembler::arith_op, Matcher::_regEncode[tmp], Assembler::sllx_op3, Matcher::_regEncode[src_first], 0x1020 );
- emit3_simm13( *cbuf, Assembler::arith_op, Matcher::_regEncode[src_second], Assembler::srl_op3, Matcher::_regEncode[src_second], 0x0000 );
- emit3 ( *cbuf, Assembler::arith_op, Matcher::_regEncode[dst_first], Assembler:: or_op3, Matcher::_regEncode[tmp], 0, Matcher::_regEncode[src_second] );
+ if ( cbuf ) {
+ emit3_simm13(*cbuf, Assembler::arith_op, Matcher::_regEncode[tmp], Assembler::sllx_op3, Matcher::_regEncode[src_first], 0x1020);
+ emit3_simm13(*cbuf, Assembler::arith_op, Matcher::_regEncode[src_second], Assembler::srl_op3, Matcher::_regEncode[src_second], 0x0000);
+ emit3 (*cbuf, Assembler::arith_op, Matcher::_regEncode[dst_first], Assembler:: or_op3, Matcher::_regEncode[tmp], 0, Matcher::_regEncode[src_second]);
#ifndef PRODUCT
- } else if( !do_size ) {
- if( size != 0 ) st->print("\n\t");
- st->print("SLLX R_%s,32,R_%s\t! Move O0-first to O7-high\n\t", OptoReg::regname(src_first), OptoReg::regname(tmp));
- st->print("SRL R_%s, 0,R_%s\t! Zero-extend O1\n\t", OptoReg::regname(src_second), OptoReg::regname(src_second));
- st->print("OR R_%s,R_%s,R_%s\t! spill",OptoReg::regname(tmp), OptoReg::regname(src_second), OptoReg::regname(dst_first));
+ } else {
+ print_helper(st, "SLLX R_%s,32,R_%s\t! Move O0-first to O7-high\n\t", OptoReg::regname(src_first), OptoReg::regname(tmp));
+ print_helper(st, "SRL R_%s, 0,R_%s\t! Zero-extend O1\n\t", OptoReg::regname(src_second), OptoReg::regname(src_second));
+ print_helper(st, "OR R_%s,R_%s,R_%s\t! spill",OptoReg::regname(tmp), OptoReg::regname(src_second), OptoReg::regname(dst_first));
#endif
}
- return size+12;
- }
- else if( dst_first == R_I0_num && dst_second == R_I1_num ) {
+ return;
+ } else if (dst_first == R_I0_num && dst_second == R_I1_num) {
// returning a long value in I0/I1
// a SpillCopy must be able to target a return instruction's reg_class
// Note: The _first and _second suffixes refer to the addresses of the the 2 halves of the 64-bit value
@@ -1511,27 +1524,25 @@
if (src_first == dst_first) {
tdest = OptoReg::Name(R_O7_num);
- size += 4;
}
- if( cbuf ) {
- assert( (src_first&1) == 0 && (src_first+1) == src_second, "return value was in an aligned-adjacent 64-bit reg");
+ if (cbuf) {
+ assert((src_first & 1) == 0 && (src_first + 1) == src_second, "return value was in an aligned-adjacent 64-bit reg");
// Shift value in upper 32-bits of src to lower 32-bits of I0; move lower 32-bits to I1
// ShrL_reg_imm6
- emit3_simm13( *cbuf, Assembler::arith_op, Matcher::_regEncode[tdest], Assembler::srlx_op3, Matcher::_regEncode[src_second], 32 | 0x1000 );
+ emit3_simm13(*cbuf, Assembler::arith_op, Matcher::_regEncode[tdest], Assembler::srlx_op3, Matcher::_regEncode[src_second], 32 | 0x1000);
// ShrR_reg_imm6 src, 0, dst
- emit3_simm13( *cbuf, Assembler::arith_op, Matcher::_regEncode[dst_second], Assembler::srl_op3, Matcher::_regEncode[src_first], 0x0000 );
+ emit3_simm13(*cbuf, Assembler::arith_op, Matcher::_regEncode[dst_second], Assembler::srl_op3, Matcher::_regEncode[src_first], 0x0000);
if (tdest != dst_first) {
- emit3 ( *cbuf, Assembler::arith_op, Matcher::_regEncode[dst_first], Assembler::or_op3, 0/*G0*/, 0/*op2*/, Matcher::_regEncode[tdest] );
+ emit3 (*cbuf, Assembler::arith_op, Matcher::_regEncode[dst_first], Assembler::or_op3, 0/*G0*/, 0/*op2*/, Matcher::_regEncode[tdest]);
}
}
#ifndef PRODUCT
- else if( !do_size ) {
- if( size != 0 ) st->print("\n\t"); // %%%%% !!!!!
- st->print("SRLX R_%s,32,R_%s\t! Extract MSW\n\t",OptoReg::regname(src_second),OptoReg::regname(tdest));
- st->print("SRL R_%s, 0,R_%s\t! Extract LSW\n\t",OptoReg::regname(src_first),OptoReg::regname(dst_second));
+ else {
+ print_helper(st, "SRLX R_%s,32,R_%s\t! Extract MSW\n\t",OptoReg::regname(src_second),OptoReg::regname(tdest));
+ print_helper(st, "SRL R_%s, 0,R_%s\t! Extract LSW\n\t",OptoReg::regname(src_first),OptoReg::regname(dst_second));
if (tdest != dst_first) {
- st->print("MOV R_%s,R_%s\t! spill\n\t", OptoReg::regname(tdest), OptoReg::regname(dst_first));
+ print_helper(st, "MOV R_%s,R_%s\t! spill\n\t", OptoReg::regname(tdest), OptoReg::regname(dst_first));
}
}
#endif // PRODUCT
@@ -1539,65 +1550,77 @@
}
#endif // !_LP64
// Else normal reg-reg copy
- assert( src_second != dst_first, "smashed second before evacuating it" );
- size = impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::or_op3,0,"MOV ",size, st);
- assert( (src_first&1) == 0 && (dst_first&1) == 0, "never move second-halves of int registers" );
+ assert(src_second != dst_first, "smashed second before evacuating it");
+ impl_mov_helper(cbuf, src_first, dst_first, Assembler::or_op3, 0, "MOV ", st);
+ assert((src_first & 1) == 0 && (dst_first & 1) == 0, "never move second-halves of int registers");
// This moves an aligned adjacent pair.
// See if we are done.
- if( src_first+1 == src_second && dst_first+1 == dst_second )
- return size;
+ if (src_first + 1 == src_second && dst_first + 1 == dst_second) {
+ return;
+ }
}
// Check for integer store
- if( src_first_rc == rc_int && dst_first_rc == rc_stack ) {
+ if (src_first_rc == rc_int && dst_first_rc == rc_stack) {
int offset = ra_->reg2offset(dst_first);
// Further check for aligned-adjacent pair, so we can use a double store
- if( (src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second )
- return impl_helper(this,cbuf,ra_,do_size,false,offset,src_first,Assembler::stx_op3,"STX ",size, st);
- size = impl_helper(this,cbuf,ra_,do_size,false,offset,src_first,Assembler::stw_op3,"STW ",size, st);
+ if ((src_first & 1) == 0 && src_first + 1 == src_second && (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
+ impl_helper(mach, cbuf, ra_, false, offset, src_first, Assembler::stx_op3, "STX ", st);
+ return;
+ }
+ impl_helper(mach, cbuf, ra_, false, offset, src_first, Assembler::stw_op3, "STW ", st);
}
// Check for integer load
- if( dst_first_rc == rc_int && src_first_rc == rc_stack ) {
+ if (dst_first_rc == rc_int && src_first_rc == rc_stack) {
int offset = ra_->reg2offset(src_first);
// Further check for aligned-adjacent pair, so we can use a double load
- if( (src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second )
- return impl_helper(this,cbuf,ra_,do_size,true,offset,dst_first,Assembler::ldx_op3 ,"LDX ",size, st);
- size = impl_helper(this,cbuf,ra_,do_size,true,offset,dst_first,Assembler::lduw_op3,"LDUW",size, st);
+ if ((src_first & 1) == 0 && src_first + 1 == src_second && (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
+ impl_helper(mach, cbuf, ra_, true, offset, dst_first, Assembler::ldx_op3, "LDX ", st);
+ return;
+ }
+ impl_helper(mach, cbuf, ra_, true, offset, dst_first, Assembler::lduw_op3, "LDUW", st);
}
// Check for float reg-reg copy
- if( src_first_rc == rc_float && dst_first_rc == rc_float ) {
+ if (src_first_rc == rc_float && dst_first_rc == rc_float) {
// Further check for aligned-adjacent pair, so we can use a double move
- if( (src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second )
- return impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::fpop1_op3,Assembler::fmovd_opf,"FMOVD",size, st);
- size = impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::fpop1_op3,Assembler::fmovs_opf,"FMOVS",size, st);
+ if ((src_first & 1) == 0 && src_first + 1 == src_second && (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
+ impl_mov_helper(cbuf, src_first, dst_first, Assembler::fpop1_op3, Assembler::fmovd_opf, "FMOVD", st);
+ return;
+ }
+ impl_mov_helper(cbuf, src_first, dst_first, Assembler::fpop1_op3, Assembler::fmovs_opf, "FMOVS", st);
}
// Check for float store
- if( src_first_rc == rc_float && dst_first_rc == rc_stack ) {
+ if (src_first_rc == rc_float && dst_first_rc == rc_stack) {
int offset = ra_->reg2offset(dst_first);
// Further check for aligned-adjacent pair, so we can use a double store
- if( (src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second )
- return impl_helper(this,cbuf,ra_,do_size,false,offset,src_first,Assembler::stdf_op3,"STDF",size, st);
- size = impl_helper(this,cbuf,ra_,do_size,false,offset,src_first,Assembler::stf_op3 ,"STF ",size, st);
+ if ((src_first & 1) == 0 && src_first + 1 == src_second && (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
+ impl_helper(mach, cbuf, ra_, false, offset, src_first, Assembler::stdf_op3, "STDF", st);
+ return;
+ }
+ impl_helper(mach, cbuf, ra_, false, offset, src_first, Assembler::stf_op3, "STF ", st);
}
// Check for float load
- if( dst_first_rc == rc_float && src_first_rc == rc_stack ) {
+ if (dst_first_rc == rc_float && src_first_rc == rc_stack) {
int offset = ra_->reg2offset(src_first);
// Further check for aligned-adjacent pair, so we can use a double load
- if( (src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second )
- return impl_helper(this,cbuf,ra_,do_size,true,offset,dst_first,Assembler::lddf_op3,"LDDF",size, st);
- size = impl_helper(this,cbuf,ra_,do_size,true,offset,dst_first,Assembler::ldf_op3 ,"LDF ",size, st);
+ if ((src_first & 1) == 0 && src_first + 1 == src_second && (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
+ impl_helper(mach, cbuf, ra_, true, offset, dst_first, Assembler::lddf_op3, "LDDF", st);
+ return;
+ }
+ impl_helper(mach, cbuf, ra_, true, offset, dst_first, Assembler::ldf_op3, "LDF ", st);
}
// --------------------------------------------------------------------
// Check for hi bits still needing moving. Only happens for misaligned
// arguments to native calls.
- if( src_second == dst_second )
- return size; // Self copy; no move
- assert( src_second_rc != rc_bad && dst_second_rc != rc_bad, "src_second & dst_second cannot be Bad" );
+ if (src_second == dst_second) {
+ return; // Self copy; no move
+ }
+ assert(src_second_rc != rc_bad && dst_second_rc != rc_bad, "src_second & dst_second cannot be Bad");
#ifndef _LP64
// In the LP64 build, all registers can be moved as aligned/adjacent
@@ -1609,52 +1632,57 @@
// 32-bits of a 64-bit register, but are needed in low bits of another
// register (else it's a hi-bits-to-hi-bits copy which should have
// happened already as part of a 64-bit move)
- if( src_second_rc == rc_int && dst_second_rc == rc_int ) {
- assert( (src_second&1)==1, "its the evil O0/O1 native return case" );
- assert( (dst_second&1)==0, "should have moved with 1 64-bit move" );
+ if (src_second_rc == rc_int && dst_second_rc == rc_int) {
+ assert((src_second & 1) == 1, "its the evil O0/O1 native return case");
+ assert((dst_second & 1) == 0, "should have moved with 1 64-bit move");
// Shift src_second down to dst_second's low bits.
- if( cbuf ) {
- emit3_simm13( *cbuf, Assembler::arith_op, Matcher::_regEncode[dst_second], Assembler::srlx_op3, Matcher::_regEncode[src_second-1], 0x1020 );
+ if (cbuf) {
+ emit3_simm13(*cbuf, Assembler::arith_op, Matcher::_regEncode[dst_second], Assembler::srlx_op3, Matcher::_regEncode[src_second-1], 0x1020);
#ifndef PRODUCT
- } else if( !do_size ) {
- if( size != 0 ) st->print("\n\t");
- st->print("SRLX R_%s,32,R_%s\t! spill: Move high bits down low",OptoReg::regname(src_second-1),OptoReg::regname(dst_second));
+ } else {
+ print_helper(st, "SRLX R_%s,32,R_%s\t! spill: Move high bits down low", OptoReg::regname(src_second - 1), OptoReg::regname(dst_second));
#endif
}
- return size+4;
+ return;
}
// Check for high word integer store. Must down-shift the hi bits
// into a temp register, then fall into the case of storing int bits.
- if( src_second_rc == rc_int && dst_second_rc == rc_stack && (src_second&1)==1 ) {
+ if (src_second_rc == rc_int && dst_second_rc == rc_stack && (src_second & 1) == 1) {
// Shift src_second down to dst_second's low bits.
- if( cbuf ) {
- emit3_simm13( *cbuf, Assembler::arith_op, Matcher::_regEncode[R_O7_num], Assembler::srlx_op3, Matcher::_regEncode[src_second-1], 0x1020 );
+ if (cbuf) {
+ emit3_simm13(*cbuf, Assembler::arith_op, Matcher::_regEncode[R_O7_num], Assembler::srlx_op3, Matcher::_regEncode[src_second-1], 0x1020);
#ifndef PRODUCT
- } else if( !do_size ) {
- if( size != 0 ) st->print("\n\t");
- st->print("SRLX R_%s,32,R_%s\t! spill: Move high bits down low",OptoReg::regname(src_second-1),OptoReg::regname(R_O7_num));
+ } else {
+ print_helper(st, "SRLX R_%s,32,R_%s\t! spill: Move high bits down low", OptoReg::regname(src_second-1), OptoReg::regname(R_O7_num));
#endif
}
- size+=4;
src_second = OptoReg::Name(R_O7_num); // Not R_O7H_num!
}
// Check for high word integer load
- if( dst_second_rc == rc_int && src_second_rc == rc_stack )
- return impl_helper(this,cbuf,ra_,do_size,true ,ra_->reg2offset(src_second),dst_second,Assembler::lduw_op3,"LDUW",size, st);
+ if (dst_second_rc == rc_int && src_second_rc == rc_stack)
+ return impl_helper(this, cbuf, ra_, true, ra_->reg2offset(src_second), dst_second, Assembler::lduw_op3, "LDUW", size, st);
// Check for high word integer store
- if( src_second_rc == rc_int && dst_second_rc == rc_stack )
- return impl_helper(this,cbuf,ra_,do_size,false,ra_->reg2offset(dst_second),src_second,Assembler::stw_op3 ,"STW ",size, st);
+ if (src_second_rc == rc_int && dst_second_rc == rc_stack)
+ return impl_helper(this, cbuf, ra_, false, ra_->reg2offset(dst_second), src_second, Assembler::stw_op3, "STW ", size, st);
// Check for high word float store
- if( src_second_rc == rc_float && dst_second_rc == rc_stack )
- return impl_helper(this,cbuf,ra_,do_size,false,ra_->reg2offset(dst_second),src_second,Assembler::stf_op3 ,"STF ",size, st);
+ if (src_second_rc == rc_float && dst_second_rc == rc_stack)
+ return impl_helper(this, cbuf, ra_, false, ra_->reg2offset(dst_second), src_second, Assembler::stf_op3, "STF ", size, st);
#endif // !_LP64
Unimplemented();
+}
+
+uint MachSpillCopyNode::implementation(CodeBuffer *cbuf,
+ PhaseRegAlloc *ra_,
+ bool do_size,
+ outputStream* st) const {
+ assert(!do_size, "not supported");
+ mach_spill_copy_implementation_helper(this, cbuf, ra_, st);
return 0;
}
@@ -1669,19 +1697,19 @@
}
uint MachSpillCopyNode::size(PhaseRegAlloc *ra_) const {
- return implementation( NULL, ra_, true, NULL );
+ return MachNode::size(ra_);
}
//=============================================================================
#ifndef PRODUCT
-void MachNopNode::format( PhaseRegAlloc *, outputStream *st ) const {
+void MachNopNode::format(PhaseRegAlloc *, outputStream *st) const {
st->print("NOP \t# %d bytes pad for loops and calls", 4 * _count);
}
#endif
-void MachNopNode::emit(CodeBuffer &cbuf, PhaseRegAlloc * ) const {
+void MachNopNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *) const {
MacroAssembler _masm(&cbuf);
- for(int i = 0; i < _count; i += 1) {
+ for (int i = 0; i < _count; i += 1) {
__ nop();
}
}
@@ -5197,7 +5225,6 @@
// No match rule to avoid chain rule match.
effect(DEF dst, USE src);
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "LDF $src,$dst\t! stkI to regF" %}
opcode(Assembler::ldf_op3);
ins_encode(simple_form3_mem_reg(src, dst));
@@ -5208,7 +5235,6 @@
// No match rule to avoid chain rule match.
effect(DEF dst, USE src);
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "LDDF $src,$dst\t! stkL to regD" %}
opcode(Assembler::lddf_op3);
ins_encode(simple_form3_mem_reg(src, dst));
@@ -5219,7 +5245,6 @@
// No match rule to avoid chain rule match.
effect(DEF dst, USE src);
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STF $src,$dst\t! regF to stkI" %}
opcode(Assembler::stf_op3);
ins_encode(simple_form3_mem_reg(dst, src));
@@ -5230,7 +5255,6 @@
// No match rule to avoid chain rule match.
effect(DEF dst, USE src);
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STDF $src,$dst\t! regD to stkL" %}
opcode(Assembler::stdf_op3);
ins_encode(simple_form3_mem_reg(dst, src));
@@ -5240,7 +5264,6 @@
instruct regI_to_stkLHi(stackSlotL dst, iRegI src) %{
effect(DEF dst, USE src);
ins_cost(MEMORY_REF_COST*2);
- size(8);
format %{ "STW $src,$dst.hi\t! long\n\t"
"STW R_G0,$dst.lo" %}
opcode(Assembler::stw_op3);
@@ -5252,7 +5275,6 @@
// No match rule to avoid chain rule match.
effect(DEF dst, USE src);
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STX $src,$dst\t! regL to stkD" %}
opcode(Assembler::stx_op3);
ins_encode(simple_form3_mem_reg( dst, src ) );
@@ -5266,7 +5288,6 @@
match(Set dst src);
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "LDUW $src,$dst\t!stk" %}
opcode(Assembler::lduw_op3);
ins_encode(simple_form3_mem_reg( src, dst ) );
@@ -5278,7 +5299,6 @@
match(Set dst src);
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STW $src,$dst\t!stk" %}
opcode(Assembler::stw_op3);
ins_encode(simple_form3_mem_reg( dst, src ) );
@@ -5290,7 +5310,6 @@
match(Set dst src);
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "LDX $src,$dst\t! long" %}
opcode(Assembler::ldx_op3);
ins_encode(simple_form3_mem_reg( src, dst ) );
@@ -5302,7 +5321,6 @@
match(Set dst src);
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STX $src,$dst\t! long" %}
opcode(Assembler::stx_op3);
ins_encode(simple_form3_mem_reg( dst, src ) );
@@ -5314,7 +5332,6 @@
instruct stkP_to_regP( iRegP dst, stackSlotP src ) %{
match(Set dst src);
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "LDX $src,$dst\t!ptr" %}
opcode(Assembler::ldx_op3);
ins_encode(simple_form3_mem_reg( src, dst ) );
@@ -5325,7 +5342,6 @@
instruct regP_to_stkP(stackSlotP dst, iRegP src) %{
match(Set dst src);
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STX $src,$dst\t!ptr" %}
opcode(Assembler::stx_op3);
ins_encode(simple_form3_mem_reg( dst, src ) );
@@ -5771,7 +5787,6 @@
match(Set dst (LoadL_unaligned mem));
effect(KILL tmp);
ins_cost(MEMORY_REF_COST*2+DEFAULT_COST);
- size(16);
format %{ "LDUW $mem+4,R_O7\t! misaligned long\n"
"\tLDUW $mem ,$dst\n"
"\tSLLX #32, $dst, $dst\n"
@@ -5786,7 +5801,6 @@
match(Set dst (LoadRange mem));
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "LDUW $mem,$dst\t! range" %}
opcode(Assembler::lduw_op3);
ins_encode(simple_form3_mem_reg( mem, dst ) );
@@ -5797,7 +5811,6 @@
instruct loadI_freg(regF dst, memory mem) %{
match(Set dst (LoadI mem));
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "LDF $mem,$dst\t! for fitos/fitod" %}
opcode(Assembler::ldf_op3);
@@ -5876,7 +5889,6 @@
match(Set dst (LoadD mem));
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "LDDF $mem,$dst" %}
opcode(Assembler::lddf_op3);
ins_encode(simple_form3_mem_reg( mem, dst ) );
@@ -5887,7 +5899,6 @@
instruct loadD_unaligned(regD_low dst, memory mem ) %{
match(Set dst (LoadD_unaligned mem));
ins_cost(MEMORY_REF_COST*2+DEFAULT_COST);
- size(8);
format %{ "LDF $mem ,$dst.hi\t! misaligned double\n"
"\tLDF $mem+4,$dst.lo\t!" %}
opcode(Assembler::ldf_op3);
@@ -5900,7 +5911,6 @@
match(Set dst (LoadF mem));
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "LDF $mem,$dst" %}
opcode(Assembler::ldf_op3);
ins_encode(simple_form3_mem_reg( mem, dst ) );
@@ -6119,7 +6129,6 @@
predicate(AllocatePrefetchInstr == 0);
match( PrefetchAllocation mem );
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "PREFETCH $mem,2\t! Prefetch allocation" %}
opcode(Assembler::prefetch_op3);
@@ -6175,7 +6184,6 @@
match(Set mem (StoreB mem src));
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STB $src,$mem\t! byte" %}
opcode(Assembler::stb_op3);
ins_encode(simple_form3_mem_reg( mem, src ) );
@@ -6186,7 +6194,6 @@
match(Set mem (StoreB mem src));
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STB $src,$mem\t! byte" %}
opcode(Assembler::stb_op3);
ins_encode(simple_form3_mem_reg( mem, R_G0 ) );
@@ -6197,7 +6204,6 @@
match(Set mem (StoreCM mem src));
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STB $src,$mem\t! CMS card-mark byte 0" %}
opcode(Assembler::stb_op3);
ins_encode(simple_form3_mem_reg( mem, R_G0 ) );
@@ -6209,7 +6215,6 @@
match(Set mem (StoreC mem src));
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STH $src,$mem\t! short" %}
opcode(Assembler::sth_op3);
ins_encode(simple_form3_mem_reg( mem, src ) );
@@ -6220,7 +6225,6 @@
match(Set mem (StoreC mem src));
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STH $src,$mem\t! short" %}
opcode(Assembler::sth_op3);
ins_encode(simple_form3_mem_reg( mem, R_G0 ) );
@@ -6232,7 +6236,6 @@
match(Set mem (StoreI mem src));
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STW $src,$mem" %}
opcode(Assembler::stw_op3);
ins_encode(simple_form3_mem_reg( mem, src ) );
@@ -6243,7 +6246,6 @@
instruct storeL(memory mem, iRegL src) %{
match(Set mem (StoreL mem src));
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STX $src,$mem\t! long" %}
opcode(Assembler::stx_op3);
ins_encode(simple_form3_mem_reg( mem, src ) );
@@ -6254,7 +6256,6 @@
match(Set mem (StoreI mem src));
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STW $src,$mem" %}
opcode(Assembler::stw_op3);
ins_encode(simple_form3_mem_reg( mem, R_G0 ) );
@@ -6265,7 +6266,6 @@
match(Set mem (StoreL mem src));
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STX $src,$mem" %}
opcode(Assembler::stx_op3);
ins_encode(simple_form3_mem_reg( mem, R_G0 ) );
@@ -6277,7 +6277,6 @@
match(Set mem (StoreI mem src));
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STF $src,$mem\t! after fstoi/fdtoi" %}
opcode(Assembler::stf_op3);
ins_encode(simple_form3_mem_reg( mem, src ) );
@@ -6288,7 +6287,6 @@
instruct storeP(memory dst, sp_ptr_RegP src) %{
match(Set dst (StoreP dst src));
ins_cost(MEMORY_REF_COST);
- size(4);
#ifndef _LP64
format %{ "STW $src,$dst\t! ptr" %}
@@ -6304,7 +6302,6 @@
instruct storeP0(memory dst, immP0 src) %{
match(Set dst (StoreP dst src));
ins_cost(MEMORY_REF_COST);
- size(4);
#ifndef _LP64
format %{ "STW $src,$dst\t! ptr" %}
@@ -6379,7 +6376,6 @@
match(Set mem (StoreD mem src));
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STDF $src,$mem" %}
opcode(Assembler::stdf_op3);
ins_encode(simple_form3_mem_reg( mem, src ) );
@@ -6390,7 +6386,6 @@
match(Set mem (StoreD mem src));
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STX $src,$mem" %}
opcode(Assembler::stx_op3);
ins_encode(simple_form3_mem_reg( mem, R_G0 ) );
@@ -6402,7 +6397,6 @@
match(Set mem (StoreF mem src));
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STF $src,$mem" %}
opcode(Assembler::stf_op3);
ins_encode(simple_form3_mem_reg( mem, src ) );
@@ -6413,7 +6407,6 @@
match(Set mem (StoreF mem src));
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STW $src,$mem\t! storeF0" %}
opcode(Assembler::stw_op3);
ins_encode(simple_form3_mem_reg( mem, R_G0 ) );
@@ -7068,7 +7061,6 @@
ins_cost(MEMORY_REF_COST);
#ifndef _LP64
- size(4);
format %{ "LDUW $mem,$dst\t! ptr" %}
opcode(Assembler::lduw_op3, 0, REGP_OP);
#else
@@ -8138,7 +8130,6 @@
effect(DEF dst, USE src);
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "LDUW $src,$dst\t! MoveF2I" %}
opcode(Assembler::lduw_op3);
ins_encode(simple_form3_mem_reg( src, dst ) );
@@ -8150,7 +8141,6 @@
effect(DEF dst, USE src);
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "LDF $src,$dst\t! MoveI2F" %}
opcode(Assembler::ldf_op3);
ins_encode(simple_form3_mem_reg(src, dst));
@@ -8162,7 +8152,6 @@
effect(DEF dst, USE src);
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "LDX $src,$dst\t! MoveD2L" %}
opcode(Assembler::ldx_op3);
ins_encode(simple_form3_mem_reg( src, dst ) );
@@ -8174,7 +8163,6 @@
effect(DEF dst, USE src);
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "LDDF $src,$dst\t! MoveL2D" %}
opcode(Assembler::lddf_op3);
ins_encode(simple_form3_mem_reg(src, dst));
@@ -8186,7 +8174,6 @@
effect(DEF dst, USE src);
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STF $src,$dst\t! MoveF2I" %}
opcode(Assembler::stf_op3);
ins_encode(simple_form3_mem_reg(dst, src));
@@ -8198,7 +8185,6 @@
effect(DEF dst, USE src);
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STW $src,$dst\t! MoveI2F" %}
opcode(Assembler::stw_op3);
ins_encode(simple_form3_mem_reg( dst, src ) );
@@ -8210,7 +8196,6 @@
effect(DEF dst, USE src);
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STDF $src,$dst\t! MoveD2L" %}
opcode(Assembler::stdf_op3);
ins_encode(simple_form3_mem_reg(dst, src));
@@ -8222,7 +8207,6 @@
effect(DEF dst, USE src);
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STX $src,$dst\t! MoveL2D" %}
opcode(Assembler::stx_op3);
ins_encode(simple_form3_mem_reg( dst, src ) );
@@ -8427,7 +8411,6 @@
instruct convI2D_mem(regD_low dst, memory mem) %{
match(Set dst (ConvI2D (LoadI mem)));
ins_cost(DEFAULT_COST + MEMORY_REF_COST);
- size(8);
format %{ "LDF $mem,$dst\n\t"
"FITOD $dst,$dst" %}
opcode(Assembler::ldf_op3, Assembler::fitod_opf);
@@ -8468,7 +8451,6 @@
instruct convI2F_mem( regF dst, memory mem ) %{
match(Set dst (ConvI2F (LoadI mem)));
ins_cost(DEFAULT_COST + MEMORY_REF_COST);
- size(8);
format %{ "LDF $mem,$dst\n\t"
"FITOS $dst,$dst" %}
opcode(Assembler::ldf_op3, Assembler::fitos_opf);
--- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -463,3 +463,37 @@
}
return result;
}
+
+
+int VM_Version::parse_features(const char* implementation) {
+ int features = unknown_m;
+ // Convert to UPPER case before compare.
+ char* impl = os::strdup_check_oom(implementation);
+
+ for (int i = 0; impl[i] != 0; i++)
+ impl[i] = (char)toupper((uint)impl[i]);
+
+ if (strstr(impl, "SPARC64") != NULL) {
+ features |= sparc64_family_m;
+ } else if (strstr(impl, "SPARC-M") != NULL) {
+ // M-series SPARC is based on T-series.
+ features |= (M_family_m | T_family_m);
+ } else if (strstr(impl, "SPARC-T") != NULL) {
+ features |= T_family_m;
+ if (strstr(impl, "SPARC-T1") != NULL) {
+ features |= T1_model_m;
+ }
+ } else {
+ if (strstr(impl, "SPARC") == NULL) {
+#ifndef PRODUCT
+ // kstat on Solaris 8 virtual machines (branded zones)
+ // returns "(unsupported)" implementation. Solaris 8 is not
+ // supported anymore, but include this check to be on the
+ // safe side.
+ warning("Can't parse CPU implementation = '%s', assume generic SPARC", impl);
+#endif
+ }
+ }
+ os::free((void*)impl);
+ return features;
+}
--- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp Wed Mar 09 14:18:12 2016 +0100
@@ -121,7 +121,7 @@
static bool is_T1_model(int features) { return is_T_family(features) && ((features & T1_model_m) != 0); }
static int maximum_niagara1_processor_count() { return 32; }
-
+ static int parse_features(const char* implementation);
public:
// Initialization
static void initialize();
--- a/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -161,13 +161,7 @@
create_klass_exception),
rarg, rarg2);
} else {
- // kind of lame ExternalAddress can't take NULL because
- // external_word_Relocation will assert.
- if (message != NULL) {
- __ lea(rarg2, ExternalAddress((address)message));
- } else {
- __ movptr(rarg2, NULL_WORD);
- }
+ __ lea(rarg2, ExternalAddress((address)message));
__ call_VM(rax,
CAST_FROM_FN_PTR(address, InterpreterRuntime::create_exception),
rarg, rarg2);
--- a/hotspot/src/cpu/x86/vm/x86_32.ad Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/cpu/x86/vm/x86_32.ad Wed Mar 09 14:18:12 2016 +0100
@@ -7236,6 +7236,7 @@
instruct compareAndSwapL( rRegI res, eSIRegP mem_ptr, eADXRegL oldval, eBCXRegL newval, eFlagsReg cr ) %{
predicate(VM_Version::supports_cx8());
match(Set res (CompareAndSwapL mem_ptr (Binary oldval newval)));
+ match(Set res (WeakCompareAndSwapL mem_ptr (Binary oldval newval)));
effect(KILL cr, KILL oldval);
format %{ "CMPXCHG8 [$mem_ptr],$newval\t# If EDX:EAX==[$mem_ptr] Then store $newval into [$mem_ptr]\n\t"
"MOV $res,0\n\t"
@@ -7249,6 +7250,7 @@
instruct compareAndSwapP( rRegI res, pRegP mem_ptr, eAXRegP oldval, eCXRegP newval, eFlagsReg cr) %{
match(Set res (CompareAndSwapP mem_ptr (Binary oldval newval)));
+ match(Set res (WeakCompareAndSwapP mem_ptr (Binary oldval newval)));
effect(KILL cr, KILL oldval);
format %{ "CMPXCHG [$mem_ptr],$newval\t# If EAX==[$mem_ptr] Then store $newval into [$mem_ptr]\n\t"
"MOV $res,0\n\t"
@@ -7261,6 +7263,7 @@
instruct compareAndSwapI( rRegI res, pRegP mem_ptr, eAXRegI oldval, eCXRegI newval, eFlagsReg cr) %{
match(Set res (CompareAndSwapI mem_ptr (Binary oldval newval)));
+ match(Set res (WeakCompareAndSwapI mem_ptr (Binary oldval newval)));
effect(KILL cr, KILL oldval);
format %{ "CMPXCHG [$mem_ptr],$newval\t# If EAX==[$mem_ptr] Then store $newval into [$mem_ptr]\n\t"
"MOV $res,0\n\t"
@@ -7271,6 +7274,31 @@
ins_pipe( pipe_cmpxchg );
%}
+instruct compareAndExchangeL( eSIRegP mem_ptr, eADXRegL oldval, eBCXRegL newval, eFlagsReg cr ) %{
+ predicate(VM_Version::supports_cx8());
+ match(Set oldval (CompareAndExchangeL mem_ptr (Binary oldval newval)));
+ effect(KILL cr);
+ format %{ "CMPXCHG8 [$mem_ptr],$newval\t# If EDX:EAX==[$mem_ptr] Then store $newval into [$mem_ptr]\n\t" %}
+ ins_encode( enc_cmpxchg8(mem_ptr) );
+ ins_pipe( pipe_cmpxchg );
+%}
+
+instruct compareAndExchangeP( pRegP mem_ptr, eAXRegP oldval, eCXRegP newval, eFlagsReg cr) %{
+ match(Set oldval (CompareAndExchangeP mem_ptr (Binary oldval newval)));
+ effect(KILL cr);
+ format %{ "CMPXCHG [$mem_ptr],$newval\t# If EAX==[$mem_ptr] Then store $newval into [$mem_ptr]\n\t" %}
+ ins_encode( enc_cmpxchg(mem_ptr) );
+ ins_pipe( pipe_cmpxchg );
+%}
+
+instruct compareAndExchangeI( pRegP mem_ptr, eAXRegI oldval, eCXRegI newval, eFlagsReg cr) %{
+ match(Set oldval (CompareAndExchangeI mem_ptr (Binary oldval newval)));
+ effect(KILL cr);
+ format %{ "CMPXCHG [$mem_ptr],$newval\t# If EAX==[$mem_ptr] Then store $newval into [$mem_ptr]\n\t" %}
+ ins_encode( enc_cmpxchg(mem_ptr) );
+ ins_pipe( pipe_cmpxchg );
+%}
+
instruct xaddI_no_res( memory mem, Universe dummy, immI add, eFlagsReg cr) %{
predicate(n->as_LoadStore()->result_not_used());
match(Set dummy (GetAndAddI mem add));
--- a/hotspot/src/cpu/x86/vm/x86_64.ad Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/cpu/x86/vm/x86_64.ad Wed Mar 09 14:18:12 2016 +0100
@@ -7281,6 +7281,7 @@
%{
predicate(VM_Version::supports_cx8());
match(Set res (CompareAndSwapP mem_ptr (Binary oldval newval)));
+ match(Set res (WeakCompareAndSwapP mem_ptr (Binary oldval newval)));
effect(KILL cr, KILL oldval);
format %{ "cmpxchgq $mem_ptr,$newval\t# "
@@ -7305,6 +7306,7 @@
%{
predicate(VM_Version::supports_cx8());
match(Set res (CompareAndSwapL mem_ptr (Binary oldval newval)));
+ match(Set res (WeakCompareAndSwapL mem_ptr (Binary oldval newval)));
effect(KILL cr, KILL oldval);
format %{ "cmpxchgq $mem_ptr,$newval\t# "
@@ -7328,6 +7330,7 @@
rFlagsReg cr)
%{
match(Set res (CompareAndSwapI mem_ptr (Binary oldval newval)));
+ match(Set res (WeakCompareAndSwapI mem_ptr (Binary oldval newval)));
effect(KILL cr, KILL oldval);
format %{ "cmpxchgl $mem_ptr,$newval\t# "
@@ -7351,6 +7354,7 @@
rax_RegN oldval, rRegN newval,
rFlagsReg cr) %{
match(Set res (CompareAndSwapN mem_ptr (Binary oldval newval)));
+ match(Set res (WeakCompareAndSwapN mem_ptr (Binary oldval newval)));
effect(KILL cr, KILL oldval);
format %{ "cmpxchgl $mem_ptr,$newval\t# "
@@ -7368,6 +7372,83 @@
ins_pipe( pipe_cmpxchg );
%}
+instruct compareAndExchangeI(
+ memory mem_ptr,
+ rax_RegI oldval, rRegI newval,
+ rFlagsReg cr)
+%{
+ match(Set oldval (CompareAndExchangeI mem_ptr (Binary oldval newval)));
+ effect(KILL cr);
+
+ format %{ "cmpxchgl $mem_ptr,$newval\t# "
+ "If rax == $mem_ptr then store $newval into $mem_ptr\n\t" %}
+ opcode(0x0F, 0xB1);
+ ins_encode(lock_prefix,
+ REX_reg_mem(newval, mem_ptr),
+ OpcP, OpcS,
+ reg_mem(newval, mem_ptr) // lock cmpxchg
+ );
+ ins_pipe( pipe_cmpxchg );
+%}
+
+instruct compareAndExchangeL(
+ memory mem_ptr,
+ rax_RegL oldval, rRegL newval,
+ rFlagsReg cr)
+%{
+ predicate(VM_Version::supports_cx8());
+ match(Set oldval (CompareAndExchangeL mem_ptr (Binary oldval newval)));
+ effect(KILL cr);
+
+ format %{ "cmpxchgq $mem_ptr,$newval\t# "
+ "If rax == $mem_ptr then store $newval into $mem_ptr\n\t" %}
+ opcode(0x0F, 0xB1);
+ ins_encode(lock_prefix,
+ REX_reg_mem_wide(newval, mem_ptr),
+ OpcP, OpcS,
+ reg_mem(newval, mem_ptr) // lock cmpxchg
+ );
+ ins_pipe( pipe_cmpxchg );
+%}
+
+instruct compareAndExchangeN(
+ memory mem_ptr,
+ rax_RegN oldval, rRegN newval,
+ rFlagsReg cr) %{
+ match(Set oldval (CompareAndExchangeN mem_ptr (Binary oldval newval)));
+ effect(KILL cr);
+
+ format %{ "cmpxchgl $mem_ptr,$newval\t# "
+ "If rax == $mem_ptr then store $newval into $mem_ptr\n\t" %}
+ opcode(0x0F, 0xB1);
+ ins_encode(lock_prefix,
+ REX_reg_mem(newval, mem_ptr),
+ OpcP, OpcS,
+ reg_mem(newval, mem_ptr) // lock cmpxchg
+ );
+ ins_pipe( pipe_cmpxchg );
+%}
+
+instruct compareAndExchangeP(
+ memory mem_ptr,
+ rax_RegP oldval, rRegP newval,
+ rFlagsReg cr)
+%{
+ predicate(VM_Version::supports_cx8());
+ match(Set oldval (CompareAndExchangeP mem_ptr (Binary oldval newval)));
+ effect(KILL cr);
+
+ format %{ "cmpxchgq $mem_ptr,$newval\t# "
+ "If rax == $mem_ptr then store $newval into $mem_ptr\n\t" %}
+ opcode(0x0F, 0xB1);
+ ins_encode(lock_prefix,
+ REX_reg_mem_wide(newval, mem_ptr),
+ OpcP, OpcS,
+ reg_mem(newval, mem_ptr) // lock cmpxchg
+ );
+ ins_pipe( pipe_cmpxchg );
+%}
+
instruct xaddI_no_res( memory mem, Universe dummy, immI add, rFlagsReg cr) %{
predicate(n->as_LoadStore()->result_not_used());
match(Set dummy (GetAndAddI mem add));
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java Wed Mar 09 14:18:12 2016 +0100
@@ -22,6 +22,7 @@
*/
package jdk.vm.ci.amd64;
+import static jdk.vm.ci.code.MemoryBarriers.LOAD_LOAD;
import static jdk.vm.ci.code.MemoryBarriers.LOAD_STORE;
import static jdk.vm.ci.code.MemoryBarriers.STORE_STORE;
import static jdk.vm.ci.code.Register.SPECIAL;
@@ -220,7 +221,7 @@
private final AMD64Kind largestKind;
public AMD64(EnumSet<CPUFeature> features, EnumSet<Flag> flags) {
- super("AMD64", AMD64Kind.QWORD, ByteOrder.LITTLE_ENDIAN, true, allRegisters, LOAD_STORE | STORE_STORE, 1, 8);
+ super("AMD64", AMD64Kind.QWORD, ByteOrder.LITTLE_ENDIAN, true, allRegisters, LOAD_LOAD | LOAD_STORE | STORE_STORE, 1, 8);
this.features = features;
this.flags = flags;
assert features.contains(CPUFeature.SSE2) : "minimum config for x64";
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java Wed Mar 09 14:18:12 2016 +0100
@@ -1141,7 +1141,7 @@
@HotSpotVMField(name = "JavaFrameAnchor::_last_Java_sp", type = "intptr_t*", get = HotSpotVMField.Type.OFFSET) @Stable private int javaFrameAnchorLastJavaSpOffset;
@HotSpotVMField(name = "JavaFrameAnchor::_last_Java_pc", type = "address", get = HotSpotVMField.Type.OFFSET) @Stable private int javaFrameAnchorLastJavaPcOffset;
- @HotSpotVMField(name = "JavaFrameAnchor::_last_Java_fp", type = "intptr_t*", get = HotSpotVMField.Type.OFFSET, archs = {"amd64"}) @Stable private int javaFrameAnchorLastJavaFpOffset;
+ @HotSpotVMField(name = "JavaFrameAnchor::_last_Java_fp", type = "intptr_t*", get = HotSpotVMField.Type.OFFSET, archs = {"aarch64, amd64"}) @Stable private int javaFrameAnchorLastJavaFpOffset;
@HotSpotVMField(name = "JavaFrameAnchor::_flags", type = "int", get = HotSpotVMField.Type.OFFSET, archs = {"sparc"}) @Stable private int javaFrameAnchorFlagsOffset;
public int threadLastJavaSpOffset() {
@@ -1152,11 +1152,8 @@
return javaThreadAnchorOffset + javaFrameAnchorLastJavaPcOffset;
}
- /**
- * This value is only valid on AMD64.
- */
public int threadLastJavaFpOffset() {
- // TODO add an assert for AMD64
+ assert getHostArchitectureName().equals("aarch64") || getHostArchitectureName().equals("amd64");
return javaThreadAnchorOffset + javaFrameAnchorLastJavaFpOffset;
}
--- a/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -264,6 +264,7 @@
// We need to keep these here as long as we have to build on Solaris
// versions before 10.
+
#ifndef SI_ARCHITECTURE_32
#define SI_ARCHITECTURE_32 516 /* basic 32-bit SI_ARCHITECTURE */
#endif
@@ -272,36 +273,87 @@
#define SI_ARCHITECTURE_64 517 /* basic 64-bit SI_ARCHITECTURE */
#endif
-static void do_sysinfo(int si, const char* string, int* features, int mask) {
- char tmp;
- size_t bufsize = sysinfo(si, &tmp, 1);
+#ifndef SI_CPUBRAND
+#define SI_CPUBRAND 523 /* return cpu brand string */
+#endif
- // All SI defines used below must be supported.
- guarantee(bufsize != -1, "must be supported");
+class Sysinfo {
+ char* _string;
+public:
+ Sysinfo(int si) : _string(NULL) {
+ char tmp;
+ size_t bufsize = sysinfo(si, &tmp, 1);
- char* buf = (char*) os::malloc(bufsize, mtInternal);
-
- if (buf == NULL)
- return;
+ if (bufsize != -1) {
+ char* buf = (char*) os::malloc(bufsize, mtInternal);
+ if (buf != NULL) {
+ if (sysinfo(si, buf, bufsize) == bufsize) {
+ _string = buf;
+ } else {
+ os::free(buf);
+ }
+ }
+ }
+ }
- if (sysinfo(si, buf, bufsize) == bufsize) {
- // Compare the string.
- if (strcmp(buf, string) == 0) {
- *features |= mask;
+ ~Sysinfo() {
+ if (_string != NULL) {
+ os::free(_string);
}
}
- os::free(buf);
-}
+ const char* value() const {
+ return _string;
+ }
+
+ bool valid() const {
+ return _string != NULL;
+ }
+
+ bool match(const char* s) const {
+ return valid() ? strcmp(_string, s) == 0 : false;
+ }
+
+ bool match_substring(const char* s) const {
+ return valid() ? strstr(_string, s) != NULL : false;
+ }
+};
+
+class Sysconf {
+ int _value;
+public:
+ Sysconf(int sc) : _value(-1) {
+ _value = sysconf(sc);
+ }
+ bool valid() const {
+ return _value != -1;
+ }
+ int value() const {
+ return _value;
+ }
+};
+
+
+#ifndef _SC_DCACHE_LINESZ
+#define _SC_DCACHE_LINESZ 508 /* Data cache line size */
+#endif
+
+#ifndef _SC_L2CACHE_LINESZ
+#define _SC_L2CACHE_LINESZ 527 /* Size of L2 cache line */
+#endif
int VM_Version::platform_features(int features) {
assert(os::Solaris::supports_getisax(), "getisax() must be available");
// Check 32-bit architecture.
- do_sysinfo(SI_ARCHITECTURE_32, "sparc", &features, v8_instructions_m);
+ if (Sysinfo(SI_ARCHITECTURE_32).match("sparc")) {
+ features |= v8_instructions_m;
+ }
// Check 64-bit architecture.
- do_sysinfo(SI_ARCHITECTURE_64, "sparcv9", &features, generic_v9_m);
+ if (Sysinfo(SI_ARCHITECTURE_64).match("sparcv9")) {
+ features |= generic_v9_m;
+ }
// Extract valid instruction set extensions.
uint_t avs[2];
@@ -388,67 +440,63 @@
if (av & AV_SPARC_SHA512) features |= sha512_instruction_m;
// Determine the machine type.
- do_sysinfo(SI_MACHINE, "sun4v", &features, sun4v_m);
+ if (Sysinfo(SI_MACHINE).match("sun4v")) {
+ features |= sun4v_m;
+ }
- {
- // Using kstat to determine the machine type.
+ bool use_solaris_12_api = false;
+ Sysinfo impl(SI_CPUBRAND);
+ if (impl.valid()) {
+ // If SI_CPUBRAND works, that means Solaris 12 API to get the cache line sizes
+ // is available to us as well
+ use_solaris_12_api = true;
+ features |= parse_features(impl.value());
+ } else {
+ // Otherwise use kstat to determine the machine type.
kstat_ctl_t* kc = kstat_open();
kstat_t* ksp = kstat_lookup(kc, (char*)"cpu_info", -1, NULL);
- const char* implementation = "UNKNOWN";
+ const char* implementation;
+ bool has_implementation = false;
if (ksp != NULL) {
if (kstat_read(kc, ksp, NULL) != -1 && ksp->ks_data != NULL) {
kstat_named_t* knm = (kstat_named_t *)ksp->ks_data;
for (int i = 0; i < ksp->ks_ndata; i++) {
if (strcmp((const char*)&(knm[i].name),"implementation") == 0) {
implementation = KSTAT_NAMED_STR_PTR(&knm[i]);
+ has_implementation = true;
#ifndef PRODUCT
if (PrintMiscellaneous && Verbose) {
tty->print_cr("cpu_info.implementation: %s", implementation);
}
#endif
- // Convert to UPPER case before compare.
- char* impl = os::strdup_check_oom(implementation);
-
- for (int i = 0; impl[i] != 0; i++)
- impl[i] = (char)toupper((uint)impl[i]);
-
- if (strstr(impl, "SPARC64") != NULL) {
- features |= sparc64_family_m;
- } else if (strstr(impl, "SPARC-M") != NULL) {
- // M-series SPARC is based on T-series.
- features |= (M_family_m | T_family_m);
- } else if (strstr(impl, "SPARC-T") != NULL) {
- features |= T_family_m;
- if (strstr(impl, "SPARC-T1") != NULL) {
- features |= T1_model_m;
- }
- } else {
- if (strstr(impl, "SPARC") == NULL) {
-#ifndef PRODUCT
- // kstat on Solaris 8 virtual machines (branded zones)
- // returns "(unsupported)" implementation. Solaris 8 is not
- // supported anymore, but include this check to be on the
- // safe side.
- warning("kstat cpu_info implementation = '%s', assume generic SPARC", impl);
-#endif
- implementation = "SPARC";
- }
- }
- os::free((void*)impl);
+ features |= parse_features(implementation);
break;
}
} // for(
}
}
- assert(strcmp(implementation, "UNKNOWN") != 0,
- "unknown cpu info (changed kstat interface?)");
+ assert(has_implementation, "unknown cpu info (changed kstat interface?)");
kstat_close(kc);
}
- // Figure out cache line sizes using PICL
- PICL picl((features & sparc64_family_m) != 0, (features & sun4v_m) != 0);
- _L1_data_cache_line_size = picl.L1_data_cache_line_size();
- _L2_data_cache_line_size = picl.L2_data_cache_line_size();
+ bool is_sun4v = (features & sun4v_m) != 0;
+ if (use_solaris_12_api && is_sun4v) {
+ // If Solaris 12 API is supported and it's sun4v use sysconf() to get the cache line sizes
+ Sysconf l1_dcache_line_size(_SC_DCACHE_LINESZ);
+ if (l1_dcache_line_size.valid()) {
+ _L1_data_cache_line_size = l1_dcache_line_size.value();
+ }
+ Sysconf l2_dcache_line_size(_SC_L2CACHE_LINESZ);
+ if (l2_dcache_line_size.valid()) {
+ _L2_data_cache_line_size = l2_dcache_line_size.value();
+ }
+ } else {
+ // Otherwise figure out the cache line sizes using PICL
+ bool is_fujitsu = (features & sparc64_family_m) != 0;
+ PICL picl(is_fujitsu, is_sun4v);
+ _L1_data_cache_line_size = picl.L1_data_cache_line_size();
+ _L2_data_cache_line_size = picl.L2_data_cache_line_size();
+ }
return features;
}
--- a/hotspot/src/os_cpu/windows_x86/vm/assembler_windows_x86.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/os_cpu/windows_x86/vm/assembler_windows_x86.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -51,11 +51,8 @@
// movl reg, [reg + thread_ptr_offset] Load thread
//
void MacroAssembler::get_thread(Register thread) {
- // can't use ExternalAddress because it can't take NULL
- AddressLiteral null(0, relocInfo::none);
-
prefix(FS_segment);
- movptr(thread, null);
+ movptr(thread, ExternalAddress(NULL));
assert(os::win32::get_thread_ptr_offset() != 0,
"Thread Pointer Offset has not been initialized");
movl(thread, Address(thread, os::win32::get_thread_ptr_offset()));
--- a/hotspot/src/share/vm/adlc/formssel.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/adlc/formssel.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -3491,6 +3491,8 @@
"LoadPLocked",
"StorePConditional", "StoreIConditional", "StoreLConditional",
"CompareAndSwapI", "CompareAndSwapL", "CompareAndSwapP", "CompareAndSwapN",
+ "WeakCompareAndSwapI", "WeakCompareAndSwapL", "WeakCompareAndSwapP", "WeakCompareAndSwapN",
+ "CompareAndExchangeI", "CompareAndExchangeL", "CompareAndExchangeP", "CompareAndExchangeN",
"StoreCM",
"ClearArray",
"GetAndAddI", "GetAndSetI", "GetAndSetP",
--- a/hotspot/src/share/vm/c1/c1_CFGPrinter.hpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/c1/c1_CFGPrinter.hpp Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -34,7 +34,9 @@
// compilation for later analysis.
class CFGPrinterOutput;
-class IntervalList;
+class Interval;
+
+typedef GrowableArray<Interval*> IntervalList;
class CFGPrinter : public AllStatic {
private:
--- a/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -222,27 +222,36 @@
}
void Canonicalizer::do_ArrayLength (ArrayLength* x) {
- NewArray* array = x->array()->as_NewArray();
- if (array != NULL && array->length() != NULL) {
- Constant* length = array->length()->as_Constant();
- if (length != NULL) {
- // do not use the Constant itself, but create a new Constant
- // with same value Otherwise a Constant is live over multiple
- // blocks without being registered in a state array.
+ NewArray* na;
+ Constant* ct;
+ LoadField* lf;
+
+ if ((na = x->array()->as_NewArray()) != NULL) {
+ // New arrays might have the known length.
+ // Do not use the Constant itself, but create a new Constant
+ // with same value Otherwise a Constant is live over multiple
+ // blocks without being registered in a state array.
+ Constant* length;
+ if (na->length() != NULL &&
+ (length = na->length()->as_Constant()) != NULL) {
assert(length->type()->as_IntConstant() != NULL, "array length must be integer");
set_constant(length->type()->as_IntConstant()->value());
}
- } else {
- LoadField* lf = x->array()->as_LoadField();
- if (lf != NULL) {
- ciField* field = lf->field();
- if (field->is_constant() && field->is_static()) {
- // final static field
- ciObject* c = field->constant_value().as_object();
- if (c->is_array()) {
- ciArray* array = (ciArray*) c;
- set_constant(array->length());
- }
+
+ } else if ((ct = x->array()->as_Constant()) != NULL) {
+ // Constant arrays have constant lengths.
+ ArrayConstant* cnst = ct->type()->as_ArrayConstant();
+ if (cnst != NULL) {
+ set_constant(cnst->value()->length());
+ }
+
+ } else if ((lf = x->array()->as_LoadField()) != NULL) {
+ ciField* field = lf->field();
+ if (field->is_constant() && field->is_static()) {
+ assert(PatchALot || ScavengeRootsInCode < 2, "Constant field loads are folded during parsing");
+ ciObject* c = field->constant_value().as_object();
+ if (!c->is_null_object()) {
+ set_constant(c->as_array()->length());
}
}
}
--- a/hotspot/src/share/vm/c1/c1_LinearScan.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/c1/c1_LinearScan.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -1434,41 +1434,73 @@
}
#ifndef PRODUCT
+int interval_cmp(Interval* const& l, Interval* const& r) {
+ return l->from() - r->from();
+}
+
+bool find_interval(Interval* interval, IntervalArray* intervals) {
+ bool found;
+ int idx = intervals->find_sorted<Interval*, interval_cmp>(interval, found);
+
+ if (!found) {
+ return false;
+ }
+
+ int from = interval->from();
+
+ // The index we've found using binary search is pointing to an interval
+ // that is defined in the same place as the interval we were looking for.
+ // So now we have to look around that index and find exact interval.
+ for (int i = idx; i >= 0; i--) {
+ if (intervals->at(i) == interval) {
+ return true;
+ }
+ if (intervals->at(i)->from() != from) {
+ break;
+ }
+ }
+
+ for (int i = idx + 1; i < intervals->length(); i++) {
+ if (intervals->at(i) == interval) {
+ return true;
+ }
+ if (intervals->at(i)->from() != from) {
+ break;
+ }
+ }
+
+ return false;
+}
+
bool LinearScan::is_sorted(IntervalArray* intervals) {
int from = -1;
- int i, j;
- for (i = 0; i < intervals->length(); i ++) {
+ int null_count = 0;
+
+ for (int i = 0; i < intervals->length(); i++) {
Interval* it = intervals->at(i);
if (it != NULL) {
- if (from > it->from()) {
- assert(false, "");
- return false;
- }
+ assert(from <= it->from(), "Intervals are unordered");
from = it->from();
- }
- }
-
- // check in both directions if sorted list and unsorted list contain same intervals
- for (i = 0; i < interval_count(); i++) {
- if (interval_at(i) != NULL) {
- int num_found = 0;
- for (j = 0; j < intervals->length(); j++) {
- if (interval_at(i) == intervals->at(j)) {
- num_found++;
- }
- }
- assert(num_found == 1, "lists do not contain same intervals");
- }
- }
- for (j = 0; j < intervals->length(); j++) {
- int num_found = 0;
- for (i = 0; i < interval_count(); i++) {
- if (interval_at(i) == intervals->at(j)) {
- num_found++;
- }
- }
- assert(num_found == 1, "lists do not contain same intervals");
- }
+ } else {
+ null_count++;
+ }
+ }
+
+ assert(null_count == 0, "Sorted intervals should not contain nulls");
+
+ null_count = 0;
+
+ for (int i = 0; i < interval_count(); i++) {
+ Interval* interval = interval_at(i);
+ if (interval != NULL) {
+ assert(find_interval(interval, intervals), "Lists do not contain same intervals");
+ } else {
+ null_count++;
+ }
+ }
+
+ assert(interval_count() - null_count == intervals->length(),
+ "Sorted list should contain the same amount of non-NULL intervals as unsorted list");
return true;
}
@@ -1536,7 +1568,7 @@
sorted_len++;
}
}
- IntervalArray* sorted_list = new IntervalArray(sorted_len);
+ IntervalArray* sorted_list = new IntervalArray(sorted_len, sorted_len, NULL);
// special sorting algorithm: the original interval-list is almost sorted,
// only some intervals are swapped. So this is much faster than a complete QuickSort
@@ -1574,8 +1606,8 @@
_needs_full_resort = false;
}
- IntervalArray* old_list = _sorted_intervals;
- IntervalList* new_list = _new_intervals_from_allocation;
+ IntervalArray* old_list = _sorted_intervals;
+ IntervalList* new_list = _new_intervals_from_allocation;
int old_len = old_list->length();
int new_len = new_list->length();
@@ -1589,7 +1621,8 @@
new_list->sort(interval_cmp);
// merge old and new list (both already sorted) into one combined list
- IntervalArray* combined_list = new IntervalArray(old_len + new_len);
+ int combined_list_len = old_len + new_len;
+ IntervalArray* combined_list = new IntervalArray(combined_list_len, combined_list_len, NULL);
int old_idx = 0;
int new_idx = 0;
@@ -3211,6 +3244,10 @@
has_error = true;
}
+ // special intervals that are created in MoveResolver
+ // -> ignore them because the range information has no meaning there
+ if (i1->from() == 1 && i1->to() == 2) continue;
+
if (i1->first() == Range::end()) {
tty->print_cr("Interval %d has no Range", i1->reg_num()); i1->print(); tty->cr();
has_error = true;
@@ -3225,18 +3262,13 @@
for (int j = i + 1; j < len; j++) {
Interval* i2 = interval_at(j);
- if (i2 == NULL) continue;
-
- // special intervals that are created in MoveResolver
- // -> ignore them because the range information has no meaning there
- if (i1->from() == 1 && i1->to() == 2) continue;
- if (i2->from() == 1 && i2->to() == 2) continue;
+ if (i2 == NULL || (i2->from() == 1 && i2->to() == 2)) continue;
int r1 = i1->assigned_reg();
int r1Hi = i1->assigned_regHi();
int r2 = i2->assigned_reg();
int r2Hi = i2->assigned_regHi();
- if (i1->intersects(i2) && (r1 == r2 || r1 == r2Hi || (r1Hi != any_reg && (r1Hi == r2 || r1Hi == r2Hi)))) {
+ if ((r1 == r2 || r1 == r2Hi || (r1Hi != any_reg && (r1Hi == r2 || r1Hi == r2Hi))) && i1->intersects(i2)) {
tty->print_cr("Intervals %d and %d overlap and have the same register assigned", i1->reg_num(), i2->reg_num());
i1->print(); tty->cr();
i2->print(); tty->cr();
@@ -3429,7 +3461,8 @@
void RegisterVerifier::verify(BlockBegin* start) {
// setup input registers (method arguments) for first block
- IntervalList* input_state = new IntervalList(state_size(), NULL);
+ int input_state_len = state_size();
+ IntervalList* input_state = new IntervalList(input_state_len, input_state_len, NULL);
CallingConvention* args = compilation()->frame_map()->incoming_arguments();
for (int n = 0; n < args->length(); n++) {
LIR_Opr opr = args->at(n);
@@ -3543,7 +3576,7 @@
IntervalList* RegisterVerifier::copy(IntervalList* input_state) {
IntervalList* copy_state = new IntervalList(input_state->length());
- copy_state->push_all(input_state);
+ copy_state->appendAll(input_state);
return copy_state;
}
@@ -5506,7 +5539,7 @@
IntervalList* processed = _spill_intervals[reg];
for (int i = 0; i < _spill_intervals[regHi]->length(); i++) {
Interval* it = _spill_intervals[regHi]->at(i);
- if (processed->index_of(it) == -1) {
+ if (processed->find_from_end(it) == -1) {
remove_from_list(it);
split_and_spill_interval(it);
}
--- a/hotspot/src/share/vm/c1/c1_LinearScan.hpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/c1/c1_LinearScan.hpp Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -42,8 +42,8 @@
class MoveResolver;
class Range;
-define_array(IntervalArray, Interval*)
-define_stack(IntervalList, IntervalArray)
+typedef GrowableArray<Interval*> IntervalArray;
+typedef GrowableArray<Interval*> IntervalList;
define_array(IntervalsArray, IntervalList*)
define_stack(IntervalsList, IntervalsArray)
--- a/hotspot/src/share/vm/ci/ciArray.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/ci/ciArray.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -107,8 +107,9 @@
intptr_t header = arrayOopDesc::base_offset_in_bytes(elembt);
intptr_t index = (element_offset - header) >> shift;
intptr_t offset = header + ((intptr_t)index << shift);
- if (offset != element_offset || index != (jint)index)
+ if (offset != element_offset || index != (jint)index || index < 0 || index >= length()) {
return ciConstant();
+ }
return element_value((jint) index);
}
--- a/hotspot/src/share/vm/ci/ciConstantPoolCache.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/ci/ciConstantPoolCache.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -41,15 +41,21 @@
_keys = new (arena) GrowableArray<int>(arena, expected_size, 0, 0);
}
+int ciConstantPoolCache::key_compare(const int& key, const int& elt) {
+ if (key < elt) return -1;
+ else if (key > elt) return 1;
+ else return 0;
+}
+
// ------------------------------------------------------------------
// ciConstantPoolCache::get
//
// Get the entry at some index
void* ciConstantPoolCache::get(int index) {
ASSERT_IN_VM;
- int pos = find(index);
- if (pos >= _keys->length() ||
- _keys->at(pos) != index) {
+ bool found = false;
+ int pos = _keys->find_sorted<int, ciConstantPoolCache::key_compare>(index, found);
+ if (!found) {
// This element is not present in the cache.
return NULL;
}
@@ -57,42 +63,15 @@
}
// ------------------------------------------------------------------
-// ciConstantPoolCache::find
-//
-// Use binary search to find the position of this index in the cache.
-// If there is no entry in the cache corresponding to this oop, return
-// the position at which the index would be inserted.
-int ciConstantPoolCache::find(int key) {
- int min = 0;
- int max = _keys->length()-1;
-
- while (max >= min) {
- int mid = (max + min) / 2;
- int value = _keys->at(mid);
- if (value < key) {
- min = mid + 1;
- } else if (value > key) {
- max = mid - 1;
- } else {
- return mid;
- }
- }
- return min;
-}
-
-// ------------------------------------------------------------------
// ciConstantPoolCache::insert
//
// Insert a ciObject into the table at some index.
void ciConstantPoolCache::insert(int index, void* elem) {
- int i;
- int pos = find(index);
- for (i = _keys->length()-1; i >= pos; i--) {
- _keys->at_put_grow(i+1, _keys->at(i));
- _elements->at_put_grow(i+1, _elements->at(i));
- }
- _keys->at_put_grow(pos, index);
- _elements->at_put_grow(pos, elem);
+ bool found = false;
+ int pos = _keys->find_sorted<int, ciConstantPoolCache::key_compare>(index, found);
+ assert(!found, "duplicate");
+ _keys->insert_before(pos, index);
+ _elements->insert_before(pos, elem);
}
// ------------------------------------------------------------------
--- a/hotspot/src/share/vm/ci/ciConstantPoolCache.hpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/ci/ciConstantPoolCache.hpp Wed Mar 09 14:18:12 2016 +0100
@@ -38,7 +38,7 @@
GrowableArray<int>* _keys;
GrowableArray<void*>* _elements;
- int find(int index);
+ static int key_compare(const int& key, const int& elt);
public:
ciConstantPoolCache(Arena* arena, int expected_size);
--- a/hotspot/src/share/vm/ci/ciObjectFactory.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/ci/ciObjectFactory.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -260,6 +260,13 @@
return new_object;
}
+int ciObjectFactory::metadata_compare(Metadata* const& key, ciMetadata* const& elt) {
+ Metadata* value = elt->constant_encoding();
+ if (key < value) return -1;
+ else if (key > value) return 1;
+ else return 0;
+}
+
// ------------------------------------------------------------------
// ciObjectFactory::get_metadata
//
@@ -280,7 +287,8 @@
}
#endif // ASSERT
int len = _ci_metadata->length();
- int index = find(key, _ci_metadata);
+ bool found = false;
+ int index = _ci_metadata->find_sorted<Metadata*, ciObjectFactory::metadata_compare>(key, found);
#ifdef ASSERT
if (CIObjectFactoryVerify) {
for (int i=0; i<_ci_metadata->length(); i++) {
@@ -290,7 +298,8 @@
}
}
#endif
- if (!is_found_at(index, key, _ci_metadata)) {
+
+ if (!found) {
// The ciMetadata does not yet exist. Create it and insert it
// into the cache.
ciMetadata* new_object = create_new_metadata(key);
@@ -300,10 +309,10 @@
if (len != _ci_metadata->length()) {
// creating the new object has recursively entered new objects
// into the table. We need to recompute our index.
- index = find(key, _ci_metadata);
+ index = _ci_metadata->find_sorted<Metadata*, ciObjectFactory::metadata_compare>(key, found);
}
- assert(!is_found_at(index, key, _ci_metadata), "no double insert");
- insert(index, new_object, _ci_metadata);
+ assert(!found, "no double insert");
+ _ci_metadata->insert_before(index, new_object);
return new_object;
}
return _ci_metadata->at(index)->as_metadata();
@@ -655,60 +664,6 @@
obj->set_ident(_next_ident++);
}
-// ------------------------------------------------------------------
-// ciObjectFactory::find
-//
-// Use binary search to find the position of this oop in the cache.
-// If there is no entry in the cache corresponding to this oop, return
-// the position at which the oop should be inserted.
-int ciObjectFactory::find(Metadata* key, GrowableArray<ciMetadata*>* objects) {
- int min = 0;
- int max = objects->length()-1;
-
- // print_contents();
-
- while (max >= min) {
- int mid = (max + min) / 2;
- Metadata* value = objects->at(mid)->constant_encoding();
- if (value < key) {
- min = mid + 1;
- } else if (value > key) {
- max = mid - 1;
- } else {
- return mid;
- }
- }
- return min;
-}
-
-// ------------------------------------------------------------------
-// ciObjectFactory::is_found_at
-//
-// Verify that the binary seach found the given key.
-bool ciObjectFactory::is_found_at(int index, Metadata* key, GrowableArray<ciMetadata*>* objects) {
- return (index < objects->length() &&
- objects->at(index)->constant_encoding() == key);
-}
-
-
-// ------------------------------------------------------------------
-// ciObjectFactory::insert
-//
-// Insert a ciObject into the table at some index.
-void ciObjectFactory::insert(int index, ciMetadata* obj, GrowableArray<ciMetadata*>* objects) {
- int len = objects->length();
- if (len == index) {
- objects->append(obj);
- } else {
- objects->append(objects->at(len-1));
- int pos;
- for (pos = len-2; pos >= index; pos--) {
- objects->at_put(pos+1,objects->at(pos));
- }
- objects->at_put(index, obj);
- }
-}
-
static ciObjectFactory::NonPermObject* emptyBucket = NULL;
// ------------------------------------------------------------------
--- a/hotspot/src/share/vm/ci/ciObjectFactory.hpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/ci/ciObjectFactory.hpp Wed Mar 09 14:18:12 2016 +0100
@@ -68,9 +68,7 @@
NonPermObject* _non_perm_bucket[NON_PERM_BUCKETS];
int _non_perm_count;
- int find(Metadata* key, GrowableArray<ciMetadata*>* objects);
- bool is_found_at(int index, Metadata* key, GrowableArray<ciMetadata*>* objects);
- void insert(int index, ciMetadata* obj, GrowableArray<ciMetadata*>* objects);
+ static int metadata_compare(Metadata* const& key, ciMetadata* const& elt);
ciObject* create_new_object(oop o);
ciMetadata* create_new_metadata(Metadata* o);
--- a/hotspot/src/share/vm/classfile/vmSymbols.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/classfile/vmSymbols.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -542,6 +542,42 @@
case vmIntrinsics::_putLongVolatile:
case vmIntrinsics::_putFloatVolatile:
case vmIntrinsics::_putDoubleVolatile:
+ case vmIntrinsics::_getObjectAcquire:
+ case vmIntrinsics::_getBooleanAcquire:
+ case vmIntrinsics::_getByteAcquire:
+ case vmIntrinsics::_getShortAcquire:
+ case vmIntrinsics::_getCharAcquire:
+ case vmIntrinsics::_getIntAcquire:
+ case vmIntrinsics::_getLongAcquire:
+ case vmIntrinsics::_getFloatAcquire:
+ case vmIntrinsics::_getDoubleAcquire:
+ case vmIntrinsics::_putObjectRelease:
+ case vmIntrinsics::_putBooleanRelease:
+ case vmIntrinsics::_putByteRelease:
+ case vmIntrinsics::_putShortRelease:
+ case vmIntrinsics::_putCharRelease:
+ case vmIntrinsics::_putIntRelease:
+ case vmIntrinsics::_putLongRelease:
+ case vmIntrinsics::_putFloatRelease:
+ case vmIntrinsics::_putDoubleRelease:
+ case vmIntrinsics::_getObjectOpaque:
+ case vmIntrinsics::_getBooleanOpaque:
+ case vmIntrinsics::_getByteOpaque:
+ case vmIntrinsics::_getShortOpaque:
+ case vmIntrinsics::_getCharOpaque:
+ case vmIntrinsics::_getIntOpaque:
+ case vmIntrinsics::_getLongOpaque:
+ case vmIntrinsics::_getFloatOpaque:
+ case vmIntrinsics::_getDoubleOpaque:
+ case vmIntrinsics::_putObjectOpaque:
+ case vmIntrinsics::_putBooleanOpaque:
+ case vmIntrinsics::_putByteOpaque:
+ case vmIntrinsics::_putShortOpaque:
+ case vmIntrinsics::_putCharOpaque:
+ case vmIntrinsics::_putIntOpaque:
+ case vmIntrinsics::_putLongOpaque:
+ case vmIntrinsics::_putFloatOpaque:
+ case vmIntrinsics::_putDoubleOpaque:
case vmIntrinsics::_getByte_raw:
case vmIntrinsics::_getShort_raw:
case vmIntrinsics::_getChar_raw:
@@ -567,9 +603,27 @@
case vmIntrinsics::_loadFence:
case vmIntrinsics::_storeFence:
case vmIntrinsics::_fullFence:
+ case vmIntrinsics::_compareAndSwapLong:
+ case vmIntrinsics::_weakCompareAndSwapLong:
+ case vmIntrinsics::_weakCompareAndSwapLongAcquire:
+ case vmIntrinsics::_weakCompareAndSwapLongRelease:
+ case vmIntrinsics::_compareAndSwapInt:
+ case vmIntrinsics::_weakCompareAndSwapInt:
+ case vmIntrinsics::_weakCompareAndSwapIntAcquire:
+ case vmIntrinsics::_weakCompareAndSwapIntRelease:
case vmIntrinsics::_compareAndSwapObject:
- case vmIntrinsics::_compareAndSwapLong:
- case vmIntrinsics::_compareAndSwapInt:
+ case vmIntrinsics::_weakCompareAndSwapObject:
+ case vmIntrinsics::_weakCompareAndSwapObjectAcquire:
+ case vmIntrinsics::_weakCompareAndSwapObjectRelease:
+ case vmIntrinsics::_compareAndExchangeIntVolatile:
+ case vmIntrinsics::_compareAndExchangeIntAcquire:
+ case vmIntrinsics::_compareAndExchangeIntRelease:
+ case vmIntrinsics::_compareAndExchangeLongVolatile:
+ case vmIntrinsics::_compareAndExchangeLongAcquire:
+ case vmIntrinsics::_compareAndExchangeLongRelease:
+ case vmIntrinsics::_compareAndExchangeObjectVolatile:
+ case vmIntrinsics::_compareAndExchangeObjectAcquire:
+ case vmIntrinsics::_compareAndExchangeObjectRelease:
if (!InlineUnsafeOps) return true;
break;
case vmIntrinsics::_getShortUnaligned:
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp Wed Mar 09 14:18:12 2016 +0100
@@ -123,7 +123,7 @@
template(sun_misc_Launcher_ExtClassLoader, "sun/misc/Launcher$ExtClassLoader") \
\
/* Java runtime version access */ \
- template(sun_misc_Version, "sun/misc/Version") \
+ template(java_lang_VersionProps, "java/lang/VersionProps") \
template(java_runtime_name_name, "java_runtime_name") \
template(java_runtime_version_name, "java_runtime_version") \
\
@@ -1146,6 +1146,64 @@
do_intrinsic(_putFloatVolatile, jdk_internal_misc_Unsafe, putFloatVolatile_name, putFloat_signature, F_RN) \
do_intrinsic(_putDoubleVolatile, jdk_internal_misc_Unsafe, putDoubleVolatile_name, putDouble_signature, F_RN) \
\
+ do_name(getObjectOpaque_name,"getObjectOpaque") do_name(putObjectOpaque_name,"putObjectOpaque") \
+ do_name(getBooleanOpaque_name,"getBooleanOpaque") do_name(putBooleanOpaque_name,"putBooleanOpaque") \
+ do_name(getByteOpaque_name,"getByteOpaque") do_name(putByteOpaque_name,"putByteOpaque") \
+ do_name(getShortOpaque_name,"getShortOpaque") do_name(putShortOpaque_name,"putShortOpaque") \
+ do_name(getCharOpaque_name,"getCharOpaque") do_name(putCharOpaque_name,"putCharOpaque") \
+ do_name(getIntOpaque_name,"getIntOpaque") do_name(putIntOpaque_name,"putIntOpaque") \
+ do_name(getLongOpaque_name,"getLongOpaque") do_name(putLongOpaque_name,"putLongOpaque") \
+ do_name(getFloatOpaque_name,"getFloatOpaque") do_name(putFloatOpaque_name,"putFloatOpaque") \
+ do_name(getDoubleOpaque_name,"getDoubleOpaque") do_name(putDoubleOpaque_name,"putDoubleOpaque") \
+ \
+ do_intrinsic(_getObjectOpaque, jdk_internal_misc_Unsafe, getObjectOpaque_name, getObject_signature, F_R) \
+ do_intrinsic(_getBooleanOpaque, jdk_internal_misc_Unsafe, getBooleanOpaque_name, getBoolean_signature, F_R) \
+ do_intrinsic(_getByteOpaque, jdk_internal_misc_Unsafe, getByteOpaque_name, getByte_signature, F_R) \
+ do_intrinsic(_getShortOpaque, jdk_internal_misc_Unsafe, getShortOpaque_name, getShort_signature, F_R) \
+ do_intrinsic(_getCharOpaque, jdk_internal_misc_Unsafe, getCharOpaque_name, getChar_signature, F_R) \
+ do_intrinsic(_getIntOpaque, jdk_internal_misc_Unsafe, getIntOpaque_name, getInt_signature, F_R) \
+ do_intrinsic(_getLongOpaque, jdk_internal_misc_Unsafe, getLongOpaque_name, getLong_signature, F_R) \
+ do_intrinsic(_getFloatOpaque, jdk_internal_misc_Unsafe, getFloatOpaque_name, getFloat_signature, F_R) \
+ do_intrinsic(_getDoubleOpaque, jdk_internal_misc_Unsafe, getDoubleOpaque_name, getDouble_signature, F_R) \
+ do_intrinsic(_putObjectOpaque, jdk_internal_misc_Unsafe, putObjectOpaque_name, putObject_signature, F_R) \
+ do_intrinsic(_putBooleanOpaque, jdk_internal_misc_Unsafe, putBooleanOpaque_name, putBoolean_signature, F_R) \
+ do_intrinsic(_putByteOpaque, jdk_internal_misc_Unsafe, putByteOpaque_name, putByte_signature, F_R) \
+ do_intrinsic(_putShortOpaque, jdk_internal_misc_Unsafe, putShortOpaque_name, putShort_signature, F_R) \
+ do_intrinsic(_putCharOpaque, jdk_internal_misc_Unsafe, putCharOpaque_name, putChar_signature, F_R) \
+ do_intrinsic(_putIntOpaque, jdk_internal_misc_Unsafe, putIntOpaque_name, putInt_signature, F_R) \
+ do_intrinsic(_putLongOpaque, jdk_internal_misc_Unsafe, putLongOpaque_name, putLong_signature, F_R) \
+ do_intrinsic(_putFloatOpaque, jdk_internal_misc_Unsafe, putFloatOpaque_name, putFloat_signature, F_R) \
+ do_intrinsic(_putDoubleOpaque, jdk_internal_misc_Unsafe, putDoubleOpaque_name, putDouble_signature, F_R) \
+ \
+ do_name(getObjectAcquire_name, "getObjectAcquire") do_name(putObjectRelease_name, "putObjectRelease") \
+ do_name(getBooleanAcquire_name, "getBooleanAcquire") do_name(putBooleanRelease_name, "putBooleanRelease") \
+ do_name(getByteAcquire_name, "getByteAcquire") do_name(putByteRelease_name, "putByteRelease") \
+ do_name(getShortAcquire_name, "getShortAcquire") do_name(putShortRelease_name, "putShortRelease") \
+ do_name(getCharAcquire_name, "getCharAcquire") do_name(putCharRelease_name, "putCharRelease") \
+ do_name(getIntAcquire_name, "getIntAcquire") do_name(putIntRelease_name, "putIntRelease") \
+ do_name(getLongAcquire_name, "getLongAcquire") do_name(putLongRelease_name, "putLongRelease") \
+ do_name(getFloatAcquire_name, "getFloatAcquire") do_name(putFloatRelease_name, "putFloatRelease") \
+ do_name(getDoubleAcquire_name, "getDoubleAcquire") do_name(putDoubleRelease_name, "putDoubleRelease") \
+ \
+ do_intrinsic(_getObjectAcquire, jdk_internal_misc_Unsafe, getObjectAcquire_name, getObject_signature, F_R) \
+ do_intrinsic(_getBooleanAcquire, jdk_internal_misc_Unsafe, getBooleanAcquire_name, getBoolean_signature, F_R) \
+ do_intrinsic(_getByteAcquire, jdk_internal_misc_Unsafe, getByteAcquire_name, getByte_signature, F_R) \
+ do_intrinsic(_getShortAcquire, jdk_internal_misc_Unsafe, getShortAcquire_name, getShort_signature, F_R) \
+ do_intrinsic(_getCharAcquire, jdk_internal_misc_Unsafe, getCharAcquire_name, getChar_signature, F_R) \
+ do_intrinsic(_getIntAcquire, jdk_internal_misc_Unsafe, getIntAcquire_name, getInt_signature, F_R) \
+ do_intrinsic(_getLongAcquire, jdk_internal_misc_Unsafe, getLongAcquire_name, getLong_signature, F_R) \
+ do_intrinsic(_getFloatAcquire, jdk_internal_misc_Unsafe, getFloatAcquire_name, getFloat_signature, F_R) \
+ do_intrinsic(_getDoubleAcquire, jdk_internal_misc_Unsafe, getDoubleAcquire_name, getDouble_signature, F_R) \
+ do_intrinsic(_putObjectRelease, jdk_internal_misc_Unsafe, putObjectRelease_name, putObject_signature, F_R) \
+ do_intrinsic(_putBooleanRelease, jdk_internal_misc_Unsafe, putBooleanRelease_name, putBoolean_signature, F_R) \
+ do_intrinsic(_putByteRelease, jdk_internal_misc_Unsafe, putByteRelease_name, putByte_signature, F_R) \
+ do_intrinsic(_putShortRelease, jdk_internal_misc_Unsafe, putShortRelease_name, putShort_signature, F_R) \
+ do_intrinsic(_putCharRelease, jdk_internal_misc_Unsafe, putCharRelease_name, putChar_signature, F_R) \
+ do_intrinsic(_putIntRelease, jdk_internal_misc_Unsafe, putIntRelease_name, putInt_signature, F_R) \
+ do_intrinsic(_putLongRelease, jdk_internal_misc_Unsafe, putLongRelease_name, putLong_signature, F_R) \
+ do_intrinsic(_putFloatRelease, jdk_internal_misc_Unsafe, putFloatRelease_name, putFloat_signature, F_R) \
+ do_intrinsic(_putDoubleRelease, jdk_internal_misc_Unsafe, putDoubleRelease_name, putDouble_signature, F_R) \
+ \
do_name(getShortUnaligned_name,"getShortUnaligned") do_name(putShortUnaligned_name,"putShortUnaligned") \
do_name(getCharUnaligned_name,"getCharUnaligned") do_name(putCharUnaligned_name,"putCharUnaligned") \
do_name(getIntUnaligned_name,"getIntUnaligned") do_name(putIntUnaligned_name,"putIntUnaligned") \
@@ -1197,24 +1255,68 @@
do_intrinsic(_putDouble_raw, jdk_internal_misc_Unsafe, putDouble_name, putDouble_raw_signature, F_R) \
do_intrinsic(_putAddress_raw, jdk_internal_misc_Unsafe, putAddress_name, putAddress_raw_signature, F_R) \
\
- do_intrinsic(_compareAndSwapObject, jdk_internal_misc_Unsafe, compareAndSwapObject_name, compareAndSwapObject_signature, F_R) \
- do_name( compareAndSwapObject_name, "compareAndSwapObject") \
- do_signature(compareAndSwapObject_signature, "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z") \
- do_intrinsic(_compareAndSwapLong, jdk_internal_misc_Unsafe, compareAndSwapLong_name, compareAndSwapLong_signature, F_R) \
- do_name( compareAndSwapLong_name, "compareAndSwapLong") \
- do_signature(compareAndSwapLong_signature, "(Ljava/lang/Object;JJJ)Z") \
- do_intrinsic(_compareAndSwapInt, jdk_internal_misc_Unsafe, compareAndSwapInt_name, compareAndSwapInt_signature, F_R) \
- do_name( compareAndSwapInt_name, "compareAndSwapInt") \
- do_signature(compareAndSwapInt_signature, "(Ljava/lang/Object;JII)Z") \
- do_intrinsic(_putOrderedObject, jdk_internal_misc_Unsafe, putOrderedObject_name, putOrderedObject_signature, F_R) \
- do_name( putOrderedObject_name, "putOrderedObject") \
- do_alias( putOrderedObject_signature, /*(LObject;JLObject;)V*/ putObject_signature) \
- do_intrinsic(_putOrderedLong, jdk_internal_misc_Unsafe, putOrderedLong_name, putOrderedLong_signature, F_R) \
- do_name( putOrderedLong_name, "putOrderedLong") \
- do_alias( putOrderedLong_signature, /*(Ljava/lang/Object;JJ)V*/ putLong_signature) \
- do_intrinsic(_putOrderedInt, jdk_internal_misc_Unsafe, putOrderedInt_name, putOrderedInt_signature, F_R) \
- do_name( putOrderedInt_name, "putOrderedInt") \
- do_alias( putOrderedInt_signature, /*(Ljava/lang/Object;JI)V*/ putInt_signature) \
+ do_signature(compareAndSwapObject_signature, "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z") \
+ do_signature(compareAndExchangeObject_signature, "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;") \
+ do_signature(compareAndSwapLong_signature, "(Ljava/lang/Object;JJJ)Z") \
+ do_signature(compareAndExchangeLong_signature, "(Ljava/lang/Object;JJJ)J") \
+ do_signature(compareAndSwapInt_signature, "(Ljava/lang/Object;JII)Z") \
+ do_signature(compareAndExchangeInt_signature, "(Ljava/lang/Object;JII)I") \
+ \
+ do_name(compareAndSwapObject_name, "compareAndSwapObject") \
+ do_name(compareAndExchangeObjectVolatile_name, "compareAndExchangeObjectVolatile") \
+ do_name(compareAndExchangeObjectAcquire_name, "compareAndExchangeObjectAcquire") \
+ do_name(compareAndExchangeObjectRelease_name, "compareAndExchangeObjectRelease") \
+ do_name(compareAndSwapLong_name, "compareAndSwapLong") \
+ do_name(compareAndExchangeLongVolatile_name, "compareAndExchangeLongVolatile") \
+ do_name(compareAndExchangeLongAcquire_name, "compareAndExchangeLongAcquire") \
+ do_name(compareAndExchangeLongRelease_name, "compareAndExchangeLongRelease") \
+ do_name(compareAndSwapInt_name, "compareAndSwapInt") \
+ do_name(compareAndExchangeIntVolatile_name, "compareAndExchangeIntVolatile") \
+ do_name(compareAndExchangeIntAcquire_name, "compareAndExchangeIntAcquire") \
+ do_name(compareAndExchangeIntRelease_name, "compareAndExchangeIntRelease") \
+ \
+ do_name(weakCompareAndSwapObject_name, "weakCompareAndSwapObject") \
+ do_name(weakCompareAndSwapObjectAcquire_name, "weakCompareAndSwapObjectAcquire") \
+ do_name(weakCompareAndSwapObjectRelease_name, "weakCompareAndSwapObjectRelease") \
+ do_name(weakCompareAndSwapLong_name, "weakCompareAndSwapLong") \
+ do_name(weakCompareAndSwapLongAcquire_name, "weakCompareAndSwapLongAcquire") \
+ do_name(weakCompareAndSwapLongRelease_name, "weakCompareAndSwapLongRelease") \
+ do_name(weakCompareAndSwapInt_name, "weakCompareAndSwapInt") \
+ do_name(weakCompareAndSwapIntAcquire_name, "weakCompareAndSwapIntAcquire") \
+ do_name(weakCompareAndSwapIntRelease_name, "weakCompareAndSwapIntRelease") \
+ \
+ do_intrinsic(_compareAndSwapObject, jdk_internal_misc_Unsafe, compareAndSwapObject_name, compareAndSwapObject_signature, F_RN) \
+ do_intrinsic(_compareAndExchangeObjectVolatile, jdk_internal_misc_Unsafe, compareAndExchangeObjectVolatile_name, compareAndExchangeObject_signature, F_RN) \
+ do_intrinsic(_compareAndExchangeObjectAcquire, jdk_internal_misc_Unsafe, compareAndExchangeObjectAcquire_name, compareAndExchangeObject_signature, F_R) \
+ do_intrinsic(_compareAndExchangeObjectRelease, jdk_internal_misc_Unsafe, compareAndExchangeObjectRelease_name, compareAndExchangeObject_signature, F_R) \
+ do_intrinsic(_compareAndSwapLong, jdk_internal_misc_Unsafe, compareAndSwapLong_name, compareAndSwapLong_signature, F_RN) \
+ do_intrinsic(_compareAndExchangeLongVolatile, jdk_internal_misc_Unsafe, compareAndExchangeLongVolatile_name, compareAndExchangeLong_signature, F_RN) \
+ do_intrinsic(_compareAndExchangeLongAcquire, jdk_internal_misc_Unsafe, compareAndExchangeLongAcquire_name, compareAndExchangeLong_signature, F_R) \
+ do_intrinsic(_compareAndExchangeLongRelease, jdk_internal_misc_Unsafe, compareAndExchangeLongRelease_name, compareAndExchangeLong_signature, F_R) \
+ do_intrinsic(_compareAndSwapInt, jdk_internal_misc_Unsafe, compareAndSwapInt_name, compareAndSwapInt_signature, F_RN) \
+ do_intrinsic(_compareAndExchangeIntVolatile, jdk_internal_misc_Unsafe, compareAndExchangeIntVolatile_name, compareAndExchangeInt_signature, F_RN) \
+ do_intrinsic(_compareAndExchangeIntAcquire, jdk_internal_misc_Unsafe, compareAndExchangeIntAcquire_name, compareAndExchangeInt_signature, F_R) \
+ do_intrinsic(_compareAndExchangeIntRelease, jdk_internal_misc_Unsafe, compareAndExchangeIntRelease_name, compareAndExchangeInt_signature, F_R) \
+ \
+ do_intrinsic(_weakCompareAndSwapObject, jdk_internal_misc_Unsafe, weakCompareAndSwapObject_name, compareAndSwapObject_signature, F_R) \
+ do_intrinsic(_weakCompareAndSwapObjectAcquire, jdk_internal_misc_Unsafe, weakCompareAndSwapObjectAcquire_name, compareAndSwapObject_signature, F_R) \
+ do_intrinsic(_weakCompareAndSwapObjectRelease, jdk_internal_misc_Unsafe, weakCompareAndSwapObjectRelease_name, compareAndSwapObject_signature, F_R) \
+ do_intrinsic(_weakCompareAndSwapLong, jdk_internal_misc_Unsafe, weakCompareAndSwapLong_name, compareAndSwapLong_signature, F_R) \
+ do_intrinsic(_weakCompareAndSwapLongAcquire, jdk_internal_misc_Unsafe, weakCompareAndSwapLongAcquire_name, compareAndSwapLong_signature, F_R) \
+ do_intrinsic(_weakCompareAndSwapLongRelease, jdk_internal_misc_Unsafe, weakCompareAndSwapLongRelease_name, compareAndSwapLong_signature, F_R) \
+ do_intrinsic(_weakCompareAndSwapInt, jdk_internal_misc_Unsafe, weakCompareAndSwapInt_name, compareAndSwapInt_signature, F_R) \
+ do_intrinsic(_weakCompareAndSwapIntAcquire, jdk_internal_misc_Unsafe, weakCompareAndSwapIntAcquire_name, compareAndSwapInt_signature, F_R) \
+ do_intrinsic(_weakCompareAndSwapIntRelease, jdk_internal_misc_Unsafe, weakCompareAndSwapIntRelease_name, compareAndSwapInt_signature, F_R) \
+ \
+ do_intrinsic(_putOrderedObject, jdk_internal_misc_Unsafe, putOrderedObject_name, putOrderedObject_signature, F_RN) \
+ do_name( putOrderedObject_name, "putOrderedObject") \
+ do_alias( putOrderedObject_signature, /*(LObject;JLObject;)V*/ putObject_signature) \
+ do_intrinsic(_putOrderedLong, jdk_internal_misc_Unsafe, putOrderedLong_name, putOrderedLong_signature, F_RN) \
+ do_name( putOrderedLong_name, "putOrderedLong") \
+ do_alias( putOrderedLong_signature, /*(Ljava/lang/Object;JJ)V*/ putLong_signature) \
+ do_intrinsic(_putOrderedInt, jdk_internal_misc_Unsafe, putOrderedInt_name, putOrderedInt_signature, F_RN) \
+ do_name( putOrderedInt_name, "putOrderedInt") \
+ do_alias( putOrderedInt_signature, /*(Ljava/lang/Object;JI)V*/ putInt_signature) \
\
do_intrinsic(_getAndAddInt, jdk_internal_misc_Unsafe, getAndAddInt_name, getAndAddInt_signature, F_R) \
do_name( getAndAddInt_name, "getAndAddInt") \
--- a/hotspot/src/share/vm/code/codeCache.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/code/codeCache.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -1045,7 +1045,7 @@
// Keeps track of time spent for checking dependencies
NOT_PRODUCT(static elapsedTimer dependentCheckTime;)
-int CodeCache::mark_for_deoptimization(DepChange& changes) {
+int CodeCache::mark_for_deoptimization(KlassDepChange& changes) {
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
int number_of_marked_CodeBlobs = 0;
--- a/hotspot/src/share/vm/code/codeCache.hpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/code/codeCache.hpp Wed Mar 09 14:18:12 2016 +0100
@@ -72,7 +72,7 @@
// Solaris and BSD.
class OopClosure;
-class DepChange;
+class KlassDepChange;
class CodeCache : AllStatic {
friend class VMStructs;
@@ -231,7 +231,7 @@
// Deoptimization
private:
- static int mark_for_deoptimization(DepChange& changes);
+ static int mark_for_deoptimization(KlassDepChange& changes);
#ifdef HOTSWAP
static int mark_for_evol_deoptimization(instanceKlassHandle dependee);
#endif // HOTSWAP
--- a/hotspot/src/share/vm/code/dependencies.hpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/code/dependencies.hpp Wed Mar 09 14:18:12 2016 +0100
@@ -664,6 +664,8 @@
virtual bool is_klass_change() const { return false; }
virtual bool is_call_site_change() const { return false; }
+ virtual void mark_for_deoptimization(nmethod* nm) = 0;
+
// Subclass casting with assertions.
KlassDepChange* as_klass_change() {
assert(is_klass_change(), "bad cast");
@@ -753,6 +755,10 @@
// What kind of DepChange is this?
virtual bool is_klass_change() const { return true; }
+ virtual void mark_for_deoptimization(nmethod* nm) {
+ nm->mark_for_deoptimization(/*inc_recompile_counts=*/true);
+ }
+
Klass* new_type() { return _new_type(); }
// involves_context(k) is true if k is new_type or any of the super types
@@ -772,6 +778,10 @@
// What kind of DepChange is this?
virtual bool is_call_site_change() const { return true; }
+ virtual void mark_for_deoptimization(nmethod* nm) {
+ nm->mark_for_deoptimization(/*inc_recompile_counts=*/false);
+ }
+
oop call_site() const { return _call_site(); }
oop method_handle() const { return _method_handle(); }
};
--- a/hotspot/src/share/vm/code/dependencyContext.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/code/dependencyContext.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -73,7 +73,7 @@
nm->print();
nm->print_dependencies();
}
- nm->mark_for_deoptimization();
+ changes.mark_for_deoptimization(nm);
found++;
}
}
--- a/hotspot/src/share/vm/code/nmethod.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/code/nmethod.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -536,7 +536,7 @@
_has_method_handle_invokes = 0;
_lazy_critical_native = 0;
_has_wide_vectors = 0;
- _marked_for_deoptimization = 0;
+ _mark_for_deoptimization_status = not_marked;
_lock_count = 0;
_stack_traversal_mark = 0;
_unload_reported = false; // jvmti state
@@ -1458,7 +1458,7 @@
SharedRuntime::get_handle_wrong_method_stub());
}
- if (is_in_use()) {
+ if (is_in_use() && update_recompile_counts()) {
// It's a true state change, so mark the method as decompiled.
// Do it only for transition from alive.
inc_decompile_count();
--- a/hotspot/src/share/vm/code/nmethod.hpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/code/nmethod.hpp Wed Mar 09 14:18:12 2016 +0100
@@ -107,6 +107,7 @@
// [Implicit Null Pointer exception table]
// - implicit null table array
+class DepChange;
class Dependencies;
class ExceptionHandlerTable;
class ImplicitExceptionTable;
@@ -188,7 +189,13 @@
bool _has_flushed_dependencies; // Used for maintenance of dependencies (CodeCache_lock)
bool _marked_for_reclamation; // Used by NMethodSweeper (set only by sweeper)
- bool _marked_for_deoptimization; // Used for stack deoptimization
+
+ enum MarkForDeoptimizationStatus {
+ not_marked,
+ deoptimize,
+ deoptimize_noupdate };
+
+ MarkForDeoptimizationStatus _mark_for_deoptimization_status; // Used for stack deoptimization
// used by jvmti to track if an unload event has been posted for this nmethod.
bool _unload_reported;
@@ -462,8 +469,16 @@
void set_unloading_clock(unsigned char unloading_clock);
unsigned char unloading_clock();
- bool is_marked_for_deoptimization() const { return _marked_for_deoptimization; }
- void mark_for_deoptimization() { _marked_for_deoptimization = true; }
+ bool is_marked_for_deoptimization() const { return _mark_for_deoptimization_status != not_marked; }
+ void mark_for_deoptimization(bool inc_recompile_counts = true) {
+ _mark_for_deoptimization_status = (inc_recompile_counts ? deoptimize : deoptimize_noupdate);
+ }
+ bool update_recompile_counts() const {
+ // Update recompile counts when either the update is explicitly requested (deoptimize)
+ // or the nmethod is not marked for deoptimization at all (not_marked).
+ // The latter happens during uncommon traps when deoptimized nmethod is made not entrant.
+ return _mark_for_deoptimization_status != deoptimize_noupdate;
+ }
void make_unloaded(BoolObjectClosure* is_alive, oop cause);
--- a/hotspot/src/share/vm/code/relocInfo.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/code/relocInfo.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -457,49 +457,6 @@
return itr._rh;
}
-int32_t Relocation::runtime_address_to_index(address runtime_address) {
- assert(!is_reloc_index((intptr_t)runtime_address), "must not look like an index");
-
- if (runtime_address == NULL) return 0;
-
- StubCodeDesc* p = StubCodeDesc::desc_for(runtime_address);
- if (p != NULL && p->begin() == runtime_address) {
- assert(is_reloc_index(p->index()), "there must not be too many stubs");
- return (int32_t)p->index();
- } else {
- // Known "miscellaneous" non-stub pointers:
- // os::get_polling_page(), SafepointSynchronize::address_of_state()
- if (PrintRelocations) {
- tty->print_cr("random unregistered address in relocInfo: " INTPTR_FORMAT, p2i(runtime_address));
- }
-#ifndef _LP64
- return (int32_t) (intptr_t)runtime_address;
-#else
- // didn't fit return non-index
- return -1;
-#endif /* _LP64 */
- }
-}
-
-
-address Relocation::index_to_runtime_address(int32_t index) {
- if (index == 0) return NULL;
-
- if (is_reloc_index(index)) {
- StubCodeDesc* p = StubCodeDesc::desc_for_index(index);
- assert(p != NULL, "there must be a stub for this index");
- return p->begin();
- } else {
-#ifndef _LP64
- // this only works on 32bit machines
- return (address) ((intptr_t) index);
-#else
- fatal("Relocation::index_to_runtime_address, int32_t not pointer sized");
- return NULL;
-#endif /* _LP64 */
- }
-}
-
address Relocation::old_addr_for(address newa,
const CodeBuffer* src, CodeBuffer* dest) {
int sect = dest->section_index_of(newa);
@@ -623,20 +580,13 @@
void external_word_Relocation::pack_data_to(CodeSection* dest) {
short* p = (short*) dest->locs_end();
- int32_t index = runtime_address_to_index(_target);
#ifndef _LP64
- p = pack_1_int_to(p, index);
+ p = pack_1_int_to(p, (int32_t) (intptr_t)_target);
#else
- if (is_reloc_index(index)) {
- p = pack_2_ints_to(p, index, 0);
- } else {
- jlong t = (jlong) _target;
- int32_t lo = low(t);
- int32_t hi = high(t);
- p = pack_2_ints_to(p, lo, hi);
- DEBUG_ONLY(jlong t1 = jlong_from(hi, lo));
- assert(!is_reloc_index(t1) && (address) t1 == _target, "not symmetric");
- }
+ jlong t = (jlong) _target;
+ int32_t lo = low(t);
+ int32_t hi = high(t);
+ p = pack_2_ints_to(p, lo, hi);
#endif /* _LP64 */
dest->set_locs_end((relocInfo*) p);
}
@@ -644,16 +594,12 @@
void external_word_Relocation::unpack_data() {
#ifndef _LP64
- _target = index_to_runtime_address(unpack_1_int());
+ _target = (address) (intptr_t)unpack_1_int();
#else
int32_t lo, hi;
unpack_2_ints(lo, hi);
jlong t = jlong_from(hi, lo);;
- if (is_reloc_index(t)) {
- _target = index_to_runtime_address(t);
- } else {
- _target = (address) t;
- }
+ _target = (address) t;
#endif /* _LP64 */
}
--- a/hotspot/src/share/vm/code/relocInfo.hpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/code/relocInfo.hpp Wed Mar 09 14:18:12 2016 +0100
@@ -707,10 +707,6 @@
assert(datalen()==0 || type()==relocInfo::none, "no data here");
}
- static bool is_reloc_index(intptr_t index) {
- return 0 < index && index < os::vm_page_size();
- }
-
protected:
// Helper functions for pack_data_to() and unpack_data().
@@ -806,10 +802,6 @@
return base + byte_offset;
}
- // these convert between indexes and addresses in the runtime system
- static int32_t runtime_address_to_index(address runtime_address);
- static address index_to_runtime_address(int32_t index);
-
// helpers for mapping between old and new addresses after a move or resize
address old_addr_for(address newa, const CodeBuffer* src, CodeBuffer* dest);
address new_addr_for(address olda, const CodeBuffer* src, CodeBuffer* dest);
@@ -1253,7 +1245,8 @@
// Some address looking values aren't safe to treat as relocations
// and should just be treated as constants.
static bool can_be_relocated(address target) {
- return target != NULL && !is_reloc_index((intptr_t)target);
+ assert(target == NULL || (uintptr_t)target >= (uintptr_t)os::vm_page_size(), INTPTR_FORMAT, (intptr_t)target);
+ return target != NULL;
}
private:
--- a/hotspot/src/share/vm/compiler/compileBroker.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/compiler/compileBroker.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -469,7 +469,6 @@
void CompileBroker::print_compile_queues(outputStream* st) {
st->print_cr("Current compiles: ");
MutexLocker locker(MethodCompileQueue_lock);
- MutexLocker locker2(Threads_lock);
char buf[2000];
int buflen = sizeof(buf);
@@ -2152,18 +2151,33 @@
if (CITime) {
int bytes_compiled = method->code_size() + task->num_inlined_bytecodes();
- JVMCI_ONLY(CompilerStatistics* stats = compiler(task->comp_level())->stats();)
if (is_osr) {
_t_osr_compilation.add(time);
_sum_osr_bytes_compiled += bytes_compiled;
- JVMCI_ONLY(stats->_osr.update(time, bytes_compiled);)
} else {
_t_standard_compilation.add(time);
_sum_standard_bytes_compiled += method->code_size() + task->num_inlined_bytecodes();
- JVMCI_ONLY(stats->_standard.update(time, bytes_compiled);)
}
- JVMCI_ONLY(stats->_nmethods_size += code->total_size();)
- JVMCI_ONLY(stats->_nmethods_code_size += code->insts_size();)
+
+#if INCLUDE_JVMCI
+ AbstractCompiler* comp = compiler(task->comp_level());
+ if (comp) {
+ CompilerStatistics* stats = comp->stats();
+ if (stats) {
+ if (is_osr) {
+ stats->_osr.update(time, bytes_compiled);
+ } else {
+ stats->_standard.update(time, bytes_compiled);
+ }
+ stats->_nmethods_size += code->total_size();
+ stats->_nmethods_code_size += code->insts_size();
+ } else { // if (!stats)
+ assert(false, "Compiler statistics object must exist");
+ }
+ } else { // if (!comp)
+ assert(false, "Compiler object must exist");
+ }
+#endif // INCLUDE_JVMCI
}
if (UsePerfData) {
@@ -2222,11 +2236,15 @@
#if INCLUDE_JVMCI
void CompileBroker::print_times(AbstractCompiler* comp) {
CompilerStatistics* stats = comp->stats();
- tty->print_cr(" %s {speed: %d bytes/s; standard: %6.3f s, %d bytes, %d methods; osr: %6.3f s, %d bytes, %d methods; nmethods_size: %d bytes; nmethods_code_size: %d bytes}",
+ if (stats) {
+ tty->print_cr(" %s {speed: %d bytes/s; standard: %6.3f s, %d bytes, %d methods; osr: %6.3f s, %d bytes, %d methods; nmethods_size: %d bytes; nmethods_code_size: %d bytes}",
comp->name(), stats->bytes_per_second(),
stats->_standard._time.seconds(), stats->_standard._bytes, stats->_standard._count,
stats->_osr._time.seconds(), stats->_osr._bytes, stats->_osr._count,
stats->_nmethods_size, stats->_nmethods_code_size);
+ } else { // if (!stats)
+ assert(false, "Compiler statistics object must exist");
+ }
comp->print_timers();
}
#endif // INCLUDE_JVMCI
@@ -2260,17 +2278,21 @@
}
CompilerStatistics* stats = comp->stats();
- standard_compilation.add(stats->_standard._time);
- osr_compilation.add(stats->_osr._time);
+ if (stats) {
+ standard_compilation.add(stats->_standard._time);
+ osr_compilation.add(stats->_osr._time);
- standard_bytes_compiled += stats->_standard._bytes;
- osr_bytes_compiled += stats->_osr._bytes;
+ standard_bytes_compiled += stats->_standard._bytes;
+ osr_bytes_compiled += stats->_osr._bytes;
- standard_compile_count += stats->_standard._count;
- osr_compile_count += stats->_osr._count;
+ standard_compile_count += stats->_standard._count;
+ osr_compile_count += stats->_osr._count;
- nmethods_size += stats->_nmethods_size;
- nmethods_code_size += stats->_nmethods_code_size;
+ nmethods_size += stats->_nmethods_size;
+ nmethods_code_size += stats->_nmethods_code_size;
+ } else { // if (!stats)
+ assert(false, "Compiler statistics object must exist");
+ }
if (per_compiler) {
print_times(comp);
--- a/hotspot/src/share/vm/jvmci/commandLineFlagConstraintsJVMCI.cpp Wed Mar 09 14:54:18 2016 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include "precompiled.hpp"
-#include "jvmci/commandLineFlagConstraintsJVMCI.hpp"
-#include "runtime/arguments.hpp"
-#include "runtime/globals.hpp"
-#include "utilities/defaultStream.hpp"
-
-Flag::Error EnableJVMCIMustBeEnabledConstraintFunc(bool value, bool verbose) {
- if (!EnableJVMCI) {
- if (verbose == true) {
- jio_fprintf(defaultStream::error_stream(), "EnableJVMCI must be enabled\n");
- }
- return Flag::VIOLATES_CONSTRAINT;
- } else {
- return Flag::SUCCESS;
- }
-}
-
-Flag::Error EnableJVMCIMustBeEnabledConstraintFunc(intx value, bool verbose) {
- if (!EnableJVMCI) {
- if (verbose == true) {
- jio_fprintf(defaultStream::error_stream(), "EnableJVMCI must be enabled\n");
- }
- return Flag::VIOLATES_CONSTRAINT;
- } else {
- return Flag::SUCCESS;
- }
-}
--- a/hotspot/src/share/vm/jvmci/commandLineFlagConstraintsJVMCI.hpp Wed Mar 09 14:54:18 2016 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#ifndef SHARE_VM_JVMCI_COMMANDLINEFLAGCONSTRAINTSJVMCI_HPP
-#define SHARE_VM_JVMCI_COMMANDLINEFLAGCONSTRAINTSJVMCI_HPP
-
-#include "runtime/globals.hpp"
-#include "utilities/globalDefinitions.hpp"
-
-/*
- * Here we have JVMCI arguments constraints functions, which are called automatically
- * whenever flag's value changes. If the constraint fails the function should return
- * an appropriate error value.
- */
-
-Flag::Error EnableJVMCIMustBeEnabledConstraintFunc(bool value, bool verbose);
-Flag::Error EnableJVMCIMustBeEnabledConstraintFunc(intx value, bool verbose);
-
-#endif /* SHARE_VM_JVMCI_COMMANDLINEFLAGCONSTRAINTSJVMCI_HPP */
--- a/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -551,6 +551,14 @@
compiler, _debug_recorder, _dependencies, env, id,
has_unsafe_access, _has_wide_vector, installed_code, compiled_code, speculation_log);
cb = nm;
+ if (nm != NULL && env == NULL) {
+ DirectiveSet* directive = DirectivesStack::getMatchingDirective(method, compiler);
+ bool printnmethods = directive->PrintAssemblyOption || directive->PrintNMethodsOption;
+ if (printnmethods || PrintDebugInfo || PrintRelocations || PrintDependencies || PrintExceptionHandlers) {
+ nm->print_nmethod(printnmethods);
+ }
+ DirectivesStack::release(directive);
+ }
}
if (cb != NULL) {
--- a/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -293,13 +293,11 @@
// tracing
if (log_is_enabled(Info, exceptions)) {
ResourceMark rm;
- log_info(exceptions)("Exception <%s> (" INTPTR_FORMAT ") thrown in"
- " compiled method <%s> at PC " INTPTR_FORMAT
- " for thread " INTPTR_FORMAT,
- exception->print_value_string(),
- p2i((address)exception()),
- nm->method()->print_value_string(), p2i(pc),
- p2i(thread));
+ stringStream tempst;
+ tempst.print("compiled method <%s>\n"
+ " at PC" INTPTR_FORMAT " for thread " INTPTR_FORMAT,
+ nm->method()->print_value_string(), p2i(pc), p2i(thread));
+ Exceptions::log_exception(exception, tempst);
}
// for AbortVMOnException flag
NOT_PRODUCT(Exceptions::debug_check_abort(exception));
--- a/hotspot/src/share/vm/jvmci/jvmci_globals.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/jvmci/jvmci_globals.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -24,6 +24,8 @@
#include "precompiled.hpp"
#include "jvmci/jvmci_globals.hpp"
+#include "utilities/defaultStream.hpp"
+#include "runtime/globals_extension.hpp"
JVMCI_FLAGS(MATERIALIZE_DEVELOPER_FLAG, \
MATERIALIZE_PD_DEVELOPER_FLAG, \
@@ -34,3 +36,185 @@
MATERIALIZE_NOTPRODUCT_FLAG,
IGNORE_RANGE, \
IGNORE_CONSTRAINT)
+
+#define JVMCI_IGNORE_FLAG_FOUR_PARAM(type, name, value, doc)
+#define JVMCI_IGNORE_FLAG_THREE_PARAM(type, name, doc)
+
+// Return true if jvmci flags are consistent.
+bool JVMCIGlobals::check_jvmci_flags_are_consistent() {
+ if (EnableJVMCI) {
+ return true;
+ }
+
+ // "FLAG_IS_DEFAULT" fail count.
+ int fail_count = 0;
+ // Number of "FLAG_IS_DEFAULT" fails that should be skipped before code
+ // detect real consistency failure.
+ int skip_fail_count;
+
+ // EnableJVMCI flag is false here.
+ // If any other flag is changed, consistency check should fail.
+ // JVMCI_FLAGS macros added below can handle all JVMCI flags automatically.
+ // But it contains check for EnableJVMCI flag too, which is required to be
+ // skipped. This can't be handled easily!
+ // So the code looks for at-least two flag changes to detect consistency
+ // failure when EnableJVMCI flag is changed.
+ // Otherwise one flag change is sufficient to detect consistency failure.
+ // Set skip_fail_count to 0 if EnableJVMCI flag is default.
+ // Set skip_fail_count to 1 if EnableJVMCI flag is changed.
+ // This value will be used to skip fails in macro expanded code later.
+ if (!FLAG_IS_DEFAULT(EnableJVMCI)) {
+ skip_fail_count = 1;
+ } else {
+ skip_fail_count = 0;
+ }
+
+#define EMIT_FLAG_VALUE_CHANGED_CHECK_CODE(FLAG) \
+ if (!FLAG_IS_DEFAULT(FLAG)) { \
+ fail_count++; \
+ if (fail_count > skip_fail_count) { \
+ return false; \
+ } \
+ }
+
+#define JVMCI_DIAGNOSTIC_FLAG_VALUE_CHANGED_CHECK_CODE(type, name, value, doc) EMIT_FLAG_VALUE_CHANGED_CHECK_CODE(name)
+#define JVMCI_EXPERIMENTAL_FLAG_VALUE_CHANGED_CHECK_CODE(type, name, value, doc) EMIT_FLAG_VALUE_CHANGED_CHECK_CODE(name)
+
+ // Check consistency of diagnostic flags if UnlockDiagnosticVMOptions is true
+ // or not default. UnlockDiagnosticVMOptions is default true in debug builds.
+ if (UnlockDiagnosticVMOptions || !FLAG_IS_DEFAULT(UnlockDiagnosticVMOptions)) {
+ JVMCI_FLAGS(JVMCI_IGNORE_FLAG_FOUR_PARAM, \
+ JVMCI_IGNORE_FLAG_THREE_PARAM, \
+ JVMCI_IGNORE_FLAG_FOUR_PARAM, \
+ JVMCI_IGNORE_FLAG_THREE_PARAM, \
+ JVMCI_DIAGNOSTIC_FLAG_VALUE_CHANGED_CHECK_CODE, \
+ JVMCI_IGNORE_FLAG_FOUR_PARAM, \
+ JVMCI_IGNORE_FLAG_FOUR_PARAM, \
+ IGNORE_RANGE, \
+ IGNORE_CONSTRAINT)
+ }
+
+ // Check consistency of experimental flags if UnlockExperimentalVMOptions is
+ // true or not default.
+ if (UnlockExperimentalVMOptions || !FLAG_IS_DEFAULT(UnlockExperimentalVMOptions)) {
+ JVMCI_FLAGS(JVMCI_IGNORE_FLAG_FOUR_PARAM, \
+ JVMCI_IGNORE_FLAG_THREE_PARAM, \
+ JVMCI_IGNORE_FLAG_FOUR_PARAM, \
+ JVMCI_IGNORE_FLAG_THREE_PARAM, \
+ JVMCI_IGNORE_FLAG_FOUR_PARAM, \
+ JVMCI_EXPERIMENTAL_FLAG_VALUE_CHANGED_CHECK_CODE, \
+ JVMCI_IGNORE_FLAG_FOUR_PARAM, \
+ IGNORE_RANGE, \
+ IGNORE_CONSTRAINT)
+ }
+
+#ifndef PRODUCT
+#define JVMCI_DEVELOP_FLAG_VALUE_CHANGED_CHECK_CODE(type, name, value, doc) EMIT_FLAG_VALUE_CHANGED_CHECK_CODE(name)
+#define JVMCI_PD_DEVELOP_FLAG_VALUE_CHANGED_CHECK_CODE(type, name, doc) EMIT_FLAG_VALUE_CHANGED_CHECK_CODE(name)
+#define JVMCI_NOTPRODUCT_FLAG_VALUE_CHANGED_CHECK_CODE(type, name, value, doc) EMIT_FLAG_VALUE_CHANGED_CHECK_CODE(name)
+#else
+#define JVMCI_DEVELOP_FLAG_VALUE_CHANGED_CHECK_CODE(type, name, value, doc)
+#define JVMCI_PD_DEVELOP_FLAG_VALUE_CHANGED_CHECK_CODE(type, name, doc)
+#define JVMCI_NOTPRODUCT_FLAG_VALUE_CHANGED_CHECK_CODE(type, name, value, doc)
+#endif
+
+#define JVMCI_PD_PRODUCT_FLAG_VALUE_CHANGED_CHECK_CODE(type, name, doc) EMIT_FLAG_VALUE_CHANGED_CHECK_CODE(name)
+#define JVMCI_PRODUCT_FLAG_VALUE_CHANGED_CHECK_CODE(type, name, value, doc) EMIT_FLAG_VALUE_CHANGED_CHECK_CODE(name)
+
+ JVMCI_FLAGS(JVMCI_DEVELOP_FLAG_VALUE_CHANGED_CHECK_CODE, \
+ JVMCI_PD_DEVELOP_FLAG_VALUE_CHANGED_CHECK_CODE, \
+ JVMCI_PRODUCT_FLAG_VALUE_CHANGED_CHECK_CODE, \
+ JVMCI_PD_PRODUCT_FLAG_VALUE_CHANGED_CHECK_CODE, \
+ JVMCI_IGNORE_FLAG_FOUR_PARAM, \
+ JVMCI_IGNORE_FLAG_FOUR_PARAM, \
+ JVMCI_NOTPRODUCT_FLAG_VALUE_CHANGED_CHECK_CODE, \
+ IGNORE_RANGE, \
+ IGNORE_CONSTRAINT)
+
+#undef EMIT_FLAG_VALUE_CHANGED_CHECK_CODE
+#undef JVMCI_DEVELOP_FLAG_VALUE_CHANGED_CHECK_CODE
+#undef JVMCI_PD_DEVELOP_FLAG_VALUE_CHANGED_CHECK_CODE
+#undef JVMCI_NOTPRODUCT_FLAG_VALUE_CHANGED_CHECK_CODE
+#undef JVMCI_DIAGNOSTIC_FLAG_VALUE_CHANGED_CHECK_CODE
+#undef JVMCI_PD_PRODUCT_FLAG_VALUE_CHANGED_CHECK_CODE
+#undef JVMCI_PRODUCT_FLAG_VALUE_CHANGED_CHECK_CODE
+#undef JVMCI_EXPERIMENTAL_FLAG_VALUE_CHANGED_CHECK_CODE
+
+ return true;
+}
+
+// Print jvmci arguments inconsistency error message.
+void JVMCIGlobals::print_jvmci_args_inconsistency_error_message() {
+ const char* error_msg = "Improperly specified VM option '%s'\n";
+ jio_fprintf(defaultStream::error_stream(), "EnableJVMCI must be enabled\n");
+
+#define EMIT_CHECK_PRINT_ERR_MSG_CODE(FLAG) \
+ if (!FLAG_IS_DEFAULT(FLAG)) { \
+ if (strcmp(#FLAG, "EnableJVMCI")) { \
+ jio_fprintf(defaultStream::error_stream(), error_msg, #FLAG); \
+ } \
+ }
+
+#define JVMCI_DIAGNOSTIC_FLAG_CHECK_PRINT_ERR_MSG_CODE(type, name, value, doc) EMIT_CHECK_PRINT_ERR_MSG_CODE(name)
+#define JVMCI_EXPERIMENTAL_FLAG_CHECK_PRINT_ERR_MSG_CODE(type, name, value, doc) EMIT_CHECK_PRINT_ERR_MSG_CODE(name)
+
+ if (UnlockDiagnosticVMOptions || !FLAG_IS_DEFAULT(UnlockDiagnosticVMOptions)) {
+ JVMCI_FLAGS(JVMCI_IGNORE_FLAG_FOUR_PARAM, \
+ JVMCI_IGNORE_FLAG_THREE_PARAM, \
+ JVMCI_IGNORE_FLAG_FOUR_PARAM, \
+ JVMCI_IGNORE_FLAG_THREE_PARAM, \
+ JVMCI_DIAGNOSTIC_FLAG_CHECK_PRINT_ERR_MSG_CODE, \
+ JVMCI_IGNORE_FLAG_FOUR_PARAM, \
+ JVMCI_IGNORE_FLAG_FOUR_PARAM, \
+ IGNORE_RANGE, \
+ IGNORE_CONSTRAINT)
+ }
+
+ if (UnlockExperimentalVMOptions || !FLAG_IS_DEFAULT(UnlockExperimentalVMOptions)) {
+ JVMCI_FLAGS(JVMCI_IGNORE_FLAG_FOUR_PARAM, \
+ JVMCI_IGNORE_FLAG_THREE_PARAM, \
+ JVMCI_IGNORE_FLAG_FOUR_PARAM, \
+ JVMCI_IGNORE_FLAG_THREE_PARAM, \
+ JVMCI_IGNORE_FLAG_FOUR_PARAM, \
+ JVMCI_EXPERIMENTAL_FLAG_CHECK_PRINT_ERR_MSG_CODE, \
+ JVMCI_IGNORE_FLAG_FOUR_PARAM, \
+ IGNORE_RANGE, \
+ IGNORE_CONSTRAINT)
+ }
+
+#ifndef PRODUCT
+#define JVMCI_DEVELOP_FLAG_CHECK_PRINT_ERR_MSG_CODE(type, name, value, doc) EMIT_CHECK_PRINT_ERR_MSG_CODE(name)
+#define JVMCI_PD_DEVELOP_FLAG_CHECK_PRINT_ERR_MSG_CODE(type, name, doc) EMIT_CHECK_PRINT_ERR_MSG_CODE(name)
+#define JVMCI_NOTPRODUCT_FLAG_CHECK_PRINT_ERR_MSG_CODE(type, name, value, doc) EMIT_CHECK_PRINT_ERR_MSG_CODE(name)
+#else
+#define JVMCI_DEVELOP_FLAG_CHECK_PRINT_ERR_MSG_CODE(type, name, value, doc)
+#define JVMCI_PD_DEVELOP_FLAG_CHECK_PRINT_ERR_MSG_CODE(type, name, doc)
+#define JVMCI_NOTPRODUCT_FLAG_CHECK_PRINT_ERR_MSG_CODE(type, name, value, doc)
+#endif
+
+#define JVMCI_PD_PRODUCT_FLAG_CHECK_PRINT_ERR_MSG_CODE(type, name, doc) EMIT_CHECK_PRINT_ERR_MSG_CODE(name)
+#define JVMCI_PRODUCT_FLAG_CHECK_PRINT_ERR_MSG_CODE(type, name, value, doc) EMIT_CHECK_PRINT_ERR_MSG_CODE(name)
+
+ JVMCI_FLAGS(JVMCI_DEVELOP_FLAG_CHECK_PRINT_ERR_MSG_CODE, \
+ JVMCI_PD_DEVELOP_FLAG_CHECK_PRINT_ERR_MSG_CODE, \
+ JVMCI_PRODUCT_FLAG_CHECK_PRINT_ERR_MSG_CODE, \
+ JVMCI_PD_PRODUCT_FLAG_CHECK_PRINT_ERR_MSG_CODE, \
+ JVMCI_IGNORE_FLAG_FOUR_PARAM, \
+ JVMCI_IGNORE_FLAG_FOUR_PARAM, \
+ JVMCI_NOTPRODUCT_FLAG_CHECK_PRINT_ERR_MSG_CODE, \
+ IGNORE_RANGE, \
+ IGNORE_CONSTRAINT)
+
+#undef EMIT_CHECK_PRINT_ERR_MSG_CODE
+#undef JVMCI_DEVELOP_FLAG_CHECK_PRINT_ERR_MSG_CODE
+#undef JVMCI_PD_DEVELOP_FLAG_CHECK_PRINT_ERR_MSG_CODE
+#undef JVMCI_NOTPRODUCT_FLAG_CHECK_PRINT_ERR_MSG_CODE
+#undef JVMCI_PD_PRODUCT_FLAG_CHECK_PRINT_ERR_MSG_CODE
+#undef JVMCI_PRODUCT_FLAG_CHECK_PRINT_ERR_MSG_CODE
+#undef JVMCI_DIAGNOSTIC_FLAG_CHECK_PRINT_ERR_MSG_CODE
+#undef JVMCI_EXPERIMENTAL_FLAG_CHECK_PRINT_ERR_MSG_CODE
+
+}
+
+#undef JVMCI_IGNORE_FLAG_FOUR_PARAM
+#undef JVMCI_IGNORE_FLAG_THREE_PARAM
--- a/hotspot/src/share/vm/jvmci/jvmci_globals.hpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/jvmci/jvmci_globals.hpp Wed Mar 09 14:18:12 2016 +0100
@@ -39,29 +39,23 @@
\
experimental(bool, UseJVMCICompiler, false, \
"Use JVMCI as the default compiler") \
- constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \
\
experimental(bool, BootstrapJVMCI, false, \
"Bootstrap JVMCI before running Java main method") \
- constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \
\
experimental(bool, PrintBootstrap, true, \
"Print JVMCI bootstrap progress and summary") \
- constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \
\
experimental(intx, JVMCIThreads, 1, \
"Force number of JVMCI compiler threads to use") \
range(1, max_jint) \
- constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \
\
experimental(intx, JVMCIHostThreads, 1, \
"Force number of compiler threads for JVMCI host compiler") \
range(1, max_jint) \
- constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \
\
experimental(bool, CodeInstallSafepointChecks, true, \
"Perform explicit safepoint checks while installing code") \
- constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \
\
NOT_COMPILER2(product(intx, MaxVectorSize, 64, \
"Max vector size in bytes, " \
@@ -74,28 +68,22 @@
"Trace level for JVMCI: " \
"1 means emit a message for each CompilerToVM call," \
"levels greater than 1 provide progressively greater detail") \
- constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \
\
experimental(intx, JVMCICounterSize, 0, \
"Reserved size for benchmark counters") \
range(0, max_jint) \
- constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \
\
experimental(bool, JVMCICountersExcludeCompiler, true, \
"Exclude JVMCI compiler threads from benchmark counters") \
- constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \
\
develop(bool, JVMCIUseFastLocking, true, \
"Use fast inlined locking code") \
- constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \
\
experimental(intx, JVMCINMethodSizeLimit, (80*K)*wordSize, \
"Maximum size of a compiled method.") \
- constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \
\
develop(bool, TraceUncollectedSpeculations, false, \
- "Print message when a failed speculation was not collected") \
- constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \
+ "Print message when a failed speculation was not collected")
// Read default values for JVMCI globals
@@ -110,4 +98,11 @@
IGNORE_RANGE, \
IGNORE_CONSTRAINT)
+class JVMCIGlobals {
+ public:
+ // Return true if jvmci flags are consistent.
+ static bool check_jvmci_flags_are_consistent();
+ // Print jvmci arguments inconsistency error message.
+ static void print_jvmci_args_inconsistency_error_message();
+};
#endif // SHARE_VM_JVMCI_JVMCIGLOBALS_HPP
--- a/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -592,6 +592,14 @@
#endif // TARGET_OS_FAMILY_bsd
+#ifdef TARGET_ARCH_aarch64
+
+#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \
+ volatile_nonstatic_field(JavaFrameAnchor, _last_Java_fp, intptr_t*)
+
+#endif // TARGET_ARCH_aarch64
+
+
#ifdef TARGET_ARCH_x86
#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -1879,7 +1879,7 @@
return dep_context;
}
-int InstanceKlass::mark_dependent_nmethods(DepChange& changes) {
+int InstanceKlass::mark_dependent_nmethods(KlassDepChange& changes) {
return dependencies().mark_dependent_nmethods(changes);
}
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp Wed Mar 09 14:18:12 2016 +0100
@@ -56,7 +56,7 @@
// forward declaration for class -- see below for definition
class BreakpointInfo;
class ClassFileParser;
-class DepChange;
+class KlassDepChange;
class DependencyContext;
class fieldDescriptor;
class jniIdMapBase;
@@ -821,7 +821,7 @@
// maintenance of deoptimization dependencies
inline DependencyContext dependencies();
- int mark_dependent_nmethods(DepChange& changes);
+ int mark_dependent_nmethods(KlassDepChange& changes);
void add_dependent_nmethod(nmethod* nm);
void remove_dependent_nmethod(nmethod* nm, bool delete_immediately);
--- a/hotspot/src/share/vm/opto/c2compiler.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/opto/c2compiler.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -243,14 +243,72 @@
case vmIntrinsics::_reverseBytes_l:
if (!Matcher::match_rule_supported(Op_ReverseBytesL)) return false;
break;
+
+ /* CompareAndSwap, Object: */
case vmIntrinsics::_compareAndSwapObject:
#ifdef _LP64
+ if ( UseCompressedOops && !Matcher::match_rule_supported(Op_CompareAndSwapN)) return false;
if (!UseCompressedOops && !Matcher::match_rule_supported(Op_CompareAndSwapP)) return false;
+#else
+ if (!Matcher::match_rule_supported(Op_CompareAndSwapP)) return false;
#endif
break;
+ case vmIntrinsics::_weakCompareAndSwapObject:
+ case vmIntrinsics::_weakCompareAndSwapObjectAcquire:
+ case vmIntrinsics::_weakCompareAndSwapObjectRelease:
+#ifdef _LP64
+ if ( UseCompressedOops && !Matcher::match_rule_supported(Op_WeakCompareAndSwapN)) return false;
+ if (!UseCompressedOops && !Matcher::match_rule_supported(Op_WeakCompareAndSwapP)) return false;
+#else
+ if (!Matcher::match_rule_supported(Op_WeakCompareAndSwapP)) return false;
+#endif
+ break;
+ /* CompareAndSwap, Long: */
case vmIntrinsics::_compareAndSwapLong:
if (!Matcher::match_rule_supported(Op_CompareAndSwapL)) return false;
break;
+ case vmIntrinsics::_weakCompareAndSwapLong:
+ case vmIntrinsics::_weakCompareAndSwapLongAcquire:
+ case vmIntrinsics::_weakCompareAndSwapLongRelease:
+ if (!Matcher::match_rule_supported(Op_WeakCompareAndSwapL)) return false;
+ break;
+
+ /* CompareAndSwap, Int: */
+ case vmIntrinsics::_compareAndSwapInt:
+ if (!Matcher::match_rule_supported(Op_CompareAndSwapI)) return false;
+ break;
+ case vmIntrinsics::_weakCompareAndSwapInt:
+ case vmIntrinsics::_weakCompareAndSwapIntAcquire:
+ case vmIntrinsics::_weakCompareAndSwapIntRelease:
+ if (!Matcher::match_rule_supported(Op_WeakCompareAndSwapL)) return false;
+ break;
+
+ /* CompareAndExchange, Object: */
+ case vmIntrinsics::_compareAndExchangeObjectVolatile:
+ case vmIntrinsics::_compareAndExchangeObjectAcquire:
+ case vmIntrinsics::_compareAndExchangeObjectRelease:
+#ifdef _LP64
+ if ( UseCompressedOops && !Matcher::match_rule_supported(Op_CompareAndExchangeN)) return false;
+ if (!UseCompressedOops && !Matcher::match_rule_supported(Op_CompareAndExchangeP)) return false;
+#else
+ if (!Matcher::match_rule_supported(Op_CompareAndExchangeP)) return false;
+#endif
+ break;
+
+ /* CompareAndExchange, Long: */
+ case vmIntrinsics::_compareAndExchangeLongVolatile:
+ case vmIntrinsics::_compareAndExchangeLongAcquire:
+ case vmIntrinsics::_compareAndExchangeLongRelease:
+ if (!Matcher::match_rule_supported(Op_CompareAndExchangeL)) return false;
+ break;
+
+ /* CompareAndExchange, Int: */
+ case vmIntrinsics::_compareAndExchangeIntVolatile:
+ case vmIntrinsics::_compareAndExchangeIntAcquire:
+ case vmIntrinsics::_compareAndExchangeIntRelease:
+ if (!Matcher::match_rule_supported(Op_CompareAndExchangeI)) return false;
+ break;
+
case vmIntrinsics::_getAndAddInt:
if (!Matcher::match_rule_supported(Op_GetAndAddI)) return false;
break;
@@ -382,6 +440,42 @@
case vmIntrinsics::_putLongVolatile:
case vmIntrinsics::_putFloatVolatile:
case vmIntrinsics::_putDoubleVolatile:
+ case vmIntrinsics::_getObjectAcquire:
+ case vmIntrinsics::_getBooleanAcquire:
+ case vmIntrinsics::_getByteAcquire:
+ case vmIntrinsics::_getShortAcquire:
+ case vmIntrinsics::_getCharAcquire:
+ case vmIntrinsics::_getIntAcquire:
+ case vmIntrinsics::_getLongAcquire:
+ case vmIntrinsics::_getFloatAcquire:
+ case vmIntrinsics::_getDoubleAcquire:
+ case vmIntrinsics::_putObjectRelease:
+ case vmIntrinsics::_putBooleanRelease:
+ case vmIntrinsics::_putByteRelease:
+ case vmIntrinsics::_putShortRelease:
+ case vmIntrinsics::_putCharRelease:
+ case vmIntrinsics::_putIntRelease:
+ case vmIntrinsics::_putLongRelease:
+ case vmIntrinsics::_putFloatRelease:
+ case vmIntrinsics::_putDoubleRelease:
+ case vmIntrinsics::_getObjectOpaque:
+ case vmIntrinsics::_getBooleanOpaque:
+ case vmIntrinsics::_getByteOpaque:
+ case vmIntrinsics::_getShortOpaque:
+ case vmIntrinsics::_getCharOpaque:
+ case vmIntrinsics::_getIntOpaque:
+ case vmIntrinsics::_getLongOpaque:
+ case vmIntrinsics::_getFloatOpaque:
+ case vmIntrinsics::_getDoubleOpaque:
+ case vmIntrinsics::_putObjectOpaque:
+ case vmIntrinsics::_putBooleanOpaque:
+ case vmIntrinsics::_putByteOpaque:
+ case vmIntrinsics::_putShortOpaque:
+ case vmIntrinsics::_putCharOpaque:
+ case vmIntrinsics::_putIntOpaque:
+ case vmIntrinsics::_putLongOpaque:
+ case vmIntrinsics::_putFloatOpaque:
+ case vmIntrinsics::_putDoubleOpaque:
case vmIntrinsics::_getShortUnaligned:
case vmIntrinsics::_getCharUnaligned:
case vmIntrinsics::_getIntUnaligned:
@@ -390,7 +484,6 @@
case vmIntrinsics::_putCharUnaligned:
case vmIntrinsics::_putIntUnaligned:
case vmIntrinsics::_putLongUnaligned:
- case vmIntrinsics::_compareAndSwapInt:
case vmIntrinsics::_putOrderedObject:
case vmIntrinsics::_putOrderedInt:
case vmIntrinsics::_putOrderedLong:
--- a/hotspot/src/share/vm/opto/classes.hpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/opto/classes.hpp Wed Mar 09 14:18:12 2016 +0100
@@ -85,6 +85,14 @@
macro(CompareAndSwapL)
macro(CompareAndSwapP)
macro(CompareAndSwapN)
+macro(WeakCompareAndSwapI)
+macro(WeakCompareAndSwapL)
+macro(WeakCompareAndSwapP)
+macro(WeakCompareAndSwapN)
+macro(CompareAndExchangeI)
+macro(CompareAndExchangeL)
+macro(CompareAndExchangeP)
+macro(CompareAndExchangeN)
macro(GetAndAddI)
macro(GetAndAddL)
macro(GetAndSetI)
--- a/hotspot/src/share/vm/opto/compile.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/opto/compile.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -88,7 +88,27 @@
// Return the index at which m must be inserted (or already exists).
// The sort order is by the address of the ciMethod, with is_virtual as minor key.
-int Compile::intrinsic_insertion_index(ciMethod* m, bool is_virtual) {
+class IntrinsicDescPair {
+ private:
+ ciMethod* _m;
+ bool _is_virtual;
+ public:
+ IntrinsicDescPair(ciMethod* m, bool is_virtual) : _m(m), _is_virtual(is_virtual) {}
+ static int compare(IntrinsicDescPair* const& key, CallGenerator* const& elt) {
+ ciMethod* m= elt->method();
+ ciMethod* key_m = key->_m;
+ if (key_m < m) return -1;
+ else if (key_m > m) return 1;
+ else {
+ bool is_virtual = elt->is_virtual();
+ bool key_virtual = key->_is_virtual;
+ if (key_virtual < is_virtual) return -1;
+ else if (key_virtual > is_virtual) return 1;
+ else return 0;
+ }
+ }
+};
+int Compile::intrinsic_insertion_index(ciMethod* m, bool is_virtual, bool& found) {
#ifdef ASSERT
for (int i = 1; i < _intrinsics->length(); i++) {
CallGenerator* cg1 = _intrinsics->at(i-1);
@@ -99,63 +119,28 @@
"compiler intrinsics list must stay sorted");
}
#endif
- // Binary search sorted list, in decreasing intervals [lo, hi].
- int lo = 0, hi = _intrinsics->length()-1;
- while (lo <= hi) {
- int mid = (uint)(hi + lo) / 2;
- ciMethod* mid_m = _intrinsics->at(mid)->method();
- if (m < mid_m) {
- hi = mid-1;
- } else if (m > mid_m) {
- lo = mid+1;
- } else {
- // look at minor sort key
- bool mid_virt = _intrinsics->at(mid)->is_virtual();
- if (is_virtual < mid_virt) {
- hi = mid-1;
- } else if (is_virtual > mid_virt) {
- lo = mid+1;
- } else {
- return mid; // exact match
- }
- }
- }
- return lo; // inexact match
+ IntrinsicDescPair pair(m, is_virtual);
+ return _intrinsics->find_sorted<IntrinsicDescPair*, IntrinsicDescPair::compare>(&pair, found);
}
void Compile::register_intrinsic(CallGenerator* cg) {
if (_intrinsics == NULL) {
_intrinsics = new (comp_arena())GrowableArray<CallGenerator*>(comp_arena(), 60, 0, NULL);
}
- // This code is stolen from ciObjectFactory::insert.
- // Really, GrowableArray should have methods for
- // insert_at, remove_at, and binary_search.
int len = _intrinsics->length();
- int index = intrinsic_insertion_index(cg->method(), cg->is_virtual());
- if (index == len) {
- _intrinsics->append(cg);
- } else {
-#ifdef ASSERT
- CallGenerator* oldcg = _intrinsics->at(index);
- assert(oldcg->method() != cg->method() || oldcg->is_virtual() != cg->is_virtual(), "don't register twice");
-#endif
- _intrinsics->append(_intrinsics->at(len-1));
- int pos;
- for (pos = len-2; pos >= index; pos--) {
- _intrinsics->at_put(pos+1,_intrinsics->at(pos));
- }
- _intrinsics->at_put(index, cg);
- }
+ bool found = false;
+ int index = intrinsic_insertion_index(cg->method(), cg->is_virtual(), found);
+ assert(!found, "registering twice");
+ _intrinsics->insert_before(index, cg);
assert(find_intrinsic(cg->method(), cg->is_virtual()) == cg, "registration worked");
}
CallGenerator* Compile::find_intrinsic(ciMethod* m, bool is_virtual) {
assert(m->is_loaded(), "don't try this on unloaded methods");
if (_intrinsics != NULL) {
- int index = intrinsic_insertion_index(m, is_virtual);
- if (index < _intrinsics->length()
- && _intrinsics->at(index)->method() == m
- && _intrinsics->at(index)->is_virtual() == is_virtual) {
+ bool found = false;
+ int index = intrinsic_insertion_index(m, is_virtual, found);
+ if (found) {
return _intrinsics->at(index);
}
}
@@ -2801,6 +2786,14 @@
case Op_CompareAndSwapL:
case Op_CompareAndSwapP:
case Op_CompareAndSwapN:
+ case Op_WeakCompareAndSwapI:
+ case Op_WeakCompareAndSwapL:
+ case Op_WeakCompareAndSwapP:
+ case Op_WeakCompareAndSwapN:
+ case Op_CompareAndExchangeI:
+ case Op_CompareAndExchangeL:
+ case Op_CompareAndExchangeP:
+ case Op_CompareAndExchangeN:
case Op_GetAndAddI:
case Op_GetAndAddL:
case Op_GetAndSetI:
--- a/hotspot/src/share/vm/opto/compile.hpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/opto/compile.hpp Wed Mar 09 14:18:12 2016 +0100
@@ -1250,7 +1250,7 @@
// Intrinsic setup.
void register_library_intrinsics(); // initializer
CallGenerator* make_vm_intrinsic(ciMethod* m, bool is_virtual); // constructor
- int intrinsic_insertion_index(ciMethod* m, bool is_virtual); // helper
+ int intrinsic_insertion_index(ciMethod* m, bool is_virtual, bool& found); // helper
CallGenerator* find_intrinsic(ciMethod* m, bool is_virtual); // query fn
void register_intrinsic(CallGenerator* cg); // update fn
--- a/hotspot/src/share/vm/opto/escape.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/opto/escape.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -490,6 +490,8 @@
}
break;
}
+ case Op_CompareAndExchangeP:
+ case Op_CompareAndExchangeN:
case Op_GetAndSetP:
case Op_GetAndSetN: {
add_objload_to_connection_graph(n, delayed_worklist);
@@ -499,6 +501,8 @@
case Op_StoreN:
case Op_StoreNKlass:
case Op_StorePConditional:
+ case Op_WeakCompareAndSwapP:
+ case Op_WeakCompareAndSwapN:
case Op_CompareAndSwapP:
case Op_CompareAndSwapN: {
Node* adr = n->in(MemNode::Address);
@@ -698,8 +702,12 @@
case Op_StoreN:
case Op_StoreNKlass:
case Op_StorePConditional:
+ case Op_CompareAndExchangeP:
+ case Op_CompareAndExchangeN:
case Op_CompareAndSwapP:
case Op_CompareAndSwapN:
+ case Op_WeakCompareAndSwapP:
+ case Op_WeakCompareAndSwapN:
case Op_GetAndSetP:
case Op_GetAndSetN: {
Node* adr = n->in(MemNode::Address);
--- a/hotspot/src/share/vm/opto/graphKit.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/opto/graphKit.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -1179,8 +1179,10 @@
// Helper function to do a NULL pointer check. Returned value is
// the incoming address with NULL casted away. You are allowed to use the
// not-null value only if you are control dependent on the test.
+#ifndef PRODUCT
extern int explicit_null_checks_inserted,
explicit_null_checks_elided;
+#endif
Node* GraphKit::null_check_common(Node* value, BasicType type,
// optional arguments for variations:
bool assert_null,
@@ -1193,7 +1195,7 @@
value = cast_not_null(value); // Make it appear to be non-null (4962416).
return value;
}
- explicit_null_checks_inserted++;
+ NOT_PRODUCT(explicit_null_checks_inserted++);
// Construct NULL check
Node *chk = NULL;
@@ -1233,7 +1235,7 @@
// See if the type is contained in NULL_PTR.
// If so, then the value is already null.
if (t->higher_equal(TypePtr::NULL_PTR)) {
- explicit_null_checks_elided++;
+ NOT_PRODUCT(explicit_null_checks_elided++);
return value; // Elided null assert quickly!
}
} else {
@@ -1242,7 +1244,7 @@
// type. In other words, "value" was not-null.
if (t->meet(TypePtr::NULL_PTR) != t->remove_speculative()) {
// same as: if (!TypePtr::NULL_PTR->higher_equal(t)) ...
- explicit_null_checks_elided++;
+ NOT_PRODUCT(explicit_null_checks_elided++);
return value; // Elided null check quickly!
}
}
@@ -1282,7 +1284,7 @@
set_control(cfg);
Node *res = cast_not_null(value);
set_control(oldcontrol);
- explicit_null_checks_elided++;
+ NOT_PRODUCT(explicit_null_checks_elided++);
return res;
}
cfg = IfNode::up_one_dom(cfg, /*linear_only=*/ true);
@@ -1326,15 +1328,18 @@
IfNode* iff = create_and_map_if(control(), tst, ok_prob, COUNT_UNKNOWN);
Node* null_true = _gvn.transform( new IfFalseNode(iff));
set_control( _gvn.transform( new IfTrueNode(iff)));
- if (null_true == top())
+#ifndef PRODUCT
+ if (null_true == top()) {
explicit_null_checks_elided++;
+ }
+#endif
(*null_control) = null_true;
} else {
BuildCutout unless(this, tst, ok_prob);
// Check for optimizer eliding test at parse time
if (stopped()) {
// Failure not possible; do not bother making uncommon trap.
- explicit_null_checks_elided++;
+ NOT_PRODUCT(explicit_null_checks_elided++);
} else if (assert_null) {
uncommon_trap(reason,
Deoptimization::Action_make_not_entrant,
@@ -3149,6 +3154,19 @@
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) {
@@ -3840,7 +3858,7 @@
BasicType bt = T_BYTE;
if (UseConcMarkSweepGC && UseCondCardMark) {
- insert_mem_bar(Op_MemBarVolatile); // StoreLoad barrier
+ insert_store_load_for_barrier();
__ sync_kit(this);
}
@@ -4280,8 +4298,7 @@
__ if_then(card_val, BoolTest::ne, young_card); {
sync_kit(ideal);
- // Use Op_MemBarVolatile to achieve the effect of a StoreLoad barrier.
- insert_mem_bar(Op_MemBarVolatile, oop_store);
+ insert_store_load_for_barrier();
__ sync_kit(this);
Node* card_val_reload = __ load(__ ctrl(), card_adr, TypeInt::INT, T_BYTE, Compile::AliasIdxRaw);
--- a/hotspot/src/share/vm/opto/graphKit.hpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/opto/graphKit.hpp Wed Mar 09 14:18:12 2016 +0100
@@ -834,6 +834,7 @@
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/hotspot/src/share/vm/opto/ifnode.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/opto/ifnode.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -40,7 +40,9 @@
// Optimization - Graph Style
+#ifndef PRODUCT
extern int explicit_null_checks_elided;
+#endif
//=============================================================================
//------------------------------Value------------------------------------------
@@ -1504,24 +1506,28 @@
Node* prev_dom = this;
int op = Opcode();
// Search up the dominator tree for an If with an identical test
- while( dom->Opcode() != op || // Not same opcode?
+ while (dom->Opcode() != op || // Not same opcode?
dom->in(1) != in(1) || // Not same input 1?
(req() == 3 && dom->in(2) != in(2)) || // Not same input 2?
- prev_dom->in(0) != dom ) { // One path of test does not dominate?
- if( dist < 0 ) return NULL;
+ prev_dom->in(0) != dom) { // One path of test does not dominate?
+ if (dist < 0) return NULL;
dist--;
prev_dom = dom;
- dom = up_one_dom( dom );
- if( !dom ) return NULL;
+ dom = up_one_dom(dom);
+ if (!dom) return NULL;
}
// Check that we did not follow a loop back to ourselves
- if( this == dom )
+ if (this == dom) {
return NULL;
+ }
- if( dist > 2 ) // Add to count of NULL checks elided
+#ifndef PRODUCT
+ if (dist > 2) { // Add to count of NULL checks elided
explicit_null_checks_elided++;
+ }
+#endif
return prev_dom;
}
--- a/hotspot/src/share/vm/opto/lcm.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/opto/lcm.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -348,8 +348,10 @@
}
// ---- Found an implicit null check
+#ifndef PRODUCT
extern int implicit_null_checks;
implicit_null_checks++;
+#endif
if( is_decoden ) {
// Check if we need to hoist decodeHeapOop_not_null first.
--- a/hotspot/src/share/vm/opto/library_call.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/opto/library_call.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -243,7 +243,9 @@
// Generates the guards that check whether the result of
// Unsafe.getObject should be recorded in an SATB log buffer.
void insert_pre_barrier(Node* base_oop, Node* offset, Node* pre_val, bool need_mem_bar);
- bool inline_unsafe_access(bool is_native_ptr, bool is_store, BasicType type, bool is_volatile, bool is_unaligned);
+
+ typedef enum { Relaxed, Opaque, Volatile, Acquire, Release } AccessKind;
+ bool inline_unsafe_access(bool is_native_ptr, bool is_store, BasicType type, AccessKind kind, bool is_unaligned);
static bool klass_needs_init_guard(Node* kls);
bool inline_unsafe_allocate();
bool inline_unsafe_copyMemory();
@@ -273,9 +275,10 @@
JVMState* arraycopy_restore_alloc_state(AllocateArrayNode* alloc, int& saved_reexecute_sp);
void arraycopy_move_allocation_here(AllocateArrayNode* alloc, Node* dest, JVMState* saved_jvms, int saved_reexecute_sp);
- typedef enum { LS_xadd, LS_xchg, LS_cmpxchg } LoadStoreKind;
- bool inline_unsafe_load_store(BasicType type, LoadStoreKind kind);
- bool inline_unsafe_ordered_store(BasicType type);
+ typedef enum { LS_get_add, LS_get_set, LS_cmp_swap, LS_cmp_swap_weak, LS_cmp_exchange } LoadStoreKind;
+ MemNode::MemOrd access_kind_to_memord_LS(AccessKind access_kind, bool is_store);
+ MemNode::MemOrd access_kind_to_memord(AccessKind access_kind);
+ bool inline_unsafe_load_store(BasicType type, LoadStoreKind kind, AccessKind access_kind);
bool inline_unsafe_fence(vmIntrinsics::ID id);
bool inline_fp_conversions(vmIntrinsics::ID id);
bool inline_number_methods(vmIntrinsics::ID id);
@@ -552,86 +555,147 @@
case vmIntrinsics::_inflateStringC:
case vmIntrinsics::_inflateStringB: return inline_string_copy(!is_compress);
- case vmIntrinsics::_getObject: return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, !is_volatile, false);
- case vmIntrinsics::_getBoolean: return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, !is_volatile, false);
- case vmIntrinsics::_getByte: return inline_unsafe_access(!is_native_ptr, !is_store, T_BYTE, !is_volatile, false);
- case vmIntrinsics::_getShort: return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, !is_volatile, false);
- case vmIntrinsics::_getChar: return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, !is_volatile, false);
- case vmIntrinsics::_getInt: return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, !is_volatile, false);
- case vmIntrinsics::_getLong: return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, !is_volatile, false);
- case vmIntrinsics::_getFloat: return inline_unsafe_access(!is_native_ptr, !is_store, T_FLOAT, !is_volatile, false);
- case vmIntrinsics::_getDouble: return inline_unsafe_access(!is_native_ptr, !is_store, T_DOUBLE, !is_volatile, false);
- case vmIntrinsics::_putObject: return inline_unsafe_access(!is_native_ptr, is_store, T_OBJECT, !is_volatile, false);
- case vmIntrinsics::_putBoolean: return inline_unsafe_access(!is_native_ptr, is_store, T_BOOLEAN, !is_volatile, false);
- case vmIntrinsics::_putByte: return inline_unsafe_access(!is_native_ptr, is_store, T_BYTE, !is_volatile, false);
- case vmIntrinsics::_putShort: return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, !is_volatile, false);
- case vmIntrinsics::_putChar: return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, !is_volatile, false);
- case vmIntrinsics::_putInt: return inline_unsafe_access(!is_native_ptr, is_store, T_INT, !is_volatile, false);
- case vmIntrinsics::_putLong: return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, !is_volatile, false);
- case vmIntrinsics::_putFloat: return inline_unsafe_access(!is_native_ptr, is_store, T_FLOAT, !is_volatile, false);
- case vmIntrinsics::_putDouble: return inline_unsafe_access(!is_native_ptr, is_store, T_DOUBLE, !is_volatile, false);
-
- case vmIntrinsics::_getByte_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_BYTE, !is_volatile, false);
- case vmIntrinsics::_getShort_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_SHORT, !is_volatile, false);
- case vmIntrinsics::_getChar_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_CHAR, !is_volatile, false);
- case vmIntrinsics::_getInt_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_INT, !is_volatile, false);
- case vmIntrinsics::_getLong_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_LONG, !is_volatile, false);
- case vmIntrinsics::_getFloat_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_FLOAT, !is_volatile, false);
- case vmIntrinsics::_getDouble_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_DOUBLE, !is_volatile, false);
- case vmIntrinsics::_getAddress_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_ADDRESS, !is_volatile, false);
-
- case vmIntrinsics::_putByte_raw: return inline_unsafe_access( is_native_ptr, is_store, T_BYTE, !is_volatile, false);
- case vmIntrinsics::_putShort_raw: return inline_unsafe_access( is_native_ptr, is_store, T_SHORT, !is_volatile, false);
- case vmIntrinsics::_putChar_raw: return inline_unsafe_access( is_native_ptr, is_store, T_CHAR, !is_volatile, false);
- case vmIntrinsics::_putInt_raw: return inline_unsafe_access( is_native_ptr, is_store, T_INT, !is_volatile, false);
- case vmIntrinsics::_putLong_raw: return inline_unsafe_access( is_native_ptr, is_store, T_LONG, !is_volatile, false);
- case vmIntrinsics::_putFloat_raw: return inline_unsafe_access( is_native_ptr, is_store, T_FLOAT, !is_volatile, false);
- case vmIntrinsics::_putDouble_raw: return inline_unsafe_access( is_native_ptr, is_store, T_DOUBLE, !is_volatile, false);
- case vmIntrinsics::_putAddress_raw: return inline_unsafe_access( is_native_ptr, is_store, T_ADDRESS, !is_volatile, false);
-
- case vmIntrinsics::_getObjectVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, is_volatile, false);
- case vmIntrinsics::_getBooleanVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, is_volatile, false);
- case vmIntrinsics::_getByteVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_BYTE, is_volatile, false);
- case vmIntrinsics::_getShortVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, is_volatile, false);
- case vmIntrinsics::_getCharVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, is_volatile, false);
- case vmIntrinsics::_getIntVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, is_volatile, false);
- case vmIntrinsics::_getLongVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, is_volatile, false);
- case vmIntrinsics::_getFloatVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_FLOAT, is_volatile, false);
- case vmIntrinsics::_getDoubleVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_DOUBLE, is_volatile, false);
-
- case vmIntrinsics::_putObjectVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_OBJECT, is_volatile, false);
- case vmIntrinsics::_putBooleanVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_BOOLEAN, is_volatile, false);
- case vmIntrinsics::_putByteVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_BYTE, is_volatile, false);
- case vmIntrinsics::_putShortVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, is_volatile, false);
- case vmIntrinsics::_putCharVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, is_volatile, false);
- case vmIntrinsics::_putIntVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_INT, is_volatile, false);
- case vmIntrinsics::_putLongVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, is_volatile, false);
- case vmIntrinsics::_putFloatVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_FLOAT, is_volatile, false);
- case vmIntrinsics::_putDoubleVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_DOUBLE, is_volatile, false);
-
- case vmIntrinsics::_getShortUnaligned: return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, !is_volatile, true);
- case vmIntrinsics::_getCharUnaligned: return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, !is_volatile, true);
- case vmIntrinsics::_getIntUnaligned: return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, !is_volatile, true);
- case vmIntrinsics::_getLongUnaligned: return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, !is_volatile, true);
-
- case vmIntrinsics::_putShortUnaligned: return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, !is_volatile, true);
- case vmIntrinsics::_putCharUnaligned: return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, !is_volatile, true);
- case vmIntrinsics::_putIntUnaligned: return inline_unsafe_access(!is_native_ptr, is_store, T_INT, !is_volatile, true);
- case vmIntrinsics::_putLongUnaligned: return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, !is_volatile, true);
-
- case vmIntrinsics::_compareAndSwapObject: return inline_unsafe_load_store(T_OBJECT, LS_cmpxchg);
- case vmIntrinsics::_compareAndSwapInt: return inline_unsafe_load_store(T_INT, LS_cmpxchg);
- case vmIntrinsics::_compareAndSwapLong: return inline_unsafe_load_store(T_LONG, LS_cmpxchg);
-
- case vmIntrinsics::_putOrderedObject: return inline_unsafe_ordered_store(T_OBJECT);
- case vmIntrinsics::_putOrderedInt: return inline_unsafe_ordered_store(T_INT);
- case vmIntrinsics::_putOrderedLong: return inline_unsafe_ordered_store(T_LONG);
-
- case vmIntrinsics::_getAndAddInt: return inline_unsafe_load_store(T_INT, LS_xadd);
- case vmIntrinsics::_getAndAddLong: return inline_unsafe_load_store(T_LONG, LS_xadd);
- case vmIntrinsics::_getAndSetInt: return inline_unsafe_load_store(T_INT, LS_xchg);
- case vmIntrinsics::_getAndSetLong: return inline_unsafe_load_store(T_LONG, LS_xchg);
- case vmIntrinsics::_getAndSetObject: return inline_unsafe_load_store(T_OBJECT, LS_xchg);
+ case vmIntrinsics::_getObject: return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, Relaxed, false);
+ case vmIntrinsics::_getBoolean: return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, Relaxed, false);
+ case vmIntrinsics::_getByte: return inline_unsafe_access(!is_native_ptr, !is_store, T_BYTE, Relaxed, false);
+ case vmIntrinsics::_getShort: return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, Relaxed, false);
+ case vmIntrinsics::_getChar: return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, Relaxed, false);
+ case vmIntrinsics::_getInt: return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, Relaxed, false);
+ case vmIntrinsics::_getLong: return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, Relaxed, false);
+ case vmIntrinsics::_getFloat: return inline_unsafe_access(!is_native_ptr, !is_store, T_FLOAT, Relaxed, false);
+ case vmIntrinsics::_getDouble: return inline_unsafe_access(!is_native_ptr, !is_store, T_DOUBLE, Relaxed, false);
+
+ case vmIntrinsics::_putObject: return inline_unsafe_access(!is_native_ptr, is_store, T_OBJECT, Relaxed, false);
+ case vmIntrinsics::_putBoolean: return inline_unsafe_access(!is_native_ptr, is_store, T_BOOLEAN, Relaxed, false);
+ case vmIntrinsics::_putByte: return inline_unsafe_access(!is_native_ptr, is_store, T_BYTE, Relaxed, false);
+ case vmIntrinsics::_putShort: return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, Relaxed, false);
+ case vmIntrinsics::_putChar: return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, Relaxed, false);
+ case vmIntrinsics::_putInt: return inline_unsafe_access(!is_native_ptr, is_store, T_INT, Relaxed, false);
+ case vmIntrinsics::_putLong: return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, Relaxed, false);
+ case vmIntrinsics::_putFloat: return inline_unsafe_access(!is_native_ptr, is_store, T_FLOAT, Relaxed, false);
+ case vmIntrinsics::_putDouble: return inline_unsafe_access(!is_native_ptr, is_store, T_DOUBLE, Relaxed, false);
+
+ case vmIntrinsics::_getByte_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_BYTE, Relaxed, false);
+ case vmIntrinsics::_getShort_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_SHORT, Relaxed, false);
+ case vmIntrinsics::_getChar_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_CHAR, Relaxed, false);
+ case vmIntrinsics::_getInt_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_INT, Relaxed, false);
+ case vmIntrinsics::_getLong_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_LONG, Relaxed, false);
+ case vmIntrinsics::_getFloat_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_FLOAT, Relaxed, false);
+ case vmIntrinsics::_getDouble_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_DOUBLE, Relaxed, false);
+ case vmIntrinsics::_getAddress_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_ADDRESS, Relaxed, false);
+
+ case vmIntrinsics::_putByte_raw: return inline_unsafe_access( is_native_ptr, is_store, T_BYTE, Relaxed, false);
+ case vmIntrinsics::_putShort_raw: return inline_unsafe_access( is_native_ptr, is_store, T_SHORT, Relaxed, false);
+ case vmIntrinsics::_putChar_raw: return inline_unsafe_access( is_native_ptr, is_store, T_CHAR, Relaxed, false);
+ case vmIntrinsics::_putInt_raw: return inline_unsafe_access( is_native_ptr, is_store, T_INT, Relaxed, false);
+ case vmIntrinsics::_putLong_raw: return inline_unsafe_access( is_native_ptr, is_store, T_LONG, Relaxed, false);
+ case vmIntrinsics::_putFloat_raw: return inline_unsafe_access( is_native_ptr, is_store, T_FLOAT, Relaxed, false);
+ case vmIntrinsics::_putDouble_raw: return inline_unsafe_access( is_native_ptr, is_store, T_DOUBLE, Relaxed, false);
+ case vmIntrinsics::_putAddress_raw: return inline_unsafe_access( is_native_ptr, is_store, T_ADDRESS, Relaxed, false);
+
+ case vmIntrinsics::_getObjectVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, Volatile, false);
+ case vmIntrinsics::_getBooleanVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, Volatile, false);
+ case vmIntrinsics::_getByteVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_BYTE, Volatile, false);
+ case vmIntrinsics::_getShortVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, Volatile, false);
+ case vmIntrinsics::_getCharVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, Volatile, false);
+ case vmIntrinsics::_getIntVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, Volatile, false);
+ case vmIntrinsics::_getLongVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, Volatile, false);
+ case vmIntrinsics::_getFloatVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_FLOAT, Volatile, false);
+ case vmIntrinsics::_getDoubleVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_DOUBLE, Volatile, false);
+
+ case vmIntrinsics::_putObjectVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_OBJECT, Volatile, false);
+ case vmIntrinsics::_putBooleanVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_BOOLEAN, Volatile, false);
+ case vmIntrinsics::_putByteVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_BYTE, Volatile, false);
+ case vmIntrinsics::_putShortVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, Volatile, false);
+ case vmIntrinsics::_putCharVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, Volatile, false);
+ case vmIntrinsics::_putIntVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_INT, Volatile, false);
+ case vmIntrinsics::_putLongVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, Volatile, false);
+ case vmIntrinsics::_putFloatVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_FLOAT, Volatile, false);
+ case vmIntrinsics::_putDoubleVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_DOUBLE, Volatile, false);
+
+ case vmIntrinsics::_getShortUnaligned: return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, Relaxed, true);
+ case vmIntrinsics::_getCharUnaligned: return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, Relaxed, true);
+ case vmIntrinsics::_getIntUnaligned: return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, Relaxed, true);
+ case vmIntrinsics::_getLongUnaligned: return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, Relaxed, true);
+
+ case vmIntrinsics::_putShortUnaligned: return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, Relaxed, true);
+ case vmIntrinsics::_putCharUnaligned: return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, Relaxed, true);
+ case vmIntrinsics::_putIntUnaligned: return inline_unsafe_access(!is_native_ptr, is_store, T_INT, Relaxed, true);
+ case vmIntrinsics::_putLongUnaligned: return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, Relaxed, true);
+
+ case vmIntrinsics::_putOrderedObject: return inline_unsafe_access(!is_native_ptr, is_store, T_OBJECT, Release, false);
+ case vmIntrinsics::_putOrderedInt: return inline_unsafe_access(!is_native_ptr, is_store, T_INT, Release, false);
+ case vmIntrinsics::_putOrderedLong: return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, Release, false);
+
+ case vmIntrinsics::_getObjectAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, Acquire, false);
+ case vmIntrinsics::_getBooleanAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, Acquire, false);
+ case vmIntrinsics::_getByteAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_BYTE, Acquire, false);
+ case vmIntrinsics::_getShortAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, Acquire, false);
+ case vmIntrinsics::_getCharAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, Acquire, false);
+ case vmIntrinsics::_getIntAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, Acquire, false);
+ case vmIntrinsics::_getLongAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, Acquire, false);
+ case vmIntrinsics::_getFloatAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_FLOAT, Acquire, false);
+ case vmIntrinsics::_getDoubleAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_DOUBLE, Acquire, false);
+
+ case vmIntrinsics::_putObjectRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_OBJECT, Release, false);
+ case vmIntrinsics::_putBooleanRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_BOOLEAN, Release, false);
+ case vmIntrinsics::_putByteRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_BYTE, Release, false);
+ case vmIntrinsics::_putShortRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, Release, false);
+ case vmIntrinsics::_putCharRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, Release, false);
+ case vmIntrinsics::_putIntRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_INT, Release, false);
+ case vmIntrinsics::_putLongRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, Release, false);
+ case vmIntrinsics::_putFloatRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_FLOAT, Release, false);
+ case vmIntrinsics::_putDoubleRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_DOUBLE, Release, false);
+
+ case vmIntrinsics::_getObjectOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, Opaque, false);
+ case vmIntrinsics::_getBooleanOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, Opaque, false);
+ case vmIntrinsics::_getByteOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_BYTE, Opaque, false);
+ case vmIntrinsics::_getShortOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, Opaque, false);
+ case vmIntrinsics::_getCharOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, Opaque, false);
+ case vmIntrinsics::_getIntOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, Opaque, false);
+ case vmIntrinsics::_getLongOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, Opaque, false);
+ case vmIntrinsics::_getFloatOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_FLOAT, Opaque, false);
+ case vmIntrinsics::_getDoubleOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_DOUBLE, Opaque, false);
+
+ case vmIntrinsics::_putObjectOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_OBJECT, Opaque, false);
+ case vmIntrinsics::_putBooleanOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_BOOLEAN, Opaque, false);
+ case vmIntrinsics::_putByteOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_BYTE, Opaque, false);
+ case vmIntrinsics::_putShortOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, Opaque, false);
+ case vmIntrinsics::_putCharOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, Opaque, false);
+ case vmIntrinsics::_putIntOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_INT, Opaque, false);
+ case vmIntrinsics::_putLongOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, Opaque, false);
+ case vmIntrinsics::_putFloatOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_FLOAT, Opaque, false);
+ case vmIntrinsics::_putDoubleOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_DOUBLE, Opaque, false);
+
+ case vmIntrinsics::_compareAndSwapObject: return inline_unsafe_load_store(T_OBJECT, LS_cmp_swap, Volatile);
+ case vmIntrinsics::_compareAndSwapInt: return inline_unsafe_load_store(T_INT, LS_cmp_swap, Volatile);
+ case vmIntrinsics::_compareAndSwapLong: return inline_unsafe_load_store(T_LONG, LS_cmp_swap, Volatile);
+
+ case vmIntrinsics::_weakCompareAndSwapObject: return inline_unsafe_load_store(T_OBJECT, LS_cmp_swap_weak, Relaxed);
+ case vmIntrinsics::_weakCompareAndSwapObjectAcquire: return inline_unsafe_load_store(T_OBJECT, LS_cmp_swap_weak, Acquire);
+ case vmIntrinsics::_weakCompareAndSwapObjectRelease: return inline_unsafe_load_store(T_OBJECT, LS_cmp_swap_weak, Release);
+ case vmIntrinsics::_weakCompareAndSwapInt: return inline_unsafe_load_store(T_INT, LS_cmp_swap_weak, Relaxed);
+ case vmIntrinsics::_weakCompareAndSwapIntAcquire: return inline_unsafe_load_store(T_INT, LS_cmp_swap_weak, Acquire);
+ case vmIntrinsics::_weakCompareAndSwapIntRelease: return inline_unsafe_load_store(T_INT, LS_cmp_swap_weak, Release);
+ case vmIntrinsics::_weakCompareAndSwapLong: return inline_unsafe_load_store(T_LONG, LS_cmp_swap_weak, Relaxed);
+ case vmIntrinsics::_weakCompareAndSwapLongAcquire: return inline_unsafe_load_store(T_LONG, LS_cmp_swap_weak, Acquire);
+ case vmIntrinsics::_weakCompareAndSwapLongRelease: return inline_unsafe_load_store(T_LONG, LS_cmp_swap_weak, Release);
+
+ case vmIntrinsics::_compareAndExchangeObjectVolatile: return inline_unsafe_load_store(T_OBJECT, LS_cmp_exchange, Volatile);
+ case vmIntrinsics::_compareAndExchangeObjectAcquire: return inline_unsafe_load_store(T_OBJECT, LS_cmp_exchange, Acquire);
+ case vmIntrinsics::_compareAndExchangeObjectRelease: return inline_unsafe_load_store(T_OBJECT, LS_cmp_exchange, Release);
+ case vmIntrinsics::_compareAndExchangeIntVolatile: return inline_unsafe_load_store(T_INT, LS_cmp_exchange, Volatile);
+ case vmIntrinsics::_compareAndExchangeIntAcquire: return inline_unsafe_load_store(T_INT, LS_cmp_exchange, Acquire);
+ case vmIntrinsics::_compareAndExchangeIntRelease: return inline_unsafe_load_store(T_INT, LS_cmp_exchange, Release);
+ case vmIntrinsics::_compareAndExchangeLongVolatile: return inline_unsafe_load_store(T_LONG, LS_cmp_exchange, Volatile);
+ case vmIntrinsics::_compareAndExchangeLongAcquire: return inline_unsafe_load_store(T_LONG, LS_cmp_exchange, Acquire);
+ case vmIntrinsics::_compareAndExchangeLongRelease: return inline_unsafe_load_store(T_LONG, LS_cmp_exchange, Release);
+
+ case vmIntrinsics::_getAndAddInt: return inline_unsafe_load_store(T_INT, LS_get_add, Volatile);
+ case vmIntrinsics::_getAndAddLong: return inline_unsafe_load_store(T_LONG, LS_get_add, Volatile);
+ case vmIntrinsics::_getAndSetInt: return inline_unsafe_load_store(T_INT, LS_get_set, Volatile);
+ case vmIntrinsics::_getAndSetLong: return inline_unsafe_load_store(T_LONG, LS_get_set, Volatile);
+ case vmIntrinsics::_getAndSetObject: return inline_unsafe_load_store(T_OBJECT, LS_get_set, Volatile);
case vmIntrinsics::_loadFence:
case vmIntrinsics::_storeFence:
@@ -1581,6 +1645,13 @@
assert (type2aelembytes(T_CHAR) == type2aelembytes(T_BYTE)*2,
"sanity: byte[] and char[] scales agree");
+ // Bail when getChar over constants is requested: constant folding would
+ // reject folding mismatched char access over byte[]. A normal inlining for getChar
+ // Java method would constant fold nicely instead.
+ if (!is_store && value->is_Con() && index->is_Con()) {
+ return false;
+ }
+
Node* adr = array_element_address(value, index, T_CHAR);
if (is_store) {
(void) store_to_memory(control(), adr, ch, T_CHAR, TypeAryPtr::BYTES, MemNode::unordered,
@@ -2274,8 +2345,10 @@
return NULL;
}
-bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, BasicType type, bool is_volatile, bool unaligned) {
+bool LibraryCallKit::inline_unsafe_access(const bool is_native_ptr, bool is_store, const BasicType type, const AccessKind kind, const bool unaligned) {
if (callee()->is_static()) return false; // caller must have the capability!
+ guarantee(!is_store || kind != Acquire, "Acquire accesses can be produced only for loads");
+ guarantee( is_store || kind != Release, "Release accesses can be produced only for stores");
#ifndef PRODUCT
{
@@ -2364,7 +2437,42 @@
// the barriers get omitted and the unsafe reference begins to "pollute"
// the alias analysis of the rest of the graph, either Compile::can_alias
// or Compile::must_alias will throw a diagnostic assert.)
- bool need_mem_bar = (alias_type->adr_type() == TypeOopPtr::BOTTOM);
+ bool need_mem_bar;
+ switch (kind) {
+ case Relaxed:
+ need_mem_bar = (alias_type->adr_type() == TypeOopPtr::BOTTOM);
+ break;
+ case Opaque:
+ // Opaque uses CPUOrder membars for protection against code movement.
+ case Acquire:
+ case Release:
+ case Volatile:
+ need_mem_bar = true;
+ break;
+ default:
+ ShouldNotReachHere();
+ }
+
+ // Some accesses require access atomicity for all types, notably longs and doubles.
+ // When AlwaysAtomicAccesses is enabled, all accesses are atomic.
+ bool requires_atomic_access = false;
+ switch (kind) {
+ case Relaxed:
+ case Opaque:
+ requires_atomic_access = AlwaysAtomicAccesses;
+ break;
+ case Acquire:
+ case Release:
+ case Volatile:
+ requires_atomic_access = true;
+ break;
+ default:
+ ShouldNotReachHere();
+ }
+
+ // Figure out the memory ordering.
+ // Acquire/Release/Volatile accesses require marking the loads/stores with MemOrd
+ MemNode::MemOrd mo = access_kind_to_memord_LS(kind, is_store);
// If we are reading the value of the referent field of a Reference
// object (either by using Unsafe directly or through reflection)
@@ -2391,22 +2499,30 @@
// and it is not possible to fully distinguish unintended nulls
// from intended ones in this API.
- if (is_volatile) {
- // We need to emit leading and trailing CPU membars (see below) in
- // addition to memory membars when is_volatile. This is a little
- // too strong, but avoids the need to insert per-alias-type
- // volatile membars (for stores; compare Parse::do_put_xxx), which
- // we cannot do effectively here because we probably only have a
- // rough approximation of type.
- need_mem_bar = true;
- // For Stores, place a memory ordering barrier now.
- if (is_store) {
- insert_mem_bar(Op_MemBarRelease);
- } else {
- if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
- insert_mem_bar(Op_MemBarVolatile);
+ // We need to emit leading and trailing CPU membars (see below) in
+ // addition to memory membars for special access modes. This is a little
+ // too strong, but avoids the need to insert per-alias-type
+ // volatile membars (for stores; compare Parse::do_put_xxx), which
+ // we cannot do effectively here because we probably only have a
+ // rough approximation of type.
+
+ switch(kind) {
+ case Relaxed:
+ case Opaque:
+ case Acquire:
+ break;
+ case Release:
+ case Volatile:
+ if (is_store) {
+ insert_mem_bar(Op_MemBarRelease);
+ } else {
+ if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
+ insert_mem_bar(Op_MemBarVolatile);
+ }
}
- }
+ break;
+ default:
+ ShouldNotReachHere();
}
// Memory barrier to prevent normal and 'unsafe' accesses from
@@ -2422,10 +2538,12 @@
if (alias_type->element() != NULL || alias_type->field() != NULL) {
BasicType bt;
if (alias_type->element() != NULL) {
- const Type* element = alias_type->element();
+ // Use address type to get the element type. Alias type doesn't provide
+ // enough information (e.g., doesn't differentiate between byte[] and boolean[]).
+ const Type* element = adr_type->is_aryptr()->elem();
bt = element->isa_narrowoop() ? T_OBJECT : element->array_element_basic_type();
} else {
- bt = alias_type->field()->type()->basic_type();
+ bt = alias_type->field()->layout_type();
}
if (bt == T_ARRAY) {
// accessing an array field with getObject is not a mismatch
@@ -2442,7 +2560,7 @@
// Try to constant fold a load from a constant field
ciField* field = alias_type->field();
if (heap_base_oop != top() &&
- field != NULL && field->is_constant() && field->layout_type() == type) {
+ field != NULL && field->is_constant() && !mismatched) {
// final or stable field
const Type* con_type = Type::make_constant(alias_type->field(), heap_base_oop);
if (con_type != NULL) {
@@ -2450,10 +2568,9 @@
}
}
if (p == NULL) {
- MemNode::MemOrd mo = is_volatile ? MemNode::acquire : MemNode::unordered;
// To be valid, unsafe loads may depend on other conditions than
// the one that guards them: pin the Load node
- p = make_load(control(), adr, value_type, type, adr_type, mo, LoadNode::Pinned, is_volatile, unaligned, mismatched);
+ p = make_load(control(), adr, value_type, type, adr_type, mo, LoadNode::Pinned, requires_atomic_access, unaligned, mismatched);
// load value
switch (type) {
case T_BOOLEAN:
@@ -2467,7 +2584,9 @@
break;
case T_OBJECT:
if (need_read_barrier) {
- insert_pre_barrier(heap_base_oop, offset, p, !(is_volatile || need_mem_bar));
+ // We do not require a mem bar inside pre_barrier if need_mem_bar
+ // is set: the barriers would be emitted by us.
+ insert_pre_barrier(heap_base_oop, offset, p, !need_mem_bar);
}
break;
case T_ADDRESS:
@@ -2498,9 +2617,8 @@
break;
}
- MemNode::MemOrd mo = is_volatile ? MemNode::release : MemNode::unordered;
- if (type != T_OBJECT ) {
- (void) store_to_memory(control(), adr, val, type, adr_type, mo, is_volatile, unaligned, mismatched);
+ if (type != T_OBJECT) {
+ (void) store_to_memory(control(), adr, val, type, adr_type, mo, requires_atomic_access, unaligned, mismatched);
} else {
// Possibly an oop being stored to Java heap or native memory
if (!TypePtr::NULL_PTR->higher_equal(_gvn.type(heap_base_oop))) {
@@ -2521,7 +2639,7 @@
// Update IdealKit memory.
__ sync_kit(this);
} __ else_(); {
- __ store(__ ctrl(), adr, val, type, alias_type->index(), mo, is_volatile, mismatched);
+ __ store(__ ctrl(), adr, val, type, alias_type->index(), mo, requires_atomic_access, mismatched);
} __ end_if();
// Final sync IdealKit and GraphKit.
final_sync(ideal);
@@ -2530,14 +2648,23 @@
}
}
- if (is_volatile) {
- if (!is_store) {
- insert_mem_bar(Op_MemBarAcquire);
- } else {
- if (!support_IRIW_for_not_multiple_copy_atomic_cpu) {
- insert_mem_bar(Op_MemBarVolatile);
+ switch(kind) {
+ case Relaxed:
+ case Opaque:
+ case Release:
+ break;
+ case Acquire:
+ case Volatile:
+ if (!is_store) {
+ insert_mem_bar(Op_MemBarAcquire);
+ } else {
+ if (!support_IRIW_for_not_multiple_copy_atomic_cpu) {
+ insert_mem_bar(Op_MemBarVolatile);
+ }
}
- }
+ break;
+ default:
+ ShouldNotReachHere();
}
if (need_mem_bar) insert_mem_bar(Op_MemBarCPUOrder);
@@ -2548,21 +2675,52 @@
//----------------------------inline_unsafe_load_store----------------------------
// This method serves a couple of different customers (depending on LoadStoreKind):
//
-// LS_cmpxchg:
-// public final native boolean compareAndSwapObject(Object o, long offset, Object expected, Object x);
-// public final native boolean compareAndSwapInt( Object o, long offset, int expected, int x);
-// public final native boolean compareAndSwapLong( Object o, long offset, long expected, long x);
+// LS_cmp_swap:
+//
+// boolean compareAndSwapObject(Object o, long offset, Object expected, Object x);
+// boolean compareAndSwapInt( Object o, long offset, int expected, int x);
+// boolean compareAndSwapLong( Object o, long offset, long expected, long x);
+//
+// LS_cmp_swap_weak:
+//
+// boolean weakCompareAndSwapObject( Object o, long offset, Object expected, Object x);
+// boolean weakCompareAndSwapObjectAcquire(Object o, long offset, Object expected, Object x);
+// boolean weakCompareAndSwapObjectRelease(Object o, long offset, Object expected, Object x);
+//
+// boolean weakCompareAndSwapInt( Object o, long offset, int expected, int x);
+// boolean weakCompareAndSwapIntAcquire( Object o, long offset, int expected, int x);
+// boolean weakCompareAndSwapIntRelease( Object o, long offset, int expected, int x);
+//
+// boolean weakCompareAndSwapLong( Object o, long offset, long expected, long x);
+// boolean weakCompareAndSwapLongAcquire( Object o, long offset, long expected, long x);
+// boolean weakCompareAndSwapLongRelease( Object o, long offset, long expected, long x);
//
-// LS_xadd:
-// public int getAndAddInt( Object o, long offset, int delta)
-// public long getAndAddLong(Object o, long offset, long delta)
+// LS_cmp_exchange:
+//
+// Object compareAndExchangeObjectVolatile(Object o, long offset, Object expected, Object x);
+// Object compareAndExchangeObjectAcquire( Object o, long offset, Object expected, Object x);
+// Object compareAndExchangeObjectRelease( Object o, long offset, Object expected, Object x);
+//
+// Object compareAndExchangeIntVolatile( Object o, long offset, Object expected, Object x);
+// Object compareAndExchangeIntAcquire( Object o, long offset, Object expected, Object x);
+// Object compareAndExchangeIntRelease( Object o, long offset, Object expected, Object x);
//
-// LS_xchg:
+// Object compareAndExchangeLongVolatile( Object o, long offset, Object expected, Object x);
+// Object compareAndExchangeLongAcquire( Object o, long offset, Object expected, Object x);
+// Object compareAndExchangeLongRelease( Object o, long offset, Object expected, Object x);
+//
+// LS_get_add:
+//
+// int getAndAddInt( Object o, long offset, int delta)
+// long getAndAddLong(Object o, long offset, long delta)
+//
+// LS_get_set:
+//
// int getAndSet(Object o, long offset, int newValue)
// long getAndSet(Object o, long offset, long newValue)
// Object getAndSet(Object o, long offset, Object newValue)
//
-bool LibraryCallKit::inline_unsafe_load_store(BasicType type, LoadStoreKind kind) {
+bool LibraryCallKit::inline_unsafe_load_store(const BasicType type, const LoadStoreKind kind, const AccessKind access_kind) {
// This basic scheme here is the same as inline_unsafe_access, but
// differs in enough details that combining them would make the code
// overly confusing. (This is a true fact! I originally combined
@@ -2579,7 +2737,9 @@
// Check the signatures.
ciSignature* sig = callee()->signature();
rtype = sig->return_type()->basic_type();
- if (kind == LS_xadd || kind == LS_xchg) {
+ switch(kind) {
+ case LS_get_add:
+ case LS_get_set: {
// Check the signatures.
#ifdef ASSERT
assert(rtype == type, "get and set must return the expected type");
@@ -2588,7 +2748,10 @@
assert(sig->type_at(1)->basic_type() == T_LONG, "get and set offset is long");
assert(sig->type_at(2)->basic_type() == type, "get and set must take expected type as new value/delta");
#endif // ASSERT
- } else if (kind == LS_cmpxchg) {
+ break;
+ }
+ case LS_cmp_swap:
+ case LS_cmp_swap_weak: {
// Check the signatures.
#ifdef ASSERT
assert(rtype == T_BOOLEAN, "CAS must return boolean");
@@ -2596,8 +2759,20 @@
assert(sig->type_at(0)->basic_type() == T_OBJECT, "CAS base is object");
assert(sig->type_at(1)->basic_type() == T_LONG, "CAS offset is long");
#endif // ASSERT
- } else {
- ShouldNotReachHere();
+ break;
+ }
+ case LS_cmp_exchange: {
+ // Check the signatures.
+#ifdef ASSERT
+ assert(rtype == type, "CAS must return the expected type");
+ assert(sig->count() == 4, "CAS has 4 arguments");
+ assert(sig->type_at(0)->basic_type() == T_OBJECT, "CAS base is object");
+ assert(sig->type_at(1)->basic_type() == T_LONG, "CAS offset is long");
+#endif // ASSERT
+ break;
+ }
+ default:
+ ShouldNotReachHere();
}
}
#endif //PRODUCT
@@ -2610,19 +2785,29 @@
Node* offset = NULL;
Node* oldval = NULL;
Node* newval = NULL;
- if (kind == LS_cmpxchg) {
- const bool two_slot_type = type2size[type] == 2;
- receiver = argument(0); // type: oop
- base = argument(1); // type: oop
- offset = argument(2); // type: long
- oldval = argument(4); // type: oop, int, or long
- newval = argument(two_slot_type ? 6 : 5); // type: oop, int, or long
- } else if (kind == LS_xadd || kind == LS_xchg){
- receiver = argument(0); // type: oop
- base = argument(1); // type: oop
- offset = argument(2); // type: long
- oldval = NULL;
- newval = argument(4); // type: oop, int, or long
+ switch(kind) {
+ case LS_cmp_swap:
+ case LS_cmp_swap_weak:
+ case LS_cmp_exchange: {
+ const bool two_slot_type = type2size[type] == 2;
+ receiver = argument(0); // type: oop
+ base = argument(1); // type: oop
+ offset = argument(2); // type: long
+ oldval = argument(4); // type: oop, int, or long
+ newval = argument(two_slot_type ? 6 : 5); // type: oop, int, or long
+ break;
+ }
+ case LS_get_add:
+ case LS_get_set: {
+ receiver = argument(0); // type: oop
+ base = argument(1); // type: oop
+ offset = argument(2); // type: long
+ oldval = NULL;
+ newval = argument(4); // type: oop, int, or long
+ break;
+ }
+ default:
+ ShouldNotReachHere();
}
// Null check receiver.
@@ -2647,11 +2832,23 @@
Compile::AliasType* alias_type = C->alias_type(adr_type);
assert(alias_type->index() != Compile::AliasIdxBot, "no bare pointers here");
- if (kind == LS_xchg && type == T_OBJECT) {
- const TypeOopPtr* tjp = sharpen_unsafe_type(alias_type, adr_type);
- if (tjp != NULL) {
- value_type = tjp;
+ switch (kind) {
+ case LS_get_set:
+ case LS_cmp_exchange: {
+ if (type == T_OBJECT) {
+ const TypeOopPtr* tjp = sharpen_unsafe_type(alias_type, adr_type);
+ if (tjp != NULL) {
+ value_type = tjp;
+ }
+ }
+ break;
}
+ case LS_cmp_swap:
+ case LS_cmp_swap_weak:
+ case LS_get_add:
+ break;
+ default:
+ ShouldNotReachHere();
}
int alias_idx = C->get_alias_index(adr_type);
@@ -2661,9 +2858,22 @@
// into actual barriers on most machines, but we still need rest of
// compiler to respect ordering.
- insert_mem_bar(Op_MemBarRelease);
+ switch (access_kind) {
+ case Relaxed:
+ case Acquire:
+ break;
+ case Release:
+ case Volatile:
+ insert_mem_bar(Op_MemBarRelease);
+ break;
+ default:
+ ShouldNotReachHere();
+ }
insert_mem_bar(Op_MemBarCPUOrder);
+ // Figure out the memory ordering.
+ MemNode::MemOrd mo = access_kind_to_memord(access_kind);
+
// 4984716: MemBars must be inserted before this
// memory node in order to avoid a false
// dependency which will confuse the scheduler.
@@ -2674,25 +2884,45 @@
Node* load_store = NULL;
switch(type) {
case T_INT:
- if (kind == LS_xadd) {
- load_store = _gvn.transform(new GetAndAddINode(control(), mem, adr, newval, adr_type));
- } else if (kind == LS_xchg) {
- load_store = _gvn.transform(new GetAndSetINode(control(), mem, adr, newval, adr_type));
- } else if (kind == LS_cmpxchg) {
- load_store = _gvn.transform(new CompareAndSwapINode(control(), mem, adr, newval, oldval));
- } else {
- ShouldNotReachHere();
+ switch(kind) {
+ case LS_get_add:
+ load_store = _gvn.transform(new GetAndAddINode(control(), mem, adr, newval, adr_type));
+ break;
+ case LS_get_set:
+ load_store = _gvn.transform(new GetAndSetINode(control(), mem, adr, newval, adr_type));
+ break;
+ case LS_cmp_swap_weak:
+ load_store = _gvn.transform(new WeakCompareAndSwapINode(control(), mem, adr, newval, oldval, mo));
+ break;
+ case LS_cmp_swap:
+ load_store = _gvn.transform(new CompareAndSwapINode(control(), mem, adr, newval, oldval, mo));
+ break;
+ case LS_cmp_exchange:
+ load_store = _gvn.transform(new CompareAndExchangeINode(control(), mem, adr, newval, oldval, adr_type, mo));
+ break;
+ default:
+ ShouldNotReachHere();
}
break;
case T_LONG:
- if (kind == LS_xadd) {
- load_store = _gvn.transform(new GetAndAddLNode(control(), mem, adr, newval, adr_type));
- } else if (kind == LS_xchg) {
- load_store = _gvn.transform(new GetAndSetLNode(control(), mem, adr, newval, adr_type));
- } else if (kind == LS_cmpxchg) {
- load_store = _gvn.transform(new CompareAndSwapLNode(control(), mem, adr, newval, oldval));
- } else {
- ShouldNotReachHere();
+ switch(kind) {
+ case LS_get_add:
+ load_store = _gvn.transform(new GetAndAddLNode(control(), mem, adr, newval, adr_type));
+ break;
+ case LS_get_set:
+ load_store = _gvn.transform(new GetAndSetLNode(control(), mem, adr, newval, adr_type));
+ break;
+ case LS_cmp_swap_weak:
+ load_store = _gvn.transform(new WeakCompareAndSwapLNode(control(), mem, adr, newval, oldval, mo));
+ break;
+ case LS_cmp_swap:
+ load_store = _gvn.transform(new CompareAndSwapLNode(control(), mem, adr, newval, oldval, mo));
+ break;
+ case LS_cmp_exchange:
+ load_store = _gvn.transform(new CompareAndExchangeLNode(control(), mem, adr, newval, oldval, adr_type, mo));
+ break;
+ default:
+ ShouldNotReachHere();
}
break;
case T_OBJECT:
@@ -2703,65 +2933,109 @@
newval = _gvn.makecon(TypePtr::NULL_PTR);
// Reference stores need a store barrier.
- if (kind == LS_xchg) {
- // If pre-barrier must execute before the oop store, old value will require do_load here.
- if (!can_move_pre_barrier()) {
- pre_barrier(true /* do_load*/,
- control(), base, adr, alias_idx, newval, value_type->make_oopptr(),
- NULL /* pre_val*/,
+ switch(kind) {
+ case LS_get_set: {
+ // If pre-barrier must execute before the oop store, old value will require do_load here.
+ if (!can_move_pre_barrier()) {
+ pre_barrier(true /* do_load*/,
+ control(), base, adr, alias_idx, newval, value_type->make_oopptr(),
+ NULL /* pre_val*/,
+ T_OBJECT);
+ } // Else move pre_barrier to use load_store value, see below.
+ break;
+ }
+ case LS_cmp_swap_weak:
+ case LS_cmp_swap:
+ case LS_cmp_exchange: {
+ // Same as for newval above:
+ if (_gvn.type(oldval) == TypePtr::NULL_PTR) {
+ oldval = _gvn.makecon(TypePtr::NULL_PTR);
+ }
+ // The only known value which might get overwritten is oldval.
+ pre_barrier(false /* do_load */,
+ control(), NULL, NULL, max_juint, NULL, NULL,
+ oldval /* pre_val */,
T_OBJECT);
- } // Else move pre_barrier to use load_store value, see below.
- } else if (kind == LS_cmpxchg) {
- // Same as for newval above:
- if (_gvn.type(oldval) == TypePtr::NULL_PTR) {
- oldval = _gvn.makecon(TypePtr::NULL_PTR);
+ break;
}
- // The only known value which might get overwritten is oldval.
- pre_barrier(false /* do_load */,
- control(), NULL, NULL, max_juint, NULL, NULL,
- oldval /* pre_val */,
- T_OBJECT);
- } else {
- ShouldNotReachHere();
+ default:
+ ShouldNotReachHere();
}
#ifdef _LP64
if (adr->bottom_type()->is_ptr_to_narrowoop()) {
Node *newval_enc = _gvn.transform(new EncodePNode(newval, newval->bottom_type()->make_narrowoop()));
- if (kind == LS_xchg) {
- load_store = _gvn.transform(new GetAndSetNNode(control(), mem, adr,
- newval_enc, adr_type, value_type->make_narrowoop()));
- } else {
- assert(kind == LS_cmpxchg, "wrong LoadStore operation");
- Node *oldval_enc = _gvn.transform(new EncodePNode(oldval, oldval->bottom_type()->make_narrowoop()));
- load_store = _gvn.transform(new CompareAndSwapNNode(control(), mem, adr,
- newval_enc, oldval_enc));
+
+ switch(kind) {
+ case LS_get_set:
+ load_store = _gvn.transform(new GetAndSetNNode(control(), mem, adr, newval_enc, adr_type, value_type->make_narrowoop()));
+ break;
+ case LS_cmp_swap_weak: {
+ Node *oldval_enc = _gvn.transform(new EncodePNode(oldval, oldval->bottom_type()->make_narrowoop()));
+ load_store = _gvn.transform(new WeakCompareAndSwapNNode(control(), mem, adr, newval_enc, oldval_enc, mo));
+ break;
+ }
+ case LS_cmp_swap: {
+ Node *oldval_enc = _gvn.transform(new EncodePNode(oldval, oldval->bottom_type()->make_narrowoop()));
+ load_store = _gvn.transform(new CompareAndSwapNNode(control(), mem, adr, newval_enc, oldval_enc, mo));
+ break;
+ }
+ case LS_cmp_exchange: {
+ Node *oldval_enc = _gvn.transform(new EncodePNode(oldval, oldval->bottom_type()->make_narrowoop()));
+ load_store = _gvn.transform(new CompareAndExchangeNNode(control(), mem, adr, newval_enc, oldval_enc, adr_type, value_type->make_narrowoop(), mo));
+ break;
+ }
+ default:
+ ShouldNotReachHere();
}
} else
#endif
- {
- if (kind == LS_xchg) {
+ switch (kind) {
+ case LS_get_set:
load_store = _gvn.transform(new GetAndSetPNode(control(), mem, adr, newval, adr_type, value_type->is_oopptr()));
- } else {
- assert(kind == LS_cmpxchg, "wrong LoadStore operation");
- load_store = _gvn.transform(new CompareAndSwapPNode(control(), mem, adr, newval, oldval));
- }
+ break;
+ case LS_cmp_swap_weak:
+ load_store = _gvn.transform(new WeakCompareAndSwapPNode(control(), mem, adr, newval, oldval, mo));
+ break;
+ case LS_cmp_swap:
+ load_store = _gvn.transform(new CompareAndSwapPNode(control(), mem, adr, newval, oldval, mo));
+ break;
+ case LS_cmp_exchange:
+ load_store = _gvn.transform(new CompareAndExchangePNode(control(), mem, adr, newval, oldval, adr_type, value_type->is_oopptr(), mo));
+ break;
+ default:
+ ShouldNotReachHere();
}
- if (kind == LS_cmpxchg) {
- // Emit the post barrier only when the actual store happened.
- // This makes sense to check only for compareAndSet that can fail to set the value.
- // CAS success path is marked more likely since we anticipate this is a performance
- // critical path, while CAS failure path can use the penalty for going through unlikely
- // path as backoff. Which is still better than doing a store barrier there.
- IdealKit ideal(this);
- ideal.if_then(load_store, BoolTest::ne, ideal.ConI(0), PROB_STATIC_FREQUENT); {
- sync_kit(ideal);
- post_barrier(ideal.ctrl(), load_store, base, adr, alias_idx, newval, T_OBJECT, true);
- ideal.sync_kit(this);
- } ideal.end_if();
- final_sync(ideal);
- } else {
- post_barrier(control(), load_store, base, adr, alias_idx, newval, T_OBJECT, true);
+
+ // Emit the post barrier only when the actual store happened. This makes sense
+ // to check only for LS_cmp_* that can fail to set the value.
+ // LS_cmp_exchange does not produce any branches by default, so there is no
+ // boolean result to piggyback on. TODO: When we merge CompareAndSwap with
+ // CompareAndExchange and move branches here, it would make sense to conditionalize
+ // post_barriers for LS_cmp_exchange as well.
+ //
+ // CAS success path is marked more likely since we anticipate this is a performance
+ // critical path, while CAS failure path can use the penalty for going through unlikely
+ // path as backoff. Which is still better than doing a store barrier there.
+ switch (kind) {
+ case LS_get_set:
+ case LS_cmp_exchange: {
+ post_barrier(control(), load_store, base, adr, alias_idx, newval, T_OBJECT, true);
+ break;
+ }
+ case LS_cmp_swap_weak:
+ case LS_cmp_swap: {
+ IdealKit ideal(this);
+ ideal.if_then(load_store, BoolTest::ne, ideal.ConI(0), PROB_STATIC_FREQUENT); {
+ sync_kit(ideal);
+ post_barrier(ideal.ctrl(), load_store, base, adr, alias_idx, newval, T_OBJECT, true);
+ ideal.sync_kit(this);
+ } ideal.end_if();
+ final_sync(ideal);
+ break;
+ }
+ default:
+ ShouldNotReachHere();
}
break;
default:
@@ -2775,7 +3049,7 @@
Node* proj = _gvn.transform(new SCMemProjNode(load_store));
set_memory(proj, alias_idx);
- if (type == T_OBJECT && kind == LS_xchg) {
+ if (type == T_OBJECT && (kind == LS_get_set || kind == LS_cmp_exchange)) {
#ifdef _LP64
if (adr->bottom_type()->is_ptr_to_narrowoop()) {
load_store = _gvn.transform(new DecodeNNode(load_store, load_store->get_ptr_type()));
@@ -2794,74 +3068,52 @@
// Add the trailing membar surrounding the access
insert_mem_bar(Op_MemBarCPUOrder);
- insert_mem_bar(Op_MemBarAcquire);
+
+ switch (access_kind) {
+ case Relaxed:
+ case Release:
+ break; // do nothing
+ case Acquire:
+ case Volatile:
+ insert_mem_bar(Op_MemBarAcquire);
+ break;
+ default:
+ ShouldNotReachHere();
+ }
assert(type2size[load_store->bottom_type()->basic_type()] == type2size[rtype], "result type should match");
set_result(load_store);
return true;
}
-//----------------------------inline_unsafe_ordered_store----------------------
-// public native void Unsafe.putOrderedObject(Object o, long offset, Object x);
-// public native void Unsafe.putOrderedInt(Object o, long offset, int x);
-// public native void Unsafe.putOrderedLong(Object o, long offset, long x);
-bool LibraryCallKit::inline_unsafe_ordered_store(BasicType type) {
- // This is another variant of inline_unsafe_access, differing in
- // that it always issues store-store ("release") barrier and ensures
- // store-atomicity (which only matters for "long").
-
- if (callee()->is_static()) return false; // caller must have the capability!
-
-#ifndef PRODUCT
- {
- ResourceMark rm;
- // Check the signatures.
- ciSignature* sig = callee()->signature();
-#ifdef ASSERT
- BasicType rtype = sig->return_type()->basic_type();
- assert(rtype == T_VOID, "must return void");
- assert(sig->count() == 3, "has 3 arguments");
- assert(sig->type_at(0)->basic_type() == T_OBJECT, "base is object");
- assert(sig->type_at(1)->basic_type() == T_LONG, "offset is long");
-#endif // ASSERT
- }
-#endif //PRODUCT
-
- C->set_has_unsafe_access(true); // Mark eventual nmethod as "unsafe".
-
- // Get arguments:
- Node* receiver = argument(0); // type: oop
- Node* base = argument(1); // type: oop
- Node* offset = argument(2); // type: long
- Node* val = argument(4); // type: oop, int, or long
-
- // Null check receiver.
- receiver = null_check(receiver);
- if (stopped()) {
- return true;
- }
-
- // Build field offset expression.
- assert(Unsafe_field_offset_to_byte_offset(11) == 11, "fieldOffset must be byte-scaled");
- // 32-bit machines ignore the high half of long offsets
- offset = ConvL2X(offset);
- Node* adr = make_unsafe_address(base, offset);
- const TypePtr *adr_type = _gvn.type(adr)->isa_ptr();
- const Type *value_type = Type::get_const_basic_type(type);
- Compile::AliasType* alias_type = C->alias_type(adr_type);
-
- insert_mem_bar(Op_MemBarRelease);
- insert_mem_bar(Op_MemBarCPUOrder);
- // Ensure that the store is atomic for longs:
- const bool require_atomic_access = true;
- Node* store;
- if (type == T_OBJECT) // reference stores need a store barrier.
- store = store_oop_to_unknown(control(), base, adr, adr_type, val, type, MemNode::release);
- else {
- store = store_to_memory(control(), adr, val, type, adr_type, MemNode::release, require_atomic_access);
- }
- insert_mem_bar(Op_MemBarCPUOrder);
- return true;
+MemNode::MemOrd LibraryCallKit::access_kind_to_memord_LS(AccessKind kind, bool is_store) {
+ MemNode::MemOrd mo = MemNode::unset;
+ switch(kind) {
+ case Opaque:
+ case Relaxed: mo = MemNode::unordered; break;
+ case Acquire: mo = MemNode::acquire; break;
+ case Release: mo = MemNode::release; break;
+ case Volatile: mo = is_store ? MemNode::release : MemNode::acquire; break;
+ default:
+ ShouldNotReachHere();
+ }
+ guarantee(mo != MemNode::unset, "Should select memory ordering");
+ return mo;
+}
+
+MemNode::MemOrd LibraryCallKit::access_kind_to_memord(AccessKind kind) {
+ MemNode::MemOrd mo = MemNode::unset;
+ switch(kind) {
+ case Opaque:
+ case Relaxed: mo = MemNode::unordered; break;
+ case Acquire: mo = MemNode::acquire; break;
+ case Release: mo = MemNode::release; break;
+ case Volatile: mo = MemNode::seqcst; break;
+ default:
+ ShouldNotReachHere();
+ }
+ guarantee(mo != MemNode::unset, "Should select memory ordering");
+ return mo;
}
bool LibraryCallKit::inline_unsafe_fence(vmIntrinsics::ID id) {
--- a/hotspot/src/share/vm/opto/loopTransform.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/opto/loopTransform.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -2417,6 +2417,14 @@
((bol->in(1)->Opcode() == Op_StorePConditional ) ||
(bol->in(1)->Opcode() == Op_StoreIConditional ) ||
(bol->in(1)->Opcode() == Op_StoreLConditional ) ||
+ (bol->in(1)->Opcode() == Op_CompareAndExchangeI ) ||
+ (bol->in(1)->Opcode() == Op_CompareAndExchangeL ) ||
+ (bol->in(1)->Opcode() == Op_CompareAndExchangeP ) ||
+ (bol->in(1)->Opcode() == Op_CompareAndExchangeN ) ||
+ (bol->in(1)->Opcode() == Op_WeakCompareAndSwapI ) ||
+ (bol->in(1)->Opcode() == Op_WeakCompareAndSwapL ) ||
+ (bol->in(1)->Opcode() == Op_WeakCompareAndSwapP ) ||
+ (bol->in(1)->Opcode() == Op_WeakCompareAndSwapN ) ||
(bol->in(1)->Opcode() == Op_CompareAndSwapI ) ||
(bol->in(1)->Opcode() == Op_CompareAndSwapL ) ||
(bol->in(1)->Opcode() == Op_CompareAndSwapP ) ||
--- a/hotspot/src/share/vm/opto/loopnode.hpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/opto/loopnode.hpp Wed Mar 09 14:18:12 2016 +0100
@@ -285,20 +285,29 @@
Node *incr() const { Node *tmp = cmp_node(); return (tmp && tmp->req()==3) ? tmp->in(1) : NULL; }
Node *limit() const { Node *tmp = cmp_node(); return (tmp && tmp->req()==3) ? tmp->in(2) : NULL; }
Node *stride() const { Node *tmp = incr (); return (tmp && tmp->req()==3) ? tmp->in(2) : NULL; }
- Node *phi() const { Node *tmp = incr (); return (tmp && tmp->req()==3) ? tmp->in(1) : NULL; }
Node *init_trip() const { Node *tmp = phi (); return (tmp && tmp->req()==3) ? tmp->in(1) : NULL; }
int stride_con() const;
bool stride_is_con() const { Node *tmp = stride (); return (tmp != NULL && tmp->is_Con()); }
BoolTest::mask test_trip() const { return in(TestValue)->as_Bool()->_test._test; }
+ PhiNode *phi() const {
+ Node *tmp = incr();
+ if (tmp && tmp->req() == 3) {
+ Node* phi = tmp->in(1);
+ if (phi->is_Phi()) {
+ return phi->as_Phi();
+ }
+ }
+ return NULL;
+ }
CountedLoopNode *loopnode() const {
// The CountedLoopNode that goes with this CountedLoopEndNode may
// have been optimized out by the IGVN so be cautious with the
// pattern matching on the graph
- if (phi() == NULL) {
+ PhiNode* iv_phi = phi();
+ if (iv_phi == NULL) {
return NULL;
}
- assert(phi()->is_Phi(), "should be PhiNode");
- Node *ln = phi()->in(0);
+ Node *ln = iv_phi->in(0);
if (ln->is_CountedLoop() && ln->as_CountedLoop()->loopexit() == this) {
return (CountedLoopNode*)ln;
}
--- a/hotspot/src/share/vm/opto/macroArrayCopy.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/opto/macroArrayCopy.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -880,8 +880,14 @@
Node* sptr = basic_plus_adr(src, src_off);
Node* dptr = basic_plus_adr(dest, dest_off);
uint alias_idx = C->get_alias_index(adr_type);
- Node* sval = transform_later(LoadNode::make(_igvn, *ctrl, (*mem)->memory_at(alias_idx), sptr, adr_type, TypeInt::INT, T_INT, MemNode::unordered));
- Node* st = transform_later(StoreNode::make(_igvn, *ctrl, (*mem)->memory_at(alias_idx), dptr, adr_type, sval, T_INT, MemNode::unordered));
+ bool is_mismatched = (basic_elem_type != T_INT);
+ Node* sval = transform_later(
+ LoadNode::make(_igvn, *ctrl, (*mem)->memory_at(alias_idx), sptr, adr_type,
+ TypeInt::INT, T_INT, MemNode::unordered, LoadNode::DependsOnlyOnTest,
+ false /*unaligned*/, is_mismatched));
+ Node* st = transform_later(
+ StoreNode::make(_igvn, *ctrl, (*mem)->memory_at(alias_idx), dptr, adr_type,
+ sval, T_INT, MemNode::unordered));
(*mem)->set_memory_at(alias_idx, st);
src_off += BytesPerInt;
dest_off += BytesPerInt;
--- a/hotspot/src/share/vm/opto/matcher.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/opto/matcher.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -2307,6 +2307,14 @@
case Op_StorePConditional:
case Op_StoreIConditional:
case Op_StoreLConditional:
+ case Op_CompareAndExchangeI:
+ case Op_CompareAndExchangeL:
+ case Op_CompareAndExchangeP:
+ case Op_CompareAndExchangeN:
+ case Op_WeakCompareAndSwapI:
+ case Op_WeakCompareAndSwapL:
+ case Op_WeakCompareAndSwapP:
+ case Op_WeakCompareAndSwapN:
case Op_CompareAndSwapI:
case Op_CompareAndSwapL:
case Op_CompareAndSwapP:
@@ -2407,8 +2415,10 @@
bool push_it = false;
if( proj->Opcode() == Op_IfTrue ) {
+#ifndef PRODUCT
extern int all_null_checks_found;
all_null_checks_found++;
+#endif
if( b->_test._test == BoolTest::ne ) {
push_it = true;
}
@@ -2522,6 +2532,14 @@
// that a monitor exit operation contains a serializing instruction.
if (xop == Op_MemBarVolatile ||
+ xop == Op_CompareAndExchangeI ||
+ xop == Op_CompareAndExchangeL ||
+ xop == Op_CompareAndExchangeP ||
+ xop == Op_CompareAndExchangeN ||
+ xop == Op_WeakCompareAndSwapL ||
+ xop == Op_WeakCompareAndSwapP ||
+ xop == Op_WeakCompareAndSwapN ||
+ xop == Op_WeakCompareAndSwapI ||
xop == Op_CompareAndSwapL ||
xop == Op_CompareAndSwapP ||
xop == Op_CompareAndSwapN ||
--- a/hotspot/src/share/vm/opto/memnode.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/opto/memnode.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -1582,6 +1582,21 @@
return NULL;
}
+static bool is_mismatched_access(ciConstant con, BasicType loadbt) {
+ BasicType conbt = con.basic_type();
+ switch (conbt) {
+ case T_BOOLEAN: conbt = T_BYTE; break;
+ case T_ARRAY: conbt = T_OBJECT; break;
+ }
+ switch (loadbt) {
+ case T_BOOLEAN: loadbt = T_BYTE; break;
+ case T_NARROWOOP: loadbt = T_OBJECT; break;
+ case T_ARRAY: loadbt = T_OBJECT; break;
+ case T_ADDRESS: loadbt = T_OBJECT; break;
+ }
+ return (conbt != loadbt);
+}
+
// Try to constant-fold a stable array element.
static const Type* fold_stable_ary_elem(const TypeAryPtr* ary, int off, BasicType loadbt) {
assert(ary->const_oop(), "array should be constant");
@@ -1590,10 +1605,12 @@
// Decode the results of GraphKit::array_element_address.
ciArray* aobj = ary->const_oop()->as_array();
ciConstant con = aobj->element_value_by_offset(off);
-
if (con.basic_type() != T_ILLEGAL && !con.is_null_or_zero()) {
+ bool is_mismatched = is_mismatched_access(con, loadbt);
+ assert(!is_mismatched, "conbt=%s; loadbt=%s", type2name(con.basic_type()), type2name(loadbt));
const Type* con_type = Type::make_from_constant(con);
- if (con_type != NULL) {
+ // Guard against erroneous constant folding.
+ if (!is_mismatched && con_type != NULL) {
if (con_type->isa_aryptr()) {
// Join with the array element type, in case it is also stable.
int dim = ary->stable_dimension();
@@ -1642,7 +1659,7 @@
const bool off_beyond_header = ((uint)off >= (uint)min_base_off);
// Try to constant-fold a stable array element.
- if (FoldStableValues && ary->is_stable() && ary->const_oop() != NULL) {
+ if (FoldStableValues && !is_mismatched_access() && ary->is_stable() && ary->const_oop() != NULL) {
// Make sure the reference is not into the header and the offset is constant
if (off_beyond_header && adr->is_AddP() && off != Type::OffsetBot) {
const Type* con_type = fold_stable_ary_elem(ary, off, memory_type());
--- a/hotspot/src/share/vm/opto/memnode.hpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/opto/memnode.hpp Wed Mar 09 14:18:12 2016 +0100
@@ -56,7 +56,9 @@
};
typedef enum { unordered = 0,
acquire, // Load has to acquire or be succeeded by MemBarAcquire.
- release // Store has to release or be preceded by MemBarRelease.
+ release, // Store has to release or be preceded by MemBarRelease.
+ seqcst, // LoadStore has to have both acquire and release semantics.
+ unset // The memory ordering is not set (used for testing)
} MemOrd;
protected:
MemNode( Node *c0, Node *c1, Node *c2, const TypePtr* at )
@@ -848,34 +850,121 @@
virtual uint ideal_reg() const { return Op_RegFlags; }
};
+class CompareAndSwapNode : public LoadStoreConditionalNode {
+private:
+ const MemNode::MemOrd _mem_ord;
+public:
+ CompareAndSwapNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex, MemNode::MemOrd mem_ord) : LoadStoreConditionalNode(c, mem, adr, val, ex), _mem_ord(mem_ord) {}
+ MemNode::MemOrd order() const {
+ return _mem_ord;
+ }
+};
+
+class CompareAndExchangeNode : public LoadStoreNode {
+private:
+ const MemNode::MemOrd _mem_ord;
+public:
+ enum {
+ ExpectedIn = MemNode::ValueIn+1 // One more input than MemNode
+ };
+ CompareAndExchangeNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex, MemNode::MemOrd mem_ord, const TypePtr* at, const Type* t) :
+ LoadStoreNode(c, mem, adr, val, at, t, 5), _mem_ord(mem_ord) {
+ init_req(ExpectedIn, ex );
+ }
+
+ MemNode::MemOrd order() const {
+ return _mem_ord;
+ }
+};
//------------------------------CompareAndSwapLNode---------------------------
-class CompareAndSwapLNode : public LoadStoreConditionalNode {
+class CompareAndSwapLNode : public CompareAndSwapNode {
public:
- CompareAndSwapLNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex) : LoadStoreConditionalNode(c, mem, adr, val, ex) { }
+ CompareAndSwapLNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex, MemNode::MemOrd mem_ord) : CompareAndSwapNode(c, mem, adr, val, ex, mem_ord) { }
virtual int Opcode() const;
};
//------------------------------CompareAndSwapINode---------------------------
-class CompareAndSwapINode : public LoadStoreConditionalNode {
+class CompareAndSwapINode : public CompareAndSwapNode {
public:
- CompareAndSwapINode( Node *c, Node *mem, Node *adr, Node *val, Node *ex) : LoadStoreConditionalNode(c, mem, adr, val, ex) { }
+ CompareAndSwapINode( Node *c, Node *mem, Node *adr, Node *val, Node *ex, MemNode::MemOrd mem_ord) : CompareAndSwapNode(c, mem, adr, val, ex, mem_ord) { }
virtual int Opcode() const;
};
//------------------------------CompareAndSwapPNode---------------------------
-class CompareAndSwapPNode : public LoadStoreConditionalNode {
+class CompareAndSwapPNode : public CompareAndSwapNode {
public:
- CompareAndSwapPNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex) : LoadStoreConditionalNode(c, mem, adr, val, ex) { }
+ CompareAndSwapPNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex, MemNode::MemOrd mem_ord) : CompareAndSwapNode(c, mem, adr, val, ex, mem_ord) { }
virtual int Opcode() const;
};
//------------------------------CompareAndSwapNNode---------------------------
-class CompareAndSwapNNode : public LoadStoreConditionalNode {
+class CompareAndSwapNNode : public CompareAndSwapNode {
+public:
+ CompareAndSwapNNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex, MemNode::MemOrd mem_ord) : CompareAndSwapNode(c, mem, adr, val, ex, mem_ord) { }
+ virtual int Opcode() const;
+};
+
+
+//------------------------------WeakCompareAndSwapLNode---------------------------
+class WeakCompareAndSwapLNode : public CompareAndSwapNode {
+public:
+ WeakCompareAndSwapLNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex, MemNode::MemOrd mem_ord) : CompareAndSwapNode(c, mem, adr, val, ex, mem_ord) { }
+ virtual int Opcode() const;
+};
+
+
+//------------------------------WeakCompareAndSwapINode---------------------------
+class WeakCompareAndSwapINode : public CompareAndSwapNode {
+public:
+ WeakCompareAndSwapINode( Node *c, Node *mem, Node *adr, Node *val, Node *ex, MemNode::MemOrd mem_ord) : CompareAndSwapNode(c, mem, adr, val, ex, mem_ord) { }
+ virtual int Opcode() const;
+};
+
+
+//------------------------------WeakCompareAndSwapPNode---------------------------
+class WeakCompareAndSwapPNode : public CompareAndSwapNode {
public:
- CompareAndSwapNNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex) : LoadStoreConditionalNode(c, mem, adr, val, ex) { }
+ WeakCompareAndSwapPNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex, MemNode::MemOrd mem_ord) : CompareAndSwapNode(c, mem, adr, val, ex, mem_ord) { }
+ virtual int Opcode() const;
+};
+
+//------------------------------WeakCompareAndSwapNNode---------------------------
+class WeakCompareAndSwapNNode : public CompareAndSwapNode {
+public:
+ WeakCompareAndSwapNNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex, MemNode::MemOrd mem_ord) : CompareAndSwapNode(c, mem, adr, val, ex, mem_ord) { }
+ virtual int Opcode() const;
+};
+
+//------------------------------CompareAndExchangeLNode---------------------------
+class CompareAndExchangeLNode : public CompareAndExchangeNode {
+public:
+ CompareAndExchangeLNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex, const TypePtr* at, MemNode::MemOrd mem_ord) : CompareAndExchangeNode(c, mem, adr, val, ex, mem_ord, at, TypeLong::LONG) { }
+ virtual int Opcode() const;
+};
+
+
+//------------------------------CompareAndExchangeINode---------------------------
+class CompareAndExchangeINode : public CompareAndExchangeNode {
+public:
+ CompareAndExchangeINode( Node *c, Node *mem, Node *adr, Node *val, Node *ex, const TypePtr* at, MemNode::MemOrd mem_ord) : CompareAndExchangeNode(c, mem, adr, val, ex, mem_ord, at, TypeInt::INT) { }
+ virtual int Opcode() const;
+};
+
+
+//------------------------------CompareAndExchangePNode---------------------------
+class CompareAndExchangePNode : public CompareAndExchangeNode {
+public:
+ CompareAndExchangePNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex, const TypePtr* at, const Type* t, MemNode::MemOrd mem_ord) : CompareAndExchangeNode(c, mem, adr, val, ex, mem_ord, at, t) { }
+ virtual int Opcode() const;
+};
+
+//------------------------------CompareAndExchangeNNode---------------------------
+class CompareAndExchangeNNode : public CompareAndExchangeNode {
+public:
+ CompareAndExchangeNNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex, const TypePtr* at, const Type* t, MemNode::MemOrd mem_ord) : CompareAndExchangeNode(c, mem, adr, val, ex, mem_ord, at, t) { }
virtual int Opcode() const;
};
--- a/hotspot/src/share/vm/opto/node.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/opto/node.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -576,17 +576,11 @@
//------------------------------~Node------------------------------------------
// Fancy destructor; eagerly attempt to reclaim Node numberings and storage
-extern int reclaim_idx ;
-extern int reclaim_in ;
-extern int reclaim_node;
void Node::destruct() {
// Eagerly reclaim unique Node numberings
Compile* compile = Compile::current();
if ((uint)_idx+1 == compile->unique()) {
compile->set_unique(compile->unique()-1);
-#ifdef ASSERT
- reclaim_idx++;
-#endif
}
// Clear debug info:
Node_Notes* nn = compile->node_notes_at(_idx);
@@ -604,43 +598,25 @@
int out_edge_size = _outmax*sizeof(void*);
char *edge_end = ((char*)_in) + edge_size;
char *out_array = (char*)(_out == NO_OUT_ARRAY? NULL: _out);
- char *out_edge_end = out_array + out_edge_size;
int node_size = size_of();
// Free the output edge array
if (out_edge_size > 0) {
-#ifdef ASSERT
- if( out_edge_end == compile->node_arena()->hwm() )
- reclaim_in += out_edge_size; // count reclaimed out edges with in edges
-#endif
compile->node_arena()->Afree(out_array, out_edge_size);
}
// Free the input edge array and the node itself
if( edge_end == (char*)this ) {
-#ifdef ASSERT
- if( edge_end+node_size == compile->node_arena()->hwm() ) {
- reclaim_in += edge_size;
- reclaim_node+= node_size;
- }
-#else
// It was; free the input array and object all in one hit
+#ifndef ASSERT
compile->node_arena()->Afree(_in,edge_size+node_size);
#endif
} else {
-
// Free just the input array
-#ifdef ASSERT
- if( edge_end == compile->node_arena()->hwm() )
- reclaim_in += edge_size;
-#endif
compile->node_arena()->Afree(_in,edge_size);
// Free just the object
-#ifdef ASSERT
- if( ((char*)this) + node_size == compile->node_arena()->hwm() )
- reclaim_node+= node_size;
-#else
+#ifndef ASSERT
compile->node_arena()->Afree(this,node_size);
#endif
}
--- a/hotspot/src/share/vm/opto/node.hpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/opto/node.hpp Wed Mar 09 14:18:12 2016 +0100
@@ -60,6 +60,8 @@
class CodeBuffer;
class ConstraintCastNode;
class ConNode;
+class CompareAndSwapNode;
+class CompareAndExchangeNode;
class CountedLoopNode;
class CountedLoopEndNode;
class DecodeNarrowPtrNode;
@@ -679,6 +681,9 @@
DEFINE_CLASS_ID(Store, Mem, 1)
DEFINE_CLASS_ID(StoreVector, Store, 0)
DEFINE_CLASS_ID(LoadStore, Mem, 2)
+ DEFINE_CLASS_ID(LoadStoreConditional, LoadStore, 0)
+ DEFINE_CLASS_ID(CompareAndSwap, LoadStoreConditional, 0)
+ DEFINE_CLASS_ID(CompareAndExchangeNode, LoadStore, 1)
DEFINE_CLASS_ID(Region, Node, 5)
DEFINE_CLASS_ID(Loop, Region, 0)
--- a/hotspot/src/share/vm/opto/parse.hpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/opto/parse.hpp Wed Mar 09 14:18:12 2016 +0100
@@ -104,13 +104,6 @@
// For temporary (stack-allocated, stateless) ilts:
InlineTree(Compile* c, ciMethod* callee_method, JVMState* caller_jvms, float site_invoke_ratio, int max_inline_level);
- // InlineTree enum
- enum InlineStyle {
- Inline_do_not_inline = 0, //
- Inline_cha_is_monomorphic = 1, //
- Inline_type_profile_monomorphic = 2 //
- };
-
// See if it is OK to inline.
// The receiver is the inline tree for the caller.
//
@@ -349,9 +342,6 @@
Block* _block; // block currently getting parsed
ciBytecodeStream _iter; // stream of this method's bytecodes
- int _blocks_merged; // Progress meter: state merges from BB preds
- int _blocks_parsed; // Progress meter: BBs actually parsed
-
const FastLockNode* _synch_lock; // FastLockNode for synchronized method
#ifndef PRODUCT
--- a/hotspot/src/share/vm/opto/parse1.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/opto/parse1.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -45,6 +45,7 @@
// the most. Some of the non-static variables are needed in bytecodeInfo.cpp
// and eventually should be encapsulated in a proper class (gri 8/18/98).
+#ifndef PRODUCT
int nodes_created = 0;
int methods_parsed = 0;
int methods_seen = 0;
@@ -53,42 +54,42 @@
int explicit_null_checks_inserted = 0;
int explicit_null_checks_elided = 0;
-int all_null_checks_found = 0, implicit_null_checks = 0;
-int implicit_null_throws = 0;
+int all_null_checks_found = 0;
+int implicit_null_checks = 0;
-int reclaim_idx = 0;
-int reclaim_in = 0;
-int reclaim_node = 0;
-
-#ifndef PRODUCT
bool Parse::BytecodeParseHistogram::_initialized = false;
uint Parse::BytecodeParseHistogram::_bytecodes_parsed [Bytecodes::number_of_codes];
uint Parse::BytecodeParseHistogram::_nodes_constructed[Bytecodes::number_of_codes];
uint Parse::BytecodeParseHistogram::_nodes_transformed[Bytecodes::number_of_codes];
uint Parse::BytecodeParseHistogram::_new_values [Bytecodes::number_of_codes];
-#endif
//------------------------------print_statistics-------------------------------
-#ifndef PRODUCT
void Parse::print_statistics() {
tty->print_cr("--- Compiler Statistics ---");
tty->print("Methods seen: %d Methods parsed: %d", methods_seen, methods_parsed);
tty->print(" Nodes created: %d", nodes_created);
tty->cr();
- if (methods_seen != methods_parsed)
+ if (methods_seen != methods_parsed) {
tty->print_cr("Reasons for parse failures (NOT cumulative):");
+ }
tty->print_cr("Blocks parsed: %d Blocks seen: %d", blocks_parsed, blocks_seen);
- if( explicit_null_checks_inserted )
- tty->print_cr("%d original NULL checks - %d elided (%2d%%); optimizer leaves %d,", explicit_null_checks_inserted, explicit_null_checks_elided, (100*explicit_null_checks_elided)/explicit_null_checks_inserted, all_null_checks_found);
- if( all_null_checks_found )
+ if (explicit_null_checks_inserted) {
+ tty->print_cr("%d original NULL checks - %d elided (%2d%%); optimizer leaves %d,",
+ explicit_null_checks_inserted, explicit_null_checks_elided,
+ (100*explicit_null_checks_elided)/explicit_null_checks_inserted,
+ all_null_checks_found);
+ }
+ if (all_null_checks_found) {
tty->print_cr("%d made implicit (%2d%%)", implicit_null_checks,
(100*implicit_null_checks)/all_null_checks_found);
- if( implicit_null_throws )
+ }
+ if (SharedRuntime::_implicit_null_throws) {
tty->print_cr("%d implicit null exceptions at runtime",
- implicit_null_throws);
+ SharedRuntime::_implicit_null_throws);
+ }
- if( PrintParseStatistics && BytecodeParseHistogram::initialized() ) {
+ if (PrintParseStatistics && BytecodeParseHistogram::initialized()) {
BytecodeParseHistogram::print();
}
}
@@ -495,7 +496,7 @@
C->dependencies()->assert_evol_method(method());
}
- methods_seen++;
+ NOT_PRODUCT(methods_seen++);
// Do some special top-level things.
if (depth() == 1 && C->is_osr_compilation()) {
@@ -530,8 +531,8 @@
}
#endif
+#ifndef PRODUCT
methods_parsed++;
-#ifndef PRODUCT
// add method size here to guarantee that inlined methods are added too
if (CITime)
_total_bytes_compiled += method()->code_size();
@@ -652,7 +653,7 @@
continue;
}
- blocks_parsed++;
+ NOT_PRODUCT(blocks_parsed++);
progress = true;
if (block->is_loop_head() || block->is_handler() || has_irreducible && !block->is_ready()) {
@@ -712,9 +713,9 @@
}
}
+#ifndef PRODUCT
blocks_seen += block_count();
-#ifndef PRODUCT
// Make sure there are no half-processed blocks remaining.
// Every remaining unprocessed block is dead and may be ignored now.
for (int rpo = 0; rpo < block_count(); rpo++) {
@@ -1446,7 +1447,6 @@
assert(block()->is_merged(), "must be merged before being parsed");
block()->mark_parsed();
- ++_blocks_parsed;
// Set iterator to start of block.
iter().reset_to_bci(block()->start());
@@ -1596,9 +1596,6 @@
return;
}
- // Record that a new block has been merged.
- ++_blocks_merged;
-
// Make a region if we know there are multiple or unpredictable inputs.
// (Also, if this is a plain fall-through, we might see another region,
// which must not be allowed into this block's map.)
--- a/hotspot/src/share/vm/opto/parse2.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/opto/parse2.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -44,8 +44,10 @@
#include "runtime/deoptimization.hpp"
#include "runtime/sharedRuntime.hpp"
+#ifndef PRODUCT
extern int explicit_null_checks_inserted,
explicit_null_checks_elided;
+#endif
//---------------------------------array_load----------------------------------
void Parse::array_load(BasicType elem_type) {
@@ -997,7 +999,7 @@
return;
}
- explicit_null_checks_inserted++;
+ NOT_PRODUCT(explicit_null_checks_inserted++);
// Generate real control flow
Node *tst = _gvn.transform( new BoolNode( c, btest ) );
@@ -1013,7 +1015,7 @@
set_control(iftrue);
if (stopped()) { // Path is dead?
- explicit_null_checks_elided++;
+ NOT_PRODUCT(explicit_null_checks_elided++);
if (C->eliminate_boxing()) {
// Mark the successor block as parsed
branch_block->next_path_num();
@@ -1033,7 +1035,7 @@
set_control(iffalse);
if (stopped()) { // Path is dead?
- explicit_null_checks_elided++;
+ NOT_PRODUCT(explicit_null_checks_elided++);
if (C->eliminate_boxing()) {
// Mark the successor block as parsed
next_block->next_path_num();
--- a/hotspot/src/share/vm/opto/phaseX.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/opto/phaseX.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -1471,6 +1471,27 @@
}
}
+// Return counted loop Phi if as a counted loop exit condition, cmp
+// compares the the induction variable with n
+static PhiNode* countedloop_phi_from_cmp(CmpINode* cmp, Node* n) {
+ for (DUIterator_Fast imax, i = cmp->fast_outs(imax); i < imax; i++) {
+ Node* bol = cmp->fast_out(i);
+ for (DUIterator_Fast i2max, i2 = bol->fast_outs(i2max); i2 < i2max; i2++) {
+ Node* iff = bol->fast_out(i2);
+ if (iff->is_CountedLoopEnd()) {
+ CountedLoopEndNode* cle = iff->as_CountedLoopEnd();
+ if (cle->limit() == n) {
+ PhiNode* phi = cle->phi();
+ if (phi != NULL) {
+ return phi;
+ }
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
void PhaseIterGVN::add_users_to_worklist( Node *n ) {
add_users_to_worklist0(n);
@@ -1500,18 +1521,7 @@
Node* bol = use->raw_out(0);
if (bol->outcnt() > 0) {
Node* iff = bol->raw_out(0);
- if (use_op == Op_CmpI &&
- iff->is_CountedLoopEnd()) {
- CountedLoopEndNode* cle = iff->as_CountedLoopEnd();
- if (cle->limit() == n && cle->phi() != NULL) {
- // If an opaque node feeds into the limit condition of a
- // CountedLoop, we need to process the Phi node for the
- // induction variable when the opaque node is removed:
- // the range of values taken by the Phi is now known and
- // so its type is also known.
- _worklist.push(cle->phi());
- }
- } else if (iff->outcnt() == 2) {
+ if (iff->outcnt() == 2) {
// Look for the 'is_x2logic' pattern: "x ? : 0 : 1" and put the
// phi merging either 0 or 1 onto the worklist
Node* ifproj0 = iff->raw_out(0);
@@ -1526,6 +1536,15 @@
}
}
if (use_op == Op_CmpI) {
+ Node* phi = countedloop_phi_from_cmp((CmpINode*)use, n);
+ if (phi != NULL) {
+ // If an opaque node feeds into the limit condition of a
+ // CountedLoop, we need to process the Phi node for the
+ // induction variable when the opaque node is removed:
+ // the range of values taken by the Phi is now known and
+ // so its type is also known.
+ _worklist.push(phi);
+ }
Node* in1 = use->in(1);
for (uint i = 0; i < in1->outcnt(); i++) {
if (in1->raw_out(i)->Opcode() == Op_CastII) {
@@ -1714,6 +1733,15 @@
}
}
}
+ // If n is used in a counted loop exit condition then the type
+ // of the counted loop's Phi depends on the type of n. See
+ // PhiNode::Value().
+ if (m_op == Op_CmpI) {
+ PhiNode* phi = countedloop_phi_from_cmp((CmpINode*)m, n);
+ if (phi != NULL) {
+ worklist.push(phi);
+ }
+ }
}
}
}
--- a/hotspot/src/share/vm/opto/phaseX.hpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/opto/phaseX.hpp Wed Mar 09 14:18:12 2016 +0100
@@ -431,7 +431,7 @@
// Phase for iteratively performing local, pessimistic GVN-style optimizations.
// and ideal transformations on the graph.
class PhaseIterGVN : public PhaseGVN {
- private:
+private:
bool _delay_transform; // When true simply register the node when calling transform
// instead of actually optimizing it
--- a/hotspot/src/share/vm/prims/jvmtiCodeBlobEvents.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/prims/jvmtiCodeBlobEvents.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -173,9 +173,7 @@
_global_code_blobs = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<JvmtiCodeBlobDesc*>(50,true);
// iterate over the stub code descriptors and put them in the list first.
- int index = 0;
- StubCodeDesc* desc;
- while ((desc = StubCodeDesc::desc_for_index(++index)) != NULL) {
+ for (StubCodeDesc* desc = StubCodeDesc::first(); desc != NULL; desc = StubCodeDesc::next(desc)) {
_global_code_blobs->append(new JvmtiCodeBlobDesc(desc->name(), desc->begin(), desc->end()));
}
--- a/hotspot/src/share/vm/prims/unsafe.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/prims/unsafe.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -1117,6 +1117,44 @@
// JSR166 ------------------------------------------------------------------
+UNSAFE_ENTRY(jobject, Unsafe_CompareAndExchangeObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject e_h, jobject x_h))
+ UnsafeWrapper("Unsafe_CompareAndExchangeObject");
+ oop x = JNIHandles::resolve(x_h);
+ oop e = JNIHandles::resolve(e_h);
+ oop p = JNIHandles::resolve(obj);
+ HeapWord* addr = (HeapWord *)index_oop_from_field_offset_long(p, offset);
+ oop res = oopDesc::atomic_compare_exchange_oop(x, addr, e, true);
+ if (res == e)
+ update_barrier_set((void*)addr, x);
+ return JNIHandles::make_local(env, res);
+UNSAFE_END
+
+UNSAFE_ENTRY(jint, Unsafe_CompareAndExchangeInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x))
+ UnsafeWrapper("Unsafe_CompareAndExchangeInt");
+ oop p = JNIHandles::resolve(obj);
+ jint* addr = (jint *) index_oop_from_field_offset_long(p, offset);
+ return (jint)(Atomic::cmpxchg(x, addr, e));
+UNSAFE_END
+
+UNSAFE_ENTRY(jlong, Unsafe_CompareAndExchangeLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong e, jlong x))
+ UnsafeWrapper("Unsafe_CompareAndExchangeLong");
+ Handle p (THREAD, JNIHandles::resolve(obj));
+ jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset));
+#ifdef SUPPORTS_NATIVE_CX8
+ return (jlong)(Atomic::cmpxchg(x, addr, e));
+#else
+ if (VM_Version::supports_cx8())
+ return (jlong)(Atomic::cmpxchg(x, addr, e));
+ else {
+ MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag);
+ jlong val = Atomic::load(addr);
+ if (val == e)
+ Atomic::store(x, addr);
+ return val;
+ }
+#endif
+UNSAFE_END
+
UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject e_h, jobject x_h))
UnsafeWrapper("Unsafe_CompareAndSwapObject");
oop x = JNIHandles::resolve(x_h);
@@ -1384,6 +1422,10 @@
{CC "compareAndSwapObject", CC "(" OBJ "J" OBJ "" OBJ ")Z", FN_PTR(Unsafe_CompareAndSwapObject)},
{CC "compareAndSwapInt", CC "(" OBJ "J""I""I"")Z", FN_PTR(Unsafe_CompareAndSwapInt)},
{CC "compareAndSwapLong", CC "(" OBJ "J""J""J"")Z", FN_PTR(Unsafe_CompareAndSwapLong)},
+ {CC "compareAndExchangeObjectVolatile", CC "(" OBJ "J" OBJ "" OBJ ")" OBJ, FN_PTR(Unsafe_CompareAndExchangeObject)},
+ {CC "compareAndExchangeIntVolatile", CC "(" OBJ "J""I""I"")I", FN_PTR(Unsafe_CompareAndExchangeInt)},
+ {CC "compareAndExchangeLongVolatile", CC "(" OBJ "J""J""J"")J", FN_PTR(Unsafe_CompareAndExchangeLong)},
+
{CC "putOrderedObject", CC "(" OBJ "J" OBJ ")V", FN_PTR(Unsafe_SetOrderedObject)},
{CC "putOrderedInt", CC "(" OBJ "JI)V", FN_PTR(Unsafe_SetOrderedInt)},
{CC "putOrderedLong", CC "(" OBJ "JJ)V", FN_PTR(Unsafe_SetOrderedLong)},
--- a/hotspot/src/share/vm/prims/whitebox.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/prims/whitebox.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -34,6 +34,7 @@
#include "memory/metadataFactory.hpp"
#include "memory/metaspaceShared.hpp"
#include "memory/universe.hpp"
+#include "oops/constantPool.hpp"
#include "oops/oop.inline.hpp"
#include "prims/wbtestmethods/parserTests.hpp"
#include "prims/whitebox.hpp"
@@ -643,12 +644,12 @@
return (mh->queued_for_compilation() || nm != NULL);
WB_END
-WB_ENTRY(jboolean, WB_ShouldPrintAssembly(JNIEnv* env, jobject o, jobject method))
+WB_ENTRY(jboolean, WB_ShouldPrintAssembly(JNIEnv* env, jobject o, jobject method, jint comp_level))
jmethodID jmid = reflected_method_to_jmid(thread, env, method);
CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
- DirectiveSet* directive = DirectivesStack::getMatchingDirective(mh, CompileBroker::compiler(CompLevel_simple));
+ DirectiveSet* directive = DirectivesStack::getMatchingDirective(mh, CompileBroker::compiler(comp_level));
bool result = directive->PrintAssemblyOption;
DirectivesStack::release(directive);
@@ -1305,6 +1306,38 @@
return (jlong) ikh->constants();
WB_END
+WB_ENTRY(jint, WB_GetConstantPoolCacheIndexTag(JNIEnv* env, jobject wb))
+ return ConstantPool::CPCACHE_INDEX_TAG;
+WB_END
+
+WB_ENTRY(jint, WB_GetConstantPoolCacheLength(JNIEnv* env, jobject wb, jclass klass))
+ instanceKlassHandle ikh(java_lang_Class::as_Klass(JNIHandles::resolve(klass)));
+ ConstantPool* cp = ikh->constants();
+ if (cp->cache() == NULL) {
+ return -1;
+ }
+ return cp->cache()->length();
+WB_END
+
+WB_ENTRY(jint, WB_ConstantPoolRemapInstructionOperandFromCache(JNIEnv* env, jobject wb, jclass klass, jint index))
+ instanceKlassHandle ikh(java_lang_Class::as_Klass(JNIHandles::resolve(klass)));
+ ConstantPool* cp = ikh->constants();
+ if (cp->cache() == NULL) {
+ THROW_MSG_0(vmSymbols::java_lang_IllegalStateException(), "Constant pool does not have a cache");
+ }
+ jint cpci = index;
+ jint cpciTag = ConstantPool::CPCACHE_INDEX_TAG;
+ if (cpciTag > cpci || cpci >= cp->cache()->length() + cpciTag) {
+ THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Constant pool cache index is out of range");
+ }
+ jint cpi = cp->remap_instruction_operand_from_cache(cpci);
+ return cpi;
+WB_END
+
+WB_ENTRY(jint, WB_ConstantPoolEncodeIndyIndex(JNIEnv* env, jobject wb, jint index))
+ return ConstantPool::encode_invokedynamic_index(index);
+WB_END
+
WB_ENTRY(void, WB_ClearInlineCaches(JNIEnv* env, jobject wb))
VM_ClearICs clear_ics;
VMThread::execute(&clear_ics);
@@ -1523,8 +1556,8 @@
#endif // INCLUDE_NMT
{CC"deoptimizeFrames", CC"(Z)I", (void*)&WB_DeoptimizeFrames },
{CC"deoptimizeAll", CC"()V", (void*)&WB_DeoptimizeAll },
- {CC"deoptimizeMethod0", CC"(Ljava/lang/reflect/Executable;Z)I",
- (void*)&WB_DeoptimizeMethod },
+ {CC"deoptimizeMethod0", CC"(Ljava/lang/reflect/Executable;Z)I",
+ (void*)&WB_DeoptimizeMethod },
{CC"isMethodCompiled0", CC"(Ljava/lang/reflect/Executable;Z)Z",
(void*)&WB_IsMethodCompiled },
{CC"isMethodCompilable0", CC"(Ljava/lang/reflect/Executable;IZ)Z",
@@ -1559,7 +1592,7 @@
CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)I",
(void*)&WB_MatchesInline},
{CC"shouldPrintAssembly",
- CC"(Ljava/lang/reflect/Executable;)Z",
+ CC"(Ljava/lang/reflect/Executable;I)Z",
(void*)&WB_ShouldPrintAssembly},
{CC"isConstantVMFlag", CC"(Ljava/lang/String;)Z", (void*)&WB_IsConstantVMFlag},
@@ -1620,6 +1653,12 @@
{CC"isMonitorInflated0", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsMonitorInflated },
{CC"forceSafepoint", CC"()V", (void*)&WB_ForceSafepoint },
{CC"getConstantPool0", CC"(Ljava/lang/Class;)J", (void*)&WB_GetConstantPool },
+ {CC"getConstantPoolCacheIndexTag0", CC"()I", (void*)&WB_GetConstantPoolCacheIndexTag},
+ {CC"getConstantPoolCacheLength0", CC"(Ljava/lang/Class;)I", (void*)&WB_GetConstantPoolCacheLength},
+ {CC"remapInstructionOperandFromCPCache0",
+ CC"(Ljava/lang/Class;I)I", (void*)&WB_ConstantPoolRemapInstructionOperandFromCache},
+ {CC"encodeConstantPoolIndyIndex0",
+ CC"(I)I", (void*)&WB_ConstantPoolEncodeIndyIndex},
{CC"getMethodBooleanOption",
CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/Boolean;",
(void*)&WB_GetMethodBooleaneOption},
--- a/hotspot/src/share/vm/runtime/arguments.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -2318,6 +2318,17 @@
//===========================================================================================================
// Parsing of main arguments
+#if INCLUDE_JVMCI
+// Check consistency of jvmci vm argument settings.
+bool Arguments::check_jvmci_args_consistency() {
+ if (!EnableJVMCI && !JVMCIGlobals::check_jvmci_flags_are_consistent()) {
+ JVMCIGlobals::print_jvmci_args_inconsistency_error_message();
+ return false;
+ }
+ return true;
+}
+#endif //INCLUDE_JVMCI
+
// Check consistency of GC selection
bool Arguments::check_gc_consistency() {
// Ensure that the user has not selected conflicting sets
@@ -2414,6 +2425,9 @@
#endif
}
#if INCLUDE_JVMCI
+
+ status = status && check_jvmci_args_consistency();
+
if (EnableJVMCI) {
if (!ScavengeRootsInCode) {
warning("forcing ScavengeRootsInCode non-zero because JVMCI is enabled");
--- a/hotspot/src/share/vm/runtime/arguments.hpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/runtime/arguments.hpp Wed Mar 09 14:18:12 2016 +0100
@@ -505,7 +505,10 @@
static void set_gc_specific_flags();
static inline bool gc_selected(); // whether a gc has been selected
static void select_gc_ergonomically();
-
+#if INCLUDE_JVMCI
+ // Check consistency of jvmci vm argument settings.
+ static bool check_jvmci_args_consistency();
+#endif
// Check for consistency in the selection of the garbage collector.
static bool check_gc_consistency(); // Check user-selected gc
// Check consistency or otherwise of VM argument settings
--- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -33,9 +33,6 @@
#include "runtime/commandLineFlagConstraintsRuntime.hpp"
#include "runtime/os.hpp"
#include "utilities/macros.hpp"
-#if INCLUDE_JVMCI
-#include "jvmci/commandLineFlagConstraintsJVMCI.hpp"
-#endif
class CommandLineFlagConstraint_bool : public CommandLineFlagConstraint {
CommandLineFlagConstraintFunc_bool _constraint;
@@ -254,17 +251,6 @@
IGNORE_RANGE,
EMIT_CONSTRAINT_CHECK));
-#if INCLUDE_JVMCI
- emit_constraint_no(NULL JVMCI_FLAGS(EMIT_CONSTRAINT_DEVELOPER_FLAG,
- EMIT_CONSTRAINT_PD_DEVELOPER_FLAG,
- EMIT_CONSTRAINT_PRODUCT_FLAG,
- EMIT_CONSTRAINT_PD_PRODUCT_FLAG,
- EMIT_CONSTRAINT_DIAGNOSTIC_FLAG,
- EMIT_CONSTRAINT_EXPERIMENTAL_FLAG,
- EMIT_CONSTRAINT_NOTPRODUCT_FLAG,
- IGNORE_RANGE,
- EMIT_CONSTRAINT_CHECK));
-#endif // INCLUDE_JVMCI
#ifdef COMPILER1
emit_constraint_no(NULL C1_FLAGS(EMIT_CONSTRAINT_DEVELOPER_FLAG,
--- a/hotspot/src/share/vm/runtime/frame.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/runtime/frame.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -662,14 +662,14 @@
st->print("J %d%s %s ",
nm->compile_id(), (nm->is_osr_method() ? "%" : ""),
((nm->compiler() != NULL) ? nm->compiler()->name() : ""));
+ st->print("%s (%d bytes) @ " PTR_FORMAT " [" PTR_FORMAT "+" INTPTR_FORMAT "]",
+ buf, m->code_size(), p2i(_pc), p2i(_cb->code_begin()), _pc - _cb->code_begin());
#if INCLUDE_JVMCI
char* jvmciName = nm->jvmci_installed_code_name(buf, buflen);
if (jvmciName != NULL) {
st->print(" (%s)", jvmciName);
}
#endif
- st->print("%s (%d bytes) @ " PTR_FORMAT " [" PTR_FORMAT "+" INTPTR_FORMAT "]",
- buf, m->code_size(), p2i(_pc), p2i(_cb->code_begin()), _pc - _cb->code_begin());
} else {
st->print("J " PTR_FORMAT, p2i(pc()));
}
--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -1134,12 +1134,19 @@
MethodHandles::is_signature_polymorphic_intrinsic(id)) {
bc = MethodHandles::signature_polymorphic_intrinsic_bytecode(id);
- // Need to adjust invokehandle since inlining through signature-polymorphic
- // method happened.
- if (bc == Bytecodes::_invokehandle &&
- !MethodHandles::is_signature_polymorphic_method(attached_method())) {
- bc = attached_method->is_static() ? Bytecodes::_invokestatic
- : Bytecodes::_invokevirtual;
+ // Adjust invocation mode according to the attached method.
+ switch (bc) {
+ case Bytecodes::_invokeinterface:
+ if (!attached_method->method_holder()->is_interface()) {
+ bc = Bytecodes::_invokevirtual;
+ }
+ break;
+ case Bytecodes::_invokehandle:
+ if (!MethodHandles::is_signature_polymorphic_method(attached_method())) {
+ bc = attached_method->is_static() ? Bytecodes::_invokestatic
+ : Bytecodes::_invokevirtual;
+ }
+ break;
}
}
} else {
--- a/hotspot/src/share/vm/runtime/stubCodeGenerator.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/runtime/stubCodeGenerator.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -36,19 +36,13 @@
// Implementation of StubCodeDesc
StubCodeDesc* StubCodeDesc::_list = NULL;
-int StubCodeDesc::_count = 0;
bool StubCodeDesc::_frozen = false;
StubCodeDesc* StubCodeDesc::desc_for(address pc) {
StubCodeDesc* p = _list;
- while (p != NULL && !p->contains(pc)) p = p->_next;
- // p == NULL || p->contains(pc)
- return p;
-}
-
-StubCodeDesc* StubCodeDesc::desc_for_index(int index) {
- StubCodeDesc* p = _list;
- while (p != NULL && p->index() != index) p = p->_next;
+ while (p != NULL && !p->contains(pc)) {
+ p = p->_next;
+ }
return p;
}
@@ -73,43 +67,17 @@
// Implementation of StubCodeGenerator
StubCodeGenerator::StubCodeGenerator(CodeBuffer* code, bool print_code) {
- _masm = new MacroAssembler(code);
- _first_stub = _last_stub = NULL;
- _print_code = print_code;
-}
-
-extern "C" {
- static int compare_cdesc(const void* void_a, const void* void_b) {
- int ai = (*((StubCodeDesc**) void_a))->index();
- int bi = (*((StubCodeDesc**) void_b))->index();
- return ai - bi;
- }
+ _masm = new MacroAssembler(code );
+ _print_code = PrintStubCode || print_code;
}
StubCodeGenerator::~StubCodeGenerator() {
- if (PrintStubCode || _print_code) {
+ if (_print_code) {
CodeBuffer* cbuf = _masm->code();
CodeBlob* blob = CodeCache::find_blob_unsafe(cbuf->insts()->start());
if (blob != NULL) {
blob->set_strings(cbuf->strings());
}
- bool saw_first = false;
- StubCodeDesc* toprint[1000];
- int toprint_len = 0;
- for (StubCodeDesc* cdesc = _last_stub; cdesc != NULL; cdesc = cdesc->_next) {
- toprint[toprint_len++] = cdesc;
- if (cdesc == _first_stub) { saw_first = true; break; }
- }
- assert(toprint_len == 0 || saw_first, "must get both first & last");
- // Print in reverse order:
- qsort(toprint, toprint_len, sizeof(toprint[0]), compare_cdesc);
- for (int i = 0; i < toprint_len; i++) {
- StubCodeDesc* cdesc = toprint[i];
- cdesc->print();
- tty->cr();
- Disassembler::decode(cdesc->begin(), cdesc->end());
- tty->cr();
- }
}
}
@@ -118,9 +86,12 @@
}
void StubCodeGenerator::stub_epilog(StubCodeDesc* cdesc) {
- // default implementation - record the cdesc
- if (_first_stub == NULL) _first_stub = cdesc;
- _last_stub = cdesc;
+ if (_print_code) {
+ cdesc->print();
+ tty->cr();
+ Disassembler::decode(cdesc->begin(), cdesc->end());
+ tty->cr();
+ }
}
--- a/hotspot/src/share/vm/runtime/stubCodeGenerator.hpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/runtime/stubCodeGenerator.hpp Wed Mar 09 14:18:12 2016 +0100
@@ -39,13 +39,11 @@
class StubCodeDesc: public CHeapObj<mtCode> {
private:
static StubCodeDesc* _list; // the list of all descriptors
- static int _count; // length of list
static bool _frozen; // determines whether _list modifications are allowed
StubCodeDesc* _next; // the next element in the linked list
const char* _group; // the group to which the stub code belongs
const char* _name; // the name assigned to the stub code
- int _index; // serial number assigned to the stub
address _begin; // points to the first byte of the stub code (included)
address _end; // points to the first byte after the stub code (excluded)
@@ -64,8 +62,10 @@
friend class StubCodeGenerator;
public:
+ static StubCodeDesc* first() { return _list; }
+ static StubCodeDesc* next(StubCodeDesc* desc) { return desc->_next; }
+
static StubCodeDesc* desc_for(address pc); // returns the code descriptor for the code containing pc or NULL
- static StubCodeDesc* desc_for_index(int); // returns the code descriptor for the index or NULL
static const char* name_for(address pc); // returns the name of the code containing pc or NULL
StubCodeDesc(const char* group, const char* name, address begin, address end = NULL) {
@@ -74,7 +74,6 @@
_next = _list;
_group = group;
_name = name;
- _index = ++_count; // (never zero)
_begin = begin;
_end = end;
_list = this;
@@ -84,7 +83,6 @@
const char* group() const { return _group; }
const char* name() const { return _name; }
- int index() const { return _index; }
address begin() const { return _begin; }
address end() const { return _end; }
int size_in_bytes() const { return _end - _begin; }
@@ -97,13 +95,12 @@
// Provides utility functions.
class StubCodeGenerator: public StackObj {
+ private:
+ bool _print_code;
+
protected:
MacroAssembler* _masm;
- StubCodeDesc* _first_stub;
- StubCodeDesc* _last_stub;
- bool _print_code;
-
public:
StubCodeGenerator(CodeBuffer* code, bool print_code = false);
~StubCodeGenerator();
--- a/hotspot/src/share/vm/runtime/thread.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/runtime/thread.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -1009,9 +1009,9 @@
char java_runtime_name[128] = "";
char java_runtime_version[128] = "";
-// extract the JRE name from sun.misc.Version.java_runtime_name
+// extract the JRE name from java.lang.VersionProps.java_runtime_name
static const char* get_java_runtime_name(TRAPS) {
- Klass* k = SystemDictionary::find(vmSymbols::sun_misc_Version(),
+ Klass* k = SystemDictionary::find(vmSymbols::java_lang_VersionProps(),
Handle(), Handle(), CHECK_AND_CLEAR_NULL);
fieldDescriptor fd;
bool found = k != NULL &&
@@ -1031,9 +1031,9 @@
}
}
-// extract the JRE version from sun.misc.Version.java_runtime_version
+// extract the JRE version from java.lang.VersionProps.java_runtime_version
static const char* get_java_runtime_version(TRAPS) {
- Klass* k = SystemDictionary::find(vmSymbols::sun_misc_Version(),
+ Klass* k = SystemDictionary::find(vmSymbols::java_lang_VersionProps(),
Handle(), Handle(), CHECK_AND_CLEAR_NULL);
fieldDescriptor fd;
bool found = k != NULL &&
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -960,7 +960,6 @@
nonstatic_field(nmethod, _compile_id, int) \
nonstatic_field(nmethod, _comp_level, int) \
nonstatic_field(nmethod, _exception_cache, ExceptionCache*) \
- nonstatic_field(nmethod, _marked_for_deoptimization, bool) \
\
unchecked_c2_static_field(Deoptimization, _trap_reason_name, void*) \
\
@@ -2006,10 +2005,20 @@
declare_c2_type(LoadStoreNode, Node) \
declare_c2_type(StorePConditionalNode, LoadStoreNode) \
declare_c2_type(StoreLConditionalNode, LoadStoreNode) \
- declare_c2_type(CompareAndSwapLNode, LoadStoreNode) \
- declare_c2_type(CompareAndSwapINode, LoadStoreNode) \
- declare_c2_type(CompareAndSwapPNode, LoadStoreNode) \
- declare_c2_type(CompareAndSwapNNode, LoadStoreNode) \
+ declare_c2_type(CompareAndSwapNode, LoadStoreConditionalNode) \
+ declare_c2_type(CompareAndSwapLNode, CompareAndSwapNode) \
+ declare_c2_type(CompareAndSwapINode, CompareAndSwapNode) \
+ declare_c2_type(CompareAndSwapPNode, CompareAndSwapNode) \
+ declare_c2_type(CompareAndSwapNNode, CompareAndSwapNode) \
+ declare_c2_type(WeakCompareAndSwapLNode, CompareAndSwapNode) \
+ declare_c2_type(WeakCompareAndSwapINode, CompareAndSwapNode) \
+ declare_c2_type(WeakCompareAndSwapPNode, CompareAndSwapNode) \
+ declare_c2_type(WeakCompareAndSwapNNode, CompareAndSwapNode) \
+ declare_c2_type(CompareAndExchangeNode, LoadStoreNode) \
+ declare_c2_type(CompareAndExchangeLNode, CompareAndExchangeNode) \
+ declare_c2_type(CompareAndExchangeINode, CompareAndExchangeNode) \
+ declare_c2_type(CompareAndExchangePNode, CompareAndExchangeNode) \
+ declare_c2_type(CompareAndExchangeNNode, CompareAndExchangeNode) \
declare_c2_type(MulNode, Node) \
declare_c2_type(MulINode, MulNode) \
declare_c2_type(MulLNode, MulNode) \
--- a/hotspot/src/share/vm/runtime/vm_operations.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/runtime/vm_operations.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -485,6 +485,10 @@
}
}
+void VM_PrintCompileQueue::doit() {
+ CompileBroker::print_compile_queues(_out);
+}
+
#if INCLUDE_SERVICES
void VM_PrintClassHierarchy::doit() {
KlassHierarchy::print_class_hierarchy(_out, _print_interfaces, _print_subclasses, _classname);
--- a/hotspot/src/share/vm/runtime/vm_operations.hpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/runtime/vm_operations.hpp Wed Mar 09 14:18:12 2016 +0100
@@ -105,6 +105,7 @@
template(DumpHashtable) \
template(DumpTouchedMethods) \
template(MarkActiveNMethods) \
+ template(PrintCompileQueue) \
template(PrintClassHierarchy) \
class VM_Operation: public CHeapObj<mtInternal> {
@@ -421,6 +422,17 @@
void doit();
};
+class VM_PrintCompileQueue: public VM_Operation {
+ private:
+ outputStream* _out;
+
+ public:
+ VM_PrintCompileQueue(outputStream* st) : _out(st) {}
+ VMOp_Type type() const { return VMOp_PrintCompileQueue; }
+ Mode evaluation_mode() const { return _safepoint; }
+ void doit();
+};
+
#if INCLUDE_SERVICES
class VM_PrintClassHierarchy: public VM_Operation {
private:
--- a/hotspot/src/share/vm/services/diagnosticCommand.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -893,7 +893,8 @@
}
void CompileQueueDCmd::execute(DCmdSource source, TRAPS) {
- CompileBroker::print_compile_queues(output());
+ VM_PrintCompileQueue printCompileQueueOp(output());
+ VMThread::execute(&printCompileQueueOp);
}
void CodeListDCmd::execute(DCmdSource source, TRAPS) {
--- a/hotspot/src/share/vm/utilities/growableArray.hpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/utilities/growableArray.hpp Wed Mar 09 14:18:12 2016 +0100
@@ -396,7 +396,7 @@
int max = length() - 1;
while (max >= min) {
- int mid = (max + min) / 2;
+ int mid = (int)(((uint)max + min) / 2);
E value = at(mid);
int diff = compare(key, value);
if (diff > 0) {
--- a/hotspot/src/share/vm/utilities/vmError.cpp Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/src/share/vm/utilities/vmError.cpp Wed Mar 09 14:18:12 2016 +0100
@@ -1121,6 +1121,10 @@
if (first_error_tid == -1 &&
Atomic::cmpxchg_ptr(mytid, &first_error_tid, -1) == -1) {
+ // Initialize time stamps to use the same base.
+ out.time_stamp().update_to(1);
+ log.time_stamp().update_to(1);
+
_id = id;
_message = message;
_thread = thread;
--- a/hotspot/test/TEST.groups Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/TEST.groups Wed Mar 09 14:18:12 2016 +0100
@@ -299,7 +299,8 @@
compiler/types/ \
compiler/uncommontrap/ \
compiler/unsafe/ \
- -compiler/intrinsics/bmi/verifycode \
+ -compiler/intrinsics/adler32 \
+ -compiler/intrinsics/bmi \
-compiler/intrinsics/mathexact \
-compiler/intrinsics/multiplytolen \
-compiler/intrinsics/sha \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/c1/CanonicalizeArrayLength.java Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,155 @@
+/*
+ * 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
+ * @bug 8150102 8150514 8150534
+ * @summary C1 crashes in Canonicalizer::do_ArrayLength() after fix for JDK-8150102
+ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -XX:CompileThreshold=100 -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -XX:-BackgroundCompilation CanonicalizeArrayLength
+ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -XX:CompileThreshold=100 -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -XX:-BackgroundCompilation -XX:+PatchALot CanonicalizeArrayLength
+ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -XX:CompileThreshold=100 -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -XX:-BackgroundCompilation -XX:ScavengeRootsInCode=0 CanonicalizeArrayLength
+ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -XX:CompileThreshold=100 -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -XX:-BackgroundCompilation -XX:ScavengeRootsInCode=1 CanonicalizeArrayLength
+ */
+public class CanonicalizeArrayLength {
+ int[] arr = new int[42];
+ int[] arrNull = null;
+
+ final int[] finalArr = new int[42];
+ final int[] finalArrNull = null;
+
+ static int[] staticArr = new int[42];
+ static int[] staticArrNull = null;
+
+ static final int[] staticFinalArr = new int[42];
+ static final int[] staticFinalArrNull = null;
+
+ public static void main(String... args) {
+ CanonicalizeArrayLength t = new CanonicalizeArrayLength();
+ for (int i = 0; i < 20000; i++) {
+ if (t.testLocal() != 42)
+ throw new IllegalStateException();
+ if (t.testLocalNull() != 42)
+ throw new IllegalStateException();
+ if (t.testField() != 42)
+ throw new IllegalStateException();
+ if (t.testFieldNull() != 42)
+ throw new IllegalStateException();
+ if (t.testFinalField() != 42)
+ throw new IllegalStateException();
+ if (t.testFinalFieldNull() != 42)
+ throw new IllegalStateException();
+ if (t.testStaticField() != 42)
+ throw new IllegalStateException();
+ if (t.testStaticFieldNull() != 42)
+ throw new IllegalStateException();
+ if (t.testStaticFinalField() != 42)
+ throw new IllegalStateException();
+ if (t.testStaticFinalFieldNull() != 42)
+ throw new IllegalStateException();
+ }
+ }
+
+ int testField() {
+ try {
+ return arr.length;
+ } catch (Throwable t) {
+ return -1;
+ }
+ }
+
+ int testFieldNull() {
+ try {
+ return arrNull.length;
+ } catch (Throwable t) {
+ return 42;
+ }
+ }
+
+ int testFinalField() {
+ try {
+ return finalArr.length;
+ } catch (Throwable t) {
+ return -1;
+ }
+ }
+
+ int testFinalFieldNull() {
+ try {
+ return finalArrNull.length;
+ } catch (Throwable t) {
+ return 42;
+ }
+ }
+
+ int testStaticField() {
+ try {
+ return staticArr.length;
+ } catch (Throwable t) {
+ return -1;
+ }
+ }
+
+ int testStaticFieldNull() {
+ try {
+ return staticArrNull.length;
+ } catch (Throwable t) {
+ return 42;
+ }
+ }
+
+ int testStaticFinalField() {
+ try {
+ return staticFinalArr.length;
+ } catch (Throwable t) {
+ return -1;
+ }
+ }
+
+ int testStaticFinalFieldNull() {
+ try {
+ return staticFinalArrNull.length;
+ } catch (Throwable t) {
+ return 42;
+ }
+ }
+
+ int testLocal() {
+ int[] arr = new int[42];
+ try {
+ return arr.length;
+ } catch (Throwable t) {
+ return -1;
+ }
+ }
+
+ int testLocalNull() {
+ int[] arrNull = null;
+ try {
+ return arrNull.length;
+ } catch (Throwable t) {
+ return 42;
+ }
+ }
+
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/c2/TestDominatingDeadCheckCast.java Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,91 @@
+/*
+ * 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
+ * @bug 8149797
+ * @summary node replaced by dominating dead cast during parsing
+ * @run main/othervm -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -XX:TypeProfileLevel=200 -XX:CompileCommand=dontinline,TestDominatingDeadCheckCast::not_inlined TestDominatingDeadCheckCast
+ *
+ */
+
+public class TestDominatingDeadCheckCast {
+
+ static class A {
+ int f;
+ }
+
+ static class B extends A {
+ }
+
+ static A not_inlined() {
+ return new A();
+ }
+
+ static void inlined(A param) {
+ param.f = 42;
+ }
+
+ static A field;
+
+ static void test(boolean flag1, boolean flag2, boolean flag3, boolean flag4, boolean flag5) {
+ // Go through memory rather than through a local to defeat C2's replace_in_map
+ field = not_inlined();
+ // Speculation adds a CheckCast on entry of this inlined
+ // method for the parameter
+ inlined(field);
+ // Walk up the dominators is depth limited, make the CheckCast
+ // above unreachable from the last inlined call
+ if (flag1) {
+ if (flag2) {
+ if (flag3) {
+ // Speculation adds a CheckCast on entry of this
+ // inlined method for the parameter. This
+ // CheckCast is replaced by the CheckCast of the
+ // first inlined method call but the replaced
+ // CheckCast is still around during parsing.
+ inlined(field);
+ // Same as above, some useless control
+ if (flag4) {
+ if (flag5) {
+ // Speculation adds a CheckCast on entry
+ // of this inlined method for the
+ // parameter. This CheckCast is replaced
+ // by the dead CheckCast of the previous
+ // inlined() call.
+ inlined(field);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ static public void main(String[] args) {
+ field = new A();
+ for (int i = 0; i < 20000; i++) {
+ test(true, true, true, true, true);
+ }
+ }
+}
--- a/hotspot/test/compiler/calls/fromCompiled/CompiledInvokeDynamic2CompiledTest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/compiler/calls/fromCompiled/CompiledInvokeDynamic2CompiledTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -24,9 +24,10 @@
/*
* @test
* @library /test/lib /testlibrary /
+ * @modules java.base/jdk.internal.org.objectweb.asm
* @build compiler.calls.common.InvokeDynamic
* @build compiler.calls.common.InvokeDynamicPatcher
- * @run driver compiler.calls.common.InvokeDynamicPatcher
+ * @run main compiler.calls.common.InvokeDynamicPatcher
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
--- a/hotspot/test/compiler/calls/fromCompiled/CompiledInvokeDynamic2InterpretedTest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/compiler/calls/fromCompiled/CompiledInvokeDynamic2InterpretedTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -24,9 +24,10 @@
/*
* @test
* @library /test/lib /testlibrary /
+ * @modules java.base/jdk.internal.org.objectweb.asm
* @build compiler.calls.common.InvokeDynamic
* @build compiler.calls.common.InvokeDynamicPatcher
- * @run driver compiler.calls.common.InvokeDynamicPatcher
+ * @run main compiler.calls.common.InvokeDynamicPatcher
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
--- a/hotspot/test/compiler/calls/fromCompiled/CompiledInvokeDynamic2NativeTest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/compiler/calls/fromCompiled/CompiledInvokeDynamic2NativeTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -24,9 +24,10 @@
/*
* @test
* @library /test/lib /testlibrary /
+ * @modules java.base/jdk.internal.org.objectweb.asm
* @build compiler.calls.common.InvokeDynamic
* @build compiler.calls.common.InvokeDynamicPatcher
- * @run driver compiler.calls.common.InvokeDynamicPatcher
+ * @run main compiler.calls.common.InvokeDynamicPatcher
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
--- a/hotspot/test/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2CompiledTest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2CompiledTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -24,9 +24,10 @@
/*
* @test
* @library /test/lib /testlibrary /
+ * @modules java.base/jdk.internal.org.objectweb.asm
* @build compiler.calls.common.InvokeDynamic
* @build compiler.calls.common.InvokeDynamicPatcher
- * @run driver compiler.calls.common.InvokeDynamicPatcher
+ * @run main compiler.calls.common.InvokeDynamicPatcher
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
--- a/hotspot/test/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2InterpretedTest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2InterpretedTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -24,9 +24,10 @@
/*
* @test
* @library /test/lib /testlibrary /
+ * @modules java.base/jdk.internal.org.objectweb.asm
* @build compiler.calls.common.InvokeDynamic
* @build compiler.calls.common.InvokeDynamicPatcher
- * @run driver compiler.calls.common.InvokeDynamicPatcher
+ * @run main compiler.calls.common.InvokeDynamicPatcher
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
--- a/hotspot/test/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2NativeTest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2NativeTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -24,9 +24,10 @@
/*
* @test
* @library /test/lib /testlibrary /
+ * @modules java.base/jdk.internal.org.objectweb.asm
* @build compiler.calls.common.InvokeDynamic
* @build compiler.calls.common.InvokeDynamicPatcher
- * @run driver compiler.calls.common.InvokeDynamicPatcher
+ * @run main compiler.calls.common.InvokeDynamicPatcher
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
--- a/hotspot/test/compiler/codecache/jmx/PeakUsageTest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/compiler/codecache/jmx/PeakUsageTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -27,6 +27,7 @@
/*
* @test PeakUsageTest
+ * @ignore 8151345
* @library /testlibrary /test/lib
* @modules java.base/sun.misc
* java.management
--- a/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityBase.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityBase.java Wed Mar 09 14:18:12 2016 +0100
@@ -24,25 +24,26 @@
/*
* @test TestCompilerDirectivesCompatibilityBase
* @bug 8137167
- * @library /testlibrary /test/lib
+ * @library /testlibrary /test/lib /
* @modules java.base/sun.misc
* java.compiler
* java.management
* @build jdk.test.lib.*
- * @build jdk.test.lib.dcmd.*
- * @build sun.hotspot.WhiteBox
- * @run main ClassFileInstaller sun.hotspot.WhiteBox
- * sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run testng/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI TestCompilerDirectivesCompatibilityBase
+ * jdk.test.lib.dcmd.*
+ * sun.hotspot.WhiteBox
+ * compiler.testlibrary.CompilerUtils
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run testng/othervm -Xbootclasspath/a:. -Xmixed -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI TestCompilerDirectivesCompatibilityBase
* @summary Test compiler control compatibility with compile command
*/
+import compiler.testlibrary.CompilerUtils;
+import compiler.whitebox.CompilerWhiteBoxTest;
import jdk.test.lib.dcmd.CommandExecutor;
import jdk.test.lib.dcmd.JMXExecutor;
-
import org.testng.annotations.Test;
import org.testng.Assert;
-
import sun.hotspot.WhiteBox;
import java.io.BufferedReader;
@@ -64,32 +65,38 @@
method = getMethod(TestCompilerDirectivesCompatibilityBase.class, "helper");
nomatch = getMethod(TestCompilerDirectivesCompatibilityBase.class, "another");
- testCompatibility(executor);
+ int[] levels = CompilerUtils.getAvailableCompilationLevels();
+ for (int complevel : levels) {
+ // Only test the major compilers, ignore profiling levels
+ if (complevel == CompilerWhiteBoxTest.COMP_LEVEL_SIMPLE || complevel == CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION){
+ testCompatibility(executor, complevel);
+ }
+ }
}
- public void testCompatibility(CommandExecutor executor) throws Exception {
+ public void testCompatibility(CommandExecutor executor, int comp_level) throws Exception {
// Call all validation twice to catch error when overwriting a directive
// Flag is default off
expect(!WB.getBooleanVMFlag("PrintAssembly"));
- expect(!WB.shouldPrintAssembly(method));
- expect(!WB.shouldPrintAssembly(nomatch));
- expect(!WB.shouldPrintAssembly(method));
- expect(!WB.shouldPrintAssembly(nomatch));
+ expect(!WB.shouldPrintAssembly(method, comp_level));
+ expect(!WB.shouldPrintAssembly(nomatch, comp_level));
+ expect(!WB.shouldPrintAssembly(method, comp_level));
+ expect(!WB.shouldPrintAssembly(nomatch, comp_level));
// load directives that turn it on
executor.execute("Compiler.directives_add " + control_on);
- expect(WB.shouldPrintAssembly(method));
- expect(!WB.shouldPrintAssembly(nomatch));
- expect(WB.shouldPrintAssembly(method));
- expect(!WB.shouldPrintAssembly(nomatch));
+ expect(WB.shouldPrintAssembly(method, comp_level));
+ expect(!WB.shouldPrintAssembly(nomatch, comp_level));
+ expect(WB.shouldPrintAssembly(method, comp_level));
+ expect(!WB.shouldPrintAssembly(nomatch, comp_level));
// remove and see that it is true again
executor.execute("Compiler.directives_remove");
- expect(!WB.shouldPrintAssembly(method));
- expect(!WB.shouldPrintAssembly(nomatch));
- expect(!WB.shouldPrintAssembly(method));
- expect(!WB.shouldPrintAssembly(nomatch));
+ expect(!WB.shouldPrintAssembly(method, comp_level));
+ expect(!WB.shouldPrintAssembly(nomatch, comp_level));
+ expect(!WB.shouldPrintAssembly(method, comp_level));
+ expect(!WB.shouldPrintAssembly(nomatch, comp_level));
}
public void expect(boolean test) throws Exception {
--- a/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOff.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOff.java Wed Mar 09 14:18:12 2016 +0100
@@ -24,16 +24,17 @@
/*
* @test TestCompilerDirectivesCompatibilityCommandOff
* @bug 8137167
- * @library /testlibrary /test/lib
+ * @library /testlibrary /test/lib /
* @modules java.base/sun.misc
* java.compiler
* java.management
* @build jdk.test.lib.*
- * @build jdk.test.lib.dcmd.*
- * @build sun.hotspot.WhiteBox
- * @run main ClassFileInstaller sun.hotspot.WhiteBox
- * sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run testng/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * jdk.test.lib.dcmd.*
+ * sun.hotspot.WhiteBox
+ * compiler.testlibrary.CompilerUtils
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run testng/othervm -Xbootclasspath/a:. -Xmixed -XX:+UnlockDiagnosticVMOptions
* -XX:-PrintAssembly -XX:CompileCommand=option,*.helper,bool,PrintAssembly,false
* -XX:+WhiteBoxAPI TestCompilerDirectivesCompatibilityCommandOff
* @summary Test compiler control compatibility with compile command
@@ -55,27 +56,27 @@
public class TestCompilerDirectivesCompatibilityCommandOff extends TestCompilerDirectivesCompatibilityBase {
- public void testCompatibility(CommandExecutor executor) throws Exception {
+ public void testCompatibility(CommandExecutor executor, int comp_level) throws Exception {
// Call all validation twice to catch error when overwriting a directive
// Flag is default off
- expect(!WB.shouldPrintAssembly(method));
- expect(!WB.shouldPrintAssembly(nomatch));
- expect(!WB.shouldPrintAssembly(method));
- expect(!WB.shouldPrintAssembly(nomatch));
+ expect(!WB.shouldPrintAssembly(method, comp_level));
+ expect(!WB.shouldPrintAssembly(nomatch, comp_level));
+ expect(!WB.shouldPrintAssembly(method, comp_level));
+ expect(!WB.shouldPrintAssembly(nomatch, comp_level));
// load directives that turn it on
executor.execute("Compiler.directives_add " + control_on);
- expect(WB.shouldPrintAssembly(method));
- expect(!WB.shouldPrintAssembly(nomatch));
- expect(WB.shouldPrintAssembly(method));
- expect(!WB.shouldPrintAssembly(nomatch));
+ expect(WB.shouldPrintAssembly(method, comp_level));
+ expect(!WB.shouldPrintAssembly(nomatch, comp_level));
+ expect(WB.shouldPrintAssembly(method, comp_level));
+ expect(!WB.shouldPrintAssembly(nomatch, comp_level));
// remove and see that it is false again
executor.execute("Compiler.directives_remove");
- expect(!WB.shouldPrintAssembly(method));
- expect(!WB.shouldPrintAssembly(nomatch));
- expect(!WB.shouldPrintAssembly(method));
- expect(!WB.shouldPrintAssembly(nomatch));
+ expect(!WB.shouldPrintAssembly(method, comp_level));
+ expect(!WB.shouldPrintAssembly(nomatch, comp_level));
+ expect(!WB.shouldPrintAssembly(method, comp_level));
+ expect(!WB.shouldPrintAssembly(nomatch, comp_level));
}
}
--- a/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOn.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOn.java Wed Mar 09 14:18:12 2016 +0100
@@ -24,16 +24,17 @@
/*
* @test TestCompilerDirectivesCompatibilityCommandOn
* @bug 8137167
- * @library /testlibrary /test/lib
+ * @library /testlibrary /test/lib /
* @modules java.base/sun.misc
* java.compiler
* java.management
* @build jdk.test.lib.*
- * @build jdk.test.lib.dcmd.*
- * @build sun.hotspot.WhiteBox
- * @run main ClassFileInstaller sun.hotspot.WhiteBox
- * sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run testng/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * jdk.test.lib.dcmd.*
+ * sun.hotspot.WhiteBox
+ * compiler.testlibrary.CompilerUtils
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run testng/othervm -Xbootclasspath/a:. -Xmixed -XX:+UnlockDiagnosticVMOptions
* -XX:-PrintAssembly -XX:CompileCommand=print,*.* -XX:+WhiteBoxAPI
* TestCompilerDirectivesCompatibilityCommandOn
* @summary Test compiler control compatibility with compile command
@@ -55,27 +56,27 @@
public class TestCompilerDirectivesCompatibilityCommandOn extends TestCompilerDirectivesCompatibilityBase{
- public void testCompatibility(CommandExecutor executor) throws Exception {
+ public void testCompatibility(CommandExecutor executor, int comp_level) throws Exception {
// Call all validation twice to catch error when overwriting a directive
// Flag is default on
- expect(WB.shouldPrintAssembly(method));
- expect(WB.shouldPrintAssembly(nomatch));
- expect(WB.shouldPrintAssembly(method));
- expect(WB.shouldPrintAssembly(nomatch));
+ expect(WB.shouldPrintAssembly(method, comp_level));
+ expect(WB.shouldPrintAssembly(nomatch, comp_level));
+ expect(WB.shouldPrintAssembly(method, comp_level));
+ expect(WB.shouldPrintAssembly(nomatch, comp_level));
// load directives that turn it off
executor.execute("Compiler.directives_add " + control_off);
- expect(!WB.shouldPrintAssembly(method));
- expect(WB.shouldPrintAssembly(nomatch));
- expect(!WB.shouldPrintAssembly(method));
- expect(WB.shouldPrintAssembly(nomatch));
+ expect(!WB.shouldPrintAssembly(method, comp_level));
+ expect(WB.shouldPrintAssembly(nomatch, comp_level));
+ expect(!WB.shouldPrintAssembly(method, comp_level));
+ expect(WB.shouldPrintAssembly(nomatch, comp_level));
// remove and see that it is true again
executor.execute("Compiler.directives_remove");
- expect(WB.shouldPrintAssembly(method));
- expect(WB.shouldPrintAssembly(nomatch));
- expect(WB.shouldPrintAssembly(method));
- expect(WB.shouldPrintAssembly(nomatch));
+ expect(WB.shouldPrintAssembly(method, comp_level));
+ expect(WB.shouldPrintAssembly(nomatch, comp_level));
+ expect(WB.shouldPrintAssembly(method, comp_level));
+ expect(WB.shouldPrintAssembly(nomatch, comp_level));
}
}
--- a/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityFlag.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityFlag.java Wed Mar 09 14:18:12 2016 +0100
@@ -24,16 +24,17 @@
/*
* @test TestCompilerDirectivesCompatibilityFlag
* @bug 8137167
- * @library /testlibrary /test/lib
+ * @library /testlibrary /test/lib /
* @modules java.base/sun.misc
* java.compiler
* java.management
* @build jdk.test.lib.*
- * @build jdk.test.lib.dcmd.*
- * @build sun.hotspot.WhiteBox
- * @run main ClassFileInstaller sun.hotspot.WhiteBox
- * sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run testng/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * jdk.test.lib.dcmd.*
+ * sun.hotspot.WhiteBox
+ * compiler.testlibrary.CompilerUtils
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run testng/othervm -Xbootclasspath/a:. -Xmixed -XX:+UnlockDiagnosticVMOptions
* -XX:+PrintAssembly -XX:+WhiteBoxAPI TestCompilerDirectivesCompatibilityFlag
* @summary Test compiler control compatibility with compile command
*/
@@ -54,28 +55,28 @@
public class TestCompilerDirectivesCompatibilityFlag extends TestCompilerDirectivesCompatibilityBase {
- public void testCompatibility(CommandExecutor executor) throws Exception {
+ public void testCompatibility(CommandExecutor executor, int comp_level) throws Exception {
// Call all validation twice to catch error when overwriting a directive
// Flag is default on
expect(WB.getBooleanVMFlag("PrintAssembly"));
- expect(WB.shouldPrintAssembly(method));
- expect(WB.shouldPrintAssembly(nomatch));
- expect(WB.shouldPrintAssembly(method));
- expect(WB.shouldPrintAssembly(nomatch));
+ expect(WB.shouldPrintAssembly(method, comp_level));
+ expect(WB.shouldPrintAssembly(nomatch, comp_level));
+ expect(WB.shouldPrintAssembly(method, comp_level));
+ expect(WB.shouldPrintAssembly(nomatch, comp_level));
// load directives that turn it off
executor.execute("Compiler.directives_add " + control_off);
- expect(!WB.shouldPrintAssembly(method));
- expect(WB.shouldPrintAssembly(nomatch));
- expect(!WB.shouldPrintAssembly(method));
- expect(WB.shouldPrintAssembly(nomatch));
+ expect(!WB.shouldPrintAssembly(method, comp_level));
+ expect(WB.shouldPrintAssembly(nomatch, comp_level));
+ expect(!WB.shouldPrintAssembly(method, comp_level));
+ expect(WB.shouldPrintAssembly(nomatch, comp_level));
// remove and see that it is true again
executor.execute("Compiler.directives_remove");
- expect(WB.shouldPrintAssembly(method));
- expect(WB.shouldPrintAssembly(nomatch));
- expect(WB.shouldPrintAssembly(method));
- expect(WB.shouldPrintAssembly(nomatch));
+ expect(WB.shouldPrintAssembly(method, comp_level));
+ expect(WB.shouldPrintAssembly(nomatch, comp_level));
+ expect(WB.shouldPrintAssembly(method, comp_level));
+ expect(WB.shouldPrintAssembly(nomatch, comp_level));
}
}
--- a/hotspot/test/compiler/compilercontrol/share/AbstractTestBase.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/compiler/compilercontrol/share/AbstractTestBase.java Wed Mar 09 14:18:12 2016 +0100
@@ -51,8 +51,9 @@
for (int i = 0; !md.isValid() && i < ATTEMPTS; i++) {
md = METHOD_GEN.generateRandomDescriptor(exec);
}
- if (!md.isValid()) {
- System.out.println("WARN: Using predefined pattern");
+ if (!md.isValid() || "any.method()".matches(md.getRegexp())) {
+ /* if we haven't got a valid pattern or it matches any method
+ leading to timeouts, then use plain standard descriptor */
md = MethodGenerator.commandDescriptor(exec);
}
return md;
--- a/hotspot/test/compiler/intrinsics/string/TestStringIntrinsics2.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/compiler/intrinsics/string/TestStringIntrinsics2.java Wed Mar 09 14:18:12 2016 +0100
@@ -494,6 +494,29 @@
return s.indexOf("1");
}
+ static String text1UTF16 = "A" + "\u05d0" + "\u05d1" + "B";
+
+ @Test(role = Role.TEST_ENTRY)
+ public static void test_indexOf_immUTF16() {
+ assertEquals( 3, indexOf_imm1Latin1_needle(text1UTF16), "test_indexOf_immUTF16");
+ assertEquals( 1, indexOf_imm1UTF16_needle(text1UTF16), "test_indexOf_immUTF16");
+ assertEquals( 1, indexOf_immUTF16_needle(text1UTF16), "test_indexOf_immUTF16");
+ }
+
+ @Test(role = Role.TEST_HELPER, compileAt = 4, warmup = 1, warmupArgs = { "A" + "\u05d0" + "\u05d1" + "B" })
+ static int indexOf_imm1Latin1_needle(String s) {
+ return s.indexOf("B");
+ }
+
+ @Test(role = Role.TEST_HELPER, compileAt = 4, warmup = 1, warmupArgs = { "A" + "\u05d0" + "\u05d1" + "B" })
+ static int indexOf_imm1UTF16_needle(String s) {
+ return s.indexOf("\u05d0");
+ }
+
+ @Test(role = Role.TEST_HELPER, compileAt = 4, warmup = 1, warmupArgs = { "A" + "\u05d0" + "\u05d1" + "B" })
+ static int indexOf_immUTF16_needle(String s) {
+ return s.indexOf("\u05d0" + "\u05d1");
+ }
@Test(role = Role.TEST_HELPER, compileAt = 4, warmup = 1, warmupArgs = { "abc", "abcd" })
public static int asmStringCompareTo(String a, String b) {
--- a/hotspot/test/compiler/intrinsics/unsafe/TestUnsafeUnalignedMismatchedAccesses.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/compiler/intrinsics/unsafe/TestUnsafeUnalignedMismatchedAccesses.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -26,6 +26,7 @@
* @test
* @bug 8136473
* @summary Mismatched stores on same slice possible with Unsafe.Put*Unaligned methods
+ * @modules java.base/jdk.internal.misc
* @run main/othervm -XX:-UseOnStackReplacement -XX:-BackgroundCompilation TestUnsafeUnalignedMismatchedAccesses
* @run main/othervm -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -XX:+UnlockDiagnosticVMOptions -XX:-UseUnalignedAccesses TestUnsafeUnalignedMismatchedAccesses
*
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jsr292/ContinuousCallSiteTargetChange.java Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,103 @@
+/*
+ * 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 /testlibrary
+ * @run main ContinuousCallSiteTargetChange
+ */
+import java.lang.invoke.*;
+import jdk.test.lib.*;
+
+public class ContinuousCallSiteTargetChange {
+ static void testServer() throws Exception {
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+ "-XX:+IgnoreUnrecognizedVMOptions",
+ "-server", "-XX:-TieredCompilation", "-Xbatch",
+ "-XX:PerBytecodeRecompilationCutoff=10", "-XX:PerMethodRecompilationCutoff=10",
+ "-XX:+PrintCompilation", "-XX:+UnlockDiagnosticVMOptions", "-XX:+PrintInlining",
+ "ContinuousCallSiteTargetChange$Test", "100");
+
+ OutputAnalyzer analyzer = new OutputAnalyzer(pb.start());
+
+ analyzer.shouldHaveExitValue(0);
+
+ analyzer.shouldNotContain("made not compilable");
+ analyzer.shouldNotContain("decompile_count > PerMethodRecompilationCutoff");
+ }
+
+ static void testClient() throws Exception {
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+ "-XX:+IgnoreUnrecognizedVMOptions",
+ "-client", "-XX:+TieredCompilation", "-XX:TieredStopAtLevel=1", "-Xbatch",
+ "-XX:PerBytecodeRecompilationCutoff=10", "-XX:PerMethodRecompilationCutoff=10",
+ "-XX:+PrintCompilation", "-XX:+UnlockDiagnosticVMOptions", "-XX:+PrintInlining",
+ "ContinuousCallSiteTargetChange$Test", "100");
+
+ OutputAnalyzer analyzer = new OutputAnalyzer(pb.start());
+
+ analyzer.shouldHaveExitValue(0);
+
+ analyzer.shouldNotContain("made not compilable");
+ analyzer.shouldNotContain("decompile_count > PerMethodRecompilationCutoff");
+ }
+
+ public static void main(String[] args) throws Exception {
+ testServer();
+ testClient();
+ }
+
+ static class Test {
+ static final MethodType mt = MethodType.methodType(void.class);
+ static final CallSite cs = new MutableCallSite(mt);
+
+ static final MethodHandle mh = cs.dynamicInvoker();
+
+ static void f() {
+ }
+
+ static void test1() throws Throwable {
+ mh.invokeExact();
+ }
+
+ static void test2() throws Throwable {
+ cs.getTarget().invokeExact();
+ }
+
+ static void iteration() throws Throwable {
+ MethodHandle mh1 = MethodHandles.lookup().findStatic(ContinuousCallSiteTargetChange.Test.class, "f", mt);
+ cs.setTarget(mh1);
+ for (int i = 0; i < 20_000; i++) {
+ test1();
+ test2();
+ }
+ }
+
+ public static void main(String[] args) throws Throwable {
+ int iterations = Integer.parseInt(args[0]);
+ for (int i = 0; i < iterations; i++) {
+ iteration();
+ }
+ }
+ }
+}
--- a/hotspot/test/compiler/jsr292/NonInlinedCall/InvokeTest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/compiler/jsr292/NonInlinedCall/InvokeTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -180,7 +180,10 @@
static void testInterface() {
System.out.println("linkToInterface");
- // Monomorphic case (optimized virtual call)
+ // Monomorphic case (optimized virtual call), concrete target method
+ run(() -> linkToInterface(new P1(), P1.class));
+
+ // Monomorphic case (optimized virtual call), default target method
run(() -> linkToInterface(new T(), I.class));
// Megamorphic case (virtual call)
--- a/hotspot/test/compiler/jvmci/JVM_GetJVMCIRuntimeTest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/compiler/jvmci/JVM_GetJVMCIRuntimeTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -27,6 +27,7 @@
* @bug 8136421
* @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
* @library /testlibrary /
+ * @modules jdk.vm.ci/jdk.vm.ci.runtime
* @run main/othervm -XX:+UnlockExperimentalVMOptions
* -Dcompiler.jvmci.JVM_GetJVMCIRuntimeTest.positive=true
* -XX:+EnableJVMCI
--- a/hotspot/test/compiler/jvmci/code/InterpreterFrameSizeTest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/compiler/jvmci/code/InterpreterFrameSizeTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -24,6 +24,14 @@
/**
* @test
* @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @modules jdk.vm.ci/jdk.vm.ci.hotspot
+ * jdk.vm.ci/jdk.vm.ci.code
+ * jdk.vm.ci/jdk.vm.ci.code.site
+ * jdk.vm.ci/jdk.vm.ci.meta
+ * jdk.vm.ci/jdk.vm.ci.runtime
+ * jdk.vm.ci/jdk.vm.ci.common
+ * jdk.vm.ci/jdk.vm.ci.amd64
+ * jdk.vm.ci/jdk.vm.ci.sparc
* @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java amd64/AMD64TestAssembler.java sparc/SPARCTestAssembler.java
* @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI compiler.jvmci.code.InterpreterFrameSizeTest
*/
--- a/hotspot/test/compiler/jvmci/common/testcases/MultipleAbstractImplementer.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/compiler/jvmci/common/testcases/MultipleAbstractImplementer.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -23,13 +23,93 @@
package compiler.jvmci.common.testcases;
+import java.util.HashMap;
+import java.util.Map;
+
public abstract class MultipleAbstractImplementer
implements MultipleImplementersInterface {
+ // Different access levels on the fields of this class are used on purpose.
+ // It is needed to verify jdk.vm.ci.CompilerToVM constant pool related
+ // methods, e.g. resolveFieldInPool.
+
+ private static int intStaticField = INT_CONSTANT;
+ final static long longStaticField = LONG_CONSTANT;
+ volatile static float floatStaticField = FLOAT_CONSTANT;
+ static double doubleStaticField = DOUBLE_CONSTANT;
+ public static String stringStaticField = STRING_CONSTANT;
+ protected static Object objectStaticField = OBJECT_CONSTANT;
+
+ public int intField = INT_CONSTANT;
+ private long longField = LONG_CONSTANT;
+ protected float floatField = FLOAT_CONSTANT;
+ transient double doubleField = DOUBLE_CONSTANT;
+ volatile String stringField = STRING_CONSTANT;
+ String stringFieldEmpty = "";
+ final Object objectField;
+
+ public MultipleAbstractImplementer() {
+ intField = Integer.MAX_VALUE;
+ longField = Long.MAX_VALUE;
+ floatField = Float.MAX_VALUE;
+ doubleField = Double.MAX_VALUE;
+ stringField = "Message";
+ objectField = new Object();
+ }
+
public abstract void abstractMethod();
@Override
public void finalize() throws Throwable {
super.finalize();
}
+
+ public void lambdaUsingMethod2() {
+ Thread t = new Thread(this::testMethod);
+ t.start();
+ }
+
+ /**
+ * This method is needed to have "getstatic" and "getfield" instructions
+ * in the class. These instructions are needed to test
+ * resolveFieldInPool method, because it needs a bytecode as one of its arguments.
+ */
+ public void printFileds() {
+ System.out.println(intStaticField);
+ System.out.println(longStaticField);
+ System.out.println(floatStaticField);
+ System.out.println(doubleStaticField);
+ System.out.println(stringStaticField);
+ System.out.println(objectStaticField);
+ System.out.println(intField);
+ System.out.println(longField);
+ System.out.println(floatField);
+ System.out.println(doubleField);
+ System.out.println(stringField);
+ System.out.println(stringFieldEmpty);
+ System.out.println(objectField);
+ }
+
+ public static void staticMethod() {
+ System.getProperties(); // calling some static method
+ Map map = new HashMap(); // calling some constructor
+ map.put(OBJECT_CONSTANT, OBJECT_CONSTANT); // calling some interface method
+ map.remove(OBJECT_CONSTANT); // calling some default interface method
+ }
+
+ @Override
+ public void instanceMethod() {
+ toString(); // calling some virtual method
+ super.toString(); // calling some special method
+ }
+
+ @Override
+ public void anonClassMethod() {
+ new Runnable() {
+ @Override
+ public void run() {
+ System.out.println("Running");
+ }
+ }.run();
+ }
}
--- a/hotspot/test/compiler/jvmci/common/testcases/MultipleImplementer2.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/compiler/jvmci/common/testcases/MultipleImplementer2.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -23,11 +23,18 @@
package compiler.jvmci.common.testcases;
+import java.util.HashMap;
+import java.util.Map;
+
public class MultipleImplementer2 implements MultipleImplementersInterface {
+ // Different access levels on the fields of this class are used on purpose.
+ // It is needed to verify jdk.vm.ci.CompilerToVM constant pool related
+ // methods, e.g. resolveFieldInPool.
+
private static int intStaticField = INT_CONSTANT;
- static long longStaticField = LONG_CONSTANT;
- static float floatStaticField = FLOAT_CONSTANT;
+ final static long longStaticField = LONG_CONSTANT;
+ volatile static float floatStaticField = FLOAT_CONSTANT;
static double doubleStaticField = DOUBLE_CONSTANT;
public static String stringStaticField = STRING_CONSTANT;
protected static Object objectStaticField = OBJECT_CONSTANT;
@@ -35,9 +42,10 @@
public int intField = INT_CONSTANT;
private long longField = LONG_CONSTANT;
protected float floatField = FLOAT_CONSTANT;
- double doubleField = DOUBLE_CONSTANT;
- String stringField = STRING_CONSTANT;
- Object objectField = OBJECT_CONSTANT;
+ transient double doubleField = DOUBLE_CONSTANT;
+ volatile String stringField = STRING_CONSTANT;
+ String stringFieldEmpty = "";
+ final Object objectField;
public MultipleImplementer2() {
intField = Integer.MAX_VALUE;
@@ -58,12 +66,52 @@
super.finalize();
}
- public void interfaceMethodReferral2(MultipleImplementersInterface obj) {
- obj.interfaceMethodReferral(obj);
- }
-
public void lambdaUsingMethod2() {
Thread t = new Thread(this::testMethod);
t.start();
}
+
+ /**
+ * This method is needed to have "getstatic" and "getfield" instructions
+ * in the class. These instructions are needed to test
+ * resolveFieldInPool method, because it needs a bytecode as one of its arguments.
+ */
+ public void printFileds() {
+ System.out.println(intStaticField);
+ System.out.println(longStaticField);
+ System.out.println(floatStaticField);
+ System.out.println(doubleStaticField);
+ System.out.println(stringStaticField);
+ System.out.println(objectStaticField);
+ System.out.println(intField);
+ System.out.println(longField);
+ System.out.println(floatField);
+ System.out.println(doubleField);
+ System.out.println(stringField);
+ System.out.println(stringFieldEmpty);
+ System.out.println(objectField);
+ }
+
+ public static void staticMethod() {
+ System.getProperties(); // calling some static method
+ Map map = new HashMap(); // calling some constructor
+ map.put(OBJECT_CONSTANT, OBJECT_CONSTANT); // calling some interface method
+ map.remove(OBJECT_CONSTANT); // calling some default interface method
+ }
+
+ @Override
+ public void instanceMethod() {
+ toString(); // calling some virtual method
+ super.toString(); // calling some special method
+ }
+
+ @Override
+ public void anonClassMethod() {
+ new Runnable() {
+ @Override
+ public void run() {
+ System.out.println("Running");
+ }
+ }.run();
+ }
}
--- a/hotspot/test/compiler/jvmci/common/testcases/MultipleImplementersInterface.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/compiler/jvmci/common/testcases/MultipleImplementersInterface.java Wed Mar 09 14:18:12 2016 +0100
@@ -23,6 +23,9 @@
package compiler.jvmci.common.testcases;
+import java.util.HashMap;
+import java.util.Map;
+
public interface MultipleImplementersInterface {
int INT_CONSTANT = Integer.MAX_VALUE;
@@ -42,12 +45,34 @@
// empty
}
- default void interfaceMethodReferral(MultipleImplementersInterface obj) {
- obj.defaultMethod();
- }
-
default void lambdaUsingMethod() {
Thread t = new Thread(this::defaultMethod);
t.start();
}
+
+ default void printFields() {
+ System.out.println(OBJECT_CONSTANT);
+ String s = "";
+ System.out.println(s);
+ }
+
+ static void staticMethod() {
+ System.getProperties(); // calling some static method
+ Map map = new HashMap(); // calling some constructor
+ map.put(OBJECT_CONSTANT, OBJECT_CONSTANT); // calling some interface method
+ map.remove(OBJECT_CONSTANT); // calling some default interface method
+ }
+
+ default void instanceMethod() {
+ toString(); // calling some virtual method
+ }
+
+ default void anonClassMethod() {
+ new Runnable() {
+ @Override
+ public void run() {
+ System.out.println("Running");
+ }
+ }.run();
+ }
}
--- a/hotspot/test/compiler/jvmci/compilerToVM/ConstantPoolTestCase.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ConstantPoolTestCase.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -27,118 +27,214 @@
import java.util.HashMap;
import java.util.Map;
import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
-import jdk.internal.misc.SharedSecrets;
+import sun.hotspot.WhiteBox;
import sun.reflect.ConstantPool;
+import sun.reflect.ConstantPool.Tag;
+import compiler.jvmci.compilerToVM.ConstantPoolTestsHelper.DummyClasses;
+import static compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes.*;
/**
* Common class for jdk.vm.ci.hotspot.CompilerToVM constant pool tests
*/
public class ConstantPoolTestCase {
- private final Map<ConstantPoolTestsHelper.ConstantTypes, Validator> typeTests;
+
+ private static final Map<Tag, ConstantTypes> TAG_TO_TYPE_MAP;
+ static {
+ TAG_TO_TYPE_MAP = new HashMap<>();
+ TAG_TO_TYPE_MAP.put(Tag.CLASS, CONSTANT_CLASS);
+ TAG_TO_TYPE_MAP.put(Tag.FIELDREF, CONSTANT_FIELDREF);
+ TAG_TO_TYPE_MAP.put(Tag.METHODREF, CONSTANT_METHODREF);
+ TAG_TO_TYPE_MAP.put(Tag.INTERFACEMETHODREF, CONSTANT_INTERFACEMETHODREF);
+ TAG_TO_TYPE_MAP.put(Tag.STRING, CONSTANT_STRING);
+ TAG_TO_TYPE_MAP.put(Tag.INTEGER, CONSTANT_INTEGER);
+ TAG_TO_TYPE_MAP.put(Tag.FLOAT, CONSTANT_FLOAT);
+ TAG_TO_TYPE_MAP.put(Tag.LONG, CONSTANT_LONG);
+ TAG_TO_TYPE_MAP.put(Tag.DOUBLE, CONSTANT_DOUBLE);
+ TAG_TO_TYPE_MAP.put(Tag.NAMEANDTYPE, CONSTANT_NAMEANDTYPE);
+ TAG_TO_TYPE_MAP.put(Tag.UTF8, CONSTANT_UTF8);
+ TAG_TO_TYPE_MAP.put(Tag.METHODHANDLE, CONSTANT_METHODHANDLE);
+ TAG_TO_TYPE_MAP.put(Tag.METHODTYPE, CONSTANT_METHODTYPE);
+ TAG_TO_TYPE_MAP.put(Tag.INVOKEDYNAMIC, CONSTANT_INVOKEDYNAMIC);
+ TAG_TO_TYPE_MAP.put(Tag.INVALID, CONSTANT_INVALID);
+ }
+ private static final WhiteBox WB = WhiteBox.getWhiteBox();
+ private final Map<ConstantTypes, Validator> typeTests;
+
+ public static enum ConstantTypes {
+ CONSTANT_CLASS {
+ @Override
+ public TestedCPEntry getTestedCPEntry(DummyClasses dummyClass, int index) {
+ ConstantPool constantPoolSS = dummyClass.constantPoolSS;
+ checkIndex(constantPoolSS, index);
+ Class<?> klass = constantPoolSS.getClassAt(index);
+ String klassName = klass.getName();
+ TestedCPEntry[] testedEntries = dummyClass.testedCP.get(this);
+ for (TestedCPEntry entry : testedEntries) {
+ if (entry.klass.replaceAll("/", "\\.").equals(klassName)) {
+ return entry;
+ }
+ }
+ return null;
+ }
+ },
+ CONSTANT_FIELDREF {
+ @Override
+ public TestedCPEntry getTestedCPEntry(DummyClasses dummyClass, int index) {
+ return this.getTestedCPEntryForMethodAndField(dummyClass, index);
+ }
+ },
+ CONSTANT_METHODREF {
+ @Override
+ public TestedCPEntry getTestedCPEntry(DummyClasses dummyClass, int index) {
+ return this.getTestedCPEntryForMethodAndField(dummyClass, index);
+ }
+ },
+ CONSTANT_INTERFACEMETHODREF {
+ @Override
+ public TestedCPEntry getTestedCPEntry(DummyClasses dummyClass, int index) {
+ return this.getTestedCPEntryForMethodAndField(dummyClass, index);
+ }
+ },
+ CONSTANT_STRING {
+ @Override
+ public TestedCPEntry getTestedCPEntry(DummyClasses dummyClass, int index) {
+ ConstantPool constantPoolSS = dummyClass.constantPoolSS;
+ checkIndex(constantPoolSS, index);
+ String value = constantPoolSS.getStringAt(index);
+ TestedCPEntry[] testedEntries = dummyClass.testedCP.get(this);
+ for (TestedCPEntry entry : testedEntries) {
+ if (entry.name.equals(value)) {
+ return entry;
+ }
+ }
+ return null;
+ }
+ },
+ CONSTANT_INTEGER,
+ CONSTANT_FLOAT,
+ CONSTANT_LONG,
+ CONSTANT_DOUBLE,
+ CONSTANT_NAMEANDTYPE,
+ CONSTANT_UTF8,
+ CONSTANT_METHODHANDLE,
+ CONSTANT_METHODTYPE,
+ CONSTANT_INVOKEDYNAMIC {
+ @Override
+ public TestedCPEntry getTestedCPEntry(DummyClasses dummyClass, int index) {
+ ConstantPool constantPoolSS = dummyClass.constantPoolSS;
+ checkIndex(constantPoolSS, index);
+ int nameAndTypeIndex = constantPoolSS.getNameAndTypeRefIndexAt(index);
+ String[] info = constantPoolSS.getNameAndTypeRefInfoAt(nameAndTypeIndex);
+ TestedCPEntry[] testedEntries = dummyClass.testedCP.get(this);
+ for (TestedCPEntry entry : testedEntries) {
+ if (info[0].equals(entry.name) && info[1].equals(entry.type)) {
+ return entry;
+ }
+ }
+ return null;
+ }
+ },
+ CONSTANT_INVALID;
+
+ public TestedCPEntry getTestedCPEntry(DummyClasses dummyClass, int index) {
+ return null; // returning null by default
+ }
+
+ public TestedCPEntry[] getAllCPEntriesForType(DummyClasses dummyClass) {
+ TestedCPEntry[] toReturn = dummyClass.testedCP.get(this);
+ if (toReturn == null) {
+ return new TestedCPEntry[0];
+ }
+ return dummyClass.testedCP.get(this);
+ }
+
+ protected TestedCPEntry getTestedCPEntryForMethodAndField(DummyClasses dummyClass, int index) {
+ ConstantPool constantPoolSS = dummyClass.constantPoolSS;
+ checkIndex(constantPoolSS, index);
+ String[] info = constantPoolSS.getMemberRefInfoAt(index);
+ TestedCPEntry[] testedEntries = dummyClass.testedCP.get(this);
+ for (TestedCPEntry entry : testedEntries) {
+ if (info[0].equals(entry.klass) && info[1].equals(entry.name) && info[2].equals(entry.type)) {
+ return entry;
+ }
+ }
+ return null;
+ }
+
+ protected void checkIndex(ConstantPool constantPoolSS, int index) {
+ ConstantPool.Tag tag = constantPoolSS.getTagAt(index);
+ ConstantTypes type = mapTagToCPType(tag);
+ if (!this.equals(type)) {
+ String msg = String.format("TESTBUG: CP tag should be a %s, but is %s",
+ this.name(),
+ type.name());
+ throw new Error(msg);
+ }
+ }
+ }
public static interface Validator {
void validate(jdk.vm.ci.meta.ConstantPool constantPoolCTVM,
- ConstantPool constantPoolSS,
- ConstantPoolTestsHelper.DummyClasses dummyClass, int index);
+ ConstantTypes cpType,
+ DummyClasses dummyClass,
+ int index);
}
- public ConstantPoolTestCase(Map<ConstantPoolTestsHelper.ConstantTypes,Validator> typeTests) {
+ public static class TestedCPEntry {
+ public final String klass;
+ public final String name;
+ public final String type;
+ public final byte[] opcodes;
+ public final long accFlags;
+
+ public TestedCPEntry(String klass, String name, String type, byte[] opcodes, long accFlags) {
+ this.klass = klass;
+ this.name = name;
+ this.type = type;
+ if (opcodes != null) {
+ this.opcodes = new byte[opcodes.length];
+ System.arraycopy(opcodes, 0, this.opcodes, 0, opcodes.length);
+ } else {
+ this.opcodes = null;
+ }
+ this.accFlags = accFlags;
+ }
+
+ public TestedCPEntry(String klass, String name, String type, byte[] opcodes) {
+ this(klass, name, type, opcodes, 0);
+ }
+
+ public TestedCPEntry(String klass, String name, String type) {
+ this(klass, name, type, null, 0);
+ }
+ }
+
+ public static ConstantTypes mapTagToCPType(Tag tag) {
+ return TAG_TO_TYPE_MAP.get(tag);
+ }
+
+ public ConstantPoolTestCase(Map<ConstantTypes, Validator> typeTests) {
this.typeTests = new HashMap<>();
this.typeTests.putAll(typeTests);
}
- private void messageOnFail(Throwable t,
- ConstantPoolTestsHelper.ConstantTypes cpType,
- ConstantPoolTestsHelper.DummyClasses dummyClass, int index) {
- ConstantPool constantPoolSS = SharedSecrets.getJavaLangAccess().
- getConstantPool(dummyClass.klass);
- String msg = String.format("Test for %s constant pool entry of"
- + " type %s",
- dummyClass.klass, cpType.name());
- switch (cpType) {
- case CONSTANT_CLASS:
- case CONSTANT_STRING:
- case CONSTANT_METHODTYPE:
- String utf8 = constantPoolSS
- .getUTF8At((int) dummyClass.cp.get(index).value);
- msg = String.format("%s (%s) failed with %s", msg, utf8, t);
- break;
- case CONSTANT_INTEGER:
- int intValue = constantPoolSS.getIntAt(index);
- msg = String.format("%s (%d) failed with %s", msg, intValue, t);
- break;
- case CONSTANT_LONG:
- long longValue = constantPoolSS.getLongAt(index);
- msg = String.format("%s (%d) failed with %s", msg, longValue, t);
- break;
- case CONSTANT_FLOAT:
- float floatValue = constantPoolSS.getFloatAt(index);
- msg = String.format("%s (%E) failed with %s", msg, floatValue, t);
- break;
- case CONSTANT_DOUBLE:
- double doubleValue = constantPoolSS.getDoubleAt(index);
- msg = String.format("%s (%E) failed with %s", msg, doubleValue, t);
- break;
- case CONSTANT_UTF8:
- String utf8Value = constantPoolSS.getUTF8At(index);
- msg = String.format("%s (%s) failed with %s", msg, utf8Value, t);
- break;
- case CONSTANT_INVOKEDYNAMIC:
- index = ((int[]) dummyClass.cp.get(index).value)[1];
- case CONSTANT_NAMEANDTYPE:
- String name = constantPoolSS
- .getUTF8At(((int[]) dummyClass.cp.get(index).value)[0]);
- String type = constantPoolSS
- .getUTF8At(((int[]) dummyClass.cp.get(index).value)[1]);
- msg = String.format("%s (%s:%s) failed with %s",
- msg, name, type, t);
- break;
- case CONSTANT_METHODHANDLE:
- index = ((int[]) dummyClass.cp.get(index).value)[1];
- case CONSTANT_METHODREF:
- case CONSTANT_INTERFACEMETHODREF:
- case CONSTANT_FIELDREF:
- int classIndex = ((int[]) dummyClass.cp.get(index).value)[0];
- int nameAndTypeIndex = ((int[]) dummyClass.cp.get(index).value)[1];
- String cName = constantPoolSS
- .getUTF8At((int) dummyClass.cp.get(classIndex).value);
- String mName = constantPoolSS
- .getUTF8At(((int[]) dummyClass.cp.get(nameAndTypeIndex).value)[0]);
- String mType = constantPoolSS
- .getUTF8At(((int[]) dummyClass.cp.get(nameAndTypeIndex).value)[1]);
- msg = String.format("%s (%s.%s:%s) failed with %s ",
- msg, cName, mName, mType, t);
- break;
- default:
- msg = String.format("Test bug: unknown constant type %s ", cpType);
- }
- throw new Error(msg + t.getMessage(), t);
- }
-
public void test() {
- for (ConstantPoolTestsHelper.DummyClasses dummyClass
- : ConstantPoolTestsHelper.DummyClasses.values()) {
- System.out.printf("%nTesting dummy %s%n", dummyClass.klass);
- HotSpotResolvedObjectType holder = HotSpotResolvedObjectType
- .fromObjectClass(dummyClass.klass);
- jdk.vm.ci.meta.ConstantPool constantPoolCTVM
- = holder.getConstantPool();
- ConstantPool constantPoolSS = SharedSecrets.getJavaLangAccess().
- getConstantPool(dummyClass.klass);
- for (Integer i : dummyClass.cp.keySet()) {
- ConstantPoolTestsHelper.ConstantTypes cpType
- = dummyClass.cp.get(i).type;
+ for (DummyClasses dummyClass : DummyClasses.values()) {
+ boolean isCPCached = WB.getConstantPoolCacheLength(dummyClass.klass) > -1;
+ System.out.printf("Testing dummy %s with constant pool cached = %b%n",
+ dummyClass.klass,
+ isCPCached);
+ HotSpotResolvedObjectType holder = HotSpotResolvedObjectType.fromObjectClass(dummyClass.klass);
+ jdk.vm.ci.meta.ConstantPool constantPoolCTVM = holder.getConstantPool();
+ ConstantPool constantPoolSS = dummyClass.constantPoolSS;
+ for (int i = 0; i < constantPoolSS.getSize(); i++) {
+ Tag tag = constantPoolSS.getTagAt(i);
+ ConstantTypes cpType = mapTagToCPType(tag);
if (!typeTests.keySet().contains(cpType)) {
continue;
}
- try {
- typeTests.get(cpType).validate(constantPoolCTVM,
- constantPoolSS, dummyClass, i);
- } catch (Throwable t) {
- messageOnFail(t, cpType, dummyClass, i);
- }
+ typeTests.get(cpType).validate(constantPoolCTVM, cpType, dummyClass, i);
}
}
}
}
-
--- a/hotspot/test/compiler/jvmci/compilerToVM/ConstantPoolTestsHelper.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ConstantPoolTestsHelper.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -23,10 +23,19 @@
*/
package compiler.jvmci.compilerToVM;
+import compiler.jvmci.common.testcases.MultipleAbstractImplementer;
import compiler.jvmci.common.testcases.MultipleImplementer2;
import compiler.jvmci.common.testcases.MultipleImplementersInterface;
+import compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes;
+import static compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes.*;
+import compiler.jvmci.compilerToVM.ConstantPoolTestCase.TestedCPEntry;
import java.util.HashMap;
import java.util.Map;
+import jdk.internal.misc.SharedSecrets;
+import jdk.internal.org.objectweb.asm.Opcodes;
+import sun.hotspot.WhiteBox;
+import sun.reflect.ConstantPool;
+import sun.reflect.ConstantPool.Tag;
/**
* Class contains hard-coded constant pool tables for dummy classes used for
@@ -34,104 +43,437 @@
*/
public class ConstantPoolTestsHelper {
- public enum ConstantTypes {
- CONSTANT_CLASS,
- CONSTANT_FIELDREF,
- CONSTANT_METHODREF,
- CONSTANT_INTERFACEMETHODREF,
- CONSTANT_STRING,
- CONSTANT_INTEGER,
- CONSTANT_FLOAT,
- CONSTANT_LONG,
- CONSTANT_DOUBLE,
- CONSTANT_NAMEANDTYPE,
- CONSTANT_UTF8,
- CONSTANT_METHODHANDLE,
- CONSTANT_METHODTYPE,
- CONSTANT_INVOKEDYNAMIC;
- }
+ public static final int NO_CP_CACHE_PRESENT = Integer.MAX_VALUE;
public enum DummyClasses {
DUMMY_CLASS(MultipleImplementer2.class, CP_MAP_FOR_CLASS),
+ DUMMY_ABS_CLASS(MultipleAbstractImplementer.class, CP_MAP_FOR_ABS_CLASS),
DUMMY_INTERFACE(MultipleImplementersInterface.class, CP_MAP_FOR_INTERFACE);
+ private static final WhiteBox WB = WhiteBox.getWhiteBox();
public final Class<?> klass;
- public final Map<Integer, ConstantPoolEntry> cp;
+ public final ConstantPool constantPoolSS;
+ public final Map<ConstantTypes, TestedCPEntry[]> testedCP;
- DummyClasses(Class<?> klass, Map<Integer, ConstantPoolEntry> cp) {
+ DummyClasses(Class<?> klass, Map<ConstantTypes, TestedCPEntry[]> testedCP) {
this.klass = klass;
- this.cp = cp;
+ this.constantPoolSS = SharedSecrets.getJavaLangAccess().getConstantPool(klass);
+ this.testedCP = testedCP;
}
- }
- public static class ConstantPoolEntry {
-
- public final ConstantTypes type;
- public final Object value;
-
- public ConstantPoolEntry(ConstantTypes type, Object value) {
- this.type = type;
- this.value = value;
+ public int getCPCacheIndex(int cpi) {
+ int cacheLength = WB.getConstantPoolCacheLength(this.klass);
+ int indexTag = WB.getConstantPoolCacheIndexTag();
+ for (int cpci = indexTag; cpci < cacheLength + indexTag; cpci++) {
+ if (WB.remapInstructionOperandFromCPCache(this.klass, cpci) == cpi) {
+ if (constantPoolSS.getTagAt(cpi).equals(Tag.INVOKEDYNAMIC)) {
+ return WB.encodeConstantPoolIndyIndex(cpci) + indexTag;
+ }
+ return cpci;
+ }
+ }
+ return NO_CP_CACHE_PRESENT;
}
}
- private static final Map<Integer, ConstantPoolEntry> CP_MAP_FOR_CLASS
- = new HashMap<>();
+ private static final Map<ConstantTypes, TestedCPEntry[]> CP_MAP_FOR_CLASS = new HashMap<>();
static {
- CP_MAP_FOR_CLASS.put(1, new ConstantPoolEntry(ConstantTypes.CONSTANT_METHODREF, new int[]{22, 68}));
- CP_MAP_FOR_CLASS.put(2, new ConstantPoolEntry(ConstantTypes.CONSTANT_CLASS, 69));
- CP_MAP_FOR_CLASS.put(3, new ConstantPoolEntry(ConstantTypes.CONSTANT_INTEGER, 2147483647));
- CP_MAP_FOR_CLASS.put(4, new ConstantPoolEntry(ConstantTypes.CONSTANT_FIELDREF, new int[]{35, 70}));
- CP_MAP_FOR_CLASS.put(5, new ConstantPoolEntry(ConstantTypes.CONSTANT_LONG, 9223372036854775807L));
- CP_MAP_FOR_CLASS.put(8, new ConstantPoolEntry(ConstantTypes.CONSTANT_FLOAT, 3.4028235E38F));
- CP_MAP_FOR_CLASS.put(10, new ConstantPoolEntry(ConstantTypes.CONSTANT_DOUBLE, 1.7976931348623157E308D));
- CP_MAP_FOR_CLASS.put(13, new ConstantPoolEntry(ConstantTypes.CONSTANT_STRING, 74));
- CP_MAP_FOR_CLASS.put(22, new ConstantPoolEntry(ConstantTypes.CONSTANT_CLASS, 83));
- CP_MAP_FOR_CLASS.put(23, new ConstantPoolEntry(ConstantTypes.CONSTANT_METHODREF, new int[]{22, 84}));
- CP_MAP_FOR_CLASS.put(24, new ConstantPoolEntry(ConstantTypes.CONSTANT_INTERFACEMETHODREF, new int[]{2, 85}));
- CP_MAP_FOR_CLASS.put(26, new ConstantPoolEntry(ConstantTypes.CONSTANT_INVOKEDYNAMIC, new int[]{0, 91}));
- CP_MAP_FOR_CLASS.put(29, new ConstantPoolEntry(ConstantTypes.CONSTANT_FIELDREF, new int[]{35, 94}));
- CP_MAP_FOR_CLASS.put(35, new ConstantPoolEntry(ConstantTypes.CONSTANT_CLASS, 100));
- CP_MAP_FOR_CLASS.put(68, new ConstantPoolEntry(ConstantTypes.CONSTANT_NAMEANDTYPE, new int[]{54, 55}));
- CP_MAP_FOR_CLASS.put(70, new ConstantPoolEntry(ConstantTypes.CONSTANT_NAMEANDTYPE, new int[]{48, 37}));
- CP_MAP_FOR_CLASS.put(84, new ConstantPoolEntry(ConstantTypes.CONSTANT_NAMEANDTYPE, new int[]{59, 55}));
- CP_MAP_FOR_CLASS.put(85, new ConstantPoolEntry(ConstantTypes.CONSTANT_NAMEANDTYPE, new int[]{103, 63}));
- CP_MAP_FOR_CLASS.put(91, new ConstantPoolEntry(ConstantTypes.CONSTANT_NAMEANDTYPE, new int[]{106, 107}));
- CP_MAP_FOR_CLASS.put(94, new ConstantPoolEntry(ConstantTypes.CONSTANT_NAMEANDTYPE, new int[]{36, 37}));
- CP_MAP_FOR_CLASS.put(104, new ConstantPoolEntry(ConstantTypes.CONSTANT_METHODREF, new int[]{110, 111}));
- CP_MAP_FOR_CLASS.put(105, new ConstantPoolEntry(ConstantTypes.CONSTANT_METHODREF, new int[]{35, 112}));
- CP_MAP_FOR_CLASS.put(110, new ConstantPoolEntry(ConstantTypes.CONSTANT_CLASS, 113));
- CP_MAP_FOR_CLASS.put(111, new ConstantPoolEntry(ConstantTypes.CONSTANT_NAMEANDTYPE, new int[]{114, 118}));
- CP_MAP_FOR_CLASS.put(112, new ConstantPoolEntry(ConstantTypes.CONSTANT_NAMEANDTYPE, new int[]{58, 55}));
+ CP_MAP_FOR_CLASS.put(CONSTANT_CLASS,
+ new TestedCPEntry[] {
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementersInterface", null, null),
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementer2", null, null),
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementer2$1", null, null),
+ new TestedCPEntry("java/lang/invoke/MethodHandles$Lookup", null, null),
+ }
+ );
+ CP_MAP_FOR_CLASS.put(CONSTANT_FIELDREF,
+ new TestedCPEntry[] {
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementer2",
+ "intStaticField",
+ "I",
+ new byte[] {(byte) Opcodes.PUTSTATIC, (byte) Opcodes.GETSTATIC},
+ Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC),
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementer2",
+ "longStaticField",
+ "J",
+ new byte[] {(byte) Opcodes.PUTSTATIC, (byte) Opcodes.GETSTATIC},
+ Opcodes.ACC_FINAL | Opcodes.ACC_STATIC),
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementer2",
+ "floatStaticField",
+ "F",
+ new byte[] {(byte) Opcodes.PUTSTATIC, (byte) Opcodes.GETSTATIC},
+ Opcodes.ACC_VOLATILE | Opcodes.ACC_STATIC),
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementer2",
+ "doubleStaticField",
+ "D",
+ new byte[] {(byte) Opcodes.PUTSTATIC, (byte) Opcodes.GETSTATIC},
+ Opcodes.ACC_STATIC),
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementer2",
+ "stringStaticField",
+ "Ljava/lang/String;",
+ new byte[] {(byte) Opcodes.PUTSTATIC, (byte) Opcodes.GETSTATIC},
+ Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC),
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementer2",
+ "objectStaticField",
+ "Ljava/lang/Object;",
+ new byte[] {(byte) Opcodes.PUTSTATIC, (byte) Opcodes.GETSTATIC},
+ Opcodes.ACC_PROTECTED | Opcodes.ACC_STATIC),
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementer2",
+ "intField",
+ "I",
+ new byte[] {(byte) Opcodes.PUTFIELD | (byte) Opcodes.GETFIELD},
+ Opcodes.ACC_PUBLIC),
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementer2",
+ "longField",
+ "J",
+ new byte[] {(byte) Opcodes.PUTFIELD | (byte) Opcodes.GETFIELD},
+ Opcodes.ACC_PRIVATE),
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementer2",
+ "floatField",
+ "F",
+ new byte[] {(byte) Opcodes.PUTFIELD | (byte) Opcodes.GETFIELD},
+ Opcodes.ACC_PROTECTED),
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementer2",
+ "doubleField",
+ "D",
+ new byte[] {(byte) Opcodes.PUTFIELD | (byte) Opcodes.GETFIELD},
+ Opcodes.ACC_TRANSIENT),
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementer2",
+ "objectField",
+ "Ljava/lang/Object;",
+ new byte[] {(byte) Opcodes.PUTFIELD | (byte) Opcodes.GETFIELD},
+ Opcodes.ACC_FINAL),
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementer2",
+ "stringField",
+ "Ljava/lang/String;",
+ new byte[] {(byte) Opcodes.PUTFIELD | (byte) Opcodes.GETFIELD},
+ Opcodes.ACC_VOLATILE),
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementer2",
+ "stringFieldEmpty",
+ "Ljava/lang/String;",
+ new byte[] {(byte) Opcodes.PUTFIELD | (byte) Opcodes.GETFIELD},
+ 0L),
+ }
+ );
+ CP_MAP_FOR_CLASS.put(CONSTANT_METHODREF,
+ new TestedCPEntry[] {
+ new TestedCPEntry("java/lang/System",
+ "getProperties",
+ "()Ljava/util/Properties;",
+ new byte[] {(byte) Opcodes.INVOKESTATIC}),
+ new TestedCPEntry("java/util/HashMap",
+ "<init>",
+ "()V",
+ new byte[] {(byte) Opcodes.INVOKESPECIAL}),
+ new TestedCPEntry("java/lang/Object",
+ "toString",
+ "()Ljava/lang/String;",
+ new byte[] {(byte) Opcodes.INVOKESPECIAL,
+ (byte) Opcodes.INVOKEVIRTUAL}),
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementer2$1",
+ "<init>",
+ "(Lcompiler/jvmci/common/testcases/MultipleImplementer2;)V",
+ new byte[0]),
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer$1",
+ "run",
+ "()V",
+ new byte[0]),
+ }
+ );
+ CP_MAP_FOR_CLASS.put(CONSTANT_INTERFACEMETHODREF,
+ new TestedCPEntry[] {
+ new TestedCPEntry("java/util/Map",
+ "put",
+ "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
+ new byte[] {(byte) Opcodes.INVOKEINTERFACE}),
+ new TestedCPEntry("java/util/Map",
+ "remove",
+ "(Ljava/lang/Object;)Ljava/lang/Object;",
+ new byte[] {(byte) Opcodes.INVOKEINTERFACE}),
+ }
+ );
+ CP_MAP_FOR_CLASS.put(CONSTANT_STRING,
+ new TestedCPEntry[] {
+ new TestedCPEntry(null, "Message", null),
+ new TestedCPEntry(null, "", null),
+ }
+ );
+ CP_MAP_FOR_CLASS.put(CONSTANT_METHODHANDLE,
+ new TestedCPEntry[] {
+ new TestedCPEntry("java/lang/invoke/LambdaMetafactory",
+ "metafactory",
+ "(Ljava/lang/invoke/MethodHandles$Lookup;"
+ + "Ljava/lang/String;"
+ + "Ljava/lang/invoke/MethodType;"
+ + "Ljava/lang/invoke/MethodType;"
+ + "Ljava/lang/invoke/MethodHandle;"
+ + "Ljava/lang/invoke/MethodType;)"
+ + "Ljava/lang/invoke/CallSite;",
+ null),
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementer2",
+ "testMethod",
+ "()V"),
+ }
+ );
+ CP_MAP_FOR_CLASS.put(CONSTANT_METHODTYPE,
+ new TestedCPEntry[] {
+ new TestedCPEntry(null, null, "()V"),
+ }
+ );
+ CP_MAP_FOR_CLASS.put(CONSTANT_INVOKEDYNAMIC,
+ new TestedCPEntry[] {
+ new TestedCPEntry(null,
+ "run",
+ "(Lcompiler/jvmci/common/testcases/MultipleImplementer2;)"
+ + "Ljava/lang/Runnable;"),
+ }
+ );
}
- private static final Map<Integer, ConstantPoolEntry> CP_MAP_FOR_INTERFACE
+ private static final Map<ConstantTypes, TestedCPEntry[]> CP_MAP_FOR_ABS_CLASS
= new HashMap<>();
static {
- CP_MAP_FOR_INTERFACE.put(1, new ConstantPoolEntry(ConstantTypes.CONSTANT_CLASS, 48));
- CP_MAP_FOR_INTERFACE.put(5, new ConstantPoolEntry(ConstantTypes.CONSTANT_INTERFACEMETHODREF, new int[]{13, 52}));
- CP_MAP_FOR_INTERFACE.put(6, new ConstantPoolEntry(ConstantTypes.CONSTANT_CLASS, 53));
- CP_MAP_FOR_INTERFACE.put(7, new ConstantPoolEntry(ConstantTypes.CONSTANT_INVOKEDYNAMIC, new int[]{0, 58}));
- CP_MAP_FOR_INTERFACE.put(8, new ConstantPoolEntry(ConstantTypes.CONSTANT_METHODREF, new int[]{6, 59}));
- CP_MAP_FOR_INTERFACE.put(9, new ConstantPoolEntry(ConstantTypes.CONSTANT_METHODREF, new int[]{6, 60}));
- CP_MAP_FOR_INTERFACE.put(12, new ConstantPoolEntry(ConstantTypes.CONSTANT_FIELDREF, new int[]{13, 63}));
- CP_MAP_FOR_INTERFACE.put(13, new ConstantPoolEntry(ConstantTypes.CONSTANT_CLASS, 64));
- CP_MAP_FOR_INTERFACE.put(17, new ConstantPoolEntry(ConstantTypes.CONSTANT_INTEGER, 2147483647));
- CP_MAP_FOR_INTERFACE.put(20, new ConstantPoolEntry(ConstantTypes.CONSTANT_LONG, 9223372036854775807l));
- CP_MAP_FOR_INTERFACE.put(24, new ConstantPoolEntry(ConstantTypes.CONSTANT_FLOAT, 3.4028235E38f));
- CP_MAP_FOR_INTERFACE.put(27, new ConstantPoolEntry(ConstantTypes.CONSTANT_DOUBLE, 1.7976931348623157E308d));
- CP_MAP_FOR_INTERFACE.put(31, new ConstantPoolEntry(ConstantTypes.CONSTANT_STRING, 65));
- CP_MAP_FOR_INTERFACE.put(52, new ConstantPoolEntry(ConstantTypes.CONSTANT_NAMEANDTYPE, new int[]{34, 35}));
- CP_MAP_FOR_INTERFACE.put(55, new ConstantPoolEntry(ConstantTypes.CONSTANT_METHODHANDLE, new int[]{6, 67}));
- CP_MAP_FOR_INTERFACE.put(56, new ConstantPoolEntry(ConstantTypes.CONSTANT_METHODTYPE, 35));
- CP_MAP_FOR_INTERFACE.put(57, new ConstantPoolEntry(ConstantTypes.CONSTANT_METHODHANDLE, new int[]{9, 5}));
- CP_MAP_FOR_INTERFACE.put(58, new ConstantPoolEntry(ConstantTypes.CONSTANT_NAMEANDTYPE, new int[]{68, 69}));
- CP_MAP_FOR_INTERFACE.put(59, new ConstantPoolEntry(ConstantTypes.CONSTANT_NAMEANDTYPE, new int[]{70, 71}));
- CP_MAP_FOR_INTERFACE.put(60, new ConstantPoolEntry(ConstantTypes.CONSTANT_NAMEANDTYPE, new int[]{72, 35}));
- CP_MAP_FOR_INTERFACE.put(63, new ConstantPoolEntry(ConstantTypes.CONSTANT_NAMEANDTYPE, new int[]{32, 33}));
- CP_MAP_FOR_INTERFACE.put(67, new ConstantPoolEntry(ConstantTypes.CONSTANT_METHODREF, new int[]{73, 74}));
- CP_MAP_FOR_INTERFACE.put(73, new ConstantPoolEntry(ConstantTypes.CONSTANT_CLASS, 75));
- CP_MAP_FOR_INTERFACE.put(74, new ConstantPoolEntry(ConstantTypes.CONSTANT_NAMEANDTYPE, new int[]{76, 80}));
- CP_MAP_FOR_INTERFACE.put(77, new ConstantPoolEntry(ConstantTypes.CONSTANT_CLASS, 82));
+ CP_MAP_FOR_ABS_CLASS.put(CONSTANT_CLASS,
+ new TestedCPEntry[] {
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementersInterface", null, null),
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer", null, null),
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer$1", null, null),
+ new TestedCPEntry("java/lang/invoke/MethodHandles$Lookup", null, null),
+ }
+ );
+ CP_MAP_FOR_ABS_CLASS.put(CONSTANT_FIELDREF,
+ new TestedCPEntry[] {
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer",
+ "intStaticField",
+ "I",
+ new byte[] {(byte) Opcodes.PUTSTATIC, (byte) Opcodes.GETSTATIC},
+ Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC),
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer",
+ "longStaticField",
+ "J",
+ new byte[] {(byte) Opcodes.PUTSTATIC, (byte) Opcodes.GETSTATIC},
+ Opcodes.ACC_FINAL | Opcodes.ACC_STATIC),
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer",
+ "floatStaticField",
+ "F",
+ new byte[] {(byte) Opcodes.PUTSTATIC, (byte) Opcodes.GETSTATIC},
+ Opcodes.ACC_VOLATILE | Opcodes.ACC_STATIC),
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer",
+ "doubleStaticField",
+ "D",
+ new byte[] {(byte) Opcodes.PUTSTATIC, (byte) Opcodes.GETSTATIC},
+ Opcodes.ACC_STATIC),
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer",
+ "stringStaticField",
+ "Ljava/lang/String;",
+ new byte[] {(byte) Opcodes.PUTSTATIC, (byte) Opcodes.GETSTATIC},
+ Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC),
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer",
+ "objectStaticField",
+ "Ljava/lang/Object;",
+ new byte[] {(byte) Opcodes.PUTSTATIC, (byte) Opcodes.GETSTATIC},
+ Opcodes.ACC_PROTECTED | Opcodes.ACC_STATIC),
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer",
+ "intField",
+ "I",
+ new byte[] {(byte) Opcodes.PUTFIELD | (byte) Opcodes.GETFIELD},
+ Opcodes.ACC_PUBLIC),
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer",
+ "longField",
+ "J",
+ new byte[] {(byte) Opcodes.PUTFIELD | (byte) Opcodes.GETFIELD},
+ Opcodes.ACC_PRIVATE),
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer",
+ "floatField",
+ "F",
+ new byte[] {(byte) Opcodes.PUTFIELD | (byte) Opcodes.GETFIELD},
+ Opcodes.ACC_PROTECTED),
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer",
+ "doubleField",
+ "D",
+ new byte[] {(byte) Opcodes.PUTFIELD | (byte) Opcodes.GETFIELD},
+ Opcodes.ACC_TRANSIENT),
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer",
+ "objectField",
+ "Ljava/lang/Object;",
+ new byte[] {(byte) Opcodes.PUTFIELD | (byte) Opcodes.GETFIELD},
+ Opcodes.ACC_FINAL),
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer",
+ "stringField",
+ "Ljava/lang/String;",
+ new byte[] {(byte) Opcodes.PUTFIELD | (byte) Opcodes.GETFIELD},
+ Opcodes.ACC_VOLATILE),
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer",
+ "stringFieldEmpty",
+ "Ljava/lang/String;",
+ new byte[] {(byte) Opcodes.PUTFIELD | (byte) Opcodes.GETFIELD},
+ 0L),
+ }
+ );
+ CP_MAP_FOR_ABS_CLASS.put(CONSTANT_METHODREF,
+ new TestedCPEntry[] {
+ new TestedCPEntry("java/lang/System",
+ "getProperties",
+ "()Ljava/util/Properties;",
+ new byte[] {(byte) Opcodes.INVOKESTATIC}),
+ new TestedCPEntry("java/util/HashMap",
+ "<init>",
+ "()V",
+ new byte[] {(byte) Opcodes.INVOKESPECIAL}),
+ new TestedCPEntry("java/lang/Object",
+ "toString",
+ "()Ljava/lang/String;",
+ new byte[] {(byte) Opcodes.INVOKESPECIAL,
+ (byte) Opcodes.INVOKEVIRTUAL}),
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer$1",
+ "<init>",
+ "(Lcompiler/jvmci/common/testcases/MultipleAbstractImplementer;)V",
+ new byte[0]),
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer$1",
+ "run",
+ "()V",
+ new byte[0]),
+ }
+ );
+ CP_MAP_FOR_ABS_CLASS.put(CONSTANT_INTERFACEMETHODREF,
+ new TestedCPEntry[] {
+ new TestedCPEntry("java/util/Map",
+ "put",
+ "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
+ new byte[] {(byte) Opcodes.INVOKEINTERFACE}),
+ new TestedCPEntry("java/util/Map",
+ "remove",
+ "(Ljava/lang/Object;)Ljava/lang/Object;",
+ new byte[] {(byte) Opcodes.INVOKEINTERFACE}),
+ }
+ );
+ CP_MAP_FOR_ABS_CLASS.put(CONSTANT_STRING,
+ new TestedCPEntry[] {
+ new TestedCPEntry(null, "Message", null),
+ new TestedCPEntry(null, "", null),
+ }
+ );
+ CP_MAP_FOR_ABS_CLASS.put(CONSTANT_METHODHANDLE,
+ new TestedCPEntry[] {
+ new TestedCPEntry("java/lang/invoke/LambdaMetafactory",
+ "metafactory",
+ "(Ljava/lang/invoke/MethodHandles$Lookup;"
+ + "Ljava/lang/String;"
+ + "Ljava/lang/invoke/MethodType;"
+ + "Ljava/lang/invoke/MethodType;"
+ + "Ljava/lang/invoke/MethodHandle;"
+ + "Ljava/lang/invoke/MethodType;)"
+ + "Ljava/lang/invoke/CallSite;",
+ null),
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer",
+ "testMethod",
+ "()V"),
+ }
+ );
+ CP_MAP_FOR_ABS_CLASS.put(CONSTANT_METHODTYPE,
+ new TestedCPEntry[] {
+ new TestedCPEntry(null, null, "()V"),
+ }
+ );
+ CP_MAP_FOR_ABS_CLASS.put(CONSTANT_INVOKEDYNAMIC,
+ new TestedCPEntry[] {
+ new TestedCPEntry(null,
+ "run",
+ "(Lcompiler/jvmci/common/testcases/MultipleAbstractImplementer;)"
+ + "Ljava/lang/Runnable;"),
+ }
+ );
+ }
+
+ private static final Map<ConstantTypes, TestedCPEntry[]> CP_MAP_FOR_INTERFACE
+ = new HashMap<>();
+ static {
+ CP_MAP_FOR_INTERFACE.put(CONSTANT_CLASS,
+ new TestedCPEntry[] {
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementersInterface", null, null),
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementersInterface$1", null, null),
+ new TestedCPEntry("java/lang/Object", null, null),
+ new TestedCPEntry("java/lang/invoke/MethodHandles$Lookup", null, null),
+ }
+ );
+ CP_MAP_FOR_INTERFACE.put(CONSTANT_FIELDREF,
+ new TestedCPEntry[] {
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementersInterface",
+ "OBJECT_CONSTANT",
+ "Ljava/lang/Object;",
+ new byte[] {(byte) Opcodes.PUTSTATIC, (byte) Opcodes.GETSTATIC},
+ Opcodes.ACC_STATIC | Opcodes.ACC_FINAL | Opcodes.ACC_PUBLIC),
+ }
+ );
+ CP_MAP_FOR_INTERFACE.put(CONSTANT_METHODREF,
+ new TestedCPEntry[] {
+ new TestedCPEntry("java/lang/System",
+ "getProperties",
+ "()Ljava/util/Properties;",
+ new byte[] {(byte) Opcodes.INVOKESTATIC}),
+ new TestedCPEntry("java/util/HashMap",
+ "<init>",
+ "()V",
+ new byte[] {(byte) Opcodes.INVOKESPECIAL}),
+ new TestedCPEntry("java/lang/Object",
+ "toString",
+ "()Ljava/lang/String;",
+ new byte[] {(byte) Opcodes.INVOKEVIRTUAL}),
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer$1",
+ "<init>",
+ "(Lcompiler/jvmci/common/testcases/MultipleAbstractImplementer;)V",
+ new byte[0]),
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer$1",
+ "run",
+ "()V",
+ new byte[0]),
+ }
+ );
+ CP_MAP_FOR_INTERFACE.put(CONSTANT_INTERFACEMETHODREF,
+ new TestedCPEntry[] {
+ new TestedCPEntry("java/util/Map",
+ "put",
+ "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
+ new byte[] {(byte) Opcodes.INVOKEINTERFACE}),
+ new TestedCPEntry("java/util/Map",
+ "remove",
+ "(Ljava/lang/Object;)Ljava/lang/Object;",
+ new byte[] {(byte) Opcodes.INVOKEINTERFACE}),
+ }
+ );
+ CP_MAP_FOR_INTERFACE.put(CONSTANT_STRING,
+ new TestedCPEntry[] {
+ new TestedCPEntry(null, "Hello", null),
+ new TestedCPEntry(null, "", null),
+ }
+ );
+ CP_MAP_FOR_INTERFACE.put(CONSTANT_METHODHANDLE,
+ new TestedCPEntry[] {
+ new TestedCPEntry("java/lang/invoke/LambdaMetafactory",
+ "metafactory",
+ "(Ljava/lang/invoke/MethodHandles$Lookup;"
+ + "Ljava/lang/String;Ljava/lang/invoke/MethodType;"
+ + "Ljava/lang/invoke/MethodType;"
+ + "Ljava/lang/invoke/MethodHandle;"
+ + "Ljava/lang/invoke/MethodType;)"
+ + "Ljava/lang/invoke/CallSite;"),
+ new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementersInterface",
+ "defaultMethod",
+ "()V"),
+ }
+ );
+ CP_MAP_FOR_INTERFACE.put(CONSTANT_METHODTYPE,
+ new TestedCPEntry[] {
+ new TestedCPEntry(null, null, "()V"),
+ }
+ );
+ CP_MAP_FOR_INTERFACE.put(CONSTANT_INVOKEDYNAMIC,
+ new TestedCPEntry[] {
+ new TestedCPEntry(null,
+ "run",
+ "(Lcompiler/jvmci/common/testcases/MultipleImplementersInterface;)"
+ + "Ljava/lang/Runnable;"),
+ }
+ );
}
}
--- a/hotspot/test/compiler/jvmci/compilerToVM/JVM_RegisterJVMCINatives.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/JVM_RegisterJVMCINatives.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -27,6 +27,8 @@
* @bug 8136421
* @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
* @library /testlibrary /
+ * @modules jdk.vm.ci/jdk.vm.ci.hotspot
+ * jdk.vm.ci/jdk.vm.ci.runtime
* @run main/othervm -XX:+UnlockExperimentalVMOptions
* -Dcompiler.jvmci.compilerToVM.JVM_RegisterJVMCINatives.positive=true
* -XX:+EnableJVMCI
--- a/hotspot/test/compiler/jvmci/compilerToVM/LookupKlassInPoolTest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/LookupKlassInPoolTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -29,58 +29,73 @@
* @summary Testing compiler.jvmci.CompilerToVM.lookupKlassInPool method
* @library /testlibrary /test/lib /
* @compile ../common/CompilerToVMHelper.java
- * @build compiler.jvmci.common.testcases.MultipleImplementersInterface
- * compiler.jvmci.common.testcases.MultipleImplementer2
- * compiler.jvmci.compilerToVM.ConstantPoolTestsHelper
- * compiler.jvmci.compilerToVM.ConstantPoolTestCase
+ * @build sun.hotspot.WhiteBox
* compiler.jvmci.compilerToVM.LookupKlassInPoolTest
- * @run main ClassFileInstaller jdk.vm.ci.hotspot.CompilerToVMHelper
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockExperimentalVMOptions
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions
* -XX:+EnableJVMCI compiler.jvmci.compilerToVM.LookupKlassInPoolTest
*/
package compiler.jvmci.compilerToVM;
+import compiler.jvmci.compilerToVM.ConstantPoolTestsHelper.DummyClasses;
+import compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes;
+import static compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes.*;
+import compiler.jvmci.compilerToVM.ConstantPoolTestCase.TestedCPEntry;
+import compiler.jvmci.compilerToVM.ConstantPoolTestCase.Validator;
import java.util.HashMap;
import java.util.Map;
import jdk.vm.ci.hotspot.CompilerToVMHelper;
import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
-import sun.reflect.ConstantPool;
+import jdk.vm.ci.meta.ConstantPool;
/**
- * Test for {@code compiler.jvmci.CompilerToVM.lookupKlassInPool} method
+ * Test for {@code jdk.vm.ci.hotspot.CompilerToVM.lookupKlassInPool} method
*/
public class LookupKlassInPoolTest {
- public static void main(String[] args) {
- Map<ConstantPoolTestsHelper.ConstantTypes,
- ConstantPoolTestCase.Validator> typeTests = new HashMap<>(1);
- typeTests.put(ConstantPoolTestsHelper.ConstantTypes.CONSTANT_CLASS,
- LookupKlassInPoolTest::validate);
+ public static void main(String[] args) throws Exception {
+ Map<ConstantTypes, Validator> typeTests = new HashMap<>();
+ typeTests.put(CONSTANT_CLASS, LookupKlassInPoolTest::validate);
ConstantPoolTestCase testCase = new ConstantPoolTestCase(typeTests);
testCase.test();
+ // The next "Class.forName" and repeating "testCase.test()"
+ // are here for the following reason.
+ // The first test run is without dummy class initialization,
+ // which means no constant pool cache exists.
+ // The second run is with initialized class (with constant pool cache available).
+ // Some CompilerToVM methods require different input
+ // depending on whether CP cache exists or not.
+ for (DummyClasses dummy : DummyClasses.values()) {
+ Class.forName(dummy.klass.getName());
+ }
+ testCase.test();
}
- public static void validate(jdk.vm.ci.meta.ConstantPool constantPoolCTVM,
- ConstantPool constantPoolSS,
- ConstantPoolTestsHelper.DummyClasses dummyClass, int i) {
- Object classToVerify = CompilerToVMHelper
- .lookupKlassInPool(constantPoolCTVM, i);
- if (!(classToVerify instanceof HotSpotResolvedObjectType)
- && !(classToVerify instanceof String)) {
- String msg = String.format("Output of method"
- + " CTVM.lookupKlassInPool is neither"
- + " a HotSpotResolvedObjectType, nor a String");
+ public static void validate(ConstantPool constantPoolCTVM,
+ ConstantTypes cpType,
+ DummyClasses dummyClass,
+ int i) {
+ TestedCPEntry entry = cpType.getTestedCPEntry(dummyClass, i);
+ if (entry == null) {
+ return;
+ }
+ Object classToVerify = CompilerToVMHelper.lookupKlassInPool(constantPoolCTVM, i);
+ if (!(classToVerify instanceof HotSpotResolvedObjectType) && !(classToVerify instanceof String)) {
+ String msg = String.format("Output of method CTVM.lookupKlassInPool is neither"
+ + " a HotSpotResolvedObjectType, nor a String");
throw new AssertionError(msg);
}
- int classNameIndex = (int) dummyClass.cp.get(i).value;
- String classNameToRefer
- = constantPoolSS.getUTF8At(classNameIndex);
+ String classNameToRefer = entry.klass;
String outputToVerify = classToVerify.toString();
if (!outputToVerify.contains(classNameToRefer)) {
- String msg = String.format("Wrong class accessed by constant"
- + " pool index %d: %s, but should be %s",
- i, outputToVerify, classNameToRefer);
+ String msg = String.format("Wrong class accessed by constant pool index %d: %s, but should be %s",
+ i,
+ outputToVerify,
+ classNameToRefer);
throw new AssertionError(msg);
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/LookupKlassRefIndexInPoolTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,102 @@
+/*
+ * 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
+ * @bug 8138708
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
+ * @library /testlibrary /test/lib /
+ * @compile ../common/CompilerToVMHelper.java
+ * @build sun.hotspot.WhiteBox
+ * compiler.jvmci.compilerToVM.LookupKlassRefIndexInPoolTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * compiler.jvmci.compilerToVM.LookupKlassRefIndexInPoolTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import compiler.jvmci.compilerToVM.ConstantPoolTestsHelper.DummyClasses;
+import compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes;
+import static compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes.*;
+import compiler.jvmci.compilerToVM.ConstantPoolTestCase.TestedCPEntry;
+import compiler.jvmci.compilerToVM.ConstantPoolTestCase.Validator;
+import java.util.HashMap;
+import java.util.Map;
+import jdk.test.lib.Asserts;
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.vm.ci.meta.ConstantPool;
+
+/**
+ * Test for {@code jdk.vm.ci.hotspot.CompilerToVM.lookupKlassRefIndexInPool} method
+ */
+public class LookupKlassRefIndexInPoolTest {
+
+ public static void main(String[] args) throws Exception {
+ Map<ConstantTypes, Validator> typeTests = new HashMap<>();
+ typeTests.put(CONSTANT_METHODREF, LookupKlassRefIndexInPoolTest::validate);
+ typeTests.put(CONSTANT_INTERFACEMETHODREF, LookupKlassRefIndexInPoolTest::validate);
+ typeTests.put(CONSTANT_FIELDREF, LookupKlassRefIndexInPoolTest::validate);
+ ConstantPoolTestCase testCase = new ConstantPoolTestCase(typeTests);
+ testCase.test();
+ // The next "Class.forName" and repeating "testCase.test()"
+ // are here for the following reason.
+ // The first test run is without dummy class initialization,
+ // which means no constant pool cache exists.
+ // The second run is with initialized class (with constant pool cache available).
+ // Some CompilerToVM methods require different input
+ // depending on whether CP cache exists or not.
+ for (DummyClasses dummy : DummyClasses.values()) {
+ Class.forName(dummy.klass.getName());
+ }
+ testCase.test();
+ }
+
+ private static void validate(ConstantPool constantPoolCTVM,
+ ConstantTypes cpType,
+ DummyClasses dummyClass,
+ int cpi) {
+ TestedCPEntry entry = cpType.getTestedCPEntry(dummyClass, cpi);
+ if (entry == null) {
+ return;
+ }
+ int index = cpi;
+ String cached = "";
+ int cpci = dummyClass.getCPCacheIndex(cpi);
+ if (cpci != ConstantPoolTestsHelper.NO_CP_CACHE_PRESENT) {
+ index = cpci;
+ cached = "cached ";
+ }
+ int indexToVerify = CompilerToVMHelper.lookupKlassRefIndexInPool(constantPoolCTVM, index);
+ int indexToRefer = dummyClass.constantPoolSS.getClassRefIndexAt(cpi);
+ String msg = String.format("Wrong class index returned by lookupKlassRefIndexInPool method "
+ + "applied to %sconstant pool index %d",
+ cached,
+ index);
+ Asserts.assertEQ(indexToRefer, indexToVerify, msg);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/LookupMethodInPoolTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,120 @@
+/*
+ * 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
+ * @bug 8138708
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
+ * @library /testlibrary /test/lib /
+ * @compile ../common/CompilerToVMHelper.java
+ * @build sun.hotspot.WhiteBox
+ * compiler.jvmci.compilerToVM.LookupMethodInPoolTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * compiler.jvmci.compilerToVM.LookupMethodInPoolTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import compiler.jvmci.compilerToVM.ConstantPoolTestsHelper.DummyClasses;
+import compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes;
+import static compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes.*;
+import compiler.jvmci.compilerToVM.ConstantPoolTestCase.TestedCPEntry;
+import compiler.jvmci.compilerToVM.ConstantPoolTestCase.Validator;
+import java.util.HashMap;
+import java.util.Map;
+import jdk.test.lib.Asserts;
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
+import jdk.vm.ci.meta.ConstantPool;
+
+/**
+ * Test for {@code jdk.vm.ci.hotspot.CompilerToVM.lookupMethodInPool} method
+ */
+public class LookupMethodInPoolTest {
+
+ public static void main(String[] args) throws Exception {
+ Map<ConstantTypes, Validator> typeTests = new HashMap<>();
+ typeTests.put(CONSTANT_METHODREF, LookupMethodInPoolTest::validate);
+ typeTests.put(CONSTANT_INTERFACEMETHODREF, LookupMethodInPoolTest::validate);
+ ConstantPoolTestCase testCase = new ConstantPoolTestCase(typeTests);
+ testCase.test();
+ // The next "Class.forName" and repeating "testCase.test()"
+ // are here for the following reason.
+ // The first test run is without dummy class initialization,
+ // which means no constant pool cache exists.
+ // The second run is with initialized class (with constant pool cache available).
+ // Some CompilerToVM methods require different input
+ // depending on whether CP cache exists or not.
+ for (DummyClasses dummy : DummyClasses.values()) {
+ Class.forName(dummy.klass.getName());
+ }
+ testCase.test();
+ }
+
+ private static void validate(ConstantPool constantPoolCTVM,
+ ConstantTypes cpType,
+ DummyClasses dummyClass,
+ int cpi) {
+ TestedCPEntry entry = cpType.getTestedCPEntry(dummyClass, cpi);
+ if (entry == null) {
+ return;
+ }
+ int index = cpi;
+ String cached = "";
+ int cpci = dummyClass.getCPCacheIndex(cpi);
+ if (cpci != ConstantPoolTestsHelper.NO_CP_CACHE_PRESENT) {
+ index = cpci;
+ cached = "cached ";
+ }
+ for (int j = 0; j < entry.opcodes.length; j++) {
+ HotSpotResolvedJavaMethod methodToVerify = CompilerToVMHelper
+ .lookupMethodInPool(constantPoolCTVM, index, entry.opcodes[j]);
+ String msg = String.format("Object returned by lookupMethodInPool method"
+ + " for %sindex %d should not be null",
+ cached,
+ index);
+ Asserts.assertNotNull(methodToVerify, msg);
+ String[] classNameSplit = entry.klass.split("/");
+ String classNameToRefer = classNameSplit[classNameSplit.length - 1];
+ String methodNameToRefer = entry.name;
+ String methodToVerifyToString = methodToVerify.toString();
+ if (!methodToVerifyToString.contains(classNameToRefer)
+ || !methodToVerifyToString.contains(methodNameToRefer)) {
+ msg = String.format("String representation \"%s\" of the object"
+ + " returned by lookupMethodInPool method"
+ + " for index %d does not contain a method's class name"
+ + " or method's name, should contain %s.%s",
+ methodToVerifyToString,
+ index,
+ classNameToRefer,
+ methodNameToRefer);
+ throw new AssertionError(msg);
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/LookupNameAndTypeRefIndexInPoolTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,103 @@
+/*
+ * 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
+ * @bug 8138708
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
+ * @library /testlibrary /test/lib /
+ * @compile ../common/CompilerToVMHelper.java
+ * @build sun.hotspot.WhiteBox
+ * compiler.jvmci.compilerToVM.LookupNameAndTypeRefIndexInPoolTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * compiler.jvmci.compilerToVM.LookupNameAndTypeRefIndexInPoolTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import compiler.jvmci.compilerToVM.ConstantPoolTestsHelper.DummyClasses;
+import compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes;
+import static compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes.*;
+import compiler.jvmci.compilerToVM.ConstantPoolTestCase.TestedCPEntry;
+import compiler.jvmci.compilerToVM.ConstantPoolTestCase.Validator;
+import java.util.HashMap;
+import java.util.Map;
+import jdk.test.lib.Asserts;
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.vm.ci.meta.ConstantPool;
+
+/**
+ * Test for {@code jdk.vm.ci.hotspot.CompilerToVM.lookupNameAndTypeRefIndexInPool} method
+ */
+public class LookupNameAndTypeRefIndexInPoolTest {
+
+ public static void main(String[] args) throws Exception {
+ Map<ConstantTypes, Validator> typeTests = new HashMap<>();
+ typeTests.put(CONSTANT_METHODREF, LookupNameAndTypeRefIndexInPoolTest::validate);
+ typeTests.put(CONSTANT_INTERFACEMETHODREF, LookupNameAndTypeRefIndexInPoolTest::validate);
+ typeTests.put(CONSTANT_FIELDREF, LookupNameAndTypeRefIndexInPoolTest::validate);
+ typeTests.put(CONSTANT_INVOKEDYNAMIC, LookupNameAndTypeRefIndexInPoolTest::validate);
+ ConstantPoolTestCase testCase = new ConstantPoolTestCase(typeTests);
+ testCase.test();
+ // The next "Class.forName" and repeating "testCase.test()"
+ // are here for the following reason.
+ // The first test run is without dummy class initialization,
+ // which means no constant pool cache exists.
+ // The second run is with initialized class (with constant pool cache available).
+ // Some CompilerToVM methods require different input
+ // depending on whether CP cache exists or not.
+ for (DummyClasses dummy : DummyClasses.values()) {
+ Class.forName(dummy.klass.getName());
+ }
+ testCase.test();
+ }
+
+ private static void validate(ConstantPool constantPoolCTVM,
+ ConstantTypes cpType,
+ DummyClasses dummyClass,
+ int cpi) {
+ TestedCPEntry entry = cpType.getTestedCPEntry(dummyClass, cpi);
+ if (entry == null) {
+ return;
+ }
+ int index = cpi;
+ String cached = "";
+ int cpci = dummyClass.getCPCacheIndex(cpi);
+ if (cpci != ConstantPoolTestsHelper.NO_CP_CACHE_PRESENT) {
+ index = cpci;
+ cached = "cached ";
+ }
+ int indexToVerify = CompilerToVMHelper.lookupNameAndTypeRefIndexInPool(constantPoolCTVM, index);
+ int indexToRefer = dummyClass.constantPoolSS.getNameAndTypeRefIndexAt(cpi);
+ String msg = String.format("Wrong nameAndType index returned by lookupNameAndTypeRefIndexInPool"
+ + " method applied to %sconstant pool index %d",
+ cached,
+ index);
+ Asserts.assertEQ(indexToRefer, indexToVerify, msg);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/LookupNameInPoolTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,100 @@
+/*
+ * 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
+ * @bug 8138708
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
+ * @library /testlibrary /test/lib /
+ * @compile ../common/CompilerToVMHelper.java
+ * @build sun.hotspot.WhiteBox
+ * compiler.jvmci.compilerToVM.LookupNameInPoolTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * compiler.jvmci.compilerToVM.LookupNameInPoolTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import compiler.jvmci.compilerToVM.ConstantPoolTestsHelper.DummyClasses;
+import compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes;
+import static compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes.*;
+import compiler.jvmci.compilerToVM.ConstantPoolTestCase.TestedCPEntry;
+import compiler.jvmci.compilerToVM.ConstantPoolTestCase.Validator;
+import java.util.HashMap;
+import java.util.Map;
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.vm.ci.meta.ConstantPool;
+import jdk.test.lib.Asserts;
+
+/**
+ * Test for {@code jdk.vm.ci.hotspot.CompilerToVM.lookupNameInPool} method
+ */
+public class LookupNameInPoolTest {
+
+ public static void main(String[] args) throws Exception {
+ Map<ConstantTypes, Validator> typeTests = new HashMap<>();
+ typeTests.put(CONSTANT_METHODREF, LookupNameInPoolTest::validate);
+ typeTests.put(CONSTANT_INTERFACEMETHODREF, LookupNameInPoolTest::validate);
+ typeTests.put(CONSTANT_FIELDREF, LookupNameInPoolTest::validate);
+ typeTests.put(CONSTANT_INVOKEDYNAMIC, LookupNameInPoolTest::validate);
+ ConstantPoolTestCase testCase = new ConstantPoolTestCase(typeTests);
+ testCase.test();
+ // The next "Class.forName" and repeating "testCase.test()"
+ // are here for the following reason.
+ // The first test run is without dummy class initialization,
+ // which means no constant pool cache exists.
+ // The second run is with initialized class (with constant pool cache available).
+ // Some CompilerToVM methods require different input
+ // depending on whether CP cache exists or not.
+ for (DummyClasses dummy : DummyClasses.values()) {
+ Class.forName(dummy.klass.getName());
+ }
+ testCase.test();
+ }
+
+ private static void validate(ConstantPool constantPoolCTVM,
+ ConstantTypes cpType,
+ DummyClasses dummyClass,
+ int cpi) {
+ TestedCPEntry entry = cpType.getTestedCPEntry(dummyClass, cpi);
+ if (entry == null) {
+ return;
+ }
+ int index = cpi;
+ String cached = "";
+ int cpci = dummyClass.getCPCacheIndex(cpi);
+ if (cpci != ConstantPoolTestsHelper.NO_CP_CACHE_PRESENT) {
+ index = cpci;
+ cached = "cached ";
+ }
+ String nameToVerify = CompilerToVMHelper.lookupNameInPool(constantPoolCTVM, index);
+ String nameToRefer = entry.name;
+ String msg = String.format("Wrong name accessed by %sconstant pool index %d", cached, index);
+ Asserts.assertEQ(nameToVerify, nameToRefer, msg);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/LookupSignatureInPoolTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,102 @@
+/*
+ * 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
+ * @bug 8138708
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
+ * @library /testlibrary /test/lib /
+ * @compile ../common/CompilerToVMHelper.java
+ * @build sun.hotspot.WhiteBox
+ * compiler.jvmci.compilerToVM.LookupSignatureInPoolTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * compiler.jvmci.compilerToVM.LookupSignatureInPoolTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import compiler.jvmci.compilerToVM.ConstantPoolTestsHelper.DummyClasses;
+import compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes;
+import static compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes.*;
+import compiler.jvmci.compilerToVM.ConstantPoolTestCase.TestedCPEntry;
+import compiler.jvmci.compilerToVM.ConstantPoolTestCase.Validator;
+import java.util.HashMap;
+import java.util.Map;
+import jdk.test.lib.Asserts;
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.vm.ci.meta.ConstantPool;
+
+/**
+ * Test for {@code jdk.vm.ci.hotspot.CompilerToVM.lookupSignatureInPool} method
+ */
+public class LookupSignatureInPoolTest {
+
+ public static void main(String[] args) throws Exception {
+ Map<ConstantTypes, Validator> typeTests = new HashMap<>();
+ typeTests.put(CONSTANT_METHODREF, LookupSignatureInPoolTest::validate);
+ typeTests.put(CONSTANT_INTERFACEMETHODREF, LookupSignatureInPoolTest::validate);
+ typeTests.put(CONSTANT_FIELDREF, LookupSignatureInPoolTest::validate);
+ typeTests.put(CONSTANT_INVOKEDYNAMIC, LookupSignatureInPoolTest::validate);
+ ConstantPoolTestCase testCase = new ConstantPoolTestCase(typeTests);
+ testCase.test();
+ // The next "Class.forName" and repeating "testCase.test()"
+ // are here for the following reason.
+ // The first test run is without dummy class initialization,
+ // which means no constant pool cache exists.
+ // The second run is with initialized class (with constant pool cache available).
+ // Some CompilerToVM methods require different input
+ // depending on whether CP cache exists or not.
+ for (DummyClasses dummy : DummyClasses.values()) {
+ Class.forName(dummy.klass.getName());
+ }
+ testCase.test();
+ }
+
+ private static void validate(ConstantPool constantPoolCTVM,
+ ConstantTypes cpType,
+ DummyClasses dummyClass,
+ int cpi) {
+ TestedCPEntry entry = cpType.getTestedCPEntry(dummyClass, cpi);
+ if (entry == null) {
+ return;
+ }
+ int index = cpi;
+ String cached = "";
+ int cpci = dummyClass.getCPCacheIndex(cpi);
+ if (cpci != ConstantPoolTestsHelper.NO_CP_CACHE_PRESENT) {
+ index = cpci;
+ cached = "cached ";
+ }
+ String sigToVerify = CompilerToVMHelper.lookupSignatureInPool(constantPoolCTVM, index);
+ String sigToRefer = entry.type;
+ String msg = String.format("Wrong signature accessed by %sconstant pool index %d",
+ cached,
+ index);
+ Asserts.assertEQ(sigToVerify, sigToRefer, msg);
+ }
+}
--- a/hotspot/test/compiler/jvmci/compilerToVM/ResolveConstantInPoolTest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ResolveConstantInPoolTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -28,66 +28,86 @@
* @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
* @library /testlibrary /test/lib /
* @compile ../common/CompilerToVMHelper.java
- * @build compiler.jvmci.compilerToVM.ResolveConstantInPoolTest
- * @run main ClassFileInstaller jdk.vm.ci.hotspot.CompilerToVMHelper
- * @run main/othervm -Xbootclasspath/a:.
- * -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * @build sun.hotspot.WhiteBox
+ * compiler.jvmci.compilerToVM.ResolveConstantInPoolTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
* compiler.jvmci.compilerToVM.ResolveConstantInPoolTest
*/
package compiler.jvmci.compilerToVM;
+import compiler.jvmci.compilerToVM.ConstantPoolTestsHelper.DummyClasses;
+import compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes;
+import static compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes.*;
+import compiler.jvmci.compilerToVM.ConstantPoolTestCase.Validator;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodType;
import java.util.HashMap;
import java.util.Map;
+import jdk.test.lib.Asserts;
import jdk.vm.ci.hotspot.CompilerToVMHelper;
-import jdk.test.lib.Asserts;
-import sun.reflect.ConstantPool;
+import jdk.vm.ci.meta.ConstantPool;
/**
- * Test for {@code compiler.jvmci.CompilerToVM.resolveConstantInPool} method
+ * Test for {@code jdk.vm.ci.hotspot.CompilerToVM.resolveConstantInPool} method
*/
public class ResolveConstantInPoolTest {
+ private static final String NOT_NULL_MSG
+ = "Object returned by resolveConstantInPool method should not be null";
+
public static void main(String[] args) throws Exception {
- Map<ConstantPoolTestsHelper.ConstantTypes,
- ConstantPoolTestCase.Validator> typeTests = new HashMap<>(2);
- typeTests.put(ConstantPoolTestsHelper.ConstantTypes.CONSTANT_METHODHANDLE,
- ResolveConstantInPoolTest::validateMethodHandle);
- typeTests.put(ConstantPoolTestsHelper.ConstantTypes.CONSTANT_METHODTYPE,
- ResolveConstantInPoolTest::validateMethodType);
+ Map<ConstantTypes, Validator> typeTests = new HashMap<>();
+ typeTests.put(CONSTANT_METHODHANDLE, ResolveConstantInPoolTest::validateMethodHandle);
+ typeTests.put(CONSTANT_METHODTYPE, ResolveConstantInPoolTest::validateMethodType);
ConstantPoolTestCase testCase = new ConstantPoolTestCase(typeTests);
testCase.test();
+ // The next "Class.forName" and repeating "testCase.test()"
+ // are here for the following reason.
+ // The first test run is without dummy class initialization,
+ // which means no constant pool cache exists.
+ // The second run is with initialized class (with constant pool cache available).
+ // Some CompilerToVM methods require different input
+ // depending on whether CP cache exists or not.
+ for (DummyClasses dummy : DummyClasses.values()) {
+ Class.forName(dummy.klass.getName());
+ }
+ testCase.test();
}
- private static void validateMethodHandle(
- jdk.vm.ci.meta.ConstantPool constantPoolCTVM,
- ConstantPool constantPoolSS,
- ConstantPoolTestsHelper.DummyClasses dummyClass, int index) {
- Object constantInPool = CompilerToVMHelper
- .resolveConstantInPool(constantPoolCTVM, index);
+ private static void validateMethodHandle(ConstantPool constantPoolCTVM,
+ ConstantTypes cpType,
+ DummyClasses dummyClass,
+ int index) {
+ Object constantInPool = CompilerToVMHelper.resolveConstantInPool(constantPoolCTVM, index);
+ String msg = String.format("%s for index %d", NOT_NULL_MSG, index);
+ Asserts.assertNotNull(constantInPool, msg);
if (!(constantInPool instanceof MethodHandle)) {
- String msg = String.format(
- "Wrong constant pool entry accessed by index"
- + " %d: %s, but should be subclass of %s",
- index + 1, constantInPool.getClass(),
- MethodHandle.class.getName());
+ msg = String.format("Wrong constant pool entry accessed by index"
+ + " %d: %s, but should be subclass of %s",
+ index,
+ constantInPool.getClass(),
+ MethodHandle.class.getName());
throw new AssertionError(msg);
}
}
- private static void validateMethodType(
- jdk.vm.ci.meta.ConstantPool constantPoolCTVM,
- ConstantPool constantPoolSS,
- ConstantPoolTestsHelper.DummyClasses dummyClass, int index) {
- Object constantInPool = CompilerToVMHelper
- .resolveConstantInPool(constantPoolCTVM, index);
+ private static void validateMethodType(ConstantPool constantPoolCTVM,
+ ConstantTypes cpType,
+ DummyClasses dummyClass,
+ int index) {
+ Object constantInPool = CompilerToVMHelper.resolveConstantInPool(constantPoolCTVM, index);
+ String msg = String.format("%s for index %d", NOT_NULL_MSG, index);
+ Asserts.assertNotNull(constantInPool, msg);
Class mtToVerify = constantInPool.getClass();
Class mtToRefer = MethodType.class;
- String msg = String.format("Wrong %s accessed by constant pool index"
- + " %d: %s, but should be %s", "method type class",
- index, mtToVerify, mtToRefer);
+ msg = String.format("Wrong method type class accessed by"
+ + " constant pool index %d",
+ index);
Asserts.assertEQ(mtToRefer, mtToVerify, msg);
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ResolveFieldInPoolTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,159 @@
+/*
+ * 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
+ * @bug 8138708
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
+ * @library /testlibrary /test/lib /
+ * @compile ../common/CompilerToVMHelper.java
+ * @build sun.hotspot.WhiteBox
+ * compiler.jvmci.compilerToVM.ResolveFieldInPoolTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * compiler.jvmci.compilerToVM.ResolveFieldInPoolTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import compiler.jvmci.compilerToVM.ConstantPoolTestsHelper.DummyClasses;
+import compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes;
+import static compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes.*;
+import compiler.jvmci.compilerToVM.ConstantPoolTestCase.TestedCPEntry;
+import compiler.jvmci.compilerToVM.ConstantPoolTestCase.Validator;
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Map;
+import jdk.internal.org.objectweb.asm.Opcodes;
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
+import jdk.vm.ci.meta.ConstantPool;
+import jdk.test.lib.Asserts;
+import jdk.test.lib.Utils;
+import sun.misc.Unsafe;
+
+/**
+ * Test for {@code jdk.vm.ci.hotspot.CompilerToVM.resolveFieldInPool} method
+ */
+public class ResolveFieldInPoolTest {
+
+ private static final Unsafe UNSAFE = Utils.getUnsafe();
+
+ public static void main(String[] args) throws Exception {
+ Map<ConstantTypes, Validator> typeTests = new HashMap<>();
+ typeTests.put(CONSTANT_FIELDREF, ResolveFieldInPoolTest::validate);
+ ConstantPoolTestCase testCase = new ConstantPoolTestCase(typeTests);
+ testCase.test();
+ // The next "Class.forName" and repeating "testCase.test()"
+ // are here for the following reason.
+ // The first test run is without dummy class initialization,
+ // which means no constant pool cache exists.
+ // The second run is with initialized class (with constant pool cache available).
+ // Some CompilerToVM methods require different input
+ // depending on whether CP cache exists or not.
+ for (DummyClasses dummy : DummyClasses.values()) {
+ Class.forName(dummy.klass.getName());
+ }
+ testCase.test();
+ }
+
+ private static void validate(ConstantPool constantPoolCTVM,
+ ConstantTypes cpType,
+ DummyClasses dummyClass,
+ int cpi) {
+ TestedCPEntry entry = cpType.getTestedCPEntry(dummyClass, cpi);
+ if (entry == null) {
+ return;
+ }
+ int index = cpi;
+ String cached = "";
+ int cpci = dummyClass.getCPCacheIndex(cpi);
+ if (cpci != ConstantPoolTestsHelper.NO_CP_CACHE_PRESENT) {
+ index = cpci;
+ cached = "cached ";
+ }
+ for (int j = 0; j < entry.opcodes.length; j++) {
+ long[] info = new long[2];
+ HotSpotResolvedObjectType fieldToVerify
+ = CompilerToVMHelper.resolveFieldInPool(constantPoolCTVM,
+ index,
+ entry.opcodes[j],
+ info);
+ String msg = String.format("Object returned by resolveFieldInPool method"
+ + " for %sindex %d should not be null",
+ cached,
+ index);
+ Asserts.assertNotNull(fieldToVerify, msg);
+ String classNameToRefer = entry.klass;
+ String fieldToVerifyKlassToString = fieldToVerify.klass().toValueString();
+ if (!fieldToVerifyKlassToString.contains(classNameToRefer)) {
+ msg = String.format("String representation \"%s\" of the object"
+ + " returned by resolveFieldInPool method"
+ + " for index %d does not contain a field's class name,"
+ + " should contain %s",
+ fieldToVerifyKlassToString,
+ index,
+ classNameToRefer);
+ throw new AssertionError(msg);
+ }
+ msg = String.format("Access flags returned by resolveFieldInPool"
+ + " method are wrong for the field %s.%s"
+ + " at %sindex %d",
+ entry.klass,
+ entry.name,
+ cached,
+ index);
+ Asserts.assertEQ(info[0], entry.accFlags, msg);
+ if (cpci == -1) {
+ return;
+ }
+ Class classOfTheField = null;
+ Field fieldToRefer = null;
+ try {
+ classOfTheField = Class.forName(classNameToRefer.replaceAll("/", "\\."));
+ fieldToRefer = classOfTheField.getDeclaredField(entry.name);
+ fieldToRefer.setAccessible(true);
+ } catch (Exception ex) {
+ throw new Error("Unexpected exception", ex);
+ }
+ long offsetToRefer;
+ if ((entry.accFlags & Opcodes.ACC_STATIC) != 0) {
+ offsetToRefer = UNSAFE.staticFieldOffset(fieldToRefer);
+ } else {
+ offsetToRefer = UNSAFE.objectFieldOffset(fieldToRefer);
+ }
+ msg = String.format("Field offset returned by resolveFieldInPool"
+ + " method is wrong for the field %s.%s"
+ + " at %sindex %d",
+ entry.klass,
+ entry.name,
+ cached,
+ index);
+ Asserts.assertEQ(info[1], offsetToRefer, msg);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ResolvePossiblyCachedConstantInPoolTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,96 @@
+/*
+ * 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
+ * @bug 8138708
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
+ * @library /testlibrary /test/lib /
+ * @compile ../common/CompilerToVMHelper.java
+ * @build sun.hotspot.WhiteBox
+ * compiler.jvmci.compilerToVM.ResolvePossiblyCachedConstantInPoolTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * compiler.jvmci.compilerToVM.ResolvePossiblyCachedConstantInPoolTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import compiler.jvmci.compilerToVM.ConstantPoolTestsHelper.DummyClasses;
+import compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes;
+import static compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes.*;
+import compiler.jvmci.compilerToVM.ConstantPoolTestCase.TestedCPEntry;
+import compiler.jvmci.compilerToVM.ConstantPoolTestCase.Validator;
+import java.util.HashMap;
+import java.util.Map;
+import jdk.test.lib.Asserts;
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.vm.ci.meta.ConstantPool;
+
+/**
+ * Test for {@code jdk.vm.ci.hotspot.CompilerToVM.resolvePossiblyCachedConstantInPool} method
+ */
+public class ResolvePossiblyCachedConstantInPoolTest {
+
+ public static void main(String[] args) throws Exception {
+ Map<ConstantTypes, Validator> typeTests = new HashMap<>();
+ typeTests.put(CONSTANT_STRING, ResolvePossiblyCachedConstantInPoolTest::validateString);
+ ConstantPoolTestCase testCase = new ConstantPoolTestCase(typeTests);
+ // The next "Class.forName" is here for the following reason.
+ // When class is initialized, constant pool cache is available.
+ // This method works only with cached constant pool.
+ for (DummyClasses dummy : DummyClasses.values()) {
+ Class.forName(dummy.klass.getName());
+ }
+ testCase.test();
+ }
+
+ private static void validateString(ConstantPool constantPoolCTVM,
+ ConstantTypes cpType,
+ DummyClasses dummyClass,
+ int cpi) {
+ TestedCPEntry entry = cpType.getTestedCPEntry(dummyClass, cpi);
+ if (entry == null) {
+ return;
+ }
+ int index = cpi;
+ String cached = "";
+ int cpci = dummyClass.getCPCacheIndex(cpi);
+ if (cpci != ConstantPoolTestsHelper.NO_CP_CACHE_PRESENT) {
+ index = cpci;
+ cached = "cached ";
+ }
+ Object constantInPool = CompilerToVMHelper.resolvePossiblyCachedConstantInPool(constantPoolCTVM, index);
+ String stringToVerify = (String) constantInPool;
+ String stringToRefer = entry.name;
+ if (stringToRefer.equals("") && cpci != ConstantPoolTestsHelper.NO_CP_CACHE_PRESENT) {
+ stringToRefer = null; // tested method returns null for cached empty strings
+ }
+ String msg = String.format("Wrong string accessed by %sconstant pool index %d", cached, index);
+ Asserts.assertEQ(stringToRefer, stringToVerify, msg);
+ }
+}
--- a/hotspot/test/compiler/jvmci/compilerToVM/ResolveTypeInPoolTest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ResolveTypeInPoolTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -29,51 +29,69 @@
* @summary Testing compiler.jvmci.CompilerToVM.resolveTypeInPool method
* @library /testlibrary /test/lib /
* @compile ../common/CompilerToVMHelper.java
- * @build compiler.jvmci.common.testcases.MultipleImplementersInterface
- * compiler.jvmci.common.testcases.MultipleImplementer2
- * compiler.jvmci.compilerToVM.ConstantPoolTestsHelper
- * compiler.jvmci.compilerToVM.ConstantPoolTestCase
+ * @build sun.hotspot.WhiteBox
* compiler.jvmci.compilerToVM.ResolveTypeInPoolTest
- * @run main ClassFileInstaller jdk.vm.ci.hotspot.CompilerToVMHelper
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockExperimentalVMOptions
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions
* -XX:+EnableJVMCI compiler.jvmci.compilerToVM.ResolveTypeInPoolTest
*/
package compiler.jvmci.compilerToVM;
+import compiler.jvmci.compilerToVM.ConstantPoolTestsHelper.DummyClasses;
+import compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes;
+import static compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes.*;
+import compiler.jvmci.compilerToVM.ConstantPoolTestCase.TestedCPEntry;
+import compiler.jvmci.compilerToVM.ConstantPoolTestCase.Validator;
import java.util.HashMap;
import java.util.Map;
import jdk.vm.ci.hotspot.CompilerToVMHelper;
import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
-import sun.reflect.ConstantPool;
+import jdk.vm.ci.meta.ConstantPool;
/**
- * Test for {@code compiler.jvmci.CompilerToVM.resolveTypeInPool} method
+ * Test for {@code jdk.vm.ci.hotspot.CompilerToVM.resolveTypeInPool} method
*/
public class ResolveTypeInPoolTest {
public static void main(String[] args) throws Exception {
- Map<ConstantPoolTestsHelper.ConstantTypes,
- ConstantPoolTestCase.Validator> typeTests = new HashMap<>(1);
- typeTests.put(ConstantPoolTestsHelper.ConstantTypes.CONSTANT_CLASS,
- ResolveTypeInPoolTest::validate);
+ Map<ConstantTypes, Validator> typeTests = new HashMap<>();
+ typeTests.put(CONSTANT_CLASS, ResolveTypeInPoolTest::validate);
ConstantPoolTestCase testCase = new ConstantPoolTestCase(typeTests);
testCase.test();
+ // The next "Class.forName" and repeating "testCase.test()"
+ // are here for the following reason.
+ // The first test run is without dummy class initialization,
+ // which means no constant pool cache exists.
+ // The second run is with initialized class (with constant pool cache available).
+ // Some CompilerToVM methods require different input
+ // depending on whether CP cache exists or not.
+ for (DummyClasses dummy : DummyClasses.values()) {
+ Class.forName(dummy.klass.getName());
+ }
+ testCase.test();
}
- public static void validate(
- jdk.vm.ci.meta.ConstantPool constantPoolCTVM,
- ConstantPool constantPoolSS,
- ConstantPoolTestsHelper.DummyClasses dummyClass, int i) {
- HotSpotResolvedObjectType typeToVerify = CompilerToVMHelper
- .resolveTypeInPool(constantPoolCTVM, i);
- int classNameIndex = (int) dummyClass.cp.get(i).value;
- String classNameToRefer = constantPoolSS.getUTF8At(classNameIndex);
+ public static void validate(ConstantPool constantPoolCTVM,
+ ConstantTypes cpType,
+ DummyClasses dummyClass,
+ int i) {
+ TestedCPEntry entry = cpType.getTestedCPEntry(dummyClass, i);
+ if (entry == null) {
+ return;
+ }
+ HotSpotResolvedObjectType typeToVerify = CompilerToVMHelper.resolveTypeInPool(constantPoolCTVM, i);
+ String classNameToRefer = entry.klass;
String outputToVerify = typeToVerify.toString();
if (!outputToVerify.contains(classNameToRefer)) {
String msg = String.format("Wrong class accessed by constant"
- + " pool index %d: %s, but should be %s",
- i, outputToVerify, classNameToRefer);
+ + " pool index %d: %s, but should be %s",
+ i,
+ outputToVerify,
+ classNameToRefer);
throw new AssertionError(msg);
}
}
--- a/hotspot/test/compiler/jvmci/errors/TestInvalidCompilationResult.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/compiler/jvmci/errors/TestInvalidCompilationResult.java Wed Mar 09 14:18:12 2016 +0100
@@ -24,7 +24,14 @@
/**
* @test
* @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
+ * @modules jdk.vm.ci/jdk.vm.ci.hotspot
+ * jdk.vm.ci/jdk.vm.ci.code
+ * jdk.vm.ci/jdk.vm.ci.code.site
+ * jdk.vm.ci/jdk.vm.ci.meta
+ * jdk.vm.ci/jdk.vm.ci.runtime
+ * jdk.vm.ci/jdk.vm.ci.common
* @compile CodeInstallerTest.java
+ * @build compiler.jvmci.errors.TestInvalidCompilationResult
* @run junit/othervm -da:jdk.vm.ci... -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI compiler.jvmci.errors.TestInvalidCompilationResult
*/
--- a/hotspot/test/compiler/jvmci/errors/TestInvalidDebugInfo.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/compiler/jvmci/errors/TestInvalidDebugInfo.java Wed Mar 09 14:18:12 2016 +0100
@@ -24,6 +24,12 @@
/**
* @test
* @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
+ * @modules jdk.vm.ci/jdk.vm.ci.hotspot
+ * jdk.vm.ci/jdk.vm.ci.code
+ * jdk.vm.ci/jdk.vm.ci.code.site
+ * jdk.vm.ci/jdk.vm.ci.meta
+ * jdk.vm.ci/jdk.vm.ci.runtime
+ * jdk.vm.ci/jdk.vm.ci.common
* @compile CodeInstallerTest.java
* @run junit/othervm -da:jdk.vm.ci... -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI compiler.jvmci.errors.TestInvalidDebugInfo
*/
--- a/hotspot/test/compiler/jvmci/errors/TestInvalidOopMap.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/compiler/jvmci/errors/TestInvalidOopMap.java Wed Mar 09 14:18:12 2016 +0100
@@ -24,6 +24,12 @@
/**
* @test
* @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
+ * @modules jdk.vm.ci/jdk.vm.ci.hotspot
+ * jdk.vm.ci/jdk.vm.ci.code
+ * jdk.vm.ci/jdk.vm.ci.code.site
+ * jdk.vm.ci/jdk.vm.ci.meta
+ * jdk.vm.ci/jdk.vm.ci.runtime
+ * jdk.vm.ci/jdk.vm.ci.common
* @compile CodeInstallerTest.java
* @run junit/othervm -da:jdk.vm.ci... -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI compiler.jvmci.errors.TestInvalidOopMap
*/
--- a/hotspot/test/compiler/jvmci/events/JvmciShutdownEventTest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/compiler/jvmci/events/JvmciShutdownEventTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -26,6 +26,10 @@
* @bug 8136421
* @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
* @library /testlibrary /
+ * @modules jdk.vm.ci/jdk.vm.ci.hotspot
+ * jdk.vm.ci/jdk.vm.ci.code
+ * jdk.vm.ci/jdk.vm.ci.meta
+ * jdk.vm.ci/jdk.vm.ci.runtime
* @build compiler.jvmci.common.JVMCIHelpers
* compiler.jvmci.events.JvmciShutdownEventListener
* compiler.jvmci.events.JvmciShutdownEventTest
@@ -36,10 +40,11 @@
* compiler.jvmci.common.JVMCIHelpers$EmptyHotspotCompiler
* compiler.jvmci.common.JVMCIHelpers$EmptyCompilerFactory
* compiler.jvmci.events.JvmciShutdownEventListener
- * @run driver
- * compiler.jvmci.events.JvmciShutdownEventTest
+ * @run main/othervm compiler.jvmci.events.JvmciShutdownEventTest
*/
+ // as soon as CODETOOLS-7901589 fixed, '@run main/othervm' at L43 should be replaced w/ '@run driver'
+
package compiler.jvmci.events;
import jdk.test.lib.ExitCode;
--- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveConcreteMethodTest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveConcreteMethodTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -24,6 +24,8 @@
/**
* @test
* @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
+ * @modules jdk.vm.ci/jdk.vm.ci.meta
+ * jdk.vm.ci/jdk.vm.ci.runtime
* @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.runtime.test.ResolvedJavaTypeResolveConcreteMethodTest
*/
--- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveMethodTest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveMethodTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -24,6 +24,8 @@
/**
* @test
* @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
+ * @modules jdk.vm.ci/jdk.vm.ci.meta
+ * jdk.vm.ci/jdk.vm.ci.runtime
* @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.runtime.test.ResolvedJavaTypeResolveMethodTest
*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/native/TestDirtyInt.java Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,46 @@
+/*
+ * 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
+ * @run main/native TestDirtyInt
+ */
+public class TestDirtyInt {
+ static {
+ System.loadLibrary("TestDirtyInt");
+ }
+
+ native static int test(int v);
+
+ static int compiled(int v) {
+ return test(v<<2);
+ }
+
+ static public void main(String[] args) {
+ for (int i = 0; i < 20000; i++) {
+ int res = compiled(Integer.MAX_VALUE);
+ if (res != 0x42) {
+ throw new RuntimeException("Test failed");
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/native/libTestDirtyInt.c Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+#include "jni.h"
+#include <stdio.h>
+
+static int array = 0x42;
+
+JNIEXPORT jint JNICALL Java_TestDirtyInt_test(JNIEnv* env, jclass jclazz, jint v)
+{
+ int* ptr = &array + v + 4;
+ return *ptr;
+}
--- a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestBoolean.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestBoolean.java Wed Mar 09 14:18:12 2016 +0100
@@ -128,6 +128,20 @@
}
+ // Lazy
+ {
+ UNSAFE.putBooleanRelease(base, offset, true);
+ boolean x = UNSAFE.getBooleanAcquire(base, offset);
+ assertEquals(x, true, "putRelease boolean value");
+ }
+
+ // Opaque
+ {
+ UNSAFE.putBooleanOpaque(base, offset, false);
+ boolean x = UNSAFE.getBooleanOpaque(base, offset);
+ assertEquals(x, false, "putOpaque boolean value");
+ }
+
}
--- a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestByte.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestByte.java Wed Mar 09 14:18:12 2016 +0100
@@ -157,6 +157,20 @@
}
+ // Lazy
+ {
+ UNSAFE.putByteRelease(base, offset, (byte)1);
+ byte x = UNSAFE.getByteAcquire(base, offset);
+ assertEquals(x, (byte)1, "putRelease byte value");
+ }
+
+ // Opaque
+ {
+ UNSAFE.putByteOpaque(base, offset, (byte)2);
+ byte x = UNSAFE.getByteOpaque(base, offset);
+ assertEquals(x, (byte)2, "putOpaque byte value");
+ }
+
}
--- a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestChar.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestChar.java Wed Mar 09 14:18:12 2016 +0100
@@ -157,6 +157,20 @@
}
+ // Lazy
+ {
+ UNSAFE.putCharRelease(base, offset, 'a');
+ char x = UNSAFE.getCharAcquire(base, offset);
+ assertEquals(x, 'a', "putRelease char value");
+ }
+
+ // Opaque
+ {
+ UNSAFE.putCharOpaque(base, offset, 'b');
+ char x = UNSAFE.getCharOpaque(base, offset);
+ assertEquals(x, 'b', "putOpaque char value");
+ }
+
// Unaligned
{
UNSAFE.putCharUnaligned(base, offset, 'b');
--- a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestDouble.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestDouble.java Wed Mar 09 14:18:12 2016 +0100
@@ -157,6 +157,20 @@
}
+ // Lazy
+ {
+ UNSAFE.putDoubleRelease(base, offset, 1.0d);
+ double x = UNSAFE.getDoubleAcquire(base, offset);
+ assertEquals(x, 1.0d, "putRelease double value");
+ }
+
+ // Opaque
+ {
+ UNSAFE.putDoubleOpaque(base, offset, 2.0d);
+ double x = UNSAFE.getDoubleOpaque(base, offset);
+ assertEquals(x, 2.0d, "putOpaque double value");
+ }
+
}
--- a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestFloat.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestFloat.java Wed Mar 09 14:18:12 2016 +0100
@@ -157,6 +157,20 @@
}
+ // Lazy
+ {
+ UNSAFE.putFloatRelease(base, offset, 1.0f);
+ float x = UNSAFE.getFloatAcquire(base, offset);
+ assertEquals(x, 1.0f, "putRelease float value");
+ }
+
+ // Opaque
+ {
+ UNSAFE.putFloatOpaque(base, offset, 2.0f);
+ float x = UNSAFE.getFloatOpaque(base, offset);
+ assertEquals(x, 2.0f, "putOpaque float value");
+ }
+
}
--- a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestInt.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestInt.java Wed Mar 09 14:18:12 2016 +0100
@@ -163,6 +163,20 @@
assertEquals(x, 1, "putRelease int value");
}
+ // Lazy
+ {
+ UNSAFE.putIntRelease(base, offset, 1);
+ int x = UNSAFE.getIntAcquire(base, offset);
+ assertEquals(x, 1, "putRelease int value");
+ }
+
+ // Opaque
+ {
+ UNSAFE.putIntOpaque(base, offset, 2);
+ int x = UNSAFE.getIntOpaque(base, offset);
+ assertEquals(x, 2, "putOpaque int value");
+ }
+
// Unaligned
{
UNSAFE.putIntUnaligned(base, offset, 2);
@@ -199,6 +213,70 @@
assertEquals(x, 2, "failing compareAndSwap int value");
}
+ // Advanced compare
+ {
+ int r = UNSAFE.compareAndExchangeIntVolatile(base, offset, 2, 1);
+ assertEquals(r, 2, "success compareAndExchangeVolatile int");
+ int x = UNSAFE.getInt(base, offset);
+ assertEquals(x, 1, "success compareAndExchangeVolatile int value");
+ }
+
+ {
+ int r = UNSAFE.compareAndExchangeIntVolatile(base, offset, 2, 3);
+ assertEquals(r, 1, "failing compareAndExchangeVolatile int");
+ int x = UNSAFE.getInt(base, offset);
+ assertEquals(x, 1, "failing compareAndExchangeVolatile int value");
+ }
+
+ {
+ int r = UNSAFE.compareAndExchangeIntAcquire(base, offset, 1, 2);
+ assertEquals(r, 1, "success compareAndExchangeAcquire int");
+ int x = UNSAFE.getInt(base, offset);
+ assertEquals(x, 2, "success compareAndExchangeAcquire int value");
+ }
+
+ {
+ int r = UNSAFE.compareAndExchangeIntAcquire(base, offset, 1, 3);
+ assertEquals(r, 2, "failing compareAndExchangeAcquire int");
+ int x = UNSAFE.getInt(base, offset);
+ assertEquals(x, 2, "failing compareAndExchangeAcquire int value");
+ }
+
+ {
+ int r = UNSAFE.compareAndExchangeIntRelease(base, offset, 2, 1);
+ assertEquals(r, 2, "success compareAndExchangeRelease int");
+ int x = UNSAFE.getInt(base, offset);
+ assertEquals(x, 1, "success compareAndExchangeRelease int value");
+ }
+
+ {
+ int r = UNSAFE.compareAndExchangeIntRelease(base, offset, 2, 3);
+ assertEquals(r, 1, "failing compareAndExchangeRelease int");
+ int x = UNSAFE.getInt(base, offset);
+ assertEquals(x, 1, "failing compareAndExchangeRelease int value");
+ }
+
+ {
+ boolean r = UNSAFE.weakCompareAndSwapInt(base, offset, 1, 2);
+ assertEquals(r, true, "weakCompareAndSwap int");
+ int x = UNSAFE.getInt(base, offset);
+ assertEquals(x, 2, "weakCompareAndSwap int value");
+ }
+
+ {
+ boolean r = UNSAFE.weakCompareAndSwapIntAcquire(base, offset, 2, 1);
+ assertEquals(r, true, "weakCompareAndSwapAcquire int");
+ int x = UNSAFE.getInt(base, offset);
+ assertEquals(x, 1, "weakCompareAndSwapAcquire int");
+ }
+
+ {
+ boolean r = UNSAFE.weakCompareAndSwapIntRelease(base, offset, 1, 2);
+ assertEquals(r, true, "weakCompareAndSwapRelease int");
+ int x = UNSAFE.getInt(base, offset);
+ assertEquals(x, 2, "weakCompareAndSwapRelease int");
+ }
+
// Compare set and get
{
int o = UNSAFE.getAndSetInt(base, offset, 1);
--- a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestLong.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestLong.java Wed Mar 09 14:18:12 2016 +0100
@@ -163,6 +163,20 @@
assertEquals(x, 1L, "putRelease long value");
}
+ // Lazy
+ {
+ UNSAFE.putLongRelease(base, offset, 1L);
+ long x = UNSAFE.getLongAcquire(base, offset);
+ assertEquals(x, 1L, "putRelease long value");
+ }
+
+ // Opaque
+ {
+ UNSAFE.putLongOpaque(base, offset, 2L);
+ long x = UNSAFE.getLongOpaque(base, offset);
+ assertEquals(x, 2L, "putOpaque long value");
+ }
+
// Unaligned
{
UNSAFE.putLongUnaligned(base, offset, 2L);
@@ -199,6 +213,70 @@
assertEquals(x, 2L, "failing compareAndSwap long value");
}
+ // Advanced compare
+ {
+ long r = UNSAFE.compareAndExchangeLongVolatile(base, offset, 2L, 1L);
+ assertEquals(r, 2L, "success compareAndExchangeVolatile long");
+ long x = UNSAFE.getLong(base, offset);
+ assertEquals(x, 1L, "success compareAndExchangeVolatile long value");
+ }
+
+ {
+ long r = UNSAFE.compareAndExchangeLongVolatile(base, offset, 2L, 3L);
+ assertEquals(r, 1L, "failing compareAndExchangeVolatile long");
+ long x = UNSAFE.getLong(base, offset);
+ assertEquals(x, 1L, "failing compareAndExchangeVolatile long value");
+ }
+
+ {
+ long r = UNSAFE.compareAndExchangeLongAcquire(base, offset, 1L, 2L);
+ assertEquals(r, 1L, "success compareAndExchangeAcquire long");
+ long x = UNSAFE.getLong(base, offset);
+ assertEquals(x, 2L, "success compareAndExchangeAcquire long value");
+ }
+
+ {
+ long r = UNSAFE.compareAndExchangeLongAcquire(base, offset, 1L, 3L);
+ assertEquals(r, 2L, "failing compareAndExchangeAcquire long");
+ long x = UNSAFE.getLong(base, offset);
+ assertEquals(x, 2L, "failing compareAndExchangeAcquire long value");
+ }
+
+ {
+ long r = UNSAFE.compareAndExchangeLongRelease(base, offset, 2L, 1L);
+ assertEquals(r, 2L, "success compareAndExchangeRelease long");
+ long x = UNSAFE.getLong(base, offset);
+ assertEquals(x, 1L, "success compareAndExchangeRelease long value");
+ }
+
+ {
+ long r = UNSAFE.compareAndExchangeLongRelease(base, offset, 2L, 3L);
+ assertEquals(r, 1L, "failing compareAndExchangeRelease long");
+ long x = UNSAFE.getLong(base, offset);
+ assertEquals(x, 1L, "failing compareAndExchangeRelease long value");
+ }
+
+ {
+ boolean r = UNSAFE.weakCompareAndSwapLong(base, offset, 1L, 2L);
+ assertEquals(r, true, "weakCompareAndSwap long");
+ long x = UNSAFE.getLong(base, offset);
+ assertEquals(x, 2L, "weakCompareAndSwap long value");
+ }
+
+ {
+ boolean r = UNSAFE.weakCompareAndSwapLongAcquire(base, offset, 2L, 1L);
+ assertEquals(r, true, "weakCompareAndSwapAcquire long");
+ long x = UNSAFE.getLong(base, offset);
+ assertEquals(x, 1L, "weakCompareAndSwapAcquire long");
+ }
+
+ {
+ boolean r = UNSAFE.weakCompareAndSwapLongRelease(base, offset, 1L, 2L);
+ assertEquals(r, true, "weakCompareAndSwapRelease long");
+ long x = UNSAFE.getLong(base, offset);
+ assertEquals(x, 2L, "weakCompareAndSwapRelease long");
+ }
+
// Compare set and get
{
long o = UNSAFE.getAndSetLong(base, offset, 1L);
--- a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestObject.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestObject.java Wed Mar 09 14:18:12 2016 +0100
@@ -134,6 +134,20 @@
assertEquals(x, "foo", "putRelease Object value");
}
+ // Lazy
+ {
+ UNSAFE.putObjectRelease(base, offset, "foo");
+ Object x = UNSAFE.getObjectAcquire(base, offset);
+ assertEquals(x, "foo", "putRelease Object value");
+ }
+
+ // Opaque
+ {
+ UNSAFE.putObjectOpaque(base, offset, "bar");
+ Object x = UNSAFE.getObjectOpaque(base, offset);
+ assertEquals(x, "bar", "putOpaque Object value");
+ }
+
UNSAFE.putObject(base, offset, "foo");
@@ -152,6 +166,70 @@
assertEquals(x, "bar", "failing compareAndSwap Object value");
}
+ // Advanced compare
+ {
+ Object r = UNSAFE.compareAndExchangeObjectVolatile(base, offset, "bar", "foo");
+ assertEquals(r, "bar", "success compareAndExchangeVolatile Object");
+ Object x = UNSAFE.getObject(base, offset);
+ assertEquals(x, "foo", "success compareAndExchangeVolatile Object value");
+ }
+
+ {
+ Object r = UNSAFE.compareAndExchangeObjectVolatile(base, offset, "bar", "baz");
+ assertEquals(r, "foo", "failing compareAndExchangeVolatile Object");
+ Object x = UNSAFE.getObject(base, offset);
+ assertEquals(x, "foo", "failing compareAndExchangeVolatile Object value");
+ }
+
+ {
+ Object r = UNSAFE.compareAndExchangeObjectAcquire(base, offset, "foo", "bar");
+ assertEquals(r, "foo", "success compareAndExchangeAcquire Object");
+ Object x = UNSAFE.getObject(base, offset);
+ assertEquals(x, "bar", "success compareAndExchangeAcquire Object value");
+ }
+
+ {
+ Object r = UNSAFE.compareAndExchangeObjectAcquire(base, offset, "foo", "baz");
+ assertEquals(r, "bar", "failing compareAndExchangeAcquire Object");
+ Object x = UNSAFE.getObject(base, offset);
+ assertEquals(x, "bar", "failing compareAndExchangeAcquire Object value");
+ }
+
+ {
+ Object r = UNSAFE.compareAndExchangeObjectRelease(base, offset, "bar", "foo");
+ assertEquals(r, "bar", "success compareAndExchangeRelease Object");
+ Object x = UNSAFE.getObject(base, offset);
+ assertEquals(x, "foo", "success compareAndExchangeRelease Object value");
+ }
+
+ {
+ Object r = UNSAFE.compareAndExchangeObjectRelease(base, offset, "bar", "baz");
+ assertEquals(r, "foo", "failing compareAndExchangeRelease Object");
+ Object x = UNSAFE.getObject(base, offset);
+ assertEquals(x, "foo", "failing compareAndExchangeRelease Object value");
+ }
+
+ {
+ boolean r = UNSAFE.weakCompareAndSwapObject(base, offset, "foo", "bar");
+ assertEquals(r, true, "weakCompareAndSwap Object");
+ Object x = UNSAFE.getObject(base, offset);
+ assertEquals(x, "bar", "weakCompareAndSwap Object value");
+ }
+
+ {
+ boolean r = UNSAFE.weakCompareAndSwapObjectAcquire(base, offset, "bar", "foo");
+ assertEquals(r, true, "weakCompareAndSwapAcquire Object");
+ Object x = UNSAFE.getObject(base, offset);
+ assertEquals(x, "foo", "weakCompareAndSwapAcquire Object");
+ }
+
+ {
+ boolean r = UNSAFE.weakCompareAndSwapObjectRelease(base, offset, "foo", "bar");
+ assertEquals(r, true, "weakCompareAndSwapRelease Object");
+ Object x = UNSAFE.getObject(base, offset);
+ assertEquals(x, "bar", "weakCompareAndSwapRelease Object");
+ }
+
// Compare set and get
{
Object o = UNSAFE.getAndSetObject(base, offset, "foo");
--- a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestShort.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestShort.java Wed Mar 09 14:18:12 2016 +0100
@@ -157,6 +157,20 @@
}
+ // Lazy
+ {
+ UNSAFE.putShortRelease(base, offset, (short)1);
+ short x = UNSAFE.getShortAcquire(base, offset);
+ assertEquals(x, (short)1, "putRelease short value");
+ }
+
+ // Opaque
+ {
+ UNSAFE.putShortOpaque(base, offset, (short)2);
+ short x = UNSAFE.getShortOpaque(base, offset);
+ assertEquals(x, (short)2, "putOpaque short value");
+ }
+
// Unaligned
{
UNSAFE.putShortUnaligned(base, offset, (short)2);
--- a/hotspot/test/compiler/unsafe/UnsafeGetConstantField.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/compiler/unsafe/UnsafeGetConstantField.java Wed Mar 09 14:18:12 2016 +0100
@@ -27,6 +27,9 @@
* @test
* @summary tests on constant folding of unsafe get operations
* @library /testlibrary /test/lib
+ *
+ * @requires vm.flavor != "client"
+ *
* @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions
* -Xbatch -XX:-TieredCompilation
* -XX:+FoldStableValues
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/unsafe/UnsafeGetStableArrayElement.java Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,325 @@
+/*
+ * 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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 tests on constant folding of unsafe get operations from stable arrays
+ * @library /testlibrary /test/lib
+ * @ignore 8151137
+ *
+ * @requires vm.flavor != "client"
+ *
+ * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions
+ * -Xbatch -XX:-TieredCompilation
+ * -XX:+FoldStableValues
+ * -XX:CompileCommand=dontinline,*Test::test*
+ * UnsafeGetStableArrayElement
+ */
+import jdk.internal.misc.Unsafe;
+import jdk.internal.vm.annotation.Stable;
+import java.util.concurrent.Callable;
+
+import static jdk.internal.misc.Unsafe.*;
+import static jdk.test.lib.Asserts.*;
+
+public class UnsafeGetStableArrayElement {
+ @Stable static final boolean[] STABLE_BOOLEAN_ARRAY = new boolean[16];
+ @Stable static final byte[] STABLE_BYTE_ARRAY = new byte[16];
+ @Stable static final short[] STABLE_SHORT_ARRAY = new short[8];
+ @Stable static final char[] STABLE_CHAR_ARRAY = new char[8];
+ @Stable static final int[] STABLE_INT_ARRAY = new int[4];
+ @Stable static final long[] STABLE_LONG_ARRAY = new long[2];
+ @Stable static final float[] STABLE_FLOAT_ARRAY = new float[4];
+ @Stable static final double[] STABLE_DOUBLE_ARRAY = new double[2];
+ @Stable static final Object[] STABLE_OBJECT_ARRAY = new Object[4];
+
+ static {
+ Setter.reset();
+ }
+ static final Unsafe U = Unsafe.getUnsafe();
+
+ static class Setter {
+ private static void setZ(boolean defaultVal) { STABLE_BOOLEAN_ARRAY[0] = defaultVal ? false : true; }
+ private static void setB(boolean defaultVal) { STABLE_BYTE_ARRAY[0] = defaultVal ? 0 : Byte.MAX_VALUE; }
+ private static void setS(boolean defaultVal) { STABLE_SHORT_ARRAY[0] = defaultVal ? 0 : Short.MAX_VALUE; }
+ private static void setC(boolean defaultVal) { STABLE_CHAR_ARRAY[0] = defaultVal ? 0 : Character.MAX_VALUE; }
+ private static void setI(boolean defaultVal) { STABLE_INT_ARRAY[0] = defaultVal ? 0 : Integer.MAX_VALUE; }
+ private static void setJ(boolean defaultVal) { STABLE_LONG_ARRAY[0] = defaultVal ? 0 : Long.MAX_VALUE; }
+ private static void setF(boolean defaultVal) { STABLE_FLOAT_ARRAY[0] = defaultVal ? 0 : Float.MAX_VALUE; }
+ private static void setD(boolean defaultVal) { STABLE_DOUBLE_ARRAY[0] = defaultVal ? 0 : Double.MAX_VALUE; }
+ private static void setL(boolean defaultVal) { STABLE_OBJECT_ARRAY[0] = defaultVal ? null : new Object(); }
+
+ static void reset() {
+ setZ(false);
+ setB(false);
+ setS(false);
+ setC(false);
+ setI(false);
+ setJ(false);
+ setF(false);
+ setD(false);
+ setL(false);
+ }
+ }
+
+ static class Test {
+ static void changeZ() { Setter.setZ(true); }
+ static void changeB() { Setter.setB(true); }
+ static void changeS() { Setter.setS(true); }
+ static void changeC() { Setter.setC(true); }
+ static void changeI() { Setter.setI(true); }
+ static void changeJ() { Setter.setJ(true); }
+ static void changeF() { Setter.setF(true); }
+ static void changeD() { Setter.setD(true); }
+ static void changeL() { Setter.setL(true); }
+
+ static boolean testZ_Z() { return U.getBoolean(STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); }
+ static byte testZ_B() { return U.getByte( STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); }
+ static short testZ_S() { return U.getShort( STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); }
+ static char testZ_C() { return U.getChar( STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); }
+ static int testZ_I() { return U.getInt( STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); }
+ static long testZ_J() { return U.getLong( STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); }
+ static float testZ_F() { return U.getFloat( STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); }
+ static double testZ_D() { return U.getDouble( STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); }
+
+ static boolean testB_Z() { return U.getBoolean(STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); }
+ static byte testB_B() { return U.getByte( STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); }
+ static short testB_S() { return U.getShort( STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); }
+ static char testB_C() { return U.getChar( STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); }
+ static int testB_I() { return U.getInt( STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); }
+ static long testB_J() { return U.getLong( STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); }
+ static float testB_F() { return U.getFloat( STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); }
+ static double testB_D() { return U.getDouble( STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); }
+
+ static boolean testS_Z() { return U.getBoolean(STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); }
+ static byte testS_B() { return U.getByte( STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); }
+ static short testS_S() { return U.getShort( STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); }
+ static char testS_C() { return U.getChar( STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); }
+ static int testS_I() { return U.getInt( STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); }
+ static long testS_J() { return U.getLong( STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); }
+ static float testS_F() { return U.getFloat( STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); }
+ static double testS_D() { return U.getDouble( STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); }
+
+ static boolean testC_Z() { return U.getBoolean(STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); }
+ static byte testC_B() { return U.getByte( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); }
+ static short testC_S() { return U.getShort( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); }
+ static char testC_C() { return U.getChar( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); }
+ static int testC_I() { return U.getInt( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); }
+ static long testC_J() { return U.getLong( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); }
+ static float testC_F() { return U.getFloat( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); }
+ static double testC_D() { return U.getDouble( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); }
+
+ static boolean testI_Z() { return U.getBoolean(STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); }
+ static byte testI_B() { return U.getByte( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); }
+ static short testI_S() { return U.getShort( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); }
+ static char testI_C() { return U.getChar( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); }
+ static int testI_I() { return U.getInt( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); }
+ static long testI_J() { return U.getLong( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); }
+ static float testI_F() { return U.getFloat( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); }
+ static double testI_D() { return U.getDouble( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); }
+
+ static boolean testJ_Z() { return U.getBoolean(STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); }
+ static byte testJ_B() { return U.getByte( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); }
+ static short testJ_S() { return U.getShort( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); }
+ static char testJ_C() { return U.getChar( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); }
+ static int testJ_I() { return U.getInt( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); }
+ static long testJ_J() { return U.getLong( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); }
+ static float testJ_F() { return U.getFloat( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); }
+ static double testJ_D() { return U.getDouble( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); }
+
+ static boolean testF_Z() { return U.getBoolean(STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); }
+ static byte testF_B() { return U.getByte( STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); }
+ static short testF_S() { return U.getShort( STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); }
+ static char testF_C() { return U.getChar( STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); }
+ static int testF_I() { return U.getInt( STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); }
+ static long testF_J() { return U.getLong( STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); }
+ static float testF_F() { return U.getFloat( STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); }
+ static double testF_D() { return U.getDouble( STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); }
+
+ static boolean testD_Z() { return U.getBoolean(STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); }
+ static byte testD_B() { return U.getByte( STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); }
+ static short testD_S() { return U.getShort( STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); }
+ static char testD_C() { return U.getChar( STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); }
+ static int testD_I() { return U.getInt( STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); }
+ static long testD_J() { return U.getLong( STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); }
+ static float testD_F() { return U.getFloat( STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); }
+ static double testD_D() { return U.getDouble( STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); }
+
+ static Object testL_L() { return U.getObject( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); }
+ static boolean testL_Z() { return U.getBoolean(STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); }
+ static byte testL_B() { return U.getByte( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); }
+ static short testL_S() { return U.getShort( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); }
+ static char testL_C() { return U.getChar( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); }
+ static int testL_I() { return U.getInt( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); }
+ static long testL_J() { return U.getLong( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); }
+ static float testL_F() { return U.getFloat( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); }
+ static double testL_D() { return U.getDouble( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); }
+
+ static short testS_U() { return U.getShortUnaligned(STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET + 1); }
+ static char testC_U() { return U.getCharUnaligned( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET + 1); }
+ static int testI_U() { return U.getIntUnaligned( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET + 1); }
+ static long testJ_U() { return U.getLongUnaligned( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET + 1); }
+ }
+
+ static void run(Callable<?> c) throws Exception {
+ run(c, null, null);
+ }
+
+ static void run(Callable<?> c, Runnable sameResultAction, Runnable changeResultAction) throws Exception {
+ Object first = c.call();
+
+ // Trigger compilation.
+ for (int i = 0; i < 20_000; i++) {
+ // Don't compare results here, since most of Test::testL_* results vary across iterations (due to GC).
+ c.call();
+ }
+
+ if (sameResultAction != null) {
+ sameResultAction.run();
+ assertEQ(first, c.call());
+ }
+
+ if (changeResultAction != null) {
+ changeResultAction.run();
+ assertNE(first, c.call());
+ assertEQ(c.call(), c.call());
+ }
+ }
+
+ static void testMatched(Callable<?> c, Runnable setDefaultAction) throws Exception {
+ run(c, setDefaultAction, null);
+ Setter.reset();
+ }
+
+ static void testMismatched(Callable<?> c, Runnable setDefaultAction) throws Exception {
+ run(c, null, setDefaultAction);
+ Setter.reset();
+ }
+
+ public static void main(String[] args) throws Exception {
+ // boolean[], aligned accesses
+ testMatched( Test::testZ_Z, Test::changeZ);
+ testMismatched(Test::testZ_B, Test::changeZ);
+ testMismatched(Test::testZ_S, Test::changeZ);
+ testMismatched(Test::testZ_C, Test::changeZ);
+ testMismatched(Test::testZ_I, Test::changeZ);
+ testMismatched(Test::testZ_J, Test::changeZ);
+ testMismatched(Test::testZ_F, Test::changeZ);
+ testMismatched(Test::testZ_D, Test::changeZ);
+
+ // byte[], aligned accesses
+ testMismatched(Test::testB_Z, Test::changeB);
+ testMatched( Test::testB_B, Test::changeB);
+ testMismatched(Test::testB_S, Test::changeB);
+ testMismatched(Test::testB_C, Test::changeB);
+ testMismatched(Test::testB_I, Test::changeB);
+ testMismatched(Test::testB_J, Test::changeB);
+ testMismatched(Test::testB_F, Test::changeB);
+ testMismatched(Test::testB_D, Test::changeB);
+
+ // short[], aligned accesses
+ testMismatched(Test::testS_Z, Test::changeS);
+ testMismatched(Test::testS_B, Test::changeS);
+ testMatched( Test::testS_S, Test::changeS);
+ testMismatched(Test::testS_C, Test::changeS);
+ testMismatched(Test::testS_I, Test::changeS);
+ testMismatched(Test::testS_J, Test::changeS);
+ testMismatched(Test::testS_F, Test::changeS);
+ testMismatched(Test::testS_D, Test::changeS);
+
+ // char[], aligned accesses
+ testMismatched(Test::testC_Z, Test::changeC);
+ testMismatched(Test::testC_B, Test::changeC);
+ testMismatched(Test::testC_S, Test::changeC);
+ testMatched( Test::testC_C, Test::changeC);
+ testMismatched(Test::testC_I, Test::changeC);
+ testMismatched(Test::testC_J, Test::changeC);
+ testMismatched(Test::testC_F, Test::changeC);
+ testMismatched(Test::testC_D, Test::changeC);
+
+ // int[], aligned accesses
+ testMismatched(Test::testI_Z, Test::changeI);
+ testMismatched(Test::testI_B, Test::changeI);
+ testMismatched(Test::testI_S, Test::changeI);
+ testMismatched(Test::testI_C, Test::changeI);
+ testMatched( Test::testI_I, Test::changeI);
+ testMismatched(Test::testI_J, Test::changeI);
+ testMismatched(Test::testI_F, Test::changeI);
+ testMismatched(Test::testI_D, Test::changeI);
+
+ // long[], aligned accesses
+ testMismatched(Test::testJ_Z, Test::changeJ);
+ testMismatched(Test::testJ_B, Test::changeJ);
+ testMismatched(Test::testJ_S, Test::changeJ);
+ testMismatched(Test::testJ_C, Test::changeJ);
+ testMismatched(Test::testJ_I, Test::changeJ);
+ testMatched( Test::testJ_J, Test::changeJ);
+ testMismatched(Test::testJ_F, Test::changeJ);
+ testMismatched(Test::testJ_D, Test::changeJ);
+
+ // float[], aligned accesses
+ testMismatched(Test::testF_Z, Test::changeF);
+ testMismatched(Test::testF_B, Test::changeF);
+ testMismatched(Test::testF_S, Test::changeF);
+ testMismatched(Test::testF_C, Test::changeF);
+ testMismatched(Test::testF_I, Test::changeF);
+ testMismatched(Test::testF_J, Test::changeF);
+ testMatched( Test::testF_F, Test::changeF);
+ testMismatched(Test::testF_D, Test::changeF);
+
+ // double[], aligned accesses
+ testMismatched(Test::testD_Z, Test::changeD);
+ testMismatched(Test::testD_B, Test::changeD);
+ testMismatched(Test::testD_S, Test::changeD);
+ testMismatched(Test::testD_C, Test::changeD);
+ testMismatched(Test::testD_I, Test::changeD);
+ testMismatched(Test::testD_J, Test::changeD);
+ testMismatched(Test::testD_F, Test::changeD);
+ testMatched( Test::testD_D, Test::changeD);
+
+ // Object[], aligned accesses
+ testMismatched(Test::testL_J, Test::changeL); // long & double are always as large as an OOP
+ testMismatched(Test::testL_D, Test::changeL);
+ testMatched( Test::testL_L, Test::changeL);
+
+ // Unaligned accesses
+ testMismatched(Test::testS_U, Test::changeS);
+ testMismatched(Test::testC_U, Test::changeC);
+ testMismatched(Test::testI_U, Test::changeI);
+ testMismatched(Test::testJ_U, Test::changeJ);
+
+ // No way to reliably check the expected behavior:
+ // (1) OOPs change during GC;
+ // (2) there's no way to reliably change some part of an OOP (e.g., when reading a byte from it).
+ //
+ // Just trigger the compilation hoping to catch any problems with asserts.
+ run(Test::testL_B);
+ run(Test::testL_Z);
+ run(Test::testL_S);
+ run(Test::testL_C);
+ run(Test::testL_I);
+ run(Test::testL_F);
+ }
+}
--- a/hotspot/test/compiler/unsafe/X-UnsafeAccessTest.java.template Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/compiler/unsafe/X-UnsafeAccessTest.java.template Wed Mar 09 14:18:12 2016 +0100
@@ -170,6 +170,22 @@
#end[Ordered]
#if[JdkInternalMisc]
+ // Lazy
+ {
+ UNSAFE.put$Type$Release(base, offset, $value1$);
+ $type$ x = UNSAFE.get$Type$Acquire(base, offset);
+ assertEquals(x, $value1$, "putRelease $type$ value");
+ }
+
+ // Opaque
+ {
+ UNSAFE.put$Type$Opaque(base, offset, $value2$);
+ $type$ x = UNSAFE.get$Type$Opaque(base, offset);
+ assertEquals(x, $value2$, "putOpaque $type$ value");
+ }
+#end[JdkInternalMisc]
+
+#if[JdkInternalMisc]
#if[Unaligned]
// Unaligned
{
@@ -210,6 +226,72 @@
assertEquals(x, $value2$, "failing compareAndSwap $type$ value");
}
+#if[JdkInternalMisc]
+ // Advanced compare
+ {
+ $type$ r = UNSAFE.compareAndExchange$Type$Volatile(base, offset, $value2$, $value1$);
+ assertEquals(r, $value2$, "success compareAndExchangeVolatile $type$");
+ $type$ x = UNSAFE.get$Type$(base, offset);
+ assertEquals(x, $value1$, "success compareAndExchangeVolatile $type$ value");
+ }
+
+ {
+ $type$ r = UNSAFE.compareAndExchange$Type$Volatile(base, offset, $value2$, $value3$);
+ assertEquals(r, $value1$, "failing compareAndExchangeVolatile $type$");
+ $type$ x = UNSAFE.get$Type$(base, offset);
+ assertEquals(x, $value1$, "failing compareAndExchangeVolatile $type$ value");
+ }
+
+ {
+ $type$ r = UNSAFE.compareAndExchange$Type$Acquire(base, offset, $value1$, $value2$);
+ assertEquals(r, $value1$, "success compareAndExchangeAcquire $type$");
+ $type$ x = UNSAFE.get$Type$(base, offset);
+ assertEquals(x, $value2$, "success compareAndExchangeAcquire $type$ value");
+ }
+
+ {
+ $type$ r = UNSAFE.compareAndExchange$Type$Acquire(base, offset, $value1$, $value3$);
+ assertEquals(r, $value2$, "failing compareAndExchangeAcquire $type$");
+ $type$ x = UNSAFE.get$Type$(base, offset);
+ assertEquals(x, $value2$, "failing compareAndExchangeAcquire $type$ value");
+ }
+
+ {
+ $type$ r = UNSAFE.compareAndExchange$Type$Release(base, offset, $value2$, $value1$);
+ assertEquals(r, $value2$, "success compareAndExchangeRelease $type$");
+ $type$ x = UNSAFE.get$Type$(base, offset);
+ assertEquals(x, $value1$, "success compareAndExchangeRelease $type$ value");
+ }
+
+ {
+ $type$ r = UNSAFE.compareAndExchange$Type$Release(base, offset, $value2$, $value3$);
+ assertEquals(r, $value1$, "failing compareAndExchangeRelease $type$");
+ $type$ x = UNSAFE.get$Type$(base, offset);
+ assertEquals(x, $value1$, "failing compareAndExchangeRelease $type$ value");
+ }
+
+ {
+ boolean r = UNSAFE.weakCompareAndSwap$Type$(base, offset, $value1$, $value2$);
+ assertEquals(r, true, "weakCompareAndSwap $type$");
+ $type$ x = UNSAFE.get$Type$(base, offset);
+ assertEquals(x, $value2$, "weakCompareAndSwap $type$ value");
+ }
+
+ {
+ boolean r = UNSAFE.weakCompareAndSwap$Type$Acquire(base, offset, $value2$, $value1$);
+ assertEquals(r, true, "weakCompareAndSwapAcquire $type$");
+ $type$ x = UNSAFE.get$Type$(base, offset);
+ assertEquals(x, $value1$, "weakCompareAndSwapAcquire $type$");
+ }
+
+ {
+ boolean r = UNSAFE.weakCompareAndSwap$Type$Release(base, offset, $value1$, $value2$);
+ assertEquals(r, true, "weakCompareAndSwapRelease $type$");
+ $type$ x = UNSAFE.get$Type$(base, offset);
+ assertEquals(x, $value2$, "weakCompareAndSwapRelease $type$");
+ }
+#end[JdkInternalMisc]
+
// Compare set and get
{
$type$ o = UNSAFE.getAndSet$Type$(base, offset, $value1$);
@@ -244,4 +326,5 @@
}
#end[!boolean]
#end[!Object]
-}
\ No newline at end of file
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/unsafe/generate-unsafe-tests.sh Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,97 @@
+#!/bin/bash
+
+javac -d . ../../../../jdk/make/src/classes/build/tools/spp/Spp.java
+
+SPP=build.tools.spp.Spp
+
+# Generates unsafe access tests for objects and all primitive types
+# $1 = package name to Unsafe, sun.misc | jdk.internal.misc
+# $2 = test class qualifier name, SunMisc | JdkInternalMisc
+function generate {
+ package=$1
+ Qualifier=$2
+
+ for type in boolean byte short char int long float double Object
+ do
+ Type="$(tr '[:lower:]' '[:upper:]' <<< ${type:0:1})${type:1}"
+ args="-K$type -Dtype=$type -DType=$Type"
+
+ case $type in
+ Object|int|long)
+ args="$args -KCAS -KOrdered"
+ ;;
+ esac
+
+ case $type in
+ int|long)
+ args="$args -KAtomicAdd"
+ ;;
+ esac
+
+ case $type in
+ short|char|int|long)
+ args="$args -KUnaligned"
+ ;;
+ esac
+
+ case $type in
+ boolean)
+ value1=true
+ value2=false
+ value3=false
+ ;;
+ byte)
+ value1=(byte)1
+ value2=(byte)2
+ value3=(byte)3
+ ;;
+ short)
+ value1=(short)1
+ value2=(short)2
+ value3=(short)3
+ ;;
+ char)
+ value1=\'a\'
+ value2=\'b\'
+ value3=\'c\'
+ ;;
+ int)
+ value1=1
+ value2=2
+ value3=3
+ ;;
+ long)
+ value1=1L
+ value2=2L
+ value3=3L
+ ;;
+ float)
+ value1=1.0f
+ value2=2.0f
+ value3=3.0f
+ ;;
+ double)
+ value1=1.0d
+ value2=2.0d
+ value3=3.0d
+ ;;
+ Object)
+ value1=\"foo\"
+ value2=\"bar\"
+ value3=\"baz\"
+ ;;
+ esac
+
+ args="$args -Dvalue1=$value1 -Dvalue2=$value2 -Dvalue3=$value3"
+
+ echo $args
+
+ java $SPP -nel -K$Qualifier -Dpackage=$package -DQualifier=$Qualifier \
+ $args < X-UnsafeAccessTest.java.template > ${Qualifier}UnsafeAccessTest${Type}.java
+ done
+}
+
+generate sun.misc SunMisc
+generate jdk.internal.misc JdkInternalMisc
+
+rm -fr build
\ No newline at end of file
--- a/hotspot/test/runtime/RedefineTests/RedefineRunningMethodsWithResolutionErrors.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/runtime/RedefineTests/RedefineRunningMethodsWithResolutionErrors.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -26,8 +26,9 @@
* @bug 8076110
* @summary Redefine running methods that have cached resolution errors
* @library /testlibrary
- * @modules java.instrument
- * java.base/jdk.internal.org.objectweb.asm
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ * java.instrument
+ * jdk.jartool/sun.tools.jar
* @build RedefineClassHelper
* @run main RedefineClassHelper
* @run main/othervm -javaagent:redefineagent.jar -XX:TraceRedefineClasses=0x600 RedefineRunningMethodsWithResolutionErrors
--- a/hotspot/test/runtime/ReservedStack/ReservedStackTest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/runtime/ReservedStack/ReservedStackTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -24,6 +24,7 @@
/*
* @test ReservedStackTest
* @library /testlibrary
+ * @modules java.base/jdk.internal.vm.annotation
* @build jdk.test.lib.*
* @run main/othervm -XX:-Inline -XX:CompileCommand=exclude,java/util/concurrent/locks/AbstractOwnableSynchronizer.setExclusiveOwnerThread ReservedStackTest
*/
--- a/hotspot/test/runtime/SharedArchiveFile/LimitSharedSizes.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/runtime/SharedArchiveFile/LimitSharedSizes.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -26,6 +26,7 @@
* @library /testlibrary /runtime/CommandLine/OptionsValidation/common
* @modules java.base/sun.misc
* java.management
+ * jdk.attach/sun.tools.attach
* @run main LimitSharedSizes
*/
--- a/hotspot/test/runtime/contended/Basic.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/runtime/contended/Basic.java Wed Mar 09 14:18:12 2016 +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
@@ -42,7 +42,7 @@
* @test
* @bug 8003985
* @summary Support Contended Annotation - JEP 142
- * @modules java.base/sun.misc
+ * @modules java.base/jdk.internal.vm.annotation
* @run main/othervm -XX:-RestrictContended Basic
*/
public class Basic {
--- a/hotspot/test/runtime/contended/DefaultValue.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/runtime/contended/DefaultValue.java Wed Mar 09 14:18:12 2016 +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
@@ -43,7 +43,7 @@
* @bug 8014509
* @summary \@Contended: explicit default value behaves differently from the implicit value
*
- * @modules java.base/sun.misc
+ * @modules java.base/jdk.internal.vm.annotation
* @run main/othervm -XX:-RestrictContended DefaultValue
*/
public class DefaultValue {
--- a/hotspot/test/runtime/contended/HasNonStatic.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/runtime/contended/HasNonStatic.java Wed Mar 09 14:18:12 2016 +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
@@ -43,7 +43,7 @@
* @bug 8015270
* @summary \@Contended: fix multiple issues in the layout code
*
- * @modules java.base/sun.misc
+ * @modules java.base/jdk.internal.vm.annotation
* @run main/othervm -XX:-RestrictContended HasNonStatic
*/
public class HasNonStatic {
--- a/hotspot/test/runtime/contended/Inheritance1.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/runtime/contended/Inheritance1.java Wed Mar 09 14:18:12 2016 +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
@@ -43,7 +43,7 @@
* @bug 8012939
* @summary \@Contended doesn't work correctly with inheritance
*
- * @modules java.base/sun.misc
+ * @modules java.base/jdk.internal.vm.annotation
* @run main/othervm -XX:-RestrictContended Inheritance1
*/
public class Inheritance1 {
--- a/hotspot/test/runtime/contended/OopMaps.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/runtime/contended/OopMaps.java Wed Mar 09 14:18:12 2016 +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
@@ -44,7 +44,7 @@
* @bug 8015493
* @summary \@Contended: fix multiple issues in the layout code
*
- * @modules java.base/sun.misc
+ * @modules java.base/jdk.internal.vm.annotation
* @run main/othervm -XX:-RestrictContended -XX:ContendedPaddingWidth=128 -Xmx128m OopMaps
*/
public class OopMaps {
--- a/hotspot/test/runtime/contended/OopMapsSameGroup.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/runtime/contended/OopMapsSameGroup.java Wed Mar 09 14:18:12 2016 +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
@@ -43,7 +43,7 @@
* @bug 8015272
* @summary \@Contended within the same group to use the same oop map
*
- * @modules java.base/sun.misc
+ * @modules java.base/jdk.internal.vm.annotation
* @run main/othervm -XX:-RestrictContended -XX:ContendedPaddingWidth=128 -Xmx128m OopMapsSameGroup
*/
public class OopMapsSameGroup {
--- a/hotspot/test/runtime/lambda-features/TestStaticandInstance.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/runtime/lambda-features/TestStaticandInstance.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -26,6 +26,7 @@
* @test
* @bug 8087342
* @summary Test linkresolver search static, instance and overpass duplicates
+ * @modules java.base/jdk.internal.org.objectweb.asm
* @run main/othervm -Xverify:none TestStaticandInstance
*/
--- a/hotspot/test/serviceability/attach/AttachSetGetFlag.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/serviceability/attach/AttachSetGetFlag.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -32,7 +32,7 @@
* jdk.attach/sun.tools.attach
* jdk.jvmstat/sun.jvmstat.monitor
* @build jdk.test.lib.* AttachSetGetFlag
- * @run driver AttachSetGetFlag
+ * @run main AttachSetGetFlag
*/
import java.io.BufferedReader;
--- a/hotspot/test/serviceability/attach/AttachWithStalePidFile.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/serviceability/attach/AttachWithStalePidFile.java Wed Mar 09 14:18:12 2016 +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
@@ -26,6 +26,7 @@
* @bug 7162400
* @key regression
* @summary Regression test for attach issue where stale pid files in /tmp lead to connection issues
+ * @modules jdk.attach/sun.tools.attach
* @library /testlibrary
* @build jdk.test.lib.* AttachWithStalePidFileTarget
* @run main AttachWithStalePidFile
--- a/hotspot/test/serviceability/dcmd/compiler/CompilerQueueTest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/serviceability/dcmd/compiler/CompilerQueueTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -24,25 +24,33 @@
/*
* @test CompilerQueueTest
* @bug 8054889
- * @library /testlibrary
+ * @library /testlibrary /test/lib /
* @modules java.base/sun.misc
* java.compiler
* java.management
* jdk.jvmstat/sun.jvmstat.monitor
- * @ignore 8069160
* @build jdk.test.lib.*
- * @build jdk.test.lib.dcmd.*
- * @run testng CompilerQueueTest
- * @run testng/othervm -XX:-TieredCompilation CompilerQueueTest
- * @run testng/othervm -Xint CompilerQueueTest
+ * jdk.test.lib.dcmd.*
+ * sun.hotspot.WhiteBox
+ * compiler.testlibrary.CompilerUtils
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run testng/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -Xmixed -XX:+WhiteBoxAPI CompilerQueueTest
+ * @run testng/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -Xmixed -XX:-TieredCompilation -XX:+WhiteBoxAPI CompilerQueueTest
+ * @run testng/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -Xint -XX:+WhiteBoxAPI CompilerQueueTest
* @summary Test of diagnostic command Compiler.queue
*/
+import compiler.testlibrary.CompilerUtils;
import jdk.test.lib.OutputAnalyzer;
import jdk.test.lib.dcmd.CommandExecutor;
import jdk.test.lib.dcmd.JMXExecutor;
import org.testng.annotations.Test;
+import org.testng.Assert;
+import sun.hotspot.WhiteBox;
+import java.lang.reflect.Executable;
+import java.lang.reflect.Method;
import java.util.Iterator;
public class CompilerQueueTest {
@@ -54,70 +62,123 @@
*
* Output example:
*
- * Contents of C1 compile queue
- * ----------------------------
- * 73 3 java.lang.AbstractStringBuilder::append (50 bytes)
- * 74 1 java.util.TreeMap::size (5 bytes)
- * 75 3 java.lang.StringBuilder::append (8 bytes)
- * 83 3 java.util.TreeMap$ValueIterator::next (8 bytes)
- * 84 1 javax.management.MBeanFeatureInfo::getName (5 bytes)
- * ----------------------------
- * Contents of C2 compile queue
- * ----------------------------
+ * Current compiles:
+ * C1 CompilerThread14 267 3 java.net.URLStreamHandler::parseURL (1166 bytes)
+ * C1 CompilerThread13 760 3 javax.management.StandardMBean::getDescription (11 bytes)
+ * C1 CompilerThread12 757 s 3 com.sun.jmx.mbeanserver.DefaultMXBeanMappingFactory::getMapping (27 bytes)
+ * C1 CompilerThread11 756 s! 3 com.sun.jmx.mbeanserver.DefaultMXBeanMappingFactory::mappingForType (110 bytes)
+ * C1 CompilerThread10 761 3 java.lang.StringLatin1::indexOf (121 bytes)
+ * C2 CompilerThread7 769 4 CompilerQueueTest::testcaseMethod4 (1 bytes)
+ *
+ * C1 compile queue:
+ * 762 3 java.lang.invoke.MethodType::basicType (8 bytes)
+ * 763 3 java.util.ArrayList::rangeCheck (22 bytes)
+ * 764 3 java.util.ArrayList::elementData (7 bytes)
+ * 765 3 jdk.internal.org.objectweb.asm.MethodVisitor::<init> (35 bytes)
+ * 766 1 CompilerQueueTest::testcaseMethod1 (1 bytes)
+ * 767 2 CompilerQueueTest::testcaseMethod2 (1 bytes)
+ * 768 3 CompilerQueueTest::testcaseMethod3 (1 bytes)
+ * 770 3 java.util.Properties::getProperty (46 bytes)
+ *
+ * C2 compile queue:
* Empty
- * ----------------------------
*
**/
+ protected static final WhiteBox WB = WhiteBox.getWhiteBox();
+
public void run(CommandExecutor executor) {
+ TestCase[] testcases = {
+ new TestCase(1, "testcaseMethod1"),
+ new TestCase(2, "testcaseMethod2"),
+ new TestCase(3, "testcaseMethod3"),
+ new TestCase(4, "testcaseMethod4"),
+ };
+
+ // Lock compilation makes all compiles stay in queue or compile thread before completion
+ WB.lockCompilation();
+
+ // Enqueue one test method for each available level
+ int[] complevels = CompilerUtils.getAvailableCompilationLevels();
+ for (int level : complevels) {
+ TestCase testcase = testcases[level - 1];
+
+ boolean added = WB.enqueueMethodForCompilation(testcase.method, testcase.level);
+ // Set results to false for those methods we must to find
+ // We will also assert if we find any test method we don't expect
+ Assert.assertTrue(WB.isMethodQueuedForCompilation(testcase.method));
+ testcase.check = false;
+ }
+
// Get output from dcmd (diagnostic command)
OutputAnalyzer output = executor.execute("Compiler.queue");
Iterator<String> lines = output.asLines().iterator();
+ // Loop over output set result for all found methods
while (lines.hasNext()) {
String str = lines.next();
- if (str.startsWith("Contents of C")) {
- match(lines.next(), "----------------------------");
- str = lines.next();
- if (!str.equals("Empty")) {
- while (str.charAt(0) != '-') {
- validateMethodLine(str);
- str = lines.next();
+ // Fast check for common part of method name
+ if (str.contains("testcaseMethod")) {
+ for (TestCase testcase : testcases) {
+ if (str.contains(testcase.methodName)) {
+ Assert.assertFalse(testcase.check, "Must not be found or already found.");
+ testcase.check = true;
}
- } else {
- str = lines.next();
}
- match(str,"----------------------------");
- } else {
- Assert.fail("Failed parsing dcmd queue, line: " + str);
}
}
- }
- private static void validateMethodLine(String str) {
- // Skip until package/class name begins. Trim to remove whitespace that
- // may differ.
- String name = str.substring(14).trim();
- int sep = name.indexOf("::");
- if (sep == -1) {
- Assert.fail("Failed dcmd queue, didn't find separator :: in: " + name);
+ for (TestCase testcase : testcases) {
+ if (!testcase.check) {
+ // If this method wasn't found it must have been removed by policy,
+ // verify that it is now removed from the queue
+ Assert.assertFalse(WB.isMethodQueuedForCompilation(testcase.method), "Must be found or not in queue");
+ }
+ // Otherwise all good.
}
- try {
- Class.forName(name.substring(0, sep));
- } catch (ClassNotFoundException e) {
- Assert.fail("Failed dcmd queue, Class for name: " + str);
- }
- }
- public static void match(String line, String str) {
- if (!line.equals(str)) {
- Assert.fail("String equals: " + line + ", " + str);
- }
+ // Enable compilations again
+ WB.unlockCompilation();
}
@Test
public void jmx() {
run(new JMXExecutor());
}
+
+ public void testcaseMethod1() {
+ }
+
+ public void testcaseMethod2() {
+ }
+
+ public void testcaseMethod3() {
+ }
+
+ public void testcaseMethod4() {
+ }
+
+ public static Method getMethod(Class klass, String name, Class<?>... parameterTypes) {
+ try {
+ return klass.getDeclaredMethod(name, parameterTypes);
+ } catch (NoSuchMethodException | SecurityException e) {
+ throw new RuntimeException("exception on getting method Helper." + name, e);
+ }
+ }
+
+ class TestCase {
+ Method method;
+ int level;
+ String methodName;
+ Boolean check;
+
+ public TestCase(int level, String methodName) {
+ this.method = getMethod(CompilerQueueTest.class, methodName);
+ this.level = level;
+ this.methodName = methodName;
+ this.check = true;
+ }
+ }
+
}
--- a/hotspot/test/testlibrary_tests/ctw/ClassesDirTest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/testlibrary_tests/ctw/ClassesDirTest.java Wed Mar 09 14:18:12 2016 +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
@@ -25,7 +25,7 @@
* @test
* @bug 8012447
* @library /testlibrary /test/lib /testlibrary/ctw/src
- * @modules java.base/sun.misc
+ * @modules java.base/jdk.internal.misc
* java.base/sun.reflect
* java.management
* @build ClassFileInstaller sun.hotspot.tools.ctw.CompileTheWorld sun.hotspot.WhiteBox Foo Bar
--- a/hotspot/test/testlibrary_tests/ctw/ClassesListTest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/testlibrary_tests/ctw/ClassesListTest.java Wed Mar 09 14:18:12 2016 +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
@@ -25,7 +25,7 @@
* @test
* @bug 8012447
* @library /testlibrary /test/lib /testlibrary/ctw/src
- * @modules java.base/sun.misc
+ * @modules java.base/jdk.internal.misc
* java.base/sun.reflect
* java.management
* @build ClassFileInstaller sun.hotspot.tools.ctw.CompileTheWorld sun.hotspot.WhiteBox Foo Bar
--- a/hotspot/test/testlibrary_tests/ctw/JarDirTest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/testlibrary_tests/ctw/JarDirTest.java Wed Mar 09 14:18:12 2016 +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
@@ -25,7 +25,7 @@
* @test
* @bug 8012447
* @library /testlibrary /test/lib /testlibrary/ctw/src
- * @modules java.base/sun.misc
+ * @modules java.base/jdk.internal.misc
* java.base/sun.reflect
* java.compiler
* java.management
--- a/hotspot/test/testlibrary_tests/ctw/JarsTest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/hotspot/test/testlibrary_tests/ctw/JarsTest.java Wed Mar 09 14:18:12 2016 +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
@@ -25,7 +25,7 @@
* @test
* @bug 8012447
* @library /testlibrary /test/lib /testlibrary/ctw/src
- * @modules java.base/sun.misc
+ * @modules java.base/jdk.internal.misc
* java.base/sun.reflect
* java.compiler
* java.management
--- a/jaxp/.hgtags Wed Mar 09 14:54:18 2016 +0100
+++ b/jaxp/.hgtags Wed Mar 09 14:18:12 2016 +0100
@@ -350,3 +350,4 @@
5acf6071d4d610068a19c79e004ba8e59cf1b087 jdk-9+105
65d615f71e81bae46dcb4d053e590582e5705879 jdk-9+106
781b83dadcae89b8ae7545bb4044ddc62c6fa006 jdk-9+107
+3b9fa8b1491479f7ae18131a34036b58b647493e jdk-9+108
--- a/jaxws/.hgtags Wed Mar 09 14:54:18 2016 +0100
+++ b/jaxws/.hgtags Wed Mar 09 14:18:12 2016 +0100
@@ -353,3 +353,4 @@
45a666c58e4c7d07638878684ad09decb3229dc9 jdk-9+105
c072c572d14948563ef5d86e1921699b3a2396ab jdk-9+106
fafd694e801f0f5a7c737fb08630ced3ca8f772c jdk-9+107
+513eb2e432f64f85992442da9acdfcfbb36555d9 jdk-9+108
--- a/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/Const.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/Const.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -29,12 +29,12 @@
* @author Kohsuke Kawaguchi
*/
public final class Const {
- public static byte default_value_byte = 0;
- public static boolean default_value_boolean = false;
- public static char default_value_char = 0;
- public static float default_value_float = 0;
- public static double default_value_double = 0;
- public static int default_value_int = 0;
- public static long default_value_long = 0;
- public static short default_value_short = 0;
+ public static final byte default_value_byte = 0;
+ public static final boolean default_value_boolean = false;
+ public static final char default_value_char = 0;
+ public static final float default_value_float = 0;
+ public static final double default_value_double = 0;
+ public static final int default_value_int = 0;
+ public static final long default_value_long = 0;
+ public static final short default_value_short = 0;
}
--- a/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/StructureLoader.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/StructureLoader.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -231,22 +231,11 @@
@Override
public void childElement(UnmarshallingContext.State state, TagName arg) throws SAXException {
ChildLoader child = childUnmarshallers.get(arg.uri,arg.local);
- if(child==null) {
- if ((beanInfo != null) && (beanInfo.getTypeNames() != null)) {
- Iterator typeNamesIt = beanInfo.getTypeNames().iterator();
- QName parentQName = null;
- if ((typeNamesIt != null) && (typeNamesIt.hasNext()) && (catchAll == null)) {
- parentQName = (QName) typeNamesIt.next();
- String parentUri = parentQName.getNamespaceURI();
- child = childUnmarshallers.get(parentUri, arg.local);
- }
- }
- if (child == null) {
- child = catchAll;
- if(child==null) {
- super.childElement(state,arg);
- return;
- }
+ if (child == null) {
+ child = catchAll;
+ if (child==null) {
+ super.childElement(state,arg);
+ return;
}
}
--- a/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/schemagen/XmlSchemaGenerator.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/schemagen/XmlSchemaGenerator.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -110,6 +110,7 @@
import com.sun.xml.internal.txw2.output.ResultFactory;
import com.sun.xml.internal.txw2.output.XmlSerializer;
import java.util.Collection;
+import java.util.HashSet;
import org.xml.sax.SAXParseException;
/**
@@ -436,7 +437,7 @@
if(logger.isLoggable(Level.FINE)) {
// debug logging to see what's going on.
- logger.log(Level.FINE,"Wrigin XML Schema for "+toString(),new StackRecorder());
+ logger.log(Level.FINE,"Writing XML Schema for "+toString(),new StackRecorder());
}
// make it fool-proof
@@ -465,6 +466,8 @@
systemIds.put(n,output.getSystemId());
}
}
+ //Clear the namespace specific set with already written classes
+ n.resetWritten();
}
// then write'em all
@@ -542,6 +545,11 @@
*/
private boolean useMimeNs;
+ /**
+ * Container for already processed classes
+ */
+ private final Set<ClassInfo> written = new HashSet<ClassInfo>();
+
public Namespace(String uri) {
this.uri = uri;
assert !XmlSchemaGenerator.this.namespaces.containsKey(uri);
@@ -549,6 +557,13 @@
}
/**
+ * Clear out the set of already processed classes for this namespace
+ */
+ void resetWritten() {
+ written.clear();
+ }
+
+ /**
* Process the given PropertyInfo looking for references to namespaces that
* are foreign to the given namespace. Any foreign namespace references
* found are added to the given namespaces dependency list and an {@code <import>}
@@ -853,6 +868,10 @@
* @param parent the writer of the parent element into which the type will be defined
*/
private void writeClass(ClassInfo<T,C> c, TypeHost parent) {
+ if (written.contains(c)) { // to avoid cycles let's check if we haven't already processed the class
+ return;
+ }
+ written.add(c);
// special handling for value properties
if (containsValueProp(c)) {
if (c.getProperties().size() == 1) {
@@ -1080,9 +1099,13 @@
}
}
}
- if (cImpl != null)
- e.ref(new QName(cImpl.getElementName().getNamespaceURI(), tn.getLocalPart()));
- else
+ if (cImpl != null) {
+ if (tn.getNamespaceURI() != null && tn.getNamespaceURI().trim().length() != 0) {
+ e.ref(new QName(tn.getNamespaceURI(), tn.getLocalPart()));
+ } else {
+ e.ref(new QName(cImpl.getElementName().getNamespaceURI(), tn.getLocalPart()));
+ }
+ } else
e.ref(new QName("", tn.getLocalPart()));
} else
e.ref(tn);
--- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/client/p2p/HttpSOAPConnection.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/client/p2p/HttpSOAPConnection.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -512,13 +512,9 @@
: httpConnection.getInputStream());
// If no reply message is returned,
// content-Length header field value is expected to be zero.
- // java SE 6 documentation says :
- // available() : an estimate of the number of bytes that can be read
- //(or skipped over) from this input stream without blocking
- //or 0 when it reaches the end of the input stream.
+ // InputStream#available() can't be used here - it just says no data *YET*!
if ((httpIn == null )
- || (httpConnection.getContentLength() == 0)
- || (httpIn.available() == 0)) {
+ || (httpConnection.getContentLength() == 0)) {
response = null;
log.warning("SAAJ0014.p2p.content.zero");
} else {
--- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/packaging/mime/internet/InternetHeaders.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/packaging/mime/internet/InternetHeaders.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -285,7 +285,7 @@
*
* @return Header objects
*/
- public FinalArrayList<hdr> getAllHeaders() {
+ public List<? extends Header> getAllHeaders() {
return headers; // conceptually it should be read-only, but for performance reason I'm not wrapping it here
}
--- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/packaging/mime/internet/MimeBodyPart.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/packaging/mime/internet/MimeBodyPart.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -32,6 +32,7 @@
package com.sun.xml.internal.messaging.saaj.packaging.mime.internet;
+import com.sun.xml.internal.messaging.saaj.packaging.mime.Header;
import com.sun.xml.internal.messaging.saaj.packaging.mime.MessagingException;
import com.sun.xml.internal.messaging.saaj.packaging.mime.util.OutputUtil;
import com.sun.xml.internal.messaging.saaj.util.ByteOutputStream;
@@ -1041,7 +1042,7 @@
* Return all the headers from this Message as an Enumeration of
* Header objects.
*/
- public FinalArrayList<hdr> getAllHeaders() {
+ public List<? extends Header> getAllHeaders() {
return headers.getAllHeaders();
}
--- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/api/pipe/ThreadHelper.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/api/pipe/ThreadHelper.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -32,7 +32,7 @@
/**
* Simple utility class to instantiate correct Thread instance
- * depending on runtime context (jdk/non-jdk usage) and Java version.
+ * depending on Java version.
*
* @author miroslav.kos@oracle.com
*/
@@ -101,16 +101,16 @@
SunMiscThreadFactory(Constructor<?> ctr) { this.ctr = ctr; }
@Override public Thread newThread(Runnable r) {
return AccessController.doPrivileged(
- new PrivilegedAction<Thread>() {
- @Override
- public Thread run() {
- try {
- return (Thread) ctr.newInstance(r);
- } catch (Exception e) {
- return new Thread(r);
+ new PrivilegedAction<Thread>() {
+ @Override
+ public Thread run() {
+ try {
+ return (Thread) ctr.newInstance(r);
+ } catch (Exception e) {
+ return new Thread(r);
+ }
}
}
- }
);
}
}
--- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/transport/Headers.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/transport/Headers.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -127,5 +127,17 @@
l.add (value);
put(key, l);
}
+ /**
+ * Added to fix issue
+ * putAll() is easier to deal with as it doesn't return anything
+ */
+ public void putAll(Map<? extends String,? extends List<String>> map) {
+ for (String k : map.keySet()) {
+ List<String> list = map.get(k);
+ for (String v : list) {
+ add(k,v);
+ }
+ }
+ }
}
--- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/ServiceFinder.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/ServiceFinder.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -338,13 +338,13 @@
int lc = 1;
while ((lc = parseLine(service, u, r, lc, names, returned)) >= 0) ;
} catch (IOException x) {
- fail(service, ": " + x);
+ fail(service, ": " + x +";URL is :"+u.toString());
} finally {
try {
if (r != null) r.close();
if (in != null) in.close();
} catch (IOException y) {
- fail(service, ": " + y);
+ fail(service, ": " + y +";URL is :"+u.toString());
}
}
return names.iterator();
--- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/version.properties Wed Mar 09 14:54:18 2016 +0100
+++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/version.properties Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2012, 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
@@ -26,4 +26,4 @@
build-id=2.3.0-SNAPSHOT
build-version=JAX-WS RI 2.3.0-SNAPSHOT
major-version=2.3.0
-svn-revision=ffaa49e66cc05e1bb2ddc103076a340dad5df997
+svn-revision=282759e2b822078de9ba78c743ed663541c16ead
--- a/jaxws/src/java.xml.ws/share/classes/javax/xml/soap/FactoryFinder.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jaxws/src/java.xml.ws/share/classes/javax/xml/soap/FactoryFinder.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 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
@@ -184,7 +184,7 @@
private static String fromJDKProperties(String factoryId, String deprecatedFactoryId) {
Path path = null;
try {
- String JAVA_HOME = System.getProperty("java.home");
+ String JAVA_HOME = getSystemProperty("java.home");
path = Paths.get(JAVA_HOME, "conf", "jaxm.properties");
logger.log(Level.FINE, "Checking configuration in {0}", path);
--- a/jaxws/src/java.xml.ws/share/classes/javax/xml/ws/spi/FactoryFinder.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jaxws/src/java.xml.ws/share/classes/javax/xml/ws/spi/FactoryFinder.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -137,7 +137,8 @@
} catch (Exception ignored) {
logger.log(Level.SEVERE, "Error reading JAX-WS configuration from [" + path +
"] file. Check it is accessible and has correct format.", ignored);
- } return null;
+ }
+ return null;
}
private static final String OSGI_SERVICE_LOADER_CLASS_NAME = "com.sun.org.glassfish.hk2.osgiresourcelocator.ServiceLoader";
--- a/jaxws/src/jdk.xml.bind/share/classes/com/sun/codemodel/internal/JJavaName.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/codemodel/internal/JJavaName.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -85,7 +85,7 @@
* ("my_children","MyChildren","myChildren", and "MY-CHILDREN", "CODE003-children" respectively)
* <p>
* Although this method only works for English words, it handles non-English
- * words gracefully (by just returning it as-is.) For example, 日本語
+ * words gracefully (by just returning it as-is.) For example, "日本語"
* will be returned as-is without modified, not "日本語s"
* <p>
* This method doesn't handle suffixes very well. For example, passing
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle.properties Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,49 @@
+#
+# Copyright (c) 1997, 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. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# 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.
+#
+
+UNEXPECTED_NGCC_TOKEN = \
+ Unexpected {0} appears at line {1} column {2}
+
+BASEDIR_DOESNT_EXIST = \
+ Non-existent directory: {0}
+
+VERSION = \
+ schemagen 2.3.0-SNAPSHOT
+
+FULLVERSION = \
+ schemagen full version "2.3.0-SNAPSHOT"
+
+USAGE = \
+Usage: schemagen [-options ...] <java files> \n\
+Options: \n\
+\ \ \ \ -d <path> : specify where to place processor and javac generated class files\n\
+\ \ \ \ -cp <path> : specify where to find user specified files\n\
+\ \ \ \ -classpath <path> : specify where to find user specified files\n\
+\ \ \ \ -encoding <encoding> : specify encoding to be used for annotation processing/javac invocation \n\
+\ \ \ \ -episode <file> : generate episode file for separate compilation\n\
+\ \ \ \ -disableXmlSecurity : disables XML security features for usage on xml parsing apis \n\
+\ \ \ \ -version : display version information\n\
+\ \ \ \ -fullversion : display full version information\n\
+\ \ \ \ -help : display this usage message
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_de.properties Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,34 @@
+#
+# Copyright (c) 1997, 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. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# 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.
+#
+
+UNEXPECTED_NGCC_TOKEN = Nicht erkanntes {0} in Zeile {1} Spalte {2}
+
+BASEDIR_DOESNT_EXIST = Nicht vorhandenes Verzeichnis: {0}
+
+VERSION = schemagen 2.3.0-SNAPSHOT
+
+FULLVERSION = schemagen vollst\u00E4ndige Version "2.3.0-SNAPSHOT"
+
+USAGE = Verwendung: schemagen [-options ...] <java files> \nOptionen: \n\\ \\ \\ \\ -d <path> : Gibt an, wo die von Prozessor und javac generierten Klassendateien gespeichert werden sollen\n\\ \\ \\ \\ -cp <path> : Gibt an, wo die vom Benutzer angegebenen Dateien gespeichert sind\n\\ \\ \\ \\ -classpath <path> : Gibt an, wo die vom Benutzer angegebenen Dateien gespeichert sind\n\\ \\ \\ \\ -encoding <encoding> : Gibt die Codierung f\u00FCr die Annotationsverarbeitung/den javac-Aufruf an \n\\ \\ \\ \\ -episode <file> : Generiert Episodendatei f\u00FCr separate Kompilierung\n\\ \\ \\ \\ -version : Zeigt Versionsinformation an\n\\ \\ \\ \\ -fullversion : Zeigt vollst\u00E4ndige Versionsinformationen an\n\\ \\ \\ \\ -help : Zeigt diese Verwendungsmeldung an
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_es.properties Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,34 @@
+#
+# Copyright (c) 1997, 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. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# 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.
+#
+
+UNEXPECTED_NGCC_TOKEN = Aparece un {0} inesperado en la l\u00EDnea {1} y la columna {2}
+
+BASEDIR_DOESNT_EXIST = Directorio no existente: {0}
+
+VERSION = schemagen 2.3.0-SNAPSHOT
+
+FULLVERSION = versi\u00F3n completa de schemagen "2.3.0-SNAPSHOT"
+
+USAGE = Sintaxis: schemagen [-options ...] <archivos java> \nOpciones: \n\\ \\ \\ \\ -d <ruta de acceso> : especifique d\u00F3nde se colocan los archivos de clase generados por javac y el procesador\n\\ \\ \\ \\ -cp <ruta de acceso> : especifique d\u00F3nde se encuentran los archivos especificados por el usuario\n\\ \\ \\ \\ -encoding <codificaci\u00F3n> : especifique la codificaci\u00F3n que se va a utilizar para el procesamiento de anotaciones/llamada de javac\n\\ \\ \\ \\ -episode <archivo> : genera un archivo de episodio para una compilaci\u00F3n diferente\n\\ \\ \\ \\ -version : muestra la informaci\u00F3n de la versi\u00F3n\n\\ \\ \\ \\ -fullversion : muestra la informaci\u00F3n completa de la versi\u00F3n\n\\ \\ \\ \\ -help : muestra este mensaje de sintaxis
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_fr.properties Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,34 @@
+#
+# Copyright (c) 1997, 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. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# 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.
+#
+
+UNEXPECTED_NGCC_TOKEN = Un \u00E9l\u00E9ment {0} inattendu appara\u00EEt \u00E0 la ligne {1}, colonne {2}
+
+BASEDIR_DOESNT_EXIST = R\u00E9pertoire {0} inexistant
+
+VERSION = schemagen 2.3.0-SNAPSHOT
+
+FULLVERSION = version compl\u00E8te de schemagen "2.3.0-SNAPSHOT"
+
+USAGE = Syntaxe : schemagen [-options ...] <java files> \nOptions : \n\ \ \ \ -d <path> : indiquez o\u00F9 placer les fichiers de classe g\u00E9n\u00E9r\u00E9s par le processeur et le compilateur javac\n\ \ \ \ -cp <path> : indiquez o\u00F9 trouver les fichiers sp\u00E9cifi\u00E9s par l'utilisateur\n\ \ \ \ -classpath <path> : indiquez o\u00F9 trouver les fichiers sp\u00E9cifi\u00E9s par l'utilisateur\n\ \ \ \ -encoding <encoding> : indiquez l'encodage \u00E0 utiliser pour l'appel de javac/traitement de l'annotation \n\ \ \ \ -episode <file> : g\u00E9n\u00E9rez un fichier d'\u00E9pisode pour la compilation s\u00E9par\u00E9e\n\ \ \ \ -version : affichez les informations de version\n\ \ \ \ -fullversion : affichez les informations compl\u00E8tes de version\n\ \ \ \ -help : affichez ce message de syntaxe
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_it.properties Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,34 @@
+#
+# Copyright (c) 1997, 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. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# 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.
+#
+
+UNEXPECTED_NGCC_TOKEN = {0} imprevisto visualizzato sulla riga {1} colonna {2}
+
+BASEDIR_DOESNT_EXIST = Directory non esistente: {0}
+
+VERSION = schemagen 2.3.0-SNAPSHOT
+
+FULLVERSION = versione completa schemagen "2.3.0-SNAPSHOT"
+
+USAGE = Uso: schemagen [-options ...] <java files> \nOpzioni: \n\ \ \ \ -d <path> : specifica dove posizionare il processore e i file della classe generata javac\n\ \ \ \ -cp <path> : specifica dove trovare i file specificati dall'utente\n\ \ \ \ -classpath <path> : specifica dove trovare i file specificati dall'utente\n\ \ \ \ -encoding <encoding> : specifica la codifica da usare per l'elaborazione dell'annotazione/richiamo javac \n\ \ \ \ -episode <file> : genera il file di episodio per la compilazione separata\n\ \ \ \ -version : visualizza le informazioni sulla versione\n\ \ \ \ -fullversion : visualizza le informazioni sulla versione completa\n\ \ \ \ -help : visualizza questo messaggio sull'uso
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_ja.properties Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,34 @@
+#
+# Copyright (c) 1997, 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. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# 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.
+#
+
+UNEXPECTED_NGCC_TOKEN = \u4E88\u671F\u3057\u306A\u3044{0}\u304C\u884C{1}\u3001\u5217{2}\u306B\u3042\u308A\u307E\u3059
+
+BASEDIR_DOESNT_EXIST = \u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u304C\u5B58\u5728\u3057\u307E\u305B\u3093: {0}
+
+VERSION = schemagen 2.3.0-SNAPSHOT
+
+FULLVERSION = schemagen\u30D5\u30EB\u30FB\u30D0\u30FC\u30B8\u30E7\u30F3"2.3.0-SNAPSHOT"
+
+USAGE = \u4F7F\u7528\u65B9\u6CD5: schemagen [-options ...] <java files> \n\u30AA\u30D7\u30B7\u30E7\u30F3: \n\ \ \ \ -d <path> : \u30D7\u30ED\u30BB\u30C3\u30B5\u304A\u3088\u3073javac\u304C\u751F\u6210\u3057\u305F\u30AF\u30E9\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u3092\u7F6E\u304F\u4F4D\u7F6E\u3092\u6307\u5B9A\u3057\u307E\u3059\n\ \ \ \ -cp <path> : \u30E6\u30FC\u30B6\u30FC\u304C\u6307\u5B9A\u3057\u305F\u30D5\u30A1\u30A4\u30EB\u3092\u691C\u7D22\u3059\u308B\u4F4D\u7F6E\u3092\u6307\u5B9A\u3057\u307E\u3059\n\ \ \ \ -classpath <path> : \u30E6\u30FC\u30B6\u30FC\u304C\u6307\u5B9A\u3057\u305F\u30D5\u30A1\u30A4\u30EB\u3092\u691C\u7D22\u3059\u308B\u4F4D\u7F6E\u3092\u6307\u5B9A\u3057\u307E\u3059\n\ \ \ \ -encoding <encoding> : \u6CE8\u91C8\u51E6\u7406/javac\u547C\u51FA\u3057\u306B\u4F7F\u7528\u3059\u308B\u30A8\u30F3\u30B3\u30FC\u30C7\u30A3\u30F3\u30B0\u3092\u6307\u5B9A\u3057\u307E\u3059\n\ \ \ \ -episode <file> : \u30B3\u30F3\u30D1\u30A4\u30EB\u3054\u3068\u306B\u30A8\u30D4\u30BD\u30FC\u30C9\u30FB\u30D5\u30A1\u30A4\u30EB\u3092\u751F\u6210\u3057\u307E\u3059\n\ \ \ \ -version : \u30D0\u30FC\u30B8\u30E7\u30F3\u60C5\u5831\u3092\u8868\u793A\u3057\u307E\u3059\n\ \ \ \ -fullversion : \u30D5\u30EB\u30FB\u30D0\u30FC\u30B8\u30E7\u30F3\u60C5\u5831\u3092\u8868\u793A\u3057\u307E\u3059\n\ \ \ \ -help : \u3053\u306E\u4F7F\u7528\u4F8B\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u8868\u793A\u3057\u307E\u3059
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_ko.properties Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,34 @@
+#
+# Copyright (c) 1997, 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. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# 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.
+#
+
+UNEXPECTED_NGCC_TOKEN = \uC608\uC0C1\uCE58 \uC54A\uC740 {0}\uC774(\uAC00) {1}\uD589 {2}\uC5F4\uC5D0 \uB098\uD0C0\uB0A9\uB2C8\uB2E4.
+
+BASEDIR_DOESNT_EXIST = \uC874\uC7AC\uD558\uC9C0 \uC54A\uB294 \uB514\uB809\uD1A0\uB9AC: {0}
+
+VERSION = schemagen 2.3.0-SNAPSHOT
+
+FULLVERSION = schemagen \uC815\uC2DD \uBC84\uC804 "2.3.0-SNAPSHOT"
+
+USAGE = \uC0AC\uC6A9\uBC95: schemagen [-options ...] <java files> \n\uC635\uC158: \n\ \ \ \ -d <path> : \uD504\uB85C\uC138\uC11C \uBC0F javac\uC5D0\uC11C \uC0DD\uC131\uD55C \uD074\uB798\uC2A4 \uD30C\uC77C\uC744 \uBC30\uCE58\uD560 \uC704\uCE58\uB97C \uC9C0\uC815\uD569\uB2C8\uB2E4.\n\ \ \ \ -cp <path> : \uC0AC\uC6A9\uC790\uAC00 \uC9C0\uC815\uD55C \uD30C\uC77C\uC744 \uCC3E\uC744 \uC704\uCE58\uB97C \uC9C0\uC815\uD569\uB2C8\uB2E4.\n\ \ \ \ -classpath <path> : \uC0AC\uC6A9\uC790\uAC00 \uC9C0\uC815\uD55C \uD30C\uC77C\uC744 \uCC3E\uC744 \uC704\uCE58\uB97C \uC9C0\uC815\uD569\uB2C8\uB2E4.\n\ \ \ \ -encoding <encoding> : \uC8FC\uC11D \uCC98\uB9AC/javac \uD638\uCD9C\uC5D0 \uC0AC\uC6A9\uD560 \uC778\uCF54\uB529\uC744 \uC9C0\uC815\uD569\uB2C8\uB2E4. \n\ \ \ \ -episode <file> : \uBCC4\uB3C4 \uCEF4\uD30C\uC77C\uC744 \uC704\uD574 episode \uD30C\uC77C\uC744 \uC0DD\uC131\uD569\uB2C8\uB2E4.\n\ \ \ \ -version : \uBC84\uC804 \uC815\uBCF4\uB97C \uD45C\uC2DC\uD569\uB2C8\uB2E4.\n\ \ \ \ -fullversion : \uC815\uC2DD \uBC84\uC804 \uC815\uBCF4\uB97C \uD45C\uC2DC\uD569\uB2C8\uB2E4.\n\ \ \ \ -help : \uC774 \uC0AC\uC6A9\uBC95 \uBA54\uC2DC\uC9C0\uB97C \uD45C\uC2DC\uD569\uB2C8\uB2E4.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_pt_BR.properties Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,34 @@
+#
+# Copyright (c) 1997, 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. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# 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.
+#
+
+UNEXPECTED_NGCC_TOKEN = {0} inesperado aparece na linha {1} coluna {2}
+
+BASEDIR_DOESNT_EXIST = Diret\u00F3rio n\u00E3o existente: {0}
+
+VERSION = gera\u00E7\u00E3o do esquema 2.3.0-SNAPSHOT
+
+FULLVERSION = vers\u00E3o completa da gera\u00E7\u00E3o do esquema "2.3.0-SNAPSHOT"
+
+USAGE = Uso: gera\u00E7\u00E3o do esquema [-options ...] <java files> \nOp\u00E7\u00F5es: \n\\ \\ \\ \\ -d <path> : especificar onde colocar o processador e os arquivos da classe gerados por javac\n\\ \\ \\ \\ -cp <path> : especificar onde localizar arquivos especificados pelo usu\u00E1rio\n\\ \\ \\ \\ -classpath <path> : especificar onde localizar os arquivos especificados pelo usu\u00E1rio\n\\ \\ \\ \\ -encoding <encoding> : especificar codifica\u00E7\u00E3o a ser usada para processamento de anota\u00E7\u00E3o/chamada javac \n\\ \\ \\ \\ -episode <file> : gerar arquivo do epis\u00F3dio para compila\u00E7\u00E3o separada\n\\ \\ \\ \\ -version : exibir informa\u00E7\u00F5es da vers\u00E3o\n\\ \\ \\ \\ -fullversion : exibir informa\u00E7\u00F5es da vers\u00E3o completa\n\\ \\ \\ \\ -help : exibir esta mensagem de uso
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_zh_CN.properties Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,34 @@
+#
+# Copyright (c) 1997, 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. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# 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.
+#
+
+UNEXPECTED_NGCC_TOKEN = \u5728\u7B2C {1} \u884C, \u7B2C {2} \u5217\u51FA\u73B0\u610F\u5916\u7684{0}
+
+BASEDIR_DOESNT_EXIST = \u4E0D\u5B58\u5728\u7684\u76EE\u5F55: {0}
+
+VERSION = schemagen 2.3.0-SNAPSHOT
+
+FULLVERSION = schemagen \u5B8C\u6574\u7248\u672C "2.3.0-SNAPSHOT"
+
+USAGE = \u7528\u6CD5: schemagen [-options ...] <java files> \n\u9009\u9879: \n\ \ \ \ -d <path> : \u6307\u5B9A\u653E\u7F6E\u5904\u7406\u7A0B\u5E8F\u548C javac \u751F\u6210\u7684\u7C7B\u6587\u4EF6\u7684\u4F4D\u7F6E\n\ \ \ \ -cp <path> : \u6307\u5B9A\u67E5\u627E\u7528\u6237\u6307\u5B9A\u6587\u4EF6\u7684\u4F4D\u7F6E\n\ \ \ \ -classpath <path> : \u6307\u5B9A\u67E5\u627E\u7528\u6237\u6307\u5B9A\u6587\u4EF6\u7684\u4F4D\u7F6E\n\ \ \ \ -encoding <encoding> : \u6307\u5B9A\u7528\u4E8E\u6CE8\u91CA\u5904\u7406/javac \u8C03\u7528\u7684\u7F16\u7801\n\ \ \ \ -episode <file> : \u751F\u6210\u7247\u6BB5\u6587\u4EF6\u4EE5\u4F9B\u5355\u72EC\u7F16\u8BD1\n\ \ \ \ -version : \u663E\u793A\u7248\u672C\u4FE1\u606F\n\ \ \ \ -fullversion : \u663E\u793A\u5B8C\u6574\u7684\u7248\u672C\u4FE1\u606F\n\ \ \ \ -help : \u663E\u793A\u6B64\u7528\u6CD5\u6D88\u606F
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_zh_TW.properties Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,34 @@
+#
+# Copyright (c) 1997, 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. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# 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.
+#
+
+UNEXPECTED_NGCC_TOKEN = \u672A\u9810\u671F\u7684 {0} \u986F\u793A\u65BC\u884C {1} \u8CC7\u6599\u6B04 {2}
+
+BASEDIR_DOESNT_EXIST = \u4E0D\u5B58\u5728\u7684\u76EE\u9304: {0}
+
+VERSION = schemagen 2.3.0-SNAPSHOT
+
+FULLVERSION = schemagen \u5B8C\u6574\u7248\u672C "2.3.0-SNAPSHOT"
+
+USAGE = \u7528\u6CD5: schemagen [-options ...] <java files> \n\u9078\u9805: \n\\ \\ \\ \\ -d <path> : \u6307\u5B9A\u8655\u7406\u5668\u4EE5\u53CA javac \u7522\u751F\u7684\u985E\u5225\u6A94\u6848\u653E\u7F6E\u4F4D\u7F6E\n\\ \\ \\ \\ -cp <path> : \u6307\u5B9A\u8981\u5C0B\u627E\u4F7F\u7528\u8005\u6307\u5B9A\u6A94\u6848\u7684\u4F4D\u7F6E\n\\ \\ \\ \\ -classpath <path> : \u6307\u5B9A\u8981\u5C0B\u627E\u4F7F\u7528\u8005\u6307\u5B9A\u6A94\u6848\u7684\u4F4D\u7F6E\n\\ \\ \\ \\ -encoding <encoding> : \u6307\u5B9A\u8981\u7528\u65BC\u8A3B\u89E3\u8655\u7406/javac \u547C\u53EB\u7684\u7DE8\u78BC \n\\ \\ \\ \\ -episode <file> : \u7522\u751F\u7368\u7ACB\u7DE8\u8B6F\u7684\u4E8B\u4EF6 (episode) \u6A94\u6848\n\\ \\ \\ \\ -version : \u986F\u793A\u7248\u672C\u8CC7\u8A0A\n\\ \\ \\ \\ -fullversion : \u986F\u793A\u5B8C\u6574\u7248\u672C\u8CC7\u8A0A\n\\ \\ \\ \\ -help : \u986F\u793A\u6B64\u7528\u6CD5\u8A0A\u606F
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle.properties Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,33 @@
+#
+# Copyright (c) 1997, 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. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# 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.
+#
+
+NON_EXISTENT_FILE = \
+ Directory "{0}" doesn't exist.
+
+UNRECOGNIZED_PARAMETER = \
+ Unrecognized option {0} is not valid.
+
+OPERAND_MISSING = \
+ Option "{0}" is missing an operand.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_de.properties Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,30 @@
+#
+# Copyright (c) 1997, 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. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# 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.
+#
+
+NON_EXISTENT_FILE = Verzeichnis "{0}" ist nicht vorhanden.
+
+UNRECOGNIZED_PARAMETER = Unbekannte Option {0} ist nicht g\u00FCltig.
+
+OPERAND_MISSING = In Option "{0}" fehlt ein Operand.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_es.properties Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,30 @@
+#
+# Copyright (c) 1997, 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. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# 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.
+#
+
+NON_EXISTENT_FILE = El directorio "{0}" no existe.
+
+UNRECOGNIZED_PARAMETER = La opci\u00F3n no reconocida {0} no es v\u00E1lida.
+
+OPERAND_MISSING = A la opci\u00F3n "{0}" le falta un operando.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_fr.properties Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,30 @@
+#
+# Copyright (c) 1997, 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. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# 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.
+#
+
+NON_EXISTENT_FILE = Le r\u00E9pertoire "{0}" n''existe pas.
+
+UNRECOGNIZED_PARAMETER = L''option {0} non reconnue n''est pas valide.
+
+OPERAND_MISSING = Un op\u00E9rande est manquant dans l''option "{0}".
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_it.properties Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,30 @@
+#
+# Copyright (c) 1997, 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. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# 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.
+#
+
+NON_EXISTENT_FILE = La directory "{0}" non esiste.
+
+UNRECOGNIZED_PARAMETER = L''opzione non riconosciuta {0} non \u00E8 valida.
+
+OPERAND_MISSING = Operando mancante nell''opzione "{0}".
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_ja.properties Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,30 @@
+#
+# Copyright (c) 1997, 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. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# 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.
+#
+
+NON_EXISTENT_FILE = \u30C7\u30A3\u30EC\u30AF\u30C8\u30EA"{0}"\u304C\u5B58\u5728\u3057\u307E\u305B\u3093\u3002
+
+UNRECOGNIZED_PARAMETER = \u8A8D\u8B58\u3055\u308C\u306A\u3044\u30AA\u30D7\u30B7\u30E7\u30F3{0}\u306F\u7121\u52B9\u3067\u3059\u3002
+
+OPERAND_MISSING = \u30AA\u30D7\u30B7\u30E7\u30F3"{0}"\u306B\u30AA\u30DA\u30E9\u30F3\u30C9\u304C\u3042\u308A\u307E\u305B\u3093\u3002
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_ko.properties Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,30 @@
+#
+# Copyright (c) 1997, 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. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# 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.
+#
+
+NON_EXISTENT_FILE = "{0}" \uB514\uB809\uD1A0\uB9AC\uAC00 \uC874\uC7AC\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.
+
+UNRECOGNIZED_PARAMETER = \uC778\uC2DD\uD560 \uC218 \uC5C6\uB294 \uC635\uC158 {0}\uC740(\uB294) \uBD80\uC801\uD569\uD569\uB2C8\uB2E4.
+
+OPERAND_MISSING = "{0}" \uC635\uC158\uC5D0 \uD53C\uC5F0\uC0B0\uC790\uAC00 \uB204\uB77D\uB418\uC5C8\uC2B5\uB2C8\uB2E4.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_pt_BR.properties Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,30 @@
+#
+# Copyright (c) 1997, 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. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# 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.
+#
+
+NON_EXISTENT_FILE = O diret\u00F3rio "{0}" n\u00E3o existe.
+
+UNRECOGNIZED_PARAMETER = A op\u00E7\u00E3o {0} n\u00E3o reconhecida \u00E9 inv\u00E1lida.
+
+OPERAND_MISSING = A op\u00E7\u00E3o "{0}" n\u00E3o encontrou um operando.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_zh_CN.properties Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,30 @@
+#
+# Copyright (c) 1997, 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. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# 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.
+#
+
+NON_EXISTENT_FILE = \u76EE\u5F55 "{0}" \u4E0D\u5B58\u5728\u3002
+
+UNRECOGNIZED_PARAMETER = \u65E0\u6CD5\u8BC6\u522B\u7684\u9009\u9879{0}, \u8BE5\u9009\u9879\u65E0\u6548\u3002
+
+OPERAND_MISSING = \u9009\u9879 "{0}" \u7F3A\u5C11\u64CD\u4F5C\u6570\u3002
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_zh_TW.properties Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,30 @@
+#
+# Copyright (c) 1997, 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. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# 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.
+#
+
+NON_EXISTENT_FILE = \u76EE\u9304 "{0}" \u4E0D\u5B58\u5728.
+
+UNRECOGNIZED_PARAMETER = \u7121\u6CD5\u8FA8\u8B58\u7684\u9078\u9805 {0} \u7121\u6548.
+
+OPERAND_MISSING = \u9078\u9805 "{0}" \u907A\u6F0F\u904B\u7B97\u5143.
--- a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/model/CTypeRef.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/model/CTypeRef.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -68,7 +68,6 @@
public CTypeRef(CNonElement type, XSElementDecl decl) {
this(type, BGMBuilder.getName(decl),getSimpleTypeName(decl), decl.isNillable(), decl.getDefaultValue() );
-
}
public QName getTypeName() {
@@ -100,10 +99,15 @@
*/
private static QName resolveSimpleTypeName(XSType declType) {
QName name = BGMBuilder.getName(declType);
- if (name != null && !XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(name.getNamespaceURI()))
- return resolveSimpleTypeName(declType.getBaseType());
- else
- return name;
+ QName result = null;
+ if (name != null && !XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(name.getNamespaceURI())) {
+ result = resolveSimpleTypeName(declType.getBaseType());
+ } else {
+ if ( !"anySimpleType".equals(declType.getName()) ) {
+ result = name;
+ }
+ }
+ return result;
}
public CTypeRef(CNonElement type, QName elementName, QName typeName, boolean nillable, XmlString defaultValue) {
--- a/jaxws/src/jdk.xml.ws/share/classes/com/sun/tools/internal/ws/version.properties Wed Mar 09 14:54:18 2016 +0100
+++ b/jaxws/src/jdk.xml.ws/share/classes/com/sun/tools/internal/ws/version.properties Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2012, 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
@@ -26,4 +26,4 @@
build-id=2.3.0-SNAPSHOT
build-version=JAX-WS RI 2.3.0-SNAPSHOT
major-version=2.3.0
-svn-revision=ffaa49e66cc05e1bb2ddc103076a340dad5df997
+svn-revision=282759e2b822078de9ba78c743ed663541c16ead
--- a/jdk/.hgtags Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/.hgtags Wed Mar 09 14:18:12 2016 +0100
@@ -350,3 +350,4 @@
55518739e399a1066c8613e19100d51b38d9f223 jdk-9+105
6e9ecae50b4e0d37483fb2719202eea5dca026a4 jdk-9+106
8701b2bb1d2e1b9abc2a9be0933993c7150a9dbe jdk-9+107
+42794e648cfe9fd67461dcbe8b7594241a84bcff jdk-9+108
--- a/jdk/make/gendata/GendataHtml32dtd.gmk Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/make/gendata/GendataHtml32dtd.gmk Wed Mar 09 14:18:12 2016 +0100
@@ -30,6 +30,6 @@
$(call LogInfo, Generating HTML DTD file)
$(MKDIR) -p $(@D)
$(RM) $@
- ($(TOOL_DTDBUILDER) $(LOG_INFO) html32 > $@) || exit 1
+ ($(TOOL_DTDBUILDER) html32 > $@) || exit 1
TARGETS += $(HTML32DTD)
--- a/jdk/make/gensrc/GensrcCLDR.gmk Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/make/gensrc/GensrcCLDR.gmk Wed Mar 09 14:18:12 2016 +0100
@@ -30,7 +30,7 @@
GENSRC_DIR := $(SUPPORT_OUTPUTDIR)/gensrc/jdk.localedata
CLDR_BASEMETAINFO_FILE := $(GENSRC_BASEDIR)/sun/util/cldr/CLDRBaseLocaleDataMetaInfo.java
-CLDR_METAINFO_FILE := $(GENSRC_DIR)/sun/util/resources/cldr/provider/CLDRLocaleDataMetaInfo_jdk_localedata.java
+CLDR_METAINFO_FILE := $(GENSRC_DIR)/sun/util/resources/cldr/provider/CLDRLocaleDataMetaInfo.java
CLDR_BASE_LOCALES := "en-US"
--- a/jdk/make/gensrc/GensrcMisc.gmk Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/make/gensrc/GensrcMisc.gmk Wed Mar 09 14:18:12 2016 +0100
@@ -25,11 +25,11 @@
##########################################################################################
# Install the launcher name, release version string, full version
-# string and the runtime name into the Version.java file.
+# string and the runtime name into the VersionProps.java file.
$(eval $(call SetupTextFileProcessing, BUILD_VERSION_JAVA, \
- SOURCE_FILES := $(JDK_TOPDIR)/src/java.base/share/classes/sun/misc/Version.java.template, \
- OUTPUT_FILE := $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/misc/Version.java, \
+ SOURCE_FILES := $(JDK_TOPDIR)/src/java.base/share/classes/java/lang/VersionProps.java.template, \
+ OUTPUT_FILE := $(SUPPORT_OUTPUTDIR)/gensrc/java.base/java/lang/VersionProps.java, \
REPLACEMENTS := \
@@LAUNCHER_NAME@@ => $(LAUNCHER_NAME) ; \
@@RUNTIME_NAME@@ => $(RUNTIME_NAME) ; \
--- a/jdk/make/mapfiles/libjava/mapfile-vers Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/make/mapfiles/libjava/mapfile-vers Wed Mar 09 14:18:12 2016 +0100
@@ -268,8 +268,6 @@
Java_sun_reflect_Reflection_getCallerClass__;
Java_sun_reflect_Reflection_getCallerClass__I;
Java_sun_reflect_Reflection_getClassAccessFlags;
- Java_sun_misc_Version_getJdkVersionInfo;
- Java_sun_misc_Version_getJvmVersionInfo;
Java_jdk_internal_misc_VM_latestUserDefinedLoader;
Java_jdk_internal_misc_VM_getuid;
Java_jdk_internal_misc_VM_geteuid;
--- a/jdk/make/src/classes/build/tools/module/boot.modules Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/make/src/classes/build/tools/module/boot.modules Wed Mar 09 14:18:12 2016 +0100
@@ -22,6 +22,7 @@
jdk.deploy.osx
jdk.httpserver
jdk.jfr
+jdk.jsobject
jdk.net
jdk.vm.cds
jdk.vm.ci
--- a/jdk/src/java.base/share/classes/com/sun/crypto/provider/DHKeyPairGenerator.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/DHKeyPairGenerator.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -43,7 +43,7 @@
* <li>By providing the size in bits of the prime modulus -
* This will be used to create a prime modulus and base generator, which will
* then be used to create the Diffie-Hellman key pair. The default size of the
- * prime modulus is 1024 bits.
+ * prime modulus is 2048 bits.
* <li>By providing a prime modulus and base generator
* </ul>
*
@@ -68,7 +68,7 @@
public DHKeyPairGenerator() {
super();
- initialize(1024, null);
+ initialize(2048, null);
}
/**
--- a/jdk/src/java.base/share/classes/com/sun/crypto/provider/DHParameterGenerator.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/DHParameterGenerator.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -37,7 +37,7 @@
*
* <p>The Diffie-Hellman parameter generation accepts the size in bits of the
* prime modulus and the size in bits of the random exponent as input.
- * The size of the prime modulus defaults to 1024 bits.
+ * The size of the prime modulus defaults to 2048 bits.
*
* @author Jan Luehe
*
@@ -50,7 +50,7 @@
extends AlgorithmParameterGeneratorSpi {
// The size in bits of the prime modulus
- private int primeSize = 1024;
+ private int primeSize = 2048;
// The size in bits of the random exponent (private value)
private int exponentSize = 0;
--- a/jdk/src/java.base/share/classes/com/sun/crypto/provider/PKCS12PBECipherCore.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/PKCS12PBECipherCore.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -50,6 +50,7 @@
private CipherCore cipher;
private int blockSize;
private int keySize;
+ private int keyLength; // in bits
private String algo = null;
private String pbeAlgo = null;
private byte[] salt = null;
@@ -166,16 +167,18 @@
throws NoSuchAlgorithmException {
algo = symmCipherAlg;
+ keyLength = defKeySize * 8;
if (algo.equals("RC4")) {
- pbeAlgo = "PBEWithSHA1AndRC4_" + defKeySize * 8;
+ pbeAlgo = "PBEWithSHA1AndRC4_" + keyLength;
} else {
SymmetricCipher symmCipher = null;
if (algo.equals("DESede")) {
symmCipher = new DESedeCrypt();
pbeAlgo = "PBEWithSHA1AndDESede";
+ keyLength = 112; // effective key length
} else if (algo.equals("RC2")) {
symmCipher = new RC2Crypt();
- pbeAlgo = "PBEWithSHA1AndRC2_" + defKeySize * 8;
+ pbeAlgo = "PBEWithSHA1AndRC2_" + keyLength;
} else {
throw new NoSuchAlgorithmException("No Cipher implementation " +
"for PBEWithSHA1And" + algo);
@@ -406,7 +409,7 @@
}
int implGetKeySize(Key key) throws InvalidKeyException {
- return keySize;
+ return keyLength;
}
byte[] implWrap(Key key) throws IllegalBlockSizeException,
--- a/jdk/src/java.base/share/classes/java/lang/AbstractStringBuilder.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/lang/AbstractStringBuilder.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -133,39 +133,62 @@
}
/**
- * This method has the same contract as ensureCapacity, but is
- * never synchronized.
+ * For positive values of {@code minimumCapacity}, this method
+ * behaves like {@code ensureCapacity}, however it is never
+ * synchronized.
+ * If {@code minimumCapacity} is non positive due to numeric
+ * overflow, this method throws {@code OutOfMemoryError}.
*/
private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
- int capacity = value.length >> coder;
- if (minimumCapacity - capacity > 0) {
- expandCapacity(minimumCapacity);
+ int oldCapacity = value.length >> coder;
+ if (minimumCapacity - oldCapacity > 0) {
+ value = Arrays.copyOf(value,
+ newCapacity(minimumCapacity) << coder);
}
}
/**
- * This implements the expansion semantics of ensureCapacity with no
- * size check or synchronization.
+ * The maximum size of array to allocate (unless necessary).
+ * Some VMs reserve some header words in an array.
+ * Attempts to allocate larger arrays may result in
+ * OutOfMemoryError: Requested array size exceeds VM limit
*/
- private void expandCapacity(int minimumCapacity) {
- int newCapacity = (value.length >> coder) * 2 + 2;
- if (newCapacity - minimumCapacity < 0) {
- newCapacity = minimumCapacity;
+ private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
+
+ /**
+ * Returns a capacity at least as large as the given minimum capacity.
+ * Returns the current capacity increased by the same amount + 2 if
+ * that suffices.
+ * Will not return a capacity greater than
+ * {@code (MAX_ARRAY_SIZE >> coder)} unless the given minimum capacity
+ * is greater than that.
+ *
+ * @param minCapacity the desired minimum capacity
+ * @throws OutOfMemoryError if minCapacity is less than zero or
+ * greater than (Integer.MAX_VALUE >> coder)
+ */
+ private int newCapacity(int minCapacity) {
+ // overflow-conscious code
+ int oldCapacity = value.length >> coder;
+ int newCapacity = (oldCapacity << 1) + 2;
+ if (newCapacity - minCapacity < 0) {
+ newCapacity = minCapacity;
}
- if (newCapacity < 0) {
- if (minimumCapacity < 0) {// overflow
- throw new OutOfMemoryError();
- }
- newCapacity = Integer.MAX_VALUE;
+ int SAFE_BOUND = MAX_ARRAY_SIZE >> coder;
+ return (newCapacity <= 0 || SAFE_BOUND - newCapacity < 0)
+ ? hugeCapacity(minCapacity)
+ : newCapacity;
+ }
+
+ private int hugeCapacity(int minCapacity) {
+ int SAFE_BOUND = MAX_ARRAY_SIZE >> coder;
+ int UNSAFE_BOUND = Integer.MAX_VALUE >> coder;
+ if (UNSAFE_BOUND - minCapacity < 0) { // overflow
+ throw new OutOfMemoryError();
}
- if (coder != LATIN1 && newCapacity > StringUTF16.MAX_LENGTH) {
- if (minimumCapacity >= StringUTF16.MAX_LENGTH) {
- throw new OutOfMemoryError();
- }
- newCapacity = StringUTF16.MAX_LENGTH;
- }
- this.value = Arrays.copyOf(value, newCapacity << coder);
+ return (minCapacity > SAFE_BOUND)
+ ? minCapacity : SAFE_BOUND;
}
/**
--- a/jdk/src/java.base/share/classes/java/lang/System.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/lang/System.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 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
@@ -1418,8 +1418,7 @@
* for the given {@code caller}.
*
* @param name the name of the logger.
- * @param caller the class for which the logger is being requested;
- * can be {@code null}.
+ * @param caller the class for which the logger is being requested.
*
* @return a {@link Logger logger} suitable for the given caller's
* use.
@@ -1831,7 +1830,7 @@
lineSeparator = props.getProperty("line.separator");
- sun.misc.Version.init();
+ VersionProps.init();
FileInputStream fdIn = new FileInputStream(FileDescriptor.in);
FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/VersionProps.java.template Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 1999, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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 java.lang;
+
+import java.io.PrintStream;
+
+class VersionProps {
+
+
+ private static final String launcher_name =
+ "@@LAUNCHER_NAME@@";
+
+ private static final String java_version =
+ "@@VERSION_SHORT@@";
+
+ private static final String java_runtime_name =
+ "@@RUNTIME_NAME@@";
+
+ private static final String java_runtime_version =
+ "@@VERSION_STRING@@";
+
+ static {
+ init();
+ }
+
+ public static void init() {
+ System.setProperty("java.version", java_version);
+ System.setProperty("java.runtime.version", java_runtime_version);
+ System.setProperty("java.runtime.name", java_runtime_name);
+ }
+
+ /**
+ * In case you were wondering this method is called by java -version.
+ * Sad that it prints to stderr; would be nicer if default printed on
+ * stdout.
+ */
+ public static void print() {
+ print(System.err);
+ }
+
+ /**
+ * This is the same as print except that it adds an extra line-feed
+ * at the end, typically used by the -showversion in the launcher
+ */
+ public static void println() {
+ print(System.err);
+ System.err.println();
+ }
+
+ /**
+ * Give a stream, it will print version info on it.
+ */
+ public static void print(PrintStream ps) {
+ boolean isHeadless = false;
+
+ /* Report that we're running headless if the property is true */
+ String headless = System.getProperty("java.awt.headless");
+ if ( (headless != null) && (headless.equalsIgnoreCase("true")) ) {
+ isHeadless = true;
+ }
+
+ /* First line: platform version. */
+ ps.println(launcher_name + " version \"" + java_version + "\"");
+
+ /* Second line: runtime version (ie, libraries). */
+
+ String jdk_debug_level = System.getProperty("jdk.debug", "release");
+ /* Debug level is not printed for "release" builds */
+ if ("release".equals(jdk_debug_level)) {
+ jdk_debug_level = "";
+ } else {
+ jdk_debug_level = jdk_debug_level + " ";
+ }
+
+ ps.print(java_runtime_name + " (" + jdk_debug_level + "build " + java_runtime_version);
+
+ if (java_runtime_name.indexOf("Embedded") != -1 && isHeadless) {
+ // embedded builds report headless state
+ ps.print(", headless");
+ }
+ ps.println(')');
+
+ /* Third line: JVM information. */
+ String java_vm_name = System.getProperty("java.vm.name");
+ String java_vm_version = System.getProperty("java.vm.version");
+ String java_vm_info = System.getProperty("java.vm.info");
+ ps.println(java_vm_name + " (" + jdk_debug_level + "build " + java_vm_version + ", " +
+ java_vm_info + ")");
+ }
+
+}
\ No newline at end of file
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java Wed Mar 09 14:18:12 2016 +0100
@@ -3268,12 +3268,17 @@
* <li>This list of types is called the "common prefix".
* </ol>
* <p>
- * <em>Step 1B: Determine loop parameters.</em><ol type="a">
- * <li>Examine init function parameter lists.
- * <li>Omitted init functions are deemed to have {@code null} parameter lists.
- * <li>All init function parameter lists must be effectively identical.
- * <li>The longest parameter list (which is necessarily unique) is called the "common suffix".
+ * <em>Step 1B: Determine loop parameters.</em><ul>
+ * <li><b>If at least one init function is given,</b><ol type="a">
+ * <li>Examine init function parameter lists.
+ * <li>Omitted init functions are deemed to have {@code null} parameter lists.
+ * <li>All init function parameter lists must be effectively identical.
+ * <li>The longest parameter list (which is necessarily unique) is called the "common suffix".
* </ol>
+ * <li><b>If no init function is given,</b><ol type="a">
+ * <li>Examine the suffixes of the step, pred, and fini parameter lists, after removing the "common prefix".
+ * <li>The longest of these suffixes is taken as the "common suffix".
+ * </ol></ul>
* <p>
* <em>Step 1C: Determine loop return type.</em><ol type="a">
* <li>Examine fini function return types, disregarding omitted fini functions.
@@ -3286,9 +3291,6 @@
* <li>Every non-omitted pred function must have a {@code boolean} return type.
* </ol>
* <p>
- * (Implementation Note: Steps 1A, 1B, 1C, 1D are logically independent of each other, and may be performed in any
- * order.)
- * <p>
* <em>Step 2: Determine parameter lists.</em><ol type="a">
* <li>The parameter list for the resulting loop handle will be the "common suffix".
* <li>The parameter list for init functions will be adjusted to the "common suffix". (Note that their parameter
@@ -3375,10 +3377,10 @@
* <blockquote><pre>{@code
* // iterative implementation of the factorial function as a loop handle
* static int one(int k) { return 1; }
- * int inc(int i, int acc, int k) { return i + 1; }
- * int mult(int i, int acc, int k) { return i * acc; }
- * boolean pred(int i, int acc, int k) { return i < k; }
- * int fin(int i, int acc, int k) { return acc; }
+ * static int inc(int i, int acc, int k) { return i + 1; }
+ * static int mult(int i, int acc, int k) { return i * acc; }
+ * static boolean pred(int i, int acc, int k) { return i < k; }
+ * static int fin(int i, int acc, int k) { return acc; }
* // assume MH_one, MH_inc, MH_mult, MH_pred, and MH_fin are handles to the above methods
* // null initializer for counter, should initialize to 0
* MethodHandle[] counterClause = new MethodHandle[]{null, MH_inc};
@@ -3436,9 +3438,7 @@
collect(Collectors.toList());
// Step 1B: determine loop parameters.
- final List<Class<?>> empty = new ArrayList<>();
- final List<Class<?>> commonSuffix = init.stream().filter(Objects::nonNull).map(MethodHandle::type).
- map(MethodType::parameterList).reduce((p, q) -> p.size() >= q.size() ? p : q).orElse(empty);
+ final List<Class<?>> commonSuffix = buildCommonSuffix(init, step, pred, fini, commonPrefix.size());
checkLoop1b(init, commonSuffix);
// Step 1C: determine loop return type.
@@ -3520,15 +3520,15 @@
* @apiNote Example:
* <blockquote><pre>{@code
* // implement the zip function for lists as a loop handle
- * List<String> initZip(Iterator<String> a, Iterator<String> b) { return new ArrayList<>(); }
- * boolean zipPred(List<String> zip, Iterator<String> a, Iterator<String> b) { return a.hasNext() && b.hasNext(); }
- * List<String> zipStep(List<String> zip, Iterator<String> a, Iterator<String> b) {
+ * static List<String> initZip(Iterator<String> a, Iterator<String> b) { return new ArrayList<>(); }
+ * static boolean zipPred(List<String> zip, Iterator<String> a, Iterator<String> b) { return a.hasNext() && b.hasNext(); }
+ * static List<String> zipStep(List<String> zip, Iterator<String> a, Iterator<String> b) {
* zip.add(a.next());
* zip.add(b.next());
* return zip;
* }
* // assume MH_initZip, MH_zipPred, and MH_zipStep are handles to the above methods
- * MethodHandle loop = MethodHandles.doWhileLoop(MH_initZip, MH_zipStep, MH_zipPred);
+ * MethodHandle loop = MethodHandles.whileLoop(MH_initZip, MH_zipPred, MH_zipStep);
* List<String> a = Arrays.asList("a", "b", "c", "d");
* List<String> b = Arrays.asList("e", "f", "g", "h");
* List<String> zipped = Arrays.asList("a", "e", "b", "f", "c", "g", "d", "h");
@@ -3594,9 +3594,9 @@
* @apiNote Example:
* <blockquote><pre>{@code
* // int i = 0; while (i < limit) { ++i; } return i; => limit
- * int zero(int limit) { return 0; }
- * int step(int i, int limit) { return i + 1; }
- * boolean pred(int i, int limit) { return i < limit; }
+ * static int zero(int limit) { return 0; }
+ * static int step(int i, int limit) { return i + 1; }
+ * static boolean pred(int i, int limit) { return i < limit; }
* // assume MH_zero, MH_step, and MH_pred are handles to the above methods
* MethodHandle loop = MethodHandles.doWhileLoop(MH_zero, MH_step, MH_pred);
* assertEquals(23, loop.invoke(23));
@@ -3664,8 +3664,8 @@
* <blockquote><pre>{@code
* // String s = "Lambdaman!"; for (int i = 0; i < 13; ++i) { s = "na " + s; } return s;
* // => a variation on a well known theme
- * String start(String arg) { return arg; }
- * String step(int counter, String v, String arg) { return "na " + v; }
+ * static String start(String arg) { return arg; }
+ * static String step(int counter, String v, String arg) { return "na " + v; }
* // assume MH_start and MH_step are handles to the two methods above
* MethodHandle fit13 = MethodHandles.constant(int.class, 13);
* MethodHandle loop = MethodHandles.countedLoop(fit13, MH_start, MH_step);
@@ -3808,11 +3808,11 @@
* @apiNote Example:
* <blockquote><pre>{@code
* // reverse a list
- * List<String> reverseStep(String e, List<String> r, List<String> l) {
+ * static List<String> reverseStep(String e, List<String> r, List<String> l) {
* r.add(0, e);
* return r;
* }
- * List<String> newArrayList(List<String> l) { return new ArrayList<>(); }
+ * static List<String> newArrayList(List<String> l) { return new ArrayList<>(); }
* // assume MH_reverseStep, MH_newArrayList are handles to the above methods
* MethodHandle loop = MethodHandles.iteratedLoop(null, MH_newArrayList, MH_reverseStep);
* List<String> list = Arrays.asList("a", "b", "c", "d", "e");
@@ -4084,6 +4084,21 @@
}
}
+ private static List<Class<?>> buildCommonSuffix(List<MethodHandle> init, List<MethodHandle> step, List<MethodHandle> pred, List<MethodHandle> fini, int cpSize) {
+ final List<Class<?>> empty = List.of();
+ final List<MethodHandle> nonNullInits = init.stream().filter(Objects::nonNull).collect(Collectors.toList());
+ if (nonNullInits.isEmpty()) {
+ final List<Class<?>> longest = Stream.of(step, pred, fini).flatMap(List::stream).filter(Objects::nonNull).
+ // take only those that can contribute to a common suffix because they are longer than the prefix
+ map(MethodHandle::type).filter(t -> t.parameterCount() > cpSize).map(MethodType::parameterList).
+ reduce((p, q) -> p.size() >= q.size() ? p : q).orElse(empty);
+ return longest.size() == 0 ? empty : longest.subList(cpSize, longest.size());
+ } else {
+ return nonNullInits.stream().map(MethodHandle::type).map(MethodType::parameterList).
+ reduce((p, q) -> p.size() >= q.size() ? p : q).get();
+ }
+ }
+
private static void checkLoop1b(List<MethodHandle> init, List<Class<?>> commonSuffix) {
if (init.stream().filter(Objects::nonNull).map(MethodHandle::type).map(MethodType::parameterList).
anyMatch(pl -> !pl.equals(commonSuffix.subList(0, pl.size())))) {
@@ -4109,8 +4124,10 @@
}
private static void checkLoop2(List<MethodHandle> step, List<MethodHandle> pred, List<MethodHandle> fini, List<Class<?>> commonParameterSequence) {
+ final int cpSize = commonParameterSequence.size();
if (Stream.of(step, pred, fini).flatMap(List::stream).filter(Objects::nonNull).map(MethodHandle::type).
- map(MethodType::parameterList).anyMatch(pl -> !pl.equals(commonParameterSequence.subList(0, pl.size())))) {
+ map(MethodType::parameterList).
+ anyMatch(pl -> pl.size() > cpSize || !pl.equals(commonParameterSequence.subList(0, pl.size())))) {
throw newIllegalArgumentException("found non-effectively identical parameter type lists:\nstep: " + step +
"\npred: " + pred + "\nfini: " + fini + " (common parameter sequence: " + commonParameterSequence + ")");
}
--- a/jdk/src/java.base/share/classes/java/net/DatagramSocketImpl.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/net/DatagramSocketImpl.java Wed Mar 09 14:18:12 2016 +0100
@@ -27,9 +27,7 @@
import java.io.FileDescriptor;
import java.io.IOException;
-import java.io.InterruptedIOException;
import java.util.Set;
-import java.util.HashSet;
/**
* Abstract datagram and multicast socket implementation base class.
@@ -352,32 +350,32 @@
}
}
- private static final Set<SocketOption<?>> dgSocketOptions =
- new HashSet<>();
+ private static final Set<SocketOption<?>> dgSocketOptions;
- private static final Set<SocketOption<?>> mcSocketOptions =
- new HashSet<>();
+ private static final Set<SocketOption<?>> mcSocketOptions;
static {
- dgSocketOptions.add(StandardSocketOptions.SO_SNDBUF);
- dgSocketOptions.add(StandardSocketOptions.SO_RCVBUF);
- dgSocketOptions.add(StandardSocketOptions.SO_REUSEADDR);
- dgSocketOptions.add(StandardSocketOptions.IP_TOS);
+ dgSocketOptions = Set.of(StandardSocketOptions.SO_SNDBUF,
+ StandardSocketOptions.SO_RCVBUF,
+ StandardSocketOptions.SO_REUSEADDR,
+ StandardSocketOptions.IP_TOS);
- mcSocketOptions.add(StandardSocketOptions.SO_SNDBUF);
- mcSocketOptions.add(StandardSocketOptions.SO_RCVBUF);
- mcSocketOptions.add(StandardSocketOptions.SO_REUSEADDR);
- mcSocketOptions.add(StandardSocketOptions.IP_TOS);
- mcSocketOptions.add(StandardSocketOptions.IP_MULTICAST_IF);
- mcSocketOptions.add(StandardSocketOptions.IP_MULTICAST_TTL);
- mcSocketOptions.add(StandardSocketOptions.IP_MULTICAST_LOOP);
- };
+ mcSocketOptions = Set.of(StandardSocketOptions.SO_SNDBUF,
+ StandardSocketOptions.SO_RCVBUF,
+ StandardSocketOptions.SO_REUSEADDR,
+ StandardSocketOptions.IP_TOS,
+ StandardSocketOptions.IP_MULTICAST_IF,
+ StandardSocketOptions.IP_MULTICAST_TTL,
+ StandardSocketOptions.IP_MULTICAST_LOOP);
+ }
/**
* Returns a set of SocketOptions supported by this impl
* and by this impl's socket (DatagramSocket or MulticastSocket)
*
* @return a Set of SocketOptions
+ *
+ * @since 9
*/
protected Set<SocketOption<?>> supportedOptions() {
if (getDatagramSocket() instanceof MulticastSocket) {
--- a/jdk/src/java.base/share/classes/java/net/SocketImpl.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/net/SocketImpl.java Wed Mar 09 14:18:12 2016 +0100
@@ -30,8 +30,6 @@
import java.io.OutputStream;
import java.io.FileDescriptor;
import java.util.Set;
-import java.util.HashSet;
-import java.util.Collections;
/**
* The abstract class {@code SocketImpl} is a common superclass
@@ -445,31 +443,31 @@
}
}
- private static final Set<SocketOption<?>> socketOptions =
- new HashSet<>();
+ private static final Set<SocketOption<?>> socketOptions;
- private static final Set<SocketOption<?>> serverSocketOptions =
- new HashSet<>();
+ private static final Set<SocketOption<?>> serverSocketOptions;
static {
- socketOptions.add(StandardSocketOptions.SO_KEEPALIVE);
- socketOptions.add(StandardSocketOptions.SO_SNDBUF);
- socketOptions.add(StandardSocketOptions.SO_RCVBUF);
- socketOptions.add(StandardSocketOptions.SO_REUSEADDR);
- socketOptions.add(StandardSocketOptions.SO_LINGER);
- socketOptions.add(StandardSocketOptions.IP_TOS);
- socketOptions.add(StandardSocketOptions.TCP_NODELAY);
+ socketOptions = Set.of(StandardSocketOptions.SO_KEEPALIVE,
+ StandardSocketOptions.SO_SNDBUF,
+ StandardSocketOptions.SO_RCVBUF,
+ StandardSocketOptions.SO_REUSEADDR,
+ StandardSocketOptions.SO_LINGER,
+ StandardSocketOptions.IP_TOS,
+ StandardSocketOptions.TCP_NODELAY);
- serverSocketOptions.add(StandardSocketOptions.SO_RCVBUF);
- serverSocketOptions.add(StandardSocketOptions.SO_REUSEADDR);
- serverSocketOptions.add(StandardSocketOptions.IP_TOS);
- };
+ serverSocketOptions = Set.of(StandardSocketOptions.SO_RCVBUF,
+ StandardSocketOptions.SO_REUSEADDR,
+ StandardSocketOptions.IP_TOS);
+ }
/**
* Returns a set of SocketOptions supported by this impl
* and by this impl's socket (Socket or ServerSocket)
*
* @return a Set of SocketOptions
+ *
+ * @since 9
*/
protected Set<SocketOption<?>> supportedOptions() {
if (getSocket() != null) {
--- a/jdk/src/java.base/share/classes/java/nio/Bits.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/nio/Bits.java Wed Mar 09 14:18:12 2016 +0100
@@ -736,202 +736,9 @@
});
}
- // -- Bulk get/put acceleration --
-
// These numbers represent the point at which we have empirically
// determined that the average cost of a JNI call exceeds the expense
// of an element by element copy. These numbers may change over time.
static final int JNI_COPY_TO_ARRAY_THRESHOLD = 6;
static final int JNI_COPY_FROM_ARRAY_THRESHOLD = 6;
-
- // This number limits the number of bytes to copy per call to Unsafe's
- // copyMemory method. A limit is imposed to allow for safepoint polling
- // during a large copy
- static final long UNSAFE_COPY_THRESHOLD = 1024L * 1024L;
-
- // These methods do no bounds checking. Verification that the copy will not
- // result in memory corruption should be done prior to invocation.
- // All positions and lengths are specified in bytes.
-
- /**
- * Copy from given source array to destination address.
- *
- * @param src
- * source array
- * @param srcBaseOffset
- * offset of first element of storage in source array
- * @param srcPos
- * offset within source array of the first element to read
- * @param dstAddr
- * destination address
- * @param length
- * number of bytes to copy
- */
- static void copyFromArray(Object src, long srcBaseOffset, long srcPos,
- long dstAddr, long length)
- {
- long offset = srcBaseOffset + srcPos;
- while (length > 0) {
- long size = (length > UNSAFE_COPY_THRESHOLD) ? UNSAFE_COPY_THRESHOLD : length;
- unsafe.copyMemory(src, offset, null, dstAddr, size);
- length -= size;
- offset += size;
- dstAddr += size;
- }
- }
-
- /**
- * Copy from source address into given destination array.
- *
- * @param srcAddr
- * source address
- * @param dst
- * destination array
- * @param dstBaseOffset
- * offset of first element of storage in destination array
- * @param dstPos
- * offset within destination array of the first element to write
- * @param length
- * number of bytes to copy
- */
- static void copyToArray(long srcAddr, Object dst, long dstBaseOffset, long dstPos,
- long length)
- {
- long offset = dstBaseOffset + dstPos;
- while (length > 0) {
- long size = (length > UNSAFE_COPY_THRESHOLD) ? UNSAFE_COPY_THRESHOLD : length;
- unsafe.copyMemory(null, srcAddr, dst, offset, size);
- length -= size;
- srcAddr += size;
- offset += size;
- }
- }
-
- /**
- * Copy and unconditionally byte swap 16 bit elements from a heap array to off-heap memory
- *
- * @param src
- * the source array, must be a 16-bit primitive array type
- * @param srcPos
- * byte offset within source array of the first element to read
- * @param dstAddr
- * destination address
- * @param length
- * number of bytes to copy
- */
- static void copyFromCharArray(Object src, long srcPos, long dstAddr, long length) {
- unsafe.copySwapMemory(src, unsafe.arrayBaseOffset(src.getClass()) + srcPos, null, dstAddr, length, 2);
- }
-
- /**
- * Copy and unconditionally byte swap 16 bit elements from off-heap memory to a heap array
- *
- * @param srcAddr
- * source address
- * @param dst
- * destination array, must be a 16-bit primitive array type
- * @param dstPos
- * byte offset within the destination array of the first element to write
- * @param length
- * number of bytes to copy
- */
- static void copyToCharArray(long srcAddr, Object dst, long dstPos, long length) {
- unsafe.copySwapMemory(null, srcAddr, dst, unsafe.arrayBaseOffset(dst.getClass()) + dstPos, length, 2);
- }
-
- /**
- * Copy and unconditionally byte swap 16 bit elements from a heap array to off-heap memory
- *
- * @param src
- * the source array, must be a 16-bit primitive array type
- * @param srcPos
- * byte offset within source array of the first element to read
- * @param dstAddr
- * destination address
- * @param length
- * number of bytes to copy
- */
- static void copyFromShortArray(Object src, long srcPos, long dstAddr, long length) {
- unsafe.copySwapMemory(src, unsafe.arrayBaseOffset(src.getClass()) + srcPos, null, dstAddr, length, 2);
- }
-
- /**
- * Copy and unconditionally byte swap 16 bit elements from off-heap memory to a heap array
- *
- * @param srcAddr
- * source address
- * @param dst
- * destination array, must be a 16-bit primitive array type
- * @param dstPos
- * byte offset within the destination array of the first element to write
- * @param length
- * number of bytes to copy
- */
- static void copyToShortArray(long srcAddr, Object dst, long dstPos, long length) {
- unsafe.copySwapMemory(null, srcAddr, dst, unsafe.arrayBaseOffset(dst.getClass()) + dstPos, length, 2);
- }
-
- /**
- * Copy and unconditionally byte swap 32 bit elements from a heap array to off-heap memory
- *
- * @param src
- * the source array, must be a 32-bit primitive array type
- * @param srcPos
- * byte offset within source array of the first element to read
- * @param dstAddr
- * destination address
- * @param length
- * number of bytes to copy
- */
- static void copyFromIntArray(Object src, long srcPos, long dstAddr, long length) {
- unsafe.copySwapMemory(src, unsafe.arrayBaseOffset(src.getClass()) + srcPos, null, dstAddr, length, 4);
- }
-
- /**
- * Copy and unconditionally byte swap 32 bit elements from off-heap memory to a heap array
- *
- * @param srcAddr
- * source address
- * @param dst
- * destination array, must be a 32-bit primitive array type
- * @param dstPos
- * byte offset within the destination array of the first element to write
- * @param length
- * number of bytes to copy
- */
- static void copyToIntArray(long srcAddr, Object dst, long dstPos, long length) {
- unsafe.copySwapMemory(null, srcAddr, dst, unsafe.arrayBaseOffset(dst.getClass()) + dstPos, length, 4);
- }
-
- /**
- * Copy and unconditionally byte swap 64 bit elements from a heap array to off-heap memory
- *
- * @param src
- * the source array, must be a 64-bit primitive array type
- * @param srcPos
- * byte offset within source array of the first element to read
- * @param dstAddr
- * destination address
- * @param length
- * number of bytes to copy
- */
- static void copyFromLongArray(Object src, long srcPos, long dstAddr, long length) {
- unsafe.copySwapMemory(src, unsafe.arrayBaseOffset(src.getClass()) + srcPos, null, dstAddr, length, 8);
- }
-
- /**
- * Copy and unconditionally byte swap 64 bit elements from off-heap memory to a heap array
- *
- * @param srcAddr
- * source address
- * @param dst
- * destination array, must be a 64-bit primitive array type
- * @param dstPos
- * byte offset within the destination array of the first element to write
- * @param length
- * number of bytes to copy
- */
- static void copyToLongArray(long srcAddr, Object dst, long dstPos, long length) {
- unsafe.copySwapMemory(null, srcAddr, dst, unsafe.arrayBaseOffset(dst.getClass()) + dstPos, length, 8);
- }
}
--- a/jdk/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -270,16 +270,22 @@
if (length > rem)
throw new BufferUnderflowException();
+ long dstOffset = arrayBaseOffset + ((long)offset << $LG_BYTES_PER_VALUE$);
#if[!byte]
if (order() != ByteOrder.nativeOrder())
- Bits.copyTo$Memtype$Array(ix(pos), dst,
- (long)offset << $LG_BYTES_PER_VALUE$,
- (long)length << $LG_BYTES_PER_VALUE$);
+ unsafe.copySwapMemory(null,
+ ix(pos),
+ dst,
+ dstOffset,
+ (long)length << $LG_BYTES_PER_VALUE$,
+ (long)1 << $LG_BYTES_PER_VALUE$);
else
#end[!byte]
- Bits.copyToArray(ix(pos), dst, arrayBaseOffset,
- (long)offset << $LG_BYTES_PER_VALUE$,
- (long)length << $LG_BYTES_PER_VALUE$);
+ unsafe.copyMemory(null,
+ ix(pos),
+ dst,
+ dstOffset,
+ (long)length << $LG_BYTES_PER_VALUE$);
position(pos + length);
} else {
super.get(dst, offset, length);
@@ -362,18 +368,22 @@
if (length > rem)
throw new BufferOverflowException();
+ long srcOffset = arrayBaseOffset + ((long)offset << $LG_BYTES_PER_VALUE$);
#if[!byte]
if (order() != ByteOrder.nativeOrder())
- Bits.copyFrom$Memtype$Array(src,
- (long)offset << $LG_BYTES_PER_VALUE$,
- ix(pos),
- (long)length << $LG_BYTES_PER_VALUE$);
+ unsafe.copySwapMemory(src,
+ srcOffset,
+ null,
+ ix(pos),
+ (long)length << $LG_BYTES_PER_VALUE$,
+ (long)1 << $LG_BYTES_PER_VALUE$);
else
#end[!byte]
- Bits.copyFromArray(src, arrayBaseOffset,
- (long)offset << $LG_BYTES_PER_VALUE$,
- ix(pos),
- (long)length << $LG_BYTES_PER_VALUE$);
+ unsafe.copyMemory(src,
+ srcOffset,
+ null,
+ ix(pos),
+ (long)length << $LG_BYTES_PER_VALUE$);
position(pos + length);
} else {
super.put(src, offset, length);
--- a/jdk/src/java.base/share/classes/java/security/KeyPairGenerator.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/security/KeyPairGenerator.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -71,7 +71,7 @@
* associated with each of the keys.
*
* <p>If the algorithm is the <i>DSA</i> algorithm, and the keysize (modulus
- * size) is 512, 768, or 1024, then the <i>Sun</i> provider uses a set of
+ * size) is 512, 768, 1024, or 2048, then the <i>Sun</i> provider uses a set of
* precomputed values for the {@code p}, {@code q}, and
* {@code g} parameters. If the modulus size is not one of the above
* values, the <i>Sun</i> provider creates a new set of parameters. Other
@@ -96,7 +96,7 @@
* (via a call to an {@code initialize} method), each provider must
* supply (and document) a default initialization.
* For example, the <i>Sun</i> provider uses a default modulus size (keysize)
- * of 1024 bits.
+ * of 1024 bits for DSA key pairs.
*
* <p>Note that this class is abstract and extends from
* {@code KeyPairGeneratorSpi} for historical reasons.
--- a/jdk/src/java.base/share/classes/java/util/SplittableRandom.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/util/SplittableRandom.java Wed Mar 09 14:18:12 2016 +0100
@@ -219,12 +219,20 @@
return seed += gamma;
}
+ // IllegalArgumentException messages
+ static final String BAD_BOUND = "bound must be positive";
+ static final String BAD_RANGE = "bound must be greater than origin";
+ static final String BAD_SIZE = "size must be non-negative";
+
/**
* The seed generator for default constructors.
*/
- private static final AtomicLong defaultGen = new AtomicLong(initialSeed());
+ private static final AtomicLong defaultGen
+ = new AtomicLong(mix64(System.currentTimeMillis()) ^
+ mix64(System.nanoTime()));
- private static long initialSeed() {
+ // at end of <clinit> to survive static initialization circularity
+ static {
if (java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<Boolean>() {
public Boolean run() {
@@ -234,17 +242,10 @@
long s = (long)seedBytes[0] & 0xffL;
for (int i = 1; i < 8; ++i)
s = (s << 8) | ((long)seedBytes[i] & 0xffL);
- return s;
+ defaultGen.set(s);
}
- return (mix64(System.currentTimeMillis()) ^
- mix64(System.nanoTime()));
}
- // IllegalArgumentException messages
- static final String BAD_BOUND = "bound must be positive";
- static final String BAD_RANGE = "bound must be greater than origin";
- static final String BAD_SIZE = "size must be non-negative";
-
/*
* Internal versions of nextX methods used by streams, as well as
* the public nextX(origin, bound) methods. These exist mainly to
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java Wed Mar 09 14:18:12 2016 +0100
@@ -125,53 +125,6 @@
* but we provide identical statistical properties.
*/
- /** Generates per-thread initialization/probe field */
- private static final AtomicInteger probeGenerator = new AtomicInteger();
-
- /**
- * The next seed for default constructors.
- */
- private static final AtomicLong seeder = new AtomicLong(initialSeed());
-
- private static long initialSeed() {
- if (java.security.AccessController.doPrivileged(
- new java.security.PrivilegedAction<Boolean>() {
- public Boolean run() {
- return Boolean.getBoolean("java.util.secureRandomSeed");
- }})) {
- byte[] seedBytes = java.security.SecureRandom.getSeed(8);
- long s = (long)seedBytes[0] & 0xffL;
- for (int i = 1; i < 8; ++i)
- s = (s << 8) | ((long)seedBytes[i] & 0xffL);
- return s;
- }
- return (mix64(System.currentTimeMillis()) ^
- mix64(System.nanoTime()));
- }
-
- /**
- * The seed increment.
- */
- private static final long GAMMA = 0x9e3779b97f4a7c15L;
-
- /**
- * The increment for generating probe values.
- */
- private static final int PROBE_INCREMENT = 0x9e3779b9;
-
- /**
- * The increment of seeder per new instance.
- */
- private static final long SEEDER_INCREMENT = 0xbb67ae8584caa73bL;
-
- // Constants from SplittableRandom
- private static final double DOUBLE_UNIT = 0x1.0p-53; // 1.0 / (1L << 53)
- private static final float FLOAT_UNIT = 0x1.0p-24f; // 1.0f / (1 << 24)
-
- /** Rarely-used holder for the second of a pair of Gaussians */
- private static final ThreadLocal<Double> nextLocalGaussian =
- new ThreadLocal<>();
-
private static long mix64(long z) {
z = (z ^ (z >>> 33)) * 0xff51afd7ed558ccdL;
z = (z ^ (z >>> 33)) * 0xc4ceb9fe1a85ec53L;
@@ -194,9 +147,6 @@
initialized = true; // false during super() call
}
- /** The common ThreadLocalRandom */
- static final ThreadLocalRandom instance = new ThreadLocalRandom();
-
/**
* Initialize Thread fields for the current thread. Called only
* when Thread.threadLocalRandomProbe is zero, indicating that a
@@ -248,11 +198,6 @@
return (int)(mix64(nextSeed()) >>> (64 - bits));
}
- // IllegalArgumentException messages
- static final String BAD_BOUND = "bound must be positive";
- static final String BAD_RANGE = "bound must be greater than origin";
- static final String BAD_SIZE = "size must be non-negative";
-
/**
* The form of nextLong used by LongStream Spliterators. If
* origin is greater than bound, acts as unbounded form of
@@ -1050,6 +995,32 @@
return current();
}
+ // Static initialization
+
+ /**
+ * The seed increment.
+ */
+ private static final long GAMMA = 0x9e3779b97f4a7c15L;
+
+ /**
+ * The increment for generating probe values.
+ */
+ private static final int PROBE_INCREMENT = 0x9e3779b9;
+
+ /**
+ * The increment of seeder per new instance.
+ */
+ private static final long SEEDER_INCREMENT = 0xbb67ae8584caa73bL;
+
+ // Constants from SplittableRandom
+ private static final double DOUBLE_UNIT = 0x1.0p-53; // 1.0 / (1L << 53)
+ private static final float FLOAT_UNIT = 0x1.0p-24f; // 1.0f / (1 << 24)
+
+ // IllegalArgumentException messages
+ static final String BAD_BOUND = "bound must be positive";
+ static final String BAD_RANGE = "bound must be greater than origin";
+ static final String BAD_SIZE = "size must be non-negative";
+
// Unsafe mechanics
private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
private static final long SEED;
@@ -1067,4 +1038,36 @@
throw new Error(e);
}
}
+
+ /** Rarely-used holder for the second of a pair of Gaussians */
+ private static final ThreadLocal<Double> nextLocalGaussian =
+ new ThreadLocal<>();
+
+ /** Generates per-thread initialization/probe field */
+ private static final AtomicInteger probeGenerator = new AtomicInteger();
+
+ /** The common ThreadLocalRandom */
+ static final ThreadLocalRandom instance = new ThreadLocalRandom();
+
+ /**
+ * The next seed for default constructors.
+ */
+ private static final AtomicLong seeder
+ = new AtomicLong(mix64(System.currentTimeMillis()) ^
+ mix64(System.nanoTime()));
+
+ // at end of <clinit> to survive static initialization circularity
+ static {
+ if (java.security.AccessController.doPrivileged(
+ new java.security.PrivilegedAction<Boolean>() {
+ public Boolean run() {
+ return Boolean.getBoolean("java.util.secureRandomSeed");
+ }})) {
+ byte[] seedBytes = java.security.SecureRandom.getSeed(8);
+ long s = (long)seedBytes[0] & 0xffL;
+ for (int i = 1; i < 8; ++i)
+ s = (s << 8) | ((long)seedBytes[i] & 0xffL);
+ seeder.set(s);
+ }
+ }
}
--- a/jdk/src/java.base/share/classes/java/util/jar/JarFile.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/util/jar/JarFile.java Wed Mar 09 14:18:12 2016 +0100
@@ -158,7 +158,7 @@
RUNTIME_VERSION = AccessController.doPrivileged(
new PrivilegedAction<Integer>() {
public Integer run() {
- Integer v = sun.misc.Version.jdkMajorVersion(); // fixme when JEP 223 Version integrated
+ Integer v = jdk.Version.current().major();
Integer i = Integer.getInteger("jdk.util.jar.version", v);
i = i < 0 ? 0 : i;
return i > v ? v : i;
@@ -359,7 +359,7 @@
}
private boolean runtimeVersionExists() {
- int version = sun.misc.Version.jdkMajorVersion(); // fixme when JEP 223 integrated
+ int version = jdk.Version.current().major();
try {
Release.valueOf(version);
return true;
@@ -893,11 +893,15 @@
}
private JarEntry verifiableEntry(ZipEntry ze) {
- if (!(ze instanceof JarFileEntry)) {
- ze = getJarEntry(ze.getName());
+ if (ze instanceof JarFileEntry) {
+ // assure the name and entry match for verification
+ return ((JarFileEntry)ze).reifiedEntry();
}
- // assure the name and entry match for verification
- return ze == null ? null : ((JarFileEntry)ze).reifiedEntry();
+ ze = getJarEntry(ze.getName());
+ if (ze instanceof JarFileEntry) {
+ return ((JarFileEntry)ze).reifiedEntry();
+ }
+ return (JarEntry)ze;
}
// Statics for hand-coded Boyer-Moore search
--- a/jdk/src/java.base/share/classes/java/util/stream/AbstractPipeline.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/util/stream/AbstractPipeline.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -327,6 +327,8 @@
@Override
@SuppressWarnings("unchecked")
public S onClose(Runnable closeHandler) {
+ if (linkedOrConsumed)
+ throw new IllegalStateException(MSG_STREAM_LINKED);
Objects.requireNonNull(closeHandler);
Runnable existingHandler = sourceStage.sourceCloseAction;
sourceStage.sourceCloseAction =
--- a/jdk/src/java.base/share/classes/java/util/stream/DoubleStream.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/util/stream/DoubleStream.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -949,24 +949,100 @@
*/
public static DoubleStream iterate(final double seed, final DoubleUnaryOperator f) {
Objects.requireNonNull(f);
- final PrimitiveIterator.OfDouble iterator = new PrimitiveIterator.OfDouble() {
- double t = seed;
+ Spliterator.OfDouble spliterator = new Spliterators.AbstractDoubleSpliterator(Long.MAX_VALUE,
+ Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL) {
+ double prev;
+ boolean started;
@Override
- public boolean hasNext() {
+ public boolean tryAdvance(DoubleConsumer action) {
+ Objects.requireNonNull(action);
+ double t;
+ if (started)
+ t = f.applyAsDouble(prev);
+ else {
+ t = seed;
+ started = true;
+ }
+ action.accept(prev = t);
+ return true;
+ }
+ };
+ return StreamSupport.doubleStream(spliterator, false);
+ }
+
+ /**
+ * Returns a sequential ordered {@code DoubleStream} produced by iterative
+ * application of a function to an initial element, conditioned on
+ * satisfying the supplied predicate. The stream terminates as soon as
+ * the predicate returns false.
+ *
+ * <p>
+ * {@code DoubleStream.iterate} should produce the same sequence of
+ * elements as produced by the corresponding for-loop:
+ * <pre>{@code
+ * for (double index=seed; predicate.test(index); index = f.apply(index)) {
+ * ...
+ * }
+ * }</pre>
+ *
+ * <p>
+ * The resulting sequence may be empty if the predicate does not hold on
+ * the seed value. Otherwise the first element will be the supplied seed
+ * value, the next element (if present) will be the result of applying the
+ * function f to the seed value, and so on iteratively until the predicate
+ * indicates that the stream should terminate.
+ *
+ * @param seed the initial element
+ * @param predicate a predicate to apply to elements to determine when the
+ * stream must terminate.
+ * @param f a function to be applied to the previous element to produce
+ * a new element
+ * @return a new sequential {@code DoubleStream}
+ * @since 9
+ */
+ public static DoubleStream iterate(double seed, DoublePredicate predicate, DoubleUnaryOperator f) {
+ Objects.requireNonNull(f);
+ Objects.requireNonNull(predicate);
+ Spliterator.OfDouble spliterator = new Spliterators.AbstractDoubleSpliterator(Long.MAX_VALUE,
+ Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL) {
+ double prev;
+ boolean started, finished;
+
+ @Override
+ public boolean tryAdvance(DoubleConsumer action) {
+ Objects.requireNonNull(action);
+ if (finished)
+ return false;
+ double t;
+ if (started)
+ t = f.applyAsDouble(prev);
+ else {
+ t = seed;
+ started = true;
+ }
+ if (!predicate.test(t)) {
+ finished = true;
+ return false;
+ }
+ action.accept(prev = t);
return true;
}
@Override
- public double nextDouble() {
- double v = t;
- t = f.applyAsDouble(t);
- return v;
+ public void forEachRemaining(DoubleConsumer action) {
+ Objects.requireNonNull(action);
+ if (finished)
+ return;
+ finished = true;
+ double t = started ? f.applyAsDouble(prev) : seed;
+ while (predicate.test(t)) {
+ action.accept(t);
+ t = f.applyAsDouble(t);
+ }
}
};
- return StreamSupport.doubleStream(Spliterators.spliteratorUnknownSize(
- iterator,
- Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL), false);
+ return StreamSupport.doubleStream(spliterator, false);
}
/**
--- a/jdk/src/java.base/share/classes/java/util/stream/IntStream.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/util/stream/IntStream.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -885,28 +885,104 @@
* @param seed the initial element
* @param f a function to be applied to the previous element to produce
* a new element
- * @return A new sequential {@code IntStream}
+ * @return a new sequential {@code IntStream}
*/
public static IntStream iterate(final int seed, final IntUnaryOperator f) {
Objects.requireNonNull(f);
- final PrimitiveIterator.OfInt iterator = new PrimitiveIterator.OfInt() {
- int t = seed;
+ Spliterator.OfInt spliterator = new Spliterators.AbstractIntSpliterator(Long.MAX_VALUE,
+ Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL) {
+ int prev;
+ boolean started;
@Override
- public boolean hasNext() {
+ public boolean tryAdvance(IntConsumer action) {
+ Objects.requireNonNull(action);
+ int t;
+ if (started)
+ t = f.applyAsInt(prev);
+ else {
+ t = seed;
+ started = true;
+ }
+ action.accept(prev = t);
+ return true;
+ }
+ };
+ return StreamSupport.intStream(spliterator, false);
+ }
+
+ /**
+ * Returns a sequential ordered {@code IntStream} produced by iterative
+ * application of a function to an initial element, conditioned on
+ * satisfying the supplied predicate. The stream terminates as soon as
+ * the predicate returns false.
+ *
+ * <p>
+ * {@code IntStream.iterate} should produce the same sequence of elements
+ * as produced by the corresponding for-loop:
+ * <pre>{@code
+ * for (int index=seed; predicate.test(index); index = f.apply(index)) {
+ * ...
+ * }
+ * }</pre>
+ *
+ * <p>
+ * The resulting sequence may be empty if the predicate does not hold on
+ * the seed value. Otherwise the first element will be the supplied seed
+ * value, the next element (if present) will be the result of applying the
+ * function f to the seed value, and so on iteratively until the predicate
+ * indicates that the stream should terminate.
+ *
+ * @param seed the initial element
+ * @param predicate a predicate to apply to elements to determine when the
+ * stream must terminate.
+ * @param f a function to be applied to the previous element to produce
+ * a new element
+ * @return a new sequential {@code IntStream}
+ * @since 9
+ */
+ public static IntStream iterate(int seed, IntPredicate predicate, IntUnaryOperator f) {
+ Objects.requireNonNull(f);
+ Objects.requireNonNull(predicate);
+ Spliterator.OfInt spliterator = new Spliterators.AbstractIntSpliterator(Long.MAX_VALUE,
+ Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL) {
+ int prev;
+ boolean started, finished;
+
+ @Override
+ public boolean tryAdvance(IntConsumer action) {
+ Objects.requireNonNull(action);
+ if (finished)
+ return false;
+ int t;
+ if (started)
+ t = f.applyAsInt(prev);
+ else {
+ t = seed;
+ started = true;
+ }
+ if (!predicate.test(t)) {
+ finished = true;
+ return false;
+ }
+ action.accept(prev = t);
return true;
}
@Override
- public int nextInt() {
- int v = t;
- t = f.applyAsInt(t);
- return v;
+ public void forEachRemaining(IntConsumer action) {
+ Objects.requireNonNull(action);
+ if (finished)
+ return;
+ finished = true;
+ int t = started ? f.applyAsInt(prev) : seed;
+ while (predicate.test(t)) {
+ action.accept(t);
+ t = f.applyAsInt(t);
+ }
}
};
- return StreamSupport.intStream(Spliterators.spliteratorUnknownSize(
- iterator,
- Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL), false);
+ return StreamSupport.intStream(spliterator, false);
}
/**
--- a/jdk/src/java.base/share/classes/java/util/stream/LongStream.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/util/stream/LongStream.java Wed Mar 09 14:18:12 2016 +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
@@ -879,24 +879,100 @@
*/
public static LongStream iterate(final long seed, final LongUnaryOperator f) {
Objects.requireNonNull(f);
- final PrimitiveIterator.OfLong iterator = new PrimitiveIterator.OfLong() {
- long t = seed;
+ Spliterator.OfLong spliterator = new Spliterators.AbstractLongSpliterator(Long.MAX_VALUE,
+ Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL) {
+ long prev;
+ boolean started;
@Override
- public boolean hasNext() {
+ public boolean tryAdvance(LongConsumer action) {
+ Objects.requireNonNull(action);
+ long t;
+ if (started)
+ t = f.applyAsLong(prev);
+ else {
+ t = seed;
+ started = true;
+ }
+ action.accept(prev = t);
+ return true;
+ }
+ };
+ return StreamSupport.longStream(spliterator, false);
+ }
+
+ /**
+ * Returns a sequential ordered {@code LongStream} produced by iterative
+ * application of a function to an initial element, conditioned on
+ * satisfying the supplied predicate. The stream terminates as soon as
+ * the predicate returns false.
+ *
+ * <p>
+ * {@code LongStream.iterate} should produce the same sequence of elements
+ * as produced by the corresponding for-loop:
+ * <pre>{@code
+ * for (long index=seed; predicate.test(index); index = f.apply(index)) {
+ * ...
+ * }
+ * }</pre>
+ *
+ * <p>
+ * The resulting sequence may be empty if the predicate does not hold on
+ * the seed value. Otherwise the first element will be the supplied seed
+ * value, the next element (if present) will be the result of applying the
+ * function f to the seed value, and so on iteratively until the predicate
+ * indicates that the stream should terminate.
+ *
+ * @param seed the initial element
+ * @param predicate a predicate to apply to elements to determine when the
+ * stream must terminate.
+ * @param f a function to be applied to the previous element to produce
+ * a new element
+ * @return a new sequential {@code LongStream}
+ * @since 9
+ */
+ public static LongStream iterate(long seed, LongPredicate predicate, LongUnaryOperator f) {
+ Objects.requireNonNull(f);
+ Objects.requireNonNull(predicate);
+ Spliterator.OfLong spliterator = new Spliterators.AbstractLongSpliterator(Long.MAX_VALUE,
+ Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL) {
+ long prev;
+ boolean started, finished;
+
+ @Override
+ public boolean tryAdvance(LongConsumer action) {
+ Objects.requireNonNull(action);
+ if (finished)
+ return false;
+ long t;
+ if (started)
+ t = f.applyAsLong(prev);
+ else {
+ t = seed;
+ started = true;
+ }
+ if (!predicate.test(t)) {
+ finished = true;
+ return false;
+ }
+ action.accept(prev = t);
return true;
}
@Override
- public long nextLong() {
- long v = t;
- t = f.applyAsLong(t);
- return v;
+ public void forEachRemaining(LongConsumer action) {
+ Objects.requireNonNull(action);
+ if (finished)
+ return;
+ finished = true;
+ long t = started ? f.applyAsLong(prev) : seed;
+ while (predicate.test(t)) {
+ action.accept(t);
+ t = f.applyAsLong(t);
+ }
}
};
- return StreamSupport.longStream(Spliterators.spliteratorUnknownSize(
- iterator,
- Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL), false);
+ return StreamSupport.longStream(spliterator, false);
}
/**
--- a/jdk/src/java.base/share/classes/java/util/stream/Stream.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/util/stream/Stream.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -29,7 +29,6 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
-import java.util.Iterator;
import java.util.Objects;
import java.util.Optional;
import java.util.Spliterator;
@@ -1185,23 +1184,103 @@
*/
public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f) {
Objects.requireNonNull(f);
- final Iterator<T> iterator = new Iterator<T>() {
- @SuppressWarnings("unchecked")
- T t = (T) Streams.NONE;
+ Spliterator<T> spliterator = new Spliterators.AbstractSpliterator<>(Long.MAX_VALUE,
+ Spliterator.ORDERED | Spliterator.IMMUTABLE) {
+ T prev;
+ boolean started;
@Override
- public boolean hasNext() {
+ public boolean tryAdvance(Consumer<? super T> action) {
+ Objects.requireNonNull(action);
+ T t;
+ if (started)
+ t = f.apply(prev);
+ else {
+ t = seed;
+ started = true;
+ }
+ action.accept(prev = t);
+ return true;
+ }
+ };
+ return StreamSupport.stream(spliterator, false);
+ }
+
+ /**
+ * Returns a sequential ordered {@code Stream} produced by iterative
+ * application of a function to an initial element, conditioned on
+ * satisfying the supplied predicate. The stream terminates as soon as
+ * the predicate returns false.
+ *
+ * <p>
+ * {@code Stream.iterate} should produce the same sequence of elements as
+ * produced by the corresponding for-loop:
+ * <pre>{@code
+ * for (T index=seed; predicate.test(index); index = f.apply(index)) {
+ * ...
+ * }
+ * }</pre>
+ *
+ * <p>
+ * The resulting sequence may be empty if the predicate does not hold on
+ * the seed value. Otherwise the first element will be the supplied seed
+ * value, the next element (if present) will be the result of applying the
+ * function f to the seed value, and so on iteratively until the predicate
+ * indicates that the stream should terminate.
+ *
+ * @param <T> the type of stream elements
+ * @param seed the initial element
+ * @param predicate a predicate to apply to elements to determine when the
+ * stream must terminate.
+ * @param f a function to be applied to the previous element to produce
+ * a new element
+ * @return a new sequential {@code Stream}
+ * @since 9
+ */
+ public static<T> Stream<T> iterate(T seed, Predicate<? super T> predicate, UnaryOperator<T> f) {
+ Objects.requireNonNull(f);
+ Objects.requireNonNull(predicate);
+ Spliterator<T> spliterator = new Spliterators.AbstractSpliterator<>(Long.MAX_VALUE,
+ Spliterator.ORDERED | Spliterator.IMMUTABLE) {
+ T prev;
+ boolean started, finished;
+
+ @Override
+ public boolean tryAdvance(Consumer<? super T> action) {
+ Objects.requireNonNull(action);
+ if (finished)
+ return false;
+ T t;
+ if (started)
+ t = f.apply(prev);
+ else {
+ t = seed;
+ started = true;
+ }
+ if (!predicate.test(t)) {
+ prev = null;
+ finished = true;
+ return false;
+ }
+ action.accept(prev = t);
return true;
}
@Override
- public T next() {
- return t = (t == Streams.NONE) ? seed : f.apply(t);
+ public void forEachRemaining(Consumer<? super T> action) {
+ Objects.requireNonNull(action);
+ if (finished)
+ return;
+ finished = true;
+ T t = started ? f.apply(prev) : seed;
+ prev = null;
+ while (predicate.test(t)) {
+ action.accept(t);
+ t = f.apply(t);
+ }
}
};
- return StreamSupport.stream(Spliterators.spliteratorUnknownSize(
- iterator,
- Spliterator.ORDERED | Spliterator.IMMUTABLE), false);
+ return StreamSupport.stream(spliterator, false);
}
/**
--- a/jdk/src/java.base/share/classes/java/util/stream/Streams.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/util/stream/Streams.java Wed Mar 09 14:18:12 2016 +0100
@@ -49,14 +49,6 @@
}
/**
- * An object instance representing no value, that cannot be an actual
- * data element of a stream. Used when processing streams that can contain
- * {@code null} elements to distinguish between a {@code null} value and no
- * value.
- */
- static final Object NONE = new Object();
-
- /**
* An {@code int} range spliterator.
*/
static final class RangeIntSpliterator implements Spliterator.OfInt {
--- a/jdk/src/java.base/share/classes/jdk/Version.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/src/java.base/share/classes/jdk/Version.java Wed Mar 09 14:18:12 2016 +0100
@@ -28,10 +28,10 @@
import java.math.BigInteger;
import java.security.AccessController;
import java.security.PrivilegedAction;
+import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
-import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
@@ -208,11 +208,10 @@
+ s + "'");
// $VNUM is a dot-separated list of integers of arbitrary length
- version
- = Collections.unmodifiableList(
- Arrays.stream(m.group(VNUM_GROUP).split("\\."))
- .map(Integer::parseInt)
- .collect(Collectors.toList()));
+ List<Integer> list = new ArrayList<>();
+ for (String i : m.group(VNUM_GROUP).split("\\."))
+ list.add(Integer.parseInt(i));
+ version = Collections.unmodifiableList(list);
pre = Optional.ofNullable(m.group(PRE_GROUP));
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java Wed Mar 09 14:18:12 2016 +0100
@@ -118,6 +118,8 @@
}
public static JavaNetInetAddressAccess getJavaNetInetAddressAccess() {
+ if (javaNetInetAddressAccess == null)
+ unsafe.ensureClassInitialized(java.net.InetAddress.class);
return javaNetInetAddressAccess;
}
--- a/jdk/src/java.base/share/classes/sun/misc/URLClassPath.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/src/java.base/share/classes/sun/misc/URLClassPath.java Wed Mar 09 14:18:12 2016 +0100
@@ -758,9 +758,13 @@
final URL url;
try {
- // add #runtime fragment to tell JarURLConnection to use
- // runtime versioning if the underlying jar file is multi-release
- url = new URL(getBaseURL(), ParseUtil.encodePath(name, false) + "#runtime");
+ if (jar.isMultiRelease()) {
+ // add #runtime fragment to tell JarURLConnection to use
+ // runtime versioning if the underlying jar file is multi-release
+ url = new URL(getBaseURL(), ParseUtil.encodePath(name, false) + "#runtime");
+ } else {
+ url = new URL(getBaseURL(), ParseUtil.encodePath(name, false));
+ }
if (check) {
URLClassPath.check(url);
}
--- a/jdk/src/java.base/share/classes/sun/misc/Version.java.template Wed Mar 09 14:54:18 2016 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,268 +0,0 @@
-/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.misc;
-import java.io.PrintStream;
-
-public class Version {
-
-
- private static final String launcher_name =
- "@@LAUNCHER_NAME@@";
-
- private static final String java_version =
- "@@VERSION_SHORT@@";
-
- private static final String java_runtime_name =
- "@@RUNTIME_NAME@@";
-
- private static final String java_runtime_version =
- "@@VERSION_STRING@@";
-
- static {
- init();
- }
-
- public static void init() {
- System.setProperty("java.version", java_version);
- System.setProperty("java.runtime.version", java_runtime_version);
- System.setProperty("java.runtime.name", java_runtime_name);
- }
-
- private static boolean versionsInitialized = false;
- private static int jvm_major_version = 0;
- private static int jvm_minor_version = 0;
- private static int jvm_security_version = 0;
- private static int jvm_patch_version = 0;
- private static int jvm_build_number = 0;
- private static int jdk_major_version = 0;
- private static int jdk_minor_version = 0;
- private static int jdk_security_version = 0;
- private static int jdk_patch_version = 0;
- private static int jdk_build_number = 0;
-
- /**
- * In case you were wondering this method is called by java -version.
- * Sad that it prints to stderr; would be nicer if default printed on
- * stdout.
- */
- public static void print() {
- print(System.err);
- }
-
- /**
- * This is the same as print except that it adds an extra line-feed
- * at the end, typically used by the -showversion in the launcher
- */
- public static void println() {
- print(System.err);
- System.err.println();
- }
-
- /**
- * Give a stream, it will print version info on it.
- */
- public static void print(PrintStream ps) {
- boolean isHeadless = false;
-
- /* Report that we're running headless if the property is true */
- String headless = System.getProperty("java.awt.headless");
- if ( (headless != null) && (headless.equalsIgnoreCase("true")) ) {
- isHeadless = true;
- }
-
- /* First line: platform version. */
- ps.println(launcher_name + " version \"" + java_version + "\"");
-
- /* Second line: runtime version (ie, libraries). */
-
- String jdk_debug_level = System.getProperty("jdk.debug", "release");
- /* Debug level is not printed for "release" builds */
- if ("release".equals(jdk_debug_level)) {
- jdk_debug_level = "";
- } else {
- jdk_debug_level = jdk_debug_level + " ";
- }
-
- ps.print(java_runtime_name + " (" + jdk_debug_level + "build " + java_runtime_version);
-
- if (java_runtime_name.indexOf("Embedded") != -1 && isHeadless) {
- // embedded builds report headless state
- ps.print(", headless");
- }
- ps.println(')');
-
- /* Third line: JVM information. */
- String java_vm_name = System.getProperty("java.vm.name");
- String java_vm_version = System.getProperty("java.vm.version");
- String java_vm_info = System.getProperty("java.vm.info");
- ps.println(java_vm_name + " (" + jdk_debug_level + "build " + java_vm_version + ", " +
- java_vm_info + ")");
- }
-
-
- /**
- * Returns the major version of the running JVM.
- * @return the major version of the running JVM
- * @since 1.6
- */
- public static synchronized int jvmMajorVersion() {
- if (!versionsInitialized) {
- initVersions();
- }
- return jvm_major_version;
- }
-
- /**
- * Returns the minor version of the running JVM.
- * @return the minor version of the running JVM
- * @since 1.6
- */
- public static synchronized int jvmMinorVersion() {
- if (!versionsInitialized) {
- initVersions();
- }
- return jvm_minor_version;
- }
-
-
- /**
- * Returns the security version of the running JVM.
- * @return the security version of the running JVM
- * @since 9
- */
- public static synchronized int jvmSecurityVersion() {
- if (!versionsInitialized) {
- initVersions();
- }
- return jvm_security_version;
- }
-
- /**
- * Returns the patch release version of the running JVM.
- * @return the patch release version of the running JVM
- * @since 9
- */
- public static synchronized int jvmPatchVersion() {
- if (!versionsInitialized) {
- initVersions();
- }
- return jvm_patch_version;
- }
-
- /**
- * Returns the build number of the running JVM.
- * @return the build number of the running JVM
- * @since 1.6
- */
- public static synchronized int jvmBuildNumber() {
- if (!versionsInitialized) {
- initVersions();
- }
- return jvm_build_number;
- }
-
- /**
- * Returns the major version of the running JDK.
- * @return the major version of the running JDK
- * @since 1.6
- */
- public static synchronized int jdkMajorVersion() {
- if (!versionsInitialized) {
- initVersions();
- }
- return jdk_major_version;
- }
-
- /**
- * Returns the minor version of the running JDK.
- * @return the minor version of the running JDK
- * @since 1.6
- */
- public static synchronized int jdkMinorVersion() {
- if (!versionsInitialized) {
- initVersions();
- }
- return jdk_minor_version;
- }
-
- /**
- * Returns the security version of the running JDK.
- * @return the security version of the running JDK
- * @since 9
- */
- public static synchronized int jdkSecurityVersion() {
- if (!versionsInitialized) {
- initVersions();
- }
- return jdk_security_version;
- }
-
- /**
- * Returns the patch release version of the running JDK.
- * @return the patch release version of the running JDK
- * @since 9
- */
- public static synchronized int jdkPatchVersion() {
- if (!versionsInitialized) {
- initVersions();
- }
- return jdk_patch_version;
- }
-
- /**
- * Returns the build number of the running JDK.
- * @return the build number of the running JDK
- * @since 1.6
- */
- public static synchronized int jdkBuildNumber() {
- if (!versionsInitialized) {
- initVersions();
- }
- return jdk_build_number;
- }
-
- private static synchronized void initVersions() {
- if (versionsInitialized) {
- return;
- }
- if (!getJvmVersionInfo()) {
- throw new InternalError("Unable to obtain JVM version info");
- }
- getJdkVersionInfo();
- versionsInitialized = true;
- }
-
- // Gets the JVM version info if available and sets the jvm_*_version fields
- // and its capabilities.
- private static native boolean getJvmVersionInfo();
- private static native void getJdkVersionInfo();
-}
-
-// Help Emacs a little because this file doesn't end in .java.
-//
-// Local Variables: ***
-// mode: java ***
-// End: ***
--- a/jdk/src/java.base/share/classes/sun/security/rsa/RSAKeyPairGenerator.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/src/java.base/share/classes/sun/security/rsa/RSAKeyPairGenerator.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -55,7 +55,7 @@
public RSAKeyPairGenerator() {
// initialize to default in case the app does not call initialize()
- initialize(1024, null);
+ initialize(2048, null);
}
// initialize the generator. See JCA doc
--- a/jdk/src/java.base/share/conf/security/java.security Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/src/java.base/share/conf/security/java.security Wed Mar 09 14:18:12 2016 +0100
@@ -578,7 +578,7 @@
#
# Example:
# jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048
-jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768
+jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 1024
# Legacy algorithms for Secure Socket Layer/Transport Layer Security (SSL/TLS)
# processing in JSSE implementation.
--- a/jdk/src/java.base/share/native/libjava/Version.c Wed Mar 09 14:54:18 2016 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include "jni.h"
-#include "jni_util.h"
-#include "jvm.h"
-#include "jdk_util.h"
-
-#include "sun_misc_Version.h"
-
-static void setStaticIntField(JNIEnv* env, jclass cls, const char* name, jint value)
-{
- jfieldID fid;
- fid = (*env)->GetStaticFieldID(env, cls, name, "I");
- if (fid != 0) {
- (*env)->SetStaticIntField(env, cls, fid, value);
- }
-}
-
-typedef void (JNICALL *GetJvmVersionInfo_fp)(JNIEnv*, jvm_version_info*, size_t);
-
-JNIEXPORT jboolean JNICALL
-Java_sun_misc_Version_getJvmVersionInfo(JNIEnv *env, jclass cls)
-{
- jvm_version_info info;
- GetJvmVersionInfo_fp func_p;
-
- if (!JDK_InitJvmHandle()) {
- JNU_ThrowInternalError(env, "Handle for JVM not found for symbol lookup");
- return JNI_FALSE;
- }
- func_p = (GetJvmVersionInfo_fp) JDK_FindJvmEntry("JVM_GetVersionInfo");
- if (func_p == NULL) {
- return JNI_FALSE;
- }
-
- (*func_p)(env, &info, sizeof(info));
- setStaticIntField(env, cls, "jvm_major_version", JVM_VERSION_MAJOR(info.jvm_version));
- JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);
- setStaticIntField(env, cls, "jvm_minor_version", JVM_VERSION_MINOR(info.jvm_version));
- JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);
- setStaticIntField(env, cls, "jvm_security_version", JVM_VERSION_SECURITY(info.jvm_version));
- JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);
- setStaticIntField(env, cls, "jvm_build_number", JVM_VERSION_BUILD(info.jvm_version));
- JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);
- setStaticIntField(env, cls, "jvm_patch_version", info.patch_version);
- JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);
-
- return JNI_TRUE;
-}
-
-JNIEXPORT void JNICALL
-Java_sun_misc_Version_getJdkVersionInfo(JNIEnv *env, jclass cls)
-{
- jdk_version_info info;
-
- JDK_GetVersionInfo0(&info, sizeof(info));
- setStaticIntField(env, cls, "jdk_major_version", JDK_VERSION_MAJOR(info.jdk_version));
- JNU_CHECK_EXCEPTION(env);
- setStaticIntField(env, cls, "jdk_minor_version", JDK_VERSION_MINOR(info.jdk_version));
- JNU_CHECK_EXCEPTION(env);
- setStaticIntField(env, cls, "jdk_security_version", JDK_VERSION_SECURITY(info.jdk_version));
- JNU_CHECK_EXCEPTION(env);
- setStaticIntField(env, cls, "jdk_build_number", JDK_VERSION_BUILD(info.jdk_version));
- JNU_CHECK_EXCEPTION(env);
- setStaticIntField(env, cls, "jdk_patch_version", info.patch_version);
- JNU_CHECK_EXCEPTION(env);
-}
--- a/jdk/src/java.base/share/native/libjli/java.c Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/src/java.base/share/native/libjli/java.c Wed Mar 09 14:18:12 2016 +0100
@@ -1470,7 +1470,7 @@
jclass ver;
jmethodID print;
- NULL_CHECK(ver = FindBootStrapClass(env, "sun/misc/Version"));
+ NULL_CHECK(ver = FindBootStrapClass(env, "java/lang/VersionProps"));
NULL_CHECK(print = (*env)->GetStaticMethodID(env,
ver,
(extraLF == JNI_TRUE) ? "println" : "print",
--- a/jdk/src/java.logging/share/classes/java/util/logging/Logger.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/src/java.logging/share/classes/java/util/logging/Logger.java Wed Mar 09 14:18:12 2016 +0100
@@ -839,6 +839,7 @@
* @param level One of the message level identifiers, e.g., SEVERE
* @param msgSupplier A function, which when called, produces the
* desired log message
+ * @since 1.8
*/
public void log(Level level, Supplier<String> msgSupplier) {
if (!isLoggable(level)) {
--- a/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/RSAKeyPairGenerator.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/RSAKeyPairGenerator.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -46,7 +46,7 @@
// Supported by Microsoft Base, Strong and Enhanced Cryptographic Providers
static final int KEY_SIZE_MIN = 512; // disallow MSCAPI min. of 384
static final int KEY_SIZE_MAX = 16384;
- private static final int KEY_SIZE_DEFAULT = 1024;
+ private static final int KEY_SIZE_DEFAULT = 2048;
// size of the key to generate, KEY_SIZE_MIN <= keySize <= KEY_SIZE_MAX
private int keySize;
--- a/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/SunMSCAPI.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/SunMSCAPI.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -182,7 +182,7 @@
* Key Pair Generator engines
*/
attrs.clear();
- attrs.put("KeySize", "1024");
+ attrs.put("KeySize", "16384");
putService(new ProviderService(p, "KeyPairGenerator",
"RSA", "sun.security.mscapi.RSAKeyPairGenerator",
null, attrs));
--- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11KeyPairGenerator.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11KeyPairGenerator.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -106,8 +106,15 @@
maxKeyLen = 2048;
}
} else {
- // RSA, DH, and DSA
- keySize = 1024;
+ if (algorithm.equals("DSA")) {
+ // keep default keysize at 1024 since larger keysizes may be
+ // incompatible with SHA1withDSA and SHA-2 Signature algs
+ // may not be supported by native pkcs11 implementations
+ keySize = 1024;
+ } else {
+ // RSA and DH
+ keySize = 2048;
+ }
if ((minKeyLen == -1) || (minKeyLen < 512)) {
minKeyLen = 512;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jsobject/share/classes/jdk/internal/netscape/javascript/spi/JSObjectProvider.java Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,44 @@
+/*
+ * 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.internal.netscape.javascript.spi;
+
+import java.applet.Applet;
+import netscape.javascript.JSException;
+import netscape.javascript.JSObject;
+
+public interface JSObjectProvider {
+ /**
+ * Return a JSObject for the window containing the given applet.
+ * Implementations of this class should return null if not connected to a
+ * browser, for example, when running in AppletViewer.
+ *
+ * @param applet The applet.
+ * @return JSObject for the window containing the given applet or null if we
+ * are not connected to a browser.
+ * @throws JSException when an error is encountered.
+ */
+ public JSObject getWindow(Applet applet) throws JSException;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jsobject/share/classes/netscape/javascript/JSException.java Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2006, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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 netscape.javascript;
+
+/**
+ * Thrown when an exception is raised in the JavaScript engine. This is merely
+ * a marker class to indicate an exception relating to the JavaScript
+ * interface.
+ */
+public class JSException extends RuntimeException {
+ private static final long serialVersionUID = 2778103758223661489L;
+
+ /**
+ * Constructs a new JavaScript exception with null as it's detail message.
+ */
+ public JSException() {
+ super();
+ }
+
+ /**
+ * Construct a new JavaScript exception with the specified detail message.
+ *
+ * @param s The detail message
+ */
+ public JSException(String s) {
+ super(s);
+ }
+
+ /**
+ * Construct a new JavaScript exception with the specified cause.
+ *
+ * @param t Throwable cause
+ */
+ public JSException(Throwable t) {
+ super(t);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jsobject/share/classes/netscape/javascript/JSObject.java Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2006, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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 netscape.javascript;
+
+import jdk.internal.netscape.javascript.spi.JSObjectProvider;
+import java.applet.Applet;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Iterator;
+import java.util.ServiceLoader;
+
+/**
+ * <p>
+ * Allows Java code to manipulate JavaScript objects.
+ * </p>
+ *
+ * <p>
+ * When a JavaScript object is passed or returned to Java code, it
+ * is wrapped in an instance of {@code JSObject}. When a
+ * {@code JSObject} instance is passed to the JavaScript engine,
+ * it is unwrapped back to its original JavaScript object. The
+ * {@code JSObject} class provides a way to invoke JavaScript
+ * methods and examine JavaScript properties.
+ * </p>
+ *
+ * <p> Any data returned from the JavaScript engine to Java is
+ * converted to Java data types. Certain data passed to the JavaScript
+ * engine is converted to JavaScript data types.
+ * </p>
+ *
+ */
+public abstract class JSObject {
+ /**
+ * Constructs a new JSObject. Users should neither call this method nor
+ * subclass JSObject.
+ */
+ protected JSObject() {
+ }
+
+ /**
+ * Calls a JavaScript method. Equivalent to
+ * "this.methodName(args[0], args[1], ...)" in JavaScript.
+ *
+ * @param methodName The name of the JavaScript method to be invoked.
+ * @param args the Java objects passed as arguments to the method.
+ * @return Result of the method.
+ * @throws JSException when an error is reported from the browser or
+ * JavaScript engine.
+ */
+ public abstract Object call(String methodName, Object... args) throws JSException;
+
+ /**
+ * Evaluates a JavaScript expression. The expression is a string of
+ * JavaScript source code which will be evaluated in the context given by
+ * "this".
+ *
+ * @param s The JavaScript expression.
+ * @return Result of the JavaScript evaluation.
+ * @throws JSException when an error is reported from the browser or
+ * JavaScript engine.
+ */
+ public abstract Object eval(String s) throws JSException;
+
+ /**
+ * Retrieves a named member of a JavaScript object. Equivalent to
+ * "this.name" in JavaScript.
+ *
+ * @param name The name of the JavaScript property to be accessed.
+ * @return The value of the propery.
+ * @throws JSException when an error is reported from the browser or
+ * JavaScript engine.
+ */
+ public abstract Object getMember(String name) throws JSException;
+
+ /**
+ * Sets a named member of a JavaScript object. Equivalent to
+ * "this.name = value" in JavaScript.
+ *
+ * @param name The name of the JavaScript property to be accessed.
+ * @param value The value of the propery.
+ * @throws JSException when an error is reported from the browser or
+ * JavaScript engine.
+ */
+ public abstract void setMember(String name, Object value) throws JSException;
+
+ /**
+ * Removes a named member of a JavaScript object. Equivalent
+ * to "delete this.name" in JavaScript.
+ *
+ * @param name The name of the JavaScript property to be removed.
+ * @throws JSException when an error is reported from the browser or
+ * JavaScript engine.
+ */
+ public abstract void removeMember(String name) throws JSException;
+
+ /**
+ * Retrieves an indexed member of a JavaScript object. Equivalent to
+ * "this[index]" in JavaScript.
+ *
+ * @param index The index of the array to be accessed.
+ * @return The value of the indexed member.
+ * @throws JSException when an error is reported from the browser or
+ * JavaScript engine.
+ */
+ public abstract Object getSlot(int index) throws JSException;
+
+ /**
+ * Sets an indexed member of a JavaScript object. Equivalent to
+ * "this[index] = value" in JavaScript.
+ *
+ * @param index The index of the array to be accessed.
+ * @param value The value to set
+ * @throws JSException when an error is reported from the browser or
+ * JavaScript engine.
+ */
+ public abstract void setSlot(int index, Object value) throws JSException;
+
+ /**
+ * Returns a JSObject for the window containing the given applet. This
+ * method only works when the Java code is running in a browser as an
+ * applet. The object returned may be used to access the HTML DOM directly.
+ *
+ * @param applet The applet.
+ * @return JSObject representing the window containing the given applet or
+ * {@code null} if we are not connected to a browser.
+ * @throws JSException when an error is reported from the browser or
+ * JavaScript engine or if applet is {@code null}
+ */
+ public static JSObject getWindow(Applet applet) throws JSException {
+ return ProviderLoader.callGetWindow(applet);
+ }
+
+ private static class ProviderLoader {
+ private static final JSObjectProvider provider;
+
+ static {
+ provider = AccessController.doPrivileged(
+ new PrivilegedAction<>() {
+ @Override
+ public JSObjectProvider run() {
+ Iterator<JSObjectProvider> providers =
+ ServiceLoader.loadInstalled(JSObjectProvider.class).iterator();
+ if (providers.hasNext()) {
+ return providers.next();
+ }
+ return null;
+ }
+ }
+ );
+ }
+
+ private static JSObject callGetWindow(Applet applet) {
+ if (provider != null) {
+ return provider.getWindow(applet);
+ }
+ return null;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jsobject/share/classes/netscape/javascript/package-info.java Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2008, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+/**
+ * <p>
+ * Provides Java code the ability to access the JavaScript engine and the
+ * HTML DOM in the web browser.
+ * </p>
+ *
+ * <p>
+ * The classes in this package were initially specified by Netscape, and are the
+ * de facto standard mechanism for calling JavaScript from the Java runtime.
+ * </p>
+ */
+
+package netscape.javascript;
--- a/jdk/test/TEST.groups Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/TEST.groups Wed Mar 09 14:18:12 2016 +0100
@@ -28,7 +28,6 @@
tier1 = \
:jdk_lang \
-java/lang/ProcessHandle/TreeTest.java \
- -java/util/zip/TestLocalTime.java \
:jdk_util \
-java/util/WeakHashMap/GCDuringIteration.java \
-java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java \
@@ -40,7 +39,6 @@
tier2 = \
java/lang/ProcessHandle/TreeTest.java \
- java/util/zip/TestLocalTime.java \
java/util/WeakHashMap/GCDuringIteration.java \
java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java \
java/util/concurrent/forkjoin/FJExceptionTableLeak.java \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/crypto/provider/Cipher/PBE/CheckPBEKeySize.java Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,73 @@
+/*
+ * 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
+ * @bug 8151149
+ * @modules java.base/com.sun.crypto.provider
+ */
+
+import java.lang.reflect.*;
+import java.security.*;
+import javax.crypto.*;
+import javax.crypto.spec.*;
+import com.sun.crypto.provider.*;
+
+public class CheckPBEKeySize {
+
+ private static final String ALGO = "PBEWithSHA1AndDESede";
+ private static final int KEYSIZE = 112; // Triple DES effective key size
+
+ public static final void main(String[] args) throws Exception {
+
+ // Generate a PBE key
+ SecretKeyFactory skFac = SecretKeyFactory.getInstance("PBE");
+ SecretKey skey =
+ skFac.generateSecret(new PBEKeySpec("test123".toCharArray()));
+
+ // Initialize the PBE cipher
+ Cipher cipher = Cipher.getInstance(ALGO);
+ cipher.init(Cipher.ENCRYPT_MODE, skey);
+
+ // Permit access to the Cipher.spi field (a CipherSpi object)
+ Field spi = Cipher.class.getDeclaredField("spi");
+ spi.setAccessible(true);
+ Object value = spi.get(cipher);
+
+ // Permit access to the CipherSpi.engineGetKeySize method
+ Method engineGetKeySize =
+ PKCS12PBECipherCore$PBEWithSHA1AndDESede.class
+ .getDeclaredMethod("engineGetKeySize", Key.class);
+ engineGetKeySize.setAccessible(true);
+
+ // Check the key size
+ int keySize = (int) engineGetKeySize.invoke(value, skey);
+ if (keySize == KEYSIZE) {
+ System.out.println(ALGO + ".engineGetKeySize returns " + keySize +
+ " bits, as expected");
+ System.out.println("OK");
+ } else {
+ throw new Exception("ERROR: " + ALGO + " key size is incorrect");
+ }
+ }
+}
--- a/jdk/test/com/sun/crypto/provider/KeyAgreement/TestExponentSize.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/com/sun/crypto/provider/KeyAgreement/TestExponentSize.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -83,10 +83,10 @@
KeyPair kp;
KeyPairGenerator kpg = KeyPairGenerator.getInstance("DH", "SunJCE");
- // Sun's default uses a default psize of 1024 and
+ // Sun's default uses a default psize of 2048 and
// lsize of (pSize / 2) but at least 384 bits
kp = kpg.generateKeyPair();
- checkKeyPair(kp, Sizes.ten24, Sizes.five12);
+ checkKeyPair(kp, Sizes.twenty48, Sizes.ten24);
DHPublicKey publicKey = (DHPublicKey)kp.getPublic();
BigInteger p = publicKey.getParams().getP();
@@ -98,15 +98,15 @@
kpg.initialize(new DHParameterSpec(p, g, Sizes.ten24.getIntSize()));
kp = kpg.generateKeyPair();
- checkKeyPair(kp, Sizes.ten24, Sizes.ten24);
+ checkKeyPair(kp, Sizes.twenty48, Sizes.ten24);
kpg.initialize(new DHParameterSpec(p, g, Sizes.five12.getIntSize()));
kp = kpg.generateKeyPair();
- checkKeyPair(kp, Sizes.ten24, Sizes.five12);
+ checkKeyPair(kp, Sizes.twenty48, Sizes.five12);
kpg.initialize(new DHParameterSpec(p, g, Sizes.two56.getIntSize()));
kp = kpg.generateKeyPair();
- checkKeyPair(kp, Sizes.ten24, Sizes.two56);
+ checkKeyPair(kp, Sizes.twenty48, Sizes.two56);
kpg.initialize(Sizes.five12.getIntSize());
kp = kpg.generateKeyPair();
--- a/jdk/test/java/lang/ProcessHandle/Basic.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/lang/ProcessHandle/Basic.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -37,7 +37,8 @@
/*
* @test
* @library /test/lib/share/classes
- * @run testng InfoTest
+ * @modules jdk.management
+ * @run testng Basic
* @summary Basic tests for ProcessHandler
* @author Roger Riggs
*/
--- a/jdk/test/java/lang/ProcessHandle/InfoTest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/lang/ProcessHandle/InfoTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -49,6 +49,7 @@
* @test
* @bug 8077350 8081566 8081567 8098852 8136597
* @library /test/lib/share/classes
+ * @modules jdk.management
* @build jdk.test.lib.Platform jdk.test.lib.Utils
* @run testng InfoTest
* @summary Functions of ProcessHandle.Info
@@ -114,9 +115,13 @@
long cpuLoopTime = 100; // 100 ms
String[] extraArgs = {"pid", "parent", "stdin"};
JavaChild p1 = JavaChild.spawnJavaChild((Object[])extraArgs);
- Instant afterStart = Instant.now();
+ Instant afterStart = null;
try (BufferedReader lines = p1.outputReader()) {
+ // Read the args line to know the subprocess has started
+ lines.readLine();
+ afterStart = Instant.now();
+
Duration lastCpu = Duration.ofMillis(0L);
for (int j = 0; j < 10; j++) {
@@ -126,8 +131,7 @@
// Read cputime from child
Duration childCpuTime = null;
// Read lines from the child until the result from cputime is returned
- String s;
- while ((s = lines.readLine()) != null) {
+ for (String s; (s = lines.readLine()) != null;) {
String[] split = s.trim().split(" ");
if (split.length == 3 && split[1].equals("cputime")) {
long nanos = Long.valueOf(split[2]);
--- a/jdk/test/java/lang/ProcessHandle/OnExitTest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/lang/ProcessHandle/OnExitTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -39,6 +39,7 @@
/*
* @test
* @library /test/lib/share/classes
+ * @modules jdk.management
* @build jdk.test.lib.Platform jdk.test.lib.Utils
* @run testng OnExitTest
* @summary Functions of Process.onExit and ProcessHandle.onExit
--- a/jdk/test/java/lang/ProcessHandle/TreeTest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/lang/ProcessHandle/TreeTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -45,6 +45,7 @@
/*
* @test
* @library /test/lib/share/classes
+ * @modules jdk.management
* @build jdk.test.lib.Utils
* @run testng/othervm TreeTest
* @summary Test counting and JavaChild.spawning and counting of Processes.
--- a/jdk/test/java/lang/StackWalker/StackStreamTest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/lang/StackWalker/StackStreamTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -33,6 +33,7 @@
* @test
* @bug 8140450
* @summary Stack Stream Test
+ * @modules java.logging
* @run main/othervm StackStreamTest
*/
public class StackStreamTest {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/StringBuilder/Capacity.java Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,182 @@
+/*
+ * 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
+ * @bug 8149330
+ * @summary Basic set of tests of capacity management
+ * @run testng Capacity
+ */
+
+import java.lang.reflect.Field;
+import java.util.AbstractList;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.SplittableRandom;
+
+import org.testng.annotations.Test;
+import org.testng.annotations.DataProvider;
+import static org.testng.Assert.*;
+
+public class Capacity {
+ static final int DEFAULT_CAPACITY = 16;
+
+ private static int newCapacity(int oldCapacity,
+ int desiredCapacity)
+ {
+ return Math.max(oldCapacity * 2 + 2, desiredCapacity);
+ }
+
+ private static int nextNewCapacity(int oldCapacity) {
+ return newCapacity(oldCapacity, oldCapacity + 1);
+ }
+
+ @Test(dataProvider = "singleChar")
+ public void defaultCapacity(Character ch) {
+ StringBuilder sb = new StringBuilder();
+ assertEquals(sb.capacity(), DEFAULT_CAPACITY);
+ for (int i = 0; i < DEFAULT_CAPACITY; i++) {
+ sb.append(ch);
+ assertEquals(sb.capacity(), DEFAULT_CAPACITY);
+ }
+ sb.append(ch);
+ assertEquals(sb.capacity(), nextNewCapacity(DEFAULT_CAPACITY));
+ }
+
+ @Test(dataProvider = "charCapacity")
+ public void explicitCapacity(Character ch, int initCapacity) {
+ StringBuilder sb = new StringBuilder(initCapacity);
+ assertEquals(sb.capacity(), initCapacity);
+ for (int i = 0; i < initCapacity; i++) {
+ sb.append(ch);
+ assertEquals(sb.capacity(), initCapacity);
+ }
+ sb.append(ch);
+ assertEquals(sb.capacity(), nextNewCapacity(initCapacity));
+ }
+
+ @Test(dataProvider = "singleChar")
+ public void sbFromString(Character ch) {
+ String s = "string " + ch;
+ int expectedCapacity = s.length() + DEFAULT_CAPACITY;
+ StringBuilder sb = new StringBuilder(s);
+ assertEquals(sb.capacity(), expectedCapacity);
+ for (int i = 0; i < DEFAULT_CAPACITY; i++) {
+ sb.append(ch);
+ assertEquals(sb.capacity(), expectedCapacity);
+ }
+ sb.append(ch);
+ assertEquals(sb.capacity(), nextNewCapacity(expectedCapacity));
+ }
+
+ @Test(dataProvider = "singleChar")
+ public void sbFromCharSeq(Character ch) {
+ CharSequence cs = new MyCharSeq("char seq " + ch);
+ int expectedCapacity = cs.length() + DEFAULT_CAPACITY;
+ StringBuilder sb = new StringBuilder(cs);
+ assertEquals(sb.capacity(), expectedCapacity);
+ for (int i = 0; i < DEFAULT_CAPACITY; i++) {
+ sb.append(ch);
+ assertEquals(sb.capacity(), expectedCapacity);
+ }
+ sb.append(ch);
+ assertEquals(sb.capacity(), nextNewCapacity(expectedCapacity));
+ }
+
+ @Test(dataProvider = "charCapacity")
+ public void ensureCapacity(Character ch, int cap) {
+ StringBuilder sb = new StringBuilder(0);
+ assertEquals(sb.capacity(), 0);
+ sb.ensureCapacity(cap); // only has effect if cap > 0
+ int newCap = (cap == 0) ? 0 : newCapacity(0, cap);
+ assertEquals(sb.capacity(), newCap);
+ sb.ensureCapacity(newCap + 1);
+ assertEquals(sb.capacity(), nextNewCapacity(newCap));
+ sb.append(ch);
+ assertEquals(sb.capacity(), nextNewCapacity(newCap));
+ }
+
+ @Test(dataProvider = "negativeCapacity",
+ expectedExceptions = NegativeArraySizeException.class)
+ public void negativeInitialCapacity(int negCap) {
+ StringBuilder sb = new StringBuilder(negCap);
+ }
+
+ @Test(dataProvider = "negativeCapacity")
+ public void ensureNegativeCapacity(int negCap) {
+ StringBuilder sb = new StringBuilder();
+ sb.ensureCapacity(negCap);
+ assertEquals(sb.capacity(), DEFAULT_CAPACITY);
+ }
+
+ @Test(dataProvider = "charCapacity")
+ public void trimToSize(Character ch, int cap) {
+ StringBuilder sb = new StringBuilder(cap);
+ int halfOfCap = cap / 2;
+ for (int i = 0; i < halfOfCap; i++) {
+ sb.append(ch);
+ }
+ sb.trimToSize();
+ // according to the spec, capacity doesn't have to
+ // become exactly the size
+ assertTrue(sb.capacity() >= halfOfCap);
+ }
+
+ @DataProvider
+ public Object[][] singleChar() {
+ return new Object[][] { {'J'}, {'\u042b'} };
+ }
+
+ @DataProvider
+ public Object[][] charCapacity() {
+ return new Object[][] {
+ {'J', 0},
+ {'J', 1},
+ {'J', 15},
+ {'J', DEFAULT_CAPACITY},
+ {'J', 1024},
+ {'\u042b', 0},
+ {'\u042b', 1},
+ {'\u042b', 15},
+ {'\u042b', DEFAULT_CAPACITY},
+ {'\u042b', 1024},
+ };
+ }
+
+ @DataProvider
+ public Object[][] negativeCapacity() {
+ return new Object[][] { {-1}, {Integer.MIN_VALUE} };
+ }
+
+ private static class MyCharSeq implements CharSequence {
+ private CharSequence s;
+ public MyCharSeq(CharSequence s) { this.s = s; }
+ public char charAt(int i) { return s.charAt(i); }
+ public int length() { return s.length(); }
+ public CharSequence subSequence(int st, int e) {
+ return s.subSequence(st, e);
+ }
+ public String toString() { return s.toString(); }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/StringBuilder/HugeCapacity.java Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,66 @@
+/*
+ * 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
+ * @bug 8149330
+ * @summary Capacity should not get close to Integer.MAX_VALUE unless
+ * necessary
+ * @run main/othervm -Xmx5G HugeCapacity
+ * @ignore This test has huge memory requirements
+ */
+
+public class HugeCapacity {
+ private static int failures = 0;
+
+ public static void main(String[] args) {
+ testLatin1();
+ testUtf16();
+ if (failures > 0) {
+ throw new RuntimeException(failures + " tests failed");
+ }
+ }
+
+ private static void testLatin1() {
+ try {
+ StringBuilder sb = new StringBuilder();
+ sb.ensureCapacity(Integer.MAX_VALUE / 2);
+ sb.ensureCapacity(Integer.MAX_VALUE / 2 + 1);
+ } catch (OutOfMemoryError oom) {
+ oom.printStackTrace();
+ failures++;
+ }
+ }
+
+ private static void testUtf16() {
+ try {
+ StringBuilder sb = new StringBuilder();
+ sb.append('\u042b');
+ sb.ensureCapacity(Integer.MAX_VALUE / 4);
+ sb.ensureCapacity(Integer.MAX_VALUE / 4 + 1);
+ } catch (OutOfMemoryError oom) {
+ oom.printStackTrace();
+ failures++;
+ }
+ }
+}
--- a/jdk/test/java/lang/System/Logger/Level/LoggerLevelTest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/lang/System/Logger/Level/LoggerLevelTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -30,6 +30,7 @@
* @bug 8140364
* @summary Tests System.Logger.Level names and severity.
* @author danielfuchs
+ * @modules java.logging
*/
public class LoggerLevelTest {
public static void main(String[] args) {
--- a/jdk/test/java/lang/System/Logger/default/DefaultLoggerTest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/lang/System/Logger/default/DefaultLoggerTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -56,7 +56,7 @@
* @summary Tests default loggers returned by System.getLogger, and in
* particular the implementation of the the System.Logger method
* performed by the default binding.
- *
+ * @modules java.logging
* @build DefaultLoggerTest AccessSystemLogger
* @run driver AccessSystemLogger
* @run main/othervm -Xbootclasspath/a:boot DefaultLoggerTest NOSECURITY
--- a/jdk/test/java/lang/System/LoggerFinder/DefaultLoggerFinderTest/DefaultLoggerFinderTest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/lang/System/LoggerFinder/DefaultLoggerFinderTest/DefaultLoggerFinderTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -52,6 +52,7 @@
* @bug 8140364
* @summary Tests the default implementation of System.Logger, when
* JUL is the default backend.
+ * @modules java.logging
* @build AccessSystemLogger DefaultLoggerFinderTest
* @run driver AccessSystemLogger
* @run main/othervm -Xbootclasspath/a:boot DefaultLoggerFinderTest NOSECURITY
--- a/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerTest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -52,6 +52,7 @@
Tests the behavior of bootstrap loggers (and SimpleConsoleLoggers
* too).
* @modules java.base/jdk.internal.logger
+ * java.logging
* @build BootstrapLoggerUtils LogStream
* @run main/othervm BootstrapLoggerTest NO_SECURITY
* @run main/othervm BootstrapLoggerTest SECURE
--- a/jdk/test/java/lang/System/LoggerFinder/internal/LoggerBridgeTest/LoggerBridgeTest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/lang/System/LoggerFinder/internal/LoggerBridgeTest/LoggerBridgeTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -58,7 +58,9 @@
* @summary JDK implementation specific unit test for JDK internal artifacts.
* Tests all bridge methods with the a custom backend whose
* loggers implement PlatformLogger.Bridge.
- * @modules java.base/sun.util.logging java.base/jdk.internal.logger
+ * @modules java.base/sun.util.logging
+ * java.base/jdk.internal.logger
+ * java.logging
* @build CustomSystemClassLoader LoggerBridgeTest
* @run main/othervm -Djava.system.class.loader=CustomSystemClassLoader LoggerBridgeTest NOSECURITY
* @run main/othervm -Djava.system.class.loader=CustomSystemClassLoader LoggerBridgeTest NOPERMISSIONS
--- a/jdk/test/java/lang/System/LoggerFinder/internal/PlatformLoggerBridgeTest/PlatformLoggerBridgeTest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/lang/System/LoggerFinder/internal/PlatformLoggerBridgeTest/PlatformLoggerBridgeTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -57,6 +57,7 @@
* Tests all bridge methods from PlatformLogger with the a custom
* backend whose loggers implement PlatformLogger.Bridge.
* @modules java.base/sun.util.logging
+ * java.logging
* @build CustomSystemClassLoader PlatformLoggerBridgeTest
* @run main/othervm -Djava.system.class.loader=CustomSystemClassLoader PlatformLoggerBridgeTest NOSECURITY
* @run main/othervm -Djava.system.class.loader=CustomSystemClassLoader PlatformLoggerBridgeTest NOPERMISSIONS
--- a/jdk/test/java/lang/System/LoggerFinder/internal/api/LoggerFinderAPITest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/lang/System/LoggerFinder/internal/api/LoggerFinderAPITest.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -29,6 +29,7 @@
* Tests the consistency of the LoggerFinder and JDK extensions.
* @modules java.base/sun.util.logging
* java.base/jdk.internal.logger
+ * java.logging
* @run main LoggerFinderAPITest
*/
--- a/jdk/test/java/lang/System/MacEncoding/TestFileEncoding.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/lang/System/MacEncoding/TestFileEncoding.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 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
@@ -28,6 +28,7 @@
* @bug 8011194
* @summary Test value of file.encoding for corresponding value of LANG, etc
* @library ../../../../tools/launcher/ ../
+ * @modules jdk.compiler
* @build TestHelper TestFileEncoding ExpectedEncoding
* @run main TestFileEncoding UTF-8
* @run main/othervm -Dfile.encoding=MyEncoding -DuserEncoding=MyEncoding TestFileEncoding MyEncoding
--- a/jdk/test/java/lang/instrument/ManyMethodsBenchmarkAgent.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/lang/instrument/ManyMethodsBenchmarkAgent.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -27,9 +27,8 @@
* @summary Tests and benchmarks the JVMTI RedefineClasses when a
* single class (and its parent) contains many methods.
*
- * @modules java.compiler
+ * @modules jdk.compiler
* java.instrument
- * jdk.compiler
* @run build ManyMethodsBenchmarkApp ManyMethodsBenchmarkAgent
* @run shell MakeJAR3.sh ManyMethodsBenchmarkAgent 'Can-Retransform-Classes: true'
* @run main/othervm -javaagent:ManyMethodsBenchmarkAgent.jar ManyMethodsBenchmarkApp
--- a/jdk/test/java/lang/instrument/RetransformAgent.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/lang/instrument/RetransformAgent.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -28,6 +28,7 @@
* @author Robert Field, Sun Microsystems
*
* @modules java.base/jdk.internal.org.objectweb.asm
+ * java.instrument
* @run shell/timeout=240 MakeJAR2.sh RetransformAgent RetransformApp 'Can-Retransform-Classes: true'
* @run main/othervm -javaagent:RetransformAgent.jar RetransformApp
*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/FindAccessTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2015, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 8139885
+ * @run testng/othervm -ea -esa test.java.lang.invoke.FindAccessTest
+ */
+
+package test.java.lang.invoke;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
+
+import static org.testng.AssertJUnit.*;
+
+import org.testng.annotations.*;
+
+/**
+ * Tests for Lookup.findClass/accessClass extensions added in JEP 274.
+ */
+public class FindAccessTest {
+
+ static final Lookup LOOKUP = MethodHandles.lookup();
+
+ @Test
+ public static void testFindSpecial() throws Throwable {
+ FindSpecial.C c = new FindSpecial.C();
+ assertEquals("I1.m", c.m());
+ MethodType t = MethodType.methodType(String.class);
+ MethodHandle ci1m = LOOKUP.findSpecial(FindSpecial.I1.class, "m", t, FindSpecial.C.class);
+ assertEquals("I1.m", (String) ci1m.invoke(c));
+ }
+
+ @Test
+ public static void testFindSpecialAbstract() throws Throwable {
+ FindSpecial.C c = new FindSpecial.C();
+ assertEquals("q", c.q());
+ MethodType t = MethodType.methodType(String.class);
+ boolean caught = false;
+ try {
+ MethodHandle ci3q = LOOKUP.findSpecial(FindSpecial.I3.class, "q", t, FindSpecial.C.class);
+ } catch (Throwable thrown) {
+ if (!(thrown instanceof IllegalAccessException) || !FindSpecial.ABSTRACT_ERROR.equals(thrown.getMessage())) {
+ throw new AssertionError(thrown.getMessage(), thrown);
+ }
+ caught = true;
+ }
+ assertTrue(caught);
+ }
+
+ @Test(expectedExceptions = {ClassNotFoundException.class})
+ public static void testFindClassCNFE() throws ClassNotFoundException, IllegalAccessException {
+ LOOKUP.findClass("does.not.Exist");
+ }
+
+ static class FindSpecial {
+
+ interface I1 {
+ default String m() {
+ return "I1.m";
+ }
+ }
+
+ interface I2 {
+ default String m() {
+ return "I2.m";
+ }
+ }
+
+ interface I3 {
+ String q();
+ }
+
+ static class C implements I1, I2, I3 {
+ public String m() {
+ return I1.super.m();
+ }
+ public String q() {
+ return "q";
+ }
+ }
+
+ static final String ABSTRACT_ERROR = "no such method: test.java.lang.invoke.FindAccessTest$FindSpecial$I3.q()String/invokeSpecial";
+
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/FoldTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2015, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 8139885
+ * @run testng/othervm -ea -esa test.java.lang.invoke.FoldTest
+ */
+
+package test.java.lang.invoke;
+
+import java.io.StringWriter;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
+
+import static java.lang.invoke.MethodType.methodType;
+
+import static org.testng.AssertJUnit.*;
+
+import org.testng.annotations.*;
+
+/**
+ * Tests for the new fold method handle combinator added in JEP 274.
+ */
+public class FoldTest {
+
+ static final Lookup LOOKUP = MethodHandles.lookup();
+
+ @Test
+ public static void testFold0a() throws Throwable {
+ // equivalence to foldArguments(MethodHandle,MethodHandle)
+ MethodHandle fold = MethodHandles.foldArguments(Fold.MH_multer, 0, Fold.MH_adder);
+ assertEquals(Fold.MT_folded1, fold.type());
+ assertEquals(720, (int) fold.invoke(3, 4, 5));
+ }
+
+ @Test
+ public static void testFold1a() throws Throwable {
+ // test foldArguments for folding position 1
+ MethodHandle fold = MethodHandles.foldArguments(Fold.MH_multer, 1, Fold.MH_adder1);
+ assertEquals(Fold.MT_folded1, fold.type());
+ assertEquals(540, (int) fold.invoke(3, 4, 5));
+ }
+
+ @Test
+ public static void testFold0b() throws Throwable {
+ // test foldArguments equivalence with multiple types
+ MethodHandle fold = MethodHandles.foldArguments(Fold.MH_str, 0, Fold.MH_comb);
+ assertEquals(Fold.MT_folded2, fold.type());
+ assertEquals(23, (int) fold.invoke("true", true, 23));
+ }
+
+ @Test
+ public static void testFold1b() throws Throwable {
+ // test folgArguments for folding position 1, with multiple types
+ MethodHandle fold = MethodHandles.foldArguments(Fold.MH_str, 1, Fold.MH_comb2);
+ assertEquals(Fold.MT_folded3, fold.type());
+ assertEquals(1, (int) fold.invoke(true, true, 1));
+ assertEquals(-1, (int) fold.invoke(true, false, -1));
+ }
+
+ @Test
+ public static void testFoldArgumentsExample() throws Throwable {
+ // test the JavaDoc foldArguments-with-pos example
+ StringWriter swr = new StringWriter();
+ MethodHandle trace = LOOKUP.findVirtual(StringWriter.class, "write", methodType(void.class, String.class)).bindTo(swr);
+ MethodHandle cat = LOOKUP.findVirtual(String.class, "concat", methodType(String.class, String.class));
+ assertEquals("boojum", (String) cat.invokeExact("boo", "jum"));
+ MethodHandle catTrace = MethodHandles.foldArguments(cat, 1, trace);
+ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
+ assertEquals("jum", swr.toString());
+ }
+
+ static class Fold {
+
+ static int adder(int a, int b, int c) {
+ return a + b + c;
+ }
+
+ static int adder1(int a, int b) {
+ return a + b;
+ }
+
+ static int multer(int x, int q, int r, int s) {
+ return x * q * r * s;
+ }
+
+ static int str(boolean b1, String s, boolean b2, int x) {
+ return b1 && s.equals(String.valueOf(b2)) ? x : -x;
+ }
+
+ static boolean comb(String s, boolean b2) {
+ return !s.equals(b2);
+ }
+
+ static String comb2(boolean b2, int x) {
+ int ib = b2 ? 1 : 0;
+ return ib == x ? "true" : "false";
+ }
+
+ static final Class<Fold> FOLD = Fold.class;
+
+ static final MethodType MT_adder = methodType(int.class, int.class, int.class, int.class);
+ static final MethodType MT_adder1 = methodType(int.class, int.class, int.class);
+ static final MethodType MT_multer = methodType(int.class, int.class, int.class, int.class, int.class);
+ static final MethodType MT_str = methodType(int.class, boolean.class, String.class, boolean.class, int.class);
+ static final MethodType MT_comb = methodType(boolean.class, String.class, boolean.class);
+ static final MethodType MT_comb2 = methodType(String.class, boolean.class, int.class);
+
+ static final MethodHandle MH_adder;
+ static final MethodHandle MH_adder1;
+ static final MethodHandle MH_multer;
+ static final MethodHandle MH_str;
+ static final MethodHandle MH_comb;
+ static final MethodHandle MH_comb2;
+
+ static final MethodType MT_folded1 = methodType(int.class, int.class, int.class, int.class);
+ static final MethodType MT_folded2 = methodType(int.class, String.class, boolean.class, int.class);
+ static final MethodType MT_folded3 = methodType(int.class, boolean.class, boolean.class, int.class);
+
+ static {
+ try {
+ MH_adder = LOOKUP.findStatic(FOLD, "adder", MT_adder);
+ MH_adder1 = LOOKUP.findStatic(FOLD, "adder1", MT_adder1);
+ MH_multer = LOOKUP.findStatic(FOLD, "multer", MT_multer);
+ MH_str = LOOKUP.findStatic(FOLD, "str", MT_str);
+ MH_comb = LOOKUP.findStatic(FOLD, "comb", MT_comb);
+ MH_comb2 = LOOKUP.findStatic(FOLD, "comb2", MT_comb2);
+ } catch (Exception e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+ }
+
+}
--- a/jdk/test/java/lang/invoke/JavaDocExamplesTest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/lang/invoke/JavaDocExamplesTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -690,7 +690,7 @@
{{
{} /// JAVADOC
// implement the zip function for lists as a loop handle
-MethodHandle loop = MethodHandles.doWhileLoop(MH_initZip, MH_zipStep, MH_zipPred);
+MethodHandle loop = MethodHandles.whileLoop(MH_initZip, MH_zipPred, MH_zipStep);
List<String> a = Arrays.asList("a", "b", "c", "d");
List<String> b = Arrays.asList("e", "f", "g", "h");
List<String> zipped = Arrays.asList("a", "e", "b", "f", "c", "g", "d", "h");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/LoopCombinatorTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,803 @@
+/*
+ * Copyright (c) 2015, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 8139885
+ * @bug 8150635
+ * @run testng/othervm -ea -esa test.java.lang.invoke.LoopCombinatorTest
+ */
+
+package test.java.lang.invoke;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
+import java.util.*;
+
+import static java.lang.invoke.MethodType.methodType;
+
+import static org.testng.AssertJUnit.*;
+
+import org.testng.annotations.*;
+
+/**
+ * Tests for the loop combinators introduced in JEP 274.
+ */
+public class LoopCombinatorTest {
+
+ static final Lookup LOOKUP = MethodHandles.lookup();
+
+ @Test
+ public static void testLoopFac() throws Throwable {
+ MethodHandle[] counterClause = new MethodHandle[]{Fac.MH_zero, Fac.MH_inc};
+ MethodHandle[] accumulatorClause = new MethodHandle[]{Fac.MH_one, Fac.MH_mult, Fac.MH_pred, Fac.MH_fin};
+ MethodHandle loop = MethodHandles.loop(counterClause, accumulatorClause);
+ assertEquals(Fac.MT_fac, loop.type());
+ assertEquals(120, loop.invoke(5));
+ }
+
+ @Test
+ public static void testLoopFacNullInit() throws Throwable {
+ // null initializer for counter, should initialize to 0
+ MethodHandle[] counterClause = new MethodHandle[]{null, Fac.MH_inc};
+ MethodHandle[] accumulatorClause = new MethodHandle[]{Fac.MH_one, Fac.MH_mult, Fac.MH_pred, Fac.MH_fin};
+ MethodHandle loop = MethodHandles.loop(counterClause, accumulatorClause);
+ assertEquals(Fac.MT_fac, loop.type());
+ assertEquals(120, loop.invoke(5));
+ }
+
+ @Test
+ public static void testLoopNullInit() throws Throwable {
+ // null initializer for counter, should initialize to 0, one-clause loop
+ MethodHandle[] counterClause = new MethodHandle[]{null, Loop.MH_inc, Loop.MH_pred, Loop.MH_fin};
+ MethodHandle loop = MethodHandles.loop(counterClause);
+ assertEquals(Loop.MT_loop, loop.type());
+ assertEquals(10, loop.invoke(10));
+ }
+
+ @Test
+ public static void testLoopVoid1() throws Throwable {
+ // construct a post-checked loop that only does one iteration and has a void body and void local state
+ MethodHandle loop = MethodHandles.loop(new MethodHandle[]{Empty.MH_f, Empty.MH_f, Empty.MH_pred, null});
+ assertEquals(MethodType.methodType(void.class), loop.type());
+ loop.invoke();
+ }
+
+ @Test
+ public static void testLoopVoid2() throws Throwable {
+ // construct a post-checked loop that only does one iteration and has a void body and void local state,
+ // initialized implicitly from the step type
+ MethodHandle loop = MethodHandles.loop(new MethodHandle[]{null, Empty.MH_f, Empty.MH_pred, null});
+ assertEquals(MethodType.methodType(void.class), loop.type());
+ loop.invoke();
+ }
+
+ @Test
+ public static void testLoopVoid3() throws Throwable {
+ // construct a post-checked loop that only does one iteration and has a void body and void local state,
+ // and that has a void finalizer
+ MethodHandle loop = MethodHandles.loop(new MethodHandle[]{null, Empty.MH_f, Empty.MH_pred, Empty.MH_f});
+ assertEquals(MethodType.methodType(void.class), loop.type());
+ loop.invoke();
+ }
+
+ @Test
+ public static void testLoopFacWithVoidState() throws Throwable {
+ // like testLoopFac, but with additional void state that outputs a dot
+ MethodHandle[] counterClause = new MethodHandle[]{Fac.MH_zero, Fac.MH_inc};
+ MethodHandle[] accumulatorClause = new MethodHandle[]{Fac.MH_one, Fac.MH_mult, Fac.MH_pred, Fac.MH_fin};
+ MethodHandle[] dotClause = new MethodHandle[]{null, Fac.MH_dot};
+ MethodHandle loop = MethodHandles.loop(counterClause, accumulatorClause, dotClause);
+ assertEquals(Fac.MT_fac, loop.type());
+ assertEquals(120, loop.invoke(5));
+ }
+
+ @Test
+ public static void testLoopVoidInt() throws Throwable {
+ // construct a post-checked loop that only does one iteration and has a void body and void local state,
+ // and that returns a constant
+ MethodHandle loop = MethodHandles.loop(new MethodHandle[]{null, Empty.MH_f, Empty.MH_pred, Empty.MH_c});
+ assertEquals(MethodType.methodType(int.class), loop.type());
+ assertEquals(23, loop.invoke());
+ }
+
+ @Test
+ public static void testLoopWithVirtuals() throws Throwable {
+ // construct a loop (to calculate factorial) that uses a mix of static and virtual methods
+ MethodHandle[] counterClause = new MethodHandle[]{null, LoopWithVirtuals.permute(LoopWithVirtuals.MH_inc)};
+ MethodHandle[] accumulatorClause = new MethodHandle[]{
+ // init function must indicate the loop arguments (there is no other means to determine them)
+ MethodHandles.dropArguments(LoopWithVirtuals.MH_one, 0, LoopWithVirtuals.class),
+ LoopWithVirtuals.permute(LoopWithVirtuals.MH_mult),
+ LoopWithVirtuals.permute(LoopWithVirtuals.MH_pred),
+ LoopWithVirtuals.permute(LoopWithVirtuals.MH_fin)
+ };
+ MethodHandle loop = MethodHandles.loop(counterClause, accumulatorClause);
+ assertEquals(LoopWithVirtuals.MT_loop, loop.type());
+ assertEquals(120, loop.invoke(new LoopWithVirtuals(), 5));
+ }
+
+ @DataProvider
+ static Object[][] negativeTestData() {
+ MethodHandle i0 = MethodHandles.constant(int.class, 0);
+ MethodHandle ii = MethodHandles.dropArguments(i0, 0, int.class, int.class);
+ MethodHandle id = MethodHandles.dropArguments(i0, 0, int.class, double.class);
+ MethodHandle i3 = MethodHandles.dropArguments(i0, 0, int.class, int.class, int.class);
+ List<MethodHandle> inits = Arrays.asList(ii, id, i3);
+ List<Class<?>> ints = Arrays.asList(int.class, int.class, int.class);
+ List<MethodHandle> finis = Arrays.asList(Fac.MH_fin, Fac.MH_inc, Counted.MH_step);
+ List<MethodHandle> preds1 = Arrays.asList(null, null, null);
+ List<MethodHandle> preds2 = Arrays.asList(null, Fac.MH_fin, null);
+ MethodHandle eek = MethodHandles.dropArguments(i0, 0, int.class, int.class, double.class);
+ List<MethodHandle> nesteps = Arrays.asList(Fac.MH_inc, eek, Fac.MH_dot);
+ List<MethodHandle> nepreds = Arrays.asList(null, Fac.MH_pred, null);
+ List<MethodHandle> nefinis = Arrays.asList(null, Fac.MH_fin, null);
+ List<MethodHandle> lvsteps = Arrays.asList(LoopWithVirtuals.MH_inc, LoopWithVirtuals.MH_mult);
+ List<MethodHandle> lvpreds = Arrays.asList(null, LoopWithVirtuals.MH_pred);
+ List<MethodHandle> lvfinis = Arrays.asList(null, LoopWithVirtuals.MH_fin);
+ return new Object[][] {
+ {null, "null or no clauses passed"},
+ {new MethodHandle[][]{}, "null or no clauses passed"},
+ {new MethodHandle[][]{{null, Fac.MH_inc}, {Fac.MH_one, null, Fac.MH_mult, Fac.MH_pred, Fac.MH_fin}},
+ "All loop clauses must be represented as MethodHandle arrays with at most 4 elements."},
+ {new MethodHandle[][]{{null, Fac.MH_inc}, null}, "null clauses are not allowed"},
+ {new MethodHandle[][]{{Fac.MH_zero, Fac.MH_dot}},
+ "clause 0: init and step return types must match: int != void"},
+ {new MethodHandle[][]{{ii}, {id}, {i3}},
+ "found non-effectively identical init parameter type lists: " + inits +
+ " (common suffix: " + ints + ")"},
+ {new MethodHandle[][]{{null, Fac.MH_inc, null, Fac.MH_fin}, {null, Fac.MH_inc, null, Fac.MH_inc},
+ {null, Counted.MH_start, null, Counted.MH_step}},
+ "found non-identical finalizer return types: " + finis + " (return type: int)"},
+ {new MethodHandle[][]{{Fac.MH_zero, Fac.MH_inc}, {Fac.MH_one, Fac.MH_mult, null, Fac.MH_fin},
+ {null, Fac.MH_dot}}, "no predicate found: " + preds1},
+ {new MethodHandle[][]{{Fac.MH_zero, Fac.MH_inc}, {Fac.MH_one, Fac.MH_mult, Fac.MH_fin, Fac.MH_fin},
+ {null, Fac.MH_dot}}, "predicates must have boolean return type: " + preds2},
+ {new MethodHandle[][]{{Fac.MH_zero, Fac.MH_inc}, {Fac.MH_one, eek, Fac.MH_pred, Fac.MH_fin},
+ {null, Fac.MH_dot}},
+ "found non-effectively identical parameter type lists:\nstep: " + nesteps +
+ "\npred: " + nepreds + "\nfini: " + nefinis + " (common parameter sequence: " + ints + ")"},
+ {new MethodHandle[][]{{null, LoopWithVirtuals.MH_inc},
+ {LoopWithVirtuals.MH_one, LoopWithVirtuals.MH_mult, LoopWithVirtuals.MH_pred, LoopWithVirtuals.MH_fin}},
+ "found non-effectively identical parameter type lists:\nstep: " + lvsteps +
+ "\npred: " + lvpreds + "\nfini: " + lvfinis + " (common parameter sequence: " + ints + ")"}
+ };
+ }
+
+ static final MethodHandle MH_loop;
+
+ static {
+ try {
+ MH_loop = LOOKUP.findStatic(MethodHandles.class, "loop", methodType(MethodHandle.class, MethodHandle[][].class));
+ } catch (NoSuchMethodException | IllegalAccessException e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+ @Test(dataProvider = "negativeTestData")
+ public static void testLoopNegative(MethodHandle[][] clauses, String expectedMessage) throws Throwable {
+ boolean caught = false;
+ try {
+ MH_loop.invokeWithArguments(clauses);
+ } catch (IllegalArgumentException iae) {
+ assertEquals(expectedMessage, iae.getMessage());
+ caught = true;
+ }
+ assertTrue(caught);
+ }
+
+ @Test
+ public static void testWhileLoop() throws Throwable {
+ // int i = 0; while (i < limit) { ++i; } return i; => limit
+ MethodHandle loop = MethodHandles.whileLoop(While.MH_zero, While.MH_pred, While.MH_step);
+ assertEquals(While.MT_while, loop.type());
+ assertEquals(23, loop.invoke(23));
+ }
+
+ @Test
+ public static void testWhileLoopNoIteration() throws Throwable {
+ // a while loop that never executes its body because the predicate evaluates to false immediately
+ MethodHandle loop = MethodHandles.whileLoop(While.MH_initString, While.MH_predString, While.MH_stepString);
+ assertEquals(While.MT_string, loop.type());
+ assertEquals("a", loop.invoke());
+ }
+
+ @Test
+ public static void testDoWhileLoop() throws Throwable {
+ // int i = 0; do { ++i; } while (i < limit); return i; => limit
+ MethodHandle loop = MethodHandles.doWhileLoop(While.MH_zero, While.MH_step, While.MH_pred);
+ assertEquals(While.MT_while, loop.type());
+ assertEquals(23, loop.invoke(23));
+ }
+
+ @Test
+ public static void testDoWhileNullInit() throws Throwable {
+ While w = new While();
+ int v = 5;
+ MethodHandle loop = MethodHandles.doWhileLoop(null, While.MH_voidBody.bindTo(w), While.MH_voidPred.bindTo(w));
+ assertEquals(While.MT_void, loop.type());
+ loop.invoke(v);
+ assertEquals(v, w.i);
+ }
+
+ @Test
+ public static void testWhileZip() throws Throwable {
+ MethodHandle loop = MethodHandles.doWhileLoop(While.MH_zipInitZip, While.MH_zipStep, While.MH_zipPred);
+ assertEquals(While.MT_zip, loop.type());
+ List<String> a = Arrays.asList("a", "b", "c", "d");
+ List<String> b = Arrays.asList("e", "f", "g", "h");
+ List<String> zipped = Arrays.asList("a", "e", "b", "f", "c", "g", "d", "h");
+ assertEquals(zipped, (List<String>) loop.invoke(a.iterator(), b.iterator()));
+ }
+
+ @Test
+ public static void testWhileNullInit() throws Throwable {
+ While w = new While();
+ int v = 5;
+ MethodHandle loop = MethodHandles.whileLoop(null, While.MH_voidPred.bindTo(w), While.MH_voidBody.bindTo(w));
+ assertEquals(While.MT_void, loop.type());
+ loop.invoke(v);
+ assertEquals(v, w.i);
+ }
+
+ @Test
+ public static void testCountedLoop() throws Throwable {
+ // String s = "Lambdaman!"; for (int i = 0; i < 13; ++i) { s = "na " + s; } return s; => a variation on a well known theme
+ MethodHandle fit13 = MethodHandles.constant(int.class, 13);
+ MethodHandle loop = MethodHandles.countedLoop(fit13, Counted.MH_start, Counted.MH_step);
+ assertEquals(Counted.MT_counted, loop.type());
+ assertEquals("na na na na na na na na na na na na na Lambdaman!", loop.invoke("Lambdaman!"));
+ }
+
+ @Test
+ public static void testCountedArrayLoop() throws Throwable {
+ // int[] a = new int[]{0}; for (int i = 0; i < 13; ++i) { ++a[0]; } => a[0] == 13
+ MethodHandle fit13 = MethodHandles.dropArguments(MethodHandles.constant(int.class, 13), 0, int[].class);
+ MethodHandle loop = MethodHandles.countedLoop(fit13, null, Counted.MH_stepUpdateArray);
+ assertEquals(Counted.MT_arrayCounted, loop.type());
+ int[] a = new int[]{0};
+ loop.invoke(a);
+ assertEquals(13, a[0]);
+ }
+
+ @Test
+ public static void testCountedPrintingLoop() throws Throwable {
+ MethodHandle fit5 = MethodHandles.constant(int.class, 5);
+ MethodHandle loop = MethodHandles.countedLoop(fit5, null, Counted.MH_printHello);
+ assertEquals(Counted.MT_countedPrinting, loop.type());
+ loop.invoke();
+ }
+
+ @Test
+ public static void testCountedRangeLoop() throws Throwable {
+ // String s = "Lambdaman!"; for (int i = -5; i < 8; ++i) { s = "na " + s; } return s; => a well known theme
+ MethodHandle fitm5 = MethodHandles.dropArguments(Counted.MH_m5, 0, String.class);
+ MethodHandle fit8 = MethodHandles.dropArguments(Counted.MH_8, 0, String.class);
+ MethodHandle loop = MethodHandles.countedLoop(fitm5, fit8, Counted.MH_start, Counted.MH_step);
+ assertEquals(Counted.MT_counted, loop.type());
+ assertEquals("na na na na na na na na na na na na na Lambdaman!", loop.invoke("Lambdaman!"));
+ }
+
+ @Test
+ public static void testIterateSum() throws Throwable {
+ // Integer[] a = new Integer[]{1,2,3,4,5,6}; int sum = 0; for (int e : a) { sum += e; } return sum; => 21
+ MethodHandle loop = MethodHandles.iteratedLoop(Iterate.MH_sumIterator, Iterate.MH_sumInit, Iterate.MH_sumStep);
+ assertEquals(Iterate.MT_sum, loop.type());
+ assertEquals(21, loop.invoke(new Integer[]{1, 2, 3, 4, 5, 6}));
+ }
+
+ @Test
+ public static void testIterateReverse() throws Throwable {
+ MethodHandle loop = MethodHandles.iteratedLoop(null, Iterate.MH_reverseInit, Iterate.MH_reverseStep);
+ assertEquals(Iterate.MT_reverse, loop.type());
+ List<String> list = Arrays.asList("a", "b", "c", "d", "e");
+ List<String> reversedList = Arrays.asList("e", "d", "c", "b", "a");
+ assertEquals(reversedList, (List<String>) loop.invoke(list));
+ }
+
+ @Test
+ public static void testIterateLength() throws Throwable {
+ MethodHandle loop = MethodHandles.iteratedLoop(null, Iterate.MH_lengthInit, Iterate.MH_lengthStep);
+ assertEquals(Iterate.MT_length, loop.type());
+ List<Double> list = Arrays.asList(23.0, 148.0, 42.0);
+ assertEquals(list.size(), (int) loop.invoke(list));
+ }
+
+ @Test
+ public static void testIterateMap() throws Throwable {
+ MethodHandle loop = MethodHandles.iteratedLoop(null, Iterate.MH_mapInit, Iterate.MH_mapStep);
+ assertEquals(Iterate.MT_map, loop.type());
+ List<String> list = Arrays.asList("Hello", "world", "!");
+ List<String> upList = Arrays.asList("HELLO", "WORLD", "!");
+ assertEquals(upList, (List<String>) loop.invoke(list));
+ }
+
+ @Test
+ public static void testIteratePrint() throws Throwable {
+ MethodHandle loop = MethodHandles.iteratedLoop(null, null, Iterate.MH_printStep);
+ assertEquals(Iterate.MT_print, loop.type());
+ loop.invoke(Arrays.asList("hello", "world"));
+ }
+
+ @Test
+ public static void testIterateNullBody() {
+ boolean caught = false;
+ try {
+ MethodHandles.iteratedLoop(MethodHandles.identity(int.class), MethodHandles.identity(int.class), null);
+ } catch (IllegalArgumentException iae) {
+ assertEquals("iterated loop body must not be null", iae.getMessage());
+ caught = true;
+ }
+ assertTrue(caught);
+ }
+
+ static class Empty {
+
+ static void f() { }
+
+ static boolean pred() {
+ return false;
+ }
+
+ static int c() {
+ return 23;
+ }
+
+ static final Class<Empty> EMPTY = Empty.class;
+
+ static final MethodType MT_f = methodType(void.class);
+ static final MethodType MT_pred = methodType(boolean.class);
+ static final MethodType MT_c = methodType(int.class);
+
+ static final MethodHandle MH_f;
+ static final MethodHandle MH_pred;
+ static final MethodHandle MH_c;
+
+ static {
+ try {
+ MH_f = LOOKUP.findStatic(EMPTY, "f", MT_f);
+ MH_pred = LOOKUP.findStatic(EMPTY, "pred", MT_pred);
+ MH_c = LOOKUP.findStatic(EMPTY, "c", MT_c);
+ } catch (Exception e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+ }
+
+ static class Fac {
+
+ static int zero(int k) {
+ return 0;
+ }
+
+ static int one(int k) {
+ return 1;
+ }
+
+ static boolean pred(int i, int acc, int k) {
+ return i < k;
+ }
+
+ static int inc(int i, int acc, int k) {
+ return i + 1;
+ }
+
+ static int mult(int i, int acc, int k) {
+ return i * acc;
+ }
+
+ static void dot(int i, int acc, int k) {
+ System.out.print('.');
+ }
+
+ static int fin(int i, int acc, int k) {
+ return acc;
+ }
+
+ static final Class<Fac> FAC = Fac.class;
+
+ static final MethodType MT_init = methodType(int.class, int.class);
+ static final MethodType MT_fn = methodType(int.class, int.class, int.class, int.class);
+ static final MethodType MT_dot = methodType(void.class, int.class, int.class, int.class);
+ static final MethodType MT_pred = methodType(boolean.class, int.class, int.class, int.class);
+
+ static final MethodHandle MH_zero;
+ static final MethodHandle MH_one;
+ static final MethodHandle MH_pred;
+ static final MethodHandle MH_inc;
+ static final MethodHandle MH_mult;
+ static final MethodHandle MH_dot;
+ static final MethodHandle MH_fin;
+
+ static final MethodType MT_fac = methodType(int.class, int.class);
+
+ static {
+ try {
+ MH_zero = LOOKUP.findStatic(FAC, "zero", MT_init);
+ MH_one = LOOKUP.findStatic(FAC, "one", MT_init);
+ MH_pred = LOOKUP.findStatic(FAC, "pred", MT_pred);
+ MH_inc = LOOKUP.findStatic(FAC, "inc", MT_fn);
+ MH_mult = LOOKUP.findStatic(FAC, "mult", MT_fn);
+ MH_dot = LOOKUP.findStatic(FAC, "dot", MT_dot);
+ MH_fin = LOOKUP.findStatic(FAC, "fin", MT_fn);
+ } catch (Exception e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+ }
+
+ static class Loop {
+
+ static int inc(int i, int k) {
+ return i + 1;
+ }
+
+ static boolean pred(int i, int k) {
+ return i < k;
+ }
+
+ static int fin(int i, int k) {
+ return k;
+ }
+
+ static final Class<Loop> LOOP = Loop.class;
+
+ static final MethodType MT_inc = methodType(int.class, int.class, int.class);
+ static final MethodType MT_pred = methodType(boolean.class, int.class, int.class);
+ static final MethodType MT_fin = methodType(int.class, int.class, int.class);
+
+ static final MethodHandle MH_inc;
+ static final MethodHandle MH_pred;
+ static final MethodHandle MH_fin;
+
+ static final MethodType MT_loop = methodType(int.class, int.class);
+
+ static {
+ try {
+ MH_inc = LOOKUP.findStatic(LOOP, "inc", MT_inc);
+ MH_pred = LOOKUP.findStatic(LOOP, "pred", MT_pred);
+ MH_fin = LOOKUP.findStatic(LOOP, "fin", MT_fin);
+ } catch (Exception e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+ }
+
+ static class LoopWithVirtuals {
+
+ static int one(int k) {
+ return 1;
+ }
+
+ int inc(int i, int acc, int k) {
+ return i + 1;
+ }
+
+ int mult(int i, int acc, int k) {
+ return i * acc;
+ }
+
+ boolean pred(int i, int acc, int k) {
+ return i < k;
+ }
+
+ int fin(int i, int acc, int k) {
+ return acc;
+ }
+
+ static final Class<LoopWithVirtuals> LOOP_WITH_VIRTUALS = LoopWithVirtuals.class;
+
+ static final MethodType MT_one = methodType(int.class, int.class);
+ static final MethodType MT_inc = methodType(int.class, int.class, int.class, int.class);
+ static final MethodType MT_mult = methodType(int.class, int.class, int.class, int.class);
+ static final MethodType MT_pred = methodType(boolean.class, int.class, int.class, int.class);
+ static final MethodType MT_fin = methodType(int.class, int.class, int.class, int.class);
+
+ static final MethodHandle MH_one;
+ static final MethodHandle MH_inc;
+ static final MethodHandle MH_mult;
+ static final MethodHandle MH_pred;
+ static final MethodHandle MH_fin;
+
+ static final MethodType MT_loop = methodType(int.class, LOOP_WITH_VIRTUALS, int.class);
+
+ static {
+ try {
+ MH_one = LOOKUP.findStatic(LOOP_WITH_VIRTUALS, "one", MT_one);
+ MH_inc = LOOKUP.findVirtual(LOOP_WITH_VIRTUALS, "inc", MT_inc);
+ MH_mult = LOOKUP.findVirtual(LOOP_WITH_VIRTUALS, "mult", MT_mult);
+ MH_pred = LOOKUP.findVirtual(LOOP_WITH_VIRTUALS, "pred", MT_pred);
+ MH_fin = LOOKUP.findVirtual(LOOP_WITH_VIRTUALS, "fin", MT_fin);
+ } catch (Exception e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+ static MethodHandle permute(MethodHandle h) {
+ // The handles representing virtual methods need to be rearranged to match the required order of arguments
+ // (loop-local state comes first, then loop arguments). As the receiver comes first in the signature but is
+ // a loop argument, it must be moved to the appropriate position in the signature.
+ return MethodHandles.permuteArguments(h,
+ methodType(h.type().returnType(), int.class, int.class, LOOP_WITH_VIRTUALS, int.class), 2, 0, 1, 3);
+ }
+
+ }
+
+ static class While {
+
+ static int zero(int limit) {
+ return 0;
+ }
+
+ static boolean pred(int i, int limit) {
+ return i < limit;
+ }
+
+ static int step(int i, int limit) {
+ return i + 1;
+ }
+
+ static String initString() {
+ return "a";
+ }
+
+ static boolean predString(String s) {
+ return s.length() != 1;
+ }
+
+ static String stepString(String s) {
+ return s + "a";
+ }
+
+ static List<String> zipInitZip(Iterator<String> a, Iterator<String> b) {
+ return new ArrayList<>();
+ }
+
+ static boolean zipPred(List<String> zip, Iterator<String> a, Iterator<String> b) {
+ return a.hasNext() && b.hasNext();
+ }
+
+ static List<String> zipStep(List<String> zip, Iterator<String> a, Iterator<String> b) {
+ zip.add(a.next());
+ zip.add(b.next());
+ return zip;
+ }
+
+ private int i = 0;
+
+ void voidBody(int k) {
+ ++i;
+ }
+
+ boolean voidPred(int k) {
+ return i < k;
+ }
+
+ static final Class<While> WHILE = While.class;
+
+ static final MethodType MT_zero = methodType(int.class, int.class);
+ static final MethodType MT_pred = methodType(boolean.class, int.class, int.class);
+ static final MethodType MT_fn = methodType(int.class, int.class, int.class);
+ static final MethodType MT_initString = methodType(String.class);
+ static final MethodType MT_predString = methodType(boolean.class, String.class);
+ static final MethodType MT_stepString = methodType(String.class, String.class);
+ static final MethodType MT_zipInitZip = methodType(List.class, Iterator.class, Iterator.class);
+ static final MethodType MT_zipPred = methodType(boolean.class, List.class, Iterator.class, Iterator.class);
+ static final MethodType MT_zipStep = methodType(List.class, List.class, Iterator.class, Iterator.class);
+ static final MethodType MT_voidBody = methodType(void.class, int.class);
+ static final MethodType MT_voidPred = methodType(boolean.class, int.class);
+
+ static final MethodHandle MH_zero;
+ static final MethodHandle MH_pred;
+ static final MethodHandle MH_step;
+ static final MethodHandle MH_initString;
+ static final MethodHandle MH_predString;
+ static final MethodHandle MH_stepString;
+ static final MethodHandle MH_zipInitZip;
+ static final MethodHandle MH_zipPred;
+ static final MethodHandle MH_zipStep;
+ static final MethodHandle MH_voidBody;
+ static final MethodHandle MH_voidPred;
+
+ static final MethodType MT_while = methodType(int.class, int.class);
+ static final MethodType MT_string = methodType(String.class);
+ static final MethodType MT_zip = methodType(List.class, Iterator.class, Iterator.class);
+ static final MethodType MT_void = methodType(void.class, int.class);
+
+ static {
+ try {
+ MH_zero = LOOKUP.findStatic(WHILE, "zero", MT_zero);
+ MH_pred = LOOKUP.findStatic(WHILE, "pred", MT_pred);
+ MH_step = LOOKUP.findStatic(WHILE, "step", MT_fn);
+ MH_initString = LOOKUP.findStatic(WHILE, "initString", MT_initString);
+ MH_predString = LOOKUP.findStatic(WHILE, "predString", MT_predString);
+ MH_stepString = LOOKUP.findStatic(WHILE, "stepString", MT_stepString);
+ MH_zipInitZip = LOOKUP.findStatic(WHILE, "zipInitZip", MT_zipInitZip);
+ MH_zipPred = LOOKUP.findStatic(WHILE, "zipPred", MT_zipPred);
+ MH_zipStep = LOOKUP.findStatic(WHILE, "zipStep", MT_zipStep);
+ MH_voidBody = LOOKUP.findVirtual(WHILE, "voidBody", MT_voidBody);
+ MH_voidPred = LOOKUP.findVirtual(WHILE, "voidPred", MT_voidPred);
+ } catch (Exception e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+ }
+
+ static class Counted {
+
+ static String start(String arg) {
+ return arg;
+ }
+
+ static String step(int counter, String v, String arg) {
+ return "na " + v;
+ }
+
+ static void stepUpdateArray(int counter, int[] a) {
+ ++a[0];
+ }
+
+ static void printHello(int counter) {
+ System.out.print("hello");
+ }
+
+ static final Class<Counted> COUNTED = Counted.class;
+
+ static final MethodType MT_start = methodType(String.class, String.class);
+ static final MethodType MT_step = methodType(String.class, int.class, String.class, String.class);
+ static final MethodType MT_stepUpdateArray = methodType(void.class, int.class, int[].class);
+ static final MethodType MT_printHello = methodType(void.class, int.class);
+
+ static final MethodHandle MH_13;
+ static final MethodHandle MH_m5;
+ static final MethodHandle MH_8;
+ static final MethodHandle MH_start;
+ static final MethodHandle MH_step;
+ static final MethodHandle MH_stepUpdateArray;
+ static final MethodHandle MH_printHello;
+
+ static final MethodType MT_counted = methodType(String.class, String.class);
+ static final MethodType MT_arrayCounted = methodType(void.class, int[].class);
+ static final MethodType MT_countedPrinting = methodType(void.class);
+
+ static {
+ try {
+ MH_13 = MethodHandles.constant(int.class, 13);
+ MH_m5 = MethodHandles.constant(int.class, -5);
+ MH_8 = MethodHandles.constant(int.class, 8);
+ MH_start = LOOKUP.findStatic(COUNTED, "start", MT_start);
+ MH_step = LOOKUP.findStatic(COUNTED, "step", MT_step);
+ MH_stepUpdateArray = LOOKUP.findStatic(COUNTED, "stepUpdateArray", MT_stepUpdateArray);
+ MH_printHello = LOOKUP.findStatic(COUNTED, "printHello", MT_printHello);
+ } catch (Exception e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+ }
+
+ static class Iterate {
+
+ static Iterator<Integer> sumIterator(Integer[] a) {
+ return Arrays.asList(a).iterator();
+ }
+
+ static int sumInit(Integer[] a) {
+ return 0;
+ }
+
+ static int sumStep(int s, int e, Integer[] a) {
+ return s + e;
+ }
+
+ static List<String> reverseInit(List<String> l) {
+ return new ArrayList<>();
+ }
+
+ static List<String> reverseStep(String e, List<String> r, List<String> l) {
+ r.add(0, e);
+ return r;
+ }
+
+ static int lengthInit(List<Double> l) {
+ return 0;
+ }
+
+ static int lengthStep(Object o, int len, List<Double> l) {
+ return len + 1;
+ }
+
+ static List<String> mapInit(List<String> l) {
+ return new ArrayList<>();
+ }
+
+ static List<String> mapStep(String e, List<String> r, List<String> l) {
+ r.add(e.toUpperCase());
+ return r;
+ }
+
+ static void printStep(String s, List<String> l) {
+ System.out.print(s);
+ }
+
+ static final Class<Iterate> ITERATE = Iterate.class;
+
+ static final MethodType MT_sumIterator = methodType(Iterator.class, Integer[].class);
+
+ static final MethodType MT_sumInit = methodType(int.class, Integer[].class);
+ static final MethodType MT_reverseInit = methodType(List.class, List.class);
+ static final MethodType MT_lenghInit = methodType(int.class, List.class);
+ static final MethodType MT_mapInit = methodType(List.class, List.class);
+
+ static final MethodType MT_sumStep = methodType(int.class, int.class, int.class, Integer[].class);
+ static final MethodType MT_reverseStep = methodType(List.class, String.class, List.class, List.class);
+ static final MethodType MT_lengthStep = methodType(int.class, Object.class, int.class, List.class);
+ static final MethodType MT_mapStep = methodType(List.class, String.class, List.class, List.class);
+ static final MethodType MT_printStep = methodType(void.class, String.class, List.class);
+
+ static final MethodHandle MH_sumIterator;
+ static final MethodHandle MH_sumInit;
+ static final MethodHandle MH_sumStep;
+ static final MethodHandle MH_printStep;
+
+ static final MethodHandle MH_reverseInit;
+ static final MethodHandle MH_reverseStep;
+
+ static final MethodHandle MH_lengthInit;
+ static final MethodHandle MH_lengthStep;
+
+ static final MethodHandle MH_mapInit;
+ static final MethodHandle MH_mapStep;
+
+ static final MethodType MT_sum = methodType(int.class, Integer[].class);
+ static final MethodType MT_reverse = methodType(List.class, List.class);
+ static final MethodType MT_length = methodType(int.class, List.class);
+ static final MethodType MT_map = methodType(List.class, List.class);
+ static final MethodType MT_print = methodType(void.class, List.class);
+
+ static {
+ try {
+ MH_sumIterator = LOOKUP.findStatic(ITERATE, "sumIterator", MT_sumIterator);
+ MH_sumInit = LOOKUP.findStatic(ITERATE, "sumInit", MT_sumInit);
+ MH_sumStep = LOOKUP.findStatic(ITERATE, "sumStep", MT_sumStep);
+ MH_reverseInit = LOOKUP.findStatic(ITERATE, "reverseInit", MT_reverseInit);
+ MH_reverseStep = LOOKUP.findStatic(ITERATE, "reverseStep", MT_reverseStep);
+ MH_lengthInit = LOOKUP.findStatic(ITERATE, "lengthInit", MT_lenghInit);
+ MH_lengthStep = LOOKUP.findStatic(ITERATE, "lengthStep", MT_lengthStep);
+ MH_mapInit = LOOKUP.findStatic(ITERATE, "mapInit", MT_mapInit);
+ MH_mapStep = LOOKUP.findStatic(ITERATE, "mapStep", MT_mapStep);
+ MH_printStep = LOOKUP.findStatic(ITERATE, "printStep", MT_printStep);
+ } catch (Exception e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/SpreadCollectTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2015, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 8139885
+ * @bug 8143798
+ * @run testng/othervm -ea -esa test.java.lang.invoke.SpreadCollectTest
+ */
+
+package test.java.lang.invoke;
+
+import java.io.StringWriter;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.WrongMethodTypeException;
+import java.util.*;
+
+import static java.lang.invoke.MethodType.methodType;
+
+import static org.testng.AssertJUnit.*;
+
+import org.testng.annotations.*;
+
+/**
+ * Tests for the new asSpreader/asCollector API added in JEP 274.
+ */
+public class SpreadCollectTest {
+
+ static final Lookup LOOKUP = MethodHandles.lookup();
+
+ @Test
+ public static void testAsSpreader() throws Throwable {
+ MethodHandle spreader = SpreadCollect.MH_forSpreading.asSpreader(1, int[].class, 3);
+ assertEquals(SpreadCollect.MT_spreader, spreader.type());
+ assertEquals("A456B", (String) spreader.invoke("A", new int[]{4, 5, 6}, "B"));
+ }
+
+ @Test
+ public static void testAsSpreaderExample() throws Throwable {
+ // test the JavaDoc asSpreader-with-pos example
+ MethodHandle compare = LOOKUP.findStatic(Objects.class, "compare", methodType(int.class, Object.class, Object.class, Comparator.class));
+ MethodHandle compare2FromArray = compare.asSpreader(0, Object[].class, 2);
+ Object[] ints = new Object[]{3, 9, 7, 7};
+ Comparator<Integer> cmp = (a, b) -> a - b;
+ assertTrue((int) compare2FromArray.invoke(Arrays.copyOfRange(ints, 0, 2), cmp) < 0);
+ assertTrue((int) compare2FromArray.invoke(Arrays.copyOfRange(ints, 1, 3), cmp) > 0);
+ assertTrue((int) compare2FromArray.invoke(Arrays.copyOfRange(ints, 2, 4), cmp) == 0);
+ }
+
+ @DataProvider
+ static Object[][] asSpreaderIllegalPositions() {
+ return new Object[][]{{-7}, {3}, {19}};
+ }
+
+ @Test(dataProvider = "asSpreaderIllegalPositions")
+ public static void testAsSpreaderIllegalPos(int p) throws Throwable {
+ boolean caught = false;
+ try {
+ SpreadCollect.MH_forSpreading.asSpreader(p, Object[].class, 3);
+ } catch (IllegalArgumentException iae) {
+ assertEquals("bad spread position", iae.getMessage());
+ caught = true;
+ }
+ assertTrue(caught);
+ }
+
+ @Test(expectedExceptions = {WrongMethodTypeException.class})
+ public static void testAsSpreaderIllegalMethodType() {
+ MethodHandle h = MethodHandles.dropArguments(MethodHandles.constant(String.class, ""), 0, int.class, int.class);
+ MethodHandle s = h.asSpreader(String[].class, 1);
+ }
+
+ @Test
+ public static void testAsCollector() throws Throwable {
+ MethodHandle collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 1);
+ assertEquals(SpreadCollect.MT_collector1, collector.type());
+ assertEquals("A4B", (String) collector.invoke("A", 4, "B"));
+ collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 2);
+ assertEquals(SpreadCollect.MT_collector2, collector.type());
+ assertEquals("A45B", (String) collector.invoke("A", 4, 5, "B"));
+ collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 3);
+ assertEquals(SpreadCollect.MT_collector3, collector.type());
+ assertEquals("A456B", (String) collector.invoke("A", 4, 5, 6, "B"));
+ }
+
+ @Test
+ public static void testAsCollectorInvokeWithArguments() throws Throwable {
+ MethodHandle collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 1);
+ assertEquals(SpreadCollect.MT_collector1, collector.type());
+ assertEquals("A4B", (String) collector.invokeWithArguments("A", 4, "B"));
+ collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 2);
+ assertEquals(SpreadCollect.MT_collector2, collector.type());
+ assertEquals("A45B", (String) collector.invokeWithArguments("A", 4, 5, "B"));
+ collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 3);
+ assertEquals(SpreadCollect.MT_collector3, collector.type());
+ assertEquals("A456B", (String) collector.invokeWithArguments("A", 4, 5, 6, "B"));
+ }
+
+ @Test
+ public static void testAsCollectorLeading() throws Throwable {
+ MethodHandle collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 1);
+ assertEquals(SpreadCollect.MT_collectorLeading1, collector.type());
+ assertEquals("7Q", (String) collector.invoke(7, "Q"));
+ collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 2);
+ assertEquals(SpreadCollect.MT_collectorLeading2, collector.type());
+ assertEquals("78Q", (String) collector.invoke(7, 8, "Q"));
+ collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 3);
+ assertEquals(SpreadCollect.MT_collectorLeading3, collector.type());
+ assertEquals("789Q", (String) collector.invoke(7, 8, 9, "Q"));
+ }
+
+ @Test
+ public static void testAsCollectorLeadingInvokeWithArguments() throws Throwable {
+ MethodHandle collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 1);
+ assertEquals(SpreadCollect.MT_collectorLeading1, collector.type());
+ assertEquals("7Q", (String) collector.invokeWithArguments(7, "Q"));
+ collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 2);
+ assertEquals(SpreadCollect.MT_collectorLeading2, collector.type());
+ assertEquals("78Q", (String) collector.invokeWithArguments(7, 8, "Q"));
+ collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 3);
+ assertEquals(SpreadCollect.MT_collectorLeading3, collector.type());
+ assertEquals("789Q", (String) collector.invokeWithArguments(7, 8, 9, "Q"));
+ }
+
+ @Test
+ public static void testAsCollectorNone() throws Throwable {
+ MethodHandle collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 0);
+ assertEquals(SpreadCollect.MT_collector0, collector.type());
+ assertEquals("AB", (String) collector.invoke("A", "B"));
+ }
+
+ @DataProvider
+ static Object[][] asCollectorIllegalPositions() {
+ return new Object[][]{{-1}, {17}};
+ }
+
+ @Test(dataProvider = "asCollectorIllegalPositions")
+ public static void testAsCollectorIllegalPos(int p) {
+ boolean caught = false;
+ try {
+ SpreadCollect.MH_forCollecting.asCollector(p, int[].class, 0);
+ } catch (IllegalArgumentException iae) {
+ assertEquals("bad collect position", iae.getMessage());
+ caught = true;
+ }
+ assertTrue(caught);
+ }
+
+ @Test
+ public static void testAsCollectorExample() throws Throwable {
+ // test the JavaDoc asCollector-with-pos example
+ StringWriter swr = new StringWriter();
+ MethodHandle swWrite = LOOKUP.
+ findVirtual(StringWriter.class, "write", methodType(void.class, char[].class, int.class, int.class)).
+ bindTo(swr);
+ MethodHandle swWrite4 = swWrite.asCollector(0, char[].class, 4);
+ swWrite4.invoke('A', 'B', 'C', 'D', 1, 2);
+ assertEquals("BC", swr.toString());
+ swWrite4.invoke('P', 'Q', 'R', 'S', 0, 4);
+ assertEquals("BCPQRS", swr.toString());
+ swWrite4.invoke('W', 'X', 'Y', 'Z', 3, 1);
+ assertEquals("BCPQRSZ", swr.toString());
+ }
+
+ static class SpreadCollect {
+
+ static String forSpreading(String s1, int i1, int i2, int i3, String s2) {
+ return s1 + i1 + i2 + i3 + s2;
+ }
+
+ static String forCollecting(String s1, int[] is, String s2) {
+ StringBuilder sb = new StringBuilder(s1);
+ for (int i : is) {
+ sb.append(i);
+ }
+ return sb.append(s2).toString();
+ }
+
+ static String forCollectingLeading(int[] is, String s) {
+ return forCollecting("", is, s);
+ }
+
+ static final Class<SpreadCollect> SPREAD_COLLECT = SpreadCollect.class;
+
+ static final MethodType MT_forSpreading = methodType(String.class, String.class, int.class, int.class, int.class, String.class);
+ static final MethodType MT_forCollecting = methodType(String.class, String.class, int[].class, String.class);
+ static final MethodType MT_forCollectingLeading = methodType(String.class, int[].class, String.class);
+
+ static final MethodHandle MH_forSpreading;
+ static final MethodHandle MH_forCollecting;
+ static final MethodHandle MH_forCollectingLeading;
+
+ static final MethodType MT_spreader = methodType(String.class, String.class, int[].class, String.class);
+ static final MethodType MT_collector0 = methodType(String.class, String.class, String.class);
+ static final MethodType MT_collector1 = methodType(String.class, String.class, int.class, String.class);
+ static final MethodType MT_collector2 = methodType(String.class, String.class, int.class, int.class, String.class);
+ static final MethodType MT_collector3 = methodType(String.class, String.class, int.class, int.class, int.class, String.class);
+ static final MethodType MT_collectorLeading1 = methodType(String.class, int.class, String.class);
+ static final MethodType MT_collectorLeading2 = methodType(String.class, int.class, int.class, String.class);
+ static final MethodType MT_collectorLeading3 = methodType(String.class, int.class, int.class, int.class, String.class);
+
+ static final String NONE_ERROR = "zero array length in MethodHandle.asCollector";
+
+ static {
+ try {
+ MH_forSpreading = LOOKUP.findStatic(SPREAD_COLLECT, "forSpreading", MT_forSpreading);
+ MH_forCollecting = LOOKUP.findStatic(SPREAD_COLLECT, "forCollecting", MT_forCollecting);
+ MH_forCollectingLeading = LOOKUP.findStatic(SPREAD_COLLECT, "forCollectingLeading", MT_forCollectingLeading);
+ } catch (Exception e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+ }
+
+}
--- a/jdk/test/java/lang/invoke/T8139885.java Wed Mar 09 14:54:18 2016 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1111 +0,0 @@
-/*
- * Copyright (c) 2015, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/* @test
- * @bug 8139885
- * @bug 8143798
- * @bug 8150825
- * @run testng/othervm -ea -esa test.java.lang.invoke.T8139885
- */
-
-package test.java.lang.invoke;
-
-import java.io.StringWriter;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodHandles.Lookup;
-import java.lang.invoke.MethodType;
-import java.lang.invoke.WrongMethodTypeException;
-import java.util.*;
-
-import static java.lang.invoke.MethodType.methodType;
-
-import static org.testng.AssertJUnit.*;
-
-import org.testng.annotations.*;
-
-/**
- * Example-scale and negative tests for JEP 274 extensions.
- */
-public class T8139885 {
-
- static final Lookup LOOKUP = MethodHandles.lookup();
-
- //
- // Tests.
- //
-
- @Test
- public static void testLoopFac() throws Throwable {
- MethodHandle[] counterClause = new MethodHandle[]{Fac.MH_zero, Fac.MH_inc};
- MethodHandle[] accumulatorClause = new MethodHandle[]{Fac.MH_one, Fac.MH_mult, Fac.MH_pred, Fac.MH_fin};
- MethodHandle loop = MethodHandles.loop(counterClause, accumulatorClause);
- assertEquals(Fac.MT_fac, loop.type());
- assertEquals(120, loop.invoke(5));
- }
-
- @Test
- public static void testLoopFacNullInit() throws Throwable {
- // null initializer for counter, should initialize to 0
- MethodHandle[] counterClause = new MethodHandle[]{null, Fac.MH_inc};
- MethodHandle[] accumulatorClause = new MethodHandle[]{Fac.MH_one, Fac.MH_mult, Fac.MH_pred, Fac.MH_fin};
- MethodHandle loop = MethodHandles.loop(counterClause, accumulatorClause);
- assertEquals(Fac.MT_fac, loop.type());
- assertEquals(120, loop.invoke(5));
- }
-
- @Test
- public static void testLoopVoid1() throws Throwable {
- // construct a post-checked loop that only does one iteration and has a void body and void local state
- MethodHandle loop = MethodHandles.loop(new MethodHandle[]{Empty.MH_f, Empty.MH_f, Empty.MH_pred, null});
- assertEquals(MethodType.methodType(void.class), loop.type());
- loop.invoke();
- }
-
- @Test
- public static void testLoopVoid2() throws Throwable {
- // construct a post-checked loop that only does one iteration and has a void body and void local state,
- // initialized implicitly from the step type
- MethodHandle loop = MethodHandles.loop(new MethodHandle[]{null, Empty.MH_f, Empty.MH_pred, null});
- assertEquals(MethodType.methodType(void.class), loop.type());
- loop.invoke();
- }
-
- @Test
- public static void testLoopFacWithVoidState() throws Throwable {
- // like testLoopFac, but with additional void state that outputs a dot
- MethodHandle[] counterClause = new MethodHandle[]{Fac.MH_zero, Fac.MH_inc};
- MethodHandle[] accumulatorClause = new MethodHandle[]{Fac.MH_one, Fac.MH_mult, Fac.MH_pred, Fac.MH_fin};
- MethodHandle[] dotClause = new MethodHandle[]{null, Fac.MH_dot};
- MethodHandle loop = MethodHandles.loop(counterClause, accumulatorClause, dotClause);
- assertEquals(Fac.MT_fac, loop.type());
- assertEquals(120, loop.invoke(5));
- }
-
- @Test
- public static void testLoopNegative() throws Throwable {
- MethodHandle mh_loop =
- LOOKUP.findStatic(MethodHandles.class, "loop", methodType(MethodHandle.class, MethodHandle[][].class));
- MethodHandle i0 = MethodHandles.constant(int.class, 0);
- MethodHandle ii = MethodHandles.dropArguments(i0, 0, int.class, int.class);
- MethodHandle id = MethodHandles.dropArguments(i0, 0, int.class, double.class);
- MethodHandle i3 = MethodHandles.dropArguments(i0, 0, int.class, int.class, int.class);
- List<MethodHandle> inits = Arrays.asList(ii, id, i3);
- List<Class<?>> ints = Arrays.asList(int.class, int.class, int.class);
- List<MethodHandle> finis = Arrays.asList(Fac.MH_fin, Fac.MH_inc, Counted.MH_step);
- List<MethodHandle> preds1 = Arrays.asList(null, null, null);
- List<MethodHandle> preds2 = Arrays.asList(null, Fac.MH_fin, null);
- MethodHandle eek = MethodHandles.dropArguments(i0, 0, int.class, int.class, double.class);
- List<MethodHandle> nesteps = Arrays.asList(Fac.MH_inc, eek, Fac.MH_dot);
- List<MethodHandle> nepreds = Arrays.asList(null, Fac.MH_pred, null);
- List<MethodHandle> nefinis = Arrays.asList(null, Fac.MH_fin, null);
- MethodHandle[][][] cases = {
- null,
- {},
- {{null, Fac.MH_inc}, {Fac.MH_one, null, Fac.MH_mult, Fac.MH_pred, Fac.MH_fin}},
- {{null, Fac.MH_inc}, null},
- {{Fac.MH_zero, Fac.MH_dot}},
- {{ii}, {id}, {i3}},
- {{null, Fac.MH_inc, null, Fac.MH_fin}, {null, Fac.MH_inc, null, Fac.MH_inc},
- {null, Counted.MH_start, null, Counted.MH_step}},
- {{Fac.MH_zero, Fac.MH_inc}, {Fac.MH_one, Fac.MH_mult, null, Fac.MH_fin}, {null, Fac.MH_dot}},
- {{Fac.MH_zero, Fac.MH_inc}, {Fac.MH_one, Fac.MH_mult, Fac.MH_fin, Fac.MH_fin}, {null, Fac.MH_dot}},
- {{Fac.MH_zero, Fac.MH_inc}, {Fac.MH_one, eek, Fac.MH_pred, Fac.MH_fin}, {null, Fac.MH_dot}}
- };
- String[] messages = {
- "null or no clauses passed",
- "null or no clauses passed",
- "All loop clauses must be represented as MethodHandle arrays with at most 4 elements.",
- "null clauses are not allowed",
- "clause 0: init and step return types must match: int != void",
- "found non-effectively identical init parameter type lists: " + inits + " (common suffix: " + ints + ")",
- "found non-identical finalizer return types: " + finis + " (return type: int)",
- "no predicate found: " + preds1,
- "predicates must have boolean return type: " + preds2,
- "found non-effectively identical parameter type lists:\nstep: " + nesteps + "\npred: " + nepreds +
- "\nfini: " + nefinis + " (common parameter sequence: " + ints + ")"
- };
- for (int i = 0; i < cases.length; ++i) {
- boolean caught = false;
- try {
- mh_loop.invokeWithArguments(cases[i]);
- } catch (IllegalArgumentException iae) {
- assertEquals(messages[i], iae.getMessage());
- caught = true;
- }
- assertTrue(caught);
- }
- }
-
- @Test
- public static void testWhileLoop() throws Throwable {
- // int i = 0; while (i < limit) { ++i; } return i; => limit
- MethodHandle loop = MethodHandles.whileLoop(While.MH_zero, While.MH_pred, While.MH_step);
- assertEquals(While.MT_while, loop.type());
- assertEquals(23, loop.invoke(23));
- }
-
- @Test
- public static void testWhileLoopNoIteration() throws Throwable {
- // a while loop that never executes its body because the predicate evaluates to false immediately
- MethodHandle loop = MethodHandles.whileLoop(While.MH_initString, While.MH_predString, While.MH_stepString);
- assertEquals(While.MT_string, loop.type());
- assertEquals("a", loop.invoke());
- }
-
- @Test
- public static void testDoWhileLoop() throws Throwable {
- // int i = 0; do { ++i; } while (i < limit); return i; => limit
- MethodHandle loop = MethodHandles.doWhileLoop(While.MH_zero, While.MH_step, While.MH_pred);
- assertEquals(While.MT_while, loop.type());
- assertEquals(23, loop.invoke(23));
- }
-
- @Test
- public static void testWhileZip() throws Throwable {
- MethodHandle loop = MethodHandles.doWhileLoop(While.MH_zipInitZip, While.MH_zipStep, While.MH_zipPred);
- assertEquals(While.MT_zip, loop.type());
- List<String> a = Arrays.asList("a", "b", "c", "d");
- List<String> b = Arrays.asList("e", "f", "g", "h");
- List<String> zipped = Arrays.asList("a", "e", "b", "f", "c", "g", "d", "h");
- assertEquals(zipped, (List<String>) loop.invoke(a.iterator(), b.iterator()));
- }
-
- @Test
- public static void testCountedLoop() throws Throwable {
- // String s = "Lambdaman!"; for (int i = 0; i < 13; ++i) { s = "na " + s; } return s; => a variation on a well known theme
- MethodHandle fit13 = MethodHandles.constant(int.class, 13);
- MethodHandle loop = MethodHandles.countedLoop(fit13, Counted.MH_start, Counted.MH_step);
- assertEquals(Counted.MT_counted, loop.type());
- assertEquals("na na na na na na na na na na na na na Lambdaman!", loop.invoke("Lambdaman!"));
- }
-
- @Test
- public static void testCountedArrayLoop() throws Throwable {
- // int[] a = new int[]{0}; for (int i = 0; i < 13; ++i) { ++a[0]; } => a[0] == 13
- MethodHandle fit13 = MethodHandles.dropArguments(MethodHandles.constant(int.class, 13), 0, int[].class);
- MethodHandle loop = MethodHandles.countedLoop(fit13, null, Counted.MH_stepUpdateArray);
- assertEquals(Counted.MT_arrayCounted, loop.type());
- int[] a = new int[]{0};
- loop.invoke(a);
- assertEquals(13, a[0]);
- }
-
- @Test
- public static void testCountedPrintingLoop() throws Throwable {
- MethodHandle fit5 = MethodHandles.constant(int.class, 5);
- MethodHandle loop = MethodHandles.countedLoop(fit5, null, Counted.MH_printHello);
- assertEquals(Counted.MT_countedPrinting, loop.type());
- loop.invoke();
- }
-
- @Test
- public static void testCountedRangeLoop() throws Throwable {
- // String s = "Lambdaman!"; for (int i = -5; i < 8; ++i) { s = "na " + s; } return s; => a well known theme
- MethodHandle fitm5 = MethodHandles.dropArguments(Counted.MH_m5, 0, String.class);
- MethodHandle fit8 = MethodHandles.dropArguments(Counted.MH_8, 0, String.class);
- MethodHandle loop = MethodHandles.countedLoop(fitm5, fit8, Counted.MH_start, Counted.MH_step);
- assertEquals(Counted.MT_counted, loop.type());
- assertEquals("na na na na na na na na na na na na na Lambdaman!", loop.invoke("Lambdaman!"));
- }
-
- @Test
- public static void testIterateSum() throws Throwable {
- // Integer[] a = new Integer[]{1,2,3,4,5,6}; int sum = 0; for (int e : a) { sum += e; } return sum; => 21
- MethodHandle loop = MethodHandles.iteratedLoop(Iterate.MH_sumIterator, Iterate.MH_sumInit, Iterate.MH_sumStep);
- assertEquals(Iterate.MT_sum, loop.type());
- assertEquals(21, loop.invoke(new Integer[]{1, 2, 3, 4, 5, 6}));
- }
-
- @Test
- public static void testIterateReverse() throws Throwable {
- MethodHandle loop = MethodHandles.iteratedLoop(null, Iterate.MH_reverseInit, Iterate.MH_reverseStep);
- assertEquals(Iterate.MT_reverse, loop.type());
- List<String> list = Arrays.asList("a", "b", "c", "d", "e");
- List<String> reversedList = Arrays.asList("e", "d", "c", "b", "a");
- assertEquals(reversedList, (List<String>) loop.invoke(list));
- }
-
- @Test
- public static void testIterateLength() throws Throwable {
- MethodHandle loop = MethodHandles.iteratedLoop(null, Iterate.MH_lengthInit, Iterate.MH_lengthStep);
- assertEquals(Iterate.MT_length, loop.type());
- List<Double> list = Arrays.asList(23.0, 148.0, 42.0);
- assertEquals(list.size(), (int) loop.invoke(list));
- }
-
- @Test
- public static void testIterateMap() throws Throwable {
- MethodHandle loop = MethodHandles.iteratedLoop(null, Iterate.MH_mapInit, Iterate.MH_mapStep);
- assertEquals(Iterate.MT_map, loop.type());
- List<String> list = Arrays.asList("Hello", "world", "!");
- List<String> upList = Arrays.asList("HELLO", "WORLD", "!");
- assertEquals(upList, (List<String>) loop.invoke(list));
- }
-
- @Test
- public static void testIteratePrint() throws Throwable {
- MethodHandle loop = MethodHandles.iteratedLoop(null, null, Iterate.MH_printStep);
- assertEquals(Iterate.MT_print, loop.type());
- loop.invoke(Arrays.asList("hello", "world"));
- }
-
- @Test
- public static void testIterateNullBody() {
- boolean caught = false;
- try {
- MethodHandles.iteratedLoop(MethodHandles.identity(int.class), MethodHandles.identity(int.class), null);
- } catch (IllegalArgumentException iae) {
- assertEquals("iterated loop body must not be null", iae.getMessage());
- caught = true;
- }
- assertTrue(caught);
- }
-
- @Test
- public static void testTryFinally() throws Throwable {
- MethodHandle hello = MethodHandles.tryFinally(TryFinally.MH_greet, TryFinally.MH_exclaim);
- assertEquals(TryFinally.MT_hello, hello.type());
- assertEquals("Hello, world!", hello.invoke("world"));
- }
-
- @Test
- public static void testTryFinallyVoid() throws Throwable {
- MethodHandle tfVoid = MethodHandles.tryFinally(TryFinally.MH_print, TryFinally.MH_printMore);
- assertEquals(TryFinally.MT_printHello, tfVoid.type());
- tfVoid.invoke("world");
- }
-
- @Test
- public static void testTryFinallySublist() throws Throwable {
- MethodHandle helloMore = MethodHandles.tryFinally(TryFinally.MH_greetMore, TryFinally.MH_exclaimMore);
- assertEquals(TryFinally.MT_moreHello, helloMore.type());
- assertEquals("Hello, world and universe (but world first)!", helloMore.invoke("world", "universe"));
- }
-
- @Test
- public static void testTryFinallyNegative() {
- MethodHandle intid = MethodHandles.identity(int.class);
- MethodHandle intco = MethodHandles.constant(int.class, 0);
- MethodHandle errTarget = MethodHandles.dropArguments(intco, 0, int.class, double.class, String.class, int.class);
- MethodHandle errCleanup = MethodHandles.dropArguments(MethodHandles.constant(int.class, 0), 0, Throwable.class,
- int.class, double.class, Object.class);
- MethodHandle[][] cases = {
- {intid, MethodHandles.identity(double.class)},
- {intid, MethodHandles.dropArguments(intid, 0, String.class)},
- {intid, MethodHandles.dropArguments(intid, 0, Throwable.class, double.class)},
- {errTarget, errCleanup},
- {TryFinally.MH_voidTarget, TryFinally.MH_voidCleanup}
- };
- String[] messages = {
- "target and return types must match: double != int",
- "cleanup first argument and Throwable must match: (String,int)int != class java.lang.Throwable",
- "cleanup second argument and target return type must match: (Throwable,double,int)int != int",
- "cleanup parameters after (Throwable,result) and target parameter list prefix must match: " +
- errCleanup.type() + " != " + errTarget.type(),
- "cleanup parameters after (Throwable,result) and target parameter list prefix must match: " +
- TryFinally.MH_voidCleanup.type() + " != " + TryFinally.MH_voidTarget.type()
- };
- for (int i = 0; i < cases.length; ++i) {
- boolean caught = false;
- try {
- MethodHandles.tryFinally(cases[i][0], cases[i][1]);
- } catch (IllegalArgumentException iae) {
- assertEquals(messages[i], iae.getMessage());
- caught = true;
- }
- assertTrue(caught);
- }
- }
-
- @Test
- public static void testFold0a() throws Throwable {
- // equivalence to foldArguments(MethodHandle,MethodHandle)
- MethodHandle fold = MethodHandles.foldArguments(Fold.MH_multer, 0, Fold.MH_adder);
- assertEquals(Fold.MT_folded1, fold.type());
- assertEquals(720, (int) fold.invoke(3, 4, 5));
- }
-
- @Test
- public static void testFold1a() throws Throwable {
- // test foldArguments for folding position 1
- MethodHandle fold = MethodHandles.foldArguments(Fold.MH_multer, 1, Fold.MH_adder1);
- assertEquals(Fold.MT_folded1, fold.type());
- assertEquals(540, (int) fold.invoke(3, 4, 5));
- }
-
- @Test
- public static void testFold0b() throws Throwable {
- // test foldArguments equivalence with multiple types
- MethodHandle fold = MethodHandles.foldArguments(Fold.MH_str, 0, Fold.MH_comb);
- assertEquals(Fold.MT_folded2, fold.type());
- assertEquals(23, (int) fold.invoke("true", true, 23));
- }
-
- @Test
- public static void testFold1b() throws Throwable {
- // test folgArguments for folding position 1, with multiple types
- MethodHandle fold = MethodHandles.foldArguments(Fold.MH_str, 1, Fold.MH_comb2);
- assertEquals(Fold.MT_folded3, fold.type());
- assertEquals(1, (int) fold.invoke(true, true, 1));
- assertEquals(-1, (int) fold.invoke(true, false, -1));
- }
-
- @Test
- public static void testFoldArgumentsExample() throws Throwable {
- // test the JavaDoc foldArguments-with-pos example
- StringWriter swr = new StringWriter();
- MethodHandle trace = LOOKUP.findVirtual(StringWriter.class, "write", methodType(void.class, String.class)).bindTo(swr);
- MethodHandle cat = LOOKUP.findVirtual(String.class, "concat", methodType(String.class, String.class));
- assertEquals("boojum", (String) cat.invokeExact("boo", "jum"));
- MethodHandle catTrace = MethodHandles.foldArguments(cat, 1, trace);
- assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
- assertEquals("jum", swr.toString());
- }
-
- @Test
- public static void testAsSpreader() throws Throwable {
- MethodHandle spreader = SpreadCollect.MH_forSpreading.asSpreader(1, int[].class, 3);
- assertEquals(SpreadCollect.MT_spreader, spreader.type());
- assertEquals("A456B", (String) spreader.invoke("A", new int[]{4, 5, 6}, "B"));
- }
-
- @Test
- public static void testAsSpreaderExample() throws Throwable {
- // test the JavaDoc asSpreader-with-pos example
- MethodHandle compare = LOOKUP.findStatic(Objects.class, "compare", methodType(int.class, Object.class, Object.class, Comparator.class));
- MethodHandle compare2FromArray = compare.asSpreader(0, Object[].class, 2);
- Object[] ints = new Object[]{3, 9, 7, 7};
- Comparator<Integer> cmp = (a, b) -> a - b;
- assertTrue((int) compare2FromArray.invoke(Arrays.copyOfRange(ints, 0, 2), cmp) < 0);
- assertTrue((int) compare2FromArray.invoke(Arrays.copyOfRange(ints, 1, 3), cmp) > 0);
- assertTrue((int) compare2FromArray.invoke(Arrays.copyOfRange(ints, 2, 4), cmp) == 0);
- }
-
- @Test
- public static void testAsSpreaderIllegalPos() throws Throwable {
- int[] illegalPos = {-7, 3, 19};
- int caught = 0;
- for (int p : illegalPos) {
- try {
- SpreadCollect.MH_forSpreading.asSpreader(p, Object[].class, 3);
- } catch (IllegalArgumentException iae) {
- assertEquals("bad spread position", iae.getMessage());
- ++caught;
- }
- }
- assertEquals(illegalPos.length, caught);
- }
-
- @Test
- public static void testAsSpreaderIllegalMethodType() throws Throwable {
- MethodHandle h = MethodHandles.dropArguments(MethodHandles.constant(String.class, ""), 0, int.class, int.class);
- boolean caught = false;
- try {
- MethodHandle s = h.asSpreader(String[].class, 1);
- } catch (WrongMethodTypeException wmte) {
- caught = true;
- }
- assertTrue(caught);
- }
-
- @Test
- public static void testAsCollector() throws Throwable {
- MethodHandle collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 1);
- assertEquals(SpreadCollect.MT_collector1, collector.type());
- assertEquals("A4B", (String) collector.invoke("A", 4, "B"));
- collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 2);
- assertEquals(SpreadCollect.MT_collector2, collector.type());
- assertEquals("A45B", (String) collector.invoke("A", 4, 5, "B"));
- collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 3);
- assertEquals(SpreadCollect.MT_collector3, collector.type());
- assertEquals("A456B", (String) collector.invoke("A", 4, 5, 6, "B"));
- }
-
- @Test
- public static void testAsCollectorInvokeWithArguments() throws Throwable {
- MethodHandle collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 1);
- assertEquals(SpreadCollect.MT_collector1, collector.type());
- assertEquals("A4B", (String) collector.invokeWithArguments("A", 4, "B"));
- collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 2);
- assertEquals(SpreadCollect.MT_collector2, collector.type());
- assertEquals("A45B", (String) collector.invokeWithArguments("A", 4, 5, "B"));
- collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 3);
- assertEquals(SpreadCollect.MT_collector3, collector.type());
- assertEquals("A456B", (String) collector.invokeWithArguments("A", 4, 5, 6, "B"));
- }
-
- @Test
- public static void testAsCollectorLeading() throws Throwable {
- MethodHandle collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 1);
- assertEquals(SpreadCollect.MT_collectorLeading1, collector.type());
- assertEquals("7Q", (String) collector.invoke(7, "Q"));
- collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 2);
- assertEquals(SpreadCollect.MT_collectorLeading2, collector.type());
- assertEquals("78Q", (String) collector.invoke(7, 8, "Q"));
- collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 3);
- assertEquals(SpreadCollect.MT_collectorLeading3, collector.type());
- assertEquals("789Q", (String) collector.invoke(7, 8, 9, "Q"));
- }
-
- @Test
- public static void testAsCollectorLeadingInvokeWithArguments() throws Throwable {
- MethodHandle collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 1);
- assertEquals(SpreadCollect.MT_collectorLeading1, collector.type());
- assertEquals("7Q", (String) collector.invokeWithArguments(7, "Q"));
- collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 2);
- assertEquals(SpreadCollect.MT_collectorLeading2, collector.type());
- assertEquals("78Q", (String) collector.invokeWithArguments(7, 8, "Q"));
- collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 3);
- assertEquals(SpreadCollect.MT_collectorLeading3, collector.type());
- assertEquals("789Q", (String) collector.invokeWithArguments(7, 8, 9, "Q"));
- }
-
- @Test
- public static void testAsCollectorNone() throws Throwable {
- MethodHandle collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 0);
- assertEquals(SpreadCollect.MT_collector0, collector.type());
- assertEquals("AB", (String) collector.invoke("A", "B"));
- }
-
- @Test
- public static void testAsCollectorIllegalPos() throws Throwable {
- int[] illegalPos = {-1, 17};
- int caught = 0;
- for (int p : illegalPos) {
- try {
- SpreadCollect.MH_forCollecting.asCollector(p, int[].class, 0);
- } catch (IllegalArgumentException iae) {
- assertEquals("bad collect position", iae.getMessage());
- ++caught;
- }
- }
- assertEquals(illegalPos.length, caught);
- }
-
- @Test
- public static void testAsCollectorExample() throws Throwable {
- // test the JavaDoc asCollector-with-pos example
- StringWriter swr = new StringWriter();
- MethodHandle swWrite = LOOKUP.
- findVirtual(StringWriter.class, "write", methodType(void.class, char[].class, int.class, int.class)).
- bindTo(swr);
- MethodHandle swWrite4 = swWrite.asCollector(0, char[].class, 4);
- swWrite4.invoke('A', 'B', 'C', 'D', 1, 2);
- assertEquals("BC", swr.toString());
- swWrite4.invoke('P', 'Q', 'R', 'S', 0, 4);
- assertEquals("BCPQRS", swr.toString());
- swWrite4.invoke('W', 'X', 'Y', 'Z', 3, 1);
- assertEquals("BCPQRSZ", swr.toString());
- }
-
- @Test
- public static void testFindSpecial() throws Throwable {
- FindSpecial.C c = new FindSpecial.C();
- assertEquals("I1.m", c.m());
- MethodType t = MethodType.methodType(String.class);
- MethodHandle ci1m = LOOKUP.findSpecial(FindSpecial.I1.class, "m", t, FindSpecial.C.class);
- assertEquals("I1.m", (String) ci1m.invoke(c));
- }
-
- @Test
- public static void testFindSpecialAbstract() throws Throwable {
- FindSpecial.C c = new FindSpecial.C();
- assertEquals("q", c.q());
- MethodType t = MethodType.methodType(String.class);
- boolean caught = false;
- try {
- MethodHandle ci3q = LOOKUP.findSpecial(FindSpecial.I3.class, "q", t, FindSpecial.C.class);
- } catch (Throwable thrown) {
- if (!(thrown instanceof IllegalAccessException) || !FindSpecial.ABSTRACT_ERROR.equals(thrown.getMessage())) {
- throw new AssertionError(thrown.getMessage(), thrown);
- }
- caught = true;
- }
- assertTrue(caught);
- }
-
- @Test
- public static void testFindClassCNFE() throws Throwable {
- boolean caught = false;
- try {
- LOOKUP.findClass("does.not.Exist");
- } catch (ClassNotFoundException cnfe) {
- caught = true;
- }
- assertTrue(caught);
- }
-
- //
- // Methods used to assemble tests.
- //
-
- static class Empty {
-
- static void f() { }
-
- static boolean pred() {
- return false;
- }
-
- static final Class<Empty> EMPTY = Empty.class;
-
- static final MethodType MT_f = methodType(void.class);
- static final MethodType MT_pred = methodType(boolean.class);
-
- static final MethodHandle MH_f;
- static final MethodHandle MH_pred;
-
- static {
- try {
- MH_f = LOOKUP.findStatic(EMPTY, "f", MT_f);
- MH_pred = LOOKUP.findStatic(EMPTY, "pred", MT_pred);
- } catch (Exception e) {
- throw new ExceptionInInitializerError(e);
- }
- }
- }
-
- static class Fac {
-
- static int zero(int k) {
- return 0;
- }
-
- static int one(int k) {
- return 1;
- }
-
- static boolean pred(int i, int acc, int k) {
- return i < k;
- }
-
- static int inc(int i, int acc, int k) {
- return i + 1;
- }
-
- static int mult(int i, int acc, int k) {
- return i * acc;
- }
-
- static void dot(int i, int acc, int k) {
- System.out.print('.');
- }
-
- static int fin(int i, int acc, int k) {
- return acc;
- }
-
- static final Class<Fac> FAC = Fac.class;
-
- static final MethodType MT_init = methodType(int.class, int.class);
- static final MethodType MT_fn = methodType(int.class, int.class, int.class, int.class);
- static final MethodType MT_dot = methodType(void.class, int.class, int.class, int.class);
- static final MethodType MT_pred = methodType(boolean.class, int.class, int.class, int.class);
-
- static final MethodHandle MH_zero;
- static final MethodHandle MH_one;
- static final MethodHandle MH_pred;
- static final MethodHandle MH_inc;
- static final MethodHandle MH_mult;
- static final MethodHandle MH_dot;
- static final MethodHandle MH_fin;
-
- static final MethodType MT_fac = methodType(int.class, int.class);
-
- static {
- try {
- MH_zero = LOOKUP.findStatic(FAC, "zero", MT_init);
- MH_one = LOOKUP.findStatic(FAC, "one", MT_init);
- MH_pred = LOOKUP.findStatic(FAC, "pred", MT_pred);
- MH_inc = LOOKUP.findStatic(FAC, "inc", MT_fn);
- MH_mult = LOOKUP.findStatic(FAC, "mult", MT_fn);
- MH_dot = LOOKUP.findStatic(FAC, "dot", MT_dot);
- MH_fin = LOOKUP.findStatic(FAC, "fin", MT_fn);
- } catch (Exception e) {
- throw new ExceptionInInitializerError(e);
- }
- }
-
- }
-
- static class While {
-
- static int zero(int limit) {
- return 0;
- }
-
- static boolean pred(int i, int limit) {
- return i < limit;
- }
-
- static int step(int i, int limit) {
- return i + 1;
- }
-
- static String initString() {
- return "a";
- }
-
- static boolean predString(String s) {
- return s.length() != 1;
- }
-
- static String stepString(String s) {
- return s + "a";
- }
-
- static List<String> zipInitZip(Iterator<String> a, Iterator<String> b) {
- return new ArrayList<>();
- }
-
- static boolean zipPred(List<String> zip, Iterator<String> a, Iterator<String> b) {
- return a.hasNext() && b.hasNext();
- }
-
- static List<String> zipStep(List<String> zip, Iterator<String> a, Iterator<String> b) {
- zip.add(a.next());
- zip.add(b.next());
- return zip;
- }
-
- static final Class<While> WHILE = While.class;
-
- static final MethodType MT_zero = methodType(int.class, int.class);
- static final MethodType MT_pred = methodType(boolean.class, int.class, int.class);
- static final MethodType MT_fn = methodType(int.class, int.class, int.class);
- static final MethodType MT_initString = methodType(String.class);
- static final MethodType MT_predString = methodType(boolean.class, String.class);
- static final MethodType MT_stepString = methodType(String.class, String.class);
- static final MethodType MT_zipInitZip = methodType(List.class, Iterator.class, Iterator.class);
- static final MethodType MT_zipPred = methodType(boolean.class, List.class, Iterator.class, Iterator.class);
- static final MethodType MT_zipStep = methodType(List.class, List.class, Iterator.class, Iterator.class);
-
- static final MethodHandle MH_zero;
- static final MethodHandle MH_pred;
- static final MethodHandle MH_step;
- static final MethodHandle MH_initString;
- static final MethodHandle MH_predString;
- static final MethodHandle MH_stepString;
- static final MethodHandle MH_zipInitZip;
- static final MethodHandle MH_zipPred;
- static final MethodHandle MH_zipStep;
-
- static final MethodType MT_while = methodType(int.class, int.class);
- static final MethodType MT_string = methodType(String.class);
- static final MethodType MT_zip = methodType(List.class, Iterator.class, Iterator.class);
-
- static {
- try {
- MH_zero = LOOKUP.findStatic(WHILE, "zero", MT_zero);
- MH_pred = LOOKUP.findStatic(WHILE, "pred", MT_pred);
- MH_step = LOOKUP.findStatic(WHILE, "step", MT_fn);
- MH_initString = LOOKUP.findStatic(WHILE, "initString", MT_initString);
- MH_predString = LOOKUP.findStatic(WHILE, "predString", MT_predString);
- MH_stepString = LOOKUP.findStatic(WHILE, "stepString", MT_stepString);
- MH_zipInitZip = LOOKUP.findStatic(WHILE, "zipInitZip", MT_zipInitZip);
- MH_zipPred = LOOKUP.findStatic(WHILE, "zipPred", MT_zipPred);
- MH_zipStep = LOOKUP.findStatic(WHILE, "zipStep", MT_zipStep);
- } catch (Exception e) {
- throw new ExceptionInInitializerError(e);
- }
- }
-
- }
-
- static class Counted {
-
- static String start(String arg) {
- return arg;
- }
-
- static String step(int counter, String v, String arg) {
- return "na " + v;
- }
-
- static void stepUpdateArray(int counter, int[] a) {
- ++a[0];
- }
-
- static void printHello(int counter) {
- System.out.print("hello");
- }
-
- static final Class<Counted> COUNTED = Counted.class;
-
- static final MethodType MT_start = methodType(String.class, String.class);
- static final MethodType MT_step = methodType(String.class, int.class, String.class, String.class);
- static final MethodType MT_stepUpdateArray = methodType(void.class, int.class, int[].class);
- static final MethodType MT_printHello = methodType(void.class, int.class);
-
- static final MethodHandle MH_13;
- static final MethodHandle MH_m5;
- static final MethodHandle MH_8;
- static final MethodHandle MH_start;
- static final MethodHandle MH_step;
- static final MethodHandle MH_stepUpdateArray;
- static final MethodHandle MH_printHello;
-
- static final MethodType MT_counted = methodType(String.class, String.class);
- static final MethodType MT_arrayCounted = methodType(void.class, int[].class);
- static final MethodType MT_countedPrinting = methodType(void.class);
-
- static {
- try {
- MH_13 = MethodHandles.constant(int.class, 13);
- MH_m5 = MethodHandles.constant(int.class, -5);
- MH_8 = MethodHandles.constant(int.class, 8);
- MH_start = LOOKUP.findStatic(COUNTED, "start", MT_start);
- MH_step = LOOKUP.findStatic(COUNTED, "step", MT_step);
- MH_stepUpdateArray = LOOKUP.findStatic(COUNTED, "stepUpdateArray", MT_stepUpdateArray);
- MH_printHello = LOOKUP.findStatic(COUNTED, "printHello", MT_printHello);
- } catch (Exception e) {
- throw new ExceptionInInitializerError(e);
- }
- }
-
- }
-
- static class Iterate {
-
- static Iterator<Integer> sumIterator(Integer[] a) {
- return Arrays.asList(a).iterator();
- }
-
- static int sumInit(Integer[] a) {
- return 0;
- }
-
- static int sumStep(int s, int e, Integer[] a) {
- return s + e;
- }
-
- static List<String> reverseInit(List<String> l) {
- return new ArrayList<>();
- }
-
- static List<String> reverseStep(String e, List<String> r, List<String> l) {
- r.add(0, e);
- return r;
- }
-
- static int lengthInit(List<Double> l) {
- return 0;
- }
-
- static int lengthStep(Object o, int len, List<Double> l) {
- return len + 1;
- }
-
- static List<String> mapInit(List<String> l) {
- return new ArrayList<>();
- }
-
- static List<String> mapStep(String e, List<String> r, List<String> l) {
- r.add(e.toUpperCase());
- return r;
- }
-
- static void printStep(String s, List<String> l) {
- System.out.print(s);
- }
-
- static final Class<Iterate> ITERATE = Iterate.class;
-
- static final MethodType MT_sumIterator = methodType(Iterator.class, Integer[].class);
-
- static final MethodType MT_sumInit = methodType(int.class, Integer[].class);
- static final MethodType MT_reverseInit = methodType(List.class, List.class);
- static final MethodType MT_lenghInit = methodType(int.class, List.class);
- static final MethodType MT_mapInit = methodType(List.class, List.class);
-
- static final MethodType MT_sumStep = methodType(int.class, int.class, int.class, Integer[].class);
- static final MethodType MT_reverseStep = methodType(List.class, String.class, List.class, List.class);
- static final MethodType MT_lengthStep = methodType(int.class, Object.class, int.class, List.class);
- static final MethodType MT_mapStep = methodType(List.class, String.class, List.class, List.class);
- static final MethodType MT_printStep = methodType(void.class, String.class, List.class);
-
- static final MethodHandle MH_sumIterator;
- static final MethodHandle MH_sumInit;
- static final MethodHandle MH_sumStep;
- static final MethodHandle MH_printStep;
-
- static final MethodHandle MH_reverseInit;
- static final MethodHandle MH_reverseStep;
-
- static final MethodHandle MH_lengthInit;
- static final MethodHandle MH_lengthStep;
-
- static final MethodHandle MH_mapInit;
- static final MethodHandle MH_mapStep;
-
- static final MethodType MT_sum = methodType(int.class, Integer[].class);
- static final MethodType MT_reverse = methodType(List.class, List.class);
- static final MethodType MT_length = methodType(int.class, List.class);
- static final MethodType MT_map = methodType(List.class, List.class);
- static final MethodType MT_print = methodType(void.class, List.class);
-
- static {
- try {
- MH_sumIterator = LOOKUP.findStatic(ITERATE, "sumIterator", MT_sumIterator);
- MH_sumInit = LOOKUP.findStatic(ITERATE, "sumInit", MT_sumInit);
- MH_sumStep = LOOKUP.findStatic(ITERATE, "sumStep", MT_sumStep);
- MH_reverseInit = LOOKUP.findStatic(ITERATE, "reverseInit", MT_reverseInit);
- MH_reverseStep = LOOKUP.findStatic(ITERATE, "reverseStep", MT_reverseStep);
- MH_lengthInit = LOOKUP.findStatic(ITERATE, "lengthInit", MT_lenghInit);
- MH_lengthStep = LOOKUP.findStatic(ITERATE, "lengthStep", MT_lengthStep);
- MH_mapInit = LOOKUP.findStatic(ITERATE, "mapInit", MT_mapInit);
- MH_mapStep = LOOKUP.findStatic(ITERATE, "mapStep", MT_mapStep);
- MH_printStep = LOOKUP.findStatic(ITERATE, "printStep", MT_printStep);
- } catch (Exception e) {
- throw new ExceptionInInitializerError(e);
- }
- }
-
- }
-
- static class TryFinally {
-
- static String greet(String whom) {
- return "Hello, " + whom;
- }
-
- static String exclaim(Throwable t, String r, String whom) {
- return r + "!";
- }
-
- static void print(String what) {
- System.out.print("Hello, " + what);
- }
-
- static void printMore(Throwable t, String what) {
- System.out.println("!");
- }
-
- static String greetMore(String first, String second) {
- return "Hello, " + first + " and " + second;
- }
-
- static String exclaimMore(Throwable t, String r, String first) {
- return r + " (but " + first + " first)!";
- }
-
- static void voidTarget() {}
-
- static void voidCleanup(Throwable t, int a) {}
-
- static final Class<TryFinally> TRY_FINALLY = TryFinally.class;
-
- static final MethodType MT_greet = methodType(String.class, String.class);
- static final MethodType MT_exclaim = methodType(String.class, Throwable.class, String.class, String.class);
- static final MethodType MT_print = methodType(void.class, String.class);
- static final MethodType MT_printMore = methodType(void.class, Throwable.class, String.class);
- static final MethodType MT_greetMore = methodType(String.class, String.class, String.class);
- static final MethodType MT_exclaimMore = methodType(String.class, Throwable.class, String.class, String.class);
- static final MethodType MT_voidTarget = methodType(void.class);
- static final MethodType MT_voidCleanup = methodType(void.class, Throwable.class, int.class);
-
- static final MethodHandle MH_greet;
- static final MethodHandle MH_exclaim;
- static final MethodHandle MH_print;
- static final MethodHandle MH_printMore;
- static final MethodHandle MH_greetMore;
- static final MethodHandle MH_exclaimMore;
- static final MethodHandle MH_voidTarget;
- static final MethodHandle MH_voidCleanup;
-
- static final MethodType MT_hello = methodType(String.class, String.class);
- static final MethodType MT_printHello = methodType(void.class, String.class);
- static final MethodType MT_moreHello = methodType(String.class, String.class, String.class);
-
- static {
- try {
- MH_greet = LOOKUP.findStatic(TRY_FINALLY, "greet", MT_greet);
- MH_exclaim = LOOKUP.findStatic(TRY_FINALLY, "exclaim", MT_exclaim);
- MH_print = LOOKUP.findStatic(TRY_FINALLY, "print", MT_print);
- MH_printMore = LOOKUP.findStatic(TRY_FINALLY, "printMore", MT_printMore);
- MH_greetMore = LOOKUP.findStatic(TRY_FINALLY, "greetMore", MT_greetMore);
- MH_exclaimMore = LOOKUP.findStatic(TRY_FINALLY, "exclaimMore", MT_exclaimMore);
- MH_voidTarget = LOOKUP.findStatic(TRY_FINALLY, "voidTarget", MT_voidTarget);
- MH_voidCleanup = LOOKUP.findStatic(TRY_FINALLY, "voidCleanup", MT_voidCleanup);
- } catch (Exception e) {
- throw new ExceptionInInitializerError(e);
- }
- }
-
- }
-
- static class Fold {
-
- static int adder(int a, int b, int c) {
- return a + b + c;
- }
-
- static int adder1(int a, int b) {
- return a + b;
- }
-
- static int multer(int x, int q, int r, int s) {
- return x * q * r * s;
- }
-
- static int str(boolean b1, String s, boolean b2, int x) {
- return b1 && s.equals(String.valueOf(b2)) ? x : -x;
- }
-
- static boolean comb(String s, boolean b2) {
- return !s.equals(b2);
- }
-
- static String comb2(boolean b2, int x) {
- int ib = b2 ? 1 : 0;
- return ib == x ? "true" : "false";
- }
-
- static final Class<Fold> FOLD = Fold.class;
-
- static final MethodType MT_adder = methodType(int.class, int.class, int.class, int.class);
- static final MethodType MT_adder1 = methodType(int.class, int.class, int.class);
- static final MethodType MT_multer = methodType(int.class, int.class, int.class, int.class, int.class);
- static final MethodType MT_str = methodType(int.class, boolean.class, String.class, boolean.class, int.class);
- static final MethodType MT_comb = methodType(boolean.class, String.class, boolean.class);
- static final MethodType MT_comb2 = methodType(String.class, boolean.class, int.class);
-
- static final MethodHandle MH_adder;
- static final MethodHandle MH_adder1;
- static final MethodHandle MH_multer;
- static final MethodHandle MH_str;
- static final MethodHandle MH_comb;
- static final MethodHandle MH_comb2;
-
- static final MethodType MT_folded1 = methodType(int.class, int.class, int.class, int.class);
- static final MethodType MT_folded2 = methodType(int.class, String.class, boolean.class, int.class);
- static final MethodType MT_folded3 = methodType(int.class, boolean.class, boolean.class, int.class);
-
- static {
- try {
- MH_adder = LOOKUP.findStatic(FOLD, "adder", MT_adder);
- MH_adder1 = LOOKUP.findStatic(FOLD, "adder1", MT_adder1);
- MH_multer = LOOKUP.findStatic(FOLD, "multer", MT_multer);
- MH_str = LOOKUP.findStatic(FOLD, "str", MT_str);
- MH_comb = LOOKUP.findStatic(FOLD, "comb", MT_comb);
- MH_comb2 = LOOKUP.findStatic(FOLD, "comb2", MT_comb2);
- } catch (Exception e) {
- throw new ExceptionInInitializerError(e);
- }
- }
- }
-
- static class SpreadCollect {
-
- static String forSpreading(String s1, int i1, int i2, int i3, String s2) {
- return s1 + i1 + i2 + i3 + s2;
- }
-
- static String forCollecting(String s1, int[] is, String s2) {
- StringBuilder sb = new StringBuilder(s1);
- for (int i : is) {
- sb.append(i);
- }
- return sb.append(s2).toString();
- }
-
- static String forCollectingLeading(int[] is, String s) {
- return forCollecting("", is, s);
- }
-
- static final Class<SpreadCollect> SPREAD_COLLECT = SpreadCollect.class;
-
- static final MethodType MT_forSpreading = methodType(String.class, String.class, int.class, int.class, int.class, String.class);
- static final MethodType MT_forCollecting = methodType(String.class, String.class, int[].class, String.class);
- static final MethodType MT_forCollectingLeading = methodType(String.class, int[].class, String.class);
-
- static final MethodHandle MH_forSpreading;
- static final MethodHandle MH_forCollecting;
- static final MethodHandle MH_forCollectingLeading;
-
- static final MethodType MT_spreader = methodType(String.class, String.class, int[].class, String.class);
- static final MethodType MT_collector0 = methodType(String.class, String.class, String.class);
- static final MethodType MT_collector1 = methodType(String.class, String.class, int.class, String.class);
- static final MethodType MT_collector2 = methodType(String.class, String.class, int.class, int.class, String.class);
- static final MethodType MT_collector3 = methodType(String.class, String.class, int.class, int.class, int.class, String.class);
- static final MethodType MT_collectorLeading1 = methodType(String.class, int.class, String.class);
- static final MethodType MT_collectorLeading2 = methodType(String.class, int.class, int.class, String.class);
- static final MethodType MT_collectorLeading3 = methodType(String.class, int.class, int.class, int.class, String.class);
-
- static final String NONE_ERROR = "zero array length in MethodHandle.asCollector";
-
- static {
- try {
- MH_forSpreading = LOOKUP.findStatic(SPREAD_COLLECT, "forSpreading", MT_forSpreading);
- MH_forCollecting = LOOKUP.findStatic(SPREAD_COLLECT, "forCollecting", MT_forCollecting);
- MH_forCollectingLeading = LOOKUP.findStatic(SPREAD_COLLECT, "forCollectingLeading", MT_forCollectingLeading);
- } catch (Exception e) {
- throw new ExceptionInInitializerError(e);
- }
- }
-
- }
-
- static class FindSpecial {
-
- interface I1 {
- default String m() {
- return "I1.m";
- }
- }
-
- interface I2 {
- default String m() {
- return "I2.m";
- }
- }
-
- interface I3 {
- String q();
- }
-
- static class C implements I1, I2, I3 {
- public String m() {
- return I1.super.m();
- }
- public String q() {
- return "q";
- }
- }
-
- static final String ABSTRACT_ERROR = "no such method: test.java.lang.invoke.T8139885$FindSpecial$I3.q()String/invokeSpecial";
-
- }
-
- //
- // Auxiliary methods.
- //
-
- static MethodHandle[] mha(MethodHandle... mhs) {
- return mhs;
- }
-
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/TryFinallyTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2015, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 8139885
+ * @bug 8150825
+ * @run testng/othervm -ea -esa test.java.lang.invoke.TryFinallyTest
+ */
+
+package test.java.lang.invoke;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
+
+import static java.lang.invoke.MethodType.methodType;
+
+import static org.testng.AssertJUnit.*;
+
+import org.testng.annotations.*;
+
+/**
+ * Tests for the tryFinally method handle combinator introduced in JEP 274.
+ */
+public class TryFinallyTest {
+
+ static final Lookup LOOKUP = MethodHandles.lookup();
+
+ @Test
+ public static void testTryFinally() throws Throwable {
+ MethodHandle hello = MethodHandles.tryFinally(TryFinally.MH_greet, TryFinally.MH_exclaim);
+ assertEquals(TryFinally.MT_hello, hello.type());
+ assertEquals("Hello, world!", hello.invoke("world"));
+ }
+
+ @Test
+ public static void testTryFinallyVoid() throws Throwable {
+ MethodHandle tfVoid = MethodHandles.tryFinally(TryFinally.MH_print, TryFinally.MH_printMore);
+ assertEquals(TryFinally.MT_printHello, tfVoid.type());
+ tfVoid.invoke("world");
+ }
+
+ @Test
+ public static void testTryFinallySublist() throws Throwable {
+ MethodHandle helloMore = MethodHandles.tryFinally(TryFinally.MH_greetMore, TryFinally.MH_exclaimMore);
+ assertEquals(TryFinally.MT_moreHello, helloMore.type());
+ assertEquals("Hello, world and universe (but world first)!", helloMore.invoke("world", "universe"));
+ }
+
+ @DataProvider
+ static Object[][] negativeTestData() {
+ MethodHandle intid = MethodHandles.identity(int.class);
+ MethodHandle intco = MethodHandles.constant(int.class, 0);
+ MethodHandle errTarget = MethodHandles.dropArguments(intco, 0, int.class, double.class, String.class, int.class);
+ MethodHandle errCleanup = MethodHandles.dropArguments(MethodHandles.constant(int.class, 0), 0, Throwable.class,
+ int.class, double.class, Object.class);
+ return new Object[][]{
+ {intid, MethodHandles.identity(double.class),
+ "target and return types must match: double != int"},
+ {intid, MethodHandles.dropArguments(intid, 0, String.class),
+ "cleanup first argument and Throwable must match: (String,int)int != class java.lang.Throwable"},
+ {intid, MethodHandles.dropArguments(intid, 0, Throwable.class, double.class),
+ "cleanup second argument and target return type must match: (Throwable,double,int)int != int"},
+ {errTarget, errCleanup,
+ "cleanup parameters after (Throwable,result) and target parameter list prefix must match: " +
+ errCleanup.type() + " != " + errTarget.type()},
+ {TryFinally.MH_voidTarget, TryFinally.MH_voidCleanup,
+ "cleanup parameters after (Throwable,result) and target parameter list prefix must match: " +
+ TryFinally.MH_voidCleanup.type() + " != " + TryFinally.MH_voidTarget.type()}
+ };
+ }
+
+ @Test(dataProvider = "negativeTestData")
+ public static void testTryFinallyNegative(MethodHandle target, MethodHandle cleanup, String expectedMessage) {
+ boolean caught = false;
+ try {
+ MethodHandles.tryFinally(target, cleanup);
+ } catch (IllegalArgumentException iae) {
+ assertEquals(expectedMessage, iae.getMessage());
+ caught = true;
+ }
+ assertTrue(caught);
+ }
+
+ static class TryFinally {
+
+ static String greet(String whom) {
+ return "Hello, " + whom;
+ }
+
+ static String exclaim(Throwable t, String r, String whom) {
+ return r + "!";
+ }
+
+ static void print(String what) {
+ System.out.print("Hello, " + what);
+ }
+
+ static void printMore(Throwable t, String what) {
+ System.out.println("!");
+ }
+
+ static String greetMore(String first, String second) {
+ return "Hello, " + first + " and " + second;
+ }
+
+ static String exclaimMore(Throwable t, String r, String first) {
+ return r + " (but " + first + " first)!";
+ }
+
+ static void voidTarget() {}
+
+ static void voidCleanup(Throwable t, int a) {}
+
+ static final Class<TryFinally> TRY_FINALLY = TryFinally.class;
+
+ static final MethodType MT_greet = methodType(String.class, String.class);
+ static final MethodType MT_exclaim = methodType(String.class, Throwable.class, String.class, String.class);
+ static final MethodType MT_print = methodType(void.class, String.class);
+ static final MethodType MT_printMore = methodType(void.class, Throwable.class, String.class);
+ static final MethodType MT_greetMore = methodType(String.class, String.class, String.class);
+ static final MethodType MT_exclaimMore = methodType(String.class, Throwable.class, String.class, String.class);
+ static final MethodType MT_voidTarget = methodType(void.class);
+ static final MethodType MT_voidCleanup = methodType(void.class, Throwable.class, int.class);
+
+ static final MethodHandle MH_greet;
+ static final MethodHandle MH_exclaim;
+ static final MethodHandle MH_print;
+ static final MethodHandle MH_printMore;
+ static final MethodHandle MH_greetMore;
+ static final MethodHandle MH_exclaimMore;
+ static final MethodHandle MH_voidTarget;
+ static final MethodHandle MH_voidCleanup;
+
+ static final MethodType MT_hello = methodType(String.class, String.class);
+ static final MethodType MT_printHello = methodType(void.class, String.class);
+ static final MethodType MT_moreHello = methodType(String.class, String.class, String.class);
+
+ static {
+ try {
+ MH_greet = LOOKUP.findStatic(TRY_FINALLY, "greet", MT_greet);
+ MH_exclaim = LOOKUP.findStatic(TRY_FINALLY, "exclaim", MT_exclaim);
+ MH_print = LOOKUP.findStatic(TRY_FINALLY, "print", MT_print);
+ MH_printMore = LOOKUP.findStatic(TRY_FINALLY, "printMore", MT_printMore);
+ MH_greetMore = LOOKUP.findStatic(TRY_FINALLY, "greetMore", MT_greetMore);
+ MH_exclaimMore = LOOKUP.findStatic(TRY_FINALLY, "exclaimMore", MT_exclaimMore);
+ MH_voidTarget = LOOKUP.findStatic(TRY_FINALLY, "voidTarget", MT_voidTarget);
+ MH_voidCleanup = LOOKUP.findStatic(TRY_FINALLY, "voidCleanup", MT_voidCleanup);
+ } catch (Exception e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+ }
+
+}
--- a/jdk/test/java/lang/invoke/lambda/LambdaAccessControlDoPrivilegedTest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/lang/invoke/lambda/LambdaAccessControlDoPrivilegedTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -27,6 +27,7 @@
* @summary tests DoPrivileged action (implemented as lambda expressions) by
* inserting them into the BootClassPath.
* @modules jdk.compiler
+ * jdk.zipfs
* @compile -XDignore.symbol.file LambdaAccessControlDoPrivilegedTest.java LUtils.java
* @run main/othervm LambdaAccessControlDoPrivilegedTest
*/
--- a/jdk/test/java/lang/invoke/lambda/LambdaAsm.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/lang/invoke/lambda/LambdaAsm.java Wed Mar 09 14:18:12 2016 +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
@@ -28,6 +28,7 @@
* generate bytecodes with correct constant pool references
* @modules java.base/jdk.internal.org.objectweb.asm
* jdk.jdeps/com.sun.tools.classfile
+ * jdk.zipfs
* @compile -XDignore.symbol.file LambdaAsm.java LUtils.java
* @run main/othervm LambdaAsm
*/
--- a/jdk/test/java/lang/invoke/lambda/LogGeneratedClassesTest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/lang/invoke/lambda/LogGeneratedClassesTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -26,6 +26,8 @@
* @bug 8023524
* @summary tests logging generated classes for lambda
* @library /java/nio/file
+ * @modules jdk.compiler
+ * jdk.zipfs
* @run testng LogGeneratedClassesTest
*/
import java.io.File;
--- a/jdk/test/java/lang/ref/CleanerTest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/lang/ref/CleanerTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -52,7 +52,10 @@
* @library /test/lib/share/classes /lib/testlibrary /test/lib
* @build sun.hotspot.WhiteBox
* @build jdk.test.lib.Utils
- * @modules java.base/jdk.internal.misc java.base/jdk.internal.ref
+ * @modules java.base/jdk.internal
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.ref
+ * java.management
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* @run testng/othervm
* -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/SocketOption/ImmutableOptions.java Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,184 @@
+/*
+ * 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
+ * @bug 8148609
+ * @run testng/othervm ImmutableOptions
+ * @summary Assert that the set of socket options are immutable
+ */
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.*;
+import java.util.Set;
+
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+public class ImmutableOptions {
+
+ @BeforeTest
+ void setupServerSocketFactory() throws IOException {
+ ServerSocket.setSocketFactory(new ServerSocketImplFactory());
+ }
+
+ @Test(expectedExceptions = UnsupportedOperationException.class)
+ public void socketThrows() throws IOException {
+ CustomSocketImpl impl = new CustomSocketImpl();
+ Socket socket = new CustomSocket(impl);
+ socket.supportedOptions().clear();
+ }
+
+ @Test(expectedExceptions = UnsupportedOperationException.class)
+ public void socketImplThrows() throws IOException {
+ CustomSocketImpl impl = new CustomSocketImpl();
+ impl.supportedOptions().clear();
+ }
+
+ @Test(expectedExceptions = UnsupportedOperationException.class)
+ public void serverSocketThrows() throws IOException {
+ ServerSocket ss = new ServerSocket();
+ ss.supportedOptions().clear();
+ }
+
+ @Test(expectedExceptions = UnsupportedOperationException.class)
+ public void serverSocketImplThrows() throws IOException {
+ ServerSocket ss = new ServerSocket();
+ ServerSocketImplFactory.mostRecentlyCreated.supportedOptions().clear();
+ }
+
+ @Test(expectedExceptions = UnsupportedOperationException.class)
+ public void datagramSocketThrows() throws IOException {
+ CustomDatagramSocketImpl impl = new CustomDatagramSocketImpl();
+ DatagramSocket socket = new CustomDatagramSocket(impl);
+ socket.supportedOptions().clear();
+ }
+
+ @Test(expectedExceptions = UnsupportedOperationException.class)
+ public void datagramSocketImplThrows() throws IOException {
+ CustomDatagramSocketImpl impl = new CustomDatagramSocketImpl();
+ impl.supportedOptions().clear();
+ }
+
+
+ // Socket descendants
+ static class CustomSocket extends Socket {
+ public CustomSocket(SocketImpl impl) throws IOException {
+ super(impl);
+ }
+ }
+
+ static class CustomDatagramSocket extends DatagramSocket {
+ public CustomDatagramSocket(DatagramSocketImpl impl) {
+ super(impl);
+ }
+ }
+
+ static class ServerSocketImplFactory implements SocketImplFactory {
+ static volatile CustomSocketImpl mostRecentlyCreated;
+
+ @Override public SocketImpl createSocketImpl() {
+ return mostRecentlyCreated = new CustomSocketImpl();
+ }
+ }
+
+ // Custom impl's
+ static class CustomSocketImpl extends SocketImpl {
+ // The only method interesting to this test.
+ @Override public Set<SocketOption<?>> supportedOptions() {
+ return super.supportedOptions();
+ }
+
+ public void create(boolean stream) throws IOException { }
+
+ public void connect(String host, int port) throws IOException { }
+
+ public void connect(InetAddress addr, int port) throws IOException { }
+
+ public void connect(SocketAddress addr, int timeout) throws IOException { }
+
+ public void bind(InetAddress host, int port) throws IOException { }
+
+ public void listen(int backlog) throws IOException { }
+
+ public void accept(SocketImpl s) throws IOException { }
+
+ public InputStream getInputStream() throws IOException { return null; }
+
+ public OutputStream getOutputStream() throws IOException { return null; }
+
+ public int available() throws IOException { return 0; }
+
+ public void close() throws IOException { }
+
+ public void sendUrgentData(int data) throws IOException { }
+
+ public Object getOption(int i) throws SocketException { return null; }
+
+ public void setOption(int i, Object o) throws SocketException { }
+ }
+
+ static class CustomDatagramSocketImpl extends DatagramSocketImpl {
+ // The only method interesting to this test.
+ @Override public Set<SocketOption<?>> supportedOptions() {
+ return super.supportedOptions();
+ }
+
+ protected void create() throws SocketException { }
+
+ protected void bind(int lport, InetAddress laddr) throws SocketException { }
+
+ protected void send(DatagramPacket p) throws IOException { }
+
+ protected int peek(InetAddress i) throws IOException { return 0; }
+
+ protected int peekData(DatagramPacket p) throws IOException { return 0; }
+
+ protected void receive(DatagramPacket p) throws IOException { }
+
+ protected void setTTL(byte ttl) throws IOException { }
+
+ protected byte getTTL() throws IOException { return 0; }
+
+ protected void setTimeToLive(int ttl) throws IOException { }
+
+ protected int getTimeToLive() throws IOException { return 0; }
+
+ protected void join(InetAddress inetaddr) throws IOException { }
+
+ protected void leave(InetAddress inetaddr) throws IOException { }
+
+ protected void joinGroup(SocketAddress x, NetworkInterface y)
+ throws IOException { }
+
+ protected void leaveGroup(SocketAddress x, NetworkInterface y)
+ throws IOException { }
+
+ protected void close() { }
+
+ public void setOption(int optID, Object value) throws SocketException { }
+
+ public Object getOption(int optID) throws SocketException { return null; }
+ }
+}
--- a/jdk/test/java/net/ipv6tests/UdpTest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/net/ipv6tests/UdpTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -24,6 +24,7 @@
/*
* @test
* @bug 4868820
+ * @key intermittent
* @summary IPv6 support for Windows XP and 2003 server
*/
--- a/jdk/test/java/rmi/server/Unreferenced/leaseCheckInterval/LeaseCheckInterval.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/rmi/server/Unreferenced/leaseCheckInterval/LeaseCheckInterval.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -43,6 +43,7 @@
* java.rmi/sun.rmi.transport.tcp
* @build TestLibrary JavaVM LeaseCheckInterval_Stub SelfTerminator
* @run main/othervm LeaseCheckInterval
+ * @key intermittent
*/
import java.rmi.Remote;
--- a/jdk/test/java/util/WeakHashMap/GCDuringIteration.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/WeakHashMap/GCDuringIteration.java Wed Mar 09 14:18:12 2016 +0100
@@ -29,26 +29,50 @@
* @run main GCDuringIteration
* @summary Check that iterators work properly in the presence of
* concurrent finalization and removal of elements.
- * @key randomness intermittent
+ * @key randomness
*/
-import java.util.*;
+import static java.util.concurrent.TimeUnit.SECONDS;
+
+import java.lang.ref.WeakReference;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Random;
+import java.util.WeakHashMap;
import java.util.concurrent.CountDownLatch;
+import java.util.function.BooleanSupplier;
import jdk.testlibrary.RandomFactory;
public class GCDuringIteration {
- private static void waitForFinalizersToRun() {
- for (int i = 0; i < 2; i++)
- tryWaitForFinalizersToRun();
+
+ /** No guarantees, but effective in practice. */
+ static void forceFullGc() {
+ CountDownLatch finalizeDone = new CountDownLatch(1);
+ WeakReference<?> ref = new WeakReference<Object>(new Object() {
+ protected void finalize() { finalizeDone.countDown(); }});
+ try {
+ for (int i = 0; i < 10; i++) {
+ System.gc();
+ if (finalizeDone.await(1L, SECONDS) && ref.get() == null) {
+ System.runFinalization(); // try to pick up stragglers
+ return;
+ }
+ }
+ } catch (InterruptedException unexpected) {
+ throw new AssertionError("unexpected InterruptedException");
+ }
+ throw new AssertionError("failed to do a \"full\" gc");
}
- private static void tryWaitForFinalizersToRun() {
- System.gc();
- final CountDownLatch fin = new CountDownLatch(1);
- new Object() { protected void finalize() { fin.countDown(); }};
- System.gc();
- try { fin.await(); }
- catch (InterruptedException ie) { throw new Error(ie); }
+ static void gcAwait(BooleanSupplier s) {
+ for (int i = 0; i < 10; i++) {
+ if (s.getAsBoolean())
+ return;
+ forceFullGc();
+ }
+ throw new AssertionError("failed to satisfy condition");
}
// A class with the traditional pessimal hashCode implementation,
@@ -76,9 +100,13 @@
if (rnd.nextBoolean()) check(it.hasNext());
equal(it.next().getValue(), i);
}
- if (rnd.nextBoolean())
- THROWS(NoSuchElementException.class,
- new F(){void f(){it.next();}});
+ if (rnd.nextBoolean()) {
+ try {
+ it.next();
+ throw new AssertionError("should throw");
+ } catch (NoSuchElementException success) {}
+ }
+
if (rnd.nextBoolean())
check(! it.hasNext());
}
@@ -106,9 +134,7 @@
int first = firstValue(map);
final Iterator<Map.Entry<Foo,Integer>> it = map.entrySet().iterator();
foos[first] = null;
- for (int i = 0; i < 10 && map.size() != first; i++)
- tryWaitForFinalizersToRun();
- equal(map.size(), first);
+ gcAwait(() -> map.size() == first);
checkIterator(it, first-1);
equal(map.size(), first);
equal(firstValue(map), first-1);
@@ -119,15 +145,14 @@
final Iterator<Map.Entry<Foo,Integer>> it = map.entrySet().iterator();
it.next(); // protects first entry
System.out.println(map.values());
+ int oldSize = map.size();
foos[first] = null;
- tryWaitForFinalizersToRun();
- equal(map.size(), first+1);
+ forceFullGc();
+ equal(map.size(), oldSize);
System.out.println(map.values());
checkIterator(it, first-1);
// first entry no longer protected
- for (int i = 0; i < 10 && map.size() != first; i++)
- tryWaitForFinalizersToRun();
- equal(map.size(), first);
+ gcAwait(() -> map.size() == first);
equal(firstValue(map), first-1);
}
@@ -137,15 +162,12 @@
it.next(); // protects first entry
System.out.println(map.values());
foos[first] = foos[first-1] = null;
- tryWaitForFinalizersToRun();
- equal(map.size(), first);
+ gcAwait(() -> map.size() == first);
equal(firstValue(map), first);
System.out.println(map.values());
checkIterator(it, first-2);
// first entry no longer protected
- for (int i = 0; i < 10 && map.size() != first-1; i++)
- tryWaitForFinalizersToRun();
- equal(map.size(), first-1);
+ gcAwait(() -> map.size() == first-1);
equal(firstValue(map), first-2);
}
@@ -155,16 +177,15 @@
it.next(); // protects first entry
it.hasNext(); // protects second entry
System.out.println(map.values());
+ int oldSize = map.size();
foos[first] = foos[first-1] = null;
- tryWaitForFinalizersToRun();
+ forceFullGc();
+ equal(map.size(), oldSize);
equal(firstValue(map), first);
- equal(map.size(), first+1);
System.out.println(map.values());
checkIterator(it, first-1);
// first entry no longer protected
- for (int i = 0; i < 10 && map.size() != first-1; i++)
- tryWaitForFinalizersToRun();
- equal(map.size(), first-1);
+ gcAwait(() -> map.size() == first-1);
equal(firstValue(map), first-2);
}
@@ -173,17 +194,16 @@
final Iterator<Map.Entry<Foo,Integer>> it = map.entrySet().iterator();
it.next(); // protects first entry
System.out.println(map.values());
+ equal(map.size(), first+1);
foos[first] = foos[first-1] = null;
- tryWaitForFinalizersToRun();
+ gcAwait(() -> map.size() == first);
it.remove();
equal(firstValue(map), first-2);
equal(map.size(), first-1);
System.out.println(map.values());
checkIterator(it, first-2);
// first entry no longer protected
- for (int i = 0; i < 10 && map.size() != first-1; i++)
- tryWaitForFinalizersToRun();
- equal(map.size(), first-1);
+ gcAwait(() -> map.size() == first-1);
equal(firstValue(map), first-2);
}
@@ -194,15 +214,14 @@
it.remove();
it.hasNext(); // protects second entry
System.out.println(map.values());
+ equal(map.size(), first);
foos[first] = foos[first-1] = null;
- tryWaitForFinalizersToRun();
+ forceFullGc();
equal(firstValue(map), first-1);
equal(map.size(), first);
System.out.println(map.values());
checkIterator(it, first-1);
- for (int i = 0; i < 10 && map.size() != first-1; i++)
- tryWaitForFinalizersToRun();
- equal(map.size(), first-1);
+ gcAwait(() -> map.size() == first-1);
equal(firstValue(map), first-2);
}
@@ -211,14 +230,11 @@
final Iterator<Map.Entry<Foo,Integer>> it = map.entrySet().iterator();
it.hasNext(); // protects first entry
Arrays.fill(foos, null);
- tryWaitForFinalizersToRun();
- equal(map.size(), 1);
+ gcAwait(() -> map.size() == 1);
System.out.println(map.values());
equal(it.next().getValue(), first);
check(! it.hasNext());
- for (int i = 0; i < 10 && map.size() != 0; i++)
- tryWaitForFinalizersToRun();
- equal(map.size(), 0);
+ gcAwait(() -> map.size() == 0);
check(map.isEmpty());
}
}
@@ -239,11 +255,4 @@
try {test(args);} catch (Throwable t) {unexpected(t);}
System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
if (failed > 0) throw new AssertionError("Some tests failed");}
- abstract class F {abstract void f() throws Throwable;}
- void THROWS(Class<? extends Throwable> k, F... fs) {
- for (F f : fs)
- try {f.f(); fail("Expected " + k.getName() + " not thrown");}
- catch (Throwable t) {
- if (k.isAssignableFrom(t.getClass())) pass();
- else unexpected(t);}}
}
--- a/jdk/test/java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java Wed Mar 09 14:18:12 2016 +0100
@@ -35,8 +35,11 @@
* @test
* @bug 4486658
* @summary Checks for responsiveness of blocking queues to cancellation.
+ * @library /lib/testlibrary/
*/
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
import java.util.ArrayList;
import java.util.List;
import java.util.SplittableRandom;
@@ -53,8 +56,10 @@
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
+import jdk.testlibrary.Utils;
public class CancelledProducerConsumerLoops {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static ExecutorService pool;
public static void main(String[] args) throws Exception {
@@ -73,7 +78,7 @@
new CancelledProducerConsumerLoops(i, queue).run();
}
pool.shutdown();
- if (! pool.awaitTermination(10L, TimeUnit.SECONDS))
+ if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS))
throw new AssertionError("timed out");
pool = null;
}
@@ -117,18 +122,18 @@
assertCancelled(cons[i]);
}
- if (!producersInterrupted.await(10L, TimeUnit.SECONDS))
+ if (!producersInterrupted.await(LONG_DELAY_MS, MILLISECONDS))
throw new AssertionError("timed out");
- if (!consumersInterrupted.await(10L, TimeUnit.SECONDS))
+ if (!consumersInterrupted.await(LONG_DELAY_MS, MILLISECONDS))
throw new AssertionError("timed out");
if (prods[0].isDone() || prods[0].isCancelled())
throw new AssertionError("completed too early");
done = true;
- if (! (prods[0].get(10L, TimeUnit.SECONDS) instanceof Integer))
+ if (! (prods[0].get(LONG_DELAY_MS, MILLISECONDS) instanceof Integer))
throw new AssertionError("expected Integer");
- if (! (cons[0].get(10L, TimeUnit.SECONDS) instanceof Integer))
+ if (! (cons[0].get(LONG_DELAY_MS, MILLISECONDS) instanceof Integer))
throw new AssertionError("expected Integer");
}
@@ -138,7 +143,7 @@
if (!future.isCancelled())
throw new AssertionError("not cancelled");
try {
- future.get(10L, TimeUnit.SECONDS);
+ future.get(LONG_DELAY_MS, MILLISECONDS);
throw new AssertionError("should throw CancellationException");
} catch (CancellationException success) {}
}
--- a/jdk/test/java/util/concurrent/BlockingQueue/Interrupt.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/concurrent/BlockingQueue/Interrupt.java Wed Mar 09 14:18:12 2016 +0100
@@ -26,10 +26,10 @@
* @bug 6384064
* @summary Check proper handling of interrupts
* @author Martin Buchholz
+ * @library /lib/testlibrary/
*/
import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import static java.util.concurrent.TimeUnit.SECONDS;
import java.util.ArrayList;
import java.util.List;
@@ -41,8 +41,10 @@
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledThreadPoolExecutor;
+import jdk.testlibrary.Utils;
public class Interrupt {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static void checkInterrupted0(Iterable<Fun> fs, Executor ex) {
for (Fun f : fs) {
@@ -71,7 +73,7 @@
checkInterrupted0(fs, immediateExecutor);
checkInterrupted0(fs, delayedExecutor);
stpe.shutdown();
- check(stpe.awaitTermination(10L, SECONDS));
+ check(stpe.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
}
static void testQueue(final BlockingQueue<Object> q) {
@@ -82,12 +84,12 @@
q.clear();
List<Fun> fs = new ArrayList<Fun>();
fs.add(() -> q.take());
- fs.add(() -> q.poll(60, SECONDS));
+ fs.add(() -> q.poll(LONG_DELAY_MS, MILLISECONDS));
if (deq != null) {
fs.add(() -> deq.takeFirst());
fs.add(() -> deq.takeLast());
- fs.add(() -> deq.pollFirst(7, SECONDS));
- fs.add(() -> deq.pollLast(7, SECONDS));
+ fs.add(() -> deq.pollFirst(LONG_DELAY_MS, MILLISECONDS));
+ fs.add(() -> deq.pollLast(LONG_DELAY_MS, MILLISECONDS));
}
checkInterrupted(fs);
@@ -99,12 +101,12 @@
fs.clear();
fs.add(() -> q.put(1));
- fs.add(() -> q.offer(1, 7, SECONDS));
+ fs.add(() -> q.offer(1, LONG_DELAY_MS, MILLISECONDS));
if (deq != null) {
fs.add(() -> deq.putFirst(1));
fs.add(() -> deq.putLast(1));
- fs.add(() -> deq.offerFirst(1, 7, SECONDS));
- fs.add(() -> deq.offerLast(1, 7, SECONDS));
+ fs.add(() -> deq.offerFirst(1, LONG_DELAY_MS, MILLISECONDS));
+ fs.add(() -> deq.offerLast(1, LONG_DELAY_MS, MILLISECONDS));
}
checkInterrupted(fs);
} catch (Throwable t) {
--- a/jdk/test/java/util/concurrent/BlockingQueue/MultipleProducersSingleConsumerLoops.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/concurrent/BlockingQueue/MultipleProducersSingleConsumerLoops.java Wed Mar 09 14:18:12 2016 +0100
@@ -35,10 +35,11 @@
* @test
* @bug 4486658
* @summary multiple producers and single consumer using blocking queues
+ * @library /lib/testlibrary/
*/
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
-import static java.util.concurrent.TimeUnit.SECONDS;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
@@ -51,8 +52,10 @@
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.atomic.AtomicInteger;
+import jdk.testlibrary.Utils;
public class MultipleProducersSingleConsumerLoops {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static ExecutorService pool;
public static void main(String[] args) throws Exception {
@@ -77,7 +80,7 @@
}
pool.shutdown();
- if (! pool.awaitTermination(10L, SECONDS))
+ if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS))
throw new Error();
pool = null;
}
--- a/jdk/test/java/util/concurrent/BlockingQueue/ProducerConsumerLoops.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/concurrent/BlockingQueue/ProducerConsumerLoops.java Wed Mar 09 14:18:12 2016 +0100
@@ -35,10 +35,11 @@
* @test
* @bug 4486658
* @summary multiple producers and consumers using blocking queues
+ * @library /lib/testlibrary/
*/
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
-import static java.util.concurrent.TimeUnit.SECONDS;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
@@ -51,8 +52,10 @@
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.atomic.AtomicInteger;
+import jdk.testlibrary.Utils;
public class ProducerConsumerLoops {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static ExecutorService pool;
public static void main(String[] args) throws Exception {
@@ -77,7 +80,7 @@
run(new ArrayBlockingQueue<Integer>(100, true), i, 100);
}
pool.shutdown();
- if (! pool.awaitTermination(60L, SECONDS))
+ if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS))
throw new Error();
pool = null;
}
--- a/jdk/test/java/util/concurrent/BlockingQueue/SingleProducerMultipleConsumerLoops.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/concurrent/BlockingQueue/SingleProducerMultipleConsumerLoops.java Wed Mar 09 14:18:12 2016 +0100
@@ -35,10 +35,11 @@
* @test
* @bug 4486658
* @summary check ordering for blocking queues with 1 producer and multiple consumers
+ * @library /lib/testlibrary/
*/
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
-import static java.util.concurrent.TimeUnit.SECONDS;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
@@ -50,8 +51,10 @@
import java.util.concurrent.LinkedTransferQueue;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.SynchronousQueue;
+import jdk.testlibrary.Utils;
public class SingleProducerMultipleConsumerLoops {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static ExecutorService pool;
public static void main(String[] args) throws Exception {
@@ -75,7 +78,7 @@
run(new ArrayBlockingQueue<Integer>(100, true), i, 100);
}
pool.shutdown();
- if (! pool.awaitTermination(60L, SECONDS))
+ if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS))
throw new Error();
pool = null;
}
--- a/jdk/test/java/util/concurrent/CompletableFuture/Basic.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/concurrent/CompletableFuture/Basic.java Wed Mar 09 14:18:12 2016 +0100
@@ -34,15 +34,17 @@
/*
* @test
* @bug 8005696
+ * @summary Basic tests for CompletableFuture
+ * @library /lib/testlibrary/
* @run main Basic
* @run main/othervm -Djava.util.concurrent.ForkJoinPool.common.parallelism=0 Basic
- * @summary Basic tests for CompletableFuture
* @author Chris Hegarty
*/
import static java.util.concurrent.CompletableFuture.runAsync;
import static java.util.concurrent.CompletableFuture.supplyAsync;
import static java.util.concurrent.ForkJoinPool.commonPool;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import java.lang.reflect.Array;
@@ -54,8 +56,10 @@
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
+import jdk.testlibrary.Utils;
public class Basic {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static void checkCompletedNormally(CompletableFuture<?> cf, Object value) {
checkCompletedNormally(cf, value == null ? null : new Object[] { value });
@@ -109,12 +113,13 @@
}
private static void realMain(String[] args) throws Throwable {
- ExecutorService executor = Executors.newFixedThreadPool(2);
+ ExecutorService pool = Executors.newFixedThreadPool(2);
try {
- test(executor);
+ test(pool);
} finally {
- executor.shutdown();
- executor.awaitTermination(30L, SECONDS);
+ pool.shutdown();
+ if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS))
+ throw new Error();
}
}
--- a/jdk/test/java/util/concurrent/ConcurrentHashMap/MapLoops.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/concurrent/ConcurrentHashMap/MapLoops.java Wed Mar 09 14:18:12 2016 +0100
@@ -34,7 +34,6 @@
/*
* @test
* @bug 4486658
- * @run main/timeout=1600 MapLoops
* @summary Exercise multithreaded maps, by default ConcurrentHashMap.
* Multithreaded hash table test. Each thread does a random walk
* though elements of "key" array. On each iteration, it checks if
@@ -42,9 +41,11 @@
* inserts it, and if present, with probability premove it removes
* it. (pinsert and premove are expressed as percentages to simplify
* parsing from command line.)
+ * @library /lib/testlibrary/
+ * @run main/timeout=1600 MapLoops
*/
-import static java.util.concurrent.TimeUnit.SECONDS;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.util.List;
import java.util.Map;
@@ -53,8 +54,10 @@
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import jdk.testlibrary.Utils;
public class MapLoops {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static int nkeys = 1000; // 10_000
static int pinsert = 60;
static int premove = 2;
@@ -126,7 +129,7 @@
i = k;
}
pool.shutdown();
- if (! pool.awaitTermination(60L, SECONDS))
+ if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS))
throw new Error();
if (! throwables.isEmpty())
--- a/jdk/test/java/util/concurrent/ConcurrentQueues/ConcurrentQueueLoops.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/concurrent/ConcurrentQueues/ConcurrentQueueLoops.java Wed Mar 09 14:18:12 2016 +0100
@@ -34,11 +34,12 @@
/*
* @test
* @bug 4486658 6785442
+ * @summary Checks that a set of threads can repeatedly get and modify items
+ * @library /lib/testlibrary/
* @run main ConcurrentQueueLoops 8 123456
- * @summary Checks that a set of threads can repeatedly get and modify items
*/
-import static java.util.concurrent.TimeUnit.SECONDS;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.util.ArrayList;
import java.util.Collection;
@@ -57,8 +58,10 @@
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.LinkedTransferQueue;
import java.util.concurrent.atomic.AtomicInteger;
+import jdk.testlibrary.Utils;
public class ConcurrentQueueLoops {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
ExecutorService pool;
AtomicInteger totalItems;
boolean print;
@@ -106,16 +109,14 @@
print = false;
System.out.println("Warmup...");
oneRun(1, items, q);
- //Thread.sleep(100);
oneRun(3, items, q);
- Thread.sleep(100);
print = true;
for (int i = 1; i <= maxStages; i += (i+1) >>> 1) {
oneRun(i, items, q);
}
pool.shutdown();
- check(pool.awaitTermination(60L, SECONDS));
+ check(pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
}
class Stage implements Callable<Integer> {
--- a/jdk/test/java/util/concurrent/ConcurrentQueues/GCRetention.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/concurrent/ConcurrentQueues/GCRetention.java Wed Mar 09 14:18:12 2016 +0100
@@ -38,10 +38,14 @@
* @run main GCRetention 12345
*/
+import static java.util.concurrent.TimeUnit.SECONDS;
+
+import java.lang.ref.WeakReference;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.LinkedTransferQueue;
@@ -59,6 +63,25 @@
// Suitable for benchmarking. Overridden by args[0] for testing.
int count = 1024 * 1024;
+ /** No guarantees, but effective in practice. */
+ static void forceFullGc() {
+ CountDownLatch finalizeDone = new CountDownLatch(1);
+ WeakReference<?> ref = new WeakReference<Object>(new Object() {
+ protected void finalize() { finalizeDone.countDown(); }});
+ try {
+ for (int i = 0; i < 10; i++) {
+ System.gc();
+ if (finalizeDone.await(1L, SECONDS) && ref.get() == null) {
+ System.runFinalization(); // try to pick up stragglers
+ return;
+ }
+ }
+ } catch (InterruptedException unexpected) {
+ throw new AssertionError("unexpected InterruptedException");
+ }
+ throw new AssertionError("failed to do a \"full\" gc");
+ }
+
final Map<String,String> results = new ConcurrentHashMap<String,String>();
Collection<Queue<Boolean>> queues() {
@@ -117,8 +140,8 @@
long t0 = System.nanoTime();
for (int i = 0; i < count; i++)
check(q.add(Boolean.TRUE));
- System.gc();
- System.gc();
+ forceFullGc();
+ // forceFullGc();
Boolean x;
while ((x = q.poll()) != null)
equal(x, Boolean.TRUE);
--- a/jdk/test/java/util/concurrent/CyclicBarrier/Basic.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/concurrent/CyclicBarrier/Basic.java Wed Mar 09 14:18:12 2016 +0100
@@ -25,11 +25,11 @@
* @test
* @bug 6253848 6366811
* @summary Basic tests for CyclicBarrier
+ * @library /lib/testlibrary/
* @author Martin Buchholz, David Holmes
*/
import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import static java.util.concurrent.TimeUnit.SECONDS;
import java.util.ArrayList;
import java.util.Iterator;
@@ -39,8 +39,10 @@
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
+import jdk.testlibrary.Utils;
public class Basic {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
private static void checkBroken(final CyclicBarrier barrier) {
check(barrier.isBroken());
@@ -77,7 +79,7 @@
private static final CyclicBarrier atTheStartingGate = new CyclicBarrier(3);
private static void toTheStartingGate() {
- try { atTheStartingGate.await(10, SECONDS); pass(); }
+ try { atTheStartingGate.await(LONG_DELAY_MS, MILLISECONDS); pass(); }
catch (Throwable t) {
unexpected(t);
reset(atTheStartingGate);
@@ -314,13 +316,13 @@
Throwable throwable() { return this.throwable; }
boolean interruptBit() { return this.interrupted; }
void realRun() throws Throwable {
- startingGate.await(10, SECONDS);
+ startingGate.await(LONG_DELAY_MS, MILLISECONDS);
try {
- if (timed) barrier.await(10, SECONDS);
+ if (timed) barrier.await(LONG_DELAY_MS, MILLISECONDS);
else barrier.await(); }
catch (Throwable throwable) { this.throwable = throwable; }
- try { doneSignal.await(10, SECONDS); }
+ try { doneSignal.await(LONG_DELAY_MS, MILLISECONDS); }
catch (InterruptedException e) { interrupted = true; }
}
}
@@ -354,7 +356,7 @@
waiter.start();
waiters.add(waiter);
}
- startingGate.await(10, SECONDS);
+ startingGate.await(LONG_DELAY_MS, MILLISECONDS);
while (barrier.getNumberWaiting() < N) Thread.yield();
barrier.await();
doneSignal.countDown();
@@ -383,7 +385,7 @@
waiter.start();
waiters.add(waiter);
}
- startingGate.await(10, SECONDS);
+ startingGate.await(LONG_DELAY_MS, MILLISECONDS);
while (barrier.getNumberWaiting() < N) Thread.yield();
for (int i = 0; i < N/2; i++)
waiters.get(i).interrupt();
--- a/jdk/test/java/util/concurrent/DelayQueue/Stress.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/concurrent/DelayQueue/Stress.java Wed Mar 09 14:18:12 2016 +0100
@@ -26,6 +26,7 @@
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
+import java.util.concurrent.TimeUnit;
/**
* This is not a regression test, but a stress benchmark test for
--- a/jdk/test/java/util/concurrent/Exchanger/ExchangeLoops.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/concurrent/Exchanger/ExchangeLoops.java Wed Mar 09 14:18:12 2016 +0100
@@ -34,18 +34,20 @@
/*
* @test
* @bug 4486658
- * @run main/timeout=720 ExchangeLoops
* @summary checks to make sure a pipeline of exchangers passes data.
+ * @library /lib/testlibrary/
*/
-import static java.util.concurrent.TimeUnit.SECONDS;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.Exchanger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import jdk.testlibrary.Utils;
public class ExchangeLoops {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static final ExecutorService pool = Executors.newCachedThreadPool();
static boolean print = false;
@@ -56,14 +58,14 @@
public static void main(String[] args) throws Exception {
int maxStages = 5;
- int iters = 10000;
+ int iters = 2000;
if (args.length > 0)
maxStages = Integer.parseInt(args[0]);
print = false;
System.out.println("Warmup...");
- oneRun(2, 100000);
+ oneRun(2, iters);
print = true;
for (int i = 2; i <= maxStages; i += (i+1) >>> 1) {
@@ -71,7 +73,7 @@
oneRun(i, iters);
}
pool.shutdown();
- if (! pool.awaitTermination(60L, SECONDS))
+ if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS))
throw new Error();
}
--- a/jdk/test/java/util/concurrent/ExecutorCompletionService/ExecutorCompletionServiceLoops.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/concurrent/ExecutorCompletionService/ExecutorCompletionServiceLoops.java Wed Mar 09 14:18:12 2016 +0100
@@ -34,19 +34,21 @@
/*
* @test
* @bug 4965960
- * @run main/timeout=3600 ExecutorCompletionServiceLoops
- * @summary Exercise ExecutorCompletionServiceLoops
+ * @summary Exercise ExecutorCompletionService
+ * @library /lib/testlibrary/
*/
-import static java.util.concurrent.TimeUnit.SECONDS;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import jdk.testlibrary.Utils;
public class ExecutorCompletionServiceLoops {
- static final int POOLSIZE = 100;
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
+ static final int POOLSIZE = 10;
static final ExecutorService pool =
Executors.newFixedThreadPool(POOLSIZE);
static final ExecutorCompletionService<Integer> ecs =
@@ -55,23 +57,21 @@
public static void main(String[] args) throws Exception {
int max = 8;
- int base = 10000;
+ int base = 2000;
if (args.length > 0)
max = Integer.parseInt(args[0]);
System.out.println("Warmup...");
oneTest(base);
- Thread.sleep(100);
print = true;
for (int i = 1; i <= max; i += (i+1) >>> 1) {
System.out.print("n: " + i * base);
oneTest(i * base);
- Thread.sleep(100);
}
pool.shutdown();
- if (! pool.awaitTermination(60L, SECONDS))
+ if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS))
throw new Error();
}
--- a/jdk/test/java/util/concurrent/Executors/AutoShutdown.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/concurrent/Executors/AutoShutdown.java Wed Mar 09 14:18:12 2016 +0100
@@ -24,26 +24,32 @@
/*
* @test
* @bug 6399443
+ * @summary Check for auto-shutdown and gc of singleThreadExecutors
+ * @library /lib/testlibrary/
* @run main/othervm/timeout=1000 AutoShutdown
- * @summary Check for auto-shutdown and gc of singleThreadExecutors
* @author Martin Buchholz
*/
+import static java.util.concurrent.Executors.defaultThreadFactory;
+import static java.util.concurrent.Executors.newFixedThreadPool;
+import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
+import static java.util.concurrent.Executors.newSingleThreadExecutor;
+
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
import java.lang.ref.WeakReference;
import java.util.Arrays;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
-import static java.util.concurrent.Executors.defaultThreadFactory;
-import static java.util.concurrent.Executors.newFixedThreadPool;
-import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
-import static java.util.concurrent.Executors.newSingleThreadExecutor;
+import jdk.testlibrary.Utils;
public class AutoShutdown {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static void await(CountDownLatch latch) throws InterruptedException {
- if (!latch.await(100L, TimeUnit.SECONDS))
+ if (!latch.await(LONG_DELAY_MS, MILLISECONDS))
throw new AssertionError("timed out waiting for latch");
}
--- a/jdk/test/java/util/concurrent/FutureTask/CancelledFutureLoops.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/concurrent/FutureTask/CancelledFutureLoops.java Wed Mar 09 14:18:12 2016 +0100
@@ -34,13 +34,14 @@
/*
* @test
* @bug 4486658
- * @run main/timeout=2000 CancelledFutureLoops
* @summary Checks for responsiveness of futures to cancellation.
* Runs under the assumption that ITERS computations require more than
* TIMEOUT msecs to complete.
+ * @library /lib/testlibrary/
+ * @run main/timeout=2000 CancelledFutureLoops
*/
-import static java.util.concurrent.TimeUnit.SECONDS;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.util.SplittableRandom;
import java.util.concurrent.BrokenBarrierException;
@@ -51,8 +52,10 @@
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.locks.ReentrantLock;
+import jdk.testlibrary.Utils;
public final class CancelledFutureLoops {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static final ExecutorService pool = Executors.newCachedThreadPool();
static final SplittableRandom rnd = new SplittableRandom();
static boolean print = false;
@@ -80,7 +83,7 @@
Thread.sleep(TIMEOUT);
}
pool.shutdown();
- if (! pool.awaitTermination(60L, SECONDS))
+ if (! pool.awaitTermination(6 * LONG_DELAY_MS, MILLISECONDS))
throw new Error();
}
--- a/jdk/test/java/util/concurrent/FutureTask/DoneMeansDone.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/concurrent/FutureTask/DoneMeansDone.java Wed Mar 09 14:18:12 2016 +0100
@@ -36,8 +36,11 @@
* @bug 8073704
* @summary Checks that once isDone() returns true,
* get() never throws InterruptedException or TimeoutException
+ * @library /lib/testlibrary/
*/
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
import java.util.ArrayList;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
@@ -49,8 +52,11 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
+import jdk.testlibrary.Utils;
public class DoneMeansDone {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
+
public static void main(String[] args) throws Throwable {
final int iters = 1000;
final int nThreads = 2;
@@ -92,7 +98,7 @@
}
done.set(true);
pool.shutdown();
- if (!pool.awaitTermination(10L, TimeUnit.SECONDS))
+ if (!pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS))
throw new AssertionError();
for (Future<?> future : futures)
future.get();
--- a/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/DelayOverflow.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/DelayOverflow.java Wed Mar 09 14:18:12 2016 +0100
@@ -35,14 +35,21 @@
* @test
* @bug 6725789
* @summary Check for long overflow in task time comparison.
+ * @library /lib/testlibrary/
*/
+import static java.util.concurrent.TimeUnit.DAYS;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static java.util.concurrent.TimeUnit.NANOSECONDS;
+
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
+import jdk.testlibrary.Utils;
public class DelayOverflow {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
+
static void waitForNanoTimeTick() {
for (long t0 = System.nanoTime(); t0 == System.nanoTime(); )
;
@@ -52,16 +59,16 @@
Runnable r, int how) {
switch (how) {
case 0:
- pool.schedule(r, 0, TimeUnit.MILLISECONDS);
+ pool.schedule(r, 0, MILLISECONDS);
break;
case 1:
- pool.schedule(Executors.callable(r), 0, TimeUnit.DAYS);
+ pool.schedule(Executors.callable(r), 0, DAYS);
break;
case 2:
- pool.scheduleWithFixedDelay(r, 0, 1000, TimeUnit.NANOSECONDS);
+ pool.scheduleWithFixedDelay(r, 0, 1000, NANOSECONDS);
break;
case 3:
- pool.scheduleAtFixedRate(r, 0, 1000, TimeUnit.MILLISECONDS);
+ pool.scheduleAtFixedRate(r, 0, 1000, MILLISECONDS);
break;
default:
fail(String.valueOf(how));
@@ -72,16 +79,16 @@
Runnable r, int how) {
switch (how) {
case 0:
- pool.schedule(r, Long.MAX_VALUE, TimeUnit.MILLISECONDS);
+ pool.schedule(r, Long.MAX_VALUE, MILLISECONDS);
break;
case 1:
- pool.schedule(Executors.callable(r), Long.MAX_VALUE, TimeUnit.DAYS);
+ pool.schedule(Executors.callable(r), Long.MAX_VALUE, DAYS);
break;
case 2:
- pool.scheduleWithFixedDelay(r, Long.MAX_VALUE, 1000, TimeUnit.NANOSECONDS);
+ pool.scheduleWithFixedDelay(r, Long.MAX_VALUE, 1000, NANOSECONDS);
break;
case 3:
- pool.scheduleAtFixedRate(r, Long.MAX_VALUE, 1000, TimeUnit.MILLISECONDS);
+ pool.scheduleAtFixedRate(r, Long.MAX_VALUE, 1000, MILLISECONDS);
break;
default:
fail(String.valueOf(how));
@@ -114,14 +121,14 @@
proceedLatch.await();
} catch (Throwable t) { unexpected(t); }
}};
- pool.schedule(keepPoolBusy, 0, TimeUnit.SECONDS);
+ pool.schedule(keepPoolBusy, 0, DAYS);
busyLatch.await();
scheduleNow(pool, notifier, nowHow);
waitForNanoTimeTick();
scheduleAtTheEndOfTime(pool, neverRuns, thenHow);
proceedLatch.countDown();
- check(runLatch.await(10L, TimeUnit.SECONDS));
+ check(runLatch.await(LONG_DELAY_MS, MILLISECONDS));
equal(runLatch.getCount(), 0L);
pool.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
@@ -142,10 +149,9 @@
} catch (Throwable t) { unexpected(t); }
}};
pool.scheduleWithFixedDelay(scheduleNowScheduler,
- 0, Long.MAX_VALUE,
- TimeUnit.NANOSECONDS);
+ 0, Long.MAX_VALUE, NANOSECONDS);
- check(runLatch.await(10L, TimeUnit.SECONDS));
+ check(runLatch.await(LONG_DELAY_MS, MILLISECONDS));
equal(runLatch.getCount(), 0L);
pool.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
--- a/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/GCRetention.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/GCRetention.java Wed Mar 09 14:18:12 2016 +0100
@@ -34,8 +34,11 @@
/*
* @test
* @summary Ensure that waiting pool threads don't retain refs to tasks.
+ * @library /lib/testlibrary/
*/
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
import java.lang.ref.WeakReference;
import java.util.concurrent.Delayed;
import java.util.concurrent.ExecutionException;
@@ -44,8 +47,11 @@
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
+import jdk.testlibrary.Utils;
public class GCRetention {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
+
/**
* A custom thread pool with a custom RunnableScheduledFuture, for the
* sole purpose of ensuring that the task retains a strong reference to
@@ -116,7 +122,7 @@
Thread.sleep(10);
}
pool.shutdown();
- pool.awaitTermination(10L, TimeUnit.SECONDS);
+ pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS);
if (cleared < size)
throw new Error(String.format
("references to %d/%d tasks retained (\"leaked\")",
--- a/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/ZeroCorePoolSize.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/ZeroCorePoolSize.java Wed Mar 09 14:18:12 2016 +0100
@@ -26,16 +26,21 @@
* @bug 7091003
* @summary ScheduledExecutorService never executes Runnable
* with corePoolSize of zero
+ * @library /lib/testlibrary/
* @author Chris Hegarty
*/
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
+import jdk.testlibrary.Utils;
/**
* Verify that tasks can be run even with a core pool size of 0.
*/
public class ZeroCorePoolSize {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
volatile boolean taskRun;
@@ -49,10 +54,10 @@
};
check(pool.getCorePoolSize() == 0);
- pool.schedule(task, 1, TimeUnit.SECONDS);
+ pool.schedule(task, 12L, MILLISECONDS);
pool.shutdown();
- check(pool.awaitTermination(20L, TimeUnit.SECONDS));
+ check(pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
check(pool.getCorePoolSize() == 0);
check(taskRun);
}
--- a/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/ZeroCoreThreads.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/ZeroCoreThreads.java Wed Mar 09 14:18:12 2016 +0100
@@ -35,9 +35,11 @@
* @test
* @bug 8022642 8065320 8129861
* @summary Ensure relative sanity when zero core threads
+ * @library /lib/testlibrary/
*/
import static java.util.concurrent.TimeUnit.HOURS;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import java.lang.reflect.Field;
@@ -45,8 +47,28 @@
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
+import java.util.function.BooleanSupplier;
+import jdk.testlibrary.Utils;
public class ZeroCoreThreads {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
+
+ static long millisElapsedSince(long startTime) {
+ return (System.nanoTime() - startTime) / (1000L * 1000L);
+ }
+
+ static void spinWaitUntil(BooleanSupplier predicate, long timeoutMillis) {
+ long startTime = -1L;
+ while (!predicate.getAsBoolean()) {
+ if (startTime == -1L)
+ startTime = System.nanoTime();
+ else if (millisElapsedSince(startTime) > timeoutMillis)
+ throw new AssertionError(
+ String.format("timed out after %s ms", timeoutMillis));
+ Thread.yield();
+ }
+ }
+
static boolean hasWaiters(ReentrantLock lock, Condition condition) {
lock.lock();
try {
@@ -56,6 +78,11 @@
}
}
+ static void awaitHasWaiters(ReentrantLock lock, Condition condition,
+ long timeoutMillis) {
+ spinWaitUntil(() -> hasWaiters(lock, condition), timeoutMillis);
+ }
+
static <T> T getField(Object x, String fieldName) {
try {
Field field = x.getClass().getDeclaredField(fieldName);
@@ -72,7 +99,7 @@
test(p);
} finally {
p.shutdownNow();
- check(p.awaitTermination(10L, SECONDS));
+ check(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
}
}
@@ -89,13 +116,7 @@
equal(0L, p.getCompletedTaskCount());
p.schedule(dummy, 1L, HOURS);
// Ensure one pool thread actually waits in timed queue poll
- long t0 = System.nanoTime();
- while (!hasWaiters(lock, available)) {
- if (System.nanoTime() - t0 > SECONDS.toNanos(10L))
- throw new AssertionError
- ("timed out waiting for a waiter to show up");
- Thread.yield();
- }
+ awaitHasWaiters(lock, available, LONG_DELAY_MS);
equal(1, p.getPoolSize());
equal(1, p.getLargestPoolSize());
equal(1L, p.getTaskCount());
--- a/jdk/test/java/util/concurrent/ThreadPoolExecutor/CoreThreadTimeOut.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/CoreThreadTimeOut.java Wed Mar 09 14:18:12 2016 +0100
@@ -25,17 +25,22 @@
* @test
* @bug 6233235 6268386
* @summary Test allowsCoreThreadTimeOut
+ * @library /lib/testlibrary/
* @author Martin Buchholz
*/
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
+import jdk.testlibrary.Utils;
public class CoreThreadTimeOut {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static class IdentifiableThreadFactory implements ThreadFactory {
static ThreadFactory defaultThreadFactory
@@ -60,8 +65,8 @@
return count;
}
- static long millisElapsedSince(long t0) {
- return (System.nanoTime() - t0) / (1000L * 1000L);
+ static long millisElapsedSince(long startTime) {
+ return (System.nanoTime() - startTime) / (1000L * 1000L);
}
void test(String[] args) throws Throwable {
@@ -89,7 +94,7 @@
equal(countExecutorThreads(), 0);
tpe.shutdown();
check(tpe.allowsCoreThreadTimeOut());
- check(tpe.awaitTermination(10L, TimeUnit.SECONDS));
+ check(tpe.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
if (failed > 0) throw new Exception("Some tests failed");
--- a/jdk/test/java/util/concurrent/ThreadPoolExecutor/Custom.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/Custom.java Wed Mar 09 14:18:12 2016 +0100
@@ -25,9 +25,12 @@
* @test
* @bug 6277663
* @summary Test TPE extensibility framework
+ * @library /lib/testlibrary/
* @author Martin Buchholz
*/
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
@@ -37,8 +40,11 @@
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.BooleanSupplier;
+import jdk.testlibrary.Utils;
public class Custom {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static volatile int passed = 0, failed = 0;
static void pass() { passed++; }
static void fail() { failed++; Thread.dumpStack(); }
@@ -97,6 +103,22 @@
private static final int threadCount = 10;
+ static long millisElapsedSince(long startTime) {
+ return (System.nanoTime() - startTime) / (1000L * 1000L);
+ }
+
+ static void spinWaitUntil(BooleanSupplier predicate, long timeoutMillis) {
+ long startTime = -1L;
+ while (!predicate.getAsBoolean()) {
+ if (startTime == -1L)
+ startTime = System.nanoTime();
+ else if (millisElapsedSince(startTime) > timeoutMillis)
+ throw new AssertionError(
+ String.format("timed out after %s ms", timeoutMillis));
+ Thread.yield();
+ }
+ }
+
public static void main(String[] args) throws Throwable {
CustomTPE tpe = new CustomTPE();
equal(tpe.getCorePoolSize(), threadCount);
@@ -106,9 +128,8 @@
equal(countExecutorThreads(), threadCount);
equal(CustomTask.births.get(), threadCount);
tpe.shutdown();
- tpe.awaitTermination(120L, TimeUnit.SECONDS);
- Thread.sleep(1000);
- equal(countExecutorThreads(), 0);
+ tpe.awaitTermination(LONG_DELAY_MS, MILLISECONDS);
+ spinWaitUntil(() -> countExecutorThreads() == 0, LONG_DELAY_MS);
CustomSTPE stpe = new CustomSTPE();
for (int i = 0; i < threadCount; i++)
@@ -116,9 +137,8 @@
equal(CustomSTPE.decorations.get(), threadCount);
equal(countExecutorThreads(), threadCount);
stpe.shutdown();
- stpe.awaitTermination(120L, TimeUnit.SECONDS);
- Thread.sleep(1000);
- equal(countExecutorThreads(), 0);
+ stpe.awaitTermination(LONG_DELAY_MS, MILLISECONDS);
+ spinWaitUntil(() -> countExecutorThreads() == 0, LONG_DELAY_MS);
System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
if (failed > 0) throw new Exception("Some tests failed");
--- a/jdk/test/java/util/concurrent/ThreadPoolExecutor/FlakyThreadFactory.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/FlakyThreadFactory.java Wed Mar 09 14:18:12 2016 +0100
@@ -35,14 +35,20 @@
/*
* @test
* @summary Should be able to shutdown a pool when worker creation failed.
+ * @library /lib/testlibrary/
*/
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
+import jdk.testlibrary.Utils;
public class FlakyThreadFactory {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
+
void test(String[] args) throws Throwable {
test(NullPointerException.class,
new ThreadFactory() {
@@ -89,7 +95,7 @@
check(exceptionClass.isInstance(t));
}
pool.shutdown();
- check(pool.awaitTermination(10L, TimeUnit.SECONDS));
+ check(pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
}
//--------------------- Infrastructure ---------------------------
--- a/jdk/test/java/util/concurrent/ThreadPoolExecutor/SelfInterrupt.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/SelfInterrupt.java Wed Mar 09 14:18:12 2016 +0100
@@ -25,14 +25,20 @@
* @test
* @bug 6576792
* @summary non-idle worker threads should not be interrupted
+ * @library /lib/testlibrary/
*/
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
+import jdk.testlibrary.Utils;
public class SelfInterrupt {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
+
void test(String[] args) throws Throwable {
final int n = 100;
final ThreadPoolExecutor pool =
@@ -58,7 +64,7 @@
} catch (Throwable t) { unexpected(t); }}});
finishLine.await();
pool.shutdown();
- check(pool.awaitTermination(1000L, TimeUnit.SECONDS));
+ check(pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
}
//--------------------- Infrastructure ---------------------------
--- a/jdk/test/java/util/concurrent/ThreadPoolExecutor/ThreadRestarts.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/ThreadRestarts.java Wed Mar 09 14:18:12 2016 +0100
@@ -36,6 +36,7 @@
* @test
* @summary Only one thread should be created when a thread needs to
* be kept alive to service a delayed task waiting in the queue.
+ * @library /lib/testlibrary/
*/
import static java.util.concurrent.TimeUnit.MILLISECONDS;
@@ -44,8 +45,12 @@
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicLong;
+import jdk.testlibrary.Utils;
public class ThreadRestarts {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
+ static final long FAR_FUTURE_MS = 10 * LONG_DELAY_MS;
+
public static void main(String[] args) throws Exception {
test(false);
test(true);
@@ -56,14 +61,15 @@
ScheduledThreadPoolExecutor stpe
= new ScheduledThreadPoolExecutor(10, ctf);
try {
+ // schedule a dummy task in the "far future"
Runnable nop = new Runnable() { public void run() {}};
- stpe.schedule(nop, 10*1000L, MILLISECONDS);
+ stpe.schedule(nop, FAR_FUTURE_MS, MILLISECONDS);
stpe.setKeepAliveTime(1L, MILLISECONDS);
stpe.allowCoreThreadTimeOut(allowTimeout);
- MILLISECONDS.sleep(100L);
+ MILLISECONDS.sleep(12L);
} finally {
stpe.shutdownNow();
- if (!stpe.awaitTermination(60L, SECONDS))
+ if (!stpe.awaitTermination(LONG_DELAY_MS, MILLISECONDS))
throw new AssertionError("timed out");
}
if (ctf.count.get() > 1)
@@ -76,8 +82,9 @@
final AtomicLong count = new AtomicLong(0L);
public Thread newThread(Runnable r) {
+ count.getAndIncrement();
Thread t = new Thread(r);
- count.getAndIncrement();
+ t.setDaemon(true);
return t;
}
}
--- a/jdk/test/java/util/concurrent/ThreadPoolExecutor/TimeOutShrink.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/TimeOutShrink.java Wed Mar 09 14:18:12 2016 +0100
@@ -25,15 +25,22 @@
* @test
* @bug 6458662
* @summary poolSize might shrink below corePoolSize after timeout
+ * @library /lib/testlibrary/
* @author Martin Buchholz
*/
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
+import jdk.testlibrary.Utils;
public class TimeOutShrink {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
+ static final long KEEPALIVE_MS = 12L;
+
static void checkPoolSizes(ThreadPoolExecutor pool,
int size, int core, int max) {
equal(pool.getPoolSize(), size);
@@ -45,7 +52,8 @@
final int n = 4;
final CyclicBarrier barrier = new CyclicBarrier(2*n+1);
final ThreadPoolExecutor pool
- = new ThreadPoolExecutor(n, 2*n, 1L, TimeUnit.SECONDS,
+ = new ThreadPoolExecutor(n, 2*n,
+ KEEPALIVE_MS, MILLISECONDS,
new SynchronousQueue<Runnable>());
final Runnable r = new Runnable() { public void run() {
try {
@@ -58,12 +66,16 @@
barrier.await();
checkPoolSizes(pool, 2*n, n, 2*n);
barrier.await();
- while (pool.getPoolSize() > n)
- Thread.sleep(100);
- Thread.sleep(100);
+ long nap = KEEPALIVE_MS + (KEEPALIVE_MS >> 2);
+ for (long sleepyTime = 0L; pool.getPoolSize() > n; ) {
+ check((sleepyTime += nap) <= LONG_DELAY_MS);
+ Thread.sleep(nap);
+ }
+ checkPoolSizes(pool, n, n, 2*n);
+ Thread.sleep(nap);
checkPoolSizes(pool, n, n, 2*n);
pool.shutdown();
- check(pool.awaitTermination(60L, TimeUnit.SECONDS));
+ check(pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
}
//--------------------- Infrastructure ---------------------------
--- a/jdk/test/java/util/concurrent/locks/Lock/CheckedLockLoops.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/concurrent/locks/Lock/CheckedLockLoops.java Wed Mar 09 14:18:12 2016 +0100
@@ -35,9 +35,10 @@
* @test
* @bug 4486658
* @summary basic safety and liveness of ReentrantLocks, and other locks based on them
+ * @library /lib/testlibrary/
*/
-import static java.util.concurrent.TimeUnit.SECONDS;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.util.SplittableRandom;
import java.util.concurrent.CyclicBarrier;
@@ -47,8 +48,10 @@
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
+import jdk.testlibrary.Utils;
public final class CheckedLockLoops {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static ExecutorService pool;
static final SplittableRandom rnd = new SplittableRandom();
@@ -63,7 +66,7 @@
oneTest(i, iters / i);
}
pool.shutdown();
- if (! pool.awaitTermination(10L, SECONDS))
+ if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS))
throw new Error();
pool = null;
}
--- a/jdk/test/java/util/concurrent/locks/Lock/FlakyMutex.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/concurrent/locks/Lock/FlakyMutex.java Wed Mar 09 14:18:12 2016 +0100
@@ -25,9 +25,12 @@
* @test
* @bug 6503247 6574123
* @summary Test resilience to tryAcquire methods that throw
+ * @library /lib/testlibrary/
* @author Martin Buchholz
*/
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
import java.util.Random;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
@@ -36,6 +39,7 @@
import java.util.concurrent.locks.AbstractQueuedLongSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
+import jdk.testlibrary.Utils;
/**
* This uses a variant of the standard Mutex demo, except with a
@@ -44,6 +48,7 @@
*/
@SuppressWarnings("serial")
public class FlakyMutex implements Lock {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static class MyError extends Error {}
static class MyException extends Exception {}
static class MyRuntimeException extends RuntimeException {}
@@ -91,7 +96,7 @@
} catch (Throwable t) { unexpected(t); }}});}
barrier.await();
es.shutdown();
- check(es.awaitTermination(30L, TimeUnit.SECONDS));
+ check(es.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
}
private static class FlakySync extends AbstractQueuedLongSynchronizer {
--- a/jdk/test/java/util/concurrent/locks/Lock/TimedAcquireLeak.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/concurrent/locks/Lock/TimedAcquireLeak.java Wed Mar 09 14:18:12 2016 +0100
@@ -25,9 +25,11 @@
* @test
* @bug 6460501 6236036 6500694 6490770
* @summary Repeated failed timed waits shouldn't leak memory
+ * @library /lib/testlibrary/
* @author Martin Buchholz
*/
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
@@ -54,8 +56,11 @@
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import jdk.testlibrary.Utils;
public class TimedAcquireLeak {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
+
static String javahome() {
String jh = System.getProperty("java.home");
return (jh.endsWith("jre")) ? jh.substring(0, jh.length() - 4) : jh;
@@ -191,7 +196,7 @@
final String[] jobCmd = {
java, "-Xmx8m", "-XX:+UsePerfData",
- "-classpath", System.getProperty("test.classes", "."),
+ "-classpath", System.getProperty("test.class.path"),
childClassName, uniqueID
};
final Process p = new ProcessBuilder(jobCmd).start();
@@ -219,7 +224,7 @@
check(Math.abs(n1 - n0) < 10);
check(n1 < 25);
drainers.shutdown();
- if (!drainers.awaitTermination(10L, SECONDS)) {
+ if (!drainers.awaitTermination(LONG_DELAY_MS, MILLISECONDS)) {
drainers.shutdownNow(); // last resort
throw new AssertionError("thread pool did not terminate");
}
--- a/jdk/test/java/util/concurrent/locks/LockSupport/ParkLoops.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/concurrent/locks/LockSupport/ParkLoops.java Wed Mar 09 14:18:12 2016 +0100
@@ -35,11 +35,12 @@
* @test
* @bug 8074773
* @summary Stress test looks for lost unparks
+ * @library /lib/testlibrary/
* @modules java.management
- * @run main/timeout=1200 ParkLoops
*/
-import static java.util.concurrent.TimeUnit.SECONDS;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.util.SplittableRandom;
@@ -49,13 +50,12 @@
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReferenceArray;
import java.util.concurrent.locks.LockSupport;
+import jdk.testlibrary.Utils;
public final class ParkLoops {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static final int THREADS = 4;
- // static final int ITERS = 2_000_000;
- // static final int TIMEOUT = 3500; // in seconds
- static final int ITERS = 100_000;
- static final int TIMEOUT = 1000; // in seconds
+ static final int ITERS = 30_000;
static class Parker implements Runnable {
static {
@@ -130,13 +130,13 @@
pool.submit(unparker);
}
try {
- if (!done.await(TIMEOUT, SECONDS)) {
+ if (!done.await(LONG_DELAY_MS, MILLISECONDS)) {
dumpAllStacks();
throw new AssertionError("lost unpark");
}
} finally {
pool.shutdown();
- pool.awaitTermination(10L, SECONDS);
+ pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS);
}
}
--- a/jdk/test/java/util/concurrent/locks/ReentrantLock/LockOncePerThreadLoops.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/concurrent/locks/ReentrantLock/LockOncePerThreadLoops.java Wed Mar 09 14:18:12 2016 +0100
@@ -34,25 +34,27 @@
/*
* @test
* @bug 4486658
- * @run main/timeout=15000 LockOncePerThreadLoops
* @summary Checks for missed signals by locking and unlocking each of an array of locks once per thread
+ * @library /lib/testlibrary/
*/
-import static java.util.concurrent.TimeUnit.SECONDS;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.util.SplittableRandom;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.ReentrantLock;
+import jdk.testlibrary.Utils;
public final class LockOncePerThreadLoops {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static final ExecutorService pool = Executors.newCachedThreadPool();
static final SplittableRandom rnd = new SplittableRandom();
static boolean print = false;
- static int nlocks = 50000;
- static int nthreads = 100;
- static int replications = 5;
+ static int nlocks = 20_000;
+ static int nthreads = 20;
+ static int replications = 3;
public static void main(String[] args) throws Exception {
if (args.length > 0)
@@ -66,10 +68,9 @@
for (int i = 0; i < replications; ++i) {
System.out.print("Iteration: " + i);
new ReentrantLockLoop().test();
- Thread.sleep(100);
}
pool.shutdown();
- if (! pool.awaitTermination(60L, SECONDS))
+ if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS))
throw new Error();
}
--- a/jdk/test/java/util/concurrent/locks/ReentrantLock/SimpleReentrantLockLoops.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/concurrent/locks/ReentrantLock/SimpleReentrantLockLoops.java Wed Mar 09 14:18:12 2016 +0100
@@ -34,23 +34,25 @@
/*
* @test
* @bug 4486658
- * @run main/timeout=4500 SimpleReentrantLockLoops
* @summary multiple threads using a single lock
+ * @library /lib/testlibrary/
*/
-import static java.util.concurrent.TimeUnit.SECONDS;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.util.SplittableRandom;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.ReentrantLock;
+import jdk.testlibrary.Utils;
public final class SimpleReentrantLockLoops {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static final ExecutorService pool = Executors.newCachedThreadPool();
static final SplittableRandom rnd = new SplittableRandom();
static boolean print = false;
- static int iters = 1000000;
+ static int iters = 100_000;
public static void main(String[] args) throws Exception {
int maxThreads = 5;
@@ -66,11 +68,10 @@
while (n-- > 0) {
System.out.print("Threads: " + i);
new ReentrantLockLoop(i).test();
- Thread.sleep(100);
}
}
pool.shutdown();
- if (! pool.awaitTermination(60L, SECONDS))
+ if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS))
throw new Error();
}
--- a/jdk/test/java/util/concurrent/locks/ReentrantLock/TimeoutLockLoops.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/concurrent/locks/ReentrantLock/TimeoutLockLoops.java Wed Mar 09 14:18:12 2016 +0100
@@ -34,18 +34,22 @@
/*
* @test
* @bug 4486658 5031862 8140471
- * @run main TimeoutLockLoops
* @summary Checks for responsiveness of locks to timeouts.
+ * @library /lib/testlibrary/
*/
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
import java.util.SplittableRandom;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
+import jdk.testlibrary.Utils;
public final class TimeoutLockLoops {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static final ExecutorService pool = Executors.newCachedThreadPool();
static final SplittableRandom rnd = new SplittableRandom();
static boolean print = false;
@@ -63,7 +67,7 @@
new ReentrantLockLoop(i).test();
}
pool.shutdown();
- if (! pool.awaitTermination(60L, TimeUnit.SECONDS))
+ if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS))
throw new Error();
}
--- a/jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/Count.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/Count.java Wed Mar 09 14:18:12 2016 +0100
@@ -25,9 +25,12 @@
* @test
* @bug 6207928 6328220 6378321 6625723
* @summary Recursive lock invariant sanity checks
+ * @library /lib/testlibrary/
* @author Martin Buchholz
*/
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -42,9 +45,11 @@
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
+import jdk.testlibrary.Utils;
// I am the Cownt, and I lahve to cownt.
public class Count {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
final Random rnd = new Random();
void lock(Lock lock) {
@@ -102,7 +107,7 @@
barrier.await();
} catch (Throwable t) { unexpected(t); }}});}
es.shutdown();
- check(es.awaitTermination(10L, TimeUnit.SECONDS));
+ check(es.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
}
void testReentrantLocks(final boolean fair,
--- a/jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/MapLoops.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/MapLoops.java Wed Mar 09 14:18:12 2016 +0100
@@ -41,17 +41,20 @@
* inserts it, and if present, with probability premove it removes
* it. (pinsert and premove are expressed as percentages to simplify
* parsing from command line.)
+ * @library /lib/testlibrary/
*/
-import static java.util.concurrent.TimeUnit.SECONDS;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.util.Map;
import java.util.SplittableRandom;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import jdk.testlibrary.Utils;
public class MapLoops {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static final int NKEYS = 100000;
static int pinsert = 60;
static int premove = 2;
@@ -125,7 +128,7 @@
map.clear();
}
pool.shutdown();
- if (! pool.awaitTermination(10L, SECONDS))
+ if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS))
throw new Error();
}
--- a/jdk/test/java/util/concurrent/locks/StampedLock/Basic.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/concurrent/locks/StampedLock/Basic.java Wed Mar 09 14:18:12 2016 +0100
@@ -35,6 +35,7 @@
* @test
* @bug 8005697
* @summary Basic tests for StampedLock
+ * @library /lib/testlibrary/
* @author Chris Hegarty
*/
@@ -49,8 +50,10 @@
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.StampedLock;
+import jdk.testlibrary.Utils;
public class Basic {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static void checkResult(Locker l, Class<? extends Throwable> c) {
Throwable t = l.thrown();
@@ -268,7 +271,7 @@
case 2: case 5:
return interruptibleReader(sl, -1, SECONDS, gate, view ^= true);
default:
- return interruptibleReader(sl, 30, SECONDS, gate, view ^= true); }}
+ return interruptibleReader(sl, LONG_DELAY_MS, MILLISECONDS, gate, view ^= true); }}
public void remove() {throw new UnsupportedOperationException();}};
}
@@ -286,7 +289,7 @@
case 2: case 5:
return interruptibleWriter(sl, -1, SECONDS, gate, view ^= true);
default:
- return interruptibleWriter(sl, 30, SECONDS, gate, view ^= true); }}
+ return interruptibleWriter(sl, LONG_DELAY_MS, MILLISECONDS, gate, view ^= true); }}
public void remove() {throw new UnsupportedOperationException();}};
}
@@ -454,13 +457,13 @@
// We test interrupting both before and after trying to acquire
boolean view = false;
StampedLock sl = new StampedLock();
- for (long timeout : new long[] { -1L, 30L, -1L, 30L }) {
+ for (long timeout : new long[] { -1L, LONG_DELAY_MS, -1L, LONG_DELAY_MS }) {
long stamp;
Thread.State state;
stamp = sl.writeLock();
try {
- Reader r = interruptibleReader(sl, timeout, SECONDS, null, view);
+ Reader r = interruptibleReader(sl, timeout, MILLISECONDS, null, view);
r.start();
r.interrupt();
r.join();
@@ -471,7 +474,7 @@
stamp = sl.writeLock();
try {
- Reader r = interruptibleReader(sl, timeout, SECONDS, null, view);
+ Reader r = interruptibleReader(sl, timeout, MILLISECONDS, null, view);
r.start();
waitForThreadToBlock(r);
r.interrupt();
@@ -483,7 +486,7 @@
stamp = sl.readLock();
try {
- Writer w = interruptibleWriter(sl, timeout, SECONDS, null, view);
+ Writer w = interruptibleWriter(sl, timeout, MILLISECONDS, null, view);
w.start();
w.interrupt();
w.join();
@@ -494,7 +497,7 @@
stamp = sl.readLock();
try {
- Writer w = interruptibleWriter(sl, timeout, SECONDS, null, view);
+ Writer w = interruptibleWriter(sl, timeout, MILLISECONDS, null, view);
w.start();
waitForThreadToBlock(w);
w.interrupt();
@@ -509,7 +512,7 @@
check(!sl.tryUnlockRead());
check(!sl.tryUnlockWrite());
check(sl.tryOptimisticRead() != 0L);
- if (timeout == 30L)
+ if (timeout == LONG_DELAY_MS)
view = true;
}
} catch (Throwable t) { unexpected(t); }
--- a/jdk/test/java/util/concurrent/tck/Collection8Test.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/concurrent/tck/Collection8Test.java Wed Mar 09 14:18:12 2016 +0100
@@ -37,6 +37,7 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
@@ -98,26 +99,29 @@
public void testForEachConcurrentStressTest() throws Throwable {
if (!impl.isConcurrent()) return;
final Collection c = impl.emptyCollection();
- final long testDurationMillis = SHORT_DELAY_MS;
+ final long testDurationMillis = timeoutMillis();
final AtomicBoolean done = new AtomicBoolean(false);
final Object elt = impl.makeElement(1);
- ExecutorService pool = Executors.newCachedThreadPool();
- Runnable checkElt = () -> {
- while (!done.get())
- c.stream().forEach((x) -> { assertSame(x, elt); }); };
- Runnable addRemove = () -> {
- while (!done.get()) {
- assertTrue(c.add(elt));
- assertTrue(c.remove(elt));
- }};
- Future<?> f1 = pool.submit(checkElt);
- Future<?> f2 = pool.submit(addRemove);
- Thread.sleep(testDurationMillis);
- done.set(true);
- pool.shutdown();
- assertTrue(pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
- assertNull(f1.get(LONG_DELAY_MS, MILLISECONDS));
- assertNull(f2.get(LONG_DELAY_MS, MILLISECONDS));
+ final Future<?> f1, f2;
+ final ExecutorService pool = Executors.newCachedThreadPool();
+ try (PoolCleaner cleaner = cleaner(pool, done)) {
+ final CountDownLatch threadsStarted = new CountDownLatch(2);
+ Runnable checkElt = () -> {
+ threadsStarted.countDown();
+ while (!done.get())
+ c.stream().forEach((x) -> { assertSame(x, elt); }); };
+ Runnable addRemove = () -> {
+ threadsStarted.countDown();
+ while (!done.get()) {
+ assertTrue(c.add(elt));
+ assertTrue(c.remove(elt));
+ }};
+ f1 = pool.submit(checkElt);
+ f2 = pool.submit(addRemove);
+ Thread.sleep(testDurationMillis);
+ }
+ assertNull(f1.get(0L, MILLISECONDS));
+ assertNull(f2.get(0L, MILLISECONDS));
}
// public void testCollection8DebugFail() { fail(); }
--- a/jdk/test/java/util/concurrent/tck/JSR166TestCase.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/concurrent/tck/JSR166TestCase.java Wed Mar 09 14:18:12 2016 +0100
@@ -88,6 +88,7 @@
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -210,11 +211,31 @@
private static final int suiteRuns =
Integer.getInteger("jsr166.suiteRuns", 1);
+ private static float systemPropertyValue(String name, float defaultValue) {
+ String floatString = System.getProperty(name);
+ if (floatString == null)
+ return defaultValue;
+ try {
+ return Float.parseFloat(floatString);
+ } catch (NumberFormatException ex) {
+ throw new IllegalArgumentException(
+ String.format("Bad float value in system property %s=%s",
+ name, floatString));
+ }
+ }
+
/**
* The scaling factor to apply to standard delays used in tests.
*/
- private static final int delayFactor =
- Integer.getInteger("jsr166.delay.factor", 1);
+ private static final float delayFactor =
+ systemPropertyValue("jsr166.delay.factor", 1.0f);
+
+ /**
+ * The timeout factor as used in the jtreg test harness.
+ * See: http://openjdk.java.net/jtreg/tag-spec.html
+ */
+ private static final float jtregTestTimeoutFactor
+ = systemPropertyValue("test.timeout.factor", 1.0f);
public JSR166TestCase() { super(); }
public JSR166TestCase(String name) { super(name); }
@@ -590,10 +611,12 @@
/**
* Returns the shortest timed delay. This can be scaled up for
- * slow machines using the jsr166.delay.factor system property.
+ * slow machines using the jsr166.delay.factor system property,
+ * or via jtreg's -timeoutFactor: flag.
+ * http://openjdk.java.net/jtreg/command-help.html
*/
protected long getShortDelay() {
- return 50 * delayFactor;
+ return (long) (50 * delayFactor * jtregTestTimeoutFactor);
}
/**
@@ -906,6 +929,14 @@
}};
}
+ PoolCleaner cleaner(ExecutorService pool, AtomicBoolean flag) {
+ return new PoolCleanerWithReleaser(pool, releaser(flag));
+ }
+
+ Runnable releaser(final AtomicBoolean flag) {
+ return new Runnable() { public void run() { flag.set(true); }};
+ }
+
/**
* Waits out termination of a thread pool or fails doing so.
*/
@@ -1462,16 +1493,20 @@
return new LatchAwaiter(latch);
}
- public void await(CountDownLatch latch) {
+ public void await(CountDownLatch latch, long timeoutMillis) {
try {
- if (!latch.await(LONG_DELAY_MS, MILLISECONDS))
+ if (!latch.await(timeoutMillis, MILLISECONDS))
fail("timed out waiting for CountDownLatch for "
- + (LONG_DELAY_MS/1000) + " sec");
+ + (timeoutMillis/1000) + " sec");
} catch (Throwable fail) {
threadUnexpectedException(fail);
}
}
+ public void await(CountDownLatch latch) {
+ await(latch, LONG_DELAY_MS);
+ }
+
public void await(Semaphore semaphore) {
try {
if (!semaphore.tryAcquire(LONG_DELAY_MS, MILLISECONDS))
--- a/jdk/test/java/util/concurrent/tck/ScheduledExecutorSubclassTest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/concurrent/tck/ScheduledExecutorSubclassTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -32,6 +32,7 @@
*/
import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static java.util.concurrent.TimeUnit.NANOSECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import java.util.ArrayList;
@@ -55,7 +56,9 @@
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
import junit.framework.Test;
import junit.framework.TestSuite;
@@ -226,52 +229,75 @@
}
/**
- * scheduleAtFixedRate executes series of tasks at given rate
+ * scheduleAtFixedRate executes series of tasks at given rate.
+ * Eventually, it must hold that:
+ * cycles - 1 <= elapsedMillis/delay < cycles
*/
public void testFixedRateSequence() throws InterruptedException {
final CustomExecutor p = new CustomExecutor(1);
try (PoolCleaner cleaner = cleaner(p)) {
for (int delay = 1; delay <= LONG_DELAY_MS; delay *= 3) {
- long startTime = System.nanoTime();
- int cycles = 10;
+ final long startTime = System.nanoTime();
+ final int cycles = 8;
final CountDownLatch done = new CountDownLatch(cycles);
- Runnable task = new CheckedRunnable() {
+ final Runnable task = new CheckedRunnable() {
public void realRun() { done.countDown(); }};
- ScheduledFuture h =
+ final ScheduledFuture periodicTask =
p.scheduleAtFixedRate(task, 0, delay, MILLISECONDS);
- await(done);
- h.cancel(true);
- double normalizedTime =
- (double) millisElapsedSince(startTime) / delay;
- if (normalizedTime >= cycles - 1 &&
- normalizedTime <= cycles)
+ final int totalDelayMillis = (cycles - 1) * delay;
+ await(done, totalDelayMillis + LONG_DELAY_MS);
+ periodicTask.cancel(true);
+ final long elapsedMillis = millisElapsedSince(startTime);
+ assertTrue(elapsedMillis >= totalDelayMillis);
+ if (elapsedMillis <= cycles * delay)
return;
+ // else retry with longer delay
}
fail("unexpected execution rate");
}
}
/**
- * scheduleWithFixedDelay executes series of tasks with given period
+ * scheduleWithFixedDelay executes series of tasks with given period.
+ * Eventually, it must hold that each task starts at least delay and at
+ * most 2 * delay after the termination of the previous task.
*/
public void testFixedDelaySequence() throws InterruptedException {
final CustomExecutor p = new CustomExecutor(1);
try (PoolCleaner cleaner = cleaner(p)) {
for (int delay = 1; delay <= LONG_DELAY_MS; delay *= 3) {
- long startTime = System.nanoTime();
- int cycles = 10;
+ final long startTime = System.nanoTime();
+ final AtomicLong previous = new AtomicLong(startTime);
+ final AtomicBoolean tryLongerDelay = new AtomicBoolean(false);
+ final int cycles = 8;
final CountDownLatch done = new CountDownLatch(cycles);
- Runnable task = new CheckedRunnable() {
- public void realRun() { done.countDown(); }};
- ScheduledFuture h =
+ final int d = delay;
+ final Runnable task = new CheckedRunnable() {
+ public void realRun() {
+ long now = System.nanoTime();
+ long elapsedMillis
+ = NANOSECONDS.toMillis(now - previous.get());
+ if (done.getCount() == cycles) { // first execution
+ if (elapsedMillis >= d)
+ tryLongerDelay.set(true);
+ } else {
+ assertTrue(elapsedMillis >= d);
+ if (elapsedMillis >= 2 * d)
+ tryLongerDelay.set(true);
+ }
+ previous.set(now);
+ done.countDown();
+ }};
+ final ScheduledFuture periodicTask =
p.scheduleWithFixedDelay(task, 0, delay, MILLISECONDS);
- await(done);
- h.cancel(true);
- double normalizedTime =
- (double) millisElapsedSince(startTime) / delay;
- if (normalizedTime >= cycles - 1 &&
- normalizedTime <= cycles)
+ final int totalDelayMillis = (cycles - 1) * delay;
+ await(done, totalDelayMillis + cycles * LONG_DELAY_MS);
+ periodicTask.cancel(true);
+ final long elapsedMillis = millisElapsedSince(startTime);
+ assertTrue(elapsedMillis >= totalDelayMillis);
+ if (!tryLongerDelay.get())
return;
+ // else retry with longer delay
}
fail("unexpected execution rate");
}
--- a/jdk/test/java/util/concurrent/tck/ScheduledExecutorTest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/concurrent/tck/ScheduledExecutorTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -34,6 +34,7 @@
*/
import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static java.util.concurrent.TimeUnit.NANOSECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import java.util.ArrayList;
@@ -52,7 +53,9 @@
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
import junit.framework.Test;
import junit.framework.TestSuite;
@@ -170,52 +173,75 @@
}
/**
- * scheduleAtFixedRate executes series of tasks at given rate
+ * scheduleAtFixedRate executes series of tasks at given rate.
+ * Eventually, it must hold that:
+ * cycles - 1 <= elapsedMillis/delay < cycles
*/
public void testFixedRateSequence() throws InterruptedException {
final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
try (PoolCleaner cleaner = cleaner(p)) {
for (int delay = 1; delay <= LONG_DELAY_MS; delay *= 3) {
- long startTime = System.nanoTime();
- int cycles = 10;
+ final long startTime = System.nanoTime();
+ final int cycles = 8;
final CountDownLatch done = new CountDownLatch(cycles);
- Runnable task = new CheckedRunnable() {
+ final Runnable task = new CheckedRunnable() {
public void realRun() { done.countDown(); }};
- ScheduledFuture h =
+ final ScheduledFuture periodicTask =
p.scheduleAtFixedRate(task, 0, delay, MILLISECONDS);
- await(done);
- h.cancel(true);
- double normalizedTime =
- (double) millisElapsedSince(startTime) / delay;
- if (normalizedTime >= cycles - 1 &&
- normalizedTime <= cycles)
+ final int totalDelayMillis = (cycles - 1) * delay;
+ await(done, totalDelayMillis + LONG_DELAY_MS);
+ periodicTask.cancel(true);
+ final long elapsedMillis = millisElapsedSince(startTime);
+ assertTrue(elapsedMillis >= totalDelayMillis);
+ if (elapsedMillis <= cycles * delay)
return;
+ // else retry with longer delay
}
fail("unexpected execution rate");
}
}
/**
- * scheduleWithFixedDelay executes series of tasks with given period
+ * scheduleWithFixedDelay executes series of tasks with given period.
+ * Eventually, it must hold that each task starts at least delay and at
+ * most 2 * delay after the termination of the previous task.
*/
public void testFixedDelaySequence() throws InterruptedException {
final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
try (PoolCleaner cleaner = cleaner(p)) {
for (int delay = 1; delay <= LONG_DELAY_MS; delay *= 3) {
- long startTime = System.nanoTime();
- int cycles = 10;
+ final long startTime = System.nanoTime();
+ final AtomicLong previous = new AtomicLong(startTime);
+ final AtomicBoolean tryLongerDelay = new AtomicBoolean(false);
+ final int cycles = 8;
final CountDownLatch done = new CountDownLatch(cycles);
- Runnable task = new CheckedRunnable() {
- public void realRun() { done.countDown(); }};
- ScheduledFuture h =
+ final int d = delay;
+ final Runnable task = new CheckedRunnable() {
+ public void realRun() {
+ long now = System.nanoTime();
+ long elapsedMillis
+ = NANOSECONDS.toMillis(now - previous.get());
+ if (done.getCount() == cycles) { // first execution
+ if (elapsedMillis >= d)
+ tryLongerDelay.set(true);
+ } else {
+ assertTrue(elapsedMillis >= d);
+ if (elapsedMillis >= 2 * d)
+ tryLongerDelay.set(true);
+ }
+ previous.set(now);
+ done.countDown();
+ }};
+ final ScheduledFuture periodicTask =
p.scheduleWithFixedDelay(task, 0, delay, MILLISECONDS);
- await(done);
- h.cancel(true);
- double normalizedTime =
- (double) millisElapsedSince(startTime) / delay;
- if (normalizedTime >= cycles - 1 &&
- normalizedTime <= cycles)
+ final int totalDelayMillis = (cycles - 1) * delay;
+ await(done, totalDelayMillis + cycles * LONG_DELAY_MS);
+ periodicTask.cancel(true);
+ final long elapsedMillis = millisElapsedSince(startTime);
+ assertTrue(elapsedMillis >= totalDelayMillis);
+ if (!tryLongerDelay.get())
return;
+ // else retry with longer delay
}
fail("unexpected execution rate");
}
--- a/jdk/test/java/util/concurrent/tck/ThreadTest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/concurrent/tck/ThreadTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -77,7 +77,7 @@
*/
public void testGetAndSetDefaultUncaughtExceptionHandler() {
assertEquals(null, Thread.getDefaultUncaughtExceptionHandler());
- // failure due to securityException is OK.
+ // failure due to SecurityException is OK.
// Would be nice to explicitly test both ways, but cannot yet.
Thread.UncaughtExceptionHandler defaultHandler
= Thread.getDefaultUncaughtExceptionHandler();
--- a/jdk/test/java/util/jar/JarFile/MultiReleaseJarAPI.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/jar/JarFile/MultiReleaseJarAPI.java Wed Mar 09 14:18:12 2016 +0100
@@ -39,9 +39,9 @@
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
+import jdk.Version;
import static java.util.jar.JarFile.Release;
-import static sun.misc.Version.jdkMajorVersion; // fixme JEP 223 Version
import org.testng.Assert;
import org.testng.annotations.AfterClass;
@@ -50,6 +50,9 @@
public class MultiReleaseJarAPI {
+
+ static final int MAJOR_VERSION = Version.current().major();
+
String userdir = System.getProperty("user.dir",".");
File unversioned = new File(userdir, "unversioned.jar");
File multirelease = new File(userdir, "multi-release.jar");
@@ -106,7 +109,7 @@
}
// assure that we have a Release object corresponding to the actual runtime version
- String version = "VERSION_" + jdkMajorVersion();
+ String version = "VERSION_" + MAJOR_VERSION;
boolean runtimeVersionExists = false;
for (Release value : values) {
if (version.equals(value.name())) runtimeVersionExists = true;
@@ -123,7 +126,7 @@
if (name.equals("BASE")) {
prefix = "";
} else if (name.equals("RUNTIME")) {
- prefix = "META-INF/versions/" + jdkMajorVersion() + "/";
+ prefix = "META-INF/versions/" + MAJOR_VERSION + "/";
} else {
prefix = "META-INF/versions/" + name.substring(8) + "/";
}
--- a/jdk/test/java/util/jar/JarFile/MultiReleaseJarIterators.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/jar/JarFile/MultiReleaseJarIterators.java Wed Mar 09 14:18:12 2016 +0100
@@ -42,9 +42,9 @@
import java.util.jar.JarFile;
import java.util.stream.Collectors;
import java.util.zip.ZipFile;
+import jdk.Version;
import static java.util.jar.JarFile.Release;
-import static sun.misc.Version.jdkMajorVersion; // fixme JEP 223 Version
import org.testng.Assert;
import org.testng.annotations.AfterClass;
@@ -53,6 +53,9 @@
public class MultiReleaseJarIterators {
+
+ static final int MAJOR_VERSION = Version.current().major();
+
String userdir = System.getProperty("user.dir", ".");
File unversioned = new File(userdir, "unversioned.jar");
File multirelease = new File(userdir, "multi-release.jar");
@@ -121,7 +124,7 @@
try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, Release.RUNTIME)) {
Map<String,JarEntry> expectedEntries;
- switch (jdkMajorVersion()) {
+ switch (MAJOR_VERSION) {
case 9:
expectedEntries = v9Entries;
break;
--- a/jdk/test/java/util/jar/JarFile/MultiReleaseJarProperties.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/jar/JarFile/MultiReleaseJarProperties.java Wed Mar 09 14:18:12 2016 +0100
@@ -54,8 +54,7 @@
import java.nio.file.Files;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
-
-import static sun.misc.Version.jdkMajorVersion; // fixme JEP 223 Version
+import jdk.Version;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
@@ -63,6 +62,9 @@
import org.testng.annotations.Test;
public class MultiReleaseJarProperties {
+
+ static final int MAJOR_VERSION = Version.current().major();
+
final static int ROOTVERSION = 8; // magic number from knowledge of internals
final static String userdir = System.getProperty("user.dir", ".");
final static File multirelease = new File(userdir, "multi-release.jar");
@@ -77,14 +79,14 @@
creator.compileEntries();
creator.buildMultiReleaseJar();
- rtVersion = Integer.getInteger("jdk.util.jar.version", jdkMajorVersion());
+ rtVersion = Integer.getInteger("jdk.util.jar.version", MAJOR_VERSION);
String mrprop = System.getProperty("jdk.util.jar.enableMultiRelease", "");
if (mrprop.equals("false")) {
rtVersion = ROOTVERSION;
} else if (rtVersion < ROOTVERSION) {
rtVersion = ROOTVERSION;
- } else if (rtVersion > jdkMajorVersion()) {
- rtVersion = jdkMajorVersion();
+ } else if (rtVersion > MAJOR_VERSION) {
+ rtVersion = MAJOR_VERSION;
}
force = mrprop.equals("force");
--- a/jdk/test/java/util/jar/JarFile/MultiReleaseJarSecurity.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/jar/JarFile/MultiReleaseJarSecurity.java Wed Mar 09 14:18:12 2016 +0100
@@ -40,6 +40,7 @@
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.zip.ZipFile;
+import jdk.Version;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
@@ -47,6 +48,9 @@
import org.testng.annotations.Test;
public class MultiReleaseJarSecurity {
+
+ static final int MAJOR_VERSION = Version.current().major();
+
String userdir = System.getProperty("user.dir",".");
File multirelease = new File(userdir, "multi-release.jar");
File signedmultirelease = new File(userdir, "signed-multi-release.jar");
@@ -68,9 +72,8 @@
@Test
public void testCertsAndSigners() throws IOException {
try (JarFile jf = new JarFile(signedmultirelease, true, ZipFile.OPEN_READ, JarFile.Release.RUNTIME)) {
- int version = sun.misc.Version.jdkMajorVersion(); // fixme JEP 223 Version
CertsAndSigners vcas = new CertsAndSigners(jf, jf.getJarEntry("version/Version.class"));
- CertsAndSigners rcas = new CertsAndSigners(jf, jf.getJarEntry("META-INF/versions/" + version + "/version/Version.class"));
+ CertsAndSigners rcas = new CertsAndSigners(jf, jf.getJarEntry("META-INF/versions/" + MAJOR_VERSION + "/version/Version.class"));
Assert.assertTrue(Arrays.equals(rcas.getCertificates(), vcas.getCertificates()));
Assert.assertTrue(Arrays.equals(rcas.getCodeSigners(), vcas.getCodeSigners()));
}
--- a/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/DoubleStreamTestDataProvider.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/DoubleStreamTestDataProvider.java Wed Mar 09 14:18:12 2016 +0100
@@ -126,6 +126,9 @@
() -> Spliterators.spliterator(isl.iterator(), doubles.length, 0)));
spliterators.add(splitDescr("Primitives.s(SpinedBuffer.iterator()):" + name,
() -> Spliterators.spliteratorUnknownSize(isl.iterator(), 0)));
+ spliterators.add(splitDescr("DoubleStream.iterate(0,x->x<l;x->x+1):" + name,
+ () -> DoubleStream.iterate(0.0, x -> x < doubles.length, x -> x + 1.0)
+ .spliterator()));
// Need more!
}
spliteratorTestData = spliterators.toArray(new Object[0][]);
--- a/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/IntStreamTestDataProvider.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/IntStreamTestDataProvider.java Wed Mar 09 14:18:12 2016 +0100
@@ -136,6 +136,8 @@
() -> IntStream.range(0, ints.length).spliterator()));
spliterators.add(splitDescr("IntStream.intRangeClosed(0,l):" + name,
() -> IntStream.rangeClosed(0, ints.length).spliterator()));
+ spliterators.add(splitDescr("IntStream.iterate(0,x->x<l,x->x+1): " + name,
+ () -> IntStream.iterate(0, x -> x < ints.length, x -> x + 1).spliterator()));
// Need more!
}
spliteratorTestData = spliterators.toArray(new Object[0][]);
--- a/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/LongStreamTestDataProvider.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/LongStreamTestDataProvider.java Wed Mar 09 14:18:12 2016 +0100
@@ -136,6 +136,9 @@
() -> LongStream.range(0, longs.length).spliterator()));
spliterators.add(splitDescr("LongStream.longRangeClosed(0,l):" + name,
() -> LongStream.rangeClosed(0, longs.length).spliterator()));
+ spliterators.add(splitDescr("LongStream.iterate(0,x->x<l;x->x+1):" + name,
+ () -> LongStream.iterate(0L, x -> x < longs.length, x -> x + 1L)
+ .spliterator()));
// Need more!
}
spliteratorTestData = spliterators.toArray(new Object[0][]);
--- a/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/StreamTestDataProvider.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/StreamTestDataProvider.java Wed Mar 09 14:18:12 2016 +0100
@@ -171,6 +171,8 @@
() -> Spliterators.spliterator(Arrays.asList(ints).iterator(), ints.length, 0)));
spliterators.add(splitDescr("Iterators.s(Arrays.s(array).iterator()):" + name,
() -> Spliterators.spliteratorUnknownSize(Arrays.asList(ints).iterator(), 0)));
+ spliterators.add(splitDescr("Stream.iterate(0,x->x<l,x->x+1): " + name,
+ () -> Stream.iterate(0, x -> x < ints.length, x -> x + 1).spliterator()));
// @@@ Add map and collection spliterators when spliterator() is exposed on Collection or Iterable
}
spliteratorTestData = spliterators.toArray(new Object[0][]);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/IterateTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,100 @@
+/*
+ * 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
+ * @bug 8072727
+ */
+
+package org.openjdk.tests.java.util.stream;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.DoubleStream;
+import java.util.stream.IntStream;
+import java.util.stream.LongStream;
+import java.util.stream.OpTestCase;
+import java.util.stream.Stream;
+import java.util.stream.TestData;
+import java.util.stream.TestData.Factory;
+
+import static java.util.stream.ThowableHelper.checkNPE;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+@Test
+public class IterateTest extends OpTestCase {
+
+ @DataProvider(name = "IterateStreamsData")
+ public static Object[][] makeIterateStreamsTestData() {
+ Object[][] data = {
+ {List.of(),
+ Factory.ofSupplier("ref.empty", () -> Stream.iterate(1, x -> x < 0, x -> x * 2))},
+ {List.of(1),
+ Factory.ofSupplier("ref.one", () -> Stream.iterate(1, x -> x < 2, x -> x * 2))},
+ {List.of(1, 2, 4, 8, 16, 32, 64, 128, 256, 512),
+ Factory.ofSupplier("ref.ten", () -> Stream.iterate(1, x -> x < 1000, x -> x * 2))},
+ {List.of(10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0),
+ Factory.ofSupplier("ref.nullCheck", () -> Stream.iterate(10, Objects::nonNull, x -> x > 0 ? x - 1 : null))},
+ {List.of(),
+ Factory.ofIntSupplier("int.empty", () -> IntStream.iterate(1, x -> x < 0, x -> x + 1))},
+ {List.of(1),
+ Factory.ofIntSupplier("int.one", () -> IntStream.iterate(1, x -> x < 2, x -> x + 1))},
+ {List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
+ Factory.ofIntSupplier("int.ten", () -> IntStream.iterate(1, x -> x <= 10, x -> x + 1))},
+ {List.of(5, 4, 3, 2, 1),
+ Factory.ofIntSupplier("int.divZero", () -> IntStream.iterate(5, x -> x != 0, x -> x - 1/x/2 - 1))},
+ {List.of(),
+ Factory.ofLongSupplier("long.empty", () -> LongStream.iterate(1L, x -> x < 0, x -> x + 1))},
+ {List.of(1L),
+ Factory.ofLongSupplier("long.one", () -> LongStream.iterate(1L, x -> x < 2, x -> x + 1))},
+ {List.of(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L),
+ Factory.ofLongSupplier("long.ten", () -> LongStream.iterate(1L, x -> x <= 10, x -> x + 1))},
+ {List.of(),
+ Factory.ofDoubleSupplier("double.empty", () -> DoubleStream.iterate(1.0, x -> x < 0, x -> x + 1))},
+ {List.of(1.0),
+ Factory.ofDoubleSupplier("double.one", () -> DoubleStream.iterate(1.0, x -> x < 2, x -> x + 1))},
+ {List.of(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0),
+ Factory.ofDoubleSupplier("double.ten", () -> DoubleStream.iterate(1.0, x -> x <= 10, x -> x + 1))}
+ };
+ return data;
+ }
+
+ @Test(dataProvider = "IterateStreamsData")
+ public <T> void testIterate(List<T> expected, TestData<T, ?> data) {
+ withData(data).stream(s -> s).expectedResult(expected).exercise();
+ }
+
+ @Test
+ public void testNPE() {
+ checkNPE(() -> Stream.iterate("", null, x -> x + "a"));
+ checkNPE(() -> Stream.iterate("", String::isEmpty, null));
+ checkNPE(() -> IntStream.iterate(0, null, x -> x + 1));
+ checkNPE(() -> IntStream.iterate(0, x -> x < 10, null));
+ checkNPE(() -> LongStream.iterate(0, null, x -> x + 1));
+ checkNPE(() -> LongStream.iterate(0, x -> x < 10, null));
+ checkNPE(() -> DoubleStream.iterate(0, null, x -> x + 1));
+ checkNPE(() -> DoubleStream.iterate(0, x -> x < 10, null));
+ }
+}
--- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamCloseTest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamCloseTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -24,7 +24,7 @@
/*
* @test
* @summary close handlers and closing streams
- * @bug 8044047
+ * @bug 8044047 8147505
*/
package org.openjdk.tests.java.util.stream;
@@ -37,6 +37,7 @@
import static java.util.stream.LambdaTestHelpers.countTo;
import static java.util.stream.ThowableHelper.checkNPE;
+import static java.util.stream.ThowableHelper.checkISE;
@Test(groups = { "serialization-hostile" })
public class StreamCloseTest extends OpTestCase {
@@ -170,4 +171,21 @@
for (int i=0; i<n-1; i++)
assertTrue(e.getSuppressed()[i].getMessage().equals(String.valueOf(i + 2)));
}
+
+ public void testConsumed() {
+ try(Stream<Integer> s = countTo(100).stream()) {
+ s.forEach(i -> {});
+ // Adding onClose handler when stream is consumed is illegal
+ // handler must not be registered
+ checkISE(() -> s.onClose(() -> fail("1")));
+ }
+
+ // close() must be idempotent:
+ // second close() invoked at the end of try-with-resources must have no effect
+ try(Stream<Integer> s = countTo(100).stream()) {
+ s.close();
+ // Adding onClose handler when stream is closed is also illegal
+ checkISE(() -> s.onClose(() -> fail("3")));
+ }
+ }
}
--- a/jdk/test/java/util/zip/TestLocalTime.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/java/util/zip/TestLocalTime.java Wed Mar 09 14:18:12 2016 +0100
@@ -24,7 +24,6 @@
/*
* @test
* @bug 8075526 8135108
- * @key intermittent
* @summary Test timestamp via ZipEntry.get/setTimeLocal()
*/
--- a/jdk/test/javax/management/mxbean/MXBeanLoadingTest1.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/javax/management/mxbean/MXBeanLoadingTest1.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -33,7 +33,6 @@
import java.lang.ref.WeakReference;
import java.net.URL;
-import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.Map;
import javax.management.Attribute;
@@ -70,16 +69,16 @@
+ " some little extra check of Descriptors, MBean*Info.");
ClassLoader myClassLoader = MXBeanLoadingTest1.class.getClassLoader();
+ if(myClassLoader == null)
+ throw new RuntimeException("Test Failed : Null Classloader for test");
+ URL url = myClassLoader.getResource(
+ MXBeanLoadingTest1.class.getCanonicalName()
+ .replace(".", "/") + ".class");
+ String clsLoadPath = url.toURI().toString().
+ replaceAll(MXBeanLoadingTest1.class.getSimpleName()
+ + ".class", "");
- if (!(myClassLoader instanceof URLClassLoader)) {
- String message = "(ERROR) Test's class loader is not " +
- "a URLClassLoader";
- System.out.println(message);
- throw new RuntimeException(message);
- }
-
- URLClassLoader myURLClassLoader = (URLClassLoader) myClassLoader;
- URL[] urls = myURLClassLoader.getURLs();
+ URL[] urls = new URL[]{new URL(clsLoadPath)};
PrivateMLet mlet = new PrivateMLet(urls, null, false);
Class<?> shadowClass = mlet.loadClass(TestMXBean.class.getName());
--- a/jdk/test/jdk/nio/zipfs/MultiReleaseJarTest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/jdk/nio/zipfs/MultiReleaseJarTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -44,7 +44,7 @@
import org.testng.annotations.*;
public class MultiReleaseJarTest {
- final private int MAJOR_VERSION= Version.current().major();
+ final private int MAJOR_VERSION = Version.current().major();
final private String userdir = System.getProperty("user.dir",".");
final private Map<String,String> stringEnv = new HashMap<>();
--- a/jdk/test/sun/misc/Version/Version.java Wed Mar 09 14:54:18 2016 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,139 +0,0 @@
-/*
- * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/* @test
- * @bug 6994413 8134365
- * @summary Check the JDK and JVM version returned by sun.misc.Version
- * matches the versions defined in the system properties.
- * Should use the API described in JDK-8136651 when available
- * @modules java.base/sun.misc
- * @compile -XDignore.symbol.file Version.java
- * @run main Version
- */
-
-import static sun.misc.Version.*;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-public class Version {
-
- public static void main(String[] args) throws Exception {
- VersionInfo jdk = newVersionInfo(System.getProperty("java.runtime.version"));
- VersionInfo v1 = new VersionInfo(jdkMajorVersion(),
- jdkMinorVersion(),
- jdkSecurityVersion(),
- jdkPatchVersion(),
- jdkBuildNumber());
- System.out.println("JDK version = " + jdk + " " + v1);
- if (!jdk.equals(v1)) {
- throw new RuntimeException("Unmatched version: " + jdk + " vs " + v1);
- }
- VersionInfo jvm = newVersionInfo(System.getProperty("java.vm.version"));
- VersionInfo v2 = new VersionInfo(jvmMajorVersion(),
- jvmMinorVersion(),
- jvmSecurityVersion(),
- jvmPatchVersion(),
- jvmBuildNumber());
- System.out.println("JVM version = " + jvm + " " + v2);
- if (!jvm.equals(v2)) {
- throw new RuntimeException("Unmatched version: " + jvm + " vs " + v2);
- }
- }
-
- static class VersionInfo {
- final int major;
- final int minor;
- final int security;
- final int patch;
- final int build;
- VersionInfo(int major, int minor, int security,
- int patch, int build) {
- this.major = major;
- this.minor = minor;
- this.security = security;
- this.patch = patch;
- this.build = build;
- }
-
- VersionInfo(int[] fields) {
- this.major = fields[0];
- this.minor = fields[1];
- this.security = fields[2];
- this.patch = fields[3];
- this.build = fields[4];
- }
-
- public boolean equals(VersionInfo v) {
- return (this.major == v.major && this.minor == v.minor &&
- this.security == v.security && this.patch == v.patch &&
- this.build == v.build);
- }
-
- public String toString() {
- StringBuilder sb = new StringBuilder();
- // Do not include trailing zeros
- if (patch > 0) {
- sb.insert(0, "." + patch);
- }
- if (security > 0 || sb.length() > 0) {
- sb.insert(0, "." + security);
- }
- if (minor > 0 || sb.length() > 0) {
- sb.insert(0, "." + minor);
- }
- sb.insert(0, major);
-
- if (build >= 0)
- sb.append("+" + build);
-
- return sb.toString();
- }
- }
-
- private static VersionInfo newVersionInfo(String version) throws Exception {
- // Version string fromat as defined by JEP-223
- String jep223Pattern =
- "^([0-9]+)(\\.([0-9]+))?(\\.([0-9]+))?(\\.([0-9]+))?" + // $VNUM
- "(-([a-zA-Z]+))?(\\.([a-zA-Z]+))?" + // $PRE
- "(\\+([0-9]+))?" + // Build Number
- "(([-a-zA-Z0-9.]+))?$"; // $OPT
-
- // Pattern group index for: Major, Minor, Security, Patch, Build
- int[] groups = {1, 3, 5, 7, 13};
- // Default values for Major, Minor, Security, Patch, Build
- int[] versionFields = {0, 0, 0, 0, 0};
-
- Pattern pattern = Pattern.compile(jep223Pattern);
- Matcher matcher = pattern.matcher(version);
- if (matcher.matches()) {
- for (int i = 0; i < versionFields.length; i++) {
- String field = matcher.group(groups[i]);
- versionFields[i] = (field != null) ? Integer.parseInt(field) : 0;
- }
- }
-
- VersionInfo vi = new VersionInfo(versionFields);
- System.out.printf("newVersionInfo: input=%s output=%s\n", version, vi);
- return vi;
- }
-}
--- a/jdk/test/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java Wed Mar 09 14:18:12 2016 +0100
@@ -42,27 +42,40 @@
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
public class MultiReleaseJarURLConnection {
String userdir = System.getProperty("user.dir",".");
- String urlFile = "jar:file:" + userdir + "/multi-release.jar!/";
- String urlEntry = urlFile + "version/Version.java";
+ String file = userdir + "/signed-multi-release.jar";
@BeforeClass
public void initialize() throws Exception {
CreateMultiReleaseTestJars creator = new CreateMultiReleaseTestJars();
creator.compileEntries();
creator.buildMultiReleaseJar();
+ creator.buildSignedMultiReleaseJar();
}
@AfterClass
public void close() throws IOException {
Files.delete(Paths.get(userdir, "multi-release.jar"));
+ Files.delete(Paths.get(userdir, "signed-multi-release.jar"));
}
- @Test
- public void testRuntimeVersioning() throws Exception {
+ @DataProvider(name = "data")
+ public Object[][] createData() {
+ return new Object[][]{
+ {"unsigned file", userdir + "/multi-release.jar"},
+ {"signed file", userdir + "/signed-multi-release.jar"},
+ };
+ }
+
+ @Test(dataProvider = "data")
+ public void testRuntimeVersioning(String ignore, String file) throws Exception {
+ String urlFile = "jar:file:" + file + "!/";
+ String urlEntry = urlFile + "version/Version.java";
+
Assert.assertTrue(readAndCompare(new URL(urlEntry), "return 8"));
// #runtime is "magic"
Assert.assertTrue(readAndCompare(new URL(urlEntry + "#runtime"), "return 9"));
@@ -72,8 +85,10 @@
Assert.assertTrue(readAndCompare(new URL(urlEntry), "return 8"));
}
- @Test
- public void testCachedJars() throws Exception {
+ @Test(dataProvider = "data")
+ public void testCachedJars(String ignore, String file) throws Exception {
+ String urlFile = "jar:file:" + file + "!/";
+
URL rootUrl = new URL(urlFile);
JarURLConnection juc = (JarURLConnection)rootUrl.openConnection();
JarFile rootJar = juc.getJarFile();
--- a/jdk/test/sun/security/pkcs11/PKCS11Test.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/sun/security/pkcs11/PKCS11Test.java Wed Mar 09 14:18:12 2016 +0100
@@ -380,7 +380,9 @@
}
static double getNSSInfo(String library) {
- String nssHeader = "$Header: NSS";
+ // look for two types of headers in NSS libraries
+ String nssHeader1 = "$Header: NSS";
+ String nssHeader2 = "Version: NSS";
boolean found = false;
String s = null;
int i = 0;
@@ -408,7 +410,8 @@
}
s = new String(data, 0, read);
- if ((i = s.indexOf(nssHeader)) > 0) {
+ i = s.indexOf(nssHeader1);
+ if (i > 0 || (i = s.indexOf(nssHeader2)) > 0) {
found = true;
// If the nssHeader is before 920 we can break, otherwise
// we may not have the whole header so do another read. If
--- a/jdk/test/sun/security/provider/NSASuiteB/TestDSAGenParameterSpec.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/sun/security/provider/NSASuiteB/TestDSAGenParameterSpec.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -37,6 +37,7 @@
/*
* @test
* @bug 8075286
+ * @key intermittent
* @summary Verify that DSAGenParameterSpec can and can only be used to generate
* DSA within some certain range of key sizes as described in the class
* specification (L, N) as (1024, 160), (2048, 224), (2048, 256) and
--- a/jdk/test/sun/security/rsa/SpecTest.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/sun/security/rsa/SpecTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -34,6 +34,7 @@
/**
* @test
* @bug 8044199
+ * @key intermittent
* @summary Check same KeyPair's private key and public key have same modulus.
* also check public key's public exponent equals to given spec's public
* exponent.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/ssl/DHKeyExchange/LegacyDHEKeyExchange.java Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,325 @@
+/*
+ * 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.
+ */
+
+// SunJSSE does not support dynamic system properties, no way to re-use
+// system properties in samevm/agentvm mode.
+
+/*
+ * @test
+ * @bug 8148108
+ * @summary Disable Diffie-Hellman keys less than 1024 bits
+ * @run main/othervm -Djdk.tls.ephemeralDHKeySize=legacy LegacyDHEKeyExchange
+ */
+
+import java.io.*;
+import javax.net.ssl.*;
+
+public class LegacyDHEKeyExchange {
+
+ /*
+ * =============================================================
+ * Set the various variables needed for the tests, then
+ * specify what tests to run on each side.
+ */
+
+ /*
+ * Should we run the client or server in a separate thread?
+ * Both sides can throw exceptions, but do you have a preference
+ * as to which side should be the main thread.
+ */
+ static boolean separateServerThread = false;
+
+ /*
+ * Where do we find the keystores?
+ */
+ static String pathToStores = "../../../../javax/net/ssl/etc";
+ static String keyStoreFile = "keystore";
+ static String trustStoreFile = "truststore";
+ static String passwd = "passphrase";
+
+ /*
+ * Is the server ready to serve?
+ */
+ volatile static boolean serverReady = false;
+
+ /*
+ * Turn on SSL debugging?
+ */
+ static boolean debug = false;
+
+ /*
+ * If the client or server is doing some kind of object creation
+ * that the other side depends on, and that thread prematurely
+ * exits, you may experience a hang. The test harness will
+ * terminate all hung threads after its timeout has expired,
+ * currently 3 minutes by default, but you might try to be
+ * smart about it....
+ */
+
+ /*
+ * Define the server side of the test.
+ *
+ * If the server prematurely exits, serverReady will be set to true
+ * to avoid infinite hangs.
+ */
+ void doServerSide() throws Exception {
+ SSLServerSocketFactory sslssf =
+ (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
+ SSLServerSocket sslServerSocket =
+ (SSLServerSocket) sslssf.createServerSocket(serverPort);
+
+ serverPort = sslServerSocket.getLocalPort();
+
+ /*
+ * Signal Client, we're ready for his connect.
+ */
+ serverReady = true;
+
+ try (SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept()) {
+ InputStream sslIS = sslSocket.getInputStream();
+ OutputStream sslOS = sslSocket.getOutputStream();
+
+ sslIS.read();
+ sslOS.write(85);
+ sslOS.flush();
+
+ throw new Exception(
+ "Leagcy DH keys (< 1024) should be restricted");
+ } catch (SSLHandshakeException she) {
+ // ignore, client should terminate the connection
+ } finally {
+ sslServerSocket.close();
+ }
+ }
+
+ /*
+ * Define the client side of the test.
+ *
+ * If the server prematurely exits, serverReady will be set to true
+ * to avoid infinite hangs.
+ */
+ void doClientSide() throws Exception {
+
+ /*
+ * Wait for server to get started.
+ */
+ while (!serverReady) {
+ Thread.sleep(50);
+ }
+
+ SSLSocketFactory sslsf =
+ (SSLSocketFactory) SSLSocketFactory.getDefault();
+ SSLSocket sslSocket = (SSLSocket)
+ sslsf.createSocket("localhost", serverPort);
+
+ String[] suites = new String [] {"TLS_DHE_RSA_WITH_AES_128_CBC_SHA"};
+ sslSocket.setEnabledCipherSuites(suites);
+
+ try {
+ InputStream sslIS = sslSocket.getInputStream();
+ OutputStream sslOS = sslSocket.getOutputStream();
+
+ sslOS.write(280);
+ sslOS.flush();
+ sslIS.read();
+
+ throw new Exception("Leagcy DH keys (< 1024) should be restricted");
+ } catch (SSLHandshakeException she) {
+ // ignore, should be caused by algorithm constraints
+ } finally {
+ sslSocket.close();
+ }
+ }
+
+ /*
+ * =============================================================
+ * The remainder is just support stuff
+ */
+
+ // use any free port by default
+ volatile int serverPort = 0;
+
+ volatile Exception serverException = null;
+ volatile Exception clientException = null;
+
+ public static void main(String[] args) throws Exception {
+ String keyFilename =
+ System.getProperty("test.src", ".") + "/" + pathToStores +
+ "/" + keyStoreFile;
+ String trustFilename =
+ System.getProperty("test.src", ".") + "/" + pathToStores +
+ "/" + trustStoreFile;
+
+ System.setProperty("javax.net.ssl.keyStore", keyFilename);
+ System.setProperty("javax.net.ssl.keyStorePassword", passwd);
+ System.setProperty("javax.net.ssl.trustStore", trustFilename);
+ System.setProperty("javax.net.ssl.trustStorePassword", passwd);
+
+ if (debug) {
+ System.setProperty("javax.net.debug", "all");
+ }
+
+ /*
+ * Start the tests.
+ */
+ new LegacyDHEKeyExchange();
+ }
+
+ Thread clientThread = null;
+ Thread serverThread = null;
+
+ /*
+ * Primary constructor, used to drive remainder of the test.
+ *
+ * Fork off the other side, then do your work.
+ */
+ LegacyDHEKeyExchange() throws Exception {
+ Exception startException = null;
+ try {
+ if (separateServerThread) {
+ startServer(true);
+ startClient(false);
+ } else {
+ startClient(true);
+ startServer(false);
+ }
+ } catch (Exception e) {
+ startException = e;
+ }
+
+ /*
+ * Wait for other side to close down.
+ */
+ if (separateServerThread) {
+ if (serverThread != null) {
+ serverThread.join();
+ }
+ } else {
+ if (clientThread != null) {
+ clientThread.join();
+ }
+ }
+
+ /*
+ * When we get here, the test is pretty much over.
+ * Which side threw the error?
+ */
+ Exception local;
+ Exception remote;
+
+ if (separateServerThread) {
+ remote = serverException;
+ local = clientException;
+ } else {
+ remote = clientException;
+ local = serverException;
+ }
+
+ Exception exception = null;
+
+ /*
+ * Check various exception conditions.
+ */
+ if ((local != null) && (remote != null)) {
+ // If both failed, return the curthread's exception.
+ local.initCause(remote);
+ exception = local;
+ } else if (local != null) {
+ exception = local;
+ } else if (remote != null) {
+ exception = remote;
+ } else if (startException != null) {
+ exception = startException;
+ }
+
+ /*
+ * If there was an exception *AND* a startException,
+ * output it.
+ */
+ if (exception != null) {
+ if (exception != startException && startException != null) {
+ exception.addSuppressed(startException);
+ }
+ throw exception;
+ }
+
+ // Fall-through: no exception to throw!
+ }
+
+ void startServer(boolean newThread) throws Exception {
+ if (newThread) {
+ serverThread = new Thread() {
+ @Override
+ public void run() {
+ try {
+ doServerSide();
+ } catch (Exception e) {
+ /*
+ * Our server thread just died.
+ *
+ * Release the client, if not active already...
+ */
+ System.err.println("Server died...");
+ serverReady = true;
+ serverException = e;
+ }
+ }
+ };
+ serverThread.start();
+ } else {
+ try {
+ doServerSide();
+ } catch (Exception e) {
+ serverException = e;
+ } finally {
+ serverReady = true;
+ }
+ }
+ }
+
+ void startClient(boolean newThread) throws Exception {
+ if (newThread) {
+ clientThread = new Thread() {
+ @Override
+ public void run() {
+ try {
+ doClientSide();
+ } catch (Exception e) {
+ /*
+ * Our client thread just died.
+ */
+ System.err.println("Client died...");
+ clientException = e;
+ }
+ }
+ };
+ clientThread.start();
+ } else {
+ try {
+ doClientSide();
+ } catch (Exception e) {
+ clientException = e;
+ }
+ }
+ }
+}
--- a/jdk/test/tools/jar/JarEntryTime.java Wed Mar 09 14:54:18 2016 +0100
+++ b/jdk/test/tools/jar/JarEntryTime.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 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
@@ -31,6 +31,8 @@
import java.io.File;
import java.io.PrintWriter;
import java.nio.file.attribute.FileTime;
+import java.util.Date;
+import java.util.TimeZone;
import sun.tools.jar.Main;
public class JarEntryTime {
@@ -39,6 +41,9 @@
// allow for e.g. rounding/truncation and networked/samba drives.
static final long PRECISION = 10000L;
+ static final TimeZone TZ = TimeZone.getDefault();
+ static final boolean DST = TZ.inDaylightTime(new Date());
+
static boolean cleanup(File dir) throws Throwable {
boolean rc = true;
File[] x = dir.listFiles();
@@ -75,11 +80,13 @@
File dirOuter = new File("outer");
File dirInner = new File(dirOuter, "inner");
File jarFile = new File("JarEntryTime.jar");
+ File testFile = new File("JarEntryTimeTest.txt");
// Remove any leftovers from prior run
cleanup(dirInner);
cleanup(dirOuter);
jarFile.delete();
+ testFile.delete();
/* Create a directory structure
* outer/
@@ -129,23 +136,39 @@
check(cleanup(dirInner));
check(cleanup(dirOuter));
+ try (PrintWriter pw = new PrintWriter(testFile)) {
+ pw.println("hello, world");
+ }
+ final long start = testFile.lastModified();
+
// Extract and check the last modified values are the current times.
// See sun.tools.jar.Main
extractJar(jarFile, true);
+
+ try (PrintWriter pw = new PrintWriter(testFile)) {
+ pw.println("hello, world");
+ }
+ final long end = testFile.lastModified();
+
check(dirOuter.exists());
check(dirInner.exists());
check(fileInner.exists());
- checkFileTime(dirOuter.lastModified(), now);
- checkFileTime(dirInner.lastModified(), now);
- checkFileTime(fileInner.lastModified(), now);
+ checkFileTime(start, dirOuter.lastModified(), end);
+ checkFileTime(start, dirInner.lastModified(), end);
+ checkFileTime(start, fileInner.lastModified(), end);
check(cleanup(dirInner));
check(cleanup(dirOuter));
check(jarFile.delete());
+ check(testFile.delete());
}
static void checkFileTime(long now, long original) {
+ if (isTimeSettingChanged()) {
+ return;
+ }
+
if (Math.abs(now - original) > PRECISION) {
System.out.format("Extracted to %s, expected to be close to %s%n",
FileTime.fromMillis(now), FileTime.fromMillis(original));
@@ -153,6 +176,27 @@
}
}
+ static void checkFileTime(long start, long now, long end) {
+ if (isTimeSettingChanged()) {
+ return;
+ }
+
+ if (now < start || now > end) {
+ System.out.format("Extracted to %s, "
+ + "expected to be after %s and before %s%n",
+ FileTime.fromMillis(now),
+ FileTime.fromMillis(start),
+ FileTime.fromMillis(end));
+ fail();
+ }
+ }
+
+ private static boolean isTimeSettingChanged() {
+ TimeZone currentTZ = TimeZone.getDefault();
+ boolean currentDST = currentTZ.inDaylightTime(new Date());
+ return (!currentTZ.equals(TZ) || currentDST != DST);
+ }
+
//--------------------- Infrastructure ---------------------------
static volatile int passed = 0, failed = 0;
static void pass() {passed++;}
--- a/langtools/.hgtags Wed Mar 09 14:54:18 2016 +0100
+++ b/langtools/.hgtags Wed Mar 09 14:18:12 2016 +0100
@@ -350,3 +350,4 @@
81bd82222f8a1f2b291a44a49e063973caa4e73b jdk-9+105
dd05d3761a341143ef4a6b1a245e0960cc125b76 jdk-9+106
7a0c343551497bd0e38ad69a77cc57d9f396615a jdk-9+107
+fd18a155ad22f62e06a9b74850ab8609d415c752 jdk-9+108
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java Wed Mar 09 14:54:18 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java Wed Mar 09 14:18:12 2016 +0100
@@ -2001,10 +2001,11 @@
}
}
+ final boolean explicitOverride = m.attribute(syms.overrideType.tsym) != null;
// Check if this method must override a super method due to being annotated with @Override
// or by virtue of being a member of a diamond inferred anonymous class. Latter case is to
// be treated "as if as they were annotated" with @Override.
- boolean mustOverride = m.attribute(syms.overrideType.tsym) != null ||
+ boolean mustOverride = explicitOverride ||
(env.info.isAnonymousDiamond && !m.isConstructor() && !m.isPrivate());
if (mustOverride && !isOverrider(m)) {
DiagnosticPosition pos = tree.pos();
@@ -2014,7 +2015,9 @@
break;
}
}
- log.error(pos, "method.does.not.override.superclass");
+ log.error(pos,
+ explicitOverride ? Errors.MethodDoesNotOverrideSuperclass :
+ Errors.AnonymousDiamondMethodDoesNotOverrideSuperclass(Fragments.DiamondAnonymousMethodsImplicitlyOverride));
}
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java Wed Mar 09 14:54:18 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java Wed Mar 09 14:18:12 2016 +0100
@@ -4043,7 +4043,12 @@
found = false;
break;
}
- allThrown = chk.intersect(allThrown, mt2.getThrownTypes());
+ List<Type> thrownTypes2 = mt2.getThrownTypes();
+ if (mt.hasTag(FORALL) && mt2.hasTag(FORALL)) {
+ // if both are generic methods, adjust thrown types ahead of intersection computation
+ thrownTypes2 = types.subst(thrownTypes2, mt2.getTypeArguments(), mt.getTypeArguments());
+ }
+ allThrown = chk.intersect(allThrown, thrownTypes2);
}
if (found) {
//all ambiguous methods were abstract and one method had
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java Wed Mar 09 14:54:18 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java Wed Mar 09 14:18:12 2016 +0100
@@ -80,6 +80,11 @@
*/
private final Type methodType;
+ /**
+ * Are we presently traversing a let expression ? Yes if depth != 0
+ */
+ private int letExprDepth;
+
public static Gen instance(Context context) {
Gen instance = context.get(genKey);
if (instance == null)
@@ -1006,8 +1011,10 @@
if (tree.init != null) {
checkStringConstant(tree.init.pos(), v.getConstValue());
if (v.getConstValue() == null || varDebugInfo) {
+ Assert.check(letExprDepth != 0 || code.state.stacksize == 0);
genExpr(tree.init, v.erasure(types)).load();
items.makeLocalItem(v).store();
+ Assert.check(letExprDepth != 0 || code.state.stacksize == 0);
}
}
checkDimension(tree.pos(), v.type);
@@ -1062,12 +1069,14 @@
CondItem c;
if (cond != null) {
code.statBegin(cond.pos);
+ Assert.check(code.state.stacksize == 0);
c = genCond(TreeInfo.skipParens(cond), CRT_FLOW_CONTROLLER);
} else {
c = items.makeCondItem(goto_);
}
Chain loopDone = c.jumpFalse();
code.resolve(c.trueJumps);
+ Assert.check(code.state.stacksize == 0);
genStat(body, loopEnv, CRT_STATEMENT | CRT_FLOW_TARGET);
code.resolve(loopEnv.info.cont);
genStats(step, loopEnv);
@@ -1080,11 +1089,13 @@
CondItem c;
if (cond != null) {
code.statBegin(cond.pos);
+ Assert.check(code.state.stacksize == 0);
c = genCond(TreeInfo.skipParens(cond), CRT_FLOW_CONTROLLER);
} else {
c = items.makeCondItem(goto_);
}
code.resolve(c.jumpTrue(), startpc);
+ Assert.check(code.state.stacksize == 0);
code.resolve(c.falseJumps);
}
Chain exit = loopEnv.info.exit;
@@ -1112,6 +1123,7 @@
int limit = code.nextreg;
Assert.check(!tree.selector.type.hasTag(CLASS));
int startpcCrt = genCrt ? code.curCP() : 0;
+ Assert.check(code.state.stacksize == 0);
Item sel = genExpr(tree.selector, syms.intType);
List<JCCase> cases = tree.cases;
if (cases.isEmpty()) {
@@ -1280,6 +1292,7 @@
int limit = code.nextreg;
// Generate code to evaluate lock and save in temporary variable.
final LocalItem lockVar = makeTemp(syms.objectType);
+ Assert.check(code.state.stacksize == 0);
genExpr(tree.lock, tree.lock.type).load().duplicate();
lockVar.store();
@@ -1526,9 +1539,11 @@
public void visitIf(JCIf tree) {
int limit = code.nextreg;
Chain thenExit = null;
+ Assert.check(code.state.stacksize == 0);
CondItem c = genCond(TreeInfo.skipParens(tree.cond),
CRT_FLOW_CONTROLLER);
Chain elseChain = c.jumpFalse();
+ Assert.check(code.state.stacksize == 0);
if (!c.isFalse()) {
code.resolve(c.trueJumps);
genStat(tree.thenpart, env, CRT_STATEMENT | CRT_FLOW_TARGET);
@@ -1542,6 +1557,7 @@
}
code.resolve(thenExit);
code.endScopes(limit);
+ Assert.check(code.state.stacksize == 0);
}
public void visitExec(JCExpressionStatement tree) {
@@ -1555,7 +1571,9 @@
((JCUnary) e).setTag(PREDEC);
break;
}
+ Assert.check(code.state.stacksize == 0);
genExpr(tree.expr, tree.expr.type).drop();
+ Assert.check(code.state.stacksize == 0);
}
public void visitBreak(JCBreak tree) {
@@ -1581,6 +1599,7 @@
*/
int tmpPos = code.pendingStatPos;
if (tree.expr != null) {
+ Assert.check(code.state.stacksize == 0);
Item r = genExpr(tree.expr, pt).load();
if (hasFinally(env.enclMethod, env)) {
r = makeTemp(pt);
@@ -1600,8 +1619,10 @@
}
public void visitThrow(JCThrow tree) {
+ Assert.check(code.state.stacksize == 0);
genExpr(tree.expr, tree.expr.type).load();
code.emitop0(athrow);
+ Assert.check(code.state.stacksize == 0);
}
/* ************************************************************************
@@ -2101,10 +2122,12 @@
}
public void visitLetExpr(LetExpr tree) {
+ letExprDepth++;
int limit = code.nextreg;
genStats(tree.defs, env);
result = genExpr(tree.expr, tree.expr.type).load();
code.endScopes(limit);
+ letExprDepth--;
}
private void generateReferencesToPrunedTree(ClassSymbol classSymbol, Pool pool) {
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Wed Mar 09 14:54:18 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Wed Mar 09 14:18:12 2016 +0100
@@ -214,6 +214,11 @@
Unexpected @FunctionalInterface annotation\n\
{0}
+# 0: message segment
+compiler.err.anonymous.diamond.method.does.not.override.superclass=\
+ method does not override or implement a method from a supertype\n\
+ {0}
+
# 0: symbol
compiler.misc.not.a.functional.intf=\
{0} is not a functional interface
@@ -1196,6 +1201,9 @@
## miscellaneous strings
##
+compiler.misc.diamond.anonymous.methods.implicitly.override=\
+ (due to <>, every non-private method declared in this anonymous class must override or implement a method from a supertype)
+
compiler.misc.source.unavailable=\
(source unavailable)
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DocTreeMaker.java Wed Mar 09 14:54:18 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DocTreeMaker.java Wed Mar 09 14:18:12 2016 +0100
@@ -50,6 +50,7 @@
import com.sun.tools.javac.parser.ParserFactory;
import com.sun.tools.javac.parser.ReferenceParser;
import com.sun.tools.javac.parser.Tokens.Comment;
+import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle;
import com.sun.tools.javac.tree.DCTree.DCAttribute;
import com.sun.tools.javac.tree.DCTree.DCAuthor;
import com.sun.tools.javac.tree.DCTree.DCComment;
@@ -206,7 +207,31 @@
lb.addAll(cast(firstSentence));
lb.addAll(cast(body));
List<DCTree> fullBody = lb.toList();
- DCDocComment tree = new DCDocComment(null, fullBody, cast(firstSentence), cast(body), cast(tags));
+
+ // A dummy comment to keep the diagnostics logic happy.
+ Comment c = new Comment() {
+ @Override
+ public String getText() {
+ return null;
+ }
+
+ @Override
+ public int getSourcePos(int index) {
+ return Position.NOPOS;
+ }
+
+ @Override
+ public CommentStyle getStyle() {
+ return CommentStyle.JAVADOC;
+ }
+
+ @Override
+ public boolean isDeprecated() {
+ return false;
+ }
+ };
+
+ DCDocComment tree = new DCDocComment(c, fullBody, cast(firstSentence), cast(body), cast(tags));
return tree;
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java Wed Mar 09 14:54:18 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java Wed Mar 09 14:18:12 2016 +0100
@@ -28,7 +28,6 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
-import java.io.Writer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
@@ -81,6 +80,10 @@
if (!validateOptions(options))
return RC_FATAL;
+ if (srcDstOverlap(options.getSources(), options.getDestDir())) {
+ return RC_FATAL;
+ }
+
if (!createIfMissing(options.getDestDir()))
return RC_FATAL;
@@ -330,6 +333,22 @@
}
+ private static boolean srcDstOverlap(List<SourceLocation> locs, Path dest) {
+ for (SourceLocation loc : locs) {
+ if (isOverlapping(loc.getPath(), dest)) {
+ Log.error("Source location " + loc.getPath() + " overlaps with destination " + dest);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static boolean isOverlapping(Path p1, Path p2) {
+ p1 = p1.toAbsolutePath().normalize();
+ p2 = p2.toAbsolutePath().normalize();
+ return p1.startsWith(p2) || p2.startsWith(p1);
+ }
+
private static boolean createIfMissing(Path dir) {
if (Files.isDirectory(dir))
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/FrameOutputWriter.java Wed Mar 09 14:54:18 2016 +0100
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/FrameOutputWriter.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -96,6 +96,7 @@
protected void generateFrameFile() throws IOException {
Content frame = getFrameDetails();
HtmlTree body = new HtmlTree(HtmlTag.BODY);
+ body.addAttr(HtmlAttr.ONLOAD, "loadFrames()");
if (configuration.allowTag(HtmlTag.MAIN)) {
HtmlTree main = HtmlTree.MAIN(frame);
body.addContent(main);
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java Wed Mar 09 14:54:18 2016 +0100
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -423,6 +423,10 @@
" }" + DocletConstants.NL +
" }" + DocletConstants.NL +
" return true;" + DocletConstants.NL +
+ " }" + DocletConstants.NL +
+ " function loadFrames() {" + DocletConstants.NL +
+ " if (targetPage != \"\" && targetPage != \"undefined\")" + DocletConstants.NL +
+ " top.classFrame.location = top.targetPage;" + DocletConstants.NL +
" }" + DocletConstants.NL;
RawHtml scriptContent = new RawHtml(scriptCode);
script.addContent(scriptContent);
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java Wed Mar 09 14:54:18 2016 +0100
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java Wed Mar 09 14:18:12 2016 +0100
@@ -196,8 +196,12 @@
div.addStyle(HtmlStyle.header);
PackageElement pkg = utils.containingPackage(typeElement);
if (!pkg.isUnnamed()) {
- Content pkgNameContent = new StringContent(utils.getPackageName(pkg));
- Content pkgNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, pkgNameContent);
+ Content classPackageLabel = HtmlTree.SPAN(HtmlStyle.packageLabelInClass, packageLabel);
+ Content pkgNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, classPackageLabel);
+ pkgNameDiv.addContent(getSpace());
+ Content pkgNameContent = getPackageLink(pkg,
+ new StringContent(pkg.getQualifiedName().toString()));
+ pkgNameDiv.addContent(pkgNameContent);
div.addContent(pkgNameDiv);
}
LinkInfoImpl linkInfo = new LinkInfoImpl(configuration,
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FrameOutputWriter.java Wed Mar 09 14:54:18 2016 +0100
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FrameOutputWriter.java Wed Mar 09 14:18:12 2016 +0100
@@ -27,6 +27,7 @@
import java.io.*;
+import jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
@@ -102,6 +103,7 @@
protected void generateFrameFile() throws IOException {
Content frame = getFrameDetails();
HtmlTree body = new HtmlTree(HtmlTag.BODY);
+ body.addAttr(HtmlAttr.ONLOAD, "loadFrames()");
if (configuration.allowTag(HtmlTag.MAIN)) {
HtmlTree main = HtmlTree.MAIN(frame);
body.addContent(main);
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java Wed Mar 09 14:54:18 2016 +0100
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -84,6 +84,7 @@
overrideSpecifyLabel,
overviewSummary,
packageHierarchyLabel,
+ packageLabelInClass,
paramLabel,
returnLabel,
rightContainer,
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlWriter.java Wed Mar 09 14:54:18 2016 +0100
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlWriter.java Wed Mar 09 14:18:12 2016 +0100
@@ -401,6 +401,10 @@
" }" + DocletConstants.NL +
" }" + DocletConstants.NL +
" return true;" + DocletConstants.NL +
+ " }" + DocletConstants.NL +
+ " function loadFrames() {" + DocletConstants.NL +
+ " if (targetPage != \"\" && targetPage != \"undefined\")" + DocletConstants.NL +
+ " top.classFrame.location = top.targetPage;" + DocletConstants.NL +
" }" + DocletConstants.NL;
RawHtml scriptContent = new RawHtml(scriptCode);
script.addContent(scriptContent);
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css Wed Mar 09 14:54:18 2016 +0100
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css Wed Mar 09 14:18:12 2016 +0100
@@ -610,8 +610,9 @@
color:#474747;
}
.deprecatedLabel, .descfrmTypeLabel, .memberNameLabel, .memberNameLink,
-.overrideSpecifyLabel, .packageHierarchyLabel, .paramLabel, .returnLabel,
-.seeLabel, .simpleTagLabel, .throwsLabel, .typeNameLabel, .typeNameLink, .searchTagLink {
+.overrideSpecifyLabel, .packageLabelInClass, .packageHierarchyLabel,
+.paramLabel, .returnLabel, .seeLabel, .simpleTagLabel, .throwsLabel,
+.typeNameLabel, .typeNameLink, .searchTagLink {
font-weight:bold;
}
.deprecationComment, .emphasizedPhrase, .interfaceName {
--- a/langtools/test/com/sun/javadoc/testHtmlVersion/TestHtmlVersion.java Wed Mar 09 14:54:18 2016 +0100
+++ b/langtools/test/com/sun/javadoc/testHtmlVersion/TestHtmlVersion.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8072945 8081854 8141492
+ * @bug 8072945 8081854 8141492 8148985
* @summary Test the version of HTML generated by the javadoc tool.
* @author bpatel
* @library ../lib
@@ -688,7 +688,7 @@
checkOutput("index.html", true,
"<!DOCTYPE HTML>",
"<link rel=\"stylesheet\" type=\"text/css\" href=\"stylesheet.css\" title=\"Style\">",
- "<body>\n"
+ "<body onload=\"loadFrames()\">\n"
+ "<main role=\"main\">\n"
+ "<div class=\"mainContainer\">\n"
+ "<div class=\"leftContainer\">\n"
@@ -1599,7 +1599,7 @@
checkOutput("index.html", true,
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">",
"<link rel=\"stylesheet\" type=\"text/css\" href=\"stylesheet.css\" title=\"Style\">",
- "<body>\n"
+ "<body onload=\"loadFrames()\">\n"
+ "<div class=\"mainContainer\">\n"
+ "<div class=\"leftContainer\">\n"
+ "<div class=\"leftTop\">\n"
--- a/langtools/test/com/sun/javadoc/testJavascript/TestJavascript.java Wed Mar 09 14:54:18 2016 +0100
+++ b/langtools/test/com/sun/javadoc/testJavascript/TestJavascript.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 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
@@ -100,8 +100,15 @@
+ " }\n"
+ " return true;\n"
+ " }\n"
+ + " function loadFrames() {\n"
+ + " if (targetPage != \"\" && targetPage != \"undefined\")\n"
+ + " top.classFrame.location = top.targetPage;\n"
+ + " }\n"
+ "</script>");
+ checkOutput("index.html", true,
+ "<body onload=\"loadFrames()\"");
+
//Make sure title javascript only runs if is-external is not true
checkOutput("pkg/C.html", true,
" try {\n"
--- a/langtools/test/jdk/javadoc/doclet/testHtmlVersion/TestHtmlVersion.java Wed Mar 09 14:54:18 2016 +0100
+++ b/langtools/test/jdk/javadoc/doclet/testHtmlVersion/TestHtmlVersion.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8072945 8081854 8141492
+ * @bug 8072945 8081854 8141492 8148985
* @summary Test the version of HTML generated by the javadoc tool.
* @author bpatel
* @library ../lib
@@ -599,7 +599,7 @@
checkOutput("index.html", true,
"<!DOCTYPE HTML>",
"<link rel=\"stylesheet\" type=\"text/css\" href=\"stylesheet.css\" title=\"Style\">",
- "<body>\n"
+ "<body onload=\"loadFrames()\">\n"
+ "<main role=\"main\">\n"
+ "<div class=\"mainContainer\">\n"
+ "<div class=\"leftContainer\">\n"
@@ -1391,7 +1391,7 @@
checkOutput("index.html", true,
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">",
"<link rel=\"stylesheet\" type=\"text/css\" href=\"stylesheet.css\" title=\"Style\">",
- "<body>\n"
+ "<body onload=\"loadFrames()\">\n"
+ "<div class=\"mainContainer\">\n"
+ "<div class=\"leftContainer\">\n"
+ "<div class=\"leftTop\">\n"
--- a/langtools/test/jdk/javadoc/doclet/testIncluded/TestIncluded.java Wed Mar 09 14:54:18 2016 +0100
+++ b/langtools/test/jdk/javadoc/doclet/testIncluded/TestIncluded.java Wed Mar 09 14:18:12 2016 +0100
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8149468
+ * @bug 8149842
* @summary Verify that non included classes are not inspected.
* @library ../lib
* @modules jdk.javadoc/jdk.javadoc.internal.tool
--- a/langtools/test/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java Wed Mar 09 14:54:18 2016 +0100
+++ b/langtools/test/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 7112427 8012295 8025633 8026567 8061305 8081854
+ * @bug 7112427 8012295 8025633 8026567 8061305 8081854 8150130
* @summary Test of the JavaFX doclet features.
* @author jvalenta
* @library ../lib
@@ -137,6 +137,7 @@
+ "</ul>\n"
+ "</li>");
}
+
/*
* Test without -javafx option, to ensure property getters and setters
* are treated just like any other java method.
@@ -181,4 +182,22 @@
+ "</span>()</code> </td>"
);
}
+
+ /*
+ * Force the doclet to emit a warning when processing a synthesized,
+ * DocComment, and ensure that the run succeeds.
+ */
+ @Test
+ void test4() {
+ javadoc("-d", "out4",
+ "-javafx",
+ "-Xdoclint:none",
+ "-sourcepath", testSrc,
+ "-package",
+ "pkg4");
+ checkExit(Exit.OK);
+
+ // make sure the doclet indeed emits the warning
+ checkOutput(Output.OUT, true, "C.java:0: warning - invalid usage of tag >");
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/jdk/javadoc/doclet/testJavaFX/pkg4/C.java Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,45 @@
+/*
+ * 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 pkg4;
+
+public class C {
+
+ /**
+ * Defines the number of cycles in this animation. The {@code cycleCount}
+ * may be {@code INDEFINITE} for animations that repeat indefinitely.
+ * Now we add a > to deliberately cause an Html error.
+ * @defaultValue 11
+ * @since JavaFX 8.0
+ */
+ public DoubleProperty rate;
+
+ public final void setRate(double value) {}
+
+ public final double getRate() {return 2.0d;}
+
+ public final DoubleProperty rateProperty() {return new DoubleProperty();}
+
+ class DoubleProperty {}
+
+}
--- a/langtools/test/jdk/javadoc/doclet/testJavascript/TestJavascript.java Wed Mar 09 14:54:18 2016 +0100
+++ b/langtools/test/jdk/javadoc/doclet/testJavascript/TestJavascript.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 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
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 4665566 4855876 7025314 8012375 8015997 8016328 8024756
+ * @bug 4665566 4855876 7025314 8012375 8015997 8016328 8024756 8148985
* @summary Verify that the output has the right javascript.
* @author jamieh
* @library ../lib
@@ -100,8 +100,15 @@
+ " }\n"
+ " return true;\n"
+ " }\n"
+ + " function loadFrames() {\n"
+ + " if (targetPage != \"\" && targetPage != \"undefined\")\n"
+ + " top.classFrame.location = top.targetPage;\n"
+ + " }\n"
+ "</script>");
+ checkOutput("index.html", true,
+ "<body onload=\"loadFrames()\"");
+
//Make sure title javascript only runs if is-external is not true
checkOutput("pkg/C.html", true,
" try {\n"
--- a/langtools/test/jdk/javadoc/doclet/testSubTitle/TestSubTitle.java Wed Mar 09 14:54:18 2016 +0100
+++ b/langtools/test/jdk/javadoc/doclet/testSubTitle/TestSubTitle.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 7010342
+ * @bug 7010342 8150000
* @summary Test for correct sub title generation.
* @author Bhavesh Patel
* @library ../lib
@@ -50,7 +50,8 @@
"<div class=\"block\">This is the description of package pkg.</div>");
checkOutput("pkg/C.html", true,
- "<div class=\"subTitle\">pkg</div>");
+ "<div class=\"subTitle\"><span class=\"packageLabelInClass\">" +
+ "Package</span> <a href=\"../pkg/package-summary.html\">pkg</a></div>");
checkOutput("pkg/package-summary.html", false,
"<p class=\"subTitle\">\n" +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/DiamondMethodDoesNotOverride.java Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+// key: compiler.err.anonymous.diamond.method.does.not.override.superclass
+// key: compiler.misc.diamond.anonymous.methods.implicitly.override
+
+class X {
+ interface Foo<T> {
+ void g(T t);
+ }
+ void m() {
+ Foo<String> fs = new Foo<>() {
+ public void g(String s) { }
+ void someMethod() { }
+ };
+ }
+}
--- a/langtools/test/tools/javac/generics/diamond/neg/Neg15.java Wed Mar 09 14:54:18 2016 +0100
+++ b/langtools/test/tools/javac/generics/diamond/neg/Neg15.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,6 +1,6 @@
/*
* @test /nodynamiccopyright/
- * @bug 8062373
+ * @bug 8062373 8151018
*
* @summary Test that javac complains when a <> inferred class contains a public method that does override a supertype method.
* @author sadayapalam
--- a/langtools/test/tools/javac/generics/diamond/neg/Neg15.out Wed Mar 09 14:54:18 2016 +0100
+++ b/langtools/test/tools/javac/generics/diamond/neg/Neg15.out Wed Mar 09 14:18:12 2016 +0100
@@ -1,4 +1,4 @@
-Neg15.java:48:28: compiler.err.method.does.not.override.superclass
-Neg15.java:52:21: compiler.err.method.does.not.override.superclass
-Neg15.java:56:31: compiler.err.method.does.not.override.superclass
+Neg15.java:48:28: compiler.err.anonymous.diamond.method.does.not.override.superclass: (compiler.misc.diamond.anonymous.methods.implicitly.override)
+Neg15.java:52:21: compiler.err.anonymous.diamond.method.does.not.override.superclass: (compiler.misc.diamond.anonymous.methods.implicitly.override)
+Neg15.java:56:31: compiler.err.anonymous.diamond.method.does.not.override.superclass: (compiler.misc.diamond.anonymous.methods.implicitly.override)
3 errors
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/generics/inference/CheckNoTimeoutException.java Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,60 @@
+/*
+ * 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
+ * @bug 8148930
+ * @summary Verify that there is no spurious unreported exception error.
+ * @modules java.sql
+ * @compile CheckNoTimeoutException.java
+ */
+
+import java.util.Collection;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.concurrent.TimeoutException;
+import java.io.*;
+import java.sql.SQLException;
+import java.sql.SQLTransientException;
+
+class CheckNoTimeoutException {
+
+ interface V {List<?> foo(List<String> arg) throws EOFException, SQLException, TimeoutException;}
+ interface U {Collection foo(List<String> arg) throws IOException, SQLTransientException;}
+
+ //SAM type ([List<String>], List<String>/List, {EOFException, SQLTransientException})
+ interface UV extends U, V {}
+
+
+ private static List<String> strs = new ArrayList<String>();
+ void methodUV(UV uv) {
+ System.out.println("methodUV(): SAM type interface UV object instantiated: " + uv);
+ try{
+ System.out.println("result returned: " + uv.foo(strs));
+ }catch(EOFException e){
+ System.out.println(e.getMessage());
+ }catch(SQLTransientException ex){
+ System.out.println(ex.getMessage());
+ }
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/generics/inference/IntersectThrownTypesTest.java Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,28 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8148930
+ * @summary Incorrect erasure of exceptions in override-equivalent dual interface impl
+ * @compile/fail/ref=IntersectThrownTypesTest.out -XDrawDiagnostics IntersectThrownTypesTest.java
+ */
+
+public class IntersectThrownTypesTest {
+
+ interface S1 {
+ <K extends Exception> void run(Class<K> clazz) throws K;
+ }
+
+ interface S2 {
+ <K extends Exception> void run(Class<K> clazz) throws K;
+ }
+
+ interface S extends S1, S2 {}
+
+ public void foo(S1 s) {
+ s.run(java.io.IOException.class);
+ }
+
+ public void foo(S s) {
+ s.run(java.io.IOException.class);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/generics/inference/IntersectThrownTypesTest.out Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,3 @@
+IntersectThrownTypesTest.java:21:14: compiler.err.unreported.exception.need.to.catch.or.throw: java.io.IOException
+IntersectThrownTypesTest.java:25:14: compiler.err.unreported.exception.need.to.catch.or.throw: java.io.IOException
+2 errors
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/sjavac/OverlappingSrcDst.java Wed Mar 09 14:18:12 2016 +0100
@@ -0,0 +1,102 @@
+/*
+ * 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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 Make sure sjavac doesn't allow overlapping source and destination
+ * directories.
+ * @bug 8061320
+ * @library /tools/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.file
+ * jdk.compiler/com.sun.tools.javac.main
+ * jdk.compiler/com.sun.tools.sjavac
+ * @build Wrapper ToolBox
+ * @run main Wrapper OverlappingSrcDst
+ */
+
+import java.io.File;
+import java.nio.file.Paths;
+
+public class OverlappingSrcDst extends SJavacTester {
+ public static void main(String... args) {
+ new OverlappingSrcDst().run();
+ }
+
+ public void run() {
+ String abs = ToolBox.currDir.toAbsolutePath().toString();
+
+ // Relative vs relative
+ test("dir", "dir", false);
+ test("dir", "dir/dst", false);
+ test("dir/src", "dir", false);
+ test("src", "dst", true);
+
+ // Absolute vs absolute
+ test(abs + "/dir", abs + "/dir", false);
+ test(abs + "/dir", abs + "/dir/dst", false);
+ test(abs + "/dir/src", abs + "/dir", false);
+ test(abs + "/src", abs + "/dst", true);
+
+ // Absolute vs relative
+ test(abs + "/dir", "dir", false);
+ test(abs + "/dir", "dir/dst", false);
+ test(abs + "/dir/src", "dir", false);
+ test(abs + "/src", "dst", true);
+
+ // Relative vs absolute
+ test("dir", abs + "/dir", false);
+ test("dir", abs + "/dir/dst", false);
+ test("dir/src", abs + "/dir", false);
+ test("src", abs + "/dst", true);
+ }
+
+ private void test(String srcDir, String dstDir, boolean shouldSucceed) {
+ boolean succeeded = testCompilation(srcDir, dstDir);
+ if (shouldSucceed != succeeded) {
+ throw new AssertionError(
+ String.format("Test failed for "
+ + "srcDir=\"%s\", "
+ + "dstDir=\"%s\". "
+ + "Compilation was expected to %s but %s.",
+ srcDir,
+ dstDir,
+ shouldSucceed ? "succeed" : "fail",
+ succeeded ? "succeeded" : "failed"));
+ }
+ }
+
+ private boolean testCompilation(String srcDir, String dstDir) {
+ try {
+ srcDir = srcDir.replace('/', File.separatorChar);
+ dstDir = dstDir.replace('/', File.separatorChar);
+ tb.writeFile(Paths.get(srcDir, "pkg", "A.java"), "package pkg; class A {}");
+ compile("--state-dir=state", "-src", srcDir, "-d", dstDir);
+ return true;
+ } catch (Exception e) {
+ return false;
+ }
+ }
+}
--- a/make/Images.gmk Wed Mar 09 14:54:18 2016 +0100
+++ b/make/Images.gmk Wed Mar 09 14:18:12 2016 +0100
@@ -42,7 +42,7 @@
jdk.security.auth jdk.security.jgss jdk.pack200 jdk.xml.dom \
jdk.accessibility jdk.internal.le jdk.dynalink \
jdk.scripting.nashorn jdk.scripting.nashorn.shell \
- jdk.vm.ci jdk.management
+ jdk.vm.ci jdk.management jdk.jsobject
# providers
PROVIDER_MODULES += jdk.charsets jdk.crypto.ec jdk.crypto.pkcs11 jdk.jvmstat jdk.jvmstat.rmi \
--- a/make/common/MakeBase.gmk Wed Mar 09 14:54:18 2016 +0100
+++ b/make/common/MakeBase.gmk Wed Mar 09 14:18:12 2016 +0100
@@ -282,7 +282,7 @@
# Default shell seems to always be /bin/sh. Must override with bash to get this to work on Solaris.
# Only use time if it's GNU time which supports format and output file.
WRAPPER_SHELL := $$(BASH) $$(SRC_ROOT)/common/bin/shell-tracer.sh $$(if $$(findstring yes,$$(IS_GNU_TIME)),$$(TIME),-) $$(OUTPUT_ROOT)/build-trace-time.log $$(SHELL)
- SHELL := $$(warning $$(if $$@,Building $$@,Running shell command) $$(if $$<, (from $$<))$$(if $$?, ($$(wordlist 1, 20, $$?) $$(if $$(wordlist 21, 22, $$?), ... [in total $$(words $$?) files]) newer)))$$(WRAPPER_SHELL)
+ SHELL = $$(warning $$(if $$@,Building $$@,Running shell command) $$(if $$<, (from $$<))$$(if $$?, ($$(wordlist 1, 20, $$?) $$(if $$(wordlist 21, 22, $$?), ... [in total $$(words $$?) files]) newer)))$$(WRAPPER_SHELL)
endif
# The warn level can never be turned off
LogWarn = $$(info $$(strip $$1))
--- a/modules.xml Wed Mar 09 14:54:18 2016 +0100
+++ b/modules.xml Wed Mar 09 14:18:12 2016 +0100
@@ -844,6 +844,18 @@
</export>
</module>
<module>
+ <name>jdk.jsobject</name>
+ <depend>java.base</depend>
+ <depend re-exports="true">java.desktop</depend>
+ <export>
+ <name>netscape.javascript</name>
+ </export>
+ <export>
+ <name>jdk.internal.netscape.javascript.spi</name>
+ <to>jdk.plugin</to>
+ </export>
+ </module>
+ <module>
<name>java.httpclient</name>
<depend>java.base</depend>
<export>
@@ -1802,10 +1814,10 @@
<name>com.sun.tools.javadoc</name>
</export>
<export>
- <name>jdk.javadoc.doclet</name>
+ <name>jdk.javadoc.doclet</name>
</export>
<export>
- <name>jdk.javadoc.doclet.taglet</name>
+ <name>jdk.javadoc.doclet.taglet</name>
</export>
</module>
<module>
--- a/nashorn/.hgtags Wed Mar 09 14:54:18 2016 +0100
+++ b/nashorn/.hgtags Wed Mar 09 14:18:12 2016 +0100
@@ -341,3 +341,4 @@
4e9749cc32f15251d9b2d0eab4373529952902a3 jdk-9+105
cfb3167456932b14c16a6d4cffd5fe295fbe01ff jdk-9+106
8042e81b530e480dfdad41fd53a7a26f69ebba26 jdk-9+107
+58409eff7e3e0c07f12f543341769964619c0acf jdk-9+108
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CodeStore.java Wed Mar 09 14:54:18 2016 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CodeStore.java Wed Mar 09 14:18:12 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -34,13 +34,10 @@
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
-import java.security.AccessControlException;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
-import java.util.Iterator;
import java.util.Map;
-import java.util.ServiceLoader;
import jdk.nashorn.internal.codegen.OptimisticTypesPersistence;
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.runtime.logging.DebugLogger;
@@ -54,11 +51,6 @@
@Logger(name="codestore")
public abstract class CodeStore implements Loggable {
- /**
- * Permission needed to provide a CodeStore instance via ServiceLoader.
- */
- public final static String NASHORN_PROVIDE_CODE_STORE = "nashorn.provideCodeStore";
-
private DebugLogger log;
/**
@@ -85,23 +77,6 @@
* @return The instance, or null if code store could not be created
*/
public static CodeStore newCodeStore(final Context context) {
- final Class<CodeStore> baseClass = CodeStore.class;
- try {
- // security check first
- final SecurityManager sm = System.getSecurityManager();
- if (sm != null) {
- sm.checkPermission(new RuntimePermission(NASHORN_PROVIDE_CODE_STORE));
- }
- final ServiceLoader<CodeStore> services = ServiceLoader.load(baseClass);
- final Iterator<CodeStore> iterator = services.iterator();
- if (iterator.hasNext()) {
- final CodeStore store = iterator.next();
- store.initLogger(context).info("using code store provider ", store.getClass().getCanonicalName());
- return store;
- }
- } catch (final AccessControlException e) {
- context.getLogger(CodeStore.class).warning("failed to load code store provider ", e);
- }
try {
final CodeStore store = new DirectoryCodeStore(context);
store.initLogger(context);