--- a/.hgtags Fri Aug 10 14:56:29 2018 -0700
+++ b/.hgtags Thu Aug 23 11:09:16 2018 -0400
@@ -500,8 +500,11 @@
ea900a7dc7d77dee30865c60eabd87fc24b1037c jdk-11+24
331888ea4a788df801b1edf8836646cd25fc758b jdk-11+25
945ba9278a272a5477ffb1b3ea1b04174fed8036 jdk-11+26
+9d7d74c6f2cbe522e39fa22dc557fdd3f79b32ad jdk-11+27
69b438908512d3dfef5852c6a843a5778333a309 jdk-12+2
990db216e7199b2ba9989d8fa20b657e0ca7d969 jdk-12+3
499b873761d8e8a1cc4aa649daf04cbe98cbce77 jdk-12+4
f8696e0ab9b795030429fc3374ec03e378fd9ed7 jdk-12+5
7939b3c4e4088bf4f70ec5bbd8030393b653372f jdk-12+6
+ef57958c7c511162da8d9a75f0b977f0f7ac464e jdk-12+7
+492b366f8e5784cc4927c2c98f9b8a3f16c067eb jdk-12+8
--- a/make/CompileJavaModules.gmk Fri Aug 10 14:56:29 2018 -0700
+++ b/make/CompileJavaModules.gmk Thu Aug 23 11:09:16 2018 -0400
@@ -534,6 +534,10 @@
--add-exports jdk.internal.vm.ci/jdk.vm.ci.sparc=jdk.internal.vm.compiler,jdk.aot \
#
+jdk.aot_EXCLUDES += \
+ jdk.tools.jaotc.test
+ #
+
################################################################################
sun.charsets_COPY += .dat
--- a/make/gensrc/Gensrc-jdk.internal.vm.compiler.gmk Fri Aug 10 14:56:29 2018 -0700
+++ b/make/gensrc/Gensrc-jdk.internal.vm.compiler.gmk Thu Aug 23 11:09:16 2018 -0400
@@ -124,7 +124,7 @@
($(CD) $(GENSRC_DIR)/META-INF/providers && \
p=""; \
impl=""; \
- for i in $$($(LS) | $(SORT)); do \
+ for i in $$($(GREP) '^' * | $(SORT) -t ':' -k 2 | $(SED) 's/:.*//'); do \
c=$$($(CAT) $$i | $(TR) -d '\n\r'); \
if test x$$p != x$$c; then \
if test x$$p != x; then \
--- a/make/jdk/src/classes/build/tools/module/GenModuleInfoSource.java Fri Aug 10 14:56:29 2018 -0700
+++ b/make/jdk/src/classes/build/tools/module/GenModuleInfoSource.java Thu Aug 23 11:09:16 2018 -0400
@@ -431,14 +431,12 @@
}
uses.put(name, statement);
break;
- /* Disable this check until jdk.internal.vm.compiler generated file is fixed.
case "provides":
if (provides.containsKey(name)) {
throw parser.newError("multiple " + keyword + " " + name);
}
provides.put(name, statement);
break;
- */
}
String lookAhead = lookAhead(parser);
if (lookAhead.equals(statement.qualifier)) {
--- a/make/jdk/src/classes/build/tools/module/ModuleInfoExtraTest.java Fri Aug 10 14:56:29 2018 -0700
+++ b/make/jdk/src/classes/build/tools/module/ModuleInfoExtraTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -230,7 +230,11 @@
new String[] {
" uses s;",
" uses s;"
- }, ".*, line .*, multiple uses s.*"
+ }, ".*, line .*, multiple uses s.*",
+ new String[] {
+ " provides s with impl1;",
+ " provides s with impl2, impl3;"
+ }, ".*, line .*, multiple provides s.*"
);
void errorCases() {
--- a/make/lib/Awt2dLibraries.gmk Fri Aug 10 14:56:29 2018 -0700
+++ b/make/lib/Awt2dLibraries.gmk Thu Aug 23 11:09:16 2018 -0400
@@ -796,6 +796,12 @@
LIBSPLASHSCREEN_CFLAGS += -DSPLASHSCREEN -DPNG_NO_MMX_CODE -DPNG_ARM_NEON_OPT=0
+ ifeq ($(OPENJDK_TARGET_OS), linux)
+ ifeq ($(OPENJDK_TARGET_CPU_ARCH), ppc)
+ LIBSPLASHSCREEN_CFLAGS += -DPNG_POWERPC_VSX_OPT=0
+ endif
+ endif
+
ifeq ($(OPENJDK_TARGET_OS), macosx)
LIBSPLASHSCREEN_CFLAGS += -DWITH_MACOSX
--- a/src/hotspot/.mx.jvmci/suite.py Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/.mx.jvmci/suite.py Thu Aug 23 11:09:16 2018 -0400
@@ -43,7 +43,8 @@
"jdk.vm.ci.services" : {
"subDir" : "../jdk.internal.vm.ci/share/classes",
"sourceDirs" : ["src"],
- "javaCompliance" : "9",
+ "javaCompliance" : "9+",
+ "checkstyleVersion" : "8.8",
"workingSets" : "API,JVMCI",
},
@@ -53,7 +54,7 @@
"subDir" : "../jdk.internal.vm.ci/share/classes",
"sourceDirs" : ["src"],
"checkstyle" : "jdk.vm.ci.services",
- "javaCompliance" : "9",
+ "javaCompliance" : "9+",
"workingSets" : "API,JVMCI",
},
@@ -61,7 +62,7 @@
"subDir" : "../jdk.internal.vm.ci/share/classes",
"sourceDirs" : ["src"],
"checkstyle" : "jdk.vm.ci.services",
- "javaCompliance" : "9",
+ "javaCompliance" : "9+",
"workingSets" : "API,JVMCI",
},
@@ -70,7 +71,7 @@
"sourceDirs" : ["src"],
"dependencies" : ["jdk.vm.ci.meta"],
"checkstyle" : "jdk.vm.ci.services",
- "javaCompliance" : "9",
+ "javaCompliance" : "9+",
"workingSets" : "API,JVMCI",
},
@@ -85,7 +86,7 @@
"jdk.vm.ci.hotspot",
],
"checkstyle" : "jdk.vm.ci.services",
- "javaCompliance" : "9",
+ "javaCompliance" : "9+",
"workingSets" : "API,JVMCI",
},
@@ -97,7 +98,7 @@
"jdk.vm.ci.services",
],
"checkstyle" : "jdk.vm.ci.services",
- "javaCompliance" : "9",
+ "javaCompliance" : "9+",
"workingSets" : "API,JVMCI",
},
@@ -110,7 +111,7 @@
"jdk.vm.ci.runtime",
],
"checkstyle" : "jdk.vm.ci.services",
- "javaCompliance" : "9",
+ "javaCompliance" : "9+",
"workingSets" : "API,JVMCI",
},
@@ -121,7 +122,7 @@
"sourceDirs" : ["src"],
"dependencies" : ["jdk.vm.ci.code"],
"checkstyle" : "jdk.vm.ci.services",
- "javaCompliance" : "9",
+ "javaCompliance" : "9+",
"workingSets" : "JVMCI,AArch64",
},
@@ -130,7 +131,7 @@
"sourceDirs" : ["src"],
"dependencies" : ["jdk.vm.ci.code"],
"checkstyle" : "jdk.vm.ci.services",
- "javaCompliance" : "9",
+ "javaCompliance" : "9+",
"workingSets" : "JVMCI,AMD64",
},
@@ -139,7 +140,7 @@
"sourceDirs" : ["src"],
"dependencies" : ["jdk.vm.ci.code"],
"checkstyle" : "jdk.vm.ci.services",
- "javaCompliance" : "9",
+ "javaCompliance" : "9+",
"workingSets" : "JVMCI,SPARC",
},
@@ -156,7 +157,7 @@
"jdk.internal.org.objectweb.asm",
],
"checkstyle" : "jdk.vm.ci.services",
- "javaCompliance" : "9",
+ "javaCompliance" : "9+",
"workingSets" : "JVMCI",
},
@@ -168,7 +169,7 @@
"jdk.vm.ci.hotspot",
],
"checkstyle" : "jdk.vm.ci.services",
- "javaCompliance" : "9",
+ "javaCompliance" : "9+",
"workingSets" : "API,JVMCI",
},
@@ -180,7 +181,7 @@
"jdk.vm.ci.hotspot",
],
"checkstyle" : "jdk.vm.ci.services",
- "javaCompliance" : "9",
+ "javaCompliance" : "9+",
"workingSets" : "JVMCI,HotSpot,AArch64",
},
@@ -192,7 +193,7 @@
"jdk.vm.ci.hotspot",
],
"checkstyle" : "jdk.vm.ci.services",
- "javaCompliance" : "9",
+ "javaCompliance" : "9+",
"workingSets" : "JVMCI,HotSpot,AMD64",
},
@@ -204,7 +205,7 @@
"jdk.vm.ci.hotspot",
],
"checkstyle" : "jdk.vm.ci.services",
- "javaCompliance" : "9",
+ "javaCompliance" : "9+",
"workingSets" : "JVMCI,HotSpot,SPARC",
},
--- a/src/hotspot/cpu/aarch64/aarch64.ad Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/cpu/aarch64/aarch64.ad Thu Aug 23 11:09:16 2018 -0400
@@ -1036,21 +1036,8 @@
}
};
- // graph traversal helpers
-
- MemBarNode *parent_membar(const Node *n);
- MemBarNode *child_membar(const MemBarNode *n);
- bool leading_membar(const MemBarNode *barrier);
-
- 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 *trailing_to_leading(const MemBarNode *trailing);
-
// predicates controlling emit of ldr<x>/ldar<x> and associated dmb
bool unnecessary_acquire(const Node *barrier);
@@ -1272,605 +1259,6 @@
// relevant dmb instructions.
//
- // graph traversal helpers used for volatile put/get and CAS
- // optimization
-
- // 1) general purpose helpers
-
- // if node n is linked to a parent MemBarNode by an intervening
- // Control and Memory ProjNode return the MemBarNode otherwise return
- // NULL.
- //
- // n may only be a Load or a MemBar.
-
- MemBarNode *parent_membar(const Node *n)
- {
- Node *ctl = NULL;
- Node *mem = NULL;
- Node *membar = NULL;
-
- if (n->is_Load()) {
- ctl = n->lookup(LoadNode::Control);
- mem = n->lookup(LoadNode::Memory);
- } else if (n->is_MemBar()) {
- ctl = n->lookup(TypeFunc::Control);
- mem = n->lookup(TypeFunc::Memory);
- } else {
- return NULL;
- }
-
- if (!ctl || !mem || !ctl->is_Proj() || !mem->is_Proj()) {
- return NULL;
- }
-
- membar = ctl->lookup(0);
-
- if (!membar || !membar->is_MemBar()) {
- return NULL;
- }
-
- if (mem->lookup(0) != membar) {
- return NULL;
- }
-
- return membar->as_MemBar();
- }
-
- // if n is linked to a child MemBarNode by intervening Control and
- // Memory ProjNodes return the MemBarNode otherwise return NULL.
-
- MemBarNode *child_membar(const MemBarNode *n)
- {
- ProjNode *ctl = n->proj_out_or_null(TypeFunc::Control);
- ProjNode *mem = n->proj_out_or_null(TypeFunc::Memory);
-
- // MemBar needs to have both a Ctl and Mem projection
- if (! ctl || ! mem)
- return NULL;
-
- MemBarNode *child = NULL;
- Node *x;
-
- for (DUIterator_Fast imax, i = ctl->fast_outs(imax); i < imax; i++) {
- x = ctl->fast_out(i);
- // if we see a membar we keep hold of it. we may also see a new
- // arena copy of the original but it will appear later
- if (x->is_MemBar()) {
- child = x->as_MemBar();
- break;
- }
- }
-
- if (child == NULL) {
- return NULL;
- }
-
- for (DUIterator_Fast imax, i = mem->fast_outs(imax); i < imax; i++) {
- x = mem->fast_out(i);
- // if we see a membar we keep hold of it. we may also see a new
- // arena copy of the original but it will appear later
- if (x == child) {
- return child;
- }
- }
- return NULL;
- }
-
- // helper predicate use to filter candidates for a leading memory
- // barrier
- //
- // returns true if barrier is a MemBarRelease or a MemBarCPUOrder
- // whose Ctl and Mem feeds come from a MemBarRelease otherwise false
-
- bool leading_membar(const MemBarNode *barrier)
- {
- int opcode = barrier->Opcode();
- // if this is a release membar we are ok
- if (opcode == Op_MemBarRelease) {
- return true;
- }
- // if its a cpuorder membar . . .
- if (opcode != Op_MemBarCPUOrder) {
- return false;
- }
- // then the parent has to be a release membar
- MemBarNode *parent = parent_membar(barrier);
- if (!parent) {
- return false;
- }
- opcode = parent->Opcode();
- return opcode == Op_MemBarRelease;
- }
-
- // 2) card mark detection helper
-
- // helper predicate which can be used to detect a volatile membar
- // introduced as part of a conditional card mark sequence either by
- // G1 or by CMS when UseCondCardMark is true.
- //
- // membar can be definitively determined to be part of a card mark
- // sequence if and only if all the following hold
- //
- // i) it is a MemBarVolatile
- //
- // ii) either UseG1GC or (UseConcMarkSweepGC && UseCondCardMark) is
- // true
- //
- // iii) the node's Mem projection feeds a StoreCM node.
-
- bool is_card_mark_membar(const MemBarNode *barrier)
- {
- if (!UseG1GC && !(UseConcMarkSweepGC && UseCondCardMark)) {
- return false;
- }
-
- if (barrier->Opcode() != Op_MemBarVolatile) {
- return false;
- }
-
- ProjNode *mem = barrier->proj_out(TypeFunc::Memory);
-
- for (DUIterator_Fast imax, i = mem->fast_outs(imax); i < imax ; i++) {
- Node *y = mem->fast_out(i);
- if (y->Opcode() == Op_StoreCM) {
- return true;
- }
- }
-
- return false;
- }
-
-
- // 3) helper predicates to traverse volatile put or CAS graphs which
- // may contain GC barrier subgraphs
-
- // Preamble
- // --------
- //
- // for volatile writes we can omit generating barriers and employ a
- // releasing store when we see a node sequence sequence with a
- // leading MemBarRelease and a trailing MemBarVolatile as follows
- //
- // MemBarRelease
- // { || } -- optional
- // {MemBarCPUOrder}
- // || \\
- // || StoreX[mo_release]
- // | \ /
- // | MergeMem
- // | /
- // {MemBarCPUOrder} -- optional
- // { || }
- // 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.
- //
- // with most GC configurations we with see this simple variant which
- // includes a post-write barrier card mark.
- //
- // MemBarRelease______________________________
- // || \\ Ctl \ \\
- // || StoreN/P[mo_release] CastP2X StoreB/CM
- // | \ / . . . /
- // | MergeMem
- // | /
- // || /
- // {MemBarCPUOrder} -- optional
- // { || }
- // MemBarVolatile
- //
- // i.e. the leading membar feeds Ctl to a CastP2X (which converts
- // 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 or G1. StoreCM differs from a normal card mark write (StoreB)
- // because it implies a requirement to order visibility of the card
- // mark (StoreCM) relative to the object put (StoreP/N) using a
- // StoreStore memory barrier (arguably this ought to be represented
- // explicitly in the ideal graph but that is not how it works). This
- // ordering is required for both non-volatile and volatile
- // puts. Normally that means we need to translate a StoreCM using
- // the sequence
- //
- // dmb ishst
- // strb
- //
- // However, when using G1 or CMS with conditional card marking (as
- // we shall see) we don't need to insert the dmb when translating
- // StoreCM because there is already an intervening StoreLoad barrier
- // between it and the StoreP/N.
- //
- // It is also possible to perform the card mark conditionally on it
- // currently being unmarked in which case the volatile put graph
- // will look slightly different
- //
- // MemBarRelease____________________________________________
- // || \\ Ctl \ Ctl \ \\ Mem \
- // || StoreN/P[mo_release] CastP2X If LoadB |
- // | \ / \ |
- // | MergeMem . . . StoreB
- // | / /
- // || /
- // MemBarVolatile
- //
- // It is worth noting at this stage that both the above
- // configurations can be uniquely identified by checking that the
- // memory flow includes the following subgraph:
- //
- // MemBarRelease
- // {MemBarCPUOrder}
- // | \ . . .
- // | StoreX[mo_release] . . .
- // | /
- // MergeMem
- // |
- // {MemBarCPUOrder}
- // 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
- //
- // MemBarRelease
- // ||
- // MemBarCPUOrder
- // || \\ . . .
- // || CompareAndSwapX
- // || |
- // || SCMemProj
- // | \ /
- // | 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/swaps. 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/swap
- // and the read of the corresponding card. This poses two additional
- // problems.
- //
- // Firstly, a card mark MemBarVolatile needs to be distinguished
- // from a normal trailing MemBarVolatile. Resolving this first
- // problem is straightforward: a card mark MemBarVolatile always
- // projects a Mem feed to a StoreCM node and that is a unique marker
- //
- // MemBarVolatile (card mark)
- // C | \ . . .
- // | StoreCM . . .
- // . . .
- //
- // The second problem is how the code generator is to translate the
- // card mark barrier? It always needs to be translated to a "dmb
- // ish" instruction whether or not it occurs as part of a volatile
- // put. A StoreLoad barrier is needed after the object put to ensure
- // i) visibility to GC threads of the object put and ii) visibility
- // to the mutator thread of any card clearing write by a GC
- // thread. Clearly a normal store (str) will not guarantee this
- // ordering but neither will a releasing store (stlr). The latter
- // guarantees that the object put is visible but does not guarantee
- // that writes by other threads have also been observed.
- //
- // So, returning to the task of translating the object put and the
- // leading/trailing membar nodes: what do the non-normal node graph
- // look like for these 2 special cases? and how can we determine the
- // status of a MemBarRelease, StoreX[mo_release] or MemBarVolatile
- // in both normal and non-normal cases?
- //
- // A CMS GC post-barrier wraps its card write (StoreCM) inside an If
- // which selects conditonal execution based on the value loaded
- // (LoadB) from the card. Ctl and Mem are fed to the If via an
- // intervening StoreLoad barrier (MemBarVolatile).
- //
- // So, with CMS we may see a node graph for a volatile object store
- // 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
- // | MergeMem
- // | |
- // {MemBarCPUOrder}
- // 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 difference being
- // that the StoreN/P node is replaced by a CompareAndSwapP/N node
- // and the trailing MemBarVolatile by a MemBarCPUOrder +
- // MemBarAcquire pair (also the MemBarCPUOrder nodes are not optional).
- //
- // MemBarRelease
- // MemBarCPUOrder_(leading)_______________
- // C | M \ \\ C \
- // | \ CompareAndSwapN/P CastP2X
- // | \ |
- // | \ SCMemProj
- // | Bot \ /
- // | MergeMem
- // | /
- // MemBarVolatile (card mark)
- // C | || M |
- // | LoadB |
- // | | |
- // | Cmp |\
- // | / | \
- // If | \
- // | \ | \
- // IfFalse IfTrue | \
- // \ / \ | \
- // \ / StoreCM |
- // \ / | |
- // Region . . . |
- // | \ /
- // | . . . \ / Bot
- // | MergeMem
- // | |
- // MemBarCPUOrder
- // MemBarVolatile (trailing)
- //
- //
- // G1 is quite a lot more complicated. The nodes inserted on behalf
- // of G1 may comprise: a pre-write graph which adds the old value to
- // the SATB queue; the releasing store itself; and, finally, a
- // post-write graph which performs a card mark.
- //
- // The pre-write graph may be omitted, but only when the put is
- // writing to a newly allocated (young gen) object and then only if
- // there is a direct memory chain to the Initialize node for the
- // object allocation. This will not happen for a volatile put since
- // any memory chain passes through the leading membar.
- //
- // The pre-write graph includes a series of 3 If tests. The outermost
- // If tests whether SATB is enabled (no else case). The next If tests
- // whether the old value is non-NULL (no else case). The third tests
- // whether the SATB queue index is > 0, if so updating the queue. The
- // else case for this third If calls out to the runtime to allocate a
- // new queue buffer.
- //
- // So with G1 the pre-write and releasing store subgraph looks like
- // this (the nested Ifs are omitted).
- //
- // MemBarRelease
- // {MemBarCPUOrder}_(leading)___________
- // C | || M \ M \ M \ M \ . . .
- // | LoadB \ LoadL LoadN \
- // | / \ \
- // If |\ \
- // | \ | \ \
- // IfFalse IfTrue | \ \
- // | | | \ |
- // | If | /\ |
- // | | \ |
- // | \ |
- // | . . . \ |
- // | / | / | |
- // Region Phi[M] | |
- // | \ | | |
- // | \_____ | ___ | |
- // C | C \ | C \ M | |
- // | CastP2X | StoreN/P[mo_release] |
- // | | | |
- // C | M | M | M |
- // \ | | /
- // . . .
- // (post write subtree elided)
- // . . .
- // C \ M /
- // \ /
- // {MemBarCPUOrder}
- // MemBarVolatile (trailing)
- //
- // n.b. the LoadB in this subgraph is not the card read -- it's a
- // read of the SATB queue active flag.
- //
- // 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
- // 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.
- //
- // The kernel of the post-write G1 subgraph is the card mark itself
- // which includes a card mark memory barrier (MemBarVolatile), a
- // card test (LoadB), and a conditional update (If feeding a
- // StoreCM). These nodes are surrounded by a series of nested Ifs
- // which try to avoid doing the card mark. The top level If skips if
- // the object reference does not cross regions (i.e. it tests if
- // (adr ^ val) >> log2(regsize) != 0) -- intra-region references
- // need not be recorded. The next If, which skips on a NULL value,
- // may be absent (it is not generated if the type of value is >=
- // OopPtr::NotNull). The 3rd If skips writes to young regions (by
- // checking if card_val != young). n.b. although this test requires
- // a pre-read of the card it can safely be done before the StoreLoad
- // barrier. However that does not bypass the need to reread the card
- // after the barrier. A final, 4th If tests if the card is already
- // marked.
- //
- // (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
- // \ /
- // {MemBarCPUOrder}
- // 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. The same variations are
- // introduced as for CMS with conditional card marking i.e. the
- // StoreP/N is swapped for a CompareAndSwapP/N with a following
- // SCMemProj, the trailing MemBarVolatile for a MemBarCPUOrder +
- // MemBarAcquire pair. There may be an extra If test introduced in
- // the CAS case, when the boolean result of the CAS is tested by the
- // caller. In that case an extra Region and AliasIdxBot Phi may be
- // introduced before the MergeMem
- //
- // So, the upshot is that in all cases the subgraph will include a
- // *normal* memory subgraph betwen the leading membar and its child
- // membar: either a normal volatile put graph including a releasing
- // StoreX and terminating with a trailing volatile membar or card
- // mark volatile membar; or a normal CAS graph including a
- // CompareAndSwapX + SCMemProj pair and terminating with a card mark
- // volatile membar or a trailing cpu order and acquire membar
- // pair. If the child membar is not a (volatile) 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 larger volatile put or CAS 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, 3 or 4
- // Phi nodes merging the leading barrier memory flow (for G1).
- //
- // The predicates controlling generation of instructions for store
- // and barrier nodes employ a few simple helper functions (described
- // below) which identify the presence or absence of all these
- // subgraph configurations and provide a means of traversing from
- // one node in the subgraph to another.
-
// is_CAS(int opcode)
//
// return true if opcode is one of the possible CompareAndSwapX
@@ -1910,674 +1298,7 @@
// traverse when searching from a card mark membar for the merge mem
// feeding a trailing membar or vice versa
- int max_phis()
- {
- if (UseG1GC) {
- return 4;
- } else if (UseConcMarkSweepGC && UseCondCardMark) {
- return 1;
- } else {
- return 0;
- }
- }
-
- // leading_to_normal
- //
- // graph traversal helper which detects the normal case Mem feed
- // from a release membar (or, optionally, its cpuorder child) to a
- // dependent volatile or acquire membar i.e. it ensures that one of
- // the following 3 Mem flow subgraphs is present.
- //
- // MemBarRelease
- // {MemBarCPUOrder} {leading}
- // | \ . . .
- // | StoreN/P[mo_release] . . .
- // | /
- // MergeMem
- // |
- // {MemBarCPUOrder}
- // MemBarVolatile {trailing or card mark}
- //
- // MemBarRelease
- // MemBarCPUOrder {leading}
- // | \ . . .
- // | CompareAndSwapX . . .
- // | /
- // MergeMem
- // |
- // MemBarVolatile {card mark}
- //
- // MemBarRelease
- // MemBarCPUOrder {leading}
- // | \ . . .
- // | CompareAndSwapX . . .
- // | /
- // MergeMem
- // |
- // MemBarCPUOrder
- // MemBarAcquire {trailing}
- //
- // if the correct configuration is present returns the trailing
- // or cardmark membar otherwise NULL.
- //
- // the input membar is expected to be either a cpuorder membar or a
- // release membar. in the latter case it should not have a cpu membar
- // child.
- //
- // the returned value may be a card mark or trailing membar
- //
-
- MemBarNode *leading_to_normal(MemBarNode *leading)
- {
- assert((leading->Opcode() == Op_MemBarRelease ||
- leading->Opcode() == Op_MemBarCPUOrder),
- "expecting a volatile or cpuroder membar!");
-
- // check the mem flow
- ProjNode *mem = leading->proj_out(TypeFunc::Memory);
-
- if (!mem) {
- return NULL;
- }
-
- Node *x = NULL;
- StoreNode * st = NULL;
- LoadStoreNode *cas = NULL;
- MergeMemNode *mm = 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;
- }
- // 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) {
- return NULL;
- }
- st = x->as_Store();
- } else if (is_CAS(x->Opcode())) {
- if (st != NULL || cas != NULL) {
- return NULL;
- }
- cas = x->as_LoadStore();
- }
- }
-
- // must have a store or a cas
- if (!st && !cas) {
- return NULL;
- }
-
- // must have a merge
- if (!mm) {
- return NULL;
- }
-
- Node *feed = NULL;
- if (cas) {
- // look for an SCMemProj
- for (DUIterator_Fast imax, i = cas->fast_outs(imax); i < imax; i++) {
- x = cas->fast_out(i);
- if (x->Opcode() == Op_SCMemProj) {
- feed = x;
- break;
- }
- }
- if (feed == NULL) {
- return NULL;
- }
- } else {
- feed = st;
- }
- // ensure the feed node feeds the existing mergemem;
- for (DUIterator_Fast imax, i = feed->fast_outs(imax); i < imax; i++) {
- x = feed->fast_out(i);
- if (x == mm) {
- break;
- }
- }
- if (x != mm) {
- 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()) {
- if (x->Opcode() == Op_MemBarCPUOrder) {
- // with a store any cpu order membar should precede a
- // trailing volatile membar. with a cas it should precede a
- // trailing acquire membar. in either case try to skip to
- // that next membar
- MemBarNode *y = x->as_MemBar();
- y = child_membar(y);
- if (y != NULL) {
- // skip to this new membar to do the check
- x = y;
- }
-
- }
- if (x->Opcode() == Op_MemBarVolatile) {
- mbar = x->as_MemBar();
- // for a volatile store this can be either a trailing membar
- // or a card mark membar. for a cas it must be a card mark
- // membar
- guarantee(cas == NULL || is_card_mark_membar(mbar),
- "in CAS graph volatile membar must be a card mark");
- } else if (cas != NULL && x->Opcode() == Op_MemBarAcquire) {
- mbar = x->as_MemBar();
- }
- break;
- }
- }
-
- return mbar;
- }
-
- // normal_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 of the following 3 Mem flow subgraphs is present.
- //
- // MemBarRelease
- // {MemBarCPUOrder} {leading}
- // | \ . . .
- // | StoreN/P[mo_release] . . .
- // | /
- // MergeMem
- // |
- // {MemBarCPUOrder}
- // MemBarVolatile {trailing or card mark}
- //
- // MemBarRelease
- // MemBarCPUOrder {leading}
- // | \ . . .
- // | CompareAndSwapX . . .
- // | /
- // MergeMem
- // |
- // MemBarVolatile {card mark}
- //
- // MemBarRelease
- // MemBarCPUOrder {leading}
- // | \ . . .
- // | CompareAndSwapX . . .
- // | /
- // MergeMem
- // |
- // MemBarCPUOrder
- // MemBarAcquire {trailing}
- //
- // 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 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)
- {
- // input must be a volatile membar
- assert((barrier->Opcode() == Op_MemBarVolatile ||
- barrier->Opcode() == Op_MemBarAcquire),
- "expecting a volatile or an acquire membar");
- bool barrier_is_acquire = barrier->Opcode() == Op_MemBarAcquire;
-
- // if we have an intervening cpu order membar then start the
- // search from it
-
- Node *x = parent_membar(barrier);
-
- if (x == NULL) {
- // stick with the original barrier
- x = (Node *)barrier;
- } else if (x->Opcode() != Op_MemBarCPUOrder) {
- // any other barrier means this is not the graph we want
- return NULL;
- }
-
- // the Mem feed to the membar should be a merge
- x = x ->in(TypeFunc::Memory);
- if (!x->is_MergeMem())
- return NULL;
-
- MergeMemNode *mm = x->as_MergeMem();
-
- // the merge should get its Bottom mem feed from the leading membar
- x = mm->in(Compile::AliasIdxBot);
-
- // ensure this is a non control projection
- if (!x->is_Proj() || x->is_CFG()) {
- return NULL;
- }
- // if it is fed by a membar that's the one we want
- x = x->in(0);
-
- if (!x->is_MemBar()) {
- return NULL;
- }
-
- MemBarNode *leading = x->as_MemBar();
- // reject invalid candidates
- if (!leading_membar(leading)) {
- return NULL;
- }
-
- // ok, we have a leading membar, now for the sanity clauses
-
- // the leading membar must feed Mem to a releasing store or CAS
- ProjNode *mem = leading->proj_out(TypeFunc::Memory);
- StoreNode *st = NULL;
- LoadStoreNode *cas = NULL;
- for (DUIterator_Fast imax, i = mem->fast_outs(imax); i < imax; i++) {
- x = mem->fast_out(i);
- if (x->is_Store() && x->as_Store()->is_release() && x->Opcode() != Op_StoreCM) {
- // two stores or CASes is one too many
- if (st != NULL || cas != NULL) {
- return NULL;
- }
- st = x->as_Store();
- } else if (is_CAS(x->Opcode())) {
- if (st != NULL || cas != NULL) {
- return NULL;
- }
- cas = x->as_LoadStore();
- }
- }
-
- // we cannot have both a store and a cas
- if (st == NULL && cas == NULL) {
- // we have neither -- this is not a normal graph
- return NULL;
- }
- if (st == NULL) {
- // if we started from a volatile membar and found a CAS then the
- // original membar ought to be for a card mark
- guarantee((barrier_is_acquire || is_card_mark_membar(barrier)),
- "unexpected volatile barrier (i.e. not card mark) in CAS graph");
- // check that the CAS feeds the merge we used to get here via an
- // intermediary SCMemProj
- Node *scmemproj = NULL;
- for (DUIterator_Fast imax, i = cas->fast_outs(imax); i < imax; i++) {
- x = cas->fast_out(i);
- if (x->Opcode() == Op_SCMemProj) {
- scmemproj = x;
- break;
- }
- }
- if (scmemproj == NULL) {
- return NULL;
- }
- for (DUIterator_Fast imax, i = scmemproj->fast_outs(imax); i < imax; i++) {
- x = scmemproj->fast_out(i);
- if (x == mm) {
- return leading;
- }
- }
- } else {
- // we should not have found a store if we started from an acquire
- guarantee(!barrier_is_acquire,
- "unexpected trailing acquire barrier in volatile store graph");
-
- // the store should feed the merge we used to get here
- for (DUIterator_Fast imax, i = st->fast_outs(imax); i < imax; i++) {
- if (st->fast_out(i) == mm) {
- return leading;
- }
- }
- }
-
- 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
- // |
- // {MemBarCPUOrder} OR MemBarCPUOrder
- // MemBarVolatile {trailing} MemBarAcquire {trailing}
- //
- //
- // 2)
- // MemBarRelease/CPUOrder (leading)
- // |
- // |
- // |\ . . .
- // | \ |
- // | \ MemBarVolatile (card mark)
- // | \ | |
- // \ \ | StoreCM . . .
- // \ \ |
- // \ Phi
- // \ /
- // Phi . . .
- // Bot | /
- // MergeMem
- // |
- // {MemBarCPUOrder} OR MemBarCPUOrder
- // MemBarVolatile {trailing} MemBarAcquire {trailing}
- //
- // 3)
- // MemBarRelease/CPUOrder (leading)
- // |
- // |\
- // | \
- // | \ . . .
- // | \ |
- // |\ \ MemBarVolatile (card mark)
- // | \ \ | |
- // | \ \ | StoreCM . . .
- // | \ \ |
- // \ \ Phi
- // \ \ /
- // \ Phi
- // \ /
- // Phi . . .
- // Bot | /
- // MergeMem
- // |
- // |
- // {MemBarCPUOrder} OR MemBarCPUOrder
- // MemBarVolatile {trailing} MemBarAcquire {trailing}
- //
- // 4)
- // MemBarRelease/CPUOrder (leading)
- // |
- // |\
- // | \
- // | \
- // | \
- // |\ \
- // | \ \
- // | \ \ . . .
- // | \ \ |
- // |\ \ \ MemBarVolatile (card mark)
- // | \ \ \ / |
- // | \ \ \ / StoreCM . . .
- // | \ \ Phi
- // \ \ \ /
- // \ \ Phi
- // \ \ /
- // \ Phi
- // \ /
- // Phi . . .
- // Bot | /
- // MergeMem
- // |
- // |
- // MemBarCPUOrder
- // MemBarAcquire {trailing}
- //
- // configuration 1 is only valid if UseConcMarkSweepGC &&
- // UseCondCardMark
- //
- // configuration 2, is only valid if UseConcMarkSweepGC &&
- // UseCondCardMark or if UseG1GC
- //
- // configurations 3 and 4 are only valid if UseG1GC.
- //
- // if a valid configuration is present returns the trailing membar
- // otherwise NULL.
- //
- // n.b. the supplied membar is expected to be a card mark
- // MemBarVolatile i.e. the caller must ensure the input node has the
- // correct operand and feeds Mem to a StoreCM node
-
- MemBarNode *card_mark_to_trailing(const MemBarNode *barrier)
- {
- // input must be a card mark volatile membar
- assert(is_card_mark_membar(barrier), "expecting a card mark membar");
-
- Node *feed = barrier->proj_out(TypeFunc::Memory);
- Node *x;
- MergeMemNode *mm = NULL;
-
- const int MAX_PHIS = max_phis(); // 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 (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
- guarantee(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 fed by the merge
- for (DUIterator_Fast imax, i = mm->fast_outs(imax); i < imax; i++) {
- x = mm->fast_out(i);
- if (x->is_MemBar()) {
- // if this is an intervening cpu order membar skip to the
- // following membar
- if (x->Opcode() == Op_MemBarCPUOrder) {
- MemBarNode *y = x->as_MemBar();
- y = child_membar(y);
- if (y != NULL) {
- x = y;
- }
- }
- if (x->Opcode() == Op_MemBarVolatile ||
- x->Opcode() == Op_MemBarAcquire) {
- 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 or MemBarAcquire 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 ||
- trailing->Opcode() == Op_MemBarAcquire,
- "expecting a volatile or acquire membar");
- assert(!is_card_mark_membar(trailing),
- "not expecting a card mark membar");
-
- Node *x = (Node *)trailing;
-
- // look for a preceding cpu order membar
- MemBarNode *y = parent_membar(x->as_MemBar());
- if (y != NULL) {
- // make sure it is a cpu order membar
- if (y->Opcode() != Op_MemBarCPUOrder) {
- // this is nto the graph we were looking for
- return NULL;
- }
- // start the search from here
- x = y;
- }
-
- // the Mem feed to the membar should be a merge
- x = x->in(TypeFunc::Memory);
- if (!x->is_MergeMem()) {
- return NULL;
- }
-
- 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 = max_phis(); // max phis we will search through
- int phicount = 0; // current search count
-
- bool retry_feed = !x->is_Proj();
-
- while (retry_feed) {
- if (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() && x->adr_type() == TypePtr::BOTTOM) {
- 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) {
- return leading;
- }
-
- // there is no normal path from trailing to leading membar. see if
- // we can arrive via a card mark membar
-
- 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
+// predicates controlling emit of ldr<x>/ldar<x> and associated dmb
bool unnecessary_acquire(const Node *barrier)
{
@@ -2588,40 +1309,19 @@
return false;
}
- // a volatile read derived from bytecode (or also from an inlined
- // SHA field read via LibraryCallKit::load_field_from_object)
- // manifests as a LoadX[mo_acquire] followed by an acquire membar
- // with a bogus read dependency on it's preceding load. so in those
- // cases we will find the load node at the PARMS offset of the
- // acquire membar. n.b. there may be an intervening DecodeN node.
-
- Node *x = barrier->lookup(TypeFunc::Parms);
- if (x) {
- // we are starting from an acquire and it has a fake dependency
- //
- // need to check for
- //
- // LoadX[mo_acquire]
- // { |1 }
- // {DecodeN}
- // |Parms
- // MemBarAcquire*
- //
- // where * tags node we were passed
- // and |k means input k
- if (x->is_DecodeNarrowPtr()) {
- x = x->in(1);
- }
-
- return (x->is_Load() && x->as_Load()->is_acquire());
+ MemBarNode* mb = barrier->as_MemBar();
+
+ if (mb->trailing_load()) {
+ return true;
}
- // other option for unnecessary membar is that it is a trailing node
- // belonging to a CAS
-
- MemBarNode *leading = trailing_to_leading(barrier->as_MemBar());
-
- return leading != NULL;
+ if (mb->trailing_load_store()) {
+ Node* load_store = mb->in(MemBarNode::Precedent);
+ assert(load_store->is_LoadStore(), "unexpected graph shape");
+ return is_CAS(load_store->Opcode());
+ }
+
+ return false;
}
bool needs_acquiring_load(const Node *n)
@@ -2634,45 +1334,7 @@
LoadNode *ld = n->as_Load();
- if (!ld->is_acquire()) {
- return false;
- }
-
- // check if this load is feeding an acquire membar
- //
- // LoadX[mo_acquire]
- // { |1 }
- // {DecodeN}
- // |Parms
- // MemBarAcquire*
- //
- // where * tags node we were passed
- // and |k means input k
-
- Node *start = ld;
- Node *mbacq = NULL;
-
- // if we hit a DecodeNarrowPtr we reset the start node and restart
- // the search through the outputs
- restart:
-
- for (DUIterator_Fast imax, i = start->fast_outs(imax); i < imax; i++) {
- Node *x = start->fast_out(i);
- if (x->is_MemBar() && x->Opcode() == Op_MemBarAcquire) {
- mbacq = x;
- } else if (!mbacq &&
- (x->is_DecodeNarrowPtr() ||
- (x->is_Mach() && x->Opcode() == Op_DecodeN))) {
- start = x;
- goto restart;
- }
- }
-
- if (mbacq) {
- return true;
- }
-
- return false;
+ return ld->is_acquire();
}
bool unnecessary_release(const Node *n)
@@ -2686,32 +1348,27 @@
return false;
}
- // if there is a dependent CPUOrder barrier then use that as the
- // leading
-
MemBarNode *barrier = n->as_MemBar();
- // check for an intervening cpuorder membar
- MemBarNode *b = child_membar(barrier);
- if (b && b->Opcode() == Op_MemBarCPUOrder) {
- // ok, so start the check from the dependent cpuorder barrier
- barrier = b;
+ if (!barrier->leading()) {
+ return false;
+ } else {
+ Node* trailing = barrier->trailing_membar();
+ MemBarNode* trailing_mb = trailing->as_MemBar();
+ assert(trailing_mb->trailing(), "Not a trailing membar?");
+ assert(trailing_mb->leading_membar() == n, "inconsistent leading/trailing membars");
+
+ Node* mem = trailing_mb->in(MemBarNode::Precedent);
+ if (mem->is_Store()) {
+ assert(mem->as_Store()->is_release(), "");
+ assert(trailing_mb->Opcode() == Op_MemBarVolatile, "");
+ return true;
+ } else {
+ assert(mem->is_LoadStore(), "");
+ assert(trailing_mb->Opcode() == Op_MemBarAcquire, "");
+ return is_CAS(mem->Opcode());
+ }
}
-
- // 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);
- return (trailing != NULL);
+ return false;
}
bool unnecessary_volatile(const Node *n)
@@ -2724,17 +1381,18 @@
MemBarNode *mbvol = n->as_MemBar();
- // first we check if this is part of a card mark. if so then we have
- // to generate a StoreLoad barrier
-
- if (is_card_mark_membar(mbvol)) {
- return false;
+ bool release = mbvol->trailing_store();
+ assert(!release || (mbvol->in(MemBarNode::Precedent)->is_Store() && mbvol->in(MemBarNode::Precedent)->as_Store()->is_release()), "");
+#ifdef ASSERT
+ if (release) {
+ Node* leading = mbvol->leading_membar();
+ assert(leading->Opcode() == Op_MemBarRelease, "");
+ assert(leading->as_MemBar()->leading_store(), "");
+ assert(leading->as_MemBar()->trailing_membar() == mbvol, "");
}
-
- // ok, if it's not a card mark then we still need to check if it is
- // a trailing membar of a volatile put graph.
-
- return (trailing_to_leading(mbvol) != NULL);
+#endif
+
+ return release;
}
// predicates controlling emit of str<x>/stlr<x> and associated dmbs
@@ -2749,53 +1407,7 @@
StoreNode *st = n->as_Store();
- // the store must be marked as releasing
- if (!st->is_release()) {
- return false;
- }
-
- // the store must be fed by a membar
-
- Node *x = st->lookup(StoreNode::Memory);
-
- if (! x || !x->is_Proj()) {
- return false;
- }
-
- ProjNode *proj = x->as_Proj();
-
- x = proj->lookup(0);
-
- if (!x || !x->is_MemBar()) {
- return false;
- }
-
- MemBarNode *barrier = x->as_MemBar();
-
- // if the barrier is a release membar or a cpuorder mmebar fed by a
- // release membar then we need to check whether that forms part of a
- // volatile put graph.
-
- // reject invalid candidates
- if (!leading_membar(barrier)) {
- return false;
- }
-
- // 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);
+ return st->trailing_membar() != NULL;
}
// predicate controlling translation of CAS
@@ -2809,48 +1421,9 @@
return false;
}
- // CAS nodes only ought to turn up in inlined unsafe CAS operations
-#ifdef ASSERT
- LoadStoreNode *st = n->as_LoadStore();
-
- // the store must be fed by a membar
-
- Node *x = st->lookup(StoreNode::Memory);
-
- assert (x && x->is_Proj(), "CAS not fed by memory proj!");
-
- ProjNode *proj = x->as_Proj();
-
- x = proj->lookup(0);
-
- assert (x && x->is_MemBar(), "CAS not fed by membar!");
-
- MemBarNode *barrier = x->as_MemBar();
-
- // the barrier must be a cpuorder mmebar fed by a release membar
-
- guarantee(barrier->Opcode() == Op_MemBarCPUOrder,
- "CAS not fed by cpuorder membar!");
-
- MemBarNode *b = parent_membar(barrier);
- assert ((b != NULL && b->Opcode() == Op_MemBarRelease),
- "CAS not fed by cpuorder+release membar pair!");
-
- // does this lead a normal subgraph?
- MemBarNode *mbar = leading_to_normal(barrier);
-
- guarantee(mbar != NULL, "CAS not embedded in normal graph!");
-
- // if this is a card mark membar check we have a trailing acquire
-
- if (is_card_mark_membar(mbar)) {
- mbar = card_mark_to_trailing(mbar);
- }
-
- guarantee(mbar != NULL, "card mark membar for CAS not embedded in normal graph!");
-
- guarantee(mbar->Opcode() == Op_MemBarAcquire, "trailing membar should be an acquire");
-#endif // ASSERT
+ LoadStoreNode* ldst = n->as_LoadStore();
+ assert(ldst->trailing_membar() != NULL, "expected trailing membar");
+
// so we can just return true here
return true;
}
@@ -11050,6 +9623,24 @@
ins_pipe(imac_reg_reg);
%}
+// Combined Integer Multiply & Neg
+
+instruct mnegI(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2, immI0 zero) %{
+ match(Set dst (MulI (SubI zero src1) src2));
+ match(Set dst (MulI src1 (SubI zero src2)));
+
+ ins_cost(INSN_COST * 3);
+ format %{ "mneg $dst, $src1, $src2" %}
+
+ ins_encode %{
+ __ mnegw(as_Register($dst$$reg),
+ as_Register($src1$$reg),
+ as_Register($src2$$reg));
+ %}
+
+ ins_pipe(imac_reg_reg);
+%}
+
// Combined Long Multiply & Add/Sub
instruct maddL(iRegLNoSp dst, iRegL src1, iRegL src2, iRegL src3) %{
@@ -11084,6 +9675,24 @@
ins_pipe(lmac_reg_reg);
%}
+// Combined Long Multiply & Neg
+
+instruct mnegL(iRegLNoSp dst, iRegL src1, iRegL src2, immL0 zero) %{
+ match(Set dst (MulL (SubL zero src1) src2));
+ match(Set dst (MulL src1 (SubL zero src2)));
+
+ ins_cost(INSN_COST * 5);
+ format %{ "mneg $dst, $src1, $src2" %}
+
+ ins_encode %{
+ __ mneg(as_Register($dst$$reg),
+ as_Register($src1$$reg),
+ as_Register($src2$$reg));
+ %}
+
+ ins_pipe(lmac_reg_reg);
+%}
+
// Integer Divide
instruct divI(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{
--- a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -295,7 +295,7 @@
int _offset;
Register _r;
public:
- PrePost(Register reg, int o) : _r(reg), _offset(o) { }
+ PrePost(Register reg, int o) : _offset(o), _r(reg) { }
int offset() { return _offset; }
Register reg() { return _r; }
};
@@ -353,7 +353,7 @@
ext::operation _op;
public:
extend() { }
- extend(int s, int o, ext::operation op) : _shift(s), _option(o), _op(op) { }
+ extend(int s, int o, ext::operation op) : _option(o), _shift(s), _op(op) { }
int option() const{ return _option; }
int shift() const { return _shift; }
ext::operation op() const { return _op; }
@@ -398,26 +398,25 @@
Address()
: _mode(no_mode) { }
Address(Register r)
- : _mode(base_plus_offset), _base(r), _offset(0), _index(noreg), _target(0) { }
+ : _base(r), _index(noreg), _offset(0), _mode(base_plus_offset), _target(0) { }
Address(Register r, int o)
- : _mode(base_plus_offset), _base(r), _offset(o), _index(noreg), _target(0) { }
+ : _base(r), _index(noreg), _offset(o), _mode(base_plus_offset), _target(0) { }
Address(Register r, long o)
- : _mode(base_plus_offset), _base(r), _offset(o), _index(noreg), _target(0) { }
+ : _base(r), _index(noreg), _offset(o), _mode(base_plus_offset), _target(0) { }
Address(Register r, unsigned long o)
- : _mode(base_plus_offset), _base(r), _offset(o), _index(noreg), _target(0) { }
+ : _base(r), _index(noreg), _offset(o), _mode(base_plus_offset), _target(0) { }
#ifdef ASSERT
Address(Register r, ByteSize disp)
- : _mode(base_plus_offset), _base(r), _offset(in_bytes(disp)),
- _index(noreg), _target(0) { }
+ : _base(r), _index(noreg), _offset(in_bytes(disp)), _mode(base_plus_offset), _target(0) { }
#endif
Address(Register r, Register r1, extend ext = lsl())
- : _mode(base_plus_offset_reg), _base(r), _index(r1),
- _ext(ext), _offset(0), _target(0) { }
+ : _base(r), _index(r1), _offset(0), _mode(base_plus_offset_reg),
+ _ext(ext), _target(0) { }
Address(Pre p)
- : _mode(pre), _base(p.reg()), _offset(p.offset()) { }
+ : _base(p.reg()), _offset(p.offset()), _mode(pre) { }
Address(Post p)
- : _mode(p.idx_reg() == NULL ? post : post_reg), _base(p.reg()),
- _offset(p.offset()), _target(0), _index(p.idx_reg()) { }
+ : _base(p.reg()), _index(p.idx_reg()), _offset(p.offset()),
+ _mode(p.idx_reg() == NULL ? post : post_reg), _target(0) { }
Address(address target, RelocationHolder const& rspec)
: _mode(literal),
_rspec(rspec),
@@ -426,7 +425,7 @@
Address(address target, relocInfo::relocType rtype = relocInfo::external_word_type);
Address(Register base, RegisterOrConstant index, extend ext = lsl())
: _base (base),
- _ext(ext), _offset(0), _target(0) {
+ _offset(0), _ext(ext), _target(0) {
if (index.is_register()) {
_mode = base_plus_offset_reg;
_index = index.as_register();
--- a/src/hotspot/cpu/aarch64/c1_CodeStubs_aarch64.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/cpu/aarch64/c1_CodeStubs_aarch64.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -50,13 +50,13 @@
}
RangeCheckStub::RangeCheckStub(CodeEmitInfo* info, LIR_Opr index, LIR_Opr array)
- : _throw_index_out_of_bounds_exception(false), _index(index), _array(array) {
+ : _index(index), _array(array), _throw_index_out_of_bounds_exception(false) {
assert(info != NULL, "must have info");
_info = new CodeEmitInfo(info);
}
RangeCheckStub::RangeCheckStub(CodeEmitInfo* info, LIR_Opr index)
- : _throw_index_out_of_bounds_exception(true), _index(index), _array(NULL) {
+ : _index(index), _array(NULL), _throw_index_out_of_bounds_exception(true) {
assert(info != NULL, "must have info");
_info = new CodeEmitInfo(info);
}
--- a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -2167,6 +2167,9 @@
Register length = op->length()->as_register();
Register tmp = op->tmp()->as_register();
+ __ resolve(ACCESS_READ, src);
+ __ resolve(ACCESS_WRITE, dst);
+
CodeStub* stub = op->stub();
int flags = op->flags();
BasicType basic_type = default_type != NULL ? default_type->element_type()->basic_type() : T_ILLEGAL;
@@ -2510,6 +2513,7 @@
scratch = op->scratch_opr()->as_register();
}
assert(BasicLock::displaced_header_offset_in_bytes() == 0, "lock_reg must point to the displaced header");
+ __ resolve(ACCESS_READ | ACCESS_WRITE, obj);
// add debug info for NullPointerException only if one is possible
int null_check_offset = __ lock_object(hdr, obj, lock, scratch, *op->stub()->entry());
if (op->info() != NULL) {
--- a/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -941,6 +941,10 @@
index = tmp;
}
+ if (is_updateBytes) {
+ base_op = access_resolve(ACCESS_READ, base_op);
+ }
+
if (offset) {
LIR_Opr tmp = new_pointer_register();
__ add(base_op, LIR_OprFact::intConst(offset), tmp);
@@ -1019,6 +1023,10 @@
index = tmp;
}
+ if (is_updateBytes) {
+ base_op = access_resolve(ACCESS_READ, base_op);
+ }
+
if (offset) {
LIR_Opr tmp = new_pointer_register();
__ add(base_op, LIR_OprFact::intConst(offset), tmp);
--- a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -1152,12 +1152,12 @@
public:
MoveOperation(int src_index, VMRegPair src, int dst_index, VMRegPair dst):
_src(src)
+ , _dst(dst)
, _src_index(src_index)
- , _dst(dst)
, _dst_index(dst_index)
+ , _processed(false)
, _next(NULL)
- , _prev(NULL)
- , _processed(false) { Unimplemented(); }
+ , _prev(NULL) { Unimplemented(); }
VMRegPair src() const { Unimplemented(); return _src; }
int src_id() const { Unimplemented(); return 0; }
--- a/src/hotspot/cpu/arm/assembler_arm_32.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/cpu/arm/assembler_arm_32.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -1083,6 +1083,7 @@
break;
default:
ShouldNotReachHere();
+ return;
}
emit_int32(0xf << 28 | 0x1 << 25 | 0x1 << 23 | 0x1 << 4 |
(imm8 >> 7) << 24 | ((imm8 & 0x70) >> 4) << 16 | (imm8 & 0xf) |
@@ -1113,6 +1114,7 @@
break;
default:
ShouldNotReachHere();
+ return;
}
emit_int32(cond << 28 | 0x1D /* 0b11101 */ << 23 | 0xB /* 0b1011 */ << 8 | 0x1 << 4 |
quad << 21 | b << 22 | e << 5 | Rs->encoding() << 12 |
@@ -1143,6 +1145,7 @@
break;
default:
ShouldNotReachHere();
+ return;
}
emit_int32(0xF /* 0b1111 */ << 28 | 0x3B /* 0b00111011 */ << 20 | 0x6 /* 0b110 */ << 9 |
quad << 6 | imm4 << 16 |
--- a/src/hotspot/cpu/arm/c1_CodeStubs_arm.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/cpu/arm/c1_CodeStubs_arm.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -52,13 +52,13 @@
RangeCheckStub::RangeCheckStub(CodeEmitInfo* info, LIR_Opr index, LIR_Opr array)
- : _throw_index_out_of_bounds_exception(false), _index(index), _array(array) {
+ : _index(index), _array(array), _throw_index_out_of_bounds_exception(false) {
assert(info != NULL, "must have info");
_info = new CodeEmitInfo(info);
}
RangeCheckStub::RangeCheckStub(CodeEmitInfo* info, LIR_Opr index)
- : _throw_index_out_of_bounds_exception(true), _index(index), _array(NULL) {
+ : _index(index), _array(NULL), _throw_index_out_of_bounds_exception(true) {
assert(info != NULL, "must have info");
_info = new CodeEmitInfo(info);
}
--- a/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -3086,7 +3086,7 @@
Label ok;
if (op->condition() != lir_cond_always) {
- AsmCondition acond;
+ AsmCondition acond = al;
switch (op->condition()) {
case lir_cond_equal: acond = eq; break;
case lir_cond_notEqual: acond = ne; break;
--- a/src/hotspot/cpu/arm/c1_LIRGenerator_arm.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/cpu/arm/c1_LIRGenerator_arm.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -733,6 +733,7 @@
default:
ShouldNotReachHere();
+ return;
}
#else
switch (x->op()) {
@@ -757,6 +758,7 @@
break;
default:
ShouldNotReachHere();
+ return;
}
LIR_Opr result = call_runtime(x->y(), x->x(), entry, x->type(), NULL);
set_result(x, result);
@@ -824,7 +826,7 @@
if (x->op() == Bytecodes::_irem) {
out_reg = FrameMap::R0_opr;
__ irem(left_arg->result(), right_arg->result(), out_reg, tmp, info);
- } else if (x->op() == Bytecodes::_idiv) {
+ } else { // (x->op() == Bytecodes::_idiv)
out_reg = FrameMap::R1_opr;
__ idiv(left_arg->result(), right_arg->result(), out_reg, tmp, info);
}
--- a/src/hotspot/cpu/ppc/c1_CodeStubs_ppc.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/cpu/ppc/c1_CodeStubs_ppc.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -39,13 +39,13 @@
RangeCheckStub::RangeCheckStub(CodeEmitInfo* info, LIR_Opr index, LIR_Opr array)
- : _throw_index_out_of_bounds_exception(false), _index(index), _array(array) {
+ : _index(index), _array(array), _throw_index_out_of_bounds_exception(false) {
assert(info != NULL, "must have info");
_info = new CodeEmitInfo(info);
}
RangeCheckStub::RangeCheckStub(CodeEmitInfo* info, LIR_Opr index)
- : _throw_index_out_of_bounds_exception(true), _index(index), _array(NULL) {
+ : _index(index), _array(NULL), _throw_index_out_of_bounds_exception(true) {
assert(info != NULL, "must have info");
_info = new CodeEmitInfo(info);
}
--- a/src/hotspot/cpu/ppc/frame_ppc.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/cpu/ppc/frame_ppc.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -359,13 +359,13 @@
// ...
//
- // frame pointer for this frame
- intptr_t* _fp;
-
// The frame's stack pointer before it has been extended by a c2i adapter;
// needed by deoptimization
intptr_t* _unextended_sp;
+ // frame pointer for this frame
+ intptr_t* _fp;
+
public:
// Accessors for fields
--- a/src/hotspot/cpu/ppc/frame_ppc.inline.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/cpu/ppc/frame_ppc.inline.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -55,7 +55,7 @@
// Constructors
// Initialize all fields, _unextended_sp will be adjusted in find_codeblob_and_set_pc_and_deopt_state.
-inline frame::frame() : _sp(NULL), _unextended_sp(NULL), _fp(NULL), _cb(NULL), _pc(NULL), _deopt_state(unknown) {}
+inline frame::frame() : _sp(NULL), _pc(NULL), _cb(NULL), _deopt_state(unknown), _unextended_sp(NULL), _fp(NULL) {}
inline frame::frame(intptr_t* sp) : _sp(sp), _unextended_sp(sp) {
find_codeblob_and_set_pc_and_deopt_state((address)own_abi()->lr); // also sets _fp and adjusts _unextended_sp
--- a/src/hotspot/cpu/s390/c1_CodeStubs_s390.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/cpu/s390/c1_CodeStubs_s390.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -41,13 +41,13 @@
#define CHECK_BAILOUT() { if (ce->compilation()->bailed_out()) return; }
RangeCheckStub::RangeCheckStub(CodeEmitInfo* info, LIR_Opr index, LIR_Opr array)
- : _throw_index_out_of_bounds_exception(false), _index(index), _array(array) {
+ : _index(index), _array(array), _throw_index_out_of_bounds_exception(false) {
assert(info != NULL, "must have info");
_info = new CodeEmitInfo(info);
}
RangeCheckStub::RangeCheckStub(CodeEmitInfo* info, LIR_Opr index)
- : _throw_index_out_of_bounds_exception(true), _index(index), _array(NULL) {
+ : _index(index), _array(NULL), _throw_index_out_of_bounds_exception(true) {
assert(info != NULL, "must have info");
_info = new CodeEmitInfo(info);
}
--- a/src/hotspot/cpu/s390/frame_s390.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/cpu/s390/frame_s390.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -444,12 +444,12 @@
// NOTE: Stack pointer is now held in the base class, so remove it from here.
+ // Needed by deoptimization.
+ intptr_t* _unextended_sp;
+
// Frame pointer for this frame.
intptr_t* _fp;
- // Needed by deoptimization.
- intptr_t* _unextended_sp;
-
public:
// Interface for all frames:
--- a/src/hotspot/cpu/s390/frame_s390.inline.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/cpu/s390/frame_s390.inline.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -54,7 +54,7 @@
// Constructors
// Initialize all fields, _unextended_sp will be adjusted in find_codeblob_and_set_pc_and_deopt_state.
-inline frame::frame() : _sp(NULL), _unextended_sp(NULL), _fp(NULL), _cb(NULL), _pc(NULL), _deopt_state(unknown) {}
+inline frame::frame() : _sp(NULL), _pc(NULL), _cb(NULL), _deopt_state(unknown), _unextended_sp(NULL), _fp(NULL) {}
inline frame::frame(intptr_t* sp) : _sp(sp), _unextended_sp(sp) {
find_codeblob_and_set_pc_and_deopt_state((address)own_abi()->return_pc);
@@ -71,7 +71,7 @@
// Generic constructor. Used by pns() in debug.cpp only
#ifndef PRODUCT
inline frame::frame(void* sp, void* pc, void* unextended_sp) :
- _sp((intptr_t*)sp), _unextended_sp((intptr_t*)unextended_sp), _cb(NULL), _pc(NULL) {
+ _sp((intptr_t*)sp), _pc(NULL), _cb(NULL), _unextended_sp((intptr_t*)unextended_sp) {
find_codeblob_and_set_pc_and_deopt_state((address)pc); // Also sets _fp and adjusts _unextended_sp.
}
#endif
--- a/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -3038,6 +3038,9 @@
Register length = op->length()->as_register();
Register tmp = op->tmp()->as_register();
+ __ resolve(ACCESS_READ, src);
+ __ resolve(ACCESS_WRITE, dst);
+
CodeStub* stub = op->stub();
int flags = op->flags();
BasicType basic_type = default_type != NULL ? default_type->element_type()->basic_type() : T_ILLEGAL;
@@ -3476,6 +3479,7 @@
scratch = op->scratch_opr()->as_register();
}
assert(BasicLock::displaced_header_offset_in_bytes() == 0, "lock_reg must point to the displaced header");
+ __ resolve(ACCESS_READ | ACCESS_WRITE, obj);
// add debug info for NullPointerException only if one is possible
int null_check_offset = __ lock_object(hdr, obj, lock, scratch, *op->stub()->entry());
if (op->info() != NULL) {
--- a/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -997,6 +997,10 @@
}
#endif
+ if (is_updateBytes) {
+ base_op = access_resolve(IS_NOT_NULL | ACCESS_READ, base_op);
+ }
+
LIR_Address* a = new LIR_Address(base_op,
index,
offset,
@@ -1054,7 +1058,7 @@
constant_aOffset = result_aOffset->as_jlong();
result_aOffset = LIR_OprFact::illegalOpr;
}
- LIR_Opr result_a = a.result();
+ LIR_Opr result_a = access_resolve(ACCESS_READ, a.result());
long constant_bOffset = 0;
LIR_Opr result_bOffset = bOffset.result();
@@ -1062,7 +1066,7 @@
constant_bOffset = result_bOffset->as_jlong();
result_bOffset = LIR_OprFact::illegalOpr;
}
- LIR_Opr result_b = b.result();
+ LIR_Opr result_b = access_resolve(ACCESS_READ, b.result());
#ifndef _LP64
result_a = new_register(T_INT);
--- a/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -23,10 +23,12 @@
#include "precompiled.hpp"
#include "asm/macroAssembler.inline.hpp"
+#include "code/codeBlob.hpp"
#include "gc/z/zBarrier.inline.hpp"
#include "gc/z/zBarrierSet.hpp"
#include "gc/z/zBarrierSetAssembler.hpp"
#include "gc/z/zBarrierSetRuntime.hpp"
+#include "memory/resourceArea.hpp"
#include "runtime/stubCodeGenerator.hpp"
#include "utilities/macros.hpp"
#ifdef COMPILER1
--- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -3123,6 +3123,16 @@
}
}
+void MacroAssembler::push_zmm(XMMRegister reg) {
+ lea(rsp, Address(rsp, -64)); // Use lea to not affect flags
+ evmovdqul(Address(rsp, 0), reg, Assembler::AVX_512bit);
+}
+
+void MacroAssembler::pop_zmm(XMMRegister reg) {
+ evmovdqul(reg, Address(rsp, 0), Assembler::AVX_512bit);
+ lea(rsp, Address(rsp, 64)); // Use lea to not affect flags
+}
+
void MacroAssembler::fremr(Register tmp) {
save_rax(tmp);
{ Label L;
@@ -3848,33 +3858,25 @@
} else if ((dst_enc < 16) && (src_enc < 16)) {
Assembler::pcmpeqb(dst, src);
} else if (src_enc < 16) {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
+ push_zmm(xmm0);
evmovdqul(xmm0, dst, Assembler::AVX_512bit);
Assembler::pcmpeqb(xmm0, src);
movdqu(dst, xmm0);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm0);
} else if (dst_enc < 16) {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
+ push_zmm(xmm0);
evmovdqul(xmm0, src, Assembler::AVX_512bit);
Assembler::pcmpeqb(dst, xmm0);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
- } else {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm1, Assembler::AVX_512bit);
+ pop_zmm(xmm0);
+ } else {
+ push_zmm(xmm0);
+ push_zmm(xmm1);
movdqu(xmm0, src);
movdqu(xmm1, dst);
Assembler::pcmpeqb(xmm1, xmm0);
movdqu(dst, xmm1);
- evmovdqul(xmm1, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm1);
+ pop_zmm(xmm0);
}
}
@@ -3886,33 +3888,25 @@
} else if ((dst_enc < 16) && (src_enc < 16)) {
Assembler::pcmpeqw(dst, src);
} else if (src_enc < 16) {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
+ push_zmm(xmm0);
evmovdqul(xmm0, dst, Assembler::AVX_512bit);
Assembler::pcmpeqw(xmm0, src);
movdqu(dst, xmm0);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm0);
} else if (dst_enc < 16) {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
+ push_zmm(xmm0);
evmovdqul(xmm0, src, Assembler::AVX_512bit);
Assembler::pcmpeqw(dst, xmm0);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
- } else {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm1, Assembler::AVX_512bit);
+ pop_zmm(xmm0);
+ } else {
+ push_zmm(xmm0);
+ push_zmm(xmm1);
movdqu(xmm0, src);
movdqu(xmm1, dst);
Assembler::pcmpeqw(xmm1, xmm0);
movdqu(dst, xmm1);
- evmovdqul(xmm1, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm1);
+ pop_zmm(xmm0);
}
}
@@ -3921,13 +3915,11 @@
if (dst_enc < 16) {
Assembler::pcmpestri(dst, src, imm8);
} else {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
+ push_zmm(xmm0);
evmovdqul(xmm0, dst, Assembler::AVX_512bit);
Assembler::pcmpestri(xmm0, src, imm8);
movdqu(dst, xmm0);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm0);
}
}
@@ -3937,33 +3929,25 @@
if ((dst_enc < 16) && (src_enc < 16)) {
Assembler::pcmpestri(dst, src, imm8);
} else if (src_enc < 16) {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
+ push_zmm(xmm0);
evmovdqul(xmm0, dst, Assembler::AVX_512bit);
Assembler::pcmpestri(xmm0, src, imm8);
movdqu(dst, xmm0);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm0);
} else if (dst_enc < 16) {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
+ push_zmm(xmm0);
evmovdqul(xmm0, src, Assembler::AVX_512bit);
Assembler::pcmpestri(dst, xmm0, imm8);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
- } else {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm1, Assembler::AVX_512bit);
+ pop_zmm(xmm0);
+ } else {
+ push_zmm(xmm0);
+ push_zmm(xmm1);
movdqu(xmm0, src);
movdqu(xmm1, dst);
Assembler::pcmpestri(xmm1, xmm0, imm8);
movdqu(dst, xmm1);
- evmovdqul(xmm1, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm1);
+ pop_zmm(xmm0);
}
}
@@ -3975,33 +3959,25 @@
} else if ((dst_enc < 16) && (src_enc < 16)) {
Assembler::pmovzxbw(dst, src);
} else if (src_enc < 16) {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
+ push_zmm(xmm0);
evmovdqul(xmm0, dst, Assembler::AVX_512bit);
Assembler::pmovzxbw(xmm0, src);
movdqu(dst, xmm0);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm0);
} else if (dst_enc < 16) {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
+ push_zmm(xmm0);
evmovdqul(xmm0, src, Assembler::AVX_512bit);
Assembler::pmovzxbw(dst, xmm0);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
- } else {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm1, Assembler::AVX_512bit);
+ pop_zmm(xmm0);
+ } else {
+ push_zmm(xmm0);
+ push_zmm(xmm1);
movdqu(xmm0, src);
movdqu(xmm1, dst);
Assembler::pmovzxbw(xmm1, xmm0);
movdqu(dst, xmm1);
- evmovdqul(xmm1, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm1);
+ pop_zmm(xmm0);
}
}
@@ -4012,13 +3988,11 @@
} else if (dst_enc < 16) {
Assembler::pmovzxbw(dst, src);
} else {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
+ push_zmm(xmm0);
evmovdqul(xmm0, dst, Assembler::AVX_512bit);
Assembler::pmovzxbw(xmm0, src);
movdqu(dst, xmm0);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm0);
}
}
@@ -4027,12 +4001,10 @@
if (src_enc < 16) {
Assembler::pmovmskb(dst, src);
} else {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
+ push_zmm(xmm0);
evmovdqul(xmm0, src, Assembler::AVX_512bit);
Assembler::pmovmskb(dst, xmm0);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm0);
}
}
@@ -4042,31 +4014,23 @@
if ((dst_enc < 16) && (src_enc < 16)) {
Assembler::ptest(dst, src);
} else if (src_enc < 16) {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
+ push_zmm(xmm0);
evmovdqul(xmm0, dst, Assembler::AVX_512bit);
Assembler::ptest(xmm0, src);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm0);
} else if (dst_enc < 16) {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
+ push_zmm(xmm0);
evmovdqul(xmm0, src, Assembler::AVX_512bit);
Assembler::ptest(dst, xmm0);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
- } else {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm1, Assembler::AVX_512bit);
+ pop_zmm(xmm0);
+ } else {
+ push_zmm(xmm0);
+ push_zmm(xmm1);
movdqu(xmm0, src);
movdqu(xmm1, dst);
Assembler::ptest(xmm1, xmm0);
- evmovdqul(xmm1, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm1);
+ pop_zmm(xmm0);
}
}
@@ -4221,13 +4185,11 @@
evmovdqul(dst, xmm0, Assembler::AVX_512bit);
evmovdqul(xmm0, src, Assembler::AVX_512bit);
} else {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
+ push_zmm(xmm0);
evmovdqul(xmm0, nds, Assembler::AVX_512bit);
vandps(xmm0, xmm0, negate_field, vector_len);
evmovdqul(dst, xmm0, Assembler::AVX_512bit);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm0);
}
}
}
@@ -4258,13 +4220,11 @@
evmovdqul(dst, xmm0, Assembler::AVX_512bit);
evmovdqul(xmm0, src, Assembler::AVX_512bit);
} else {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
+ push_zmm(xmm0);
evmovdqul(xmm0, nds, Assembler::AVX_512bit);
vandpd(xmm0, xmm0, negate_field, vector_len);
evmovdqul(dst, xmm0, Assembler::AVX_512bit);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm0);
}
}
}
@@ -4294,16 +4254,14 @@
evmovdqul(xmm0, nds, Assembler::AVX_512bit);
} else {
// worse case scenario, all regs are in the upper bank
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm1, Assembler::AVX_512bit);
+ push_zmm(xmm1);
evmovdqul(nds, xmm0, Assembler::AVX_512bit);
evmovdqul(xmm1, src, Assembler::AVX_512bit);
evmovdqul(xmm0, dst, Assembler::AVX_512bit);
Assembler::vpaddb(xmm0, xmm0, xmm1, vector_len);
evmovdqul(dst, xmm0, Assembler::AVX_512bit);
evmovdqul(xmm0, nds, Assembler::AVX_512bit);
- evmovdqul(xmm1, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm1);
}
}
@@ -4353,16 +4311,14 @@
evmovdqul(xmm0, nds, Assembler::AVX_512bit);
} else {
// worse case scenario, all regs are in the upper bank
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm1, Assembler::AVX_512bit);
+ push_zmm(xmm1);
evmovdqul(nds, xmm0, Assembler::AVX_512bit);
evmovdqul(xmm1, src, Assembler::AVX_512bit);
evmovdqul(xmm0, dst, Assembler::AVX_512bit);
Assembler::vpaddw(xmm0, xmm0, xmm1, vector_len);
evmovdqul(dst, xmm0, Assembler::AVX_512bit);
evmovdqul(xmm0, nds, Assembler::AVX_512bit);
- evmovdqul(xmm1, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm1);
}
}
@@ -4404,33 +4360,25 @@
} else if ((dst_enc < 16) && (src_enc < 16)) {
Assembler::vpbroadcastw(dst, src);
} else if (src_enc < 16) {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
+ push_zmm(xmm0);
evmovdqul(xmm0, dst, Assembler::AVX_512bit);
Assembler::vpbroadcastw(xmm0, src);
movdqu(dst, xmm0);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm0);
} else if (dst_enc < 16) {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
+ push_zmm(xmm0);
evmovdqul(xmm0, src, Assembler::AVX_512bit);
Assembler::vpbroadcastw(dst, xmm0);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
- } else {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm1, Assembler::AVX_512bit);
+ pop_zmm(xmm0);
+ } else {
+ push_zmm(xmm0);
+ push_zmm(xmm1);
movdqu(xmm0, src);
movdqu(xmm1, dst);
Assembler::vpbroadcastw(xmm1, xmm0);
movdqu(dst, xmm1);
- evmovdqul(xmm1, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm1);
+ pop_zmm(xmm0);
}
}
@@ -4442,33 +4390,25 @@
if ((dst_enc < 16) && (src_enc < 16)) {
Assembler::vpcmpeqb(dst, nds, src, vector_len);
} else if (src_enc < 16) {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
+ push_zmm(xmm0);
evmovdqul(xmm0, dst, Assembler::AVX_512bit);
Assembler::vpcmpeqb(xmm0, xmm0, src, vector_len);
movdqu(dst, xmm0);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm0);
} else if (dst_enc < 16) {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
+ push_zmm(xmm0);
evmovdqul(xmm0, src, Assembler::AVX_512bit);
Assembler::vpcmpeqb(dst, dst, xmm0, vector_len);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
- } else {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm1, Assembler::AVX_512bit);
+ pop_zmm(xmm0);
+ } else {
+ push_zmm(xmm0);
+ push_zmm(xmm1);
movdqu(xmm0, src);
movdqu(xmm1, dst);
Assembler::vpcmpeqb(xmm1, xmm1, xmm0, vector_len);
movdqu(dst, xmm1);
- evmovdqul(xmm1, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm1);
+ pop_zmm(xmm0);
}
}
@@ -4480,33 +4420,25 @@
if ((dst_enc < 16) && (src_enc < 16)) {
Assembler::vpcmpeqw(dst, nds, src, vector_len);
} else if (src_enc < 16) {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
+ push_zmm(xmm0);
evmovdqul(xmm0, dst, Assembler::AVX_512bit);
Assembler::vpcmpeqw(xmm0, xmm0, src, vector_len);
movdqu(dst, xmm0);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm0);
} else if (dst_enc < 16) {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
+ push_zmm(xmm0);
evmovdqul(xmm0, src, Assembler::AVX_512bit);
Assembler::vpcmpeqw(dst, dst, xmm0, vector_len);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
- } else {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm1, Assembler::AVX_512bit);
+ pop_zmm(xmm0);
+ } else {
+ push_zmm(xmm0);
+ push_zmm(xmm1);
movdqu(xmm0, src);
movdqu(xmm1, dst);
Assembler::vpcmpeqw(xmm1, xmm1, xmm0, vector_len);
movdqu(dst, xmm1);
- evmovdqul(xmm1, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm1);
+ pop_zmm(xmm0);
}
}
@@ -4517,13 +4449,11 @@
} else if (dst_enc < 16) {
Assembler::vpmovzxbw(dst, src, vector_len);
} else {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
+ push_zmm(xmm0);
evmovdqul(xmm0, dst, Assembler::AVX_512bit);
Assembler::vpmovzxbw(xmm0, src, vector_len);
movdqu(dst, xmm0);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm0);
}
}
@@ -4532,12 +4462,10 @@
if (src_enc < 16) {
Assembler::vpmovmskb(dst, src);
} else {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
+ push_zmm(xmm0);
evmovdqul(xmm0, src, Assembler::AVX_512bit);
Assembler::vpmovmskb(dst, xmm0);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm0);
}
}
@@ -4566,16 +4494,14 @@
evmovdqul(xmm0, nds, Assembler::AVX_512bit);
} else {
// worse case scenario, all regs are in the upper bank
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm1, Assembler::AVX_512bit);
+ push_zmm(xmm1);
evmovdqul(nds, xmm0, Assembler::AVX_512bit);
evmovdqul(xmm1, src, Assembler::AVX_512bit);
evmovdqul(xmm0, dst, Assembler::AVX_512bit);
Assembler::vpmullw(xmm0, xmm0, xmm1, vector_len);
evmovdqul(dst, xmm0, Assembler::AVX_512bit);
evmovdqul(xmm0, nds, Assembler::AVX_512bit);
- evmovdqul(xmm1, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm1);
}
}
@@ -4625,16 +4551,14 @@
evmovdqul(xmm0, nds, Assembler::AVX_512bit);
} else {
// worse case scenario, all regs are in the upper bank
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm1, Assembler::AVX_512bit);
+ push_zmm(xmm1);
evmovdqul(nds, xmm0, Assembler::AVX_512bit);
evmovdqul(xmm1, src, Assembler::AVX_512bit);
evmovdqul(xmm0, dst, Assembler::AVX_512bit);
Assembler::vpsubb(xmm0, xmm0, xmm1, vector_len);
evmovdqul(dst, xmm0, Assembler::AVX_512bit);
evmovdqul(xmm0, nds, Assembler::AVX_512bit);
- evmovdqul(xmm1, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm1);
}
}
@@ -4684,16 +4608,14 @@
evmovdqul(xmm0, nds, Assembler::AVX_512bit);
} else {
// worse case scenario, all regs are in the upper bank
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm1, Assembler::AVX_512bit);
+ push_zmm(xmm1);
evmovdqul(nds, xmm0, Assembler::AVX_512bit);
evmovdqul(xmm1, src, Assembler::AVX_512bit);
evmovdqul(xmm0, dst, Assembler::AVX_512bit);
Assembler::vpsubw(xmm0, xmm0, xmm1, vector_len);
evmovdqul(dst, xmm0, Assembler::AVX_512bit);
evmovdqul(xmm0, nds, Assembler::AVX_512bit);
- evmovdqul(xmm1, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm1);
}
}
@@ -4751,8 +4673,7 @@
evmovdqul(dst, nds, Assembler::AVX_512bit);
} else {
// worse case scenario, all regs are in the upper bank
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm1, Assembler::AVX_512bit);
+ push_zmm(xmm1);
evmovdqul(nds, xmm0, Assembler::AVX_512bit);
evmovdqul(xmm1, shift, Assembler::AVX_512bit);
evmovdqul(xmm0, dst, Assembler::AVX_512bit);
@@ -4760,8 +4681,7 @@
evmovdqul(xmm1, dst, Assembler::AVX_512bit);
evmovdqul(dst, xmm0, Assembler::AVX_512bit);
evmovdqul(xmm0, nds, Assembler::AVX_512bit);
- evmovdqul(xmm1, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm1);
}
}
@@ -4819,8 +4739,7 @@
evmovdqul(dst, nds, Assembler::AVX_512bit);
} else {
// worse case scenario, all regs are in the upper bank
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm1, Assembler::AVX_512bit);
+ push_zmm(xmm1);
evmovdqul(nds, xmm0, Assembler::AVX_512bit);
evmovdqul(xmm1, shift, Assembler::AVX_512bit);
evmovdqul(xmm0, dst, Assembler::AVX_512bit);
@@ -4828,8 +4747,7 @@
evmovdqul(xmm1, dst, Assembler::AVX_512bit);
evmovdqul(dst, xmm0, Assembler::AVX_512bit);
evmovdqul(xmm0, nds, Assembler::AVX_512bit);
- evmovdqul(xmm1, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm1);
}
}
@@ -4887,8 +4805,7 @@
evmovdqul(dst, nds, Assembler::AVX_512bit);
} else {
// worse case scenario, all regs are in the upper bank
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm1, Assembler::AVX_512bit);
+ push_zmm(xmm1);
evmovdqul(nds, xmm0, Assembler::AVX_512bit);
evmovdqul(xmm1, shift, Assembler::AVX_512bit);
evmovdqul(xmm0, dst, Assembler::AVX_512bit);
@@ -4896,8 +4813,7 @@
evmovdqul(xmm1, dst, Assembler::AVX_512bit);
evmovdqul(dst, xmm0, Assembler::AVX_512bit);
evmovdqul(xmm0, nds, Assembler::AVX_512bit);
- evmovdqul(xmm1, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm1);
}
}
@@ -4928,31 +4844,23 @@
if ((dst_enc < 16) && (src_enc < 16)) {
Assembler::vptest(dst, src);
} else if (src_enc < 16) {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
+ push_zmm(xmm0);
evmovdqul(xmm0, dst, Assembler::AVX_512bit);
Assembler::vptest(xmm0, src);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm0);
} else if (dst_enc < 16) {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
+ push_zmm(xmm0);
evmovdqul(xmm0, src, Assembler::AVX_512bit);
Assembler::vptest(dst, xmm0);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
- } else {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm1, Assembler::AVX_512bit);
+ pop_zmm(xmm0);
+ } else {
+ push_zmm(xmm0);
+ push_zmm(xmm1);
movdqu(xmm0, src);
movdqu(xmm1, dst);
Assembler::vptest(xmm1, xmm0);
- evmovdqul(xmm1, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm1);
+ pop_zmm(xmm0);
}
}
@@ -4966,45 +4874,35 @@
if (dst_enc < 16) {
Assembler::punpcklbw(dst, src);
} else {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
+ push_zmm(xmm0);
evmovdqul(xmm0, dst, Assembler::AVX_512bit);
Assembler::punpcklbw(xmm0, xmm0);
evmovdqul(dst, xmm0, Assembler::AVX_512bit);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm0);
}
} else {
if ((src_enc < 16) && (dst_enc < 16)) {
Assembler::punpcklbw(dst, src);
} else if (src_enc < 16) {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
+ push_zmm(xmm0);
evmovdqul(xmm0, dst, Assembler::AVX_512bit);
Assembler::punpcklbw(xmm0, src);
evmovdqul(dst, xmm0, Assembler::AVX_512bit);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm0);
} else if (dst_enc < 16) {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
+ push_zmm(xmm0);
evmovdqul(xmm0, src, Assembler::AVX_512bit);
Assembler::punpcklbw(dst, xmm0);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm0);
} else {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm1, Assembler::AVX_512bit);
+ push_zmm(xmm0);
+ push_zmm(xmm1);
evmovdqul(xmm0, dst, Assembler::AVX_512bit);
evmovdqul(xmm1, src, Assembler::AVX_512bit);
Assembler::punpcklbw(xmm0, xmm1);
evmovdqul(dst, xmm0, Assembler::AVX_512bit);
- evmovdqul(xmm1, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm1);
+ pop_zmm(xmm0);
}
}
} else {
@@ -5020,12 +4918,10 @@
if (dst_enc < 16) {
Assembler::pshufd(dst, src, mode);
} else {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
+ push_zmm(xmm0);
Assembler::pshufd(xmm0, src, mode);
evmovdqul(dst, xmm0, Assembler::AVX_512bit);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm0);
}
}
}
@@ -5040,45 +4936,35 @@
if (dst_enc < 16) {
Assembler::pshuflw(dst, src, mode);
} else {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
+ push_zmm(xmm0);
evmovdqul(xmm0, dst, Assembler::AVX_512bit);
Assembler::pshuflw(xmm0, xmm0, mode);
evmovdqul(dst, xmm0, Assembler::AVX_512bit);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm0);
}
} else {
if ((src_enc < 16) && (dst_enc < 16)) {
Assembler::pshuflw(dst, src, mode);
} else if (src_enc < 16) {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
+ push_zmm(xmm0);
evmovdqul(xmm0, dst, Assembler::AVX_512bit);
Assembler::pshuflw(xmm0, src, mode);
evmovdqul(dst, xmm0, Assembler::AVX_512bit);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm0);
} else if (dst_enc < 16) {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
+ push_zmm(xmm0);
evmovdqul(xmm0, src, Assembler::AVX_512bit);
Assembler::pshuflw(dst, xmm0, mode);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm0);
} else {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm1, Assembler::AVX_512bit);
+ push_zmm(xmm0);
+ push_zmm(xmm1);
evmovdqul(xmm0, dst, Assembler::AVX_512bit);
evmovdqul(xmm1, src, Assembler::AVX_512bit);
Assembler::pshuflw(xmm0, xmm1, mode);
evmovdqul(dst, xmm0, Assembler::AVX_512bit);
- evmovdqul(xmm1, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm1);
+ pop_zmm(xmm0);
}
}
} else {
@@ -5166,13 +5052,11 @@
if (VM_Version::supports_avx512novl() &&
(nds_upper_bank || dst_upper_bank)) {
if (dst_upper_bank) {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
+ push_zmm(xmm0);
movflt(xmm0, nds);
vxorps(xmm0, xmm0, src, Assembler::AVX_128bit);
movflt(dst, xmm0);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm0);
} else {
movflt(dst, nds);
vxorps(dst, dst, src, Assembler::AVX_128bit);
@@ -5190,13 +5074,11 @@
if (VM_Version::supports_avx512novl() &&
(nds_upper_bank || dst_upper_bank)) {
if (dst_upper_bank) {
- subptr(rsp, 64);
- evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
+ push_zmm(xmm0);
movdbl(xmm0, nds);
vxorpd(xmm0, xmm0, src, Assembler::AVX_128bit);
movdbl(dst, xmm0);
- evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
- addptr(rsp, 64);
+ pop_zmm(xmm0);
} else {
movdbl(dst, nds);
vxorpd(dst, dst, src, Assembler::AVX_128bit);
@@ -10567,7 +10449,7 @@
XMMRegister tmp1Reg, XMMRegister tmp2Reg,
XMMRegister tmp3Reg, XMMRegister tmp4Reg,
Register tmp5, Register result) {
- Label copy_chars_loop, return_length, return_zero, done, below_threshold;
+ Label copy_chars_loop, return_length, return_zero, done;
// rsi: src
// rdi: dst
@@ -10590,13 +10472,12 @@
set_vector_masking(); // opening of the stub context for programming mask registers
- Label copy_32_loop, copy_loop_tail, restore_k1_return_zero;
-
- // alignement
- Label post_alignement;
-
- // if length of the string is less than 16, handle it in an old fashioned
- // way
+ Label copy_32_loop, copy_loop_tail, restore_k1_return_zero, below_threshold;
+
+ // alignment
+ Label post_alignment;
+
+ // if length of the string is less than 16, handle it in an old fashioned way
testl(len, -32);
jcc(Assembler::zero, below_threshold);
@@ -10609,7 +10490,7 @@
kmovql(k3, k1);
testl(len, -64);
- jcc(Assembler::zero, post_alignement);
+ jcc(Assembler::zero, post_alignment);
movl(tmp5, dst);
andl(tmp5, (32 - 1));
@@ -10618,7 +10499,7 @@
// bail out when there is nothing to be done
testl(tmp5, 0xFFFFFFFF);
- jcc(Assembler::zero, post_alignement);
+ jcc(Assembler::zero, post_alignment);
// ~(~0 << len), where len is the # of remaining elements to process
movl(result, 0xFFFFFFFF);
@@ -10638,8 +10519,8 @@
addptr(dst, tmp5);
subl(len, tmp5);
- bind(post_alignement);
- // end of alignement
+ bind(post_alignment);
+ // end of alignment
movl(tmp5, len);
andl(tmp5, (32 - 1)); // tail count (in chars)
@@ -10694,12 +10575,13 @@
jmp(return_zero);
clear_vector_masking(); // closing of the stub context for programming mask registers
- }
+
+ bind(below_threshold);
+ }
+
if (UseSSE42Intrinsics) {
Label copy_32_loop, copy_16, copy_tail;
- bind(below_threshold);
-
movl(result, len);
movl(tmp5, 0xff00ff00); // create mask to test for Unicode chars in vectors
@@ -10812,8 +10694,7 @@
Label copy_32_loop, copy_tail;
Register tmp3_aliased = len;
- // if length of the string is less than 16, handle it in an old fashioned
- // way
+ // if length of the string is less than 16, handle it in an old fashioned way
testl(len, -16);
jcc(Assembler::zero, below_threshold);
@@ -10927,7 +10808,10 @@
addptr(dst, 8);
bind(copy_bytes);
- }
+ } else {
+ bind(below_threshold);
+ }
+
testl(len, len);
jccb(Assembler::zero, done);
lea(src, Address(src, len, Address::times_1));
--- a/src/hotspot/cpu/x86/macroAssembler_x86.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/cpu/x86/macroAssembler_x86.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -482,6 +482,10 @@
// from register xmm0. Otherwise, the value is stored from the FPU stack.
void store_double(Address dst);
+ // Save/restore ZMM (512bit) register on stack.
+ void push_zmm(XMMRegister reg);
+ void pop_zmm(XMMRegister reg);
+
// pushes double TOS element of FPU stack on CPU stack; pops from FPU stack
void push_fTOS();
--- a/src/hotspot/cpu/x86/x86_64.ad Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/cpu/x86/x86_64.ad Thu Aug 23 11:09:16 2018 -0400
@@ -317,18 +317,6 @@
// Singleton class for TLS pointer
reg_class ptr_r15_reg(R15, R15_H);
-// The registers which can be used for
-// a thread local safepoint poll
-// * R12 is reserved for heap base
-// * R13 cannot be encoded for addressing without an offset byte
-// * R15 is reserved for the JavaThread
-reg_class ptr_rex_reg(R8, R8_H,
- R9, R9_H,
- R10, R10_H,
- R11, R11_H,
- R14, R14_H);
-
-
// Class for all long registers (excluding RSP)
reg_class long_reg_with_rbp(RAX, RAX_H,
RDX, RDX_H,
@@ -3557,16 +3545,6 @@
interface(REG_INTER);
%}
-operand rex_RegP()
-%{
- constraint(ALLOC_IN_RC(ptr_rex_reg));
- match(RegP);
- match(rRegP);
-
- format %{ %}
- interface(REG_INTER);
-%}
-
operand rRegL()
%{
constraint(ALLOC_IN_RC(long_reg));
@@ -12360,7 +12338,7 @@
ins_pipe(ialu_reg_mem);
%}
-instruct safePoint_poll_tls(rFlagsReg cr, rex_RegP poll)
+instruct safePoint_poll_tls(rFlagsReg cr, rRegP poll)
%{
predicate(SafepointMechanism::uses_thread_local_poll());
match(SafePoint poll);
@@ -12369,13 +12347,12 @@
format %{ "testl rax, [$poll]\t"
"# Safepoint: poll for GC" %}
ins_cost(125);
- size(3); /* setting an explicit size will cause debug builds to assert if size is incorrect */
+ size(4); /* setting an explicit size will cause debug builds to assert if size is incorrect */
ins_encode %{
__ relocate(relocInfo::poll_type);
address pre_pc = __ pc();
__ testl(rax, Address($poll$$Register, 0));
- address post_pc = __ pc();
- guarantee(pre_pc[0] == 0x41 && pre_pc[1] == 0x85, "must emit #rex test-ax [reg]");
+ assert(nativeInstruction_at(pre_pc)->is_safepoint_poll(), "must emit test %%eax [reg]");
%}
ins_pipe(ialu_reg_mem);
%}
--- a/src/hotspot/os/linux/os_linux.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/os/linux/os_linux.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -5793,11 +5793,21 @@
core_pattern[ret] = '\0';
}
+ // Replace the %p in the core pattern with the process id. NOTE: we do this
+ // only if the pattern doesn't start with "|", and we support only one %p in
+ // the pattern.
char *pid_pos = strstr(core_pattern, "%p");
+ const char* tail = (pid_pos != NULL) ? (pid_pos + 2) : ""; // skip over the "%p"
int written;
if (core_pattern[0] == '/') {
- written = jio_snprintf(buffer, bufferSize, "%s", core_pattern);
+ if (pid_pos != NULL) {
+ *pid_pos = '\0';
+ written = jio_snprintf(buffer, bufferSize, "%s%d%s", core_pattern,
+ current_process_id(), tail);
+ } else {
+ written = jio_snprintf(buffer, bufferSize, "%s", core_pattern);
+ }
} else {
char cwd[PATH_MAX];
@@ -5810,6 +5820,10 @@
written = jio_snprintf(buffer, bufferSize,
"\"%s\" (or dumping to %s/core.%d)",
&core_pattern[1], p, current_process_id());
+ } else if (pid_pos != NULL) {
+ *pid_pos = '\0';
+ written = jio_snprintf(buffer, bufferSize, "%s/%s%d%s", p, core_pattern,
+ current_process_id(), tail);
} else {
written = jio_snprintf(buffer, bufferSize, "%s/%s", p, core_pattern);
}
--- a/src/hotspot/share/aot/aotCodeHeap.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/aot/aotCodeHeap.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -1006,7 +1006,7 @@
InstanceKlass* dyno = InstanceKlass::cast(dyno_klass);
- if (!dyno->is_anonymous()) {
+ if (!dyno->is_unsafe_anonymous()) {
if (_klasses_got[dyno_data->_got_index] != dyno) {
// compile-time class different from runtime class, fail and deoptimize
sweep_dependent_methods(holder_data);
--- a/src/hotspot/share/aot/aotCompiledMethod.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/aot/aotCompiledMethod.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -362,7 +362,7 @@
log->print(" aot='%2d'", _heap->dso_id());
}
-void AOTCompiledMethod::log_state_change() const {
+void AOTCompiledMethod::log_state_change(oop cause) const {
if (LogCompilation) {
ResourceMark m;
if (xtty != NULL) {
--- a/src/hotspot/share/aot/aotCompiledMethod.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/aot/aotCompiledMethod.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -193,7 +193,7 @@
virtual int comp_level() const { return CompLevel_aot; }
virtual address verified_entry_point() const { return _code + _meta->verified_entry_offset(); }
virtual void log_identity(xmlStream* stream) const;
- virtual void log_state_change() const;
+ virtual void log_state_change(oop cause = NULL) const;
virtual bool make_entrant() NOT_TIERED({ ShouldNotReachHere(); return false; });
virtual bool make_not_entrant() { return make_not_entrant_helper(not_entrant); }
virtual bool make_not_used() { return make_not_entrant_helper(not_used); }
--- a/src/hotspot/share/aot/aotLoader.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/aot/aotLoader.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -42,7 +42,7 @@
#define FOR_ALL_AOT_LIBRARIES(lib) for (GrowableArrayIterator<AOTLib*> lib = libraries()->begin(); lib != libraries()->end(); ++lib)
void AOTLoader::load_for_klass(InstanceKlass* ik, Thread* thread) {
- if (ik->is_anonymous()) {
+ if (ik->is_unsafe_anonymous()) {
// don't even bother
return;
}
@@ -54,7 +54,7 @@
}
uint64_t AOTLoader::get_saved_fingerprint(InstanceKlass* ik) {
- if (ik->is_anonymous()) {
+ if (ik->is_unsafe_anonymous()) {
// don't even bother
return 0;
}
--- a/src/hotspot/share/c1/c1_Decorators.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/c1/c1_Decorators.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -34,9 +34,5 @@
// Use the C1_MASK_BOOLEAN decorator for boolean accesses where the value
// needs to be masked.
const DecoratorSet C1_MASK_BOOLEAN = DECORATOR_LAST << 2;
-// The C1_WRITE_ACCESS decorator is used to mark writing accesses.
-const DecoratorSet C1_WRITE_ACCESS = DECORATOR_LAST << 3;
-// The C1_READ_ACCESS decorator is used to mark reading accesses.
-const DecoratorSet C1_READ_ACCESS = DECORATOR_LAST << 4;
#endif // SHARE_VM_C1_C1_DECORATORS_HPP
--- a/src/hotspot/share/c1/c1_GraphBuilder.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/c1/c1_GraphBuilder.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -1844,8 +1844,8 @@
// invoke-special-super
if (bc_raw == Bytecodes::_invokespecial && !target->is_object_initializer()) {
ciInstanceKlass* sender_klass =
- calling_klass->is_anonymous() ? calling_klass->host_klass() :
- calling_klass;
+ calling_klass->is_unsafe_anonymous() ? calling_klass->unsafe_anonymous_host() :
+ calling_klass;
if (sender_klass->is_interface()) {
int index = state()->stack_size() - (target->arg_size_no_receiver() + 1);
Value receiver = state()->stack_at(index);
--- a/src/hotspot/share/c1/c1_LIRGenerator.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/c1/c1_LIRGenerator.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -1285,9 +1285,10 @@
// FIXME T_ADDRESS should actually be T_METADATA but it can't because the
// meaning of these two is mixed up (see JDK-8026837).
__ move(new LIR_Address(rcvr.result(), oopDesc::klass_offset_in_bytes(), T_ADDRESS), temp, info);
- __ move_wide(new LIR_Address(temp, in_bytes(Klass::java_mirror_offset()), T_ADDRESS), result);
+ __ move_wide(new LIR_Address(temp, in_bytes(Klass::java_mirror_offset()), T_ADDRESS), temp);
// mirror = ((OopHandle)mirror)->resolve();
- __ move_wide(new LIR_Address(result, T_OBJECT), result);
+ access_load(IN_NATIVE, T_OBJECT,
+ LIR_OprFact::address(new LIR_Address(temp, T_OBJECT)), result);
}
// java.lang.Class::isPrimitive()
@@ -1614,7 +1615,7 @@
void LIRGenerator::access_load_at(DecoratorSet decorators, BasicType type,
LIRItem& base, LIR_Opr offset, LIR_Opr result,
CodeEmitInfo* patch_info, CodeEmitInfo* load_emit_info) {
- decorators |= C1_READ_ACCESS;
+ decorators |= ACCESS_READ;
LIRAccess access(this, decorators, base, offset, type, patch_info, load_emit_info);
if (access.is_raw()) {
_barrier_set->BarrierSetC1::load_at(access, result);
@@ -1623,10 +1624,22 @@
}
}
+void LIRGenerator::access_load(DecoratorSet decorators, BasicType type,
+ LIR_Opr addr, LIR_Opr result) {
+ decorators |= ACCESS_READ;
+ LIRAccess access(this, decorators, LIR_OprFact::illegalOpr, LIR_OprFact::illegalOpr, type);
+ access.set_resolved_addr(addr);
+ if (access.is_raw()) {
+ _barrier_set->BarrierSetC1::load(access, result);
+ } else {
+ _barrier_set->load(access, result);
+ }
+}
+
void LIRGenerator::access_store_at(DecoratorSet decorators, BasicType type,
LIRItem& base, LIR_Opr offset, LIR_Opr value,
CodeEmitInfo* patch_info, CodeEmitInfo* store_emit_info) {
- decorators |= C1_WRITE_ACCESS;
+ decorators |= ACCESS_WRITE;
LIRAccess access(this, decorators, base, offset, type, patch_info, store_emit_info);
if (access.is_raw()) {
_barrier_set->BarrierSetC1::store_at(access, value);
@@ -1637,9 +1650,9 @@
LIR_Opr LIRGenerator::access_atomic_cmpxchg_at(DecoratorSet decorators, BasicType type,
LIRItem& base, LIRItem& offset, LIRItem& cmp_value, LIRItem& new_value) {
+ decorators |= ACCESS_READ;
+ decorators |= ACCESS_WRITE;
// Atomic operations are SEQ_CST by default
- decorators |= C1_READ_ACCESS;
- decorators |= C1_WRITE_ACCESS;
decorators |= ((decorators & MO_DECORATOR_MASK) != 0) ? MO_SEQ_CST : 0;
LIRAccess access(this, decorators, base, offset, type);
if (access.is_raw()) {
@@ -1651,9 +1664,9 @@
LIR_Opr LIRGenerator::access_atomic_xchg_at(DecoratorSet decorators, BasicType type,
LIRItem& base, LIRItem& offset, LIRItem& value) {
+ decorators |= ACCESS_READ;
+ decorators |= ACCESS_WRITE;
// Atomic operations are SEQ_CST by default
- decorators |= C1_READ_ACCESS;
- decorators |= C1_WRITE_ACCESS;
decorators |= ((decorators & MO_DECORATOR_MASK) != 0) ? MO_SEQ_CST : 0;
LIRAccess access(this, decorators, base, offset, type);
if (access.is_raw()) {
@@ -1665,9 +1678,9 @@
LIR_Opr LIRGenerator::access_atomic_add_at(DecoratorSet decorators, BasicType type,
LIRItem& base, LIRItem& offset, LIRItem& value) {
+ decorators |= ACCESS_READ;
+ decorators |= ACCESS_WRITE;
// Atomic operations are SEQ_CST by default
- decorators |= C1_READ_ACCESS;
- decorators |= C1_WRITE_ACCESS;
decorators |= ((decorators & MO_DECORATOR_MASK) != 0) ? MO_SEQ_CST : 0;
LIRAccess access(this, decorators, base, offset, type);
if (access.is_raw()) {
@@ -1677,6 +1690,15 @@
}
}
+LIR_Opr LIRGenerator::access_resolve(DecoratorSet decorators, LIR_Opr obj) {
+ // Use stronger ACCESS_WRITE|ACCESS_READ by default.
+ if ((decorators & (ACCESS_READ | ACCESS_WRITE)) == 0) {
+ decorators |= ACCESS_READ | ACCESS_WRITE;
+ }
+
+ return _barrier_set->resolve(this, decorators, obj);
+}
+
void LIRGenerator::do_LoadField(LoadField* x) {
bool needs_patching = x->needs_patching();
bool is_volatile = x->field()->is_volatile();
@@ -1754,11 +1776,12 @@
if (GenerateRangeChecks) {
CodeEmitInfo* info = state_for(x);
CodeStub* stub = new RangeCheckStub(info, index.result());
+ LIR_Opr buf_obj = access_resolve(IS_NOT_NULL | ACCESS_READ, buf.result());
if (index.result()->is_constant()) {
- cmp_mem_int(lir_cond_belowEqual, buf.result(), java_nio_Buffer::limit_offset(), index.result()->as_jint(), info);
+ cmp_mem_int(lir_cond_belowEqual, buf_obj, java_nio_Buffer::limit_offset(), index.result()->as_jint(), info);
__ branch(lir_cond_belowEqual, T_INT, stub);
} else {
- cmp_reg_mem(lir_cond_aboveEqual, index.result(), buf.result(),
+ cmp_reg_mem(lir_cond_aboveEqual, index.result(), buf_obj,
java_nio_Buffer::limit_offset(), T_INT, info);
__ branch(lir_cond_aboveEqual, T_INT, stub);
}
--- a/src/hotspot/share/c1/c1_LIRGenerator.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/c1/c1_LIRGenerator.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -288,6 +288,9 @@
LIRItem& base, LIR_Opr offset, LIR_Opr result,
CodeEmitInfo* patch_info = NULL, CodeEmitInfo* load_emit_info = NULL);
+ void access_load(DecoratorSet decorators, BasicType type,
+ LIR_Opr addr, LIR_Opr result);
+
LIR_Opr access_atomic_cmpxchg_at(DecoratorSet decorators, BasicType type,
LIRItem& base, LIRItem& offset, LIRItem& cmp_value, LIRItem& new_value);
@@ -297,6 +300,8 @@
LIR_Opr access_atomic_add_at(DecoratorSet decorators, BasicType type,
LIRItem& base, LIRItem& offset, LIRItem& value);
+ LIR_Opr access_resolve(DecoratorSet decorators, LIR_Opr obj);
+
// These need to guarantee JMM volatile semantics are preserved on each platform
// and requires one implementation per architecture.
LIR_Opr atomic_cmpxchg(BasicType type, LIR_Opr addr, LIRItem& cmp_value, LIRItem& new_value);
--- a/src/hotspot/share/c1/c1_Runtime1.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/c1/c1_Runtime1.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -55,8 +55,9 @@
#include "runtime/atomic.hpp"
#include "runtime/biasedLocking.hpp"
#include "runtime/compilationPolicy.hpp"
+#include "runtime/fieldDescriptor.inline.hpp"
+#include "runtime/frame.inline.hpp"
#include "runtime/interfaceSupport.inline.hpp"
-#include "runtime/frame.inline.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/threadCritical.hpp"
--- a/src/hotspot/share/ci/ciField.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/ci/ciField.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -31,7 +31,7 @@
#include "interpreter/linkResolver.hpp"
#include "memory/universe.hpp"
#include "oops/oop.inline.hpp"
-#include "runtime/fieldDescriptor.hpp"
+#include "runtime/fieldDescriptor.inline.hpp"
#include "runtime/handles.inline.hpp"
// ciField
@@ -222,9 +222,9 @@
// Even if general trusting is disabled, trust system-built closures in these packages.
if (holder->is_in_package("java/lang/invoke") || holder->is_in_package("sun/invoke"))
return true;
- // Trust VM anonymous classes. They are private API (sun.misc.Unsafe) and can't be serialized,
- // so there is no hacking of finals going on with them.
- if (holder->is_anonymous())
+ // Trust VM unsafe anonymous classes. They are private API (jdk.internal.misc.Unsafe)
+ // and can't be serialized, so there is no hacking of finals going on with them.
+ if (holder->is_unsafe_anonymous())
return true;
// Trust final fields in all boxed classes
if (holder->is_box_klass())
--- a/src/hotspot/share/ci/ciInstanceKlass.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/ci/ciInstanceKlass.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -33,7 +33,7 @@
#include "memory/resourceArea.hpp"
#include "oops/oop.inline.hpp"
#include "oops/fieldStreams.hpp"
-#include "runtime/fieldDescriptor.hpp"
+#include "runtime/fieldDescriptor.inline.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/jniHandles.inline.hpp"
@@ -62,7 +62,7 @@
_nonstatic_field_size = ik->nonstatic_field_size();
_has_nonstatic_fields = ik->has_nonstatic_fields();
_has_nonstatic_concrete_methods = ik->has_nonstatic_concrete_methods();
- _is_anonymous = ik->is_anonymous();
+ _is_unsafe_anonymous = ik->is_unsafe_anonymous();
_nonstatic_fields = NULL; // initialized lazily by compute_nonstatic_fields:
_has_injected_fields = -1;
_implementor = NULL; // we will fill these lazily
@@ -73,13 +73,13 @@
// InstanceKlass are created for both weak and strong metadata. Ensuring this metadata
// alive covers the cases where there are weak roots without performance cost.
oop holder = ik->holder_phantom();
- if (ik->is_anonymous()) {
+ if (ik->is_unsafe_anonymous()) {
// Though ciInstanceKlass records class loader oop, it's not enough to keep
- // VM anonymous classes alive (loader == NULL). Klass holder should be used instead.
- // It is enough to record a ciObject, since cached elements are never removed
+ // VM unsafe anonymous classes alive (loader == NULL). Klass holder should
+ // be used instead. It is enough to record a ciObject, since cached elements are never removed
// during ciObjectFactory lifetime. ciObjectFactory itself is created for
// every compilation and lives for the whole duration of the compilation.
- assert(holder != NULL, "holder of anonymous class is the mirror which is never null");
+ assert(holder != NULL, "holder of unsafe anonymous class is the mirror which is never null");
(void)CURRENT_ENV->get_object(holder);
}
@@ -122,7 +122,7 @@
_has_nonstatic_fields = false;
_nonstatic_fields = NULL;
_has_injected_fields = -1;
- _is_anonymous = false;
+ _is_unsafe_anonymous = false;
_loader = loader;
_protection_domain = protection_domain;
_is_shared = false;
@@ -596,6 +596,7 @@
// Go into the VM to fetch the implementor.
{
VM_ENTRY_MARK;
+ MutexLocker ml(Compile_lock);
Klass* k = get_instanceKlass()->implementor();
if (k != NULL) {
if (k == get_instanceKlass()) {
@@ -614,12 +615,12 @@
return impl;
}
-ciInstanceKlass* ciInstanceKlass::host_klass() {
+ciInstanceKlass* ciInstanceKlass::unsafe_anonymous_host() {
assert(is_loaded(), "must be loaded");
- if (is_anonymous()) {
+ if (is_unsafe_anonymous()) {
VM_ENTRY_MARK
- Klass* host_klass = get_instanceKlass()->host_klass();
- return CURRENT_ENV->get_instance_klass(host_klass);
+ Klass* unsafe_anonymous_host = get_instanceKlass()->unsafe_anonymous_host();
+ return CURRENT_ENV->get_instance_klass(unsafe_anonymous_host);
}
return NULL;
}
--- a/src/hotspot/share/ci/ciInstanceKlass.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/ci/ciInstanceKlass.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
* 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 @@
bool _has_subklass;
bool _has_nonstatic_fields;
bool _has_nonstatic_concrete_methods;
- bool _is_anonymous;
+ bool _is_unsafe_anonymous;
ciFlags _flags;
jint _nonstatic_field_size;
@@ -179,8 +179,8 @@
return _has_nonstatic_concrete_methods;
}
- bool is_anonymous() {
- return _is_anonymous;
+ bool is_unsafe_anonymous() {
+ return _is_unsafe_anonymous;
}
ciInstanceKlass* get_canonical_holder(int offset);
@@ -260,7 +260,7 @@
return NULL;
}
- ciInstanceKlass* host_klass();
+ ciInstanceKlass* unsafe_anonymous_host();
bool can_be_instantiated() {
assert(is_loaded(), "must be loaded");
--- a/src/hotspot/share/ci/ciReplay.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/ci/ciReplay.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -35,6 +35,7 @@
#include "memory/resourceArea.hpp"
#include "oops/method.inline.hpp"
#include "oops/oop.inline.hpp"
+#include "runtime/fieldDescriptor.inline.hpp"
#include "utilities/copy.hpp"
#include "utilities/macros.hpp"
--- a/src/hotspot/share/classfile/classFileParser.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/classfile/classFileParser.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -2091,7 +2091,7 @@
// Privileged code can use all annotations. Other code silently drops some.
const bool privileged = loader_data->is_the_null_class_loader_data() ||
loader_data->is_platform_class_loader_data() ||
- loader_data->is_anonymous();
+ loader_data->is_unsafe_anonymous();
switch (sid) {
case vmSymbols::VM_SYMBOL_ENUM_NAME(reflect_CallerSensitive_signature): {
if (_location != _in_method) break; // only allow for methods
@@ -5591,7 +5591,7 @@
ik->set_this_class_index(_this_class_index);
- if (is_anonymous()) {
+ if (is_unsafe_anonymous()) {
// _this_class_index is a CONSTANT_Class entry that refers to this
// anonymous class itself. If this class needs to refer to its own methods or
// fields, it would use a CONSTANT_MethodRef, etc, which would reference
@@ -5607,9 +5607,9 @@
ik->set_has_nonstatic_concrete_methods(_has_nonstatic_concrete_methods);
ik->set_declares_nonstatic_concrete_methods(_declares_nonstatic_concrete_methods);
- if (_host_klass != NULL) {
- assert (ik->is_anonymous(), "should be the same");
- ik->set_host_klass(_host_klass);
+ if (_unsafe_anonymous_host != NULL) {
+ assert (ik->is_unsafe_anonymous(), "should be the same");
+ ik->set_unsafe_anonymous_host(_unsafe_anonymous_host);
}
// Set PackageEntry for this_klass
@@ -5760,15 +5760,15 @@
debug_only(ik->verify();)
}
-// For an anonymous class that is in the unnamed package, move it to its host class's
+// For an unsafe anonymous class that is in the unnamed package, move it to its host class's
// package by prepending its host class's package name to its class name and setting
// its _class_name field.
-void ClassFileParser::prepend_host_package_name(const InstanceKlass* host_klass, TRAPS) {
+void ClassFileParser::prepend_host_package_name(const InstanceKlass* unsafe_anonymous_host, TRAPS) {
ResourceMark rm(THREAD);
assert(strrchr(_class_name->as_C_string(), '/') == NULL,
- "Anonymous class should not be in a package");
+ "Unsafe anonymous class should not be in a package");
const char* host_pkg_name =
- ClassLoader::package_from_name(host_klass->name()->as_C_string(), NULL);
+ ClassLoader::package_from_name(unsafe_anonymous_host->name()->as_C_string(), NULL);
if (host_pkg_name != NULL) {
size_t host_pkg_len = strlen(host_pkg_name);
@@ -5778,7 +5778,7 @@
// Copy host package name and trailing /.
strncpy(new_anon_name, host_pkg_name, host_pkg_len);
new_anon_name[host_pkg_len] = '/';
- // Append anonymous class name. The anonymous class name can contain odd
+ // Append unsafe anonymous class name. The unsafe anonymous class name can contain odd
// characters. So, do a strncpy instead of using sprintf("%s...").
strncpy(new_anon_name + host_pkg_len + 1, (char *)_class_name->base(), class_name_len);
@@ -5793,19 +5793,19 @@
// nothing. If the anonymous class is in the unnamed package then move it to its
// host's package. If the classes are in different packages then throw an IAE
// exception.
-void ClassFileParser::fix_anonymous_class_name(TRAPS) {
- assert(_host_klass != NULL, "Expected an anonymous class");
+void ClassFileParser::fix_unsafe_anonymous_class_name(TRAPS) {
+ assert(_unsafe_anonymous_host != NULL, "Expected an unsafe anonymous class");
const jbyte* anon_last_slash = UTF8::strrchr(_class_name->base(),
_class_name->utf8_length(), '/');
if (anon_last_slash == NULL) { // Unnamed package
- prepend_host_package_name(_host_klass, CHECK);
+ prepend_host_package_name(_unsafe_anonymous_host, CHECK);
} else {
- if (!_host_klass->is_same_class_package(_host_klass->class_loader(), _class_name)) {
+ if (!_unsafe_anonymous_host->is_same_class_package(_unsafe_anonymous_host->class_loader(), _class_name)) {
ResourceMark rm(THREAD);
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Host class %s and anonymous class %s are in different packages",
- _host_klass->name()->as_C_string(), _class_name->as_C_string()));
+ _unsafe_anonymous_host->name()->as_C_string(), _class_name->as_C_string()));
}
}
}
@@ -5825,14 +5825,14 @@
Symbol* name,
ClassLoaderData* loader_data,
Handle protection_domain,
- const InstanceKlass* host_klass,
+ const InstanceKlass* unsafe_anonymous_host,
GrowableArray<Handle>* cp_patches,
Publicity pub_level,
TRAPS) :
_stream(stream),
_requested_name(name),
_loader_data(loader_data),
- _host_klass(host_klass),
+ _unsafe_anonymous_host(unsafe_anonymous_host),
_cp_patches(cp_patches),
_num_patched_klasses(0),
_max_num_patched_klasses(0),
@@ -6140,8 +6140,8 @@
// if this is an anonymous class fix up its name if it's in the unnamed
// package. Otherwise, throw IAE if it is in a different package than
// its host class.
- if (_host_klass != NULL) {
- fix_anonymous_class_name(CHECK);
+ if (_unsafe_anonymous_host != NULL) {
+ fix_unsafe_anonymous_class_name(CHECK);
}
// Verification prevents us from creating names with dots in them, this
@@ -6166,9 +6166,9 @@
warning("DumpLoadedClassList and CDS are not supported in exploded build");
DumpLoadedClassList = NULL;
} else if (SystemDictionaryShared::is_sharing_possible(_loader_data) &&
- _host_klass == NULL) {
+ _unsafe_anonymous_host == NULL) {
// Only dump the classes that can be stored into CDS archive.
- // Anonymous classes such as generated LambdaForm classes are also not included.
+ // Unsafe anonymous classes such as generated LambdaForm classes are also not included.
oop class_loader = _loader_data->class_loader();
ResourceMark rm(THREAD);
bool skip = false;
--- a/src/hotspot/share/classfile/classFileParser.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/classfile/classFileParser.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -82,7 +82,7 @@
const Symbol* _requested_name;
Symbol* _class_name;
mutable ClassLoaderData* _loader_data;
- const InstanceKlass* _host_klass;
+ const InstanceKlass* _unsafe_anonymous_host;
GrowableArray<Handle>* _cp_patches; // overrides for CP entries
int _num_patched_klasses;
int _max_num_patched_klasses;
@@ -173,8 +173,8 @@
ConstantPool* cp,
TRAPS);
- void prepend_host_package_name(const InstanceKlass* host_klass, TRAPS);
- void fix_anonymous_class_name(TRAPS);
+ void prepend_host_package_name(const InstanceKlass* unsafe_anonymous_host, TRAPS);
+ void fix_unsafe_anonymous_class_name(TRAPS);
void fill_instance_klass(InstanceKlass* ik, bool cf_changed_in_CFLH, TRAPS);
void set_klass(InstanceKlass* instance);
@@ -501,7 +501,7 @@
Symbol* name,
ClassLoaderData* loader_data,
Handle protection_domain,
- const InstanceKlass* host_klass,
+ const InstanceKlass* unsafe_anonymous_host,
GrowableArray<Handle>* cp_patches,
Publicity pub_level,
TRAPS);
@@ -524,10 +524,10 @@
u2 this_class_index() const { return _this_class_index; }
u2 super_class_index() const { return _super_class_index; }
- bool is_anonymous() const { return _host_klass != NULL; }
+ bool is_unsafe_anonymous() const { return _unsafe_anonymous_host != NULL; }
bool is_interface() const { return _access_flags.is_interface(); }
- const InstanceKlass* host_klass() const { return _host_klass; }
+ const InstanceKlass* unsafe_anonymous_host() const { return _unsafe_anonymous_host; }
const GrowableArray<Handle>* cp_patches() const { return _cp_patches; }
ClassLoaderData* loader_data() const { return _loader_data; }
const Symbol* class_name() const { return _class_name; }
--- a/src/hotspot/share/classfile/classLoader.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/classfile/classLoader.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -1400,7 +1400,7 @@
name,
loader_data,
protection_domain,
- NULL, // host_klass
+ NULL, // unsafe_anonymous_host
NULL, // cp_patches
THREAD);
if (HAS_PENDING_EXCEPTION) {
@@ -1443,8 +1443,8 @@
assert(DumpSharedSpaces, "sanity");
assert(stream != NULL, "sanity");
- if (ik->is_anonymous()) {
- // We do not archive anonymous classes.
+ if (ik->is_unsafe_anonymous()) {
+ // We do not archive unsafe anonymous classes.
return;
}
--- a/src/hotspot/share/classfile/classLoaderData.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/classfile/classLoaderData.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -141,16 +141,16 @@
_name_and_id = SymbolTable::new_symbol(cl_instance_name_and_id, CATCH);
}
-ClassLoaderData::ClassLoaderData(Handle h_class_loader, bool is_anonymous) :
+ClassLoaderData::ClassLoaderData(Handle h_class_loader, bool is_unsafe_anonymous) :
_metaspace(NULL),
_metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true,
Monitor::_safepoint_check_never)),
- _unloading(false), _is_anonymous(is_anonymous),
+ _unloading(false), _is_unsafe_anonymous(is_unsafe_anonymous),
_modified_oops(true), _accumulated_modified_oops(false),
- // An anonymous class loader data doesn't have anything to keep
- // it from being unloaded during parsing of the anonymous class.
+ // An unsafe anonymous class loader data doesn't have anything to keep
+ // it from being unloaded during parsing of the unsafe anonymous class.
// The null-class-loader should always be kept alive.
- _keep_alive((is_anonymous || h_class_loader.is_null()) ? 1 : 0),
+ _keep_alive((is_unsafe_anonymous || h_class_loader.is_null()) ? 1 : 0),
_claimed(0),
_handles(),
_klasses(NULL), _packages(NULL), _modules(NULL), _unnamed_module(NULL), _dictionary(NULL),
@@ -164,14 +164,14 @@
_class_loader_klass = h_class_loader->klass();
}
- if (!is_anonymous) {
- // The holder is initialized later for anonymous classes, and before calling anything
+ if (!is_unsafe_anonymous) {
+ // The holder is initialized later for unsafe anonymous classes, and before calling anything
// that call class_loader().
initialize_holder(h_class_loader);
- // A ClassLoaderData created solely for an anonymous class should never have a
+ // A ClassLoaderData created solely for an unsafe anonymous class should never have a
// ModuleEntryTable or PackageEntryTable created for it. The defining package
- // and module for an anonymous class will be found in its host class.
+ // and module for an unsafe anonymous class will be found in its host class.
_packages = new PackageEntryTable(PackageEntryTable::_packagetable_entry_size);
if (h_class_loader.is_null()) {
// Create unnamed module for boot loader
@@ -287,20 +287,20 @@
return (int) Atomic::cmpxchg(1, &_claimed, 0) == 0;
}
-// Anonymous classes have their own ClassLoaderData that is marked to keep alive
+// Unsafe anonymous classes have their own ClassLoaderData that is marked to keep alive
// while the class is being parsed, and if the class appears on the module fixup list.
-// Due to the uniqueness that no other class shares the anonymous class' name or
-// ClassLoaderData, no other non-GC thread has knowledge of the anonymous class while
+// Due to the uniqueness that no other class shares the unsafe anonymous class' name or
+// ClassLoaderData, no other non-GC thread has knowledge of the unsafe anonymous class while
// it is being defined, therefore _keep_alive is not volatile or atomic.
void ClassLoaderData::inc_keep_alive() {
- if (is_anonymous()) {
+ if (is_unsafe_anonymous()) {
assert(_keep_alive >= 0, "Invalid keep alive increment count");
_keep_alive++;
}
}
void ClassLoaderData::dec_keep_alive() {
- if (is_anonymous()) {
+ if (is_unsafe_anonymous()) {
assert(_keep_alive > 0, "Invalid keep alive decrement count");
_keep_alive--;
}
@@ -402,20 +402,20 @@
// Do not need to record dependency if the dependency is to a class whose
// class loader data is never freed. (i.e. the dependency's class loader
// is one of the three builtin class loaders and the dependency is not
- // anonymous.)
+ // unsafe anonymous.)
if (to_cld->is_permanent_class_loader_data()) {
return;
}
oop to;
- if (to_cld->is_anonymous()) {
- // Just return if an anonymous class is attempting to record a dependency
- // to itself. (Note that every anonymous class has its own unique class
+ if (to_cld->is_unsafe_anonymous()) {
+ // Just return if an unsafe anonymous class is attempting to record a dependency
+ // to itself. (Note that every unsafe anonymous class has its own unique class
// loader data.)
if (to_cld == from_cld) {
return;
}
- // Anonymous class dependencies are through the mirror.
+ // Unsafe anonymous class dependencies are through the mirror.
to = k->java_mirror();
} else {
to = to_cld->class_loader();
@@ -640,7 +640,7 @@
const int _default_loader_dictionary_size = 107;
Dictionary* ClassLoaderData::create_dictionary() {
- assert(!is_anonymous(), "anonymous class loader data do not have a dictionary");
+ assert(!is_unsafe_anonymous(), "unsafe anonymous class loader data do not have a dictionary");
int size;
bool resizable = false;
if (_the_null_class_loader_data == NULL) {
@@ -677,7 +677,7 @@
// Unloading support
bool ClassLoaderData::is_alive() const {
- bool alive = keep_alive() // null class loader and incomplete anonymous klasses.
+ bool alive = keep_alive() // null class loader and incomplete unsafe anonymous klasses.
|| (_holder.peek() != NULL); // and not cleaned by the GC weak handle processing.
return alive;
@@ -767,13 +767,13 @@
// Returns true if this class loader data is for the app class loader
// or a user defined system class loader. (Note that the class loader
-// data may be anonymous.)
+// data may be unsafe anonymous.)
bool ClassLoaderData::is_system_class_loader_data() const {
return SystemDictionary::is_system_class_loader(class_loader());
}
// Returns true if this class loader data is for the platform class loader.
-// (Note that the class loader data may be anonymous.)
+// (Note that the class loader data may be unsafe anonymous.)
bool ClassLoaderData::is_platform_class_loader_data() const {
return SystemDictionary::is_platform_class_loader(class_loader());
}
@@ -781,7 +781,7 @@
// Returns true if the class loader for this class loader data is one of
// the 3 builtin (boot application/system or platform) class loaders,
// including a user-defined system class loader. Note that if the class
-// loader data is for an anonymous class then it may get freed by a GC
+// loader data is for an unsafe anonymous class then it may get freed by a GC
// even if its class loader is one of these loaders.
bool ClassLoaderData::is_builtin_class_loader_data() const {
return (is_boot_class_loader_data() ||
@@ -790,10 +790,10 @@
}
// Returns true if this class loader data is a class loader data
-// that is not ever freed by a GC. It must be one of the builtin
-// class loaders and not anonymous.
+// that is not ever freed by a GC. It must be the CLD for one of the builtin
+// class loaders and not the CLD for an unsafe anonymous class.
bool ClassLoaderData::is_permanent_class_loader_data() const {
- return is_builtin_class_loader_data() && !is_anonymous();
+ return is_builtin_class_loader_data() && !is_unsafe_anonymous();
}
ClassLoaderMetaspace* ClassLoaderData::metaspace_non_null() {
@@ -810,8 +810,8 @@
if (this == the_null_class_loader_data()) {
assert (class_loader() == NULL, "Must be");
metaspace = new ClassLoaderMetaspace(_metaspace_lock, Metaspace::BootMetaspaceType);
- } else if (is_anonymous()) {
- metaspace = new ClassLoaderMetaspace(_metaspace_lock, Metaspace::AnonymousMetaspaceType);
+ } else if (is_unsafe_anonymous()) {
+ metaspace = new ClassLoaderMetaspace(_metaspace_lock, Metaspace::UnsafeAnonymousMetaspaceType);
} else if (class_loader()->is_a(SystemDictionary::reflect_DelegatingClassLoader_klass())) {
metaspace = new ClassLoaderMetaspace(_metaspace_lock, Metaspace::ReflectionMetaspaceType);
} else {
@@ -962,8 +962,8 @@
}
}
-// These anonymous class loaders are to contain classes used for JSR292
-ClassLoaderData* ClassLoaderData::anonymous_class_loader_data(Handle loader) {
+// These CLDs are to contain unsafe anonymous classes used for JSR292
+ClassLoaderData* ClassLoaderData::unsafe_anonymous_class_loader_data(Handle loader) {
// Add a new class loader data to the graph.
return ClassLoaderDataGraph::add(loader, true);
}
@@ -1005,8 +1005,8 @@
// loader data: 0xsomeaddr of 'bootstrap'
out->print("loader data: " INTPTR_FORMAT " of %s", p2i(this), loader_name_and_id());
}
- if (is_anonymous()) {
- out->print(" anonymous");
+ if (is_unsafe_anonymous()) {
+ out->print(" unsafe anonymous");
}
}
@@ -1014,7 +1014,7 @@
void ClassLoaderData::print_on(outputStream* out) const {
out->print("ClassLoaderData CLD: " PTR_FORMAT ", loader: " PTR_FORMAT ", loader_klass: %s {",
p2i(this), p2i(_class_loader.ptr_raw()), loader_name_and_id());
- if (is_anonymous()) out->print(" anonymous");
+ if (is_unsafe_anonymous()) out->print(" unsafe anonymous");
if (claimed()) out->print(" claimed");
if (is_unloading()) out->print(" unloading");
out->print(" metaspace: " INTPTR_FORMAT, p2i(metaspace_or_null()));
@@ -1032,8 +1032,8 @@
assert_locked_or_safepoint(_metaspace_lock);
oop cl = class_loader();
- guarantee(this == class_loader_data(cl) || is_anonymous(), "Must be the same");
- guarantee(cl != NULL || this == ClassLoaderData::the_null_class_loader_data() || is_anonymous(), "must be");
+ guarantee(this == class_loader_data(cl) || is_unsafe_anonymous(), "Must be the same");
+ guarantee(cl != NULL || this == ClassLoaderData::the_null_class_loader_data() || is_unsafe_anonymous(), "must be");
// Verify the integrity of the allocated space.
if (metaspace_or_null() != NULL) {
@@ -1069,14 +1069,14 @@
// Add a new class loader data node to the list. Assign the newly created
// ClassLoaderData into the java/lang/ClassLoader object as a hidden field
-ClassLoaderData* ClassLoaderDataGraph::add_to_graph(Handle loader, bool is_anonymous) {
+ClassLoaderData* ClassLoaderDataGraph::add_to_graph(Handle loader, bool is_unsafe_anonymous) {
NoSafepointVerifier no_safepoints; // we mustn't GC until we've installed the
// ClassLoaderData in the graph since the CLD
// contains oops in _handles that must be walked.
- ClassLoaderData* cld = new ClassLoaderData(loader, is_anonymous);
+ ClassLoaderData* cld = new ClassLoaderData(loader, is_unsafe_anonymous);
- if (!is_anonymous) {
+ if (!is_unsafe_anonymous) {
// First, Atomically set it
ClassLoaderData* old = java_lang_ClassLoader::cmpxchg_loader_data(cld, loader(), NULL);
if (old != NULL) {
@@ -1109,8 +1109,8 @@
} while (true);
}
-ClassLoaderData* ClassLoaderDataGraph::add(Handle loader, bool is_anonymous) {
- ClassLoaderData* loader_data = add_to_graph(loader, is_anonymous);
+ClassLoaderData* ClassLoaderDataGraph::add(Handle loader, bool is_unsafe_anonymous) {
+ ClassLoaderData* loader_data = add_to_graph(loader, is_unsafe_anonymous);
// Initialize _name and _name_and_id after the loader data is added to the
// CLDG because adding the Symbol for _name and _name_and_id might safepoint.
if (loader.not_null()) {
@@ -1119,28 +1119,6 @@
return loader_data;
}
-void ClassLoaderDataGraph::oops_do(OopClosure* f, bool must_claim) {
- for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
- cld->oops_do(f, must_claim);
- }
-}
-
-void ClassLoaderDataGraph::keep_alive_oops_do(OopClosure* f, bool must_claim) {
- for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
- if (cld->keep_alive()) {
- cld->oops_do(f, must_claim);
- }
- }
-}
-
-void ClassLoaderDataGraph::always_strong_oops_do(OopClosure* f, bool must_claim) {
- if (ClassUnloading) {
- keep_alive_oops_do(f, must_claim);
- } else {
- oops_do(f, must_claim);
- }
-}
-
void ClassLoaderDataGraph::cld_do(CLDClosure* cl) {
for (ClassLoaderData* cld = _head; cl != NULL && cld != NULL; cld = cld->next()) {
cl->do_cld(cld);
@@ -1166,13 +1144,9 @@
}
}
-void ClassLoaderDataGraph::keep_alive_cld_do(CLDClosure* cl) {
- roots_cld_do(cl, NULL);
-}
-
void ClassLoaderDataGraph::always_strong_cld_do(CLDClosure* cl) {
if (ClassUnloading) {
- keep_alive_cld_do(cl);
+ roots_cld_do(cl, NULL);
} else {
cld_do(cl);
}
--- a/src/hotspot/share/classfile/classLoaderData.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/classfile/classLoaderData.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -92,29 +92,24 @@
static volatile size_t _num_instance_classes;
static volatile size_t _num_array_classes;
- static ClassLoaderData* add_to_graph(Handle class_loader, bool anonymous);
- static ClassLoaderData* add(Handle class_loader, bool anonymous);
+ static ClassLoaderData* add_to_graph(Handle class_loader, bool is_unsafe_anonymous);
+ static ClassLoaderData* add(Handle class_loader, bool is_unsafe_anonymous);
public:
static ClassLoaderData* find_or_create(Handle class_loader);
static void clean_module_and_package_info();
static void purge();
static void clear_claimed_marks();
- // oops do
- static void oops_do(OopClosure* f, bool must_claim);
- static void keep_alive_oops_do(OopClosure* blk, bool must_claim);
- static void always_strong_oops_do(OopClosure* blk, bool must_claim);
- // cld do
+ // Iteration through CLDG inside a safepoint; GC support
static void cld_do(CLDClosure* cl);
static void cld_unloading_do(CLDClosure* cl);
static void roots_cld_do(CLDClosure* strong, CLDClosure* weak);
- static void keep_alive_cld_do(CLDClosure* cl);
static void always_strong_cld_do(CLDClosure* cl);
// klass do
// Walking classes through the ClassLoaderDataGraph include array classes. It also includes
// classes that are allocated but not loaded, classes that have errors, and scratch classes
// for redefinition. These classes are removed during the next class unloading.
- // Walking the ClassLoaderDataGraph also includes anonymous classes.
+ // Walking the ClassLoaderDataGraph also includes unsafe anonymous classes.
static void classes_do(KlassClosure* klass_closure);
static void classes_do(void f(Klass* const));
static void methods_do(void f(Method*));
@@ -238,16 +233,17 @@
// classes in the class loader are allocated.
Mutex* _metaspace_lock; // Locks the metaspace for allocations and setup.
bool _unloading; // true if this class loader goes away
- bool _is_anonymous; // if this CLD is for an anonymous class
+ bool _is_unsafe_anonymous; // CLD is dedicated to one class and that class determines the CLDs lifecycle.
+ // For example, an unsafe anonymous class.
// Remembered sets support for the oops in the class loader data.
bool _modified_oops; // Card Table Equivalent (YC/CMS support)
bool _accumulated_modified_oops; // Mod Union Equivalent (CMS support)
s2 _keep_alive; // if this CLD is kept alive.
- // Used for anonymous classes and the boot class
+ // Used for unsafe anonymous classes and the boot class
// loader. _keep_alive does not need to be volatile or
- // atomic since there is one unique CLD per anonymous class.
+ // atomic since there is one unique CLD per unsafe anonymous class.
volatile int _claimed; // true if claimed, for example during GC traces.
// To avoid applying oop closure more than once.
@@ -283,7 +279,7 @@
void set_next(ClassLoaderData* next) { _next = next; }
ClassLoaderData* next() const { return _next; }
- ClassLoaderData(Handle h_class_loader, bool is_anonymous);
+ ClassLoaderData(Handle h_class_loader, bool is_unsafe_anonymous);
~ClassLoaderData();
// The CLD are not placed in the Heap, so the Card Table or
@@ -337,7 +333,7 @@
Mutex* metaspace_lock() const { return _metaspace_lock; }
- bool is_anonymous() const { return _is_anonymous; }
+ bool is_unsafe_anonymous() const { return _is_unsafe_anonymous; }
static void init_null_class_loader_data();
@@ -346,15 +342,15 @@
}
// Returns true if this class loader data is for the system class loader.
- // (Note that the class loader data may be anonymous.)
+ // (Note that the class loader data may be unsafe anonymous.)
bool is_system_class_loader_data() const;
// Returns true if this class loader data is for the platform class loader.
- // (Note that the class loader data may be anonymous.)
+ // (Note that the class loader data may be unsafe anonymous.)
bool is_platform_class_loader_data() const;
// Returns true if this class loader data is for the boot class loader.
- // (Note that the class loader data may be anonymous.)
+ // (Note that the class loader data may be unsafe anonymous.)
inline bool is_boot_class_loader_data() const;
bool is_builtin_class_loader_data() const;
@@ -372,7 +368,7 @@
return _unloading;
}
- // Used to refcount an anonymous class's CLD in order to
+ // Used to refcount an unsafe anonymous class's CLD in order to
// indicate their aliveness.
void inc_keep_alive();
void dec_keep_alive();
@@ -412,7 +408,7 @@
static ClassLoaderData* class_loader_data(oop loader);
static ClassLoaderData* class_loader_data_or_null(oop loader);
- static ClassLoaderData* anonymous_class_loader_data(Handle loader);
+ static ClassLoaderData* unsafe_anonymous_class_loader_data(Handle loader);
// Returns Klass* of associated class loader, or NULL if associated loader is 'bootstrap'.
// Also works if unloading.
--- a/src/hotspot/share/classfile/classLoaderData.inline.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/classfile/classLoaderData.inline.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -94,9 +94,15 @@
}
bool ClassLoaderDataGraph::should_clean_metaspaces_and_reset() {
+ // Only clean metaspaces after full GC.
bool do_cleaning = _safepoint_cleanup_needed;
+#if INCLUDE_JVMTI
+ do_cleaning = do_cleaning && (_should_clean_deallocate_lists || InstanceKlass::has_previous_versions());
+#else
+ do_cleaning = do_cleaning && _should_clean_deallocate_lists;
+#endif
_safepoint_cleanup_needed = false; // reset
- return (do_cleaning && _should_clean_deallocate_lists) || InstanceKlass::has_previous_versions();
+ return do_cleaning;
}
#endif // SHARE_VM_CLASSFILE_CLASSLOADERDATA_INLINE_HPP
--- a/src/hotspot/share/classfile/classLoaderExt.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/classfile/classLoaderExt.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -50,6 +50,7 @@
jshort ClassLoaderExt::_app_class_paths_start_index = ClassLoaderExt::max_classpath_index;
jshort ClassLoaderExt::_app_module_paths_start_index = ClassLoaderExt::max_classpath_index;
+jshort ClassLoaderExt::_max_used_path_index = 0;
bool ClassLoaderExt::_has_app_classes = false;
bool ClassLoaderExt::_has_platform_classes = false;
@@ -242,6 +243,9 @@
classloader_type = ClassLoader::PLATFORM_LOADER;
ClassLoaderExt::set_has_platform_classes();
}
+ if (classpath_index > ClassLoaderExt::max_used_path_index()) {
+ ClassLoaderExt::set_max_used_path_index(classpath_index);
+ }
result->set_shared_classpath_index(classpath_index);
result->set_class_loader_type(classloader_type);
}
@@ -294,7 +298,7 @@
name,
loader_data,
protection_domain,
- NULL, // host_klass
+ NULL, // unsafe_anonymous_host
NULL, // cp_patches
THREAD);
--- a/src/hotspot/share/classfile/classLoaderExt.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/classfile/classLoaderExt.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -49,6 +49,8 @@
static jshort _app_class_paths_start_index;
// index of first modular JAR in shared modulepath entry table
static jshort _app_module_paths_start_index;
+ // the largest path index being used during CDS dump time
+ static jshort _max_used_path_index;
static bool _has_app_classes;
static bool _has_platform_classes;
@@ -91,6 +93,12 @@
static jshort app_module_paths_start_index() { return _app_module_paths_start_index; }
+ static jshort max_used_path_index() { return _max_used_path_index; }
+
+ static void set_max_used_path_index(jshort used_index) {
+ _max_used_path_index = used_index;
+ }
+
static void init_paths_start_index(jshort app_start) {
_app_class_paths_start_index = app_start;
}
--- a/src/hotspot/share/classfile/classLoaderHierarchyDCmd.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/classfile/classLoaderHierarchyDCmd.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -128,7 +128,7 @@
class LoaderTreeNode : public ResourceObj {
- // We walk the CLDG and, for each CLD which is non-anonymous, add
+ // We walk the CLDG and, for each CLD which is non-unsafe_anonymous, add
// a tree node.
// To add a node we need its parent node; if the parent node does not yet
// exist - because we have not yet encountered the CLD for the parent loader -
@@ -219,7 +219,7 @@
if (print_classes) {
if (_classes != NULL) {
for (LoadedClassInfo* lci = _classes; lci; lci = lci->_next) {
- // Non-anonymous classes should live in the primary CLD of its loader
+ // Non-unsafe anonymous classes should live in the primary CLD of its loader
assert(lci->_cld == _cld, "must be");
branchtracker.print(st);
@@ -252,12 +252,12 @@
for (LoadedClassInfo* lci = _anon_classes; lci; lci = lci->_next) {
branchtracker.print(st);
if (lci == _anon_classes) { // first iteration
- st->print("%*s ", indentation, "Anonymous Classes:");
+ st->print("%*s ", indentation, "Unsafe Anonymous Classes:");
} else {
st->print("%*s ", indentation, "");
}
st->print("%s", lci->_klass->external_name());
- // For anonymous classes, also print CLD if verbose. Should be a different one than the primary CLD.
+ // For unsafe anonymous classes, also print CLD if verbose. Should be a different one than the primary CLD.
assert(lci->_cld != _cld, "must be");
if (verbose) {
st->print(" (Loader Data: " PTR_FORMAT ")", p2i(lci->_cld));
@@ -266,7 +266,7 @@
}
branchtracker.print(st);
st->print("%*s ", indentation, "");
- st->print_cr("(%u anonymous class%s)", _num_anon_classes, (_num_anon_classes == 1) ? "" : "es");
+ st->print_cr("(%u unsafe anonymous class%s)", _num_anon_classes, (_num_anon_classes == 1) ? "" : "es");
// Empty line
branchtracker.print(st);
@@ -318,14 +318,14 @@
_next = info;
}
- void add_classes(LoadedClassInfo* first_class, int num_classes, bool anonymous) {
- LoadedClassInfo** p_list_to_add_to = anonymous ? &_anon_classes : &_classes;
+ void add_classes(LoadedClassInfo* first_class, int num_classes, bool is_unsafe_anonymous) {
+ LoadedClassInfo** p_list_to_add_to = is_unsafe_anonymous ? &_anon_classes : &_classes;
// Search tail.
while ((*p_list_to_add_to) != NULL) {
p_list_to_add_to = &(*p_list_to_add_to)->_next;
}
*p_list_to_add_to = first_class;
- if (anonymous) {
+ if (is_unsafe_anonymous) {
_num_anon_classes += num_classes;
} else {
_num_classes += num_classes;
@@ -420,7 +420,7 @@
LoadedClassCollectClosure lccc(cld);
const_cast<ClassLoaderData*>(cld)->classes_do(&lccc);
if (lccc._num_classes > 0) {
- info->add_classes(lccc._list, lccc._num_classes, cld->is_anonymous());
+ info->add_classes(lccc._list, lccc._num_classes, cld->is_unsafe_anonymous());
}
}
@@ -480,7 +480,7 @@
assert(info != NULL, "must be");
// Update CLD in node, but only if this is the primary CLD for this loader.
- if (cld->is_anonymous() == false) {
+ if (cld->is_unsafe_anonymous() == false) {
assert(info->cld() == NULL, "there should be only one primary CLD per loader");
info->set_cld(cld);
}
--- a/src/hotspot/share/classfile/classLoaderStats.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/classfile/classLoaderStats.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -58,7 +58,7 @@
cls = *cls_ptr;
}
- if (!cld->is_anonymous()) {
+ if (!cld->is_unsafe_anonymous()) {
cls->_cld = cld;
}
@@ -70,7 +70,7 @@
ClassStatsClosure csc;
cld->classes_do(&csc);
- if(cld->is_anonymous()) {
+ if(cld->is_unsafe_anonymous()) {
cls->_anon_classes_count += csc._num_classes;
} else {
cls->_classes_count = csc._num_classes;
@@ -79,7 +79,7 @@
ClassLoaderMetaspace* ms = cld->metaspace_or_null();
if (ms != NULL) {
- if(cld->is_anonymous()) {
+ if(cld->is_unsafe_anonymous()) {
cls->_anon_chunk_sz += ms->allocated_chunks_bytes();
cls->_anon_block_sz += ms->allocated_blocks_bytes();
} else {
--- a/src/hotspot/share/classfile/compactHashtable.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/classfile/compactHashtable.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -27,6 +27,7 @@
#include "classfile/compactHashtable.inline.hpp"
#include "classfile/javaClasses.hpp"
#include "logging/logMessage.hpp"
+#include "memory/heapShared.inline.hpp"
#include "memory/metadataFactory.hpp"
#include "memory/metaspaceShared.hpp"
#include "oops/compressedOops.inline.hpp"
@@ -280,8 +281,9 @@
public:
CompactHashtable_OopIterator(OopClosure *cl) : _closure(cl) {}
inline void do_value(address base_address, u4 offset) const {
- narrowOop o = (narrowOop)offset;
- _closure->do_oop(&o);
+ narrowOop v = (narrowOop)offset;
+ oop obj = HeapShared::decode_with_archived_oop_encoding_mode(v);
+ _closure->do_oop(&obj);
}
};
--- a/src/hotspot/share/classfile/compactHashtable.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/classfile/compactHashtable.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -231,6 +231,10 @@
// For reading from/writing to the CDS archive
void serialize(SerializeClosure* soc);
+
+ inline bool empty() {
+ return (_entry_count == 0);
+ }
};
template <class T, class N> class CompactHashtable : public SimpleCompactHashtable {
--- a/src/hotspot/share/classfile/compactHashtable.inline.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/classfile/compactHashtable.inline.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -28,7 +28,8 @@
#include "classfile/compactHashtable.hpp"
#include "classfile/javaClasses.hpp"
#include "memory/allocation.inline.hpp"
-#include "oops/compressedOops.inline.hpp"
+#include "memory/filemap.hpp"
+#include "memory/heapShared.inline.hpp"
#include "oops/oop.hpp"
template <class T, class N>
@@ -46,8 +47,8 @@
template <class T, class N>
inline oop CompactHashtable<T, N>::decode_entry(CompactHashtable<oop, char>* const t,
u4 offset, const char* name, int len) {
- narrowOop obj = (narrowOop)offset;
- oop string = CompressedOops::decode(obj);
+ narrowOop v = (narrowOop)offset;
+ oop string = HeapShared::decode_with_archived_oop_encoding_mode(v);
if (java_lang_String::equals(string, (jchar*)name, len)) {
return string;
}
--- a/src/hotspot/share/classfile/defaultMethods.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/classfile/defaultMethods.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -885,7 +885,7 @@
ConstantPool* cp = bpool->create_constant_pool(CHECK);
if (cp != klass->constants()) {
// Copy resolved anonymous class into new constant pool.
- if (klass->is_anonymous()) {
+ if (klass->is_unsafe_anonymous()) {
cp->klass_at_put(klass->this_class_index(), klass);
}
klass->class_loader_data()->add_to_deallocate_list(klass->constants());
--- a/src/hotspot/share/classfile/javaClasses.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/classfile/javaClasses.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -50,7 +50,7 @@
#include "oops/symbol.hpp"
#include "oops/typeArrayOop.inline.hpp"
#include "prims/resolvedMethodTable.hpp"
-#include "runtime/fieldDescriptor.hpp"
+#include "runtime/fieldDescriptor.inline.hpp"
#include "runtime/frame.inline.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/interfaceSupport.inline.hpp"
@@ -209,7 +209,7 @@
}
#if INCLUDE_CDS
-void java_lang_String::serialize(SerializeClosure* f) {
+void java_lang_String::serialize_offsets(SerializeClosure* f) {
STRING_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
f->do_u4((u4*)&initialized);
}
@@ -1038,6 +1038,7 @@
if (m != NULL) {
// Update the field at _array_klass_offset to point to the relocated array klass.
oop archived_m = MetaspaceShared::archive_heap_object(m, THREAD);
+ assert(archived_m != NULL, "sanity");
Klass *ak = (Klass*)(archived_m->metadata_field(_array_klass_offset));
assert(ak != NULL || t == T_VOID, "should not be NULL");
if (ak != NULL) {
@@ -1212,7 +1213,7 @@
bool java_lang_Class::restore_archived_mirror(Klass *k,
Handle class_loader, Handle module,
Handle protection_domain, TRAPS) {
- oop m = MetaspaceShared::materialize_archived_object(k->archived_java_mirror_raw());
+ oop m = MetaspaceShared::materialize_archived_object(k->archived_java_mirror_raw_narrow());
if (m == NULL) {
return false;
@@ -1534,7 +1535,7 @@
}
#if INCLUDE_CDS
-void java_lang_Class::serialize(SerializeClosure* f) {
+void java_lang_Class::serialize_offsets(SerializeClosure* f) {
f->do_u4((u4*)&offsets_computed);
f->do_u4((u4*)&_init_lock_offset);
@@ -1608,7 +1609,7 @@
}
#if INCLUDE_CDS
-void java_lang_Thread::serialize(SerializeClosure* f) {
+void java_lang_Thread::serialize_offsets(SerializeClosure* f) {
THREAD_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
}
#endif
@@ -1860,7 +1861,7 @@
}
#if INCLUDE_CDS
-void java_lang_ThreadGroup::serialize(SerializeClosure* f) {
+void java_lang_ThreadGroup::serialize_offsets(SerializeClosure* f) {
THREADGROUP_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
}
#endif
@@ -1878,7 +1879,7 @@
}
#if INCLUDE_CDS
-void java_lang_Throwable::serialize(SerializeClosure* f) {
+void java_lang_Throwable::serialize_offsets(SerializeClosure* f) {
THROWABLE_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
}
#endif
@@ -2654,7 +2655,7 @@
}
#if INCLUDE_CDS
-void java_lang_StackFrameInfo::serialize(SerializeClosure* f) {
+void java_lang_StackFrameInfo::serialize_offsets(SerializeClosure* f) {
STACKFRAMEINFO_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
STACKFRAMEINFO_INJECTED_FIELDS(INJECTED_FIELD_SERIALIZE_OFFSET);
}
@@ -2672,7 +2673,7 @@
}
#if INCLUDE_CDS
-void java_lang_LiveStackFrameInfo::serialize(SerializeClosure* f) {
+void java_lang_LiveStackFrameInfo::serialize_offsets(SerializeClosure* f) {
LIVESTACKFRAMEINFO_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
}
#endif
@@ -2686,7 +2687,7 @@
}
#if INCLUDE_CDS
-void java_lang_reflect_AccessibleObject::serialize(SerializeClosure* f) {
+void java_lang_reflect_AccessibleObject::serialize_offsets(SerializeClosure* f) {
ACCESSIBLEOBJECT_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
}
#endif
@@ -2727,7 +2728,7 @@
}
#if INCLUDE_CDS
-void java_lang_reflect_Method::serialize(SerializeClosure* f) {
+void java_lang_reflect_Method::serialize_offsets(SerializeClosure* f) {
METHOD_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
}
#endif
@@ -2914,7 +2915,7 @@
}
#if INCLUDE_CDS
-void java_lang_reflect_Constructor::serialize(SerializeClosure* f) {
+void java_lang_reflect_Constructor::serialize_offsets(SerializeClosure* f) {
CONSTRUCTOR_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
}
#endif
@@ -3063,7 +3064,7 @@
}
#if INCLUDE_CDS
-void java_lang_reflect_Field::serialize(SerializeClosure* f) {
+void java_lang_reflect_Field::serialize_offsets(SerializeClosure* f) {
FIELD_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
}
#endif
@@ -3186,7 +3187,7 @@
}
#if INCLUDE_CDS
-void reflect_ConstantPool::serialize(SerializeClosure* f) {
+void reflect_ConstantPool::serialize_offsets(SerializeClosure* f) {
CONSTANTPOOL_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
}
#endif
@@ -3203,7 +3204,7 @@
}
#if INCLUDE_CDS
-void java_lang_reflect_Parameter::serialize(SerializeClosure* f) {
+void java_lang_reflect_Parameter::serialize_offsets(SerializeClosure* f) {
PARAMETER_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
}
#endif
@@ -3281,7 +3282,7 @@
}
#if INCLUDE_CDS
-void java_lang_Module::serialize(SerializeClosure* f) {
+void java_lang_Module::serialize_offsets(SerializeClosure* f) {
MODULE_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
MODULE_INJECTED_FIELDS(INJECTED_FIELD_SERIALIZE_OFFSET);
}
@@ -3371,7 +3372,7 @@
}
#if INCLUDE_CDS
-void reflect_UnsafeStaticFieldAccessorImpl::serialize(SerializeClosure* f) {
+void reflect_UnsafeStaticFieldAccessorImpl::serialize_offsets(SerializeClosure* f) {
UNSAFESTATICFIELDACCESSORIMPL_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
}
#endif
@@ -3543,7 +3544,7 @@
}
#if INCLUDE_CDS
-void java_lang_ref_SoftReference::serialize(SerializeClosure* f) {
+void java_lang_ref_SoftReference::serialize_offsets(SerializeClosure* f) {
SOFTREFERENCE_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
}
#endif
@@ -3584,7 +3585,7 @@
}
#if INCLUDE_CDS
-void java_lang_invoke_DirectMethodHandle::serialize(SerializeClosure* f) {
+void java_lang_invoke_DirectMethodHandle::serialize_offsets(SerializeClosure* f) {
DIRECTMETHODHANDLE_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
}
#endif
@@ -3616,7 +3617,7 @@
}
#if INCLUDE_CDS
-void java_lang_invoke_MethodHandle::serialize(SerializeClosure* f) {
+void java_lang_invoke_MethodHandle::serialize_offsets(SerializeClosure* f) {
METHODHANDLE_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
}
#endif
@@ -3635,7 +3636,7 @@
}
#if INCLUDE_CDS
-void java_lang_invoke_MemberName::serialize(SerializeClosure* f) {
+void java_lang_invoke_MemberName::serialize_offsets(SerializeClosure* f) {
MEMBERNAME_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
MEMBERNAME_INJECTED_FIELDS(INJECTED_FIELD_SERIALIZE_OFFSET);
}
@@ -3648,7 +3649,7 @@
}
#if INCLUDE_CDS
-void java_lang_invoke_ResolvedMethodName::serialize(SerializeClosure* f) {
+void java_lang_invoke_ResolvedMethodName::serialize_offsets(SerializeClosure* f) {
RESOLVEDMETHOD_INJECTED_FIELDS(INJECTED_FIELD_SERIALIZE_OFFSET);
}
#endif
@@ -3663,7 +3664,7 @@
}
#if INCLUDE_CDS
-void java_lang_invoke_LambdaForm::serialize(SerializeClosure* f) {
+void java_lang_invoke_LambdaForm::serialize_offsets(SerializeClosure* f) {
LAMBDAFORM_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
}
#endif
@@ -3785,7 +3786,7 @@
}
oop new_resolved_method = k->allocate_instance(CHECK_NULL);
new_resolved_method->address_field_put(_vmtarget_offset, (address)m());
- // Add a reference to the loader (actually mirror because anonymous classes will not have
+ // Add a reference to the loader (actually mirror because unsafe anonymous classes will not have
// distinct loaders) to ensure the metadata is kept alive.
// This mirror may be different than the one in clazz field.
new_resolved_method->obj_field_put(_vmholder_offset, m->method_holder()->java_mirror());
@@ -3815,7 +3816,7 @@
}
#if INCLUDE_CDS
-void java_lang_invoke_MethodType::serialize(SerializeClosure* f) {
+void java_lang_invoke_MethodType::serialize_offsets(SerializeClosure* f) {
METHODTYPE_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
}
#endif
@@ -3909,7 +3910,7 @@
}
#if INCLUDE_CDS
-void java_lang_invoke_CallSite::serialize(SerializeClosure* f) {
+void java_lang_invoke_CallSite::serialize_offsets(SerializeClosure* f) {
CALLSITE_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
}
#endif
@@ -3931,7 +3932,7 @@
}
#if INCLUDE_CDS
-void java_lang_invoke_MethodHandleNatives_CallSiteContext::serialize(SerializeClosure* f) {
+void java_lang_invoke_MethodHandleNatives_CallSiteContext::serialize_offsets(SerializeClosure* f) {
CALLSITECONTEXT_INJECTED_FIELDS(INJECTED_FIELD_SERIALIZE_OFFSET);
}
#endif
@@ -3963,7 +3964,7 @@
}
#if INCLUDE_CDS
-void java_security_AccessControlContext::serialize(SerializeClosure* f) {
+void java_security_AccessControlContext::serialize_offsets(SerializeClosure* f) {
ACCESSCONTROLCONTEXT_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
}
#endif
@@ -4029,7 +4030,7 @@
}
#if INCLUDE_CDS
-void java_lang_ClassLoader::serialize(SerializeClosure* f) {
+void java_lang_ClassLoader::serialize_offsets(SerializeClosure* f) {
CLASSLOADER_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
CLASSLOADER_INJECTED_FIELDS(INJECTED_FIELD_SERIALIZE_OFFSET);
}
@@ -4143,7 +4144,7 @@
}
#if INCLUDE_CDS
-void java_lang_System::serialize(SerializeClosure* f) {
+void java_lang_System::serialize_offsets(SerializeClosure* f) {
SYSTEM_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
}
#endif
@@ -4247,14 +4248,7 @@
int java_util_concurrent_locks_AbstractOwnableSynchronizer::_owner_offset;
int reflect_ConstantPool::_oop_offset;
int reflect_UnsafeStaticFieldAccessorImpl::_base_offset;
-int jdk_internal_module_ArchivedModuleGraph::_archivedSystemModules_offset;
-int jdk_internal_module_ArchivedModuleGraph::_archivedModuleFinder_offset;
-int jdk_internal_module_ArchivedModuleGraph::_archivedMainModule_offset;
-int jdk_internal_module_ArchivedModuleGraph::_archivedConfiguration_offset;
-int java_lang_module_Configuration::_EMPTY_CONFIGURATION_offset;
-int java_util_ImmutableCollections_ListN::_EMPTY_LIST_offset;
-int java_util_ImmutableCollections_SetN::_EMPTY_SET_offset;
-int java_util_ImmutableCollections_MapN::_EMPTY_MAP_offset;
+
#define STACKTRACEELEMENT_FIELDS_DO(macro) \
macro(declaringClassObject_offset, k, "declaringClassObject", class_signature, false); \
@@ -4273,7 +4267,7 @@
}
#if INCLUDE_CDS
-void java_lang_StackTraceElement::serialize(SerializeClosure* f) {
+void java_lang_StackTraceElement::serialize_offsets(SerializeClosure* f) {
STACKTRACEELEMENT_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
}
#endif
@@ -4348,7 +4342,7 @@
}
#if INCLUDE_CDS
-void java_lang_AssertionStatusDirectives::serialize(SerializeClosure* f) {
+void java_lang_AssertionStatusDirectives::serialize_offsets(SerializeClosure* f) {
ASSERTIONSTATUSDIRECTIVES_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
}
#endif
@@ -4389,7 +4383,7 @@
}
#if INCLUDE_CDS
-void java_nio_Buffer::serialize(SerializeClosure* f) {
+void java_nio_Buffer::serialize_offsets(SerializeClosure* f) {
BUFFER_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
}
#endif
@@ -4408,7 +4402,7 @@
}
#if INCLUDE_CDS
-void java_util_concurrent_locks_AbstractOwnableSynchronizer::serialize(SerializeClosure* f) {
+void java_util_concurrent_locks_AbstractOwnableSynchronizer::serialize_offsets(SerializeClosure* f) {
AOS_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
}
#endif
@@ -4417,84 +4411,6 @@
return (hardcoded_offset * heapOopSize) + instanceOopDesc::base_offset_in_bytes();
}
-#define ARCHIVEDMODULEGRAPH_FIELDS_DO(macro) \
- macro(_archivedSystemModules_offset, k, "archivedSystemModules", systemModules_signature, true); \
- macro(_archivedModuleFinder_offset, k, "archivedModuleFinder", moduleFinder_signature, true); \
- macro(_archivedMainModule_offset, k, "archivedMainModule", string_signature, true); \
- macro(_archivedConfiguration_offset, k, "archivedConfiguration", configuration_signature, true)
-
-void jdk_internal_module_ArchivedModuleGraph::compute_offsets() {
- InstanceKlass* k = SystemDictionary::ArchivedModuleGraph_klass();
- assert(k != NULL, "must be loaded");
- ARCHIVEDMODULEGRAPH_FIELDS_DO(FIELD_COMPUTE_OFFSET);
-}
-
-#if INCLUDE_CDS
-void jdk_internal_module_ArchivedModuleGraph::serialize(SerializeClosure* f) {
- ARCHIVEDMODULEGRAPH_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
-}
-#endif
-
-#define CONFIGURATION_FIELDS_DO(macro) \
- macro(_EMPTY_CONFIGURATION_offset, k, "EMPTY_CONFIGURATION", configuration_signature, true)
-
-void java_lang_module_Configuration::compute_offsets() {
- InstanceKlass* k = SystemDictionary::Configuration_klass();
- assert(k != NULL, "must be loaded");
- CONFIGURATION_FIELDS_DO(FIELD_COMPUTE_OFFSET);
-}
-
-#if INCLUDE_CDS
-void java_lang_module_Configuration::serialize(SerializeClosure* f) {
- CONFIGURATION_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
-}
-#endif
-
-#define LISTN_FIELDS_DO(macro) \
- macro(_EMPTY_LIST_offset, k, "EMPTY_LIST", list_signature, true)
-
-void java_util_ImmutableCollections_ListN::compute_offsets() {
- InstanceKlass* k = SystemDictionary::ImmutableCollections_ListN_klass();
- assert(k != NULL, "must be loaded");
- LISTN_FIELDS_DO(FIELD_COMPUTE_OFFSET);
-}
-
-#if INCLUDE_CDS
-void java_util_ImmutableCollections_ListN::serialize(SerializeClosure* f) {
- LISTN_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
-}
-#endif
-
-#define SETN_FIELDS_DO(macro) \
- macro(_EMPTY_SET_offset, k, "EMPTY_SET", set_signature, true)
-
-void java_util_ImmutableCollections_SetN::compute_offsets() {
- InstanceKlass* k = SystemDictionary::ImmutableCollections_SetN_klass();
- assert(k != NULL, "must be loaded");
- SETN_FIELDS_DO(FIELD_COMPUTE_OFFSET);
-}
-
-#if INCLUDE_CDS
-void java_util_ImmutableCollections_SetN::serialize(SerializeClosure* f) {
- SETN_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
-}
-#endif
-
-#define MAPN_FIELDS_DO(macro) \
- macro(_EMPTY_MAP_offset, k, "EMPTY_MAP", map_signature, true)
-
-void java_util_ImmutableCollections_MapN::compute_offsets() {
- InstanceKlass* k = SystemDictionary::ImmutableCollections_MapN_klass();
- assert(k != NULL, "must be loaded");
- MAPN_FIELDS_DO(FIELD_COMPUTE_OFFSET);
-}
-
-#if INCLUDE_CDS
-void java_util_ImmutableCollections_MapN::serialize(SerializeClosure* f) {
- MAPN_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
-}
-#endif
-
// Compute hard-coded offsets
// Invoked before SystemDictionary::initialize, so pre-loaded classes
// are not available to determine the offset_of_static_fields.
@@ -4511,6 +4427,7 @@
java_lang_ref_Reference::discovered_offset = member_offset(java_lang_ref_Reference::hc_discovered_offset);
}
+#define DO_COMPUTE_OFFSETS(k) k::compute_offsets();
// Compute non-hard-coded field offsets of all the classes in this file
void JavaClasses::compute_offsets() {
@@ -4518,51 +4435,24 @@
return; // field offsets are loaded from archive
}
- // java_lang_Class::compute_offsets was called earlier in bootstrap
- java_lang_System::compute_offsets();
- java_lang_ClassLoader::compute_offsets();
- java_lang_Throwable::compute_offsets();
- java_lang_Thread::compute_offsets();
- java_lang_ThreadGroup::compute_offsets();
- java_lang_AssertionStatusDirectives::compute_offsets();
- java_lang_ref_SoftReference::compute_offsets();
- java_lang_invoke_MethodHandle::compute_offsets();
- java_lang_invoke_DirectMethodHandle::compute_offsets();
- java_lang_invoke_MemberName::compute_offsets();
- java_lang_invoke_ResolvedMethodName::compute_offsets();
- java_lang_invoke_LambdaForm::compute_offsets();
- java_lang_invoke_MethodType::compute_offsets();
- java_lang_invoke_CallSite::compute_offsets();
- java_lang_invoke_MethodHandleNatives_CallSiteContext::compute_offsets();
- java_security_AccessControlContext::compute_offsets();
- // Initialize reflection classes. The layouts of these classes
- // changed with the new reflection implementation in JDK 1.4, and
- // since the Universe doesn't know what JDK version it is until this
- // point we defer computation of these offsets until now.
- java_lang_reflect_AccessibleObject::compute_offsets();
- java_lang_reflect_Method::compute_offsets();
- java_lang_reflect_Constructor::compute_offsets();
- java_lang_reflect_Field::compute_offsets();
- java_nio_Buffer::compute_offsets();
- reflect_ConstantPool::compute_offsets();
- reflect_UnsafeStaticFieldAccessorImpl::compute_offsets();
- java_lang_reflect_Parameter::compute_offsets();
- java_lang_Module::compute_offsets();
- java_lang_StackTraceElement::compute_offsets();
- java_lang_StackFrameInfo::compute_offsets();
- java_lang_LiveStackFrameInfo::compute_offsets();
- java_util_concurrent_locks_AbstractOwnableSynchronizer::compute_offsets();
-
- java_lang_module_Configuration::compute_offsets();
- java_util_ImmutableCollections_ListN::compute_offsets();
- java_util_ImmutableCollections_MapN::compute_offsets();
- java_util_ImmutableCollections_SetN::compute_offsets();
- jdk_internal_module_ArchivedModuleGraph::compute_offsets();
+ // We have already called the compute_offsets() of the
+ // BASIC_JAVA_CLASSES_DO_PART1 classes (java_lang_String and java_lang_Class)
+ // earlier inside SystemDictionary::resolve_preloaded_classes()
+ BASIC_JAVA_CLASSES_DO_PART2(DO_COMPUTE_OFFSETS);
// generated interpreter code wants to know about the offsets we just computed:
AbstractAssembler::update_delayed_values();
}
+#if INCLUDE_CDS
+#define DO_SERIALIZE_OFFSETS(k) k::serialize_offsets(soc);
+
+void JavaClasses::serialize_offsets(SerializeClosure* soc) {
+ BASIC_JAVA_CLASSES_DO(DO_SERIALIZE_OFFSETS);
+}
+#endif
+
+
#ifndef PRODUCT
// These functions exist to assert the validity of hard-coded field offsets to guard
--- a/src/hotspot/share/classfile/javaClasses.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/classfile/javaClasses.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -47,6 +47,46 @@
// correspondingly. The names in the enums must be identical to the actual field
// names in order for the verification code to work.
+#define BASIC_JAVA_CLASSES_DO_PART1(f) \
+ f(java_lang_Class) \
+ f(java_lang_String) \
+ //end
+
+#define BASIC_JAVA_CLASSES_DO_PART2(f) \
+ f(java_lang_System) \
+ f(java_lang_ClassLoader) \
+ f(java_lang_Throwable) \
+ f(java_lang_Thread) \
+ f(java_lang_ThreadGroup) \
+ f(java_lang_AssertionStatusDirectives) \
+ f(java_lang_ref_SoftReference) \
+ f(java_lang_invoke_MethodHandle) \
+ f(java_lang_invoke_DirectMethodHandle) \
+ f(java_lang_invoke_MemberName) \
+ f(java_lang_invoke_ResolvedMethodName) \
+ f(java_lang_invoke_LambdaForm) \
+ f(java_lang_invoke_MethodType) \
+ f(java_lang_invoke_CallSite) \
+ f(java_lang_invoke_MethodHandleNatives_CallSiteContext) \
+ f(java_security_AccessControlContext) \
+ f(java_lang_reflect_AccessibleObject) \
+ f(java_lang_reflect_Method) \
+ f(java_lang_reflect_Constructor) \
+ f(java_lang_reflect_Field) \
+ f(java_nio_Buffer) \
+ f(reflect_ConstantPool) \
+ f(reflect_UnsafeStaticFieldAccessorImpl) \
+ f(java_lang_reflect_Parameter) \
+ f(java_lang_Module) \
+ f(java_lang_StackTraceElement) \
+ f(java_lang_StackFrameInfo) \
+ f(java_lang_LiveStackFrameInfo) \
+ f(java_util_concurrent_locks_AbstractOwnableSynchronizer) \
+ //end
+
+#define BASIC_JAVA_CLASSES_DO(f) \
+ BASIC_JAVA_CLASSES_DO_PART1(f) \
+ BASIC_JAVA_CLASSES_DO_PART2(f)
// Interface to java.lang.String objects
@@ -71,7 +111,7 @@
};
static void compute_offsets();
- static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
+ static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
// Instance creation
static Handle create_from_unicode(jchar* unicode, int len, TRAPS);
@@ -224,7 +264,7 @@
static oop create_basic_type_mirror(const char* basic_type_name, BasicType type, TRAPS);
// Archiving
- static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
+ static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
static void archive_basic_type_mirrors(TRAPS) NOT_CDS_JAVA_HEAP_RETURN;
static oop archive_mirror(Klass* k, TRAPS) NOT_CDS_JAVA_HEAP_RETURN_(NULL);
static oop process_archived_mirror(Klass* k, oop mirror, oop archived_mirror, Thread *THREAD)
@@ -317,7 +357,7 @@
static void compute_offsets();
public:
- static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
+ static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
// Instance creation
static oop create();
@@ -419,7 +459,7 @@
static void compute_offsets();
public:
- static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
+ static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
// parent ThreadGroup
static oop parent(oop java_thread_group);
@@ -500,7 +540,7 @@
static void print_stack_usage(Handle stream);
static void compute_offsets();
- static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
+ static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
// Allocate space for backtrace (created but stack trace not filled in)
static void allocate_backtrace(Handle throwable, TRAPS);
@@ -531,7 +571,7 @@
static void compute_offsets();
public:
- static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
+ static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
// Accessors
static jboolean override(oop reflect);
@@ -564,7 +604,7 @@
static void compute_offsets();
public:
- static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
+ static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
// Allocation
static Handle create(TRAPS);
@@ -635,7 +675,7 @@
static void compute_offsets();
public:
- static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
+ static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
// Allocation
static Handle create(TRAPS);
@@ -695,7 +735,7 @@
static void compute_offsets();
public:
- static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
+ static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
// Allocation
static Handle create(TRAPS);
@@ -752,7 +792,7 @@
static void compute_offsets();
public:
- static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
+ static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
// Allocation
static Handle create(TRAPS);
@@ -784,7 +824,7 @@
static void compute_offsets();
public:
- static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
+ static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
// Allocation
static Handle create(Handle loader, Handle module_name, TRAPS);
@@ -815,7 +855,7 @@
static void compute_offsets();
public:
- static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
+ static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
// Allocation
static Handle create(TRAPS);
@@ -839,7 +879,7 @@
static void compute_offsets();
public:
- static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
+ static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
static int base_offset() {
return _base_offset;
@@ -944,7 +984,7 @@
static void set_clock(jlong value);
static void compute_offsets();
- static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
+ static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
};
// Interface to java.lang.invoke.MethodHandle objects
@@ -961,7 +1001,7 @@
static void compute_offsets();
public:
- static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
+ static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
// Accessors
static oop type(oop mh);
@@ -992,7 +1032,7 @@
static void compute_offsets();
public:
- static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
+ static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
// Accessors
static oop member(oop mh);
@@ -1019,7 +1059,7 @@
static void compute_offsets();
public:
- static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
+ static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
// Accessors
static oop vmentry(oop lform);
@@ -1052,7 +1092,7 @@
static void compute_offsets();
public:
- static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
+ static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
static int vmtarget_offset_in_bytes() { return _vmtarget_offset; }
@@ -1091,7 +1131,7 @@
static void compute_offsets();
public:
- static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
+ static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
// Accessors
static oop clazz(oop mname);
static void set_clazz(oop mname, oop clazz);
@@ -1156,7 +1196,7 @@
static void compute_offsets();
public:
- static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
+ static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
// Accessors
static oop rtype(oop mt);
static objArrayOop ptypes(oop mt);
@@ -1192,7 +1232,7 @@
static void compute_offsets();
public:
- static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
+ static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
// Accessors
static oop target( oop site);
static void set_target( oop site, oop target);
@@ -1226,7 +1266,7 @@
static void compute_offsets();
public:
- static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
+ static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
// Accessors
static DependencyContext vmdependencies(oop context);
@@ -1250,7 +1290,7 @@
static void compute_offsets();
public:
- static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
+ static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
static oop create(objArrayHandle context, bool isPrivileged, Handle privileged_context, TRAPS);
static bool is_authorized(Handle context);
@@ -1277,7 +1317,7 @@
public:
static void compute_offsets();
- static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
+ static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
static ClassLoaderData* loader_data(oop loader);
static ClassLoaderData* cmpxchg_loader_data(ClassLoaderData* new_data, oop loader, ClassLoaderData* expected_data);
@@ -1330,7 +1370,7 @@
static bool has_security_manager();
static void compute_offsets();
- static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
+ static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
// Debugging
friend class JavaClasses;
@@ -1368,7 +1408,7 @@
int version, int bci, Symbol* name, TRAPS);
static void compute_offsets();
- static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
+ static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
// Debugging
friend class JavaClasses;
@@ -1412,7 +1452,7 @@
static void set_version(oop info, short value);
static void compute_offsets();
- static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
+ static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
static void to_stack_trace_element(Handle stackFrame, Handle stack_trace_element, TRAPS);
@@ -1434,7 +1474,7 @@
static void set_mode(oop info, int value);
static void compute_offsets();
- static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
+ static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
// Debugging
friend class JavaClasses;
@@ -1459,7 +1499,7 @@
static void set_deflt(oop obj, bool val);
static void compute_offsets();
- static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
+ static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
// Debugging
friend class JavaClasses;
@@ -1473,7 +1513,7 @@
public:
static int limit_offset();
static void compute_offsets();
- static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
+ static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
};
class java_util_concurrent_locks_AbstractOwnableSynchronizer : AllStatic {
@@ -1482,58 +1522,7 @@
public:
static void compute_offsets();
static oop get_owner_threadObj(oop obj);
- static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
-};
-
-class jdk_internal_module_ArchivedModuleGraph: AllStatic {
- private:
- static int _archivedSystemModules_offset;
- static int _archivedModuleFinder_offset;
- static int _archivedMainModule_offset;
- static int _archivedConfiguration_offset;
- public:
- static int archivedSystemModules_offset() { return _archivedSystemModules_offset; }
- static int archivedModuleFinder_offset() { return _archivedModuleFinder_offset; }
- static int archivedMainModule_offset() { return _archivedMainModule_offset; }
- static int archivedConfiguration_offset() { return _archivedConfiguration_offset; }
- static void compute_offsets();
- static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
-};
-
-class java_lang_module_Configuration: AllStatic {
- private:
- static int _EMPTY_CONFIGURATION_offset;
- public:
- static int EMPTY_CONFIGURATION_offset() { return _EMPTY_CONFIGURATION_offset; }
- static void compute_offsets();
- static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
-};
-
-class java_util_ImmutableCollections_ListN : AllStatic {
- private:
- static int _EMPTY_LIST_offset;
- public:
- static int EMPTY_LIST_offset() { return _EMPTY_LIST_offset; }
- static void compute_offsets();
- static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
-};
-
-class java_util_ImmutableCollections_SetN : AllStatic {
- private:
- static int _EMPTY_SET_offset;
- public:
- static int EMPTY_SET_offset() { return _EMPTY_SET_offset; }
- static void compute_offsets();
- static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
-};
-
-class java_util_ImmutableCollections_MapN : AllStatic {
- private:
- static int _EMPTY_MAP_offset;
- public:
- static int EMPTY_MAP_offset() { return _EMPTY_MAP_offset; }
- static void compute_offsets();
- static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
+ static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
};
// Use to declare fields that need to be injected into Java classes
@@ -1596,7 +1585,7 @@
static void compute_hard_coded_offsets();
static void compute_offsets();
static void check_offsets() PRODUCT_RETURN;
-
+ static void serialize_offsets(SerializeClosure* soc) NOT_CDS_RETURN;
static InjectedField* get_injected(Symbol* class_name, int* field_count);
};
--- a/src/hotspot/share/classfile/klassFactory.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/classfile/klassFactory.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -183,7 +183,7 @@
Symbol* name,
ClassLoaderData* loader_data,
Handle protection_domain,
- const InstanceKlass* host_klass,
+ const InstanceKlass* unsafe_anonymous_host,
GrowableArray<Handle>* cp_patches,
TRAPS) {
assert(stream != NULL, "invariant");
@@ -201,7 +201,7 @@
THREAD->statistical_info().incr_define_class_count();
// Skip this processing for VM anonymous classes
- if (host_klass == NULL) {
+ if (unsafe_anonymous_host == NULL) {
stream = check_class_file_load_hook(stream,
name,
loader_data,
@@ -214,7 +214,7 @@
name,
loader_data,
protection_domain,
- host_klass,
+ unsafe_anonymous_host,
cp_patches,
ClassFileParser::BROADCAST, // publicity level
CHECK_NULL);
--- a/src/hotspot/share/classfile/klassFactory.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/classfile/klassFactory.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -72,7 +72,7 @@
Symbol* name,
ClassLoaderData* loader_data,
Handle protection_domain,
- const InstanceKlass* host_klass,
+ const InstanceKlass* unsafe_anonymous_host,
GrowableArray<Handle>* cp_patches,
TRAPS);
public:
--- a/src/hotspot/share/classfile/moduleEntry.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/classfile/moduleEntry.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -110,7 +110,7 @@
ClassLoaderData* loader_data() const { return _loader_data; }
void set_loader_data(ClassLoaderData* cld) {
- assert(!cld->is_anonymous(), "Unexpected anonymous class loader data");
+ assert(!cld->is_unsafe_anonymous(), "Unexpected unsafe anonymous class loader data");
_loader_data = cld;
}
--- a/src/hotspot/share/classfile/resolutionErrors.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/classfile/resolutionErrors.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -65,9 +65,10 @@
}
void ResolutionErrorEntry::set_message(Symbol* c) {
- assert(c != NULL, "must set a value");
_message = c;
- _message->increment_refcount();
+ if (_message != NULL) {
+ _message->increment_refcount();
+ }
}
// create new error entry
@@ -87,7 +88,9 @@
// decrement error refcount
assert(entry->error() != NULL, "error should be set");
entry->error()->decrement_refcount();
- entry->message()->decrement_refcount();
+ if (entry->message() != NULL) {
+ entry->message()->decrement_refcount();
+ }
Hashtable<ConstantPool*, mtClass>::free_entry(entry);
}
--- a/src/hotspot/share/classfile/sharedPathsMiscInfo.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/classfile/sharedPathsMiscInfo.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -115,10 +115,15 @@
return fail("Corrupted archive file header");
}
+ jshort cur_index = 0;
+ jshort max_cp_index = FileMapInfo::current_info()->header()->max_used_path_index();
+ jshort module_paths_start_index =
+ FileMapInfo::current_info()->header()->app_module_paths_start_index();
while (_cur_ptr < _end_ptr) {
jint type;
const char* path = _cur_ptr;
_cur_ptr += strlen(path) + 1;
+
if (!read_jint(&type)) {
return fail("Corrupted archive file header");
}
@@ -129,13 +134,19 @@
print_path(&ls, type, path);
ls.cr();
}
- if (!check(type, path)) {
- if (!PrintSharedArchiveAndExit) {
- return false;
+ // skip checking the class path(s) which was not referenced during CDS dump
+ if ((cur_index <= max_cp_index) || (cur_index >= module_paths_start_index)) {
+ if (!check(type, path)) {
+ if (!PrintSharedArchiveAndExit) {
+ return false;
+ }
+ } else {
+ ClassLoader::trace_class_path("ok");
}
} else {
- ClassLoader::trace_class_path("ok");
+ ClassLoader::trace_class_path("skipped check");
}
+ cur_index++;
}
return true;
--- a/src/hotspot/share/classfile/stringTable.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/classfile/stringTable.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -64,9 +64,9 @@
// --------------------------------------------------------------------------
StringTable* StringTable::_the_table = NULL;
-bool StringTable::_shared_string_mapped = false;
CompactHashtable<oop, char> StringTable::_shared_table;
-bool StringTable::_alt_hash = false;
+volatile bool StringTable::_shared_string_mapped = false;
+volatile bool StringTable::_alt_hash = false;
static juint murmur_seed = 0;
@@ -176,18 +176,18 @@
}
};
-static size_t ceil_pow_2(uintx val) {
+static size_t ceil_log2(size_t val) {
size_t ret;
for (ret = 1; ((size_t)1 << ret) < val; ++ret);
return ret;
}
StringTable::StringTable() : _local_table(NULL), _current_size(0), _has_work(0),
- _needs_rehashing(false), _weak_handles(NULL), _items(0), _uncleaned_items(0) {
+ _needs_rehashing(false), _weak_handles(NULL), _items_count(0), _uncleaned_items_count(0) {
_weak_handles = new OopStorage("StringTable weak",
StringTableWeakAlloc_lock,
StringTableWeakActive_lock);
- size_t start_size_log_2 = ceil_pow_2(StringTableSize);
+ size_t start_size_log_2 = ceil_log2(StringTableSize);
_current_size = ((size_t)1) << start_size_log_2;
log_trace(stringtable)("Start size: " SIZE_FORMAT " (" SIZE_FORMAT ")",
_current_size, start_size_log_2);
@@ -195,32 +195,31 @@
}
size_t StringTable::item_added() {
- return Atomic::add((size_t)1, &(the_table()->_items));
+ return Atomic::add((size_t)1, &(the_table()->_items_count));
}
-size_t StringTable::add_items_to_clean(size_t ndead) {
- size_t total = Atomic::add((size_t)ndead, &(the_table()->_uncleaned_items));
+size_t StringTable::add_items_count_to_clean(size_t ndead) {
+ size_t total = Atomic::add((size_t)ndead, &(the_table()->_uncleaned_items_count));
log_trace(stringtable)(
"Uncleaned items:" SIZE_FORMAT " added: " SIZE_FORMAT " total:" SIZE_FORMAT,
- the_table()->_uncleaned_items, ndead, total);
+ the_table()->_uncleaned_items_count, ndead, total);
return total;
}
void StringTable::item_removed() {
- Atomic::add((size_t)-1, &(the_table()->_items));
+ Atomic::add((size_t)-1, &(the_table()->_items_count));
}
double StringTable::get_load_factor() {
- return (_items*1.0)/_current_size;
+ return (double)_items_count/_current_size;
}
double StringTable::get_dead_factor() {
- return (_uncleaned_items*1.0)/_current_size;
+ return (double)_uncleaned_items_count/_current_size;
}
-size_t StringTable::table_size(Thread* thread) {
- return ((size_t)(1)) << _local_table->get_size_log2(thread != NULL ? thread
- : Thread::current());
+size_t StringTable::table_size() {
+ return ((size_t)1) << _local_table->get_size_log2(Thread::current());
}
void StringTable::trigger_concurrent_work() {
@@ -406,7 +405,7 @@
// This is the serial case without ParState.
// Just set the correct number and check for a cleaning phase.
- the_table()->_uncleaned_items = stiac._count;
+ the_table()->_uncleaned_items_count = stiac._count;
StringTable::the_table()->check_concurrent_work();
if (processed != NULL) {
@@ -433,7 +432,7 @@
_par_state_string->weak_oops_do(&stiac, &dnc);
// Accumulate the dead strings.
- the_table()->add_items_to_clean(stiac._count);
+ the_table()->add_items_count_to_clean(stiac._count);
*processed = (int) stiac._count_total;
*removed = (int) stiac._count;
@@ -465,7 +464,7 @@
}
}
gt.done(jt);
- _current_size = table_size(jt);
+ _current_size = table_size();
log_debug(stringtable)("Grown to size:" SIZE_FORMAT, _current_size);
}
@@ -843,7 +842,7 @@
assert(MetaspaceShared::is_heap_object_archiving_allowed(), "must be");
_shared_table.reset();
- int num_buckets = the_table()->_items / SharedSymbolTableBucketSize;
+ int num_buckets = the_table()->_items_count / SharedSymbolTableBucketSize;
// calculation of num_buckets can result in zero buckets, we need at least one
CompactStringTableWriter writer(num_buckets > 1 ? num_buckets : 1,
&MetaspaceShared::stats()->string);
--- a/src/hotspot/share/classfile/stringTable.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/classfile/stringTable.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -58,21 +58,22 @@
static StringTable* _the_table;
// Shared string table
static CompactHashtable<oop, char> _shared_table;
- static bool _shared_string_mapped;
- static bool _alt_hash;
+ static volatile bool _shared_string_mapped;
+ static volatile bool _alt_hash;
+
private:
- // Set if one bucket is out of balance due to hash algorithm deficiency
StringTableHash* _local_table;
size_t _current_size;
volatile bool _has_work;
+ // Set if one bucket is out of balance due to hash algorithm deficiency
volatile bool _needs_rehashing;
OopStorage* _weak_handles;
- volatile size_t _items;
+ volatile size_t _items_count;
DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, sizeof(volatile size_t));
- volatile size_t _uncleaned_items;
+ volatile size_t _uncleaned_items_count;
DEFINE_PAD_MINUS_SIZE(2, DEFAULT_CACHE_LINE_SIZE, sizeof(volatile size_t));
double get_load_factor();
@@ -83,7 +84,7 @@
static size_t item_added();
static void item_removed();
- size_t add_items_to_clean(size_t ndead);
+ size_t add_items_count_to_clean(size_t ndead);
StringTable();
@@ -100,7 +101,7 @@
public:
// The string table
static StringTable* the_table() { return _the_table; }
- size_t table_size(Thread* thread = NULL);
+ size_t table_size();
static OopStorage* weak_storage() { return the_table()->_weak_handles; }
@@ -116,7 +117,7 @@
// Must be called before a parallel walk where strings might die.
static void reset_dead_counter() {
- the_table()->_uncleaned_items = 0;
+ the_table()->_uncleaned_items_count = 0;
}
// After the parallel walk this method must be called to trigger
// cleaning. Note it might trigger a resize instead.
@@ -127,7 +128,7 @@
// If GC uses ParState directly it should add the number of cleared
// strings to this method.
static void inc_dead_counter(size_t ndead) {
- the_table()->add_items_to_clean(ndead);
+ the_table()->add_items_count_to_clean(ndead);
}
// Delete pointers to otherwise-unreachable objects.
--- a/src/hotspot/share/classfile/symbolTable.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/classfile/symbolTable.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -27,46 +27,178 @@
#include "classfile/compactHashtable.inline.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/symbolTable.hpp"
-#include "classfile/systemDictionary.hpp"
-#include "gc/shared/collectedHeap.inline.hpp"
#include "memory/allocation.inline.hpp"
-#include "memory/filemap.hpp"
#include "memory/metaspaceClosure.hpp"
#include "memory/resourceArea.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/atomic.hpp"
-#include "runtime/mutexLocker.hpp"
-#include "runtime/safepointVerifiers.hpp"
+#include "runtime/interfaceSupport.inline.hpp"
+#include "runtime/timerTrace.hpp"
#include "services/diagnosticCommand.hpp"
-#include "utilities/hashtable.inline.hpp"
+#include "utilities/concurrentHashTable.inline.hpp"
+#include "utilities/concurrentHashTableTasks.inline.hpp"
+
+// We used to not resize at all, so let's be conservative
+// and not set it too short before we decide to resize,
+// to match previous startup behavior
+#define PREF_AVG_LIST_LEN 8
+// 2^17 (131,072) is max size, which is about 6.5 times as large
+// as the previous table size (used to be 20,011),
+// which never resized
+#define END_SIZE 17
+// If a chain gets to 100 something might be wrong
+#define REHASH_LEN 100
+// We only get a chance to check whether we need
+// to clean infrequently (on class unloading),
+// so if we have even one dead entry then mark table for cleaning
+#define CLEAN_DEAD_HIGH_WATER_MARK 0.0
+
+#define ON_STACK_BUFFER_LENGTH 128
// --------------------------------------------------------------------------
-// the number of buckets a thread claims
-const int ClaimChunkSize = 32;
-
SymbolTable* SymbolTable::_the_table = NULL;
+CompactHashtable<Symbol*, char> SymbolTable::_shared_table;
+volatile bool SymbolTable::_alt_hash = false;
+volatile bool SymbolTable::_lookup_shared_first = false;
// Static arena for symbols that are not deallocated
Arena* SymbolTable::_arena = NULL;
-bool SymbolTable::_needs_rehashing = false;
-bool SymbolTable::_lookup_shared_first = false;
+
+static juint murmur_seed = 0;
+
+static inline void log_trace_symboltable_helper(Symbol* sym, const char* msg) {
+#ifndef PRODUCT
+ ResourceMark rm;
+ log_trace(symboltable)("%s [%s]", msg, sym->as_quoted_ascii());
+#endif // PRODUCT
+}
+
+// Pick hashing algorithm.
+static uintx hash_symbol(const char* s, int len, bool useAlt) {
+ return useAlt ?
+ AltHashing::murmur3_32(murmur_seed, (const jbyte*)s, len) :
+ java_lang_String::hash_code((const jbyte*)s, len);
+}
+
+static uintx hash_shared_symbol(const char* s, int len) {
+ return java_lang_String::hash_code((const jbyte*)s, len);
+}
+
+class SymbolTableConfig : public SymbolTableHash::BaseConfig {
+private:
+public:
+ static uintx get_hash(Symbol* const& value, bool* is_dead) {
+ *is_dead = (value->refcount() == 0);
+ if (*is_dead) {
+ return 0;
+ } else {
+ return hash_symbol((const char*)value->bytes(), value->utf8_length(), SymbolTable::_alt_hash);
+ }
+ }
+ // We use default allocation/deallocation but counted
+ static void* allocate_node(size_t size, Symbol* const& value) {
+ SymbolTable::item_added();
+ return SymbolTableHash::BaseConfig::allocate_node(size, value);
+ }
+ static void free_node(void* memory, Symbol* const& value) {
+ // We get here either because #1 some threads lost a race
+ // to insert a newly created Symbol, or #2 we are freeing
+ // a symbol during normal cleanup deletion.
+ // If #1, then the symbol can be a permanent (refcount==PERM_REFCOUNT),
+ // or regular newly created one but with refcount==0 (see SymbolTableCreateEntry)
+ // If #2, then the symbol must have refcount==0
+ assert((value->refcount() == PERM_REFCOUNT) || (value->refcount() == 0),
+ "refcount %d", value->refcount());
+ SymbolTable::delete_symbol(value);
+ SymbolTableHash::BaseConfig::free_node(memory, value);
+ SymbolTable::item_removed();
+ }
+};
+
+static size_t ceil_log2(size_t value) {
+ size_t ret;
+ for (ret = 1; ((size_t)1 << ret) < value; ++ret);
+ return ret;
+}
-CompactHashtable<Symbol*, char> SymbolTable::_shared_table;
+SymbolTable::SymbolTable() :
+ _symbols_removed(0), _symbols_counted(0), _local_table(NULL),
+ _current_size(0), _has_work(0), _needs_rehashing(false),
+ _items_count(0), _uncleaned_items_count(0) {
+
+ size_t start_size_log_2 = ceil_log2(SymbolTableSize);
+ _current_size = ((size_t)1) << start_size_log_2;
+ log_trace(symboltable)("Start size: " SIZE_FORMAT " (" SIZE_FORMAT ")",
+ _current_size, start_size_log_2);
+ _local_table = new SymbolTableHash(start_size_log_2, END_SIZE, REHASH_LEN);
+}
+
+void SymbolTable::delete_symbol(Symbol* sym) {
+ if (sym->refcount() == PERM_REFCOUNT) {
+ MutexLocker ml(SymbolTable_lock); // Protect arena
+ // Deleting permanent symbol should not occur very often (insert race condition),
+ // so log it.
+ log_trace_symboltable_helper(sym, "Freeing permanent symbol");
+ if (!arena()->Afree(sym, sym->size())) {
+ log_trace_symboltable_helper(sym, "Leaked permanent symbol");
+ }
+ } else {
+ delete sym;
+ }
+}
+
+void SymbolTable::item_added() {
+ Atomic::inc(&(SymbolTable::the_table()->_items_count));
+}
-Symbol* SymbolTable::allocate_symbol(const u1* name, int len, bool c_heap, TRAPS) {
+void SymbolTable::set_item_clean_count(size_t ncl) {
+ Atomic::store(ncl, &(SymbolTable::the_table()->_uncleaned_items_count));
+ log_trace(symboltable)("Set uncleaned items:" SIZE_FORMAT, SymbolTable::the_table()->_uncleaned_items_count);
+}
+
+void SymbolTable::mark_item_clean_count() {
+ if (Atomic::cmpxchg((size_t)1, &(SymbolTable::the_table()->_uncleaned_items_count), (size_t)0) == 0) { // only mark if unset
+ log_trace(symboltable)("Marked uncleaned items:" SIZE_FORMAT, SymbolTable::the_table()->_uncleaned_items_count);
+ }
+}
+
+void SymbolTable::item_removed() {
+ Atomic::inc(&(SymbolTable::the_table()->_symbols_removed));
+ Atomic::dec(&(SymbolTable::the_table()->_items_count));
+}
+
+double SymbolTable::get_load_factor() {
+ return (double)_items_count/_current_size;
+}
+
+double SymbolTable::get_dead_factor() {
+ return (double)_uncleaned_items_count/_current_size;
+}
+
+size_t SymbolTable::table_size() {
+ return ((size_t)1) << _local_table->get_size_log2(Thread::current());
+}
+
+void SymbolTable::trigger_concurrent_work() {
+ MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
+ SymbolTable::the_table()->_has_work = true;
+ Service_lock->notify_all();
+}
+
+Symbol* SymbolTable::allocate_symbol(const char* name, int len, bool c_heap, TRAPS) {
assert (len <= Symbol::max_length(), "should be checked by caller");
Symbol* sym;
-
if (DumpSharedSpaces) {
c_heap = false;
}
if (c_heap) {
// refcount starts as 1
- sym = new (len, THREAD) Symbol(name, len, 1);
+ sym = new (len, THREAD) Symbol((const u1*)name, len, 1);
assert(sym != NULL, "new should call vm_exit_out_of_memory if C_HEAP is exhausted");
} else {
// Allocate to global arena
- sym = new (len, arena(), THREAD) Symbol(name, len, PERM_REFCOUNT);
+ MutexLocker ml(SymbolTable_lock); // Protect arena
+ sym = new (len, arena(), THREAD) Symbol((const u1*)name, len, PERM_REFCOUNT);
}
return sym;
}
@@ -80,314 +212,176 @@
}
}
+class SymbolsDo : StackObj {
+ SymbolClosure *_cl;
+public:
+ SymbolsDo(SymbolClosure *cl) : _cl(cl) {}
+ bool operator()(Symbol** value) {
+ assert(value != NULL, "expected valid value");
+ assert(*value != NULL, "value should point to a symbol");
+ _cl->do_symbol(value);
+ return true;
+ };
+};
+
// Call function for all symbols in the symbol table.
void SymbolTable::symbols_do(SymbolClosure *cl) {
// all symbols from shared table
_shared_table.symbols_do(cl);
// all symbols from the dynamic table
- const int n = the_table()->table_size();
- for (int i = 0; i < n; i++) {
- for (HashtableEntry<Symbol*, mtSymbol>* p = the_table()->bucket(i);
- p != NULL;
- p = p->next()) {
- cl->do_symbol(p->literal_addr());
- }
- }
-}
-
-void SymbolTable::metaspace_pointers_do(MetaspaceClosure* it) {
- assert(DumpSharedSpaces, "called only during dump time");
- const int n = the_table()->table_size();
- for (int i = 0; i < n; i++) {
- for (HashtableEntry<Symbol*, mtSymbol>* p = the_table()->bucket(i);
- p != NULL;
- p = p->next()) {
- it->push(p->literal_addr());
- }
- }
-}
-
-int SymbolTable::_symbols_removed = 0;
-int SymbolTable::_symbols_counted = 0;
-volatile int SymbolTable::_parallel_claimed_idx = 0;
-
-void SymbolTable::buckets_unlink(int start_idx, int end_idx, BucketUnlinkContext* context) {
- for (int i = start_idx; i < end_idx; ++i) {
- HashtableEntry<Symbol*, mtSymbol>** p = the_table()->bucket_addr(i);
- HashtableEntry<Symbol*, mtSymbol>* entry = the_table()->bucket(i);
- while (entry != NULL) {
- // Shared entries are normally at the end of the bucket and if we run into
- // a shared entry, then there is nothing more to remove. However, if we
- // have rehashed the table, then the shared entries are no longer at the
- // end of the bucket.
- if (entry->is_shared() && !use_alternate_hashcode()) {
- break;
- }
- Symbol* s = entry->literal();
- context->_num_processed++;
- assert(s != NULL, "just checking");
- // If reference count is zero, remove.
- if (s->refcount() == 0) {
- assert(!entry->is_shared(), "shared entries should be kept live");
- delete s;
- *p = entry->next();
- context->free_entry(entry);
- } else {
- p = entry->next_addr();
- }
- // get next entry
- entry = (HashtableEntry<Symbol*, mtSymbol>*)HashtableEntry<Symbol*, mtSymbol>::make_ptr(*p);
- }
+ SymbolsDo sd(cl);
+ if (!SymbolTable::the_table()->_local_table->try_scan(Thread::current(), sd)) {
+ log_info(stringtable)("symbols_do unavailable at this moment");
}
}
-// Remove unreferenced symbols from the symbol table
-// This is done late during GC.
-void SymbolTable::unlink(int* processed, int* removed) {
- BucketUnlinkContext context;
- buckets_unlink(0, the_table()->table_size(), &context);
- _the_table->bulk_free_entries(&context);
- *processed = context._num_processed;
- *removed = context._num_removed;
-
- _symbols_removed = context._num_removed;
- _symbols_counted = context._num_processed;
-}
-
-void SymbolTable::possibly_parallel_unlink(int* processed, int* removed) {
- const int limit = the_table()->table_size();
+class MetaspacePointersDo : StackObj {
+ MetaspaceClosure *_it;
+public:
+ MetaspacePointersDo(MetaspaceClosure *it) : _it(it) {}
+ bool operator()(Symbol** value) {
+ assert(value != NULL, "expected valid value");
+ assert(*value != NULL, "value should point to a symbol");
+ _it->push(value);
+ return true;
+ };
+};
- BucketUnlinkContext context;
- for (;;) {
- // Grab next set of buckets to scan
- int start_idx = Atomic::add(ClaimChunkSize, &_parallel_claimed_idx) - ClaimChunkSize;
- if (start_idx >= limit) {
- // End of table
- break;
- }
-
- int end_idx = MIN2(limit, start_idx + ClaimChunkSize);
- buckets_unlink(start_idx, end_idx, &context);
- }
-
- _the_table->bulk_free_entries(&context);
- *processed = context._num_processed;
- *removed = context._num_removed;
-
- Atomic::add(context._num_processed, &_symbols_counted);
- Atomic::add(context._num_removed, &_symbols_removed);
+void SymbolTable::metaspace_pointers_do(MetaspaceClosure* it) {
+ assert(DumpSharedSpaces, "called only during dump time");
+ MetaspacePointersDo mpd(it);
+ SymbolTable::the_table()->_local_table->do_scan(Thread::current(), mpd);
}
-// Create a new table and using alternate hash code, populate the new table
-// with the existing strings. Set flag to use the alternate hash code afterwards.
-void SymbolTable::rehash_table() {
- if (DumpSharedSpaces) {
- tty->print_cr("Warning: rehash_table should not be called while dumping archive");
- return;
- }
-
- assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
- // This should never happen with -Xshare:dump but it might in testing mode.
- if (DumpSharedSpaces) return;
-
- // Create a new symbol table
- SymbolTable* new_table = new SymbolTable();
-
- the_table()->move_to(new_table);
-
- // Delete the table and buckets (entries are reused in new table).
- delete _the_table;
- // Don't check if we need rehashing until the table gets unbalanced again.
- // Then rehash with a new global seed.
- _needs_rehashing = false;
- _the_table = new_table;
-}
-
-// Lookup a symbol in a bucket.
-
-Symbol* SymbolTable::lookup_dynamic(int index, const char* name,
+Symbol* SymbolTable::lookup_dynamic(const char* name,
int len, unsigned int hash) {
- int count = 0;
- for (HashtableEntry<Symbol*, mtSymbol>* e = bucket(index); e != NULL; e = e->next()) {
- count++; // count all entries in this bucket, not just ones with same hash
- if (e->hash() == hash) {
- Symbol* sym = e->literal();
- // Skip checking already dead symbols in the bucket.
- if (sym->refcount() == 0) {
- count--; // Don't count this symbol towards rehashing.
- } else if (sym->equals(name, len)) {
- if (sym->try_increment_refcount()) {
- // something is referencing this symbol now.
- return sym;
- } else {
- count--; // don't count this symbol.
- }
- }
- }
- }
- // If the bucket size is too deep check if this hash code is insufficient.
- if (count >= rehash_count && !needs_rehashing()) {
- _needs_rehashing = check_rehash_table(count);
- }
- return NULL;
+ Symbol* sym = SymbolTable::the_table()->do_lookup(name, len, hash);
+ assert((sym == NULL) || sym->refcount() != 0, "refcount must not be zero");
+ return sym;
}
Symbol* SymbolTable::lookup_shared(const char* name,
int len, unsigned int hash) {
- if (use_alternate_hashcode()) {
- // hash_code parameter may use alternate hashing algorithm but the shared table
- // always uses the same original hash code.
- hash = hash_shared_symbol(name, len);
+ if (!_shared_table.empty()) {
+ if (SymbolTable::_alt_hash) {
+ // hash_code parameter may use alternate hashing algorithm but the shared table
+ // always uses the same original hash code.
+ hash = hash_shared_symbol(name, len);
+ }
+ return _shared_table.lookup(name, hash, len);
+ } else {
+ return NULL;
}
- return _shared_table.lookup(name, hash, len);
}
-Symbol* SymbolTable::lookup(int index, const char* name,
+Symbol* SymbolTable::lookup_common(const char* name,
int len, unsigned int hash) {
Symbol* sym;
if (_lookup_shared_first) {
sym = lookup_shared(name, len, hash);
- if (sym != NULL) {
- return sym;
+ if (sym == NULL) {
+ _lookup_shared_first = false;
+ sym = lookup_dynamic(name, len, hash);
}
- _lookup_shared_first = false;
- return lookup_dynamic(index, name, len, hash);
} else {
- sym = lookup_dynamic(index, name, len, hash);
- if (sym != NULL) {
- return sym;
+ sym = lookup_dynamic(name, len, hash);
+ if (sym == NULL) {
+ sym = lookup_shared(name, len, hash);
+ if (sym != NULL) {
+ _lookup_shared_first = true;
+ }
}
- sym = lookup_shared(name, len, hash);
- if (sym != NULL) {
- _lookup_shared_first = true;
- }
- return sym;
}
+ return sym;
}
-u4 SymbolTable::encode_shared(Symbol* sym) {
- assert(DumpSharedSpaces, "called only during dump time");
- uintx base_address = uintx(MetaspaceShared::shared_rs()->base());
- uintx offset = uintx(sym) - base_address;
- assert(offset < 0x7fffffff, "sanity");
- return u4(offset);
-}
-
-Symbol* SymbolTable::decode_shared(u4 offset) {
- assert(!DumpSharedSpaces, "called only during runtime");
- uintx base_address = _shared_table.base_address();
- Symbol* sym = (Symbol*)(base_address + offset);
-
-#ifndef PRODUCT
- const char* s = (const char*)sym->bytes();
- int len = sym->utf8_length();
- unsigned int hash = hash_symbol(s, len);
- assert(sym == lookup_shared(s, len, hash), "must be shared symbol");
-#endif
-
+Symbol* SymbolTable::lookup(const char* name, int len, TRAPS) {
+ unsigned int hash = hash_symbol(name, len, SymbolTable::_alt_hash);
+ Symbol* sym = SymbolTable::the_table()->lookup_common(name, len, hash);
+ if (sym == NULL) {
+ sym = SymbolTable::the_table()->do_add_if_needed(name, len, hash, true, CHECK_NULL);
+ }
+ assert(sym->refcount() != 0, "lookup should have incremented the count");
+ assert(sym->equals(name, len), "symbol must be properly initialized");
return sym;
}
-// Pick hashing algorithm.
-unsigned int SymbolTable::hash_symbol(const char* s, int len) {
- return use_alternate_hashcode() ?
- AltHashing::murmur3_32(seed(), (const jbyte*)s, len) :
- java_lang_String::hash_code((const jbyte*)s, len);
-}
-
-unsigned int SymbolTable::hash_shared_symbol(const char* s, int len) {
- return java_lang_String::hash_code((const jbyte*)s, len);
-}
-
-
-// We take care not to be blocking while holding the
-// SymbolTable_lock. Otherwise, the system might deadlock, since the
-// symboltable is used during compilation (VM_thread) The lock free
-// synchronization is simplified by the fact that we do not delete
-// entries in the symbol table during normal execution (only during
-// safepoints).
-
-Symbol* SymbolTable::lookup(const char* name, int len, TRAPS) {
- unsigned int hashValue = hash_symbol(name, len);
- int index = the_table()->hash_to_index(hashValue);
-
- Symbol* s = the_table()->lookup(index, name, len, hashValue);
-
- // Found
- if (s != NULL) return s;
-
- // Grab SymbolTable_lock first.
- MutexLocker ml(SymbolTable_lock, THREAD);
-
- // Otherwise, add to symbol to table
- return the_table()->basic_add(index, (u1*)name, len, hashValue, true, THREAD);
+Symbol* SymbolTable::lookup(const Symbol* sym, int begin, int end, TRAPS) {
+ assert(sym->refcount() != 0, "require a valid symbol");
+ const char* name = (const char*)sym->base() + begin;
+ int len = end - begin;
+ unsigned int hash = hash_symbol(name, len, SymbolTable::_alt_hash);
+ Symbol* found = SymbolTable::the_table()->lookup_common(name, len, hash);
+ if (found == NULL) {
+ found = SymbolTable::the_table()->do_add_if_needed(name, len, hash, true, THREAD);
+ }
+ return found;
}
-Symbol* SymbolTable::lookup(const Symbol* sym, int begin, int end, TRAPS) {
- char* buffer;
- int index, len;
- unsigned int hashValue;
- char* name;
- {
- debug_only(NoSafepointVerifier nsv;)
-
- name = (char*)sym->base() + begin;
- len = end - begin;
- hashValue = hash_symbol(name, len);
- index = the_table()->hash_to_index(hashValue);
- Symbol* s = the_table()->lookup(index, name, len, hashValue);
-
- // Found
- if (s != NULL) return s;
+class SymbolTableLookup : StackObj {
+private:
+ Thread* _thread;
+ uintx _hash;
+ int _len;
+ const char* _str;
+public:
+ SymbolTableLookup(Thread* thread, const char* key, int len, uintx hash)
+ : _thread(thread), _hash(hash), _len(len), _str(key) {}
+ uintx get_hash() const {
+ return _hash;
}
+ bool equals(Symbol** value, bool* is_dead) {
+ assert(value != NULL, "expected valid value");
+ assert(*value != NULL, "value should point to a symbol");
+ Symbol *sym = *value;
+ if (sym->equals(_str, _len)) {
+ if (sym->try_increment_refcount()) {
+ // something is referencing this symbol now.
+ return true;
+ } else {
+ assert(sym->refcount() == 0, "expected dead symbol");
+ *is_dead = true;
+ return false;
+ }
+ } else {
+ *is_dead = (sym->refcount() == 0);
+ return false;
+ }
+ }
+};
- // Otherwise, add to symbol to table. Copy to a C string first.
- char stack_buf[128];
- ResourceMark rm(THREAD);
- if (len <= 128) {
- buffer = stack_buf;
- } else {
- buffer = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, len);
+class SymbolTableGet : public StackObj {
+ Symbol* _return;
+public:
+ SymbolTableGet() : _return(NULL) {}
+ void operator()(Symbol** value) {
+ assert(value != NULL, "expected valid value");
+ assert(*value != NULL, "value should point to a symbol");
+ _return = *value;
+ }
+ Symbol* get_res_sym() {
+ return _return;
}
- for (int i=0; i<len; i++) {
- buffer[i] = name[i];
+};
+
+Symbol* SymbolTable::do_lookup(const char* name, int len, uintx hash) {
+ Thread* thread = Thread::current();
+ SymbolTableLookup lookup(thread, name, len, hash);
+ SymbolTableGet stg;
+ bool rehash_warning = false;
+ _local_table->get(thread, lookup, stg, &rehash_warning);
+ if (rehash_warning) {
+ _needs_rehashing = true;
}
- // Make sure there is no safepoint in the code above since name can't move.
- // We can't include the code in NoSafepointVerifier because of the
- // ResourceMark.
-
- // Grab SymbolTable_lock first.
- MutexLocker ml(SymbolTable_lock, THREAD);
-
- return the_table()->basic_add(index, (u1*)buffer, len, hashValue, true, THREAD);
+ Symbol* sym = stg.get_res_sym();
+ assert((sym == NULL) || sym->refcount() != 0, "found dead symbol");
+ return sym;
}
-Symbol* SymbolTable::lookup_only(const char* name, int len,
- unsigned int& hash) {
- hash = hash_symbol(name, len);
- int index = the_table()->hash_to_index(hash);
-
- Symbol* s = the_table()->lookup(index, name, len, hash);
- return s;
-}
-
-// Look up the address of the literal in the SymbolTable for this Symbol*
-// Do not create any new symbols
-// Do not increment the reference count to keep this alive
-Symbol** SymbolTable::lookup_symbol_addr(Symbol* sym){
- unsigned int hash = hash_symbol((char*)sym->bytes(), sym->utf8_length());
- int index = the_table()->hash_to_index(hash);
-
- for (HashtableEntry<Symbol*, mtSymbol>* e = the_table()->bucket(index); e != NULL; e = e->next()) {
- if (e->hash() == hash) {
- Symbol* literal_sym = e->literal();
- if (sym == literal_sym) {
- return e->literal_addr();
- }
- }
- }
- return NULL;
+Symbol* SymbolTable::lookup_only(const char* name, int len, unsigned int& hash) {
+ hash = hash_symbol(name, len, SymbolTable::_alt_hash);
+ return SymbolTable::the_table()->lookup_common(name, len, hash);
}
// Suggestion: Push unicode-based lookup all the way into the hashing
@@ -395,14 +389,14 @@
// an actual new Symbol* is created.
Symbol* SymbolTable::lookup_unicode(const jchar* name, int utf16_length, TRAPS) {
int utf8_length = UNICODE::utf8_length((jchar*) name, utf16_length);
- char stack_buf[128];
+ char stack_buf[ON_STACK_BUFFER_LENGTH];
if (utf8_length < (int) sizeof(stack_buf)) {
char* chars = stack_buf;
UNICODE::convert_to_utf8(name, utf16_length, chars);
return lookup(chars, utf8_length, THREAD);
} else {
ResourceMark rm(THREAD);
- char* chars = NEW_RESOURCE_ARRAY(char, utf8_length + 1);;
+ char* chars = NEW_RESOURCE_ARRAY(char, utf8_length + 1);
UNICODE::convert_to_utf8(name, utf16_length, chars);
return lookup(chars, utf8_length, THREAD);
}
@@ -411,214 +405,243 @@
Symbol* SymbolTable::lookup_only_unicode(const jchar* name, int utf16_length,
unsigned int& hash) {
int utf8_length = UNICODE::utf8_length((jchar*) name, utf16_length);
- char stack_buf[128];
+ char stack_buf[ON_STACK_BUFFER_LENGTH];
if (utf8_length < (int) sizeof(stack_buf)) {
char* chars = stack_buf;
UNICODE::convert_to_utf8(name, utf16_length, chars);
return lookup_only(chars, utf8_length, hash);
} else {
ResourceMark rm;
- char* chars = NEW_RESOURCE_ARRAY(char, utf8_length + 1);;
+ char* chars = NEW_RESOURCE_ARRAY(char, utf8_length + 1);
UNICODE::convert_to_utf8(name, utf16_length, chars);
return lookup_only(chars, utf8_length, hash);
}
}
void SymbolTable::add(ClassLoaderData* loader_data, const constantPoolHandle& cp,
- int names_count,
- const char** names, int* lengths, int* cp_indices,
- unsigned int* hashValues, TRAPS) {
- // Grab SymbolTable_lock first.
- MutexLocker ml(SymbolTable_lock, THREAD);
+ int names_count, const char** names, int* lengths,
+ int* cp_indices, unsigned int* hashValues, TRAPS) {
+ bool c_heap = !loader_data->is_the_null_class_loader_data();
+ for (int i = 0; i < names_count; i++) {
+ const char *name = names[i];
+ int len = lengths[i];
+ unsigned int hash = hashValues[i];
+ Symbol* sym = SymbolTable::the_table()->lookup_common(name, len, hash);
+ if (sym == NULL) {
+ sym = SymbolTable::the_table()->do_add_if_needed(name, len, hash, c_heap, CHECK);
+ }
+ assert(sym->refcount() != 0, "lookup should have incremented the count");
+ cp->symbol_at_put(cp_indices[i], sym);
+ }
+}
+
+class SymbolTableCreateEntry : public StackObj {
+private:
+ Thread* _thread;
+ const char* _name;
+ int _len;
+ bool _heap;
+ Symbol* _return;
+ Symbol* _created;
+
+ void assert_for_name(Symbol* sym, const char* where) const {
+#ifdef ASSERT
+ assert(sym->utf8_length() == _len, "%s [%d,%d]", where, sym->utf8_length(), _len);
+ for (int i = 0; i < _len; i++) {
+ assert(sym->byte_at(i) == (jbyte) _name[i],
+ "%s [%d,%d,%d]", where, i, sym->byte_at(i), _name[i]);
+ }
+#endif
+ }
+
+public:
+ SymbolTableCreateEntry(Thread* thread, const char* name, int len, bool heap)
+ : _thread(thread), _name(name) , _len(len), _heap(heap), _return(NULL) , _created(NULL) {
+ assert(_name != NULL, "expected valid name");
+ }
+ Symbol* operator()() {
+ _created = SymbolTable::the_table()->allocate_symbol(_name, _len, _heap, _thread);
+ assert(_created != NULL, "expected created symbol");
+ assert_for_name(_created, "operator()()");
+ assert(_created->equals(_name, _len),
+ "symbol must be properly initialized [%p,%d,%d]", _name, _len, (int)_heap);
+ return _created;
+ }
+ void operator()(bool inserted, Symbol** value) {
+ assert(value != NULL, "expected valid value");
+ assert(*value != NULL, "value should point to a symbol");
+ if (!inserted && (_created != NULL)) {
+ // We created our symbol, but someone else inserted
+ // theirs first, so ours will be destroyed.
+ // Since symbols are created with refcount of 1,
+ // we must decrement it here to 0 to delete,
+ // unless it's a permanent one.
+ if (_created->refcount() != PERM_REFCOUNT) {
+ assert(_created->refcount() == 1, "expected newly created symbol");
+ _created->decrement_refcount();
+ assert(_created->refcount() == 0, "expected dead symbol");
+ }
+ }
+ _return = *value;
+ assert_for_name(_return, "operator()");
+ }
+ Symbol* get_new_sym() const {
+ assert_for_name(_return, "get_new_sym");
+ return _return;
+ }
+};
- SymbolTable* table = the_table();
- bool added = table->basic_add(loader_data, cp, names_count, names, lengths,
- cp_indices, hashValues, CHECK);
- if (!added) {
- // do it the hard way
- for (int i=0; i<names_count; i++) {
- int index = table->hash_to_index(hashValues[i]);
- bool c_heap = !loader_data->is_the_null_class_loader_data();
- Symbol* sym = table->basic_add(index, (u1*)names[i], lengths[i], hashValues[i], c_heap, CHECK);
- cp->symbol_at_put(cp_indices[i], sym);
+Symbol* SymbolTable::do_add_if_needed(const char* name, int len, uintx hash, bool heap, TRAPS) {
+ SymbolTableLookup lookup(THREAD, name, len, hash);
+ SymbolTableCreateEntry stce(THREAD, name, len, heap);
+ bool rehash_warning = false;
+ bool clean_hint = false;
+ _local_table->get_insert_lazy(THREAD, lookup, stce, stce, &rehash_warning, &clean_hint);
+ if (rehash_warning) {
+ _needs_rehashing = true;
+ }
+ if (clean_hint) {
+ // we just found out that there is a dead item,
+ // which we were unable to clean right now,
+ // but we have no way of telling whether it's
+ // been previously counted or not, so mark
+ // it only if no other items were found yet
+ mark_item_clean_count();
+ check_concurrent_work();
+ }
+ Symbol* sym = stce.get_new_sym();
+ assert(sym->refcount() != 0, "zero is invalid");
+ return sym;
+}
+
+Symbol* SymbolTable::new_permanent_symbol(const char* name, TRAPS) {
+ unsigned int hash = 0;
+ int len = (int)strlen(name);
+ Symbol* sym = SymbolTable::lookup_only(name, len, hash);
+ if (sym == NULL) {
+ sym = SymbolTable::the_table()->do_add_if_needed(name, len, hash, false, CHECK_NULL);
+ }
+ if (sym->refcount() != PERM_REFCOUNT) {
+ sym->increment_refcount();
+ log_trace_symboltable_helper(sym, "Asked for a permanent symbol, but got a regular one");
+ }
+ return sym;
+}
+
+struct SizeFunc : StackObj {
+ size_t operator()(Symbol** value) {
+ assert(value != NULL, "expected valid value");
+ assert(*value != NULL, "value should point to a symbol");
+ return (*value)->size() * HeapWordSize;
+ };
+};
+
+void SymbolTable::print_table_statistics(outputStream* st,
+ const char* table_name) {
+ SizeFunc sz;
+ _local_table->statistics_to(Thread::current(), sz, st, table_name);
+}
+
+// Verification
+class VerifySymbols : StackObj {
+public:
+ bool operator()(Symbol** value) {
+ guarantee(value != NULL, "expected valid value");
+ guarantee(*value != NULL, "value should point to a symbol");
+ Symbol* sym = *value;
+ guarantee(sym->equals((const char*)sym->bytes(), sym->utf8_length()),
+ "symbol must be internally consistent");
+ return true;
+ };
+};
+
+void SymbolTable::verify() {
+ Thread* thr = Thread::current();
+ VerifySymbols vs;
+ if (!SymbolTable::the_table()->_local_table->try_scan(thr, vs)) {
+ log_info(stringtable)("verify unavailable at this moment");
+ }
+}
+
+// Dumping
+class DumpSymbol : StackObj {
+ Thread* _thr;
+ outputStream* _st;
+public:
+ DumpSymbol(Thread* thr, outputStream* st) : _thr(thr), _st(st) {}
+ bool operator()(Symbol** value) {
+ assert(value != NULL, "expected valid value");
+ assert(*value != NULL, "value should point to a symbol");
+ Symbol* sym = *value;
+ const char* utf8_string = (const char*)sym->bytes();
+ int utf8_length = sym->utf8_length();
+ _st->print("%d %d: ", utf8_length, sym->refcount());
+ HashtableTextDump::put_utf8(_st, utf8_string, utf8_length);
+ _st->cr();
+ return true;
+ };
+};
+
+void SymbolTable::dump(outputStream* st, bool verbose) {
+ if (!verbose) {
+ SymbolTable::the_table()->print_table_statistics(st, "SymbolTable");
+ } else {
+ Thread* thr = Thread::current();
+ ResourceMark rm(thr);
+ st->print_cr("VERSION: 1.1");
+ DumpSymbol ds(thr, st);
+ if (!SymbolTable::the_table()->_local_table->try_scan(thr, ds)) {
+ log_info(symboltable)("dump unavailable at this moment");
}
}
}
-Symbol* SymbolTable::new_permanent_symbol(const char* name, TRAPS) {
- unsigned int hash;
- Symbol* result = SymbolTable::lookup_only((char*)name, (int)strlen(name), hash);
- if (result != NULL) {
- return result;
- }
- // Grab SymbolTable_lock first.
- MutexLocker ml(SymbolTable_lock, THREAD);
-
- SymbolTable* table = the_table();
- int index = table->hash_to_index(hash);
- return table->basic_add(index, (u1*)name, (int)strlen(name), hash, false, THREAD);
-}
-
-Symbol* SymbolTable::basic_add(int index_arg, u1 *name, int len,
- unsigned int hashValue_arg, bool c_heap, TRAPS) {
- assert(!Universe::heap()->is_in_reserved(name),
- "proposed name of symbol must be stable");
-
- // Don't allow symbols to be created which cannot fit in a Symbol*.
- if (len > Symbol::max_length()) {
- THROW_MSG_0(vmSymbols::java_lang_InternalError(),
- "name is too long to represent");
- }
-
- // Cannot hit a safepoint in this function because the "this" pointer can move.
- NoSafepointVerifier nsv;
-
- // Check if the symbol table has been rehashed, if so, need to recalculate
- // the hash value and index.
- unsigned int hashValue;
- int index;
- if (use_alternate_hashcode()) {
- hashValue = hash_symbol((const char*)name, len);
- index = hash_to_index(hashValue);
- } else {
- hashValue = hashValue_arg;
- index = index_arg;
- }
-
- // Since look-up was done lock-free, we need to check if another
- // thread beat us in the race to insert the symbol.
- Symbol* test = lookup(index, (char*)name, len, hashValue);
- if (test != NULL) {
- // A race occurred and another thread introduced the symbol.
- assert(test->refcount() != 0, "lookup should have incremented the count");
- return test;
- }
-
- // Create a new symbol.
- Symbol* sym = allocate_symbol(name, len, c_heap, CHECK_NULL);
- assert(sym->equals((char*)name, len), "symbol must be properly initialized");
-
- HashtableEntry<Symbol*, mtSymbol>* entry = new_entry(hashValue, sym);
- add_entry(index, entry);
- return sym;
-}
-
-// This version of basic_add adds symbols in batch from the constant pool
-// parsing.
-bool SymbolTable::basic_add(ClassLoaderData* loader_data, const constantPoolHandle& cp,
- int names_count,
- const char** names, int* lengths,
- int* cp_indices, unsigned int* hashValues,
- TRAPS) {
+#if INCLUDE_CDS
+struct CopyToArchive : StackObj {
+ CompactSymbolTableWriter* _writer;
+ CopyToArchive(CompactSymbolTableWriter* writer) : _writer(writer) {}
+ bool operator()(Symbol** value) {
+ assert(value != NULL, "expected valid value");
+ assert(*value != NULL, "value should point to a symbol");
+ Symbol* sym = *value;
+ unsigned int fixed_hash = hash_shared_symbol((const char*)sym->bytes(), sym->utf8_length());
+ if (fixed_hash == 0) {
+ return true;
+ }
+ assert(fixed_hash == hash_symbol((const char*)sym->bytes(), sym->utf8_length(), false),
+ "must not rehash during dumping");
- // Check symbol names are not too long. If any are too long, don't add any.
- for (int i = 0; i< names_count; i++) {
- if (lengths[i] > Symbol::max_length()) {
- THROW_MSG_0(vmSymbols::java_lang_InternalError(),
- "name is too long to represent");
- }
- }
-
- // Cannot hit a safepoint in this function because the "this" pointer can move.
- NoSafepointVerifier nsv;
+ // add to the compact table
+ _writer->add(fixed_hash, sym);
- for (int i=0; i<names_count; i++) {
- // Check if the symbol table has been rehashed, if so, need to recalculate
- // the hash value.
- unsigned int hashValue;
- if (use_alternate_hashcode()) {
- hashValue = hash_symbol(names[i], lengths[i]);
- } else {
- hashValue = hashValues[i];
- }
- // Since look-up was done lock-free, we need to check if another
- // thread beat us in the race to insert the symbol.
- int index = hash_to_index(hashValue);
- Symbol* test = lookup(index, names[i], lengths[i], hashValue);
- if (test != NULL) {
- // A race occurred and another thread introduced the symbol, this one
- // will be dropped and collected. Use test instead.
- cp->symbol_at_put(cp_indices[i], test);
- assert(test->refcount() != 0, "lookup should have incremented the count");
- } else {
- // Create a new symbol. The null class loader is never unloaded so these
- // are allocated specially in a permanent arena.
- bool c_heap = !loader_data->is_the_null_class_loader_data();
- Symbol* sym = allocate_symbol((const u1*)names[i], lengths[i], c_heap, CHECK_(false));
- assert(sym->equals(names[i], lengths[i]), "symbol must be properly initialized"); // why wouldn't it be???
- HashtableEntry<Symbol*, mtSymbol>* entry = new_entry(hashValue, sym);
- add_entry(index, entry);
- cp->symbol_at_put(cp_indices[i], sym);
- }
+ return true;
}
- return true;
-}
+};
-
-void SymbolTable::verify() {
- for (int i = 0; i < the_table()->table_size(); ++i) {
- HashtableEntry<Symbol*, mtSymbol>* p = the_table()->bucket(i);
- for ( ; p != NULL; p = p->next()) {
- Symbol* s = (Symbol*)(p->literal());
- guarantee(s != NULL, "symbol is NULL");
- unsigned int h = hash_symbol((char*)s->bytes(), s->utf8_length());
- guarantee(p->hash() == h, "broken hash in symbol table entry");
- guarantee(the_table()->hash_to_index(h) == i,
- "wrong index in symbol table");
- }
- }
-}
-
-void SymbolTable::dump(outputStream* st, bool verbose) {
- if (!verbose) {
- the_table()->print_table_statistics(st, "SymbolTable");
- } else {
- st->print_cr("VERSION: 1.0");
- for (int i = 0; i < the_table()->table_size(); ++i) {
- HashtableEntry<Symbol*, mtSymbol>* p = the_table()->bucket(i);
- for ( ; p != NULL; p = p->next()) {
- Symbol* s = (Symbol*)(p->literal());
- const char* utf8_string = (const char*)s->bytes();
- int utf8_length = s->utf8_length();
- st->print("%d %d: ", utf8_length, s->refcount());
- HashtableTextDump::put_utf8(st, utf8_string, utf8_length);
- st->cr();
- }
- }
- }
+void SymbolTable::copy_shared_symbol_table(CompactSymbolTableWriter* writer) {
+ CopyToArchive copy(writer);
+ SymbolTable::the_table()->_local_table->do_scan(Thread::current(), copy);
}
void SymbolTable::write_to_archive() {
-#if INCLUDE_CDS
- _shared_table.reset();
+ _shared_table.reset();
- int num_buckets = the_table()->number_of_entries() /
- SharedSymbolTableBucketSize;
- CompactSymbolTableWriter writer(num_buckets,
- &MetaspaceShared::stats()->symbol);
- for (int i = 0; i < the_table()->table_size(); ++i) {
- HashtableEntry<Symbol*, mtSymbol>* p = the_table()->bucket(i);
- for ( ; p != NULL; p = p->next()) {
- Symbol* s = (Symbol*)(p->literal());
- unsigned int fixed_hash = hash_shared_symbol((char*)s->bytes(), s->utf8_length());
- assert(fixed_hash == p->hash(), "must not rehash during dumping");
- writer.add(fixed_hash, s);
- }
- }
+ int num_buckets = (int)(SymbolTable::the_table()->_items_count / SharedSymbolTableBucketSize);
+ // calculation of num_buckets can result in zero buckets, we need at least one
+ CompactSymbolTableWriter writer(num_buckets > 1 ? num_buckets : 1,
+ &MetaspaceShared::stats()->symbol);
+ copy_shared_symbol_table(&writer);
+ writer.dump(&_shared_table);
- writer.dump(&_shared_table);
-
- // Verify table is correct
- Symbol* sym = vmSymbols::java_lang_Object();
- const char* name = (const char*)sym->bytes();
- int len = sym->utf8_length();
- unsigned int hash = hash_symbol(name, len);
- assert(sym == _shared_table.lookup(name, hash, len), "sanity");
-#endif
+ // Verify table is correct
+ Symbol* sym = vmSymbols::java_lang_Object();
+ const char* name = (const char*)sym->bytes();
+ int len = sym->utf8_length();
+ unsigned int hash = hash_symbol(name, len, SymbolTable::_alt_hash);
+ assert(sym == _shared_table.lookup(name, hash, len), "sanity");
}
void SymbolTable::serialize(SerializeClosure* soc) {
-#if INCLUDE_CDS
_shared_table.set_type(CompactHashtable<Symbol*, char>::_symbol_table);
_shared_table.serialize(soc);
@@ -626,7 +649,201 @@
// Sanity. Make sure we don't use the shared table at dump time
_shared_table.reset();
}
-#endif
+}
+#endif //INCLUDE_CDS
+
+// Concurrent work
+void SymbolTable::grow(JavaThread* jt) {
+ SymbolTableHash::GrowTask gt(_local_table);
+ if (!gt.prepare(jt)) {
+ return;
+ }
+ log_trace(symboltable)("Started to grow");
+ {
+ TraceTime timer("Grow", TRACETIME_LOG(Debug, symboltable, perf));
+ while (gt.do_task(jt)) {
+ gt.pause(jt);
+ {
+ ThreadBlockInVM tbivm(jt);
+ }
+ gt.cont(jt);
+ }
+ }
+ gt.done(jt);
+ _current_size = table_size();
+ log_debug(symboltable)("Grown to size:" SIZE_FORMAT, _current_size);
+}
+
+struct SymbolTableDoDelete : StackObj {
+ int _deleted;
+ SymbolTableDoDelete() : _deleted(0) {}
+ void operator()(Symbol** value) {
+ assert(value != NULL, "expected valid value");
+ assert(*value != NULL, "value should point to a symbol");
+ Symbol *sym = *value;
+ assert(sym->refcount() == 0, "refcount");
+ _deleted++;
+ }
+};
+
+struct SymbolTableDeleteCheck : StackObj {
+ int _processed;
+ SymbolTableDeleteCheck() : _processed(0) {}
+ bool operator()(Symbol** value) {
+ assert(value != NULL, "expected valid value");
+ assert(*value != NULL, "value should point to a symbol");
+ _processed++;
+ Symbol *sym = *value;
+ return (sym->refcount() == 0);
+ }
+};
+
+void SymbolTable::clean_dead_entries(JavaThread* jt) {
+ SymbolTableHash::BulkDeleteTask bdt(_local_table);
+ if (!bdt.prepare(jt)) {
+ return;
+ }
+
+ SymbolTableDeleteCheck stdc;
+ SymbolTableDoDelete stdd;
+ {
+ TraceTime timer("Clean", TRACETIME_LOG(Debug, symboltable, perf));
+ while (bdt.do_task(jt, stdc, stdd)) {
+ bdt.pause(jt);
+ {
+ ThreadBlockInVM tbivm(jt);
+ }
+ bdt.cont(jt);
+ }
+ SymbolTable::the_table()->set_item_clean_count(0);
+ bdt.done(jt);
+ }
+
+ Atomic::add((size_t)stdc._processed, &_symbols_counted);
+
+ log_debug(symboltable)("Cleaned " INT32_FORMAT " of " INT32_FORMAT,
+ stdd._deleted, stdc._processed);
+}
+
+void SymbolTable::check_concurrent_work() {
+ if (_has_work) {
+ return;
+ }
+ double load_factor = SymbolTable::get_load_factor();
+ double dead_factor = SymbolTable::get_dead_factor();
+ // We should clean/resize if we have more dead than alive,
+ // more items than preferred load factor or
+ // more dead items than water mark.
+ if ((dead_factor > load_factor) ||
+ (load_factor > PREF_AVG_LIST_LEN) ||
+ (dead_factor > CLEAN_DEAD_HIGH_WATER_MARK)) {
+ log_debug(symboltable)("Concurrent work triggered, live factor:%f dead factor:%f",
+ load_factor, dead_factor);
+ trigger_concurrent_work();
+ }
+}
+
+void SymbolTable::concurrent_work(JavaThread* jt) {
+ double load_factor = get_load_factor();
+ log_debug(symboltable, perf)("Concurrent work, live factor: %g", load_factor);
+ // We prefer growing, since that also removes dead items
+ if (load_factor > PREF_AVG_LIST_LEN && !_local_table->is_max_size_reached()) {
+ grow(jt);
+ } else {
+ clean_dead_entries(jt);
+ }
+ _has_work = false;
+}
+
+class CountDead : StackObj {
+ int _count;
+public:
+ CountDead() : _count(0) {}
+ bool operator()(Symbol** value) {
+ assert(value != NULL, "expected valid value");
+ assert(*value != NULL, "value should point to a symbol");
+ Symbol* sym = *value;
+ if (sym->refcount() == 0) {
+ _count++;
+ }
+ return true;
+ };
+ int get_dead_count() {
+ return _count;
+ }
+};
+
+void SymbolTable::do_check_concurrent_work() {
+ CountDead counter;
+ if (!SymbolTable::the_table()->_local_table->try_scan(Thread::current(), counter)) {
+ log_info(symboltable)("count dead unavailable at this moment");
+ } else {
+ SymbolTable::the_table()->set_item_clean_count(counter.get_dead_count());
+ SymbolTable::the_table()->check_concurrent_work();
+ }
+}
+
+void SymbolTable::do_concurrent_work(JavaThread* jt) {
+ SymbolTable::the_table()->concurrent_work(jt);
+}
+
+// Rehash
+bool SymbolTable::do_rehash() {
+ if (!_local_table->is_safepoint_safe()) {
+ return false;
+ }
+
+ // We use max size
+ SymbolTableHash* new_table = new SymbolTableHash(END_SIZE, END_SIZE, REHASH_LEN);
+ // Use alt hash from now on
+ _alt_hash = true;
+ if (!_local_table->try_move_nodes_to(Thread::current(), new_table)) {
+ _alt_hash = false;
+ delete new_table;
+ return false;
+ }
+
+ // free old table
+ delete _local_table;
+ _local_table = new_table;
+
+ return true;
+}
+
+void SymbolTable::try_rehash_table() {
+ static bool rehashed = false;
+ log_debug(symboltable)("Table imbalanced, rehashing called.");
+
+ // Grow instead of rehash.
+ if (get_load_factor() > PREF_AVG_LIST_LEN &&
+ !_local_table->is_max_size_reached()) {
+ log_debug(symboltable)("Choosing growing over rehashing.");
+ trigger_concurrent_work();
+ _needs_rehashing = false;
+ return;
+ }
+
+ // Already rehashed.
+ if (rehashed) {
+ log_warning(symboltable)("Rehashing already done, still long lists.");
+ trigger_concurrent_work();
+ _needs_rehashing = false;
+ return;
+ }
+
+ murmur_seed = AltHashing::compute_seed();
+
+ if (do_rehash()) {
+ rehashed = true;
+ } else {
+ log_info(symboltable)("Resizes in progress rehashing skipped.");
+ }
+
+ _needs_rehashing = false;
+}
+
+void SymbolTable::rehash_table() {
+ SymbolTable::the_table()->try_rehash_table();
}
//---------------------------------------------------------------------------
@@ -634,89 +851,80 @@
#ifndef PRODUCT
-void SymbolTable::print_histogram() {
- MutexLocker ml(SymbolTable_lock);
- const int results_length = 100;
- int counts[results_length];
- int sizes[results_length];
- int i,j;
-
- // initialize results to zero
- for (j = 0; j < results_length; j++) {
- counts[j] = 0;
- sizes[j] = 0;
- }
-
- int total_size = 0;
- int total_count = 0;
- int total_length = 0;
- int max_length = 0;
- int out_of_range_count = 0;
- int out_of_range_size = 0;
- for (i = 0; i < the_table()->table_size(); i++) {
- HashtableEntry<Symbol*, mtSymbol>* p = the_table()->bucket(i);
- for ( ; p != NULL; p = p->next()) {
- int size = p->literal()->size();
- int len = p->literal()->utf8_length();
- if (len < results_length) {
- counts[len]++;
- sizes[len] += size;
- } else {
- out_of_range_count++;
- out_of_range_size += size;
- }
- total_count++;
- total_size += size;
- total_length += len;
- max_length = MAX2(max_length, len);
+class HistogramIterator : StackObj {
+public:
+ static const size_t results_length = 100;
+ size_t counts[results_length];
+ size_t sizes[results_length];
+ size_t total_size;
+ size_t total_count;
+ size_t total_length;
+ size_t max_length;
+ size_t out_of_range_count;
+ size_t out_of_range_size;
+ HistogramIterator() : total_size(0), total_count(0), total_length(0),
+ max_length(0), out_of_range_count(0), out_of_range_size(0) {
+ // initialize results to zero
+ for (size_t i = 0; i < results_length; i++) {
+ counts[i] = 0;
+ sizes[i] = 0;
}
}
+ bool operator()(Symbol** value) {
+ assert(value != NULL, "expected valid value");
+ assert(*value != NULL, "value should point to a symbol");
+ Symbol* sym = *value;
+ size_t size = sym->size();
+ size_t len = sym->utf8_length();
+ if (len < results_length) {
+ counts[len]++;
+ sizes[len] += size;
+ } else {
+ out_of_range_count++;
+ out_of_range_size += size;
+ }
+ total_count++;
+ total_size += size;
+ total_length += len;
+ max_length = MAX2(max_length, len);
+
+ return true;
+ };
+};
+
+void SymbolTable::print_histogram() {
+ SymbolTable* st = SymbolTable::the_table();
+ HistogramIterator hi;
+ st->_local_table->do_scan(Thread::current(), hi);
tty->print_cr("Symbol Table Histogram:");
- tty->print_cr(" Total number of symbols %7d", total_count);
- tty->print_cr(" Total size in memory %7dK",
- (total_size*wordSize)/1024);
- tty->print_cr(" Total counted %7d", _symbols_counted);
- tty->print_cr(" Total removed %7d", _symbols_removed);
- if (_symbols_counted > 0) {
+ tty->print_cr(" Total number of symbols " SIZE_FORMAT_W(7), hi.total_count);
+ tty->print_cr(" Total size in memory " SIZE_FORMAT_W(7) "K",
+ (hi.total_size * wordSize) / 1024);
+ tty->print_cr(" Total counted " SIZE_FORMAT_W(7), st->_symbols_counted);
+ tty->print_cr(" Total removed " SIZE_FORMAT_W(7), st->_symbols_removed);
+ if (SymbolTable::the_table()->_symbols_counted > 0) {
tty->print_cr(" Percent removed %3.2f",
- ((float)_symbols_removed/(float)_symbols_counted)* 100);
+ ((float)st->_symbols_removed / st->_symbols_counted) * 100);
}
- tty->print_cr(" Reference counts %7d", Symbol::_total_count);
- tty->print_cr(" Symbol arena used " SIZE_FORMAT_W(7) "K", arena()->used()/1024);
- tty->print_cr(" Symbol arena size " SIZE_FORMAT_W(7) "K", arena()->size_in_bytes()/1024);
- tty->print_cr(" Total symbol length %7d", total_length);
- tty->print_cr(" Maximum symbol length %7d", max_length);
- tty->print_cr(" Average symbol length %7.2f", ((float) total_length / (float) total_count));
+ tty->print_cr(" Reference counts " SIZE_FORMAT_W(7), Symbol::_total_count);
+ tty->print_cr(" Symbol arena used " SIZE_FORMAT_W(7) "K", arena()->used() / 1024);
+ tty->print_cr(" Symbol arena size " SIZE_FORMAT_W(7) "K", arena()->size_in_bytes() / 1024);
+ tty->print_cr(" Total symbol length " SIZE_FORMAT_W(7), hi.total_length);
+ tty->print_cr(" Maximum symbol length " SIZE_FORMAT_W(7), hi.max_length);
+ tty->print_cr(" Average symbol length %7.2f", ((float)hi.total_length / hi.total_count));
tty->print_cr(" Symbol length histogram:");
tty->print_cr(" %6s %10s %10s", "Length", "#Symbols", "Size");
- for (i = 0; i < results_length; i++) {
- if (counts[i] > 0) {
- tty->print_cr(" %6d %10d %10dK", i, counts[i], (sizes[i]*wordSize)/1024);
+ for (size_t i = 0; i < hi.results_length; i++) {
+ if (hi.counts[i] > 0) {
+ tty->print_cr(" " SIZE_FORMAT_W(6) " " SIZE_FORMAT_W(10) " " SIZE_FORMAT_W(10) "K",
+ i, hi.counts[i], (hi.sizes[i] * wordSize) / 1024);
}
}
- tty->print_cr(" >=%6d %10d %10dK\n", results_length,
- out_of_range_count, (out_of_range_size*wordSize)/1024);
-}
-
-void SymbolTable::print() {
- for (int i = 0; i < the_table()->table_size(); ++i) {
- HashtableEntry<Symbol*, mtSymbol>** p = the_table()->bucket_addr(i);
- HashtableEntry<Symbol*, mtSymbol>* entry = the_table()->bucket(i);
- if (entry != NULL) {
- while (entry != NULL) {
- tty->print(PTR_FORMAT " ", p2i(entry->literal()));
- entry->literal()->print();
- tty->print(" %d", entry->literal()->refcount());
- p = entry->next_addr();
- entry = (HashtableEntry<Symbol*, mtSymbol>*)HashtableEntry<Symbol*, mtSymbol>::make_ptr(*p);
- }
- tty->cr();
- }
- }
+ tty->print_cr(" >=" SIZE_FORMAT_W(6) " " SIZE_FORMAT_W(10) " " SIZE_FORMAT_W(10) "K\n",
+ hi.results_length, hi.out_of_range_count, (hi.out_of_range_size*wordSize) / 1024);
}
#endif // PRODUCT
-
// Utility for dumping symbols
SymboltableDCmd::SymboltableDCmd(outputStream* output, bool heap) :
DCmdWithParser(output, heap),
--- a/src/hotspot/share/classfile/symbolTable.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/classfile/symbolTable.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,23 +26,11 @@
#define SHARE_VM_CLASSFILE_SYMBOLTABLE_HPP
#include "memory/allocation.hpp"
+#include "memory/padded.hpp"
#include "oops/symbol.hpp"
+#include "utilities/concurrentHashTable.hpp"
#include "utilities/hashtable.hpp"
-// The symbol table holds all Symbol*s and corresponding interned strings.
-// Symbol*s and literal strings should be canonicalized.
-//
-// The interned strings are created lazily.
-//
-// It is implemented as an open hash table with a fixed number of buckets.
-//
-// %note:
-// - symbolTableEntrys are allocated in blocks to reduce the space overhead.
-
-class BoolObjectClosure;
-class outputStream;
-class SerializeClosure;
-
// TempNewSymbol acts as a handle class in a handle/body idiom and is
// responsible for proper resource management of the body (which is a Symbol*).
// The body is resource managed by a reference counting scheme.
@@ -59,7 +47,7 @@
class TempNewSymbol : public StackObj {
Symbol* _temp;
- public:
+public:
TempNewSymbol() : _temp(NULL) {}
// Conversion from a Symbol* to a TempNewSymbol.
@@ -97,35 +85,69 @@
};
template <class T, class N> class CompactHashtable;
+class CompactSymbolTableWriter;
+class SerializeClosure;
-class SymbolTable : public RehashableHashtable<Symbol*, mtSymbol> {
+class SymbolTableConfig;
+typedef ConcurrentHashTable<Symbol*,
+ SymbolTableConfig, mtSymbol> SymbolTableHash;
+
+class SymbolTableCreateEntry;
+
+class SymbolTable : public CHeapObj<mtSymbol> {
friend class VMStructs;
+ friend class Symbol;
friend class ClassFileParser;
+ friend class SymbolTableConfig;
+ friend class SymbolTableCreateEntry;
private:
+ static void delete_symbol(Symbol* sym);
+ void grow(JavaThread* jt);
+ void clean_dead_entries(JavaThread* jt);
+
// The symbol table
static SymbolTable* _the_table;
-
- // Set if one bucket is out of balance due to hash algorithm deficiency
- static bool _needs_rehashing;
- static bool _lookup_shared_first;
+ // Shared symbol table.
+ static CompactHashtable<Symbol*, char> _shared_table;
+ static volatile bool _lookup_shared_first;
+ static volatile bool _alt_hash;
// For statistics
- static int _symbols_removed;
- static int _symbols_counted;
+ volatile size_t _symbols_removed;
+ volatile size_t _symbols_counted;
+
+ SymbolTableHash* _local_table;
+ size_t _current_size;
+ volatile bool _has_work;
+ // Set if one bucket is out of balance due to hash algorithm deficiency
+ volatile bool _needs_rehashing;
+
+ volatile size_t _items_count;
+ volatile size_t _uncleaned_items_count;
- // shared symbol table.
- static CompactHashtable<Symbol*, char> _shared_table;
+ double get_load_factor();
+ double get_dead_factor();
+
+ void check_concurrent_work();
+ void trigger_concurrent_work();
- Symbol* allocate_symbol(const u1* name, int len, bool c_heap, TRAPS); // Assumes no characters larger than 0x7F
+ static void item_added();
+ static void item_removed();
+ static void set_item_clean_count(size_t ncl);
+ static void mark_item_clean_count();
+
+ SymbolTable();
+
+ Symbol* allocate_symbol(const char* name, int len, bool c_heap, TRAPS); // Assumes no characters larger than 0x7F
+ Symbol* do_lookup(const char* name, int len, uintx hash);
+ Symbol* do_add_if_needed(const char* name, int len, uintx hash, bool heap, TRAPS);
// Adding elements
- Symbol* basic_add(int index, u1* name, int len, unsigned int hashValue,
- bool c_heap, TRAPS);
- bool basic_add(ClassLoaderData* loader_data,
- const constantPoolHandle& cp, int names_count,
- const char** names, int* lengths, int* cp_indices,
- unsigned int* hashValues, TRAPS);
+ static void add(ClassLoaderData* loader_data,
+ const constantPoolHandle& cp, int names_count,
+ const char** names, int* lengths, int* cp_indices,
+ unsigned int* hashValues, TRAPS);
static void new_symbols(ClassLoaderData* loader_data,
const constantPoolHandle& cp, int names_count,
@@ -136,15 +158,8 @@
}
static Symbol* lookup_shared(const char* name, int len, unsigned int hash);
- Symbol* lookup_dynamic(int index, const char* name, int len, unsigned int hash);
- Symbol* lookup(int index, const char* name, int len, unsigned int hash);
-
- SymbolTable()
- : RehashableHashtable<Symbol*, mtSymbol>(SymbolTableSize, sizeof (HashtableEntry<Symbol*, mtSymbol>)) {}
-
- SymbolTable(HashtableBucket<mtSymbol>* t, int number_of_entries)
- : RehashableHashtable<Symbol*, mtSymbol>(SymbolTableSize, sizeof (HashtableEntry<Symbol*, mtSymbol>), t,
- number_of_entries) {}
+ Symbol* lookup_dynamic(const char* name, int len, unsigned int hash);
+ Symbol* lookup_common(const char* name, int len, unsigned int hash);
// Arena for permanent symbols (null class loader) that are never unloaded
static Arena* _arena;
@@ -152,88 +167,45 @@
static void initialize_symbols(int arena_alloc_size = 0);
- static volatile int _parallel_claimed_idx;
+ void concurrent_work(JavaThread* jt);
+ void print_table_statistics(outputStream* st, const char* table_name);
+
+ void try_rehash_table();
+ bool do_rehash();
- typedef SymbolTable::BucketUnlinkContext BucketUnlinkContext;
- // Release any dead symbols. Unlinked bucket entries are collected in the given
- // context to be freed later.
- // This allows multiple threads to work on the table at once.
- static void buckets_unlink(int start_idx, int end_idx, BucketUnlinkContext* context);
public:
+ // The symbol table
+ static SymbolTable* the_table() { return _the_table; }
+ size_t table_size();
+
enum {
symbol_alloc_batch_size = 8,
// Pick initial size based on java -version size measurements
- symbol_alloc_arena_size = 360*K
+ symbol_alloc_arena_size = 360*K // TODO (revisit)
};
- // The symbol table
- static SymbolTable* the_table() { return _the_table; }
-
- // Size of one bucket in the string table. Used when checking for rollover.
- static uint bucket_size() { return sizeof(HashtableBucket<mtSymbol>); }
-
static void create_table() {
assert(_the_table == NULL, "One symbol table allowed.");
_the_table = new SymbolTable();
initialize_symbols(symbol_alloc_arena_size);
}
- static unsigned int hash_symbol(const char* s, int len);
- static unsigned int hash_shared_symbol(const char* s, int len);
+ static void unlink() {
+ do_check_concurrent_work();
+ }
+ static void do_check_concurrent_work();
+ static void do_concurrent_work(JavaThread* jt);
+ static bool has_work() { return the_table()->_has_work; }
+ // Probing
static Symbol* lookup(const char* name, int len, TRAPS);
// lookup only, won't add. Also calculate hash.
static Symbol* lookup_only(const char* name, int len, unsigned int& hash);
- // Only copy to C string to be added if lookup failed.
+ // adds new symbol if not found
static Symbol* lookup(const Symbol* sym, int begin, int end, TRAPS);
-
- static void release(Symbol* sym);
-
- // Look up the address of the literal in the SymbolTable for this Symbol*
- static Symbol** lookup_symbol_addr(Symbol* sym);
-
// jchar (UTF16) version of lookups
static Symbol* lookup_unicode(const jchar* name, int len, TRAPS);
static Symbol* lookup_only_unicode(const jchar* name, int len, unsigned int& hash);
-
- static void add(ClassLoaderData* loader_data,
- const constantPoolHandle& cp, int names_count,
- const char** names, int* lengths, int* cp_indices,
- unsigned int* hashValues, TRAPS);
-
- // Release any dead symbols
- static void unlink() {
- int processed = 0;
- int removed = 0;
- unlink(&processed, &removed);
- }
- static void unlink(int* processed, int* removed);
- // Release any dead symbols, possibly parallel version
- static void possibly_parallel_unlink(int* processed, int* removed);
-
- // iterate over symbols
- static void symbols_do(SymbolClosure *cl);
- static void metaspace_pointers_do(MetaspaceClosure* it);
-
- // Symbol creation
- static Symbol* new_symbol(const char* utf8_buffer, int length, TRAPS) {
- assert(utf8_buffer != NULL, "just checking");
- return lookup(utf8_buffer, length, THREAD);
- }
- static Symbol* new_symbol(const char* name, TRAPS) {
- return new_symbol(name, (int)strlen(name), THREAD);
- }
- static Symbol* new_symbol(const Symbol* sym, int begin, int end, TRAPS) {
- assert(begin <= end && end <= sym->utf8_length(), "just checking");
- return lookup(sym, begin, end, THREAD);
- }
-
- // Create a symbol in the arena for symbols that are not deleted
- static Symbol* new_permanent_symbol(const char* name, TRAPS);
-
- // Symbol lookup
- static Symbol* lookup(int index, const char* name, int len, TRAPS);
-
// Needed for preloading classes in signatures when compiling.
// Returns the symbol is already present in symbol table, otherwise
// NULL. NO ALLOCATION IS GUARANTEED!
@@ -246,27 +218,45 @@
return lookup_only_unicode(name, len, ignore_hash);
}
- // Histogram
- static void print_histogram() PRODUCT_RETURN;
- static void print() PRODUCT_RETURN;
+ // Symbol creation
+ static Symbol* new_symbol(const char* utf8_buffer, int length, TRAPS) {
+ assert(utf8_buffer != NULL, "just checking");
+ return lookup(utf8_buffer, length, THREAD);
+ }
+ static Symbol* new_symbol(const char* name, TRAPS) {
+ return new_symbol(name, (int)strlen(name), THREAD);
+ }
+ static Symbol* new_symbol(const Symbol* sym, int begin, int end, TRAPS) {
+ assert(begin <= end && end <= sym->utf8_length(), "just checking");
+ return lookup(sym, begin, end, THREAD);
+ }
+ // Create a symbol in the arena for symbols that are not deleted
+ static Symbol* new_permanent_symbol(const char* name, TRAPS);
- // Debugging
- static void verify();
- static void dump(outputStream* st, bool verbose=false);
- static void read(const char* filename, TRAPS);
+ // Rehash the string table if it gets out of balance
+ static void rehash_table();
+ static bool needs_rehashing()
+ { return SymbolTable::the_table()->_needs_rehashing; }
+
+ // Heap dumper and CDS
+ static void symbols_do(SymbolClosure *cl);
// Sharing
- static void write_to_archive();
- static void serialize(SerializeClosure* soc);
- static u4 encode_shared(Symbol* sym);
- static Symbol* decode_shared(u4 offset);
+private:
+ static void copy_shared_symbol_table(CompactSymbolTableWriter* ch_table);
+public:
+ static void write_to_archive() NOT_CDS_RETURN;
+ static void serialize(SerializeClosure* soc) NOT_CDS_RETURN;
+ static void metaspace_pointers_do(MetaspaceClosure* it);
- // Rehash the symbol table if it gets out of balance
- static void rehash_table();
- static bool needs_rehashing() { return _needs_rehashing; }
- // Parallel chunked scanning
- static void clear_parallel_claimed_index() { _parallel_claimed_idx = 0; }
- static int parallel_claimed_index() { return _parallel_claimed_idx; }
+ // Jcmd
+ static void dump(outputStream* st, bool verbose=false);
+ // Debugging
+ static void verify();
+ static void read(const char* filename, TRAPS);
+
+ // Histogram
+ static void print_histogram() PRODUCT_RETURN;
};
#endif // SHARE_VM_CLASSFILE_SYMBOLTABLE_HPP
--- a/src/hotspot/share/classfile/systemDictionary.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/classfile/systemDictionary.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -988,18 +988,18 @@
Handle class_loader,
Handle protection_domain,
ClassFileStream* st,
- const InstanceKlass* host_klass,
+ const InstanceKlass* unsafe_anonymous_host,
GrowableArray<Handle>* cp_patches,
TRAPS) {
EventClassLoad class_load_start_event;
ClassLoaderData* loader_data;
- if (host_klass != NULL) {
- // Create a new CLD for anonymous class, that uses the same class loader
- // as the host_klass
- guarantee(oopDesc::equals(host_klass->class_loader(), class_loader()), "should be the same");
- loader_data = ClassLoaderData::anonymous_class_loader_data(class_loader);
+ if (unsafe_anonymous_host != NULL) {
+ // Create a new CLD for an unsafe anonymous class, that uses the same class loader
+ // as the unsafe_anonymous_host
+ guarantee(oopDesc::equals(unsafe_anonymous_host->class_loader(), class_loader()), "should be the same");
+ loader_data = ClassLoaderData::unsafe_anonymous_class_loader_data(class_loader);
} else {
loader_data = ClassLoaderData::class_loader_data(class_loader());
}
@@ -1016,12 +1016,12 @@
class_name,
loader_data,
protection_domain,
- host_klass,
+ unsafe_anonymous_host,
cp_patches,
CHECK_NULL);
- if (host_klass != NULL && k != NULL) {
- // Anonymous classes must update ClassLoaderData holder (was host_klass loader)
+ if (unsafe_anonymous_host != NULL && k != NULL) {
+ // Unsafe anonymous classes must update ClassLoaderData holder (was unsafe_anonymous_host loader)
// so that they can be unloaded when the mirror is no longer referenced.
k->class_loader_data()->initialize_holder(Handle(THREAD, k->java_mirror()));
@@ -1056,8 +1056,8 @@
post_class_load_event(&class_load_start_event, k, loader_data);
}
}
- assert(host_klass != NULL || NULL == cp_patches,
- "cp_patches only found with host_klass");
+ assert(unsafe_anonymous_host != NULL || NULL == cp_patches,
+ "cp_patches only found with unsafe_anonymous_host");
return k;
}
@@ -1115,7 +1115,7 @@
class_name,
loader_data,
protection_domain,
- NULL, // host_klass
+ NULL, // unsafe_anonymous_host
NULL, // cp_patches
CHECK_NULL);
}
@@ -1858,10 +1858,19 @@
}
}
+ // TODO: just return if !unloading_occurred.
if (unloading_occurred) {
- GCTraceTime(Debug, gc, phases) t("Dictionary", gc_timer);
- constraints()->purge_loader_constraints();
- resolution_errors()->purge_resolution_errors();
+ {
+ GCTraceTime(Debug, gc, phases) t("SymbolTable", gc_timer);
+ // Check if there's work to do in the SymbolTable
+ SymbolTable::do_check_concurrent_work();
+ }
+
+ {
+ GCTraceTime(Debug, gc, phases) t("Dictionary", gc_timer);
+ constraints()->purge_loader_constraints();
+ resolution_errors()->purge_resolution_errors();
+ }
}
{
@@ -1874,7 +1883,7 @@
if (do_cleaning) {
GCTraceTime(Debug, gc, phases) t("ResolvedMethodTable", gc_timer);
- ResolvedMethodTable::unlink();
+ ResolvedMethodTable::trigger_cleanup();
}
return unloading_occurred;
@@ -3001,7 +3010,7 @@
_master_dictionary(master_dictionary) {}
void do_cld(ClassLoaderData* cld) {
ResourceMark rm;
- if (cld->is_anonymous()) {
+ if (cld->is_unsafe_anonymous()) {
return;
}
if (cld->is_system_class_loader_data() || cld->is_platform_class_loader_data()) {
--- a/src/hotspot/share/classfile/systemDictionary.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/classfile/systemDictionary.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -187,11 +187,6 @@
do_klass(jdk_internal_loader_ClassLoaders_AppClassLoader_klass, jdk_internal_loader_ClassLoaders_AppClassLoader, Pre ) \
do_klass(jdk_internal_loader_ClassLoaders_PlatformClassLoader_klass, jdk_internal_loader_ClassLoaders_PlatformClassLoader, Pre ) \
do_klass(CodeSource_klass, java_security_CodeSource, Pre ) \
- do_klass(Configuration_klass, java_lang_module_Configuration, Pre ) \
- do_klass(ImmutableCollections_ListN_klass, java_util_ImmutableCollections_ListN, Pre ) \
- do_klass(ImmutableCollections_MapN_klass, java_util_ImmutableCollections_MapN, Pre ) \
- do_klass(ImmutableCollections_SetN_klass, java_util_ImmutableCollections_SetN, Pre ) \
- do_klass(ArchivedModuleGraph_klass, jdk_internal_module_ArchivedModuleGraph, Pre ) \
\
do_klass(StackTraceElement_klass, java_lang_StackTraceElement, Opt ) \
\
@@ -303,7 +298,7 @@
class_loader,
protection_domain,
st,
- NULL, // host klass
+ NULL, // unsafe_anonymous_host
NULL, // cp_patches
THREAD);
}
@@ -311,7 +306,7 @@
Handle class_loader,
Handle protection_domain,
ClassFileStream* st,
- const InstanceKlass* host_klass,
+ const InstanceKlass* unsafe_anonymous_host,
GrowableArray<Handle>* cp_patches,
TRAPS);
--- a/src/hotspot/share/classfile/systemDictionaryShared.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/classfile/systemDictionaryShared.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -755,11 +755,11 @@
Symbol* from_name, bool from_field_is_protected, bool from_is_array, bool from_is_object) {
assert(DumpSharedSpaces, "called at dump time only");
- // Skip anonymous classes, which are not archived as they are not in
- // dictionary (see assert_no_anonymoys_classes_in_dictionaries() in
+ // Skip unsafe anonymous classes, which are not archived as they are not in
+ // dictionary (see assert_no_unsafe_anonymous_classes_in_dictionaries() in
// VM_PopulateDumpSharedSpace::doit()).
- if (k->class_loader_data()->is_anonymous()) {
- return true; // anonymous classes are not archived, skip
+ if (k->class_loader_data()->is_unsafe_anonymous()) {
+ return true; // unsafe anonymous classes are not archived, skip
}
SharedDictionaryEntry* entry = ((SharedDictionary*)(k->class_loader_data()->dictionary()))->find_entry_for(k);
--- a/src/hotspot/share/classfile/systemDictionaryShared.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/classfile/systemDictionaryShared.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -293,9 +293,6 @@
static void allocate_shared_data_arrays(int size, TRAPS);
static void oops_do(OopClosure* f);
- static void roots_oops_do(OopClosure* f) {
- oops_do(f);
- }
// Check if sharing is supported for the class loader.
static bool is_sharing_possible(ClassLoaderData* loader_data);
--- a/src/hotspot/share/classfile/verifier.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/classfile/verifier.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -2823,20 +2823,20 @@
current_class()->super()->name()))) {
bool subtype = false;
bool have_imr_indirect = cp->tag_at(index).value() == JVM_CONSTANT_InterfaceMethodref;
- if (!current_class()->is_anonymous()) {
+ if (!current_class()->is_unsafe_anonymous()) {
subtype = ref_class_type.is_assignable_from(
current_type(), this, false, CHECK_VERIFY(this));
} else {
- VerificationType host_klass_type =
- VerificationType::reference_type(current_class()->host_klass()->name());
- subtype = ref_class_type.is_assignable_from(host_klass_type, this, false, CHECK_VERIFY(this));
+ VerificationType unsafe_anonymous_host_type =
+ VerificationType::reference_type(current_class()->unsafe_anonymous_host()->name());
+ subtype = ref_class_type.is_assignable_from(unsafe_anonymous_host_type, this, false, CHECK_VERIFY(this));
// If invokespecial of IMR, need to recheck for same or
// direct interface relative to the host class
have_imr_indirect = (have_imr_indirect &&
!is_same_or_direct_interface(
- current_class()->host_klass(),
- host_klass_type, ref_class_type));
+ current_class()->unsafe_anonymous_host(),
+ unsafe_anonymous_host_type, ref_class_type));
}
if (!subtype) {
verify_error(ErrorContext::bad_code(bci),
@@ -2866,15 +2866,15 @@
} else { // other methods
// Ensures that target class is assignable to method class.
if (opcode == Bytecodes::_invokespecial) {
- if (!current_class()->is_anonymous()) {
+ if (!current_class()->is_unsafe_anonymous()) {
current_frame->pop_stack(current_type(), CHECK_VERIFY(this));
} else {
// anonymous class invokespecial calls: check if the
- // objectref is a subtype of the host_klass of the current class
- // to allow an anonymous class to reference methods in the host_klass
+ // objectref is a subtype of the unsafe_anonymous_host of the current class
+ // to allow an anonymous class to reference methods in the unsafe_anonymous_host
VerificationType top = current_frame->pop_stack(CHECK_VERIFY(this));
VerificationType hosttype =
- VerificationType::reference_type(current_class()->host_klass()->name());
+ VerificationType::reference_type(current_class()->unsafe_anonymous_host()->name());
bool subtype = hosttype.is_assignable_from(top, this, false, CHECK_VERIFY(this));
if (!subtype) {
verify_error( ErrorContext::bad_type(current_frame->offset(),
--- a/src/hotspot/share/classfile/vmSymbols.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/classfile/vmSymbols.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -124,7 +124,6 @@
template(getBootClassPathEntryForClass_name, "getBootClassPathEntryForClass") \
template(jdk_internal_vm_PostVMInitHook, "jdk/internal/vm/PostVMInitHook") \
template(sun_net_www_ParseUtil, "sun/net/www/ParseUtil") \
- template(jdk_internal_module_ArchivedModuleGraph, "jdk/internal/module/ArchivedModuleGraph") \
\
template(jdk_internal_loader_ClassLoaders_AppClassLoader, "jdk/internal/loader/ClassLoaders$AppClassLoader") \
template(jdk_internal_loader_ClassLoaders_PlatformClassLoader, "jdk/internal/loader/ClassLoaders$PlatformClassLoader") \
@@ -438,6 +437,7 @@
template(fileToEncodedURL_signature, "(Ljava/io/File;)Ljava/net/URL;") \
template(getProtectionDomain_name, "getProtectionDomain") \
template(getProtectionDomain_signature, "(Ljava/security/CodeSource;)Ljava/security/ProtectionDomain;") \
+ template(java_lang_Integer_array_signature, "[Ljava/lang/Integer;") \
template(url_code_signer_array_void_signature, "(Ljava/net/URL;[Ljava/security/CodeSigner;)V") \
template(module_entry_name, "module_entry") \
template(resolved_references_name, "<resolved_references>") \
@@ -648,17 +648,7 @@
JFR_TEMPLATES(template) \
\
/* cds */ \
- template(configuration_signature, "Ljava/lang/module/Configuration;") \
- template(java_lang_module_Configuration, "java/lang/module/Configuration") \
- template(java_util_ImmutableCollections_ListN, "java/util/ImmutableCollections$ListN") \
- template(java_util_ImmutableCollections_MapN, "java/util/ImmutableCollections$MapN") \
- template(java_util_ImmutableCollections_SetN, "java/util/ImmutableCollections$SetN") \
template(jdk_internal_loader_ClassLoaders, "jdk/internal/loader/ClassLoaders") \
- template(list_signature, "Ljava/util/List;") \
- template(map_signature, "Ljava/util/Map;") \
- template(moduleFinder_signature, "Ljava/lang/module/ModuleFinder;") \
- template(set_signature, "Ljava/util/Set;") \
- template(systemModules_signature, "Ljdk/internal/module/SystemModules;") \
template(toFileURL_name, "toFileURL") \
template(toFileURL_signature, "(Ljava/lang/String;)Ljava/net/URL;") \
template(url_void_signature, "(Ljava/net/URL;)V") \
--- a/src/hotspot/share/code/compiledMethod.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/code/compiledMethod.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -202,7 +202,7 @@
virtual address verified_entry_point() const = 0;
virtual void log_identity(xmlStream* log) const = 0;
- virtual void log_state_change() const = 0;
+ virtual void log_state_change(oop cause = NULL) const = 0;
virtual bool make_not_used() = 0;
virtual bool make_not_entrant() = 0;
virtual bool make_entrant() = 0;
--- a/src/hotspot/share/code/nmethod.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/code/nmethod.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -422,7 +422,7 @@
#if INCLUDE_JVMCI
_jvmci_installed_code = NULL;
_speculation_log = NULL;
- _jvmci_installed_code_triggers_unloading = false;
+ _jvmci_installed_code_triggers_invalidation = false;
#endif
}
@@ -690,9 +690,9 @@
_speculation_log = speculation_log;
oop obj = JNIHandles::resolve(installed_code);
if (obj == NULL || (obj->is_a(HotSpotNmethod::klass()) && HotSpotNmethod::isDefault(obj))) {
- _jvmci_installed_code_triggers_unloading = false;
+ _jvmci_installed_code_triggers_invalidation = false;
} else {
- _jvmci_installed_code_triggers_unloading = true;
+ _jvmci_installed_code_triggers_invalidation = true;
}
if (compiler->is_jvmci()) {
@@ -786,6 +786,13 @@
if (TieredCompilation) {
log->print(" level='%d'", comp_level());
}
+#if INCLUDE_JVMCI
+ char buffer[O_BUFLEN];
+ char* jvmci_name = jvmci_installed_code_name(buffer, O_BUFLEN);
+ if (jvmci_name != NULL) {
+ log->print(" jvmci_installed_code_name='%s'", jvmci_name);
+ }
+#endif
}
@@ -1083,7 +1090,7 @@
_state = unloaded;
// Log the unloading.
- log_state_change();
+ log_state_change(cause);
#if INCLUDE_JVMCI
// The method can only be unloaded after the pointer to the installed code
@@ -1107,7 +1114,7 @@
}
}
-void nmethod::log_state_change() const {
+void nmethod::log_state_change(oop cause) const {
if (LogCompilation) {
if (xtty != NULL) {
ttyLocker ttyl; // keep the following output all in one block
@@ -1120,6 +1127,9 @@
(_state == zombie ? " zombie='1'" : ""));
}
log_identity(xtty);
+ if (cause != NULL) {
+ xtty->print(" cause='%s'", cause->klass()->external_name());
+ }
xtty->stamp();
xtty->end_elem();
}
@@ -1150,7 +1160,8 @@
// Make sure neither the nmethod nor the method is flushed in case of a safepoint in code below.
nmethodLocker nml(this);
methodHandle the_method(method());
- NoSafepointVerifier nsv;
+ // This can be called while the system is already at a safepoint which is ok
+ NoSafepointVerifier nsv(true, !SafepointSynchronize::is_at_safepoint());
// during patching, depending on the nmethod state we must notify the GC that
// code has been unloaded, unregistering it. We cannot do this right while
@@ -1507,13 +1518,12 @@
bool nmethod::do_unloading_jvmci() {
if (_jvmci_installed_code != NULL) {
if (JNIHandles::is_global_weak_cleared(_jvmci_installed_code)) {
- if (_jvmci_installed_code_triggers_unloading) {
- // jweak reference processing has already cleared the referent
- make_unloaded(NULL);
- return true;
- } else {
- clear_jvmci_installed_code();
+ if (_jvmci_installed_code_triggers_invalidation) {
+ // The reference to the installed code has been dropped so invalidate
+ // this nmethod and allow the sweeper to reclaim it.
+ make_not_entrant();
}
+ clear_jvmci_installed_code();
}
}
return false;
@@ -2948,7 +2958,7 @@
return JNIHandles::resolve(_speculation_log);
}
-char* nmethod::jvmci_installed_code_name(char* buf, size_t buflen) {
+char* nmethod::jvmci_installed_code_name(char* buf, size_t buflen) const {
if (!this->is_compiled_by_jvmci()) {
return NULL;
}
--- a/src/hotspot/share/code/nmethod.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/code/nmethod.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -78,7 +78,7 @@
// That is, installed code other than a "default"
// HotSpotNMethod causes nmethod unloading.
// This field is ignored once _jvmci_installed_code is NULL.
- bool _jvmci_installed_code_triggers_unloading;
+ bool _jvmci_installed_code_triggers_invalidation;
#endif
// To support simple linked-list chaining of nmethods:
@@ -456,7 +456,7 @@
// Copies the value of the name field in the InstalledCode
// object (if any) associated with this nmethod into buf.
// Returns the value of buf if it was updated otherwise NULL.
- char* jvmci_installed_code_name(char* buf, size_t buflen);
+ char* jvmci_installed_code_name(char* buf, size_t buflen) const;
// Updates the state of the InstalledCode (if any) associated with
// this nmethod based on the current value of _state.
@@ -486,7 +486,7 @@
protected:
virtual bool do_unloading_oops(address low_boundary, BoolObjectClosure* is_alive);
#if INCLUDE_JVMCI
- // See comment for _jvmci_installed_code_triggers_unloading field.
+ // See comment for _jvmci_installed_code_triggers_invalidation field.
// Returns whether this nmethod was unloaded.
virtual bool do_unloading_jvmci();
#endif
@@ -555,7 +555,7 @@
// Logging
void log_identity(xmlStream* log) const;
void log_new_nmethod() const;
- void log_state_change() const;
+ void log_state_change(oop cause = NULL) const;
// Prints block-level comments, including nmethod specific block labels:
virtual void print_block_comment(outputStream* stream, address block_begin) const {
--- a/src/hotspot/share/gc/g1/collectionSetChooser.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/g1/collectionSetChooser.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -243,7 +243,7 @@
// sets for old regions.
r->rem_set()->clear(true /* only_cardset */);
} else {
- assert(!r->is_old() || !r->rem_set()->is_tracked(),
+ assert(r->is_archive() || !r->is_old() || !r->rem_set()->is_tracked(),
"Missed to clear unused remembered set of region %u (%s) that is %s",
r->hrm_index(), r->get_type_str(), r->rem_set()->get_state_str());
}
--- a/src/hotspot/share/gc/g1/dirtyCardQueue.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/g1/dirtyCardQueue.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
* 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 @@
#ifndef SHARE_VM_GC_G1_DIRTYCARDQUEUE_HPP
#define SHARE_VM_GC_G1_DIRTYCARDQUEUE_HPP
-#include "gc/g1/ptrQueue.hpp"
+#include "gc/shared/ptrQueue.hpp"
#include "memory/allocation.hpp"
class FreeIdSet;
--- a/src/hotspot/share/gc/g1/g1Allocator.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1Allocator.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -361,7 +361,7 @@
hr->set_closed_archive();
}
_g1h->g1_policy()->remset_tracker()->update_at_allocate(hr);
- _g1h->old_set_add(hr);
+ _g1h->archive_set_add(hr);
_g1h->hr_printer()->alloc(hr);
_allocated_regions.append(hr);
_allocation_region = hr;
--- a/src/hotspot/share/gc/g1/g1BarrierSet.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1BarrierSet.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -27,9 +27,10 @@
#include "gc/g1/g1BarrierSetAssembler.hpp"
#include "gc/g1/g1CardTable.inline.hpp"
#include "gc/g1/g1CollectedHeap.inline.hpp"
+#include "gc/g1/g1SATBMarkQueueSet.hpp"
#include "gc/g1/g1ThreadLocalData.hpp"
#include "gc/g1/heapRegion.hpp"
-#include "gc/g1/satbMarkQueue.hpp"
+#include "gc/shared/satbMarkQueue.hpp"
#include "logging/log.hpp"
#include "oops/access.inline.hpp"
#include "oops/compressedOops.inline.hpp"
@@ -48,27 +49,30 @@
class G1BarrierSetC1;
class G1BarrierSetC2;
-G1SATBMarkQueueSet G1BarrierSet::_satb_mark_queue_set;
-DirtyCardQueueSet G1BarrierSet::_dirty_card_queue_set;
-
G1BarrierSet::G1BarrierSet(G1CardTable* card_table) :
CardTableBarrierSet(make_barrier_set_assembler<G1BarrierSetAssembler>(),
make_barrier_set_c1<G1BarrierSetC1>(),
make_barrier_set_c2<G1BarrierSetC2>(),
card_table,
- BarrierSet::FakeRtti(BarrierSet::G1BarrierSet)) {}
+ BarrierSet::FakeRtti(BarrierSet::G1BarrierSet)),
+ _satb_mark_queue_set(),
+ _dirty_card_queue_set()
+{}
void G1BarrierSet::enqueue(oop pre_val) {
// Nulls should have been already filtered.
assert(oopDesc::is_oop(pre_val, true), "Error");
- if (!_satb_mark_queue_set.is_active()) return;
+ G1SATBMarkQueueSet& queue_set = satb_mark_queue_set();
+ if (!queue_set.is_active()) {
+ return;
+ }
Thread* thr = Thread::current();
if (thr->is_Java_thread()) {
G1ThreadLocalData::satb_mark_queue(thr).enqueue(pre_val);
} else {
MutexLockerEx x(Shared_SATB_Q_lock, Mutex::_no_safepoint_check_flag);
- _satb_mark_queue_set.shared_satb_queue()->enqueue(pre_val);
+ queue_set.shared_satb_queue()->enqueue(pre_val);
}
}
--- a/src/hotspot/share/gc/g1/g1BarrierSet.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1BarrierSet.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -39,8 +39,12 @@
class G1BarrierSet: public CardTableBarrierSet {
friend class VMStructs;
private:
- static G1SATBMarkQueueSet _satb_mark_queue_set;
- static DirtyCardQueueSet _dirty_card_queue_set;
+ G1SATBMarkQueueSet _satb_mark_queue_set;
+ DirtyCardQueueSet _dirty_card_queue_set;
+
+ static G1BarrierSet* g1_barrier_set() {
+ return barrier_set_cast<G1BarrierSet>(BarrierSet::barrier_set());
+ }
public:
G1BarrierSet(G1CardTable* table);
@@ -75,12 +79,12 @@
virtual void on_thread_attach(JavaThread* thread);
virtual void on_thread_detach(JavaThread* thread);
- static SATBMarkQueueSet& satb_mark_queue_set() {
- return _satb_mark_queue_set;
+ static G1SATBMarkQueueSet& satb_mark_queue_set() {
+ return g1_barrier_set()->_satb_mark_queue_set;
}
static DirtyCardQueueSet& dirty_card_queue_set() {
- return _dirty_card_queue_set;
+ return g1_barrier_set()->_dirty_card_queue_set;
}
// Callbacks for runtime accesses.
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -25,7 +25,6 @@
#include "precompiled.hpp"
#include "classfile/metadataOnStackMark.hpp"
#include "classfile/stringTable.hpp"
-#include "classfile/symbolTable.hpp"
#include "code/codeCache.hpp"
#include "code/icBuffer.hpp"
#include "gc/g1/g1Allocator.inline.hpp"
@@ -52,7 +51,7 @@
#include "gc/g1/g1RemSet.hpp"
#include "gc/g1/g1RootClosures.hpp"
#include "gc/g1/g1RootProcessor.hpp"
-#include "gc/g1/g1SATBMarkQueueFilter.hpp"
+#include "gc/g1/g1SATBMarkQueueSet.hpp"
#include "gc/g1/g1StringDedup.hpp"
#include "gc/g1/g1ThreadLocalData.hpp"
#include "gc/g1/g1YCTypes.hpp"
@@ -84,7 +83,6 @@
#include "oops/access.inline.hpp"
#include "oops/compressedOops.inline.hpp"
#include "oops/oop.inline.hpp"
-#include "prims/resolvedMethodTable.hpp"
#include "runtime/atomic.hpp"
#include "runtime/flags/flagSetting.hpp"
#include "runtime/handles.inline.hpp"
@@ -645,7 +643,7 @@
curr_region->set_closed_archive();
}
_hr_printer.alloc(curr_region);
- _old_set.add(curr_region);
+ _archive_set.add(curr_region);
HeapWord* top;
HeapRegion* next_region;
if (curr_region != last_region) {
@@ -802,7 +800,7 @@
guarantee(curr_region->is_archive(),
"Expected archive region at index %u", curr_region->hrm_index());
uint curr_index = curr_region->hrm_index();
- _old_set.remove(curr_region);
+ _archive_set.remove(curr_region);
curr_region->set_free();
curr_region->set_top(curr_region->bottom());
if (curr_region != last_region) {
@@ -1127,7 +1125,7 @@
const bool do_clear_all_soft_refs = clear_all_soft_refs ||
soft_ref_policy()->should_clear_all_soft_refs();
- G1FullCollector collector(this, &_full_gc_memory_manager, explicit_gc, do_clear_all_soft_refs);
+ G1FullCollector collector(this, explicit_gc, do_clear_all_soft_refs);
GCTraceTime(Info, gc) tm("Pause Full", NULL, gc_cause(), true);
collector.prepare_collection();
@@ -1407,6 +1405,68 @@
_verifier->verify_region_sets_optional();
}
+class OldRegionSetChecker : public HeapRegionSetChecker {
+public:
+ void check_mt_safety() {
+ // Master Old Set MT safety protocol:
+ // (a) If we're at a safepoint, operations on the master old set
+ // should be invoked:
+ // - by the VM thread (which will serialize them), or
+ // - by the GC workers while holding the FreeList_lock, if we're
+ // at a safepoint for an evacuation pause (this lock is taken
+ // anyway when an GC alloc region is retired so that a new one
+ // is allocated from the free list), or
+ // - by the GC workers while holding the OldSets_lock, if we're at a
+ // safepoint for a cleanup pause.
+ // (b) If we're not at a safepoint, operations on the master old set
+ // should be invoked while holding the Heap_lock.
+
+ if (SafepointSynchronize::is_at_safepoint()) {
+ guarantee(Thread::current()->is_VM_thread() ||
+ FreeList_lock->owned_by_self() || OldSets_lock->owned_by_self(),
+ "master old set MT safety protocol at a safepoint");
+ } else {
+ guarantee(Heap_lock->owned_by_self(), "master old set MT safety protocol outside a safepoint");
+ }
+ }
+ bool is_correct_type(HeapRegion* hr) { return hr->is_old(); }
+ const char* get_description() { return "Old Regions"; }
+};
+
+class ArchiveRegionSetChecker : public HeapRegionSetChecker {
+public:
+ void check_mt_safety() {
+ guarantee(!Universe::is_fully_initialized() || SafepointSynchronize::is_at_safepoint(),
+ "May only change archive regions during initialization or safepoint.");
+ }
+ bool is_correct_type(HeapRegion* hr) { return hr->is_archive(); }
+ const char* get_description() { return "Archive Regions"; }
+};
+
+class HumongousRegionSetChecker : public HeapRegionSetChecker {
+public:
+ void check_mt_safety() {
+ // Humongous Set MT safety protocol:
+ // (a) If we're at a safepoint, operations on the master humongous
+ // set should be invoked by either the VM thread (which will
+ // serialize them) or by the GC workers while holding the
+ // OldSets_lock.
+ // (b) If we're not at a safepoint, operations on the master
+ // humongous set should be invoked while holding the Heap_lock.
+
+ if (SafepointSynchronize::is_at_safepoint()) {
+ guarantee(Thread::current()->is_VM_thread() ||
+ OldSets_lock->owned_by_self(),
+ "master humongous set MT safety protocol at a safepoint");
+ } else {
+ guarantee(Heap_lock->owned_by_self(),
+ "master humongous set MT safety protocol outside a safepoint");
+ }
+ }
+ bool is_correct_type(HeapRegion* hr) { return hr->is_humongous(); }
+ const char* get_description() { return "Humongous Regions"; }
+};
+
G1CollectedHeap::G1CollectedHeap(G1CollectorPolicy* collector_policy) :
CollectedHeap(),
_young_gen_sampling_thread(NULL),
@@ -1414,13 +1474,9 @@
_collector_policy(collector_policy),
_card_table(NULL),
_soft_ref_policy(),
- _memory_manager("G1 Young Generation", "end of minor GC"),
- _full_gc_memory_manager("G1 Old Generation", "end of major GC"),
- _eden_pool(NULL),
- _survivor_pool(NULL),
- _old_pool(NULL),
- _old_set("Old Set", false /* humongous */, new OldRegionSetMtSafeChecker()),
- _humongous_set("Master Humongous Set", true /* humongous */, new HumongousRegionSetMtSafeChecker()),
+ _old_set("Old Region Set", new OldRegionSetChecker()),
+ _archive_set("Archive Region Set", new ArchiveRegionSetChecker()),
+ _humongous_set("Humongous Region Set", new HumongousRegionSetChecker()),
_bot(NULL),
_listener(),
_hrm(),
@@ -1687,11 +1743,11 @@
// Perform any initialization actions delegated to the policy.
g1_policy()->init(this, &_collection_set);
- G1SATBMarkQueueFilter* satb_filter = new G1SATBMarkQueueFilter(this);
- G1BarrierSet::satb_mark_queue_set().initialize(satb_filter,
+ G1BarrierSet::satb_mark_queue_set().initialize(this,
SATB_Q_CBL_mon,
SATB_Q_FL_lock,
G1SATBProcessCompletedThreshold,
+ G1SATBBufferEnqueueingThresholdPercent,
Shared_SATB_Q_lock);
jint ecode = initialize_concurrent_refinement();
@@ -1747,20 +1803,6 @@
return JNI_OK;
}
-void G1CollectedHeap::initialize_serviceability() {
- _eden_pool = new G1EdenPool(this);
- _survivor_pool = new G1SurvivorPool(this);
- _old_pool = new G1OldGenPool(this);
-
- _full_gc_memory_manager.add_pool(_eden_pool);
- _full_gc_memory_manager.add_pool(_survivor_pool);
- _full_gc_memory_manager.add_pool(_old_pool);
-
- _memory_manager.add_pool(_eden_pool);
- _memory_manager.add_pool(_survivor_pool);
- _memory_manager.add_pool(_old_pool, false /* always_affected_by_gc */);
-}
-
void G1CollectedHeap::stop() {
// Stop all concurrent threads. We do this to make sure these threads
// do not continue to execute and access resources (e.g. logging)
@@ -2857,9 +2899,9 @@
active_workers = workers()->update_active_workers(active_workers);
log_info(gc,task)("Using %u workers of %u for evacuation", active_workers, workers()->total_workers());
- TraceCollectorStats tcs(g1mm()->incremental_collection_counters());
- TraceMemoryManagerStats tms(&_memory_manager, gc_cause(),
- collector_state()->yc_type() == Mixed /* allMemoryPoolsAffected */);
+ G1MonitoringScope ms(g1mm(),
+ false /* full_gc */,
+ collector_state()->yc_type() == Mixed /* all_memory_pools_affected */);
G1HeapTransition heap_transition(this);
size_t heap_used_bytes_before_gc = used();
@@ -3256,56 +3298,40 @@
undo_waste * HeapWordSize / K);
}
-class G1StringAndSymbolCleaningTask : public AbstractGangTask {
+class G1StringCleaningTask : public AbstractGangTask {
private:
BoolObjectClosure* _is_alive;
G1StringDedupUnlinkOrOopsDoClosure _dedup_closure;
OopStorage::ParState<false /* concurrent */, false /* const */> _par_state_string;
int _initial_string_table_size;
- int _initial_symbol_table_size;
bool _process_strings;
int _strings_processed;
int _strings_removed;
- bool _process_symbols;
- int _symbols_processed;
- int _symbols_removed;
-
bool _process_string_dedup;
public:
- G1StringAndSymbolCleaningTask(BoolObjectClosure* is_alive, bool process_strings, bool process_symbols, bool process_string_dedup) :
- AbstractGangTask("String/Symbol Unlinking"),
+ G1StringCleaningTask(BoolObjectClosure* is_alive, bool process_strings, bool process_string_dedup) :
+ AbstractGangTask("String Unlinking"),
_is_alive(is_alive),
_dedup_closure(is_alive, NULL, false),
_par_state_string(StringTable::weak_storage()),
_process_strings(process_strings), _strings_processed(0), _strings_removed(0),
- _process_symbols(process_symbols), _symbols_processed(0), _symbols_removed(0),
_process_string_dedup(process_string_dedup) {
_initial_string_table_size = (int) StringTable::the_table()->table_size();
- _initial_symbol_table_size = SymbolTable::the_table()->table_size();
- if (process_symbols) {
- SymbolTable::clear_parallel_claimed_index();
- }
if (process_strings) {
StringTable::reset_dead_counter();
}
}
- ~G1StringAndSymbolCleaningTask() {
- guarantee(!_process_symbols || SymbolTable::parallel_claimed_index() >= _initial_symbol_table_size,
- "claim value %d after unlink less than initial symbol table size %d",
- SymbolTable::parallel_claimed_index(), _initial_symbol_table_size);
-
+ ~G1StringCleaningTask() {
log_info(gc, stringtable)(
- "Cleaned string and symbol table, "
- "strings: " SIZE_FORMAT " processed, " SIZE_FORMAT " removed, "
- "symbols: " SIZE_FORMAT " processed, " SIZE_FORMAT " removed",
- strings_processed(), strings_removed(),
- symbols_processed(), symbols_removed());
+ "Cleaned string table, "
+ "strings: " SIZE_FORMAT " processed, " SIZE_FORMAT " removed",
+ strings_processed(), strings_removed());
if (_process_strings) {
StringTable::finish_dead_counter();
}
@@ -3314,18 +3340,11 @@
void work(uint worker_id) {
int strings_processed = 0;
int strings_removed = 0;
- int symbols_processed = 0;
- int symbols_removed = 0;
if (_process_strings) {
StringTable::possibly_parallel_unlink(&_par_state_string, _is_alive, &strings_processed, &strings_removed);
Atomic::add(strings_processed, &_strings_processed);
Atomic::add(strings_removed, &_strings_removed);
}
- if (_process_symbols) {
- SymbolTable::possibly_parallel_unlink(&symbols_processed, &symbols_removed);
- Atomic::add(symbols_processed, &_symbols_processed);
- Atomic::add(symbols_removed, &_symbols_removed);
- }
if (_process_string_dedup) {
G1StringDedup::parallel_unlink(&_dedup_closure, worker_id);
}
@@ -3333,9 +3352,6 @@
size_t strings_processed() const { return (size_t)_strings_processed; }
size_t strings_removed() const { return (size_t)_strings_removed; }
-
- size_t symbols_processed() const { return (size_t)_symbols_processed; }
- size_t symbols_removed() const { return (size_t)_symbols_removed; }
};
class G1CodeCacheUnloadingTask {
@@ -3559,46 +3575,22 @@
}
};
-class G1ResolvedMethodCleaningTask : public StackObj {
- volatile int _resolved_method_task_claimed;
-public:
- G1ResolvedMethodCleaningTask() :
- _resolved_method_task_claimed(0) {}
-
- bool claim_resolved_method_task() {
- if (_resolved_method_task_claimed) {
- return false;
- }
- return Atomic::cmpxchg(1, &_resolved_method_task_claimed, 0) == 0;
- }
-
- // These aren't big, one thread can do it all.
- void work() {
- if (claim_resolved_method_task()) {
- ResolvedMethodTable::unlink();
- }
- }
-};
-
-
// To minimize the remark pause times, the tasks below are done in parallel.
class G1ParallelCleaningTask : public AbstractGangTask {
private:
bool _unloading_occurred;
- G1StringAndSymbolCleaningTask _string_symbol_task;
+ G1StringCleaningTask _string_task;
G1CodeCacheUnloadingTask _code_cache_task;
G1KlassCleaningTask _klass_cleaning_task;
- G1ResolvedMethodCleaningTask _resolved_method_cleaning_task;
public:
// The constructor is run in the VMThread.
G1ParallelCleaningTask(BoolObjectClosure* is_alive, uint num_workers, bool unloading_occurred) :
AbstractGangTask("Parallel Cleaning"),
_unloading_occurred(unloading_occurred),
- _string_symbol_task(is_alive, true, true, G1StringDedup::is_enabled()),
+ _string_task(is_alive, true, G1StringDedup::is_enabled()),
_code_cache_task(num_workers, is_alive, unloading_occurred),
- _klass_cleaning_task(),
- _resolved_method_cleaning_task() {
+ _klass_cleaning_task() {
}
// The parallel work done by all worker threads.
@@ -3609,11 +3601,8 @@
// Let the threads mark that the first pass is done.
_code_cache_task.barrier_mark(worker_id);
- // Clean the Strings and Symbols.
- _string_symbol_task.work(worker_id);
-
- // Clean unreferenced things in the ResolvedMethodTable
- _resolved_method_cleaning_task.work();
+ // Clean the Strings.
+ _string_task.work(worker_id);
// Wait for all workers to finish the first code cache cleaning pass.
_code_cache_task.barrier_wait(worker_id);
@@ -3642,16 +3631,14 @@
void G1CollectedHeap::partial_cleaning(BoolObjectClosure* is_alive,
bool process_strings,
- bool process_symbols,
bool process_string_dedup) {
- if (!process_strings && !process_symbols && !process_string_dedup) {
+ if (!process_strings && !process_string_dedup) {
// Nothing to clean.
return;
}
- G1StringAndSymbolCleaningTask g1_unlink_task(is_alive, process_strings, process_symbols, process_string_dedup);
+ G1StringCleaningTask g1_unlink_task(is_alive, process_strings, process_string_dedup);
workers()->run_task(&g1_unlink_task);
-
}
class G1RedirtyLoggedCardsTask : public AbstractGangTask {
@@ -4045,7 +4032,7 @@
process_discovered_references(per_thread_states);
// FIXME
- // CM's reference processing also cleans up the string and symbol tables.
+ // CM's reference processing also cleans up the string table.
// Should we do that here also? We could, but it is a serial operation
// and could significantly increase the pause time.
@@ -4650,7 +4637,6 @@
#endif // ASSERT
class TearDownRegionSetsClosure : public HeapRegionClosure {
-private:
HeapRegionSet *_old_set;
public:
@@ -4663,9 +4649,9 @@
r->uninstall_surv_rate_group();
} else {
// We ignore free regions, we'll empty the free list afterwards.
- // We ignore humongous regions, we're not tearing down the
- // humongous regions set.
- assert(r->is_free() || r->is_humongous(),
+ // We ignore humongous and archive regions, we're not tearing down these
+ // sets.
+ assert(r->is_archive() || r->is_free() || r->is_humongous(),
"it cannot be another type");
}
return false;
@@ -4708,14 +4694,17 @@
class RebuildRegionSetsClosure : public HeapRegionClosure {
private:
- bool _free_list_only;
- HeapRegionSet* _old_set;
- HeapRegionManager* _hrm;
- size_t _total_used;
+ bool _free_list_only;
+
+ HeapRegionSet* _old_set;
+ HeapRegionManager* _hrm;
+
+ size_t _total_used;
public:
RebuildRegionSetsClosure(bool free_list_only,
- HeapRegionSet* old_set, HeapRegionManager* hrm) :
+ HeapRegionSet* old_set,
+ HeapRegionManager* hrm) :
_free_list_only(free_list_only),
_old_set(old_set), _hrm(hrm), _total_used(0) {
assert(_hrm->num_free_regions() == 0, "pre-condition");
@@ -4733,11 +4722,11 @@
_hrm->insert_into_free_list(r);
} else if (!_free_list_only) {
- if (r->is_humongous()) {
- // We ignore humongous regions. We left the humongous set unchanged.
+ if (r->is_archive() || r->is_humongous()) {
+ // We ignore archive and humongous regions. We left these sets unchanged.
} else {
assert(r->is_young() || r->is_free() || r->is_old(), "invariant");
- // We now move all (non-humongous, non-old) regions to old gen, and register them as such.
+ // We now move all (non-humongous, non-old, non-archive) regions to old gen, and register them as such.
r->move_to_old();
_old_set->add(r);
}
@@ -4811,7 +4800,7 @@
_hr_printer.retire(alloc_region);
// We update the eden sizes here, when the region is retired,
// instead of when it's allocated, since this is the point that its
- // used space has been recored in _summary_bytes_used.
+ // used space has been recorded in _summary_bytes_used.
g1mm()->update_eden_size();
}
@@ -4862,7 +4851,7 @@
alloc_region->note_end_of_copying(during_im);
g1_policy()->record_bytes_copied_during_gc(allocated_bytes);
if (dest.is_old()) {
- _old_set.add(alloc_region);
+ old_set_add(alloc_region);
}
_hr_printer.retire(alloc_region);
}
@@ -4987,17 +4976,14 @@
CodeCache::blobs_do(&blob_cl);
}
+void G1CollectedHeap::initialize_serviceability() {
+ _g1mm->initialize_serviceability();
+}
+
GrowableArray<GCMemoryManager*> G1CollectedHeap::memory_managers() {
- GrowableArray<GCMemoryManager*> memory_managers(2);
- memory_managers.append(&_memory_manager);
- memory_managers.append(&_full_gc_memory_manager);
- return memory_managers;
+ return _g1mm->memory_managers();
}
GrowableArray<MemoryPool*> G1CollectedHeap::memory_pools() {
- GrowableArray<MemoryPool*> memory_pools(3);
- memory_pools.append(_eden_pool);
- memory_pools.append(_survivor_pool);
- memory_pools.append(_old_pool);
- return memory_pools;
+ return _g1mm->memory_pools();
}
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -51,7 +51,6 @@
#include "gc/shared/preservedMarks.hpp"
#include "gc/shared/softRefPolicy.hpp"
#include "memory/memRegion.hpp"
-#include "services/memoryManager.hpp"
#include "utilities/stack.hpp"
// A "G1CollectedHeap" is an implementation of a java heap for HotSpot.
@@ -67,6 +66,7 @@
class G1ParScanThreadStateSet;
class G1ParScanThreadState;
class MemoryPool;
+class MemoryManager;
class ObjectClosure;
class SpaceClosure;
class CompactibleSpaceClosure;
@@ -160,23 +160,13 @@
SoftRefPolicy _soft_ref_policy;
- GCMemoryManager _memory_manager;
- GCMemoryManager _full_gc_memory_manager;
-
- MemoryPool* _eden_pool;
- MemoryPool* _survivor_pool;
- MemoryPool* _old_pool;
-
static size_t _humongous_object_threshold_in_words;
- // It keeps track of the old regions.
+ // These sets keep track of old, archive and humongous regions respectively.
HeapRegionSet _old_set;
-
- // It keeps track of the humongous regions.
+ HeapRegionSet _archive_set;
HeapRegionSet _humongous_set;
- virtual void initialize_serviceability();
-
void eagerly_reclaim_humongous_regions();
// Start a new incremental collection set for the next pause.
void start_new_collection_set();
@@ -970,6 +960,7 @@
virtual SoftRefPolicy* soft_ref_policy();
+ virtual void initialize_serviceability();
virtual GrowableArray<GCMemoryManager*> memory_managers();
virtual GrowableArray<MemoryPool*> memory_pools();
@@ -1046,8 +1037,10 @@
inline void old_set_add(HeapRegion* hr);
inline void old_set_remove(HeapRegion* hr);
+ inline void archive_set_add(HeapRegion* hr);
+
size_t non_young_capacity_bytes() {
- return (_old_set.length() + _humongous_set.length()) * HeapRegion::GrainBytes;
+ return (old_regions_count() + _archive_set.length() + humongous_regions_count()) * HeapRegion::GrainBytes;
}
// Determine whether the given region is one that we are using as an
@@ -1232,20 +1225,11 @@
const G1SurvivorRegions* survivor() const { return &_survivor; }
- uint survivor_regions_count() const {
- return _survivor.length();
- }
-
- uint eden_regions_count() const {
- return _eden.length();
- }
-
- uint young_regions_count() const {
- return _eden.length() + _survivor.length();
- }
-
+ uint eden_regions_count() const { return _eden.length(); }
+ uint survivor_regions_count() const { return _survivor.length(); }
+ uint young_regions_count() const { return _eden.length() + _survivor.length(); }
uint old_regions_count() const { return _old_set.length(); }
-
+ uint archive_regions_count() const { return _archive_set.length(); }
uint humongous_regions_count() const { return _humongous_set.length(); }
#ifdef ASSERT
@@ -1324,9 +1308,8 @@
// Partial cleaning used when class unloading is disabled.
// Let the caller choose what structures to clean out:
// - StringTable
- // - SymbolTable
// - StringDeduplication structures
- void partial_cleaning(BoolObjectClosure* is_alive, bool unlink_strings, bool unlink_symbols, bool unlink_string_dedup);
+ void partial_cleaning(BoolObjectClosure* is_alive, bool unlink_strings, bool unlink_string_dedup);
// Complete cleaning used when class unloading is enabled.
// Cleans out all structures handled by partial_cleaning and also the CodeCache.
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -92,6 +92,10 @@
_old_set.remove(hr);
}
+inline void G1CollectedHeap::archive_set_add(HeapRegion* hr) {
+ _archive_set.add(hr);
+}
+
// It dirties the cards that cover the block so that the post
// write barrier never queues anything when updating objects on this
// block. It is assumed (and in fact we assert) that the block
--- a/src/hotspot/share/gc/g1/g1CollectionSet.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1CollectionSet.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -328,10 +328,10 @@
return cl.valid();
}
-class G1PrintCollectionSetClosure : public HeapRegionClosure {
+class G1PrintCollectionSetDetailClosure : public HeapRegionClosure {
outputStream* _st;
public:
- G1PrintCollectionSetClosure(outputStream* st) : HeapRegionClosure(), _st(st) { }
+ G1PrintCollectionSetDetailClosure(outputStream* st) : HeapRegionClosure(), _st(st) { }
virtual bool do_heap_region(HeapRegion* r) {
assert(r->in_collection_set(), "Region %u should be in collection set", r->hrm_index());
@@ -347,7 +347,7 @@
void G1CollectionSet::print(outputStream* st) {
st->print_cr("\nCollection_set:");
- G1PrintCollectionSetClosure cl(st);
+ G1PrintCollectionSetDetailClosure cl(st);
iterate(&cl);
}
#endif // !PRODUCT
--- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -24,7 +24,6 @@
#include "precompiled.hpp"
#include "classfile/metadataOnStackMark.hpp"
-#include "classfile/symbolTable.hpp"
#include "code/codeCache.hpp"
#include "gc/g1/g1BarrierSet.hpp"
#include "gc/g1/g1CollectedHeap.inline.hpp"
@@ -1578,8 +1577,8 @@
// Is alive closure.
G1CMIsAliveClosure g1_is_alive(_g1h);
- // Inner scope to exclude the cleaning of the string and symbol
- // tables from the displayed time.
+ // Inner scope to exclude the cleaning of the string table
+ // from the displayed time.
{
GCTraceTime(Debug, gc, phases) debug("Reference Processing", _gc_timer_cm);
@@ -1673,16 +1672,16 @@
WeakProcessor::weak_oops_do(&g1_is_alive, &do_nothing_cl);
}
- // Unload Klasses, String, Symbols, Code Cache, etc.
+ // Unload Klasses, String, Code Cache, etc.
if (ClassUnloadingWithConcurrentMark) {
GCTraceTime(Debug, gc, phases) debug("Class Unloading", _gc_timer_cm);
bool purged_classes = SystemDictionary::do_unloading(_gc_timer_cm, false /* Defer cleaning */);
_g1h->complete_cleaning(&g1_is_alive, purged_classes);
} else {
GCTraceTime(Debug, gc, phases) debug("Cleanup", _gc_timer_cm);
- // No need to clean string table and symbol table as they are treated as strong roots when
+ // No need to clean string table as it is treated as strong roots when
// class unloading is disabled.
- _g1h->partial_cleaning(&g1_is_alive, false, false, G1StringDedup::is_enabled());
+ _g1h->partial_cleaning(&g1_is_alive, false, G1StringDedup::is_enabled());
}
}
--- a/src/hotspot/share/gc/g1/g1ConcurrentMark.inline.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.inline.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -52,7 +52,7 @@
return false;
}
assert(_g1h->is_in_reserved(obj), "Trying to discover obj " PTR_FORMAT " not in heap", p2i(obj));
- return _g1h->heap_region_containing(obj)->is_old_or_humongous();
+ return _g1h->heap_region_containing(obj)->is_old_or_humongous_or_archive();
}
inline bool G1ConcurrentMark::mark_in_next_bitmap(uint const worker_id, oop const obj, size_t const obj_size) {
--- a/src/hotspot/share/gc/g1/g1FullCollector.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1FullCollector.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -103,9 +103,9 @@
return worker_count;
}
-G1FullCollector::G1FullCollector(G1CollectedHeap* heap, GCMemoryManager* memory_manager, bool explicit_gc, bool clear_soft_refs) :
+G1FullCollector::G1FullCollector(G1CollectedHeap* heap, bool explicit_gc, bool clear_soft_refs) :
_heap(heap),
- _scope(memory_manager, explicit_gc, clear_soft_refs),
+ _scope(heap->g1mm(), explicit_gc, clear_soft_refs),
_num_workers(calc_active_workers()),
_oop_queue_set(_num_workers),
_array_queue_set(_num_workers),
@@ -226,8 +226,8 @@
_heap->complete_cleaning(&_is_alive, purged_class);
} else {
GCTraceTime(Debug, gc, phases) debug("Phase 1: String and Symbol Tables Cleanup", scope()->timer());
- // If no class unloading just clean out strings and symbols.
- _heap->partial_cleaning(&_is_alive, true, true, G1StringDedup::is_enabled());
+ // If no class unloading just clean out strings.
+ _heap->partial_cleaning(&_is_alive, true, G1StringDedup::is_enabled());
}
scope()->tracer()->report_object_count_after_gc(&_is_alive);
--- a/src/hotspot/share/gc/g1/g1FullCollector.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1FullCollector.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -72,7 +72,7 @@
ReferenceProcessorSubjectToDiscoveryMutator _is_subject_mutator;
public:
- G1FullCollector(G1CollectedHeap* heap, GCMemoryManager* memory_manager, bool explicit_gc, bool clear_soft_refs);
+ G1FullCollector(G1CollectedHeap* heap, bool explicit_gc, bool clear_soft_refs);
~G1FullCollector();
void prepare_collection();
--- a/src/hotspot/share/gc/g1/g1FullGCScope.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1FullGCScope.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* 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 @@
#include "precompiled.hpp"
#include "gc/g1/g1FullGCScope.hpp"
-G1FullGCScope::G1FullGCScope(GCMemoryManager* memory_manager, bool explicit_gc, bool clear_soft) :
+G1FullGCScope::G1FullGCScope(G1MonitoringSupport* monitoring_support, bool explicit_gc, bool clear_soft) :
_rm(),
_explicit_gc(explicit_gc),
_g1h(G1CollectedHeap::heap()),
@@ -36,8 +36,7 @@
_active(),
_cpu_time(),
_soft_refs(clear_soft, _g1h->soft_ref_policy()),
- _collector_stats(_g1h->g1mm()->full_collection_counters()),
- _memory_stats(memory_manager, _g1h->gc_cause()),
+ _monitoring_scope(monitoring_support, true /* full_gc */, true /* all_memory_pools_affected */),
_heap_transition(_g1h) {
_timer.register_gc_start();
_tracer.report_gc_start(_g1h->gc_cause(), _timer.gc_start());
--- a/src/hotspot/share/gc/g1/g1FullGCScope.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1FullGCScope.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +27,6 @@
#include "gc/g1/g1CollectedHeap.hpp"
#include "gc/g1/g1HeapTransition.hpp"
-#include "gc/shared/collectorCounters.hpp"
#include "gc/shared/gcId.hpp"
#include "gc/shared/gcTrace.hpp"
#include "gc/shared/gcTraceTime.hpp"
@@ -51,12 +50,11 @@
IsGCActiveMark _active;
GCTraceCPUTime _cpu_time;
ClearedAllSoftRefs _soft_refs;
- TraceCollectorStats _collector_stats;
- TraceMemoryManagerStats _memory_stats;
+ G1MonitoringScope _monitoring_scope;
G1HeapTransition _heap_transition;
public:
- G1FullGCScope(GCMemoryManager* memory_manager, bool explicit_gc, bool clear_soft);
+ G1FullGCScope(G1MonitoringSupport* monitoring_support, bool explicit_gc, bool clear_soft);
~G1FullGCScope();
bool is_explicit_gc();
--- a/src/hotspot/share/gc/g1/g1HeapRegionTraceType.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1HeapRegionTraceType.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,6 @@
StartsHumongous,
ContinuesHumongous,
Old,
- Pinned,
OpenArchive,
ClosedArchive,
G1HeapRegionTypeEndSentinel
@@ -51,7 +50,6 @@
case StartsHumongous: return "Starts Humongous";
case ContinuesHumongous: return "Continues Humongous";
case Old: return "Old";
- case Pinned: return "Pinned";
case OpenArchive: return "OpenArchive";
case ClosedArchive: return "ClosedArchive";
default: ShouldNotReachHere(); return NULL;
--- a/src/hotspot/share/gc/g1/g1HeapTransition.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1HeapTransition.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
* 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 @@
_eden_length = g1_heap->eden_regions_count();
_survivor_length = g1_heap->survivor_regions_count();
_old_length = g1_heap->old_regions_count();
+ _archive_length = g1_heap->archive_regions_count();
_humongous_length = g1_heap->humongous_regions_count();
_metaspace_used_bytes = MetaspaceUtils::used_bytes();
}
@@ -43,16 +44,19 @@
size_t _eden_used;
size_t _survivor_used;
size_t _old_used;
+ size_t _archive_used;
size_t _humongous_used;
size_t _eden_region_count;
size_t _survivor_region_count;
size_t _old_region_count;
+ size_t _archive_region_count;
size_t _humongous_region_count;
DetailedUsage() :
- _eden_used(0), _survivor_used(0), _old_used(0), _humongous_used(0),
- _eden_region_count(0), _survivor_region_count(0), _old_region_count(0), _humongous_region_count(0) {}
+ _eden_used(0), _survivor_used(0), _old_used(0), _archive_used(0), _humongous_used(0),
+ _eden_region_count(0), _survivor_region_count(0), _old_region_count(0),
+ _archive_region_count(0), _humongous_region_count(0) {}
};
class DetailedUsageClosure: public HeapRegionClosure {
@@ -62,6 +66,9 @@
if (r->is_old()) {
_usage._old_used += r->used();
_usage._old_region_count++;
+ } else if (r->is_archive()) {
+ _usage._archive_used += r->used();
+ _usage._archive_region_count++;
} else if (r->is_survivor()) {
_usage._survivor_used += r->used();
_usage._survivor_region_count++;
@@ -94,6 +101,8 @@
after._survivor_length, usage._survivor_region_count);
assert(usage._old_region_count == after._old_length, "Expected old to be " SIZE_FORMAT " but was " SIZE_FORMAT,
after._old_length, usage._old_region_count);
+ assert(usage._archive_region_count == after._archive_length, "Expected archive to be " SIZE_FORMAT " but was " SIZE_FORMAT,
+ after._archive_length, usage._archive_region_count);
assert(usage._humongous_region_count == after._humongous_length, "Expected humongous to be " SIZE_FORMAT " but was " SIZE_FORMAT,
after._humongous_length, usage._humongous_region_count);
}
@@ -112,6 +121,11 @@
log_trace(gc, heap)(" Used: " SIZE_FORMAT "K, Waste: " SIZE_FORMAT "K",
usage._old_used / K, ((after._old_length * HeapRegion::GrainBytes) - usage._old_used) / K);
+ log_info(gc, heap)("Archive regions: " SIZE_FORMAT "->" SIZE_FORMAT,
+ _before._archive_length, after._archive_length);
+ log_trace(gc, heap)(" Used: " SIZE_FORMAT "K, Waste: " SIZE_FORMAT "K",
+ usage._archive_used / K, ((after._archive_length * HeapRegion::GrainBytes) - usage._archive_used) / K);
+
log_info(gc, heap)("Humongous regions: " SIZE_FORMAT "->" SIZE_FORMAT,
_before._humongous_length, after._humongous_length);
log_trace(gc, heap)(" Used: " SIZE_FORMAT "K, Waste: " SIZE_FORMAT "K",
--- a/src/hotspot/share/gc/g1/g1HeapTransition.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1HeapTransition.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
* 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 @@
size_t _eden_length;
size_t _survivor_length;
size_t _old_length;
+ size_t _archive_length;
size_t _humongous_length;
size_t _metaspace_used_bytes;
--- a/src/hotspot/share/gc/g1/g1HeapVerifier.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1HeapVerifier.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -488,19 +488,22 @@
class VerifyRegionListsClosure : public HeapRegionClosure {
private:
HeapRegionSet* _old_set;
+ HeapRegionSet* _archive_set;
HeapRegionSet* _humongous_set;
- HeapRegionManager* _hrm;
+ HeapRegionManager* _hrm;
public:
uint _old_count;
+ uint _archive_count;
uint _humongous_count;
uint _free_count;
VerifyRegionListsClosure(HeapRegionSet* old_set,
+ HeapRegionSet* archive_set,
HeapRegionSet* humongous_set,
HeapRegionManager* hrm) :
- _old_set(old_set), _humongous_set(humongous_set), _hrm(hrm),
- _old_count(), _humongous_count(), _free_count(){ }
+ _old_set(old_set), _archive_set(archive_set), _humongous_set(humongous_set), _hrm(hrm),
+ _old_count(), _archive_count(), _humongous_count(), _free_count(){ }
bool do_heap_region(HeapRegion* hr) {
if (hr->is_young()) {
@@ -511,6 +514,9 @@
} else if (hr->is_empty()) {
assert(_hrm->is_free(hr), "Heap region %u is empty but not on the free list.", hr->hrm_index());
_free_count++;
+ } else if (hr->is_archive()) {
+ assert(hr->containing_set() == _archive_set, "Heap region %u is archive but not in the archive set.", hr->hrm_index());
+ _archive_count++;
} else if (hr->is_old()) {
assert(hr->containing_set() == _old_set, "Heap region %u is old but not in the old set.", hr->hrm_index());
_old_count++;
@@ -523,8 +529,9 @@
return false;
}
- void verify_counts(HeapRegionSet* old_set, HeapRegionSet* humongous_set, HeapRegionManager* free_list) {
+ void verify_counts(HeapRegionSet* old_set, HeapRegionSet* archive_set, HeapRegionSet* humongous_set, HeapRegionManager* free_list) {
guarantee(old_set->length() == _old_count, "Old set count mismatch. Expected %u, actual %u.", old_set->length(), _old_count);
+ guarantee(archive_set->length() == _archive_count, "Archive set count mismatch. Expected %u, actual %u.", archive_set->length(), _archive_count);
guarantee(humongous_set->length() == _humongous_count, "Hum set count mismatch. Expected %u, actual %u.", humongous_set->length(), _humongous_count);
guarantee(free_list->num_free_regions() == _free_count, "Free list count mismatch. Expected %u, actual %u.", free_list->num_free_regions(), _free_count);
}
@@ -539,9 +546,9 @@
// Finally, make sure that the region accounting in the lists is
// consistent with what we see in the heap.
- VerifyRegionListsClosure cl(&_g1h->_old_set, &_g1h->_humongous_set, &_g1h->_hrm);
+ VerifyRegionListsClosure cl(&_g1h->_old_set, &_g1h->_archive_set, &_g1h->_humongous_set, &_g1h->_hrm);
_g1h->heap_region_iterate(&cl);
- cl.verify_counts(&_g1h->_old_set, &_g1h->_humongous_set, &_g1h->_hrm);
+ cl.verify_counts(&_g1h->_old_set, &_g1h->_archive_set, &_g1h->_humongous_set, &_g1h->_hrm);
}
void G1HeapVerifier::prepare_for_verify() {
@@ -755,6 +762,11 @@
return true;
}
if (cset_state.is_in_cset()) {
+ if (hr->is_archive()) {
+ log_error(gc, verify)("## is_archive in collection set for region %u", i);
+ _failures = true;
+ return true;
+ }
if (hr->is_young() != (cset_state.is_young())) {
log_error(gc, verify)("## is_young %d / cset state " CSETSTATE_FORMAT " inconsistency for region %u",
hr->is_young(), cset_state.value(), i);
--- a/src/hotspot/share/gc/g1/g1MemoryPool.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1MemoryPool.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -40,50 +40,41 @@
assert(UseG1GC, "sanity");
}
-G1EdenPool::G1EdenPool(G1CollectedHeap* g1h) :
+G1EdenPool::G1EdenPool(G1CollectedHeap* g1h, size_t initial_size) :
G1MemoryPoolSuper(g1h,
"G1 Eden Space",
- g1h->g1mm()->eden_space_committed(), /* init_size */
- _undefined_max,
+ initial_size,
+ MemoryUsage::undefined_size(),
false /* support_usage_threshold */) { }
MemoryUsage G1EdenPool::get_memory_usage() {
- size_t initial_sz = initial_size();
- size_t max_sz = max_size();
- size_t used = used_in_bytes();
size_t committed = _g1mm->eden_space_committed();
- return MemoryUsage(initial_sz, used, committed, max_sz);
+ return MemoryUsage(initial_size(), used_in_bytes(), committed, max_size());
}
-G1SurvivorPool::G1SurvivorPool(G1CollectedHeap* g1h) :
+G1SurvivorPool::G1SurvivorPool(G1CollectedHeap* g1h, size_t initial_size) :
G1MemoryPoolSuper(g1h,
"G1 Survivor Space",
- g1h->g1mm()->survivor_space_committed(), /* init_size */
- _undefined_max,
+ initial_size,
+ MemoryUsage::undefined_size(),
false /* support_usage_threshold */) { }
MemoryUsage G1SurvivorPool::get_memory_usage() {
- size_t initial_sz = initial_size();
- size_t max_sz = max_size();
- size_t used = used_in_bytes();
size_t committed = _g1mm->survivor_space_committed();
- return MemoryUsage(initial_sz, used, committed, max_sz);
+ return MemoryUsage(initial_size(), used_in_bytes(), committed, max_size());
}
-G1OldGenPool::G1OldGenPool(G1CollectedHeap* g1h) :
+G1OldGenPool::G1OldGenPool(G1CollectedHeap* g1h, size_t initial_size, size_t max_size) :
G1MemoryPoolSuper(g1h,
"G1 Old Gen",
- g1h->g1mm()->old_space_committed(), /* init_size */
- g1h->g1mm()->old_gen_max(),
+ initial_size,
+ max_size,
true /* support_usage_threshold */) { }
MemoryUsage G1OldGenPool::get_memory_usage() {
- size_t initial_sz = initial_size();
- size_t max_sz = max_size();
- size_t used = used_in_bytes();
- size_t committed = _g1mm->old_space_committed();
+ size_t committed = _g1mm->old_gen_committed();
- return MemoryUsage(initial_sz, used, committed, max_sz);
+ return MemoryUsage(initial_size(), used_in_bytes(), committed, max_size());
}
--- a/src/hotspot/share/gc/g1/g1MemoryPool.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1MemoryPool.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -53,7 +53,6 @@
// (G1EdenPool, G1SurvivorPool, G1OldGenPool).
class G1MemoryPoolSuper : public CollectedMemoryPool {
protected:
- const static size_t _undefined_max = (size_t) -1;
G1MonitoringSupport* _g1mm;
// Would only be called from subclasses.
@@ -67,42 +66,30 @@
// Memory pool that represents the G1 eden.
class G1EdenPool : public G1MemoryPoolSuper {
public:
- G1EdenPool(G1CollectedHeap* g1h);
+ G1EdenPool(G1CollectedHeap* g1h, size_t initial_size);
- size_t used_in_bytes() {
- return _g1mm->eden_space_used();
- }
- size_t max_size() const {
- return _undefined_max;
- }
+ size_t used_in_bytes() { return _g1mm->eden_space_used(); }
+
MemoryUsage get_memory_usage();
};
// Memory pool that represents the G1 survivor.
class G1SurvivorPool : public G1MemoryPoolSuper {
public:
- G1SurvivorPool(G1CollectedHeap* g1h);
+ G1SurvivorPool(G1CollectedHeap* g1h, size_t initial_size);
- size_t used_in_bytes() {
- return _g1mm->survivor_space_used();
- }
- size_t max_size() const {
- return _undefined_max;
- }
+ size_t used_in_bytes() { return _g1mm->survivor_space_used(); }
+
MemoryUsage get_memory_usage();
};
// Memory pool that represents the G1 old gen.
class G1OldGenPool : public G1MemoryPoolSuper {
public:
- G1OldGenPool(G1CollectedHeap* g1h);
+ G1OldGenPool(G1CollectedHeap* g1h, size_t initial_size, size_t max_size);
- size_t used_in_bytes() {
- return _g1mm->old_space_used();
- }
- size_t max_size() const {
- return _g1mm->old_gen_max();
- }
+ size_t used_in_bytes() { return _g1mm->old_gen_used(); }
+
MemoryUsage get_memory_usage();
};
--- a/src/hotspot/share/gc/g1/g1MonitoringSupport.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1MonitoringSupport.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -26,83 +26,95 @@
#include "gc/g1/g1CollectedHeap.inline.hpp"
#include "gc/g1/g1MonitoringSupport.hpp"
#include "gc/g1/g1Policy.hpp"
-#include "gc/shared/collectorCounters.hpp"
+#include "gc/g1/g1MemoryPool.hpp"
#include "gc/shared/hSpaceCounters.hpp"
#include "memory/metaspaceCounters.hpp"
+#include "services/memoryPool.hpp"
-G1GenerationCounters::G1GenerationCounters(G1MonitoringSupport* g1mm,
- const char* name,
- int ordinal, int spaces,
- size_t min_capacity,
- size_t max_capacity,
- size_t curr_capacity)
+class G1GenerationCounters : public GenerationCounters {
+protected:
+ G1MonitoringSupport* _g1mm;
+
+public:
+ G1GenerationCounters(G1MonitoringSupport* g1mm,
+ const char* name, int ordinal, int spaces,
+ size_t min_capacity, size_t max_capacity,
+ size_t curr_capacity)
: GenerationCounters(name, ordinal, spaces, min_capacity,
max_capacity, curr_capacity), _g1mm(g1mm) { }
+};
-// We pad the capacity three times given that the young generation
-// contains three spaces (eden and two survivors).
-G1YoungGenerationCounters::G1YoungGenerationCounters(G1MonitoringSupport* g1mm,
- const char* name)
+class G1YoungGenerationCounters : public G1GenerationCounters {
+public:
+ // We pad the capacity three times given that the young generation
+ // contains three spaces (eden and two survivors).
+ G1YoungGenerationCounters(G1MonitoringSupport* g1mm, const char* name, size_t max_size)
: G1GenerationCounters(g1mm, name, 0 /* ordinal */, 3 /* spaces */,
- G1MonitoringSupport::pad_capacity(0, 3) /* min_capacity */,
- G1MonitoringSupport::pad_capacity(g1mm->young_gen_max(), 3),
- G1MonitoringSupport::pad_capacity(0, 3) /* curr_capacity */) {
- if (UsePerfData) {
- update_all();
+ G1MonitoringSupport::pad_capacity(0, 3) /* min_capacity */,
+ G1MonitoringSupport::pad_capacity(max_size, 3),
+ G1MonitoringSupport::pad_capacity(0, 3) /* curr_capacity */) {
+ if (UsePerfData) {
+ update_all();
+ }
}
-}
-G1OldGenerationCounters::G1OldGenerationCounters(G1MonitoringSupport* g1mm,
- const char* name)
+ virtual void update_all() {
+ size_t committed =
+ G1MonitoringSupport::pad_capacity(_g1mm->young_gen_committed(), 3);
+ _current_size->set_value(committed);
+ }
+};
+
+class G1OldGenerationCounters : public G1GenerationCounters {
+public:
+ G1OldGenerationCounters(G1MonitoringSupport* g1mm, const char* name, size_t max_size)
: G1GenerationCounters(g1mm, name, 1 /* ordinal */, 1 /* spaces */,
- G1MonitoringSupport::pad_capacity(0) /* min_capacity */,
- G1MonitoringSupport::pad_capacity(g1mm->old_gen_max()),
- G1MonitoringSupport::pad_capacity(0) /* curr_capacity */) {
- if (UsePerfData) {
- update_all();
+ G1MonitoringSupport::pad_capacity(0) /* min_capacity */,
+ G1MonitoringSupport::pad_capacity(max_size),
+ G1MonitoringSupport::pad_capacity(0) /* curr_capacity */) {
+ if (UsePerfData) {
+ update_all();
+ }
}
-}
-void G1YoungGenerationCounters::update_all() {
- size_t committed =
- G1MonitoringSupport::pad_capacity(_g1mm->young_gen_committed(), 3);
- _current_size->set_value(committed);
-}
-
-void G1OldGenerationCounters::update_all() {
- size_t committed =
- G1MonitoringSupport::pad_capacity(_g1mm->old_gen_committed());
- _current_size->set_value(committed);
-}
+ virtual void update_all() {
+ size_t committed =
+ G1MonitoringSupport::pad_capacity(_g1mm->old_gen_committed());
+ _current_size->set_value(committed);
+ }
+};
G1MonitoringSupport::G1MonitoringSupport(G1CollectedHeap* g1h) :
_g1h(g1h),
+ _incremental_memory_manager("G1 Young Generation", "end of minor GC"),
+ _full_gc_memory_manager("G1 Old Generation", "end of major GC"),
+ _eden_space_pool(NULL),
+ _survivor_space_pool(NULL),
+ _old_gen_pool(NULL),
_incremental_collection_counters(NULL),
_full_collection_counters(NULL),
_conc_collection_counters(NULL),
- _young_collection_counters(NULL),
- _old_collection_counters(NULL),
+ _young_gen_counters(NULL),
+ _old_gen_counters(NULL),
_old_space_counters(NULL),
- _eden_counters(NULL),
- _from_counters(NULL),
- _to_counters(NULL),
+ _eden_space_counters(NULL),
+ _from_space_counters(NULL),
+ _to_space_counters(NULL),
- _overall_reserved(0),
_overall_committed(0),
_overall_used(0),
- _young_region_num(0),
_young_gen_committed(0),
- _eden_committed(0),
- _eden_used(0),
- _survivor_committed(0),
- _survivor_used(0),
- _old_committed(0),
- _old_used(0) {
+ _old_gen_committed(0),
- _overall_reserved = g1h->max_capacity();
+ _eden_space_committed(0),
+ _eden_space_used(0),
+ _survivor_space_committed(0),
+ _survivor_space_used(0),
+ _old_gen_used(0) {
+
recalculate_sizes();
- // Counters for GC collections
+ // Counters for garbage collections
//
// name "collector.0". In a generational collector this would be the
// young generation collection.
@@ -117,77 +129,96 @@
_conc_collection_counters =
new CollectorCounters("G1 stop-the-world phases", 2);
- // timer sampling for all counters supporting sampling only update the
- // used value. See the take_sample() method. G1 requires both used and
- // capacity updated so sampling is not currently used. It might
- // be sufficient to update all counters in take_sample() even though
- // take_sample() only returns "used". When sampling was used, there
- // were some anomolous values emitted which may have been the consequence
- // of not updating all values simultaneously (i.e., see the calculation done
- // in eden_space_used(), is it possible that the values used to
- // calculate either eden_used or survivor_used are being updated by
- // the collector when the sample is being done?).
- const bool sampled = false;
-
// "Generation" and "Space" counters.
//
// name "generation.1" This is logically the old generation in
// generational GC terms. The "1, 1" parameters are for
// the n-th generation (=1) with 1 space.
// Counters are created from minCapacity, maxCapacity, and capacity
- _old_collection_counters = new G1OldGenerationCounters(this, "old");
+ _old_gen_counters = new G1OldGenerationCounters(this, "old", _g1h->max_capacity());
// name "generation.1.space.0"
// Counters are created from maxCapacity, capacity, initCapacity,
// and used.
- _old_space_counters = new HSpaceCounters(_old_collection_counters->name_space(),
+ _old_space_counters = new HSpaceCounters(_old_gen_counters->name_space(),
"space", 0 /* ordinal */,
- pad_capacity(overall_reserved()) /* max_capacity */,
- pad_capacity(old_space_committed()) /* init_capacity */);
+ pad_capacity(g1h->max_capacity()) /* max_capacity */,
+ pad_capacity(_old_gen_committed) /* init_capacity */);
// Young collection set
// name "generation.0". This is logically the young generation.
// The "0, 3" are parameters for the n-th generation (=0) with 3 spaces.
// See _old_collection_counters for additional counters
- _young_collection_counters = new G1YoungGenerationCounters(this, "young");
+ _young_gen_counters = new G1YoungGenerationCounters(this, "young", _g1h->max_capacity());
- const char* young_collection_name_space = _young_collection_counters->name_space();
+ const char* young_collection_name_space = _young_gen_counters->name_space();
// name "generation.0.space.0"
// See _old_space_counters for additional counters
- _eden_counters = new HSpaceCounters(young_collection_name_space,
+ _eden_space_counters = new HSpaceCounters(young_collection_name_space,
"eden", 0 /* ordinal */,
- pad_capacity(overall_reserved()) /* max_capacity */,
- pad_capacity(eden_space_committed()) /* init_capacity */);
+ pad_capacity(g1h->max_capacity()) /* max_capacity */,
+ pad_capacity(_eden_space_committed) /* init_capacity */);
// name "generation.0.space.1"
// See _old_space_counters for additional counters
// Set the arguments to indicate that this survivor space is not used.
- _from_counters = new HSpaceCounters(young_collection_name_space,
+ _from_space_counters = new HSpaceCounters(young_collection_name_space,
"s0", 1 /* ordinal */,
pad_capacity(0) /* max_capacity */,
pad_capacity(0) /* init_capacity */);
+ // Given that this survivor space is not used, we update it here
+ // once to reflect that its used space is 0 so that we don't have to
+ // worry about updating it again later.
+ _from_space_counters->update_used(0);
// name "generation.0.space.2"
// See _old_space_counters for additional counters
- _to_counters = new HSpaceCounters(young_collection_name_space,
+ _to_space_counters = new HSpaceCounters(young_collection_name_space,
"s1", 2 /* ordinal */,
- pad_capacity(overall_reserved()) /* max_capacity */,
- pad_capacity(survivor_space_committed()) /* init_capacity */);
+ pad_capacity(g1h->max_capacity()) /* max_capacity */,
+ pad_capacity(_survivor_space_committed) /* init_capacity */);
+}
+
+G1MonitoringSupport::~G1MonitoringSupport() {
+ delete _eden_space_pool;
+ delete _survivor_space_pool;
+ delete _old_gen_pool;
+}
+
+void G1MonitoringSupport::initialize_serviceability() {
+ _eden_space_pool = new G1EdenPool(_g1h, _eden_space_committed);
+ _survivor_space_pool = new G1SurvivorPool(_g1h, _survivor_space_committed);
+ _old_gen_pool = new G1OldGenPool(_g1h, _old_gen_committed, _g1h->max_capacity());
- if (UsePerfData) {
- // Given that this survivor space is not used, we update it here
- // once to reflect that its used space is 0 so that we don't have to
- // worry about updating it again later.
- _from_counters->update_used(0);
- }
+ _full_gc_memory_manager.add_pool(_eden_space_pool);
+ _full_gc_memory_manager.add_pool(_survivor_space_pool);
+ _full_gc_memory_manager.add_pool(_old_gen_pool);
+
+ _incremental_memory_manager.add_pool(_eden_space_pool);
+ _incremental_memory_manager.add_pool(_survivor_space_pool);
+ _incremental_memory_manager.add_pool(_old_gen_pool, false /* always_affected_by_gc */);
+}
+
+GrowableArray<GCMemoryManager*> G1MonitoringSupport::memory_managers() {
+ GrowableArray<GCMemoryManager*> memory_managers(2);
+ memory_managers.append(&_incremental_memory_manager);
+ memory_managers.append(&_full_gc_memory_manager);
+ return memory_managers;
+}
+
+GrowableArray<MemoryPool*> G1MonitoringSupport::memory_pools() {
+ GrowableArray<MemoryPool*> memory_pools(3);
+ memory_pools.append(_eden_space_pool);
+ memory_pools.append(_survivor_space_pool);
+ memory_pools.append(_old_gen_pool);
+ return memory_pools;
}
void G1MonitoringSupport::recalculate_sizes() {
- // Recalculate all the sizes from scratch. We assume that this is
- // called at a point where no concurrent updates to the various
- // values we read here are possible (i.e., at a STW phase at the end
- // of a GC).
+ assert_heap_locked_or_at_safepoint(true);
+
+ // Recalculate all the sizes from scratch.
uint young_list_length = _g1h->young_regions_count();
uint survivor_list_length = _g1h->survivor_regions_count();
@@ -200,14 +231,13 @@
uint eden_list_max_length = young_list_max_length - survivor_list_length;
_overall_used = _g1h->used_unlocked();
- _eden_used = (size_t) eden_list_length * HeapRegion::GrainBytes;
- _survivor_used = (size_t) survivor_list_length * HeapRegion::GrainBytes;
- _young_region_num = young_list_length;
- _old_used = subtract_up_to_zero(_overall_used, _eden_used + _survivor_used);
+ _eden_space_used = (size_t) eden_list_length * HeapRegion::GrainBytes;
+ _survivor_space_used = (size_t) survivor_list_length * HeapRegion::GrainBytes;
+ _old_gen_used = subtract_up_to_zero(_overall_used, _eden_space_used + _survivor_space_used);
// First calculate the committed sizes that can be calculated independently.
- _survivor_committed = _survivor_used;
- _old_committed = HeapRegion::align_up_to_region_byte_size(_old_used);
+ _survivor_space_committed = _survivor_space_used;
+ _old_gen_committed = HeapRegion::align_up_to_region_byte_size(_old_gen_used);
// Next, start with the overall committed size.
_overall_committed = _g1h->capacity();
@@ -215,70 +245,64 @@
// Remove the committed size we have calculated so far (for the
// survivor and old space).
- assert(committed >= (_survivor_committed + _old_committed), "sanity");
- committed -= _survivor_committed + _old_committed;
+ assert(committed >= (_survivor_space_committed + _old_gen_committed), "sanity");
+ committed -= _survivor_space_committed + _old_gen_committed;
// Next, calculate and remove the committed size for the eden.
- _eden_committed = (size_t) eden_list_max_length * HeapRegion::GrainBytes;
+ _eden_space_committed = (size_t) eden_list_max_length * HeapRegion::GrainBytes;
// Somewhat defensive: be robust in case there are inaccuracies in
// the calculations
- _eden_committed = MIN2(_eden_committed, committed);
- committed -= _eden_committed;
+ _eden_space_committed = MIN2(_eden_space_committed, committed);
+ committed -= _eden_space_committed;
// Finally, give the rest to the old space...
- _old_committed += committed;
+ _old_gen_committed += committed;
// ..and calculate the young gen committed.
- _young_gen_committed = _eden_committed + _survivor_committed;
+ _young_gen_committed = _eden_space_committed + _survivor_space_committed;
assert(_overall_committed ==
- (_eden_committed + _survivor_committed + _old_committed),
+ (_eden_space_committed + _survivor_space_committed + _old_gen_committed),
"the committed sizes should add up");
// Somewhat defensive: cap the eden used size to make sure it
// never exceeds the committed size.
- _eden_used = MIN2(_eden_used, _eden_committed);
+ _eden_space_used = MIN2(_eden_space_used, _eden_space_committed);
// _survivor_committed and _old_committed are calculated in terms of
// the corresponding _*_used value, so the next two conditions
// should hold.
- assert(_survivor_used <= _survivor_committed, "post-condition");
- assert(_old_used <= _old_committed, "post-condition");
-}
-
-void G1MonitoringSupport::recalculate_eden_size() {
- // When a new eden region is allocated, only the eden_used size is
- // affected (since we have recalculated everything else at the last GC).
-
- uint young_region_num = _g1h->young_regions_count();
- if (young_region_num > _young_region_num) {
- uint diff = young_region_num - _young_region_num;
- _eden_used += (size_t) diff * HeapRegion::GrainBytes;
- // Somewhat defensive: cap the eden used size to make sure it
- // never exceeds the committed size.
- _eden_used = MIN2(_eden_used, _eden_committed);
- _young_region_num = young_region_num;
- }
+ assert(_survivor_space_used <= _survivor_space_committed, "post-condition");
+ assert(_old_gen_used <= _old_gen_committed, "post-condition");
}
void G1MonitoringSupport::update_sizes() {
recalculate_sizes();
if (UsePerfData) {
- eden_counters()->update_capacity(pad_capacity(eden_space_committed()));
- eden_counters()->update_used(eden_space_used());
- // only the to survivor space (s1) is active, so we don't need to
- // update the counters for the from survivor space (s0)
- to_counters()->update_capacity(pad_capacity(survivor_space_committed()));
- to_counters()->update_used(survivor_space_used());
- old_space_counters()->update_capacity(pad_capacity(old_space_committed()));
- old_space_counters()->update_used(old_space_used());
- old_collection_counters()->update_all();
- young_collection_counters()->update_all();
+ _eden_space_counters->update_capacity(pad_capacity(_eden_space_committed));
+ _eden_space_counters->update_used(_eden_space_used);
+ // only the "to" survivor space is active, so we don't need to
+ // update the counters for the "from" survivor space
+ _to_space_counters->update_capacity(pad_capacity(_survivor_space_committed));
+ _to_space_counters->update_used(_survivor_space_used);
+ _old_space_counters->update_capacity(pad_capacity(_old_gen_committed));
+ _old_space_counters->update_used(_old_gen_used);
+
+ _young_gen_counters->update_all();
+ _old_gen_counters->update_all();
+
MetaspaceCounters::update_performance_counters();
CompressedClassSpaceCounters::update_performance_counters();
}
}
void G1MonitoringSupport::update_eden_size() {
- recalculate_eden_size();
+ // Recalculate everything - this is fast enough.
+ recalculate_sizes();
if (UsePerfData) {
- eden_counters()->update_used(eden_space_used());
+ _eden_space_counters->update_used(_eden_space_used);
}
}
+
+G1MonitoringScope::G1MonitoringScope(G1MonitoringSupport* g1mm, bool full_gc, bool all_memory_pools_affected) :
+ _tcs(full_gc ? g1mm->_full_collection_counters : g1mm->_incremental_collection_counters),
+ _tms(full_gc ? &g1mm->_full_gc_memory_manager : &g1mm->_incremental_memory_manager,
+ G1CollectedHeap::heap()->gc_cause(), all_memory_pools_affected) {
+}
--- a/src/hotspot/share/gc/g1/g1MonitoringSupport.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1MonitoringSupport.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -25,11 +25,15 @@
#ifndef SHARE_VM_GC_G1_G1MONITORINGSUPPORT_HPP
#define SHARE_VM_GC_G1_G1MONITORINGSUPPORT_HPP
+#include "gc/shared/collectorCounters.hpp"
#include "gc/shared/generationCounters.hpp"
+#include "services/memoryManager.hpp"
+#include "services/memoryService.hpp"
class CollectorCounters;
class G1CollectedHeap;
class HSpaceCounters;
+class MemoryPool;
// Class for monitoring logical spaces in G1. It provides data for
// both G1's jstat counters as well as G1's memory pools.
@@ -116,9 +120,18 @@
class G1MonitoringSupport : public CHeapObj<mtGC> {
friend class VMStructs;
+ friend class G1MonitoringScope;
G1CollectedHeap* _g1h;
+ // java.lang.management MemoryManager and MemoryPool support
+ GCMemoryManager _incremental_memory_manager;
+ GCMemoryManager _full_gc_memory_manager;
+
+ MemoryPool* _eden_space_pool;
+ MemoryPool* _survivor_space_pool;
+ MemoryPool* _old_gen_pool;
+
// jstat performance counters
// incremental collections both young and mixed
CollectorCounters* _incremental_collection_counters;
@@ -129,37 +142,36 @@
// young collection set counters. The _eden_counters,
// _from_counters, and _to_counters are associated with
// this "generational" counter.
- GenerationCounters* _young_collection_counters;
+ GenerationCounters* _young_gen_counters;
// old collection set counters. The _old_space_counters
// below are associated with this "generational" counter.
- GenerationCounters* _old_collection_counters;
+ GenerationCounters* _old_gen_counters;
// Counters for the capacity and used for
// the whole heap
HSpaceCounters* _old_space_counters;
// the young collection
- HSpaceCounters* _eden_counters;
+ HSpaceCounters* _eden_space_counters;
// the survivor collection (only one, _to_counters, is actively used)
- HSpaceCounters* _from_counters;
- HSpaceCounters* _to_counters;
+ HSpaceCounters* _from_space_counters;
+ HSpaceCounters* _to_space_counters;
// When it's appropriate to recalculate the various sizes (at the
// end of a GC, when a new eden region is allocated, etc.) we store
// them here so that we can easily report them when needed and not
// have to recalculate them every time.
- size_t _overall_reserved;
size_t _overall_committed;
size_t _overall_used;
- uint _young_region_num;
size_t _young_gen_committed;
- size_t _eden_committed;
- size_t _eden_used;
- size_t _survivor_committed;
- size_t _survivor_used;
+ size_t _old_gen_committed;
- size_t _old_committed;
- size_t _old_used;
+ size_t _eden_space_committed;
+ size_t _eden_space_used;
+ size_t _survivor_space_committed;
+ size_t _survivor_space_used;
+
+ size_t _old_gen_used;
// It returns x - y if x > y, 0 otherwise.
// As described in the comment above, some of the inputs to the
@@ -178,11 +190,16 @@
// Recalculate all the sizes.
void recalculate_sizes();
- // Recalculate only what's necessary when a new eden region is allocated.
+
void recalculate_eden_size();
- public:
+public:
G1MonitoringSupport(G1CollectedHeap* g1h);
+ ~G1MonitoringSupport();
+
+ void initialize_serviceability();
+ GrowableArray<GCMemoryManager*> memory_managers();
+ GrowableArray<MemoryPool*> memory_pools();
// Unfortunately, the jstat tool assumes that no space has 0
// capacity. In our case, given that each space is logical, it's
@@ -202,73 +219,35 @@
// Recalculate all the sizes from scratch and update all the jstat
// counters accordingly.
void update_sizes();
- // Recalculate only what's necessary when a new eden region is
- // allocated and update any jstat counters that need to be updated.
+
void update_eden_size();
- CollectorCounters* incremental_collection_counters() {
- return _incremental_collection_counters;
- }
- CollectorCounters* full_collection_counters() {
- return _full_collection_counters;
- }
CollectorCounters* conc_collection_counters() {
return _conc_collection_counters;
}
- GenerationCounters* young_collection_counters() {
- return _young_collection_counters;
- }
- GenerationCounters* old_collection_counters() {
- return _old_collection_counters;
- }
- HSpaceCounters* old_space_counters() { return _old_space_counters; }
- HSpaceCounters* eden_counters() { return _eden_counters; }
- HSpaceCounters* from_counters() { return _from_counters; }
- HSpaceCounters* to_counters() { return _to_counters; }
// Monitoring support used by
// MemoryService
// jstat counters
// Tracing
- size_t overall_reserved() { return _overall_reserved; }
- size_t overall_committed() { return _overall_committed; }
- size_t overall_used() { return _overall_used; }
+ size_t young_gen_committed() { return _young_gen_committed; }
- size_t young_gen_committed() { return _young_gen_committed; }
- size_t young_gen_max() { return overall_reserved(); }
- size_t eden_space_committed() { return _eden_committed; }
- size_t eden_space_used() { return _eden_used; }
- size_t survivor_space_committed() { return _survivor_committed; }
- size_t survivor_space_used() { return _survivor_used; }
+ size_t eden_space_committed() { return _eden_space_committed; }
+ size_t eden_space_used() { return _eden_space_used; }
+ size_t survivor_space_committed() { return _survivor_space_committed; }
+ size_t survivor_space_used() { return _survivor_space_used; }
- size_t old_gen_committed() { return old_space_committed(); }
- size_t old_gen_max() { return overall_reserved(); }
- size_t old_space_committed() { return _old_committed; }
- size_t old_space_used() { return _old_used; }
+ size_t old_gen_committed() { return _old_gen_committed; }
+ size_t old_gen_used() { return _old_gen_used; }
};
-class G1GenerationCounters: public GenerationCounters {
-protected:
- G1MonitoringSupport* _g1mm;
-
+// Scope object for java.lang.management support.
+class G1MonitoringScope : public StackObj {
+ TraceCollectorStats _tcs;
+ TraceMemoryManagerStats _tms;
public:
- G1GenerationCounters(G1MonitoringSupport* g1mm,
- const char* name, int ordinal, int spaces,
- size_t min_capacity, size_t max_capacity,
- size_t curr_capacity);
-};
-
-class G1YoungGenerationCounters: public G1GenerationCounters {
-public:
- G1YoungGenerationCounters(G1MonitoringSupport* g1mm, const char* name);
- virtual void update_all();
-};
-
-class G1OldGenerationCounters: public G1GenerationCounters {
-public:
- G1OldGenerationCounters(G1MonitoringSupport* g1mm, const char* name);
- virtual void update_all();
+ G1MonitoringScope(G1MonitoringSupport* g1mm, bool full_gc, bool all_memory_pools_affected);
};
#endif // SHARE_VM_GC_G1_G1MONITORINGSUPPORT_HPP
--- a/src/hotspot/share/gc/g1/g1RemSet.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1RemSet.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -132,7 +132,7 @@
virtual bool do_heap_region(HeapRegion* r) {
uint hrm_index = r->hrm_index();
- if (!r->in_collection_set() && r->is_old_or_humongous()) {
+ if (!r->in_collection_set() && r->is_old_or_humongous_or_archive()) {
_scan_top[hrm_index] = r->top();
} else {
_scan_top[hrm_index] = r->bottom();
@@ -571,7 +571,7 @@
// In the normal (non-stale) case, the synchronization between the
// enqueueing of the card and processing it here will have ensured
// we see the up-to-date region type here.
- if (!r->is_old_or_humongous()) {
+ if (!r->is_old_or_humongous_or_archive()) {
return;
}
@@ -600,7 +600,7 @@
// Check whether the region formerly in the cache should be
// ignored, as discussed earlier for the original card. The
// region could have been freed while in the cache.
- if (!r->is_old_or_humongous()) {
+ if (!r->is_old_or_humongous_or_archive()) {
return;
}
} // Else we still have the original card.
--- a/src/hotspot/share/gc/g1/g1RemSetSummary.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1RemSetSummary.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -226,6 +226,7 @@
RegionTypeCounter _humongous;
RegionTypeCounter _free;
RegionTypeCounter _old;
+ RegionTypeCounter _archive;
RegionTypeCounter _all;
size_t _max_rs_mem_sz;
@@ -248,7 +249,7 @@
public:
HRRSStatsIter() : _young("Young"), _humongous("Humongous"),
- _free("Free"), _old("Old"), _all("All"),
+ _free("Free"), _old("Old"), _archive("Archive"), _all("All"),
_max_rs_mem_sz(0), _max_rs_mem_sz_region(NULL),
_max_code_root_mem_sz(0), _max_code_root_mem_sz_region(NULL)
{}
@@ -280,6 +281,8 @@
current = &_humongous;
} else if (r->is_old()) {
current = &_old;
+ } else if (r->is_archive()) {
+ current = &_archive;
} else {
ShouldNotReachHere();
}
@@ -290,7 +293,7 @@
}
void print_summary_on(outputStream* out) {
- RegionTypeCounter* counters[] = { &_young, &_humongous, &_free, &_old, NULL };
+ RegionTypeCounter* counters[] = { &_young, &_humongous, &_free, &_old, &_archive, NULL };
out->print_cr(" Current rem set statistics");
out->print_cr(" Total per region rem sets sizes = " SIZE_FORMAT "%s."
--- a/src/hotspot/share/gc/g1/g1RemSetTrackingPolicy.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1RemSetTrackingPolicy.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -141,8 +141,9 @@
void G1RemSetTrackingPolicy::update_after_rebuild(HeapRegion* r) {
assert(SafepointSynchronize::is_at_safepoint(), "should be at safepoint");
- if (r->is_old_or_humongous()) {
+ if (r->is_old_or_humongous_or_archive()) {
if (r->rem_set()->is_updating()) {
+ assert(!r->is_archive(), "Archive region %u with remembered set", r->hrm_index());
r->rem_set()->set_state_complete();
}
G1CollectedHeap* g1h = G1CollectedHeap::heap();
--- a/src/hotspot/share/gc/g1/g1SATBMarkQueueFilter.cpp Fri Aug 10 14:56:29 2018 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,107 +0,0 @@
-/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include "precompiled.hpp"
-#include "gc/g1/g1CollectedHeap.inline.hpp"
-#include "gc/g1/g1SATBMarkQueueFilter.hpp"
-#include "gc/g1/heapRegion.hpp"
-#include "gc/g1/satbMarkQueue.hpp"
-#include "oops/oop.hpp"
-#include "utilities/debug.hpp"
-#include "utilities/globalDefinitions.hpp"
-
-G1SATBMarkQueueFilter::G1SATBMarkQueueFilter(G1CollectedHeap* g1h) : _g1h(g1h) {}
-
-// Return true if a SATB buffer entry refers to an object that
-// requires marking.
-//
-// The entry must point into the G1 heap. In particular, it must not
-// be a NULL pointer. NULL pointers are pre-filtered and never
-// inserted into a SATB buffer.
-//
-// An entry that is below the NTAMS pointer for the containing heap
-// region requires marking. Such an entry must point to a valid object.
-//
-// An entry that is at least the NTAMS pointer for the containing heap
-// region might be any of the following, none of which should be marked.
-//
-// * A reference to an object allocated since marking started.
-// According to SATB, such objects are implicitly kept live and do
-// not need to be dealt with via SATB buffer processing.
-//
-// * A reference to a young generation object. Young objects are
-// handled separately and are not marked by concurrent marking.
-//
-// * A stale reference to a young generation object. If a young
-// generation object reference is recorded and not filtered out
-// before being moved by a young collection, the reference becomes
-// stale.
-//
-// * A stale reference to an eagerly reclaimed humongous object. If a
-// humongous object is recorded and then reclaimed, the reference
-// becomes stale.
-//
-// The stale reference cases are implicitly handled by the NTAMS
-// comparison. Because of the possibility of stale references, buffer
-// processing must be somewhat circumspect and not assume entries
-// in an unfiltered buffer refer to valid objects.
-
-static inline bool requires_marking(const void* entry, G1CollectedHeap* g1h) {
- // Includes rejection of NULL pointers.
- assert(g1h->is_in_reserved(entry),
- "Non-heap pointer in SATB buffer: " PTR_FORMAT, p2i(entry));
-
- HeapRegion* region = g1h->heap_region_containing(entry);
- assert(region != NULL, "No region for " PTR_FORMAT, p2i(entry));
- if (entry >= region->next_top_at_mark_start()) {
- return false;
- }
-
- assert(oopDesc::is_oop(oop(entry), true /* ignore mark word */),
- "Invalid oop in SATB buffer: " PTR_FORMAT, p2i(entry));
-
- return true;
-}
-
-static inline bool discard_entry(const void* entry, G1CollectedHeap* g1h) {
- return !requires_marking(entry, g1h) || g1h->is_marked_next((oop)entry);
-}
-
-// Workaround for not yet having std::bind.
-class G1SATBMarkQueueFilterFn {
- G1CollectedHeap* _g1h;
-
-public:
- G1SATBMarkQueueFilterFn(G1CollectedHeap* g1h) : _g1h(g1h) {}
-
- // Return true if entry should be filtered out (removed), false if
- // it should be retained.
- bool operator()(const void* entry) const {
- return discard_entry(entry, _g1h);
- }
-};
-
-void G1SATBMarkQueueFilter::filter(SATBMarkQueue* queue) {
- queue->apply_filter(G1SATBMarkQueueFilterFn(_g1h));
-}
--- a/src/hotspot/share/gc/g1/g1SATBMarkQueueFilter.hpp Fri Aug 10 14:56:29 2018 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
- * 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_GC_G1_G1SATBMARKQUEUEFILTER_HPP
-#define SHARE_GC_G1_G1SATBMARKQUEUEFILTER_HPP
-
-#include "gc/g1/satbMarkQueue.hpp"
-
-class G1CollectedHeap;
-
-class G1SATBMarkQueueFilter : public SATBMarkQueueFilter {
- G1CollectedHeap* _g1h;
-
-public:
- G1SATBMarkQueueFilter(G1CollectedHeap* g1h);
-
- virtual void filter(SATBMarkQueue* queue);
-};
-
-#endif // SHARE_GC_G1_G1SATBMARKQUEUEFILTER_HPP
--- a/src/hotspot/share/gc/g1/g1SATBMarkQueueSet.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1SATBMarkQueueSet.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -23,8 +23,28 @@
*/
#include "precompiled.hpp"
+#include "gc/g1/g1CollectedHeap.inline.hpp"
#include "gc/g1/g1SATBMarkQueueSet.hpp"
#include "gc/g1/g1ThreadLocalData.hpp"
+#include "gc/g1/heapRegion.hpp"
+#include "gc/shared/satbMarkQueue.hpp"
+#include "oops/oop.hpp"
+#include "utilities/debug.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+G1SATBMarkQueueSet::G1SATBMarkQueueSet() : _g1h(NULL) {}
+
+void G1SATBMarkQueueSet::initialize(G1CollectedHeap* g1h,
+ Monitor* cbl_mon, Mutex* fl_lock,
+ int process_completed_threshold,
+ uint buffer_enqueue_threshold_percentage,
+ Mutex* lock) {
+ SATBMarkQueueSet::initialize(cbl_mon, fl_lock,
+ process_completed_threshold,
+ buffer_enqueue_threshold_percentage,
+ lock);
+ _g1h = g1h;
+}
void G1SATBMarkQueueSet::handle_zero_index_for_thread(JavaThread* t) {
G1ThreadLocalData::satb_mark_queue(t).handle_zero_index();
@@ -33,3 +53,77 @@
SATBMarkQueue& G1SATBMarkQueueSet::satb_queue_for_thread(JavaThread* const t) const{
return G1ThreadLocalData::satb_mark_queue(t);
}
+
+// Return true if a SATB buffer entry refers to an object that
+// requires marking.
+//
+// The entry must point into the G1 heap. In particular, it must not
+// be a NULL pointer. NULL pointers are pre-filtered and never
+// inserted into a SATB buffer.
+//
+// An entry that is below the NTAMS pointer for the containing heap
+// region requires marking. Such an entry must point to a valid object.
+//
+// An entry that is at least the NTAMS pointer for the containing heap
+// region might be any of the following, none of which should be marked.
+//
+// * A reference to an object allocated since marking started.
+// According to SATB, such objects are implicitly kept live and do
+// not need to be dealt with via SATB buffer processing.
+//
+// * A reference to a young generation object. Young objects are
+// handled separately and are not marked by concurrent marking.
+//
+// * A stale reference to a young generation object. If a young
+// generation object reference is recorded and not filtered out
+// before being moved by a young collection, the reference becomes
+// stale.
+//
+// * A stale reference to an eagerly reclaimed humongous object. If a
+// humongous object is recorded and then reclaimed, the reference
+// becomes stale.
+//
+// The stale reference cases are implicitly handled by the NTAMS
+// comparison. Because of the possibility of stale references, buffer
+// processing must be somewhat circumspect and not assume entries
+// in an unfiltered buffer refer to valid objects.
+
+static inline bool requires_marking(const void* entry, G1CollectedHeap* g1h) {
+ // Includes rejection of NULL pointers.
+ assert(g1h->is_in_reserved(entry),
+ "Non-heap pointer in SATB buffer: " PTR_FORMAT, p2i(entry));
+
+ HeapRegion* region = g1h->heap_region_containing(entry);
+ assert(region != NULL, "No region for " PTR_FORMAT, p2i(entry));
+ if (entry >= region->next_top_at_mark_start()) {
+ return false;
+ }
+
+ assert(oopDesc::is_oop(oop(entry), true /* ignore mark word */),
+ "Invalid oop in SATB buffer: " PTR_FORMAT, p2i(entry));
+
+ return true;
+}
+
+static inline bool discard_entry(const void* entry, G1CollectedHeap* g1h) {
+ return !requires_marking(entry, g1h) || g1h->is_marked_next((oop)entry);
+}
+
+// Workaround for not yet having std::bind.
+class G1SATBMarkQueueFilterFn {
+ G1CollectedHeap* _g1h;
+
+public:
+ G1SATBMarkQueueFilterFn(G1CollectedHeap* g1h) : _g1h(g1h) {}
+
+ // Return true if entry should be filtered out (removed), false if
+ // it should be retained.
+ bool operator()(const void* entry) const {
+ return discard_entry(entry, _g1h);
+ }
+};
+
+void G1SATBMarkQueueSet::filter(SATBMarkQueue* queue) {
+ assert(_g1h != NULL, "SATB queue set not initialized");
+ apply_filter(G1SATBMarkQueueFilterFn(_g1h), queue);
+}
--- a/src/hotspot/share/gc/g1/g1SATBMarkQueueSet.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1SATBMarkQueueSet.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -25,14 +25,26 @@
#ifndef SHARE_VM_GC_G1_G1SATBMARKQUEUE_HPP
#define SHARE_VM_GC_G1_G1SATBMARKQUEUE_HPP
-#include "gc/g1/satbMarkQueue.hpp"
+#include "gc/shared/satbMarkQueue.hpp"
+class G1CollectedHeap;
class JavaThread;
class G1SATBMarkQueueSet : public SATBMarkQueueSet {
+ G1CollectedHeap* _g1h;
+
public:
+ G1SATBMarkQueueSet();
+
+ void initialize(G1CollectedHeap* g1h,
+ Monitor* cbl_mon, Mutex* fl_lock,
+ int process_completed_threshold,
+ uint buffer_enqueue_threshold_percentage,
+ Mutex* lock);
+
static void handle_zero_index_for_thread(JavaThread* t);
virtual SATBMarkQueue& satb_queue_for_thread(JavaThread* const t) const;
+ virtual void filter(SATBMarkQueue* queue);
};
#endif // SHARE_VM_GC_G1_G1SATBMARKQUEUE_HPP
--- a/src/hotspot/share/gc/g1/g1ThreadLocalData.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1ThreadLocalData.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -26,7 +26,7 @@
#include "gc/g1/dirtyCardQueue.hpp"
#include "gc/g1/g1BarrierSet.hpp"
-#include "gc/g1/satbMarkQueue.hpp"
+#include "gc/shared/satbMarkQueue.hpp"
#include "runtime/thread.hpp"
#include "utilities/debug.hpp"
#include "utilities/sizes.hpp"
--- a/src/hotspot/share/gc/g1/heapRegion.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/g1/heapRegion.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -426,6 +426,8 @@
bool is_old_or_humongous() const { return _type.is_old_or_humongous(); }
+ bool is_old_or_humongous_or_archive() const { return _type.is_old_or_humongous_or_archive(); }
+
// A pinned region contains objects which are not moved by garbage collections.
// Humongous regions and archive regions are pinned.
bool is_pinned() const { return _type.is_pinned(); }
--- a/src/hotspot/share/gc/g1/heapRegion.inline.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/g1/heapRegion.inline.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -350,7 +350,7 @@
if (is_humongous()) {
return do_oops_on_card_in_humongous<Closure, is_gc_active>(mr, cl, g1h);
}
- assert(is_old(), "precondition");
+ assert(is_old() || is_archive(), "Wrongly trying to iterate over region %u type %s", _hrm_index, get_type_str());
// Because mr has been trimmed to what's been allocated in this
// region, the parts of the heap that are examined here are always
--- a/src/hotspot/share/gc/g1/heapRegionManager.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/g1/heapRegionManager.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,41 @@
#include "gc/g1/heapRegionSet.inline.hpp"
#include "memory/allocation.hpp"
+class MasterFreeRegionListChecker : public HeapRegionSetChecker {
+public:
+ void check_mt_safety() {
+ // Master Free List MT safety protocol:
+ // (a) If we're at a safepoint, operations on the master free list
+ // should be invoked by either the VM thread (which will serialize
+ // them) or by the GC workers while holding the
+ // FreeList_lock.
+ // (b) If we're not at a safepoint, operations on the master free
+ // list should be invoked while holding the Heap_lock.
+
+ if (SafepointSynchronize::is_at_safepoint()) {
+ guarantee(Thread::current()->is_VM_thread() ||
+ FreeList_lock->owned_by_self(), "master free list MT safety protocol at a safepoint");
+ } else {
+ guarantee(Heap_lock->owned_by_self(), "master free list MT safety protocol outside a safepoint");
+ }
+ }
+ bool is_correct_type(HeapRegion* hr) { return hr->is_free(); }
+ const char* get_description() { return "Free Regions"; }
+};
+
+HeapRegionManager::HeapRegionManager() :
+ _regions(), _heap_mapper(NULL),
+ _prev_bitmap_mapper(NULL),
+ _next_bitmap_mapper(NULL),
+ _bot_mapper(NULL),
+ _cardtable_mapper(NULL),
+ _card_counts_mapper(NULL),
+ _free_list("Free list", new MasterFreeRegionListChecker()),
+ _available_map(mtGC),
+ _num_committed(0),
+ _allocated_heapregions_length(0)
+{ }
+
void HeapRegionManager::initialize(G1RegionToSpaceMapper* heap_storage,
G1RegionToSpaceMapper* prev_bitmap,
G1RegionToSpaceMapper* next_bitmap,
--- a/src/hotspot/share/gc/g1/heapRegionManager.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/g1/heapRegionManager.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -128,14 +128,7 @@
public:
// Empty constructor, we'll initialize it with the initialize() method.
- HeapRegionManager() :
- _regions(), _heap_mapper(NULL),
- _prev_bitmap_mapper(NULL), _next_bitmap_mapper(NULL), _bot_mapper(NULL),
- _cardtable_mapper(NULL), _card_counts_mapper(NULL),
- _free_list("Free list", new MasterFreeRegionListMtSafeChecker()),
- _available_map(mtGC), _num_committed(0),
- _allocated_heapregions_length(0)
- { }
+ HeapRegionManager();
void initialize(G1RegionToSpaceMapper* heap_storage,
G1RegionToSpaceMapper* prev_bitmap,
--- a/src/hotspot/share/gc/g1/heapRegionSet.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/g1/heapRegionSet.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -33,8 +33,8 @@
void HeapRegionSetBase::verify_region(HeapRegion* hr) {
assert(hr->containing_set() == this, "Inconsistent containing set for %u", hr->hrm_index());
assert(!hr->is_young(), "Adding young region %u", hr->hrm_index()); // currently we don't use these sets for young regions
- assert(hr->is_humongous() == regions_humongous(), "Wrong humongous state for region %u and set %s", hr->hrm_index(), name());
- assert(hr->is_free() == regions_free(), "Wrong free state for region %u and set %s", hr->hrm_index(), name());
+ assert(_checker == NULL || _checker->is_correct_type(hr), "Wrong type of region %u (%s) and set %s",
+ hr->hrm_index(), hr->get_type_str(), name());
assert(!hr->is_free() || hr->is_empty(), "Free region %u is not empty for set %s", hr->hrm_index(), name());
assert(!hr->is_empty() || hr->is_free() || hr->is_archive(),
"Empty region %u is not free or archive for set %s", hr->hrm_index(), name());
@@ -75,21 +75,14 @@
void HeapRegionSetBase::print_on(outputStream* out, bool print_contents) {
out->cr();
out->print_cr("Set: %s (" PTR_FORMAT ")", name(), p2i(this));
- out->print_cr(" Region Assumptions");
- out->print_cr(" humongous : %s", BOOL_TO_STR(regions_humongous()));
- out->print_cr(" free : %s", BOOL_TO_STR(regions_free()));
- out->print_cr(" Attributes");
- out->print_cr(" length : %14u", length());
+ out->print_cr(" Region Type : %s", _checker->get_description());
+ out->print_cr(" Length : %14u", length());
}
-HeapRegionSetBase::HeapRegionSetBase(const char* name, bool humongous, bool free, HRSMtSafeChecker* mt_safety_checker)
- : _is_humongous(humongous),
- _is_free(free),
- _mt_safety_checker(mt_safety_checker),
- _length(0),
- _name(name),
- _verify_in_progress(false)
-{ }
+HeapRegionSetBase::HeapRegionSetBase(const char* name, HeapRegionSetChecker* checker)
+ : _checker(checker), _length(0), _name(name), _verify_in_progress(false)
+{
+}
void FreeRegionList::set_unrealistically_long_length(uint len) {
guarantee(_unrealistically_long_length == 0, "should only be set once");
@@ -295,73 +288,3 @@
guarantee(_tail == NULL || _tail->next() == NULL, "_tail should not have a next");
guarantee(length() == count, "%s count mismatch. Expected %u, actual %u.", name(), length(), count);
}
-
-// Note on the check_mt_safety() methods below:
-//
-// Verification of the "master" heap region sets / lists that are
-// maintained by G1CollectedHeap is always done during a STW pause and
-// by the VM thread at the start / end of the pause. The standard
-// verification methods all assert check_mt_safety(). This is
-// important as it ensures that verification is done without
-// concurrent updates taking place at the same time. It follows, that,
-// for the "master" heap region sets / lists, the check_mt_safety()
-// method should include the VM thread / STW case.
-
-void MasterFreeRegionListMtSafeChecker::check() {
- // Master Free List MT safety protocol:
- // (a) If we're at a safepoint, operations on the master free list
- // should be invoked by either the VM thread (which will serialize
- // them) or by the GC workers while holding the
- // FreeList_lock.
- // (b) If we're not at a safepoint, operations on the master free
- // list should be invoked while holding the Heap_lock.
-
- if (SafepointSynchronize::is_at_safepoint()) {
- guarantee(Thread::current()->is_VM_thread() ||
- FreeList_lock->owned_by_self(), "master free list MT safety protocol at a safepoint");
- } else {
- guarantee(Heap_lock->owned_by_self(), "master free list MT safety protocol outside a safepoint");
- }
-}
-
-void OldRegionSetMtSafeChecker::check() {
- // Master Old Set MT safety protocol:
- // (a) If we're at a safepoint, operations on the master old set
- // should be invoked:
- // - by the VM thread (which will serialize them), or
- // - by the GC workers while holding the FreeList_lock, if we're
- // at a safepoint for an evacuation pause (this lock is taken
- // anyway when an GC alloc region is retired so that a new one
- // is allocated from the free list), or
- // - by the GC workers while holding the OldSets_lock, if we're at a
- // safepoint for a cleanup pause.
- // (b) If we're not at a safepoint, operations on the master old set
- // should be invoked while holding the Heap_lock.
-
- if (SafepointSynchronize::is_at_safepoint()) {
- guarantee(Thread::current()->is_VM_thread()
- || FreeList_lock->owned_by_self() || OldSets_lock->owned_by_self(),
- "master old set MT safety protocol at a safepoint");
- } else {
- guarantee(Heap_lock->owned_by_self(), "master old set MT safety protocol outside a safepoint");
- }
-}
-
-void HumongousRegionSetMtSafeChecker::check() {
- // Humongous Set MT safety protocol:
- // (a) If we're at a safepoint, operations on the master humongous
- // set should be invoked by either the VM thread (which will
- // serialize them) or by the GC workers while holding the
- // OldSets_lock.
- // (b) If we're not at a safepoint, operations on the master
- // humongous set should be invoked while holding the Heap_lock.
-
- if (SafepointSynchronize::is_at_safepoint()) {
- guarantee(Thread::current()->is_VM_thread() ||
- OldSets_lock->owned_by_self(),
- "master humongous set MT safety protocol at a safepoint");
- } else {
- guarantee(Heap_lock->owned_by_self(),
- "master humongous set MT safety protocol outside a safepoint");
- }
-}
--- a/src/hotspot/share/gc/g1/heapRegionSet.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/g1/heapRegionSet.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -47,15 +47,18 @@
} while (0)
-class HRSMtSafeChecker : public CHeapObj<mtGC> {
+// Interface collecting various instance specific verification methods of
+// HeapRegionSets.
+class HeapRegionSetChecker : public CHeapObj<mtGC> {
public:
- virtual void check() = 0;
+ // Verify MT safety for this HeapRegionSet.
+ virtual void check_mt_safety() = 0;
+ // Returns true if the given HeapRegion is of the correct type for this HeapRegionSet.
+ virtual bool is_correct_type(HeapRegion* hr) = 0;
+ // Return a description of the type of regions this HeapRegionSet contains.
+ virtual const char* get_description() = 0;
};
-class MasterFreeRegionListMtSafeChecker : public HRSMtSafeChecker { public: void check(); };
-class HumongousRegionSetMtSafeChecker : public HRSMtSafeChecker { public: void check(); };
-class OldRegionSetMtSafeChecker : public HRSMtSafeChecker { public: void check(); };
-
// Base class for all the classes that represent heap region sets. It
// contains the basic attributes that each set needs to maintain
// (e.g., length, region num, used bytes sum) plus any shared
@@ -63,10 +66,8 @@
class HeapRegionSetBase {
friend class VMStructs;
-private:
- bool _is_humongous;
- bool _is_free;
- HRSMtSafeChecker* _mt_safety_checker;
+
+ HeapRegionSetChecker* _checker;
protected:
// The number of regions in to the set.
@@ -80,21 +81,13 @@
// added to / removed from a set are consistent.
void verify_region(HeapRegion* hr) PRODUCT_RETURN;
- // Indicates whether all regions in the set should be humongous or
- // not. Only used during verification.
- bool regions_humongous() { return _is_humongous; }
-
- // Indicates whether all regions in the set should be free or
- // not. Only used during verification.
- bool regions_free() { return _is_free; }
-
void check_mt_safety() {
- if (_mt_safety_checker != NULL) {
- _mt_safety_checker->check();
+ if (_checker != NULL) {
+ _checker->check_mt_safety();
}
}
- HeapRegionSetBase(const char* name, bool humongous, bool free, HRSMtSafeChecker* mt_safety_checker);
+ HeapRegionSetBase(const char* name, HeapRegionSetChecker* verifier);
public:
const char* name() { return _name; }
@@ -121,15 +114,6 @@
virtual void print_on(outputStream* out, bool print_contents = false);
};
-#define hrs_assert_sets_match(_set1_, _set2_) \
- do { \
- assert(((_set1_)->regions_humongous() == (_set2_)->regions_humongous()) && \
- ((_set1_)->regions_free() == (_set2_)->regions_free()), \
- "the contents of set %s and set %s should match", \
- (_set1_)->name(), \
- (_set2_)->name()); \
- } while (0)
-
// This class represents heap region sets whose members are not
// explicitly tracked. It's helpful to group regions using such sets
// so that we can reason about all the region groups in the heap using
@@ -137,8 +121,9 @@
class HeapRegionSet : public HeapRegionSetBase {
public:
- HeapRegionSet(const char* name, bool humongous, HRSMtSafeChecker* mt_safety_checker):
- HeapRegionSetBase(name, humongous, false /* free */, mt_safety_checker) { }
+ HeapRegionSet(const char* name, HeapRegionSetChecker* checker):
+ HeapRegionSetBase(name, checker) {
+ }
void bulk_remove(const uint removed) {
_length -= removed;
@@ -173,8 +158,8 @@
virtual void clear();
public:
- FreeRegionList(const char* name, HRSMtSafeChecker* mt_safety_checker = NULL):
- HeapRegionSetBase(name, false /* humongous */, true /* empty */, mt_safety_checker) {
+ FreeRegionList(const char* name, HeapRegionSetChecker* checker = NULL):
+ HeapRegionSetBase(name, checker) {
clear();
}
--- a/src/hotspot/share/gc/g1/heapRegionType.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/g1/heapRegionType.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -86,8 +86,8 @@
// Objects within these regions are allowed to have references to objects
// contained in any other kind of regions.
ArchiveMask = 32,
- OpenArchiveTag = ArchiveMask | PinnedMask | OldMask,
- ClosedArchiveTag = ArchiveMask | PinnedMask | OldMask + 1
+ OpenArchiveTag = ArchiveMask | PinnedMask,
+ ClosedArchiveTag = ArchiveMask | PinnedMask + 1
} Tag;
volatile Tag _tag;
@@ -139,6 +139,8 @@
bool is_old_or_humongous() const { return (get() & (OldMask | HumongousMask)) != 0; }
+ bool is_old_or_humongous_or_archive() const { return (get() & (OldMask | HumongousMask | ArchiveMask)) != 0; }
+
// is_pinned regions may be archive or humongous
bool is_pinned() const { return (get() & PinnedMask) != 0; }
--- a/src/hotspot/share/gc/g1/ptrQueue.cpp Fri Aug 10 14:56:29 2018 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,314 +0,0 @@
-/*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include "precompiled.hpp"
-#include "gc/g1/ptrQueue.hpp"
-#include "memory/allocation.hpp"
-#include "memory/allocation.inline.hpp"
-#include "runtime/mutex.hpp"
-#include "runtime/mutexLocker.hpp"
-#include "runtime/thread.inline.hpp"
-
-#include <new>
-
-PtrQueue::PtrQueue(PtrQueueSet* qset, bool permanent, bool active) :
- _qset(qset),
- _active(active),
- _permanent(permanent),
- _index(0),
- _capacity_in_bytes(0),
- _buf(NULL),
- _lock(NULL)
-{}
-
-PtrQueue::~PtrQueue() {
- assert(_permanent || (_buf == NULL), "queue must be flushed before delete");
-}
-
-void PtrQueue::flush_impl() {
- if (_buf != NULL) {
- BufferNode* node = BufferNode::make_node_from_buffer(_buf, index());
- if (is_empty()) {
- // No work to do.
- qset()->deallocate_buffer(node);
- } else {
- qset()->enqueue_complete_buffer(node);
- }
- _buf = NULL;
- set_index(0);
- }
-}
-
-
-void PtrQueue::enqueue_known_active(void* ptr) {
- while (_index == 0) {
- handle_zero_index();
- }
-
- assert(_buf != NULL, "postcondition");
- assert(index() > 0, "postcondition");
- assert(index() <= capacity(), "invariant");
- _index -= _element_size;
- _buf[index()] = ptr;
-}
-
-void PtrQueue::locking_enqueue_completed_buffer(BufferNode* node) {
- assert(_lock->owned_by_self(), "Required.");
- qset()->enqueue_complete_buffer(node);
-}
-
-
-BufferNode* BufferNode::allocate(size_t size) {
- size_t byte_size = size * sizeof(void*);
- void* data = NEW_C_HEAP_ARRAY(char, buffer_offset() + byte_size, mtGC);
- return new (data) BufferNode;
-}
-
-void BufferNode::deallocate(BufferNode* node) {
- node->~BufferNode();
- FREE_C_HEAP_ARRAY(char, node);
-}
-
-PtrQueueSet::PtrQueueSet(bool notify_when_complete) :
- _buffer_size(0),
- _cbl_mon(NULL),
- _completed_buffers_head(NULL),
- _completed_buffers_tail(NULL),
- _n_completed_buffers(0),
- _process_completed_threshold(0),
- _process_completed(false),
- _fl_lock(NULL),
- _buf_free_list(NULL),
- _buf_free_list_sz(0),
- _fl_owner(NULL),
- _all_active(false),
- _notify_when_complete(notify_when_complete),
- _max_completed_queue(0),
- _completed_queue_padding(0)
-{
- _fl_owner = this;
-}
-
-PtrQueueSet::~PtrQueueSet() {
- // There are presently only a couple (derived) instances ever
- // created, and they are permanent, so no harm currently done by
- // doing nothing here.
-}
-
-void PtrQueueSet::initialize(Monitor* cbl_mon,
- Mutex* fl_lock,
- int process_completed_threshold,
- int max_completed_queue,
- PtrQueueSet *fl_owner) {
- _max_completed_queue = max_completed_queue;
- _process_completed_threshold = process_completed_threshold;
- _completed_queue_padding = 0;
- assert(cbl_mon != NULL && fl_lock != NULL, "Init order issue?");
- _cbl_mon = cbl_mon;
- _fl_lock = fl_lock;
- _fl_owner = (fl_owner != NULL) ? fl_owner : this;
-}
-
-void** PtrQueueSet::allocate_buffer() {
- BufferNode* node = NULL;
- {
- MutexLockerEx x(_fl_owner->_fl_lock, Mutex::_no_safepoint_check_flag);
- node = _fl_owner->_buf_free_list;
- if (node != NULL) {
- _fl_owner->_buf_free_list = node->next();
- _fl_owner->_buf_free_list_sz--;
- }
- }
- if (node == NULL) {
- node = BufferNode::allocate(buffer_size());
- } else {
- // Reinitialize buffer obtained from free list.
- node->set_index(0);
- node->set_next(NULL);
- }
- return BufferNode::make_buffer_from_node(node);
-}
-
-void PtrQueueSet::deallocate_buffer(BufferNode* node) {
- MutexLockerEx x(_fl_owner->_fl_lock, Mutex::_no_safepoint_check_flag);
- node->set_next(_fl_owner->_buf_free_list);
- _fl_owner->_buf_free_list = node;
- _fl_owner->_buf_free_list_sz++;
-}
-
-void PtrQueueSet::reduce_free_list() {
- assert(_fl_owner == this, "Free list reduction is allowed only for the owner");
- // For now we'll adopt the strategy of deleting half.
- MutexLockerEx x(_fl_lock, Mutex::_no_safepoint_check_flag);
- size_t n = _buf_free_list_sz / 2;
- for (size_t i = 0; i < n; ++i) {
- assert(_buf_free_list != NULL,
- "_buf_free_list_sz is wrong: " SIZE_FORMAT, _buf_free_list_sz);
- BufferNode* node = _buf_free_list;
- _buf_free_list = node->next();
- _buf_free_list_sz--;
- BufferNode::deallocate(node);
- }
-}
-
-void PtrQueue::handle_zero_index() {
- assert(index() == 0, "precondition");
-
- // This thread records the full buffer and allocates a new one (while
- // holding the lock if there is one).
- if (_buf != NULL) {
- if (!should_enqueue_buffer()) {
- assert(index() > 0, "the buffer can only be re-used if it's not full");
- return;
- }
-
- if (_lock) {
- assert(_lock->owned_by_self(), "Required.");
-
- BufferNode* node = BufferNode::make_node_from_buffer(_buf, index());
- _buf = NULL; // clear shared _buf field
-
- locking_enqueue_completed_buffer(node); // enqueue completed buffer
- assert(_buf == NULL, "multiple enqueuers appear to be racing");
- } else {
- BufferNode* node = BufferNode::make_node_from_buffer(_buf, index());
- if (qset()->process_or_enqueue_complete_buffer(node)) {
- // Recycle the buffer. No allocation.
- assert(_buf == BufferNode::make_buffer_from_node(node), "invariant");
- assert(capacity() == qset()->buffer_size(), "invariant");
- reset();
- return;
- }
- }
- }
- // Set capacity in case this is the first allocation.
- set_capacity(qset()->buffer_size());
- // Allocate a new buffer.
- _buf = qset()->allocate_buffer();
- reset();
-}
-
-bool PtrQueueSet::process_or_enqueue_complete_buffer(BufferNode* node) {
- if (Thread::current()->is_Java_thread()) {
- // We don't lock. It is fine to be epsilon-precise here.
- if (_max_completed_queue == 0 ||
- (_max_completed_queue > 0 &&
- _n_completed_buffers >= _max_completed_queue + _completed_queue_padding)) {
- bool b = mut_process_buffer(node);
- if (b) {
- // True here means that the buffer hasn't been deallocated and the caller may reuse it.
- return true;
- }
- }
- }
- // The buffer will be enqueued. The caller will have to get a new one.
- enqueue_complete_buffer(node);
- return false;
-}
-
-void PtrQueueSet::enqueue_complete_buffer(BufferNode* cbn) {
- MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
- cbn->set_next(NULL);
- if (_completed_buffers_tail == NULL) {
- assert(_completed_buffers_head == NULL, "Well-formedness");
- _completed_buffers_head = cbn;
- _completed_buffers_tail = cbn;
- } else {
- _completed_buffers_tail->set_next(cbn);
- _completed_buffers_tail = cbn;
- }
- _n_completed_buffers++;
-
- if (!_process_completed && _process_completed_threshold >= 0 &&
- _n_completed_buffers >= (size_t)_process_completed_threshold) {
- _process_completed = true;
- if (_notify_when_complete) {
- _cbl_mon->notify();
- }
- }
- DEBUG_ONLY(assert_completed_buffer_list_len_correct_locked());
-}
-
-size_t PtrQueueSet::completed_buffers_list_length() {
- size_t n = 0;
- BufferNode* cbn = _completed_buffers_head;
- while (cbn != NULL) {
- n++;
- cbn = cbn->next();
- }
- return n;
-}
-
-void PtrQueueSet::assert_completed_buffer_list_len_correct() {
- MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
- assert_completed_buffer_list_len_correct_locked();
-}
-
-void PtrQueueSet::assert_completed_buffer_list_len_correct_locked() {
- guarantee(completed_buffers_list_length() == _n_completed_buffers,
- "Completed buffer length is wrong.");
-}
-
-void PtrQueueSet::set_buffer_size(size_t sz) {
- assert(_buffer_size == 0 && sz > 0, "Should be called only once.");
- _buffer_size = sz;
-}
-
-// Merge lists of buffers. Notify the processing threads.
-// The source queue is emptied as a result. The queues
-// must share the monitor.
-void PtrQueueSet::merge_bufferlists(PtrQueueSet *src) {
- assert(_cbl_mon == src->_cbl_mon, "Should share the same lock");
- MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
- if (_completed_buffers_tail == NULL) {
- assert(_completed_buffers_head == NULL, "Well-formedness");
- _completed_buffers_head = src->_completed_buffers_head;
- _completed_buffers_tail = src->_completed_buffers_tail;
- } else {
- assert(_completed_buffers_head != NULL, "Well formedness");
- if (src->_completed_buffers_head != NULL) {
- _completed_buffers_tail->set_next(src->_completed_buffers_head);
- _completed_buffers_tail = src->_completed_buffers_tail;
- }
- }
- _n_completed_buffers += src->_n_completed_buffers;
-
- src->_n_completed_buffers = 0;
- src->_completed_buffers_head = NULL;
- src->_completed_buffers_tail = NULL;
-
- assert(_completed_buffers_head == NULL && _completed_buffers_tail == NULL ||
- _completed_buffers_head != NULL && _completed_buffers_tail != NULL,
- "Sanity");
-}
-
-void PtrQueueSet::notify_if_necessary() {
- MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
- assert(_process_completed_threshold >= 0, "_process_completed is negative");
- if (_n_completed_buffers >= (size_t)_process_completed_threshold || _max_completed_queue == 0) {
- _process_completed = true;
- if (_notify_when_complete)
- _cbl_mon->notify();
- }
-}
--- a/src/hotspot/share/gc/g1/ptrQueue.hpp Fri Aug 10 14:56:29 2018 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,371 +0,0 @@
-/*
- * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#ifndef SHARE_VM_GC_G1_PTRQUEUE_HPP
-#define SHARE_VM_GC_G1_PTRQUEUE_HPP
-
-#include "utilities/align.hpp"
-#include "utilities/sizes.hpp"
-
-// There are various techniques that require threads to be able to log
-// addresses. For example, a generational write barrier might log
-// the addresses of modified old-generation objects. This type supports
-// this operation.
-
-class BufferNode;
-class PtrQueueSet;
-class PtrQueue {
- friend class VMStructs;
-
- // Noncopyable - not defined.
- PtrQueue(const PtrQueue&);
- PtrQueue& operator=(const PtrQueue&);
-
- // The ptr queue set to which this queue belongs.
- PtrQueueSet* const _qset;
-
- // Whether updates should be logged.
- bool _active;
-
- // If true, the queue is permanent, and doesn't need to deallocate
- // its buffer in the destructor (since that obtains a lock which may not
- // be legally locked by then.
- const bool _permanent;
-
- // The (byte) index at which an object was last enqueued. Starts at
- // capacity_in_bytes (indicating an empty buffer) and goes towards zero.
- // Value is always pointer-size aligned.
- size_t _index;
-
- // Size of the current buffer, in bytes.
- // Value is always pointer-size aligned.
- size_t _capacity_in_bytes;
-
- static const size_t _element_size = sizeof(void*);
-
- // Get the capacity, in bytes. The capacity must have been set.
- size_t capacity_in_bytes() const {
- assert(_capacity_in_bytes > 0, "capacity not set");
- return _capacity_in_bytes;
- }
-
- void set_capacity(size_t entries) {
- size_t byte_capacity = index_to_byte_index(entries);
- assert(_capacity_in_bytes == 0 || _capacity_in_bytes == byte_capacity,
- "changing capacity " SIZE_FORMAT " -> " SIZE_FORMAT,
- _capacity_in_bytes, byte_capacity);
- _capacity_in_bytes = byte_capacity;
- }
-
- static size_t byte_index_to_index(size_t ind) {
- assert(is_aligned(ind, _element_size), "precondition");
- return ind / _element_size;
- }
-
- static size_t index_to_byte_index(size_t ind) {
- return ind * _element_size;
- }
-
-protected:
- // The buffer.
- void** _buf;
-
- size_t index() const {
- return byte_index_to_index(_index);
- }
-
- void set_index(size_t new_index) {
- size_t byte_index = index_to_byte_index(new_index);
- assert(byte_index <= capacity_in_bytes(), "precondition");
- _index = byte_index;
- }
-
- size_t capacity() const {
- return byte_index_to_index(capacity_in_bytes());
- }
-
- // If there is a lock associated with this buffer, this is that lock.
- Mutex* _lock;
-
- PtrQueueSet* qset() { return _qset; }
- bool is_permanent() const { return _permanent; }
-
- // Process queue entries and release resources.
- void flush_impl();
-
- // Initialize this queue to contain a null buffer, and be part of the
- // given PtrQueueSet.
- PtrQueue(PtrQueueSet* qset, bool permanent = false, bool active = false);
-
- // Requires queue flushed or permanent.
- ~PtrQueue();
-
-public:
-
- // Associate a lock with a ptr queue.
- void set_lock(Mutex* lock) { _lock = lock; }
-
- // Forcibly set empty.
- void reset() {
- if (_buf != NULL) {
- _index = capacity_in_bytes();
- }
- }
-
- void enqueue(volatile void* ptr) {
- enqueue((void*)(ptr));
- }
-
- // Enqueues the given "obj".
- void enqueue(void* ptr) {
- if (!_active) return;
- else enqueue_known_active(ptr);
- }
-
- // This method is called when we're doing the zero index handling
- // and gives a chance to the queues to do any pre-enqueueing
- // processing they might want to do on the buffer. It should return
- // true if the buffer should be enqueued, or false if enough
- // entries were cleared from it so that it can be re-used. It should
- // not return false if the buffer is still full (otherwise we can
- // get into an infinite loop).
- virtual bool should_enqueue_buffer() { return true; }
- void handle_zero_index();
- void locking_enqueue_completed_buffer(BufferNode* node);
-
- void enqueue_known_active(void* ptr);
-
- // Return the size of the in-use region.
- size_t size() const {
- size_t result = 0;
- if (_buf != NULL) {
- assert(_index <= capacity_in_bytes(), "Invariant");
- result = byte_index_to_index(capacity_in_bytes() - _index);
- }
- return result;
- }
-
- bool is_empty() const {
- return _buf == NULL || capacity_in_bytes() == _index;
- }
-
- // Set the "active" property of the queue to "b". An enqueue to an
- // inactive thread is a no-op. Setting a queue to inactive resets its
- // log to the empty state.
- void set_active(bool b) {
- _active = b;
- if (!b && _buf != NULL) {
- reset();
- } else if (b && _buf != NULL) {
- assert(index() == capacity(),
- "invariant: queues are empty when activated.");
- }
- }
-
- bool is_active() const { return _active; }
-
- // To support compiler.
-
-protected:
- template<typename Derived>
- static ByteSize byte_offset_of_index() {
- return byte_offset_of(Derived, _index);
- }
-
- static ByteSize byte_width_of_index() { return in_ByteSize(sizeof(size_t)); }
-
- template<typename Derived>
- static ByteSize byte_offset_of_buf() {
- return byte_offset_of(Derived, _buf);
- }
-
- static ByteSize byte_width_of_buf() { return in_ByteSize(_element_size); }
-
- template<typename Derived>
- static ByteSize byte_offset_of_active() {
- return byte_offset_of(Derived, _active);
- }
-
- static ByteSize byte_width_of_active() { return in_ByteSize(sizeof(bool)); }
-
-};
-
-class BufferNode {
- size_t _index;
- BufferNode* _next;
- void* _buffer[1]; // Pseudo flexible array member.
-
- BufferNode() : _index(0), _next(NULL) { }
- ~BufferNode() { }
-
- static size_t buffer_offset() {
- return offset_of(BufferNode, _buffer);
- }
-
-public:
- BufferNode* next() const { return _next; }
- void set_next(BufferNode* n) { _next = n; }
- size_t index() const { return _index; }
- void set_index(size_t i) { _index = i; }
-
- // Allocate a new BufferNode with the "buffer" having size elements.
- static BufferNode* allocate(size_t size);
-
- // Free a BufferNode.
- static void deallocate(BufferNode* node);
-
- // Return the BufferNode containing the buffer, after setting its index.
- static BufferNode* make_node_from_buffer(void** buffer, size_t index) {
- BufferNode* node =
- reinterpret_cast<BufferNode*>(
- reinterpret_cast<char*>(buffer) - buffer_offset());
- node->set_index(index);
- return node;
- }
-
- // Return the buffer for node.
- static void** make_buffer_from_node(BufferNode *node) {
- // &_buffer[0] might lead to index out of bounds warnings.
- return reinterpret_cast<void**>(
- reinterpret_cast<char*>(node) + buffer_offset());
- }
-};
-
-// A PtrQueueSet represents resources common to a set of pointer queues.
-// In particular, the individual queues allocate buffers from this shared
-// set, and return completed buffers to the set.
-// All these variables are are protected by the TLOQ_CBL_mon. XXX ???
-class PtrQueueSet {
- // The size of all buffers in the set.
- size_t _buffer_size;
-
-protected:
- Monitor* _cbl_mon; // Protects the fields below.
- BufferNode* _completed_buffers_head;
- BufferNode* _completed_buffers_tail;
- size_t _n_completed_buffers;
- int _process_completed_threshold;
- volatile bool _process_completed;
-
- // This (and the interpretation of the first element as a "next"
- // pointer) are protected by the TLOQ_FL_lock.
- Mutex* _fl_lock;
- BufferNode* _buf_free_list;
- size_t _buf_free_list_sz;
- // Queue set can share a freelist. The _fl_owner variable
- // specifies the owner. It is set to "this" by default.
- PtrQueueSet* _fl_owner;
-
- bool _all_active;
-
- // If true, notify_all on _cbl_mon when the threshold is reached.
- bool _notify_when_complete;
-
- // Maximum number of elements allowed on completed queue: after that,
- // enqueuer does the work itself. Zero indicates no maximum.
- int _max_completed_queue;
- size_t _completed_queue_padding;
-
- size_t completed_buffers_list_length();
- void assert_completed_buffer_list_len_correct_locked();
- void assert_completed_buffer_list_len_correct();
-
-protected:
- // A mutator thread does the the work of processing a buffer.
- // Returns "true" iff the work is complete (and the buffer may be
- // deallocated).
- virtual bool mut_process_buffer(BufferNode* node) {
- ShouldNotReachHere();
- return false;
- }
-
- // Create an empty ptr queue set.
- PtrQueueSet(bool notify_when_complete = false);
- ~PtrQueueSet();
-
- // Because of init-order concerns, we can't pass these as constructor
- // arguments.
- void initialize(Monitor* cbl_mon,
- Mutex* fl_lock,
- int process_completed_threshold,
- int max_completed_queue,
- PtrQueueSet *fl_owner = NULL);
-
-public:
-
- // Return the buffer for a BufferNode of size buffer_size().
- void** allocate_buffer();
-
- // Return an empty buffer to the free list. The node is required
- // to have been allocated with a size of buffer_size().
- void deallocate_buffer(BufferNode* node);
-
- // Declares that "buf" is a complete buffer.
- void enqueue_complete_buffer(BufferNode* node);
-
- // To be invoked by the mutator.
- bool process_or_enqueue_complete_buffer(BufferNode* node);
-
- bool completed_buffers_exist_dirty() {
- return _n_completed_buffers > 0;
- }
-
- bool process_completed_buffers() { return _process_completed; }
- void set_process_completed(bool x) { _process_completed = x; }
-
- bool is_active() { return _all_active; }
-
- // Set the buffer size. Should be called before any "enqueue" operation
- // can be called. And should only be called once.
- void set_buffer_size(size_t sz);
-
- // Get the buffer size. Must have been set.
- size_t buffer_size() const {
- assert(_buffer_size > 0, "buffer size not set");
- return _buffer_size;
- }
-
- // Get/Set the number of completed buffers that triggers log processing.
- void set_process_completed_threshold(int sz) { _process_completed_threshold = sz; }
- int process_completed_threshold() const { return _process_completed_threshold; }
-
- // Must only be called at a safe point. Indicates that the buffer free
- // list size may be reduced, if that is deemed desirable.
- void reduce_free_list();
-
- size_t completed_buffers_num() { return _n_completed_buffers; }
-
- void merge_bufferlists(PtrQueueSet* src);
-
- void set_max_completed_queue(int m) { _max_completed_queue = m; }
- int max_completed_queue() { return _max_completed_queue; }
-
- void set_completed_queue_padding(size_t padding) { _completed_queue_padding = padding; }
- size_t completed_queue_padding() { return _completed_queue_padding; }
-
- // Notify the consumer if the number of buffers crossed the threshold
- void notify_if_necessary();
-};
-
-#endif // SHARE_VM_GC_G1_PTRQUEUE_HPP
--- a/src/hotspot/share/gc/g1/satbMarkQueue.cpp Fri Aug 10 14:56:29 2018 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,255 +0,0 @@
-/*
- * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
- * 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 "jvm.h"
-#include "gc/g1/g1CollectedHeap.inline.hpp"
-#include "gc/g1/satbMarkQueue.hpp"
-#include "gc/shared/collectedHeap.hpp"
-#include "memory/allocation.inline.hpp"
-#include "oops/oop.inline.hpp"
-#include "runtime/mutexLocker.hpp"
-#include "runtime/safepoint.hpp"
-#include "runtime/thread.hpp"
-#include "runtime/threadSMR.hpp"
-#include "runtime/vmThread.hpp"
-
-SATBMarkQueue::SATBMarkQueue(SATBMarkQueueSet* qset, bool permanent) :
- // SATB queues are only active during marking cycles. We create
- // them with their active field set to false. If a thread is
- // created during a cycle and its SATB queue needs to be activated
- // before the thread starts running, we'll need to set its active
- // field to true. This is done in G1SBarrierSet::on_thread_attach().
- PtrQueue(qset, permanent, false /* active */)
-{ }
-
-void SATBMarkQueue::flush() {
- // Filter now to possibly save work later. If filtering empties the
- // buffer then flush_impl can deallocate the buffer.
- filter();
- flush_impl();
-}
-
-// This method will first apply filtering to the buffer. If filtering
-// retains a small enough collection in the buffer, we can continue to
-// use the buffer as-is, instead of enqueueing and replacing it.
-
-bool SATBMarkQueue::should_enqueue_buffer() {
- assert(_lock == NULL || _lock->owned_by_self(),
- "we should have taken the lock before calling this");
-
- // If G1SATBBufferEnqueueingThresholdPercent == 0 we could skip filtering.
-
- // This method should only be called if there is a non-NULL buffer
- // that is full.
- assert(index() == 0, "pre-condition");
- assert(_buf != NULL, "pre-condition");
-
- filter();
-
- size_t cap = capacity();
- size_t percent_used = ((cap - index()) * 100) / cap;
- bool should_enqueue = percent_used > G1SATBBufferEnqueueingThresholdPercent;
- return should_enqueue;
-}
-
-void SATBMarkQueue::apply_closure_and_empty(SATBBufferClosure* cl) {
- assert(SafepointSynchronize::is_at_safepoint(),
- "SATB queues must only be processed at safepoints");
- if (_buf != NULL) {
- cl->do_buffer(&_buf[index()], size());
- reset();
- }
-}
-
-#ifndef PRODUCT
-// Helpful for debugging
-
-static void print_satb_buffer(const char* name,
- void** buf,
- size_t index,
- size_t capacity) {
- tty->print_cr(" SATB BUFFER [%s] buf: " PTR_FORMAT " index: " SIZE_FORMAT
- " capacity: " SIZE_FORMAT,
- name, p2i(buf), index, capacity);
-}
-
-void SATBMarkQueue::print(const char* name) {
- print_satb_buffer(name, _buf, index(), capacity());
-}
-
-#endif // PRODUCT
-
-SATBMarkQueueSet::SATBMarkQueueSet() :
- PtrQueueSet(),
- _shared_satb_queue(this, true /* permanent */),
- _filter(NULL)
-{}
-
-void SATBMarkQueueSet::initialize(SATBMarkQueueFilter* filter,
- Monitor* cbl_mon, Mutex* fl_lock,
- int process_completed_threshold,
- Mutex* lock) {
- PtrQueueSet::initialize(cbl_mon, fl_lock, process_completed_threshold, -1);
- _shared_satb_queue.set_lock(lock);
- _filter = filter;
-}
-
-#ifdef ASSERT
-void SATBMarkQueueSet::dump_active_states(bool expected_active) {
- log_error(gc, verify)("Expected SATB active state: %s", expected_active ? "ACTIVE" : "INACTIVE");
- log_error(gc, verify)("Actual SATB active states:");
- log_error(gc, verify)(" Queue set: %s", is_active() ? "ACTIVE" : "INACTIVE");
- for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) {
- log_error(gc, verify)(" Thread \"%s\" queue: %s", t->name(), satb_queue_for_thread(t).is_active() ? "ACTIVE" : "INACTIVE");
- }
- log_error(gc, verify)(" Shared queue: %s", shared_satb_queue()->is_active() ? "ACTIVE" : "INACTIVE");
-}
-
-void SATBMarkQueueSet::verify_active_states(bool expected_active) {
- // Verify queue set state
- if (is_active() != expected_active) {
- dump_active_states(expected_active);
- guarantee(false, "SATB queue set has an unexpected active state");
- }
-
- // Verify thread queue states
- for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) {
- if (satb_queue_for_thread(t).is_active() != expected_active) {
- dump_active_states(expected_active);
- guarantee(false, "Thread SATB queue has an unexpected active state");
- }
- }
-
- // Verify shared queue state
- if (shared_satb_queue()->is_active() != expected_active) {
- dump_active_states(expected_active);
- guarantee(false, "Shared SATB queue has an unexpected active state");
- }
-}
-#endif // ASSERT
-
-void SATBMarkQueueSet::set_active_all_threads(bool active, bool expected_active) {
- assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
-#ifdef ASSERT
- verify_active_states(expected_active);
-#endif // ASSERT
- _all_active = active;
- for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) {
- satb_queue_for_thread(t).set_active(active);
- }
- shared_satb_queue()->set_active(active);
-}
-
-void SATBMarkQueueSet::filter_thread_buffers() {
- for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) {
- satb_queue_for_thread(t).filter();
- }
- shared_satb_queue()->filter();
-}
-
-bool SATBMarkQueueSet::apply_closure_to_completed_buffer(SATBBufferClosure* cl) {
- BufferNode* nd = NULL;
- {
- MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
- if (_completed_buffers_head != NULL) {
- nd = _completed_buffers_head;
- _completed_buffers_head = nd->next();
- if (_completed_buffers_head == NULL) _completed_buffers_tail = NULL;
- _n_completed_buffers--;
- if (_n_completed_buffers == 0) _process_completed = false;
- }
- }
- if (nd != NULL) {
- void **buf = BufferNode::make_buffer_from_node(nd);
- size_t index = nd->index();
- size_t size = buffer_size();
- assert(index <= size, "invariant");
- cl->do_buffer(buf + index, size - index);
- deallocate_buffer(nd);
- return true;
- } else {
- return false;
- }
-}
-
-#ifndef PRODUCT
-// Helpful for debugging
-
-#define SATB_PRINTER_BUFFER_SIZE 256
-
-void SATBMarkQueueSet::print_all(const char* msg) {
- char buffer[SATB_PRINTER_BUFFER_SIZE];
- assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
-
- tty->cr();
- tty->print_cr("SATB BUFFERS [%s]", msg);
-
- BufferNode* nd = _completed_buffers_head;
- int i = 0;
- while (nd != NULL) {
- void** buf = BufferNode::make_buffer_from_node(nd);
- jio_snprintf(buffer, SATB_PRINTER_BUFFER_SIZE, "Enqueued: %d", i);
- print_satb_buffer(buffer, buf, nd->index(), buffer_size());
- nd = nd->next();
- i += 1;
- }
-
- for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) {
- jio_snprintf(buffer, SATB_PRINTER_BUFFER_SIZE, "Thread: %s", t->name());
- satb_queue_for_thread(t).print(buffer);
- }
-
- shared_satb_queue()->print("Shared");
-
- tty->cr();
-}
-#endif // PRODUCT
-
-void SATBMarkQueueSet::abandon_partial_marking() {
- BufferNode* buffers_to_delete = NULL;
- {
- MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
- while (_completed_buffers_head != NULL) {
- BufferNode* nd = _completed_buffers_head;
- _completed_buffers_head = nd->next();
- nd->set_next(buffers_to_delete);
- buffers_to_delete = nd;
- }
- _completed_buffers_tail = NULL;
- _n_completed_buffers = 0;
- DEBUG_ONLY(assert_completed_buffer_list_len_correct_locked());
- }
- while (buffers_to_delete != NULL) {
- BufferNode* nd = buffers_to_delete;
- buffers_to_delete = nd->next();
- deallocate_buffer(nd);
- }
- assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
- // So we can safely manipulate these queues.
- for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) {
- satb_queue_for_thread(t).reset();
- }
- shared_satb_queue()->reset();
-}
--- a/src/hotspot/share/gc/g1/satbMarkQueue.hpp Fri Aug 10 14:56:29 2018 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,189 +0,0 @@
-/*
- * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#ifndef SHARE_VM_GC_G1_SATBMARKQUEUE_HPP
-#define SHARE_VM_GC_G1_SATBMARKQUEUE_HPP
-
-#include "gc/g1/ptrQueue.hpp"
-#include "memory/allocation.hpp"
-
-class JavaThread;
-class SATBMarkQueueSet;
-
-// Base class for processing the contents of a SATB buffer.
-class SATBBufferClosure : public StackObj {
-protected:
- ~SATBBufferClosure() { }
-
-public:
- // Process the SATB entries in the designated buffer range.
- virtual void do_buffer(void** buffer, size_t size) = 0;
-};
-
-// A PtrQueue whose elements are (possibly stale) pointers to object heads.
-class SATBMarkQueue: public PtrQueue {
- friend class SATBMarkQueueSet;
-
-private:
- // Filter out unwanted entries from the buffer.
- inline void filter();
-
-public:
- SATBMarkQueue(SATBMarkQueueSet* qset, bool permanent = false);
-
- // Removes entries from the buffer that are no longer needed.
- template<typename Filter>
- inline void apply_filter(Filter filter_out);
-
- // Process queue entries and free resources.
- void flush();
-
- // Apply cl to the active part of the buffer.
- // Prerequisite: Must be at a safepoint.
- void apply_closure_and_empty(SATBBufferClosure* cl);
-
- // Overrides PtrQueue::should_enqueue_buffer(). See the method's
- // definition for more information.
- virtual bool should_enqueue_buffer();
-
-#ifndef PRODUCT
- // Helpful for debugging
- void print(const char* name);
-#endif // PRODUCT
-
- // Compiler support.
- static ByteSize byte_offset_of_index() {
- return PtrQueue::byte_offset_of_index<SATBMarkQueue>();
- }
- using PtrQueue::byte_width_of_index;
-
- static ByteSize byte_offset_of_buf() {
- return PtrQueue::byte_offset_of_buf<SATBMarkQueue>();
- }
- using PtrQueue::byte_width_of_buf;
-
- static ByteSize byte_offset_of_active() {
- return PtrQueue::byte_offset_of_active<SATBMarkQueue>();
- }
- using PtrQueue::byte_width_of_active;
-
-};
-
-class SATBMarkQueueFilter : public CHeapObj<mtGC> {
-public:
- virtual ~SATBMarkQueueFilter() {}
- virtual void filter(SATBMarkQueue* queue) = 0;
-};
-
-class SATBMarkQueueSet: public PtrQueueSet {
- SATBMarkQueue _shared_satb_queue;
- SATBMarkQueueFilter* _filter;
-
-#ifdef ASSERT
- void dump_active_states(bool expected_active);
- void verify_active_states(bool expected_active);
-#endif // ASSERT
-
-public:
- SATBMarkQueueSet();
-
- void initialize(SATBMarkQueueFilter* filter,
- Monitor* cbl_mon, Mutex* fl_lock,
- int process_completed_threshold,
- Mutex* lock);
-
- virtual SATBMarkQueue& satb_queue_for_thread(JavaThread* const t) const = 0;
-
- // Apply "set_active(active)" to all SATB queues in the set. It should be
- // called only with the world stopped. The method will assert that the
- // SATB queues of all threads it visits, as well as the SATB queue
- // set itself, has an active value same as expected_active.
- void set_active_all_threads(bool active, bool expected_active);
-
- void filter(SATBMarkQueue* queue) {
- _filter->filter(queue);
- }
-
- // Filter all the currently-active SATB buffers.
- void filter_thread_buffers();
-
- // If there exists some completed buffer, pop and process it, and
- // return true. Otherwise return false. Processing a buffer
- // consists of applying the closure to the active range of the
- // buffer; the leading entries may be excluded due to filtering.
- bool apply_closure_to_completed_buffer(SATBBufferClosure* cl);
-
-#ifndef PRODUCT
- // Helpful for debugging
- void print_all(const char* msg);
-#endif // PRODUCT
-
- SATBMarkQueue* shared_satb_queue() { return &_shared_satb_queue; }
-
- // If a marking is being abandoned, reset any unprocessed log buffers.
- void abandon_partial_marking();
-};
-
-inline void SATBMarkQueue::filter() {
- static_cast<SATBMarkQueueSet*>(qset())->filter(this);
-}
-
-// Removes entries from the buffer that are no longer needed, as
-// determined by filter. If e is a void* entry in the buffer,
-// filter_out(e) must be a valid expression whose value is convertible
-// to bool. Entries are removed (filtered out) if the result is true,
-// retained if false.
-template<typename Filter>
-inline void SATBMarkQueue::apply_filter(Filter filter_out) {
- void** buf = this->_buf;
-
- if (buf == NULL) {
- // nothing to do
- return;
- }
-
- // Two-fingered compaction toward the end.
- void** src = &buf[this->index()];
- void** dst = &buf[this->capacity()];
- assert(src <= dst, "invariant");
- for ( ; src < dst; ++src) {
- // Search low to high for an entry to keep.
- void* entry = *src;
- if (!filter_out(entry)) {
- // Found keeper. Search high to low for an entry to discard.
- while (src < --dst) {
- if (filter_out(*dst)) {
- *dst = entry; // Replace discard with keeper.
- break;
- }
- }
- // If discard search failed (src == dst), the outer loop will also end.
- }
- }
- // dst points to the lowest retained entry, or the end of the buffer
- // if all the entries were filtered out.
- this->set_index(dst - buf);
-}
-
-#endif // SHARE_VM_GC_G1_SATBMARKQUEUE_HPP
--- a/src/hotspot/share/gc/g1/vmStructs_g1.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/g1/vmStructs_g1.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -56,14 +56,15 @@
nonstatic_field(G1CollectedHeap, _hrm, HeapRegionManager) \
nonstatic_field(G1CollectedHeap, _g1mm, G1MonitoringSupport*) \
nonstatic_field(G1CollectedHeap, _old_set, HeapRegionSetBase) \
+ nonstatic_field(G1CollectedHeap, _archive_set, HeapRegionSetBase) \
nonstatic_field(G1CollectedHeap, _humongous_set, HeapRegionSetBase) \
\
- nonstatic_field(G1MonitoringSupport, _eden_committed, size_t) \
- nonstatic_field(G1MonitoringSupport, _eden_used, size_t) \
- nonstatic_field(G1MonitoringSupport, _survivor_committed, size_t) \
- nonstatic_field(G1MonitoringSupport, _survivor_used, size_t) \
- nonstatic_field(G1MonitoringSupport, _old_committed, size_t) \
- nonstatic_field(G1MonitoringSupport, _old_used, size_t) \
+ nonstatic_field(G1MonitoringSupport, _eden_space_committed, size_t) \
+ nonstatic_field(G1MonitoringSupport, _eden_space_used, size_t) \
+ nonstatic_field(G1MonitoringSupport, _survivor_space_committed, size_t) \
+ nonstatic_field(G1MonitoringSupport, _survivor_space_used, size_t) \
+ nonstatic_field(G1MonitoringSupport, _old_gen_committed, size_t) \
+ nonstatic_field(G1MonitoringSupport, _old_gen_used, size_t) \
\
nonstatic_field(HeapRegionSetBase, _length, uint) \
\
--- a/src/hotspot/share/gc/parallel/pcTasks.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/parallel/pcTasks.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -107,8 +107,10 @@
SystemDictionary::oops_do(&mark_and_push_closure);
break;
- case class_loader_data:
- ClassLoaderDataGraph::always_strong_oops_do(&mark_and_push_closure, true);
+ case class_loader_data: {
+ CLDToOopClosure cld_closure(&mark_and_push_closure);
+ ClassLoaderDataGraph::always_strong_cld_do(&cld_closure);
+ }
break;
case code_cache:
--- a/src/hotspot/share/gc/parallel/psCompactionManager.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/parallel/psCompactionManager.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -153,14 +153,14 @@
// Follow the klass field in the mirror.
Klass* klass = java_lang_Class::as_Klass(obj);
if (klass != NULL) {
- // An anonymous class doesn't have its own class loader, so the call
- // to follow_klass will mark and push its java mirror instead of the
- // class loader. When handling the java mirror for an anonymous class
- // we need to make sure its class loader data is claimed, this is done
- // by calling follow_class_loader explicitly. For non-anonymous classes
- // the call to follow_class_loader is made when the class loader itself
- // is handled.
- if (klass->is_instance_klass() && InstanceKlass::cast(klass)->is_anonymous()) {
+ // An unsafe anonymous class doesn't have its own class loader,
+ // so the call to follow_klass will mark and push its java mirror instead of the
+ // class loader. When handling the java mirror for an unsafe anonymous
+ // class we need to make sure its class loader data is claimed, this is done
+ // by calling follow_class_loader explicitly. For non-anonymous classes the
+ // call to follow_class_loader is made when the class loader itself is handled.
+ if (klass->is_instance_klass() &&
+ InstanceKlass::cast(klass)->is_unsafe_anonymous()) {
cm->follow_class_loader(klass->class_loader_data());
} else {
cm->follow_klass(klass);
--- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -2188,7 +2188,8 @@
Management::oops_do(&oop_closure);
JvmtiExport::oops_do(&oop_closure);
SystemDictionary::oops_do(&oop_closure);
- ClassLoaderDataGraph::oops_do(&oop_closure, true);
+ CLDToOopClosure cld_closure(&oop_closure);
+ ClassLoaderDataGraph::cld_do(&cld_closure);
// Now adjust pointers in remaining weak roots. (All of which should
// have been cleared if they pointed to non-surviving objects.)
--- a/src/hotspot/share/gc/shared/c1/barrierSetC1.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/shared/c1/barrierSetC1.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -90,6 +90,13 @@
load_at_resolved(access, result);
}
+void BarrierSetC1::load(LIRAccess& access, LIR_Opr result) {
+ DecoratorSet decorators = access.decorators();
+ bool in_heap = (decorators & IN_HEAP) != 0;
+ assert(!in_heap, "consider using load_at");
+ load_at_resolved(access, result);
+}
+
LIR_Opr BarrierSetC1::atomic_cmpxchg_at(LIRAccess& access, LIRItem& cmp_value, LIRItem& new_value) {
DecoratorSet decorators = access.decorators();
bool in_heap = (decorators & IN_HEAP) != 0;
@@ -159,13 +166,16 @@
bool is_volatile = (((decorators & MO_SEQ_CST) != 0) || AlwaysAtomicAccesses) && os::is_MP();
bool needs_patching = (decorators & C1_NEEDS_PATCHING) != 0;
bool mask_boolean = (decorators & C1_MASK_BOOLEAN) != 0;
+ bool in_native = (decorators & IN_NATIVE) != 0;
if (support_IRIW_for_not_multiple_copy_atomic_cpu && is_volatile) {
__ membar();
}
LIR_PatchCode patch_code = needs_patching ? lir_patch_normal : lir_patch_none;
- if (is_volatile && !needs_patching) {
+ if (in_native) {
+ __ move_wide(access.resolved_addr()->as_address_ptr(), result);
+ } else if (is_volatile && !needs_patching) {
gen->volatile_field_load(access.resolved_addr()->as_address_ptr(), result, access.access_emit_info());
} else {
__ load(access.resolved_addr()->as_address_ptr(), result, access.access_emit_info(), patch_code);
@@ -324,3 +334,7 @@
}
}
}
+
+LIR_Opr BarrierSetC1::resolve(LIRGenerator* gen, DecoratorSet decorators, LIR_Opr obj) {
+ return obj;
+}
--- a/src/hotspot/share/gc/shared/c1/barrierSetC1.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/shared/c1/barrierSetC1.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -127,12 +127,15 @@
public:
virtual void store_at(LIRAccess& access, LIR_Opr value);
virtual void load_at(LIRAccess& access, LIR_Opr result);
+ virtual void load(LIRAccess& access, LIR_Opr result);
virtual LIR_Opr atomic_cmpxchg_at(LIRAccess& access, LIRItem& cmp_value, LIRItem& new_value);
virtual LIR_Opr atomic_xchg_at(LIRAccess& access, LIRItem& value);
virtual LIR_Opr atomic_add_at(LIRAccess& access, LIRItem& value);
+ virtual LIR_Opr resolve(LIRGenerator* gen, DecoratorSet decorators, LIR_Opr obj);
+
virtual void generate_c1_runtime_stubs(BufferBlob* buffer_blob) {}
};
--- a/src/hotspot/share/gc/shared/c1/modRefBarrierSetC1.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/shared/c1/modRefBarrierSetC1.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -86,7 +86,7 @@
LIR_Opr ModRefBarrierSetC1::resolve_address(LIRAccess& access, bool resolve_in_register) {
DecoratorSet decorators = access.decorators();
bool needs_patching = (decorators & C1_NEEDS_PATCHING) != 0;
- bool is_write = (decorators & C1_WRITE_ACCESS) != 0;
+ bool is_write = (decorators & ACCESS_WRITE) != 0;
bool is_array = (decorators & IS_ARRAY) != 0;
bool on_anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0;
bool precise = is_array || on_anonymous;
--- a/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -104,14 +104,18 @@
bool pinned = (decorators & C2_PINNED_LOAD) != 0;
bool in_native = (decorators & IN_NATIVE) != 0;
- assert(!in_native, "not supported yet");
MemNode::MemOrd mo = access.mem_node_mo();
LoadNode::ControlDependency dep = pinned ? LoadNode::Pinned : LoadNode::DependsOnlyOnTest;
Node* control = control_dependent ? kit->control() : NULL;
- Node* load = kit->make_load(control, adr, val_type, access.type(), adr_type, mo,
- dep, requires_atomic_access, unaligned, mismatched);
+ Node* load;
+ if (in_native) {
+ load = kit->make_load(control, adr, val_type, access.type(), mo);
+ } else {
+ load = kit->make_load(control, adr, val_type, access.type(), adr_type, mo,
+ dep, requires_atomic_access, unaligned, mismatched);
+ }
access.set_raw_access(load);
return load;
@@ -119,10 +123,11 @@
class C2AccessFence: public StackObj {
C2Access& _access;
+ Node* _leading_membar;
public:
C2AccessFence(C2Access& access) :
- _access(access) {
+ _access(access), _leading_membar(NULL) {
GraphKit* kit = access.kit();
DecoratorSet decorators = access.decorators();
@@ -139,12 +144,12 @@
// into actual barriers on most machines, but we still need rest of
// compiler to respect ordering.
if (is_release) {
- kit->insert_mem_bar(Op_MemBarRelease);
+ _leading_membar = kit->insert_mem_bar(Op_MemBarRelease);
} else if (is_volatile) {
if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
- kit->insert_mem_bar(Op_MemBarVolatile);
+ _leading_membar = kit->insert_mem_bar(Op_MemBarVolatile);
} else {
- kit->insert_mem_bar(Op_MemBarRelease);
+ _leading_membar = kit->insert_mem_bar(Op_MemBarRelease);
}
}
} else if (is_write) {
@@ -152,7 +157,7 @@
// floating down past the volatile write. Also prevents commoning
// another volatile read.
if (is_volatile || is_release) {
- kit->insert_mem_bar(Op_MemBarRelease);
+ _leading_membar = kit->insert_mem_bar(Op_MemBarRelease);
}
} else {
// Memory barrier to prevent normal and 'unsafe' accesses from
@@ -161,7 +166,7 @@
// so there's no problems making a strong assert about mixing users
// of safe & unsafe memory.
if (is_volatile && support_IRIW_for_not_multiple_copy_atomic_cpu) {
- kit->insert_mem_bar(Op_MemBarVolatile);
+ _leading_membar = kit->insert_mem_bar(Op_MemBarVolatile);
}
}
@@ -196,20 +201,30 @@
if (is_atomic) {
if (is_acquire || is_volatile) {
- kit->insert_mem_bar(Op_MemBarAcquire);
+ Node* n = _access.raw_access();
+ Node* mb = kit->insert_mem_bar(Op_MemBarAcquire, n);
+ if (_leading_membar != NULL) {
+ MemBarNode::set_load_store_pair(_leading_membar->as_MemBar(), mb->as_MemBar());
+ }
}
} else if (is_write) {
// If not multiple copy atomic, we do the MemBarVolatile before the load.
if (is_volatile && !support_IRIW_for_not_multiple_copy_atomic_cpu) {
- kit->insert_mem_bar(Op_MemBarVolatile); // Use fat membar
+ Node* n = _access.raw_access();
+ Node* mb = kit->insert_mem_bar(Op_MemBarVolatile, n); // Use fat membar
+ if (_leading_membar != NULL) {
+ MemBarNode::set_store_pair(_leading_membar->as_MemBar(), mb->as_MemBar());
+ }
}
} else {
if (is_volatile || is_acquire) {
- kit->insert_mem_bar(Op_MemBarAcquire, _access.raw_access());
+ Node* n = _access.raw_access();
+ assert(_leading_membar == NULL || support_IRIW_for_not_multiple_copy_atomic_cpu, "no leading membar expected");
+ Node* mb = kit->insert_mem_bar(Op_MemBarAcquire, n);
+ mb->as_MemBar()->set_trailing_load();
}
}
}
-
};
Node* BarrierSetC2::store_at(C2Access& access, C2AccessValue& val) const {
--- a/src/hotspot/share/gc/shared/c2/barrierSetC2.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/shared/c2/barrierSetC2.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -194,6 +194,7 @@
virtual bool array_copy_requires_gc_barriers(BasicType type) const { return false; }
// Support for GC barriers emitted during parsing
+ virtual bool has_load_barriers() const { return false; }
virtual bool is_gc_barrier_node(Node* node) const { return false; }
virtual Node* step_over_gc_barrier(Node* c) const { return c; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shared/ptrQueue.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,314 @@
+/*
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc/shared/ptrQueue.hpp"
+#include "memory/allocation.hpp"
+#include "memory/allocation.inline.hpp"
+#include "runtime/mutex.hpp"
+#include "runtime/mutexLocker.hpp"
+#include "runtime/thread.inline.hpp"
+
+#include <new>
+
+PtrQueue::PtrQueue(PtrQueueSet* qset, bool permanent, bool active) :
+ _qset(qset),
+ _active(active),
+ _permanent(permanent),
+ _index(0),
+ _capacity_in_bytes(0),
+ _buf(NULL),
+ _lock(NULL)
+{}
+
+PtrQueue::~PtrQueue() {
+ assert(_permanent || (_buf == NULL), "queue must be flushed before delete");
+}
+
+void PtrQueue::flush_impl() {
+ if (_buf != NULL) {
+ BufferNode* node = BufferNode::make_node_from_buffer(_buf, index());
+ if (is_empty()) {
+ // No work to do.
+ qset()->deallocate_buffer(node);
+ } else {
+ qset()->enqueue_complete_buffer(node);
+ }
+ _buf = NULL;
+ set_index(0);
+ }
+}
+
+
+void PtrQueue::enqueue_known_active(void* ptr) {
+ while (_index == 0) {
+ handle_zero_index();
+ }
+
+ assert(_buf != NULL, "postcondition");
+ assert(index() > 0, "postcondition");
+ assert(index() <= capacity(), "invariant");
+ _index -= _element_size;
+ _buf[index()] = ptr;
+}
+
+void PtrQueue::locking_enqueue_completed_buffer(BufferNode* node) {
+ assert(_lock->owned_by_self(), "Required.");
+ qset()->enqueue_complete_buffer(node);
+}
+
+
+BufferNode* BufferNode::allocate(size_t size) {
+ size_t byte_size = size * sizeof(void*);
+ void* data = NEW_C_HEAP_ARRAY(char, buffer_offset() + byte_size, mtGC);
+ return new (data) BufferNode;
+}
+
+void BufferNode::deallocate(BufferNode* node) {
+ node->~BufferNode();
+ FREE_C_HEAP_ARRAY(char, node);
+}
+
+PtrQueueSet::PtrQueueSet(bool notify_when_complete) :
+ _buffer_size(0),
+ _cbl_mon(NULL),
+ _completed_buffers_head(NULL),
+ _completed_buffers_tail(NULL),
+ _n_completed_buffers(0),
+ _process_completed_threshold(0),
+ _process_completed(false),
+ _fl_lock(NULL),
+ _buf_free_list(NULL),
+ _buf_free_list_sz(0),
+ _fl_owner(NULL),
+ _all_active(false),
+ _notify_when_complete(notify_when_complete),
+ _max_completed_queue(0),
+ _completed_queue_padding(0)
+{
+ _fl_owner = this;
+}
+
+PtrQueueSet::~PtrQueueSet() {
+ // There are presently only a couple (derived) instances ever
+ // created, and they are permanent, so no harm currently done by
+ // doing nothing here.
+}
+
+void PtrQueueSet::initialize(Monitor* cbl_mon,
+ Mutex* fl_lock,
+ int process_completed_threshold,
+ int max_completed_queue,
+ PtrQueueSet *fl_owner) {
+ _max_completed_queue = max_completed_queue;
+ _process_completed_threshold = process_completed_threshold;
+ _completed_queue_padding = 0;
+ assert(cbl_mon != NULL && fl_lock != NULL, "Init order issue?");
+ _cbl_mon = cbl_mon;
+ _fl_lock = fl_lock;
+ _fl_owner = (fl_owner != NULL) ? fl_owner : this;
+}
+
+void** PtrQueueSet::allocate_buffer() {
+ BufferNode* node = NULL;
+ {
+ MutexLockerEx x(_fl_owner->_fl_lock, Mutex::_no_safepoint_check_flag);
+ node = _fl_owner->_buf_free_list;
+ if (node != NULL) {
+ _fl_owner->_buf_free_list = node->next();
+ _fl_owner->_buf_free_list_sz--;
+ }
+ }
+ if (node == NULL) {
+ node = BufferNode::allocate(buffer_size());
+ } else {
+ // Reinitialize buffer obtained from free list.
+ node->set_index(0);
+ node->set_next(NULL);
+ }
+ return BufferNode::make_buffer_from_node(node);
+}
+
+void PtrQueueSet::deallocate_buffer(BufferNode* node) {
+ MutexLockerEx x(_fl_owner->_fl_lock, Mutex::_no_safepoint_check_flag);
+ node->set_next(_fl_owner->_buf_free_list);
+ _fl_owner->_buf_free_list = node;
+ _fl_owner->_buf_free_list_sz++;
+}
+
+void PtrQueueSet::reduce_free_list() {
+ assert(_fl_owner == this, "Free list reduction is allowed only for the owner");
+ // For now we'll adopt the strategy of deleting half.
+ MutexLockerEx x(_fl_lock, Mutex::_no_safepoint_check_flag);
+ size_t n = _buf_free_list_sz / 2;
+ for (size_t i = 0; i < n; ++i) {
+ assert(_buf_free_list != NULL,
+ "_buf_free_list_sz is wrong: " SIZE_FORMAT, _buf_free_list_sz);
+ BufferNode* node = _buf_free_list;
+ _buf_free_list = node->next();
+ _buf_free_list_sz--;
+ BufferNode::deallocate(node);
+ }
+}
+
+void PtrQueue::handle_zero_index() {
+ assert(index() == 0, "precondition");
+
+ // This thread records the full buffer and allocates a new one (while
+ // holding the lock if there is one).
+ if (_buf != NULL) {
+ if (!should_enqueue_buffer()) {
+ assert(index() > 0, "the buffer can only be re-used if it's not full");
+ return;
+ }
+
+ if (_lock) {
+ assert(_lock->owned_by_self(), "Required.");
+
+ BufferNode* node = BufferNode::make_node_from_buffer(_buf, index());
+ _buf = NULL; // clear shared _buf field
+
+ locking_enqueue_completed_buffer(node); // enqueue completed buffer
+ assert(_buf == NULL, "multiple enqueuers appear to be racing");
+ } else {
+ BufferNode* node = BufferNode::make_node_from_buffer(_buf, index());
+ if (qset()->process_or_enqueue_complete_buffer(node)) {
+ // Recycle the buffer. No allocation.
+ assert(_buf == BufferNode::make_buffer_from_node(node), "invariant");
+ assert(capacity() == qset()->buffer_size(), "invariant");
+ reset();
+ return;
+ }
+ }
+ }
+ // Set capacity in case this is the first allocation.
+ set_capacity(qset()->buffer_size());
+ // Allocate a new buffer.
+ _buf = qset()->allocate_buffer();
+ reset();
+}
+
+bool PtrQueueSet::process_or_enqueue_complete_buffer(BufferNode* node) {
+ if (Thread::current()->is_Java_thread()) {
+ // We don't lock. It is fine to be epsilon-precise here.
+ if (_max_completed_queue == 0 ||
+ (_max_completed_queue > 0 &&
+ _n_completed_buffers >= _max_completed_queue + _completed_queue_padding)) {
+ bool b = mut_process_buffer(node);
+ if (b) {
+ // True here means that the buffer hasn't been deallocated and the caller may reuse it.
+ return true;
+ }
+ }
+ }
+ // The buffer will be enqueued. The caller will have to get a new one.
+ enqueue_complete_buffer(node);
+ return false;
+}
+
+void PtrQueueSet::enqueue_complete_buffer(BufferNode* cbn) {
+ MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
+ cbn->set_next(NULL);
+ if (_completed_buffers_tail == NULL) {
+ assert(_completed_buffers_head == NULL, "Well-formedness");
+ _completed_buffers_head = cbn;
+ _completed_buffers_tail = cbn;
+ } else {
+ _completed_buffers_tail->set_next(cbn);
+ _completed_buffers_tail = cbn;
+ }
+ _n_completed_buffers++;
+
+ if (!_process_completed && _process_completed_threshold >= 0 &&
+ _n_completed_buffers >= (size_t)_process_completed_threshold) {
+ _process_completed = true;
+ if (_notify_when_complete) {
+ _cbl_mon->notify();
+ }
+ }
+ DEBUG_ONLY(assert_completed_buffer_list_len_correct_locked());
+}
+
+size_t PtrQueueSet::completed_buffers_list_length() {
+ size_t n = 0;
+ BufferNode* cbn = _completed_buffers_head;
+ while (cbn != NULL) {
+ n++;
+ cbn = cbn->next();
+ }
+ return n;
+}
+
+void PtrQueueSet::assert_completed_buffer_list_len_correct() {
+ MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
+ assert_completed_buffer_list_len_correct_locked();
+}
+
+void PtrQueueSet::assert_completed_buffer_list_len_correct_locked() {
+ guarantee(completed_buffers_list_length() == _n_completed_buffers,
+ "Completed buffer length is wrong.");
+}
+
+void PtrQueueSet::set_buffer_size(size_t sz) {
+ assert(_buffer_size == 0 && sz > 0, "Should be called only once.");
+ _buffer_size = sz;
+}
+
+// Merge lists of buffers. Notify the processing threads.
+// The source queue is emptied as a result. The queues
+// must share the monitor.
+void PtrQueueSet::merge_bufferlists(PtrQueueSet *src) {
+ assert(_cbl_mon == src->_cbl_mon, "Should share the same lock");
+ MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
+ if (_completed_buffers_tail == NULL) {
+ assert(_completed_buffers_head == NULL, "Well-formedness");
+ _completed_buffers_head = src->_completed_buffers_head;
+ _completed_buffers_tail = src->_completed_buffers_tail;
+ } else {
+ assert(_completed_buffers_head != NULL, "Well formedness");
+ if (src->_completed_buffers_head != NULL) {
+ _completed_buffers_tail->set_next(src->_completed_buffers_head);
+ _completed_buffers_tail = src->_completed_buffers_tail;
+ }
+ }
+ _n_completed_buffers += src->_n_completed_buffers;
+
+ src->_n_completed_buffers = 0;
+ src->_completed_buffers_head = NULL;
+ src->_completed_buffers_tail = NULL;
+
+ assert(_completed_buffers_head == NULL && _completed_buffers_tail == NULL ||
+ _completed_buffers_head != NULL && _completed_buffers_tail != NULL,
+ "Sanity");
+}
+
+void PtrQueueSet::notify_if_necessary() {
+ MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
+ assert(_process_completed_threshold >= 0, "_process_completed is negative");
+ if (_n_completed_buffers >= (size_t)_process_completed_threshold || _max_completed_queue == 0) {
+ _process_completed = true;
+ if (_notify_when_complete)
+ _cbl_mon->notify();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shared/ptrQueue.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,371 @@
+/*
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * 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_GC_SHARED_PTRQUEUE_HPP
+#define SHARE_GC_SHARED_PTRQUEUE_HPP
+
+#include "utilities/align.hpp"
+#include "utilities/sizes.hpp"
+
+// There are various techniques that require threads to be able to log
+// addresses. For example, a generational write barrier might log
+// the addresses of modified old-generation objects. This type supports
+// this operation.
+
+class BufferNode;
+class PtrQueueSet;
+class PtrQueue {
+ friend class VMStructs;
+
+ // Noncopyable - not defined.
+ PtrQueue(const PtrQueue&);
+ PtrQueue& operator=(const PtrQueue&);
+
+ // The ptr queue set to which this queue belongs.
+ PtrQueueSet* const _qset;
+
+ // Whether updates should be logged.
+ bool _active;
+
+ // If true, the queue is permanent, and doesn't need to deallocate
+ // its buffer in the destructor (since that obtains a lock which may not
+ // be legally locked by then.
+ const bool _permanent;
+
+ // The (byte) index at which an object was last enqueued. Starts at
+ // capacity_in_bytes (indicating an empty buffer) and goes towards zero.
+ // Value is always pointer-size aligned.
+ size_t _index;
+
+ // Size of the current buffer, in bytes.
+ // Value is always pointer-size aligned.
+ size_t _capacity_in_bytes;
+
+ static const size_t _element_size = sizeof(void*);
+
+ // Get the capacity, in bytes. The capacity must have been set.
+ size_t capacity_in_bytes() const {
+ assert(_capacity_in_bytes > 0, "capacity not set");
+ return _capacity_in_bytes;
+ }
+
+ void set_capacity(size_t entries) {
+ size_t byte_capacity = index_to_byte_index(entries);
+ assert(_capacity_in_bytes == 0 || _capacity_in_bytes == byte_capacity,
+ "changing capacity " SIZE_FORMAT " -> " SIZE_FORMAT,
+ _capacity_in_bytes, byte_capacity);
+ _capacity_in_bytes = byte_capacity;
+ }
+
+ static size_t byte_index_to_index(size_t ind) {
+ assert(is_aligned(ind, _element_size), "precondition");
+ return ind / _element_size;
+ }
+
+ static size_t index_to_byte_index(size_t ind) {
+ return ind * _element_size;
+ }
+
+protected:
+ // The buffer.
+ void** _buf;
+
+ size_t index() const {
+ return byte_index_to_index(_index);
+ }
+
+ void set_index(size_t new_index) {
+ size_t byte_index = index_to_byte_index(new_index);
+ assert(byte_index <= capacity_in_bytes(), "precondition");
+ _index = byte_index;
+ }
+
+ size_t capacity() const {
+ return byte_index_to_index(capacity_in_bytes());
+ }
+
+ // If there is a lock associated with this buffer, this is that lock.
+ Mutex* _lock;
+
+ PtrQueueSet* qset() { return _qset; }
+ bool is_permanent() const { return _permanent; }
+
+ // Process queue entries and release resources.
+ void flush_impl();
+
+ // Initialize this queue to contain a null buffer, and be part of the
+ // given PtrQueueSet.
+ PtrQueue(PtrQueueSet* qset, bool permanent = false, bool active = false);
+
+ // Requires queue flushed or permanent.
+ ~PtrQueue();
+
+public:
+
+ // Associate a lock with a ptr queue.
+ void set_lock(Mutex* lock) { _lock = lock; }
+
+ // Forcibly set empty.
+ void reset() {
+ if (_buf != NULL) {
+ _index = capacity_in_bytes();
+ }
+ }
+
+ void enqueue(volatile void* ptr) {
+ enqueue((void*)(ptr));
+ }
+
+ // Enqueues the given "obj".
+ void enqueue(void* ptr) {
+ if (!_active) return;
+ else enqueue_known_active(ptr);
+ }
+
+ // This method is called when we're doing the zero index handling
+ // and gives a chance to the queues to do any pre-enqueueing
+ // processing they might want to do on the buffer. It should return
+ // true if the buffer should be enqueued, or false if enough
+ // entries were cleared from it so that it can be re-used. It should
+ // not return false if the buffer is still full (otherwise we can
+ // get into an infinite loop).
+ virtual bool should_enqueue_buffer() { return true; }
+ void handle_zero_index();
+ void locking_enqueue_completed_buffer(BufferNode* node);
+
+ void enqueue_known_active(void* ptr);
+
+ // Return the size of the in-use region.
+ size_t size() const {
+ size_t result = 0;
+ if (_buf != NULL) {
+ assert(_index <= capacity_in_bytes(), "Invariant");
+ result = byte_index_to_index(capacity_in_bytes() - _index);
+ }
+ return result;
+ }
+
+ bool is_empty() const {
+ return _buf == NULL || capacity_in_bytes() == _index;
+ }
+
+ // Set the "active" property of the queue to "b". An enqueue to an
+ // inactive thread is a no-op. Setting a queue to inactive resets its
+ // log to the empty state.
+ void set_active(bool b) {
+ _active = b;
+ if (!b && _buf != NULL) {
+ reset();
+ } else if (b && _buf != NULL) {
+ assert(index() == capacity(),
+ "invariant: queues are empty when activated.");
+ }
+ }
+
+ bool is_active() const { return _active; }
+
+ // To support compiler.
+
+protected:
+ template<typename Derived>
+ static ByteSize byte_offset_of_index() {
+ return byte_offset_of(Derived, _index);
+ }
+
+ static ByteSize byte_width_of_index() { return in_ByteSize(sizeof(size_t)); }
+
+ template<typename Derived>
+ static ByteSize byte_offset_of_buf() {
+ return byte_offset_of(Derived, _buf);
+ }
+
+ static ByteSize byte_width_of_buf() { return in_ByteSize(_element_size); }
+
+ template<typename Derived>
+ static ByteSize byte_offset_of_active() {
+ return byte_offset_of(Derived, _active);
+ }
+
+ static ByteSize byte_width_of_active() { return in_ByteSize(sizeof(bool)); }
+
+};
+
+class BufferNode {
+ size_t _index;
+ BufferNode* _next;
+ void* _buffer[1]; // Pseudo flexible array member.
+
+ BufferNode() : _index(0), _next(NULL) { }
+ ~BufferNode() { }
+
+ static size_t buffer_offset() {
+ return offset_of(BufferNode, _buffer);
+ }
+
+public:
+ BufferNode* next() const { return _next; }
+ void set_next(BufferNode* n) { _next = n; }
+ size_t index() const { return _index; }
+ void set_index(size_t i) { _index = i; }
+
+ // Allocate a new BufferNode with the "buffer" having size elements.
+ static BufferNode* allocate(size_t size);
+
+ // Free a BufferNode.
+ static void deallocate(BufferNode* node);
+
+ // Return the BufferNode containing the buffer, after setting its index.
+ static BufferNode* make_node_from_buffer(void** buffer, size_t index) {
+ BufferNode* node =
+ reinterpret_cast<BufferNode*>(
+ reinterpret_cast<char*>(buffer) - buffer_offset());
+ node->set_index(index);
+ return node;
+ }
+
+ // Return the buffer for node.
+ static void** make_buffer_from_node(BufferNode *node) {
+ // &_buffer[0] might lead to index out of bounds warnings.
+ return reinterpret_cast<void**>(
+ reinterpret_cast<char*>(node) + buffer_offset());
+ }
+};
+
+// A PtrQueueSet represents resources common to a set of pointer queues.
+// In particular, the individual queues allocate buffers from this shared
+// set, and return completed buffers to the set.
+// All these variables are are protected by the TLOQ_CBL_mon. XXX ???
+class PtrQueueSet {
+ // The size of all buffers in the set.
+ size_t _buffer_size;
+
+protected:
+ Monitor* _cbl_mon; // Protects the fields below.
+ BufferNode* _completed_buffers_head;
+ BufferNode* _completed_buffers_tail;
+ size_t _n_completed_buffers;
+ int _process_completed_threshold;
+ volatile bool _process_completed;
+
+ // This (and the interpretation of the first element as a "next"
+ // pointer) are protected by the TLOQ_FL_lock.
+ Mutex* _fl_lock;
+ BufferNode* _buf_free_list;
+ size_t _buf_free_list_sz;
+ // Queue set can share a freelist. The _fl_owner variable
+ // specifies the owner. It is set to "this" by default.
+ PtrQueueSet* _fl_owner;
+
+ bool _all_active;
+
+ // If true, notify_all on _cbl_mon when the threshold is reached.
+ bool _notify_when_complete;
+
+ // Maximum number of elements allowed on completed queue: after that,
+ // enqueuer does the work itself. Zero indicates no maximum.
+ int _max_completed_queue;
+ size_t _completed_queue_padding;
+
+ size_t completed_buffers_list_length();
+ void assert_completed_buffer_list_len_correct_locked();
+ void assert_completed_buffer_list_len_correct();
+
+protected:
+ // A mutator thread does the the work of processing a buffer.
+ // Returns "true" iff the work is complete (and the buffer may be
+ // deallocated).
+ virtual bool mut_process_buffer(BufferNode* node) {
+ ShouldNotReachHere();
+ return false;
+ }
+
+ // Create an empty ptr queue set.
+ PtrQueueSet(bool notify_when_complete = false);
+ ~PtrQueueSet();
+
+ // Because of init-order concerns, we can't pass these as constructor
+ // arguments.
+ void initialize(Monitor* cbl_mon,
+ Mutex* fl_lock,
+ int process_completed_threshold,
+ int max_completed_queue,
+ PtrQueueSet *fl_owner = NULL);
+
+public:
+
+ // Return the buffer for a BufferNode of size buffer_size().
+ void** allocate_buffer();
+
+ // Return an empty buffer to the free list. The node is required
+ // to have been allocated with a size of buffer_size().
+ void deallocate_buffer(BufferNode* node);
+
+ // Declares that "buf" is a complete buffer.
+ void enqueue_complete_buffer(BufferNode* node);
+
+ // To be invoked by the mutator.
+ bool process_or_enqueue_complete_buffer(BufferNode* node);
+
+ bool completed_buffers_exist_dirty() {
+ return _n_completed_buffers > 0;
+ }
+
+ bool process_completed_buffers() { return _process_completed; }
+ void set_process_completed(bool x) { _process_completed = x; }
+
+ bool is_active() { return _all_active; }
+
+ // Set the buffer size. Should be called before any "enqueue" operation
+ // can be called. And should only be called once.
+ void set_buffer_size(size_t sz);
+
+ // Get the buffer size. Must have been set.
+ size_t buffer_size() const {
+ assert(_buffer_size > 0, "buffer size not set");
+ return _buffer_size;
+ }
+
+ // Get/Set the number of completed buffers that triggers log processing.
+ void set_process_completed_threshold(int sz) { _process_completed_threshold = sz; }
+ int process_completed_threshold() const { return _process_completed_threshold; }
+
+ // Must only be called at a safe point. Indicates that the buffer free
+ // list size may be reduced, if that is deemed desirable.
+ void reduce_free_list();
+
+ size_t completed_buffers_num() { return _n_completed_buffers; }
+
+ void merge_bufferlists(PtrQueueSet* src);
+
+ void set_max_completed_queue(int m) { _max_completed_queue = m; }
+ int max_completed_queue() { return _max_completed_queue; }
+
+ void set_completed_queue_padding(size_t padding) { _completed_queue_padding = padding; }
+ size_t completed_queue_padding() { return _completed_queue_padding; }
+
+ // Notify the consumer if the number of buffers crossed the threshold
+ void notify_if_necessary();
+};
+
+#endif // SHARE_GC_SHARED_PTRQUEUE_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shared/satbMarkQueue.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc/shared/satbMarkQueue.hpp"
+#include "gc/shared/collectedHeap.hpp"
+#include "logging/log.hpp"
+#include "memory/allocation.inline.hpp"
+#include "oops/oop.inline.hpp"
+#include "runtime/mutexLocker.hpp"
+#include "runtime/os.hpp"
+#include "runtime/safepoint.hpp"
+#include "runtime/thread.hpp"
+#include "runtime/threadSMR.hpp"
+#include "runtime/vmThread.hpp"
+
+SATBMarkQueue::SATBMarkQueue(SATBMarkQueueSet* qset, bool permanent) :
+ // SATB queues are only active during marking cycles. We create
+ // them with their active field set to false. If a thread is
+ // created during a cycle and its SATB queue needs to be activated
+ // before the thread starts running, we'll need to set its active
+ // field to true. This must be done in the collector-specific
+ // BarrierSet::on_thread_attach() implementation.
+ PtrQueue(qset, permanent, false /* active */)
+{ }
+
+void SATBMarkQueue::flush() {
+ // Filter now to possibly save work later. If filtering empties the
+ // buffer then flush_impl can deallocate the buffer.
+ filter();
+ flush_impl();
+}
+
+// This method will first apply filtering to the buffer. If filtering
+// retains a small enough collection in the buffer, we can continue to
+// use the buffer as-is, instead of enqueueing and replacing it.
+
+bool SATBMarkQueue::should_enqueue_buffer() {
+ assert(_lock == NULL || _lock->owned_by_self(),
+ "we should have taken the lock before calling this");
+
+ // This method should only be called if there is a non-NULL buffer
+ // that is full.
+ assert(index() == 0, "pre-condition");
+ assert(_buf != NULL, "pre-condition");
+
+ filter();
+
+ SATBMarkQueueSet* satb_qset = static_cast<SATBMarkQueueSet*>(qset());
+ size_t threshold = satb_qset->buffer_enqueue_threshold();
+ // Ensure we'll enqueue completely full buffers.
+ assert(threshold > 0, "enqueue threshold = 0");
+ // Ensure we won't enqueue empty buffers.
+ assert(threshold <= capacity(),
+ "enqueue threshold " SIZE_FORMAT " exceeds capacity " SIZE_FORMAT,
+ threshold, capacity());
+ return index() < threshold;
+}
+
+void SATBMarkQueue::apply_closure_and_empty(SATBBufferClosure* cl) {
+ assert(SafepointSynchronize::is_at_safepoint(),
+ "SATB queues must only be processed at safepoints");
+ if (_buf != NULL) {
+ cl->do_buffer(&_buf[index()], size());
+ reset();
+ }
+}
+
+#ifndef PRODUCT
+// Helpful for debugging
+
+static void print_satb_buffer(const char* name,
+ void** buf,
+ size_t index,
+ size_t capacity) {
+ tty->print_cr(" SATB BUFFER [%s] buf: " PTR_FORMAT " index: " SIZE_FORMAT
+ " capacity: " SIZE_FORMAT,
+ name, p2i(buf), index, capacity);
+}
+
+void SATBMarkQueue::print(const char* name) {
+ print_satb_buffer(name, _buf, index(), capacity());
+}
+
+#endif // PRODUCT
+
+SATBMarkQueueSet::SATBMarkQueueSet() :
+ PtrQueueSet(),
+ _shared_satb_queue(this, true /* permanent */),
+ _buffer_enqueue_threshold(0)
+{}
+
+void SATBMarkQueueSet::initialize(Monitor* cbl_mon, Mutex* fl_lock,
+ int process_completed_threshold,
+ uint buffer_enqueue_threshold_percentage,
+ Mutex* lock) {
+ PtrQueueSet::initialize(cbl_mon, fl_lock, process_completed_threshold, -1);
+ _shared_satb_queue.set_lock(lock);
+ assert(buffer_size() != 0, "buffer size not initialized");
+ // Minimum threshold of 1 ensures enqueuing of completely full buffers.
+ size_t size = buffer_size();
+ size_t enqueue_qty = (size * buffer_enqueue_threshold_percentage) / 100;
+ _buffer_enqueue_threshold = MAX2(size - enqueue_qty, (size_t)1);
+}
+
+#ifdef ASSERT
+void SATBMarkQueueSet::dump_active_states(bool expected_active) {
+ log_error(gc, verify)("Expected SATB active state: %s", expected_active ? "ACTIVE" : "INACTIVE");
+ log_error(gc, verify)("Actual SATB active states:");
+ log_error(gc, verify)(" Queue set: %s", is_active() ? "ACTIVE" : "INACTIVE");
+ for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) {
+ log_error(gc, verify)(" Thread \"%s\" queue: %s", t->name(), satb_queue_for_thread(t).is_active() ? "ACTIVE" : "INACTIVE");
+ }
+ log_error(gc, verify)(" Shared queue: %s", shared_satb_queue()->is_active() ? "ACTIVE" : "INACTIVE");
+}
+
+void SATBMarkQueueSet::verify_active_states(bool expected_active) {
+ // Verify queue set state
+ if (is_active() != expected_active) {
+ dump_active_states(expected_active);
+ guarantee(false, "SATB queue set has an unexpected active state");
+ }
+
+ // Verify thread queue states
+ for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) {
+ if (satb_queue_for_thread(t).is_active() != expected_active) {
+ dump_active_states(expected_active);
+ guarantee(false, "Thread SATB queue has an unexpected active state");
+ }
+ }
+
+ // Verify shared queue state
+ if (shared_satb_queue()->is_active() != expected_active) {
+ dump_active_states(expected_active);
+ guarantee(false, "Shared SATB queue has an unexpected active state");
+ }
+}
+#endif // ASSERT
+
+void SATBMarkQueueSet::set_active_all_threads(bool active, bool expected_active) {
+ assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
+#ifdef ASSERT
+ verify_active_states(expected_active);
+#endif // ASSERT
+ _all_active = active;
+ for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) {
+ satb_queue_for_thread(t).set_active(active);
+ }
+ shared_satb_queue()->set_active(active);
+}
+
+void SATBMarkQueueSet::filter_thread_buffers() {
+ for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) {
+ satb_queue_for_thread(t).filter();
+ }
+ shared_satb_queue()->filter();
+}
+
+bool SATBMarkQueueSet::apply_closure_to_completed_buffer(SATBBufferClosure* cl) {
+ BufferNode* nd = NULL;
+ {
+ MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
+ if (_completed_buffers_head != NULL) {
+ nd = _completed_buffers_head;
+ _completed_buffers_head = nd->next();
+ if (_completed_buffers_head == NULL) _completed_buffers_tail = NULL;
+ _n_completed_buffers--;
+ if (_n_completed_buffers == 0) _process_completed = false;
+ }
+ }
+ if (nd != NULL) {
+ void **buf = BufferNode::make_buffer_from_node(nd);
+ size_t index = nd->index();
+ size_t size = buffer_size();
+ assert(index <= size, "invariant");
+ cl->do_buffer(buf + index, size - index);
+ deallocate_buffer(nd);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+#ifndef PRODUCT
+// Helpful for debugging
+
+#define SATB_PRINTER_BUFFER_SIZE 256
+
+void SATBMarkQueueSet::print_all(const char* msg) {
+ char buffer[SATB_PRINTER_BUFFER_SIZE];
+ assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
+
+ tty->cr();
+ tty->print_cr("SATB BUFFERS [%s]", msg);
+
+ BufferNode* nd = _completed_buffers_head;
+ int i = 0;
+ while (nd != NULL) {
+ void** buf = BufferNode::make_buffer_from_node(nd);
+ os::snprintf(buffer, SATB_PRINTER_BUFFER_SIZE, "Enqueued: %d", i);
+ print_satb_buffer(buffer, buf, nd->index(), buffer_size());
+ nd = nd->next();
+ i += 1;
+ }
+
+ for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) {
+ os::snprintf(buffer, SATB_PRINTER_BUFFER_SIZE, "Thread: %s", t->name());
+ satb_queue_for_thread(t).print(buffer);
+ }
+
+ shared_satb_queue()->print("Shared");
+
+ tty->cr();
+}
+#endif // PRODUCT
+
+void SATBMarkQueueSet::abandon_partial_marking() {
+ BufferNode* buffers_to_delete = NULL;
+ {
+ MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
+ while (_completed_buffers_head != NULL) {
+ BufferNode* nd = _completed_buffers_head;
+ _completed_buffers_head = nd->next();
+ nd->set_next(buffers_to_delete);
+ buffers_to_delete = nd;
+ }
+ _completed_buffers_tail = NULL;
+ _n_completed_buffers = 0;
+ DEBUG_ONLY(assert_completed_buffer_list_len_correct_locked());
+ }
+ while (buffers_to_delete != NULL) {
+ BufferNode* nd = buffers_to_delete;
+ buffers_to_delete = nd->next();
+ deallocate_buffer(nd);
+ }
+ assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
+ // So we can safely manipulate these queues.
+ for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) {
+ satb_queue_for_thread(t).reset();
+ }
+ shared_satb_queue()->reset();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shared/satbMarkQueue.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * 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_GC_SHARED_SATBMARKQUEUE_HPP
+#define SHARE_GC_SHARED_SATBMARKQUEUE_HPP
+
+#include "gc/shared/ptrQueue.hpp"
+#include "memory/allocation.hpp"
+
+class JavaThread;
+class SATBMarkQueueSet;
+
+// Base class for processing the contents of a SATB buffer.
+class SATBBufferClosure : public StackObj {
+protected:
+ ~SATBBufferClosure() { }
+
+public:
+ // Process the SATB entries in the designated buffer range.
+ virtual void do_buffer(void** buffer, size_t size) = 0;
+};
+
+// A PtrQueue whose elements are (possibly stale) pointers to object heads.
+class SATBMarkQueue: public PtrQueue {
+ friend class SATBMarkQueueSet;
+
+private:
+ // Filter out unwanted entries from the buffer.
+ inline void filter();
+
+ // Removes entries from the buffer that are no longer needed.
+ template<typename Filter>
+ inline void apply_filter(Filter filter_out);
+
+public:
+ SATBMarkQueue(SATBMarkQueueSet* qset, bool permanent = false);
+
+ // Process queue entries and free resources.
+ void flush();
+
+ // Apply cl to the active part of the buffer.
+ // Prerequisite: Must be at a safepoint.
+ void apply_closure_and_empty(SATBBufferClosure* cl);
+
+ // Overrides PtrQueue::should_enqueue_buffer(). See the method's
+ // definition for more information.
+ virtual bool should_enqueue_buffer();
+
+#ifndef PRODUCT
+ // Helpful for debugging
+ void print(const char* name);
+#endif // PRODUCT
+
+ // Compiler support.
+ static ByteSize byte_offset_of_index() {
+ return PtrQueue::byte_offset_of_index<SATBMarkQueue>();
+ }
+ using PtrQueue::byte_width_of_index;
+
+ static ByteSize byte_offset_of_buf() {
+ return PtrQueue::byte_offset_of_buf<SATBMarkQueue>();
+ }
+ using PtrQueue::byte_width_of_buf;
+
+ static ByteSize byte_offset_of_active() {
+ return PtrQueue::byte_offset_of_active<SATBMarkQueue>();
+ }
+ using PtrQueue::byte_width_of_active;
+
+};
+
+class SATBMarkQueueSet: public PtrQueueSet {
+ SATBMarkQueue _shared_satb_queue;
+ size_t _buffer_enqueue_threshold;
+
+#ifdef ASSERT
+ void dump_active_states(bool expected_active);
+ void verify_active_states(bool expected_active);
+#endif // ASSERT
+
+protected:
+ SATBMarkQueueSet();
+ ~SATBMarkQueueSet() {}
+
+ template<typename Filter>
+ void apply_filter(Filter filter, SATBMarkQueue* queue) {
+ queue->apply_filter(filter);
+ }
+
+ void initialize(Monitor* cbl_mon, Mutex* fl_lock,
+ int process_completed_threshold,
+ uint buffer_enqueue_threshold_percentage,
+ Mutex* lock);
+
+public:
+ virtual SATBMarkQueue& satb_queue_for_thread(JavaThread* const t) const = 0;
+
+ // Apply "set_active(active)" to all SATB queues in the set. It should be
+ // called only with the world stopped. The method will assert that the
+ // SATB queues of all threads it visits, as well as the SATB queue
+ // set itself, has an active value same as expected_active.
+ void set_active_all_threads(bool active, bool expected_active);
+
+ size_t buffer_enqueue_threshold() const { return _buffer_enqueue_threshold; }
+ virtual void filter(SATBMarkQueue* queue) = 0;
+
+ // Filter all the currently-active SATB buffers.
+ void filter_thread_buffers();
+
+ // If there exists some completed buffer, pop and process it, and
+ // return true. Otherwise return false. Processing a buffer
+ // consists of applying the closure to the active range of the
+ // buffer; the leading entries may be excluded due to filtering.
+ bool apply_closure_to_completed_buffer(SATBBufferClosure* cl);
+
+#ifndef PRODUCT
+ // Helpful for debugging
+ void print_all(const char* msg);
+#endif // PRODUCT
+
+ SATBMarkQueue* shared_satb_queue() { return &_shared_satb_queue; }
+
+ // If a marking is being abandoned, reset any unprocessed log buffers.
+ void abandon_partial_marking();
+};
+
+inline void SATBMarkQueue::filter() {
+ static_cast<SATBMarkQueueSet*>(qset())->filter(this);
+}
+
+// Removes entries from the buffer that are no longer needed, as
+// determined by filter. If e is a void* entry in the buffer,
+// filter_out(e) must be a valid expression whose value is convertible
+// to bool. Entries are removed (filtered out) if the result is true,
+// retained if false.
+template<typename Filter>
+inline void SATBMarkQueue::apply_filter(Filter filter_out) {
+ void** buf = this->_buf;
+
+ if (buf == NULL) {
+ // nothing to do
+ return;
+ }
+
+ // Two-fingered compaction toward the end.
+ void** src = &buf[this->index()];
+ void** dst = &buf[this->capacity()];
+ assert(src <= dst, "invariant");
+ for ( ; src < dst; ++src) {
+ // Search low to high for an entry to keep.
+ void* entry = *src;
+ if (!filter_out(entry)) {
+ // Found keeper. Search high to low for an entry to discard.
+ while (src < --dst) {
+ if (filter_out(*dst)) {
+ *dst = entry; // Replace discard with keeper.
+ break;
+ }
+ }
+ // If discard search failed (src == dst), the outer loop will also end.
+ }
+ }
+ // dst points to the lowest retained entry, or the end of the buffer
+ // if all the entries were filtered out.
+ this->set_index(dst - buf);
+}
+
+#endif // SHARE_GC_SHARED_SATBMARKQUEUE_HPP
--- a/src/hotspot/share/gc/shared/stringdedup/stringDedupThread.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/shared/stringdedup/stringDedupThread.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -59,8 +59,8 @@
public:
StringDedupSharedClosure(StringDedupStat* stat) : _stat(stat) {}
- virtual void do_oop(oop* p) { ShouldNotReachHere(); }
- virtual void do_oop(narrowOop* p) {
+ virtual void do_oop(narrowOop* p) { ShouldNotReachHere(); }
+ virtual void do_oop(oop* p) {
oop java_string = RawAccess<>::oop_load(p);
StringDedupTable::deduplicate(java_string, _stat);
}
--- a/src/hotspot/share/gc/shared/threadLocalAllocBuffer.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/shared/threadLocalAllocBuffer.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -226,7 +226,9 @@
// Assuming each thread's active tlab is, on average,
// 1/2 full at a GC
_target_refills = 100 / (2 * TLABWasteTargetPercent);
- _target_refills = MAX2(_target_refills, (unsigned)1U);
+ // We need to set initial target refills to 2 to avoid a GC which causes VM
+ // abort during VM initialization.
+ _target_refills = MAX2(_target_refills, 2U);
_global_stats = new GlobalTLABStats();
--- a/src/hotspot/share/gc/z/c1/zBarrierSetC1.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/z/c1/zBarrierSetC1.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -190,8 +190,8 @@
// Downgrade access to MO_UNORDERED
decorators = (decorators & ~MO_DECORATOR_MASK) | MO_UNORDERED;
- // Remove C1_WRITE_ACCESS
- decorators = (decorators & ~C1_WRITE_ACCESS);
+ // Remove ACCESS_WRITE
+ decorators = (decorators & ~ACCESS_WRITE);
// Generate synthetic load at
access.gen()->access_load_at(decorators,
--- a/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -68,7 +68,26 @@
}
bool ZBarrierSetC2::is_gc_barrier_node(Node* node) const {
- return node->is_LoadBarrier();
+ // 1. This step follows potential oop projections of a load barrier before expansion
+ if (node->is_Proj()) {
+ node = node->in(0);
+ }
+
+ // 2. This step checks for unexpanded load barriers
+ if (node->is_LoadBarrier()) {
+ return true;
+ }
+
+ // 3. This step checks for the phi corresponding to an optimized load barrier expansion
+ if (node->is_Phi()) {
+ PhiNode* phi = node->as_Phi();
+ Node* n = phi->in(1);
+ if (n != NULL && (n->is_LoadBarrierSlowReg() || n->is_LoadBarrierWeakSlowReg())) {
+ return true;
+ }
+ }
+
+ return false;
}
void ZBarrierSetC2::register_potential_barrier_node(Node* node) const {
@@ -109,7 +128,7 @@
ZBarrierSetC2State* s = bs->state();
if (s->load_barrier_count() >= 2) {
Compile::TracePhase tp("idealLoop", &C->timers[Phase::_t_idealLoop]);
- PhaseIdealLoop ideal_loop(igvn, true, false, true);
+ PhaseIdealLoop ideal_loop(igvn, LoopOptsLastRound);
if (C->major_progress()) C->print_method(PHASE_PHASEIDEALLOOP_ITERATIONS, 2);
}
}
@@ -637,7 +656,10 @@
if (barrier == transformed_barrier) {
kit->set_control(gvn.transform(new ProjNode(barrier, LoadBarrierNode::Control)));
}
- return gvn.transform(new ProjNode(transformed_barrier, LoadBarrierNode::Oop));
+ Node* result = gvn.transform(new ProjNode(transformed_barrier, LoadBarrierNode::Oop));
+ assert(is_gc_barrier_node(result), "sanity");
+ assert(step_over_gc_barrier(result) == val, "sanity");
+ return result;
} else {
return val;
}
@@ -963,6 +985,9 @@
traverse(preceding_barrier_node, result_region, result_phi, -1);
#endif
+ assert(is_gc_barrier_node(result_phi), "sanity");
+ assert(step_over_gc_barrier(result_phi) == in_val, "sanity");
+
return;
}
@@ -1376,6 +1401,32 @@
}
}
+Node* ZBarrierSetC2::step_over_gc_barrier(Node* c) const {
+ Node* node = c;
+
+ // 1. This step follows potential oop projections of a load barrier before expansion
+ if (node->is_Proj()) {
+ node = node->in(0);
+ }
+
+ // 2. This step checks for unexpanded load barriers
+ if (node->is_LoadBarrier()) {
+ return node->in(LoadBarrierNode::Oop);
+ }
+
+ // 3. This step checks for the phi corresponding to an optimized load barrier expansion
+ if (node->is_Phi()) {
+ PhiNode* phi = node->as_Phi();
+ Node* n = phi->in(1);
+ if (n != NULL && (n->is_LoadBarrierSlowReg() || n->is_LoadBarrierWeakSlowReg())) {
+ assert(c == node, "projections from step 1 should only be seen before macro expansion");
+ return phi->in(2);
+ }
+ }
+
+ return c;
+}
+
// == Verification ==
#ifdef ASSERT
--- a/src/hotspot/share/gc/z/c2/zBarrierSetC2.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/z/c2/zBarrierSetC2.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -101,7 +101,9 @@
const TypePtr* t,
MemOrd mo,
ControlDependency control_dependency = DependsOnlyOnTest)
- : LoadPNode(c, mem, adr, at, t, mo, control_dependency) {}
+ : LoadPNode(c, mem, adr, at, t, mo, control_dependency) {
+ init_class_id(Class_LoadBarrierSlowReg);
+ }
virtual const char * name() {
return "LoadBarrierSlowRegNode";
@@ -123,7 +125,9 @@
const TypePtr* t,
MemOrd mo,
ControlDependency control_dependency = DependsOnlyOnTest)
- : LoadPNode(c, mem, adr, at, t, mo, control_dependency) {}
+ : LoadPNode(c, mem, adr, at, t, mo, control_dependency) {
+ init_class_id(Class_LoadBarrierWeakSlowReg);
+ }
virtual const char * name() {
return "LoadBarrierWeakSlowRegNode";
@@ -182,6 +186,7 @@
bool oop_reload_allowed = true) const;
virtual void* create_barrier_state(Arena* comp_arena) const;
+ virtual bool has_load_barriers() const { return true; }
virtual bool is_gc_barrier_node(Node* node) const;
virtual void eliminate_gc_barrier(PhaseMacroExpand* macro, Node* node) const { }
virtual void eliminate_useless_gc_barriers(Unique_Node_List &useful) const;
@@ -190,7 +195,7 @@
virtual void register_potential_barrier_node(Node* node) const;
virtual void unregister_potential_barrier_node(Node* node) const;
virtual bool array_copy_requires_gc_barriers(BasicType type) const { return true; }
- virtual Node* step_over_gc_barrier(Node* c) const { return c; }
+ virtual Node* step_over_gc_barrier(Node* c) const;
// If the BarrierSetC2 state has kept macro nodes in its compilation unit state to be
// expanded later, then now is the time to do so.
virtual bool expand_macro_nodes(PhaseMacroExpand* macro) const;
--- a/src/hotspot/share/gc/z/zBarrierSet.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/z/zBarrierSet.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -22,23 +22,27 @@
*/
#include "precompiled.hpp"
+#include "gc/z/zBarrierSet.hpp"
+#include "gc/z/zBarrierSetAssembler.hpp"
+#include "gc/z/zGlobals.hpp"
+#include "gc/z/zHeap.inline.hpp"
+#include "gc/z/zThreadLocalData.hpp"
+#include "runtime/thread.hpp"
+#include "utilities/macros.hpp"
#ifdef COMPILER1
#include "gc/z/c1/zBarrierSetC1.hpp"
#endif
#ifdef COMPILER2
#include "gc/z/c2/zBarrierSetC2.hpp"
#endif
-#include "gc/z/zBarrierSet.hpp"
-#include "gc/z/zBarrierSetAssembler.hpp"
-#include "gc/z/zGlobals.hpp"
-#include "gc/z/zHeap.inline.hpp"
-#include "gc/z/zThreadLocalData.hpp"
-#include "runtime/thread.hpp"
+
+class ZBarrierSetC1;
+class ZBarrierSetC2;
ZBarrierSet::ZBarrierSet() :
BarrierSet(make_barrier_set_assembler<ZBarrierSetAssembler>(),
- COMPILER1_PRESENT( make_barrier_set_c1<ZBarrierSetC1>() ) NOT_COMPILER1(NULL),
- COMPILER2_PRESENT( make_barrier_set_c2<ZBarrierSetC2>() ) NOT_COMPILER2(NULL),
+ make_barrier_set_c1<ZBarrierSetC1>(),
+ make_barrier_set_c2<ZBarrierSetC2>(),
BarrierSet::FakeRtti(BarrierSet::ZBarrierSet)) {}
ZBarrierSetAssembler* ZBarrierSet::assembler() {
--- a/src/hotspot/share/gc/z/zGlobals.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/z/zGlobals.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -117,11 +117,8 @@
// Marked state
extern uintptr_t ZAddressMetadataMarked;
-// Address space for mark stack allocations
-const size_t ZMarkStackSpaceSizeShift = 40; // 1TB
-const size_t ZMarkStackSpaceSize = (size_t)1 << ZMarkStackSpaceSizeShift;
-const uintptr_t ZMarkStackSpaceStart = ZAddressSpaceEnd + ZMarkStackSpaceSize;
-const uintptr_t ZMarkStackSpaceEnd = ZMarkStackSpaceStart + ZMarkStackSpaceSize;
+// Mark stack space
+extern uintptr_t ZMarkStackSpaceStart;
const size_t ZMarkStackSpaceExpandSize = (size_t)1 << 25; // 32M
// Mark stack and magazine sizes
--- a/src/hotspot/share/gc/z/zMark.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/z/zMark.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -25,6 +25,7 @@
#define SHARE_GC_Z_ZMARK_HPP
#include "gc/z/zMarkStack.hpp"
+#include "gc/z/zMarkStackAllocator.hpp"
#include "gc/z/zMarkTerminate.hpp"
#include "oops/oopsHierarchy.hpp"
#include "utilities/globalDefinitions.hpp"
--- a/src/hotspot/share/gc/z/zMarkStack.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/z/zMarkStack.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -22,173 +22,11 @@
*/
#include "precompiled.hpp"
-#include "gc/z/zErrno.hpp"
-#include "gc/z/zGlobals.hpp"
-#include "gc/z/zLock.inline.hpp"
#include "gc/z/zMarkStack.inline.hpp"
+#include "gc/z/zMarkStackAllocator.hpp"
#include "logging/log.hpp"
-#include "runtime/atomic.hpp"
#include "utilities/debug.hpp"
-#include <sys/mman.h>
-#include <sys/types.h>
-
-ZMarkStackSpace::ZMarkStackSpace() :
- _expand_lock(),
- _top(0),
- _end(0) {
- assert(ZMarkStacksMax >= ZMarkStackSpaceExpandSize, "ZMarkStacksMax too small");
- assert(ZMarkStacksMax <= ZMarkStackSpaceSize, "ZMarkStacksMax too large");
-
- // Reserve address space
- const void* res = mmap((void*)ZMarkStackSpaceStart, ZMarkStackSpaceSize,
- PROT_NONE, MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
- if (res != (void*)ZMarkStackSpaceStart) {
- log_error(gc, marking)("Failed to reserve address space for marking stacks");
- return;
- }
-
- // Successfully initialized
- _top = _end = ZMarkStackSpaceStart;
-}
-
-bool ZMarkStackSpace::is_initialized() const {
- return _top != 0;
-}
-
-void ZMarkStackSpace::expand() {
- const size_t max = ZMarkStackSpaceStart + ZMarkStacksMax;
- if (_end + ZMarkStackSpaceExpandSize > max) {
- // Expansion limit reached. This is a fatal error since we
- // currently can't recover from running out of mark stack space.
- fatal("Mark stack overflow (current size " SIZE_FORMAT "M, max size " SIZE_FORMAT "M),"
- " use -XX:ZMarkStacksMax=<size> to increase this limit",
- (_end - ZMarkStackSpaceStart) / M, ZMarkStacksMax / M);
- }
-
- void* const res = mmap((void*)_end, ZMarkStackSpaceExpandSize,
- PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE|MAP_FIXED, -1, 0);
- if (res == MAP_FAILED) {
- // Failed to map memory. This is a fatal error since we
- // currently can't recover from running out of mark stack space.
- ZErrno err;
- fatal("Failed to map memory for marking stacks (%s)", err.to_string());
- }
-}
-
-uintptr_t ZMarkStackSpace::alloc_space(size_t size) {
- uintptr_t top = _top;
-
- for (;;) {
- const uintptr_t new_top = top + size;
- if (new_top > _end) {
- // Not enough space left
- return 0;
- }
-
- const uintptr_t prev_top = Atomic::cmpxchg(new_top, &_top, top);
- if (prev_top == top) {
- // Success
- return top;
- }
-
- // Retry
- top = prev_top;
- }
-}
-
-uintptr_t ZMarkStackSpace::expand_and_alloc_space(size_t size) {
- ZLocker locker(&_expand_lock);
-
- // Retry allocation before expanding
- uintptr_t addr = alloc_space(size);
- if (addr != 0) {
- return addr;
- }
-
- // Expand stack space
- expand();
-
- log_debug(gc, marking)("Expanding mark stack space: " SIZE_FORMAT "M->" SIZE_FORMAT "M",
- (_end - ZMarkStackSpaceStart) / M,
- (_end - ZMarkStackSpaceStart + ZMarkStackSpaceExpandSize) / M);
-
- // Increment top before end to make sure another
- // thread can't steal out newly expanded space.
- addr = Atomic::add(size, &_top) - size;
- _end += ZMarkStackSpaceExpandSize;
-
- return addr;
-}
-
-uintptr_t ZMarkStackSpace::alloc(size_t size) {
- const uintptr_t addr = alloc_space(size);
- if (addr != 0) {
- return addr;
- }
-
- return expand_and_alloc_space(size);
-}
-
-ZMarkStackAllocator::ZMarkStackAllocator() :
- _freelist(),
- _space() {
- guarantee(sizeof(ZMarkStack) == ZMarkStackSize, "Size mismatch");
- guarantee(sizeof(ZMarkStackMagazine) <= ZMarkStackSize, "Size mismatch");
-
- // Prime free list to avoid an immediate space
- // expansion when marking starts.
- if (_space.is_initialized()) {
- prime_freelist();
- }
-}
-
-bool ZMarkStackAllocator::is_initialized() const {
- return _space.is_initialized();
-}
-
-void ZMarkStackAllocator::prime_freelist() {
- for (size_t size = 0; size < ZMarkStackSpaceExpandSize; size += ZMarkStackMagazineSize) {
- const uintptr_t addr = _space.alloc(ZMarkStackMagazineSize);
- ZMarkStackMagazine* const magazine = create_magazine_from_space(addr, ZMarkStackMagazineSize);
- free_magazine(magazine);
- }
-}
-
-ZMarkStackMagazine* ZMarkStackAllocator::create_magazine_from_space(uintptr_t addr, size_t size) {
- assert(is_aligned(size, ZMarkStackSize), "Invalid size");
-
- // Use first stack as magazine
- ZMarkStackMagazine* const magazine = new ((void*)addr) ZMarkStackMagazine();
- for (size_t i = ZMarkStackSize; i < size; i += ZMarkStackSize) {
- ZMarkStack* const stack = new ((void*)(addr + i)) ZMarkStack();
- const bool success = magazine->push(stack);
- assert(success, "Magazine should never get full");
- }
-
- return magazine;
-}
-
-ZMarkStackMagazine* ZMarkStackAllocator::alloc_magazine() {
- // Try allocating from the free list first
- ZMarkStackMagazine* const magazine = _freelist.pop_atomic();
- if (magazine != NULL) {
- return magazine;
- }
-
- // Allocate new magazine
- const uintptr_t addr = _space.alloc(ZMarkStackMagazineSize);
- if (addr == 0) {
- return NULL;
- }
-
- return create_magazine_from_space(addr, ZMarkStackMagazineSize);
-}
-
-void ZMarkStackAllocator::free_magazine(ZMarkStackMagazine* magazine) {
- _freelist.push_atomic(magazine);
-}
-
ZMarkStripe::ZMarkStripe() :
_published(),
_overflowed() {}
--- a/src/hotspot/share/gc/z/zMarkStack.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/z/zMarkStack.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -25,9 +25,7 @@
#define SHARE_GC_Z_ZMARKSTACK_HPP
#include "gc/z/zGlobals.hpp"
-#include "gc/z/zLock.hpp"
#include "gc/z/zMarkStackEntry.hpp"
-#include "memory/allocation.hpp"
#include "utilities/globalDefinitions.hpp"
template <typename T, size_t S>
@@ -73,42 +71,6 @@
typedef ZStack<ZMarkStack*, ZMarkStackMagazineSlots> ZMarkStackMagazine;
typedef ZStackList<ZMarkStackMagazine> ZMarkStackMagazineList;
-class ZMarkStackSpace {
-private:
- ZLock _expand_lock;
- volatile uintptr_t _top;
- volatile uintptr_t _end;
-
- void expand();
-
- uintptr_t alloc_space(size_t size);
- uintptr_t expand_and_alloc_space(size_t size);
-
-public:
- ZMarkStackSpace();
-
- bool is_initialized() const;
-
- uintptr_t alloc(size_t size);
-};
-
-class ZMarkStackAllocator {
-private:
- ZMarkStackMagazineList _freelist ATTRIBUTE_ALIGNED(ZCacheLineSize);
- ZMarkStackSpace _space ATTRIBUTE_ALIGNED(ZCacheLineSize);
-
- void prime_freelist();
- ZMarkStackMagazine* create_magazine_from_space(uintptr_t addr, size_t size);
-
-public:
- ZMarkStackAllocator();
-
- bool is_initialized() const;
-
- ZMarkStackMagazine* alloc_magazine();
- void free_magazine(ZMarkStackMagazine* magazine);
-};
-
class ZMarkStripe {
private:
ZMarkStackList _published ATTRIBUTE_ALIGNED(ZCacheLineSize);
@@ -144,6 +106,8 @@
ZMarkStripe* stripe_for_addr(uintptr_t addr);
};
+class ZMarkStackAllocator;
+
class ZMarkThreadLocalStacks {
private:
ZMarkStackMagazine* _magazine;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/z/zMarkStackAllocator.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "precompiled.hpp"
+#include "gc/z/zLock.inline.hpp"
+#include "gc/z/zMarkStack.inline.hpp"
+#include "gc/z/zMarkStackAllocator.hpp"
+#include "logging/log.hpp"
+#include "runtime/atomic.hpp"
+#include "runtime/os.hpp"
+#include "utilities/debug.hpp"
+
+uintptr_t ZMarkStackSpaceStart;
+
+ZMarkStackSpace::ZMarkStackSpace() :
+ _expand_lock(),
+ _start(0),
+ _top(0),
+ _end(0) {
+ assert(ZMarkStackSpaceLimit >= ZMarkStackSpaceExpandSize, "ZMarkStackSpaceLimit too small");
+
+ // Reserve address space
+ const size_t size = ZMarkStackSpaceLimit;
+ const size_t alignment = (size_t)os::vm_allocation_granularity();
+ const uintptr_t addr = (uintptr_t)os::reserve_memory(size, NULL, alignment, mtGC);
+ if (addr == 0) {
+ log_error(gc, marking)("Failed to reserve address space for mark stacks");
+ return;
+ }
+
+ // Successfully initialized
+ _start = _top = _end = addr;
+
+ // Register mark stack space start
+ ZMarkStackSpaceStart = _start;
+}
+
+bool ZMarkStackSpace::is_initialized() const {
+ return _start != 0;
+}
+
+uintptr_t ZMarkStackSpace::alloc_space(size_t size) {
+ uintptr_t top = Atomic::load(&_top);
+
+ for (;;) {
+ const uintptr_t end = Atomic::load(&_end);
+ const uintptr_t new_top = top + size;
+ if (new_top > end) {
+ // Not enough space left
+ return 0;
+ }
+
+ const uintptr_t prev_top = Atomic::cmpxchg(new_top, &_top, top);
+ if (prev_top == top) {
+ // Success
+ return top;
+ }
+
+ // Retry
+ top = prev_top;
+ }
+}
+
+uintptr_t ZMarkStackSpace::expand_and_alloc_space(size_t size) {
+ ZLocker locker(&_expand_lock);
+
+ // Retry allocation before expanding
+ uintptr_t addr = alloc_space(size);
+ if (addr != 0) {
+ return addr;
+ }
+
+ // Check expansion limit
+ const size_t expand_size = ZMarkStackSpaceExpandSize;
+ const size_t old_size = _end - _start;
+ const size_t new_size = old_size + expand_size;
+ if (new_size > ZMarkStackSpaceLimit) {
+ // Expansion limit reached. This is a fatal error since we
+ // currently can't recover from running out of mark stack space.
+ fatal("Mark stack space exhausted. Use -XX:ZMarkStackSpaceLimit=<size> to increase the "
+ "maximum number of bytes allocated for mark stacks. Current limit is " SIZE_FORMAT "M.",
+ ZMarkStackSpaceLimit / M);
+ }
+
+ log_debug(gc, marking)("Expanding mark stack space: " SIZE_FORMAT "M->" SIZE_FORMAT "M",
+ old_size / M, new_size / M);
+
+ // Expand
+ os::commit_memory_or_exit((char*)_end, expand_size, false /* executable */, "Mark stack space");
+
+ // Increment top before end to make sure another
+ // thread can't steal out newly expanded space.
+ addr = Atomic::add(size, &_top) - size;
+ Atomic::add(expand_size, &_end);
+
+ return addr;
+}
+
+uintptr_t ZMarkStackSpace::alloc(size_t size) {
+ const uintptr_t addr = alloc_space(size);
+ if (addr != 0) {
+ return addr;
+ }
+
+ return expand_and_alloc_space(size);
+}
+
+ZMarkStackAllocator::ZMarkStackAllocator() :
+ _freelist(),
+ _space() {
+ guarantee(sizeof(ZMarkStack) == ZMarkStackSize, "Size mismatch");
+ guarantee(sizeof(ZMarkStackMagazine) <= ZMarkStackSize, "Size mismatch");
+
+ // Prime free list to avoid an immediate space
+ // expansion when marking starts.
+ if (_space.is_initialized()) {
+ prime_freelist();
+ }
+}
+
+bool ZMarkStackAllocator::is_initialized() const {
+ return _space.is_initialized();
+}
+
+void ZMarkStackAllocator::prime_freelist() {
+ for (size_t size = 0; size < ZMarkStackSpaceExpandSize; size += ZMarkStackMagazineSize) {
+ const uintptr_t addr = _space.alloc(ZMarkStackMagazineSize);
+ ZMarkStackMagazine* const magazine = create_magazine_from_space(addr, ZMarkStackMagazineSize);
+ free_magazine(magazine);
+ }
+}
+
+ZMarkStackMagazine* ZMarkStackAllocator::create_magazine_from_space(uintptr_t addr, size_t size) {
+ assert(is_aligned(size, ZMarkStackSize), "Invalid size");
+
+ // Use first stack as magazine
+ ZMarkStackMagazine* const magazine = new ((void*)addr) ZMarkStackMagazine();
+ for (size_t i = ZMarkStackSize; i < size; i += ZMarkStackSize) {
+ ZMarkStack* const stack = new ((void*)(addr + i)) ZMarkStack();
+ const bool success = magazine->push(stack);
+ assert(success, "Magazine should never get full");
+ }
+
+ return magazine;
+}
+
+ZMarkStackMagazine* ZMarkStackAllocator::alloc_magazine() {
+ // Try allocating from the free list first
+ ZMarkStackMagazine* const magazine = _freelist.pop_atomic();
+ if (magazine != NULL) {
+ return magazine;
+ }
+
+ // Allocate new magazine
+ const uintptr_t addr = _space.alloc(ZMarkStackMagazineSize);
+ if (addr == 0) {
+ return NULL;
+ }
+
+ return create_magazine_from_space(addr, ZMarkStackMagazineSize);
+}
+
+void ZMarkStackAllocator::free_magazine(ZMarkStackMagazine* magazine) {
+ _freelist.push_atomic(magazine);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/z/zMarkStackAllocator.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * 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_GC_Z_ZMARKSTACKALLOCATOR_HPP
+#define SHARE_GC_Z_ZMARKSTACKALLOCATOR_HPP
+
+#include "gc/z/zGlobals.hpp"
+#include "gc/z/zLock.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+class ZMarkStackSpace {
+private:
+ ZLock _expand_lock;
+ uintptr_t _start;
+ volatile uintptr_t _top;
+ volatile uintptr_t _end;
+
+ void expand();
+
+ uintptr_t alloc_space(size_t size);
+ uintptr_t expand_and_alloc_space(size_t size);
+
+public:
+ ZMarkStackSpace();
+
+ bool is_initialized() const;
+
+ uintptr_t alloc(size_t size);
+};
+
+class ZMarkStackAllocator {
+private:
+ ZMarkStackMagazineList _freelist ATTRIBUTE_ALIGNED(ZCacheLineSize);
+ ZMarkStackSpace _space ATTRIBUTE_ALIGNED(ZCacheLineSize);
+
+ void prime_freelist();
+ ZMarkStackMagazine* create_magazine_from_space(uintptr_t addr, size_t size);
+
+public:
+ ZMarkStackAllocator();
+
+ bool is_initialized() const;
+
+ ZMarkStackMagazine* alloc_magazine();
+ void free_magazine(ZMarkStackMagazine* magazine);
+};
+
+#endif // SHARE_GC_Z_ZMARKSTACKALLOCATOR_HPP
--- a/src/hotspot/share/gc/z/zRelocationSetSelector.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/z/zRelocationSetSelector.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -63,34 +63,34 @@
const size_t partition_size_shift = exact_log2(partition_size);
const size_t npages = _registered_pages.size();
- size_t partition_slots[npartitions];
- size_t partition_finger[npartitions];
+ // Partition slots/fingers
+ size_t partitions[npartitions];
// Allocate destination array
_sorted_pages = REALLOC_C_HEAP_ARRAY(const ZPage*, _sorted_pages, npages, mtGC);
debug_only(memset(_sorted_pages, 0, npages * sizeof(ZPage*)));
// Calculate partition slots
- memset(partition_slots, 0, sizeof(partition_slots));
+ memset(partitions, 0, sizeof(partitions));
ZArrayIterator<const ZPage*> iter1(&_registered_pages);
for (const ZPage* page; iter1.next(&page);) {
const size_t index = page->live_bytes() >> partition_size_shift;
- partition_slots[index]++;
+ partitions[index]++;
}
- // Calculate accumulated partition slots and fingers
- size_t prev_partition_slots = 0;
+ // Calculate partition fingers
+ size_t finger = 0;
for (size_t i = 0; i < npartitions; i++) {
- partition_slots[i] += prev_partition_slots;
- partition_finger[i] = prev_partition_slots;
- prev_partition_slots = partition_slots[i];
+ const size_t slots = partitions[i];
+ partitions[i] = finger;
+ finger += slots;
}
// Sort pages into partitions
ZArrayIterator<const ZPage*> iter2(&_registered_pages);
for (const ZPage* page; iter2.next(&page);) {
const size_t index = page->live_bytes() >> partition_size_shift;
- const size_t finger = partition_finger[index]++;
+ const size_t finger = partitions[index]++;
assert(_sorted_pages[finger] == NULL, "Invalid finger");
_sorted_pages[finger] = page;
}
--- a/src/hotspot/share/gc/z/zRootsIterator.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/z/zRootsIterator.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -24,7 +24,6 @@
#include "precompiled.hpp"
#include "classfile/classLoaderData.hpp"
#include "classfile/stringTable.hpp"
-#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "code/codeCache.hpp"
#include "compiler/oopMap.hpp"
@@ -74,7 +73,6 @@
static const ZStatSubPhase ZSubPhasePauseWeakRootsJNIWeakHandles("Pause Weak Roots JNIWeakHandles");
static const ZStatSubPhase ZSubPhasePauseWeakRootsJVMTIWeakExport("Pause Weak Roots JVMTIWeakExport");
static const ZStatSubPhase ZSubPhasePauseWeakRootsJFRWeak("Pause Weak Roots JFRWeak");
-static const ZStatSubPhase ZSubPhasePauseWeakRootsSymbolTable("Pause Weak Roots SymbolTable");
static const ZStatSubPhase ZSubPhasePauseWeakRootsStringTable("Pause Weak Roots StringTable");
static const ZStatSubPhase ZSubPhaseConcurrentWeakRoots("Concurrent Weak Roots");
@@ -302,11 +300,9 @@
_jfr_weak(this),
_vm_weak_handles(this),
_jni_weak_handles(this),
- _symbol_table(this),
_string_table(this) {
assert(SafepointSynchronize::is_at_safepoint(), "Should be at safepoint");
ZStatTimer timer(ZSubPhasePauseWeakRootsSetup);
- SymbolTable::clear_parallel_claimed_index();
StringTable::reset_dead_counter();
}
@@ -337,12 +333,6 @@
#endif
}
-void ZWeakRootsIterator::do_symbol_table(BoolObjectClosure* is_alive, OopClosure* cl) {
- ZStatTimer timer(ZSubPhasePauseWeakRootsSymbolTable);
- int dummy;
- SymbolTable::possibly_parallel_unlink(&dummy, &dummy);
-}
-
class ZStringTableDeadCounterBoolObjectClosure : public BoolObjectClosure {
private:
BoolObjectClosure* const _cl;
@@ -375,9 +365,6 @@
void ZWeakRootsIterator::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* cl) {
ZStatTimer timer(ZSubPhasePauseWeakRoots);
- if (ZSymbolTableUnloading) {
- _symbol_table.weak_oops_do(is_alive, cl);
- }
if (ZWeakRoots) {
_jvmti_weak_export.weak_oops_do(is_alive, cl);
_jfr_weak.weak_oops_do(is_alive, cl);
--- a/src/hotspot/share/gc/z/zRootsIterator.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/z/zRootsIterator.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -130,14 +130,12 @@
void do_jni_weak_handles(BoolObjectClosure* is_alive, OopClosure* cl);
void do_jvmti_weak_export(BoolObjectClosure* is_alive, OopClosure* cl);
void do_jfr_weak(BoolObjectClosure* is_alive, OopClosure* cl);
- void do_symbol_table(BoolObjectClosure* is_alive, OopClosure* cl);
void do_string_table(BoolObjectClosure* is_alive, OopClosure* cl);
ZSerialWeakOopsDo<ZWeakRootsIterator, &ZWeakRootsIterator::do_jvmti_weak_export> _jvmti_weak_export;
ZSerialWeakOopsDo<ZWeakRootsIterator, &ZWeakRootsIterator::do_jfr_weak> _jfr_weak;
ZParallelWeakOopsDo<ZWeakRootsIterator, &ZWeakRootsIterator::do_vm_weak_handles> _vm_weak_handles;
ZParallelWeakOopsDo<ZWeakRootsIterator, &ZWeakRootsIterator::do_jni_weak_handles> _jni_weak_handles;
- ZParallelWeakOopsDo<ZWeakRootsIterator, &ZWeakRootsIterator::do_symbol_table> _symbol_table;
ZParallelWeakOopsDo<ZWeakRootsIterator, &ZWeakRootsIterator::do_string_table> _string_table;
public:
--- a/src/hotspot/share/gc/z/z_globals.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/gc/z/z_globals.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -53,9 +53,9 @@
"Allow Java threads to stall and wait for GC to complete " \
"instead of immediately throwing an OutOfMemoryError") \
\
- product(size_t, ZMarkStacksMax, NOT_LP64(512*M) LP64_ONLY(8*G), \
- "Maximum number of bytes allocated for marking stacks") \
- range(32*M, NOT_LP64(512*M) LP64_ONLY(1024*G)) \
+ product(size_t, ZMarkStackSpaceLimit, 8*G, \
+ "Maximum number of bytes allocated for mark stacks") \
+ range(32*M, 1024*G) \
\
product(uint, ZCollectionInterval, 0, \
"Force GC at a fixed time interval (in seconds)") \
@@ -79,9 +79,6 @@
diagnostic(bool, ZVerifyForwarding, false, \
"Verify forwarding tables") \
\
- diagnostic(bool, ZSymbolTableUnloading, false, \
- "Unload unused VM symbols") \
- \
diagnostic(bool, ZWeakRoots, true, \
"Treat JNI WeakGlobalRefs and StringTable as weak roots") \
\
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/include/cds.h Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * 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_INCLUDE_CDS_H
+#define SHARE_INCLUDE_CDS_H
+
+// This file declares the CDS data structures that are used by the HotSpot Serviceability Agent
+// (see C sources inside src/jdk.hotspot.agent).
+//
+// We should use only standard C types. Do not use custom types such as bool, intx,
+// etc, to avoid introducing unnecessary dependencies to other HotSpot type declarations.
+//
+// Also, this is a C header file. Do not use C++ here.
+
+#define NUM_CDS_REGIONS 9
+#define CDS_ARCHIVE_MAGIC 0xf00baba2
+#define CURRENT_CDS_ARCHIVE_VERSION 5
+#define INVALID_CDS_ARCHIVE_VERSION -1
+
+struct CDSFileMapRegion {
+ int _crc; // crc checksum of the current space
+ size_t _file_offset; // sizeof(this) rounded to vm page size
+ union {
+ char* _base; // copy-on-write base address
+ size_t _offset; // offset from the compressed oop encoding base, only used
+ // by archive heap space
+ } _addr;
+ size_t _used; // for setting space top on read
+ int _read_only; // read only space?
+ int _allow_exec; // executable code in space?
+ void* _oopmap; // bitmap for relocating embedded oops
+ size_t _oopmap_size_in_bits;
+};
+
+struct CDSFileMapHeaderBase {
+ unsigned int _magic; // identify file type
+ int _crc; // header crc checksum
+ int _version; // must be CURRENT_CDS_ARCHIVE_VERSION
+ struct CDSFileMapRegion _space[NUM_CDS_REGIONS];
+};
+
+typedef struct CDSFileMapHeaderBase CDSFileMapHeaderBase;
+
+#endif // SHARE_INCLUDE_CDS_H
--- a/src/hotspot/share/interpreter/interpreterRuntime.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/interpreter/interpreterRuntime.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -52,7 +52,7 @@
#include "runtime/biasedLocking.hpp"
#include "runtime/compilationPolicy.hpp"
#include "runtime/deoptimization.hpp"
-#include "runtime/fieldDescriptor.hpp"
+#include "runtime/fieldDescriptor.inline.hpp"
#include "runtime/frame.inline.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/icache.hpp"
@@ -924,11 +924,11 @@
info.call_kind() == CallInfo::vtable_call, "");
}
#endif
- // Get sender or sender's host_klass, and only set cpCache entry to resolved if
+ // Get sender or sender's unsafe_anonymous_host, and only set cpCache entry to resolved if
// it is not an interface. The receiver for invokespecial calls within interface
// methods must be checked for every call.
InstanceKlass* sender = pool->pool_holder();
- sender = sender->has_host_klass() ? sender->host_klass() : sender;
+ sender = sender->is_unsafe_anonymous() ? sender->unsafe_anonymous_host() : sender;
switch (info.call_kind()) {
case CallInfo::direct_call:
--- a/src/hotspot/share/interpreter/linkResolver.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/interpreter/linkResolver.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -48,7 +48,7 @@
#include "prims/methodHandles.hpp"
#include "prims/nativeLookup.hpp"
#include "runtime/compilationPolicy.hpp"
-#include "runtime/fieldDescriptor.hpp"
+#include "runtime/fieldDescriptor.inline.hpp"
#include "runtime/frame.inline.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/reflection.hpp"
@@ -1167,9 +1167,9 @@
Klass* current_klass = link_info.current_klass();
if (current_klass != NULL && resolved_klass->is_interface()) {
InstanceKlass* ck = InstanceKlass::cast(current_klass);
- InstanceKlass *klass_to_check = !ck->is_anonymous() ?
+ InstanceKlass *klass_to_check = !ck->is_unsafe_anonymous() ?
ck :
- InstanceKlass::cast(ck->host_klass());
+ InstanceKlass::cast(ck->unsafe_anonymous_host());
// Disable verification for the dynamically-generated reflection bytecodes.
bool is_reflect = klass_to_check->is_subclass_of(
SystemDictionary::reflect_MagicAccessorImpl_klass());
@@ -1260,7 +1260,7 @@
// The verifier also checks that the receiver is a subtype of the sender, if the sender is
// a class. If the sender is an interface, the check has to be performed at runtime.
InstanceKlass* sender = InstanceKlass::cast(current_klass);
- sender = sender->is_anonymous() ? sender->host_klass() : sender;
+ sender = sender->is_unsafe_anonymous() ? sender->unsafe_anonymous_host() : sender;
if (sender->is_interface() && recv.not_null()) {
Klass* receiver_klass = recv->klass();
if (!receiver_klass->is_subtype_of(sender)) {
--- a/src/hotspot/share/interpreter/rewriter.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/interpreter/rewriter.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -30,6 +30,7 @@
#include "memory/resourceArea.hpp"
#include "oops/generateOopMap.hpp"
#include "prims/methodHandles.hpp"
+#include "runtime/fieldDescriptor.inline.hpp"
#include "runtime/handles.inline.hpp"
// Computes a CPC map (new_index -> original_index) for constant pool entries
--- a/src/hotspot/share/jfr/jni/jfrJavaSupport.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/jfr/jni/jfrJavaSupport.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -39,7 +39,7 @@
#include "oops/objArrayKlass.hpp"
#include "oops/objArrayOop.inline.hpp"
#include "runtime/handles.inline.hpp"
-#include "runtime/fieldDescriptor.hpp"
+#include "runtime/fieldDescriptor.inline.hpp"
#include "runtime/java.hpp"
#include "runtime/jniHandles.inline.hpp"
#include "runtime/synchronizer.hpp"
--- a/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleDescription.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleDescription.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -29,6 +29,7 @@
#include "jfr/leakprofiler/checkpoint/objectSampleDescription.hpp"
#include "jfr/recorder/checkpoint/jfrCheckpointWriter.hpp"
#include "oops/oop.inline.hpp"
+#include "runtime/fieldDescriptor.inline.hpp"
#include "runtime/thread.hpp"
#include "utilities/ostream.hpp"
@@ -161,10 +162,10 @@
if (k->is_instance_klass()) {
const InstanceKlass* ik = InstanceKlass::cast(k);
- if (ik->is_anonymous()) {
+ if (ik->is_unsafe_anonymous()) {
return;
}
- assert(!ik->is_anonymous(), "invariant");
+ assert(!ik->is_unsafe_anonymous(), "invariant");
const Symbol* name = ik->name();
if (name != NULL) {
write_text("Class Name: ");
--- a/src/hotspot/share/jfr/metadata/metadata.xml Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/jfr/metadata/metadata.xml Thu Aug 23 11:09:16 2018 -0400
@@ -200,7 +200,7 @@
<Event name="MetaspaceAllocationFailure" category="Java Virtual Machine, GC, Metaspace" label="Metaspace Allocation Failure" startTime="false"
stackTrace="true">
<Field type="ClassLoader" name="classLoader" label="Class Loader" />
- <Field type="boolean" name="anonymousClassLoader" label="Anonymous Class Loader" />
+ <Field type="boolean" name="unsafeAnonymousClassLoader" label="Unsafe Anonymous Class Loader" />
<Field type="ulong" contentType="bytes" name="size" label="Size" />
<Field type="MetadataType" name="metadataType" label="Metadata Type" />
<Field type="MetaspaceObjectType" name="metaspaceObjectType" label="Metaspace Object Type" />
@@ -208,7 +208,7 @@
<Event name="MetaspaceOOM" category="Java Virtual Machine, GC, Metaspace" label="Metaspace Out of Memory" startTime="false" stackTrace="true">
<Field type="ClassLoader" name="classLoader" label="Class Loader" />
- <Field type="boolean" name="anonymousClassLoader" label="Anonymous Class Loader" />
+ <Field type="boolean" name="unsafeAnonymousClassLoader" label="Unsafe Anonymous Class Loader" />
<Field type="ulong" contentType="bytes" name="size" label="Size" />
<Field type="MetadataType" name="metadataType" label="Metadata Type" />
<Field type="MetaspaceObjectType" name="metaspaceObjectType" label="Metaspace Object Type" />
@@ -682,11 +682,11 @@
<Field type="long" name="classCount" label="Classes" description="Number of loaded classes" />
<Field type="ulong" contentType="bytes" name="chunkSize" label="Total Chunk Size" description="Total size of all allocated metaspace chunks (each chunk has several blocks)" />
<Field type="ulong" contentType="bytes" name="blockSize" label="Total Block Size" description="Total size of all allocated metaspace blocks (each chunk has several blocks)" />
- <Field type="long" name="anonymousClassCount" label="Unsafe Anonymous Classes" description="Number of loaded classes to support invokedynamic" />
- <Field type="ulong" contentType="bytes" name="anonymousChunkSize" label="Total Unsafe Anonymous Classes Chunk Size"
- description="Total size of all allocated metaspace chunks for anonymous classes (each chunk has several blocks)" />
- <Field type="ulong" contentType="bytes" name="anonymousBlockSize" label="Total Unsafe Anonymous Classes Block Size"
- description="Total size of all allocated metaspace blocks for anonymous classes (each chunk has several blocks)" />
+ <Field type="long" name="unsafeAnonymousClassCount" label="Unsafe Anonymous Classes" description="Number of loaded classes to support invokedynamic" />
+ <Field type="ulong" contentType="bytes" name="unsafeAnonymousChunkSize" label="Total Unsafe Anonymous Classes Chunk Size"
+ description="Total size of all allocated metaspace chunks for unsafe anonymous classes (each chunk has several blocks)" />
+ <Field type="ulong" contentType="bytes" name="unsafeAnonymousBlockSize" label="Total Unsafe Anonymous Classes Block Size"
+ description="Total size of all allocated metaspace blocks for unsafe anonymous classes (each chunk has several blocks)" />
</Event>
<Event name="ThreadAllocationStatistics" category="Java Application, Statistics" label="Thread Allocation Statistics" period="everyChunk">
--- a/src/hotspot/share/jfr/periodic/jfrPeriodic.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/jfr/periodic/jfrPeriodic.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -476,9 +476,9 @@
event.set_classCount(cls->_classes_count);
event.set_chunkSize(cls->_chunk_sz);
event.set_blockSize(cls->_block_sz);
- event.set_anonymousClassCount(cls->_anon_classes_count);
- event.set_anonymousChunkSize(cls->_anon_chunk_sz);
- event.set_anonymousBlockSize(cls->_anon_block_sz);
+ event.set_unsafeAnonymousClassCount(cls->_anon_classes_count);
+ event.set_unsafeAnonymousChunkSize(cls->_anon_chunk_sz);
+ event.set_unsafeAnonymousBlockSize(cls->_anon_block_sz);
event.commit();
return true;
}
--- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -77,7 +77,7 @@
static traceid cld_id(CldPtr cld) {
assert(cld != NULL, "invariant");
- return cld->is_anonymous() ? 0 : TRACE_ID(cld);
+ return cld->is_unsafe_anonymous() ? 0 : TRACE_ID(cld);
}
static void tag_leakp_klass_artifacts(KlassPtr k, bool class_unload) {
@@ -92,7 +92,7 @@
}
CldPtr cld = k->class_loader_data();
assert(cld != NULL, "invariant");
- if (!cld->is_anonymous()) {
+ if (!cld->is_unsafe_anonymous()) {
tag_leakp_artifact(cld, class_unload);
}
}
@@ -230,7 +230,7 @@
int write__artifact__classloader(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* c) {
assert(c != NULL, "invariant");
CldPtr cld = (CldPtr)c;
- assert(!cld->is_anonymous(), "invariant");
+ assert(!cld->is_unsafe_anonymous(), "invariant");
const traceid cld_id = TRACE_ID(cld);
// class loader type
const Klass* class_loader_klass = cld->class_loader_klass();
@@ -301,9 +301,9 @@
assert(artifacts != NULL, "invaiant");
assert(k != NULL, "invariant");
const InstanceKlass* const ik = (const InstanceKlass*)k;
- if (ik->is_anonymous()) {
+ if (ik->is_unsafe_anonymous()) {
CStringEntryPtr entry =
- artifacts->map_cstring(JfrSymbolId::anonymous_klass_name_hash_code(ik));
+ artifacts->map_cstring(JfrSymbolId::unsafe_anonymous_klass_name_hash_code(ik));
assert(entry != NULL, "invariant");
return write__artifact__cstring__entry__(writer, entry);
}
@@ -358,7 +358,7 @@
}
CldPtr cld = klass->class_loader_data();
assert(cld != NULL, "invariant");
- if (!cld->is_anonymous()) {
+ if (!cld->is_unsafe_anonymous()) {
count += class_loader_symbols(cld);
}
if (_method_used_predicate(klass)) {
@@ -374,9 +374,9 @@
assert(klass != NULL, "invariant");
assert(_predicate(klass), "invariant");
const InstanceKlass* const ik = (const InstanceKlass*)klass;
- if (ik->is_anonymous()) {
+ if (ik->is_unsafe_anonymous()) {
CStringEntryPtr entry =
- this->_artifacts->map_cstring(JfrSymbolId::anonymous_klass_name_hash_code(ik));
+ this->_artifacts->map_cstring(JfrSymbolId::unsafe_anonymous_klass_name_hash_code(ik));
assert(entry != NULL, "invariant");
return _unique_predicate(entry->id()) ? write__artifact__cstring__entry__(this->_writer, entry) : 0;
}
@@ -432,7 +432,7 @@
template <template <typename> class Predicate>
int KlassSymbolWriterImpl<Predicate>::class_loader_symbols(CldPtr cld) {
assert(cld != NULL, "invariant");
- assert(!cld->is_anonymous(), "invariant");
+ assert(!cld->is_unsafe_anonymous(), "invariant");
int count = 0;
// class loader type
const Klass* class_loader_klass = cld->class_loader_klass();
@@ -696,7 +696,7 @@
static TypePtr select(KlassPtr klass) {
assert(klass != NULL, "invariant");
CldPtr cld = klass->class_loader_data();
- return cld->is_anonymous() ? NULL : cld;
+ return cld->is_unsafe_anonymous() ? NULL : cld;
}
};
@@ -922,7 +922,7 @@
CLDCallback(bool class_unload) : _class_unload(class_unload) {}
void do_cld(ClassLoaderData* cld) {
assert(cld != NULL, "invariant");
- if (cld->is_anonymous()) {
+ if (cld->is_unsafe_anonymous()) {
return;
}
if (_class_unload) {
--- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -59,14 +59,14 @@
delete _cstring_table;
}
-traceid JfrSymbolId::mark_anonymous_klass_name(const Klass* k) {
+traceid JfrSymbolId::mark_unsafe_anonymous_klass_name(const Klass* k) {
assert(k != NULL, "invariant");
assert(k->is_instance_klass(), "invariant");
- assert(is_anonymous_klass(k), "invariant");
+ assert(is_unsafe_anonymous_klass(k), "invariant");
uintptr_t anonymous_symbol_hash_code = 0;
const char* const anonymous_symbol =
- create_anonymous_klass_symbol((const InstanceKlass*)k, anonymous_symbol_hash_code);
+ create_unsafe_anonymous_klass_symbol((const InstanceKlass*)k, anonymous_symbol_hash_code);
if (anonymous_symbol == NULL) {
return 0;
@@ -119,8 +119,8 @@
traceid JfrSymbolId::mark(const Klass* k) {
assert(k != NULL, "invariant");
traceid symbol_id = 0;
- if (is_anonymous_klass(k)) {
- symbol_id = mark_anonymous_klass_name(k);
+ if (is_unsafe_anonymous_klass(k)) {
+ symbol_id = mark_unsafe_anonymous_klass_name(k);
}
if (0 == symbol_id) {
const Symbol* const sym = k->name();
@@ -148,9 +148,9 @@
return _cstring_table->id(str, hash);
}
-bool JfrSymbolId::is_anonymous_klass(const Klass* k) {
+bool JfrSymbolId::is_unsafe_anonymous_klass(const Klass* k) {
assert(k != NULL, "invariant");
- return k->is_instance_klass() && ((const InstanceKlass*)k)->is_anonymous();
+ return k->is_instance_klass() && ((const InstanceKlass*)k)->is_unsafe_anonymous();
}
/*
@@ -161,23 +161,23 @@
* caller needs ResourceMark
*/
-uintptr_t JfrSymbolId::anonymous_klass_name_hash_code(const InstanceKlass* ik) {
+uintptr_t JfrSymbolId::unsafe_anonymous_klass_name_hash_code(const InstanceKlass* ik) {
assert(ik != NULL, "invariant");
- assert(ik->is_anonymous(), "invariant");
+ assert(ik->is_unsafe_anonymous(), "invariant");
const oop mirror = ik->java_mirror();
assert(mirror != NULL, "invariant");
return (uintptr_t)mirror->identity_hash();
}
-const char* JfrSymbolId::create_anonymous_klass_symbol(const InstanceKlass* ik, uintptr_t& hashcode) {
+const char* JfrSymbolId::create_unsafe_anonymous_klass_symbol(const InstanceKlass* ik, uintptr_t& hashcode) {
assert(ik != NULL, "invariant");
- assert(ik->is_anonymous(), "invariant");
+ assert(ik->is_unsafe_anonymous(), "invariant");
assert(0 == hashcode, "invariant");
char* anonymous_symbol = NULL;
const oop mirror = ik->java_mirror();
assert(mirror != NULL, "invariant");
char hash_buf[40];
- hashcode = anonymous_klass_name_hash_code(ik);
+ hashcode = unsafe_anonymous_klass_name_hash_code(ik);
sprintf(hash_buf, "/" UINTX_FORMAT, hashcode);
const size_t hash_len = strlen(hash_buf);
const size_t result_len = ik->name()->utf8_length();
@@ -223,8 +223,8 @@
// _klass_list will be cleared by a ResourceMark
}
-traceid JfrArtifactSet::mark_anonymous_klass_name(const Klass* klass) {
- return _symbol_id->mark_anonymous_klass_name(klass);
+traceid JfrArtifactSet::mark_unsafe_anonymous_klass_name(const Klass* klass) {
+ return _symbol_id->mark_unsafe_anonymous_klass_name(klass);
}
traceid JfrArtifactSet::mark(const Symbol* sym, uintptr_t hash) {
--- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -236,9 +236,9 @@
bool equals(const char* query, uintptr_t hash, const CStringEntry* entry);
public:
- static bool is_anonymous_klass(const Klass* k);
- static const char* create_anonymous_klass_symbol(const InstanceKlass* ik, uintptr_t& hashcode);
- static uintptr_t anonymous_klass_name_hash_code(const InstanceKlass* ik);
+ static bool is_unsafe_anonymous_klass(const Klass* k);
+ static const char* create_unsafe_anonymous_klass_symbol(const InstanceKlass* ik, uintptr_t& hashcode);
+ static uintptr_t unsafe_anonymous_klass_name_hash_code(const InstanceKlass* ik);
static uintptr_t regular_klass_name_hash_code(const Klass* k);
JfrSymbolId();
@@ -247,7 +247,7 @@
void initialize();
void clear();
- traceid mark_anonymous_klass_name(const Klass* k);
+ traceid mark_unsafe_anonymous_klass_name(const Klass* k);
traceid mark(const Symbol* sym, uintptr_t hash);
traceid mark(const Klass* k);
traceid mark(const Symbol* symbol);
@@ -259,7 +259,7 @@
template <typename T>
void symbol(T& functor, const Klass* k) {
- if (is_anonymous_klass(k)) {
+ if (is_unsafe_anonymous_klass(k)) {
return;
}
functor(map_symbol(regular_klass_name_hash_code(k)));
@@ -274,10 +274,10 @@
template <typename T>
void cstring(T& functor, const Klass* k) {
- if (!is_anonymous_klass(k)) {
+ if (!is_unsafe_anonymous_klass(k)) {
return;
}
- functor(map_cstring(anonymous_klass_name_hash_code((const InstanceKlass*)k)));
+ functor(map_cstring(unsafe_anonymous_klass_name_hash_code((const InstanceKlass*)k)));
}
template <typename T>
@@ -327,7 +327,7 @@
traceid mark(const Klass* klass);
traceid mark(const Symbol* symbol);
traceid mark(const char* const str, uintptr_t hash);
- traceid mark_anonymous_klass_name(const Klass* klass);
+ traceid mark_unsafe_anonymous_klass_name(const Klass* klass);
const JfrSymbolId::SymbolEntry* map_symbol(const Symbol* symbol) const;
const JfrSymbolId::SymbolEntry* map_symbol(uintptr_t hash) const;
--- a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -120,7 +120,7 @@
void JfrTraceId::assign(const ClassLoaderData* cld) {
assert(cld != NULL, "invariant");
- if (cld->is_anonymous()) {
+ if (cld->is_unsafe_anonymous()) {
cld->set_trace_id(0);
return;
}
--- a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -96,7 +96,7 @@
inline traceid JfrTraceId::use(const ClassLoaderData* cld, bool leakp /* false */) {
assert(cld != NULL, "invariant");
- return cld->is_anonymous() ? 0 : set_used_and_get_shifted(cld, leakp);
+ return cld->is_unsafe_anonymous() ? 0 : set_used_and_get_shifted(cld, leakp);
}
inline bool JfrTraceId::in_visible_set(const Klass* klass) {
--- a/src/hotspot/share/jfr/writers/jfrJavaEventWriter.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/jfr/writers/jfrJavaEventWriter.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -34,7 +34,7 @@
#include "jfr/writers/jfrJavaEventWriter.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/oop.inline.hpp"
-#include "runtime/fieldDescriptor.hpp"
+#include "runtime/fieldDescriptor.inline.hpp"
#include "runtime/handles.hpp"
#include "runtime/jniHandles.inline.hpp"
#include "runtime/thread.inline.hpp"
--- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -37,6 +37,7 @@
#include "jvmci/jvmciCompilerToVM.hpp"
#include "jvmci/jvmciCodeInstaller.hpp"
#include "jvmci/jvmciRuntime.hpp"
+#include "runtime/fieldDescriptor.inline.hpp"
#include "runtime/flags/jvmFlag.hpp"
#include "runtime/frame.inline.hpp"
#include "runtime/interfaceSupport.inline.hpp"
@@ -382,7 +383,12 @@
err_msg("Expected interface type, got %s", klass->external_name()));
}
InstanceKlass* iklass = InstanceKlass::cast(klass);
- JVMCIKlassHandle handle(THREAD, iklass->implementor());
+ JVMCIKlassHandle handle(THREAD);
+ {
+ // Need Compile_lock around implementor()
+ MutexLocker locker(Compile_lock);
+ handle = iklass->implementor();
+ }
oop implementor = CompilerToVM::get_jvmci_type(handle, CHECK_NULL);
return JNIHandles::make_local(THREAD, implementor);
C2V_END
@@ -1431,7 +1437,7 @@
C2V_VMENTRY(jobject, getHostClass, (JNIEnv*, jobject, jobject jvmci_type))
InstanceKlass* k = InstanceKlass::cast(CompilerToVM::asKlass(jvmci_type));
- InstanceKlass* host = k->host_klass();
+ InstanceKlass* host = k->unsafe_anonymous_host();
JVMCIKlassHandle handle(THREAD, host);
oop result = CompilerToVM::get_jvmci_type(handle, CHECK_NULL);
return JNIHandles::make_local(THREAD, result);
--- a/src/hotspot/share/jvmci/jvmciEnv.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/jvmci/jvmciEnv.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -44,6 +44,7 @@
#include "oops/objArrayKlass.hpp"
#include "oops/oop.inline.hpp"
#include "prims/jvmtiExport.hpp"
+#include "runtime/fieldDescriptor.inline.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/init.hpp"
#include "runtime/reflection.hpp"
--- a/src/hotspot/share/jvmci/jvmciJavaClasses.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/jvmci/jvmciJavaClasses.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -27,6 +27,7 @@
#include "memory/resourceArea.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/jniHandles.inline.hpp"
+#include "runtime/fieldDescriptor.inline.hpp"
// This macro expands for non-inline functions, in class declarations.
--- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -527,7 +527,7 @@
\
declare_constant(InstanceKlass::linked) \
declare_constant(InstanceKlass::fully_initialized) \
- declare_constant(InstanceKlass::_misc_is_anonymous) \
+ declare_constant(InstanceKlass::_misc_is_unsafe_anonymous) \
\
declare_constant(JumpData::taken_off_set) \
declare_constant(JumpData::displacement_off_set) \
--- a/src/hotspot/share/logging/logPrefix.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/logging/logPrefix.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -80,6 +80,7 @@
LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, reloc)) \
LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, start)) \
LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, stringtable)) \
+ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, symboltable)) \
LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, sweep)) \
LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, task)) \
LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, task, start)) \
--- a/src/hotspot/share/logging/logTag.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/logging/logTag.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -147,6 +147,7 @@
LOG_TAG(stats) \
LOG_TAG(stringdedup) \
LOG_TAG(stringtable) \
+ LOG_TAG(symboltable) \
LOG_TAG(stackmap) \
LOG_TAG(subclass) \
LOG_TAG(survivor) \
--- a/src/hotspot/share/memory/arena.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/memory/arena.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -199,12 +199,18 @@
}
// Fast delete in area. Common case is: NOP (except for storage reclaimed)
- void Afree(void *ptr, size_t size) {
+ bool Afree(void *ptr, size_t size) {
#ifdef ASSERT
if (ZapResourceArea) memset(ptr, badResourceValue, size); // zap freed memory
- if (UseMallocOnly) return;
+ if (UseMallocOnly) return true;
#endif
- if (((char*)ptr) + size == _hwm) _hwm = (char*)ptr;
+ if (((char*)ptr) + size == _hwm) {
+ _hwm = (char*)ptr;
+ return true;
+ } else {
+ // Unable to fast free, so we just drop it.
+ return false;
+ }
}
void *Arealloc( void *old_ptr, size_t old_size, size_t new_size,
--- a/src/hotspot/share/memory/filemap.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/memory/filemap.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -35,22 +35,26 @@
#include "logging/logStream.hpp"
#include "logging/logMessage.hpp"
#include "memory/filemap.hpp"
+#include "memory/heapShared.inline.hpp"
+#include "memory/iterator.inline.hpp"
#include "memory/metadataFactory.hpp"
#include "memory/metaspaceClosure.hpp"
#include "memory/metaspaceShared.hpp"
#include "memory/oopFactory.hpp"
#include "oops/compressedOops.inline.hpp"
#include "oops/objArrayOop.hpp"
+#include "oops/oop.inline.hpp"
#include "prims/jvmtiExport.hpp"
#include "runtime/arguments.hpp"
#include "runtime/java.hpp"
-#include "runtime/os.hpp"
+#include "runtime/os.inline.hpp"
#include "runtime/vm_version.hpp"
#include "services/memTracker.hpp"
#include "utilities/align.hpp"
#include "utilities/defaultStream.hpp"
#if INCLUDE_G1GC
#include "gc/g1/g1CollectedHeap.hpp"
+#include "gc/g1/heapRegion.hpp"
#endif
# include <sys/stat.h>
@@ -159,8 +163,8 @@
memset((void*)this, 0, sizeof(FileMapInfo));
_file_offset = 0;
_file_open = false;
- _header = new FileMapHeader();
- _header->_version = _invalid_version;
+ _header = (FileMapHeader*)os::malloc(sizeof(FileMapHeader), mtInternal);
+ _header->_version = INVALID_CDS_ARCHIVE_VERSION;
_header->_has_platform_or_app_classes = true;
}
@@ -173,9 +177,9 @@
_header->populate(this, alignment);
}
-void FileMapInfo::FileMapHeader::populate(FileMapInfo* mapinfo, size_t alignment) {
- _magic = 0xf00baba2;
- _version = _current_version;
+void FileMapHeader::populate(FileMapInfo* mapinfo, size_t alignment) {
+ _magic = CDS_ARCHIVE_MAGIC;
+ _version = CURRENT_CDS_ARCHIVE_VERSION;
_alignment = alignment;
_obj_alignment = ObjectAlignmentInBytes;
_compact_strings = CompactStrings;
@@ -188,6 +192,9 @@
_shared_path_table_size = mapinfo->_shared_path_table_size;
_shared_path_table = mapinfo->_shared_path_table;
_shared_path_entry_size = mapinfo->_shared_path_entry_size;
+ if (MetaspaceShared::is_heap_object_archiving_allowed()) {
+ _heap_reserved = Universe::heap()->reserved_region();
+ }
// The following fields are for sanity checks for whether this archive
// will function correctly with this JVM and the bootclasspath it's
@@ -199,6 +206,7 @@
ClassLoaderExt::finalize_shared_paths_misc_info();
_app_class_paths_start_index = ClassLoaderExt::app_class_paths_start_index();
_app_module_paths_start_index = ClassLoaderExt::app_module_paths_start_index();
+ _max_used_path_index = ClassLoaderExt::max_used_path_index();
_verify_local = BytecodeVerificationLocal;
_verify_remote = BytecodeVerificationRemote;
@@ -359,13 +367,13 @@
bool has_nonempty_dir = false;
- int end = _shared_path_table_size;
- if (!ClassLoaderExt::has_platform_or_app_classes()) {
- // only check the boot path if no app class is loaded
- end = ClassLoaderExt::app_class_paths_start_index();
+ int last = _shared_path_table_size - 1;
+ if (last > ClassLoaderExt::max_used_path_index()) {
+ // no need to check any path beyond max_used_path_index
+ last = ClassLoaderExt::max_used_path_index();
}
- for (int i = 0; i < end; i++) {
+ for (int i = 0; i <= last; i++) {
SharedClassPathEntry *e = shared_path(i);
if (e->is_dir()) {
const char* path = e->name();
@@ -467,13 +475,8 @@
int module_paths_start_index = _header->_app_module_paths_start_index;
- // If the shared archive contain app or platform classes, validate all entries
- // in the shared path table. Otherwise, only validate the boot path entries (with
- // entry index < _app_class_paths_start_index).
- int count = _header->has_platform_or_app_classes() ?
- _shared_path_table_size : _header->_app_class_paths_start_index;
-
- for (int i=0; i<count; i++) {
+ // validate the path entries up to the _max_used_path_index
+ for (int i=0; i < _header->_max_used_path_index + 1; i++) {
if (i < module_paths_start_index) {
if (shared_path(i)->validate()) {
log_info(class, path)("ok");
@@ -497,14 +500,13 @@
// Read the FileMapInfo information from the file.
bool FileMapInfo::init_from_file(int fd) {
- size_t sz = _header->data_size();
- char* addr = _header->data();
- size_t n = os::read(fd, addr, (unsigned int)sz);
+ size_t sz = sizeof(FileMapHeader);
+ size_t n = os::read(fd, _header, (unsigned int)sz);
if (n != sz) {
fail_continue("Unable to read the file header.");
return false;
}
- if (_header->_version != current_version()) {
+ if (_header->_version != CURRENT_CDS_ARCHIVE_VERSION) {
fail_continue("The shared archive file has the wrong version.");
return false;
}
@@ -525,8 +527,7 @@
}
size_t len = lseek(fd, 0, SEEK_END);
- struct FileMapInfo::FileMapHeader::space_info* si =
- &_header->_space[MetaspaceShared::last_valid_region];
+ CDSFileMapRegion* si = space_at(MetaspaceShared::last_valid_region);
// The last space might be empty
if (si->_file_offset > len || len - si->_file_offset < si->_used) {
fail_continue("The shared archive file has been truncated.");
@@ -595,10 +596,8 @@
_header->_paths_misc_info_size = info_size;
align_file_position();
- size_t sz = _header->data_size();
- char* addr = _header->data();
- write_bytes(addr, (int)sz); // skip the C++ vtable
- write_bytes(ClassLoader::get_shared_paths_misc_info(), info_size);
+ write_bytes(_header, sizeof(FileMapHeader));
+ write_bytes(ClassLoader::get_shared_paths_misc_info(), (size_t)info_size);
align_file_position();
}
@@ -607,7 +606,7 @@
void FileMapInfo::write_region(int region, char* base, size_t size,
bool read_only, bool allow_exec) {
- struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[region];
+ CDSFileMapRegion* si = space_at(region);
if (_file_open) {
guarantee(si->_file_offset == _file_offset, "file offset mismatch.");
@@ -632,7 +631,7 @@
si->_allow_exec = allow_exec;
si->_crc = ClassLoader::crc32(0, base, (jint)size);
if (base != NULL) {
- write_bytes_aligned(base, (int)size);
+ write_bytes_aligned(base, size);
}
}
@@ -661,13 +660,14 @@
// "_" represented unused spaced in the heap region.
//
//
-// |ah0 | ah1 | ah2| ...... | ahn |
+// |ah0 | ah1 | ah2| ...... | ahn|
// |XXXXXX|__ |XXXXX|XXXX|XXXXXXXX|XXXX|
// |<-r0->| |<- r1 ----------------->|
// ^^^
// |
// +-- gap
size_t FileMapInfo::write_archive_heap_regions(GrowableArray<MemRegion> *heap_mem,
+ GrowableArray<ArchiveHeapOopmapInfo> *oopmaps,
int first_region_id, int max_num_regions) {
assert(max_num_regions <= 2, "Only support maximum 2 memory regions");
@@ -692,15 +692,19 @@
log_info(cds)("Archive heap region %d " INTPTR_FORMAT " - " INTPTR_FORMAT " = " SIZE_FORMAT_W(8) " bytes",
i, p2i(start), p2i(start + size), size);
write_region(i, start, size, false, false);
+ if (size > 0) {
+ space_at(i)->_oopmap = oopmaps->at(arr_idx)._oopmap;
+ space_at(i)->_oopmap_size_in_bits = oopmaps->at(arr_idx)._oopmap_size_in_bits;
+ }
}
return total_size;
}
// Dump bytes to file -- at the current file position.
-void FileMapInfo::write_bytes(const void* buffer, int nbytes) {
+void FileMapInfo::write_bytes(const void* buffer, size_t nbytes) {
if (_file_open) {
- int n = ::write(_fd, buffer, nbytes);
+ size_t n = os::write(_fd, buffer, (unsigned int)nbytes);
if (n != nbytes) {
// It is dangerous to leave the corrupted shared archive file around,
// close and remove the file. See bug 6372906.
@@ -736,7 +740,7 @@
// Dump bytes to file -- at the current file position.
-void FileMapInfo::write_bytes_aligned(const void* buffer, int nbytes) {
+void FileMapInfo::write_bytes_aligned(const void* buffer, size_t nbytes) {
align_file_position();
write_bytes(buffer, nbytes);
align_file_position();
@@ -760,7 +764,7 @@
// Remap the shared readonly space to shared readwrite, private.
bool FileMapInfo::remap_shared_readonly_as_readwrite() {
int idx = MetaspaceShared::ro;
- struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[idx];
+ CDSFileMapRegion* si = space_at(idx);
if (!si->_read_only) {
// the space is already readwrite so we are done
return true;
@@ -770,7 +774,7 @@
if (!open_for_read()) {
return false;
}
- char *addr = _header->region_addr(idx);
+ char *addr = region_addr(idx);
char *base = os::remap_memory(_fd, _full_path, si->_file_offset,
addr, size, false /* !read_only */,
si->_allow_exec);
@@ -789,7 +793,7 @@
// Map the whole region at once, assumed to be allocated contiguously.
ReservedSpace FileMapInfo::reserve_shared_memory() {
- char* requested_addr = _header->region_addr(0);
+ char* requested_addr = region_addr(0);
size_t size = FileMapInfo::core_spaces_size();
// Reserve the space first, then map otherwise map will go right over some
@@ -812,11 +816,11 @@
char* FileMapInfo::map_region(int i, char** top_ret) {
assert(!MetaspaceShared::is_heap_region(i), "sanity");
- struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[i];
+ CDSFileMapRegion* si = space_at(i);
size_t used = si->_used;
size_t alignment = os::vm_allocation_granularity();
size_t size = align_up(used, alignment);
- char *requested_addr = _header->region_addr(i);
+ char *requested_addr = region_addr(i);
// If a tool agent is in use (debugging enabled), we must map the address space RW
if (JvmtiExport::can_modify_any_class() || JvmtiExport::can_walk_any_space()) {
@@ -846,19 +850,57 @@
return base;
}
+address FileMapInfo::decode_start_address(CDSFileMapRegion* spc, bool with_current_oop_encoding_mode) {
+ if (with_current_oop_encoding_mode) {
+ return (address)CompressedOops::decode_not_null(offset_of_space(spc));
+ } else {
+ return (address)HeapShared::decode_with_archived_oop_encoding_mode(offset_of_space(spc));
+ }
+}
+
static MemRegion *string_ranges = NULL;
static MemRegion *open_archive_heap_ranges = NULL;
static int num_string_ranges = 0;
static int num_open_archive_heap_ranges = 0;
#if INCLUDE_CDS_JAVA_HEAP
+bool FileMapInfo::has_heap_regions() {
+ return (_header->_space[MetaspaceShared::first_string]._used > 0);
+}
+
+// Returns the address range of the archived heap regions computed using the
+// current oop encoding mode. This range may be different than the one seen at
+// dump time due to encoding mode differences. The result is used in determining
+// if/how these regions should be relocated at run time.
+MemRegion FileMapInfo::get_heap_regions_range_with_current_oop_encoding_mode() {
+ address start = (address) max_uintx;
+ address end = NULL;
+
+ for (int i = MetaspaceShared::first_string; i <= MetaspaceShared::last_valid_region; i++) {
+ CDSFileMapRegion* si = space_at(i);
+ size_t size = si->_used;
+ if (size > 0) {
+ address s = start_address_with_current_oop_encoding_mode(si);
+ address e = s + size;
+ if (start > s) {
+ start = s;
+ }
+ if (end < e) {
+ end = e;
+ }
+ }
+ }
+ assert(end != NULL, "must have at least one used heap region");
+ return MemRegion((HeapWord*)start, (HeapWord*)end);
+}
+
//
// Map the shared string objects and open archive heap objects to the runtime
// java heap.
//
-// The shared strings are mapped near the runtime java heap top. The
-// mapped strings contain no out-going references to any other java heap
-// regions. GC does not write into the mapped shared strings.
+// The shared strings are mapped close to the end of the java heap top in
+// closed archive regions. The mapped strings contain no out-going references
+// to any other java heap regions. GC does not write into the mapped shared strings.
//
// The open archive heap objects are mapped below the shared strings in
// the runtime java heap. The mapped open archive heap data only contain
@@ -866,54 +908,108 @@
// During runtime execution, out-going references to any other java heap
// regions may be added. GC may mark and update references in the mapped
// open archive objects.
-void FileMapInfo::map_heap_regions() {
- if (MetaspaceShared::is_heap_object_archiving_allowed()) {
- log_info(cds)("Archived narrow_oop_mode = %d, narrow_oop_base = " PTR_FORMAT ", narrow_oop_shift = %d",
- narrow_oop_mode(), p2i(narrow_oop_base()), narrow_oop_shift());
- log_info(cds)("Archived narrow_klass_base = " PTR_FORMAT ", narrow_klass_shift = %d",
- p2i(narrow_klass_base()), narrow_klass_shift());
+void FileMapInfo::map_heap_regions_impl() {
+ if (!MetaspaceShared::is_heap_object_archiving_allowed()) {
+ log_info(cds)("CDS heap data is being ignored. UseG1GC, "
+ "UseCompressedOops and UseCompressedClassPointers are required.");
+ return;
+ }
+
+ MemRegion heap_reserved = Universe::heap()->reserved_region();
+
+ log_info(cds)("CDS archive was created with max heap size = " SIZE_FORMAT "M, and the following configuration:",
+ max_heap_size()/M);
+ log_info(cds)(" narrow_klass_base = " PTR_FORMAT ", narrow_klass_shift = %d",
+ p2i(narrow_klass_base()), narrow_klass_shift());
+ log_info(cds)(" narrow_oop_mode = %d, narrow_oop_base = " PTR_FORMAT ", narrow_oop_shift = %d",
+ narrow_oop_mode(), p2i(narrow_oop_base()), narrow_oop_shift());
+
+ log_info(cds)("The current max heap size = " SIZE_FORMAT "M, HeapRegion::GrainBytes = " SIZE_FORMAT,
+ heap_reserved.byte_size()/M, HeapRegion::GrainBytes);
+ log_info(cds)(" narrow_klass_base = " PTR_FORMAT ", narrow_klass_shift = %d",
+ p2i(Universe::narrow_klass_base()), Universe::narrow_klass_shift());
+ log_info(cds)(" narrow_oop_mode = %d, narrow_oop_base = " PTR_FORMAT ", narrow_oop_shift = %d",
+ Universe::narrow_oop_mode(), p2i(Universe::narrow_oop_base()), Universe::narrow_oop_shift());
+
+ if (narrow_klass_base() != Universe::narrow_klass_base() ||
+ narrow_klass_shift() != Universe::narrow_klass_shift()) {
+ log_info(cds)("CDS heap data cannot be used because the archive was created with an incompatible narrow klass encoding mode.");
+ return;
+ }
+
+ if (narrow_oop_mode() != Universe::narrow_oop_mode() ||
+ narrow_oop_base() != Universe::narrow_oop_base() ||
+ narrow_oop_shift() != Universe::narrow_oop_shift()) {
+ log_info(cds)("CDS heap data need to be relocated because the archive was created with an incompatible oop encoding mode.");
+ _heap_pointers_need_patching = true;
+ } else {
+ MemRegion range = get_heap_regions_range_with_current_oop_encoding_mode();
+ if (!heap_reserved.contains(range)) {
+ log_info(cds)("CDS heap data need to be relocated because");
+ log_info(cds)("the desired range " PTR_FORMAT " - " PTR_FORMAT, p2i(range.start()), p2i(range.end()));
+ log_info(cds)("is outside of the heap " PTR_FORMAT " - " PTR_FORMAT, p2i(heap_reserved.start()), p2i(heap_reserved.end()));
+ _heap_pointers_need_patching = true;
+ }
+ }
- // Check that all the narrow oop and klass encodings match the archive
- if (narrow_oop_mode() != Universe::narrow_oop_mode() ||
- narrow_oop_base() != Universe::narrow_oop_base() ||
- narrow_oop_shift() != Universe::narrow_oop_shift() ||
- narrow_klass_base() != Universe::narrow_klass_base() ||
- narrow_klass_shift() != Universe::narrow_klass_shift()) {
- if (log_is_enabled(Info, cds) && _header->_space[MetaspaceShared::first_string]._used > 0) {
- log_info(cds)("Cached heap data from the CDS archive is being ignored. "
- "The current CompressedOops/CompressedClassPointers encoding differs from "
- "that archived due to heap size change. The archive was dumped using max heap "
- "size " UINTX_FORMAT "M.", max_heap_size()/M);
- log_info(cds)("Current narrow_oop_mode = %d, narrow_oop_base = " PTR_FORMAT ", narrow_oop_shift = %d",
- Universe::narrow_oop_mode(), p2i(Universe::narrow_oop_base()),
- Universe::narrow_oop_shift());
- log_info(cds)("Current narrow_klass_base = " PTR_FORMAT ", narrow_klass_shift = %d",
- p2i(Universe::narrow_klass_base()), Universe::narrow_klass_shift());
- }
- } else {
- // First, map string regions as closed archive heap regions.
- // GC does not write into the regions.
- if (map_heap_data(&string_ranges,
- MetaspaceShared::first_string,
- MetaspaceShared::max_strings,
- &num_string_ranges)) {
- StringTable::set_shared_string_mapped();
+ ptrdiff_t delta = 0;
+ if (_heap_pointers_need_patching) {
+ // dumptime heap end ------------v
+ // [ |archived heap regions| ] runtime heap end ------v
+ // [ |archived heap regions| ]
+ // |<-----delta-------------------->|
+ //
+ // At dump time, the archived heap regions were near the top of the heap.
+ // At run time, they may not be inside the heap, so we move them so
+ // that they are now near the top of the runtime time. This can be done by
+ // the simple math of adding the delta as shown above.
+ address dumptime_heap_end = (address)_header->_heap_reserved.end();
+ address runtime_heap_end = (address)heap_reserved.end();
+ delta = runtime_heap_end - dumptime_heap_end;
+ }
+
+ log_info(cds)("CDS heap data relocation delta = " INTX_FORMAT " bytes", delta);
+ HeapShared::init_narrow_oop_decoding(narrow_oop_base() + delta, narrow_oop_shift());
+
+ CDSFileMapRegion* si = space_at(MetaspaceShared::first_string);
+ address relocated_strings_bottom = start_address_with_archived_oop_encoding_mode(si);
+ if (!is_aligned(relocated_strings_bottom + delta, HeapRegion::GrainBytes)) {
+ // Align the bottom of the string regions at G1 region boundary. This will avoid
+ // the situation where the highest open region and the lowest string region sharing
+ // the same G1 region. Otherwise we will fail to map the open regions.
+ size_t align = size_t(relocated_strings_bottom) % HeapRegion::GrainBytes;
+ delta -= align;
+ assert(is_aligned(relocated_strings_bottom + delta, HeapRegion::GrainBytes), "must be");
- // Now, map open_archive heap regions, GC can write into the regions.
- if (map_heap_data(&open_archive_heap_ranges,
- MetaspaceShared::first_open_archive_heap_region,
- MetaspaceShared::max_open_archive_heap_region,
- &num_open_archive_heap_ranges,
- true /* open */)) {
- MetaspaceShared::set_open_archive_heap_region_mapped();
- }
- }
+ log_info(cds)("CDS heap data need to be relocated lower by a further " SIZE_FORMAT
+ " bytes to be aligned with HeapRegion::GrainBytes", align);
+
+ HeapShared::init_narrow_oop_decoding(narrow_oop_base() + delta, narrow_oop_shift());
+ _heap_pointers_need_patching = true;
+ }
+
+ // First, map string regions as closed archive heap regions.
+ // GC does not write into the regions.
+ if (map_heap_data(&string_ranges,
+ MetaspaceShared::first_string,
+ MetaspaceShared::max_strings,
+ &num_string_ranges)) {
+ StringTable::set_shared_string_mapped();
+
+ // Now, map open_archive heap regions, GC can write into the regions.
+ if (map_heap_data(&open_archive_heap_ranges,
+ MetaspaceShared::first_open_archive_heap_region,
+ MetaspaceShared::max_open_archive_heap_region,
+ &num_open_archive_heap_ranges,
+ true /* open */)) {
+ MetaspaceShared::set_open_archive_heap_region_mapped();
}
- } else {
- if (log_is_enabled(Info, cds) && _header->_space[MetaspaceShared::first_string]._used > 0) {
- log_info(cds)("Cached heap data from the CDS archive is being ignored. UseG1GC, "
- "UseCompressedOops and UseCompressedClassPointers are required.");
- }
+ }
+}
+
+void FileMapInfo::map_heap_regions() {
+ if (has_heap_regions()) {
+ map_heap_regions_impl();
}
if (!StringTable::shared_string_mapped()) {
@@ -928,19 +1024,19 @@
bool FileMapInfo::map_heap_data(MemRegion **heap_mem, int first,
int max, int* num, bool is_open_archive) {
MemRegion * regions = new MemRegion[max];
- struct FileMapInfo::FileMapHeader::space_info* si;
+ CDSFileMapRegion* si;
int region_num = 0;
for (int i = first;
i < first + max; i++) {
- si = &_header->_space[i];
- size_t used = si->_used;
- if (used > 0) {
- size_t size = used;
- char* requested_addr = (char*)((void*)CompressedOops::decode_not_null(
- (narrowOop)si->_addr._offset));
- regions[region_num] = MemRegion((HeapWord*)requested_addr, size / HeapWordSize);
+ si = space_at(i);
+ size_t size = si->_used;
+ if (size > 0) {
+ HeapWord* start = (HeapWord*)start_address_with_archived_oop_encoding_mode(si);
+ regions[region_num] = MemRegion(start, size / HeapWordSize);
region_num ++;
+ log_info(cds)("Trying to map heap data: region[%d] at " INTPTR_FORMAT ", size = " SIZE_FORMAT_W(8) " bytes",
+ i, p2i(start), size);
}
}
@@ -950,16 +1046,14 @@
// Check that ranges are within the java heap
if (!G1CollectedHeap::heap()->check_archive_addresses(regions, region_num)) {
- log_info(cds)("UseSharedSpaces: Unable to allocate region, "
- "range is not within java heap.");
+ log_info(cds)("UseSharedSpaces: Unable to allocate region, range is not within java heap.");
return false;
}
// allocate from java heap
if (!G1CollectedHeap::heap()->alloc_archive_regions(
regions, region_num, is_open_archive)) {
- log_info(cds)("UseSharedSpaces: Unable to allocate region, "
- "java heap range is already in use.");
+ log_info(cds)("UseSharedSpaces: Unable to allocate region, java heap range is already in use.");
return false;
}
@@ -967,7 +1061,7 @@
// for mapped regions as they are part of the reserved java heap, which is
// already recorded.
for (int i = 0; i < region_num; i++) {
- si = &_header->_space[first + i];
+ si = space_at(first + i);
char* addr = (char*)regions[i].start();
char* base = os::map_memory(_fd, _full_path, si->_file_offset,
addr, regions[i].byte_size(), si->_read_only,
@@ -975,7 +1069,9 @@
if (base == NULL || base != addr) {
// dealloc the regions from java heap
dealloc_archive_heap_regions(regions, region_num);
- log_info(cds)("UseSharedSpaces: Unable to map at required address in java heap.");
+ log_info(cds)("UseSharedSpaces: Unable to map at required address in java heap. "
+ INTPTR_FORMAT ", size = " SIZE_FORMAT " bytes",
+ p2i(addr), regions[i].byte_size());
return false;
}
}
@@ -1003,6 +1099,31 @@
return true;
}
+void FileMapInfo::patch_archived_heap_embedded_pointers() {
+ if (!_heap_pointers_need_patching) {
+ return;
+ }
+
+ patch_archived_heap_embedded_pointers(string_ranges,
+ num_string_ranges,
+ MetaspaceShared::first_string);
+
+ patch_archived_heap_embedded_pointers(open_archive_heap_ranges,
+ num_open_archive_heap_ranges,
+ MetaspaceShared::first_open_archive_heap_region);
+}
+
+void FileMapInfo::patch_archived_heap_embedded_pointers(MemRegion* ranges, int num_ranges,
+ int first_region_idx) {
+ for (int i=0; i<num_ranges; i++) {
+ CDSFileMapRegion* si = space_at(i + first_region_idx);
+ HeapShared::patch_archived_heap_embedded_pointers(ranges[i], (address)si->_oopmap,
+ si->_oopmap_size_in_bits);
+ }
+}
+
+// This internally allocates objects using SystemDictionary::Object_klass(), so it
+// must be called after the well-known classes are resolved.
void FileMapInfo::fixup_mapped_heap_regions() {
// If any string regions were found, call the fill routine to make them parseable.
// Note that string_ranges may be non-NULL even if no ranges were found.
@@ -1033,7 +1154,7 @@
return true;
}
- size_t sz = _header->_space[i]._used;
+ size_t sz = space_at(i)->_used;
if (sz == 0) {
return true; // no data
@@ -1044,9 +1165,9 @@
!MetaspaceShared::open_archive_heap_region_mapped())) {
return true; // archived heap data is not mapped
}
- const char* buf = _header->region_addr(i);
+ const char* buf = region_addr(i);
int crc = ClassLoader::crc32(0, buf, (jint)sz);
- if (crc != _header->_space[i]._crc) {
+ if (crc != space_at(i)->_crc) {
fail_continue("Checksum verification failed.");
return false;
}
@@ -1057,7 +1178,7 @@
void FileMapInfo::unmap_region(int i) {
assert(!MetaspaceShared::is_heap_region(i), "sanity");
- struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[i];
+ CDSFileMapRegion* si = space_at(i);
size_t used = si->_used;
size_t size = align_up(used, os::vm_allocation_granularity());
@@ -1065,7 +1186,7 @@
return;
}
- char* addr = _header->region_addr(i);
+ char* addr = region_addr(i);
if (!os::unmap_memory(addr, size)) {
fail_stop("Unable to unmap shared space.");
}
@@ -1086,6 +1207,7 @@
FileMapInfo* FileMapInfo::_current_info = NULL;
+bool FileMapInfo::_heap_pointers_need_patching = false;
Array<u8>* FileMapInfo::_shared_path_table = NULL;
int FileMapInfo::_shared_path_table_size = 0;
size_t FileMapInfo::_shared_path_entry_size = 0x1234baad;
@@ -1115,28 +1237,30 @@
return true;
}
-char* FileMapInfo::FileMapHeader::region_addr(int idx) {
+char* FileMapInfo::region_addr(int idx) {
+ CDSFileMapRegion* si = space_at(idx);
if (MetaspaceShared::is_heap_region(idx)) {
- return _space[idx]._used > 0 ?
- (char*)((void*)CompressedOops::decode_not_null((narrowOop)_space[idx]._addr._offset)) : NULL;
+ assert(DumpSharedSpaces, "The following doesn't work at runtime");
+ return si->_used > 0 ?
+ (char*)start_address_with_current_oop_encoding_mode(si) : NULL;
} else {
- return _space[idx]._addr._base;
+ return si->_addr._base;
}
}
-int FileMapInfo::FileMapHeader::compute_crc() {
- char* header = data();
+int FileMapHeader::compute_crc() {
+ char* start = (char*)this;
// start computing from the field after _crc
- char* buf = (char*)&_crc + sizeof(int);
- size_t sz = data_size() - (buf - header);
+ char* buf = (char*)&_crc + sizeof(_crc);
+ size_t sz = sizeof(FileMapHeader) - (buf - start);
int crc = ClassLoader::crc32(0, buf, (jint)sz);
return crc;
}
// This function should only be called during run time with UseSharedSpaces enabled.
-bool FileMapInfo::FileMapHeader::validate() {
+bool FileMapHeader::validate() {
if (VerifySharedSpaces && compute_crc() != _crc) {
- fail_continue("Header checksum verification failed.");
+ FileMapInfo::fail_continue("Header checksum verification failed.");
return false;
}
@@ -1145,11 +1269,11 @@
return false;
}
- if (_version != current_version()) {
+ if (_version != CURRENT_CDS_ARCHIVE_VERSION) {
FileMapInfo::fail_continue("The shared archive file is the wrong version.");
return false;
}
- if (_magic != (int)0xf00baba2) {
+ if (_magic != CDS_ARCHIVE_MAGIC) {
FileMapInfo::fail_continue("The shared archive file has a bad magic number.");
return false;
}
@@ -1224,34 +1348,25 @@
idx == MetaspaceShared::rw ||
idx == MetaspaceShared::mc ||
idx == MetaspaceShared::md, "invalid region index");
- char* base = _header->region_addr(idx);
- if (p >= base && p < base + _header->_space[idx]._used) {
+ char* base = region_addr(idx);
+ if (p >= base && p < base + space_at(idx)->_used) {
return true;
}
return false;
}
-void FileMapInfo::print_shared_spaces() {
- tty->print_cr("Shared Spaces:");
- for (int i = 0; i < MetaspaceShared::n_regions; i++) {
- struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[i];
- char *base = _header->region_addr(i);
- tty->print(" %s " INTPTR_FORMAT "-" INTPTR_FORMAT,
- shared_region_name[i],
- p2i(base), p2i(base + si->_used));
- }
-}
-
// Unmap mapped regions of shared space.
void FileMapInfo::stop_sharing_and_unmap(const char* msg) {
FileMapInfo *map_info = FileMapInfo::current_info();
if (map_info) {
map_info->fail_continue("%s", msg);
for (int i = 0; i < MetaspaceShared::num_non_heap_spaces; i++) {
- char *addr = map_info->_header->region_addr(i);
- if (addr != NULL && !MetaspaceShared::is_heap_region(i)) {
- map_info->unmap_region(i);
- map_info->_header->_space[i]._addr._base = NULL;
+ if (!MetaspaceShared::is_heap_region(i)) {
+ char *addr = map_info->region_addr(i);
+ if (addr != NULL) {
+ map_info->unmap_region(i);
+ map_info->space_at(i)->_addr._base = NULL;
+ }
}
}
// Dealloc the archive heap regions only without unmapping. The regions are part
--- a/src/hotspot/share/memory/filemap.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/memory/filemap.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -26,6 +26,7 @@
#define SHARE_VM_MEMORY_FILEMAP_HPP
#include "classfile/classLoader.hpp"
+#include "include/cds.h"
#include "memory/metaspaceShared.hpp"
#include "memory/metaspace.hpp"
#include "memory/universe.hpp"
@@ -87,17 +88,94 @@
}
};
+struct ArchiveHeapOopmapInfo {
+ address _oopmap; // bitmap for relocating embedded oops
+ size_t _oopmap_size_in_bits;
+};
+
+struct FileMapHeader : public CDSFileMapHeaderBase {
+ size_t _alignment; // how shared archive should be aligned
+ int _obj_alignment; // value of ObjectAlignmentInBytes
+ address _narrow_oop_base; // compressed oop encoding base
+ int _narrow_oop_shift; // compressed oop encoding shift
+ bool _compact_strings; // value of CompactStrings
+ uintx _max_heap_size; // java max heap size during dumping
+ Universe::NARROW_OOP_MODE _narrow_oop_mode; // compressed oop encoding mode
+ int _narrow_klass_shift; // save narrow klass base and shift
+ address _narrow_klass_base;
+ char* _misc_data_patching_start;
+ char* _read_only_tables_start;
+ address _cds_i2i_entry_code_buffers;
+ size_t _cds_i2i_entry_code_buffers_size;
+ size_t _core_spaces_size; // number of bytes allocated by the core spaces
+ // (mc, md, ro, rw and od).
+ MemRegion _heap_reserved; // reserved region for the entire heap at dump time.
+
+ // The following fields are all sanity checks for whether this archive
+ // will function correctly with this JVM and the bootclasspath it's
+ // invoked with.
+ char _jvm_ident[JVM_IDENT_MAX]; // identifier for jvm
+
+ // The _paths_misc_info is a variable-size structure that records "miscellaneous"
+ // information during dumping. It is generated and validated by the
+ // SharedPathsMiscInfo class. See SharedPathsMiscInfo.hpp for
+ // detailed description.
+ //
+ // The _paths_misc_info data is stored as a byte array in the archive file header,
+ // immediately after the _header field. This information is used only when
+ // checking the validity of the archive and is deallocated after the archive is loaded.
+ //
+ // Note that the _paths_misc_info does NOT include information for JAR files
+ // that existed during dump time. Their information is stored in _shared_path_table.
+ int _paths_misc_info_size;
+
+ // The following is a table of all the class path entries that were used
+ // during dumping. At run time, we require these files to exist and have the same
+ // size/modification time, or else the archive will refuse to load.
+ //
+ // All of these entries must be JAR files. The dumping process would fail if a non-empty
+ // directory was specified in the classpaths. If an empty directory was specified
+ // it is checked by the _paths_misc_info as described above.
+ //
+ // FIXME -- if JAR files in the tail of the list were specified but not used during dumping,
+ // they should be removed from this table, to save space and to avoid spurious
+ // loading failures during runtime.
+ int _shared_path_table_size;
+ size_t _shared_path_entry_size;
+ Array<u8>* _shared_path_table;
+
+ jshort _app_class_paths_start_index; // Index of first app classpath entry
+ jshort _app_module_paths_start_index; // Index of first module path entry
+ jshort _max_used_path_index; // max path index referenced during CDS dump
+ bool _verify_local; // BytecodeVerificationLocal setting
+ bool _verify_remote; // BytecodeVerificationRemote setting
+ bool _has_platform_or_app_classes; // Archive contains app classes
+
+ void set_has_platform_or_app_classes(bool v) {
+ _has_platform_or_app_classes = v;
+ }
+ bool has_platform_or_app_classes() { return _has_platform_or_app_classes; }
+ jshort max_used_path_index() { return _max_used_path_index; }
+ jshort app_module_paths_start_index() { return _app_module_paths_start_index; }
+
+ bool validate();
+ void populate(FileMapInfo* info, size_t alignment);
+ int compute_crc();
+
+ CDSFileMapRegion* space_at(int i) {
+ assert(i >= 0 && i < NUM_CDS_REGIONS, "invalid region");
+ return &_space[i];
+ }
+};
+
class FileMapInfo : public CHeapObj<mtInternal> {
private:
friend class ManifestStream;
friend class VMStructs;
- enum {
- _invalid_version = -1,
- _current_version = 3
- };
+ friend struct FileMapHeader;
- bool _file_open;
- int _fd;
+ bool _file_open;
+ int _fd;
size_t _file_offset;
private:
@@ -116,97 +194,7 @@
// methods, we would get sizeof(FileMapHeaderBase) == 1 with gcc.
intx _dummy;
};
- struct FileMapHeader : FileMapHeaderBase {
- // Use data() and data_size() to memcopy to/from the FileMapHeader. We need to
- // avoid read/writing the C++ vtable pointer.
- static size_t data_size() {
- return sizeof(FileMapHeader) - sizeof(FileMapInfo::FileMapHeaderBase);
- }
- char* data() {
- return ((char*)this) + sizeof(FileMapHeaderBase);
- }
- int _magic; // identify file type.
- int _crc; // header crc checksum.
- int _version; // (from enum, above.)
- size_t _alignment; // how shared archive should be aligned
- int _obj_alignment; // value of ObjectAlignmentInBytes
- address _narrow_oop_base; // compressed oop encoding base
- int _narrow_oop_shift; // compressed oop encoding shift
- bool _compact_strings; // value of CompactStrings
- uintx _max_heap_size; // java max heap size during dumping
- Universe::NARROW_OOP_MODE _narrow_oop_mode; // compressed oop encoding mode
- int _narrow_klass_shift; // save narrow klass base and shift
- address _narrow_klass_base;
- char* _misc_data_patching_start;
- char* _read_only_tables_start;
- address _cds_i2i_entry_code_buffers;
- size_t _cds_i2i_entry_code_buffers_size;
- size_t _core_spaces_size; // number of bytes allocated by the core spaces
- // (mc, md, ro, rw and od).
- struct space_info {
- int _crc; // crc checksum of the current space
- size_t _file_offset; // sizeof(this) rounded to vm page size
- union {
- char* _base; // copy-on-write base address
- intx _offset; // offset from the compressed oop encoding base, only used
- // by archive heap space
- } _addr;
- size_t _used; // for setting space top on read
- bool _read_only; // read only space?
- bool _allow_exec; // executable code in space?
- } _space[MetaspaceShared::n_regions];
-
- // The following fields are all sanity checks for whether this archive
- // will function correctly with this JVM and the bootclasspath it's
- // invoked with.
- char _jvm_ident[JVM_IDENT_MAX]; // identifier for jvm
-
- // The _paths_misc_info is a variable-size structure that records "miscellaneous"
- // information during dumping. It is generated and validated by the
- // SharedPathsMiscInfo class. See SharedPathsMiscInfo.hpp for
- // detailed description.
- //
- // The _paths_misc_info data is stored as a byte array in the archive file header,
- // immediately after the _header field. This information is used only when
- // checking the validity of the archive and is deallocated after the archive is loaded.
- //
- // Note that the _paths_misc_info does NOT include information for JAR files
- // that existed during dump time. Their information is stored in _shared_path_table.
- int _paths_misc_info_size;
-
- // The following is a table of all the class path entries that were used
- // during dumping. At run time, we require these files to exist and have the same
- // size/modification time, or else the archive will refuse to load.
- //
- // All of these entries must be JAR files. The dumping process would fail if a non-empty
- // directory was specified in the classpaths. If an empty directory was specified
- // it is checked by the _paths_misc_info as described above.
- //
- // FIXME -- if JAR files in the tail of the list were specified but not used during dumping,
- // they should be removed from this table, to save space and to avoid spurious
- // loading failures during runtime.
- int _shared_path_table_size;
- size_t _shared_path_entry_size;
- Array<u8>* _shared_path_table;
-
- jshort _app_class_paths_start_index; // Index of first app classpath entry
- jshort _app_module_paths_start_index; // Index of first module path entry
- bool _verify_local; // BytecodeVerificationLocal setting
- bool _verify_remote; // BytecodeVerificationRemote setting
- bool _has_platform_or_app_classes; // Archive contains app classes
-
- void set_has_platform_or_app_classes(bool v) {
- _has_platform_or_app_classes = v;
- }
- bool has_platform_or_app_classes() { return _has_platform_or_app_classes; }
-
- char* region_addr(int idx);
-
- bool validate();
- void populate(FileMapInfo* info, size_t alignment);
- int compute_crc();
- };
FileMapHeader * _header;
@@ -214,6 +202,7 @@
char* _paths_misc_info;
static FileMapInfo* _current_info;
+ static bool _heap_pointers_need_patching;
bool init_from_file(int fd);
void align_file_position();
@@ -224,7 +213,6 @@
FileMapInfo();
~FileMapInfo();
- static int current_version() { return _current_version; }
int compute_header_crc() { return _header->compute_crc(); }
void set_header_crc(int crc) { _header->_crc = crc; }
void populate_header(size_t alignment);
@@ -274,12 +262,19 @@
void write_region(int region, char* base, size_t size,
bool read_only, bool allow_exec);
size_t write_archive_heap_regions(GrowableArray<MemRegion> *heap_mem,
+ GrowableArray<ArchiveHeapOopmapInfo> *oopmaps,
int first_region_id, int max_num_regions);
- void write_bytes(const void* buffer, int count);
- void write_bytes_aligned(const void* buffer, int count);
+ void write_bytes(const void* buffer, size_t count);
+ void write_bytes_aligned(const void* buffer, size_t count);
char* map_region(int i, char** top_ret);
+ void map_heap_regions_impl() NOT_CDS_JAVA_HEAP_RETURN;
void map_heap_regions() NOT_CDS_JAVA_HEAP_RETURN;
void fixup_mapped_heap_regions() NOT_CDS_JAVA_HEAP_RETURN;
+ void patch_archived_heap_embedded_pointers() NOT_CDS_JAVA_HEAP_RETURN;
+ void patch_archived_heap_embedded_pointers(MemRegion* ranges, int num_ranges,
+ int first_region_idx) NOT_CDS_JAVA_HEAP_RETURN;
+ bool has_heap_regions() NOT_CDS_JAVA_HEAP_RETURN_(false);
+ MemRegion get_heap_regions_range_with_current_oop_encoding_mode() NOT_CDS_JAVA_HEAP_RETURN_(MemRegion());
void unmap_region(int i);
bool verify_region_checksum(int i);
void close();
@@ -295,7 +290,6 @@
static void fail_continue(const char *msg, ...) ATTRIBUTE_PRINTF(1, 2);
bool is_in_shared_region(const void* p, int idx) NOT_CDS_RETURN_(false);
- void print_shared_spaces() NOT_CDS_RETURN;
// Stop CDS sharing and unmap CDS regions.
static void stop_sharing_and_unmap(const char* msg);
@@ -324,11 +318,33 @@
return _shared_path_table_size;
}
+ char* region_addr(int idx);
+
private:
bool map_heap_data(MemRegion **heap_mem, int first, int max, int* num,
bool is_open = false) NOT_CDS_JAVA_HEAP_RETURN_(false);
bool verify_mapped_heap_regions(int first, int num) NOT_CDS_JAVA_HEAP_RETURN_(false);
void dealloc_archive_heap_regions(MemRegion* regions, int num) NOT_CDS_JAVA_HEAP_RETURN;
+
+ CDSFileMapRegion* space_at(int i) {
+ return _header->space_at(i);
+ }
+
+ narrowOop offset_of_space(CDSFileMapRegion* spc) {
+ return (narrowOop)(spc->_addr._offset);
+ }
+
+ // The starting address of spc, as calculated with CompressedOop::decode_non_null()
+ address start_address_with_current_oop_encoding_mode(CDSFileMapRegion* spc) {
+ return decode_start_address(spc, true);
+ }
+
+ // The starting address of spc, as calculated with HeapShared::decode_with_archived_oop_encoding_mode()
+ address start_address_with_archived_oop_encoding_mode(CDSFileMapRegion* spc) {
+ return decode_start_address(spc, false);
+ }
+
+ address decode_start_address(CDSFileMapRegion* spc, bool with_current_oop_encoding_mode);
};
#endif // SHARE_VM_MEMORY_FILEMAP_HPP
--- a/src/hotspot/share/memory/heapShared.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/memory/heapShared.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -24,11 +24,12 @@
#include "precompiled.hpp"
#include "classfile/javaClasses.inline.hpp"
+#include "classfile/symbolTable.hpp"
#include "classfile/vmSymbols.hpp"
#include "logging/log.hpp"
#include "logging/logMessage.hpp"
#include "logging/logStream.hpp"
-#include "memory/heapShared.hpp"
+#include "memory/heapShared.inline.hpp"
#include "memory/iterator.inline.hpp"
#include "memory/metadataFactory.hpp"
#include "memory/metaspaceClosure.hpp"
@@ -36,6 +37,8 @@
#include "memory/resourceArea.hpp"
#include "oops/compressedOops.inline.hpp"
#include "oops/oop.inline.hpp"
+#include "runtime/fieldDescriptor.inline.hpp"
+#include "utilities/bitMap.inline.hpp"
#if INCLUDE_CDS_JAVA_HEAP
KlassSubGraphInfo* HeapShared::_subgraph_info_list = NULL;
@@ -70,6 +73,9 @@
return info;
}
+address HeapShared::_narrow_oop_base;
+int HeapShared::_narrow_oop_shift;
+
int HeapShared::num_of_subgraph_infos() {
int num = 0;
KlassSubGraphInfo* info = _subgraph_info_list;
@@ -318,7 +324,7 @@
// point. All objects in the subgraph reachable from the object are
// also 'known' by GC.
oop v = MetaspaceShared::materialize_archived_object(
- CompressedOops::decode(entry_field_records->at(i+1)));
+ entry_field_records->at(i+1));
m->obj_field_put(field_offset, v);
i += 2;
}
@@ -352,7 +358,7 @@
// A java.lang.Class instance can not be included in an archived
// object sub-graph.
if (java_lang_Class::is_instance(obj)) {
- tty->print("Unknown java.lang.Class object is in the archived sub-graph\n");
+ log_error(cds, heap)("Unknown java.lang.Class object is in the archived sub-graph\n");
vm_exit(1);
}
@@ -392,6 +398,17 @@
Thread* THREAD = Thread::current();
// Archive the current oop before iterating through its references
archived = MetaspaceShared::archive_heap_object(obj, THREAD);
+ if (archived == NULL) {
+ ResourceMark rm;
+ LogTarget(Error, cds, heap) log_err;
+ LogStream ls_err(log_err);
+ outputStream* out_err = &ls_err;
+ log_err.print("Failed to archive %s object ("
+ PTR_FORMAT "), size[" SIZE_FORMAT "] in sub-graph",
+ obj->klass()->external_name(), p2i(obj), (size_t)obj->size());
+ obj->print_on(out_err);
+ vm_exit(1);
+ }
assert(MetaspaceShared::is_archive_object(archived), "must be archived");
log.print("=== archiving oop " PTR_FORMAT " ==> " PTR_FORMAT,
p2i(obj), p2i(archived));
@@ -465,7 +482,7 @@
return;
}
- if (field_type == T_OBJECT) {
+ if (field_type == T_OBJECT || field_type == T_ARRAY) {
// obtain k's subGraph Info
KlassSubGraphInfo* subgraph_info = get_subgraph_info(k);
@@ -480,6 +497,15 @@
// get the archived copy of the field referenced object
oop af = MetaspaceShared::archive_heap_object(f, THREAD);
+ if (af == NULL) {
+ // Skip archiving the sub-graph referenced from the current entry field.
+ ResourceMark rm;
+ log_info(cds, heap)(
+ "Cannot archive the sub-graph referenced from %s object ("
+ PTR_FORMAT ") size[" SIZE_FORMAT "], skipped.",
+ f->klass()->external_name(), p2i(f), (size_t)f->size());
+ return;
+ }
if (!MetaspaceShared::is_archive_object(f)) {
WalkOopAndArchiveClosure walker(1, subgraph_info, f, af);
f->oop_iterate(&walker);
@@ -492,6 +518,10 @@
Klass *relocated_k = af->klass();
Klass *orig_k = f->klass();
subgraph_info->add_subgraph_object_klass(orig_k, relocated_k);
+ ResourceMark rm;
+ log_info(cds, heap)(
+ "Archived the sub-graph referenced from %s object " PTR_FORMAT,
+ f->klass()->external_name(), p2i(f));
} else {
// The field contains null, we still need to record the entry point,
// so it can be restored at runtime.
@@ -502,17 +532,169 @@
}
}
-#define do_module_object_graph(archive_object_graph_do) \
- archive_object_graph_do(SystemDictionary::ArchivedModuleGraph_klass(), jdk_internal_module_ArchivedModuleGraph::archivedSystemModules_offset(), T_OBJECT, CHECK); \
- archive_object_graph_do(SystemDictionary::ArchivedModuleGraph_klass(), jdk_internal_module_ArchivedModuleGraph::archivedModuleFinder_offset(), T_OBJECT, CHECK); \
- archive_object_graph_do(SystemDictionary::ArchivedModuleGraph_klass(), jdk_internal_module_ArchivedModuleGraph::archivedMainModule_offset(), T_OBJECT, CHECK); \
- archive_object_graph_do(SystemDictionary::ArchivedModuleGraph_klass(), jdk_internal_module_ArchivedModuleGraph::archivedConfiguration_offset(), T_OBJECT, CHECK); \
- archive_object_graph_do(SystemDictionary::ImmutableCollections_ListN_klass(), java_util_ImmutableCollections_ListN::EMPTY_LIST_offset(), T_OBJECT, CHECK); \
- archive_object_graph_do(SystemDictionary::ImmutableCollections_MapN_klass(), java_util_ImmutableCollections_MapN::EMPTY_MAP_offset(), T_OBJECT, CHECK); \
- archive_object_graph_do(SystemDictionary::ImmutableCollections_SetN_klass(), java_util_ImmutableCollections_SetN::EMPTY_SET_offset(), T_OBJECT, CHECK); \
- archive_object_graph_do(SystemDictionary::Configuration_klass(), java_lang_module_Configuration::EMPTY_CONFIGURATION_offset(), T_OBJECT, CHECK)
+struct ArchivableStaticFieldInfo {
+ const char* class_name;
+ const char* field_name;
+ InstanceKlass* klass;
+ int offset;
+ BasicType type;
+};
+
+// If you add new entries to this table, you should know what you're doing!
+static ArchivableStaticFieldInfo archivable_static_fields[] = {
+ {"jdk/internal/module/ArchivedModuleGraph", "archivedSystemModules"},
+ {"jdk/internal/module/ArchivedModuleGraph", "archivedModuleFinder"},
+ {"jdk/internal/module/ArchivedModuleGraph", "archivedMainModule"},
+ {"jdk/internal/module/ArchivedModuleGraph", "archivedConfiguration"},
+ {"java/util/ImmutableCollections$ListN", "EMPTY_LIST"},
+ {"java/util/ImmutableCollections$MapN", "EMPTY_MAP"},
+ {"java/util/ImmutableCollections$SetN", "EMPTY_SET"},
+ {"java/lang/Integer$IntegerCache", "archivedCache"},
+ {"java/lang/module/Configuration", "EMPTY_CONFIGURATION"},
+};
+
+const static int num_archivable_static_fields = sizeof(archivable_static_fields) / sizeof(ArchivableStaticFieldInfo);
+
+class ArchivableStaticFieldFinder: public FieldClosure {
+ InstanceKlass* _ik;
+ Symbol* _field_name;
+ bool _found;
+ int _offset;
+ BasicType _type;
+public:
+ ArchivableStaticFieldFinder(InstanceKlass* ik, Symbol* field_name) :
+ _ik(ik), _field_name(field_name), _found(false), _offset(-1), _type(T_ILLEGAL) {}
+
+ virtual void do_field(fieldDescriptor* fd) {
+ if (fd->name() == _field_name) {
+ assert(!_found, "fields cannot be overloaded");
+ _found = true;
+ _offset = fd->offset();
+ _type = fd->field_type();
+ assert(_type == T_OBJECT || _type == T_ARRAY, "can archive only obj or array fields");
+ }
+ }
+ bool found() { return _found; }
+ int offset() { return _offset; }
+ BasicType type() { return _type; }
+};
+
+void HeapShared::init_archivable_static_fields(Thread* THREAD) {
+ for (int i = 0; i < num_archivable_static_fields; i++) {
+ ArchivableStaticFieldInfo* info = &archivable_static_fields[i];
+ TempNewSymbol class_name = SymbolTable::new_symbol(info->class_name, THREAD);
+ TempNewSymbol field_name = SymbolTable::new_symbol(info->field_name, THREAD);
+
+ Klass* k = SystemDictionary::resolve_or_null(class_name, THREAD);
+ assert(k != NULL && !HAS_PENDING_EXCEPTION, "class must exist");
+ InstanceKlass* ik = InstanceKlass::cast(k);
+
+ ArchivableStaticFieldFinder finder(ik, field_name);
+ ik->do_local_static_fields(&finder);
+ assert(finder.found(), "field must exist");
+
+ info->klass = ik;
+ info->offset = finder.offset();
+ info->type = finder.type();
+ }
+}
void HeapShared::archive_module_graph_objects(Thread* THREAD) {
- do_module_object_graph(archive_reachable_objects_from_static_field);
+ for (int i = 0; i < num_archivable_static_fields; i++) {
+ ArchivableStaticFieldInfo* info = &archivable_static_fields[i];
+ archive_reachable_objects_from_static_field(info->klass, info->offset, info->type, CHECK);
+ }
}
+
+// At dump-time, find the location of all the non-null oop pointers in an archived heap
+// region. This way we can quickly relocate all the pointers without using
+// BasicOopIterateClosure at runtime.
+class FindEmbeddedNonNullPointers: public BasicOopIterateClosure {
+ narrowOop* _start;
+ BitMap *_oopmap;
+ int _num_total_oops;
+ int _num_null_oops;
+ public:
+ FindEmbeddedNonNullPointers(narrowOop* start, BitMap* oopmap)
+ : _start(start), _oopmap(oopmap), _num_total_oops(0), _num_null_oops(0) {}
+
+ virtual bool should_verify_oops(void) {
+ return false;
+ }
+ virtual void do_oop(narrowOop* p) {
+ _num_total_oops ++;
+ narrowOop v = *p;
+ if (!CompressedOops::is_null(v)) {
+ size_t idx = p - _start;
+ _oopmap->set_bit(idx);
+ } else {
+ _num_null_oops ++;
+ }
+ }
+ virtual void do_oop(oop *p) {
+ ShouldNotReachHere();
+ }
+ int num_total_oops() const { return _num_total_oops; }
+ int num_null_oops() const { return _num_null_oops; }
+};
+
+ResourceBitMap HeapShared::calculate_oopmap(MemRegion region) {
+ assert(UseCompressedOops, "must be");
+ size_t num_bits = region.byte_size() / sizeof(narrowOop);
+ ResourceBitMap oopmap(num_bits);
+
+ HeapWord* p = region.start();
+ HeapWord* end = region.end();
+ FindEmbeddedNonNullPointers finder((narrowOop*)p, &oopmap);
+
+ int num_objs = 0;
+ while (p < end) {
+ oop o = (oop)p;
+ o->oop_iterate(&finder);
+ p += o->size();
+ ++ num_objs;
+ }
+
+ log_info(cds, heap)("calculate_oopmap: objects = %6d, embedded oops = %7d, nulls = %7d",
+ num_objs, finder.num_total_oops(), finder.num_null_oops());
+ return oopmap;
+}
+
+void HeapShared::init_narrow_oop_decoding(address base, int shift) {
+ _narrow_oop_base = base;
+ _narrow_oop_shift = shift;
+}
+
+// Patch all the embedded oop pointers inside an archived heap region,
+// to be consistent with the runtime oop encoding.
+class PatchEmbeddedPointers: public BitMapClosure {
+ narrowOop* _start;
+
+ public:
+ PatchEmbeddedPointers(narrowOop* start) : _start(start) {}
+
+ bool do_bit(size_t offset) {
+ narrowOop* p = _start + offset;
+ narrowOop v = *p;
+ assert(!CompressedOops::is_null(v), "null oops should have been filtered out at dump time");
+ oop o = HeapShared::decode_with_archived_oop_encoding_mode(v);
+ RawAccess<IS_NOT_NULL>::oop_store(p, o);
+ return true;
+ }
+};
+
+void HeapShared::patch_archived_heap_embedded_pointers(MemRegion region, address oopmap,
+ size_t oopmap_size_in_bits) {
+ BitMapView bm((BitMap::bm_word_t*)oopmap, oopmap_size_in_bits);
+
+#ifndef PRODUCT
+ ResourceMark rm;
+ ResourceBitMap checkBm = calculate_oopmap(region);
+ assert(bm.is_same(checkBm), "sanity");
+#endif
+
+ PatchEmbeddedPointers patcher((narrowOop*)region.start());
+ bm.iterate(&patcher);
+}
+
#endif // INCLUDE_CDS_JAVA_HEAP
--- a/src/hotspot/share/memory/heapShared.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/memory/heapShared.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -30,6 +30,7 @@
#include "oops/objArrayKlass.hpp"
#include "oops/oop.hpp"
#include "oops/typeArrayKlass.hpp"
+#include "utilities/bitMap.hpp"
#include "utilities/growableArray.hpp"
#if INCLUDE_CDS_JAVA_HEAP
@@ -123,12 +124,33 @@
static int num_of_subgraph_infos();
static size_t build_archived_subgraph_info_records(int num_records);
+
+ // Used by decode_with_archived_oop_encoding_mode
+ static address _narrow_oop_base;
+ static int _narrow_oop_shift;
+
#endif // INCLUDE_CDS_JAVA_HEAP
public:
static char* read_archived_subgraph_infos(char* buffer) NOT_CDS_JAVA_HEAP_RETURN_(buffer);
static void write_archived_subgraph_infos() NOT_CDS_JAVA_HEAP_RETURN;
static void initialize_from_archived_subgraph(Klass* k) NOT_CDS_JAVA_HEAP_RETURN;
+ // NarrowOops stored in the CDS archive may use a different encoding scheme
+ // than Universe::narrow_oop_{base,shift} -- see FileMapInfo::map_heap_regions_impl.
+ // To decode them, do not use CompressedOops::decode_not_null. Use this
+ // function instead.
+ inline static oop decode_with_archived_oop_encoding_mode(narrowOop v) NOT_CDS_JAVA_HEAP_RETURN_(NULL);
+
+ static void init_narrow_oop_decoding(address base, int shift) NOT_CDS_JAVA_HEAP_RETURN;
+
+ static void patch_archived_heap_embedded_pointers(MemRegion mem, address oopmap,
+ size_t oopmap_in_bits) NOT_CDS_JAVA_HEAP_RETURN;
+
+ static void init_archivable_static_fields(Thread* THREAD) NOT_CDS_JAVA_HEAP_RETURN;
static void archive_module_graph_objects(Thread* THREAD) NOT_CDS_JAVA_HEAP_RETURN;
+
+#if INCLUDE_CDS_JAVA_HEAP
+ static ResourceBitMap calculate_oopmap(MemRegion region);
+#endif
};
#endif // SHARE_VM_MEMORY_HEAPSHARED_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/memory/heapShared.inline.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * 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_MEMORY_HEAPSHARED_INLINE_HPP
+#define SHARE_VM_MEMORY_HEAPSHARED_INLINE_HPP
+
+#include "oops/compressedOops.inline.hpp"
+#include "memory/heapShared.hpp"
+
+#if INCLUDE_CDS_JAVA_HEAP
+
+inline oop HeapShared::decode_with_archived_oop_encoding_mode(narrowOop v) {
+ assert(!CompressedOops::is_null(v), "narrow oop value can never be zero");
+ oop result = (oop)(void*)((uintptr_t)_narrow_oop_base + ((uintptr_t)v << _narrow_oop_shift));
+ assert(check_obj_alignment(result), "address not aligned: " INTPTR_FORMAT, p2i((void*) result));
+ return result;
+}
+
+#endif
+
+#endif // SHARE_VM_MEMORY_HEAPSHARED_INLINE_HPP
--- a/src/hotspot/share/memory/metaspace.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/memory/metaspace.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -62,7 +62,7 @@
switch (t) {
case Metaspace::StandardMetaspaceType: s = "Standard"; break;
case Metaspace::BootMetaspaceType: s = "Boot"; break;
- case Metaspace::AnonymousMetaspaceType: s = "Anonymous"; break;
+ case Metaspace::UnsafeAnonymousMetaspaceType: s = "UnsafeAnonymous"; break;
case Metaspace::ReflectionMetaspaceType: s = "Reflection"; break;
default: ShouldNotReachHere();
}
--- a/src/hotspot/share/memory/metaspace.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/memory/metaspace.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -102,8 +102,8 @@
ZeroMetaspaceType = 0,
StandardMetaspaceType = ZeroMetaspaceType,
BootMetaspaceType = StandardMetaspaceType + 1,
- AnonymousMetaspaceType = BootMetaspaceType + 1,
- ReflectionMetaspaceType = AnonymousMetaspaceType + 1,
+ UnsafeAnonymousMetaspaceType = BootMetaspaceType + 1,
+ ReflectionMetaspaceType = UnsafeAnonymousMetaspaceType + 1,
MetaspaceTypeCount
};
--- a/src/hotspot/share/memory/metaspace/printCLDMetaspaceInfoClosure.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/memory/metaspace/printCLDMetaspaceInfoClosure.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -102,7 +102,7 @@
_out->print(" (unloading)");
}
_out->print(":");
- if (cld->is_anonymous()) {
+ if (cld->is_unsafe_anonymous()) {
_out->print(" <anonymous class>, loaded by");
}
if (name != NULL) {
--- a/src/hotspot/share/memory/metaspace/spaceManager.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/memory/metaspace/spaceManager.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -74,17 +74,17 @@
if (is_class()) {
switch (type) {
- case Metaspace::BootMetaspaceType: requested = Metaspace::first_class_chunk_word_size(); break;
- case Metaspace::AnonymousMetaspaceType: requested = ClassSpecializedChunk; break;
- case Metaspace::ReflectionMetaspaceType: requested = ClassSpecializedChunk; break;
- default: requested = ClassSmallChunk; break;
+ case Metaspace::BootMetaspaceType: requested = Metaspace::first_class_chunk_word_size(); break;
+ case Metaspace::UnsafeAnonymousMetaspaceType: requested = ClassSpecializedChunk; break;
+ case Metaspace::ReflectionMetaspaceType: requested = ClassSpecializedChunk; break;
+ default: requested = ClassSmallChunk; break;
}
} else {
switch (type) {
- case Metaspace::BootMetaspaceType: requested = Metaspace::first_chunk_word_size(); break;
- case Metaspace::AnonymousMetaspaceType: requested = SpecializedChunk; break;
- case Metaspace::ReflectionMetaspaceType: requested = SpecializedChunk; break;
- default: requested = SmallChunk; break;
+ case Metaspace::BootMetaspaceType: requested = Metaspace::first_chunk_word_size(); break;
+ case Metaspace::UnsafeAnonymousMetaspaceType: requested = SpecializedChunk; break;
+ case Metaspace::ReflectionMetaspaceType: requested = SpecializedChunk; break;
+ default: requested = SmallChunk; break;
}
}
@@ -114,13 +114,15 @@
// After that a medium chunk is preferred.
size_t chunk_word_size;
- // Special case for anonymous metadata space.
- // Anonymous metadata space is usually small, with majority within 1K - 2K range and
+ // Special case for unsafe anonymous metadata space.
+ // UnsafeAnonymous metadata space is usually small since it is used for
+ // class loader data's whose life cycle is governed by one class such as an
+ // unsafe anonymous class. The majority within 1K - 2K range and
// rarely about 4K (64-bits JVM).
// Instead of jumping to SmallChunk after initial chunk exhausted, keeping allocation
// from SpecializeChunk up to _anon_or_delegating_metadata_specialize_chunk_limit (4)
// reduces space waste from 60+% to around 30%.
- if ((_space_type == Metaspace::AnonymousMetaspaceType || _space_type == Metaspace::ReflectionMetaspaceType) &&
+ if ((_space_type == Metaspace::UnsafeAnonymousMetaspaceType || _space_type == Metaspace::ReflectionMetaspaceType) &&
_mdtype == Metaspace::NonClassType &&
num_chunks_by_type(SpecializedIndex) < anon_and_delegating_metadata_specialize_chunk_limit &&
word_size + Metachunk::overhead() <= SpecializedChunk) {
--- a/src/hotspot/share/memory/metaspaceShared.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/memory/metaspaceShared.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -39,7 +39,7 @@
#include "logging/log.hpp"
#include "logging/logMessage.hpp"
#include "memory/filemap.hpp"
-#include "memory/heapShared.hpp"
+#include "memory/heapShared.inline.hpp"
#include "memory/metaspace.hpp"
#include "memory/metaspaceClosure.hpp"
#include "memory/metaspaceShared.hpp"
@@ -61,6 +61,7 @@
#include "runtime/vmThread.hpp"
#include "runtime/vm_operations.hpp"
#include "utilities/align.hpp"
+#include "utilities/bitMap.hpp"
#include "utilities/defaultStream.hpp"
#include "utilities/hashtable.inline.hpp"
#if INCLUDE_G1GC
@@ -227,7 +228,7 @@
// Map in spaces now also
if (mapinfo->initialize() && map_shared_spaces(mapinfo)) {
size_t cds_total = core_spaces_size();
- cds_address = (address)mapinfo->header()->region_addr(0);
+ cds_address = (address)mapinfo->region_addr(0);
#ifdef _LP64
if (Metaspace::using_class_space()) {
char* cds_end = (char*)(cds_address + cds_total);
@@ -309,10 +310,10 @@
Universe::set_narrow_klass_range(cds_total);
Metaspace::initialize_class_space(tmp_class_space);
- tty->print_cr("narrow_klass_base = " PTR_FORMAT ", narrow_klass_shift = %d",
+ log_info(cds)("narrow_klass_base = " PTR_FORMAT ", narrow_klass_shift = %d",
p2i(Universe::narrow_klass_base()), Universe::narrow_klass_shift());
- tty->print_cr("Allocated temporary class space: " SIZE_FORMAT " bytes at " PTR_FORMAT,
+ log_info(cds)("Allocated temporary class space: " SIZE_FORMAT " bytes at " PTR_FORMAT,
CompressedClassSpaceSize, p2i(tmp_class_space.base()));
#endif
@@ -333,7 +334,7 @@
int size = FileMapInfo::get_number_of_shared_paths();
if (size > 0) {
SystemDictionaryShared::allocate_shared_data_arrays(size, THREAD);
- FileMapInfo::FileMapHeader* header = FileMapInfo::current_info()->header();
+ FileMapHeader* header = FileMapInfo::current_info()->header();
ClassLoaderExt::init_paths_start_index(header->_app_class_paths_start_index);
ClassLoaderExt::init_app_module_paths_start_index(header->_app_module_paths_start_index);
}
@@ -423,51 +424,13 @@
StringTable::serialize(soc);
soc->do_tag(--tag);
- serialize_well_known_classes(soc);
+ JavaClasses::serialize_offsets(soc);
+ InstanceMirrorKlass::serialize_offsets(soc);
soc->do_tag(--tag);
soc->do_tag(666);
}
-void MetaspaceShared::serialize_well_known_classes(SerializeClosure* soc) {
- java_lang_Class::serialize(soc);
- java_lang_String::serialize(soc);
- java_lang_System::serialize(soc);
- java_lang_ClassLoader::serialize(soc);
- java_lang_Throwable::serialize(soc);
- java_lang_Thread::serialize(soc);
- java_lang_ThreadGroup::serialize(soc);
- java_lang_AssertionStatusDirectives::serialize(soc);
- java_lang_module_Configuration::serialize(soc);
- java_lang_ref_SoftReference::serialize(soc);
- java_lang_invoke_MethodHandle::serialize(soc);
- java_lang_invoke_DirectMethodHandle::serialize(soc);
- java_lang_invoke_MemberName::serialize(soc);
- java_lang_invoke_ResolvedMethodName::serialize(soc);
- java_lang_invoke_LambdaForm::serialize(soc);
- java_lang_invoke_MethodType::serialize(soc);
- java_lang_invoke_CallSite::serialize(soc);
- java_lang_invoke_MethodHandleNatives_CallSiteContext::serialize(soc);
- java_security_AccessControlContext::serialize(soc);
- java_lang_reflect_AccessibleObject::serialize(soc);
- java_lang_reflect_Method::serialize(soc);
- java_lang_reflect_Constructor::serialize(soc);
- java_lang_reflect_Field::serialize(soc);
- java_nio_Buffer::serialize(soc);
- reflect_ConstantPool::serialize(soc);
- reflect_UnsafeStaticFieldAccessorImpl::serialize(soc);
- java_lang_reflect_Parameter::serialize(soc);
- java_lang_Module::serialize(soc);
- java_lang_StackTraceElement::serialize(soc);
- java_lang_StackFrameInfo::serialize(soc);
- java_lang_LiveStackFrameInfo::serialize(soc);
- java_util_concurrent_locks_AbstractOwnableSynchronizer::serialize(soc);
- java_util_ImmutableCollections_ListN::serialize(soc);
- java_util_ImmutableCollections_MapN::serialize(soc);
- java_util_ImmutableCollections_SetN::serialize(soc);
- jdk_internal_module_ArchivedModuleGraph::serialize(soc);
-}
-
address MetaspaceShared::cds_i2i_entry_code_buffers(size_t total_size) {
if (DumpSharedSpaces) {
if (_cds_i2i_entry_code_buffers == NULL) {
@@ -618,14 +581,13 @@
}
NOT_PRODUCT(
-static void assert_not_anonymous_class(InstanceKlass* k) {
- assert(!(k->is_anonymous()), "cannot archive anonymous classes");
+static void assert_not_unsafe_anonymous_class(InstanceKlass* k) {
+ assert(!(k->is_unsafe_anonymous()), "cannot archive unsafe anonymous classes");
}
-// Anonymous classes are not stored inside any dictionaries. They are created by
-// SystemDictionary::parse_stream() with a non-null host_klass.
-static void assert_no_anonymoys_classes_in_dictionaries() {
- ClassLoaderDataGraph::dictionary_classes_do(assert_not_anonymous_class);
+// Unsafe anonymous classes are not stored inside any dictionaries.
+static void assert_no_unsafe_anonymous_classes_in_dictionaries() {
+ ClassLoaderDataGraph::dictionary_classes_do(assert_not_unsafe_anonymous_class);
})
// Objects of the Metadata types (such as Klass and ConstantPool) have C++ vtables.
@@ -1057,7 +1019,13 @@
GrowableArray<MemRegion> *_closed_archive_heap_regions;
GrowableArray<MemRegion> *_open_archive_heap_regions;
+ GrowableArray<ArchiveHeapOopmapInfo> *_closed_archive_heap_oopmaps;
+ GrowableArray<ArchiveHeapOopmapInfo> *_open_archive_heap_oopmaps;
+
void dump_java_heap_objects() NOT_CDS_JAVA_HEAP_RETURN;
+ void dump_archive_heap_oopmaps() NOT_CDS_JAVA_HEAP_RETURN;
+ void dump_archive_heap_oopmaps(GrowableArray<MemRegion>* regions,
+ GrowableArray<ArchiveHeapOopmapInfo>* oopmaps);
void dump_symbols();
char* dump_read_only_tables();
void print_region_stats();
@@ -1369,6 +1337,9 @@
WriteClosure wc(&_ro_region);
MetaspaceShared::serialize(&wc);
+ // Write the bitmaps for patching the archive heap regions
+ dump_archive_heap_oopmaps();
+
char* newtop = _ro_region.top();
ArchiveCompactor::alloc_stats()->record_other_type(int(newtop - oldtop), true);
return buckets_top;
@@ -1435,9 +1406,9 @@
remove_unshareable_in_classes();
tty->print_cr("done. ");
- // We don't support archiving anonymous classes. Verify that they are not stored in
- // the any dictionaries.
- NOT_PRODUCT(assert_no_anonymoys_classes_in_dictionaries());
+ // We don't support archiving unsafe anonymous classes. Verify that they are not stored in
+ // any dictionaries.
+ NOT_PRODUCT(assert_no_unsafe_anonymous_classes_in_dictionaries());
SystemDictionaryShared::finalize_verification_constraints();
@@ -1511,10 +1482,12 @@
_total_string_region_size = mapinfo->write_archive_heap_regions(
_closed_archive_heap_regions,
+ _closed_archive_heap_oopmaps,
MetaspaceShared::first_string,
MetaspaceShared::max_strings);
_total_open_archive_region_size = mapinfo->write_archive_heap_regions(
_open_archive_heap_regions,
+ _open_archive_heap_oopmaps,
MetaspaceShared::first_open_archive_heap_region,
MetaspaceShared::max_open_archive_heap_region);
}
@@ -1737,6 +1710,7 @@
tty->print_cr("Rewriting and linking classes: done");
SystemDictionary::clear_invoke_method_table();
+ HeapShared::init_archivable_static_fields(THREAD);
VM_PopulateDumpSharedSpace op;
VMThread::execute(&op);
@@ -1849,6 +1823,36 @@
G1HeapVerifier::verify_archive_regions();
}
+void VM_PopulateDumpSharedSpace::dump_archive_heap_oopmaps() {
+ if (MetaspaceShared::is_heap_object_archiving_allowed()) {
+ _closed_archive_heap_oopmaps = new GrowableArray<ArchiveHeapOopmapInfo>(2);
+ dump_archive_heap_oopmaps(_closed_archive_heap_regions, _closed_archive_heap_oopmaps);
+
+ _open_archive_heap_oopmaps = new GrowableArray<ArchiveHeapOopmapInfo>(2);
+ dump_archive_heap_oopmaps(_open_archive_heap_regions, _open_archive_heap_oopmaps);
+ }
+}
+
+void VM_PopulateDumpSharedSpace::dump_archive_heap_oopmaps(GrowableArray<MemRegion>* regions,
+ GrowableArray<ArchiveHeapOopmapInfo>* oopmaps) {
+ for (int i=0; i<regions->length(); i++) {
+ ResourceBitMap oopmap = HeapShared::calculate_oopmap(regions->at(i));
+ size_t size_in_bits = oopmap.size();
+ size_t size_in_bytes = oopmap.size_in_bytes();
+ uintptr_t* buffer = (uintptr_t*)_ro_region.allocate(size_in_bytes, sizeof(intptr_t));
+ oopmap.write_to(buffer, size_in_bytes);
+ log_info(cds)("Oopmap = " INTPTR_FORMAT " (" SIZE_FORMAT_W(6) " bytes) for heap region "
+ INTPTR_FORMAT " (" SIZE_FORMAT_W(8) " bytes)",
+ p2i(buffer), size_in_bytes,
+ p2i(regions->at(i).start()), regions->at(i).byte_size());
+
+ ArchiveHeapOopmapInfo info;
+ info._oopmap = (address)buffer;
+ info._oopmap_size_in_bits = size_in_bits;
+ oopmaps->append(info);
+ }
+}
+
void MetaspaceShared::dump_closed_archive_heap_objects(
GrowableArray<MemRegion> * closed_archive) {
assert(is_heap_object_archiving_allowed(), "Cannot dump java heap objects");
@@ -1912,6 +1916,8 @@
int len = obj->size();
if (G1CollectedHeap::heap()->is_archive_alloc_too_large(len)) {
+ log_debug(cds, heap)("Cannot archive, object (" PTR_FORMAT ") is too large: " SIZE_FORMAT,
+ p2i(obj), (size_t)obj->size());
return NULL;
}
@@ -1922,14 +1928,20 @@
relocate_klass_ptr(archived_oop);
ArchivedObjectCache* cache = MetaspaceShared::archive_object_cache();
cache->put(obj, archived_oop);
+ log_debug(cds, heap)("Archived heap object " PTR_FORMAT " ==> " PTR_FORMAT,
+ p2i(obj), p2i(archived_oop));
+ } else {
+ log_error(cds, heap)(
+ "Cannot allocate space for object " PTR_FORMAT " in archived heap region",
+ p2i(obj));
+ vm_exit(1);
}
- log_debug(cds, heap)("Archived heap object " PTR_FORMAT " ==> " PTR_FORMAT,
- p2i(obj), p2i(archived_oop));
return archived_oop;
}
-oop MetaspaceShared::materialize_archived_object(oop obj) {
- if (obj != NULL) {
+oop MetaspaceShared::materialize_archived_object(narrowOop v) {
+ if (!CompressedOops::is_null(v)) {
+ oop obj = HeapShared::decode_with_archived_oop_encoding_mode(v);
return G1CollectedHeap::heap()->materialize_archived_object(obj);
}
return NULL;
@@ -2005,7 +2017,7 @@
"Archived heap object is not allowed");
assert(MetaspaceShared::open_archive_heap_region_mapped(),
"Open archive heap region is not mapped");
- *p = CompressedOops::decode_not_null(o);
+ *p = HeapShared::decode_with_archived_oop_encoding_mode(o);
}
}
@@ -2035,13 +2047,6 @@
return false;
}
-void MetaspaceShared::print_shared_spaces() {
- if (UseSharedSpaces) {
- FileMapInfo::current_info()->print_shared_spaces();
- }
-}
-
-
// Map shared spaces at requested addresses and return if succeeded.
bool MetaspaceShared::map_shared_spaces(FileMapInfo* mapinfo) {
size_t image_alignment = mapinfo->alignment();
@@ -2152,6 +2157,8 @@
// Initialize the run-time symbol table.
SymbolTable::create_table();
+ mapinfo->patch_archived_heap_embedded_pointers();
+
// Close the mapinfo file
mapinfo->close();
--- a/src/hotspot/share/memory/metaspaceShared.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/memory/metaspaceShared.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -79,6 +79,7 @@
// mapped java heap regions
first_string = od + 1, // index of first string region
max_strings = 2, // max number of string regions in string space
+ last_string = first_string + max_strings - 1,
first_open_archive_heap_region = first_string + max_strings,
max_open_archive_heap_region = 2,
@@ -111,7 +112,7 @@
}
static oop find_archived_heap_object(oop obj);
static oop archive_heap_object(oop obj, Thread* THREAD);
- static oop materialize_archived_object(oop obj);
+ static oop materialize_archived_object(narrowOop v);
static void archive_klass_objects(Thread* THREAD);
#endif
@@ -204,7 +205,6 @@
static void patch_cpp_vtable_pointers();
static bool is_valid_shared_method(const Method* m) NOT_CDS_RETURN_(false);
static void serialize(SerializeClosure* sc) NOT_CDS_RETURN;
- static void serialize_well_known_classes(SerializeClosure* soc) NOT_CDS_RETURN;
static MetaspaceSharedStats* stats() {
return &_stats;
@@ -222,8 +222,6 @@
NOT_CDS(return false);
}
- static void print_shared_spaces();
-
static bool try_link_class(InstanceKlass* ik, TRAPS);
static void link_and_cleanup_shared_classes(TRAPS);
static void check_shared_class_loader_type(InstanceKlass* ik);
--- a/src/hotspot/share/memory/metaspaceTracer.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/memory/metaspaceTracer.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -62,10 +62,10 @@
E event;
if (event.should_commit()) {
event.set_classLoader(cld);
- if (cld->is_anonymous()) {
- event.set_anonymousClassLoader(true);
+ if (cld->is_unsafe_anonymous()) {
+ event.set_unsafeAnonymousClassLoader(true);
} else {
- event.set_anonymousClassLoader(false);
+ event.set_unsafeAnonymousClassLoader(false);
}
event.set_size(word_size * BytesPerWord);
event.set_metadataType((u1) mdtype);
--- a/src/hotspot/share/memory/universe.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/memory/universe.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -517,8 +517,11 @@
// that the number of objects allocated at this point is very small.
assert(SystemDictionary::Class_klass_loaded(), "java.lang.Class should be loaded");
HandleMark hm(THREAD);
- // Cache the start of the static fields
- InstanceMirrorKlass::init_offset_of_static_fields();
+
+ if (!UseSharedSpaces) {
+ // Cache the start of the static fields
+ InstanceMirrorKlass::init_offset_of_static_fields();
+ }
GrowableArray <Klass*>* list = java_lang_Class::fixup_mirror_list();
int list_length = list->length();
--- a/src/hotspot/share/oops/constantPool.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/oops/constantPool.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -221,7 +221,7 @@
allocate_resolved_klasses(loader_data, num_klasses, THREAD);
}
-// Anonymous class support:
+// Unsafe anonymous class support:
void ConstantPool::klass_at_put(int class_index, int name_index, int resolved_klass_index, Klass* k, Symbol* name) {
assert(is_within_bounds(class_index), "index out of bounds");
assert(is_within_bounds(name_index), "index out of bounds");
@@ -243,7 +243,7 @@
}
}
-// Anonymous class support:
+// Unsafe anonymous class support:
void ConstantPool::klass_at_put(int class_index, Klass* k) {
assert(k != NULL, "must be valid klass");
CPKlassSlot kslot = klass_slot_at(class_index);
@@ -296,6 +296,11 @@
}
oop archived = MetaspaceShared::archive_heap_object(rr, THREAD);
+ // If the resolved references array is not archived (too large),
+ // the 'archived' object is NULL. No need to explicitly check
+ // the return value of archive_heap_object here. At runtime, the
+ // resolved references will be created using the normal process
+ // when there is no archived value.
_cache->set_archived_references(archived);
set_resolved_references(NULL);
}
@@ -764,10 +769,14 @@
void ConstantPool::throw_resolution_error(const constantPoolHandle& this_cp, int which, TRAPS) {
Symbol* message = NULL;
Symbol* error = SystemDictionary::find_resolution_error(this_cp, which, &message);
- assert(error != NULL && message != NULL, "checking");
+ assert(error != NULL, "checking");
CLEAR_PENDING_EXCEPTION;
- ResourceMark rm;
- THROW_MSG(error, message->as_C_string());
+ if (message != NULL) {
+ ResourceMark rm;
+ THROW_MSG(error, message->as_C_string());
+ } else {
+ THROW(error);
+ }
}
// If resolution for Class, Dynamic constant, MethodHandle or MethodType fails, save the
--- a/src/hotspot/share/oops/constantPool.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/oops/constantPool.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -271,7 +271,7 @@
*int_at_addr(which) = name_index;
}
- // Anonymous class support:
+ // Unsafe anonymous class support:
void klass_at_put(int class_index, int name_index, int resolved_klass_index, Klass* k, Symbol* name);
void klass_at_put(int class_index, Klass* k);
@@ -455,7 +455,7 @@
// A "pseudo-string" is an non-string oop that has found its way into
// a String entry.
// This can happen if the user patches a live
- // object into a CONSTANT_String entry of an anonymous class.
+ // object into a CONSTANT_String entry of an unsafe anonymous class.
// Method oops internally created for method handles may also
// use pseudo-strings to link themselves to related metaobjects.
--- a/src/hotspot/share/oops/cpCache.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/oops/cpCache.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -477,7 +477,6 @@
Symbol* error = PENDING_EXCEPTION->klass()->name();
Symbol* message = java_lang_Throwable::detail_message(PENDING_EXCEPTION);
- assert(message != NULL, "Missing detail message");
SystemDictionary::add_resolution_error(cpool, index, error, message);
set_indy_resolution_failed();
@@ -778,7 +777,7 @@
if (CompressedOops::is_null(_archived_references)) {
return NULL;
}
- return MetaspaceShared::materialize_archived_object(CompressedOops::decode_not_null(_archived_references));
+ return MetaspaceShared::materialize_archived_object(_archived_references);
}
void ConstantPoolCache::set_archived_references(oop o) {
--- a/src/hotspot/share/oops/instanceKlass.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/oops/instanceKlass.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -66,7 +66,7 @@
#include "prims/jvmtiThreadState.hpp"
#include "prims/methodComparator.hpp"
#include "runtime/atomic.hpp"
-#include "runtime/fieldDescriptor.hpp"
+#include "runtime/fieldDescriptor.inline.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/mutexLocker.hpp"
@@ -341,8 +341,8 @@
parser.itable_size(),
nonstatic_oop_map_size(parser.total_oop_map_count()),
parser.is_interface(),
- parser.is_anonymous(),
- should_store_fingerprint(parser.is_anonymous()));
+ parser.is_unsafe_anonymous(),
+ should_store_fingerprint(parser.is_unsafe_anonymous()));
const Symbol* const class_name = parser.class_name();
assert(class_name != NULL, "invariant");
@@ -412,7 +412,7 @@
set_vtable_length(parser.vtable_size());
set_kind(kind);
set_access_flags(parser.access_flags());
- set_is_anonymous(parser.is_anonymous());
+ set_is_unsafe_anonymous(parser.is_unsafe_anonymous());
set_layout_helper(Klass::instance_layout_helper(parser.layout_size(),
false));
@@ -1051,6 +1051,38 @@
}
}
+Klass* InstanceKlass::implementor() const {
+ assert_locked_or_safepoint(Compile_lock);
+ Klass** k = adr_implementor();
+ if (k == NULL) {
+ return NULL;
+ } else {
+ return *k;
+ }
+}
+
+void InstanceKlass::set_implementor(Klass* k) {
+ assert_lock_strong(Compile_lock);
+ assert(is_interface(), "not interface");
+ Klass** addr = adr_implementor();
+ assert(addr != NULL, "null addr");
+ if (addr != NULL) {
+ *addr = k;
+ }
+}
+
+int InstanceKlass::nof_implementors() const {
+ assert_lock_strong(Compile_lock);
+ Klass* k = implementor();
+ if (k == NULL) {
+ return 0;
+ } else if (k != this) {
+ return 1;
+ } else {
+ return 2;
+ }
+}
+
// The embedded _implementor field can only record one implementor.
// When there are more than one implementors, the _implementor field
// is set to the interface Klass* itself. Following are the possible
@@ -1061,7 +1093,7 @@
//
// The _implementor field only exists for interfaces.
void InstanceKlass::add_implementor(Klass* k) {
- assert(Compile_lock->owned_by_self(), "");
+ assert_lock_strong(Compile_lock);
assert(is_interface(), "not interface");
// Filter out my subinterfaces.
// (Note: Interfaces are never on the subklass list.)
@@ -2161,7 +2193,7 @@
return true;
}
-bool InstanceKlass::should_store_fingerprint(bool is_anonymous) {
+bool InstanceKlass::should_store_fingerprint(bool is_unsafe_anonymous) {
#if INCLUDE_AOT
// We store the fingerprint into the InstanceKlass only in the following 2 cases:
if (CalculateClassFingerprint) {
@@ -2172,8 +2204,8 @@
// (2) We are running -Xshare:dump to create a shared archive
return true;
}
- if (UseAOT && is_anonymous) {
- // (3) We are using AOT code from a shared library and see an anonymous class
+ if (UseAOT && is_unsafe_anonymous) {
+ // (3) We are using AOT code from a shared library and see an unsafe anonymous class
return true;
}
#endif
@@ -2270,7 +2302,10 @@
if (is_linked()) {
unlink_class();
}
- init_implementor();
+ {
+ MutexLocker ml(Compile_lock);
+ init_implementor();
+ }
constants()->remove_unshareable_info();
@@ -2472,8 +2507,8 @@
int hash_len = 0;
char hash_buf[40];
- // If this is an anonymous class, append a hash to make the name unique
- if (is_anonymous()) {
+ // If this is an unsafe anonymous class, append a hash to make the name unique
+ if (is_unsafe_anonymous()) {
intptr_t hash = (java_mirror() != NULL) ? java_mirror()->identity_hash() : 0;
jio_snprintf(hash_buf, sizeof(hash_buf), "/" UINTX_FORMAT, (uintx)hash);
hash_len = (int)strlen(hash_buf);
@@ -2524,14 +2559,19 @@
}
ModuleEntry* InstanceKlass::module() const {
+ // For an unsafe anonymous class return the host class' module
+ if (is_unsafe_anonymous()) {
+ assert(unsafe_anonymous_host() != NULL, "unsafe anonymous class must have a host class");
+ return unsafe_anonymous_host()->module();
+ }
+
+ // Class is in a named package
if (!in_unnamed_package()) {
return _package_entry->module();
}
- const Klass* host = host_klass();
- if (host == NULL) {
- return class_loader_data()->unnamed_module();
- }
- return host->class_loader_data()->unnamed_module();
+
+ // Class is in an unnamed package, return its loader's unnamed module
+ return class_loader_data()->unnamed_module();
}
void InstanceKlass::set_package(ClassLoaderData* loader_data, TRAPS) {
@@ -2778,7 +2818,7 @@
*inner_is_member = true;
}
if (NULL == outer_klass) {
- // It may be anonymous; try for that.
+ // It may be unsafe anonymous; try for that.
int encl_method_class_idx = enclosing_method_class_index();
if (encl_method_class_idx != 0) {
Klass* ok = i_cp->klass_at(encl_method_class_idx, CHECK_NULL);
@@ -3089,6 +3129,7 @@
st->cr();
if (is_interface()) {
+ MutexLocker ml(Compile_lock);
st->print_cr(BULLET"nof implementors: %d", nof_implementors());
if (nof_implementors() == 1) {
st->print_cr(BULLET"implementor: ");
@@ -3125,7 +3166,7 @@
class_loader_data()->print_value_on(st);
st->cr();
}
- st->print(BULLET"host class: "); Metadata::print_value_on_maybe_null(st, host_klass()); st->cr();
+ st->print(BULLET"unsafe anonymous host class: "); Metadata::print_value_on_maybe_null(st, unsafe_anonymous_host()); st->cr();
if (source_file_name() != NULL) {
st->print(BULLET"source file: ");
source_file_name()->print_value_on(st);
@@ -3496,14 +3537,8 @@
guarantee(sib->super() == super, "siblings should have same superklass");
}
- // Verify implementor fields
- Klass* im = implementor();
- if (im != NULL) {
- guarantee(is_interface(), "only interfaces should have implementor set");
- guarantee(im->is_klass(), "should be klass");
- guarantee(!im->is_interface() || im == this,
- "implementors cannot be interfaces");
- }
+ // Verify implementor fields requires the Compile_lock, but this is sometimes
+ // called inside a safepoint, so don't verify.
// Verify local interfaces
if (local_interfaces()) {
@@ -3582,9 +3617,9 @@
if (constants() != NULL) {
guarantee(constants()->is_constantPool(), "should be constant pool");
}
- const Klass* host = host_klass();
- if (host != NULL) {
- guarantee(host->is_klass(), "should be klass");
+ const Klass* anonymous_host = unsafe_anonymous_host();
+ if (anonymous_host != NULL) {
+ guarantee(anonymous_host->is_klass(), "should be klass");
}
}
--- a/src/hotspot/share/oops/instanceKlass.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/oops/instanceKlass.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -54,7 +54,7 @@
// The embedded nonstatic oop-map blocks are short pairs (offset, length)
// indicating where oops are located in instances of this klass.
// [EMBEDDED implementor of the interface] only exist for interface
-// [EMBEDDED host klass ] only exist for an anonymous class (JSR 292 enabled)
+// [EMBEDDED unsafe_anonymous_host klass] only exist for an unsafe anonymous class (JSR 292 enabled)
// [EMBEDDED fingerprint ] only if should_store_fingerprint()==true
@@ -226,7 +226,7 @@
_misc_rewritten = 1 << 2, // methods rewritten.
_misc_has_nonstatic_fields = 1 << 3, // for sizing with UseCompressedOops
_misc_should_verify_class = 1 << 4, // allow caching of preverification
- _misc_is_anonymous = 1 << 5, // has embedded _host_klass field
+ _misc_is_unsafe_anonymous = 1 << 5, // has embedded _unsafe_anonymous_host field
_misc_is_contended = 1 << 6, // marked with contended annotation
_misc_has_nonstatic_concrete_methods = 1 << 7, // class/superclass/implemented interfaces has non-static, concrete methods
_misc_declares_nonstatic_concrete_methods = 1 << 8, // directly declares non-static, concrete methods
@@ -315,11 +315,11 @@
// NULL: no implementor.
// A Klass* that's not itself: one implementor.
// Itself: more than one implementors.
- // embedded host klass follows here
- // The embedded host klass only exists in an anonymous class for
+ // embedded unsafe_anonymous_host klass follows here
+ // The embedded host klass only exists in an unsafe anonymous class for
// dynamic language support (JSR 292 enabled). The host class grants
// its access privileges to this class also. The host class is either
- // named, or a previously loaded anonymous class. A non-anonymous class
+ // named, or a previously loaded unsafe anonymous class. A non-anonymous class
// or an anonymous class loaded through normal classloading does not
// have this embedded field.
//
@@ -650,43 +650,40 @@
objArrayOop signers() const;
// host class
- InstanceKlass* host_klass() const {
- InstanceKlass** hk = adr_host_klass();
+ InstanceKlass* unsafe_anonymous_host() const {
+ InstanceKlass** hk = adr_unsafe_anonymous_host();
if (hk == NULL) {
- assert(!is_anonymous(), "Anonymous classes have host klasses");
+ assert(!is_unsafe_anonymous(), "Unsafe anonymous classes have host klasses");
return NULL;
} else {
assert(*hk != NULL, "host klass should always be set if the address is not null");
- assert(is_anonymous(), "Only anonymous classes have host klasses");
+ assert(is_unsafe_anonymous(), "Only unsafe anonymous classes have host klasses");
return *hk;
}
}
- void set_host_klass(const InstanceKlass* host) {
- assert(is_anonymous(), "not anonymous");
- const InstanceKlass** addr = (const InstanceKlass **)adr_host_klass();
+ void set_unsafe_anonymous_host(const InstanceKlass* host) {
+ assert(is_unsafe_anonymous(), "not unsafe anonymous");
+ const InstanceKlass** addr = (const InstanceKlass **)adr_unsafe_anonymous_host();
assert(addr != NULL, "no reversed space");
if (addr != NULL) {
*addr = host;
}
}
- bool has_host_klass() const {
- return adr_host_klass() != NULL;
- }
- bool is_anonymous() const {
- return (_misc_flags & _misc_is_anonymous) != 0;
+ bool is_unsafe_anonymous() const {
+ return (_misc_flags & _misc_is_unsafe_anonymous) != 0;
}
- void set_is_anonymous(bool value) {
+ void set_is_unsafe_anonymous(bool value) {
if (value) {
- _misc_flags |= _misc_is_anonymous;
+ _misc_flags |= _misc_is_unsafe_anonymous;
} else {
- _misc_flags &= ~_misc_is_anonymous;
+ _misc_flags &= ~_misc_is_unsafe_anonymous;
}
}
// Oop that keeps the metadata for this class from being unloaded
// in places where the metadata is stored in other places, like nmethods
oop klass_holder() const {
- return is_anonymous() ? java_mirror() : class_loader();
+ return (is_unsafe_anonymous()) ? java_mirror() : class_loader();
}
bool is_contended() const {
@@ -780,8 +777,8 @@
}
bool supers_have_passed_fingerprint_checks();
- static bool should_store_fingerprint(bool is_anonymous);
- bool should_store_fingerprint() const { return should_store_fingerprint(is_anonymous()); }
+ static bool should_store_fingerprint(bool is_unsafe_anonymous);
+ bool should_store_fingerprint() const { return should_store_fingerprint(is_unsafe_anonymous()); }
bool has_stored_fingerprint() const;
uint64_t get_stored_fingerprint() const;
void store_fingerprint(uint64_t fingerprint);
@@ -1014,36 +1011,9 @@
#endif
// Access to the implementor of an interface.
- Klass* implementor() const
- {
- Klass** k = adr_implementor();
- if (k == NULL) {
- return NULL;
- } else {
- return *k;
- }
- }
-
- void set_implementor(Klass* k) {
- assert(is_interface(), "not interface");
- Klass** addr = adr_implementor();
- assert(addr != NULL, "null addr");
- if (addr != NULL) {
- *addr = k;
- }
- }
-
- int nof_implementors() const {
- Klass* k = implementor();
- if (k == NULL) {
- return 0;
- } else if (k != this) {
- return 1;
- } else {
- return 2;
- }
- }
-
+ Klass* implementor() const;
+ void set_implementor(Klass* k);
+ int nof_implementors() const;
void add_implementor(Klass* k); // k is a new class that implements this interface
void init_implementor(); // initialize
@@ -1090,20 +1060,20 @@
static int size(int vtable_length, int itable_length,
int nonstatic_oop_map_size,
- bool is_interface, bool is_anonymous, bool has_stored_fingerprint) {
+ bool is_interface, bool is_unsafe_anonymous, bool has_stored_fingerprint) {
return align_metadata_size(header_size() +
vtable_length +
itable_length +
nonstatic_oop_map_size +
(is_interface ? (int)sizeof(Klass*)/wordSize : 0) +
- (is_anonymous ? (int)sizeof(Klass*)/wordSize : 0) +
+ (is_unsafe_anonymous ? (int)sizeof(Klass*)/wordSize : 0) +
(has_stored_fingerprint ? (int)sizeof(uint64_t*)/wordSize : 0));
}
int size() const { return size(vtable_length(),
itable_length(),
nonstatic_oop_map_size(),
is_interface(),
- is_anonymous(),
+ is_unsafe_anonymous(),
has_stored_fingerprint());
}
#if INCLUDE_SERVICES
@@ -1134,8 +1104,8 @@
}
};
- InstanceKlass** adr_host_klass() const {
- if (is_anonymous()) {
+ InstanceKlass** adr_unsafe_anonymous_host() const {
+ if (is_unsafe_anonymous()) {
InstanceKlass** adr_impl = (InstanceKlass **)adr_implementor();
if (adr_impl != NULL) {
return adr_impl + 1;
@@ -1149,7 +1119,7 @@
address adr_fingerprint() const {
if (has_stored_fingerprint()) {
- InstanceKlass** adr_host = adr_host_klass();
+ InstanceKlass** adr_host = adr_unsafe_anonymous_host();
if (adr_host != NULL) {
return (address)(adr_host + 1);
}
--- a/src/hotspot/share/oops/instanceMirrorKlass.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/oops/instanceMirrorKlass.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -66,3 +66,9 @@
}
return 0;
}
+
+#if INCLUDE_CDS
+void InstanceMirrorKlass::serialize_offsets(SerializeClosure* f) {
+ f->do_u4((u4*)&_offset_of_static_fields);
+}
+#endif
--- a/src/hotspot/share/oops/instanceMirrorKlass.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/oops/instanceMirrorKlass.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -99,6 +99,8 @@
void oop_pc_update_pointers(oop obj, ParCompactionManager* cm);
#endif
+ static void serialize_offsets(class SerializeClosure* f) NOT_CDS_RETURN;
+
// Oop fields (and metadata) iterators
//
// The InstanceMirrorKlass iterators also visit the hidden Klass pointer.
--- a/src/hotspot/share/oops/instanceMirrorKlass.inline.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/oops/instanceMirrorKlass.inline.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -51,9 +51,10 @@
Klass* klass = java_lang_Class::as_Klass(obj);
// We'll get NULL for primitive mirrors.
if (klass != NULL) {
- if (klass->is_instance_klass() && InstanceKlass::cast(klass)->is_anonymous()) {
- // An anonymous class doesn't have its own class loader, so when handling
- // the java mirror for an anonymous class we need to make sure its class
+ if (klass->is_instance_klass() &&
+ InstanceKlass::cast(klass)->is_unsafe_anonymous()) {
+ // An unsafe anonymous class doesn't have its own class loader, so
+ // when handling the java mirror for the class we need to make sure its class
// loader data is claimed, this is done by calling do_cld explicitly.
// For non-anonymous classes the call to do_cld is made when the class
// loader itself is handled.
--- a/src/hotspot/share/oops/klass.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/oops/klass.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -571,6 +571,11 @@
return CompressedOops::decode(_archived_mirror);
}
+narrowOop Klass::archived_java_mirror_raw_narrow() {
+ assert(has_raw_archived_mirror(), "must have raw archived mirror");
+ return _archived_mirror;
+}
+
// No GC barrier
void Klass::set_archived_java_mirror_raw(oop m) {
assert(DumpSharedSpaces, "called only during runtime");
@@ -612,7 +617,7 @@
const char* Klass::external_name() const {
if (is_instance_klass()) {
const InstanceKlass* ik = static_cast<const InstanceKlass*>(this);
- if (ik->is_anonymous()) {
+ if (ik->is_unsafe_anonymous()) {
char addr_buf[20];
jio_snprintf(addr_buf, 20, "/" INTPTR_FORMAT, p2i(ik));
size_t addr_len = strlen(addr_buf);
--- a/src/hotspot/share/oops/klass.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/oops/klass.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -261,6 +261,7 @@
void set_java_mirror(Handle m);
oop archived_java_mirror_raw() NOT_CDS_JAVA_HEAP_RETURN_(NULL); // no GC barrier
+ narrowOop archived_java_mirror_raw_narrow() NOT_CDS_JAVA_HEAP_RETURN_(0); // no GC barrier
void set_archived_java_mirror_raw(oop m) NOT_CDS_JAVA_HEAP_RETURN; // no GC barrier
// Temporary mirror switch used by RedefineClasses
@@ -654,7 +655,7 @@
virtual void metaspace_pointers_do(MetaspaceClosure* iter);
virtual MetaspaceObj::Type type() const { return ClassType; }
- // Iff the class loader (or mirror for anonymous classes) is alive the
+ // Iff the class loader (or mirror for unsafe anonymous classes) is alive the
// Klass is considered alive. Has already been marked as unloading.
bool is_loader_alive() const { return !class_loader_data()->is_unloading(); }
--- a/src/hotspot/share/oops/symbol.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/oops/symbol.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -318,4 +318,4 @@
}
// SymbolTable prints this in its statistics
-NOT_PRODUCT(int Symbol::_total_count = 0;)
+NOT_PRODUCT(size_t Symbol::_total_count = 0;)
--- a/src/hotspot/share/oops/symbol.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/oops/symbol.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -256,7 +256,7 @@
// only for getting its vtable pointer.
Symbol() { }
- static int _total_count;
+ static size_t _total_count;
#endif
};
--- a/src/hotspot/share/opto/compile.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/opto/compile.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -2113,7 +2113,7 @@
// PhaseIdealLoop is expensive so we only try it once we are
// out of live nodes and we only try it again if the previous
// helped got the number of nodes down significantly
- PhaseIdealLoop ideal_loop( igvn, false, true );
+ PhaseIdealLoop ideal_loop(igvn, LoopOptsNone);
if (failing()) return;
low_live_nodes = live_nodes();
_major_progress = true;
@@ -2164,6 +2164,21 @@
}
+bool Compile::optimize_loops(int& loop_opts_cnt, PhaseIterGVN& igvn, LoopOptsMode mode) {
+ if(loop_opts_cnt > 0) {
+ debug_only( int cnt = 0; );
+ while(major_progress() && (loop_opts_cnt > 0)) {
+ TracePhase tp("idealLoop", &timers[_t_idealLoop]);
+ assert( cnt++ < 40, "infinite cycle in loop optimization" );
+ PhaseIdealLoop ideal_loop(igvn, mode);
+ loop_opts_cnt--;
+ if (failing()) return false;
+ if (major_progress()) print_method(PHASE_PHASEIDEALLOOP_ITERATIONS, 2);
+ }
+ }
+ return true;
+}
+
//------------------------------Optimize---------------------------------------
// Given a graph, optimize it.
void Compile::Optimize() {
@@ -2202,10 +2217,10 @@
igvn.optimize();
}
+ if (failing()) return;
+
print_method(PHASE_ITER_GVN1, 2);
- if (failing()) return;
-
inline_incrementally(igvn);
print_method(PHASE_INCREMENTAL_INLINE, 2);
@@ -2254,7 +2269,7 @@
if (has_loops()) {
// Cleanup graph (remove dead nodes).
TracePhase tp("idealLoop", &timers[_t_idealLoop]);
- PhaseIdealLoop ideal_loop( igvn, false, true );
+ PhaseIdealLoop ideal_loop(igvn, LoopOptsNone);
if (major_progress()) print_method(PHASE_PHASEIDEAL_BEFORE_EA, 2);
if (failing()) return;
}
@@ -2289,7 +2304,7 @@
if((loop_opts_cnt > 0) && (has_loops() || has_split_ifs())) {
{
TracePhase tp("idealLoop", &timers[_t_idealLoop]);
- PhaseIdealLoop ideal_loop( igvn, true );
+ PhaseIdealLoop ideal_loop(igvn, LoopOptsDefault);
loop_opts_cnt--;
if (major_progress()) print_method(PHASE_PHASEIDEALLOOP1, 2);
if (failing()) return;
@@ -2297,7 +2312,7 @@
// Loop opts pass if partial peeling occurred in previous pass
if(PartialPeelLoop && major_progress() && (loop_opts_cnt > 0)) {
TracePhase tp("idealLoop", &timers[_t_idealLoop]);
- PhaseIdealLoop ideal_loop( igvn, false );
+ PhaseIdealLoop ideal_loop(igvn, LoopOptsSkipSplitIf);
loop_opts_cnt--;
if (major_progress()) print_method(PHASE_PHASEIDEALLOOP2, 2);
if (failing()) return;
@@ -2305,7 +2320,7 @@
// Loop opts pass for loop-unrolling before CCP
if(major_progress() && (loop_opts_cnt > 0)) {
TracePhase tp("idealLoop", &timers[_t_idealLoop]);
- PhaseIdealLoop ideal_loop( igvn, false );
+ PhaseIdealLoop ideal_loop(igvn, LoopOptsSkipSplitIf);
loop_opts_cnt--;
if (major_progress()) print_method(PHASE_PHASEIDEALLOOP3, 2);
}
@@ -2341,16 +2356,8 @@
// Loop transforms on the ideal graph. Range Check Elimination,
// peeling, unrolling, etc.
- if(loop_opts_cnt > 0) {
- debug_only( int cnt = 0; );
- while(major_progress() && (loop_opts_cnt > 0)) {
- TracePhase tp("idealLoop", &timers[_t_idealLoop]);
- assert( cnt++ < 40, "infinite cycle in loop optimization" );
- PhaseIdealLoop ideal_loop( igvn, true);
- loop_opts_cnt--;
- if (major_progress()) print_method(PHASE_PHASEIDEALLOOP_ITERATIONS, 2);
- if (failing()) return;
- }
+ if (!optimize_loops(loop_opts_cnt, igvn, LoopOptsDefault)) {
+ return;
}
#if INCLUDE_ZGC
@@ -2767,6 +2774,17 @@
LoadNode::is_immutable_value(n->in(MemNode::Address))),
"raw memory operations should have control edge");
}
+ if (n->is_MemBar()) {
+ MemBarNode* mb = n->as_MemBar();
+ if (mb->trailing_store() || mb->trailing_load_store()) {
+ assert(mb->leading_membar()->trailing_membar() == mb, "bad membar pair");
+ Node* mem = mb->in(MemBarNode::Precedent);
+ assert((mb->trailing_store() && mem->is_Store() && mem->as_Store()->is_release()) ||
+ (mb->trailing_load_store() && mem->is_LoadStore()), "missing mem op");
+ } else if (mb->leading()) {
+ assert(mb->trailing_membar()->leading_membar() == mb, "bad membar pair");
+ }
+ }
#endif
// Count FPU ops and common calls, implements item (3)
switch( nop ) {
--- a/src/hotspot/share/opto/compile.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/opto/compile.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -90,6 +90,14 @@
class Node_Stack;
struct Final_Reshape_Counts;
+enum LoopOptsMode {
+ LoopOptsDefault,
+ LoopOptsNone,
+ LoopOptsSkipSplitIf,
+ LoopOptsVerify,
+ LoopOptsLastRound
+};
+
typedef unsigned int node_idx_t;
class NodeCloneInfo {
private:
@@ -1079,6 +1087,7 @@
void inline_incrementally(PhaseIterGVN& igvn);
void inline_string_calls(bool parse_time);
void inline_boxing_calls(PhaseIterGVN& igvn);
+ bool optimize_loops(int& loop_opts_cnt, PhaseIterGVN& igvn, LoopOptsMode mode);
// Matching, CFG layout, allocation, code generation
PhaseCFG* cfg() { return _cfg; }
--- a/src/hotspot/share/opto/doCall.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/opto/doCall.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -510,8 +510,8 @@
if (iter().cur_bc_raw() == Bytecodes::_invokespecial && !orig_callee->is_object_initializer()) {
ciInstanceKlass* calling_klass = method()->holder();
ciInstanceKlass* sender_klass =
- calling_klass->is_anonymous() ? calling_klass->host_klass() :
- calling_klass;
+ calling_klass->is_unsafe_anonymous() ? calling_klass->unsafe_anonymous_host() :
+ calling_klass;
if (sender_klass->is_interface()) {
receiver_constraint = sender_klass;
}
--- a/src/hotspot/share/opto/graphKit.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/opto/graphKit.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -1595,6 +1595,23 @@
}
}
+Node* GraphKit::access_load(Node* adr, // actual adress to load val at
+ const Type* val_type,
+ BasicType bt,
+ DecoratorSet decorators) {
+ if (stopped()) {
+ return top(); // Dead path ?
+ }
+
+ C2AccessValuePtr addr(adr, NULL);
+ C2Access access(this, decorators | C2_READ_ACCESS, bt, NULL, addr);
+ if (access.is_raw()) {
+ return _barrier_set->BarrierSetC2::load_at(access, val_type);
+ } else {
+ return _barrier_set->load_at(access, val_type);
+ }
+}
+
Node* GraphKit::access_atomic_cmpxchg_val_at(Node* ctl,
Node* obj,
Node* adr,
--- a/src/hotspot/share/opto/graphKit.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/opto/graphKit.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -582,12 +582,17 @@
DecoratorSet decorators);
Node* access_load_at(Node* obj, // containing obj
- Node* adr, // actual adress to store val at
+ Node* adr, // actual adress to load val at
const TypePtr* adr_type,
const Type* val_type,
BasicType bt,
DecoratorSet decorators);
+ Node* access_load(Node* adr, // actual adress to load val at
+ const Type* val_type,
+ BasicType bt,
+ DecoratorSet decorators);
+
Node* access_atomic_cmpxchg_val_at(Node* ctl,
Node* obj,
Node* adr,
--- a/src/hotspot/share/opto/ifnode.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/opto/ifnode.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -267,6 +267,13 @@
Node* predicate_c = NULL;
Node* predicate_x = NULL;
bool counted_loop = r->is_CountedLoop();
+ if (counted_loop) {
+ // Ignore counted loops for now because the split-if logic does not work
+ // in all the cases (for example, with strip mined loops). Also, above
+ // checks only pass for already degraded loops without a tripcount phi
+ // and these are essentially dead and will go away during igvn.
+ return NULL;
+ }
Node *region_c = new RegionNode(req_c + 1);
Node *phi_c = con1;
--- a/src/hotspot/share/opto/library_call.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/opto/library_call.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -1100,6 +1100,9 @@
Node* arg1 = argument(0);
Node* arg2 = argument(1);
+ arg1 = must_be_not_null(arg1, true);
+ arg2 = must_be_not_null(arg2, true);
+
// Get start addr and length of first argument
Node* arg1_start = array_element_address(arg1, intcon(0), T_BYTE);
Node* arg1_cnt = load_array_length(arg1);
@@ -1123,6 +1126,10 @@
Node* phi = new PhiNode(region, TypeInt::BOOL);
if (!stopped()) {
+
+ arg1 = must_be_not_null(arg1, true);
+ arg2 = must_be_not_null(arg2, true);
+
// Get start addr and length of first argument
Node* arg1_start = array_element_address(arg1, intcon(0), T_BYTE);
Node* arg1_cnt = load_array_length(arg1);
@@ -1182,6 +1189,8 @@
Node* offset = argument(1);
Node* len = argument(2);
+ ba = must_be_not_null(ba, true);
+
// Range checks
generate_string_range_check(ba, offset, len, false);
if (stopped()) {
@@ -1254,6 +1263,9 @@
RegionNode* result_rgn = new RegionNode(4);
Node* result_phi = new PhiNode(result_rgn, TypeInt::INT);
+ src = must_be_not_null(src, true);
+ tgt = must_be_not_null(tgt, true);
+
// Get start addr and length of source string
Node* src_start = array_element_address(src, intcon(0), T_BYTE);
Node* src_count = load_array_length(src);
@@ -1298,6 +1310,9 @@
Node* tgt_count = argument(3); // char count
Node* from_index = argument(4); // char index
+ src = must_be_not_null(src, true);
+ tgt = must_be_not_null(tgt, true);
+
// Multiply byte array index by 2 if String is UTF16 encoded
Node* src_offset = (ae == StrIntrinsicNode::LL) ? from_index : _gvn.transform(new LShiftINode(from_index, intcon(1)));
src_count = _gvn.transform(new SubINode(src_count, from_index));
@@ -1383,6 +1398,8 @@
Node* from_index = argument(2);
Node* max = argument(3);
+ src = must_be_not_null(src, true);
+
Node* src_offset = _gvn.transform(new LShiftINode(from_index, intcon(1)));
Node* src_start = array_element_address(src, src_offset, T_BYTE);
Node* src_count = _gvn.transform(new SubINode(max, from_index));
@@ -1453,6 +1470,9 @@
(!compress && src_elem == T_BYTE && (dst_elem == T_BYTE || dst_elem == T_CHAR)),
"Unsupported array types for inline_string_copy");
+ src = must_be_not_null(src, true);
+ dst = must_be_not_null(dst, true);
+
// Convert char[] offsets to byte[] offsets
bool convert_src = (compress && src_elem == T_BYTE);
bool convert_dst = (!compress && dst_elem == T_BYTE);
@@ -1709,6 +1729,8 @@
return false;
}
+ value = must_be_not_null(value, true);
+
Node* adr = array_element_address(value, index, T_CHAR);
if (adr->is_top()) {
return false;
@@ -1815,7 +1837,7 @@
set_result(_gvn.transform(new MulDNode(base, base)));
return true;
}
- return StubRoutines::dexp() != NULL ?
+ return StubRoutines::dpow() != NULL ?
runtime_math(OptoRuntime::Math_DD_D_Type(), StubRoutines::dpow(), "dpow") :
runtime_math(OptoRuntime::Math_DD_D_Type(), FN_PTR(SharedRuntime::dpow), "POW");
}
@@ -3006,7 +3028,7 @@
Node* p = basic_plus_adr(klass, in_bytes(Klass::java_mirror_offset()));
Node* load = make_load(NULL, p, TypeRawPtr::NOTNULL, T_ADDRESS, MemNode::unordered);
// mirror = ((OopHandle)mirror)->resolve();
- return make_load(NULL, load, TypeInstPtr::MIRROR, T_OBJECT, MemNode::unordered);
+ return access_load(load, TypeInstPtr::MIRROR, T_OBJECT, IN_NATIVE);
}
//-----------------------load_klass_from_mirror_common-------------------------
@@ -4866,6 +4888,9 @@
Node *dst_offset = argument(3);
Node *length = argument(4);
+ src = must_be_not_null(src, true);
+ dst = must_be_not_null(dst, true);
+
const Type* src_type = src->Value(&_gvn);
const Type* dst_type = dst->Value(&_gvn);
const TypeAryPtr* top_src = src_type->isa_aryptr();
@@ -4918,6 +4943,9 @@
Node* ylen = argument(3);
Node* z = argument(4);
+ x = must_be_not_null(x, true);
+ y = must_be_not_null(y, true);
+
const Type* x_type = x->Value(&_gvn);
const Type* y_type = y->Value(&_gvn);
const TypeAryPtr* top_x = x_type->isa_aryptr();
@@ -4963,7 +4991,12 @@
} __ else_(); {
// Update graphKit memory and control from IdealKit.
sync_kit(ideal);
- Node* zlen_arg = load_array_length(z);
+ Node *cast = new CastPPNode(z, TypePtr::NOTNULL);
+ cast->init_req(0, control());
+ _gvn.set_type(cast, cast->bottom_type());
+ C->record_for_igvn(cast);
+
+ Node* zlen_arg = load_array_length(cast);
// Update IdealKit memory and control from graphKit.
__ sync_kit(this);
__ if_then(zlen_arg, BoolTest::lt, zlen); {
@@ -5018,6 +5051,9 @@
Node* z = argument(2);
Node* zlen = argument(3);
+ x = must_be_not_null(x, true);
+ z = must_be_not_null(z, true);
+
const Type* x_type = x->Value(&_gvn);
const Type* z_type = z->Value(&_gvn);
const TypeAryPtr* top_x = x_type->isa_aryptr();
@@ -5065,6 +5101,8 @@
Node* len = argument(3);
Node* k = argument(4);
+ out = must_be_not_null(out, true);
+
const Type* out_type = out->Value(&_gvn);
const Type* in_type = in->Value(&_gvn);
const TypeAryPtr* top_out = out_type->isa_aryptr();
@@ -5317,6 +5355,7 @@
}
// 'src_start' points to src array + scaled offset
+ src = must_be_not_null(src, true);
Node* src_start = array_element_address(src, offset, src_elem);
// We assume that range check is done by caller.
@@ -5405,10 +5444,12 @@
}
// 'src_start' points to src array + scaled offset
+ src = must_be_not_null(src, true);
Node* src_start = array_element_address(src, offset, src_elem);
// static final int[] byteTable in class CRC32C
Node* table = get_table_from_crc32c_class(callee()->holder());
+ table = must_be_not_null(table, true);
Node* table_start = array_element_address(table, intcon(0), T_INT);
// We assume that range check is done by caller.
@@ -5452,6 +5493,7 @@
// static final int[] byteTable in class CRC32C
Node* table = get_table_from_crc32c_class(callee()->holder());
+ table = must_be_not_null(table, true);
Node* table_start = array_element_address(table, intcon(0), T_INT);
// Call the stub.
@@ -5695,6 +5737,9 @@
Node* dest = argument(3);
Node* dest_offset = argument(4);
+ src = must_be_not_null(src, true);
+ dest = must_be_not_null(dest, true);
+
// (1) src and dest are arrays.
const Type* src_type = src->Value(&_gvn);
const Type* dest_type = dest->Value(&_gvn);
@@ -5765,6 +5810,9 @@
Node* dest = argument(4);
Node* dest_offset = argument(5);
+ src = must_be_not_null(src, false);
+ dest = must_be_not_null(dest, false);
+
// (1) src and dest are arrays.
const Type* src_type = src->Value(&_gvn);
const Type* dest_type = dest->Value(&_gvn);
@@ -5970,6 +6018,9 @@
// The receiver was checked for NULL already.
Node* objCBC = argument(0);
+ Node* src = argument(1);
+ Node* dest = argument(4);
+
// Load embeddedCipher field of CipherBlockChaining object.
Node* embeddedCipherObj = load_field_from_object(objCBC, "embeddedCipher", "Lcom/sun/crypto/provider/SymmetricCipher;", /*is_exact*/ false);
@@ -5988,6 +6039,10 @@
set_control(top()); // no regular fast path
return ctrl;
}
+
+ src = must_be_not_null(src, true);
+ dest = must_be_not_null(dest, true);
+
ciInstanceKlass* instklass_AESCrypt = klass_AESCrypt->as_instance_klass();
Node* instof = gen_instanceof(embeddedCipherObj, makecon(TypeKlassPtr::make(instklass_AESCrypt)));
@@ -6005,8 +6060,7 @@
// see the original java code for why.
RegionNode* region = new RegionNode(3);
region->init_req(1, instof_false);
- Node* src = argument(1);
- Node* dest = argument(4);
+
Node* cmp_src_dest = _gvn.transform(new CmpPNode(src, dest));
Node* bool_src_dest = _gvn.transform(new BoolNode(cmp_src_dest, BoolTest::eq));
Node* src_dest_conjoint = generate_guard(bool_src_dest, NULL, PROB_MIN);
@@ -6073,6 +6127,10 @@
Node* state = argument(3);
Node* subkeyH = argument(4);
+ state = must_be_not_null(state, true);
+ subkeyH = must_be_not_null(subkeyH, true);
+ data = must_be_not_null(data, true);
+
Node* state_start = array_element_address(state, intcon(0), T_LONG);
assert(state_start, "state is NULL");
Node* subkeyH_start = array_element_address(subkeyH, intcon(0), T_LONG);
@@ -6146,6 +6204,7 @@
return false;
}
// 'src_start' points to src array + offset
+ src = must_be_not_null(src, true);
Node* src_start = array_element_address(src, ofs, src_elem);
Node* state = NULL;
address stubAddr;
@@ -6212,6 +6271,7 @@
return false;
}
// 'src_start' points to src array + offset
+ src = must_be_not_null(src, false);
Node* src_start = array_element_address(src, ofs, src_elem);
const char* klass_SHA_name = NULL;
--- a/src/hotspot/share/opto/loopnode.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/opto/loopnode.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -2662,7 +2662,10 @@
//----------------------------build_and_optimize-------------------------------
// Create a PhaseLoop. Build the ideal Loop tree. Map each Ideal Node to
// its corresponding LoopNode. If 'optimize' is true, do some loop cleanups.
-void PhaseIdealLoop::build_and_optimize(bool do_split_ifs, bool skip_loop_opts, bool last_round) {
+void PhaseIdealLoop::build_and_optimize(LoopOptsMode mode) {
+ bool do_split_ifs = (mode == LoopOptsDefault || mode == LoopOptsLastRound);
+ bool skip_loop_opts = (mode == LoopOptsNone);
+
ResourceMark rm;
int old_progress = C->major_progress();
@@ -2904,9 +2907,9 @@
// that require basic-block info (like cloning through Phi's)
if( SplitIfBlocks && do_split_ifs ) {
visited.Clear();
- split_if_with_blocks( visited, nstack, last_round );
+ split_if_with_blocks( visited, nstack, mode == LoopOptsLastRound );
NOT_PRODUCT( if( VerifyLoopOptimizations ) verify(); );
- if (last_round) {
+ if (mode == LoopOptsLastRound) {
C->set_major_progress();
}
}
--- a/src/hotspot/share/opto/loopnode.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/opto/loopnode.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -922,11 +922,11 @@
_verify_me(NULL),
_verify_only(true),
_dom_lca_tags(arena()) { // Thread::resource_area
- build_and_optimize(false, false);
+ build_and_optimize(LoopOptsVerify);
}
// build the loop tree and perform any requested optimizations
- void build_and_optimize(bool do_split_if, bool skip_loop_opts, bool last_round = false);
+ void build_and_optimize(LoopOptsMode mode);
// Dominators for the sea of nodes
void Dominators();
@@ -936,23 +936,23 @@
Node *dom_lca_internal( Node *n1, Node *n2 ) const;
// Compute the Ideal Node to Loop mapping
- PhaseIdealLoop( PhaseIterGVN &igvn, bool do_split_ifs, bool skip_loop_opts = false, bool last_round = false) :
+ PhaseIdealLoop(PhaseIterGVN &igvn, LoopOptsMode mode) :
PhaseTransform(Ideal_Loop),
_igvn(igvn),
_verify_me(NULL),
_verify_only(false),
_dom_lca_tags(arena()) { // Thread::resource_area
- build_and_optimize(do_split_ifs, skip_loop_opts, last_round);
+ build_and_optimize(mode);
}
// Verify that verify_me made the same decisions as a fresh run.
- PhaseIdealLoop( PhaseIterGVN &igvn, const PhaseIdealLoop *verify_me) :
+ PhaseIdealLoop(PhaseIterGVN &igvn, const PhaseIdealLoop *verify_me) :
PhaseTransform(Ideal_Loop),
_igvn(igvn),
_verify_me(verify_me),
_verify_only(false),
_dom_lca_tags(arena()) { // Thread::resource_area
- build_and_optimize(false, false);
+ build_and_optimize(LoopOptsVerify);
}
// Build and verify the loop tree without modifying the graph. This
--- a/src/hotspot/share/opto/memnode.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/opto/memnode.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -25,6 +25,8 @@
#include "precompiled.hpp"
#include "classfile/systemDictionary.hpp"
#include "compiler/compileLog.hpp"
+#include "gc/shared/barrierSet.hpp"
+#include "gc/shared/c2/barrierSetC2.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/resourceArea.hpp"
#include "oops/objArrayKlass.hpp"
@@ -2209,6 +2211,12 @@
const TypeOopPtr* toop = phase->type(adr)->isa_oopptr();
if (toop == NULL) return this;
+ // Step over potential GC barrier for OopHandle resolve
+ BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();
+ if (bs->is_gc_barrier_node(base)) {
+ base = bs->step_over_gc_barrier(base);
+ }
+
// We can fetch the klass directly through an AllocateNode.
// This works even if the klass is not constant (clone or newArray).
if (offset == oopDesc::klass_offset_in_bytes()) {
@@ -2226,10 +2234,6 @@
// mirror go completely dead. (Current exception: Class
// mirrors may appear in debug info, but we could clean them out by
// introducing a new debug info operator for Klass.java_mirror).
- //
- // If the code pattern requires a barrier for
- // mirror = ((OopHandle)mirror)->resolve();
- // this won't match.
if (toop->isa_instptr() && toop->klass() == phase->C->env()->Class_klass()
&& offset == java_lang_Class::klass_offset_in_bytes()) {
@@ -2521,45 +2525,63 @@
Node* adr = in(MemNode::Address);
Node* val = in(MemNode::ValueIn);
+ Node* result = this;
+
// Load then Store? Then the Store is useless
if (val->is_Load() &&
val->in(MemNode::Address)->eqv_uncast(adr) &&
val->in(MemNode::Memory )->eqv_uncast(mem) &&
val->as_Load()->store_Opcode() == Opcode()) {
- return mem;
+ result = mem;
}
// Two stores in a row of the same value?
- if (mem->is_Store() &&
+ if (result == this &&
+ mem->is_Store() &&
mem->in(MemNode::Address)->eqv_uncast(adr) &&
mem->in(MemNode::ValueIn)->eqv_uncast(val) &&
mem->Opcode() == Opcode()) {
- return mem;
+ result = mem;
}
// Store of zero anywhere into a freshly-allocated object?
// Then the store is useless.
// (It must already have been captured by the InitializeNode.)
- if (ReduceFieldZeroing && phase->type(val)->is_zero_type()) {
+ if (result == this &&
+ ReduceFieldZeroing && phase->type(val)->is_zero_type()) {
// a newly allocated object is already all-zeroes everywhere
if (mem->is_Proj() && mem->in(0)->is_Allocate()) {
- return mem;
+ result = mem;
}
- // the store may also apply to zero-bits in an earlier object
- Node* prev_mem = find_previous_store(phase);
- // Steps (a), (b): Walk past independent stores to find an exact match.
- if (prev_mem != NULL) {
- Node* prev_val = can_see_stored_value(prev_mem, phase);
- if (prev_val != NULL && phase->eqv(prev_val, val)) {
- // prev_val and val might differ by a cast; it would be good
- // to keep the more informative of the two.
- return mem;
+ if (result == this) {
+ // the store may also apply to zero-bits in an earlier object
+ Node* prev_mem = find_previous_store(phase);
+ // Steps (a), (b): Walk past independent stores to find an exact match.
+ if (prev_mem != NULL) {
+ Node* prev_val = can_see_stored_value(prev_mem, phase);
+ if (prev_val != NULL && phase->eqv(prev_val, val)) {
+ // prev_val and val might differ by a cast; it would be good
+ // to keep the more informative of the two.
+ result = mem;
+ }
}
}
}
- return this;
+ if (result != this && phase->is_IterGVN() != NULL) {
+ MemBarNode* trailing = trailing_membar();
+ if (trailing != NULL) {
+#ifdef ASSERT
+ const TypeOopPtr* t_oop = phase->type(in(Address))->isa_oopptr();
+ assert(t_oop == NULL || t_oop->is_known_instance_field(), "only for non escaping objects");
+#endif
+ PhaseIterGVN* igvn = phase->is_IterGVN();
+ trailing->remove(igvn);
+ }
+ }
+
+ return result;
}
//------------------------------match_edge-------------------------------------
@@ -2637,6 +2659,33 @@
return true;
}
+MemBarNode* StoreNode::trailing_membar() const {
+ if (is_release()) {
+ MemBarNode* trailing_mb = NULL;
+ for (DUIterator_Fast imax, i = fast_outs(imax); i < imax; i++) {
+ Node* u = fast_out(i);
+ if (u->is_MemBar()) {
+ if (u->as_MemBar()->trailing_store()) {
+ assert(u->Opcode() == Op_MemBarVolatile, "");
+ assert(trailing_mb == NULL, "only one");
+ trailing_mb = u->as_MemBar();
+#ifdef ASSERT
+ Node* leading = u->as_MemBar()->leading_membar();
+ assert(leading->Opcode() == Op_MemBarRelease, "incorrect membar");
+ assert(leading->as_MemBar()->leading_store(), "incorrect membar pair");
+ assert(leading->as_MemBar()->trailing_membar() == u, "incorrect membar pair");
+#endif
+ } else {
+ assert(u->as_MemBar()->standalone(), "");
+ }
+ }
+ }
+ return trailing_mb;
+ }
+ return NULL;
+}
+
+
//=============================================================================
//------------------------------Ideal------------------------------------------
// If the store is from an AND mask that leaves the low bits untouched, then
@@ -2749,6 +2798,30 @@
return true;
}
+MemBarNode* LoadStoreNode::trailing_membar() const {
+ MemBarNode* trailing = NULL;
+ for (DUIterator_Fast imax, i = fast_outs(imax); i < imax; i++) {
+ Node* u = fast_out(i);
+ if (u->is_MemBar()) {
+ if (u->as_MemBar()->trailing_load_store()) {
+ assert(u->Opcode() == Op_MemBarAcquire, "");
+ assert(trailing == NULL, "only one");
+ trailing = u->as_MemBar();
+#ifdef ASSERT
+ Node* leading = trailing->leading_membar();
+ assert(support_IRIW_for_not_multiple_copy_atomic_cpu || leading->Opcode() == Op_MemBarRelease, "incorrect membar");
+ assert(leading->as_MemBar()->leading_load_store(), "incorrect membar pair");
+ assert(leading->as_MemBar()->trailing_membar() == trailing, "incorrect membar pair");
+#endif
+ } else {
+ assert(u->as_MemBar()->standalone(), "wrong barrier kind");
+ }
+ }
+ }
+
+ return trailing;
+}
+
uint LoadStoreNode::size_of() const { return sizeof(*this); }
//=============================================================================
@@ -2934,7 +3007,10 @@
//=============================================================================
MemBarNode::MemBarNode(Compile* C, int alias_idx, Node* precedent)
: MultiNode(TypeFunc::Parms + (precedent == NULL? 0: 1)),
- _adr_type(C->get_adr_type(alias_idx))
+ _adr_type(C->get_adr_type(alias_idx)), _kind(Standalone)
+#ifdef ASSERT
+ , _pair_idx(0)
+#endif
{
init_class_id(Class_MemBar);
Node* top = C->top();
@@ -2969,6 +3045,21 @@
}
}
+void MemBarNode::remove(PhaseIterGVN *igvn) {
+ if (outcnt() != 2) {
+ return;
+ }
+ if (trailing_store() || trailing_load_store()) {
+ MemBarNode* leading = leading_membar();
+ if (leading != NULL) {
+ assert(leading->trailing_membar() == this, "inconsistent leading/trailing membars");
+ leading->remove(igvn);
+ }
+ }
+ igvn->replace_node(proj_out(TypeFunc::Memory), in(TypeFunc::Memory));
+ igvn->replace_node(proj_out(TypeFunc::Control), in(TypeFunc::Control));
+}
+
//------------------------------Ideal------------------------------------------
// Return a node which is more "ideal" than the current node. Strip out
// control copies
@@ -3035,8 +3126,7 @@
if (eliminate) {
// Replace MemBar projections by its inputs.
PhaseIterGVN* igvn = phase->is_IterGVN();
- igvn->replace_node(proj_out(TypeFunc::Memory), in(TypeFunc::Memory));
- igvn->replace_node(proj_out(TypeFunc::Control), in(TypeFunc::Control));
+ remove(igvn);
// Must return either the original node (now dead) or a new node
// (Do not return a top here, since that would break the uniqueness of top.)
return new ConINode(TypeInt::ZERO);
@@ -3065,6 +3155,98 @@
return NULL;
}
+void MemBarNode::set_store_pair(MemBarNode* leading, MemBarNode* trailing) {
+ trailing->_kind = TrailingStore;
+ leading->_kind = LeadingStore;
+#ifdef ASSERT
+ trailing->_pair_idx = leading->_idx;
+ leading->_pair_idx = leading->_idx;
+#endif
+}
+
+void MemBarNode::set_load_store_pair(MemBarNode* leading, MemBarNode* trailing) {
+ trailing->_kind = TrailingLoadStore;
+ leading->_kind = LeadingLoadStore;
+#ifdef ASSERT
+ trailing->_pair_idx = leading->_idx;
+ leading->_pair_idx = leading->_idx;
+#endif
+}
+
+MemBarNode* MemBarNode::trailing_membar() const {
+ Node* trailing = (Node*)this;
+ VectorSet seen(Thread::current()->resource_area());
+ while (!trailing->is_MemBar() || !trailing->as_MemBar()->trailing()) {
+ if (seen.test_set(trailing->_idx)) {
+ // Dying subgraph?
+ return NULL;
+ }
+ for (DUIterator_Fast jmax, j = trailing->fast_outs(jmax); j < jmax; j++) {
+ Node* next = trailing->fast_out(j);
+ if (next != trailing && next->is_CFG()) {
+ trailing = next;
+ break;
+ }
+ }
+ }
+ MemBarNode* mb = trailing->as_MemBar();
+ assert((mb->_kind == TrailingStore && _kind == LeadingStore) ||
+ (mb->_kind == TrailingLoadStore && _kind == LeadingLoadStore), "bad trailing membar");
+ assert(mb->_pair_idx == _pair_idx, "bad trailing membar");
+ return mb;
+}
+
+MemBarNode* MemBarNode::leading_membar() const {
+ VectorSet seen(Thread::current()->resource_area());
+ Node* leading = in(0);
+ while (leading != NULL && (!leading->is_MemBar() || !leading->as_MemBar()->leading())) {
+ if (seen.test_set(leading->_idx)) {
+ // Dying subgraph?
+ return NULL;
+ }
+ if (leading->is_Region()) {
+ leading = leading->in(1);
+ } else {
+ leading = leading->in(0);
+ }
+ }
+#ifdef ASSERT
+ Unique_Node_List wq;
+ wq.push((Node*)this);
+ uint found = 0;
+ for (uint i = 0; i < wq.size(); i++) {
+ Node* n = wq.at(i);
+ if (n->is_Region()) {
+ for (uint j = 1; j < n->req(); j++) {
+ Node* in = n->in(j);
+ if (in != NULL && !in->is_top()) {
+ wq.push(in);
+ }
+ }
+ } else {
+ if (n->is_MemBar() && n->as_MemBar()->leading()) {
+ assert(n == leading, "consistency check failed");
+ found++;
+ } else {
+ Node* in = n->in(0);
+ if (in != NULL && !in->is_top()) {
+ wq.push(in);
+ }
+ }
+ }
+ }
+ assert(found == 1 || (found == 0 && leading == NULL), "consistency check failed");
+#endif
+ if (leading == NULL) {
+ return NULL;
+ }
+ MemBarNode* mb = leading->as_MemBar();
+ assert((mb->_kind == LeadingStore && _kind == TrailingStore) ||
+ (mb->_kind == LeadingLoadStore && _kind == TrailingLoadStore), "bad leading membar");
+ assert(mb->_pair_idx == _pair_idx, "bad leading membar");
+ return mb;
+}
+
//===========================InitializeNode====================================
// SUMMARY:
// This node acts as a memory barrier on raw memory, after some raw stores.
--- a/src/hotspot/share/opto/memnode.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/opto/memnode.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -607,6 +607,8 @@
// have all possible loads of the value stored been optimized away?
bool value_never_loaded(PhaseTransform *phase) const;
+
+ MemBarNode* trailing_membar() const;
};
//------------------------------StoreBNode-------------------------------------
@@ -816,6 +818,7 @@
virtual const class TypePtr *adr_type() const { return _adr_type; } // returns bottom_type of address
bool result_not_used() const;
+ MemBarNode* trailing_membar() const;
};
class LoadStoreConditionalNode : public LoadStoreNode {
@@ -1142,6 +1145,20 @@
// Memory type this node is serializing. Usually either rawptr or bottom.
const TypePtr* _adr_type;
+ // How is this membar related to a nearby memory access?
+ enum {
+ Standalone,
+ TrailingLoad,
+ TrailingStore,
+ LeadingStore,
+ TrailingLoadStore,
+ LeadingLoadStore
+ } _kind;
+
+#ifdef ASSERT
+ uint _pair_idx;
+#endif
+
public:
enum {
Precedent = TypeFunc::Parms // optional edge to force precedence
@@ -1159,6 +1176,24 @@
static MemBarNode* make(Compile* C, int opcode,
int alias_idx = Compile::AliasIdxBot,
Node* precedent = NULL);
+
+ MemBarNode* trailing_membar() const;
+ MemBarNode* leading_membar() const;
+
+ void set_trailing_load() { _kind = TrailingLoad; }
+ bool trailing_load() const { return _kind == TrailingLoad; }
+ bool trailing_store() const { return _kind == TrailingStore; }
+ bool leading_store() const { return _kind == LeadingStore; }
+ bool trailing_load_store() const { return _kind == TrailingLoadStore; }
+ bool leading_load_store() const { return _kind == LeadingLoadStore; }
+ bool trailing() const { return _kind == TrailingLoad || _kind == TrailingStore || _kind == TrailingLoadStore; }
+ bool leading() const { return _kind == LeadingStore || _kind == LeadingLoadStore; }
+ bool standalone() const { return _kind == Standalone; }
+
+ static void set_store_pair(MemBarNode* leading, MemBarNode* trailing);
+ static void set_load_store_pair(MemBarNode* leading, MemBarNode* trailing);
+
+ void remove(PhaseIterGVN *igvn);
};
// "Acquire" - no following ref can move before (but earlier refs can
--- a/src/hotspot/share/opto/phaseX.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/opto/phaseX.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -1639,14 +1639,24 @@
}
// Loading the java mirror from a Klass requires two loads and the type
// of the mirror load depends on the type of 'n'. See LoadNode::Value().
- // If the code pattern requires a barrier for
- // mirror = ((OopHandle)mirror)->resolve();
- // this won't match.
+ // LoadBarrier?(LoadP(LoadP(AddP(foo:Klass, #java_mirror))))
+ BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();
+ bool has_load_barriers = bs->has_load_barriers();
+
if (use_op == Op_LoadP && use->bottom_type()->isa_rawptr()) {
for (DUIterator_Fast i2max, i2 = use->fast_outs(i2max); i2 < i2max; i2++) {
Node* u = use->fast_out(i2);
const Type* ut = u->bottom_type();
if (u->Opcode() == Op_LoadP && ut->isa_instptr()) {
+ if (has_load_barriers) {
+ // Search for load barriers behind the load
+ for (DUIterator_Fast i3max, i3 = u->fast_outs(i3max); i3 < i3max; i3++) {
+ Node* b = u->fast_out(i3);
+ if (bs->is_gc_barrier_node(b)) {
+ _worklist.push(b);
+ }
+ }
+ }
_worklist.push(u);
}
}
@@ -1788,14 +1798,23 @@
}
// Loading the java mirror from a Klass requires two loads and the type
// of the mirror load depends on the type of 'n'. See LoadNode::Value().
- // If the code pattern requires a barrier for
- // mirror = ((OopHandle)mirror)->resolve();
- // this won't match.
+ BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();
+ bool has_load_barriers = bs->has_load_barriers();
+
if (m_op == Op_LoadP && m->bottom_type()->isa_rawptr()) {
for (DUIterator_Fast i2max, i2 = m->fast_outs(i2max); i2 < i2max; i2++) {
Node* u = m->fast_out(i2);
const Type* ut = u->bottom_type();
if (u->Opcode() == Op_LoadP && ut->isa_instptr() && ut != type(u)) {
+ if (has_load_barriers) {
+ // Search for load barriers behind the load
+ for (DUIterator_Fast i3max, i3 = u->fast_outs(i3max); i3 < i3max; i3++) {
+ Node* b = u->fast_out(i3);
+ if (bs->is_gc_barrier_node(b)) {
+ _worklist.push(b);
+ }
+ }
+ }
worklist.push(u);
}
}
--- a/src/hotspot/share/opto/subnode.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/opto/subnode.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -24,6 +24,8 @@
#include "precompiled.hpp"
#include "compiler/compileLog.hpp"
+#include "gc/shared/barrierSet.hpp"
+#include "gc/shared/c2/barrierSetC2.hpp"
#include "memory/allocation.inline.hpp"
#include "opto/addnode.hpp"
#include "opto/callnode.hpp"
@@ -878,8 +880,13 @@
static inline Node* isa_java_mirror_load(PhaseGVN* phase, Node* n) {
// Return the klass node for (indirect load from OopHandle)
- // LoadP(LoadP(AddP(foo:Klass, #java_mirror)))
+ // LoadBarrier?(LoadP(LoadP(AddP(foo:Klass, #java_mirror))))
// or NULL if not matching.
+ BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();
+ if (bs->is_gc_barrier_node(n)) {
+ n = bs->step_over_gc_barrier(n);
+ }
+
if (n->Opcode() != Op_LoadP) return NULL;
const TypeInstPtr* tp = phase->type(n)->isa_instptr();
--- a/src/hotspot/share/precompiled/precompiled.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/precompiled/precompiled.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -101,8 +101,10 @@
# include "gc/shared/generationCounters.hpp"
# include "gc/shared/jvmFlagConstraintsGC.hpp"
# include "gc/shared/modRefBarrierSet.hpp"
+# include "gc/shared/ptrQueue.hpp"
# include "gc/shared/referencePolicy.hpp"
# include "gc/shared/referenceProcessor.hpp"
+# include "gc/shared/satbMarkQueue.hpp"
# include "gc/shared/space.hpp"
# include "gc/shared/spaceDecorator.hpp"
# include "gc/shared/taskqueue.hpp"
@@ -309,8 +311,6 @@
# include "gc/g1/g1OopClosures.hpp"
# include "gc/g1/g1_globals.hpp"
# include "gc/g1/jvmFlagConstraintsG1.hpp"
-# include "gc/g1/ptrQueue.hpp"
-# include "gc/g1/satbMarkQueue.hpp"
#endif // INCLUDE_G1GC
#if INCLUDE_PARALLELGC
# include "gc/parallel/gcAdaptivePolicyCounters.hpp"
--- a/src/hotspot/share/prims/cdsoffsets.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/prims/cdsoffsets.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -42,17 +42,17 @@
#define ADD_NEXT(list, name, value) \
list->add_end(new CDSOffsets(name, value, NULL))
-#define CREATE_OFFSET_MAPS \
- _all = new CDSOffsets("size_t_size", sizeof(size_t), NULL); \
- ADD_NEXT(_all, "FileMapHeader::_magic", offset_of(FileMapInfo::FileMapHeader, _magic)); \
- ADD_NEXT(_all, "FileMapHeader::_crc", offset_of(FileMapInfo::FileMapHeader, _crc)); \
- ADD_NEXT(_all, "FileMapHeader::_version", offset_of(FileMapInfo::FileMapHeader, _version)); \
- ADD_NEXT(_all, "FileMapHeader::_space[0]", offset_of(FileMapInfo::FileMapHeader, _space)); \
- ADD_NEXT(_all, "space_info::_crc", offset_of(FileMapInfo::FileMapHeader::space_info, _crc)); \
- ADD_NEXT(_all, "space_info::_used", offset_of(FileMapInfo::FileMapHeader::space_info, _used)); \
- ADD_NEXT(_all, "FileMapHeader::_paths_misc_info_size", offset_of(FileMapInfo::FileMapHeader, _paths_misc_info_size)); \
- ADD_NEXT(_all, "file_header_size", sizeof(FileMapInfo::FileMapHeader)); \
- ADD_NEXT(_all, "space_info_size", sizeof(FileMapInfo::FileMapHeader::space_info));
+#define CREATE_OFFSET_MAPS \
+ _all = new CDSOffsets("size_t_size", sizeof(size_t), NULL); \
+ ADD_NEXT(_all, "FileMapHeader::_magic", offset_of(FileMapHeader, _magic)); \
+ ADD_NEXT(_all, "FileMapHeader::_crc", offset_of(FileMapHeader, _crc)); \
+ ADD_NEXT(_all, "FileMapHeader::_version", offset_of(FileMapHeader, _version)); \
+ ADD_NEXT(_all, "FileMapHeader::_space[0]", offset_of(FileMapHeader, _space)); \
+ ADD_NEXT(_all, "CDSFileMapRegion::_crc", offset_of(CDSFileMapRegion, _crc)); \
+ ADD_NEXT(_all, "CDSFileMapRegion::_used", offset_of(CDSFileMapRegion, _used)); \
+ ADD_NEXT(_all, "FileMapHeader::_paths_misc_info_size", offset_of(FileMapHeader, _paths_misc_info_size)); \
+ ADD_NEXT(_all, "file_header_size", sizeof(FileMapHeader)); \
+ ADD_NEXT(_all, "CDSFileMapRegion_size", sizeof(CDSFileMapRegion));
int CDSOffsets::find_offset(const char* name) {
if (_all == NULL) {
--- a/src/hotspot/share/prims/jni.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/prims/jni.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -66,7 +66,7 @@
#include "prims/jvmtiThreadState.hpp"
#include "runtime/atomic.hpp"
#include "runtime/compilationPolicy.hpp"
-#include "runtime/fieldDescriptor.hpp"
+#include "runtime/fieldDescriptor.inline.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/interfaceSupport.inline.hpp"
#include "runtime/java.hpp"
--- a/src/hotspot/share/prims/jniCheck.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/prims/jniCheck.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -35,7 +35,7 @@
#include "oops/symbol.hpp"
#include "prims/jniCheck.hpp"
#include "prims/jvm_misc.hpp"
-#include "runtime/fieldDescriptor.hpp"
+#include "runtime/fieldDescriptor.inline.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/interfaceSupport.inline.hpp"
#include "runtime/jfieldIDWorkaround.hpp"
--- a/src/hotspot/share/prims/jvmtiEnter.xsl Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/prims/jvmtiEnter.xsl Thu Aug 23 11:09:16 2018 -0400
@@ -45,6 +45,7 @@
# include "prims/jvmtiEnter.inline.hpp"
# include "prims/jvmtiRawMonitor.hpp"
# include "prims/jvmtiUtil.hpp"
+# include "runtime/fieldDescriptor.inline.hpp"
# include "runtime/threadSMR.hpp"
</xsl:text>
--- a/src/hotspot/share/prims/jvmtiEnv.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/prims/jvmtiEnv.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -55,6 +55,7 @@
#include "prims/jvmtiUtil.hpp"
#include "runtime/arguments.hpp"
#include "runtime/deoptimization.hpp"
+#include "runtime/fieldDescriptor.inline.hpp"
#include "runtime/interfaceSupport.inline.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/jfieldIDWorkaround.hpp"
--- a/src/hotspot/share/prims/jvmtiExport.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/prims/jvmtiExport.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -47,6 +47,7 @@
#include "prims/jvmtiTagMap.hpp"
#include "prims/jvmtiThreadState.inline.hpp"
#include "runtime/arguments.hpp"
+#include "runtime/fieldDescriptor.inline.hpp"
#include "runtime/handles.hpp"
#include "runtime/interfaceSupport.inline.hpp"
#include "runtime/javaCalls.hpp"
--- a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -136,7 +136,7 @@
}
oop mirror = JNIHandles::resolve_non_null(_class_defs[i].klass);
- // classes for primitives and arrays and vm anonymous classes cannot be redefined
+ // classes for primitives and arrays and vm unsafe anonymous classes cannot be redefined
// check here so following code can assume these classes are InstanceKlass
if (!is_modifiable_class(mirror)) {
_res = JVMTI_ERROR_UNMODIFIABLE_CLASS;
@@ -278,8 +278,8 @@
return false;
}
- // Cannot redefine or retransform an anonymous class.
- if (InstanceKlass::cast(k)->is_anonymous()) {
+ // Cannot redefine or retransform an unsafe anonymous class.
+ if (InstanceKlass::cast(k)->is_unsafe_anonymous()) {
return false;
}
return true;
@@ -2650,7 +2650,7 @@
case 0x10:
// kind: type in extends clause of class or interface declaration
- // (including the direct superclass of an anonymous class declaration),
+ // (including the direct superclass of an unsafe anonymous class declaration),
// or in implements clause of interface declaration
// location: ClassFile
--- a/src/hotspot/share/prims/jvmtiTagMap.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/prims/jvmtiTagMap.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -3009,7 +3009,8 @@
// Preloaded classes and loader from the system dictionary
blk.set_kind(JVMTI_HEAP_REFERENCE_SYSTEM_CLASS);
SystemDictionary::oops_do(&blk);
- ClassLoaderDataGraph::always_strong_oops_do(&blk, false);
+ CLDToOopClosure cld_closure(&blk, false);
+ ClassLoaderDataGraph::always_strong_cld_do(&cld_closure);
if (blk.stopped()) {
return false;
}
--- a/src/hotspot/share/prims/methodHandles.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/prims/methodHandles.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -39,6 +39,7 @@
#include "oops/typeArrayOop.inline.hpp"
#include "prims/methodHandles.hpp"
#include "runtime/compilationPolicy.hpp"
+#include "runtime/fieldDescriptor.inline.hpp"
#include "runtime/interfaceSupport.inline.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/jniHandles.inline.hpp"
--- a/src/hotspot/share/prims/resolvedMethodTable.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/prims/resolvedMethodTable.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -57,6 +57,7 @@
: Hashtable<ClassLoaderWeakHandle, mtClass>(_table_size, sizeof(ResolvedMethodEntry)) { }
oop ResolvedMethodTable::lookup(int index, unsigned int hash, Method* method) {
+ assert_locked_or_safepoint(ResolvedMethodTable_lock);
for (ResolvedMethodEntry* p = bucket(index); p != NULL; p = p->next()) {
if (p->hash() == hash) {
@@ -114,6 +115,7 @@
ResolvedMethodTable* ResolvedMethodTable::_the_table = NULL;
oop ResolvedMethodTable::find_method(Method* method) {
+ MutexLocker ml(ResolvedMethodTable_lock);
oop entry = _the_table->lookup(method);
return entry;
}
@@ -144,9 +146,19 @@
int ResolvedMethodTable::_oops_removed = 0;
int ResolvedMethodTable::_oops_counted = 0;
+// There are no dead entries at start
+bool ResolvedMethodTable::_dead_entries = false;
+
+void ResolvedMethodTable::trigger_cleanup() {
+ MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
+ _dead_entries = true;
+ Service_lock->notify_all();
+}
+
// Serially invoke removed unused oops from the table.
-// This is done late during GC.
+// This is done by the ServiceThread after being notified on class unloading
void ResolvedMethodTable::unlink() {
+ MutexLocker ml(ResolvedMethodTable_lock);
_oops_removed = 0;
_oops_counted = 0;
for (int i = 0; i < _the_table->table_size(); ++i) {
@@ -173,10 +185,12 @@
}
log_debug(membername, table) ("ResolvedMethod entries counted %d removed %d",
_oops_counted, _oops_removed);
+ _dead_entries = false;
}
#ifndef PRODUCT
void ResolvedMethodTable::print() {
+ MutexLocker ml(ResolvedMethodTable_lock);
for (int i = 0; i < table_size(); ++i) {
ResolvedMethodEntry* entry = bucket(i);
while (entry != NULL) {
--- a/src/hotspot/share/prims/resolvedMethodTable.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/prims/resolvedMethodTable.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -59,6 +59,8 @@
static int _oops_removed;
static int _oops_counted;
+ static bool _dead_entries;
+
static ResolvedMethodTable* _the_table;
private:
ResolvedMethodEntry* bucket(int i) {
@@ -90,6 +92,9 @@
static oop find_method(Method* method);
static oop add_method(Handle rmethod_name);
+ static bool has_work() { return _dead_entries; }
+ static void trigger_cleanup();
+
#if INCLUDE_JVMTI
// It is called at safepoint only for RedefineClasses
static void adjust_method_entries(bool * trace_name_printed);
--- a/src/hotspot/share/prims/unsafe.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/prims/unsafe.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -776,8 +776,8 @@
// Make sure it's the real host class, not another anonymous class.
while (host_klass != NULL && host_klass->is_instance_klass() &&
- InstanceKlass::cast(host_klass)->is_anonymous()) {
- host_klass = InstanceKlass::cast(host_klass)->host_klass();
+ InstanceKlass::cast(host_klass)->is_unsafe_anonymous()) {
+ host_klass = InstanceKlass::cast(host_klass)->unsafe_anonymous_host();
}
// Primitive types have NULL Klass* fields in their java.lang.Class instances.
--- a/src/hotspot/share/prims/whitebox.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/prims/whitebox.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -53,6 +53,7 @@
#include "runtime/arguments.hpp"
#include "runtime/compilationPolicy.hpp"
#include "runtime/deoptimization.hpp"
+#include "runtime/fieldDescriptor.inline.hpp"
#include "runtime/flags/jvmFlag.hpp"
#include "runtime/frame.inline.hpp"
#include "runtime/handshake.hpp"
--- a/src/hotspot/share/runtime/arguments.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/runtime/arguments.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -1585,7 +1585,7 @@
if (RequireSharedSpaces) {
jio_fprintf(defaultStream::error_stream(),
"Class data sharing is inconsistent with other specified options.\n");
- vm_exit_during_initialization("Unable to use shared archive.", message);
+ vm_exit_during_initialization("Unable to use shared archive", message);
} else {
FLAG_SET_DEFAULT(UseSharedSpaces, false);
}
--- a/src/hotspot/share/runtime/fieldDescriptor.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/runtime/fieldDescriptor.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -31,7 +31,7 @@
#include "oops/instanceKlass.hpp"
#include "oops/oop.inline.hpp"
#include "oops/fieldStreams.hpp"
-#include "runtime/fieldDescriptor.hpp"
+#include "runtime/fieldDescriptor.inline.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/signature.hpp"
--- a/src/hotspot/share/runtime/fieldDescriptor.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/runtime/fieldDescriptor.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -44,15 +44,9 @@
constantPoolHandle _cp;
// update the access_flags for the field in the klass
- void update_klass_field_access_flag() {
- InstanceKlass* ik = field_holder();
- ik->field(index())->set_access_flags(_access_flags.as_short());
- }
+ inline void update_klass_field_access_flag();
- FieldInfo* field() const {
- InstanceKlass* ik = field_holder();
- return ik->field(_index);
- }
+ inline FieldInfo* field() const;
public:
fieldDescriptor() {
@@ -62,26 +56,23 @@
DEBUG_ONLY(_index = badInt);
reinitialize(ik, index);
}
- Symbol* name() const {
- return field()->name(_cp());
- }
- Symbol* signature() const {
- return field()->signature(_cp());
- }
- InstanceKlass* field_holder() const { return _cp->pool_holder(); }
- ConstantPool* constants() const { return _cp(); }
+ inline Symbol* name() const;
+ inline Symbol* signature() const;
+ inline InstanceKlass* field_holder() const;
+ inline ConstantPool* constants() const;
+
AccessFlags access_flags() const { return _access_flags; }
oop loader() const;
// Offset (in words) of field from start of instanceOop / Klass*
- int offset() const { return field()->offset(); }
+ inline int offset() const;
Symbol* generic_signature() const;
int index() const { return _index; }
AnnotationArray* annotations() const;
AnnotationArray* type_annotations() const;
// Initial field value
- bool has_initial_value() const { return field()->initval_index() != 0; }
- int initial_value_index() const { return field()->initval_index(); }
+ inline bool has_initial_value() const;
+ inline int initial_value_index() const;
constantTag initial_value_tag() const; // The tag will return true on one of is_int(), is_long(), is_single(), is_double()
jint int_initial_value() const;
jlong long_initial_value() const;
@@ -90,7 +81,7 @@
oop string_initial_value(TRAPS) const;
// Field signature type
- BasicType field_type() const { return FieldType::basic_type(signature()); }
+ inline BasicType field_type() const;
// Access flags
bool is_public() const { return access_flags().is_public(); }
@@ -111,20 +102,9 @@
bool has_initialized_final_update() const { return access_flags().has_field_initialized_final_update(); }
bool has_generic_signature() const { return access_flags().field_has_generic_signature(); }
- void set_is_field_access_watched(const bool value) {
- _access_flags.set_is_field_access_watched(value);
- update_klass_field_access_flag();
- }
-
- void set_is_field_modification_watched(const bool value) {
- _access_flags.set_is_field_modification_watched(value);
- update_klass_field_access_flag();
- }
-
- void set_has_initialized_final_update(const bool value) {
- _access_flags.set_has_field_initialized_final_update(value);
- update_klass_field_access_flag();
- }
+ inline void set_is_field_access_watched(const bool value);
+ inline void set_is_field_modification_watched(const bool value);
+ inline void set_has_initialized_final_update(const bool value);
// Initialization
void reinitialize(InstanceKlass* ik, int index);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/runtime/fieldDescriptor.inline.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_RUNTIME_FIELDDESCRIPTOR_INLINE_HPP
+#define SHARE_VM_RUNTIME_FIELDDESCRIPTOR_INLINE_HPP
+
+#include "runtime/handles.inline.hpp"
+
+// All fieldDescriptor inline functions that (directly or indirectly) use "_cp()" or "_cp->"
+// must be put in this file, as they require runtime/handles.inline.hpp.
+
+inline Symbol* fieldDescriptor::name() const {
+ return field()->name(_cp());
+}
+
+inline Symbol* fieldDescriptor::signature() const {
+ return field()->signature(_cp());
+}
+
+inline InstanceKlass* fieldDescriptor::field_holder() const {
+ return _cp->pool_holder();
+}
+
+inline ConstantPool* fieldDescriptor::constants() const {
+ return _cp();
+}
+
+inline FieldInfo* fieldDescriptor::field() const {
+ InstanceKlass* ik = field_holder();
+ return ik->field(_index);
+}
+
+inline int fieldDescriptor::offset() const { return field()->offset(); }
+inline bool fieldDescriptor::has_initial_value() const { return field()->initval_index() != 0; }
+inline int fieldDescriptor::initial_value_index() const { return field()->initval_index(); }
+
+inline void fieldDescriptor::update_klass_field_access_flag() {
+ InstanceKlass* ik = field_holder();
+ ik->field(index())->set_access_flags(_access_flags.as_short());
+}
+
+inline void fieldDescriptor::set_is_field_access_watched(const bool value) {
+ _access_flags.set_is_field_access_watched(value);
+ update_klass_field_access_flag();
+}
+
+inline void fieldDescriptor::set_is_field_modification_watched(const bool value) {
+ _access_flags.set_is_field_modification_watched(value);
+ update_klass_field_access_flag();
+}
+
+inline void fieldDescriptor::set_has_initialized_final_update(const bool value) {
+ _access_flags.set_has_field_initialized_final_update(value);
+ update_klass_field_access_flag();
+}
+
+inline BasicType fieldDescriptor::field_type() const {
+ return FieldType::basic_type(signature());
+}
+
+#endif // SHARE_VM_RUNTIME_FIELDDESCRIPTOR_INLINE_HPP
--- a/src/hotspot/share/runtime/handshake.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/runtime/handshake.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -338,7 +338,13 @@
}
bool HandshakeState::vmthread_can_process_handshake(JavaThread* target) {
- return SafepointSynchronize::safepoint_safe(target, target->thread_state());
+ // SafepointSynchronize::safepoint_safe() does not consider an externally
+ // suspended thread to be safe. However, this function must be called with
+ // the Threads_lock held so an externally suspended thread cannot be
+ // resumed thus it is safe.
+ assert(Threads_lock->owned_by_self(), "Not holding Threads_lock.");
+ return SafepointSynchronize::safepoint_safe(target, target->thread_state()) ||
+ target->is_ext_suspended();
}
bool HandshakeState::claim_handshake_for_vmthread() {
--- a/src/hotspot/share/runtime/mutexLocker.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/runtime/mutexLocker.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -263,11 +263,6 @@
def(Terminator_lock , PaddedMonitor, nonleaf, true, Monitor::_safepoint_check_sometimes);
def(VtableStubs_lock , PaddedMutex , nonleaf, true, Monitor::_safepoint_check_always);
def(Notify_lock , PaddedMonitor, nonleaf, true, Monitor::_safepoint_check_always);
- // OopStorage-based JNI may lock the alloc_locks while releasing a handle,
- // while previous JNI didn't need a lock for handle release. This runs afoul
- // of some places which hold other locks while releasing a handle, including
- // the Patching_lock, which is of "special" rank. As a temporary workaround,
- // lower the JNI oopstorage lock ranks to make them super-special.
def(JNIGlobalAlloc_lock , PaddedMutex , nonleaf, true, Monitor::_safepoint_check_never);
def(JNIGlobalActive_lock , PaddedMutex , nonleaf-1, true, Monitor::_safepoint_check_never);
def(JNIWeakAlloc_lock , PaddedMutex , nonleaf, true, Monitor::_safepoint_check_never);
--- a/src/hotspot/share/runtime/reflection.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/runtime/reflection.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -43,6 +43,7 @@
#include "oops/typeArrayOop.inline.hpp"
#include "prims/jvmtiExport.hpp"
#include "runtime/arguments.hpp"
+#include "runtime/fieldDescriptor.inline.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/reflection.hpp"
@@ -424,18 +425,18 @@
return result;
}
-static bool under_host_klass(const InstanceKlass* ik, const InstanceKlass* host_klass) {
+static bool under_unsafe_anonymous_host(const InstanceKlass* ik, const InstanceKlass* unsafe_anonymous_host) {
DEBUG_ONLY(int inf_loop_check = 1000 * 1000 * 1000);
for (;;) {
- const InstanceKlass* hc = ik->host_klass();
+ const InstanceKlass* hc = ik->unsafe_anonymous_host();
if (hc == NULL) return false;
- if (hc == host_klass) return true;
+ if (hc == unsafe_anonymous_host) return true;
ik = hc;
// There's no way to make a host class loop short of patching memory.
// Therefore there cannot be a loop here unless there's another bug.
// Still, let's check for it.
- assert(--inf_loop_check > 0, "no host_klass loop");
+ assert(--inf_loop_check > 0, "no unsafe_anonymous_host loop");
}
}
@@ -446,10 +447,10 @@
const InstanceKlass* accessor_ik = InstanceKlass::cast(accessor);
const InstanceKlass* accessee_ik = InstanceKlass::cast(accessee);
- // If either is on the other's host_klass chain, access is OK,
+ // If either is on the other's unsafe_anonymous_host chain, access is OK,
// because one is inside the other.
- if (under_host_klass(accessor_ik, accessee_ik) ||
- under_host_klass(accessee_ik, accessor_ik))
+ if (under_unsafe_anonymous_host(accessor_ik, accessee_ik) ||
+ under_unsafe_anonymous_host(accessee_ik, accessor_ik))
return true;
if ((RelaxAccessControlCheck &&
@@ -676,13 +677,13 @@
}
const Klass* host_class = current_class;
- if (host_class->is_instance_klass() &&
- InstanceKlass::cast(host_class)->is_anonymous()) {
- host_class = InstanceKlass::cast(host_class)->host_klass();
- assert(host_class != NULL, "Anonymous class has null host class");
+ if (current_class->is_instance_klass() &&
+ InstanceKlass::cast(current_class)->is_unsafe_anonymous()) {
+ host_class = InstanceKlass::cast(current_class)->unsafe_anonymous_host();
+ assert(host_class != NULL, "Unsafe anonymous class has null host class");
assert(!(host_class->is_instance_klass() &&
- InstanceKlass::cast(host_class)->is_anonymous()),
- "host_class should not be anonymous");
+ InstanceKlass::cast(host_class)->is_unsafe_anonymous()),
+ "unsafe_anonymous_host should not be unsafe anonymous itself");
}
if (host_class == member_class) {
return true;
@@ -710,7 +711,7 @@
}
// private access between different classes needs a nestmate check, but
- // not for anonymous classes - so check host_class
+ // not for unsafe anonymous classes - so check host_class
if (access.is_private() && host_class == current_class) {
if (current_class->is_instance_klass() && member_class->is_instance_klass() ) {
InstanceKlass* cur_ik = const_cast<InstanceKlass*>(InstanceKlass::cast(current_class));
@@ -742,7 +743,7 @@
// Checks that the 'outer' klass has declared 'inner' as being an inner klass. If not,
// throw an incompatible class change exception
// If inner_is_member, require the inner to be a member of the outer.
-// If !inner_is_member, require the inner to be anonymous (a non-member).
+// If !inner_is_member, require the inner to be unsafe anonymous (a non-member).
// Caller is responsible for figuring out in advance which case must be true.
void Reflection::check_for_inner_class(const InstanceKlass* outer, const InstanceKlass* inner,
bool inner_is_member, TRAPS) {
--- a/src/hotspot/share/runtime/serviceThread.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/runtime/serviceThread.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -24,12 +24,14 @@
#include "precompiled.hpp"
#include "classfile/stringTable.hpp"
+#include "classfile/symbolTable.hpp"
#include "runtime/interfaceSupport.inline.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/serviceThread.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/os.hpp"
#include "prims/jvmtiImpl.hpp"
+#include "prims/resolvedMethodTable.hpp"
#include "services/diagnosticArgument.hpp"
#include "services/diagnosticFramework.hpp"
#include "services/gcNotifier.hpp"
@@ -84,6 +86,8 @@
bool has_dcmd_notification_event = false;
bool acs_notify = false;
bool stringtable_work = false;
+ bool symboltable_work = false;
+ bool resolved_method_table_work = false;
JvmtiDeferredEvent jvmti_event;
{
// Need state transition ThreadBlockInVM so that this thread
@@ -101,7 +105,9 @@
!(has_jvmti_events = JvmtiDeferredEventQueue::has_events()) &&
!(has_gc_notification_event = GCNotifier::has_event()) &&
!(has_dcmd_notification_event = DCmdFactory::has_pending_jmx_notification()) &&
- !(stringtable_work = StringTable::has_work())) {
+ !(stringtable_work = StringTable::has_work()) &&
+ !(symboltable_work = SymbolTable::has_work()) &&
+ !(resolved_method_table_work = ResolvedMethodTable::has_work())) {
// wait until one of the sensors has pending requests, or there is a
// pending JVMTI event or JMX GC notification to post
Service_lock->wait(Mutex::_no_safepoint_check_flag);
@@ -116,6 +122,10 @@
StringTable::do_concurrent_work(jt);
}
+ if (symboltable_work) {
+ SymbolTable::do_concurrent_work(jt);
+ }
+
if (has_jvmti_events) {
jvmti_event.post();
}
@@ -125,12 +135,16 @@
}
if(has_gc_notification_event) {
- GCNotifier::sendNotification(CHECK);
+ GCNotifier::sendNotification(CHECK);
}
if(has_dcmd_notification_event) {
DCmdFactory::send_notification(CHECK);
}
+
+ if (resolved_method_table_work) {
+ ResolvedMethodTable::unlink();
+ }
}
}
--- a/src/hotspot/share/runtime/sharedRuntime.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/runtime/sharedRuntime.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -2135,17 +2135,21 @@
static int _max_size; // max. arg size seen
static void add_method_to_histogram(nmethod* nm) {
- Method* m = nm->method();
- ArgumentCount args(m->signature());
- int arity = args.size() + (m->is_static() ? 0 : 1);
- int argsize = m->size_of_parameters();
- arity = MIN2(arity, MAX_ARITY-1);
- argsize = MIN2(argsize, MAX_ARITY-1);
- int count = nm->method()->compiled_invocation_count();
- _arity_histogram[arity] += count;
- _size_histogram[argsize] += count;
- _max_arity = MAX2(_max_arity, arity);
- _max_size = MAX2(_max_size, argsize);
+ // These checks are taken from CodeHeapState::print_names()
+ Method* m = (nm == NULL) ? NULL : nm->method(); // nm->method() may be uninitialized, i.e. != NULL, but invalid
+ if ((nm != NULL) && (m != NULL) && !nm->is_zombie() && !nm->is_not_installed() &&
+ os::is_readable_pointer(m) && os::is_readable_pointer(m->constants())) {
+ ArgumentCount args(m->signature());
+ int arity = args.size() + (m->is_static() ? 0 : 1);
+ int argsize = m->size_of_parameters();
+ arity = MIN2(arity, MAX_ARITY-1);
+ argsize = MIN2(argsize, MAX_ARITY-1);
+ int count = nm->method()->compiled_invocation_count();
+ _arity_histogram[arity] += count;
+ _size_histogram[argsize] += count;
+ _max_arity = MAX2(_max_arity, arity);
+ _max_size = MAX2(_max_size, argsize);
+ }
}
void print_histogram_helper(int n, int* histo, const char* name) {
--- a/src/hotspot/share/runtime/thread.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/runtime/thread.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -65,6 +65,7 @@
#include "runtime/arguments.hpp"
#include "runtime/atomic.hpp"
#include "runtime/biasedLocking.hpp"
+#include "runtime/fieldDescriptor.inline.hpp"
#include "runtime/flags/jvmFlagConstraintList.hpp"
#include "runtime/flags/jvmFlagRangeList.hpp"
#include "runtime/flags/jvmFlagWriteableList.hpp"
--- a/src/hotspot/share/runtime/vmStructs.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/runtime/vmStructs.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -162,12 +162,8 @@
typedef HashtableEntry<intptr_t, mtInternal> IntptrHashtableEntry;
typedef Hashtable<intptr_t, mtInternal> IntptrHashtable;
-typedef Hashtable<Symbol*, mtSymbol> SymbolHashtable;
-typedef HashtableEntry<Symbol*, mtClass> SymbolHashtableEntry;
typedef Hashtable<InstanceKlass*, mtClass> KlassHashtable;
typedef HashtableEntry<InstanceKlass*, mtClass> KlassHashtableEntry;
-typedef CompactHashtable<Symbol*, char> SymbolCompactHashTable;
-typedef RehashableHashtable<Symbol*, mtSymbol> RehashableSymbolHashtable;
typedef PaddedEnd<ObjectMonitor> PaddedObjectMonitor;
@@ -467,24 +463,6 @@
static_field(PerfMemory, _prologue, PerfDataPrologue*) \
static_field(PerfMemory, _initialized, int) \
\
- /***************/ \
- /* SymbolTable */ \
- /***************/ \
- \
- static_field(SymbolTable, _the_table, SymbolTable*) \
- static_field(SymbolTable, _shared_table, SymbolCompactHashTable) \
- static_field(RehashableSymbolHashtable, _seed, juint) \
- \
- /********************/ \
- /* CompactHashTable */ \
- /********************/ \
- \
- nonstatic_field(SymbolCompactHashTable, _base_address, address) \
- nonstatic_field(SymbolCompactHashTable, _entry_count, u4) \
- nonstatic_field(SymbolCompactHashTable, _bucket_count, u4) \
- nonstatic_field(SymbolCompactHashTable, _buckets, u4*) \
- nonstatic_field(SymbolCompactHashTable, _entries, u4*) \
- \
/********************/ \
/* SystemDictionary */ \
/********************/ \
@@ -538,7 +516,7 @@
nonstatic_field(ClassLoaderData, _class_loader, OopHandle) \
nonstatic_field(ClassLoaderData, _next, ClassLoaderData*) \
volatile_nonstatic_field(ClassLoaderData, _klasses, Klass*) \
- nonstatic_field(ClassLoaderData, _is_anonymous, bool) \
+ nonstatic_field(ClassLoaderData, _is_unsafe_anonymous, bool) \
volatile_nonstatic_field(ClassLoaderData, _dictionary, Dictionary*) \
\
static_field(ClassLoaderDataGraph, _head, ClassLoaderData*) \
@@ -1117,11 +1095,11 @@
/* FileMapInfo fields (CDS archive related) */ \
/********************************************/ \
\
- CDS_ONLY(nonstatic_field(FileMapInfo, _header, FileMapInfo::FileMapHeader*)) \
- CDS_ONLY( static_field(FileMapInfo, _current_info, FileMapInfo*)) \
- CDS_ONLY(nonstatic_field(FileMapInfo::FileMapHeader, _space[0], FileMapInfo::FileMapHeader::space_info))\
- CDS_ONLY(nonstatic_field(FileMapInfo::FileMapHeader::space_info, _addr._base, char*)) \
- CDS_ONLY(nonstatic_field(FileMapInfo::FileMapHeader::space_info, _used, size_t)) \
+ CDS_ONLY(nonstatic_field(FileMapInfo, _header, FileMapHeader*)) \
+ CDS_ONLY( static_field(FileMapInfo, _current_info, FileMapInfo*)) \
+ CDS_ONLY(nonstatic_field(FileMapHeader, _space[0], CDSFileMapRegion)) \
+ CDS_ONLY(nonstatic_field(CDSFileMapRegion, _addr._base, char*)) \
+ CDS_ONLY(nonstatic_field(CDSFileMapRegion, _used, size_t)) \
\
/******************/ \
/* VMError fields */ \
@@ -1351,15 +1329,13 @@
declare_toplevel_type(PerfMemory) \
declare_type(PerfData, CHeapObj<mtInternal>) \
\
- /*********************************/ \
- /* SymbolTable, SystemDictionary */ \
- /*********************************/ \
+ /********************/ \
+ /* SystemDictionary */ \
+ /********************/ \
\
declare_toplevel_type(BasicHashtable<mtInternal>) \
declare_type(IntptrHashtable, BasicHashtable<mtInternal>) \
declare_toplevel_type(BasicHashtable<mtSymbol>) \
- declare_type(RehashableSymbolHashtable, BasicHashtable<mtSymbol>) \
- declare_type(SymbolTable, SymbolHashtable) \
declare_type(Dictionary, KlassHashtable) \
declare_toplevel_type(BasicHashtableEntry<mtInternal>) \
declare_type(IntptrHashtableEntry, BasicHashtableEntry<mtInternal>) \
@@ -1373,8 +1349,6 @@
declare_toplevel_type(Arena) \
declare_type(ResourceArea, Arena) \
\
- declare_toplevel_type(SymbolCompactHashTable) \
- \
/***********************************************************/ \
/* Thread hierarchy (needed for run-time type information) */ \
/***********************************************************/ \
@@ -2004,9 +1978,8 @@
declare_toplevel_type(Annotations*) \
declare_type(OopMapValue, StackObj) \
declare_type(FileMapInfo, CHeapObj<mtInternal>) \
- declare_type(FileMapInfo::FileMapHeaderBase, CHeapObj<mtClass>) \
- declare_type(FileMapInfo::FileMapHeader, FileMapInfo::FileMapHeaderBase)\
- declare_toplevel_type(FileMapInfo::FileMapHeader::space_info) \
+ declare_toplevel_type(FileMapHeader) \
+ declare_toplevel_type(CDSFileMapRegion) \
\
/************/ \
/* GC types */ \
@@ -2293,7 +2266,7 @@
declare_constant(InstanceKlass::_misc_rewritten) \
declare_constant(InstanceKlass::_misc_has_nonstatic_fields) \
declare_constant(InstanceKlass::_misc_should_verify_class) \
- declare_constant(InstanceKlass::_misc_is_anonymous) \
+ declare_constant(InstanceKlass::_misc_is_unsafe_anonymous) \
declare_constant(InstanceKlass::_misc_is_contended) \
declare_constant(InstanceKlass::_misc_has_nonstatic_concrete_methods) \
declare_constant(InstanceKlass::_misc_declares_nonstatic_concrete_methods)\
--- a/src/hotspot/share/services/diagnosticCommand.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/services/diagnosticCommand.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -35,6 +35,7 @@
#include "oops/objArrayOop.inline.hpp"
#include "oops/oop.inline.hpp"
#include "oops/typeArrayOop.inline.hpp"
+#include "runtime/fieldDescriptor.inline.hpp"
#include "runtime/flags/jvmFlag.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/javaCalls.hpp"
--- a/src/hotspot/share/services/memoryPool.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/services/memoryPool.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -85,6 +85,8 @@
bool support_usage_threshold,
bool support_gc_threshold);
+ virtual ~MemoryPool() { }
+
const char* name() { return _name; }
bool is_heap() { return _type == Heap; }
bool is_non_heap() { return _type == NonHeap; }
--- a/src/hotspot/share/utilities/bitMap.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/utilities/bitMap.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -672,6 +672,11 @@
prefix, p2i(map()), p2i((char*)map() + (size() >> LogBitsPerByte)));
}
+void BitMap::write_to(bm_word_t* buffer, size_t buffer_size_in_bytes) const {
+ assert(buffer_size_in_bytes == size_in_bytes(), "must be");
+ memcpy(buffer, _map, size_in_bytes());
+}
+
#ifndef PRODUCT
void BitMap::print_on(outputStream* st) const {
--- a/src/hotspot/share/utilities/bitMap.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/utilities/bitMap.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -288,6 +288,7 @@
bool is_full() const;
bool is_empty() const;
+ void write_to(bm_word_t* buffer, size_t buffer_size_in_bytes) const;
void print_on_error(outputStream* st, const char* prefix) const;
#ifndef PRODUCT
--- a/src/hotspot/share/utilities/concurrentHashTable.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/utilities/concurrentHashTable.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -309,7 +309,7 @@
// Insert which handles a number of cases.
template <typename LOOKUP_FUNC, typename VALUE_FUNC, typename CALLBACK_FUNC>
bool internal_insert(Thread* thread, LOOKUP_FUNC& lookup_f, VALUE_FUNC& value_f,
- CALLBACK_FUNC& callback, bool* grow_hint = NULL);
+ CALLBACK_FUNC& callback, bool* grow_hint = NULL, bool* clean_hint = NULL);
// Returns true if an item matching LOOKUP_FUNC is removed.
// Calls DELETE_FUNC before destroying the node.
@@ -396,8 +396,8 @@
// value already exists.
template <typename LOOKUP_FUNC, typename VALUE_FUNC, typename CALLBACK_FUNC>
bool get_insert_lazy(Thread* thread, LOOKUP_FUNC& lookup_f, VALUE_FUNC& val_f,
- CALLBACK_FUNC& callback_f, bool* grow_hint = NULL) {
- return !internal_insert(thread, lookup_f, val_f, callback_f, grow_hint);
+ CALLBACK_FUNC& callback_f, bool* grow_hint = NULL, bool* clean_hint = NULL) {
+ return !internal_insert(thread, lookup_f, val_f, callback_f, grow_hint, clean_hint);
}
// Same without CALLBACK_FUNC.
@@ -436,9 +436,9 @@
// LOOKUP_FUNC.
template <typename LOOKUP_FUNC>
bool insert(Thread* thread, LOOKUP_FUNC& lookup_f, const VALUE& value,
- bool* grow_hint = NULL) {
+ bool* grow_hint = NULL, bool* clean_hint = NULL) {
LazyValueRetrieve vp(value);
- return internal_insert(thread, lookup_f, vp, noOp, grow_hint);
+ return internal_insert(thread, lookup_f, vp, noOp, grow_hint, clean_hint);
}
// This does a fast unsafe insert and can thus only be used when there is no
--- a/src/hotspot/share/utilities/concurrentHashTable.inline.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/utilities/concurrentHashTable.inline.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -540,6 +540,8 @@
inline void ConcurrentHashTable<VALUE, CONFIG, F>::
delete_in_bucket(Thread* thread, Bucket* bucket, LOOKUP_FUNC& lookup_f)
{
+ assert(bucket->is_locked(), "Must be locked.");
+
size_t dels = 0;
Node* ndel[BULK_DELETE_LIMIT];
Node* const volatile * rem_n_prev = bucket->first_ptr();
@@ -874,7 +876,7 @@
template <typename LOOKUP_FUNC, typename VALUE_FUNC, typename CALLBACK_FUNC>
inline bool ConcurrentHashTable<VALUE, CONFIG, F>::
internal_insert(Thread* thread, LOOKUP_FUNC& lookup_f, VALUE_FUNC& value_f,
- CALLBACK_FUNC& callback, bool* grow_hint)
+ CALLBACK_FUNC& callback, bool* grow_hint, bool* clean_hint)
{
bool ret = false;
bool clean = false;
@@ -925,15 +927,20 @@
} else if (i == 0 && clean) {
// We only do cleaning on fast inserts.
Bucket* bucket = get_bucket_locked(thread, lookup_f.get_hash());
- assert(bucket->is_locked(), "Must be locked.");
delete_in_bucket(thread, bucket, lookup_f);
bucket->unlock();
+
+ clean = false;
}
if (grow_hint != NULL) {
*grow_hint = loops > _grow_hint;
}
+ if (clean_hint != NULL) {
+ *clean_hint = clean;
+ }
+
return ret;
}
--- a/src/hotspot/share/utilities/globalCounter.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/utilities/globalCounter.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -61,6 +61,11 @@
// Atomic::add must provide fence since we have storeload dependency.
volatile uintx gbl_cnt = Atomic::add((uintx)COUNTER_INCREMENT, &_global_counter._counter,
memory_order_conservative);
+ // Handle bootstrap
+ if (Threads::number_of_threads() == 0) {
+ return;
+ }
+
// Do all RCU threads.
CounterThreadCheck ctc(gbl_cnt);
for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thread = jtiwh.next(); ) {
--- a/src/hotspot/share/utilities/globalDefinitions.hpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/hotspot/share/utilities/globalDefinitions.hpp Thu Aug 23 11:09:16 2018 -0400
@@ -422,13 +422,14 @@
const int max_method_code_size = 64*K - 1; // JVM spec, 2nd ed. section 4.8.1 (p.134)
//----------------------------------------------------------------------------------------------------
-// Default and minimum StringTableSize values
+// Default and minimum StringTable and SymbolTable size values
+// Must be a power of 2
-const int defaultStringTableSize = NOT_LP64(1024) LP64_ONLY(65536);
-const int minimumStringTableSize = 128;
+const size_t defaultStringTableSize = NOT_LP64(1024) LP64_ONLY(65536);
+const size_t minimumStringTableSize = 128;
-const int defaultSymbolTableSize = 20011;
-const int minimumSymbolTableSize = 1009;
+const size_t defaultSymbolTableSize = 32768; // 2^15
+const size_t minimumSymbolTableSize = 1024;
//----------------------------------------------------------------------------------------------------
--- a/src/java.base/share/classes/com/sun/crypto/provider/HmacPKCS12PBESHA1.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/com/sun/crypto/provider/HmacPKCS12PBESHA1.java Thu Aug 23 11:09:16 2018 -0400
@@ -73,62 +73,69 @@
salt = pbeKey.getSalt(); // maybe null if unspecified
iCount = pbeKey.getIterationCount(); // maybe 0 if unspecified
} else if (key instanceof SecretKey) {
- byte[] passwdBytes = key.getEncoded();
- if ((passwdBytes == null) ||
- !(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3))) {
+ byte[] passwdBytes;
+ if (!(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3)) ||
+ (passwdBytes = key.getEncoded()) == null) {
throw new InvalidKeyException("Missing password");
}
passwdChars = new char[passwdBytes.length];
for (int i=0; i<passwdChars.length; i++) {
passwdChars[i] = (char) (passwdBytes[i] & 0x7f);
}
+ Arrays.fill(passwdBytes, (byte)0x00);
} else {
throw new InvalidKeyException("SecretKey of PBE type required");
}
- if (params == null) {
- // should not auto-generate default values since current
- // javax.crypto.Mac api does not have any method for caller to
- // retrieve the generated defaults.
- if ((salt == null) || (iCount == 0)) {
+
+ byte[] derivedKey;
+ try {
+ if (params == null) {
+ // should not auto-generate default values since current
+ // javax.crypto.Mac api does not have any method for caller to
+ // retrieve the generated defaults.
+ if ((salt == null) || (iCount == 0)) {
+ throw new InvalidAlgorithmParameterException
+ ("PBEParameterSpec required for salt and iteration count");
+ }
+ } else if (!(params instanceof PBEParameterSpec)) {
throw new InvalidAlgorithmParameterException
- ("PBEParameterSpec required for salt and iteration count");
- }
- } else if (!(params instanceof PBEParameterSpec)) {
- throw new InvalidAlgorithmParameterException
- ("PBEParameterSpec type required");
- } else {
- PBEParameterSpec pbeParams = (PBEParameterSpec) params;
- // make sure the parameter values are consistent
- if (salt != null) {
- if (!Arrays.equals(salt, pbeParams.getSalt())) {
- throw new InvalidAlgorithmParameterException
- ("Inconsistent value of salt between key and params");
+ ("PBEParameterSpec type required");
+ } else {
+ PBEParameterSpec pbeParams = (PBEParameterSpec) params;
+ // make sure the parameter values are consistent
+ if (salt != null) {
+ if (!Arrays.equals(salt, pbeParams.getSalt())) {
+ throw new InvalidAlgorithmParameterException
+ ("Inconsistent value of salt between key and params");
+ }
+ } else {
+ salt = pbeParams.getSalt();
}
- } else {
- salt = pbeParams.getSalt();
+ if (iCount != 0) {
+ if (iCount != pbeParams.getIterationCount()) {
+ throw new InvalidAlgorithmParameterException
+ ("Different iteration count between key and params");
+ }
+ } else {
+ iCount = pbeParams.getIterationCount();
+ }
}
- if (iCount != 0) {
- if (iCount != pbeParams.getIterationCount()) {
- throw new InvalidAlgorithmParameterException
- ("Different iteration count between key and params");
- }
- } else {
- iCount = pbeParams.getIterationCount();
+ // For security purpose, we need to enforce a minimum length
+ // for salt; just require the minimum salt length to be 8-byte
+ // which is what PKCS#5 recommends and openssl does.
+ if (salt.length < 8) {
+ throw new InvalidAlgorithmParameterException
+ ("Salt must be at least 8 bytes long");
}
+ if (iCount <= 0) {
+ throw new InvalidAlgorithmParameterException
+ ("IterationCount must be a positive number");
+ }
+ derivedKey = PKCS12PBECipherCore.derive(passwdChars, salt,
+ iCount, engineGetMacLength(), PKCS12PBECipherCore.MAC_KEY);
+ } finally {
+ Arrays.fill(passwdChars, '\0');
}
- // For security purpose, we need to enforce a minimum length
- // for salt; just require the minimum salt length to be 8-byte
- // which is what PKCS#5 recommends and openssl does.
- if (salt.length < 8) {
- throw new InvalidAlgorithmParameterException
- ("Salt must be at least 8 bytes long");
- }
- if (iCount <= 0) {
- throw new InvalidAlgorithmParameterException
- ("IterationCount must be a positive number");
- }
- byte[] derivedKey = PKCS12PBECipherCore.derive(passwdChars, salt,
- iCount, engineGetMacLength(), PKCS12PBECipherCore.MAC_KEY);
SecretKey cipherKey = new SecretKeySpec(derivedKey, "HmacSHA1");
super.engineInit(cipherKey, null);
}
--- a/src/java.base/share/classes/com/sun/crypto/provider/KeyProtector.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/com/sun/crypto/provider/KeyProtector.java Thu Aug 23 11:09:16 2018 -0400
@@ -310,14 +310,14 @@
Cipher cipher;
try {
sKey = new PBEKey(pbeKeySpec, "PBEWithMD5AndTripleDES", false);
- pbeKeySpec.clearPassword();
+ pbeKeySpec.clearPassword();
- // seal key
- PBEWithMD5AndTripleDESCipher cipherSpi;
- cipherSpi = new PBEWithMD5AndTripleDESCipher();
- cipher = new CipherForKeyProtector(cipherSpi, SunJCE.getInstance(),
- "PBEWithMD5AndTripleDES");
- cipher.init(Cipher.ENCRYPT_MODE, sKey, pbeSpec);
+ // seal key
+ PBEWithMD5AndTripleDESCipher cipherSpi;
+ cipherSpi = new PBEWithMD5AndTripleDESCipher();
+ cipher = new CipherForKeyProtector(cipherSpi, SunJCE.getInstance(),
+ "PBEWithMD5AndTripleDES");
+ cipher.init(Cipher.ENCRYPT_MODE, sKey, pbeSpec);
} finally {
if (sKey != null) sKey.destroy();
}
--- a/src/java.base/share/classes/com/sun/crypto/provider/PBEKey.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/com/sun/crypto/provider/PBEKey.java Thu Aug 23 11:09:16 2018 -0400
@@ -73,7 +73,7 @@
this.key = new byte[passwd.length];
for (int i=0; i<passwd.length; i++)
this.key[i] = (byte) (passwd[i] & 0x7f);
- Arrays.fill(passwd, ' ');
+ Arrays.fill(passwd, '\0');
type = keytype;
// Use the cleaner to zero the key when no longer referenced
--- a/src/java.base/share/classes/com/sun/crypto/provider/PBES1Core.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/com/sun/crypto/provider/PBES1Core.java Thu Aug 23 11:09:16 2018 -0400
@@ -27,6 +27,7 @@
import java.security.*;
import java.security.spec.*;
+import java.util.Arrays;
import javax.crypto.*;
import javax.crypto.spec.*;
@@ -213,35 +214,43 @@
throw new InvalidAlgorithmParameterException("Parameters "
+ "missing");
}
- if ((key == null) ||
- (key.getEncoded() == null) ||
- !(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3))) {
- throw new InvalidKeyException("Missing password");
+ if (key == null) {
+ throw new InvalidKeyException("Null key");
}
- if (params == null) {
- // create random salt and use default iteration count
- salt = new byte[8];
- random.nextBytes(salt);
- } else {
- if (!(params instanceof PBEParameterSpec)) {
- throw new InvalidAlgorithmParameterException
- ("Wrong parameter type: PBE expected");
+ byte[] derivedKey;
+ byte[] passwdBytes = key.getEncoded();
+ try {
+ if ((passwdBytes == null) ||
+ !(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3))) {
+ throw new InvalidKeyException("Missing password");
}
- salt = ((PBEParameterSpec) params).getSalt();
- // salt must be 8 bytes long (by definition)
- if (salt.length != 8) {
- throw new InvalidAlgorithmParameterException
- ("Salt must be 8 bytes long");
+
+ if (params == null) {
+ // create random salt and use default iteration count
+ salt = new byte[8];
+ random.nextBytes(salt);
+ } else {
+ if (!(params instanceof PBEParameterSpec)) {
+ throw new InvalidAlgorithmParameterException
+ ("Wrong parameter type: PBE expected");
+ }
+ salt = ((PBEParameterSpec) params).getSalt();
+ // salt must be 8 bytes long (by definition)
+ if (salt.length != 8) {
+ throw new InvalidAlgorithmParameterException
+ ("Salt must be 8 bytes long");
+ }
+ iCount = ((PBEParameterSpec) params).getIterationCount();
+ if (iCount <= 0) {
+ throw new InvalidAlgorithmParameterException
+ ("IterationCount must be a positive number");
+ }
}
- iCount = ((PBEParameterSpec) params).getIterationCount();
- if (iCount <= 0) {
- throw new InvalidAlgorithmParameterException
- ("IterationCount must be a positive number");
- }
+ derivedKey = deriveCipherKey(passwdBytes);
+ } finally {
+ if (passwdBytes != null) Arrays.fill(passwdBytes, (byte) 0x00);
}
-
- byte[] derivedKey = deriveCipherKey(key);
// use all but the last 8 bytes as the key value
SecretKeySpec cipherKey = new SecretKeySpec(derivedKey, 0,
derivedKey.length-8, algo);
@@ -253,16 +262,14 @@
cipher.init(opmode, cipherKey, ivSpec, random);
}
- private byte[] deriveCipherKey(Key key) {
+ private byte[] deriveCipherKey(byte[] passwdBytes) {
byte[] result = null;
- byte[] passwdBytes = key.getEncoded();
if (algo.equals("DES")) {
// P || S (password concatenated with salt)
byte[] concat = new byte[Math.addExact(passwdBytes.length, salt.length)];
System.arraycopy(passwdBytes, 0, concat, 0, passwdBytes.length);
- java.util.Arrays.fill(passwdBytes, (byte)0x00);
System.arraycopy(salt, 0, concat, passwdBytes.length, salt.length);
// digest P || S with c iterations
@@ -271,7 +278,7 @@
md.update(toBeHashed);
toBeHashed = md.digest(); // this resets the digest
}
- java.util.Arrays.fill(concat, (byte)0x00);
+ Arrays.fill(concat, (byte)0x00);
result = toBeHashed;
} else if (algo.equals("DESede")) {
// if the 2 salt halves are the same, invert one of them
@@ -294,8 +301,6 @@
// Concatenate the output from each digest round with the
// password, and use the result as the input to the next digest
// operation.
- byte[] kBytes = null;
- IvParameterSpec iv = null;
byte[] toBeHashed = null;
result = new byte[DESedeKeySpec.DES_EDE_KEY_LEN +
DESConstants.DES_BLOCK_SIZE];
@@ -306,12 +311,14 @@
for (int j=0; j < iCount; j++) {
md.update(toBeHashed);
md.update(passwdBytes);
- toBeHashed = md.digest(); // this resets the digest
+ toBeHashed = md.digest();
}
System.arraycopy(toBeHashed, 0, result, i*16,
toBeHashed.length);
}
}
+ // clear data used in message
+ md.reset();
return result;
}
@@ -478,9 +485,9 @@
byte[] wrap(Key key)
throws IllegalBlockSizeException, InvalidKeyException {
byte[] result = null;
-
+ byte[] encodedKey = null;
try {
- byte[] encodedKey = key.getEncoded();
+ encodedKey = key.getEncoded();
if ((encodedKey == null) || (encodedKey.length == 0)) {
throw new InvalidKeyException("Cannot get an encoding of " +
"the key to be wrapped");
@@ -489,6 +496,8 @@
result = doFinal(encodedKey, 0, encodedKey.length);
} catch (BadPaddingException e) {
// Should never happen
+ } finally {
+ if (encodedKey != null) Arrays.fill(encodedKey, (byte)0x00);
}
return result;
--- a/src/java.base/share/classes/com/sun/crypto/provider/PBES2Core.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/com/sun/crypto/provider/PBES2Core.java Thu Aug 23 11:09:16 2018 -0400
@@ -27,6 +27,7 @@
import java.security.*;
import java.security.spec.*;
+import java.util.Arrays;
import javax.crypto.*;
import javax.crypto.spec.*;
@@ -173,101 +174,105 @@
SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException {
- if ((key == null) ||
- (key.getEncoded() == null) ||
- !(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3))) {
- throw new InvalidKeyException("Missing password");
- }
-
- // TBD: consolidate the salt, ic and IV parameter checks below
-
- // Extract salt and iteration count from the key, if present
- if (key instanceof javax.crypto.interfaces.PBEKey) {
- salt = ((javax.crypto.interfaces.PBEKey)key).getSalt();
- if (salt != null && salt.length < 8) {
- throw new InvalidAlgorithmParameterException(
- "Salt must be at least 8 bytes long");
- }
- iCount = ((javax.crypto.interfaces.PBEKey)key).getIterationCount();
- if (iCount == 0) {
- iCount = DEFAULT_COUNT;
- } else if (iCount < 0) {
- throw new InvalidAlgorithmParameterException(
- "Iteration count must be a positive number");
- }
+ if (key == null) {
+ throw new InvalidKeyException("Null key");
}
- // Extract salt, iteration count and IV from the params, if present
- if (params == null) {
- if (salt == null) {
- // generate random salt and use default iteration count
- salt = new byte[DEFAULT_SALT_LENGTH];
- random.nextBytes(salt);
- iCount = DEFAULT_COUNT;
+ byte[] passwdBytes = key.getEncoded();
+ char[] passwdChars = null;
+ PBEKeySpec pbeSpec;
+ try {
+ if ((passwdBytes == null) ||
+ !(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3))) {
+ throw new InvalidKeyException("Missing password");
}
- if ((opmode == Cipher.ENCRYPT_MODE) ||
- (opmode == Cipher.WRAP_MODE)) {
- // generate random IV
- byte[] ivBytes = new byte[blkSize];
- random.nextBytes(ivBytes);
- ivSpec = new IvParameterSpec(ivBytes);
- }
- } else {
- if (!(params instanceof PBEParameterSpec)) {
- throw new InvalidAlgorithmParameterException
- ("Wrong parameter type: PBE expected");
+
+ // TBD: consolidate the salt, ic and IV parameter checks below
+
+ // Extract salt and iteration count from the key, if present
+ if (key instanceof javax.crypto.interfaces.PBEKey) {
+ salt = ((javax.crypto.interfaces.PBEKey)key).getSalt();
+ if (salt != null && salt.length < 8) {
+ throw new InvalidAlgorithmParameterException(
+ "Salt must be at least 8 bytes long");
+ }
+ iCount = ((javax.crypto.interfaces.PBEKey)key).getIterationCount();
+ if (iCount == 0) {
+ iCount = DEFAULT_COUNT;
+ } else if (iCount < 0) {
+ throw new InvalidAlgorithmParameterException(
+ "Iteration count must be a positive number");
+ }
}
- // salt and iteration count from the params take precedence
- byte[] specSalt = ((PBEParameterSpec) params).getSalt();
- if (specSalt != null && specSalt.length < 8) {
- throw new InvalidAlgorithmParameterException(
- "Salt must be at least 8 bytes long");
- }
- salt = specSalt;
- int specICount = ((PBEParameterSpec) params).getIterationCount();
- if (specICount == 0) {
- specICount = DEFAULT_COUNT;
- } else if (specICount < 0) {
- throw new InvalidAlgorithmParameterException(
- "Iteration count must be a positive number");
- }
- iCount = specICount;
- AlgorithmParameterSpec specParams =
- ((PBEParameterSpec) params).getParameterSpec();
- if (specParams != null) {
- if (specParams instanceof IvParameterSpec) {
- ivSpec = (IvParameterSpec)specParams;
+ // Extract salt, iteration count and IV from the params, if present
+ if (params == null) {
+ if (salt == null) {
+ // generate random salt and use default iteration count
+ salt = new byte[DEFAULT_SALT_LENGTH];
+ random.nextBytes(salt);
+ iCount = DEFAULT_COUNT;
+ }
+ if ((opmode == Cipher.ENCRYPT_MODE) ||
+ (opmode == Cipher.WRAP_MODE)) {
+ // generate random IV
+ byte[] ivBytes = new byte[blkSize];
+ random.nextBytes(ivBytes);
+ ivSpec = new IvParameterSpec(ivBytes);
+ }
+ } else {
+ if (!(params instanceof PBEParameterSpec)) {
+ throw new InvalidAlgorithmParameterException
+ ("Wrong parameter type: PBE expected");
+ }
+ // salt and iteration count from the params take precedence
+ byte[] specSalt = ((PBEParameterSpec) params).getSalt();
+ if (specSalt != null && specSalt.length < 8) {
+ throw new InvalidAlgorithmParameterException(
+ "Salt must be at least 8 bytes long");
+ }
+ salt = specSalt;
+ int specICount = ((PBEParameterSpec) params).getIterationCount();
+ if (specICount == 0) {
+ specICount = DEFAULT_COUNT;
+ } else if (specICount < 0) {
+ throw new InvalidAlgorithmParameterException(
+ "Iteration count must be a positive number");
+ }
+ iCount = specICount;
+
+ AlgorithmParameterSpec specParams =
+ ((PBEParameterSpec) params).getParameterSpec();
+ if (specParams != null) {
+ if (specParams instanceof IvParameterSpec) {
+ ivSpec = (IvParameterSpec)specParams;
+ } else {
+ throw new InvalidAlgorithmParameterException(
+ "Wrong parameter type: IV expected");
+ }
+ } else if ((opmode == Cipher.ENCRYPT_MODE) ||
+ (opmode == Cipher.WRAP_MODE)) {
+ // generate random IV
+ byte[] ivBytes = new byte[blkSize];
+ random.nextBytes(ivBytes);
+ ivSpec = new IvParameterSpec(ivBytes);
} else {
throw new InvalidAlgorithmParameterException(
- "Wrong parameter type: IV expected");
+ "Missing parameter type: IV expected");
}
- } else if ((opmode == Cipher.ENCRYPT_MODE) ||
- (opmode == Cipher.WRAP_MODE)) {
- // generate random IV
- byte[] ivBytes = new byte[blkSize];
- random.nextBytes(ivBytes);
- ivSpec = new IvParameterSpec(ivBytes);
- } else {
- throw new InvalidAlgorithmParameterException(
- "Missing parameter type: IV expected");
}
- }
- SecretKeySpec cipherKey = null;
- byte[] derivedKey = null;
- byte[] passwdBytes = key.getEncoded();
- char[] passwdChars = new char[passwdBytes.length];
+ passwdChars = new char[passwdBytes.length];
+ for (int i = 0; i < passwdChars.length; i++)
+ passwdChars[i] = (char) (passwdBytes[i] & 0x7f);
- for (int i=0; i<passwdChars.length; i++)
- passwdChars[i] = (char) (passwdBytes[i] & 0x7f);
-
- PBEKeySpec pbeSpec =
- new PBEKeySpec(passwdChars, salt, iCount, keyLength);
+ pbeSpec = new PBEKeySpec(passwdChars, salt, iCount, keyLength);
// password char[] was cloned in PBEKeySpec constructor,
// so we can zero it out here
- java.util.Arrays.fill(passwdChars, ' ');
- java.util.Arrays.fill(passwdBytes, (byte)0x00);
+ } finally {
+ if (passwdChars != null) Arrays.fill(passwdChars, '\0');
+ if (passwdBytes != null) Arrays.fill(passwdBytes, (byte)0x00);
+ }
SecretKey s = null;
@@ -280,8 +285,8 @@
ike.initCause(ikse);
throw ike;
}
- derivedKey = s.getEncoded();
- cipherKey = new SecretKeySpec(derivedKey, cipherAlgo);
+ byte[] derivedKey = s.getEncoded();
+ SecretKeySpec cipherKey = new SecretKeySpec(derivedKey, cipherAlgo);
// initialize the underlying cipher
cipher.init(opmode, cipherKey, ivSpec, random);
--- a/src/java.base/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java Thu Aug 23 11:09:16 2018 -0400
@@ -93,46 +93,50 @@
}
// Convert the password from char[] to byte[]
byte[] passwdBytes = getPasswordBytes(this.passwd);
+ // remove local copy
+ if (passwd != null) Arrays.fill(passwd, '\0');
- this.salt = keySpec.getSalt();
- if (salt == null) {
- throw new InvalidKeySpecException("Salt not found");
- }
- this.iterCount = keySpec.getIterationCount();
- if (iterCount == 0) {
- throw new InvalidKeySpecException("Iteration count not found");
- } else if (iterCount < 0) {
- throw new InvalidKeySpecException("Iteration count is negative");
- }
- int keyLength = keySpec.getKeyLength();
- if (keyLength == 0) {
- throw new InvalidKeySpecException("Key length not found");
- } else if (keyLength < 0) {
- throw new InvalidKeySpecException("Key length is negative");
- }
try {
+ this.salt = keySpec.getSalt();
+ if (salt == null) {
+ throw new InvalidKeySpecException("Salt not found");
+ }
+ this.iterCount = keySpec.getIterationCount();
+ if (iterCount == 0) {
+ throw new InvalidKeySpecException("Iteration count not found");
+ } else if (iterCount < 0) {
+ throw new InvalidKeySpecException("Iteration count is negative");
+ }
+ int keyLength = keySpec.getKeyLength();
+ if (keyLength == 0) {
+ throw new InvalidKeySpecException("Key length not found");
+ } else if (keyLength < 0) {
+ throw new InvalidKeySpecException("Key length is negative");
+ }
this.prf = Mac.getInstance(prfAlgo);
// SunPKCS11 requires a non-empty PBE password
if (passwdBytes.length == 0 &&
- this.prf.getProvider().getName().startsWith("SunPKCS11")) {
+ this.prf.getProvider().getName().startsWith("SunPKCS11")) {
this.prf = Mac.getInstance(prfAlgo, SunJCE.getInstance());
}
+ this.key = deriveKey(prf, passwdBytes, salt, iterCount, keyLength);
} catch (NoSuchAlgorithmException nsae) {
// not gonna happen; re-throw just in case
InvalidKeySpecException ike = new InvalidKeySpecException();
ike.initCause(nsae);
throw ike;
- }
- this.key = deriveKey(prf, passwdBytes, salt, iterCount, keyLength);
+ } finally {
+ Arrays.fill(passwdBytes, (byte) 0x00);
- // Use the cleaner to zero the key when no longer referenced
- final byte[] k = this.key;
- final char[] p = this.passwd;
- CleanerFactory.cleaner().register(this,
- () -> {
- java.util.Arrays.fill(k, (byte)0x00);
- java.util.Arrays.fill(p, '0');
- });
+ // Use the cleaner to zero the key when no longer referenced
+ final byte[] k = this.key;
+ final char[] p = this.passwd;
+ CleanerFactory.cleaner().register(this,
+ () -> {
+ Arrays.fill(k, (byte) 0x00);
+ Arrays.fill(p, '\0');
+ });
+ }
}
private static byte[] deriveKey(final Mac prf, final byte[] password,
@@ -266,8 +270,8 @@
if (!(that.getFormat().equalsIgnoreCase("RAW")))
return false;
byte[] thatEncoded = that.getEncoded();
- boolean ret = MessageDigest.isEqual(key, that.getEncoded());
- java.util.Arrays.fill(thatEncoded, (byte)0x00);
+ boolean ret = MessageDigest.isEqual(key, thatEncoded);
+ Arrays.fill(thatEncoded, (byte)0x00);
return ret;
}
--- a/src/java.base/share/classes/com/sun/crypto/provider/PBMAC1Core.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/com/sun/crypto/provider/PBMAC1Core.java Thu Aug 23 11:09:16 2018 -0400
@@ -108,72 +108,76 @@
salt = pbeKey.getSalt(); // maybe null if unspecified
iCount = pbeKey.getIterationCount(); // maybe 0 if unspecified
} else if (key instanceof SecretKey) {
- byte[] passwdBytes = key.getEncoded();
- if ((passwdBytes == null) ||
- !(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3))) {
+ byte[] passwdBytes;
+ if (!(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3)) ||
+ (passwdBytes = key.getEncoded()) == null) {
throw new InvalidKeyException("Missing password");
}
passwdChars = new char[passwdBytes.length];
for (int i=0; i<passwdChars.length; i++) {
passwdChars[i] = (char) (passwdBytes[i] & 0x7f);
}
+ Arrays.fill(passwdBytes, (byte)0x00);
} else {
throw new InvalidKeyException("SecretKey of PBE type required");
}
- if (params == null) {
- // should not auto-generate default values since current
- // javax.crypto.Mac api does not have any method for caller to
- // retrieve the generated defaults.
- if ((salt == null) || (iCount == 0)) {
+
+ PBEKeySpec pbeSpec;
+ try {
+ if (params == null) {
+ // should not auto-generate default values since current
+ // javax.crypto.Mac api does not have any method for caller to
+ // retrieve the generated defaults.
+ if ((salt == null) || (iCount == 0)) {
+ throw new InvalidAlgorithmParameterException
+ ("PBEParameterSpec required for salt and iteration count");
+ }
+ } else if (!(params instanceof PBEParameterSpec)) {
throw new InvalidAlgorithmParameterException
- ("PBEParameterSpec required for salt and iteration count");
- }
- } else if (!(params instanceof PBEParameterSpec)) {
- throw new InvalidAlgorithmParameterException
- ("PBEParameterSpec type required");
- } else {
- PBEParameterSpec pbeParams = (PBEParameterSpec) params;
- // make sure the parameter values are consistent
- if (salt != null) {
- if (!Arrays.equals(salt, pbeParams.getSalt())) {
- throw new InvalidAlgorithmParameterException
- ("Inconsistent value of salt between key and params");
- }
+ ("PBEParameterSpec type required");
} else {
- salt = pbeParams.getSalt();
- }
- if (iCount != 0) {
- if (iCount != pbeParams.getIterationCount()) {
- throw new InvalidAlgorithmParameterException
- ("Different iteration count between key and params");
+ PBEParameterSpec pbeParams = (PBEParameterSpec) params;
+ // make sure the parameter values are consistent
+ if (salt != null) {
+ if (!Arrays.equals(salt, pbeParams.getSalt())) {
+ throw new InvalidAlgorithmParameterException
+ ("Inconsistent value of salt between key and params");
+ }
+ } else {
+ salt = pbeParams.getSalt();
}
- } else {
- iCount = pbeParams.getIterationCount();
+ if (iCount != 0) {
+ if (iCount != pbeParams.getIterationCount()) {
+ throw new InvalidAlgorithmParameterException
+ ("Different iteration count between key and params");
+ }
+ } else {
+ iCount = pbeParams.getIterationCount();
+ }
}
- }
- // For security purpose, we need to enforce a minimum length
- // for salt; just require the minimum salt length to be 8-byte
- // which is what PKCS#5 recommends and openssl does.
- if (salt.length < 8) {
- throw new InvalidAlgorithmParameterException
- ("Salt must be at least 8 bytes long");
- }
- if (iCount <= 0) {
- throw new InvalidAlgorithmParameterException
- ("IterationCount must be a positive number");
+ // For security purpose, we need to enforce a minimum length
+ // for salt; just require the minimum salt length to be 8-byte
+ // which is what PKCS#5 recommends and openssl does.
+ if (salt.length < 8) {
+ throw new InvalidAlgorithmParameterException
+ ("Salt must be at least 8 bytes long");
+ }
+ if (iCount <= 0) {
+ throw new InvalidAlgorithmParameterException
+ ("IterationCount must be a positive number");
+ }
+
+ pbeSpec = new PBEKeySpec(passwdChars, salt, iCount, blockLength);
+ // password char[] was cloned in PBEKeySpec constructor,
+ // so we can zero it out here
+ } finally {
+ Arrays.fill(passwdChars, '\0');
}
- PBEKeySpec pbeSpec =
- new PBEKeySpec(passwdChars, salt, iCount, blockLength);
- // password char[] was cloned in PBEKeySpec constructor,
- // so we can zero it out here
- java.util.Arrays.fill(passwdChars, ' ');
-
- SecretKey s = null;
+ SecretKey s;
PBKDF2Core kdf = getKDFImpl(kdfAlgo);
try {
s = kdf.engineGenerateSecret(pbeSpec);
-
} catch (InvalidKeySpecException ikse) {
InvalidKeyException ike =
new InvalidKeyException("Cannot construct PBE key");
--- a/src/java.base/share/classes/com/sun/crypto/provider/PKCS12PBECipherCore.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/com/sun/crypto/provider/PKCS12PBECipherCore.java Thu Aug 23 11:09:16 2018 -0400
@@ -104,6 +104,7 @@
Arrays.fill(D, (byte)type);
concat(salt, I, 0, s);
concat(passwd, I, s, p);
+ Arrays.fill(passwd, (byte) 0x00);
byte[] Ai;
byte[] B = new byte[v];
@@ -268,87 +269,92 @@
salt = pbeKey.getSalt(); // maybe null if unspecified
iCount = pbeKey.getIterationCount(); // maybe 0 if unspecified
} else if (key instanceof SecretKey) {
- byte[] passwdBytes = key.getEncoded();
- if ((passwdBytes == null) ||
- !(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3))) {
+ byte[] passwdBytes;
+ if (!(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3)) ||
+ (passwdBytes = key.getEncoded()) == null) {
throw new InvalidKeyException("Missing password");
}
passwdChars = new char[passwdBytes.length];
for (int i=0; i<passwdChars.length; i++) {
passwdChars[i] = (char) (passwdBytes[i] & 0x7f);
}
+ Arrays.fill(passwdBytes, (byte)0x00);
} else {
throw new InvalidKeyException("SecretKey of PBE type required");
}
- if (((opmode == Cipher.DECRYPT_MODE) ||
- (opmode == Cipher.UNWRAP_MODE)) &&
- ((params == null) && ((salt == null) || (iCount == 0)))) {
- throw new InvalidAlgorithmParameterException
- ("Parameters missing");
- }
+ try {
+ if (((opmode == Cipher.DECRYPT_MODE) ||
+ (opmode == Cipher.UNWRAP_MODE)) &&
+ ((params == null) && ((salt == null) || (iCount == 0)))) {
+ throw new InvalidAlgorithmParameterException
+ ("Parameters missing");
+ }
- if (params == null) {
- // generate default for salt and iteration count if necessary
- if (salt == null) {
- salt = new byte[DEFAULT_SALT_LENGTH];
- if (random != null) {
- random.nextBytes(salt);
+ if (params == null) {
+ // generate default for salt and iteration count if necessary
+ if (salt == null) {
+ salt = new byte[DEFAULT_SALT_LENGTH];
+ if (random != null) {
+ random.nextBytes(salt);
+ } else {
+ SunJCE.getRandom().nextBytes(salt);
+ }
+ }
+ if (iCount == 0) iCount = DEFAULT_COUNT;
+ } else if (!(params instanceof PBEParameterSpec)) {
+ throw new InvalidAlgorithmParameterException
+ ("PBEParameterSpec type required");
+ } else {
+ PBEParameterSpec pbeParams = (PBEParameterSpec) params;
+ // make sure the parameter values are consistent
+ if (salt != null) {
+ if (!Arrays.equals(salt, pbeParams.getSalt())) {
+ throw new InvalidAlgorithmParameterException
+ ("Inconsistent value of salt between key and params");
+ }
} else {
- SunJCE.getRandom().nextBytes(salt);
+ salt = pbeParams.getSalt();
+ }
+ if (iCount != 0) {
+ if (iCount != pbeParams.getIterationCount()) {
+ throw new InvalidAlgorithmParameterException
+ ("Different iteration count between key and params");
+ }
+ } else {
+ iCount = pbeParams.getIterationCount();
}
}
- if (iCount == 0) iCount = DEFAULT_COUNT;
- } else if (!(params instanceof PBEParameterSpec)) {
- throw new InvalidAlgorithmParameterException
- ("PBEParameterSpec type required");
- } else {
- PBEParameterSpec pbeParams = (PBEParameterSpec) params;
- // make sure the parameter values are consistent
- if (salt != null) {
- if (!Arrays.equals(salt, pbeParams.getSalt())) {
- throw new InvalidAlgorithmParameterException
- ("Inconsistent value of salt between key and params");
- }
- } else {
- salt = pbeParams.getSalt();
+ // salt is recommended to be ideally as long as the output
+ // of the hash function. However, it may be too strict to
+ // force this; so instead, we'll just require the minimum
+ // salt length to be 8-byte which is what PKCS#5 recommends
+ // and openssl does.
+ if (salt.length < 8) {
+ throw new InvalidAlgorithmParameterException
+ ("Salt must be at least 8 bytes long");
}
- if (iCount != 0) {
- if (iCount != pbeParams.getIterationCount()) {
- throw new InvalidAlgorithmParameterException
- ("Different iteration count between key and params");
- }
- } else {
- iCount = pbeParams.getIterationCount();
+ if (iCount <= 0) {
+ throw new InvalidAlgorithmParameterException
+ ("IterationCount must be a positive number");
}
- }
- // salt is recommended to be ideally as long as the output
- // of the hash function. However, it may be too strict to
- // force this; so instead, we'll just require the minimum
- // salt length to be 8-byte which is what PKCS#5 recommends
- // and openssl does.
- if (salt.length < 8) {
- throw new InvalidAlgorithmParameterException
- ("Salt must be at least 8 bytes long");
- }
- if (iCount <= 0) {
- throw new InvalidAlgorithmParameterException
- ("IterationCount must be a positive number");
- }
- byte[] derivedKey = derive(passwdChars, salt, iCount,
- keySize, CIPHER_KEY);
- SecretKey cipherKey = new SecretKeySpec(derivedKey, algo);
+ byte[] derivedKey = derive(passwdChars, salt, iCount,
+ keySize, CIPHER_KEY);
+ SecretKey cipherKey = new SecretKeySpec(derivedKey, algo);
+
+ if (cipherImpl != null && cipherImpl instanceof ARCFOURCipher) {
+ ((ARCFOURCipher)cipherImpl).engineInit(opmode, cipherKey, random);
- if (cipherImpl != null && cipherImpl instanceof ARCFOURCipher) {
- ((ARCFOURCipher)cipherImpl).engineInit(opmode, cipherKey, random);
+ } else {
+ byte[] derivedIv = derive(passwdChars, salt, iCount, 8,
+ CIPHER_IV);
+ IvParameterSpec ivSpec = new IvParameterSpec(derivedIv, 0, 8);
- } else {
- byte[] derivedIv = derive(passwdChars, salt, iCount, 8,
- CIPHER_IV);
- IvParameterSpec ivSpec = new IvParameterSpec(derivedIv, 0, 8);
-
- // initialize the underlying cipher
- cipher.init(opmode, cipherKey, ivSpec, random);
+ // initialize the underlying cipher
+ cipher.init(opmode, cipherKey, ivSpec, random);
+ }
+ } finally {
+ Arrays.fill(passwdChars, '\0');
}
}
--- a/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java Thu Aug 23 11:09:16 2018 -0400
@@ -118,7 +118,8 @@
final String BLOCK_PADS = "NOPADDING|PKCS5PADDING|ISO10126PADDING";
AccessController.doPrivileged(
- new java.security.PrivilegedAction<>() {
+ new java.security.PrivilegedAction<Object>() {
+ @Override
public Object run() {
/*
--- a/src/java.base/share/classes/com/sun/security/ntlm/NTLM.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/com/sun/security/ntlm/NTLM.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,8 @@
package com.sun.security.ntlm;
+import sun.security.action.GetBooleanAction;
+
import static com.sun.security.ntlm.Version.*;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
@@ -55,10 +57,8 @@
private final MessageDigest md4;
private final Mac hmac;
private final MessageDigest md5;
- private static final boolean DEBUG =
- java.security.AccessController.doPrivileged(
- new sun.security.action.GetBooleanAction("ntlm.debug"))
- .booleanValue();
+ private static final boolean DEBUG
+ = GetBooleanAction.privilegedGetProperty("ntlm.debug");
final Version v;
--- a/src/java.base/share/classes/java/lang/Enum.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/java/lang/Enum.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* 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 @@
* java.util.EnumMap map} implementations are available.
*
* @param <E> The enum type subclass
+ * @serial exclude
* @author Josh Bloch
* @author Neal Gafter
* @see Class#getEnumConstants()
--- a/src/java.base/share/classes/java/lang/Integer.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/java/lang/Integer.java Thu Aug 23 11:09:16 2018 -0400
@@ -635,11 +635,11 @@
negative = true;
limit = Integer.MIN_VALUE;
} else if (firstChar != '+') {
- throw NumberFormatException.forInputString(s);
+ throw NumberFormatException.forInputString(s, radix);
}
if (len == 1) { // Cannot have lone "+" or "-"
- throw NumberFormatException.forInputString(s);
+ throw NumberFormatException.forInputString(s, radix);
}
i++;
}
@@ -649,17 +649,17 @@
// Accumulating negatively avoids surprises near MAX_VALUE
int digit = Character.digit(s.charAt(i++), radix);
if (digit < 0 || result < multmin) {
- throw NumberFormatException.forInputString(s);
+ throw NumberFormatException.forInputString(s, radix);
}
result *= radix;
if (result < limit + digit) {
- throw NumberFormatException.forInputString(s);
+ throw NumberFormatException.forInputString(s, radix);
}
result -= digit;
}
return negative ? result : -result;
} else {
- throw NumberFormatException.forInputString(s);
+ throw NumberFormatException.forInputString(s, radix);
}
}
@@ -745,7 +745,7 @@
}
return negative ? result : -result;
} else {
- throw NumberFormatException.forInputString("");
+ throw NumberFormatException.forInputString("", radix);
}
}
@@ -842,7 +842,7 @@
}
}
} else {
- throw NumberFormatException.forInputString(s);
+ throw NumberFormatException.forInputString(s, radix);
}
}
@@ -997,7 +997,8 @@
private static class IntegerCache {
static final int low = -128;
static final int high;
- static final Integer cache[];
+ static final Integer[] cache;
+ static Integer[] archivedCache;
static {
// high value may be configured by property
@@ -1016,11 +1017,19 @@
}
high = h;
- cache = new Integer[(high - low) + 1];
- int j = low;
- for(int k = 0; k < cache.length; k++)
- cache[k] = new Integer(j++);
+ // Load IntegerCache.archivedCache from archive, if possible
+ VM.initializeFromArchive(IntegerCache.class);
+ int size = (high - low) + 1;
+ // Use the archived cache if it exists and is large enough
+ if (archivedCache == null || size > archivedCache.length) {
+ Integer[] c = new Integer[size];
+ int j = low;
+ for(int k = 0; k < c.length; k++)
+ c[k] = new Integer(j++);
+ archivedCache = c;
+ }
+ cache = archivedCache;
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
--- a/src/java.base/share/classes/java/lang/Long.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/java/lang/Long.java Thu Aug 23 11:09:16 2018 -0400
@@ -675,11 +675,11 @@
negative = true;
limit = Long.MIN_VALUE;
} else if (firstChar != '+') {
- throw NumberFormatException.forInputString(s);
+ throw NumberFormatException.forInputString(s, radix);
}
if (len == 1) { // Cannot have lone "+" or "-"
- throw NumberFormatException.forInputString(s);
+ throw NumberFormatException.forInputString(s, radix);
}
i++;
}
@@ -689,17 +689,17 @@
// Accumulating negatively avoids surprises near MAX_VALUE
int digit = Character.digit(s.charAt(i++),radix);
if (digit < 0 || result < multmin) {
- throw NumberFormatException.forInputString(s);
+ throw NumberFormatException.forInputString(s, radix);
}
result *= radix;
if (result < limit + digit) {
- throw NumberFormatException.forInputString(s);
+ throw NumberFormatException.forInputString(s, radix);
}
result -= digit;
}
return negative ? result : -result;
} else {
- throw NumberFormatException.forInputString(s);
+ throw NumberFormatException.forInputString(s, radix);
}
}
@@ -945,7 +945,7 @@
return result;
}
} else {
- throw NumberFormatException.forInputString(s);
+ throw NumberFormatException.forInputString(s, radix);
}
}
@@ -1063,7 +1063,7 @@
return result;
}
} else {
- throw NumberFormatException.forInputString("");
+ throw NumberFormatException.forInputString("", radix);
}
}
--- a/src/java.base/share/classes/java/lang/NumberFormatException.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/java/lang/NumberFormatException.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -61,8 +61,11 @@
*
* @param s the input causing the error
*/
- static NumberFormatException forInputString(String s) {
- return new NumberFormatException("For input string: \"" + s + "\"");
+ static NumberFormatException forInputString(String s, int radix) {
+ return new NumberFormatException("For input string: \"" + s + "\"" +
+ (radix == 10 ?
+ "" :
+ " under radix " + radix));
}
/**
--- a/src/java.base/share/classes/java/lang/Package.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/java/lang/Package.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -286,7 +286,7 @@
for (int i = 0; i < sa.length; i++) {
si[i] = Integer.parseInt(sa[i]);
if (si[i] < 0)
- throw NumberFormatException.forInputString("" + si[i]);
+ throw NumberFormatException.forInputString("" + si[i], 10);
}
String [] da = desired.split("\\.", -1);
@@ -294,7 +294,7 @@
for (int i = 0; i < da.length; i++) {
di[i] = Integer.parseInt(da[i]);
if (di[i] < 0)
- throw NumberFormatException.forInputString("" + di[i]);
+ throw NumberFormatException.forInputString("" + di[i], 10);
}
int len = Math.max(di.length, si.length);
--- a/src/java.base/share/classes/java/lang/StringCoding.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/java/lang/StringCoding.java Thu Aug 23 11:09:16 2018 -0400
@@ -1068,7 +1068,7 @@
byte[] val = s.value();
byte coder = s.coder();
if (cs == UTF_8) {
- if (isASCII(val)) {
+ if (coder == LATIN1 && isASCII(val)) {
return val;
}
return encodeUTF8(coder, val, false);
--- a/src/java.base/share/classes/java/lang/invoke/MethodType.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/java/lang/invoke/MethodType.java Thu Aug 23 11:09:16 2018 -0400
@@ -786,9 +786,25 @@
* @param x object to compare
* @see Object#equals(Object)
*/
+ // This implementation may also return true if x is a WeakEntry containing
+ // a method type that is equal to this. This is an internal implementation
+ // detail to allow for faster method type lookups.
+ // See ConcurrentWeakInternSet.WeakEntry#equals(Object)
@Override
public boolean equals(Object x) {
- return this == x || x instanceof MethodType && equals((MethodType)x);
+ if (this == x) {
+ return true;
+ }
+ if (x instanceof MethodType) {
+ return equals((MethodType)x);
+ }
+ if (x instanceof ConcurrentWeakInternSet.WeakEntry) {
+ Object o = ((ConcurrentWeakInternSet.WeakEntry)x).get();
+ if (o instanceof MethodType) {
+ return equals((MethodType)o);
+ }
+ }
+ return false;
}
private boolean equals(MethodType that) {
@@ -808,10 +824,10 @@
*/
@Override
public int hashCode() {
- int hashCode = 31 + rtype.hashCode();
- for (Class<?> ptype : ptypes)
- hashCode = 31*hashCode + ptype.hashCode();
- return hashCode;
+ int hashCode = 31 + rtype.hashCode();
+ for (Class<?> ptype : ptypes)
+ hashCode = 31 * hashCode + ptype.hashCode();
+ return hashCode;
}
/**
@@ -1286,7 +1302,7 @@
if (elem == null) throw new NullPointerException();
expungeStaleElements();
- WeakEntry<T> value = map.get(new WeakEntry<>(elem));
+ WeakEntry<T> value = map.get(elem);
if (value != null) {
T res = value.get();
if (res != null) {
@@ -1338,19 +1354,25 @@
hashcode = key.hashCode();
}
- public WeakEntry(T key) {
- super(key);
- hashcode = key.hashCode();
- }
-
+ /**
+ * This implementation returns {@code true} if {@code obj} is another
+ * {@code WeakEntry} whose referent is equals to this referent, or
+ * if {@code obj} is equals to the referent of this. This allows
+ * lookups to be made without wrapping in a {@code WeakEntry}.
+ *
+ * @param obj the object to compare
+ * @return true if {@code obj} is equals to this or the referent of this
+ * @see MethodType#equals(Object)
+ * @see Object#equals(Object)
+ */
@Override
public boolean equals(Object obj) {
+ Object mine = get();
if (obj instanceof WeakEntry) {
Object that = ((WeakEntry) obj).get();
- Object mine = get();
return (that == null || mine == null) ? (this == obj) : mine.equals(that);
}
- return false;
+ return (mine == null) ? (obj == null) : mine.equals(obj);
}
@Override
--- a/src/java.base/share/classes/java/security/Key.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/java/security/Key.java Thu Aug 23 11:09:16 2018 -0400
@@ -108,8 +108,12 @@
* The class fingerprint that is set to indicate
* serialization compatibility with a previous
* version of the class.
+ *
+ * @deprecated A {@code serialVersionUID} field in an interface is
+ * ineffectual. Do not use; no replacement.
*/
- @SuppressWarnings("serial") // serialVersionUID in an interface is ineffectual
+ @Deprecated
+ @SuppressWarnings("serial")
static final long serialVersionUID = 6603384152749567654L;
/**
--- a/src/java.base/share/classes/java/security/PrivateKey.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/java/security/PrivateKey.java Thu Aug 23 11:09:16 2018 -0400
@@ -63,7 +63,11 @@
/**
* The class fingerprint that is set to indicate serialization
* compatibility with a previous version of the class.
- */
- @SuppressWarnings("serial") // serialVersionUID in an interface is ineffectual
+ *
+ * @deprecated A {@code serialVersionUID} field in an interface is
+ * ineffectual. Do not use; no replacement.
+ */
+ @Deprecated
+ @SuppressWarnings("serial")
static final long serialVersionUID = 6034044314589513430L;
}
--- a/src/java.base/share/classes/java/security/PublicKey.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/java/security/PublicKey.java Thu Aug 23 11:09:16 2018 -0400
@@ -49,7 +49,11 @@
/**
* The class fingerprint that is set to indicate serialization
* compatibility with a previous version of the class.
+ *
+ * @deprecated A {@code serialVersionUID} field in an interface is
+ * ineffectual. Do not use; no replacement.
*/
- @SuppressWarnings("serial") // serialVersionUID in an interface is ineffectual
+ @Deprecated
+ @SuppressWarnings("serial")
static final long serialVersionUID = 7187392471159151072L;
}
--- a/src/java.base/share/classes/java/security/interfaces/DSAPrivateKey.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/java/security/interfaces/DSAPrivateKey.java Thu Aug 23 11:09:16 2018 -0400
@@ -47,8 +47,12 @@
* The class fingerprint that is set to indicate
* serialization compatibility with a previous
* version of the class.
+ *
+ * @deprecated A {@code serialVersionUID} field in an interface is
+ * ineffectual. Do not use; no replacement.
*/
- @SuppressWarnings("serial") // serialVersionUID in an interface is ineffectual
+ @Deprecated
+ @SuppressWarnings("serial")
static final long serialVersionUID = 7776497482533790279L;
/**
--- a/src/java.base/share/classes/java/security/interfaces/DSAPublicKey.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/java/security/interfaces/DSAPublicKey.java Thu Aug 23 11:09:16 2018 -0400
@@ -47,8 +47,12 @@
* The class fingerprint that is set to indicate
* serialization compatibility with a previous
* version of the class.
+ *
+ * @deprecated A {@code serialVersionUID} field in an interface is
+ * ineffectual. Do not use; no replacement.
*/
- @SuppressWarnings("serial") // serialVersionUID in an interface is ineffectual
+ @Deprecated
+ @SuppressWarnings("serial")
static final long serialVersionUID = 1234526332779022332L;
/**
--- a/src/java.base/share/classes/java/security/interfaces/ECPrivateKey.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/java/security/interfaces/ECPrivateKey.java Thu Aug 23 11:09:16 2018 -0400
@@ -42,8 +42,12 @@
/**
* The class fingerprint that is set to indicate
* serialization compatibility.
+ *
+ * @deprecated A {@code serialVersionUID} field in an interface is
+ * ineffectual. Do not use; no replacement.
*/
- @SuppressWarnings("serial") // serialVersionUID in an interface is ineffectual
+ @Deprecated
+ @SuppressWarnings("serial")
static final long serialVersionUID = -7896394956925609184L;
/**
--- a/src/java.base/share/classes/java/security/interfaces/ECPublicKey.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/java/security/interfaces/ECPublicKey.java Thu Aug 23 11:09:16 2018 -0400
@@ -44,8 +44,12 @@
/**
* The class fingerprint that is set to indicate
* serialization compatibility.
+ *
+ * @deprecated A {@code serialVersionUID} field in an interface is
+ * ineffectual. Do not use; no replacement.
*/
- @SuppressWarnings("serial") // serialVersionUID in an interface is ineffectual
+ @Deprecated
+ @SuppressWarnings("serial")
static final long serialVersionUID = -3314988629879632826L;
/**
--- a/src/java.base/share/classes/java/security/interfaces/RSAMultiPrimePrivateCrtKey.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/java/security/interfaces/RSAMultiPrimePrivateCrtKey.java Thu Aug 23 11:09:16 2018 -0400
@@ -50,8 +50,12 @@
* The type fingerprint that is set to indicate
* serialization compatibility with a previous
* version of the type.
+ *
+ * @deprecated A {@code serialVersionUID} field in an interface is
+ * ineffectual. Do not use; no replacement.
*/
- @SuppressWarnings("serial") // serialVersionUID in an interface is ineffectual
+ @Deprecated
+ @SuppressWarnings("serial")
static final long serialVersionUID = 618058533534628008L;
/**
--- a/src/java.base/share/classes/java/security/interfaces/RSAPrivateCrtKey.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/java/security/interfaces/RSAPrivateCrtKey.java Thu Aug 23 11:09:16 2018 -0400
@@ -45,8 +45,12 @@
* The type fingerprint that is set to indicate
* serialization compatibility with a previous
* version of the type.
+ *
+ * @deprecated A {@code serialVersionUID} field in an interface is
+ * ineffectual. Do not use; no replacement.
*/
- @SuppressWarnings("serial") // serialVersionUID in an interface is ineffectual
+ @Deprecated
+ @SuppressWarnings("serial")
static final long serialVersionUID = -5682214253527700368L;
/**
--- a/src/java.base/share/classes/java/security/interfaces/RSAPrivateKey.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/java/security/interfaces/RSAPrivateKey.java Thu Aug 23 11:09:16 2018 -0400
@@ -44,8 +44,12 @@
* The type fingerprint that is set to indicate
* serialization compatibility with a previous
* version of the type.
+ *
+ * @deprecated A {@code serialVersionUID} field in an interface is
+ * ineffectual. Do not use; no replacement.
*/
- @SuppressWarnings("serial") // serialVersionUID in an interface is ineffectual
+ @Deprecated
+ @SuppressWarnings("serial")
static final long serialVersionUID = 5187144804936595022L;
/**
--- a/src/java.base/share/classes/java/security/interfaces/RSAPublicKey.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/java/security/interfaces/RSAPublicKey.java Thu Aug 23 11:09:16 2018 -0400
@@ -41,8 +41,12 @@
* The type fingerprint that is set to indicate
* serialization compatibility with a previous
* version of the type.
+ *
+ * @deprecated A {@code serialVersionUID} field in an interface is
+ * ineffectual. Do not use; no replacement.
*/
- @SuppressWarnings("serial") // serialVersionUID in an interface is ineffectual
+ @Deprecated
+ @SuppressWarnings("serial")
static final long serialVersionUID = -8727434096241101194L;
/**
--- a/src/java.base/share/classes/javax/crypto/SecretKey.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/javax/crypto/SecretKey.java Thu Aug 23 11:09:16 2018 -0400
@@ -63,7 +63,11 @@
/**
* The class fingerprint that is set to indicate serialization
* compatibility since J2SE 1.4.
+ *
+ * @deprecated A {@code serialVersionUID} field in an interface is
+ * ineffectual. Do not use; no replacement.
*/
- @SuppressWarnings("serial") // serialVersionUID in an interface is ineffectual
+ @Deprecated
+ @SuppressWarnings("serial")
static final long serialVersionUID = -4795878709595146952L;
}
--- a/src/java.base/share/classes/javax/crypto/interfaces/DHPrivateKey.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/javax/crypto/interfaces/DHPrivateKey.java Thu Aug 23 11:09:16 2018 -0400
@@ -41,8 +41,12 @@
/**
* The class fingerprint that is set to indicate serialization
* compatibility since J2SE 1.4.
+ *
+ * @deprecated A {@code serialVersionUID} field in an interface is
+ * ineffectual. Do not use; no replacement.
*/
- @SuppressWarnings("serial") // serialVersionUID in an interface is ineffectual
+ @Deprecated
+ @SuppressWarnings("serial")
static final long serialVersionUID = 2211791113380396553L;
/**
--- a/src/java.base/share/classes/javax/crypto/interfaces/DHPublicKey.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/javax/crypto/interfaces/DHPublicKey.java Thu Aug 23 11:09:16 2018 -0400
@@ -41,8 +41,12 @@
/**
* The class fingerprint that is set to indicate serialization
* compatibility since J2SE 1.4.
+ *
+ * @deprecated A {@code serialVersionUID} field in an interface is
+ * ineffectual. Do not use; no replacement.
*/
- @SuppressWarnings("serial") // serialVersionUID in an interface is ineffectual
+ @Deprecated
+ @SuppressWarnings("serial")
static final long serialVersionUID = -6628103563352519193L;
/**
--- a/src/java.base/share/classes/javax/crypto/interfaces/PBEKey.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/javax/crypto/interfaces/PBEKey.java Thu Aug 23 11:09:16 2018 -0400
@@ -41,8 +41,12 @@
/**
* The class fingerprint that is set to indicate serialization
* compatibility since J2SE 1.4.
+ *
+ * @deprecated A {@code serialVersionUID} field in an interface is
+ * ineffectual. Do not use; no replacement.
*/
- @SuppressWarnings("serial") // serialVersionUID in an interface is ineffectual
+ @Deprecated
+ @SuppressWarnings("serial")
static final long serialVersionUID = -1430015993304333921L;
/**
--- a/src/java.base/share/classes/javax/net/ssl/SSLEngine.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/javax/net/ssl/SSLEngine.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -145,7 +145,7 @@
* application messages are encrypted and integrity protected,
* and inbound messages reverse the process.
*
- * <li> Rehandshaking - Either side may request a renegotiation of
+ * <li> Rehandshaking - Either side may request a renegotiation of
* the session at any time during the Application Data phase. New
* handshaking data can be intermixed among the application data.
* Before starting the rehandshake phase, the application may
@@ -156,12 +156,20 @@
* configuration settings will not be used until the next
* handshake.
*
- * <li> Closure - When the connection is no longer needed, the
- * application should close the {@code SSLEngine} and should
- * send/receive any remaining messages to the peer before
- * closing the underlying transport mechanism. Once an engine is
- * closed, it is not reusable: a new {@code SSLEngine} must
- * be created.
+ * <li> Closure - When the connection is no longer needed, the client
+ * and the server applications should each close both sides of their
+ * respective connections. For {@code SSLEngine} objects, an
+ * application should call {@link SSLEngine#closeOutbound()} and
+ * send any remaining messages to the peer. Likewise, an application
+ * should receive any remaining messages from the peer before calling
+ * {@link SSLEngine#closeInbound()}. The underlying transport mechanism
+ * can then be closed after both sides of the {@code SSLEngine} have
+ * been closed. If the connection is not closed in an orderly manner
+ * (for example {@link SSLEngine#closeInbound()} is called before the
+ * peer's write closure notification has been received), exceptions
+ * will be raised to indicate that an error has occurred. Once an
+ * engine is closed, it is not reusable: a new {@code SSLEngine}
+ * must be created.
* </OL>
* An {@code SSLEngine} is created by calling {@link
* SSLContext#createSSLEngine()} from an initialized
@@ -229,7 +237,7 @@
* BUFFER_UNDERFLOW:
* int netSize = engine.getSession().getPacketBufferSize();
* // Resize buffer if needed.
- * if (netSize > dst.capacity()) {
+ * if (netSize > src.capacity()) {
* ByteBuffer b = ByteBuffer.allocate(netSize);
* src.flip();
* b.put(src);
--- a/src/java.base/share/classes/javax/net/ssl/SSLSocket.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/javax/net/ssl/SSLSocket.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -130,6 +130,21 @@
* socket can not switch between client and server modes, even when
* performing renegotiations.
*
+ * @apiNote
+ * When the connection is no longer needed, the client and server
+ * applications should each close both sides of their respective connection.
+ * For {@code SSLSocket} objects, for example, an application can call
+ * {@link Socket#shutdownOutput()} or {@link java.io.OutputStream#close()}
+ * for output strean close and call {@link Socket#shutdownInput()} or
+ * {@link java.io.InputStream#close()} for input stream close. Note that
+ * in some cases, closing the input stream may depend on the peer's output
+ * stream being closed first. If the connection is not closed in an orderly
+ * manner (for example {@link Socket#shutdownInput()} is called before the
+ * peer's write closure notification has been received), exceptions may
+ * be raised to indicate that an error has occurred. Once an
+ * {@code SSLSocket} is closed, it is not reusable: a new {@code SSLSocket}
+ * must be created.
+ *
* @see java.net.Socket
* @see SSLServerSocket
* @see SSLSocketFactory
--- a/src/java.base/share/classes/sun/security/action/GetBooleanAction.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/sun/security/action/GetBooleanAction.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,8 @@
package sun.security.action;
+import java.security.AccessController;
+
/**
* A convenience class for retrieving the boolean value of a system property
* as a privileged action.
@@ -69,4 +71,25 @@
public Boolean run() {
return Boolean.getBoolean(theProp);
}
+
+ /**
+ * Convenience method to get a property without going through doPrivileged
+ * if no security manager is present. This is unsafe for inclusion in a
+ * public API but allowable here since this class is now encapsulated.
+ *
+ * Note that this method performs a privileged action using caller-provided
+ * inputs. The caller of this method should take care to ensure that the
+ * inputs are not tainted and the returned property is not made accessible
+ * to untrusted code if it contains sensitive information.
+ *
+ * @param theProp the name of the system property.
+ */
+ public static boolean privilegedGetProperty(String theProp) {
+ if (System.getSecurityManager() == null) {
+ return Boolean.getBoolean(theProp);
+ } else {
+ return AccessController.doPrivileged(
+ new GetBooleanAction(theProp));
+ }
+ }
}
--- a/src/java.base/share/classes/sun/security/internal/interfaces/TlsMasterSecret.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/sun/security/internal/interfaces/TlsMasterSecret.java Thu Aug 23 11:09:16 2018 -0400
@@ -44,7 +44,12 @@
@Deprecated
public interface TlsMasterSecret extends SecretKey {
- @SuppressWarnings("serial") // serialVersionUID in an interface is ineffectual
+ /***
+ * @deprecated A {@code serialVersionUID} field in an interface is
+ * ineffectual. Do not use; no replacement.
+ */
+ @Deprecated
+ @SuppressWarnings("serial")
public static final long serialVersionUID = -461748105810469773L;
/**
--- a/src/java.base/share/classes/sun/security/internal/spec/TlsRsaPremasterSecretParameterSpec.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/sun/security/internal/spec/TlsRsaPremasterSecretParameterSpec.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,9 +25,9 @@
package sun.security.internal.spec;
+import sun.security.action.GetBooleanAction;
+
import java.security.spec.AlgorithmParameterSpec;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
/**
* Parameters for SSL/TLS RSA premaster secret.
@@ -51,25 +51,11 @@
* requested in its client hello version). However, we (and other
* implementations) used to send the active negotiated version. The
* system property below allows to toggle the behavior.
- */
- private static final String PROP_NAME =
- "com.sun.net.ssl.rsaPreMasterSecretFix";
-
- /*
* Default is "false" (old behavior) for compatibility reasons in
* SSLv3/TLSv1. Later protocols (TLSv1.1+) do not use this property.
*/
- private static final boolean rsaPreMasterSecretFix =
- AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
- public Boolean run() {
- String value = System.getProperty(PROP_NAME);
- if (value != null && value.equalsIgnoreCase("true")) {
- return Boolean.TRUE;
- }
-
- return Boolean.FALSE;
- }
- });
+ private static final boolean rsaPreMasterSecretFix = GetBooleanAction
+ .privilegedGetProperty("com.sun.net.ssl.rsaPreMasterSecretFix");
private final int clientVersion;
private final int serverVersion;
--- a/src/java.base/share/classes/sun/security/provider/DSAKeyFactory.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/sun/security/provider/DSAKeyFactory.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -30,7 +30,6 @@
import java.security.PrivateKey;
import java.security.KeyFactorySpi;
import java.security.InvalidKeyException;
-import java.security.AccessController;
import java.security.interfaces.DSAParams;
import java.security.spec.DSAPublicKeySpec;
import java.security.spec.DSAPrivateKeySpec;
@@ -39,8 +38,6 @@
import java.security.spec.X509EncodedKeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
-import sun.security.action.GetPropertyAction;
-
/**
* This class implements the DSA key factory of the Sun provider.
*
@@ -51,29 +48,6 @@
*/
public class DSAKeyFactory extends KeyFactorySpi {
-
- // package private for DSAKeyPairGenerator
- static final boolean SERIAL_INTEROP;
- private static final String SERIAL_PROP = "sun.security.key.serial.interop";
-
- static {
-
- /**
- * Check to see if we need to maintain interoperability for serialized
- * keys between JDK 5.0 -> JDK 1.4. In other words, determine whether
- * a key object serialized in JDK 5.0 must be deserializable in
- * JDK 1.4.
- *
- * If true, then we generate sun.security.provider.DSAPublicKey.
- * If false, then we generate sun.security.provider.DSAPublicKeyImpl.
- *
- * By default this is false.
- * This incompatibility was introduced by 4532506.
- */
- String prop = GetPropertyAction.privilegedGetProperty(SERIAL_PROP);
- SERIAL_INTEROP = "true".equalsIgnoreCase(prop);
- }
-
/**
* Generates a public key object from the provided key specification
* (key material).
@@ -90,25 +64,13 @@
try {
if (keySpec instanceof DSAPublicKeySpec) {
DSAPublicKeySpec dsaPubKeySpec = (DSAPublicKeySpec)keySpec;
- if (SERIAL_INTEROP) {
- return new DSAPublicKey(dsaPubKeySpec.getY(),
- dsaPubKeySpec.getP(),
- dsaPubKeySpec.getQ(),
- dsaPubKeySpec.getG());
- } else {
- return new DSAPublicKeyImpl(dsaPubKeySpec.getY(),
- dsaPubKeySpec.getP(),
- dsaPubKeySpec.getQ(),
- dsaPubKeySpec.getG());
- }
+ return new DSAPublicKeyImpl(dsaPubKeySpec.getY(),
+ dsaPubKeySpec.getP(),
+ dsaPubKeySpec.getQ(),
+ dsaPubKeySpec.getG());
} else if (keySpec instanceof X509EncodedKeySpec) {
- if (SERIAL_INTEROP) {
- return new DSAPublicKey
- (((X509EncodedKeySpec)keySpec).getEncoded());
- } else {
- return new DSAPublicKeyImpl
- (((X509EncodedKeySpec)keySpec).getEncoded());
- }
+ return new DSAPublicKeyImpl
+ (((X509EncodedKeySpec)keySpec).getEncoded());
} else {
throw new InvalidKeySpecException
("Inappropriate key specification");
--- a/src/java.base/share/classes/sun/security/provider/DSAKeyPairGenerator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/sun/security/provider/DSAKeyPairGenerator.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -166,11 +166,7 @@
// See the comments in DSAKeyFactory, 4532506, and 6232513.
DSAPublicKey pub;
- if (DSAKeyFactory.SERIAL_INTEROP) {
- pub = new DSAPublicKey(y, p, q, g);
- } else {
- pub = new DSAPublicKeyImpl(y, p, q, g);
- }
+ pub = new DSAPublicKeyImpl(y, p, q, g);
DSAPrivateKey priv = new DSAPrivateKey(x, p, q, g);
KeyPair pair = new KeyPair(pub, priv);
--- a/src/java.base/share/classes/sun/security/provider/DigestBase.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/sun/security/provider/DigestBase.java Thu Aug 23 11:09:16 2018 -0400
@@ -28,6 +28,7 @@
import java.security.MessageDigestSpi;
import java.security.DigestException;
import java.security.ProviderException;
+import java.util.Arrays;
import java.util.Objects;
import jdk.internal.HotSpotIntrinsicCandidate;
@@ -178,6 +179,7 @@
implReset();
bufOfs = 0;
bytesProcessed = 0;
+ Arrays.fill(buffer, (byte) 0x00);
}
// return the digest. See JCA doc.
--- a/src/java.base/share/classes/sun/security/provider/MD4.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/sun/security/provider/MD4.java Thu Aug 23 11:09:16 2018 -0400
@@ -26,6 +26,7 @@
package sun.security.provider;
import java.security.*;
+import java.util.Arrays;
import static sun.security.provider.ByteArrayAccess.*;
import static sun.security.util.SecurityConstants.PROVIDER_VER;
@@ -92,7 +93,7 @@
super("MD4", 16, 64);
state = new int[4];
x = new int[16];
- implReset();
+ resetHashes();
}
// clone this object
@@ -108,6 +109,12 @@
*/
void implReset() {
// Load magic initialization constants.
+ resetHashes();
+ // clear out old data
+ Arrays.fill(x, 0);
+ }
+
+ private void resetHashes() {
state[0] = 0x67452301;
state[1] = 0xefcdab89;
state[2] = 0x98badcfe;
--- a/src/java.base/share/classes/sun/security/provider/MD5.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/sun/security/provider/MD5.java Thu Aug 23 11:09:16 2018 -0400
@@ -25,6 +25,8 @@
package sun.security.provider;
+import java.util.Arrays;
+
import static sun.security.provider.ByteArrayAccess.*;
/**
@@ -66,7 +68,7 @@
super("MD5", 16, 64);
state = new int[4];
x = new int[16];
- implReset();
+ resetHashes();
}
// clone this object
@@ -82,6 +84,12 @@
*/
void implReset() {
// Load magic initialization constants.
+ resetHashes();
+ // clear out old data
+ Arrays.fill(x, 0);
+ }
+
+ private void resetHashes() {
state[0] = 0x67452301;
state[1] = 0xefcdab89;
state[2] = 0x98badcfe;
--- a/src/java.base/share/classes/sun/security/provider/SHA.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/sun/security/provider/SHA.java Thu Aug 23 11:09:16 2018 -0400
@@ -25,6 +25,7 @@
package sun.security.provider;
+import java.util.Arrays;
import java.util.Objects;
import static sun.security.provider.ByteArrayAccess.*;
@@ -62,7 +63,7 @@
super("SHA-1", 20, 64);
state = new int[5];
W = new int[80];
- implReset();
+ resetHashes();
}
/*
@@ -79,6 +80,13 @@
* Resets the buffers and hash value to start a new hash.
*/
void implReset() {
+ // Load magic initialization constants.
+ resetHashes();
+ // clear out old data
+ Arrays.fill(W, 0);
+ }
+
+ private void resetHashes() {
state[0] = 0x67452301;
state[1] = 0xefcdab89;
state[2] = 0x98badcfe;
--- a/src/java.base/share/classes/sun/security/provider/SHA2.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/sun/security/provider/SHA2.java Thu Aug 23 11:09:16 2018 -0400
@@ -25,6 +25,7 @@
package sun.security.provider;
+import java.util.Arrays;
import java.util.Objects;
import jdk.internal.HotSpotIntrinsicCandidate;
@@ -83,13 +84,18 @@
this.initialHashes = initialHashes;
state = new int[8];
W = new int[64];
- implReset();
+ resetHashes();
}
/**
* Resets the buffers and hash value to start a new hash.
*/
void implReset() {
+ resetHashes();
+ Arrays.fill(W, 0);
+ }
+
+ private void resetHashes() {
System.arraycopy(initialHashes, 0, state, 0, state.length);
}
--- a/src/java.base/share/classes/sun/security/provider/SHA5.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/sun/security/provider/SHA5.java Thu Aug 23 11:09:16 2018 -0400
@@ -25,6 +25,7 @@
package sun.security.provider;
+import java.util.Arrays;
import java.util.Objects;
import jdk.internal.HotSpotIntrinsicCandidate;
@@ -98,10 +99,15 @@
this.initialHashes = initialHashes;
state = new long[8];
W = new long[80];
- implReset();
+ resetHashes();
}
final void implReset() {
+ resetHashes();
+ Arrays.fill(W, 0L);
+ }
+
+ private void resetHashes() {
System.arraycopy(initialHashes, 0, state, 0, state.length);
}
--- a/src/java.base/share/classes/sun/security/provider/certpath/Builder.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/sun/security/provider/certpath/Builder.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -63,8 +63,8 @@
* Authority Information Access extension shall be enabled. Currently
* disabled by default for compatibility reasons.
*/
- static final boolean USE_AIA = AccessController.doPrivileged
- (new GetBooleanAction("com.sun.security.enableAIAcaIssuers"));
+ static final boolean USE_AIA = GetBooleanAction
+ .privilegedGetProperty("com.sun.security.enableAIAcaIssuers");
/**
* Initialize the builder with the input parameters.
--- a/src/java.base/share/classes/sun/security/ssl/Alert.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/sun/security/ssl/Alert.java Thu Aug 23 11:09:16 2018 -0400
@@ -235,13 +235,22 @@
Level level = Level.valueOf(am.level);
Alert alert = Alert.valueOf(am.id);
if (alert == Alert.CLOSE_NOTIFY) {
- if (tc.handshakeContext != null) {
+ tc.isInputCloseNotified = true;
+ tc.closeInbound();
+
+ if (tc.peerUserCanceled) {
+ tc.closeOutbound();
+ } else if (tc.handshakeContext != null) {
tc.fatal(Alert.UNEXPECTED_MESSAGE,
"Received close_notify during handshake");
}
-
- tc.isInputCloseNotified = true;
- tc.closeInbound();
+ } else if (alert == Alert.USER_CANCELED) {
+ if (level == Level.WARNING) {
+ tc.peerUserCanceled = true;
+ } else {
+ tc.fatal(alert,
+ "Received fatal close_notify alert", true, null);
+ }
} else if ((level == Level.WARNING) && (alert != null)) {
// Terminate the connection if an alert with a level of warning
// is received during handshaking, except the no_certificate
--- a/src/java.base/share/classes/sun/security/ssl/BaseSSLSocketImpl.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/sun/security/ssl/BaseSSLSocketImpl.java Thu Aug 23 11:09:16 2018 -0400
@@ -204,30 +204,35 @@
//
/**
- * The semantics of shutdownInput is not supported in TLS 1.0
- * spec. Thus when the method is called on an SSL socket, an
- * UnsupportedOperationException will be thrown.
+ * Places the input stream for this socket at "end of stream". Any data
+ * sent to the input stream side of the socket is acknowledged and then
+ * silently discarded.
*
- * @throws UnsupportedOperationException
+ * @see java.net.Socket#shutdownInput
*/
@Override
- public final void shutdownInput() throws IOException {
- throw new UnsupportedOperationException("The method shutdownInput()" +
- " is not supported in SSLSocket");
+ public void shutdownInput() throws IOException {
+ if (self == this) {
+ super.shutdownInput();
+ } else {
+ self.shutdownInput();
+ }
}
/**
- * The semantics of shutdownOutput is not supported in TLS 1.0
- * spec. Thus when the method is called on an SSL socket, an
- * UnsupportedOperationException will be thrown.
+ * Disables the output stream for this socket. For a TCP socket, any
+ * previously written data will be sent followed by TCP's normal
+ * connection termination sequence.
*
- * @throws UnsupportedOperationException
+ * @see java.net.Socket#shutdownOutput
*/
@Override
- public final void shutdownOutput() throws IOException {
- throw new UnsupportedOperationException("The method shutdownOutput()" +
- " is not supported in SSLSocket");
-
+ public void shutdownOutput() throws IOException {
+ if (self == this) {
+ super.shutdownOutput();
+ } else {
+ self.shutdownOutput();
+ }
}
/**
@@ -235,7 +240,7 @@
* @see java.net.Socket#isInputShutdown
*/
@Override
- public final boolean isInputShutdown() {
+ public boolean isInputShutdown() {
if (self == this) {
return super.isInputShutdown();
} else {
@@ -248,7 +253,7 @@
* @see java.net.Socket#isOutputShutdown
*/
@Override
- public final boolean isOutputShutdown() {
+ public boolean isOutputShutdown() {
if (self == this) {
return super.isOutputShutdown();
} else {
@@ -618,7 +623,7 @@
}
@Override
- public synchronized void close() throws IOException {
+ public void close() throws IOException {
if (self == this) {
super.close();
} else {
--- a/src/java.base/share/classes/sun/security/ssl/CipherSuite.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/sun/security/ssl/CipherSuite.java Thu Aug 23 11:09:16 2018 -0400
@@ -435,12 +435,12 @@
0x0003, false, "SSL_RSA_EXPORT_WITH_RC4_40_MD5",
"TLS_RSA_EXPORT_WITH_RC4_40_MD5",
ProtocolVersion.PROTOCOLS_TO_10,
- K_RSA_EXPORT, B_DES_40, M_MD5, H_NONE),
+ K_RSA_EXPORT, B_RC4_40, M_MD5, H_NONE),
SSL_DH_anon_EXPORT_WITH_RC4_40_MD5(
0x0017, false, "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5",
"TLS_DH_anon_EXPORT_WITH_RC4_40_MD5",
ProtocolVersion.PROTOCOLS_TO_10,
- K_DH_ANON, B_DES_40, M_MD5, H_NONE),
+ K_DH_ANON, B_RC4_40, M_MD5, H_NONE),
// no traffic encryption cipher suites
TLS_RSA_WITH_NULL_SHA256(
@@ -805,7 +805,7 @@
this.id = id;
this.isDefaultEnabled = isDefaultEnabled;
this.name = name;
- if (aliases.isEmpty()) {
+ if (!aliases.isEmpty()) {
this.aliases = Arrays.asList(aliases.split(","));
} else {
this.aliases = Collections.emptyList();
--- a/src/java.base/share/classes/sun/security/ssl/DTLSOutputRecord.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/sun/security/ssl/DTLSOutputRecord.java Thu Aug 23 11:09:16 2018 -0400
@@ -44,7 +44,7 @@
Authenticator prevWriteAuthenticator;
SSLWriteCipher prevWriteCipher;
- private final LinkedList<RecordMemo> alertMemos = new LinkedList<>();
+ private volatile boolean isCloseWaiting = false;
DTLSOutputRecord(HandshakeHash handshakeHash) {
super(handshakeHash, SSLWriteCipher.nullDTlsWriteCipher());
@@ -58,6 +58,21 @@
}
@Override
+ public synchronized void close() throws IOException {
+ if (!isClosed) {
+ if (fragmenter != null && fragmenter.hasAlert()) {
+ isCloseWaiting = true;
+ } else {
+ super.close();
+ }
+ }
+ }
+
+ boolean isClosed() {
+ return isClosed || isCloseWaiting;
+ }
+
+ @Override
void initHandshaker() {
// clean up
fragmenter = null;
@@ -71,6 +86,14 @@
@Override
void changeWriteCiphers(SSLWriteCipher writeCipher,
boolean useChangeCipherSpec) throws IOException {
+ if (isClosed()) {
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
+ SSLLogger.warning("outbound has closed, ignore outbound " +
+ "change_cipher_spec message");
+ }
+ return;
+ }
+
if (useChangeCipherSpec) {
encodeChangeCipherSpec();
}
@@ -91,23 +114,31 @@
@Override
void encodeAlert(byte level, byte description) throws IOException {
- RecordMemo memo = new RecordMemo();
+ if (isClosed()) {
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
+ SSLLogger.warning("outbound has closed, ignore outbound " +
+ "alert message: " + Alert.nameOf(description));
+ }
+ return;
+ }
- memo.contentType = ContentType.ALERT.id;
- memo.majorVersion = protocolVersion.major;
- memo.minorVersion = protocolVersion.minor;
- memo.encodeEpoch = writeEpoch;
- memo.encodeCipher = writeCipher;
+ if (fragmenter == null) {
+ fragmenter = new DTLSFragmenter();
+ }
- memo.fragment = new byte[2];
- memo.fragment[0] = level;
- memo.fragment[1] = description;
-
- alertMemos.add(memo);
+ fragmenter.queueUpAlert(level, description);
}
@Override
void encodeChangeCipherSpec() throws IOException {
+ if (isClosed()) {
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
+ SSLLogger.warning("outbound has closed, ignore outbound " +
+ "change_cipher_spec message");
+ }
+ return;
+ }
+
if (fragmenter == null) {
fragmenter = new DTLSFragmenter();
}
@@ -117,6 +148,15 @@
@Override
void encodeHandshake(byte[] source,
int offset, int length) throws IOException {
+ if (isClosed()) {
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
+ SSLLogger.warning("outbound has closed, ignore outbound " +
+ "handshake message",
+ ByteBuffer.wrap(source, offset, length));
+ }
+ return;
+ }
+
if (firstMessage) {
firstMessage = false;
}
@@ -132,6 +172,23 @@
Ciphertext encode(
ByteBuffer[] srcs, int srcsOffset, int srcsLength,
ByteBuffer[] dsts, int dstsOffset, int dstsLength) throws IOException {
+
+ if (isClosed) {
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
+ SSLLogger.warning("outbound has closed, ignore outbound " +
+ "application data or cached messages");
+ }
+
+ return null;
+ } else if (isCloseWaiting) {
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
+ SSLLogger.warning("outbound has closed, ignore outbound " +
+ "application data");
+ }
+
+ srcs = null; // use no application data.
+ }
+
return encode(srcs, srcsOffset, srcsLength, dsts[0]);
}
@@ -237,48 +294,6 @@
private Ciphertext acquireCiphertext(
ByteBuffer destination) throws IOException {
- if (alertMemos != null && !alertMemos.isEmpty()) {
- RecordMemo memo = alertMemos.pop();
-
- int dstPos = destination.position();
- int dstLim = destination.limit();
- int dstContent = dstPos + headerSize +
- writeCipher.getExplicitNonceSize();
- destination.position(dstContent);
-
- destination.put(memo.fragment);
-
- destination.limit(destination.position());
- destination.position(dstContent);
-
- if (SSLLogger.isOn && SSLLogger.isOn("record")) {
- SSLLogger.fine(
- "WRITE: " + protocolVersion + " " +
- ContentType.ALERT.name +
- ", length = " + destination.remaining());
- }
-
- // Encrypt the fragment and wrap up a record.
- long recordSN = encrypt(memo.encodeCipher,
- ContentType.ALERT.id,
- destination, dstPos, dstLim, headerSize,
- ProtocolVersion.valueOf(memo.majorVersion,
- memo.minorVersion));
-
- if (SSLLogger.isOn && SSLLogger.isOn("packet")) {
- ByteBuffer temporary = destination.duplicate();
- temporary.limit(temporary.position());
- temporary.position(dstPos);
- SSLLogger.fine("Raw write", temporary);
- }
-
- // remain the limit unchanged
- destination.limit(dstLim);
-
- return new Ciphertext(ContentType.ALERT.id,
- SSLHandshake.NOT_APPLICABLE.id, recordSN);
- }
-
if (fragmenter != null) {
return fragmenter.acquireCiphertext(destination);
}
@@ -288,16 +303,14 @@
@Override
boolean isEmpty() {
- return ((fragmenter == null) || fragmenter.isEmpty()) &&
- ((alertMemos == null) || alertMemos.isEmpty());
+ return (fragmenter == null) || fragmenter.isEmpty();
}
@Override
void launchRetransmission() {
// Note: Please don't retransmit if there are handshake messages
// or alerts waiting in the queue.
- if (((alertMemos == null) || alertMemos.isEmpty()) &&
- (fragmenter != null) && fragmenter.isRetransmittable()) {
+ if ((fragmenter != null) && fragmenter.isRetransmittable()) {
fragmenter.setRetransmission();
}
}
@@ -338,29 +351,6 @@
// size is bigger than 256 bytes.
private int retransmits = 2; // attemps of retransmits
- void queueUpChangeCipherSpec() {
-
- // Cleanup if a new flight starts.
- if (flightIsReady) {
- handshakeMemos.clear();
- acquireIndex = 0;
- flightIsReady = false;
- }
-
- RecordMemo memo = new RecordMemo();
-
- memo.contentType = ContentType.CHANGE_CIPHER_SPEC.id;
- memo.majorVersion = protocolVersion.major;
- memo.minorVersion = protocolVersion.minor;
- memo.encodeEpoch = writeEpoch;
- memo.encodeCipher = writeCipher;
-
- memo.fragment = new byte[1];
- memo.fragment[0] = 1;
-
- handshakeMemos.add(memo);
- }
-
void queueUpHandshake(byte[] buf,
int offset, int length) throws IOException {
@@ -401,6 +391,45 @@
}
}
+ void queueUpChangeCipherSpec() {
+
+ // Cleanup if a new flight starts.
+ if (flightIsReady) {
+ handshakeMemos.clear();
+ acquireIndex = 0;
+ flightIsReady = false;
+ }
+
+ RecordMemo memo = new RecordMemo();
+
+ memo.contentType = ContentType.CHANGE_CIPHER_SPEC.id;
+ memo.majorVersion = protocolVersion.major;
+ memo.minorVersion = protocolVersion.minor;
+ memo.encodeEpoch = writeEpoch;
+ memo.encodeCipher = writeCipher;
+
+ memo.fragment = new byte[1];
+ memo.fragment[0] = 1;
+
+ handshakeMemos.add(memo);
+ }
+
+ void queueUpAlert(byte level, byte description) throws IOException {
+ RecordMemo memo = new RecordMemo();
+
+ memo.contentType = ContentType.ALERT.id;
+ memo.majorVersion = protocolVersion.major;
+ memo.minorVersion = protocolVersion.minor;
+ memo.encodeEpoch = writeEpoch;
+ memo.encodeCipher = writeCipher;
+
+ memo.fragment = new byte[2];
+ memo.fragment[0] = level;
+ memo.fragment[1] = description;
+
+ handshakeMemos.add(memo);
+ }
+
Ciphertext acquireCiphertext(ByteBuffer dstBuf) throws IOException {
if (isEmpty()) {
if (isRetransmittable()) {
@@ -500,8 +529,13 @@
return new Ciphertext(hsMemo.contentType,
hsMemo.handshakeType, recordSN);
} else {
+ if (isCloseWaiting &&
+ memo.contentType == ContentType.ALERT.id) {
+ close();
+ }
+
acquireIndex++;
- return new Ciphertext(ContentType.CHANGE_CIPHER_SPEC.id,
+ return new Ciphertext(memo.contentType,
SSLHandshake.NOT_APPLICABLE.id, recordSN);
}
}
@@ -552,6 +586,16 @@
return false;
}
+ boolean hasAlert() {
+ for (RecordMemo memo : handshakeMemos) {
+ if (memo.contentType == ContentType.ALERT.id) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
boolean isRetransmittable() {
return (flightIsReady && !handshakeMemos.isEmpty() &&
(acquireIndex >= handshakeMemos.size()));
--- a/src/java.base/share/classes/sun/security/ssl/HandshakeContext.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/sun/security/ssl/HandshakeContext.java Thu Aug 23 11:09:16 2018 -0400
@@ -47,7 +47,6 @@
import sun.security.ssl.SupportedGroupsExtension.NamedGroupType;
import static sun.security.ssl.SupportedGroupsExtension.NamedGroupType.*;
import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
-import sun.security.ssl.PskKeyExchangeModesExtension.PskKeyExchangeMode;
abstract class HandshakeContext implements ConnectionContext {
// System properties
--- a/src/java.base/share/classes/sun/security/ssl/HandshakeOutStream.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/sun/security/ssl/HandshakeOutStream.java Thu Aug 23 11:09:16 2018 -0400
@@ -27,6 +27,7 @@
import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.nio.ByteBuffer;
/**
* Output stream for handshake data. This is used only internally
@@ -57,7 +58,14 @@
}
if (outputRecord != null) {
- outputRecord.encodeHandshake(buf, 0, count);
+ if (!outputRecord.isClosed()) {
+ outputRecord.encodeHandshake(buf, 0, count);
+ } else {
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
+ SSLLogger.warning("outbound has closed, ignore outbound " +
+ "handshake messages", ByteBuffer.wrap(buf, 0, count));
+ }
+ }
// reset the byte array output stream
reset();
--- a/src/java.base/share/classes/sun/security/ssl/KeyUpdate.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/sun/security/ssl/KeyUpdate.java Thu Aug 23 11:09:16 2018 -0400
@@ -223,8 +223,8 @@
Authenticator.valueOf(hc.conContext.protocolVersion),
hc.conContext.protocolVersion, key, ivSpec,
hc.sslContext.getSecureRandom());
+ rc.baseSecret = nplus1;
hc.conContext.inputRecord.changeReadCiphers(rc);
- hc.conContext.inputRecord.readCipher.baseSecret = nplus1;
if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
SSLLogger.fine("KeyUpdate: read key updated");
}
@@ -303,13 +303,12 @@
return null;
}
- // Output the handshake message.
- km.write(hc.handshakeOutput);
- hc.handshakeOutput.flush();
-
- // change write cipher
- hc.conContext.outputRecord.changeWriteCiphers(wc, false);
- hc.conContext.outputRecord.writeCipher.baseSecret = nplus1;
+ // Output the handshake message and change the write cipher.
+ //
+ // The KeyUpdate handshake message SHALL be delivered in the
+ // changeWriteCiphers() implementation.
+ wc.baseSecret = nplus1;
+ hc.conContext.outputRecord.changeWriteCiphers(wc, km.status.id);
if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
SSLLogger.fine("KeyUpdate: write key updated");
}
--- a/src/java.base/share/classes/sun/security/ssl/OutputRecord.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/sun/security/ssl/OutputRecord.java Thu Aug 23 11:09:16 2018 -0400
@@ -66,7 +66,7 @@
int fragmentSize;
// closed or not?
- boolean isClosed;
+ volatile boolean isClosed;
/*
* Mappings from V3 cipher suite encodings to their pure V2 equivalents.
@@ -76,6 +76,8 @@
{-1, -1, -1, 0x02, 0x01, -1, 0x04, 0x05, -1, 0x06, 0x07};
private static final int[] V3toV2CipherMap3 =
{-1, -1, -1, 0x80, 0x80, -1, 0x80, 0x80, -1, 0x40, 0xC0};
+ private static final byte[] HANDSHAKE_MESSAGE_KEY_UPDATE =
+ {SSLHandshake.KEY_UPDATE.id, 0x00, 0x00, 0x01, 0x00};
OutputRecord(HandshakeHash handshakeHash, SSLWriteCipher writeCipher) {
this.writeCipher = writeCipher;
@@ -87,7 +89,7 @@
// Please set packetSize and protocolVersion in the implementation.
}
- void setVersion(ProtocolVersion protocolVersion) {
+ synchronized void setVersion(ProtocolVersion protocolVersion) {
this.protocolVersion = protocolVersion;
}
@@ -106,7 +108,7 @@
return false;
}
- boolean seqNumIsHuge() {
+ synchronized boolean seqNumIsHuge() {
return (writeCipher.authenticator != null) &&
writeCipher.authenticator.seqNumIsHuge();
}
@@ -145,8 +147,17 @@
throw new UnsupportedOperationException();
}
- void changeWriteCiphers(SSLWriteCipher writeCipher,
+ // Change write ciphers, may use change_cipher_spec record.
+ synchronized void changeWriteCiphers(SSLWriteCipher writeCipher,
boolean useChangeCipherSpec) throws IOException {
+ if (isClosed()) {
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
+ SSLLogger.warning("outbound has closed, ignore outbound " +
+ "change_cipher_spec message");
+ }
+ return;
+ }
+
if (useChangeCipherSpec) {
encodeChangeCipherSpec();
}
@@ -165,15 +176,39 @@
this.isFirstAppOutputRecord = true;
}
- void changePacketSize(int packetSize) {
+ // Change write ciphers using key_update handshake message.
+ synchronized void changeWriteCiphers(SSLWriteCipher writeCipher,
+ byte keyUpdateRequest) throws IOException {
+ if (isClosed()) {
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
+ SSLLogger.warning("outbound has closed, ignore outbound " +
+ "key_update handshake message");
+ }
+ return;
+ }
+
+ // encode the handshake message, KeyUpdate
+ byte[] hm = HANDSHAKE_MESSAGE_KEY_UPDATE.clone();
+ hm[hm.length - 1] = keyUpdateRequest;
+ encodeHandshake(hm, 0, hm.length);
+ flush();
+
+ // Dispose of any intermediate state in the underlying cipher.
+ writeCipher.dispose();
+
+ this.writeCipher = writeCipher;
+ this.isFirstAppOutputRecord = true;
+ }
+
+ synchronized void changePacketSize(int packetSize) {
this.packetSize = packetSize;
}
- void changeFragmentSize(int fragmentSize) {
+ synchronized void changeFragmentSize(int fragmentSize) {
this.fragmentSize = fragmentSize;
}
- int getMaxPacketSize() {
+ synchronized int getMaxPacketSize() {
return packetSize;
}
@@ -194,13 +229,15 @@
@Override
public synchronized void close() throws IOException {
- if (!isClosed) {
- isClosed = true;
- writeCipher.dispose();
+ if (isClosed) {
+ return;
}
+
+ isClosed = true;
+ writeCipher.dispose();
}
- synchronized boolean isClosed() {
+ boolean isClosed() {
return isClosed;
}
@@ -241,7 +278,7 @@
}
}
- static long d13Encrypt(
+ private static long d13Encrypt(
SSLWriteCipher encCipher, byte contentType, ByteBuffer destination,
int headerOffset, int dstLim, int headerSize,
ProtocolVersion protocolVersion) {
@@ -282,7 +319,7 @@
return Authenticator.toLong(sequenceNumber);
}
- static long t13Encrypt(
+ private static long t13Encrypt(
SSLWriteCipher encCipher, byte contentType, ByteBuffer destination,
int headerOffset, int dstLim, int headerSize,
ProtocolVersion protocolVersion) {
@@ -321,7 +358,7 @@
return Authenticator.toLong(sequenceNumber);
}
- static long t10Encrypt(
+ private static long t10Encrypt(
SSLWriteCipher encCipher, byte contentType, ByteBuffer destination,
int headerOffset, int dstLim, int headerSize,
ProtocolVersion protocolVersion) {
@@ -362,7 +399,7 @@
private static final byte[] zeros = new byte[16];
}
- long t13Encrypt(
+ private long t13Encrypt(
SSLWriteCipher encCipher, byte contentType, int headerSize) {
if (!encCipher.isNullCipher()) {
// inner plaintext
@@ -375,9 +412,10 @@
int contentLen = count - position;
// ensure the capacity
- int packetSize = encCipher.calculatePacketSize(contentLen, headerSize);
- if (packetSize > buf.length) {
- byte[] newBuf = new byte[packetSize];
+ int requiredPacketSize =
+ encCipher.calculatePacketSize(contentLen, headerSize);
+ if (requiredPacketSize > buf.length) {
+ byte[] newBuf = new byte[requiredPacketSize];
System.arraycopy(buf, 0, newBuf, 0, count);
buf = newBuf;
}
@@ -406,16 +444,17 @@
return Authenticator.toLong(sequenceNumber);
}
- long t10Encrypt(
+ private long t10Encrypt(
SSLWriteCipher encCipher, byte contentType, int headerSize) {
byte[] sequenceNumber = encCipher.authenticator.sequenceNumber();
int position = headerSize + writeCipher.getExplicitNonceSize();
int contentLen = count - position;
// ensure the capacity
- int packetSize = encCipher.calculatePacketSize(contentLen, headerSize);
- if (packetSize > buf.length) {
- byte[] newBuf = new byte[packetSize];
+ int requiredPacketSize =
+ encCipher.calculatePacketSize(contentLen, headerSize);
+ if (requiredPacketSize > buf.length) {
+ byte[] newBuf = new byte[requiredPacketSize];
System.arraycopy(buf, 0, newBuf, 0, count);
buf = newBuf;
}
--- a/src/java.base/share/classes/sun/security/ssl/ProtocolVersion.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/sun/security/ssl/ProtocolVersion.java Thu Aug 23 11:09:16 2018 -0400
@@ -38,8 +38,7 @@
* @since 1.4.1
*/
enum ProtocolVersion {
-// TLS13 (0x0304, "TLSv1.3", false),
- TLS13 (SSLConfiguration.tls13VN, "TLSv1.3", false),
+ TLS13 (0x0304, "TLSv1.3", false),
TLS12 (0x0303, "TLSv1.2", false),
TLS11 (0x0302, "TLSv1.1", false),
TLS10 (0x0301, "TLSv1", false),
--- a/src/java.base/share/classes/sun/security/ssl/SSLConfiguration.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/sun/security/ssl/SSLConfiguration.java Thu Aug 23 11:09:16 2018 -0400
@@ -96,9 +96,9 @@
static final boolean useCompatibilityMode = Utilities.getBooleanProperty(
"jdk.tls.client.useCompatibilityMode", true);
-// TODO: Please remove after TLS 1.3 draft interop testing
-// delete me
-static int tls13VN;
+ // Respond a close_notify alert if receiving close_notify alert.
+ static final boolean acknowledgeCloseNotify = Utilities.getBooleanProperty(
+ "jdk.tls.acknowledgeCloseNotify", false);
// Is the extended_master_secret extension supported?
static {
@@ -112,21 +112,6 @@
}
}
useExtendedMasterSecret = supportExtendedMasterSecret;
-
-// delete me
-try {
- tls13VN =
- AccessController.doPrivileged(
- new PrivilegedExceptionAction<Integer>() {
- @Override
- public Integer run() throws Exception {
- return Integer.parseInt(
- System.getProperty("jdk.tls13.version", "0304"), 16);
- }
- });
-} catch (PrivilegedActionException ex) {
- // blank
-}
}
SSLConfiguration(SSLContextImpl sslContext, boolean isClientMode) {
--- a/src/java.base/share/classes/sun/security/ssl/SSLEngineImpl.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/sun/security/ssl/SSLEngineImpl.java Thu Aug 23 11:09:16 2018 -0400
@@ -155,6 +155,7 @@
ByteBuffer[] srcs, int srcsOffset, int srcsLength,
ByteBuffer[] dsts, int dstsOffset, int dstsLength) throws IOException {
+ // May need to deliver cached records.
if (isOutboundDone()) {
return new SSLEngineResult(
Status.CLOSED, getHandshakeStatus(), 0, 0);
@@ -162,8 +163,9 @@
HandshakeContext hc = conContext.handshakeContext;
HandshakeStatus hsStatus = null;
- if (!conContext.isNegotiated &&
- !conContext.isClosed() && !conContext.isBroken) {
+ if (!conContext.isNegotiated && !conContext.isBroken &&
+ !conContext.isInboundClosed() &&
+ !conContext.isOutboundClosed()) {
conContext.kickstart();
hsStatus = getHandshakeStatus();
@@ -315,7 +317,8 @@
}
// Is the sequence number is nearly overflow?
- if (conContext.outputRecord.seqNumIsHuge()) {
+ if (conContext.outputRecord.seqNumIsHuge() ||
+ conContext.outputRecord.writeCipher.atKeyLimit()) {
hsStatus = tryKeyUpdate(hsStatus);
}
@@ -343,25 +346,29 @@
}
/**
- * Try renegotiation or key update for sequence number wrap.
+ * Try key update for sequence number wrap or key usage limit.
*
* Note that in order to maintain the handshake status properly, we check
- * the sequence number after the last record reading/writing process. As
- * we request renegotiation or close the connection for wrapped sequence
+ * the sequence number and key usage limit after the last record
+ * reading/writing process.
+ *
+ * As we request renegotiation or close the connection for wrapped sequence
* number when there is enough sequence number space left to handle a few
* more records, so the sequence number of the last record cannot be
* wrapped.
*/
private HandshakeStatus tryKeyUpdate(
HandshakeStatus currentHandshakeStatus) throws IOException {
- // Don't bother to kickstart the renegotiation or key update when the
- // local is asking for it.
+ // Don't bother to kickstart if handshaking is in progress, or if the
+ // connection is not duplex-open.
if ((conContext.handshakeContext == null) &&
- !conContext.isClosed() && !conContext.isBroken) {
+ !conContext.isOutboundClosed() &&
+ !conContext.isInboundClosed() &&
+ !conContext.isBroken) {
if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
- SSLLogger.finest("key update to wrap sequence number");
+ SSLLogger.finest("trigger key update");
}
- conContext.keyUpdate();
+ beginHandshake();
return conContext.getHandshakeStatus();
}
@@ -471,8 +478,9 @@
}
HandshakeStatus hsStatus = null;
- if (!conContext.isNegotiated &&
- !conContext.isClosed() && !conContext.isBroken) {
+ if (!conContext.isNegotiated && !conContext.isBroken &&
+ !conContext.isInboundClosed() &&
+ !conContext.isOutboundClosed()) {
conContext.kickstart();
/*
@@ -677,7 +685,8 @@
}
// Is the sequence number is nearly overflow?
- if (conContext.inputRecord.seqNumIsHuge()) {
+ if (conContext.inputRecord.seqNumIsHuge() ||
+ conContext.inputRecord.readCipher.atKeyLimit()) {
pt.handshakeStatus =
tryKeyUpdate(pt.handshakeStatus);
}
@@ -700,16 +709,42 @@
@Override
public synchronized void closeInbound() throws SSLException {
+ if (isInboundDone()) {
+ return;
+ }
+
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
+ SSLLogger.finest("Closing inbound of SSLEngine");
+ }
+
+ // Is it ready to close inbound?
+ //
+ // No need to throw exception if the initial handshake is not started.
+ if (!conContext.isInputCloseNotified &&
+ (conContext.isNegotiated || conContext.handshakeContext != null)) {
+
+ conContext.fatal(Alert.INTERNAL_ERROR,
+ "closing inbound before receiving peer's close_notify");
+ }
+
conContext.closeInbound();
}
@Override
public synchronized boolean isInboundDone() {
- return conContext.isInboundDone();
+ return conContext.isInboundClosed();
}
@Override
public synchronized void closeOutbound() {
+ if (conContext.isOutboundClosed()) {
+ return;
+ }
+
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
+ SSLLogger.finest("Closing outbound of SSLEngine");
+ }
+
conContext.closeOutbound();
}
--- a/src/java.base/share/classes/sun/security/ssl/SSLEngineInputRecord.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/sun/security/ssl/SSLEngineInputRecord.java Thu Aug 23 11:09:16 2018 -0400
@@ -34,8 +34,6 @@
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.SSLProtocolException;
import sun.security.ssl.SSLCipher.SSLReadCipher;
-import sun.security.ssl.KeyUpdate.KeyUpdateMessage;
-import sun.security.ssl.KeyUpdate.KeyUpdateRequest;
/**
* {@code InputRecord} implementation for {@code SSLEngine}.
@@ -300,7 +298,7 @@
handshakeBuffer.put(handshakeFrag);
handshakeBuffer.rewind();
break;
- } if (remaining == handshakeMessageLen) {
+ } else if (remaining == handshakeMessageLen) {
if (handshakeHash.isHashable(handshakeType)) {
handshakeHash.receive(handshakeFrag);
}
@@ -333,20 +331,6 @@
return plaintexts.toArray(new Plaintext[0]);
}
- // KeyLimit check during application data.
- // atKeyLimit() inactive when limits not checked, tc set when limits
- // are active.
-
- if (readCipher.atKeyLimit()) {
- if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
- SSLLogger.fine("KeyUpdate: triggered, read side.");
- }
-
- PostHandshakeContext p = new PostHandshakeContext(tc);
- KeyUpdate.handshakeProducer.produce(p,
- new KeyUpdateMessage(p, KeyUpdateRequest.REQUESTED));
- }
-
return new Plaintext[] {
new Plaintext(contentType,
majorVersion, minorVersion, -1, -1L, fragment)
--- a/src/java.base/share/classes/sun/security/ssl/SSLEngineOutputRecord.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/sun/security/ssl/SSLEngineOutputRecord.java Thu Aug 23 11:09:16 2018 -0400
@@ -31,8 +31,6 @@
import javax.net.ssl.SSLHandshakeException;
import sun.security.ssl.SSLCipher.SSLWriteCipher;
-import sun.security.ssl.KeyUpdate.KeyUpdateMessage;
-import sun.security.ssl.KeyUpdate.KeyUpdateRequest;
/**
* {@code OutputRecord} implementation for {@code SSLEngine}.
@@ -43,7 +41,7 @@
private boolean isTalkingToV2 = false; // SSLv2Hello
private ByteBuffer v2ClientHello = null; // SSLv2Hello
- private boolean isCloseWaiting = false;
+ private volatile boolean isCloseWaiting = false;
SSLEngineOutputRecord(HandshakeHash handshakeHash) {
super(handshakeHash, SSLWriteCipher.nullTlsWriteCipher());
@@ -63,8 +61,20 @@
}
}
+ boolean isClosed() {
+ return isClosed || isCloseWaiting;
+ }
+
@Override
void encodeAlert(byte level, byte description) throws IOException {
+ if (isClosed()) {
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
+ SSLLogger.warning("outbound has closed, ignore outbound " +
+ "alert message: " + Alert.nameOf(description));
+ }
+ return;
+ }
+
if (fragmenter == null) {
fragmenter = new HandshakeFragment();
}
@@ -75,6 +85,14 @@
@Override
void encodeHandshake(byte[] source,
int offset, int length) throws IOException {
+ if (isClosed()) {
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
+ SSLLogger.warning("outbound has closed, ignore outbound " +
+ "handshake message",
+ ByteBuffer.wrap(source, offset, length));
+ }
+ return;
+ }
if (fragmenter == null) {
fragmenter = new HandshakeFragment();
@@ -114,6 +132,14 @@
@Override
void encodeChangeCipherSpec() throws IOException {
+ if (isClosed()) {
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
+ SSLLogger.warning("outbound has closed, ignore outbound " +
+ "change_cipher_spec message");
+ }
+ return;
+ }
+
if (fragmenter == null) {
fragmenter = new HandshakeFragment();
}
@@ -129,6 +155,23 @@
Ciphertext encode(
ByteBuffer[] srcs, int srcsOffset, int srcsLength,
ByteBuffer[] dsts, int dstsOffset, int dstsLength) throws IOException {
+
+ if (isClosed) {
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
+ SSLLogger.warning("outbound has closed, ignore outbound " +
+ "application data or cached messages");
+ }
+
+ return null;
+ } else if (isCloseWaiting) {
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
+ SSLLogger.warning("outbound has closed, ignore outbound " +
+ "application data");
+ }
+
+ srcs = null; // use no application data.
+ }
+
return encode(srcs, srcsOffset, srcsLength, dsts[0]);
}
@@ -248,25 +291,14 @@
if (isFirstAppOutputRecord) {
isFirstAppOutputRecord = false;
}
-
- // atKeyLimit() inactive when limits not checked, tc set when limits
- // are active.
- if (writeCipher.atKeyLimit()) {
- if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
- SSLLogger.fine("KeyUpdate: triggered, write side.");
- }
-
- PostHandshakeContext p = new PostHandshakeContext(tc);
- KeyUpdate.handshakeProducer.produce(p,
- new KeyUpdateMessage(p, KeyUpdateRequest.REQUESTED));
- }
}
return new Ciphertext(ContentType.APPLICATION_DATA.id,
SSLHandshake.NOT_APPLICABLE.id, recordSN);
}
- private Ciphertext acquireCiphertext(ByteBuffer destination) throws IOException {
+ private Ciphertext acquireCiphertext(
+ ByteBuffer destination) throws IOException {
if (isTalkingToV2) { // SSLv2Hello
// We don't support SSLv2. Send an SSLv2 error message
// so that the connection can be closed gracefully.
@@ -517,7 +549,7 @@
boolean hasAlert() {
for (RecordMemo memo : handshakeMemos) {
- if (memo.contentType == ContentType.ALERT.id) {
+ if (memo.contentType == ContentType.ALERT.id) {
return true;
}
}
--- a/src/java.base/share/classes/sun/security/ssl/SSLHandshake.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/sun/security/ssl/SSLHandshake.java Thu Aug 23 11:09:16 2018 -0400
@@ -366,6 +366,7 @@
SSLHandshake(byte id, String name,
Map.Entry<SSLConsumer, ProtocolVersion[]>[] handshakeConsumers,
Map.Entry<HandshakeProducer, ProtocolVersion[]>[] handshakeProducers) {
+
this(id, name, handshakeConsumers, handshakeProducers,
(Map.Entry<HandshakeAbsence, ProtocolVersion[]>[])(
new Map.Entry[0]));
@@ -375,6 +376,7 @@
Map.Entry<SSLConsumer, ProtocolVersion[]>[] handshakeConsumers,
Map.Entry<HandshakeProducer, ProtocolVersion[]>[] handshakeProducers,
Map.Entry<HandshakeAbsence, ProtocolVersion[]>[] handshakeAbsence) {
+
this.id = id;
this.name = name;
this.handshakeConsumers = handshakeConsumers;
@@ -404,7 +406,12 @@
ProtocolVersion protocolVersion;
if ((hc.negotiatedProtocol == null) ||
(hc.negotiatedProtocol == ProtocolVersion.NONE)) {
- protocolVersion = hc.maximumActiveProtocol;
+ if (hc.conContext.isNegotiated &&
+ hc.conContext.protocolVersion != ProtocolVersion.NONE) {
+ protocolVersion = hc.conContext.protocolVersion;
+ } else {
+ protocolVersion = hc.maximumActiveProtocol;
+ }
} else {
protocolVersion = hc.negotiatedProtocol;
}
@@ -444,7 +451,12 @@
ProtocolVersion protocolVersion;
if ((hc.negotiatedProtocol == null) ||
(hc.negotiatedProtocol == ProtocolVersion.NONE)) {
- protocolVersion = hc.maximumActiveProtocol;
+ if (hc.conContext.isNegotiated &&
+ hc.conContext.protocolVersion != ProtocolVersion.NONE) {
+ protocolVersion = hc.conContext.protocolVersion;
+ } else {
+ protocolVersion = hc.maximumActiveProtocol;
+ }
} else {
protocolVersion = hc.negotiatedProtocol;
}
--- a/src/java.base/share/classes/sun/security/ssl/SSLSessionContextImpl.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/sun/security/ssl/SSLSessionContextImpl.java Thu Aug 23 11:09:16 2018 -0400
@@ -31,6 +31,8 @@
import java.util.Locale;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSessionContext;
+
+import sun.security.action.GetPropertyAction;
import sun.security.util.Cache;
@@ -196,15 +198,9 @@
private static int getDefaultCacheLimit() {
int defaultCacheLimit = 0;
try {
- String s = java.security.AccessController.doPrivileged(
- new java.security.PrivilegedAction<String>() {
- @Override
- public String run() {
- return System.getProperty(
- "javax.net.ssl.sessionCacheSize");
- }
- });
- defaultCacheLimit = (s != null) ? Integer.parseInt(s) : 0;
+ String s = GetPropertyAction
+ .privilegedGetProperty("javax.net.ssl.sessionCacheSize");
+ defaultCacheLimit = (s != null) ? Integer.parseInt(s) : 0;
} catch (Exception e) {
// swallow the exception
}
--- a/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java Thu Aug 23 11:09:16 2018 -0400
@@ -82,7 +82,7 @@
private String peerHost;
private boolean autoClose;
private boolean isConnected = false;
- private boolean tlsIsClosed = false;
+ private volatile boolean tlsIsClosed = false;
/*
* Is the local name service trustworthy?
@@ -325,7 +325,7 @@
}
@Override
- public synchronized SSLSession getSession() {
+ public SSLSession getSession() {
try {
// start handshaking, if failed, the connection will be closed.
ensureNegotiated();
@@ -343,7 +343,11 @@
@Override
public synchronized SSLSession getHandshakeSession() {
if (conContext.handshakeContext != null) {
- return conContext.handshakeContext.handshakeSession;
+ synchronized (this) {
+ if (conContext.handshakeContext != null) {
+ return conContext.handshakeContext.handshakeSession;
+ }
+ }
}
return null;
@@ -370,23 +374,39 @@
}
@Override
- public synchronized void startHandshake() throws IOException {
- checkWrite();
- try {
- conContext.kickstart();
+ public void startHandshake() throws IOException {
+ if (!isConnected) {
+ throw new SocketException("Socket is not connected");
+ }
+
+ if (conContext.isBroken || conContext.isInboundClosed() ||
+ conContext.isOutboundClosed()) {
+ throw new SocketException("Socket has been closed or broken");
+ }
+
+ synchronized (conContext) { // handshake lock
+ // double check the context status
+ if (conContext.isBroken || conContext.isInboundClosed() ||
+ conContext.isOutboundClosed()) {
+ throw new SocketException("Socket has been closed or broken");
+ }
- // All initial handshaking goes through this operation until we
- // have a valid SSL connection.
- //
- // Handle handshake messages only, need no application data.
- if (!conContext.isNegotiated) {
- readRecord();
+ try {
+ conContext.kickstart();
+
+ // All initial handshaking goes through this operation until we
+ // have a valid SSL connection.
+ //
+ // Handle handshake messages only, need no application data.
+ if (!conContext.isNegotiated) {
+ readHandshakeRecord();
+ }
+ } catch (IOException ioe) {
+ conContext.fatal(Alert.HANDSHAKE_FAILURE,
+ "Couldn't kickstart handshaking", ioe);
+ } catch (Exception oe) { // including RuntimeException
+ handleException(oe);
}
- } catch (IOException ioe) {
- conContext.fatal(Alert.HANDSHAKE_FAILURE,
- "Couldn't kickstart handshaking", ioe);
- } catch (Exception oe) { // including RuntimeException
- handleException(oe);
}
}
@@ -437,44 +457,264 @@
}
@Override
- public synchronized boolean isClosed() {
- return tlsIsClosed && conContext.isClosed();
+ public boolean isClosed() {
+ return tlsIsClosed;
}
+ // Please don't synchronized this method. Otherwise, the read and close
+ // locks may be deadlocked.
@Override
- public synchronized void close() throws IOException {
+ public void close() throws IOException {
+ if (tlsIsClosed) {
+ return;
+ }
+
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
+ SSLLogger.fine("duplex close of SSLSocket");
+ }
+
try {
- conContext.close();
+ // shutdown output bound, which may have been closed previously.
+ if (!isOutputShutdown()) {
+ duplexCloseOutput();
+ }
+
+ // shutdown input bound, which may have been closed previously.
+ if (!isInputShutdown()) {
+ duplexCloseInput();
+ }
+
+ if (!isClosed()) {
+ // close the connection directly
+ closeSocket(false);
+ }
} catch (IOException ioe) {
// ignore the exception
if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
- SSLLogger.warning("connection context closure failed", ioe);
+ SSLLogger.warning("SSLSocket duplex close failed", ioe);
}
} finally {
tlsIsClosed = true;
}
}
+ /**
+ * Duplex close, start from closing outbound.
+ *
+ * For TLS 1.2 [RFC 5246], unless some other fatal alert has been
+ * transmitted, each party is required to send a close_notify alert
+ * before closing the write side of the connection. The other party
+ * MUST respond with a close_notify alert of its own and close down
+ * the connection immediately, discarding any pending writes. It is
+ * not required for the initiator of the close to wait for the responding
+ * close_notify alert before closing the read side of the connection.
+ *
+ * For TLS 1.3, Each party MUST send a close_notify alert before
+ * closing its write side of the connection, unless it has already sent
+ * some error alert. This does not have any effect on its read side of
+ * the connection. Both parties need not wait to receive a close_notify
+ * alert before closing their read side of the connection, though doing
+ * so would introduce the possibility of truncation.
+ *
+ * In order to support user initiated duplex-close for TLS 1.3 connections,
+ * the user_canceled alert is used together with the close_notify alert.
+ */
+ private void duplexCloseOutput() throws IOException {
+ boolean useUserCanceled = false;
+ boolean hasCloseReceipt = false;
+ if (conContext.isNegotiated) {
+ if (!conContext.protocolVersion.useTLS13PlusSpec()) {
+ hasCloseReceipt = true;
+ } else {
+ // Use a user_canceled alert for TLS 1.3 duplex close.
+ useUserCanceled = true;
+ }
+ } else if (conContext.handshakeContext != null) { // initial handshake
+ // Use user_canceled alert regardless the protocol versions.
+ useUserCanceled = true;
+
+ // The protocol version may have been negotiated.
+ ProtocolVersion pv = conContext.handshakeContext.negotiatedProtocol;
+ if (pv == null || (!pv.useTLS13PlusSpec())) {
+ hasCloseReceipt = true;
+ }
+ }
+
+ // Need a lock here so that the user_canceled alert and the
+ // close_notify alert can be delivered together.
+ try {
+ synchronized (conContext.outputRecord) {
+ // send a user_canceled alert if needed.
+ if (useUserCanceled) {
+ conContext.warning(Alert.USER_CANCELED);
+ }
+
+ // send a close_notify alert
+ conContext.warning(Alert.CLOSE_NOTIFY);
+ }
+ } finally {
+ if (!conContext.isOutboundClosed()) {
+ conContext.outputRecord.close();
+ }
+
+ if ((autoClose || !isLayered()) && !super.isOutputShutdown()) {
+ super.shutdownOutput();
+ }
+ }
+
+ if (!isInputShutdown()) {
+ bruteForceCloseInput(hasCloseReceipt);
+ }
+ }
+
+ /**
+ * Duplex close, start from closing inbound.
+ *
+ * This method should only be called when the outbound has been closed,
+ * but the inbound is still open.
+ */
+ private void duplexCloseInput() throws IOException {
+ boolean hasCloseReceipt = false;
+ if (conContext.isNegotiated &&
+ !conContext.protocolVersion.useTLS13PlusSpec()) {
+ hasCloseReceipt = true;
+ } // No close receipt if handshake has no completed.
+
+ bruteForceCloseInput(hasCloseReceipt);
+ }
+
+ /**
+ * Brute force close the input bound.
+ *
+ * This method should only be called when the outbound has been closed,
+ * but the inbound is still open.
+ */
+ private void bruteForceCloseInput(
+ boolean hasCloseReceipt) throws IOException {
+ if (hasCloseReceipt) {
+ // It is not required for the initiator of the close to wait for
+ // the responding close_notify alert before closing the read side
+ // of the connection. However, if the application protocol using
+ // TLS provides that any data may be carried over the underlying
+ // transport after the TLS connection is closed, the TLS
+ // implementation MUST receive a "close_notify" alert before
+ // indicating end-of-data to the application-layer.
+ try {
+ this.shutdown();
+ } finally {
+ if (!isInputShutdown()) {
+ shutdownInput(false);
+ }
+ }
+ } else {
+ if (!conContext.isInboundClosed()) {
+ conContext.inputRecord.close();
+ }
+
+ if ((autoClose || !isLayered()) && !super.isInputShutdown()) {
+ super.shutdownInput();
+ }
+ }
+ }
+
+ // Please don't synchronized this method. Otherwise, the read and close
+ // locks may be deadlocked.
+ @Override
+ public void shutdownInput() throws IOException {
+ shutdownInput(true);
+ }
+
+ // It is not required to check the close_notify receipt unless an
+ // application call shutdownInput() explicitly.
+ private void shutdownInput(
+ boolean checkCloseNotify) throws IOException {
+ if (isInputShutdown()) {
+ return;
+ }
+
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
+ SSLLogger.fine("close inbound of SSLSocket");
+ }
+
+ // Is it ready to close inbound?
+ //
+ // No need to throw exception if the initial handshake is not started.
+ if (checkCloseNotify && !conContext.isInputCloseNotified &&
+ (conContext.isNegotiated || conContext.handshakeContext != null)) {
+
+ conContext.fatal(Alert.INTERNAL_ERROR,
+ "closing inbound before receiving peer's close_notify");
+ }
+
+ conContext.closeInbound();
+ if ((autoClose || !isLayered()) && !super.isInputShutdown()) {
+ super.shutdownInput();
+ }
+ }
+
+ @Override
+ public boolean isInputShutdown() {
+ return conContext.isInboundClosed() &&
+ ((autoClose || !isLayered()) ? super.isInputShutdown(): true);
+ }
+
+ // Please don't synchronized this method. Otherwise, the read and close
+ // locks may be deadlocked.
+ @Override
+ public void shutdownOutput() throws IOException {
+ if (isOutputShutdown()) {
+ return;
+ }
+
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
+ SSLLogger.fine("close outbound of SSLSocket");
+ }
+ conContext.closeOutbound();
+
+ if ((autoClose || !isLayered()) && !super.isOutputShutdown()) {
+ super.shutdownOutput();
+ }
+ }
+
+ @Override
+ public boolean isOutputShutdown() {
+ return conContext.isOutboundClosed() &&
+ ((autoClose || !isLayered()) ? super.isOutputShutdown(): true);
+ }
+
@Override
public synchronized InputStream getInputStream() throws IOException {
- if (isClosed() || conContext.isInboundDone()) {
- throw new SocketException("Socket or inbound is closed");
+ if (isClosed()) {
+ throw new SocketException("Socket is closed");
}
if (!isConnected) {
throw new SocketException("Socket is not connected");
}
+ if (conContext.isInboundClosed() || isInputShutdown()) {
+ throw new SocketException("Socket input is already shutdown");
+ }
+
return appInput;
}
- private synchronized void ensureNegotiated() throws IOException {
- if (conContext.isNegotiated ||
- conContext.isClosed() || conContext.isBroken) {
+ private void ensureNegotiated() throws IOException {
+ if (conContext.isNegotiated || conContext.isBroken ||
+ conContext.isInboundClosed() || conContext.isOutboundClosed()) {
return;
}
- startHandshake();
+ synchronized (conContext) { // handshake lock
+ // double check the context status
+ if (conContext.isNegotiated || conContext.isBroken ||
+ conContext.isInboundClosed() ||
+ conContext.isOutboundClosed()) {
+ return;
+ }
+
+ startHandshake();
+ }
}
/**
@@ -489,7 +729,7 @@
private ByteBuffer buffer;
// Is application data available in the stream?
- private boolean appDataIsAvailable;
+ private volatile boolean appDataIsAvailable;
AppInputStream() {
this.appDataIsAvailable = false;
@@ -514,7 +754,7 @@
* Read a single byte, returning -1 on non-fault EOF status.
*/
@Override
- public synchronized int read() throws IOException {
+ public int read() throws IOException {
int n = read(oneByte, 0, 1);
if (n <= 0) { // EOF
return -1;
@@ -536,7 +776,7 @@
* and returning "-1" on non-fault EOF status.
*/
@Override
- public synchronized int read(byte[] b, int off, int len)
+ public int read(byte[] b, int off, int len)
throws IOException {
if (b == null) {
throw new NullPointerException("the target buffer is null");
@@ -553,75 +793,54 @@
}
// start handshaking if the connection has not been negotiated.
- if (!conContext.isNegotiated &&
- !conContext.isClosed() && !conContext.isBroken) {
+ if (!conContext.isNegotiated && !conContext.isBroken &&
+ !conContext.isInboundClosed() &&
+ !conContext.isOutboundClosed()) {
ensureNegotiated();
}
+ // Check if the Socket is invalid (error or closed).
+ if (!conContext.isNegotiated ||
+ conContext.isBroken || conContext.isInboundClosed()) {
+ throw new SocketException("Connection or inbound has closed");
+ }
+
// Read the available bytes at first.
- int remains = available();
- if (remains > 0) {
- int howmany = Math.min(remains, len);
- buffer.get(b, off, howmany);
-
- return howmany;
- }
+ //
+ // Note that the receiving and processing of post-handshake message
+ // are also synchronized with the read lock.
+ synchronized (this) {
+ int remains = available();
+ if (remains > 0) {
+ int howmany = Math.min(remains, len);
+ buffer.get(b, off, howmany);
- appDataIsAvailable = false;
- int volume = 0;
- try {
- /*
- * Read data if needed ... notice that the connection
- * guarantees that handshake, alert, and change cipher spec
- * data streams are handled as they arrive, so we never
- * see them here.
- */
- while (volume == 0) {
- // Clear the buffer for a new record reading.
- buffer.clear();
+ return howmany;
+ }
- // grow the buffer if needed
- int inLen = conContext.inputRecord.bytesInCompletePacket();
- if (inLen < 0) { // EOF
- handleEOF(null);
-
- // if no exception thrown
+ appDataIsAvailable = false;
+ try {
+ ByteBuffer bb = readApplicationRecord(buffer);
+ if (bb == null) { // EOF
return -1;
+ } else {
+ // The buffer may be reallocated for bigger capacity.
+ buffer = bb;
}
- // Is this packet bigger than SSL/TLS normally allows?
- if (inLen > SSLRecord.maxLargeRecordSize) {
- throw new SSLProtocolException(
- "Illegal packet size: " + inLen);
- }
-
- if (inLen > buffer.remaining()) {
- buffer = ByteBuffer.allocate(inLen);
- }
+ bb.flip();
+ int volume = Math.min(len, bb.remaining());
+ buffer.get(b, off, volume);
+ appDataIsAvailable = true;
- volume = readRecord(buffer);
- buffer.flip();
- if (volume < 0) { // EOF
- // treat like receiving a close_notify warning message.
- conContext.isInputCloseNotified = true;
- conContext.closeInbound();
- return -1;
- } else if (volume > 0) {
- appDataIsAvailable = true;
- break;
- }
+ return volume;
+ } catch (Exception e) { // including RuntimeException
+ // shutdown and rethrow (wrapped) exception as appropriate
+ handleException(e);
+
+ // dummy for compiler
+ return -1;
}
-
- // file the destination buffer
- int howmany = Math.min(len, volume);
- buffer.get(b, off, howmany);
- return howmany;
- } catch (Exception e) { // including RuntimeException
- // shutdown and rethrow (wrapped) exception as appropriate
- handleException(e);
-
- // dummy for compiler
- return -1;
}
}
@@ -658,20 +877,53 @@
SSLLogger.finest("Closing input stream");
}
- conContext.closeInbound();
+ try {
+ shutdownInput(false);
+ } catch (IOException ioe) {
+ // ignore the exception
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
+ SSLLogger.warning("input stream close failed", ioe);
+ }
+ }
+ }
+
+ /**
+ * Return whether we have reached end-of-file.
+ *
+ * If the socket is not connected, has been shutdown because of an error
+ * or has been closed, throw an Exception.
+ */
+ private boolean checkEOF() throws IOException {
+ if (conContext.isInboundClosed()) {
+ return true;
+ } else if (conContext.isInputCloseNotified || conContext.isBroken) {
+ if (conContext.closeReason == null) {
+ return true;
+ } else {
+ throw new SSLException(
+ "Connection has closed: " + conContext.closeReason,
+ conContext.closeReason);
+ }
+ }
+
+ return false;
}
}
@Override
public synchronized OutputStream getOutputStream() throws IOException {
- if (isClosed() || conContext.isOutboundDone()) {
- throw new SocketException("Socket or outbound is closed");
+ if (isClosed()) {
+ throw new SocketException("Socket is closed");
}
if (!isConnected) {
throw new SocketException("Socket is not connected");
}
+ if (conContext.isOutboundDone() || isOutputShutdown()) {
+ throw new SocketException("Socket output is already shutdown");
+ }
+
return appOutput;
}
@@ -691,7 +943,7 @@
}
@Override
- public synchronized void write(byte[] b,
+ public void write(byte[] b,
int off, int len) throws IOException {
if (b == null) {
throw new NullPointerException("the source buffer is null");
@@ -700,25 +952,47 @@
"buffer length: " + b.length + ", offset; " + off +
", bytes to read:" + len);
} else if (len == 0) {
+ //
+ // Don't bother to really write empty records. We went this
+ // far to drive the handshake machinery, for correctness; not
+ // writing empty records improves performance by cutting CPU
+ // time and network resource usage. However, some protocol
+ // implementations are fragile and don't like to see empty
+ // records, so this also increases robustness.
+ //
return;
}
- // start handshaking if the connection has not been negotiated.
- if (!conContext.isNegotiated &&
- !conContext.isClosed() && !conContext.isBroken) {
+ // Start handshaking if the connection has not been negotiated.
+ if (!conContext.isNegotiated && !conContext.isBroken &&
+ !conContext.isInboundClosed() &&
+ !conContext.isOutboundClosed()) {
ensureNegotiated();
}
- // check if the Socket is invalid (error or closed)
- checkWrite();
+ // Check if the Socket is invalid (error or closed).
+ if (!conContext.isNegotiated ||
+ conContext.isBroken || conContext.isOutboundClosed()) {
+ throw new SocketException("Connection or outbound has closed");
+ }
+
+ //
// Delegate the writing to the underlying socket.
try {
- writeRecord(b, off, len);
- checkWrite();
- } catch (IOException ioe) {
- // shutdown and rethrow (wrapped) exception as appropriate
- handleException(ioe);
+ conContext.outputRecord.deliver(b, off, len);
+ } catch (SSLHandshakeException she) {
+ // may be record sequence number overflow
+ conContext.fatal(Alert.HANDSHAKE_FAILURE, she);
+ } catch (IOException e) {
+ conContext.fatal(Alert.UNEXPECTED_MESSAGE, e);
+ }
+
+ // Is the sequence number is nearly overflow, or has the key usage
+ // limit been reached?
+ if (conContext.outputRecord.seqNumIsHuge() ||
+ conContext.outputRecord.writeCipher.atKeyLimit()) {
+ tryKeyUpdate();
}
}
@@ -728,7 +1002,14 @@
SSLLogger.finest("Closing output stream");
}
- conContext.closeOutbound();
+ try {
+ shutdownOutput();
+ } catch (IOException ioe) {
+ // ignore the exception
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
+ SSLLogger.warning("output stream close failed", ioe);
+ }
+ }
}
}
@@ -773,39 +1054,11 @@
return conContext.sslConfig.socketAPSelector;
}
- private synchronized void writeRecord(byte[] source,
- int offset, int length) throws IOException {
- if (conContext.isOutboundDone()) {
- throw new SocketException("Socket or outbound closed");
- }
-
- //
- // Don't bother to really write empty records. We went this
- // far to drive the handshake machinery, for correctness; not
- // writing empty records improves performance by cutting CPU
- // time and network resource usage. However, some protocol
- // implementations are fragile and don't like to see empty
- // records, so this also increases robustness.
- //
- if (length > 0) {
- try {
- conContext.outputRecord.deliver(source, offset, length);
- } catch (SSLHandshakeException she) {
- // may be record sequence number overflow
- conContext.fatal(Alert.HANDSHAKE_FAILURE, she);
- } catch (IOException e) {
- conContext.fatal(Alert.UNEXPECTED_MESSAGE, e);
- }
- }
-
- // Is the sequence number is nearly overflow?
- if (conContext.outputRecord.seqNumIsHuge()) {
- tryKeyUpdate();
- }
- }
-
- private synchronized int readRecord() throws IOException {
- while (!conContext.isInboundDone()) {
+ /**
+ * Read the initial handshake records.
+ */
+ private int readHandshakeRecord() throws IOException {
+ while (!conContext.isInboundClosed()) {
try {
Plaintext plainText = decode(null);
if ((plainText.contentType == ContentType.HANDSHAKE.id) &&
@@ -816,7 +1069,7 @@
throw ssle;
} catch (IOException ioe) {
if (!(ioe instanceof SSLException)) {
- throw new SSLException("readRecord", ioe);
+ throw new SSLException("readHandshakeRecord", ioe);
} else {
throw ioe;
}
@@ -826,8 +1079,20 @@
return -1;
}
- private synchronized int readRecord(ByteBuffer buffer) throws IOException {
- while (!conContext.isInboundDone()) {
+ /**
+ * Read application data record. Used by AppInputStream only, but defined
+ * here so as to use the socket level synchronization.
+ *
+ * Note that the connection guarantees that handshake, alert, and change
+ * cipher spec data streams are handled as they arrive, so we never see
+ * them here.
+ *
+ * Note: Please be careful about the synchronization, and don't use this
+ * method other than in the AppInputStream class!
+ */
+ private ByteBuffer readApplicationRecord(
+ ByteBuffer buffer) throws IOException {
+ while (!conContext.isInboundClosed()) {
/*
* clean the buffer and check if it is too small, e.g. because
* the AppInputStream did not have the chance to see the
@@ -841,23 +1106,33 @@
handleEOF(null);
// if no exception thrown
- return -1;
+ return null;
}
- if (buffer.remaining() < inLen) {
- return 0;
+ // Is this packet bigger than SSL/TLS normally allows?
+ if (inLen > SSLRecord.maxLargeRecordSize) {
+ throw new SSLProtocolException(
+ "Illegal packet size: " + inLen);
+ }
+
+ if (inLen > buffer.remaining()) {
+ buffer = ByteBuffer.allocate(inLen);
}
try {
- Plaintext plainText = decode(buffer);
- if (plainText.contentType == ContentType.APPLICATION_DATA.id) {
- return buffer.position();
+ Plaintext plainText;
+ synchronized (this) {
+ plainText = decode(buffer);
+ }
+ if (plainText.contentType == ContentType.APPLICATION_DATA.id &&
+ buffer.position() > 0) {
+ return buffer;
}
} catch (SSLException ssle) {
throw ssle;
} catch (IOException ioe) {
if (!(ioe instanceof SSLException)) {
- throw new SSLException("readRecord", ioe);
+ throw new SSLException("readApplicationRecord", ioe);
} else {
throw ioe;
}
@@ -867,7 +1142,7 @@
//
// couldn't read, due to some kind of error
//
- return -1;
+ return null;
}
private Plaintext decode(ByteBuffer destination) throws IOException {
@@ -887,7 +1162,8 @@
// Is the sequence number is nearly overflow?
if (plainText != Plaintext.PLAINTEXT_NULL &&
- conContext.inputRecord.seqNumIsHuge()) {
+ (conContext.inputRecord.seqNumIsHuge() ||
+ conContext.inputRecord.readCipher.atKeyLimit())) {
tryKeyUpdate();
}
@@ -895,69 +1171,28 @@
}
/**
- * Try renegotiation or key update for sequence number wrap.
+ * Try key update for sequence number wrap or key usage limit.
*
* Note that in order to maintain the handshake status properly, we check
- * the sequence number after the last record reading/writing process. As
- * we request renegotiation or close the connection for wrapped sequence
+ * the sequence number and key usage limit after the last record
+ * reading/writing process.
+ *
+ * As we request renegotiation or close the connection for wrapped sequence
* number when there is enough sequence number space left to handle a few
* more records, so the sequence number of the last record cannot be
* wrapped.
*/
private void tryKeyUpdate() throws IOException {
- // Don't bother to kickstart the renegotiation or key update when the
- // local is asking for it.
+ // Don't bother to kickstart if handshaking is in progress, or if the
+ // connection is not duplex-open.
if ((conContext.handshakeContext == null) &&
- !conContext.isClosed() && !conContext.isBroken) {
+ !conContext.isOutboundClosed() &&
+ !conContext.isInboundClosed() &&
+ !conContext.isBroken) {
if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
- SSLLogger.finest("key update to wrap sequence number");
+ SSLLogger.finest("trigger key update");
}
- conContext.keyUpdate();
- }
- }
-
- private void closeSocket(boolean selfInitiated) throws IOException {
- if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
- SSLLogger.fine("close the ssl connection " +
- (selfInitiated ? "(initiative)" : "(passive)"));
- }
-
- if (autoClose || !isLayered()) {
- super.close();
- } else if (selfInitiated) {
- // wait for close_notify alert to clear input stream.
- waitForClose();
- }
- }
-
- /**
- * Wait for close_notify alert for a graceful closure.
- *
- * [RFC 5246] If the application protocol using TLS provides that any
- * data may be carried over the underlying transport after the TLS
- * connection is closed, the TLS implementation must receive the responding
- * close_notify alert before indicating to the application layer that
- * the TLS connection has ended. If the application protocol will not
- * transfer any additional data, but will only close the underlying
- * transport connection, then the implementation MAY choose to close the
- * transport without waiting for the responding close_notify.
- */
- private void waitForClose() throws IOException {
- if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
- SSLLogger.fine("wait for close_notify or alert");
- }
-
- while (!conContext.isInboundDone()) {
- try {
- Plaintext plainText = decode(null);
- // discard and continue
- if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
- SSLLogger.finest(
- "discard plaintext while waiting for close", plainText);
- }
- } catch (Exception e) { // including RuntimeException
- handleException(e);
- }
+ startHandshake();
}
}
@@ -1041,41 +1276,6 @@
}
/**
- * Return whether we have reached end-of-file.
- *
- * If the socket is not connected, has been shutdown because of an error
- * or has been closed, throw an Exception.
- */
- synchronized boolean checkEOF() throws IOException {
- if (conContext.isClosed()) {
- return true;
- } else if (conContext.isInputCloseNotified || conContext.isBroken) {
- if (conContext.closeReason == null) {
- return true;
- } else {
- throw new SSLException(
- "Connection has been shutdown: " + conContext.closeReason,
- conContext.closeReason);
- }
- }
-
- return false;
- }
-
- /**
- * Check if we can write data to this socket.
- */
- synchronized void checkWrite() throws IOException {
- if (checkEOF() || conContext.isOutboundClosed()) {
- // we are at EOF, write must throw Exception
- throw new SocketException("Connection closed");
- }
- if (!isConnected) {
- throw new SocketException("Socket is not connected");
- }
- }
-
- /**
* Handle an exception.
*
* This method is called by top level exception handlers (in read(),
@@ -1132,7 +1332,7 @@
} else {
// treat as if we had received a close_notify
conContext.isInputCloseNotified = true;
- conContext.transport.shutdown();
+ shutdownInput();
return Plaintext.PLAINTEXT_NULL;
}
@@ -1174,4 +1374,51 @@
}
}
}
+
+ private void closeSocket(boolean selfInitiated) throws IOException {
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
+ SSLLogger.fine("close the SSL connection " +
+ (selfInitiated ? "(initiative)" : "(passive)"));
+ }
+
+ if (autoClose || !isLayered()) {
+ super.close();
+ } else if (selfInitiated) {
+ if (!conContext.isInboundClosed() && !isInputShutdown()) {
+ // wait for close_notify alert to clear input stream.
+ waitForClose();
+ }
+ }
+ }
+
+ /**
+ * Wait for close_notify alert for a graceful closure.
+ *
+ * [RFC 5246] If the application protocol using TLS provides that any
+ * data may be carried over the underlying transport after the TLS
+ * connection is closed, the TLS implementation must receive the responding
+ * close_notify alert before indicating to the application layer that
+ * the TLS connection has ended. If the application protocol will not
+ * transfer any additional data, but will only close the underlying
+ * transport connection, then the implementation MAY choose to close the
+ * transport without waiting for the responding close_notify.
+ */
+ private void waitForClose() throws IOException {
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
+ SSLLogger.fine("wait for close_notify or alert");
+ }
+
+ while (!conContext.isInboundClosed()) {
+ try {
+ Plaintext plainText = decode(null);
+ // discard and continue
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
+ SSLLogger.finest(
+ "discard plaintext while waiting for close", plainText);
+ }
+ } catch (Exception e) { // including RuntimeException
+ handleException(e);
+ }
+ }
+ }
}
--- a/src/java.base/share/classes/sun/security/ssl/SSLSocketInputRecord.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/sun/security/ssl/SSLSocketInputRecord.java Thu Aug 23 11:09:16 2018 -0400
@@ -38,8 +38,6 @@
import javax.net.ssl.SSLProtocolException;
import sun.security.ssl.SSLCipher.SSLReadCipher;
-import sun.security.ssl.KeyUpdate.KeyUpdateMessage;
-import sun.security.ssl.KeyUpdate.KeyUpdateRequest;
/**
* {@code InputRecord} implementation for {@code SSLSocket}.
@@ -348,20 +346,6 @@
return plaintexts.toArray(new Plaintext[0]);
}
- // KeyLimit check during application data.
- // atKeyLimit() inactive when limits not checked, tc set when limits
- // are active.
-
- if (readCipher.atKeyLimit()) {
- if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
- SSLLogger.fine("KeyUpdate: triggered, read side.");
- }
-
- PostHandshakeContext p = new PostHandshakeContext(tc);
- KeyUpdate.handshakeProducer.produce(p,
- new KeyUpdateMessage(p, KeyUpdateRequest.REQUESTED));
- }
-
return new Plaintext[] {
new Plaintext(contentType,
majorVersion, minorVersion, -1, -1L, fragment)
--- a/src/java.base/share/classes/sun/security/ssl/SSLSocketOutputRecord.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/sun/security/ssl/SSLSocketOutputRecord.java Thu Aug 23 11:09:16 2018 -0400
@@ -28,12 +28,10 @@
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.OutputStream;
+import java.net.SocketException;
import java.nio.ByteBuffer;
import javax.net.ssl.SSLHandshakeException;
-import sun.security.ssl.KeyUpdate.KeyUpdateMessage;
-import sun.security.ssl.KeyUpdate.KeyUpdateRequest;
-
/**
* {@code OutputRecord} implementation for {@code SSLSocket}.
*/
@@ -53,7 +51,16 @@
}
@Override
- void encodeAlert(byte level, byte description) throws IOException {
+ synchronized void encodeAlert(
+ byte level, byte description) throws IOException {
+ if (isClosed()) {
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
+ SSLLogger.warning("outbound has closed, ignore outbound " +
+ "alert message: " + Alert.nameOf(description));
+ }
+ return;
+ }
+
// use the buf of ByteArrayOutputStream
int position = headerSize + writeCipher.getExplicitNonceSize();
count = position;
@@ -63,6 +70,7 @@
if (SSLLogger.isOn && SSLLogger.isOn("record")) {
SSLLogger.fine("WRITE: " + protocolVersion +
" " + ContentType.ALERT.name +
+ "(" + Alert.nameOf(description) + ")" +
", length = " + (count - headerSize));
}
@@ -83,8 +91,17 @@
}
@Override
- void encodeHandshake(byte[] source,
+ synchronized void encodeHandshake(byte[] source,
int offset, int length) throws IOException {
+ if (isClosed()) {
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
+ SSLLogger.warning("outbound has closed, ignore outbound " +
+ "handshake message",
+ ByteBuffer.wrap(source, offset, length));
+ }
+ return;
+ }
+
if (firstMessage) {
firstMessage = false;
@@ -182,7 +199,14 @@
}
@Override
- void encodeChangeCipherSpec() throws IOException {
+ synchronized void encodeChangeCipherSpec() throws IOException {
+ if (isClosed()) {
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
+ SSLLogger.warning("outbound has closed, ignore outbound " +
+ "change_cipher_spec message");
+ }
+ return;
+ }
// use the buf of ByteArrayOutputStream
int position = headerSize + writeCipher.getExplicitNonceSize();
@@ -207,7 +231,7 @@
}
@Override
- public void flush() throws IOException {
+ public synchronized void flush() throws IOException {
int position = headerSize + writeCipher.getExplicitNonceSize();
if (count <= position) {
return;
@@ -237,7 +261,12 @@
}
@Override
- void deliver(byte[] source, int offset, int length) throws IOException {
+ synchronized void deliver(
+ byte[] source, int offset, int length) throws IOException {
+ if (isClosed()) {
+ throw new SocketException("Connection or outbound has been closed");
+ }
+
if (writeCipher.authenticator.seqNumOverflow()) {
if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
SSLLogger.fine(
@@ -304,23 +333,11 @@
}
offset += fragLen;
-
- // atKeyLimit() inactive when limits not checked, tc set when limits
- // are active.
- if (writeCipher.atKeyLimit()) {
- if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
- SSLLogger.fine("KeyUpdate: triggered, write side.");
- }
-
- PostHandshakeContext p = new PostHandshakeContext(tc);
- KeyUpdate.handshakeProducer.produce(p,
- new KeyUpdateMessage(p, KeyUpdateRequest.REQUESTED));
- }
}
}
@Override
- void setDeliverStream(OutputStream outputStream) {
+ synchronized void setDeliverStream(OutputStream outputStream) {
this.deliverStream = outputStream;
}
@@ -347,7 +364,7 @@
* This avoids issues in the outbound direction. For a full fix,
* the peer must have similar protections.
*/
- boolean needToSplitPayload() {
+ private boolean needToSplitPayload() {
return (!protocolVersion.useTLS11PlusSpec()) &&
writeCipher.isCBCMode() && !isFirstAppOutputRecord &&
Record.enableCBCProtection;
--- a/src/java.base/share/classes/sun/security/ssl/StatusResponseManager.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/sun/security/ssl/StatusResponseManager.java Thu Aug 23 11:09:16 2018 -0400
@@ -96,10 +96,10 @@
}
defaultResponder = tmpURI;
- respOverride = AccessController.doPrivileged(
- new GetBooleanAction("jdk.tls.stapling.responderOverride"));
- ignoreExtensions = AccessController.doPrivileged(
- new GetBooleanAction("jdk.tls.stapling.ignoreExtensions"));
+ respOverride = GetBooleanAction
+ .privilegedGetProperty("jdk.tls.stapling.responderOverride");
+ ignoreExtensions = GetBooleanAction
+ .privilegedGetProperty("jdk.tls.stapling.ignoreExtensions");
threadMgr = new ScheduledThreadPoolExecutor(DEFAULT_CORE_THREADS,
new ThreadFactory() {
--- a/src/java.base/share/classes/sun/security/ssl/SupportedGroupsExtension.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/sun/security/ssl/SupportedGroupsExtension.java Thu Aug 23 11:09:16 2018 -0400
@@ -482,8 +482,8 @@
//
// If the System Property is not defined or the value is empty, the
// default groups and preferences will be used.
- String property = AccessController.doPrivileged(
- new GetPropertyAction("jdk.tls.namedGroups"));
+ String property = GetPropertyAction
+ .privilegedGetProperty("jdk.tls.namedGroups");
if (property != null && property.length() != 0) {
// remove double quote marks from beginning/end of the property
if (property.length() > 1 && property.charAt(0) == '"' &&
--- a/src/java.base/share/classes/sun/security/ssl/TransportContext.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/sun/security/ssl/TransportContext.java Thu Aug 23 11:09:16 2018 -0400
@@ -25,7 +25,6 @@
package sun.security.ssl;
-import java.io.Closeable;
import java.io.IOException;
import java.security.AccessControlContext;
import java.security.AccessController;
@@ -45,7 +44,7 @@
/**
* SSL/(D)TLS transportation context.
*/
-class TransportContext implements ConnectionContext, Closeable {
+class TransportContext implements ConnectionContext {
final SSLTransport transport;
// registered plaintext consumers
@@ -62,7 +61,7 @@
boolean isNegotiated = false;
boolean isBroken = false;
boolean isInputCloseNotified = false;
- boolean isOutputCloseNotified = false;
+ boolean peerUserCanceled = false;
Exception closeReason = null;
// negotiated security parameters
@@ -229,10 +228,6 @@
}
}
- void keyUpdate() throws IOException {
- kickstart();
- }
-
boolean isPostHandshakeContext() {
return handshakeContext != null &&
(handshakeContext instanceof PostHandshakeContext);
@@ -348,7 +343,7 @@
//
// If we haven't even started handshaking yet, or we are the recipient
// of a fatal alert, no need to generate a fatal close alert.
- if (!recvFatalAlert && !isOutboundDone() && !isBroken &&
+ if (!recvFatalAlert && !isOutboundClosed() && !isBroken &&
(isNegotiated || handshakeContext != null)) {
try {
outputRecord.encodeAlert(Alert.Level.FATAL.level, alert.id);
@@ -436,35 +431,26 @@
return outputRecord.isClosed();
}
- boolean isInboundDone() {
+ boolean isInboundClosed() {
return inputRecord.isClosed();
}
- boolean isClosed() {
- return isOutboundClosed() && isInboundDone();
- }
-
- @Override
- public void close() throws IOException {
- if (!isOutboundDone()) {
- closeOutbound();
- }
-
- if (!isInboundDone()) {
- closeInbound();
- }
- }
-
- void closeInbound() {
- if (isInboundDone()) {
+ // Close inbound, no more data should be delivered to the underlying
+ // transportation connection.
+ void closeInbound() throws SSLException {
+ if (isInboundClosed()) {
return;
}
try {
- if (isInputCloseNotified) { // passive close
+ // Important note: check if the initial handshake is started at
+ // first so that the passiveInboundClose() implementation need not
+ // to consider the case any more.
+ if (!isInputCloseNotified) {
+ // the initial handshake is not started
+ initiateInboundClose();
+ } else {
passiveInboundClose();
- } else { // initiative close
- initiateInboundClose();
}
} catch (IOException ioe) {
if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
@@ -473,8 +459,58 @@
}
}
+ // Close the connection passively. The closure could be kickoff by
+ // receiving a close_notify alert or reaching end_of_file of the socket.
+ //
+ // Note that this method is called only if the initial handshake has
+ // started or completed.
+ private void passiveInboundClose() throws IOException {
+ if (!isInboundClosed()) {
+ inputRecord.close();
+ }
+
+ // For TLS 1.2 and prior version, it is required to respond with
+ // a close_notify alert of its own and close down the connection
+ // immediately, discarding any pending writes.
+ if (!isOutboundClosed()) {
+ boolean needCloseNotify = SSLConfiguration.acknowledgeCloseNotify;
+ if (!needCloseNotify) {
+ if (isNegotiated) {
+ if (!protocolVersion.useTLS13PlusSpec()) {
+ needCloseNotify = true;
+ }
+ } else if (handshakeContext != null) { // initial handshake
+ ProtocolVersion pv = handshakeContext.negotiatedProtocol;
+ if (pv == null || (!pv.useTLS13PlusSpec())) {
+ needCloseNotify = true;
+ }
+ }
+ }
+
+ if (needCloseNotify) {
+ synchronized (outputRecord) {
+ try {
+ // send a close_notify alert
+ warning(Alert.CLOSE_NOTIFY);
+ } finally {
+ outputRecord.close();
+ }
+ }
+ }
+ }
+ }
+
+ // Initiate a inbound close when the handshake is not started.
+ private void initiateInboundClose() throws IOException {
+ if (!isInboundClosed()) {
+ inputRecord.close();
+ }
+ }
+
+ // Close outbound, no more data should be received from the underlying
+ // transportation connection.
void closeOutbound() {
- if (isOutboundDone()) {
+ if (isOutboundClosed()) {
return;
}
@@ -487,116 +523,59 @@
}
}
- // Close the connection passively. The closure could be kickoff by
- // receiving a close_notify alert or reaching end_of_file of the socket.
- private void passiveInboundClose() throws IOException {
- if (!isInboundDone()) {
- inputRecord.close();
+ // Initiate a close by sending a close_notify alert.
+ private void initiateOutboundClose() throws IOException {
+ boolean useUserCanceled = false;
+ if (!isNegotiated && (handshakeContext != null) && !peerUserCanceled) {
+ // initial handshake
+ useUserCanceled = true;
}
- // For TLS 1.2 and prior version, it is required to respond with
- // a close_notify alert of its own and close down the connection
- // immediately, discarding any pending writes.
- if (!isOutboundDone() && !isOutputCloseNotified) {
+ // Need a lock here so that the user_canceled alert and the
+ // close_notify alert can be delivered together.
+ synchronized (outputRecord) {
try {
- // send a close_notify alert
- warning(Alert.CLOSE_NOTIFY);
- } finally {
- // any data received after a closure alert is ignored.
- isOutputCloseNotified = true;
- outputRecord.close();
- }
- }
+ // send a user_canceled alert if needed.
+ if (useUserCanceled) {
+ warning(Alert.USER_CANCELED);
+ }
- transport.shutdown();
- }
-
- // Initiate a close by sending a close_notify alert.
- private void initiateInboundClose() throws IOException {
- // TLS 1.3 does not define how to initiate and close a TLS connection
- // gracefully. We will always send a close_notify alert, and close
- // the underlying transportation layer if needed.
- if (!isInboundDone() && !isInputCloseNotified) {
- try {
// send a close_notify alert
warning(Alert.CLOSE_NOTIFY);
} finally {
- // any data received after a closure alert is ignored.
- isInputCloseNotified = true;
- inputRecord.close();
- }
- }
-
- // For TLS 1.3, input closure is independent from output closure. Both
- // parties need not wait to receive a "close_notify" alert before
- // closing their read side of the connection.
- //
- // For TLS 1.2 and prior version, it is not required for the initiator
- // of the close to wait for the responding close_notify alert before
- // closing the read side of the connection.
- try {
- transport.shutdown();
- } finally {
- if (!isOutboundDone()) {
outputRecord.close();
}
}
}
- // Initiate a close by sending a close_notify alert.
- private void initiateOutboundClose() throws IOException {
- if (!isOutboundDone() && !isOutputCloseNotified) {
- try { // close outputRecord
- // send a close_notify alert
- warning(Alert.CLOSE_NOTIFY);
- } finally {
- // any data received after a closure alert is ignored.
- isOutputCloseNotified = true;
- outputRecord.close();
- }
- }
-
- // It is not required for the initiator of the close to wait for the
- // responding close_notify alert before closing the read side of the
- // connection. However, if the application protocol using TLS
- // provides that any data may be carried over the underlying transport
- // after the TLS connection is closed, the TLS implementation MUST
- // receive a "close_notify" alert before indicating end-of-data to the
- // application-layer.
- try {
- transport.shutdown();
- } finally {
- if (!isInboundDone()) {
- inputRecord.close();
- }
- }
- }
-
// Note; HandshakeStatus.FINISHED status is retrieved in other places.
HandshakeStatus getHandshakeStatus() {
if (!outputRecord.isEmpty()) {
// If no handshaking, special case to wrap alters or
// post-handshake messages.
return HandshakeStatus.NEED_WRAP;
+ } else if (isOutboundClosed() && isInboundClosed()) {
+ return HandshakeStatus.NOT_HANDSHAKING;
} else if (handshakeContext != null) {
if (!handshakeContext.delegatedActions.isEmpty()) {
return HandshakeStatus.NEED_TASK;
- } else if (sslContext.isDTLS() &&
- !inputRecord.isEmpty()) {
- return HandshakeStatus.NEED_UNWRAP_AGAIN;
- } else {
- return HandshakeStatus.NEED_UNWRAP;
+ } else if (!isInboundClosed()) {
+ if (sslContext.isDTLS() &&
+ !inputRecord.isEmpty()) {
+ return HandshakeStatus.NEED_UNWRAP_AGAIN;
+ } else {
+ return HandshakeStatus.NEED_UNWRAP;
+ }
+ } else if (!isOutboundClosed()) {
+ // Special case that the inbound was closed, but outbound open.
+ return HandshakeStatus.NEED_WRAP;
}
- } else if (isOutboundDone() && !isInboundDone()) {
- /*
- * Special case where we're closing, but
- * still need the close_notify before we
- * can officially be closed.
- *
- * Note isOutboundDone is taken care of by
- * hasOutboundData() above.
- */
+ } else if (isOutboundClosed() && !isInboundClosed()) {
+ // Special case that the outbound was closed, but inbound open.
return HandshakeStatus.NEED_UNWRAP;
+ } else if (!isOutboundClosed() && isInboundClosed()) {
+ // Special case that the inbound was closed, but outbound open.
+ return HandshakeStatus.NEED_WRAP;
}
return HandshakeStatus.NOT_HANDSHAKING;
@@ -607,8 +586,10 @@
outputRecord.tc = this;
inputRecord.tc = this;
cipherSuite = handshakeContext.negotiatedCipherSuite;
- inputRecord.readCipher.baseSecret = handshakeContext.baseReadSecret;
- outputRecord.writeCipher.baseSecret = handshakeContext.baseWriteSecret;
+ inputRecord.readCipher.baseSecret =
+ handshakeContext.baseReadSecret;
+ outputRecord.writeCipher.baseSecret =
+ handshakeContext.baseWriteSecret;
}
handshakeContext = null;
--- a/src/java.base/share/classes/sun/security/validator/PKIXValidator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/sun/security/validator/PKIXValidator.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,9 +57,8 @@
* manager. Typically, this will only work if the PKIX implementation
* supports CRL distribution points as we do not manually setup CertStores.
*/
- private static final boolean checkTLSRevocation =
- AccessController.doPrivileged
- (new GetBooleanAction("com.sun.net.ssl.checkRevocation"));
+ private static final boolean checkTLSRevocation = GetBooleanAction
+ .privilegedGetProperty("com.sun.net.ssl.checkRevocation");
private final Set<X509Certificate> trustedCerts;
private final PKIXBuilderParameters parameterTemplate;
--- a/src/java.base/share/classes/sun/security/x509/AVA.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/classes/sun/security/x509/AVA.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -64,9 +64,8 @@
// See CR 6391482: if enabled this flag preserves the old but incorrect
// PrintableString encoding for DomainComponent. It may need to be set to
// avoid breaking preexisting certificates generated with sun.security APIs.
- private static final boolean PRESERVE_OLD_DC_ENCODING =
- AccessController.doPrivileged(new GetBooleanAction
- ("com.sun.security.preserveOldDCEncoding"));
+ private static final boolean PRESERVE_OLD_DC_ENCODING = GetBooleanAction
+ .privilegedGetProperty("com.sun.security.preserveOldDCEncoding");
/**
* DEFAULT format allows both RFC1779 and RFC2253 syntax and
--- a/src/java.base/share/conf/security/java.security Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/share/conf/security/java.security Thu Aug 23 11:09:16 2018 -0400
@@ -675,8 +675,8 @@
#
# Example:
# jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048
-jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 1024, \
- EC keySize < 224, DES40_CBC, RC4_40, 3DES_EDE_CBC
+jdk.tls.disabledAlgorithms=SSLv3, RC4, DES, MD5withRSA, DH keySize < 1024, \
+ EC keySize < 224, 3DES_EDE_CBC
#
# Legacy algorithms for Secure Socket Layer/Transport Layer Security (SSL/TLS)
Binary file src/java.base/share/lib/security/cacerts has changed
--- a/src/java.base/unix/classes/java/lang/ProcessImpl.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/unix/classes/java/lang/ProcessImpl.java Thu Aug 23 11:09:16 2018 -0400
@@ -507,8 +507,7 @@
long deadline = System.nanoTime() + remainingNanos;
do {
- // Round up to next millisecond
- wait(TimeUnit.NANOSECONDS.toMillis(remainingNanos + 999_999L));
+ TimeUnit.NANOSECONDS.timedWait(this, remainingNanos);
if (hasExited) {
return true;
}
--- a/src/java.base/windows/classes/java/lang/ProcessImpl.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/windows/classes/java/lang/ProcessImpl.java Thu Aug 23 11:09:16 2018 -0400
@@ -497,10 +497,14 @@
if (getExitCodeProcess(handle) != STILL_ACTIVE) return true;
if (timeout <= 0) return false;
- long deadline = System.nanoTime() + remainingNanos ;
+ long deadline = System.nanoTime() + remainingNanos;
do {
// Round up to next millisecond
long msTimeout = TimeUnit.NANOSECONDS.toMillis(remainingNanos + 999_999L);
+ if (msTimeout < 0) {
+ // if wraps around then wait a long while
+ msTimeout = Integer.MAX_VALUE;
+ }
waitForTimeoutInterruptibly(handle, msTimeout);
if (Thread.interrupted())
throw new InterruptedException();
@@ -514,7 +518,7 @@
}
private static native void waitForTimeoutInterruptibly(
- long handle, long timeout);
+ long handle, long timeoutMillis);
@Override
public void destroy() {
--- a/src/java.base/windows/native/libjava/ProcessImpl_md.c Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.base/windows/native/libjava/ProcessImpl_md.c Thu Aug 23 11:09:16 2018 -0400
@@ -433,10 +433,10 @@
Java_java_lang_ProcessImpl_waitForTimeoutInterruptibly(JNIEnv *env,
jclass ignored,
jlong handle,
- jlong timeout)
+ jlong timeoutMillis)
{
HANDLE events[2];
- DWORD dwTimeout = (DWORD)timeout;
+ DWORD dwTimeout = (DWORD)timeoutMillis;
DWORD result;
events[0] = (HANDLE) handle;
events[1] = JVM_GetThreadInterruptEvent();
--- a/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonRadioUI.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonRadioUI.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,15 +25,63 @@
package com.apple.laf;
-import javax.swing.*;
+import javax.swing.JComponent;
+import javax.swing.ImageIcon;
+import javax.swing.JRadioButton;
+import javax.swing.Icon;
+import javax.swing.AbstractButton;
+import javax.swing.AbstractAction;
+import javax.swing.KeyStroke;
+import javax.swing.DefaultButtonModel;
+import javax.swing.ButtonGroup;
+import javax.swing.ButtonModel;
import javax.swing.plaf.ComponentUI;
-import apple.laf.JRSUIConstants.*;
+import java.awt.Component;
+import java.awt.AWTKeyStroke;
+import java.awt.KeyboardFocusManager;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.KeyListener;
+import java.awt.event.KeyEvent;
-import com.apple.laf.AquaUtilControlSize.*;
-import com.apple.laf.AquaUtils.*;
+import apple.laf.JRSUIConstants.Widget;
+import com.apple.laf.AquaUtilControlSize.SizeVariant;
+import com.apple.laf.AquaUtilControlSize.SizeDescriptor;
+import com.apple.laf.AquaUtils.RecyclableSingleton;
+import com.apple.laf.AquaUtils.RecyclableSingletonFromDefaultConstructor;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.Enumeration;
public class AquaButtonRadioUI extends AquaButtonLabeledUI {
+ private KeyListener keyListener = null;
+
+ @SuppressWarnings("serial")
+ private class SelectPreviousBtn extends AbstractAction {
+ public SelectPreviousBtn() {
+ super("Previous");
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ AquaButtonRadioUI.this.selectRadioButton(e, false);
+ }
+ }
+
+ @SuppressWarnings("serial")
+ private class SelectNextBtn extends AbstractAction {
+ public SelectNextBtn() {
+ super("Next");
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ AquaButtonRadioUI.this.selectRadioButton(e, true);
+ }
+ }
+
private static final RecyclableSingleton<AquaButtonRadioUI> instance = new RecyclableSingletonFromDefaultConstructor<AquaButtonRadioUI>(AquaButtonRadioUI.class);
private static final RecyclableSingleton<ImageIcon> sizingIcon = new RecyclableSingleton<ImageIcon>() {
protected ImageIcon getInstance() {
@@ -45,7 +93,7 @@
return instance.get();
}
- public static Icon getSizingRadioButtonIcon(){
+ public static Icon getSizingRadioButtonIcon() {
return sizingIcon.get();
}
@@ -67,4 +115,269 @@
super(other);
}
}
+
+ private KeyListener createKeyListener() {
+ if (keyListener == null) {
+ keyListener = new KeyHandler();
+ }
+
+ return keyListener;
+ }
+
+ private boolean isValidRadioButtonObj(Object obj) {
+ return ((obj instanceof JRadioButton) &&
+ ((JRadioButton)obj).isVisible() &&
+ ((JRadioButton)obj).isEnabled());
+ }
+
+ @Override
+ protected void installListeners(AbstractButton button) {
+ super.installListeners(button);
+
+ //Only for JRadioButton
+ if (!(button instanceof JRadioButton))
+ return;
+
+ keyListener = createKeyListener();
+ button.addKeyListener(keyListener);
+
+ button.setFocusTraversalKeysEnabled(false);
+
+ button.getActionMap().put("Previous", new SelectPreviousBtn());
+ button.getActionMap().put("Next", new SelectNextBtn());
+
+ button.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).
+ put(KeyStroke.getKeyStroke("UP"), "Previous");
+ button.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).
+ put(KeyStroke.getKeyStroke("DOWN"), "Next");
+ button.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).
+ put(KeyStroke.getKeyStroke("LEFT"), "Previous");
+ button.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).
+ put(KeyStroke.getKeyStroke("RIGHT"), "Next");
+ }
+
+ @Override
+ protected void uninstallListeners(AbstractButton button) {
+ super.uninstallListeners(button);
+
+ //Only for JRadioButton
+ if (!(button instanceof JRadioButton))
+ return;
+
+ //Unmap actions from the arrow keys.
+ button.getActionMap().remove("Previous");
+ button.getActionMap().remove("Next");
+
+ button.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).
+ remove(KeyStroke.getKeyStroke("UP"));
+ button.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).
+ remove(KeyStroke.getKeyStroke("DOWN"));
+ button.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).
+ remove(KeyStroke.getKeyStroke("LEFT"));
+ button.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).
+ remove(KeyStroke.getKeyStroke("RIGHT"));
+
+ if (keyListener != null ) {
+ button.removeKeyListener(keyListener);
+ keyListener = null;
+ }
+ }
+
+ /**
+ * Select radio button based on "Previous" or "Next" operation
+ *
+ * @param event, the event object.
+ * @param next, indicate if it's next one
+ */
+ private void selectRadioButton(ActionEvent event, boolean next) {
+ Object eventSrc = event.getSource();
+
+ //Check whether the source is JRadioButton, if so, whether it is visible
+ if (!isValidRadioButtonObj(eventSrc))
+ return;
+
+ ButtonGroupInfo btnGroupInfo = new ButtonGroupInfo((JRadioButton)eventSrc);
+ btnGroupInfo.selectNewButton(next);
+ }
+
+ /**
+ * ButtonGroupInfo, used to get related info in button group
+ * for given radio button.
+ */
+ private class ButtonGroupInfo {
+ JRadioButton activeBtn = null;
+
+ JRadioButton firstBtn = null;
+ JRadioButton lastBtn = null;
+
+ JRadioButton previousBtn = null;
+ JRadioButton nextBtn = null;
+
+ HashSet<JRadioButton> btnsInGroup = null;
+ boolean srcFound = false;
+
+ public ButtonGroupInfo(JRadioButton btn) {
+ activeBtn = btn;
+ btnsInGroup = new HashSet<JRadioButton>();
+ }
+
+ //Check if given object is in the button group
+ boolean containsInGroup(Object obj) {
+ return btnsInGroup.contains(obj);
+ }
+
+ //Check if the next object to gain focus belongs
+ //to the button group or not
+ Component getFocusTransferBaseComponent(boolean next) {
+ return firstBtn;
+ }
+
+ boolean getButtonGroupInfo() {
+ if (activeBtn == null)
+ return false;
+
+ btnsInGroup.clear();
+
+ //Get the button model from ths source.
+ ButtonModel model = activeBtn.getModel();
+ if (!(model instanceof DefaultButtonModel))
+ return false;
+
+ // If the button model is DefaultButtonModel, and use it, otherwise return.
+ DefaultButtonModel bm = (DefaultButtonModel) model;
+
+ //get the ButtonGroup of the button from the button model
+ ButtonGroup group = bm.getGroup();
+ if (group == null)
+ return false;
+
+ Enumeration<AbstractButton> e = group.getElements();
+ if (e == null)
+ return false;
+
+ while (e.hasMoreElements()) {
+ AbstractButton curElement = e.nextElement();
+ if (!isValidRadioButtonObj(curElement))
+ continue;
+
+ btnsInGroup.add((JRadioButton) curElement);
+
+ // If firstBtn is not set yet, curElement is that first button
+ if (null == firstBtn)
+ firstBtn = (JRadioButton)curElement;
+
+ if (activeBtn == curElement)
+ srcFound = true;
+ else if (!srcFound) {
+ //The source has not been yet found and the current element
+ // is the last previousBtn
+ previousBtn = (JRadioButton) curElement;
+ } else if (nextBtn == null) {
+ //The source has been found and the current element
+ //is the next valid button of the list
+ nextBtn = (JRadioButton) curElement;
+ }
+
+ //Set new last "valid" JRadioButton of the list
+ lastBtn = (JRadioButton)curElement;
+ }
+
+ return true;
+ }
+
+ /**
+ * Find the new radio button that focus needs to be
+ * moved to in the group, select the button
+ *
+ * @param next, indicate if it's arrow up/left or down/right
+ */
+ void selectNewButton(boolean next) {
+ if (!getButtonGroupInfo())
+ return;
+
+ if (srcFound) {
+ JRadioButton newSelectedBtn = null;
+ if (next) {
+ //Select Next button. Cycle to the first button if the source
+ //button is the last of the group.
+ newSelectedBtn = (null == nextBtn) ? firstBtn : nextBtn;
+ } else {
+ //Select previous button. Cycle to the last button if the source
+ //button is the first button of the group.
+ newSelectedBtn = (null == previousBtn) ? lastBtn: previousBtn;
+ }
+ if (newSelectedBtn != null && newSelectedBtn != activeBtn) {
+ newSelectedBtn.requestFocusInWindow();
+ newSelectedBtn.setSelected(true);
+ }
+ }
+ }
+
+ /**
+ * Find the button group the passed in JRadioButton belongs to, and
+ * move focus to next component of the last button in the group
+ * or previous compoennt of first button
+ *
+ * @param next, indicate if jump to next component or previous
+ */
+ void jumpToNextComponent(boolean next) {
+ if (!getButtonGroupInfo()) {
+ //In case the button does not belong to any group, it needs
+ //to be treated as a component
+ if (activeBtn != null) {
+ lastBtn = activeBtn;
+ firstBtn = activeBtn;
+ } else
+ return;
+ }
+
+ //If next component in the parent window is not in the button
+ //group, current active button will be base, otherwise, the base
+ // will be first or last button in the button group
+ Component focusBase = getFocusTransferBaseComponent(next);
+ if (focusBase != null) {
+ if (next) {
+ KeyboardFocusManager.
+ getCurrentKeyboardFocusManager().focusNextComponent(focusBase);
+ } else {
+ KeyboardFocusManager.
+ getCurrentKeyboardFocusManager().focusPreviousComponent(focusBase);
+ }
+ }
+ }
+ }
+
+ /**
+ * Radiobutton KeyListener
+ */
+ private class KeyHandler implements KeyListener {
+ //This listener checks if the key event is a focus traversal key event
+ // on a radio button, consume the event if so and move the focus
+ // to next/previous component
+ @Override
+ public void keyPressed(KeyEvent e) {
+ AWTKeyStroke stroke = AWTKeyStroke.getAWTKeyStrokeForEvent(e);
+ if (stroke != null && e.getSource() instanceof JRadioButton) {
+ JRadioButton source = (JRadioButton) e.getSource();
+ boolean next = isFocusTraversalKey(source,
+ KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, stroke);
+ if (next || isFocusTraversalKey(source,
+ KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, stroke)) {
+ e.consume();
+ ButtonGroupInfo btnGroupInfo = new ButtonGroupInfo(source);
+ btnGroupInfo.jumpToNextComponent(next);
+ }
+ }
+ }
+
+ private boolean isFocusTraversalKey(JComponent c, int id,
+ AWTKeyStroke stroke) {
+ Set<AWTKeyStroke> keys = c.getFocusTraversalKeys(id);
+ return keys != null && keys.contains(stroke);
+ }
+
+ @Override public void keyReleased(KeyEvent e) {}
+
+ @Override public void keyTyped(KeyEvent e) {}
+ }
}
--- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Thu Aug 23 11:09:16 2018 -0400
@@ -378,7 +378,7 @@
// Either java.awt.Frame or java.awt.Dialog can be resizable, however java.awt.Window is never resizable
{
- final boolean resizable = isTargetResizable() && isNativelyFocusableWindow();
+ final boolean resizable = isFrame ? ((Frame)target).isResizable() : (isDialog ? ((Dialog)target).isResizable() : false);
styleBits = SET(styleBits, RESIZABLE, resizable);
if (!resizable) {
styleBits = SET(styleBits, ZOOMABLE, false);
@@ -482,16 +482,6 @@
return styleBits;
}
- private boolean isTargetResizable() {
- if (target instanceof Frame) {
- return ((Frame)target).isResizable();
- } else if (target instanceof Dialog) {
- return ((Dialog)target).isResizable();
- }
-
- return false;
- }
-
// this is the counter-point to -[CWindow _nativeSetStyleBit:]
private void setStyleBits(final int mask, final boolean value) {
execute(ptr -> nativeSetNSWindowStyleBits(ptr, mask, value ? mask : 0));
@@ -686,9 +676,10 @@
// Manage the extended state when showing
if (visible) {
/* Frame or Dialog should be set property WINDOW_FULLSCREENABLE to true if the
- Frame or Dialog is resizable and focusable.
+ Frame or Dialog is resizable.
**/
- final boolean resizable = isTargetResizable() && isNativelyFocusableWindow();
+ final boolean resizable = (target instanceof Frame) ? ((Frame)target).isResizable() :
+ ((target instanceof Dialog) ? ((Dialog)target).isResizable() : false);
if (resizable) {
setCanFullscreen(true);
}
@@ -823,10 +814,9 @@
@Override
public void setResizable(final boolean resizable) {
- final boolean windowResizable = resizable && isNativelyFocusableWindow();
- setCanFullscreen(windowResizable);
- setStyleBits(RESIZABLE, windowResizable);
- setStyleBits(ZOOMABLE, windowResizable);
+ setCanFullscreen(resizable);
+ setStyleBits(RESIZABLE, resizable);
+ setStyleBits(ZOOMABLE, resizable);
}
@Override
@@ -868,8 +858,8 @@
@Override
public void updateFocusableWindowState() {
- setStyleBits(SHOULD_BECOME_KEY | SHOULD_BECOME_MAIN | RESIZABLE,
- (isNativelyFocusableWindow() && isTargetResizable()));
+ final boolean isFocusable = isNativelyFocusableWindow();
+ setStyleBits(SHOULD_BECOME_KEY | SHOULD_BECOME_MAIN, isFocusable); // set both bits at once
}
@Override
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngpriv.h Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngpriv.h Thu Aug 23 11:09:16 2018 -0400
@@ -290,13 +290,10 @@
# endif
#endif /* PNG_MIPS_MSA_OPT > 0 */
-#ifdef PNG_POWERPC_VSX_API_SUPPORTED
#if PNG_POWERPC_VSX_OPT > 0
# define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_vsx
# define PNG_POWERPC_VSX_IMPLEMENTATION 1
#endif
-#endif
-
/* Is this a build of a DLL where compilation of the object modules requires
* different preprocessor settings to those required for a simple library? If
--- a/src/java.logging/share/classes/java/util/logging/Formatter.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.logging/share/classes/java/util/logging/Formatter.java Thu Aug 23 11:09:16 2018 -0400
@@ -137,7 +137,7 @@
while ((index = format.indexOf('{', index+1)) > -1) {
if (index >= fence) break;
char digit = format.charAt(index+1);
- if (digit >= '0' & digit <= '9') {
+ if (digit >= '0' && digit <= '9') {
return java.text.MessageFormat.format(format, parameters);
}
}
--- a/src/java.naming/share/classes/javax/naming/Name.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.naming/share/classes/javax/naming/Name.java Thu Aug 23 11:09:16 2018 -0400
@@ -63,8 +63,12 @@
* The class fingerprint that is set to indicate
* serialization compatibility with a previous
* version of the class.
+ *
+ * @deprecated A {@code serialVersionUID} field in an interface is
+ * ineffectual. Do not use; no replacement.
*/
- @SuppressWarnings("serial") // serialVersionUID in an interface is ineffectual
+ @Deprecated
+ @SuppressWarnings("serial")
static final long serialVersionUID = -3617482732056931635L;
/**
--- a/src/java.naming/share/classes/javax/naming/directory/Attribute.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.naming/share/classes/javax/naming/directory/Attribute.java Thu Aug 23 11:09:16 2018 -0400
@@ -335,7 +335,11 @@
/**
* Use serialVersionUID from JNDI 1.1.1 for interoperability.
+ *
+ * @deprecated A {@code serialVersionUID} field in an interface is
+ * ineffectual. Do not use; no replacement.
*/
- @SuppressWarnings("serial") // serialVersionUID in an interface is ineffectual
+ @Deprecated
+ @SuppressWarnings("serial")
static final long serialVersionUID = 8707690322213556804L;
}
--- a/src/java.net.http/share/classes/jdk/internal/net/http/Http1Response.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/Http1Response.java Thu Aug 23 11:09:16 2018 -0400
@@ -40,6 +40,7 @@
import java.net.http.HttpHeaders;
import java.net.http.HttpResponse;
import jdk.internal.net.http.ResponseContent.BodyParser;
+import jdk.internal.net.http.ResponseContent.UnknownLengthBodyParser;
import jdk.internal.net.http.common.Log;
import jdk.internal.net.http.common.Logger;
import jdk.internal.net.http.common.MinimalFuture;
@@ -67,6 +68,7 @@
private final BodyReader bodyReader; // used to read the body
private final Http1AsyncReceiver asyncReceiver;
private volatile EOFException eof;
+ private volatile BodyParser bodyParser;
// max number of bytes of (fixed length) body to ignore on redirect
private final static int MAX_IGNORE = 1024;
@@ -230,6 +232,10 @@
return finished;
}
+ /**
+ * Return known fixed content length or -1 if chunked, or -2 if no content-length
+ * information in which case, connection termination delimits the response body
+ */
int fixupContentLen(int clen) {
if (request.method().equalsIgnoreCase("HEAD") || responseCode == HTTP_NOT_MODIFIED) {
return 0;
@@ -239,7 +245,11 @@
.equalsIgnoreCase("chunked")) {
return -1;
}
- return 0;
+ if (responseCode == 101) {
+ // this is a h2c or websocket upgrade, contentlength must be zero
+ return 0;
+ }
+ return -2;
}
return clen;
}
@@ -401,7 +411,7 @@
// to prevent the SelectorManager thread from exiting until
// the body is fully read.
refCountTracker.acquire();
- bodyReader.start(content.getBodyParser(
+ bodyParser = content.getBodyParser(
(t) -> {
try {
if (t != null) {
@@ -417,7 +427,8 @@
connection.close();
}
}
- }));
+ });
+ bodyReader.start(bodyParser);
CompletableFuture<State> bodyReaderCF = bodyReader.completion();
asyncReceiver.subscribe(bodyReader);
assert bodyReaderCF != null : "parsing not started";
@@ -723,6 +734,11 @@
@Override
public final void onReadError(Throwable t) {
+ if (t instanceof EOFException && bodyParser != null &&
+ bodyParser instanceof UnknownLengthBodyParser) {
+ ((UnknownLengthBodyParser)bodyParser).complete();
+ return;
+ }
t = wrapWithExtraDetail(t, parser::currentStateMessage);
Http1Response.this.onReadError(t);
}
--- a/src/java.net.http/share/classes/jdk/internal/net/http/ResponseContent.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/ResponseContent.java Thu Aug 23 11:09:16 2018 -0400
@@ -75,6 +75,12 @@
if (chunkedContentInitialized) {
return chunkedContent;
}
+ if (contentLength == -2) {
+ // HTTP/1.0 content
+ chunkedContentInitialized = true;
+ chunkedContent = false;
+ return chunkedContent;
+ }
if (contentLength == -1) {
String tc = headers.firstValue("Transfer-Encoding")
.orElse("");
@@ -111,7 +117,9 @@
if (contentChunked()) {
return new ChunkedBodyParser(onComplete);
} else {
- return new FixedLengthBodyParser(contentLength, onComplete);
+ return contentLength == -2
+ ? new UnknownLengthBodyParser(onComplete)
+ : new FixedLengthBodyParser(contentLength, onComplete);
}
}
@@ -392,6 +400,79 @@
}
+ class UnknownLengthBodyParser implements BodyParser {
+ final Consumer<Throwable> onComplete;
+ final Logger debug = Utils.getDebugLogger(this::dbgString, Utils.DEBUG);
+ final String dbgTag = ResponseContent.this.dbgTag + "/UnknownLengthBodyParser";
+ volatile Throwable closedExceptionally;
+ volatile AbstractSubscription sub;
+ volatile int breceived = 0;
+
+ UnknownLengthBodyParser(Consumer<Throwable> onComplete) {
+ this.onComplete = onComplete;
+ }
+
+ String dbgString() {
+ return dbgTag;
+ }
+
+ @Override
+ public void onSubscribe(AbstractSubscription sub) {
+ if (debug.on())
+ debug.log("onSubscribe: " + pusher.getClass().getName());
+ pusher.onSubscribe(this.sub = sub);
+ }
+
+ @Override
+ public String currentStateMessage() {
+ return format("http1_0 content, bytes received: %d", breceived);
+ }
+
+ @Override
+ public void accept(ByteBuffer b) {
+ if (closedExceptionally != null) {
+ if (debug.on())
+ debug.log("already closed: " + closedExceptionally);
+ return;
+ }
+ boolean completed = false;
+ try {
+ if (debug.on())
+ debug.log("Parser got %d bytes ", b.remaining());
+
+ if (b.hasRemaining()) {
+ // only reduce demand if we actually push something.
+ // we would not have come here if there was no
+ // demand.
+ boolean hasDemand = sub.demand().tryDecrement();
+ assert hasDemand;
+ breceived += b.remaining();
+ pusher.onNext(List.of(b.asReadOnlyBuffer()));
+ }
+ } catch (Throwable t) {
+ if (debug.on()) debug.log("Unexpected exception", t);
+ closedExceptionally = t;
+ if (!completed) {
+ onComplete.accept(t);
+ }
+ }
+ }
+
+ /**
+ * Must be called externally when connection has closed
+ * and therefore no more bytes can be read
+ */
+ public void complete() {
+ // We're done! All data has been received.
+ if (debug.on())
+ debug.log("Parser got all expected bytes: completing");
+ assert closedExceptionally == null;
+ onFinished.run();
+ pusher.onComplete();
+ onComplete.accept(closedExceptionally); // should be null
+ }
+ }
+
class FixedLengthBodyParser implements BodyParser {
final int contentLength;
final Consumer<Throwable> onComplete;
--- a/src/java.rmi/share/classes/java/rmi/server/RemoteRef.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.rmi/share/classes/java/rmi/server/RemoteRef.java Thu Aug 23 11:09:16 2018 -0400
@@ -38,8 +38,13 @@
*/
public interface RemoteRef extends java.io.Externalizable {
- /** indicate compatibility with JDK 1.1.x version of class. */
- @SuppressWarnings("serial") // serialVersionUID in an interface is ineffectual
+ /** indicate compatibility with JDK 1.1.x version of class.
+ *
+ * @deprecated A {@code serialVersionUID} field in an interface is
+ * ineffectual. Do not use; no replacement.
+ */
+ @Deprecated
+ @SuppressWarnings("serial")
static final long serialVersionUID = 3632638527362204081L;
/**
--- a/src/java.rmi/share/classes/java/rmi/server/ServerRef.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.rmi/share/classes/java/rmi/server/ServerRef.java Thu Aug 23 11:09:16 2018 -0400
@@ -38,8 +38,13 @@
@Deprecated
public interface ServerRef extends RemoteRef {
- /** indicate compatibility with JDK 1.1.x version of class. */
- @SuppressWarnings("serial") // serialVersionUID in an interface is ineffectual
+ /** indicate compatibility with JDK 1.1.x version of class.
+ *
+ * @deprecated A {@code serialVersionUID} field in an interface is
+ * ineffectual. Do not use; no replacement.
+ */
+ @Deprecated
+ @SuppressWarnings("serial")
static final long serialVersionUID = -4557750989390278438L;
/**
--- a/src/java.rmi/share/classes/sun/rmi/server/ActivationGroupImpl.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.rmi/share/classes/sun/rmi/server/ActivationGroupImpl.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -444,7 +444,7 @@
if (groupInactive == true)
throw new ActivationException("group is inactive");
}
- if (!active.contains(id)) {
+ if (!active.containsKey(id)) {
ActiveEntry entry = new ActiveEntry(impl);
active.put(id, entry);
// created new entry, so inform monitor of active object
--- a/src/java.security.jgss/share/classes/sun/net/www/protocol/http/spnego/NegotiatorImpl.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.security.jgss/share/classes/sun/net/www/protocol/http/spnego/NegotiatorImpl.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,8 @@
import sun.net.www.protocol.http.HttpCallerInfo;
import sun.net.www.protocol.http.Negotiator;
+import sun.security.action.GetBooleanAction;
+import sun.security.action.GetPropertyAction;
import sun.security.jgss.GSSManagerImpl;
import sun.security.jgss.GSSContextImpl;
import sun.security.jgss.GSSUtil;
@@ -50,8 +52,7 @@
public class NegotiatorImpl extends Negotiator {
private static final boolean DEBUG =
- java.security.AccessController.doPrivileged(
- new sun.security.action.GetBooleanAction("sun.security.krb5.debug"));
+ GetBooleanAction.privilegedGetProperty("sun.security.krb5.debug");
private GSSContext context;
private byte[] oneToken;
@@ -71,14 +72,8 @@
// we can only use Kerberos mech when the scheme is kerberos
oid = GSSUtil.GSS_KRB5_MECH_OID;
} else {
- String pref = java.security.AccessController.doPrivileged(
- new java.security.PrivilegedAction<String>() {
- public String run() {
- return System.getProperty(
- "http.auth.preference",
- "spnego");
- }
- });
+ String pref = GetPropertyAction
+ .privilegedGetProperty("http.auth.preference", "spnego");
if (pref.equalsIgnoreCase("kerberos")) {
oid = GSSUtil.GSS_KRB5_MECH_OID;
} else {
--- a/src/java.security.jgss/share/classes/sun/security/jgss/GSSManagerImpl.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.security.jgss/share/classes/sun/security/jgss/GSSManagerImpl.java Thu Aug 23 11:09:16 2018 -0400
@@ -26,10 +26,9 @@
package sun.security.jgss;
import org.ietf.jgss.*;
+import sun.security.action.GetBooleanAction;
import sun.security.jgss.spi.*;
import java.security.Provider;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
/**
* This class provides the default implementation of the GSSManager
@@ -38,20 +37,8 @@
public class GSSManagerImpl extends GSSManager {
// Undocumented property
- private static final String USE_NATIVE_PROP =
- "sun.security.jgss.native";
- private static final Boolean USE_NATIVE;
-
- static {
- USE_NATIVE =
- AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
- public Boolean run() {
- return Boolean.valueOf(System.getProperty
- (USE_NATIVE_PROP));
- }
- });
-
- }
+ private static final Boolean USE_NATIVE = GetBooleanAction
+ .privilegedGetProperty("sun.security.jgss.native");
private ProviderList list;
--- a/src/java.security.jgss/share/classes/sun/security/jgss/GSSUtil.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.security.jgss/share/classes/sun/security/jgss/GSSUtil.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,15 +68,8 @@
public static final Oid NT_GSS_KRB5_PRINCIPAL =
GSSUtil.createOid("1.2.840.113554.1.2.2.1");
- private static final String DEFAULT_HANDLER =
- "auth.login.defaultCallbackHandler";
-
- static final boolean DEBUG;
- static {
- DEBUG = (AccessController.doPrivileged
- (new GetBooleanAction("sun.security.jgss.debug"))).
- booleanValue();
- }
+ static final boolean DEBUG =
+ GetBooleanAction.privilegedGetProperty("sun.security.jgss.debug");
static void debug(String message) {
if (DEBUG) {
@@ -240,8 +233,8 @@
cb = new sun.net.www.protocol.http.spnego.NegotiateCallbackHandler(
((HttpCaller)caller).info());
} else {
- String defaultHandler =
- java.security.Security.getProperty(DEFAULT_HANDLER);
+ String defaultHandler = java.security.Security
+ .getProperty("auth.login.defaultCallbackHandler");
// get the default callback handler
if ((defaultHandler != null) && (defaultHandler.length() != 0)) {
cb = null;
@@ -270,8 +263,8 @@
*/
public static boolean useSubjectCredsOnly(GSSCaller caller) {
- String propValue = GetPropertyAction.privilegedGetProperty(
- "javax.security.auth.useSubjectCredsOnly");
+ String propValue = GetPropertyAction
+ .privilegedGetProperty("javax.security.auth.useSubjectCredsOnly");
// Invalid values should be ignored and the default assumed.
if (caller instanceof HttpCaller) {
@@ -295,9 +288,8 @@
* Don't use GetBooleanAction because the default value in the JRE
* (when this is unset) has to treated as true.
*/
- String propValue = AccessController.doPrivileged(
- new GetPropertyAction("sun.security.spnego.msinterop",
- "true"));
+ String propValue = GetPropertyAction
+ .privilegedGetProperty("sun.security.spnego.msinterop", "true");
/*
* This property has to be explicitly set to "false". Invalid
* values should be ignored and the default "true" assumed.
--- a/src/java.security.jgss/share/classes/sun/security/jgss/ProviderList.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.security.jgss/share/classes/sun/security/jgss/ProviderList.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +27,6 @@
import java.lang.reflect.InvocationTargetException;
import org.ietf.jgss.*;
-import java.security.AccessController;
import java.security.Provider;
import java.security.Security;
import java.util.ArrayList;
@@ -93,10 +92,6 @@
private static final String SPI_MECH_FACTORY_TYPE
= "sun.security.jgss.spi.MechanismFactory";
- // Undocumented property?
- private static final String DEFAULT_MECH_PROP =
- "sun.security.jgss.mechanism";
-
public static final Oid DEFAULT_MECH_OID;
static {
@@ -106,8 +101,8 @@
* with a valid OID value
*/
Oid defOid = null;
- String defaultOidStr = AccessController.doPrivileged
- (new GetPropertyAction(DEFAULT_MECH_PROP));
+ String defaultOidStr = GetPropertyAction
+ .privilegedGetProperty("sun.security.jgss.mechanism");
if (defaultOidStr != null) {
defOid = GSSUtil.createOid(defaultOidStr);
}
--- a/src/java.security.jgss/share/classes/sun/security/jgss/krb5/AcceptSecContextToken.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.security.jgss/share/classes/sun/security/jgss/krb5/AcceptSecContextToken.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,7 +28,6 @@
import org.ietf.jgss.*;
import java.io.InputStream;
import java.io.IOException;
-import java.security.AccessController;
import sun.security.action.GetBooleanAction;
import sun.security.krb5.*;
@@ -45,8 +44,8 @@
KrbApReq apReq)
throws KrbException, IOException, GSSException {
- boolean useSubkey = AccessController.doPrivileged(
- new GetBooleanAction("sun.security.krb5.acceptor.subkey"));
+ boolean useSubkey = GetBooleanAction
+ .privilegedGetProperty("sun.security.krb5.acceptor.subkey");
boolean useSequenceNumber = true;
--- a/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5Util.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5Util.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,12 +26,13 @@
package sun.security.jgss.krb5;
import javax.security.auth.kerberos.KerberosTicket;
-import javax.security.auth.kerberos.KerberosKey;
import javax.security.auth.kerberos.KerberosPrincipal;
import javax.security.auth.kerberos.KeyTab;
import javax.security.auth.Subject;
import javax.security.auth.login.LoginException;
import java.security.AccessControlContext;
+
+import sun.security.action.GetBooleanAction;
import sun.security.jgss.GSSUtil;
import sun.security.jgss.GSSCaller;
@@ -39,20 +40,16 @@
import sun.security.krb5.EncryptionKey;
import sun.security.krb5.KrbException;
import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
import sun.security.krb5.KerberosSecrets;
import sun.security.krb5.PrincipalName;
+
/**
* Utilities for obtaining and converting Kerberos tickets.
- *
*/
public class Krb5Util {
- static final boolean DEBUG =
- java.security.AccessController.doPrivileged(
- new sun.security.action.GetBooleanAction
- ("sun.security.krb5.debug")).booleanValue();
+ static final boolean DEBUG = GetBooleanAction
+ .privilegedGetProperty("sun.security.krb5.debug");
/**
* Default constructor
--- a/src/java.security.jgss/share/classes/sun/security/jgss/spnego/SpNegoContext.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.security.jgss/share/classes/sun/security/jgss/spnego/SpNegoContext.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
* 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 @@
import java.io.*;
import java.security.Provider;
import org.ietf.jgss.*;
+import sun.security.action.GetBooleanAction;
import sun.security.jgss.*;
import sun.security.jgss.spi.*;
import sun.security.util.*;
@@ -81,10 +82,8 @@
final private SpNegoMechFactory factory;
// debug property
- static final boolean DEBUG =
- java.security.AccessController.doPrivileged(
- new sun.security.action.GetBooleanAction
- ("sun.security.spnego.debug")).booleanValue();
+ static final boolean DEBUG = GetBooleanAction
+ .privilegedGetProperty("sun.security.spnego.debug");
/**
* Constructor for SpNegoContext to be called on the context initiator's
@@ -584,7 +583,8 @@
}
} else {
negoResult = SpNegoToken.NegoResult.REJECT;
- state = STATE_DONE;
+ state = STATE_DELETED;
+ throw new GSSException(GSSException.FAILURE);
}
if (DEBUG) {
@@ -643,7 +643,8 @@
}
} else {
negoResult = SpNegoToken.NegoResult.REJECT;
- state = STATE_DONE;
+ state = STATE_DELETED;
+ throw new GSSException(GSSException.FAILURE);
}
// generate SPNEGO token
--- a/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/SunNativeProvider.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/SunNativeProvider.java Thu Aug 23 11:09:16 2018 -0400
@@ -51,8 +51,6 @@
private static final String INFO = "Sun Native GSS provider";
private static final String MF_CLASS =
"sun.security.jgss.wrapper.NativeGSSFactory";
- private static final String LIB_PROP = "sun.security.jgss.lib";
- private static final String DEBUG_PROP = "sun.security.nativegss.debug";
private static final HashMap<String, String> MECH_MAP;
static final Provider INSTANCE;
static boolean DEBUG;
@@ -70,8 +68,8 @@
AccessController.doPrivileged(
new PrivilegedAction<HashMap<String, String>>() {
public HashMap<String, String> run() {
- DEBUG = Boolean.parseBoolean
- (System.getProperty(DEBUG_PROP));
+ DEBUG = Boolean.parseBoolean(
+ System.getProperty("sun.security.nativegss.debug"));
try {
System.loadLibrary("j2gss");
} catch (Error err) {
@@ -80,7 +78,8 @@
return null;
}
String[] gssLibs = new String[0];
- String defaultLib = System.getProperty(LIB_PROP);
+ String defaultLib
+ = System.getProperty("sun.security.jgss.lib");
if (defaultLib == null || defaultLib.trim().equals("")) {
String osname = System.getProperty("os.name");
if (osname.startsWith("SunOS")) {
--- a/src/java.security.jgss/share/classes/sun/security/krb5/Config.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.security.jgss/share/classes/sun/security/krb5/Config.java Thu Aug 23 11:09:16 2018 -0400
@@ -45,6 +45,7 @@
import java.util.regex.Pattern;
import sun.net.dns.ResolverConfiguration;
+import sun.security.action.GetPropertyAction;
import sun.security.krb5.internal.crypto.EType;
import sun.security.krb5.internal.Krb5;
@@ -122,12 +123,12 @@
private static boolean isMacosLionOrBetter() {
// split the "10.x.y" version number
- String osname = getProperty("os.name");
+ String osname = GetPropertyAction.privilegedGetProperty("os.name");
if (!osname.contains("OS X")) {
return false;
}
- String osVersion = getProperty("os.version");
+ String osVersion = GetPropertyAction.privilegedGetProperty("os.version");
String[] fragments = osVersion.split("\\.");
// sanity check the "10." part of the version
@@ -152,14 +153,16 @@
/*
* If either one system property is specified, we throw exception.
*/
- String tmp = getProperty("java.security.krb5.kdc");
+ String tmp = GetPropertyAction
+ .privilegedGetProperty("java.security.krb5.kdc");
if (tmp != null) {
// The user can specify a list of kdc hosts separated by ":"
defaultKDC = tmp.replace(':', ' ');
} else {
defaultKDC = null;
}
- defaultRealm = getProperty("java.security.krb5.realm");
+ defaultRealm = GetPropertyAction
+ .privilegedGetProperty("java.security.krb5.realm");
if ((defaultKDC == null && defaultRealm != null) ||
(defaultRealm == null && defaultKDC != null)) {
throw new KrbException
@@ -818,11 +821,12 @@
* The method returns null if it cannot find a Java config file.
*/
private String getJavaFileName() {
- String name = getProperty("java.security.krb5.conf");
+ String name = GetPropertyAction
+ .privilegedGetProperty("java.security.krb5.conf");
if (name == null) {
- name = getProperty("java.home") + File.separator +
- "conf" + File.separator + "security" +
- File.separator + "krb5.conf";
+ name = GetPropertyAction.privilegedGetProperty("java.home")
+ + File.separator + "conf" + File.separator + "security"
+ + File.separator + "krb5.conf";
if (!fileExists(name)) {
name = null;
}
@@ -852,7 +856,7 @@
*/
private String getNativeFileName() {
String name = null;
- String osname = getProperty("os.name");
+ String osname = GetPropertyAction.privilegedGetProperty("os.name");
if (osname.startsWith("Windows")) {
try {
Credentials.ensureLoaded();
@@ -899,13 +903,8 @@
return name;
}
- private static String getProperty(String property) {
- return java.security.AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction(property));
- }
-
private String findMacosConfigFile() {
- String userHome = getProperty("user.home");
+ String userHome = GetPropertyAction.privilegedGetProperty("user.home");
final String PREF_FILE = "/Library/Preferences/edu.mit.Kerberos";
String userPrefs = userHome + PREF_FILE;
--- a/src/java.security.jgss/share/classes/sun/security/krb5/Credentials.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.security.jgss/share/classes/sun/security/krb5/Credentials.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 @@
package sun.security.krb5;
+import sun.security.action.GetPropertyAction;
import sun.security.krb5.internal.*;
import sun.security.krb5.internal.ccache.CredentialsCache;
import sun.security.krb5.internal.crypto.EType;
@@ -288,8 +289,7 @@
if (ticketCache == null) {
// The default ticket cache on Windows and Mac is not a file.
- String os = java.security.AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction("os.name"));
+ String os = GetPropertyAction.privilegedGetProperty("os.name");
if (os.toUpperCase(Locale.ENGLISH).startsWith("WINDOWS") ||
os.toUpperCase(Locale.ENGLISH).contains("OS X")) {
Credentials creds = acquireDefaultCreds();
--- a/src/java.security.jgss/share/classes/sun/security/krb5/KdcComm.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.security.jgss/share/classes/sun/security/krb5/KdcComm.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,6 @@
private static final boolean DEBUG = Krb5.DEBUG;
- private static final String BAD_POLICY_KEY = "krb5.kdc.bad.policy";
-
/**
* What to do when a KDC is unavailable, specified in the
* java.security file with key krb5.kdc.bad.policy.
@@ -100,7 +98,7 @@
String value = AccessController.doPrivileged(
new PrivilegedAction<String>() {
public String run() {
- return Security.getProperty(BAD_POLICY_KEY);
+ return Security.getProperty("krb5.kdc.bad.policy");
}
});
if (value != null) {
@@ -120,7 +118,7 @@
// Ignored. Please note that tryLess is recognized and
// used, parameters using default values
if (DEBUG) {
- System.out.println("Invalid " + BAD_POLICY_KEY +
+ System.out.println("Invalid krb5.kdc.bad.policy" +
" parameter for tryLess: " +
value + ", use default");
}
--- a/src/java.security.jgss/share/classes/sun/security/krb5/Realm.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.security.jgss/share/classes/sun/security/krb5/Realm.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 @@
package sun.security.krb5;
+import sun.security.action.GetBooleanAction;
import sun.security.krb5.internal.Krb5;
import sun.security.util.*;
import java.io.IOException;
@@ -47,10 +48,8 @@
*/
public class Realm implements Cloneable {
- public static final boolean AUTODEDUCEREALM =
- java.security.AccessController.doPrivileged(
- new sun.security.action.GetBooleanAction(
- "sun.security.krb5.autodeducerealm"));
+ public static final boolean AUTODEDUCEREALM = GetBooleanAction
+ .privilegedGetProperty("sun.security.krb5.autodeducerealm");
private final String realm; // not null nor empty
--- a/src/java.security.jgss/share/classes/sun/security/krb5/internal/Krb5.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.security.jgss/share/classes/sun/security/krb5/internal/Krb5.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
* 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 @@
package sun.security.krb5.internal;
+import sun.security.action.GetBooleanAction;
+
import java.util.Hashtable;
// Constants and other defined values from RFC 4120
@@ -303,9 +305,9 @@
}
- public static final boolean DEBUG =
- java.security.AccessController.doPrivileged(
- new sun.security.action.GetBooleanAction("sun.security.krb5.debug"));
+ public static final boolean DEBUG = GetBooleanAction
+ .privilegedGetProperty("sun.security.krb5.debug");
+
public static final sun.security.util.HexDumpEncoder hexDumper =
new sun.security.util.HexDumpEncoder();
--- a/src/java.security.jgss/share/classes/sun/security/krb5/internal/ReplayCache.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.security.jgss/share/classes/sun/security/krb5/internal/ReplayCache.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,8 +30,6 @@
import sun.security.krb5.internal.rcache.MemoryCache;
import sun.security.krb5.internal.rcache.DflCache;
-import java.security.AccessController;
-
/**
* Models the replay cache of an acceptor as described in
* RFC 4120 3.2.3.
@@ -56,8 +54,8 @@
}
}
public static ReplayCache getInstance() {
- String type = AccessController.doPrivileged(
- new GetPropertyAction("sun.security.krb5.rcache"));
+ String type = GetPropertyAction
+ .privilegedGetProperty("sun.security.krb5.rcache");
return getInstance(type);
}
--- a/src/java.security.jgss/share/classes/sun/security/krb5/internal/ccache/FileCredentialsCache.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.security.jgss/share/classes/sun/security/krb5/internal/ccache/FileCredentialsCache.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
* 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 @@
*/
package sun.security.krb5.internal.ccache;
+import sun.security.action.GetPropertyAction;
import sun.security.krb5.*;
import sun.security.krb5.internal.*;
import java.util.StringTokenizer;
@@ -381,9 +382,7 @@
}
// get cache name from system.property
- String osname =
- java.security.AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction("os.name"));
+ String osname = GetPropertyAction.privilegedGetProperty("os.name");
/*
* For Unix platforms we use the default cache name to be
@@ -417,18 +416,12 @@
// we did not get the uid;
- String user_name =
- java.security.AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction("user.name"));
+ String user_name = GetPropertyAction.privilegedGetProperty("user.name");
- String user_home =
- java.security.AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction("user.home"));
+ String user_home = GetPropertyAction.privilegedGetProperty("user.home");
if (user_home == null) {
- user_home =
- java.security.AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction("user.dir"));
+ user_home = GetPropertyAction.privilegedGetProperty("user.dir");
}
if (user_name != null) {
--- a/src/java.security.jgss/share/classes/sun/security/krb5/internal/crypto/Des.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.security.jgss/share/classes/sun/security/krb5/internal/crypto/Des.java Thu Aug 23 11:09:16 2018 -0400
@@ -53,9 +53,8 @@
// string-to-key encoding. When set, the specified charset
// name is used. Otherwise, the system default charset.
- private final static String CHARSET =
- java.security.AccessController.doPrivileged(
- new GetPropertyAction("sun.security.krb5.msinterop.des.s2kcharset"));
+ private final static String CHARSET = GetPropertyAction
+ .privilegedGetProperty("sun.security.krb5.msinterop.des.s2kcharset");
private static final long[] bad_keys = {
0x0101010101010101L, 0xfefefefefefefefeL,
--- a/src/java.security.jgss/share/classes/sun/security/krb5/internal/ktab/KeyTab.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.security.jgss/share/classes/sun/security/krb5/internal/ktab/KeyTab.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 @@
package sun.security.krb5.internal.ktab;
+import sun.security.action.GetPropertyAction;
import sun.security.krb5.*;
import sun.security.krb5.internal.*;
import sun.security.krb5.internal.crypto.*;
@@ -203,14 +204,12 @@
}
if (kname == null) {
- String user_home =
- java.security.AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction("user.home"));
+ String user_home = GetPropertyAction
+ .privilegedGetProperty("user.home");
if (user_home == null) {
- user_home =
- java.security.AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction("user.dir"));
+ user_home = GetPropertyAction
+ .privilegedGetProperty("user.dir");
}
kname = user_home + File.separator + "krb5.keytab";
--- a/src/java.security.jgss/share/classes/sun/security/krb5/internal/rcache/AuthTimeWithHash.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.security.jgss/share/classes/sun/security/krb5/internal/rcache/AuthTimeWithHash.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* 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 @@
package sun.security.krb5.internal.rcache;
-import sun.security.action.GetPropertyAction;
+import sun.security.action.GetBooleanAction;
import java.util.Objects;
@@ -40,8 +40,7 @@
public static final String DEFAULT_HASH_ALG;
static {
- if (GetPropertyAction.privilegedGetProperty(
- "jdk.krb5.rcache.useMD5", "false").equals("true")) {
+ if (GetBooleanAction.privilegedGetProperty("jdk.krb5.rcache.useMD5")) {
DEFAULT_HASH_ALG = "HASH";
} else {
DEFAULT_HASH_ALG = "SHA256";
--- a/src/java.security.jgss/share/classes/sun/security/krb5/internal/rcache/DflCache.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.security.jgss/share/classes/sun/security/krb5/internal/rcache/DflCache.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -36,7 +36,6 @@
import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption;
import java.nio.file.attribute.PosixFilePermission;
-import java.security.AccessController;
import java.util.*;
import sun.security.action.GetPropertyAction;
@@ -117,8 +116,7 @@
}
private static String defaultPath() {
- return AccessController.doPrivileged(
- new GetPropertyAction("java.io.tmpdir"));
+ return GetPropertyAction.privilegedGetProperty("java.io.tmpdir");
}
private static String defaultFile(String server) {
--- a/src/java.security.jgss/share/classes/sun/security/krb5/internal/util/KerberosString.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.security.jgss/share/classes/sun/security/krb5/internal/util/KerberosString.java Thu Aug 23 11:09:16 2018 -0400
@@ -55,8 +55,8 @@
public static final boolean MSNAME;
static {
- String prop = GetPropertyAction.privilegedGetProperty(
- "sun.security.krb5.msinterop.kstring", "true");
+ String prop = GetPropertyAction
+ .privilegedGetProperty("sun.security.krb5.msinterop.kstring", "true");
MSNAME = Boolean.parseBoolean(prop);
}
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java Thu Aug 23 11:09:16 2018 -0400
@@ -1634,6 +1634,8 @@
}
} else {
//CData partially returned due to the size limit
+ fInCData = true;
+ fCDataEnd = false;
break;
}
//by this time we have also read surrogate contents if any...
@@ -2928,7 +2930,11 @@
fUsebuffer = true;
//CDATA section is read up to the chunk size limit
scanCDATASection(fContentBuffer , true);
- setScannerState(SCANNER_STATE_CONTENT);
+ if (!fCDataEnd) {
+ setScannerState(SCANNER_STATE_CDATA);
+ } else {
+ setScannerState(SCANNER_STATE_CONTENT);
+ }
//1. if fIsCoalesce is set to true we set the variable fLastSectionWasCData to true
//and just call fDispatche.next(). Since we have set the scanner state to
//SCANNER_STATE_CONTENT (super state) parser will automatically recover and
@@ -2941,9 +2947,6 @@
//there might be more data to coalesce.
continue;
} else if(fReportCdataEvent) {
- if (!fCDataEnd) {
- setScannerState(SCANNER_STATE_CDATA);
- }
return XMLEvent.CDATA;
} else {
return XMLEvent.CHARACTERS;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat;
import static org.graalvm.compiler.hotspot.meta.HotSpotAOTProfilingPlugin.Options.TieredAOT;
@@ -137,23 +139,23 @@
*/
private static final HashMap<String, String> functionNamesToAOTSymbols = new HashMap<>();
+ //@formatter:off
private static final String[][] map = {
-//@formatter:off
- {"CompilerToVM::Data::SharedRuntime_deopt_blob_unpack", "_aot_deopt_blob_unpack"},
- {"CompilerToVM::Data::SharedRuntime_deopt_blob_uncommon_trap", "_aot_deopt_blob_uncommon_trap"},
- {"CompilerToVM::Data::SharedRuntime_ic_miss_stub", "_aot_ic_miss_stub"},
- {"CompilerToVM::Data::SharedRuntime_handle_wrong_method_stub", "_aot_handle_wrong_method_stub"},
- {"SharedRuntime::exception_handler_for_return_address", "_aot_exception_handler_for_return_address"},
- {"SharedRuntime::register_finalizer", "_aot_register_finalizer"},
- {"SharedRuntime::OSR_migration_end", "_aot_OSR_migration_end"},
- {"SharedRuntime::enable_stack_reserved_zone", "_aot_enable_stack_reserved_zone"},
- {"CompilerRuntime::resolve_dynamic_invoke", "_aot_resolve_dynamic_invoke"},
- {"CompilerRuntime::resolve_string_by_symbol", "_aot_resolve_string_by_symbol"},
- {"CompilerRuntime::resolve_klass_by_symbol", "_aot_resolve_klass_by_symbol"},
- {"CompilerRuntime::resolve_method_by_symbol_and_load_counters","_aot_resolve_method_by_symbol_and_load_counters"},
- {"CompilerRuntime::initialize_klass_by_symbol", "_aot_initialize_klass_by_symbol"},
- {"CompilerRuntime::invocation_event", "_aot_invocation_event"},
- {"CompilerRuntime::backedge_event", "_aot_backedge_event"},
+ {"CompilerToVM::Data::SharedRuntime_deopt_blob_unpack", "_aot_deopt_blob_unpack"},
+ {"CompilerToVM::Data::SharedRuntime_deopt_blob_uncommon_trap", "_aot_deopt_blob_uncommon_trap"},
+ {"CompilerToVM::Data::SharedRuntime_ic_miss_stub", "_aot_ic_miss_stub"},
+ {"CompilerToVM::Data::SharedRuntime_handle_wrong_method_stub", "_aot_handle_wrong_method_stub"},
+ {"SharedRuntime::exception_handler_for_return_address", "_aot_exception_handler_for_return_address"},
+ {"SharedRuntime::register_finalizer", "_aot_register_finalizer"},
+ {"SharedRuntime::OSR_migration_end", "_aot_OSR_migration_end"},
+ {"SharedRuntime::enable_stack_reserved_zone", "_aot_enable_stack_reserved_zone"},
+ {"CompilerRuntime::resolve_dynamic_invoke", "_aot_resolve_dynamic_invoke"},
+ {"CompilerRuntime::resolve_string_by_symbol", "_aot_resolve_string_by_symbol"},
+ {"CompilerRuntime::resolve_klass_by_symbol", "_aot_resolve_klass_by_symbol"},
+ {"CompilerRuntime::resolve_method_by_symbol_and_load_counters", "_aot_resolve_method_by_symbol_and_load_counters"},
+ {"CompilerRuntime::initialize_klass_by_symbol", "_aot_initialize_klass_by_symbol"},
+ {"CompilerRuntime::invocation_event", "_aot_invocation_event"},
+ {"CompilerRuntime::backedge_event", "_aot_backedge_event"},
{"CompilerToVM::Data::dpow", "_aot_shared_runtime_dpow"},
{"CompilerToVM::Data::dexp", "_aot_shared_runtime_dexp"},
@@ -256,8 +258,8 @@
{"JVMCIRuntime::vm_error", "_aot_jvmci_runtime_vm_error"},
{"JVMCIRuntime::new_array", "_aot_jvmci_runtime_new_array"}
- //@formatter:on
};
+ //@formatter:on
static {
for (String[] entry : map) {
@@ -320,6 +322,7 @@
}
private void recordConfiguration(GraalHotSpotVMConfig graalHotSpotVMConfig, GraphBuilderConfiguration graphBuilderConfig, int gc) {
+ // @Checkstyle: stop
// @formatter:off
boolean[] booleanFlags = { graalHotSpotVMConfig.cAssertions, // Debug VM
graalHotSpotVMConfig.useCompressedOops,
@@ -343,6 +346,7 @@
gc
};
// @formatter:on
+ // @Checkstyle: resume
byte[] booleanFlagsAsBytes = flagsToByteArray(booleanFlags);
int size0 = configContainer.getByteStreamSize();
@@ -447,7 +451,6 @@
return threadLocalHandshakes;
}
-
/**
* Gets the global AOT symbol associated with the function name.
*
@@ -542,8 +545,9 @@
JPECoffRelocObject pecoffobj = new JPECoffRelocObject(this, outputFileName);
pecoffobj.createPECoffRelocObject(relocationTable, symbolTable.values());
break;
- } else
+ } else {
throw new InternalError("Unsupported platform: " + osName);
+ }
}
}
@@ -553,6 +557,7 @@
*
* @param symInfo symbol information to be added
*/
+ @Override
public void addSymbol(Symbol symInfo) {
if (symInfo.getName().startsWith("got.") && !(symInfo instanceof GotSymbol)) {
throw new InternalError("adding got. without being GotSymbol");
@@ -578,7 +583,8 @@
* @param info relocation information to be added
*/
public void addRelocation(Relocation info) {
- // System.out.println("# Relocation [" + info.getSymbol() + "] [" + info.getOffset() + "] [" +
+ // System.out.println("# Relocation [" + info.getSymbol() + "] [" + info.getOffset() + "] ["
+ // +
// info.getSection().getContainerName() + "] [" + info.getSymbol().getName() + "] [" +
// info.getSymbol().getOffset() + " @ " + info.getSymbol().getSection().getContainerName() +
// "]");
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/ByteContainer.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/ByteContainer.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,11 +21,12 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat;
import jdk.tools.jaotc.binformat.Symbol.Binding;
import jdk.tools.jaotc.binformat.Symbol.Kind;
-import jdk.tools.jaotc.binformat.Container;
import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer;
@@ -184,6 +185,7 @@
*
* @return string containing name
*/
+ @Override
public String getContainerName() {
return containerName;
}
@@ -218,6 +220,7 @@
sectionId = id;
}
+ @Override
public int getSectionId() {
if (sectionId == -1) {
throw new InternalError("Using sectionId before assigned");
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/CodeContainer.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/CodeContainer.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat;
/**
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Container.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Container.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat;
interface Container {
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/GotSymbol.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/GotSymbol.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat;
public final class GotSymbol extends Symbol {
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/HeaderContainer.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/HeaderContainer.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat;
import java.io.ByteArrayOutputStream;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/NativeSymbol.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/NativeSymbol.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,10 +21,12 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat;
/**
- * This class represents ia native OS specific Symbol
+ * This class represents a native OS specific Symbol.
*/
public abstract class NativeSymbol {
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/ReadOnlyDataContainer.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/ReadOnlyDataContainer.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat;
public final class ReadOnlyDataContainer extends ByteContainer {
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Relocation.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Relocation.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,10 +21,13 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat;
public final class Relocation {
+ // @formatter:off (workaround for Eclipse formatting bug)
public enum RelocType {
UNDEFINED,
JAVA_CALL_INDIRECT,
@@ -35,6 +38,7 @@
EXTERNAL_GOT_TO_PLT,
EXTERNAL_PLT_TO_GOT
}
+ // @formatter:on
private final RelocType type;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Symbol.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Symbol.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,14 +21,15 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat;
import java.util.Objects;
-import jdk.tools.jaotc.binformat.NativeSymbol;
-
public class Symbol {
+ // @formatter:off (workaround for Eclipse formatting bug)
public enum Binding {
UNDEFINED,
LOCAL,
@@ -42,6 +43,7 @@
OBJECT,
NOTYPE
}
+ // @formatter:on
private final String name;
private final int size;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/SymbolTable.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/SymbolTable.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat;
public interface SymbolTable {
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/AArch64JELFRelocObject.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/AArch64JELFRelocObject.java Thu Aug 23 11:09:16 2018 -0400
@@ -22,39 +22,24 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat.elf;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
import jdk.tools.jaotc.binformat.BinaryContainer;
-import jdk.tools.jaotc.binformat.ByteContainer;
-import jdk.tools.jaotc.binformat.CodeContainer;
-import jdk.tools.jaotc.binformat.ReadOnlyDataContainer;
import jdk.tools.jaotc.binformat.Relocation;
import jdk.tools.jaotc.binformat.Relocation.RelocType;
import jdk.tools.jaotc.binformat.Symbol;
-import jdk.tools.jaotc.binformat.Symbol.Binding;
-import jdk.tools.jaotc.binformat.Symbol.Kind;
-
-import jdk.tools.jaotc.binformat.elf.ElfSymbol;
-import jdk.tools.jaotc.binformat.elf.ElfTargetInfo;
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr;
-import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Shdr;
-import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Sym;
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rela;
-
public class AArch64JELFRelocObject extends JELFRelocObject {
AArch64JELFRelocObject(BinaryContainer binContainer, String outputFileName) {
super(binContainer, outputFileName);
}
+ @Override
void createRelocation(Symbol symbol, Relocation reloc, ElfRelocTable elfRelocTable) {
RelocType relocType = reloc.getType();
@@ -66,38 +51,38 @@
int addend = 0;
switch (relocType) {
- case STUB_CALL_DIRECT:
- case JAVA_CALL_DIRECT: {
- break;
- }
- case EXTERNAL_PLT_TO_GOT:
- offset -= 16;
- elfRelocTable.createRelocationEntry(sectindex, offset, symno, Elf64_Rela.R_AARCH64_ADR_PREL_PG_HI21, addend);
- elfRelocTable.createRelocationEntry(sectindex, offset + 4, symno, Elf64_Rela.R_AARCH64_ADD_ABS_LO12_NC, addend);
- return;
+ case STUB_CALL_DIRECT:
+ case JAVA_CALL_DIRECT: {
+ break;
+ }
+ case EXTERNAL_PLT_TO_GOT:
+ offset -= 16;
+ elfRelocTable.createRelocationEntry(sectindex, offset, symno, Elf64_Rela.R_AARCH64_ADR_PREL_PG_HI21, addend);
+ elfRelocTable.createRelocationEntry(sectindex, offset + 4, symno, Elf64_Rela.R_AARCH64_ADD_ABS_LO12_NC, addend);
+ return;
- case FOREIGN_CALL_INDIRECT_GOT: {
- break;
- }
- case METASPACE_GOT_REFERENCE: {
- offset -= 4;
+ case FOREIGN_CALL_INDIRECT_GOT: {
+ break;
+ }
+ case METASPACE_GOT_REFERENCE: {
+ offset -= 4;
- elfRelocTable.createRelocationEntry(sectindex, offset, symno, Elf64_Rela.R_AARCH64_ADR_PREL_PG_HI21, addend);
- elfRelocTable.createRelocationEntry(sectindex, offset + 4, symno, Elf64_Rela.R_AARCH64_ADD_ABS_LO12_NC, addend);
- return;
- }
+ elfRelocTable.createRelocationEntry(sectindex, offset, symno, Elf64_Rela.R_AARCH64_ADR_PREL_PG_HI21, addend);
+ elfRelocTable.createRelocationEntry(sectindex, offset + 4, symno, Elf64_Rela.R_AARCH64_ADD_ABS_LO12_NC, addend);
+ return;
+ }
// break;
- case JAVA_CALL_INDIRECT: {
- addend = -4;
- offset = offset + addend;
- break;
- }
- case EXTERNAL_GOT_TO_PLT: {
- // this is load time relocations
- break;
- }
- default:
- throw new InternalError("Unhandled relocation type: " + relocType);
+ case JAVA_CALL_INDIRECT: {
+ addend = -4;
+ offset = offset + addend;
+ break;
+ }
+ case EXTERNAL_GOT_TO_PLT: {
+ // this is load time relocations
+ break;
+ }
+ default:
+ throw new InternalError("Unhandled relocation type: " + relocType);
}
elfRelocTable.createRelocationEntry(sectindex, offset, symno, elfRelocType, addend);
@@ -109,14 +94,14 @@
case Elf64_Ehdr.EM_AARCH64:
// Return R_X86_64_* entries based on relocType
if (relocType == RelocType.JAVA_CALL_DIRECT ||
- relocType == RelocType.FOREIGN_CALL_INDIRECT_GOT) {
+ relocType == RelocType.FOREIGN_CALL_INDIRECT_GOT) {
elfRelocType = Elf64_Rela.R_AARCH64_CALL26;
} else if (relocType == RelocType.STUB_CALL_DIRECT) {
elfRelocType = Elf64_Rela.R_AARCH64_CALL26;
} else if (relocType == RelocType.JAVA_CALL_INDIRECT) {
elfRelocType = Elf64_Rela.R_AARCH64_CALL26;
} else if (relocType == RelocType.METASPACE_GOT_REFERENCE ||
- relocType == RelocType.EXTERNAL_PLT_TO_GOT) {
+ relocType == RelocType.EXTERNAL_PLT_TO_GOT) {
elfRelocType = Elf64_Rela.R_AARCH64_NONE;
} else if (relocType == RelocType.EXTERNAL_GOT_TO_PLT) {
elfRelocType = Elf64_Rela.R_AARCH64_ABS64;
@@ -126,8 +111,7 @@
break;
default:
- System.out.println("Relocation Type mapping: Unhandled architecture: "
- + ElfTargetInfo.getElfArch());
+ System.out.println("Relocation Type mapping: Unhandled architecture: " + ElfTargetInfo.getElfArch());
}
return elfRelocType;
}
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/AMD64JELFRelocObject.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/AMD64JELFRelocObject.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,39 +21,24 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat.elf;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
import jdk.tools.jaotc.binformat.BinaryContainer;
-import jdk.tools.jaotc.binformat.ByteContainer;
-import jdk.tools.jaotc.binformat.CodeContainer;
-import jdk.tools.jaotc.binformat.ReadOnlyDataContainer;
import jdk.tools.jaotc.binformat.Relocation;
import jdk.tools.jaotc.binformat.Relocation.RelocType;
import jdk.tools.jaotc.binformat.Symbol;
-import jdk.tools.jaotc.binformat.Symbol.Binding;
-import jdk.tools.jaotc.binformat.Symbol.Kind;
-
-import jdk.tools.jaotc.binformat.elf.ElfSymbol;
-import jdk.tools.jaotc.binformat.elf.ElfTargetInfo;
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr;
-import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Shdr;
-import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Sym;
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rela;
-
public class AMD64JELFRelocObject extends JELFRelocObject {
AMD64JELFRelocObject(BinaryContainer binContainer, String outputFileName) {
super(binContainer, outputFileName);
}
+ @Override
protected void createRelocation(Symbol symbol, Relocation reloc, ElfRelocTable elfRelocTable) {
RelocType relocType = reloc.getType();
@@ -65,62 +50,61 @@
int addend = 0;
switch (relocType) {
- case JAVA_CALL_DIRECT:
- case STUB_CALL_DIRECT:
- case FOREIGN_CALL_INDIRECT_GOT: {
- // Create relocation entry
- addend = -4; // Size in bytes of the patch location
- // Relocation should be applied at the location after call operand
- offset = offset + reloc.getSize() + addend;
- break;
- }
- case JAVA_CALL_INDIRECT:
- case METASPACE_GOT_REFERENCE:
- case EXTERNAL_PLT_TO_GOT: {
- addend = -4; // Size of 32-bit address of the GOT
- /*
- * Relocation should be applied before the test instruction to the move instruction.
- * reloc.getOffset() points to the test instruction after the instruction that loads the address of
- * polling page. So set the offset appropriately.
- */
- offset = offset + addend;
- break;
- }
- case EXTERNAL_GOT_TO_PLT: {
- // this is load time relocations
- break;
- }
- default:
- throw new InternalError("Unhandled relocation type: " + relocType);
+ case JAVA_CALL_DIRECT:
+ case STUB_CALL_DIRECT:
+ case FOREIGN_CALL_INDIRECT_GOT: {
+ // Create relocation entry
+ addend = -4; // Size in bytes of the patch location
+ // Relocation should be applied at the location after call operand
+ offset = offset + reloc.getSize() + addend;
+ break;
+ }
+ case JAVA_CALL_INDIRECT:
+ case METASPACE_GOT_REFERENCE:
+ case EXTERNAL_PLT_TO_GOT: {
+ addend = -4; // Size of 32-bit address of the GOT
+ /*
+ * Relocation should be applied before the test instruction to the move instruction.
+ * reloc.getOffset() points to the test instruction after the instruction that loads
+ * the address of polling page. So set the offset appropriately.
+ */
+ offset = offset + addend;
+ break;
+ }
+ case EXTERNAL_GOT_TO_PLT: {
+ // this is load time relocations
+ break;
+ }
+ default:
+ throw new InternalError("Unhandled relocation type: " + relocType);
}
elfRelocTable.createRelocationEntry(sectindex, offset, symno, elfRelocType, addend);
}
- private int getELFRelocationType(RelocType relocType) {
+ private static int getELFRelocationType(RelocType relocType) {
int elfRelocType = 0; // R_<ARCH>_NONE if #define'd to 0 for all values of ARCH
switch (ElfTargetInfo.getElfArch()) {
- case Elf64_Ehdr.EM_X86_64:
- // Return R_X86_64_* entries based on relocType
- if (relocType == RelocType.JAVA_CALL_DIRECT ||
- relocType == RelocType.FOREIGN_CALL_INDIRECT_GOT) {
- elfRelocType = Elf64_Rela.R_X86_64_PLT32;
- } else if (relocType == RelocType.STUB_CALL_DIRECT) {
- elfRelocType = Elf64_Rela.R_X86_64_PC32;
- } else if (relocType == RelocType.JAVA_CALL_INDIRECT) {
- elfRelocType = Elf64_Rela.R_X86_64_NONE;
- } else if (relocType == RelocType.METASPACE_GOT_REFERENCE ||
- relocType == RelocType.EXTERNAL_PLT_TO_GOT) {
- elfRelocType = Elf64_Rela.R_X86_64_PC32;
- } else if (relocType == RelocType.EXTERNAL_GOT_TO_PLT) {
- elfRelocType = Elf64_Rela.R_X86_64_64;
- } else {
- assert false : "Unhandled relocation type: " + relocType;
- }
- break;
+ case Elf64_Ehdr.EM_X86_64:
+ // Return R_X86_64_* entries based on relocType
+ if (relocType == RelocType.JAVA_CALL_DIRECT ||
+ relocType == RelocType.FOREIGN_CALL_INDIRECT_GOT) {
+ elfRelocType = Elf64_Rela.R_X86_64_PLT32;
+ } else if (relocType == RelocType.STUB_CALL_DIRECT) {
+ elfRelocType = Elf64_Rela.R_X86_64_PC32;
+ } else if (relocType == RelocType.JAVA_CALL_INDIRECT) {
+ elfRelocType = Elf64_Rela.R_X86_64_NONE;
+ } else if (relocType == RelocType.METASPACE_GOT_REFERENCE ||
+ relocType == RelocType.EXTERNAL_PLT_TO_GOT) {
+ elfRelocType = Elf64_Rela.R_X86_64_PC32;
+ } else if (relocType == RelocType.EXTERNAL_GOT_TO_PLT) {
+ elfRelocType = Elf64_Rela.R_X86_64_64;
+ } else {
+ assert false : "Unhandled relocation type: " + relocType;
+ }
+ break;
- default:
- System.out.println("Relocation Type mapping: Unhandled architecture: "
- + ElfTargetInfo.getElfArch());
+ default:
+ System.out.println("Relocation Type mapping: Unhandled architecture: " + ElfTargetInfo.getElfArch());
}
return elfRelocType;
}
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/Elf.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/Elf.java Thu Aug 23 11:09:16 2018 -0400
@@ -22,18 +22,19 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat.elf;
+//@Checkstyle: stop
+//@formatter:off
+
/**
- *
* Support for the creation of Elf Object files. Current support is limited to 64 bit x86_64.
- *
*/
-
final class Elf {
- //@formatter:off
/**
- * Elf64_Ehdr structure defines
+ * Elf64_Ehdr structure defines.
*/
enum Elf64_Ehdr {
e_ident( 0,16),
@@ -103,7 +104,7 @@
}
/**
- * Elf64_Shdr structure defines
+ * Elf64_Shdr structure defines.
*/
enum Elf64_Shdr {
sh_name( 0, 4),
@@ -190,7 +191,7 @@
}
/**
- * Elf64_Rel structure defines
+ * Elf64_Rel structure defines.
*/
enum Elf64_Rel {
r_offset( 0, 8),
@@ -207,7 +208,7 @@
static int totalsize = 16;
/**
- * Relocation types
+ * Relocation types.
*/
static final int R_X86_64_NONE = 0x0;
@@ -270,9 +271,7 @@
static final int R_AARCH64_LDST64_ABS_LO12_NC = 286;
static long ELF64_R_INFO(int symidx, int type) {
- return (((long)symidx << 32) + type);
+ return (((long) symidx << 32) + type);
}
-
}
- //@formatter:on
}
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfByteBuffer.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfByteBuffer.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,12 +21,14 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat.elf;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
+
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr;
-import jdk.tools.jaotc.binformat.elf.ElfTargetInfo;
final class ElfByteBuffer {
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfContainer.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfContainer.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat.elf;
import java.io.File;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfHeader.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfHeader.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,14 +21,14 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat.elf;
import java.nio.ByteBuffer;
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr;
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Shdr;
-import jdk.tools.jaotc.binformat.elf.ElfTargetInfo;
-import jdk.tools.jaotc.binformat.elf.ElfByteBuffer;
final class ElfHeader {
private final ByteBuffer header;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfRelocEntry.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfRelocEntry.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,12 +21,13 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat.elf;
import java.nio.ByteBuffer;
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rela;
-import jdk.tools.jaotc.binformat.elf.ElfByteBuffer;
final class ElfRelocEntry {
private final ByteBuffer entry;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfRelocTable.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfRelocTable.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,14 +21,14 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat.elf;
+import java.nio.ByteBuffer;
import java.util.ArrayList;
-import java.nio.ByteBuffer;
-import jdk.tools.jaotc.binformat.elf.ElfRelocEntry;
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rela;
-import jdk.tools.jaotc.binformat.elf.ElfByteBuffer;
final class ElfRelocTable {
private final ArrayList<ArrayList<ElfRelocEntry>> relocEntries;
@@ -45,14 +45,14 @@
relocEntries.get(sectindex).add(entry);
}
- int getNumRelocs(int section_index) {
- return relocEntries.get(section_index).size();
+ int getNumRelocs(int sectionIndex) {
+ return relocEntries.get(sectionIndex).size();
}
// Return the relocation entries for a single section
// or null if no entries added to section
- byte[] getRelocData(int section_index) {
- ArrayList<ElfRelocEntry> entryList = relocEntries.get(section_index);
+ byte[] getRelocData(int sectionIndex) {
+ ArrayList<ElfRelocEntry> entryList = relocEntries.get(sectionIndex);
if (entryList.size() == 0) {
return null;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSection.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSection.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,15 +21,16 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat.elf;
import java.nio.ByteBuffer;
-import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Shdr;
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rel;
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rela;
+import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Shdr;
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Sym;
-import jdk.tools.jaotc.binformat.elf.ElfByteBuffer;
final class ElfSection {
private final String name;
@@ -39,9 +40,9 @@
private final int sectionIndex;
/**
- * String holding section name strings
+ * String holding section name strings.
*/
- private final static StringBuilder sectNameTab = new StringBuilder();
+ private static final StringBuilder sectNameTab = new StringBuilder();
/**
* Keeps track of bytes in section string table since strTabContent.length() is number of chars,
@@ -50,7 +51,7 @@
private static int shStrTabNrOfBytes = 0;
ElfSection(String sectName, byte[] sectData, int sectFlags, int sectType,
- boolean hasRelocations, int align, int sectIndex) {
+ boolean hasRelocations, int align, int sectIndex) {
section = ElfByteBuffer.allocate(Elf64_Shdr.totalsize);
name = sectName;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSymbol.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSymbol.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,13 +21,14 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat.elf;
import java.nio.ByteBuffer;
import jdk.tools.jaotc.binformat.NativeSymbol;
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Sym;
-import jdk.tools.jaotc.binformat.elf.ElfByteBuffer;
final class ElfSymbol extends NativeSymbol {
private final ByteBuffer sym;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSymtab.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSymtab.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,14 +21,14 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat.elf;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Sym;
-import jdk.tools.jaotc.binformat.elf.ElfSymbol;
-import jdk.tools.jaotc.binformat.elf.ElfByteBuffer;
final class ElfSymtab {
@@ -36,12 +36,12 @@
private final ArrayList<ElfSymbol> globalSymbols = new ArrayList<>();
/**
- * number of symbols added
+ * Number of symbols added.
*/
private int symbolCount;
/**
- * String holding symbol table strings
+ * String holding symbol table strings.
*/
private final StringBuilder strTabContent = new StringBuilder();
@@ -77,10 +77,11 @@
strTabNrOfBytes += (name.getBytes().length + 1);
sym = new ElfSymbol(symbolCount, index, type, bind, secHdrIndex, offset, size);
- if ((bind & Elf64_Sym.STB_GLOBAL) != 0)
+ if ((bind & Elf64_Sym.STB_GLOBAL) != 0) {
globalSymbols.add(sym);
- else
+ } else {
localSymbols.add(sym);
+ }
}
symbolCount++;
return (sym);
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfTargetInfo.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfTargetInfo.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat.elf;
import java.nio.ByteOrder;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/JELFRelocObject.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/JELFRelocObject.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat.elf;
import java.io.IOException;
@@ -34,17 +36,12 @@
import jdk.tools.jaotc.binformat.CodeContainer;
import jdk.tools.jaotc.binformat.ReadOnlyDataContainer;
import jdk.tools.jaotc.binformat.Relocation;
-import jdk.tools.jaotc.binformat.Relocation.RelocType;
import jdk.tools.jaotc.binformat.Symbol;
import jdk.tools.jaotc.binformat.Symbol.Binding;
import jdk.tools.jaotc.binformat.Symbol.Kind;
-
-import jdk.tools.jaotc.binformat.elf.ElfSymbol;
-import jdk.tools.jaotc.binformat.elf.ElfTargetInfo;
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr;
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Shdr;
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Sym;
-import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rela;
public abstract class JELFRelocObject {
@@ -64,22 +61,22 @@
String archStr = System.getProperty("os.arch").toLowerCase();
if (archStr.equals("amd64") || archStr.equals("x86_64")) {
return new AMD64JELFRelocObject(binContainer, outputFileName);
- } else if (archStr.equals("aarch64")) {
+ } else if (archStr.equals("aarch64")) {
return new AArch64JELFRelocObject(binContainer, outputFileName);
}
throw new InternalError("Unsupported platform: " + archStr);
}
private static ElfSection createByteSection(ArrayList<ElfSection> sections,
- String sectName,
- byte[] scnData,
- boolean hasRelocs,
- int align,
- int scnFlags,
- int scnType) {
+ String sectName,
+ byte[] scnData,
+ boolean hasRelocs,
+ int align,
+ int scnFlags,
+ int scnType) {
ElfSection sect = new ElfSection(sectName, scnData, scnFlags, scnType,
- hasRelocs, align, sections.size());
+ hasRelocs, align, sections.size());
// Add this section to our list
sections.add(sect);
@@ -87,7 +84,7 @@
}
private void createByteSection(ArrayList<ElfSection> sections,
- ByteContainer c, int scnFlags) {
+ ByteContainer c, int scnFlags) {
ElfSection sect;
boolean hasRelocs = c.hasRelocations();
byte[] scnData = c.getByteArray();
@@ -107,8 +104,8 @@
}
sect = createByteSection(sections, c.getContainerName(),
- scnData, hasRelocs, segmentSize,
- scnFlags, scnType);
+ scnData, hasRelocs, segmentSize,
+ scnFlags, scnType);
c.setSectionId(sect.getSectionId());
}
@@ -125,7 +122,7 @@
}
/**
- * Create an ELF relocatable object
+ * Creates an ELF relocatable object.
*
* @param relocationTable
* @param symbols
@@ -166,18 +163,18 @@
// that order since symtab section needs to set the index of
// strtab in sh_link field
ElfSection strTabSection = createByteSection(sections, ".strtab",
- symtab.getStrtabArray(),
- false, 1, 0,
- Elf64_Shdr.SHT_STRTAB);
+ symtab.getStrtabArray(),
+ false, 1, 0,
+ Elf64_Shdr.SHT_STRTAB);
// Now create .symtab section with the symtab data constructed.
// On Linux, sh_link of symtab contains the index of string table
// its symbols reference and sh_info contains the index of first
// non-local symbol
ElfSection symTabSection = createByteSection(sections, ".symtab",
- symtab.getSymtabArray(),
- false, 8, 0,
- Elf64_Shdr.SHT_SYMTAB);
+ symtab.getSymtabArray(),
+ false, 8, 0,
+ Elf64_Shdr.SHT_SYMTAB);
symTabSection.setLink(strTabSection.getSectionId());
symTabSection.setInfo(symtab.getNumLocalSyms());
@@ -187,35 +184,35 @@
// Now, finally, after creating all sections, create shstrtab section
ElfSection shStrTabSection = createByteSection(sections, ".shstrtab",
- null, false, 1, 0,
- Elf64_Shdr.SHT_STRTAB);
+ null, false, 1, 0,
+ Elf64_Shdr.SHT_STRTAB);
eh.setSectionStrNdx(shStrTabSection.getSectionId());
// Update all section offsets and the Elf header section offset
// Write the Header followed by the contents of each section
// and then the section structures (section table).
- int file_offset = Elf64_Ehdr.totalsize;
+ int fileOffset = Elf64_Ehdr.totalsize;
// and round it up
- file_offset = (file_offset + (sections.get(1).getDataAlign() - 1)) &
- ~((sections.get(1).getDataAlign() - 1));
+ fileOffset = (fileOffset + (sections.get(1).getDataAlign() - 1)) &
+ ~((sections.get(1).getDataAlign() - 1));
// Calc file offsets for section data skipping null section
for (int i = 1; i < sections.size(); i++) {
ElfSection sect = sections.get(i);
- file_offset = (file_offset + (sect.getDataAlign() - 1)) &
- ~((sect.getDataAlign() - 1));
- sect.setOffset(file_offset);
- file_offset += sect.getSize();
+ fileOffset = (fileOffset + (sect.getDataAlign() - 1)) &
+ ~((sect.getDataAlign() - 1));
+ sect.setOffset(fileOffset);
+ fileOffset += sect.getSize();
}
// Align the section table
- file_offset = (file_offset + (ElfSection.getShdrAlign() - 1)) &
- ~((ElfSection.getShdrAlign() - 1));
+ fileOffset = (fileOffset + (ElfSection.getShdrAlign() - 1)) &
+ ~((ElfSection.getShdrAlign() - 1));
// Update the Elf Header with the offset of the first Elf64_Shdr
// and the number of sections.
- eh.setSectionOff(file_offset);
+ eh.setSectionOff(fileOffset);
eh.setSectionNum(sections.size());
// Write out the Header
@@ -237,8 +234,8 @@
}
/**
- * Construct ELF symbol data from BinaryContainer object's symbol tables. Both dynamic ELF symbol
- * table and ELF symbol table are created from BinaryContainer's symbol info.
+ * Construct ELF symbol data from BinaryContainer object's symbol tables. Both dynamic ELF
+ * symbol table and ELF symbol table are created from BinaryContainer's symbol info.
*
* @param symbols
*/
@@ -283,11 +280,12 @@
* @param relocationTable
*/
private ElfRelocTable createElfRelocTable(ArrayList<ElfSection> sections,
- Map<Symbol, List<Relocation>> relocationTable) {
+ Map<Symbol, List<Relocation>> relocationTable) {
ElfRelocTable elfRelocTable = new ElfRelocTable(sections.size());
/*
- * For each of the symbols with associated relocation records, create a Elf relocation entry.
+ * For each of the symbols with associated relocation records, create a Elf relocation
+ * entry.
*/
for (Map.Entry<Symbol, List<Relocation>> entry : relocationTable.entrySet()) {
List<Relocation> relocs = entry.getValue();
@@ -306,8 +304,8 @@
}
private static void createElfRelocSections(ArrayList<ElfSection> sections,
- ElfRelocTable elfRelocTable,
- int symtabsectidx) {
+ ElfRelocTable elfRelocTable,
+ int symtabsectidx) {
// Grab count before we create new sections
int count = sections.size();
@@ -317,8 +315,8 @@
ElfSection sect = sections.get(i);
String relname = ".rela" + sect.getName();
ElfSection relocSection = createByteSection(sections, relname,
- elfRelocTable.getRelocData(i),
- false, 8, 0, Elf64_Shdr.SHT_RELA);
+ elfRelocTable.getRelocData(i),
+ false, 8, 0, Elf64_Shdr.SHT_RELA);
relocSection.setLink(symtabsectidx);
relocSection.setInfo(sect.getSectionId());
}
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/JMachORelocObject.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/JMachORelocObject.java Thu Aug 23 11:09:16 2018 -0400
@@ -38,6 +38,8 @@
*
*/
+
+
package jdk.tools.jaotc.binformat.macho;
import java.io.IOException;
@@ -54,19 +56,14 @@
import jdk.tools.jaotc.binformat.Relocation.RelocType;
import jdk.tools.jaotc.binformat.Symbol;
import jdk.tools.jaotc.binformat.Symbol.Kind;
-
-import jdk.tools.jaotc.binformat.macho.MachO.section_64;
+import jdk.tools.jaotc.binformat.macho.MachO.dysymtab_command;
import jdk.tools.jaotc.binformat.macho.MachO.mach_header_64;
-import jdk.tools.jaotc.binformat.macho.MachO.segment_command_64;
-import jdk.tools.jaotc.binformat.macho.MachO.version_min_command;
-import jdk.tools.jaotc.binformat.macho.MachO.symtab_command;
-import jdk.tools.jaotc.binformat.macho.MachO.dysymtab_command;
import jdk.tools.jaotc.binformat.macho.MachO.nlist_64;
import jdk.tools.jaotc.binformat.macho.MachO.reloc_info;
-import jdk.tools.jaotc.binformat.macho.MachOContainer;
-import jdk.tools.jaotc.binformat.macho.MachOTargetInfo;
-import jdk.tools.jaotc.binformat.macho.MachOSymtab;
-import jdk.tools.jaotc.binformat.macho.MachORelocTable;
+import jdk.tools.jaotc.binformat.macho.MachO.section_64;
+import jdk.tools.jaotc.binformat.macho.MachO.segment_command_64;
+import jdk.tools.jaotc.binformat.macho.MachO.symtab_command;
+import jdk.tools.jaotc.binformat.macho.MachO.version_min_command;
public class JMachORelocObject {
@@ -83,18 +80,18 @@
}
private void createByteSection(ArrayList<MachOSection> sections,
- ByteContainer c, String sectName, String segName, int scnFlags) {
+ ByteContainer c, String sectName, String segName, int scnFlags) {
if (c.getByteArray().length == 0) {
// System.out.println("Skipping creation of " + sectName + " section, no data\n");
}
MachOSection sect = new MachOSection(sectName,
- segName,
- c.getByteArray(),
- scnFlags,
- c.hasRelocations(),
- segmentSize);
+ segName,
+ c.getByteArray(),
+ scnFlags,
+ c.hasRelocations(),
+ segmentSize);
// Add this section to our list
sections.add(sect);
@@ -107,13 +104,13 @@
private void createCodeSection(ArrayList<MachOSection> sections, CodeContainer c) {
createByteSection(sections, c, /* c.getContainerName() */ "__text", "__TEXT",
- section_64.S_ATTR_PURE_INSTRUCTIONS |
- section_64.S_ATTR_SOME_INSTRUCTIONS);
+ section_64.S_ATTR_PURE_INSTRUCTIONS |
+ section_64.S_ATTR_SOME_INSTRUCTIONS);
}
private void createReadOnlySection(ArrayList<MachOSection> sections, ReadOnlyDataContainer c) {
createByteSection(sections, c, c.getContainerName(), "__TEXT",
- section_64.S_ATTR_SOME_INSTRUCTIONS);
+ section_64.S_ATTR_SOME_INSTRUCTIONS);
}
private void createReadWriteSection(ArrayList<MachOSection> sections, ByteContainer c) {
@@ -121,7 +118,7 @@
}
/**
- * Create an MachO relocatable object
+ * Creates an MachO relocatable object.
*
* @param relocationTable
* @param symbols
@@ -130,10 +127,10 @@
public void createMachORelocObject(Map<Symbol, List<Relocation>> relocationTable, Collection<Symbol> symbols) throws IOException {
// Allocate MachO Header
// with 4 load commands
- // LC_SEGMENT_64
- // LC_VERSION_MIN_MACOSX
- // LC_SYMTAB
- // LC_DYSYMTAB
+ // LC_SEGMENT_64
+ // LC_VERSION_MIN_MACOSX
+ // LC_SYMTAB
+ // LC_DYSYMTAB
MachOHeader mh = new MachOHeader();
@@ -162,37 +159,37 @@
// Update the Header sizeofcmds size.
// This doesn't include the Header struct size
mh.setCmdSizes(4, segment_command_64.totalsize +
- (section_64.totalsize * sections.size()) +
- version_min_command.totalsize +
- symtab_command.totalsize +
- dysymtab_command.totalsize);
+ (section_64.totalsize * sections.size()) +
+ version_min_command.totalsize +
+ symtab_command.totalsize +
+ dysymtab_command.totalsize);
// Initialize file offset for data past commands
- int file_offset = mach_header_64.totalsize + mh.getCmdSize();
+ int fileOffset = mach_header_64.totalsize + mh.getCmdSize();
// and round it up
- file_offset = (file_offset + (sections.get(0).getAlign() - 1)) & ~((sections.get(0).getAlign() - 1));
+ fileOffset = (fileOffset + (sections.get(0).getAlign() - 1)) & ~((sections.get(0).getAlign() - 1));
long address = 0;
- int segment_offset = file_offset;
+ int segmentOffset = fileOffset;
for (int i = 0; i < sections.size(); i++) {
MachOSection sect = sections.get(i);
- file_offset = (file_offset + (sect.getAlign() - 1)) & ~((sect.getAlign() - 1));
+ fileOffset = (fileOffset + (sect.getAlign() - 1)) & ~((sect.getAlign() - 1));
address = (address + (sect.getAlign() - 1)) & ~((sect.getAlign() - 1));
- sect.setOffset(file_offset);
+ sect.setOffset(fileOffset);
sect.setAddr(address);
- file_offset += sect.getSize();
+ fileOffset += sect.getSize();
address += sect.getSize();
}
// File size for Segment data
- int segment_size = file_offset - segment_offset;
+ int segSize = fileOffset - segmentOffset;
// Create the LC_SEGMENT_64 Segment which contains the MachOSections
MachOSegment seg = new MachOSegment(segment_command_64.totalsize +
- (section_64.totalsize * sections.size()),
- segment_offset,
- segment_size,
- sections.size());
+ (section_64.totalsize * sections.size()),
+ segmentOffset,
+ segSize,
+ sections.size());
MachOVersion vers = new MachOVersion();
@@ -201,28 +198,28 @@
// Create LC_DYSYMTAB command
MachODySymtab dysymtab = new MachODySymtab(symtab.getNumLocalSyms(),
- symtab.getNumGlobalSyms(),
- symtab.getNumUndefSyms());
+ symtab.getNumGlobalSyms(),
+ symtab.getNumUndefSyms());
// Create the Relocation Tables
MachORelocTable machORelocs = createMachORelocTable(sections, relocationTable, symtab);
// Calculate file offset for relocation data
- file_offset = (file_offset + (MachORelocTable.getAlign() - 1)) & ~((MachORelocTable.getAlign() - 1));
+ fileOffset = (fileOffset + (MachORelocTable.getAlign() - 1)) & ~((MachORelocTable.getAlign() - 1));
// Update relocation sizing information in each section
for (int i = 0; i < sections.size(); i++) {
MachOSection sect = sections.get(i);
if (sect.hasRelocations()) {
int nreloc = machORelocs.getNumRelocs(i);
- sect.setReloff(file_offset);
+ sect.setReloff(fileOffset);
sect.setRelcount(nreloc);
- file_offset += (nreloc * reloc_info.totalsize);
+ fileOffset += (nreloc * reloc_info.totalsize);
}
}
// Calculate and set file offset for symbol table data
- file_offset = (file_offset + (MachOSymtab.getAlign() - 1)) & ~((MachOSymtab.getAlign() - 1));
- symtab.setOffset(file_offset);
+ fileOffset = (fileOffset + (MachOSymtab.getAlign() - 1)) & ~((MachOSymtab.getAlign() - 1));
+ symtab.setOffset(fileOffset);
// Write Out Header
machoContainer.writeBytes(mh.getArray());
@@ -271,7 +268,7 @@
* @param symbols
*/
private static MachOSymtab createMachOSymbolTables(ArrayList<MachOSection> sections,
- Collection<Symbol> symbols) {
+ Collection<Symbol> symbols) {
MachOSymtab symtab = new MachOSymtab();
// First, create the initial null symbol. This is a local symbol.
symtab.addSymbolEntry("", (byte) nlist_64.N_UNDF, (byte) 0, 0);
@@ -284,9 +281,9 @@
long sectionAddr = sections.get(sectionId).getAddr();
MachOSymbol machoSymbol = symtab.addSymbolEntry(symbol.getName(),
- getMachOTypeOf(symbol),
- (byte) sectionId,
- symbol.getOffset() + sectionAddr);
+ getMachOTypeOf(symbol),
+ (byte) sectionId,
+ symbol.getOffset() + sectionAddr);
symbol.setNativeSymbol(machoSymbol);
}
@@ -308,8 +305,8 @@
}
// If Function or Data, add section type
if (kind == Symbol.Kind.NATIVE_FUNCTION ||
- kind == Symbol.Kind.JAVA_FUNCTION ||
- kind == Symbol.Kind.OBJECT) {
+ kind == Symbol.Kind.JAVA_FUNCTION ||
+ kind == Symbol.Kind.OBJECT) {
type |= (nlist_64.N_SECT);
}
@@ -324,12 +321,13 @@
* @param symtab
*/
private MachORelocTable createMachORelocTable(ArrayList<MachOSection> sections,
- Map<Symbol, List<Relocation>> relocationTable,
- MachOSymtab symtab) {
+ Map<Symbol, List<Relocation>> relocationTable,
+ MachOSymtab symtab) {
MachORelocTable machORelocTable = new MachORelocTable(sections.size());
/*
- * For each of the symbols with associated relocation records, create a MachO relocation entry.
+ * For each of the symbols with associated relocation records, create a MachO relocation
+ * entry.
*/
for (Map.Entry<Symbol, List<Relocation>> entry : relocationTable.entrySet()) {
List<Relocation> relocs = entry.getValue();
@@ -380,8 +378,8 @@
int addend = -4; // Size of 32-bit address of the GOT
/*
* Relocation should be applied before the test instruction to the move instruction.
- * reloc.getOffset() points to the test instruction after the instruction that loads the address of
- * polling page. So set the offset appropriately.
+ * reloc.getOffset() points to the test instruction after the instruction that loads
+ * the address of polling page. So set the offset appropriately.
*/
offset = offset + addend;
pcrel = 1;
@@ -398,8 +396,8 @@
throw new InternalError("Unhandled relocation type: " + relocType);
}
machORelocTable.createRelocationEntry(sectindex, offset, symno,
- pcrel, length, isextern,
- machORelocType);
+ pcrel, length, isextern,
+ machORelocType);
}
private static int getMachORelocationType(RelocType relocType) {
@@ -408,14 +406,14 @@
case mach_header_64.CPU_TYPE_X86_64:
// Return X86_64_RELOC_* entries based on relocType
if (relocType == RelocType.JAVA_CALL_DIRECT ||
- relocType == RelocType.FOREIGN_CALL_INDIRECT_GOT) {
+ relocType == RelocType.FOREIGN_CALL_INDIRECT_GOT) {
machORelocType = reloc_info.X86_64_RELOC_BRANCH;
} else if (relocType == RelocType.STUB_CALL_DIRECT) {
machORelocType = reloc_info.X86_64_RELOC_BRANCH;
} else if (relocType == RelocType.JAVA_CALL_INDIRECT) {
machORelocType = reloc_info.X86_64_RELOC_NONE;
} else if (relocType == RelocType.METASPACE_GOT_REFERENCE ||
- relocType == RelocType.EXTERNAL_PLT_TO_GOT) {
+ relocType == RelocType.EXTERNAL_PLT_TO_GOT) {
machORelocType = reloc_info.X86_64_RELOC_BRANCH;
} else if (relocType == RelocType.EXTERNAL_GOT_TO_PLT) {
machORelocType = reloc_info.X86_64_RELOC_UNSIGNED;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachO.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachO.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,9 +21,13 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat.macho;
//@formatter:off
+//@Checkstyle: stop
+
/**
*
* Support for the creation of Mach-o Object files. Current support is limited to 64 bit x86_64.
@@ -305,4 +309,3 @@
static final int X86_64_RELOC_UNSIGNED = 0x0;
}
}
-//@formatter:on
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOByteBuffer.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOByteBuffer.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,11 +21,12 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat.macho;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
-import jdk.tools.jaotc.binformat.macho.MachOTargetInfo;
final class MachOByteBuffer {
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOContainer.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOContainer.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat.macho;
import java.io.File;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachODySymtab.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachODySymtab.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,12 +21,13 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat.macho;
import java.nio.ByteBuffer;
import jdk.tools.jaotc.binformat.macho.MachO.dysymtab_command;
-import jdk.tools.jaotc.binformat.macho.MachOByteBuffer;
final class MachODySymtab {
private final ByteBuffer dysymtab;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOHeader.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOHeader.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,13 +21,13 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat.macho;
import java.nio.ByteBuffer;
import jdk.tools.jaotc.binformat.macho.MachO.mach_header_64;
-import jdk.tools.jaotc.binformat.macho.MachOTargetInfo;
-import jdk.tools.jaotc.binformat.macho.MachOByteBuffer;
final class MachOHeader {
private final ByteBuffer header;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachORelocEntry.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachORelocEntry.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,12 +21,13 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat.macho;
import java.nio.ByteBuffer;
import jdk.tools.jaotc.binformat.macho.MachO.reloc_info;
-import jdk.tools.jaotc.binformat.macho.MachOByteBuffer;
final class MachORelocEntry {
private final ByteBuffer entry;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachORelocTable.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachORelocTable.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,14 +21,14 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat.macho;
+import java.nio.ByteBuffer;
import java.util.ArrayList;
-import java.nio.ByteBuffer;
-import jdk.tools.jaotc.binformat.macho.MachORelocEntry;
import jdk.tools.jaotc.binformat.macho.MachO.reloc_info;
-import jdk.tools.jaotc.binformat.macho.MachOByteBuffer;
final class MachORelocTable {
private final ArrayList<ArrayList<MachORelocEntry>> relocEntries;
@@ -50,14 +50,14 @@
return (4);
}
- int getNumRelocs(int section_index) {
- return relocEntries.get(section_index).size();
+ int getNumRelocs(int sectionIndex) {
+ return relocEntries.get(sectionIndex).size();
}
// Return the relocation entries for a single section
// or null if no entries added to section
- byte[] getRelocData(int section_index) {
- ArrayList<MachORelocEntry> entryList = relocEntries.get(section_index);
+ byte[] getRelocData(int sectionIndex) {
+ ArrayList<MachORelocEntry> entryList = relocEntries.get(sectionIndex);
if (entryList.size() == 0) {
return null;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSection.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSection.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,12 +21,13 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat.macho;
import java.nio.ByteBuffer;
import jdk.tools.jaotc.binformat.macho.MachO.section_64;
-import jdk.tools.jaotc.binformat.macho.MachOByteBuffer;
final class MachOSection {
private final ByteBuffer section;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSegment.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSegment.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,12 +21,13 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat.macho;
import java.nio.ByteBuffer;
import jdk.tools.jaotc.binformat.macho.MachO.segment_command_64;
-import jdk.tools.jaotc.binformat.macho.MachOByteBuffer;
public class MachOSegment {
ByteBuffer segment;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSymbol.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSymbol.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,13 +21,14 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat.macho;
import java.nio.ByteBuffer;
import jdk.tools.jaotc.binformat.NativeSymbol;
import jdk.tools.jaotc.binformat.macho.MachO.nlist_64;
-import jdk.tools.jaotc.binformat.macho.MachOByteBuffer;
final class MachOSymbol extends NativeSymbol {
private final ByteBuffer sym;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSymtab.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSymtab.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,20 +21,20 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat.macho;
import java.nio.ByteBuffer;
import java.util.ArrayList;
+import jdk.tools.jaotc.binformat.macho.MachO.nlist_64;
import jdk.tools.jaotc.binformat.macho.MachO.symtab_command;
-import jdk.tools.jaotc.binformat.macho.MachO.nlist_64;
-import jdk.tools.jaotc.binformat.macho.MachOSymbol;
-import jdk.tools.jaotc.binformat.macho.MachOByteBuffer;
final class MachOSymtab {
/**
- * ByteBuffer holding the LC_SYMTAB command contents
+ * ByteBuffer holding the LC_SYMTAB command contents.
*/
private final ByteBuffer symtabCmd;
@@ -45,17 +45,18 @@
private final ArrayList<MachOSymbol> undefSymbols = new ArrayList<>();
/**
- * number of symbols added
+ * Number of symbols added.
*/
private int symbolCount;
/**
- * String holding symbol table strings
+ * String holding symbol table strings.
*/
private final StringBuilder strTabContent = new StringBuilder();
/**
- * Keeps track of bytes in string table since strTabContent.length() is number of chars, not bytes.
+ * Keeps track of bytes in string table since strTabContent.length() is number of chars, not
+ * bytes.
*/
private int strTabNrOfBytes = 0;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOTargetInfo.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOTargetInfo.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat.macho;
import java.nio.ByteOrder;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOVersion.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOVersion.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,12 +21,13 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat.macho;
import java.nio.ByteBuffer;
import jdk.tools.jaotc.binformat.macho.MachO.version_min_command;
-import jdk.tools.jaotc.binformat.macho.MachOByteBuffer;
final class MachOVersion {
private final ByteBuffer version;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/JPECoffRelocObject.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/JPECoffRelocObject.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat.pecoff;
import java.io.IOException;
@@ -38,13 +40,10 @@
import jdk.tools.jaotc.binformat.Symbol;
import jdk.tools.jaotc.binformat.Symbol.Binding;
import jdk.tools.jaotc.binformat.Symbol.Kind;
-
-import jdk.tools.jaotc.binformat.pecoff.PECoffSymbol;
-import jdk.tools.jaotc.binformat.pecoff.PECoffTargetInfo;
import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_FILE_HEADER;
+import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_RELOCATION;
import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_SECTION_HEADER;
import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_SYMBOL;
-import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_RELOCATION;
public class JPECoffRelocObject {
@@ -102,7 +101,7 @@
}
/**
- * Create an PECoff relocatable object
+ * Creates a PECoff relocatable object.
*
* @param relocationTable
* @param symbols
@@ -138,7 +137,11 @@
// Add Linker Directives Section
int scnFlags = IMAGE_SECTION_HEADER.IMAGE_SCN_LNK_INFO | IMAGE_SECTION_HEADER.IMAGE_SCN_LNK_REMOVE;
- createByteSection(sections, ".drectve", symtab.getDirectiveArray(), false, scnFlags, 1 /* 1 byte alignment */);
+ createByteSection(sections, ".drectve", symtab.getDirectiveArray(), false, scnFlags, 1 /*
+ * 1
+ * byte
+ * alignment
+ */);
// Create the Relocation Tables
PECoffRelocTable pecoffRelocs = createPECoffRelocTable(sections, relocationTable);
@@ -154,28 +157,28 @@
// RELOCATION TABLE
// Calculate Offset for Symbol table
- int file_offset = IMAGE_FILE_HEADER.totalsize +
+ int fileOffset = IMAGE_FILE_HEADER.totalsize +
(IMAGE_SECTION_HEADER.totalsize * sections.size());
// Update Header fields
header.setSectionCount(sections.size());
header.setSymbolCount(symtab.getSymtabCount());
- header.setSymbolOff(file_offset);
+ header.setSymbolOff(fileOffset);
// Calculate file offset for first section
- file_offset += ((symtab.getSymtabCount() * IMAGE_SYMBOL.totalsize) +
+ fileOffset += ((symtab.getSymtabCount() * IMAGE_SYMBOL.totalsize) +
symtab.getStrtabSize());
// And round it up
- file_offset = (file_offset + (sections.get(0).getDataAlign() - 1)) &
+ fileOffset = (fileOffset + (sections.get(0).getDataAlign() - 1)) &
~((sections.get(0).getDataAlign() - 1));
// Calc file offsets for section data
for (int i = 0; i < sections.size(); i++) {
PECoffSection sect = sections.get(i);
- file_offset = (file_offset + (sect.getDataAlign() - 1)) &
+ fileOffset = (fileOffset + (sect.getDataAlign() - 1)) &
~((sect.getDataAlign() - 1));
- sect.setOffset(file_offset);
- file_offset += sect.getSize();
+ sect.setOffset(fileOffset);
+ fileOffset += sect.getSize();
}
// Update relocation sizing information in each section
@@ -183,13 +186,13 @@
PECoffSection sect = sections.get(i);
if (sect.hasRelocations()) {
int nreloc = pecoffRelocs.getNumRelocs(i);
- sect.setReloff(file_offset);
+ sect.setReloff(fileOffset);
sect.setRelcount(nreloc);
// extended relocations add an addition entry
if (nreloc > 0xFFFF) {
nreloc++;
}
- file_offset += (nreloc * IMAGE_RELOCATION.totalsize);
+ fileOffset += (nreloc * IMAGE_RELOCATION.totalsize);
}
}
@@ -269,7 +272,8 @@
PECoffRelocTable pecoffRelocTable = new PECoffRelocTable(sections.size());
/*
- * For each of the symbols with associated relocation records, create a PECoff relocation entry.
+ * For each of the symbols with associated relocation records, create a PECoff relocation
+ * entry.
*/
for (Map.Entry<Symbol, List<Relocation>> entry : relocationTable.entrySet()) {
List<Relocation> relocs = entry.getValue();
@@ -316,8 +320,8 @@
addend = -4; // Size of 32-bit address of the GOT
/*
* Relocation should be applied before the test instruction to the move instruction.
- * reloc.getOffset() points to the test instruction after the instruction that loads the address of
- * polling page. So set the offset appropriately.
+ * reloc.getOffset() points to the test instruction after the instruction that loads
+ * the address of polling page. So set the offset appropriately.
*/
offset = offset + addend;
break;
@@ -338,14 +342,14 @@
switch (PECoffTargetInfo.getPECoffArch()) {
case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64:
if (relocType == RelocType.JAVA_CALL_DIRECT ||
- relocType == RelocType.FOREIGN_CALL_INDIRECT_GOT) {
+ relocType == RelocType.FOREIGN_CALL_INDIRECT_GOT) {
pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_REL32;
} else if (relocType == RelocType.STUB_CALL_DIRECT) {
pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_REL32;
} else if (relocType == RelocType.JAVA_CALL_INDIRECT) {
pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_ABSOLUTE;
} else if (relocType == RelocType.METASPACE_GOT_REFERENCE ||
- relocType == RelocType.EXTERNAL_PLT_TO_GOT) {
+ relocType == RelocType.EXTERNAL_PLT_TO_GOT) {
pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_REL32;
} else if (relocType == RelocType.EXTERNAL_GOT_TO_PLT) {
pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_ADDR64;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoff.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoff.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat.pecoff;
/**
@@ -32,13 +34,13 @@
final class PECoff {
//@formatter:off
/**
- * IMAGE_FILE_HEADER structure defines
+ * IMAGE_FILE_HEADER structure defines.
*/
enum IMAGE_FILE_HEADER {
- Machine( 0, 2),
- NumberOfSections( 2, 2),
- TimeDateStamp( 4, 4),
- PointerToSymbolTable( 8, 4),
+ Machine(0, 2),
+ NumberOfSections(2, 2),
+ TimeDateStamp(4, 4),
+ PointerToSymbolTable(8, 4),
NumberOfSymbols(12, 4),
SizeOfOptionalHeader(16, 2),
Characteristics(18, 2);
@@ -58,7 +60,7 @@
*/
/**
- * Machine
+ * Machine.
*/
static final char IMAGE_FILE_MACHINE_UNKNOWN = 0x0;
static final char IMAGE_FILE_MACHINE_AMD64 = 0x8664;
@@ -66,12 +68,12 @@
}
/**
- * IMAGE_SECTION_HEADER structure defines
+ * IMAGE_SECTION_HEADER structure defines.
*/
enum IMAGE_SECTION_HEADER {
- Name( 0, 8),
- PhysicalAddress( 8, 4),
- VirtualSize( 8, 4),
+ Name(0, 8),
+ PhysicalAddress(8, 4),
+ VirtualSize(8, 4),
VirtualAddress(12, 4),
SizeOfRawData(16, 4),
PointerToRawData(20, 4),
@@ -96,7 +98,7 @@
*/
/**
- * Characteristics
+ * Characteristics.
*/
static final int IMAGE_SCN_CNT_CODE = 0x20;
static final int IMAGE_SCN_CNT_INITIALIZED_DATA = 0x40;
@@ -129,15 +131,15 @@
}
/**
- * Symbol table entry definitions
+ * Symbol table entry definitions.
*
* IMAGE_SYMBOL structure defines
*/
enum IMAGE_SYMBOL {
- ShortName( 0, 8),
- Short( 0, 4),
- Long( 4, 4),
- Value( 8, 4),
+ ShortName(0, 8),
+ Short(0, 4),
+ Long(4, 4),
+ Value(8, 4),
SectionNumber(12, 2),
Type(14, 2),
StorageClass(16, 1),
@@ -154,13 +156,13 @@
static int totalsize = 18;
/**
- * Type
+ * Type.
*/
static final int IMAGE_SYM_DTYPE_NONE = 0x0;
static final int IMAGE_SYM_DTYPE_FUNCTION = 0x20;
/**
- * StorageClass
+ * StorageClass.
*/
static final int IMAGE_SYM_CLASS_NULL = 0x0;
static final int IMAGE_SYM_CLASS_EXTERNAL = 0x2;
@@ -170,12 +172,12 @@
}
/**
- * IMAGE_RELOCATION structure defines
+ * IMAGE_RELOCATION structure defines.
*/
enum IMAGE_RELOCATION {
- VirtualAddress( 0, 4),
- SymbolTableIndex( 4, 4),
- Type( 8, 2);
+ VirtualAddress(0, 4),
+ SymbolTableIndex(4, 4),
+ Type(8, 2);
final int off;
final int sz;
@@ -188,7 +190,7 @@
static int totalsize = 10;
/**
- * Relocation types
+ * Relocation types.
*/
static final int IMAGE_REL_AMD64_ABSOLUTE = 0x0;
static final int IMAGE_REL_AMD64_ADDR32 = 0x2;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffByteBuffer.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffByteBuffer.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat.pecoff;
import java.nio.ByteBuffer;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffContainer.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffContainer.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat.pecoff;
import java.io.File;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffHeader.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffHeader.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,12 +21,13 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat.pecoff;
import java.nio.ByteBuffer;
import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_FILE_HEADER;
-import jdk.tools.jaotc.binformat.pecoff.PECoffByteBuffer;
final class PECoffHeader {
private final ByteBuffer header;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffRelocEntry.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffRelocEntry.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,12 +21,13 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat.pecoff;
import java.nio.ByteBuffer;
import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_RELOCATION;
-import jdk.tools.jaotc.binformat.pecoff.PECoffByteBuffer;
final class PECoffRelocEntry {
private final ByteBuffer entry;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffRelocTable.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffRelocTable.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,14 +21,14 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat.pecoff;
+import java.nio.ByteBuffer;
import java.util.ArrayList;
-import java.nio.ByteBuffer;
import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_RELOCATION;
-import jdk.tools.jaotc.binformat.pecoff.PECoffRelocEntry;
-import jdk.tools.jaotc.binformat.pecoff.PECoffByteBuffer;
final class PECoffRelocTable {
ArrayList<ArrayList<PECoffRelocEntry>> relocEntries;
@@ -49,14 +49,14 @@
return (4);
}
- int getNumRelocs(int section_index) {
- return relocEntries.get(section_index).size();
+ int getNumRelocs(int sectionIndex) {
+ return relocEntries.get(sectionIndex).size();
}
// Return the relocation entries for a single section
// or null if no entries added to section
- byte[] getRelocData(int section_index) {
- ArrayList<PECoffRelocEntry> entryList = relocEntries.get(section_index);
+ byte[] getRelocData(int sectionIndex) {
+ ArrayList<PECoffRelocEntry> entryList = relocEntries.get(sectionIndex);
int entryCount = entryList.size();
int allocCount = entryCount;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSection.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSection.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,12 +21,13 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat.pecoff;
import java.nio.ByteBuffer;
import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_SECTION_HEADER;
-import jdk.tools.jaotc.binformat.pecoff.PECoffByteBuffer;
final class PECoffSection {
private final ByteBuffer section;
@@ -47,8 +48,8 @@
}
// Copy only Max allowed bytes to Section Entry
- byte[] Name = sectName.getBytes();
- int max = Name.length <= IMAGE_SECTION_HEADER.Name.sz ? Name.length : IMAGE_SECTION_HEADER.Name.sz;
+ byte[] name = sectName.getBytes();
+ int max = name.length <= IMAGE_SECTION_HEADER.Name.sz ? name.length : IMAGE_SECTION_HEADER.Name.sz;
assert !(sectAlign < 1 || sectAlign > 1024 || (sectAlign & (sectAlign - 1)) != 0) : "section alignment is not valid: " + sectAlign;
align = sectAlign;
@@ -58,7 +59,7 @@
// Clear and set alignment bits
int sectFlags = (sectFlags0 & ~IMAGE_SECTION_HEADER.IMAGE_SCN_ALIGN_MASK) | (sectAlignBits & IMAGE_SECTION_HEADER.IMAGE_SCN_ALIGN_MASK);
- section.put(Name, IMAGE_SECTION_HEADER.Name.off, max);
+ section.put(name, IMAGE_SECTION_HEADER.Name.off, max);
section.putInt(IMAGE_SECTION_HEADER.VirtualSize.off, 0);
section.putInt(IMAGE_SECTION_HEADER.VirtualAddress.off, 0);
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSymbol.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSymbol.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,13 +21,14 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat.pecoff;
import java.nio.ByteBuffer;
import jdk.tools.jaotc.binformat.NativeSymbol;
import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_SYMBOL;
-import jdk.tools.jaotc.binformat.pecoff.PECoffByteBuffer;
final class PECoffSymbol extends NativeSymbol {
private final ByteBuffer sym;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSymtab.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSymtab.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat.pecoff;
import java.nio.ByteBuffer;
@@ -28,19 +30,17 @@
import java.util.ArrayList;
import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_SYMBOL;
-import jdk.tools.jaotc.binformat.pecoff.PECoffSymbol;
-import jdk.tools.jaotc.binformat.pecoff.PECoffByteBuffer;
final class PECoffSymtab {
ArrayList<PECoffSymbol> symbols = new ArrayList<>();
/**
- * number of symbols added
+ * Number of symbols added.
*/
private int symbolCount;
/**
- * String holding symbol table strings
+ * String holding symbol table strings.
*/
private final StringBuilder strTabContent;
@@ -51,7 +51,7 @@
private int strTabNrOfBytes;
/**
- * String holding Linker Directives
+ * String holding Linker Directives.
*/
private final StringBuilder directives;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffTargetInfo.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffTargetInfo.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc.binformat.pecoff;
import java.nio.ByteOrder;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/HelloWorld.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2018, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package jdk.tools.jaotc.test;
+
+public class HelloWorld {
+ public static void main(String[] args) {
+ System.out.println("Hello, world!");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/NativeOrderOutputStreamTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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
+ * @requires vm.aot
+ * @modules jdk.aot/jdk.tools.jaotc.utils
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.tools.jaotc.test.NativeOrderOutputStreamTest
+ */
+
+
+
+package jdk.tools.jaotc.test;
+
+import jdk.tools.jaotc.utils.NativeOrderOutputStream;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+public class NativeOrderOutputStreamTest {
+
+ private NativeOrderOutputStream target;
+
+ @Before
+ public void setup() {
+ target = new NativeOrderOutputStream();
+ }
+
+ @Test
+ public void shouldAdd4BytesForInt() {
+ target.putInt(5);
+ Assert.assertEquals(4, target.position());
+ }
+
+ @Test
+ public void shouldAdd8BytesForLong() {
+ target.putLong(8);
+ Assert.assertEquals(8, target.position());
+ }
+
+ @Test
+ public void shouldHaveCorrectSizeBeforePatch() {
+ target.patchableInt();
+ Assert.assertEquals(4, target.position());
+ }
+
+ @Test
+ public void shouldHaveCorrectSizeAfterPatch() {
+ NativeOrderOutputStream.PatchableInt patchableInt = target.patchableInt();
+ patchableInt.set(12);
+ Assert.assertEquals(4, target.position());
+ }
+
+ @Test
+ public void shouldSetCorrectValueInPatch() {
+ NativeOrderOutputStream.PatchableInt patchableInt = target.patchableInt();
+ patchableInt.set(42);
+ Assert.assertEquals(42, getInt(0));
+ }
+
+ private int getInt(int pos) {
+ ByteBuffer buffer = ByteBuffer.wrap(target.array());
+ buffer.order(ByteOrder.nativeOrder());
+ return buffer.getInt(pos);
+ }
+
+ @Test
+ public void shouldPutArrayCorrectly() {
+ target.put(new byte[]{42, 5, 43, 44});
+ Assert.assertEquals(4, target.position());
+ Assert.assertEquals(42, target.array()[0]);
+ Assert.assertEquals(4, target.position());
+ }
+
+ @Test
+ public void shouldOnlyPatchSlot() {
+ NativeOrderOutputStream.PatchableInt patchableInt = target.patchableInt();
+ target.putInt(7);
+ patchableInt.set(39);
+ Assert.assertEquals(39, getInt(0));
+ Assert.assertEquals(7, getInt(4));
+ }
+
+ @Test
+ public void shouldBeAbleToPatchAnywhere() {
+ target.putInt(19);
+ NativeOrderOutputStream.PatchableInt patchableInt = target.patchableInt();
+ patchableInt.set(242);
+
+ Assert.assertEquals(19, getInt(0));
+ Assert.assertEquals(242, getInt(4));
+ }
+
+ @Test
+ public void shouldHavePatchableAtRightOffset() {
+ target.putInt(27);
+ Assert.assertEquals(4, target.position());
+ NativeOrderOutputStream.PatchableInt patchableInt = target.patchableInt();
+ Assert.assertEquals(4, patchableInt.position());
+ }
+
+ @Test
+ public void shouldAlign() {
+ target.putInt(9);
+ target.align(16);
+ target.put(new byte[]{3});
+ target.align(8);
+ Assert.assertEquals(24, target.position());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/ClassSearchTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @requires vm.aot
+ * @modules jdk.aot/jdk.tools.jaotc
+ * jdk.aot/jdk.tools.jaotc.collect
+ * @run junit/othervm jdk.tools.jaotc.test.collect.ClassSearchTest
+ */
+
+
+
+package jdk.tools.jaotc.test.collect;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.function.BiConsumer;
+import java.util.function.BiFunction;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import jdk.tools.jaotc.LoadedClass;
+import jdk.tools.jaotc.collect.ClassSearch;
+import jdk.tools.jaotc.collect.ClassSource;
+import jdk.tools.jaotc.collect.SearchFor;
+import jdk.tools.jaotc.collect.SearchPath;
+import jdk.tools.jaotc.collect.SourceProvider;
+
+public class ClassSearchTest {
+ @Test(expected = InternalError.class)
+ public void itShouldThrowExceptionIfNoProvidersAvailable() {
+ ClassSearch target = new ClassSearch();
+ SearchPath searchPath = new SearchPath();
+ target.search(list(new SearchFor("foo")), searchPath);
+ }
+
+ @Test
+ public void itShouldFindAProviderForEachEntry() {
+ Set<String> searched = new HashSet<>();
+ ClassSearch target = new ClassSearch();
+ target.addProvider(provider("", (name, searchPath) -> {
+ searched.add(name);
+ return new NoopSource();
+ }));
+ target.search(searchForList("foo", "bar", "foobar"), null);
+ Assert.assertEquals(hashset("foo", "bar", "foobar"), searched);
+ }
+
+ private static SourceProvider provider(String supports, BiFunction<String, SearchPath, ClassSource> fn) {
+ return new SourceProvider() {
+ @Override
+ public ClassSource findSource(String name, SearchPath searchPath) {
+ return fn.apply(name, searchPath);
+ }
+
+ @Override
+ public boolean supports(String type) {
+ return supports.equals(type);
+ }
+ };
+ }
+
+ @Test
+ public void itShouldOnlySearchSupportedProvidersForKnownType() {
+ Set<String> visited = new HashSet<>();
+ ClassSearch target = new ClassSearch();
+
+ target.addProvider(provider("jar", (name, searchPath) -> {
+ visited.add("jar");
+ return null;
+ }));
+
+ target.addProvider(provider("dir", (name, searchPath) -> {
+ visited.add("dir");
+ return null;
+ }));
+
+ try {
+ target.search(list(new SearchFor("some", "dir")), null);
+ } catch (InternalError e) {
+ // throws because no provider gives a source
+ }
+
+ Assert.assertEquals(hashset("dir"), visited);
+ }
+
+ @Test(expected = InternalError.class)
+ public void itShouldThrowErrorIfMultipleSourcesAreAvailable() {
+ ClassSearch target = new ClassSearch();
+ target.addProvider(provider("", (name, searchPath) -> consumer -> Assert.fail()));
+ target.addProvider(provider("", (name, searchPath) -> consumer -> Assert.fail()));
+
+ target.search(searchForList("somethign"), null);
+ }
+
+ @Test
+ public void itShouldSearchAllProvidersForUnknownType() {
+ Set<String> visited = new HashSet<>();
+ ClassSearch target = new ClassSearch();
+ target.addProvider(provider("", (name, searchPath) -> {
+ visited.add("1");
+ return null;
+ }));
+ target.addProvider(provider("", (name, searchPath) -> {
+ visited.add("2");
+ return null;
+ }));
+
+ try {
+ target.search(searchForList("foo"), null);
+ } catch (InternalError e) {
+ // throws because no provider gives a source
+ }
+
+ Assert.assertEquals(hashset("1", "2"), visited);
+ }
+
+ @Test
+ public void itShouldTryToLoadSaidClassFromClassLoader() {
+ Set<String> loaded = new HashSet<>();
+
+ ClassSearch target = new ClassSearch();
+ target.addProvider(new SourceProvider() {
+ @Override
+ public boolean supports(String type) {
+ return true;
+ }
+
+ @Override
+ public ClassSource findSource(String name, SearchPath searchPath) {
+ return new ClassSource() {
+ @Override
+ public void eachClass(BiConsumer<String, ClassLoader> consumer) {
+ consumer.accept("foo.Bar", new ClassLoader() {
+ @Override
+ public Class<?> loadClass(String nm) throws ClassNotFoundException {
+ loaded.add(nm);
+ return null;
+ }
+ });
+ }
+ };
+ }
+ });
+
+ java.util.List<LoadedClass> search = target.search(searchForList("/tmp/something"), null);
+ Assert.assertEquals(list(new LoadedClass("foo.Bar", null)), search);
+ }
+
+ @Test(expected = InternalError.class)
+ public void itShouldThrowInternalErrorWhenClassLoaderFails() {
+ ClassLoader classLoader = new ClassLoader() {
+ @Override
+ public Class<?> loadClass(String name1) throws ClassNotFoundException {
+ throw new ClassNotFoundException("failed to find " + name1);
+ }
+ };
+
+ ClassSearch target = new ClassSearch();
+ target.addProvider(provider("", (name, searchPath) -> consumer -> consumer.accept("foo.Bar", classLoader)));
+ target.search(searchForList("foobar"), null);
+ }
+
+ private static List<SearchFor> searchForList(String... entries) {
+ List<SearchFor> list = new ArrayList<>();
+ for (String entry : entries) {
+ list.add(new SearchFor(entry));
+ }
+ return list;
+ }
+
+ @SafeVarargs
+ private static <T> List<T> list(T... entries) {
+ List<T> list = new ArrayList<>();
+ for (T entry : entries) {
+ list.add(entry);
+ }
+ return list;
+ }
+
+ @SafeVarargs
+ private static <T> Set<T> hashset(T... entries) {
+ Set<T> set = new HashSet<>();
+ for (T entry : entries) {
+ set.add(entry);
+ }
+ return set;
+ }
+
+ private static class NoopSource implements ClassSource {
+ @Override
+ public void eachClass(BiConsumer<String, ClassLoader> consumer) {
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/ClassSourceTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @requires vm.aot
+ * @modules jdk.aot/jdk.tools.jaotc
+ * jdk.aot/jdk.tools.jaotc.collect
+ * @build jdk.tools.jaotc.test.collect.Utils
+ * @run junit/othervm jdk.tools.jaotc.test.collect.ClassSourceTest
+ */
+
+
+
+package jdk.tools.jaotc.test.collect;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.nio.file.Paths;
+
+import static jdk.tools.jaotc.collect.ClassSource.makeClassName;
+
+import static jdk.tools.jaotc.test.collect.Utils.getpath;
+
+public class ClassSourceTest {
+ @Test(expected = IllegalArgumentException.class)
+ public void itShouldThrowExceptionIfPathDoesntEndWithClass() {
+ makeClassName(Paths.get("Bar.clazz"));
+ }
+
+ @Test
+ public void itShouldReplaceSlashesWithDots() {
+ Assert.assertEquals("foo.Bar", makeClassName(getpath("foo/Bar.class")));
+ }
+
+ @Test
+ public void itShouldStripLeadingSlash() {
+ Assert.assertEquals("Hello", makeClassName(getpath("/Hello.class")));
+ }
+
+ @Test
+ public void itShouldReplaceMultipleDots() {
+ Assert.assertEquals("some.foo.bar.FooBar", makeClassName(getpath("/some/foo/bar/FooBar.class")));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/FakeFileSupport.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package jdk.tools.jaotc.test.collect;
+
+import java.net.MalformedURLException;
+import java.nio.file.Path;
+import java.util.HashSet;
+import java.util.Set;
+
+import jdk.tools.jaotc.collect.FileSupport;
+
+public class FakeFileSupport extends FileSupport {
+ private final Set<String> exists = new HashSet<>();
+ private final Set<String> directories = new HashSet<>();
+
+ private final Set<String> checkedExists = new HashSet<>();
+ private final Set<String> checkedDirectory = new HashSet<>();
+ private final Set<String> checkedJarFileSystemRoots = new HashSet<>();
+ private final Set<String> classloaderPaths = new HashSet<>();
+
+ private Path jarFileSystemRoot = null;
+ private final ClassLoader classLoader;
+
+ public FakeFileSupport(Set<String> existing, Set<String> directories) {
+ this.exists.addAll(existing);
+ this.directories.addAll(directories);
+
+ classLoader = new ClassLoader() {
+ @Override
+ public Class<?> loadClass(String name) throws ClassNotFoundException {
+ return null;
+ }
+ };
+ }
+
+ public void setJarFileSystemRoot(Path path) {
+ jarFileSystemRoot = path;
+ }
+
+ @Override
+ public boolean exists(Path path) {
+ checkedExists.add(path.toString());
+ return exists.contains(path.toString());
+ }
+
+ @Override
+ public boolean isDirectory(Path path) {
+ checkedDirectory.add(path.toString());
+ return directories.contains(path.toString());
+ }
+
+ @Override
+ public ClassLoader createClassLoader(Path path) throws MalformedURLException {
+ classloaderPaths.add(path.toString());
+ return classLoader;
+ }
+
+ @Override
+ public Path getJarFileSystemRoot(Path jarFile) {
+ checkedJarFileSystemRoots.add(jarFile.toString());
+ return jarFileSystemRoot;
+ }
+
+ @Override
+ public boolean isAbsolute(Path entry) {
+ return entry.toString().startsWith("/");
+ }
+
+ public void addExist(String name) {
+ exists.add(name);
+ }
+
+ public void addDirectory(String name) {
+ directories.add(name);
+ }
+
+ public Set<String> getCheckedExists() {
+ return checkedExists;
+ }
+
+ public Set<String> getCheckedDirectory() {
+ return checkedDirectory;
+ }
+
+ public Set<String> getCheckedJarFileSystemRoots() {
+ return checkedJarFileSystemRoots;
+ }
+
+ public Set<String> getClassloaderPaths() {
+ return classloaderPaths;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/FakeSearchPath.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package jdk.tools.jaotc.test.collect;
+
+import jdk.tools.jaotc.collect.SearchPath;
+
+import java.nio.file.FileSystem;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Set;
+
+import static jdk.tools.jaotc.test.collect.Utils.set;
+
+public class FakeSearchPath extends SearchPath {
+ private Path path = null;
+ public Set<String> entries = set();
+
+ public FakeSearchPath(String name) {
+ if (name != null) {
+ path = Paths.get(name);
+ }
+ }
+
+ @Override
+ public Path find(FileSystem fileSystem, Path entry, String... defaults) {
+ entries.add(entry.toString());
+ return path;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/SearchPathTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @requires vm.aot
+ * @modules jdk.aot/jdk.tools.jaotc
+ * jdk.aot/jdk.tools.jaotc.collect
+ *
+ * @build jdk.tools.jaotc.test.collect.Utils
+ * @build jdk.tools.jaotc.test.collect.FakeFileSupport
+ * @run junit/othervm jdk.tools.jaotc.test.collect.SearchPathTest
+ */
+
+
+
+package jdk.tools.jaotc.test.collect;
+
+import static jdk.tools.jaotc.test.collect.Utils.mkpath;
+import static jdk.tools.jaotc.test.collect.Utils.mkpaths;
+import static jdk.tools.jaotc.test.collect.Utils.set;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import jdk.tools.jaotc.collect.SearchPath;
+
+public class SearchPathTest {
+ private FakeFileSupport fileSupport;
+ private FileSystem fs;
+
+ @Before
+ public void setUp() throws Exception {
+ fs = FileSystems.getDefault();
+ }
+
+ @Test
+ public void itShouldUsePathIfPathIsAbsoluteAndExisting() {
+ fileSupport = new FakeFileSupport(mkpaths("/foo"), set());
+ SearchPath target = new SearchPath(fileSupport);
+ Path foo = Paths.get(mkpath("/foo"));
+ Path result = target.find(fs, foo);
+ assertSame(result, foo);
+ }
+
+ @Test
+ public void itShouldReturnNullIfPathIsAbsoluteAndNonExisting() {
+ fileSupport = new FakeFileSupport(set(), set());
+ SearchPath target = new SearchPath(fileSupport);
+ Path result = target.find(fs, Paths.get(mkpath("/bar")));
+ assertNull(result);
+ }
+
+ @Test
+ public void itShouldUseRelativeExisting() {
+ fileSupport = new FakeFileSupport(mkpaths("hello", "tmp/hello", "search/hello"), set());
+ SearchPath target = new SearchPath(fileSupport);
+ target.add("search");
+ Path hello = Paths.get("hello");
+ Path result = target.find(fs, hello, "tmp");
+ assertSame(result, hello);
+ }
+
+ @Test
+ public void itShouldSearchDefaultsBeforeSearchPaths() {
+ fileSupport = new FakeFileSupport(mkpaths("bar/foobar"), set());
+ SearchPath target = new SearchPath(fileSupport);
+ Path result = target.find(fs, Paths.get("foobar"), "default1", "bar");
+ assertEquals(mkpath("bar/foobar"), result.toString());
+ assertEquals(mkpaths("foobar", "default1/foobar", "bar/foobar"), fileSupport.getCheckedExists());
+ }
+
+ @Test
+ public void itShouldUseSearchPathsIfNotInDefaults() {
+ fileSupport = new FakeFileSupport(mkpaths("bar/tmp/foobar"), set());
+ SearchPath target = new SearchPath(fileSupport);
+ target.add("foo/tmp", "bar/tmp");
+
+ Path result = target.find(fs, Paths.get("foobar"), "foo", "bar");
+ assertEquals(mkpath("bar/tmp/foobar"), result.toString());
+ assertEquals(mkpaths("foobar", "foo/foobar", "bar/foobar", "bar/tmp/foobar", "foo/tmp/foobar"), fileSupport.getCheckedExists());
+ }
+
+ @Test
+ public void itShouldReturnNullIfNoExistingPathIsFound() {
+ fileSupport = new FakeFileSupport(set(), set());
+ SearchPath target = new SearchPath(fileSupport);
+ target.add("dir1", "dir2");
+
+ Path result = target.find(fs, Paths.get("entry"), "dir3", "dir4");
+ assertNull(result);
+ assertEquals(mkpaths("entry", "dir1/entry", "dir2/entry", "dir3/entry", "dir4/entry"), fileSupport.getCheckedExists());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/Utils.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package jdk.tools.jaotc.test.collect;
+
+import java.io.File;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.HashSet;
+import java.util.Set;
+
+public class Utils {
+ @SafeVarargs
+ public static <T> Set<T> set(T... entries) {
+ Set<T> set = new HashSet<>();
+ for (T entry : entries) {
+ set.add(entry);
+ }
+ return set;
+ }
+
+ public static String mkpath(String path) {
+ return getpath(path).toString();
+ }
+
+ public static Set<String> mkpaths(String... paths) {
+ Set<String> set = new HashSet<>();
+ for (String entry : paths) {
+ set.add(mkpath(entry));
+ }
+ return set;
+ }
+
+ public static Path getpath(String path) {
+ if (path.startsWith("/") && System.getProperty("os.name").startsWith("Windows")) {
+ return Paths.get(new File(path).getAbsolutePath());
+ } else {
+ return Paths.get(path);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/directory/DirectorySourceProviderTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @requires vm.aot
+ * @modules jdk.aot/jdk.tools.jaotc
+ * jdk.aot/jdk.tools.jaotc.collect
+ * jdk.aot/jdk.tools.jaotc.collect.directory
+ * @compile ../Utils.java
+ * @compile ../FakeFileSupport.java
+ * @run junit/othervm jdk.tools.jaotc.test.collect.directory.DirectorySourceProviderTest
+ */
+
+
+
+package jdk.tools.jaotc.test.collect.directory;
+
+import jdk.tools.jaotc.collect.ClassSource;
+import jdk.tools.jaotc.collect.directory.DirectorySourceProvider;
+import jdk.tools.jaotc.test.collect.FakeFileSupport;
+import jdk.tools.jaotc.collect.FileSupport;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.net.MalformedURLException;
+import java.nio.file.Path;
+import java.util.Set;
+
+import static jdk.tools.jaotc.test.collect.Utils.set;
+
+public class DirectorySourceProviderTest {
+ @Test
+ public void itShouldReturnNullForNonExistantPath() {
+ DirectorySourceProvider target = new DirectorySourceProvider(new FakeFileSupport(set(), set()));
+ ClassSource result = target.findSource("hello", null);
+ Assert.assertNull(result);
+ }
+
+ @Test
+ public void itShouldReturnNullForNonDirectory() {
+ DirectorySourceProvider target = new DirectorySourceProvider(new FakeFileSupport(set("foobar"), set()));
+ ClassSource result = target.findSource("foobar", null);
+ Assert.assertNull(result);
+ }
+
+ @Test
+ public void itShouldReturnNullForMalformedURI() {
+ Set<String> visited = set();
+ DirectorySourceProvider target = new DirectorySourceProvider(new FakeFileSupport(set("foobar"), set("foobar")) {
+ @Override
+ public ClassLoader createClassLoader(Path path) throws MalformedURLException {
+ visited.add("1");
+ throw new MalformedURLException("...");
+ }
+ });
+ ClassSource result = target.findSource("foobar", null);
+ Assert.assertNull(result);
+ Assert.assertEquals(set("1"), visited);
+ }
+
+ @Test
+ public void itShouldCreateSourceIfNameExistsAndIsADirectory() {
+ FileSupport fileSupport = new FakeFileSupport(set("foo"), set("foo"));
+ DirectorySourceProvider target = new DirectorySourceProvider(fileSupport);
+ ClassSource foo = target.findSource("foo", null);
+ Assert.assertNotNull(foo);
+ Assert.assertEquals("directory:foo", foo.toString());
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/jar/JarSourceProviderTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @requires vm.aot
+ * @modules jdk.aot/jdk.tools.jaotc
+ * jdk.aot/jdk.tools.jaotc.collect
+ * jdk.aot/jdk.tools.jaotc.collect.jar
+ * @compile ../Utils.java
+ * @compile ../FakeFileSupport.java
+ * @compile ../FakeSearchPath.java
+ *
+ * @run junit/othervm jdk.tools.jaotc.test.collect.jar.JarSourceProviderTest
+ */
+
+
+
+package jdk.tools.jaotc.test.collect.jar;
+
+import static jdk.tools.jaotc.test.collect.Utils.mkpath;
+import static jdk.tools.jaotc.test.collect.Utils.set;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.ProviderNotFoundException;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import jdk.tools.jaotc.collect.ClassSource;
+import jdk.tools.jaotc.collect.jar.JarSourceProvider;
+import jdk.tools.jaotc.test.collect.FakeFileSupport;
+import jdk.tools.jaotc.test.collect.FakeSearchPath;
+
+public class JarSourceProviderTest {
+
+ private FakeFileSupport fileSupport;
+ private JarSourceProvider target;
+
+ @Before
+ public void setUp() throws Exception {
+ fileSupport = new FakeFileSupport(set(), set());
+ target = new JarSourceProvider(fileSupport);
+ }
+
+ @Test
+ public void itShouldUseSearchPathToFindPath() {
+ FakeSearchPath searchPath = new FakeSearchPath(null);
+ target.findSource("hello", searchPath);
+
+ Assert.assertEquals(set("hello"), searchPath.entries);
+ }
+
+ @Test
+ public void itShouldReturnNullIfPathIsNull() {
+ ClassSource source = target.findSource("foobar", new FakeSearchPath(null));
+ Assert.assertNull(source);
+ }
+
+ @Test
+ public void itShouldReturnNullIfPathIsDirectory() {
+ fileSupport.addDirectory("hello/foobar");
+ ClassSource source = target.findSource("foobar", new FakeSearchPath("hello/foobar"));
+
+ Assert.assertNull(source);
+ Assert.assertEquals(set(mkpath("hello/foobar")), fileSupport.getCheckedDirectory());
+ }
+
+ @Test
+ public void itShouldReturnNullIfUnableToMakeJarFileSystem() {
+ fileSupport.setJarFileSystemRoot(null);
+ ClassSource result = target.findSource("foobar", new FakeSearchPath("foo/bar"));
+
+ Assert.assertEquals(set(mkpath("foo/bar")), fileSupport.getCheckedJarFileSystemRoots());
+ Assert.assertNull(result);
+ }
+
+ @Test
+ public void itShouldReturnNullIfNotValidJarProvider() {
+ fileSupport = new FakeFileSupport(set(), set()) {
+
+ @Override
+ public Path getJarFileSystemRoot(Path jarFile) {
+ super.getJarFileSystemRoot(jarFile);
+ throw new ProviderNotFoundException();
+ }
+ };
+ fileSupport.setJarFileSystemRoot(null);
+ target = new JarSourceProvider(fileSupport);
+
+ ClassSource result = target.findSource("foobar", new FakeSearchPath("foo/bar"));
+
+ Assert.assertEquals(set(mkpath("foo/bar")), fileSupport.getCheckedJarFileSystemRoots());
+ Assert.assertNull(result);
+ }
+
+ @Test
+ public void itShouldReturnSourceWhenAllIsValid() {
+ fileSupport.setJarFileSystemRoot(Paths.get("some/bar"));
+ ClassSource result = target.findSource("foobar", new FakeSearchPath("this/bar"));
+
+ Assert.assertEquals(set(mkpath("this/bar")), fileSupport.getClassloaderPaths());
+ Assert.assertEquals("jar:" + mkpath("this/bar"), result.toString());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/module/ModuleSourceProviderTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @requires vm.aot
+ * @modules jdk.aot/jdk.tools.jaotc
+ * jdk.aot/jdk.tools.jaotc.collect
+ * jdk.aot/jdk.tools.jaotc.collect.module
+ * @compile ../Utils.java
+ * @run junit/othervm jdk.tools.jaotc.test.collect.module.ModuleSourceProviderTest
+ */
+
+
+
+package jdk.tools.jaotc.test.collect.module;
+
+import static jdk.tools.jaotc.test.collect.Utils.mkpath;
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.function.BiFunction;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import jdk.tools.jaotc.collect.FileSupport;
+import jdk.tools.jaotc.collect.module.ModuleSource;
+import jdk.tools.jaotc.collect.module.ModuleSourceProvider;
+
+public class ModuleSourceProviderTest {
+ private ClassLoader classLoader;
+ private ModuleSourceProvider target;
+ private FileSupport fileSupport;
+ private BiFunction<Path, Path, Path> getSubDirectory = null;
+
+ @Before
+ public void setUp() {
+ classLoader = new FakeClassLoader();
+ fileSupport = new FileSupport() {
+
+ @Override
+ public boolean isDirectory(Path path) {
+ return true;
+ }
+
+ @Override
+ public Path getSubDirectory(FileSystem fileSystem, Path root, Path path) throws IOException {
+ if (getSubDirectory == null) {
+ throw new IOException("Nope");
+ }
+ return getSubDirectory.apply(root, path);
+ }
+ };
+ target = new ModuleSourceProvider(FileSystems.getDefault(), classLoader, fileSupport);
+ }
+
+ @Test
+ public void itShouldUseFileSupport() {
+ getSubDirectory = (root, path) -> {
+ if (root.toString().equals("modules") && path.toString().equals("test.module")) {
+ return Paths.get("modules/test.module");
+ }
+ return null;
+ };
+
+ ModuleSource source = (ModuleSource) target.findSource("test.module", null);
+ assertEquals(mkpath("modules/test.module"), source.getModulePath().toString());
+ assertEquals("module:" + mkpath("modules/test.module"), source.toString());
+ }
+
+ private static class FakeClassLoader extends ClassLoader {
+ @Override
+ public Class<?> loadClass(String name) throws ClassNotFoundException {
+ return null;
+ }
+ }
+}
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc;
import java.util.ListIterator;
@@ -28,7 +30,6 @@
import org.graalvm.compiler.code.CompilationResult;
import org.graalvm.compiler.core.GraalCompiler;
import org.graalvm.compiler.core.common.CompilationIdentifier;
-import org.graalvm.compiler.core.common.CompilationIdentifier.Verbosity;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.hotspot.HotSpotBackend;
import org.graalvm.compiler.hotspot.HotSpotCompiledCodeBuilder;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompilationTask.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompilationTask.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc;
import java.util.concurrent.TimeUnit;
@@ -87,6 +89,7 @@
/**
* Compile a method or a constructor.
*/
+ @Override
@SuppressWarnings("try")
public void run() {
// Ensure a JVMCI runtime is initialized prior to Debug being initialized as the former
@@ -186,12 +189,15 @@
@Override
public boolean equals(Object obj) {
- if (this == obj)
+ if (this == obj) {
return true;
- if (obj == null)
+ }
+ if (obj == null) {
return false;
- if (getClass() != obj.getClass())
+ }
+ if (getClass() != obj.getClass()) {
return false;
+ }
AOTCompilationTask other = (AOTCompilationTask) obj;
return (this.id == other.id);
}
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiledClass.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiledClass.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -21,27 +21,27 @@
* questions.
*/
+
+
package jdk.tools.jaotc;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;
+import jdk.tools.jaotc.AOTDynamicTypeStore.AdapterLocation;
+import jdk.tools.jaotc.AOTDynamicTypeStore.AppendixLocation;
+import jdk.tools.jaotc.AOTDynamicTypeStore.Location;
import jdk.tools.jaotc.binformat.BinaryContainer;
import jdk.tools.jaotc.binformat.ReadOnlyDataContainer;
import jdk.tools.jaotc.binformat.Symbol.Binding;
import jdk.tools.jaotc.binformat.Symbol.Kind;
-
import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
import jdk.vm.ci.meta.ResolvedJavaField;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaType;
-import jdk.tools.jaotc.AOTDynamicTypeStore.AdapterLocation;
-import jdk.tools.jaotc.AOTDynamicTypeStore.AppendixLocation;
-import jdk.tools.jaotc.AOTDynamicTypeStore.Location;
-
/**
* Class encapsulating Graal-compiled output of a Java class. The compilation result of all methods
* of a class {@code className} are maintained in an array list.
@@ -74,7 +74,7 @@
this.dependentMethods = new ArrayList<>();
this.classId = classId;
this.type = type;
- this.metadataName = type.isAnonymous() ? "anon<"+ classId + ">": type.getName();
+ this.metadataName = type.isUnsafeAnonymous() ? "anon<" + classId + ">" : type.getName();
this.gotIndex = binaryContainer.addTwoSlotKlassSymbol(metadataName);
this.compiledMethodsOffset = -1; // Not compiled classes do not have compiled methods.
this.dependentMethodsOffset = -1;
@@ -84,9 +84,9 @@
String name = metadataName;
Set<Location> locs = dynoStore.getDynamicClassLocationsForType(type);
if (locs == null) {
- return new String[] {name};
+ return new String[]{name};
} else {
- ArrayList<String> names = new ArrayList<String>();
+ ArrayList<String> names = new ArrayList<>();
names.add(name);
for (Location l : locs) {
HotSpotResolvedObjectType cpType = l.getHolder();
@@ -95,14 +95,14 @@
// may record types that don't make it into the final graph.
// We can safely ignore those here.
if (data == null) {
- // Not a compiled or inlined method
- continue;
+ // Not a compiled or inlined method
+ continue;
}
int cpi = l.getCpi();
- String location = "<"+ data.classId + ":" + cpi + ">";
+ String location = "<" + data.classId + ":" + cpi + ">";
if (l instanceof AdapterLocation) {
names.add("adapter" + location);
- AdapterLocation a = (AdapterLocation)l;
+ AdapterLocation a = (AdapterLocation) l;
names.add("adapter:" + a.getMethodId() + location);
} else {
assert l instanceof AppendixLocation;
@@ -319,26 +319,23 @@
/**
* Add a klass data.
*/
- synchronized static AOTKlassData addAOTKlassData(BinaryContainer binaryContainer, HotSpotResolvedObjectType type) {
- String name = type.getName();
- AOTKlassData data = klassData.get(name);
- if (data != null) {
- assert data.getType() == type : "duplicate classes for name " + name;
- } else {
+ static synchronized AOTKlassData addAOTKlassData(BinaryContainer binaryContainer, HotSpotResolvedObjectType type) {
+ AOTKlassData data = getAOTKlassData(type);
+ if (data == null) {
data = new AOTKlassData(binaryContainer, type, classesCount++);
- klassData.put(name, data);
+ klassData.put(type.getName(), data);
}
return data;
}
- private synchronized static AOTKlassData getAOTKlassData(String name) {
- return klassData.get(name);
- }
-
- synchronized static AOTKlassData getAOTKlassData(HotSpotResolvedObjectType type) {
+ static synchronized AOTKlassData getAOTKlassData(HotSpotResolvedObjectType type) {
String name = type.getName();
- AOTKlassData data = getAOTKlassData(name);
- assert data == null || data.getType() == type : "duplicate classes for name " + name;
+ AOTKlassData data = klassData.get(name);
+ if (data != null) {
+ HotSpotResolvedObjectType oldType = data.getType();
+ assert oldType == type : "duplicate classes for name " + type.getName() + ", fingerprints old: " + oldType.getFingerprint() + ", new: " + type.getFingerprint() +
+ ", klass pointers old: " + oldType.klass() + ", new: " + type.klass();
+ }
return data;
}
@@ -363,17 +360,14 @@
}
}
- synchronized static AOTKlassData addFingerprintKlassData(BinaryContainer binaryContainer, HotSpotResolvedObjectType type) {
+ static synchronized AOTKlassData addFingerprintKlassData(BinaryContainer binaryContainer, HotSpotResolvedObjectType type) {
if (type.isArray()) {
return addAOTKlassData(binaryContainer, type);
}
assert type.getFingerprint() != 0 : "no fingerprint for " + type.getName();
AOTKlassData old = getAOTKlassData(type);
if (old != null) {
- boolean assertsEnabled = false;
- // Next assignment will be executed when asserts are enabled.
- assert assertsEnabled = true;
- if (assertsEnabled) {
+ if (areAssertionsEnabled()) {
HotSpotResolvedObjectType s = type.getSuperclass();
if (s != null) {
assert getAOTKlassData(s) != null : "fingerprint for super " + s.getName() + " needed for " + type.getName();
@@ -397,6 +391,14 @@
return addAOTKlassData(binaryContainer, type);
}
+ @SuppressWarnings("all")
+ private static boolean areAssertionsEnabled() {
+ boolean assertsEnabled = false;
+ // Next assignment will be executed when asserts are enabled.
+ assert assertsEnabled = true;
+ return assertsEnabled;
+ }
+
/*
* Put methods data to contained.
*/
@@ -431,9 +433,7 @@
}
static HotSpotResolvedObjectType getType(Object ref) {
- return (ref instanceof HotSpotResolvedObjectType) ?
- (HotSpotResolvedObjectType)ref :
- ((HotSpotResolvedJavaMethod)ref).getDeclaringClass();
+ return (ref instanceof HotSpotResolvedObjectType) ? (HotSpotResolvedObjectType) ref : ((HotSpotResolvedJavaMethod) ref).getDeclaringClass();
}
static String metadataName(HotSpotResolvedObjectType type) {
@@ -448,11 +448,11 @@
static String metadataName(Object ref) {
if (ref instanceof HotSpotResolvedJavaMethod) {
- HotSpotResolvedJavaMethod m = (HotSpotResolvedJavaMethod)ref;
+ HotSpotResolvedJavaMethod m = (HotSpotResolvedJavaMethod) ref;
return metadataName(m);
} else {
assert ref instanceof HotSpotResolvedObjectType : "unexpected object type " + ref.getClass().getName();
- HotSpotResolvedObjectType type = (HotSpotResolvedObjectType)ref;
+ HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) ref;
return metadataName(type);
}
}
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiler.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiler.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc;
import java.util.ArrayList;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTDynamicTypeStore.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTDynamicTypeStore.java Thu Aug 23 11:09:16 2018 -0400
@@ -20,32 +20,23 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-package jdk.tools.jaotc;
-import org.graalvm.compiler.hotspot.meta.HotSpotInvokeDynamicPlugin.DynamicTypeStore;
-import org.graalvm.compiler.nodes.ConstantNode;
-import org.graalvm.compiler.nodes.StructuredGraph;
-import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.compiler.nodes.graphbuilderconf.InvokeDynamicPlugin;
-import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
-import jdk.vm.ci.hotspot.HotSpotConstantPool;
-import jdk.vm.ci.hotspot.HotSpotConstantPoolObject;
-import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider;
-import jdk.vm.ci.hotspot.HotSpotObjectConstant;
-import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
-import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
-import jdk.vm.ci.meta.ConstantPool;
-import jdk.vm.ci.meta.ConstantReflectionProvider;
-import jdk.vm.ci.meta.JavaConstant;
-import jdk.vm.ci.meta.MetaAccessProvider;
-import jdk.vm.ci.meta.ResolvedJavaMethod;
-import jdk.vm.ci.meta.ResolvedJavaType;
+package jdk.tools.jaotc;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
+import org.graalvm.compiler.hotspot.meta.HotSpotInvokeDynamicPlugin.DynamicTypeStore;
+
+import jdk.vm.ci.hotspot.HotSpotConstantPool;
+import jdk.vm.ci.hotspot.HotSpotConstantPoolObject;
+import jdk.vm.ci.hotspot.HotSpotObjectConstant;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
+import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
+import jdk.vm.ci.meta.JavaConstant;
+
final class AOTDynamicTypeStore implements DynamicTypeStore {
public static class Location {
@@ -60,15 +51,22 @@
public HotSpotResolvedObjectType getHolder() {
return holder;
}
+
public int getCpi() {
return cpi;
}
+
+ @Override
public String toString() {
return getHolder().getName() + "@" + cpi;
}
+
+ @Override
public int hashCode() {
return holder.hashCode() + getClass().hashCode() + cpi;
}
+
+ @Override
public boolean equals(Object o) {
if (this == o) {
return true;
@@ -76,7 +74,7 @@
if (getClass() != o.getClass()) {
return false;
}
- Location l = (Location)o;
+ Location l = (Location) o;
return cpi == l.cpi && holder.equals(l.holder);
}
}
@@ -88,9 +86,12 @@
super(holder, cpi);
this.methodId = methodId;
}
+
public int getMethodId() {
return methodId;
}
+
+ @Override
public String toString() {
return "adapter:" + methodId + "@" + super.toString();
}
@@ -100,6 +101,8 @@
AppendixLocation(HotSpotResolvedObjectType holder, int cpi) {
super(holder, cpi);
}
+
+ @Override
public String toString() {
return "appendix@" + super.toString();
}
@@ -122,7 +125,7 @@
@Override
public void recordAdapter(int opcode, HotSpotResolvedObjectType holder, int index, HotSpotResolvedJavaMethod adapter) {
- int cpi = ((HotSpotConstantPool)holder.getConstantPool()).rawIndexToConstantPoolIndex(index, opcode);
+ int cpi = ((HotSpotConstantPool) holder.getConstantPool()).rawIndexToConstantPoolIndex(index, opcode);
int methodId = adapter.methodIdnum();
HotSpotResolvedObjectType adapterType = adapter.getDeclaringClass();
recordDynamicTypeLocation(new AdapterLocation(holder, cpi, methodId), adapterType);
@@ -130,8 +133,8 @@
@Override
public JavaConstant recordAppendix(int opcode, HotSpotResolvedObjectType holder, int index, JavaConstant appendix) {
- int cpi = ((HotSpotConstantPool)holder.getConstantPool()).rawIndexToConstantPoolIndex(index, opcode);
- HotSpotResolvedObjectType appendixType = ((HotSpotObjectConstant)appendix).getType();
+ int cpi = ((HotSpotConstantPool) holder.getConstantPool()).rawIndexToConstantPoolIndex(index, opcode);
+ HotSpotResolvedObjectType appendixType = ((HotSpotObjectConstant) appendix).getType();
recordDynamicTypeLocation(new AppendixLocation(holder, cpi), appendixType);
// Make the constant locatable
return HotSpotConstantPoolObject.forObject(holder, cpi, appendix);
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTHotSpotResolvedJavaMethod.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTHotSpotResolvedJavaMethod.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc;
import org.graalvm.compiler.code.CompilationResult;
@@ -39,15 +41,18 @@
this.backend = backend;
}
+ @Override
public String getSymbolName() {
return JavaMethodInfo.uniqueMethodName(method);
}
+ @Override
public String getNameAndSignature() {
String className = method.getDeclaringClass().getName();
return className + "." + method.getName() + method.getSignature().toMethodDescriptor();
}
+ @Override
public HotSpotCompiledCode compiledCode(CompilationResult result) {
return HotSpotCompiledCodeBuilder.createCompiledCode(backend.getCodeCache(), method, null, result);
}
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTStub.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTStub.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc;
import org.graalvm.compiler.code.CompilationResult;
@@ -40,14 +42,17 @@
this.backend = backend;
}
+ @Override
public String getSymbolName() {
return stub.toString();
}
+ @Override
public String getNameAndSignature() {
return stub.toString();
}
+ @Override
public HotSpotCompiledCode compiledCode(CompilationResult result) {
return HotSpotCompiledCodeBuilder.createCompiledCode(backend.getCodeCache(), null, null, result);
}
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CallInfo.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CallInfo.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc;
import org.graalvm.compiler.bytecode.Bytecodes;
@@ -33,7 +35,7 @@
final class CallInfo {
static boolean isStaticTarget(Call call) {
- return !((HotSpotResolvedJavaMethod)call.target).hasReceiver();
+ return !((HotSpotResolvedJavaMethod) call.target).hasReceiver();
}
private static boolean isStaticOpcode(Call call) {
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CallSiteRelocationInfo.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CallSiteRelocationInfo.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc;
import jdk.tools.jaotc.binformat.Relocation.RelocType;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CallSiteRelocationSymbol.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CallSiteRelocationSymbol.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc;
import jdk.tools.jaotc.binformat.BinaryContainer;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CodeOffsets.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CodeOffsets.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc;
import java.util.List;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CodeSectionProcessor.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CodeSectionProcessor.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,18 +21,18 @@
* questions.
*/
+
+
package jdk.tools.jaotc;
import java.util.ArrayList;
+import org.graalvm.compiler.code.CompilationResult;
+import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
+
import jdk.tools.jaotc.binformat.BinaryContainer;
import jdk.tools.jaotc.binformat.CodeContainer;
import jdk.tools.jaotc.binformat.Symbol;
-import jdk.tools.jaotc.StubInformation;
-import org.graalvm.compiler.code.CompilationResult;
-import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
-
-import jdk.vm.ci.aarch64.AArch64;
import jdk.vm.ci.amd64.AMD64;
import jdk.vm.ci.code.TargetDescription;
import jdk.vm.ci.code.site.Call;
@@ -75,7 +75,7 @@
if (infopoint.reason == InfopointReason.CALL) {
final Call callInfopoint = (Call) infopoint;
if (callInfopoint.target instanceof HotSpotForeignCallLinkage &&
- target.arch instanceof AMD64) {
+ target.arch instanceof AMD64) {
// TODO 4 is x86 size of relative displacement.
// For SPARC need something different.
int destOffset = infopoint.pcOffset + callInfopoint.size - 4;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Collector.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Collector.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc;
import java.io.BufferedReader;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CompilationSpec.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CompilationSpec.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc;
import java.util.HashSet;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CompiledMethodInfo.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CompiledMethodInfo.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc;
import java.util.concurrent.atomic.AtomicInteger;
@@ -147,7 +149,7 @@
}
/**
- * Method name
+ * Method name.
*/
private String name;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataBuilder.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataBuilder.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc;
import java.util.ArrayList;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataPatchProcessor.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataPatchProcessor.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,21 +21,22 @@
* questions.
*/
+
+
package jdk.tools.jaotc;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
+import org.graalvm.compiler.code.DataSection;
+import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction;
+
import jdk.tools.jaotc.binformat.BinaryContainer;
import jdk.tools.jaotc.binformat.Relocation;
import jdk.tools.jaotc.binformat.Relocation.RelocType;
import jdk.tools.jaotc.binformat.Symbol;
import jdk.tools.jaotc.binformat.Symbol.Binding;
import jdk.tools.jaotc.binformat.Symbol.Kind;
-import jdk.tools.jaotc.AOTCompiledClass;
-import org.graalvm.compiler.code.DataSection;
-import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction;
-
import jdk.vm.ci.code.TargetDescription;
import jdk.vm.ci.code.site.ConstantReference;
import jdk.vm.ci.code.site.DataPatch;
@@ -97,7 +98,7 @@
} else if (constant instanceof HotSpotObjectConstant) {
HotSpotObjectConstant oopConstant = (HotSpotObjectConstant) constant;
if (oopConstant instanceof HotSpotConstantPoolObject) {
- HotSpotConstantPoolObject cpo = (HotSpotConstantPoolObject)oopConstant;
+ HotSpotConstantPoolObject cpo = (HotSpotConstantPoolObject) oopConstant;
// Even if two locations use the same object, resolve separately
targetSymbol = "ldc." + cpo.getCpType().getName() + cpo.getCpi();
} else {
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/ELFMacroAssembler.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/ELFMacroAssembler.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,20 +21,20 @@
* questions.
*/
+
+
package jdk.tools.jaotc;
-import jdk.tools.jaotc.StubInformation;
+import jdk.tools.jaotc.aarch64.AArch64ELFMacroAssembler;
import jdk.tools.jaotc.amd64.AMD64ELFMacroAssembler;
-import jdk.tools.jaotc.aarch64.AArch64ELFMacroAssembler;
-
+import jdk.vm.ci.aarch64.AArch64;
import jdk.vm.ci.amd64.AMD64;
-import jdk.vm.ci.aarch64.AArch64;
import jdk.vm.ci.code.Architecture;
import jdk.vm.ci.code.TargetDescription;
public interface ELFMacroAssembler {
- public static ELFMacroAssembler getELFMacroAssembler(TargetDescription target) {
+ static ELFMacroAssembler getELFMacroAssembler(TargetDescription target) {
Architecture architecture = target.arch;
if (architecture instanceof AMD64) {
return new AMD64ELFMacroAssembler(target);
@@ -45,12 +45,12 @@
}
}
- public int currentEndOfInstruction();
+ int currentEndOfInstruction();
- public byte[] getPLTJumpCode();
+ byte[] getPLTJumpCode();
- public byte[] getPLTStaticEntryCode(StubInformation stub);
+ byte[] getPLTStaticEntryCode(StubInformation stub);
- public byte[] getPLTVirtualEntryCode(StubInformation stub);
+ byte[] getPLTVirtualEntryCode(StubInformation stub);
}
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/ForeignCallSiteRelocationInfo.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/ForeignCallSiteRelocationInfo.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc;
import jdk.tools.jaotc.binformat.BinaryContainer;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/ForeignCallSiteRelocationSymbol.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/ForeignCallSiteRelocationSymbol.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc;
import jdk.tools.jaotc.binformat.BinaryContainer;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/ForeignGotCallSiteRelocationSymbol.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/ForeignGotCallSiteRelocationSymbol.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc;
import jdk.tools.jaotc.binformat.BinaryContainer;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/GraalFilters.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/GraalFilters.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc;
import java.lang.annotation.Annotation;
@@ -30,12 +32,6 @@
import java.util.Set;
import java.util.stream.Collectors;
-import jdk.vm.ci.hotspot.HotSpotConstantPool;
-import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
-import jdk.vm.ci.meta.MetaAccessProvider;
-import jdk.vm.ci.meta.ResolvedJavaMethod;
-import jdk.vm.ci.meta.ResolvedJavaType;
-
import org.graalvm.compiler.api.directives.GraalDirectives;
import org.graalvm.compiler.api.replacements.ClassSubstitution;
import org.graalvm.compiler.api.replacements.MethodSubstitution;
@@ -47,6 +43,12 @@
import org.graalvm.compiler.replacements.Snippets;
import jdk.internal.vm.compiler.word.WordBase;
+import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
+import jdk.vm.ci.meta.MetaAccessProvider;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.hotspot.HotSpotConstantPool;
+
final class GraalFilters {
private List<ResolvedJavaType> specialClasses;
private List<ResolvedJavaType> specialArgumentAndReturnTypes;
@@ -90,7 +92,7 @@
return false;
}
// Skip klass with Condy until Graal is fixed.
- if (((HotSpotConstantPool)((HotSpotResolvedObjectType) klass).getConstantPool()).hasDynamicConstant()) {
+ if (((HotSpotConstantPool) ((HotSpotResolvedObjectType) klass).getConstantPool()).hasDynamicConstant()) {
return false;
}
return true;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/InfopointProcessor.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/InfopointProcessor.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc;
import jdk.tools.jaotc.binformat.BinaryContainer;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/InstructionDecoder.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/InstructionDecoder.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc;
import jdk.tools.jaotc.amd64.AMD64InstructionDecoder;
@@ -38,13 +40,13 @@
if (architecture instanceof AMD64) {
return new AMD64InstructionDecoder(target);
} else if (architecture instanceof AArch64) {
- return new AArch64InstructionDecoder(target);
+ return new AArch64InstructionDecoder();
} else {
throw new InternalError("Unsupported architecture " + architecture);
}
}
- public abstract void decodePosition(final byte[] code, int pcOffset);
+ public abstract void decodePosition(byte[] code, int pcOffset);
public abstract int currentEndOfInstruction();
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/JavaCallSiteRelocationInfo.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/JavaCallSiteRelocationInfo.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc;
import jdk.tools.jaotc.binformat.Relocation.RelocType;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/JavaCallSiteRelocationSymbol.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/JavaCallSiteRelocationSymbol.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,12 +21,12 @@
* questions.
*/
+
+
package jdk.tools.jaotc;
import jdk.tools.jaotc.binformat.BinaryContainer;
import jdk.tools.jaotc.binformat.Symbol;
-import jdk.tools.jaotc.StubInformation;
-
import jdk.vm.ci.code.site.Call;
import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
@@ -44,11 +44,11 @@
String archStr = System.getProperty("os.arch").toLowerCase();
if (archStr.equals("aarch64")) {
// AArch64 is a special case: it uses 48-bit addresses.
- byte[] non_oop_word = {-1, -1, -1, -1, -1, -1, 0, 0};
- minusOneSlot = non_oop_word;
+ byte[] nonOopWord = {-1, -1, -1, -1, -1, -1, 0, 0};
+ minusOneSlot = nonOopWord;
} else {
- byte[] non_oop_word = {-1, -1, -1, -1, -1, -1, -1, -1};
- minusOneSlot = non_oop_word;
+ byte[] nonOopWord = {-1, -1, -1, -1, -1, -1, -1, -1};
+ minusOneSlot = nonOopWord;
}
}
@@ -135,7 +135,6 @@
*/
private static String getResolveSymbolName(CompiledMethodInfo mi, Call call) {
String resolveSymbolName;
- String name = call.target.toString();
if (CallInfo.isStaticCall(call)) {
assert mi.hasMark(call, MarkId.INVOKESTATIC);
resolveSymbolName = BinaryContainer.getResolveStaticEntrySymbolName();
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/JavaMethodInfo.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/JavaMethodInfo.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc;
import org.graalvm.compiler.code.CompilationResult;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Linker.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Linker.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc;
import java.io.BufferedReader;
@@ -148,32 +150,7 @@
}
/**
- * Visual Studio supported versions Search Order is: VS2013, VS2015, VS2012
- */
- public enum VSVERSIONS {
- VS2013("VS120COMNTOOLS", "C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\VC\\bin\\amd64\\link.exe"),
- VS2015("VS140COMNTOOLS", "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\bin\\amd64\\link.exe"),
- VS2012("VS110COMNTOOLS", "C:\\Program Files (x86)\\Microsoft Visual Studio 11.0\\VC\\bin\\amd64\\link.exe");
-
- private final String envvariable;
- private final String wkp;
-
- VSVERSIONS(String envvariable, String wellknownpath) {
- this.envvariable = envvariable;
- this.wkp = wellknownpath;
- }
-
- String EnvVariable() {
- return envvariable;
- }
-
- String WellKnownPath() {
- return wkp;
- }
- }
-
- /**
- * Search for Visual Studio link.exe Search Order is: VS2013, VS2015, VS2012
+ * Search for Visual Studio link.exe Search Order is: VS2013, VS2015, VS2012.
*/
private static String getWindowsLinkPath() {
String link = "\\VC\\bin\\amd64\\link.exe";
@@ -182,7 +159,7 @@
* First try searching the paths pointed to by the VS environment variables.
*/
for (VSVERSIONS vs : VSVERSIONS.values()) {
- String vspath = System.getenv(vs.EnvVariable());
+ String vspath = System.getenv(vs.getEnvVariable());
if (vspath != null) {
File commonTools = new File(vspath);
File vsRoot = commonTools.getParentFile().getParentFile();
@@ -197,7 +174,7 @@
* If we didn't find via the VS environment variables, try the well known paths
*/
for (VSVERSIONS vs : VSVERSIONS.values()) {
- String wkp = vs.WellKnownPath();
+ String wkp = vs.getWellKnownPath();
if (new File(wkp).exists()) {
return wkp;
}
@@ -206,4 +183,30 @@
return null;
}
+ // @formatter:off (workaround for Eclipse formatting bug)
+ /**
+ * Visual Studio supported versions Search Order is: VS2013, VS2015, VS2012.
+ */
+ enum VSVERSIONS {
+ VS2013("VS120COMNTOOLS", "C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\VC\\bin\\amd64\\link.exe"),
+ VS2015("VS140COMNTOOLS", "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\bin\\amd64\\link.exe"),
+ VS2012("VS110COMNTOOLS", "C:\\Program Files (x86)\\Microsoft Visual Studio 11.0\\VC\\bin\\amd64\\link.exe");
+
+ private final String envvariable;
+ private final String wkp;
+
+ VSVERSIONS(String envvariable, String wellknownpath) {
+ this.envvariable = envvariable;
+ this.wkp = wellknownpath;
+ }
+
+ String getEnvVariable() {
+ return envvariable;
+ }
+
+ String getWellKnownPath() {
+ return wkp;
+ }
+ }
+ // @formatter:on
}
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/LoadedClass.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/LoadedClass.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc;
public class LoadedClass {
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/LogPrinter.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/LogPrinter.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc;
import java.io.FileWriter;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc;
import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
@@ -33,9 +35,6 @@
import java.util.ListIterator;
import java.util.Set;
-import jdk.tools.jaotc.binformat.BinaryContainer;
-import jdk.tools.jaotc.Options.Option;
-
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
import org.graalvm.compiler.api.runtime.GraalJVMCICompiler;
import org.graalvm.compiler.debug.DebugContext;
@@ -45,7 +44,6 @@
import org.graalvm.compiler.hotspot.HotSpotGraalCompilerFactory;
import org.graalvm.compiler.hotspot.HotSpotGraalOptionValues;
import org.graalvm.compiler.hotspot.HotSpotGraalRuntime;
-import org.graalvm.compiler.hotspot.HotSpotGraalRuntime.HotSpotGC;
import org.graalvm.compiler.hotspot.HotSpotHostBackend;
import org.graalvm.compiler.hotspot.meta.HotSpotInvokeDynamicPlugin;
import org.graalvm.compiler.java.GraphBuilderPhase;
@@ -57,6 +55,8 @@
import org.graalvm.compiler.printer.GraalDebugHandlersFactory;
import org.graalvm.compiler.runtime.RuntimeProvider;
+import jdk.tools.jaotc.Options.Option;
+import jdk.tools.jaotc.binformat.BinaryContainer;
import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.runtime.JVMCI;
@@ -182,7 +182,7 @@
System.gc();
}
- int gc = runtime.getGarbageCollector().ordinal()+1;
+ int gc = runtime.getGarbageCollector().ordinal() + 1;
BinaryContainer binaryContainer = new BinaryContainer(graalOptions, graalHotSpotVMConfig, graphBuilderConfig, gc, JVM_VERSION);
DataBuilder dataBuilder = new DataBuilder(this, backend, classes, binaryContainer);
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MarkId.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MarkId.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc;
import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
@@ -55,7 +57,7 @@
private final int value;
- private MarkId(String name) {
+ MarkId(String name) {
this.value = (int) (long) HotSpotJVMCIRuntime.runtime().getConfigStore().getConstants().get(name);
}
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MarkProcessor.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MarkProcessor.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc;
import jdk.tools.jaotc.binformat.BinaryContainer;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MetadataBuilder.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MetadataBuilder.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc;
import java.util.ArrayList;
@@ -33,7 +35,6 @@
import org.graalvm.compiler.code.CompilationResult;
import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
-
import jdk.vm.ci.code.StackSlot;
import jdk.vm.ci.code.site.DataPatch;
import jdk.vm.ci.code.site.Infopoint;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Options.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Options.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc;
import java.text.MessageFormat;
@@ -255,7 +257,8 @@
}
// Make checkstyle happy.
- for (int i = 0; i < args.length; i++) {
+ int i = 0;
+ while (i < args.length) {
String arg = args[i];
if (arg.charAt(0) == '-') {
@@ -282,6 +285,7 @@
} else {
task.options.files.add(new SearchFor(arg));
}
+ i++;
}
}
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/StubDirectCallSiteRelocationSymbol.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/StubDirectCallSiteRelocationSymbol.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc;
import jdk.tools.jaotc.binformat.BinaryContainer;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/StubInformation.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/StubInformation.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,15 +21,20 @@
* questions.
*/
+
+
package jdk.tools.jaotc;
public final class StubInformation {
private int stubOffset; // the offset inside the code (text + stubOffset)
private int stubSize; // the stub size
private int dispatchJumpOffset; // offset after main dispatch jump instruction
- private int resolveJumpOffset; // offset after jump instruction to runtime call resolution function.
- private int resolveJumpStart; // offset of jump instruction to VM runtime call resolution function.
- private int c2iJumpOffset; // offset after jump instruction to c2i adapter for static calls.
+ private int resolveJumpOffset; // offset after jump instruction to runtime call resolution
+ // function.
+ private int resolveJumpStart; // offset of jump instruction to VM runtime call resolution
+ // function.
+ private int c2iJumpOffset; // offset after jump instruction to c2i adapter for static
+ // calls.
private int movOffset; // offset after move instruction which loads from got cell:
// - Method* for static call
// - Klass* for virtual call
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Timer.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Timer.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc;
final class Timer implements AutoCloseable {
@@ -34,6 +36,7 @@
main.printer.printInfo(message);
}
+ @Override
public void close() {
final long end = System.currentTimeMillis();
main.printer.printlnInfo(" (" + (end - start) + " ms)");
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/aarch64/AArch64ELFMacroAssembler.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/aarch64/AArch64ELFMacroAssembler.java Thu Aug 23 11:09:16 2018 -0400
@@ -22,19 +22,21 @@
* questions.
*/
+
+
package jdk.tools.jaotc.aarch64;
-import jdk.tools.jaotc.StubInformation;
-import jdk.tools.jaotc.ELFMacroAssembler;
+import static jdk.vm.ci.aarch64.AArch64.r12;
+import static jdk.vm.ci.aarch64.AArch64.r16;
+import static jdk.vm.ci.aarch64.AArch64.r17;
+import static jdk.vm.ci.aarch64.AArch64.r9;
import org.graalvm.compiler.asm.aarch64.AArch64Address;
import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler;
-
+import jdk.tools.jaotc.ELFMacroAssembler;
+import jdk.tools.jaotc.StubInformation;
import jdk.vm.ci.code.TargetDescription;
-import jdk.vm.ci.code.Register;
-
-import static jdk.vm.ci.aarch64.AArch64.*;
public final class AArch64ELFMacroAssembler extends AArch64MacroAssembler implements ELFMacroAssembler {
@@ -71,7 +73,7 @@
jmp(r16);
stub.setDispatchJumpOffset(position());
- // C2I stub used to call interpreter. First load r12
+ // C2I stub used to call interpreter. First load r12
// (i.e. rmethod) with a pointer to the Method structure ...
addressOf(r12);
ldr(64, r12, AArch64Address.createBaseRegisterOnlyAddress(r12));
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/aarch64/AArch64InstructionDecoder.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/aarch64/AArch64InstructionDecoder.java Thu Aug 23 11:09:16 2018 -0400
@@ -22,17 +22,17 @@
* questions.
*/
+
+
package jdk.tools.jaotc.aarch64;
import jdk.tools.jaotc.InstructionDecoder;
-import jdk.vm.ci.code.TargetDescription;
-
public final class AArch64InstructionDecoder extends InstructionDecoder {
private int currentEndOfInstruction;
- public AArch64InstructionDecoder(TargetDescription target) {
+ public AArch64InstructionDecoder() {
}
@Override
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/amd64/AMD64ELFMacroAssembler.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/amd64/AMD64ELFMacroAssembler.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc.amd64;
import static jdk.vm.ci.amd64.AMD64.rax;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/amd64/AMD64InstructionDecoder.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/amd64/AMD64InstructionDecoder.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc.amd64;
import jdk.tools.jaotc.InstructionDecoder;
@@ -61,11 +63,13 @@
static final int VEX_2BYTES = 0xC5;
}
+ @SuppressWarnings("unused")
private static class VexPrefix {
static final int VEX_R = 0x80;
static final int VEX_W = 0x80;
}
+ @SuppressWarnings("unused")
private static class VexOpcode {
static final int VEX_OPCODE_NONE = 0x0;
static final int VEX_OPCODE_0F = 0x1;
@@ -112,7 +116,7 @@
againAfterPrefix = false;
switch (0xFF & code[ip++]) {
- // These convenience macros generate groups of "case" labels for the switch.
+ // These convenience macros generate groups of "case" labels for the switch.
case Prefix.CSSegment:
case Prefix.SSSegment:
@@ -421,18 +425,18 @@
case Prefix.VEX_3BYTES:
case Prefix.VEX_2BYTES:
assert ip == pcOffset + 1 : "no prefixes allowed";
- int vex_opcode;
+ int vexOpcode;
// First byte
if ((code[pcOffset] & 0xFF) == Prefix.VEX_3BYTES) {
- vex_opcode = VexOpcode.VEX_OPCODE_MASK & code[ip];
+ vexOpcode = VexOpcode.VEX_OPCODE_MASK & code[ip];
ip++; // third byte
is64bit = ((VexPrefix.VEX_W & code[ip]) == VexPrefix.VEX_W);
} else {
- vex_opcode = VexOpcode.VEX_OPCODE_0F;
+ vexOpcode = VexOpcode.VEX_OPCODE_0F;
}
ip++; // opcode
// To find the end of instruction (which == end_pc_operand).
- switch (vex_opcode) {
+ switch (vexOpcode) {
case VexOpcode.VEX_OPCODE_0F:
switch (0xFF & code[ip]) {
case 0x70: // pshufd r, r/a, #8
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSearch.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSearch.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc.collect;
import jdk.tools.jaotc.LoadedClass;
@@ -37,7 +39,9 @@
}
public List<LoadedClass> search(List<SearchFor> search, SearchPath searchPath) {
- return search(search, searchPath, (s, t) -> { throw new InternalError(s + " : " + t, t); } );
+ return search(search, searchPath, (s, t) -> {
+ throw new InternalError(s + " : " + t, t);
+ });
}
public List<LoadedClass> search(List<SearchFor> search, SearchPath searchPath, BiConsumer<String, Throwable> classLoadingErrorsHandler) {
@@ -53,7 +57,9 @@
if (source != null) {
source.eachClass((name, loader) -> {
LoadedClass x = loadClass(name, loader, classLoadingErrorsHandler);
- if (x != null) { loaded.add(x); }
+ if (x != null) {
+ loaded.add(x);
+ }
});
}
}
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSource.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSource.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc.collect;
import java.nio.file.Path;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/FileSupport.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/FileSupport.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,11 +21,21 @@
* questions.
*/
+
+
package jdk.tools.jaotc.collect;
import java.io.IOException;
-import java.net.*;
-import java.nio.file.*;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.file.DirectoryStream;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.util.HashMap;
public class FileSupport {
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/FileSystemFinder.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/FileSystemFinder.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,16 +21,23 @@
* questions.
*/
+
+
package jdk.tools.jaotc.collect;
+import static java.nio.file.FileVisitResult.CONTINUE;
+
import java.io.IOException;
-import java.nio.file.*;
+import java.nio.file.FileVisitResult;
+import java.nio.file.FileVisitor;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.PathMatcher;
+import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Iterator;
-import static java.nio.file.FileVisitResult.CONTINUE;
-
/**
* {@link FileVisitor} implementation to find class files recursively.
*/
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/SearchFor.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/SearchFor.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc.collect;
public final class SearchFor {
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/SearchPath.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/SearchPath.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc.collect;
import java.nio.file.FileSystem;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/SourceProvider.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/SourceProvider.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc.collect;
public interface SourceProvider {
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/classname/ClassNameSource.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/classname/ClassNameSource.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc.collect.classname;
import jdk.tools.jaotc.collect.ClassSource;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/classname/ClassNameSourceProvider.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/classname/ClassNameSourceProvider.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc.collect.classname;
import jdk.tools.jaotc.collect.ClassSource;
@@ -32,7 +34,7 @@
import java.nio.file.Paths;
public final class ClassNameSourceProvider implements SourceProvider {
- public final static String TYPE = "class";
+ public static final String TYPE = "class";
private final ClassLoader classLoader;
public ClassNameSourceProvider(FileSupport fileSupport) {
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/directory/DirectorySource.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/directory/DirectorySource.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc.collect.directory;
import jdk.tools.jaotc.collect.ClassSource;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/directory/DirectorySourceProvider.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/directory/DirectorySourceProvider.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc.collect.directory;
import jdk.tools.jaotc.collect.ClassSource;
@@ -36,7 +38,7 @@
public final class DirectorySourceProvider implements SourceProvider {
private final FileSupport fileSupport;
private final FileSystem fileSystem;
- public final static String TYPE = "directory";
+ public static final String TYPE = "directory";
public DirectorySourceProvider(FileSupport fileSupport) {
this.fileSupport = fileSupport;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/jar/JarFileSource.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/jar/JarFileSource.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc.collect.jar;
import jdk.tools.jaotc.collect.ClassSource;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/jar/JarSourceProvider.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/jar/JarSourceProvider.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc.collect.jar;
import jdk.tools.jaotc.collect.ClassSource;
@@ -37,7 +39,7 @@
public final class JarSourceProvider implements SourceProvider {
private final FileSystem fileSystem;
private final FileSupport fileSupport;
- public final static String TYPE = "jar";
+ public static final String TYPE = "jar";
public JarSourceProvider() {
this(new FileSupport());
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/module/ModuleSource.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/module/ModuleSource.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc.collect.module;
import jdk.tools.jaotc.collect.ClassSource;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/module/ModuleSourceProvider.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/module/ModuleSourceProvider.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc.collect.module;
import jdk.tools.jaotc.collect.ClassSource;
@@ -38,7 +40,7 @@
private final FileSystem fileSystem;
private final ClassLoader classLoader;
private final FileSupport fileSupport;
- public final static String TYPE = "module";
+ public static final String TYPE = "module";
public ModuleSourceProvider() {
this(FileSystems.getFileSystem(URI.create("jrt:/")), ClassLoader.getSystemClassLoader(), new FileSupport());
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/utils/NativeOrderOutputStream.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/utils/NativeOrderOutputStream.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package jdk.tools.jaotc.utils;
import java.io.ByteArrayOutputStream;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Thu Aug 23 11:09:16 2018 -0400
@@ -499,7 +499,8 @@
break;
case BOUND: /** Expr :: instMethod */
- init = tree.getQualifierExpression();
+ init = transTypes.coerce(attrEnv, tree.getQualifierExpression(),
+ types.erasure(tree.sym.owner.type));
init = attr.makeNullCheck(init);
break;
--- a/src/jdk.hotspot.agent/linux/native/libsaproc/ps_core.c Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.hotspot.agent/linux/native/libsaproc/ps_core.c Thu Aug 23 11:09:16 2018 -0400
@@ -32,6 +32,7 @@
#include <link.h>
#include "libproc_impl.h"
#include "salibelf.h"
+#include "cds.h"
// This file has the libproc implementation to read core files.
// For live processes, refer to ps_proc.c. Portions of this is adapted
@@ -203,65 +204,6 @@
// PROT_READ pages. These pages are not dumped into core dump.
// With this workaround, these pages are read from classes.jsa.
-// FIXME: !HACK ALERT!
-// The format of sharing achive file header is needed to read shared heap
-// file mappings. For now, I am hard coding portion of FileMapHeader here.
-// Refer to filemap.hpp.
-
-// FileMapHeader describes the shared space data in the file to be
-// mapped. This structure gets written to a file. It is not a class,
-// so that the compilers don't add any compiler-private data to it.
-
-#define NUM_SHARED_MAPS 9
-
-// Refer to FileMapInfo::_current_version in filemap.hpp
-#define CURRENT_ARCHIVE_VERSION 3
-
-typedef unsigned char* address;
-typedef uintptr_t uintx;
-typedef intptr_t intx;
-
-struct FileMapHeader {
- int _magic; // identify file type.
- int _crc; // header crc checksum.
- int _version; // (from enum, above.)
- size_t _alignment; // how shared archive should be aligned
- int _obj_alignment; // value of ObjectAlignmentInBytes
- address _narrow_oop_base; // compressed oop encoding base
- int _narrow_oop_shift; // compressed oop encoding shift
- bool _compact_strings; // value of CompactStrings
- uintx _max_heap_size; // java max heap size during dumping
- int _narrow_oop_mode; // compressed oop encoding mode
- int _narrow_klass_shift; // save narrow klass base and shift
- address _narrow_klass_base;
- char* _misc_data_patching_start;
- char* _read_only_tables_start;
- address _cds_i2i_entry_code_buffers;
- size_t _cds_i2i_entry_code_buffers_size;
- size_t _core_spaces_size; // number of bytes allocated by the core spaces
- // (mc, md, ro, rw and od).
-
-
- struct space_info {
- int _crc; // crc checksum of the current space
- size_t _file_offset; // sizeof(this) rounded to vm page size
- union {
- char* _base; // copy-on-write base address
- intx _offset; // offset from the compressed oop encoding base, only used
- // by archive heap space
- } _addr;
- size_t _used; // for setting space top on read
- // 4991491 NOTICE These are C++ bool's in filemap.hpp and must match up with
- // the C type matching the C++ bool type on any given platform.
- // We assume the corresponding C type is char but licensees
- // may need to adjust the type of these fields.
- char _read_only; // read only space?
- char _allow_exec; // executable code in space?
- } _space[NUM_SHARED_MAPS];
-
- // Ignore the rest of the FileMapHeader. We don't need those fields here.
-};
-
static bool read_jboolean(struct ps_prochandle* ph, uintptr_t addr, jboolean* pvalue) {
jboolean i;
if (ps_pdread(ph, (psaddr_t) addr, &i, sizeof(i)) == PS_OK) {
@@ -317,7 +259,7 @@
const char *jvm_name = 0;
if ((jvm_name = strstr(lib->name, LIBJVM_NAME)) != 0) {
char classes_jsa[PATH_MAX];
- struct FileMapHeader header;
+ CDSFileMapHeaderBase header;
int fd = -1;
int m = 0;
size_t n = 0;
@@ -374,34 +316,34 @@
print_debug("opened %s\n", classes_jsa);
}
- // read FileMapHeader from the file
- memset(&header, 0, sizeof(struct FileMapHeader));
- if ((n = read(fd, &header, sizeof(struct FileMapHeader)))
- != sizeof(struct FileMapHeader)) {
+ // read CDSFileMapHeaderBase from the file
+ memset(&header, 0, sizeof(CDSFileMapHeaderBase));
+ if ((n = read(fd, &header, sizeof(CDSFileMapHeaderBase)))
+ != sizeof(CDSFileMapHeaderBase)) {
print_debug("can't read shared archive file map header from %s\n", classes_jsa);
close(fd);
return false;
}
// check file magic
- if (header._magic != 0xf00baba2) {
- print_debug("%s has bad shared archive file magic number 0x%x, expecing 0xf00baba2\n",
- classes_jsa, header._magic);
+ if (header._magic != CDS_ARCHIVE_MAGIC) {
+ print_debug("%s has bad shared archive file magic number 0x%x, expecting 0x%x\n",
+ classes_jsa, header._magic, CDS_ARCHIVE_MAGIC);
close(fd);
return false;
}
// check version
- if (header._version != CURRENT_ARCHIVE_VERSION) {
+ if (header._version != CURRENT_CDS_ARCHIVE_VERSION) {
print_debug("%s has wrong shared archive file version %d, expecting %d\n",
- classes_jsa, header._version, CURRENT_ARCHIVE_VERSION);
+ classes_jsa, header._version, CURRENT_CDS_ARCHIVE_VERSION);
close(fd);
return false;
}
ph->core->classes_jsa_fd = fd;
// add read-only maps from classes.jsa to the list of maps
- for (m = 0; m < NUM_SHARED_MAPS; m++) {
+ for (m = 0; m < NUM_CDS_REGIONS; m++) {
if (header._space[m]._read_only) {
base = (uintptr_t) header._space[m]._addr._base;
// no need to worry about the fractional pages at-the-end.
--- a/src/jdk.hotspot.agent/macosx/native/libsaproc/ps_core.c Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.hotspot.agent/macosx/native/libsaproc/ps_core.c Thu Aug 23 11:09:16 2018 -0400
@@ -29,6 +29,7 @@
#include <stdlib.h>
#include <stddef.h>
#include "libproc_impl.h"
+#include "cds.h"
#ifdef __APPLE__
#include "sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext.h"
@@ -204,66 +205,6 @@
// PROT_READ pages. These pages are not dumped into core dump.
// With this workaround, these pages are read from classes.jsa.
-// FIXME: !HACK ALERT!
-// The format of sharing achive file header is needed to read shared heap
-// file mappings. For now, I am hard coding portion of FileMapHeader here.
-// Refer to filemap.hpp.
-
-// FileMapHeader describes the shared space data in the file to be
-// mapped. This structure gets written to a file. It is not a class,
-// so that the compilers don't add any compiler-private data to it.
-
-#define NUM_SHARED_MAPS 9
-
-// Refer to FileMapInfo::_current_version in filemap.hpp
-#define CURRENT_ARCHIVE_VERSION 3
-
-typedef unsigned char* address;
-typedef uintptr_t uintx;
-typedef intptr_t intx;
-
-
-struct FileMapHeader {
- int _magic; // identify file type.
- int _crc; // header crc checksum.
- int _version; // (from enum, above.)
- size_t _alignment; // how shared archive should be aligned
- int _obj_alignment; // value of ObjectAlignmentInBytes
- address _narrow_oop_base; // compressed oop encoding base
- int _narrow_oop_shift; // compressed oop encoding shift
- bool _compact_strings; // value of CompactStrings
- uintx _max_heap_size; // java max heap size during dumping
- int _narrow_oop_mode; // compressed oop encoding mode
- int _narrow_klass_shift; // save narrow klass base and shift
- address _narrow_klass_base;
- char* _misc_data_patching_start;
- char* _read_only_tables_start;
- address _cds_i2i_entry_code_buffers;
- size_t _cds_i2i_entry_code_buffers_size;
- size_t _core_spaces_size; // number of bytes allocated by the core spaces
- // (mc, md, ro, rw and od).
-
-
- struct space_info {
- int _crc; // crc checksum of the current space
- size_t _file_offset; // sizeof(this) rounded to vm page size
- union {
- char* _base; // copy-on-write base address
- intx _offset; // offset from the compressed oop encoding base, only used
- // by archive heap space
- } _addr;
- size_t _used; // for setting space top on read
- // 4991491 NOTICE These are C++ bool's in filemap.hpp and must match up with
- // the C type matching the C++ bool type on any given platform.
- // We assume the corresponding C type is char but licensees
- // may need to adjust the type of these fields.
- char _read_only; // read only space?
- char _allow_exec; // executable code in space?
- } _space[NUM_SHARED_MAPS];
-
- // Ignore the rest of the FileMapHeader. We don't need those fields here.
-};
-
static bool read_jboolean(struct ps_prochandle* ph, uintptr_t addr, jboolean* pvalue) {
jboolean i;
if (ps_pread(ph, (psaddr_t) addr, &i, sizeof(i)) == PS_OK) {
@@ -326,7 +267,7 @@
const char *jvm_name = 0;
if ((jvm_name = strstr(lib->name, LIBJVM_NAME)) != 0) {
char classes_jsa[PATH_MAX];
- struct FileMapHeader header;
+ CDSFileMapHeaderBase header;
int fd = -1;
uintptr_t base = 0, useSharedSpacesAddr = 0;
uintptr_t sharedArchivePathAddrAddr = 0, sharedArchivePathAddr = 0;
@@ -380,34 +321,34 @@
print_debug("opened %s\n", classes_jsa);
}
- // read FileMapHeader from the file
- memset(&header, 0, sizeof(struct FileMapHeader));
- if ((n = read(fd, &header, sizeof(struct FileMapHeader)))
- != sizeof(struct FileMapHeader)) {
+ // read CDSFileMapHeaderBase from the file
+ memset(&header, 0, sizeof(CDSFileMapHeaderBase));
+ if ((n = read(fd, &header, sizeof(CDSFileMapHeaderBase)))
+ != sizeof(CDSFileMapHeaderBase)) {
print_debug("can't read shared archive file map header from %s\n", classes_jsa);
close(fd);
return false;
}
// check file magic
- if (header._magic != 0xf00baba2) {
- print_debug("%s has bad shared archive file magic number 0x%x, expecing 0xf00baba2\n",
- classes_jsa, header._magic);
+ if (header._magic != CDS_ARCHIVE_MAGIC) {
+ print_debug("%s has bad shared archive file magic number 0x%x, expecting 0x%x\n",
+ classes_jsa, header._magic, CDS_ARCHIVE_MAGIC);
close(fd);
return false;
}
// check version
- if (header._version != CURRENT_ARCHIVE_VERSION) {
+ if (header._version != CURRENT_CDS_ARCHIVE_VERSION) {
print_debug("%s has wrong shared archive file version %d, expecting %d\n",
- classes_jsa, header._version, CURRENT_ARCHIVE_VERSION);
+ classes_jsa, header._version, CURRENT_CDS_ARCHIVE_VERSION);
close(fd);
return false;
}
ph->core->classes_jsa_fd = fd;
// add read-only maps from classes.jsa to the list of maps
- for (m = 0; m < NUM_SHARED_MAPS; m++) {
+ for (m = 0; m < NUM_CDS_REGIONS; m++) {
if (header._space[m]._read_only) {
base = (uintptr_t) header._space[m]._addr._base;
// no need to worry about the fractional pages at-the-end.
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/classfile/ClassLoaderData.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/classfile/ClassLoaderData.java Thu Aug 23 11:09:16 2018 -0400
@@ -45,14 +45,14 @@
classLoaderField = type.getAddressField("_class_loader");
nextField = type.getAddressField("_next");
klassesField = new MetadataField(type.getAddressField("_klasses"), 0);
- isAnonymousField = new CIntField(type.getCIntegerField("_is_anonymous"), 0);
+ isUnsafeAnonymousField = new CIntField(type.getCIntegerField("_is_unsafe_anonymous"), 0);
dictionaryField = type.getAddressField("_dictionary");
}
private static AddressField classLoaderField;
private static AddressField nextField;
private static MetadataField klassesField;
- private static CIntField isAnonymousField;
+ private static CIntField isUnsafeAnonymousField;
private static AddressField dictionaryField;
public ClassLoaderData(Address addr) {
@@ -81,8 +81,8 @@
return null;
}
- public boolean getIsAnonymous() {
- return isAnonymousField.getValue(this) != 0;
+ public boolean getisUnsafeAnonymous() {
+ return isUnsafeAnonymousField.getValue(this) != 0;
}
public ClassLoaderData next() {
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/g1/G1CollectedHeap.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/g1/G1CollectedHeap.java Thu Aug 23 11:09:16 2018 -0400
@@ -56,6 +56,8 @@
static private AddressField g1mmField;
// HeapRegionSet _old_set;
static private long oldSetFieldOffset;
+ // HeapRegionSet _archive_set;
+ static private long archiveSetFieldOffset;
// HeapRegionSet _humongous_set;
static private long humongousSetFieldOffset;
@@ -74,6 +76,7 @@
summaryBytesUsedField = type.getCIntegerField("_summary_bytes_used");
g1mmField = type.getAddressField("_g1mm");
oldSetFieldOffset = type.getField("_old_set").getOffset();
+ archiveSetFieldOffset = type.getField("_archive_set").getOffset();
humongousSetFieldOffset = type.getField("_humongous_set").getOffset();
}
@@ -106,6 +109,12 @@
oldSetAddr);
}
+ public HeapRegionSetBase archiveSet() {
+ Address archiveSetAddr = addr.addOffsetTo(archiveSetFieldOffset);
+ return (HeapRegionSetBase) VMObjectFactory.newObject(HeapRegionSetBase.class,
+ archiveSetAddr);
+ }
+
public HeapRegionSetBase humongousSet() {
Address humongousSetAddr = addr.addOffsetTo(humongousSetFieldOffset);
return (HeapRegionSetBase) VMObjectFactory.newObject(HeapRegionSetBase.class,
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/g1/G1MonitoringSupport.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/g1/G1MonitoringSupport.java Thu Aug 23 11:09:16 2018 -0400
@@ -37,18 +37,18 @@
// Mirror class for G1MonitoringSupport.
public class G1MonitoringSupport extends VMObject {
- // size_t _eden_committed;
- static private CIntegerField edenCommittedField;
- // size_t _eden_used;
- static private CIntegerField edenUsedField;
- // size_t _survivor_committed;
- static private CIntegerField survivorCommittedField;
- // size_t _survivor_used;
- static private CIntegerField survivorUsedField;
- // size_t _old_committed;
- static private CIntegerField oldCommittedField;
- // size_t _old_used;
- static private CIntegerField oldUsedField;
+ // size_t _eden_space_committed;
+ static private CIntegerField edenSpaceCommittedField;
+ // size_t _eden_space_used;
+ static private CIntegerField edenSpaceUsedField;
+ // size_t _survivor_space_committed;
+ static private CIntegerField survivorSpaceCommittedField;
+ // size_t _survivor_space_used;
+ static private CIntegerField survivorSpaceUsedField;
+ // size_t _old_gen_committed;
+ static private CIntegerField oldGenCommittedField;
+ // size_t _old_gen_used;
+ static private CIntegerField oldGenUsedField;
static {
VM.registerVMInitializedObserver(new Observer() {
@@ -61,44 +61,44 @@
static private synchronized void initialize(TypeDataBase db) {
Type type = db.lookupType("G1MonitoringSupport");
- edenCommittedField = type.getCIntegerField("_eden_committed");
- edenUsedField = type.getCIntegerField("_eden_used");
- survivorCommittedField = type.getCIntegerField("_survivor_committed");
- survivorUsedField = type.getCIntegerField("_survivor_used");
- oldCommittedField = type.getCIntegerField("_old_committed");
- oldUsedField = type.getCIntegerField("_old_used");
+ edenSpaceCommittedField = type.getCIntegerField("_eden_space_committed");
+ edenSpaceUsedField = type.getCIntegerField("_eden_space_used");
+ survivorSpaceCommittedField = type.getCIntegerField("_survivor_space_committed");
+ survivorSpaceUsedField = type.getCIntegerField("_survivor_space_used");
+ oldGenCommittedField = type.getCIntegerField("_old_gen_committed");
+ oldGenUsedField = type.getCIntegerField("_old_gen_used");
}
- public long edenCommitted() {
- return edenCommittedField.getValue(addr);
+ public long edenSpaceCommitted() {
+ return edenSpaceCommittedField.getValue(addr);
}
- public long edenUsed() {
- return edenUsedField.getValue(addr);
+ public long edenSpaceUsed() {
+ return edenSpaceUsedField.getValue(addr);
}
- public long edenRegionNum() {
- return edenUsed() / HeapRegion.grainBytes();
+ public long edenSpaceRegionNum() {
+ return edenSpaceUsed() / HeapRegion.grainBytes();
}
- public long survivorCommitted() {
- return survivorCommittedField.getValue(addr);
+ public long survivorSpaceCommitted() {
+ return survivorSpaceCommittedField.getValue(addr);
}
- public long survivorUsed() {
- return survivorUsedField.getValue(addr);
+ public long survivorSpaceUsed() {
+ return survivorSpaceUsedField.getValue(addr);
}
- public long survivorRegionNum() {
- return survivorUsed() / HeapRegion.grainBytes();
+ public long survivorSpaceRegionNum() {
+ return survivorSpaceUsed() / HeapRegion.grainBytes();
}
- public long oldCommitted() {
- return oldCommittedField.getValue(addr);
+ public long oldGenCommitted() {
+ return oldGenCommittedField.getValue(addr);
}
- public long oldUsed() {
- return oldUsedField.getValue(addr);
+ public long oldGenUsed() {
+ return oldGenUsedField.getValue(addr);
}
public G1MonitoringSupport(Address addr) {
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/FileMapInfo.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/FileMapInfo.java Thu Aug 23 11:09:16 2018 -0400
@@ -63,13 +63,13 @@
headerValue = headerAddress.getAddressAt(0);
// FileMapHeader
- type = db.lookupType("FileMapInfo::FileMapHeader");
+ type = db.lookupType("FileMapHeader");
AddressField spaceField = type.getAddressField("_space[0]");
Address spaceValue = headerValue.addOffsetTo(type.getField("_space[0]").getOffset());
mdSpaceValue = spaceValue.addOffsetTo(3 * spaceField.getSize());
// SpaceInfo
- type = db.lookupType("FileMapInfo::FileMapHeader::space_info");
+ type = db.lookupType("CDSFileMapRegion");
long mdRegionBaseAddressOffset = type.getField("_addr._base").getOffset();
mdRegionBaseAddress = (mdSpaceValue.addOffsetTo(mdRegionBaseAddressOffset)).getAddressAt(0);
long mdRegionSizeOffset = type.getField("_used").getOffset();
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java Thu Aug 23 11:09:16 2018 -0400
@@ -69,7 +69,7 @@
private static int MISC_REWRITTEN;
private static int MISC_HAS_NONSTATIC_FIELDS;
private static int MISC_SHOULD_VERIFY_CLASS;
- private static int MISC_IS_ANONYMOUS;
+ private static int MISC_IS_UNSAFE_ANONYMOUS;
private static int MISC_IS_CONTENDED;
private static int MISC_HAS_NONSTATIC_CONCRETE_METHODS;
private static int MISC_DECLARES_NONSTATIC_CONCRETE_METHODS;
@@ -133,7 +133,7 @@
MISC_REWRITTEN = db.lookupIntConstant("InstanceKlass::_misc_rewritten").intValue();
MISC_HAS_NONSTATIC_FIELDS = db.lookupIntConstant("InstanceKlass::_misc_has_nonstatic_fields").intValue();
MISC_SHOULD_VERIFY_CLASS = db.lookupIntConstant("InstanceKlass::_misc_should_verify_class").intValue();
- MISC_IS_ANONYMOUS = db.lookupIntConstant("InstanceKlass::_misc_is_anonymous").intValue();
+ MISC_IS_UNSAFE_ANONYMOUS = db.lookupIntConstant("InstanceKlass::_misc_is_unsafe_anonymous").intValue();
MISC_IS_CONTENDED = db.lookupIntConstant("InstanceKlass::_misc_is_contended").intValue();
MISC_HAS_NONSTATIC_CONCRETE_METHODS = db.lookupIntConstant("InstanceKlass::_misc_has_nonstatic_concrete_methods").intValue();
MISC_DECLARES_NONSTATIC_CONCRETE_METHODS = db.lookupIntConstant("InstanceKlass::_misc_declares_nonstatic_concrete_methods").intValue();
@@ -281,7 +281,7 @@
if (isInterface()) {
size += wordLength;
}
- if (isAnonymous()) {
+ if (isUnsafeAnonymous()) {
size += wordLength;
}
if (hasStoredFingerprint()) {
@@ -294,8 +294,8 @@
return (int) miscFlags.getValue(this);
}
- public boolean isAnonymous() {
- return (getMiscFlags() & MISC_IS_ANONYMOUS) != 0;
+ public boolean isUnsafeAnonymous() {
+ return (getMiscFlags() & MISC_IS_UNSAFE_ANONYMOUS) != 0;
}
public static boolean shouldStoreFingerprint() {
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/HeapSummary.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/HeapSummary.java Thu Aug 23 11:09:16 2018 -0400
@@ -225,20 +225,21 @@
public void printG1HeapSummary(G1CollectedHeap g1h) {
G1MonitoringSupport g1mm = g1h.g1mm();
- long edenRegionNum = g1mm.edenRegionNum();
- long survivorRegionNum = g1mm.survivorRegionNum();
+ long edenSpaceRegionNum = g1mm.edenSpaceRegionNum();
+ long survivorSpaceRegionNum = g1mm.survivorSpaceRegionNum();
HeapRegionSetBase oldSet = g1h.oldSet();
+ HeapRegionSetBase archiveSet = g1h.archiveSet();
HeapRegionSetBase humongousSet = g1h.humongousSet();
- long oldRegionNum = oldSet.length() + humongousSet.length();
+ long oldGenRegionNum = oldSet.length() + archiveSet.length() + humongousSet.length();
printG1Space("G1 Heap:", g1h.n_regions(),
g1h.used(), g1h.capacity());
System.out.println("G1 Young Generation:");
- printG1Space("Eden Space:", edenRegionNum,
- g1mm.edenUsed(), g1mm.edenCommitted());
- printG1Space("Survivor Space:", survivorRegionNum,
- g1mm.survivorUsed(), g1mm.survivorCommitted());
- printG1Space("G1 Old Generation:", oldRegionNum,
- g1mm.oldUsed(), g1mm.oldCommitted());
+ printG1Space("Eden Space:", edenSpaceRegionNum,
+ g1mm.edenSpaceUsed(), g1mm.edenSpaceCommitted());
+ printG1Space("Survivor Space:", survivorSpaceRegionNum,
+ g1mm.survivorSpaceUsed(), g1mm.survivorSpaceCommitted());
+ printG1Space("G1 Old Generation:", oldGenRegionNum,
+ g1mm.oldGenUsed(), g1mm.oldGenCommitted());
}
private void printG1Space(String spaceName, long regionNum,
--- a/src/jdk.hotspot.agent/solaris/native/libsaproc/saproc.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.hotspot.agent/solaris/native/libsaproc/saproc.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -31,6 +31,7 @@
#include <stdarg.h>
#include <stdlib.h>
#include <errno.h>
+#include "cds.h"
#define CHECK_EXCEPTION_(value) if(env->ExceptionOccurred()) { return value; }
#define CHECK_EXCEPTION if(env->ExceptionOccurred()) { return;}
@@ -173,7 +174,7 @@
int classes_jsa_fd = env->GetIntField(this_obj, classes_jsa_fd_ID);
if (classes_jsa_fd != -1) {
close(classes_jsa_fd);
- struct FileMapHeader* pheader = (struct FileMapHeader*) env->GetLongField(this_obj, p_file_map_header_ID);
+ CDSFileMapHeaderBase* pheader = (CDSFileMapHeaderBase*) env->GetLongField(this_obj, p_file_map_header_ID);
if (pheader != NULL) {
free(pheader);
}
@@ -484,67 +485,13 @@
return(fill_cframe_list(cd, regs, argc, argv));
}
-// part of the class sharing workaround
-
-// FIXME: !!HACK ALERT!!
-
-// The format of sharing achive file header is needed to read shared heap
-// file mappings. For now, I am hard coding portion of FileMapHeader here.
-// Refer to filemap.hpp.
-
-// FileMapHeader describes the shared space data in the file to be
-// mapped. This structure gets written to a file. It is not a class, so
-// that the compilers don't add any compiler-private data to it.
-
-const int NUM_SHARED_MAPS = 9;
-
-// Refer to FileMapInfo::_current_version in filemap.hpp
-const int CURRENT_ARCHIVE_VERSION = 3;
-
-typedef unsigned char* address;
-typedef uintptr_t uintx;
-typedef intptr_t intx;
-
-struct FileMapHeader {
- int _magic; // identify file type.
- int _crc; // header crc checksum.
- int _version; // (from enum, above.)
- size_t _alignment; // how shared archive should be aligned
- int _obj_alignment; // value of ObjectAlignmentInBytes
- address _narrow_oop_base; // compressed oop encoding base
- int _narrow_oop_shift; // compressed oop encoding shift
- bool _compact_strings; // value of CompactStrings
- uintx _max_heap_size; // java max heap size during dumping
- int _narrow_oop_mode; // compressed oop encoding mode
- int _narrow_klass_shift; // save narrow klass base and shift
- address _narrow_klass_base;
- char* _misc_data_patching_start;
- char* _read_only_tables_start;
- address _cds_i2i_entry_code_buffers;
- size_t _cds_i2i_entry_code_buffers_size;
- size_t _core_spaces_size; // number of bytes allocated by the core spaces
- // (mc, md, ro, rw and od).
-
-
- struct space_info {
- int _crc; // crc checksum of the current space
- size_t _file_offset; // sizeof(this) rounded to vm page size
- union {
- char* _base; // copy-on-write base address
- intx _offset; // offset from the compressed oop encoding base, only used
- // by archive heap space
- } _addr;
- size_t _used; // for setting space top on read
- // 4991491 NOTICE These are C++ bool's in filemap.hpp and must match up with
- // the C type matching the C++ bool type on any given platform.
- // We assume the corresponding C type is char but licensees
- // may need to adjust the type of these fields.
- char _read_only; // read only space?
- char _allow_exec; // executable code in space?
- } _space[NUM_SHARED_MAPS];
-
-// Ignore the rest of the FileMapHeader. We don't need those fields here.
-};
+//---------------------------------------------------------------
+// Part of the class sharing workaround:
+//
+// With class sharing, pages are mapped from classes.jsa file.
+// The read-only class sharing pages are mapped as MAP_SHARED,
+// PROT_READ pages. These pages are not dumped into core dump.
+// With this workaround, these pages are read from classes.jsa.
static bool
read_jboolean(struct ps_prochandle* ph, psaddr_t addr, jboolean* pvalue) {
@@ -662,16 +609,16 @@
}
// parse classes.jsa
- struct FileMapHeader* pheader = (struct FileMapHeader*) malloc(sizeof(struct FileMapHeader));
+ CDSFileMapHeaderBase* pheader = (CDSFileMapHeaderBase*) malloc(sizeof(CDSFileMapHeaderBase));
if (pheader == NULL) {
close(fd);
THROW_NEW_DEBUGGER_EXCEPTION_("can't allocate memory for shared file map header", 1);
}
- memset(pheader, 0, sizeof(struct FileMapHeader));
- // read FileMapHeader
- size_t n = read(fd, pheader, sizeof(struct FileMapHeader));
- if (n != sizeof(struct FileMapHeader)) {
+ memset(pheader, 0, sizeof(CDSFileMapHeaderBase));
+ // read CDSFileMapHeaderBase
+ size_t n = read(fd, pheader, sizeof(CDSFileMapHeaderBase));
+ if (n != sizeof(CDSFileMapHeaderBase)) {
char errMsg[ERR_MSG_SIZE];
sprintf(errMsg, "unable to read shared archive file map header from %s", classes_jsa);
close(fd);
@@ -680,27 +627,27 @@
}
// check file magic
- if (pheader->_magic != 0xf00baba2) {
+ if (pheader->_magic != CDS_ARCHIVE_MAGIC) {
char errMsg[ERR_MSG_SIZE];
- sprintf(errMsg, "%s has bad shared archive magic 0x%x, expecting 0xf00baba2",
- classes_jsa, pheader->_magic);
+ sprintf(errMsg, "%s has bad shared archive magic 0x%x, expecting 0x%x",
+ classes_jsa, pheader->_magic, CDS_ARCHIVE_MAGIC);
close(fd);
free(pheader);
THROW_NEW_DEBUGGER_EXCEPTION_(errMsg, 1);
}
// check version
- if (pheader->_version != CURRENT_ARCHIVE_VERSION) {
+ if (pheader->_version != CURRENT_CDS_ARCHIVE_VERSION) {
char errMsg[ERR_MSG_SIZE];
sprintf(errMsg, "%s has wrong shared archive version %d, expecting %d",
- classes_jsa, pheader->_version, CURRENT_ARCHIVE_VERSION);
+ classes_jsa, pheader->_version, CURRENT_CDS_ARCHIVE_VERSION);
close(fd);
free(pheader);
THROW_NEW_DEBUGGER_EXCEPTION_(errMsg, 1);
}
if (_libsaproc_debug) {
- for (int m = 0; m < NUM_SHARED_MAPS; m++) {
+ for (int m = 0; m < NUM_CDS_REGIONS; m++) {
print_debug("shared file offset %d mapped at 0x%lx, size = %ld, read only? = %d\n",
pheader->_space[m]._file_offset, pheader->_space[m]._addr._base,
pheader->_space[m]._used, pheader->_space[m]._read_only);
@@ -1091,10 +1038,10 @@
if (classes_jsa_fd != -1 && address != (jlong)0) {
print_debug("read failed at 0x%lx, attempting shared heap area\n", (long) address);
- struct FileMapHeader* pheader = (struct FileMapHeader*) env->GetLongField(this_obj, p_file_map_header_ID);
+ CDSFileMapHeaderBase* pheader = (CDSFileMapHeaderBase*) env->GetLongField(this_obj, p_file_map_header_ID);
// walk through the shared mappings -- we just have 9 of them.
// so, linear walking is okay.
- for (int m = 0; m < NUM_SHARED_MAPS; m++) {
+ for (int m = 0; m < NUM_CDS_REGIONS; m++) {
// We can skip the non-read-only maps. These are mapped as MAP_PRIVATE
// and hence will be read by libproc. Besides, the file copy may be
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java Thu Aug 23 11:09:16 2018 -0400
@@ -522,7 +522,7 @@
return lookupType(cpi, opcode);
case String:
/*
- * Normally, we would expect a String here, but anonymous classes can have
+ * Normally, we would expect a String here, but unsafe anonymous classes can have
* "pseudo strings" (arbitrary live objects) patched into a String entry. Such
* entries do not have a symbol in the constant pool slot.
*/
@@ -647,20 +647,22 @@
}
/*
- * Converts a raw index from the bytecodes to a constant pool index
- * (not a cache index).
+ * Converts a raw index from the bytecodes to a constant pool index (not a cache index).
*
* @param rawIndex index from the bytecode
+ *
* @param opcode bytecode to convert the index for
+ *
* @return constant pool index
*/
- public int rawIndexToConstantPoolIndex(int index, int opcode) {
- if (isInvokedynamicIndex(index)) {
+ public int rawIndexToConstantPoolIndex(int rawIndex, int opcode) {
+ int index;
+ if (isInvokedynamicIndex(rawIndex)) {
assert opcode == Bytecodes.INVOKEDYNAMIC;
- index = decodeInvokedynamicIndex(index) + config().constantPoolCpCacheIndexTag;
+ index = decodeInvokedynamicIndex(rawIndex) + config().constantPoolCpCacheIndexTag;
} else {
assert opcode != Bytecodes.INVOKEDYNAMIC;
- index = rawIndexToConstantPoolCacheIndex(index, opcode);
+ index = rawIndexToConstantPoolCacheIndex(rawIndex, opcode);
}
return compilerToVM().constantPoolRemapInstructionOperandFromCache(this, index);
}
@@ -772,19 +774,20 @@
}
/**
- * Check for a resolved dynamic adapter method at the specified index,
- * resulting from either a resolved invokedynamic or invokevirtual on a signature polymorphic
- * MethodHandle method (HotSpot invokehandle).
+ * Check for a resolved dynamic adapter method at the specified index, resulting from either a
+ * resolved invokedynamic or invokevirtual on a signature polymorphic MethodHandle method
+ * (HotSpot invokehandle).
*
* @param cpi the constant pool index
* @param opcode the opcode of the instruction for which the lookup is being performed
- * @return {@code true} if a signature polymorphic method reference was found, otherwise {@code false}
+ * @return {@code true} if a signature polymorphic method reference was found, otherwise
+ * {@code false}
*/
public boolean isResolvedDynamicInvoke(int cpi, int opcode) {
if (Bytecodes.isInvokeHandleAlias(opcode)) {
final int methodRefCacheIndex = rawIndexToConstantPoolCacheIndex(cpi, opcode);
assert checkTag(compilerToVM().constantPoolRemapInstructionOperandFromCache(this, methodRefCacheIndex), JVM_CONSTANT.MethodRef);
- int op = compilerToVM().isResolvedInvokeHandleInPool(this, methodRefCacheIndex);
+ int op = compilerToVM().isResolvedInvokeHandleInPool(this, methodRefCacheIndex);
return op == opcode;
}
return false;
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPoolObject.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPoolObject.java Thu Aug 23 11:09:16 2018 -0400
@@ -23,11 +23,10 @@
package jdk.vm.ci.hotspot;
import jdk.vm.ci.meta.JavaConstant;
-import jdk.vm.ci.meta.ResolvedJavaType;
/**
- * Represents a constant that was retrieved from a constant pool.
- * Used to keep track of the constant pool slot for the constant.
+ * Represents a constant that was retrieved from a constant pool. Used to keep track of the constant
+ * pool slot for the constant.
*/
public final class HotSpotConstantPoolObject extends HotSpotObjectConstantImpl {
@@ -36,14 +35,19 @@
}
public static JavaConstant forObject(HotSpotResolvedObjectType type, int cpi, JavaConstant object) {
- return forObject(type, cpi, ((HotSpotObjectConstantImpl)object).object());
+ return forObject(type, cpi, ((HotSpotObjectConstantImpl) object).object());
}
private final HotSpotResolvedObjectType type;
private final int cpi;
- public HotSpotResolvedObjectType getCpType() { return type; }
- public int getCpi() { return cpi; }
+ public HotSpotResolvedObjectType getCpType() {
+ return type;
+ }
+
+ public int getCpi() {
+ return cpi;
+ }
HotSpotConstantPoolObject(HotSpotResolvedObjectType type, int cpi, Object object) {
super(object, false);
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIMetaAccessContext.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIMetaAccessContext.java Thu Aug 23 11:09:16 2018 -0400
@@ -145,7 +145,7 @@
}
}
- private final ClassValue<WeakReference<ResolvedJavaType>> resolvedJavaType = new ClassValue<WeakReference<ResolvedJavaType>>() {
+ private final ClassValue<WeakReference<ResolvedJavaType>> resolvedJavaType = new ClassValue<>() {
@Override
protected WeakReference<ResolvedJavaType> computeValue(Class<?> type) {
return new WeakReference<>(createClass(type));
@@ -164,10 +164,9 @@
javaType = type.get();
if (javaType == null) {
/*
- * If the referent has become null, clear out the current value
- * and let computeValue above create a new value. Reload the
- * value in a loop because in theory the WeakReference referent
- * can be reclaimed at any point.
+ * If the referent has become null, clear out the current value and let computeValue
+ * above create a new value. Reload the value in a loop because in theory the
+ * WeakReference referent can be reclaimed at any point.
*/
resolvedJavaType.remove(javaClass);
}
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java Thu Aug 23 11:09:16 2018 -0400
@@ -363,44 +363,44 @@
*/
public Predicate<ResolvedJavaType> getIntrinsificationTrustPredicate(Class<?>... compilerLeafClasses) {
if (intrinsificationTrustPredicate == null) {
- intrinsificationTrustPredicate = new Predicate<ResolvedJavaType>() {
- @Override
- public boolean test(ResolvedJavaType type) {
- if (type instanceof HotSpotResolvedJavaType) {
- Class<?> mirror = getMirror((HotSpotResolvedJavaType) type);
- Module module = mirror.getModule();
- return getTrustedModules().contains(module);
- } else {
- return false;
- }
+ intrinsificationTrustPredicate = new Predicate<>() {
+ @Override
+ public boolean test(ResolvedJavaType type) {
+ if (type instanceof HotSpotResolvedJavaType) {
+ Class<?> mirror = getMirror(type);
+ Module module = mirror.getModule();
+ return getTrustedModules().contains(module);
+ } else {
+ return false;
}
+ }
- private volatile Set<Module> trustedModules;
+ private volatile Set<Module> trustedModules;
- private Set<Module> getTrustedModules() {
- Set<Module> modules = trustedModules;
- if (modules == null) {
- modules = new HashSet<>();
- for (Class<?> compilerConfiguration : compilerLeafClasses) {
- Module compilerConfigurationModule = compilerConfiguration.getModule();
- if (compilerConfigurationModule.getDescriptor().isAutomatic()) {
- throw new IllegalArgumentException(String.format("The module '%s' defining the Graal compiler configuration class '%s' must not be an automatic module",
- compilerConfigurationModule.getName(), compilerConfiguration.getClass().getName()));
- }
- modules.add(compilerConfigurationModule);
- for (Requires require : compilerConfigurationModule.getDescriptor().requires()) {
- for (Module module : compilerConfigurationModule.getLayer().modules()) {
- if (module.getName().equals(require.name())) {
- modules.add(module);
- }
+ private Set<Module> getTrustedModules() {
+ Set<Module> modules = trustedModules;
+ if (modules == null) {
+ modules = new HashSet<>();
+ for (Class<?> compilerConfiguration : compilerLeafClasses) {
+ Module compilerConfigurationModule = compilerConfiguration.getModule();
+ if (compilerConfigurationModule.getDescriptor().isAutomatic()) {
+ throw new IllegalArgumentException(String.format("The module '%s' defining the Graal compiler configuration class '%s' must not be an automatic module",
+ compilerConfigurationModule.getName(), compilerConfiguration.getClass().getName()));
+ }
+ modules.add(compilerConfigurationModule);
+ for (Requires require : compilerConfigurationModule.getDescriptor().requires()) {
+ for (Module module : compilerConfigurationModule.getLayer().modules()) {
+ if (module.getName().equals(require.name())) {
+ modules.add(module);
}
}
}
- trustedModules = modules;
}
- return modules;
+ trustedModules = modules;
}
- };
+ return modules;
+ }
+ };
}
return intrinsificationTrustPredicate;
}
@@ -413,6 +413,7 @@
* does not support mapping {@link ResolvedJavaType} instances to {@link Class}
* instances
*/
+ @SuppressWarnings("static-method")
public Class<?> getMirror(ResolvedJavaType type) {
return ((HotSpotResolvedJavaType) type).mirror();
}
@@ -654,6 +655,7 @@
*
* @return the offset in bytes
*/
+ @SuppressWarnings("static-method")
public int getArrayBaseOffset(JavaKind kind) {
switch (kind) {
case Boolean:
@@ -685,6 +687,7 @@
*
* @return the scale in order to convert the index into a byte offset
*/
+ @SuppressWarnings("static-method")
public int getArrayIndexScale(JavaKind kind) {
switch (kind) {
case Boolean:
@@ -759,6 +762,7 @@
* {@code clazz} is already linked or the SVM JVMCI library does not contain a
* JNI-compliant symbol for a native method in {@code clazz}
*/
+ @SuppressWarnings({"static-method", "unused"})
public void registerNativeMethods(Class<?> clazz) {
throw new UnsatisfiedLinkError("SVM library is not available");
}
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java Thu Aug 23 11:09:16 2018 -0400
@@ -191,7 +191,7 @@
}
try {
return holder.mirror().getDeclaredField(getName());
- } catch (NoSuchFieldException | NoClassDefFoundError e) {
+ } catch (NoSuchFieldException e) {
return null;
}
}
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java Thu Aug 23 11:09:16 2018 -0400
@@ -73,7 +73,13 @@
private final HotSpotSignature signature;
private HotSpotMethodData methodData;
private byte[] code;
- private Executable toJavaCache;
+
+ /**
+ * Cache for {@link #toJava()}. Set to {@link #signature} when resolving reflection object fails
+ * due to reflection filtering (see {@code Reflection.fieldFilterMap} and
+ * {@code Reflection.methodFilterMap}).
+ */
+ private Object toJavaCache;
/**
* Only 30% of {@link HotSpotResolvedJavaMethodImpl}s have their name accessed so compute it
@@ -322,7 +328,8 @@
}
/**
- * Sets flags on {@code method} indicating that it should never be inlined or compiled by the VM.
+ * Sets flags on {@code method} indicating that it should never be inlined or compiled by the
+ * VM.
*/
@Override
public void setNotInlinableOrCompilable() {
@@ -581,25 +588,33 @@
private Executable toJava() {
if (toJavaCache != null) {
- return toJavaCache;
+ if (toJavaCache == signature) {
+ return null;
+ }
+ return (Executable) toJavaCache;
}
- try {
- Class<?>[] parameterTypes = signatureToTypes();
- Class<?> returnType = ((HotSpotResolvedJavaType) getSignature().getReturnType(holder).resolve(holder)).mirror();
+ Class<?>[] parameterTypes = signatureToTypes();
+ Class<?> returnType = ((HotSpotResolvedJavaType) getSignature().getReturnType(holder).resolve(holder)).mirror();
- Executable result;
- if (isConstructor()) {
+ Executable result;
+ if (isConstructor()) {
+ try {
result = holder.mirror().getDeclaredConstructor(parameterTypes);
- } else {
- // Do not use Method.getDeclaredMethod() as it can return a bridge method
- // when this.isBridge() is false and vice versa.
- result = searchMethods(holder.mirror().getDeclaredMethods(), getName(), returnType, parameterTypes);
+ } catch (NoSuchMethodException e) {
+ toJavaCache = signature;
+ return null;
}
- toJavaCache = result;
- return result;
- } catch (NoSuchMethodException | NoClassDefFoundError e) {
- return null;
+ } else {
+ // Do not use Method.getDeclaredMethod() as it can return a bridge method
+ // when this.isBridge() is false and vice versa.
+ result = searchMethods(holder.mirror().getDeclaredMethods(), getName(), returnType, parameterTypes);
+ if (result == null) {
+ toJavaCache = signature;
+ return null;
+ }
}
+ toJavaCache = result;
+ return result;
}
@Override
@@ -746,7 +761,7 @@
* read the JVM_ACC_IS_OBSOLETE bit (or anything else) via the raw pointer as obsoleted methods
* are subject to clean up and deletion (see InstanceKlass::purge_previous_versions_internal).
*/
- private static final ClassValue<Map<Long, SpeculationLog>> SpeculationLogs = new ClassValue<Map<Long, SpeculationLog>>() {
+ private static final ClassValue<Map<Long, SpeculationLog>> SpeculationLogs = new ClassValue<>() {
@Override
protected Map<Long, SpeculationLog> computeValue(java.lang.Class<?> type) {
return new HashMap<>(4);
@@ -796,6 +811,7 @@
return compilerToVM().hasCompiledCodeForOSR(this, entryBCI, level);
}
+ @Override
public int methodIdnum() {
return UNSAFE.getChar(getConstMethod() + config().constMethodMethodIdnumOffset);
}
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,6 @@
@Override
ResolvedJavaMethod getClassInitializer();
- boolean isAnonymous();
+ boolean isUnsafeAnonymous();
}
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -984,8 +984,9 @@
return UNSAFE.getInt(getMetaspaceKlass() + config().instanceKlassMiscFlagsOffset);
}
- public boolean isAnonymous() {
- return (getMiscFlags() & config().instanceKlassMiscIsAnonymous) != 0;
+ @Override
+ public boolean isUnsafeAnonymous() {
+ return (getMiscFlags() & config().instanceKlassMiscIsUnsafeAnonymous) != 0;
}
}
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSignature.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSignature.java Thu Aug 23 11:09:16 2018 -0400
@@ -25,7 +25,6 @@
import java.util.ArrayList;
import java.util.List;
-import jdk.vm.ci.common.JVMCIError;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.JavaType;
import jdk.vm.ci.meta.ResolvedJavaType;
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +100,7 @@
final int instanceKlassStateLinked = getConstant("InstanceKlass::linked", Integer.class);
final int instanceKlassStateFullyInitialized = getConstant("InstanceKlass::fully_initialized", Integer.class);
- final int instanceKlassMiscIsAnonymous = getConstant("InstanceKlass::_misc_is_anonymous", Integer.class);
+ final int instanceKlassMiscIsUnsafeAnonymous = getConstant("InstanceKlass::_misc_is_unsafe_anonymous", Integer.class);
final int arrayU1LengthOffset = getFieldOffset("Array<int>::_length", Integer.class, "int");
final int arrayU1DataOffset = getFieldOffset("Array<u1>::_data", Integer.class);
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/Assumptions.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/Assumptions.java Thu Aug 23 11:09:16 2018 -0400
@@ -98,7 +98,7 @@
}
/**
- * An assumption that a given class has no subclasses implementing {@link Object#finalize()}).
+ * An assumption that a given class has no subclasses implementing {@code Object#finalize()}).
*/
public static final class NoFinalizableSubclass extends Assumption {
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.services/.checkstyle_checks.xml Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.services/.checkstyle_checks.xml Thu Aug 23 11:09:16 2018 -0400
@@ -9,7 +9,6 @@
<property name="severity" value="error"/>
<module name="TreeWalker">
<property name="tabWidth" value="4"/>
- <module name="FileContentsHolder"/>
<module name="JavadocStyle">
<property name="checkHtml" value="false"/>
</module>
@@ -132,6 +131,66 @@
<property name="format" value="new (Hashtable|Vector|Stack|StringBuffer)[^\w]"/>
<property name="message" value="Don't use old synchronized collection classes"/>
</module>
+ <module name="SuppressionCommentFilter">
+ <property name="offCommentFormat" value="Checkstyle: stop constant name check"/>
+ <property name="onCommentFormat" value="Checkstyle: resume constant name check"/>
+ <property name="checkFormat" value="ConstantNameCheck"/>
+ <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Allow non-conforming constant names"/>
+ </module>
+ <module name="SuppressionCommentFilter">
+ <property name="offCommentFormat" value="Checkstyle: stop method name check"/>
+ <property name="onCommentFormat" value="Checkstyle: resume method name check"/>
+ <property name="checkFormat" value="MethodName"/>
+ <property name="checkC" value="false"/>
+ <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable method name checks"/>
+ </module>
+ <module name="SuppressionCommentFilter">
+ <property name="offCommentFormat" value="CheckStyle: stop parameter assignment check"/>
+ <property name="onCommentFormat" value="CheckStyle: resume parameter assignment check"/>
+ <property name="checkFormat" value="ParameterAssignment"/>
+ <property name="checkC" value="false"/>
+ <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable Parameter Assignment"/>
+ </module>
+ <module name="SuppressionCommentFilter">
+ <property name="offCommentFormat" value="Checkstyle: stop final variable check"/>
+ <property name="onCommentFormat" value="Checkstyle: resume final variable check"/>
+ <property name="checkFormat" value="FinalLocalVariable"/>
+ <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable final variable checks"/>
+ </module>
+ <module name="SuppressionCommentFilter">
+ <property name="offCommentFormat" value="Checkstyle: stop"/>
+ <property name="onCommentFormat" value="Checkstyle: resume"/>
+ <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable all checks"/>
+ </module>
+ <module name="SuppressionCommentFilter">
+ <property name="offCommentFormat" value="CheckStyle: stop inner assignment check"/>
+ <property name="onCommentFormat" value="CheckStyle: resume inner assignment check"/>
+ <property name="checkFormat" value="InnerAssignment"/>
+ <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable inner assignment checks"/>
+ </module>
+ <module name="SuppressionCommentFilter">
+ <property name="offCommentFormat" value="Checkstyle: stop field name check"/>
+ <property name="onCommentFormat" value="Checkstyle: resume field name check"/>
+ <property name="checkFormat" value="MemberName"/>
+ <property name="checkC" value="false"/>
+ <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable field name checks"/>
+ </module>
+ <module name="SuppressionCommentFilter">
+ <property name="offCommentFormat" value="CheckStyle: stop header check"/>
+ <property name="onCommentFormat" value="CheckStyle: resume header check"/>
+ <property name="checkFormat" value=".*Header"/>
+ <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable header checks"/>
+ </module>
+ <module name="SuppressionCommentFilter">
+ <property name="offCommentFormat" value="CheckStyle: stop line length check"/>
+ <property name="onCommentFormat" value="CheckStyle: resume line length check"/>
+ <property name="checkFormat" value="LineLength"/>
+ </module>
+ <module name="SuppressionCommentFilter">
+ <property name="offCommentFormat" value="CheckStyle: start generated"/>
+ <property name="onCommentFormat" value="CheckStyle: stop generated"/>
+ <property name="checkFormat" value=".*Name|.*LineLength|.*Header"/>
+ </module>
</module>
<module name="RegexpHeader">
<property name="header" value="/\*\n \* Copyright \(c\) (20[0-9][0-9], )?20[0-9][0-9], Oracle and/or its affiliates. All rights reserved.\n \* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\n \*\n \* This code is free software; you can redistribute it and/or modify it\n \* under the terms of the GNU General Public License version 2 only, as\n \* published by the Free Software Foundation.\n \*\n \* This code is distributed in the hope that it will be useful, but WITHOUT\n \* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n \* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License\n \* version 2 for more details \(a copy is included in the LICENSE file that\n \* accompanied this code\).\n \*\n \* You should have received a copy of the GNU General Public License version\n \* 2 along with this work; if not, write to the Free Software Foundation,\n \* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\n \*\n \* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA\n \* or visit www.oracle.com if you need additional information or have any\n \* questions.\n \*/\n"/>
@@ -145,69 +204,9 @@
<property name="lineSeparator" value="lf"/>
</module>
<module name="Translation"/>
- <module name="SuppressionCommentFilter">
- <property name="offCommentFormat" value="Checkstyle: stop constant name check"/>
- <property name="onCommentFormat" value="Checkstyle: resume constant name check"/>
- <property name="checkFormat" value="ConstantNameCheck"/>
- <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Allow non-conforming constant names"/>
- </module>
- <module name="SuppressionCommentFilter">
- <property name="offCommentFormat" value="Checkstyle: stop method name check"/>
- <property name="onCommentFormat" value="Checkstyle: resume method name check"/>
- <property name="checkFormat" value="MethodName"/>
- <property name="checkC" value="false"/>
- <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable method name checks"/>
- </module>
- <module name="SuppressionCommentFilter">
- <property name="offCommentFormat" value="CheckStyle: stop parameter assignment check"/>
- <property name="onCommentFormat" value="CheckStyle: resume parameter assignment check"/>
- <property name="checkFormat" value="ParameterAssignment"/>
- <property name="checkC" value="false"/>
- <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable Parameter Assignment"/>
- </module>
- <module name="SuppressionCommentFilter">
- <property name="offCommentFormat" value="Checkstyle: stop final variable check"/>
- <property name="onCommentFormat" value="Checkstyle: resume final variable check"/>
- <property name="checkFormat" value="FinalLocalVariable"/>
- <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable final variable checks"/>
- </module>
- <module name="SuppressionCommentFilter">
- <property name="offCommentFormat" value="Checkstyle: stop"/>
- <property name="onCommentFormat" value="Checkstyle: resume"/>
- <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable all checks"/>
- </module>
- <module name="SuppressionCommentFilter">
- <property name="offCommentFormat" value="CheckStyle: stop inner assignment check"/>
- <property name="onCommentFormat" value="CheckStyle: resume inner assignment check"/>
- <property name="checkFormat" value="InnerAssignment"/>
- <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable inner assignment checks"/>
- </module>
- <module name="SuppressionCommentFilter">
- <property name="offCommentFormat" value="Checkstyle: stop field name check"/>
- <property name="onCommentFormat" value="Checkstyle: resume field name check"/>
- <property name="checkFormat" value="MemberName"/>
- <property name="checkC" value="false"/>
- <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable field name checks"/>
- </module>
<module name="RegexpMultiline">
<metadata name="net.sf.eclipsecs.core.comment" value="illegal Windows line ending"/>
<property name="format" value="\r\n"/>
<property name="message" value="illegal Windows line ending"/>
</module>
- <module name="SuppressionCommentFilter">
- <property name="offCommentFormat" value="CheckStyle: stop header check"/>
- <property name="onCommentFormat" value="CheckStyle: resume header check"/>
- <property name="checkFormat" value=".*Header"/>
- <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable header checks"/>
- </module>
- <module name="SuppressionCommentFilter">
- <property name="offCommentFormat" value="CheckStyle: stop line length check"/>
- <property name="onCommentFormat" value="CheckStyle: resume line length check"/>
- <property name="checkFormat" value="LineLength"/>
- </module>
- <module name="SuppressionCommentFilter">
- <property name="offCommentFormat" value="CheckStyle: start generated"/>
- <property name="onCommentFormat" value="CheckStyle: stop generated"/>
- <property name="checkFormat" value=".*Name|.*LineLength|.*Header"/>
- </module>
</module>
--- a/src/jdk.internal.vm.compiler.management/share/classes/org.graalvm.compiler.hotspot.management/src/org/graalvm/compiler/hotspot/management/JMXServiceProvider.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler.management/share/classes/org.graalvm.compiler.hotspot.management/src/org/graalvm/compiler/hotspot/management/JMXServiceProvider.java Thu Aug 23 11:09:16 2018 -0400
@@ -30,7 +30,7 @@
import java.util.List;
import org.graalvm.compiler.serviceprovider.ServiceProvider;
-import org.graalvm.compiler.serviceprovider.GraalServices.JMXService;
+import org.graalvm.compiler.serviceprovider.JMXService;
import com.sun.management.ThreadMXBean;
--- a/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections.test/src/jdk/internal/vm/compiler/collections/test/EconomicMapImplTest.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections.test/src/jdk/internal/vm/compiler/collections/test/EconomicMapImplTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -114,7 +114,12 @@
}
});
set.addAll(Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9));
- Assert.assertTrue(set.add(new Integer(0)));
+ Assert.assertTrue(set.add(newInteger(0)));
+ }
+
+ @SuppressWarnings("deprecation")
+ private static Integer newInteger(int value) {
+ return new Integer(value);
}
@Test(expected = UnsupportedOperationException.class)
--- a/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections.test/src/jdk/internal/vm/compiler/collections/test/EconomicSetTest.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections.test/src/jdk/internal/vm/compiler/collections/test/EconomicSetTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -142,7 +142,12 @@
}
Assert.assertEquals(initialList, removalList);
Assert.assertEquals(1, finalList.size());
- Assert.assertEquals(new Integer(9), finalList.get(0));
+ Assert.assertEquals(newInteger(9), finalList.get(0));
+ }
+
+ @SuppressWarnings("deprecation")
+ private static Integer newInteger(int value) {
+ return new Integer(value);
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/module-info.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/module-info.java Thu Aug 23 11:09:16 2018 -0400
@@ -39,7 +39,7 @@
uses org.graalvm.compiler.hotspot.HotSpotCodeCacheListener;
uses org.graalvm.compiler.hotspot.HotSpotGraalManagementRegistration;
uses org.graalvm.compiler.nodes.graphbuilderconf.NodeIntrinsicPluginFactory;
- uses org.graalvm.compiler.serviceprovider.GraalServices.JMXService;
+ uses org.graalvm.compiler.serviceprovider.JMXService;
exports jdk.internal.vm.compiler.collections to jdk.internal.vm.compiler.management;
exports org.graalvm.compiler.api.directives to jdk.aot;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Address.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Address.java Thu Aug 23 11:09:16 2018 -0400
@@ -80,7 +80,6 @@
* address = base + imm9. base is updated to base + imm9
*/
IMMEDIATE_PRE_INDEXED,
- AddressingMode,
}
private final Register base;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64.test/src/org/graalvm/compiler/asm/amd64/test/BitOpsTest.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64.test/src/org/graalvm/compiler/asm/amd64/test/BitOpsTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -25,16 +25,23 @@
package org.graalvm.compiler.asm.amd64.test;
+import static jdk.vm.ci.code.ValueUtil.asRegister;
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp.LZCNT;
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp.TZCNT;
-import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.DWORD;
-import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.QWORD;
-import static jdk.vm.ci.code.ValueUtil.asRegister;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.DWORD;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.QWORD;
import static org.junit.Assume.assumeTrue;
import java.lang.reflect.Field;
import java.util.EnumSet;
+import org.graalvm.compiler.asm.amd64.AMD64Address;
+import org.graalvm.compiler.asm.amd64.AMD64Assembler;
+import org.graalvm.compiler.asm.test.AssemblerTest;
+import org.graalvm.compiler.code.CompilationResult;
+import org.junit.Before;
+import org.junit.Test;
+
import jdk.vm.ci.amd64.AMD64;
import jdk.vm.ci.amd64.AMD64.CPUFeature;
import jdk.vm.ci.code.CallingConvention;
@@ -43,14 +50,6 @@
import jdk.vm.ci.code.TargetDescription;
import jdk.vm.ci.meta.JavaKind;
-import org.junit.Before;
-import org.junit.Test;
-
-import org.graalvm.compiler.asm.amd64.AMD64Address;
-import org.graalvm.compiler.asm.amd64.AMD64Assembler;
-import org.graalvm.compiler.asm.test.AssemblerTest;
-import org.graalvm.compiler.code.CompilationResult;
-
public class BitOpsTest extends AssemblerTest {
private static boolean lzcntSupported;
private static boolean tzcntSupported;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,12 +25,8 @@
package org.graalvm.compiler.asm.amd64;
import static jdk.vm.ci.amd64.AMD64.CPU;
+import static jdk.vm.ci.amd64.AMD64.MASK;
import static jdk.vm.ci.amd64.AMD64.XMM;
-import static jdk.vm.ci.amd64.AMD64.r12;
-import static jdk.vm.ci.amd64.AMD64.r13;
-import static jdk.vm.ci.amd64.AMD64.rbp;
-import static jdk.vm.ci.amd64.AMD64.rip;
-import static jdk.vm.ci.amd64.AMD64.rsp;
import static jdk.vm.ci.code.MemoryBarriers.STORE_LOAD;
import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseAddressNop;
import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseNormalNop;
@@ -45,23 +41,39 @@
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MOp.INC;
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MOp.NEG;
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MOp.NOT;
-import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.BYTE;
-import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.DWORD;
-import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.PD;
-import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.PS;
-import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.QWORD;
-import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.SD;
-import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.SS;
-import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.WORD;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.EVEXPrefixConfig.B0;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.EVEXPrefixConfig.Z0;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.BYTE;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.DWORD;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.PD;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.PS;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.QWORD;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.SD;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.SS;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.WORD;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.VEXPrefixConfig.L128;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.VEXPrefixConfig.M_0F;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.VEXPrefixConfig.M_0F38;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.VEXPrefixConfig.M_0F3A;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.VEXPrefixConfig.P_;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.VEXPrefixConfig.P_66;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.VEXPrefixConfig.P_F2;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.VEXPrefixConfig.P_F3;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.VEXPrefixConfig.W0;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.VEXPrefixConfig.W1;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.VEXPrefixConfig.WIG;
import static org.graalvm.compiler.core.common.NumUtil.isByte;
import static org.graalvm.compiler.core.common.NumUtil.isInt;
import static org.graalvm.compiler.core.common.NumUtil.isShiftCount;
import static org.graalvm.compiler.core.common.NumUtil.isUByte;
-import org.graalvm.compiler.asm.Assembler;
+import java.util.EnumSet;
+
import org.graalvm.compiler.asm.Label;
import org.graalvm.compiler.asm.amd64.AMD64Address.Scale;
+import org.graalvm.compiler.asm.amd64.AVXKind.AVXSize;
import org.graalvm.compiler.core.common.NumUtil;
+import org.graalvm.compiler.core.common.calc.Condition;
import org.graalvm.compiler.debug.GraalError;
import jdk.vm.ci.amd64.AMD64;
@@ -70,14 +82,18 @@
import jdk.vm.ci.code.Register;
import jdk.vm.ci.code.Register.RegisterCategory;
import jdk.vm.ci.code.TargetDescription;
-import jdk.vm.ci.meta.PlatformKind;
/**
* This class implements an assembler that can encode most X86 instructions.
*/
-public class AMD64Assembler extends Assembler {
-
- private static final int MinEncodingNeedsRex = 8;
+public class AMD64Assembler extends AMD64BaseAssembler {
+
+ /**
+ * Constructs an assembler for the AMD64 architecture.
+ */
+ public AMD64Assembler(TargetDescription target) {
+ super(target);
+ }
/**
* The x86 condition codes used for conditional jumps/moves.
@@ -169,214 +185,6 @@
}
/**
- * Constants for X86 prefix bytes.
- */
- private static class Prefix {
- private static final int REX = 0x40;
- private static final int REXB = 0x41;
- private static final int REXX = 0x42;
- private static final int REXXB = 0x43;
- private static final int REXR = 0x44;
- private static final int REXRB = 0x45;
- private static final int REXRX = 0x46;
- private static final int REXRXB = 0x47;
- private static final int REXW = 0x48;
- private static final int REXWB = 0x49;
- private static final int REXWX = 0x4A;
- private static final int REXWXB = 0x4B;
- private static final int REXWR = 0x4C;
- private static final int REXWRB = 0x4D;
- private static final int REXWRX = 0x4E;
- private static final int REXWRXB = 0x4F;
- private static final int VEX_3BYTES = 0xC4;
- private static final int VEX_2BYTES = 0xC5;
- }
-
- private static class VexPrefix {
- private static final int VEX_R = 0x80;
- private static final int VEX_W = 0x80;
- }
-
- private static class VexSimdPrefix {
- private static final int VEX_SIMD_NONE = 0x0;
- private static final int VEX_SIMD_66 = 0x1;
- private static final int VEX_SIMD_F3 = 0x2;
- private static final int VEX_SIMD_F2 = 0x3;
- }
-
- private static class VexOpcode {
- private static final int VEX_OPCODE_NONE = 0x0;
- private static final int VEX_OPCODE_0F = 0x1;
- private static final int VEX_OPCODE_0F_38 = 0x2;
- private static final int VEX_OPCODE_0F_3A = 0x3;
- }
-
- public static class AvxVectorLen {
- public static final int AVX_128bit = 0x0;
- public static final int AVX_256bit = 0x1;
- public static final int AVX_512bit = 0x2;
- public static final int AVX_NoVec = 0x4;
- }
-
- public static class EvexTupleType {
- public static final int EVEX_FV = 0;
- public static final int EVEX_HV = 4;
- public static final int EVEX_FVM = 6;
- public static final int EVEX_T1S = 7;
- public static final int EVEX_T1F = 11;
- public static final int EVEX_T2 = 13;
- public static final int EVEX_T4 = 15;
- public static final int EVEX_T8 = 17;
- public static final int EVEX_HVM = 18;
- public static final int EVEX_QVM = 19;
- public static final int EVEX_OVM = 20;
- public static final int EVEX_M128 = 21;
- public static final int EVEX_DUP = 22;
- public static final int EVEX_ETUP = 23;
- }
-
- public static class EvexInputSizeInBits {
- public static final int EVEX_8bit = 0;
- public static final int EVEX_16bit = 1;
- public static final int EVEX_32bit = 2;
- public static final int EVEX_64bit = 3;
- public static final int EVEX_NObit = 4;
- }
-
- private AMD64InstructionAttr curAttributes;
-
- AMD64InstructionAttr getCurAttributes() {
- return curAttributes;
- }
-
- void setCurAttributes(AMD64InstructionAttr attributes) {
- curAttributes = attributes;
- }
-
- /**
- * The x86 operand sizes.
- */
- public enum OperandSize {
- BYTE(1, AMD64Kind.BYTE) {
- @Override
- protected void emitImmediate(AMD64Assembler asm, int imm) {
- assert imm == (byte) imm;
- asm.emitByte(imm);
- }
-
- @Override
- protected int immediateSize() {
- return 1;
- }
- },
-
- WORD(2, AMD64Kind.WORD, 0x66) {
- @Override
- protected void emitImmediate(AMD64Assembler asm, int imm) {
- assert imm == (short) imm;
- asm.emitShort(imm);
- }
-
- @Override
- protected int immediateSize() {
- return 2;
- }
- },
-
- DWORD(4, AMD64Kind.DWORD) {
- @Override
- protected void emitImmediate(AMD64Assembler asm, int imm) {
- asm.emitInt(imm);
- }
-
- @Override
- protected int immediateSize() {
- return 4;
- }
- },
-
- QWORD(8, AMD64Kind.QWORD) {
- @Override
- protected void emitImmediate(AMD64Assembler asm, int imm) {
- asm.emitInt(imm);
- }
-
- @Override
- protected int immediateSize() {
- return 4;
- }
- },
-
- SS(4, AMD64Kind.SINGLE, 0xF3, true),
-
- SD(8, AMD64Kind.DOUBLE, 0xF2, true),
-
- PS(16, AMD64Kind.V128_SINGLE, true),
-
- PD(16, AMD64Kind.V128_DOUBLE, 0x66, true);
-
- private final int sizePrefix;
- private final int bytes;
- private final boolean xmm;
- private final AMD64Kind kind;
-
- OperandSize(int bytes, AMD64Kind kind) {
- this(bytes, kind, 0);
- }
-
- OperandSize(int bytes, AMD64Kind kind, int sizePrefix) {
- this(bytes, kind, sizePrefix, false);
- }
-
- OperandSize(int bytes, AMD64Kind kind, boolean xmm) {
- this(bytes, kind, 0, xmm);
- }
-
- OperandSize(int bytes, AMD64Kind kind, int sizePrefix, boolean xmm) {
- this.sizePrefix = sizePrefix;
- this.bytes = bytes;
- this.kind = kind;
- this.xmm = xmm;
- }
-
- public int getBytes() {
- return bytes;
- }
-
- public boolean isXmmType() {
- return xmm;
- }
-
- public AMD64Kind getKind() {
- return kind;
- }
-
- public static OperandSize get(PlatformKind kind) {
- for (OperandSize operandSize : OperandSize.values()) {
- if (operandSize.kind.equals(kind)) {
- return operandSize;
- }
- }
- throw GraalError.shouldNotReachHere("Unexpected kind: " + kind.toString());
- }
-
- /**
- * Emit an immediate of this size. Note that immediate {@link #QWORD} operands are encoded
- * as sign-extended 32-bit values.
- *
- * @param asm
- * @param imm
- */
- protected void emitImmediate(AMD64Assembler asm, int imm) {
- throw new UnsupportedOperationException();
- }
-
- protected int immediateSize() {
- throw new UnsupportedOperationException();
- }
- }
-
- /**
* Operand size and register type constraints.
*/
private enum OpAssertion {
@@ -417,261 +225,18 @@
assert false : "invalid operand size " + size + " used in " + op;
return false;
}
- }
-
- public abstract static class OperandDataAnnotation extends CodeAnnotation {
- /**
- * The position (bytes from the beginning of the method) of the operand.
- */
- public final int operandPosition;
- /**
- * The size of the operand, in bytes.
- */
- public final int operandSize;
- /**
- * The position (bytes from the beginning of the method) of the next instruction. On AMD64,
- * RIP-relative operands are relative to this position.
- */
- public final int nextInstructionPosition;
-
- OperandDataAnnotation(int instructionPosition, int operandPosition, int operandSize, int nextInstructionPosition) {
- super(instructionPosition);
-
- this.operandPosition = operandPosition;
- this.operandSize = operandSize;
- this.nextInstructionPosition = nextInstructionPosition;
- }
-
- @Override
- public String toString() {
- return getClass().getSimpleName() + " instruction [" + instructionPosition + ", " + nextInstructionPosition + "[ operand at " + operandPosition + " size " + operandSize;
- }
- }
-
- /**
- * Annotation that stores additional information about the displacement of a
- * {@link Assembler#getPlaceholder placeholder address} that needs patching.
- */
- public static class AddressDisplacementAnnotation extends OperandDataAnnotation {
- AddressDisplacementAnnotation(int instructionPosition, int operandPosition, int operndSize, int nextInstructionPosition) {
- super(instructionPosition, operandPosition, operndSize, nextInstructionPosition);
- }
- }
-
- /**
- * Annotation that stores additional information about the immediate operand, e.g., of a call
- * instruction, that needs patching.
- */
- public static class ImmediateOperandAnnotation extends OperandDataAnnotation {
- ImmediateOperandAnnotation(int instructionPosition, int operandPosition, int operndSize, int nextInstructionPosition) {
- super(instructionPosition, operandPosition, operndSize, nextInstructionPosition);
- }
- }
-
- /**
- * Constructs an assembler for the AMD64 architecture.
- */
- public AMD64Assembler(TargetDescription target) {
- super(target);
- }
-
- public boolean supports(CPUFeature feature) {
- return ((AMD64) target.arch).getFeatures().contains(feature);
- }
-
- private static int encode(Register r) {
- assert r.encoding < 16 && r.encoding >= 0 : "encoding out of range: " + r.encoding;
- return r.encoding & 0x7;
- }
-
- /**
- * Get RXB bits for register-register instruction. In that encoding, ModRM.rm contains a
- * register index. The R bit extends the ModRM.reg field and the B bit extends the ModRM.rm
- * field. The X bit must be 0.
- */
- protected static int getRXB(Register reg, Register rm) {
- int rxb = (reg == null ? 0 : reg.encoding & 0x08) >> 1;
- rxb |= (rm == null ? 0 : rm.encoding & 0x08) >> 3;
- return rxb;
- }
-
- /**
- * Get RXB bits for register-memory instruction. The R bit extends the ModRM.reg field. There
- * are two cases for the memory operand:<br>
- * ModRM.rm contains the base register: In that case, B extends the ModRM.rm field and X = 0.
- * <br>
- * There is an SIB byte: In that case, X extends SIB.index and B extends SIB.base.
- */
- protected static int getRXB(Register reg, AMD64Address rm) {
- int rxb = (reg == null ? 0 : reg.encoding & 0x08) >> 1;
- if (!rm.getIndex().equals(Register.None)) {
- rxb |= (rm.getIndex().encoding & 0x08) >> 2;
- }
- if (!rm.getBase().equals(Register.None)) {
- rxb |= (rm.getBase().encoding & 0x08) >> 3;
- }
- return rxb;
- }
-
- /**
- * Emit the ModR/M byte for one register operand and an opcode extension in the R field.
- * <p>
- * Format: [ 11 reg r/m ]
- */
- protected void emitModRM(int reg, Register rm) {
- assert (reg & 0x07) == reg;
- emitByte(0xC0 | (reg << 3) | (rm.encoding & 0x07));
- }
-
- /**
- * Emit the ModR/M byte for two register operands.
- * <p>
- * Format: [ 11 reg r/m ]
- */
- protected void emitModRM(Register reg, Register rm) {
- emitModRM(reg.encoding & 0x07, rm);
- }
-
- protected void emitOperandHelper(Register reg, AMD64Address addr, int additionalInstructionSize) {
- assert !reg.equals(Register.None);
- emitOperandHelper(encode(reg), addr, false, additionalInstructionSize);
+
}
- /**
- * Emits the ModR/M byte and optionally the SIB byte for one register and one memory operand.
- *
- * @param force4Byte use 4 byte encoding for displacements that would normally fit in a byte
- */
- protected void emitOperandHelper(Register reg, AMD64Address addr, boolean force4Byte, int additionalInstructionSize) {
- assert !reg.equals(Register.None);
- emitOperandHelper(encode(reg), addr, force4Byte, additionalInstructionSize);
- }
-
- protected void emitOperandHelper(int reg, AMD64Address addr, int additionalInstructionSize) {
- emitOperandHelper(reg, addr, false, additionalInstructionSize);
- }
-
- /**
- * Emits the ModR/M byte and optionally the SIB byte for one memory operand and an opcode
- * extension in the R field.
- *
- * @param force4Byte use 4 byte encoding for displacements that would normally fit in a byte
- * @param additionalInstructionSize the number of bytes that will be emitted after the operand,
- * so that the start position of the next instruction can be computed even though
- * this instruction has not been completely emitted yet.
- */
- protected void emitOperandHelper(int reg, AMD64Address addr, boolean force4Byte, int additionalInstructionSize) {
- assert (reg & 0x07) == reg;
- int regenc = reg << 3;
-
- Register base = addr.getBase();
- Register index = addr.getIndex();
-
- AMD64Address.Scale scale = addr.getScale();
- int disp = addr.getDisplacement();
-
- if (base.equals(AMD64.rip)) { // also matches addresses returned by getPlaceholder()
- // [00 000 101] disp32
- assert index.equals(Register.None) : "cannot use RIP relative addressing with index register";
- emitByte(0x05 | regenc);
- if (codePatchingAnnotationConsumer != null && addr.instructionStartPosition >= 0) {
- codePatchingAnnotationConsumer.accept(new AddressDisplacementAnnotation(addr.instructionStartPosition, position(), 4, position() + 4 + additionalInstructionSize));
- }
- emitInt(disp);
- } else if (base.isValid()) {
- int baseenc = base.isValid() ? encode(base) : 0;
- if (index.isValid()) {
- int indexenc = encode(index) << 3;
- // [base + indexscale + disp]
- if (disp == 0 && !base.equals(rbp) && !base.equals(r13)) {
- // [base + indexscale]
- // [00 reg 100][ss index base]
- assert !index.equals(rsp) : "illegal addressing mode";
- emitByte(0x04 | regenc);
- emitByte(scale.log2 << 6 | indexenc | baseenc);
- } else if (isByte(disp) && !force4Byte) {
- // [base + indexscale + imm8]
- // [01 reg 100][ss index base] imm8
- assert !index.equals(rsp) : "illegal addressing mode";
- emitByte(0x44 | regenc);
- emitByte(scale.log2 << 6 | indexenc | baseenc);
- emitByte(disp & 0xFF);
- } else {
- // [base + indexscale + disp32]
- // [10 reg 100][ss index base] disp32
- assert !index.equals(rsp) : "illegal addressing mode";
- emitByte(0x84 | regenc);
- emitByte(scale.log2 << 6 | indexenc | baseenc);
- emitInt(disp);
- }
- } else if (base.equals(rsp) || base.equals(r12)) {
- // [rsp + disp]
- if (disp == 0) {
- // [rsp]
- // [00 reg 100][00 100 100]
- emitByte(0x04 | regenc);
- emitByte(0x24);
- } else if (isByte(disp) && !force4Byte) {
- // [rsp + imm8]
- // [01 reg 100][00 100 100] disp8
- emitByte(0x44 | regenc);
- emitByte(0x24);
- emitByte(disp & 0xFF);
- } else {
- // [rsp + imm32]
- // [10 reg 100][00 100 100] disp32
- emitByte(0x84 | regenc);
- emitByte(0x24);
- emitInt(disp);
- }
- } else {
- // [base + disp]
- assert !base.equals(rsp) && !base.equals(r12) : "illegal addressing mode";
- if (disp == 0 && !base.equals(rbp) && !base.equals(r13)) {
- // [base]
- // [00 reg base]
- emitByte(0x00 | regenc | baseenc);
- } else if (isByte(disp) && !force4Byte) {
- // [base + disp8]
- // [01 reg base] disp8
- emitByte(0x40 | regenc | baseenc);
- emitByte(disp & 0xFF);
- } else {
- // [base + disp32]
- // [10 reg base] disp32
- emitByte(0x80 | regenc | baseenc);
- emitInt(disp);
- }
- }
- } else {
- if (index.isValid()) {
- int indexenc = encode(index) << 3;
- // [indexscale + disp]
- // [00 reg 100][ss index 101] disp32
- assert !index.equals(rsp) : "illegal addressing mode";
- emitByte(0x04 | regenc);
- emitByte(scale.log2 << 6 | indexenc | 0x05);
- emitInt(disp);
- } else {
- // [disp] ABSOLUTE
- // [00 reg 100][00 100 101] disp32
- emitByte(0x04 | regenc);
- emitByte(0x25);
- emitInt(disp);
- }
- }
- setCurAttributes(null);
- }
+ protected static final int P_0F = 0x0F;
+ protected static final int P_0F38 = 0x380F;
+ protected static final int P_0F3A = 0x3A0F;
/**
* Base class for AMD64 opcodes.
*/
public static class AMD64Op {
- protected static final int P_0F = 0x0F;
- protected static final int P_0F38 = 0x380F;
- protected static final int P_0F3A = 0x3A0F;
-
private final String opcode;
protected final int prefix1;
@@ -705,8 +270,8 @@
if (prefix1 != 0) {
asm.emitByte(prefix1);
}
- if (size.sizePrefix != 0) {
- asm.emitByte(size.sizePrefix);
+ if (size.getSizePrefix() != 0) {
+ asm.emitByte(size.getSizePrefix());
}
int rexPrefix = 0x40 | rxb;
if (size == QWORD) {
@@ -729,6 +294,32 @@
return true;
}
+ public OperandSize[] getAllowedSizes() {
+ return assertion.allowedSizes;
+ }
+
+ protected final boolean isSSEInstruction() {
+ if (feature == null) {
+ return false;
+ }
+ switch (feature) {
+ case SSE:
+ case SSE2:
+ case SSE3:
+ case SSSE3:
+ case SSE4A:
+ case SSE4_1:
+ case SSE4_2:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public final OpAssertion getAssertion() {
+ return assertion;
+ }
+
@Override
public String toString() {
return opcode;
@@ -743,7 +334,11 @@
private final boolean immIsByte;
protected AMD64ImmOp(String opcode, boolean immIsByte, int prefix, int op, OpAssertion assertion) {
- super(opcode, 0, prefix, op, assertion, null);
+ this(opcode, immIsByte, prefix, op, assertion, null);
+ }
+
+ protected AMD64ImmOp(String opcode, boolean immIsByte, int prefix, int op, OpAssertion assertion, CPUFeature feature) {
+ super(opcode, 0, prefix, op, assertion, feature);
this.immIsByte = immIsByte;
}
@@ -760,7 +355,7 @@
if (immIsByte) {
return 1;
} else {
- return size.bytes;
+ return size.getBytes();
}
}
}
@@ -782,22 +377,6 @@
}
/**
- * Opcode with operand order of either RM or MR for 3 address forms.
- */
- public abstract static class AMD64RRROp extends AMD64Op {
-
- protected AMD64RRROp(String opcode, int prefix1, int prefix2, int op, OpAssertion assertion, CPUFeature feature) {
- super(opcode, prefix1, prefix2, op, assertion, feature);
- }
-
- protected AMD64RRROp(String opcode, int prefix1, int prefix2, int op, boolean dstIsByte, boolean srcIsByte, OpAssertion assertion, CPUFeature feature) {
- super(opcode, prefix1, prefix2, op, dstIsByte, srcIsByte, assertion, feature);
- }
-
- public abstract void emit(AMD64Assembler asm, OperandSize size, Register dst, Register nds, Register src);
- }
-
- /**
* Opcode with operand order of RM.
*/
public static class AMD64RMOp extends AMD64RROp {
@@ -805,9 +384,12 @@
public static final AMD64RMOp IMUL = new AMD64RMOp("IMUL", P_0F, 0xAF, OpAssertion.ByteOrLargerAssertion);
public static final AMD64RMOp BSF = new AMD64RMOp("BSF", P_0F, 0xBC);
public static final AMD64RMOp BSR = new AMD64RMOp("BSR", P_0F, 0xBD);
- public static final AMD64RMOp POPCNT = new AMD64RMOp("POPCNT", 0xF3, P_0F, 0xB8, CPUFeature.POPCNT);
- public static final AMD64RMOp TZCNT = new AMD64RMOp("TZCNT", 0xF3, P_0F, 0xBC, CPUFeature.BMI1);
- public static final AMD64RMOp LZCNT = new AMD64RMOp("LZCNT", 0xF3, P_0F, 0xBD, CPUFeature.LZCNT);
+ // POPCNT, TZCNT, and LZCNT support word operation. However, the legacy size prefix should
+ // be emitted before the mandatory prefix 0xF3. Since we are not emitting bit count for
+ // 16-bit operands, here we simply use DwordOrLargerAssertion.
+ public static final AMD64RMOp POPCNT = new AMD64RMOp("POPCNT", 0xF3, P_0F, 0xB8, OpAssertion.DwordOrLargerAssertion, CPUFeature.POPCNT);
+ public static final AMD64RMOp TZCNT = new AMD64RMOp("TZCNT", 0xF3, P_0F, 0xBC, OpAssertion.DwordOrLargerAssertion, CPUFeature.BMI1);
+ public static final AMD64RMOp LZCNT = new AMD64RMOp("LZCNT", 0xF3, P_0F, 0xBD, OpAssertion.DwordOrLargerAssertion, CPUFeature.LZCNT);
public static final AMD64RMOp MOVZXB = new AMD64RMOp("MOVZXB", P_0F, 0xB6, false, true, OpAssertion.WordOrLargerAssertion);
public static final AMD64RMOp MOVZX = new AMD64RMOp("MOVZX", P_0F, 0xB7, OpAssertion.DwordOrLargerAssertion);
public static final AMD64RMOp MOVSXB = new AMD64RMOp("MOVSXB", P_0F, 0xBE, false, true, OpAssertion.WordOrLargerAssertion);
@@ -863,80 +445,35 @@
@Override
public final void emit(AMD64Assembler asm, OperandSize size, Register dst, Register src) {
assert verify(asm, size, dst, src);
- boolean isSimd = false;
- boolean noNds = false;
-
- switch (op) {
- case 0x2A:
- case 0x2C:
- case 0x2E:
- case 0x5A:
- case 0x6E:
- isSimd = true;
- noNds = true;
- break;
- case 0x10:
- case 0x51:
- case 0x54:
- case 0x55:
- case 0x56:
- case 0x57:
- case 0x58:
- case 0x59:
- case 0x5C:
- case 0x5D:
- case 0x5E:
- case 0x5F:
- isSimd = true;
- break;
- }
-
- int opc = 0;
- if (isSimd) {
- switch (prefix2) {
- case P_0F:
- opc = VexOpcode.VEX_OPCODE_0F;
+ if (isSSEInstruction()) {
+ Register nds = Register.None;
+ switch (op) {
+ case 0x10:
+ case 0x51:
+ if ((size == SS) || (size == SD)) {
+ nds = dst;
+ }
break;
- case P_0F38:
- opc = VexOpcode.VEX_OPCODE_0F_38;
- break;
- case P_0F3A:
- opc = VexOpcode.VEX_OPCODE_0F_3A;
+ case 0x2A:
+ case 0x54:
+ case 0x55:
+ case 0x56:
+ case 0x57:
+ case 0x58:
+ case 0x59:
+ case 0x5A:
+ case 0x5C:
+ case 0x5D:
+ case 0x5E:
+ case 0x5F:
+ nds = dst;
break;
default:
- opc = VexOpcode.VEX_OPCODE_NONE;
- isSimd = false;
break;
}
- }
-
- if (isSimd) {
- int pre;
- boolean rexVexW = (size == QWORD) ? true : false;
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, rexVexW, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, asm.target);
- int curPrefix = size.sizePrefix | prefix1;
- switch (curPrefix) {
- case 0x66:
- pre = VexSimdPrefix.VEX_SIMD_66;
- break;
- case 0xF2:
- pre = VexSimdPrefix.VEX_SIMD_F2;
- break;
- case 0xF3:
- pre = VexSimdPrefix.VEX_SIMD_F3;
- break;
- default:
- pre = VexSimdPrefix.VEX_SIMD_NONE;
- break;
- }
- int encode;
- if (noNds) {
- encode = asm.simdPrefixAndEncode(dst, Register.None, src, pre, opc, attributes);
- } else {
- encode = asm.simdPrefixAndEncode(dst, dst, src, pre, opc, attributes);
- }
+ asm.simdPrefix(dst, nds, src, size, prefix1, prefix2, size == QWORD);
asm.emitByte(op);
- asm.emitByte(0xC0 | encode);
+ asm.emitModRM(dst, src);
} else {
emitOpcode(asm, size, getRXB(dst, src), dst.encoding, src.encoding);
asm.emitModRM(dst, src);
@@ -945,75 +482,32 @@
public final void emit(AMD64Assembler asm, OperandSize size, Register dst, AMD64Address src) {
assert verify(asm, size, dst, null);
- boolean isSimd = false;
- boolean noNds = false;
-
- switch (op) {
- case 0x10:
- case 0x2A:
- case 0x2C:
- case 0x2E:
- case 0x6E:
- isSimd = true;
- noNds = true;
- break;
- case 0x51:
- case 0x54:
- case 0x55:
- case 0x56:
- case 0x57:
- case 0x58:
- case 0x59:
- case 0x5C:
- case 0x5D:
- case 0x5E:
- case 0x5F:
- isSimd = true;
- break;
- }
-
- int opc = 0;
- if (isSimd) {
- switch (prefix2) {
- case P_0F:
- opc = VexOpcode.VEX_OPCODE_0F;
+ if (isSSEInstruction()) {
+ Register nds = Register.None;
+ switch (op) {
+ case 0x51:
+ if ((size == SS) || (size == SD)) {
+ nds = dst;
+ }
break;
- case P_0F38:
- opc = VexOpcode.VEX_OPCODE_0F_38;
- break;
- case P_0F3A:
- opc = VexOpcode.VEX_OPCODE_0F_3A;
+ case 0x2A:
+ case 0x54:
+ case 0x55:
+ case 0x56:
+ case 0x57:
+ case 0x58:
+ case 0x59:
+ case 0x5A:
+ case 0x5C:
+ case 0x5D:
+ case 0x5E:
+ case 0x5F:
+ nds = dst;
break;
default:
- isSimd = false;
break;
}
- }
-
- if (isSimd) {
- int pre;
- boolean rexVexW = (size == QWORD) ? true : false;
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, rexVexW, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, asm.target);
- int curPrefix = size.sizePrefix | prefix1;
- switch (curPrefix) {
- case 0x66:
- pre = VexSimdPrefix.VEX_SIMD_66;
- break;
- case 0xF2:
- pre = VexSimdPrefix.VEX_SIMD_F2;
- break;
- case 0xF3:
- pre = VexSimdPrefix.VEX_SIMD_F3;
- break;
- default:
- pre = VexSimdPrefix.VEX_SIMD_NONE;
- break;
- }
- if (noNds) {
- asm.simdPrefix(dst, Register.None, src, pre, opc, attributes);
- } else {
- asm.simdPrefix(dst, dst, src, pre, opc, attributes);
- }
+ asm.simdPrefix(dst, nds, src, size, prefix1, prefix2, size == QWORD);
asm.emitByte(op);
asm.emitOperandHelper(dst, src, 0);
} else {
@@ -1024,123 +518,6 @@
}
/**
- * Opcode with operand order of RM.
- */
- public static class AMD64RRMOp extends AMD64RRROp {
- protected AMD64RRMOp(String opcode, int op) {
- this(opcode, 0, op);
- }
-
- protected AMD64RRMOp(String opcode, int op, OpAssertion assertion) {
- this(opcode, 0, op, assertion);
- }
-
- protected AMD64RRMOp(String opcode, int prefix, int op) {
- this(opcode, 0, prefix, op, null);
- }
-
- protected AMD64RRMOp(String opcode, int prefix, int op, OpAssertion assertion) {
- this(opcode, 0, prefix, op, assertion, null);
- }
-
- protected AMD64RRMOp(String opcode, int prefix, int op, OpAssertion assertion, CPUFeature feature) {
- this(opcode, 0, prefix, op, assertion, feature);
- }
-
- protected AMD64RRMOp(String opcode, int prefix, int op, boolean dstIsByte, boolean srcIsByte, OpAssertion assertion) {
- super(opcode, 0, prefix, op, dstIsByte, srcIsByte, assertion, null);
- }
-
- protected AMD64RRMOp(String opcode, int prefix1, int prefix2, int op, CPUFeature feature) {
- this(opcode, prefix1, prefix2, op, OpAssertion.WordOrLargerAssertion, feature);
- }
-
- protected AMD64RRMOp(String opcode, int prefix1, int prefix2, int op, OpAssertion assertion, CPUFeature feature) {
- super(opcode, prefix1, prefix2, op, assertion, feature);
- }
-
- @Override
- public final void emit(AMD64Assembler asm, OperandSize size, Register dst, Register nds, Register src) {
- assert verify(asm, size, dst, src);
- int pre;
- int opc;
- boolean rexVexW = (size == QWORD) ? true : false;
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, rexVexW, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, asm.target);
- int curPrefix = size.sizePrefix | prefix1;
- switch (curPrefix) {
- case 0x66:
- pre = VexSimdPrefix.VEX_SIMD_66;
- break;
- case 0xF2:
- pre = VexSimdPrefix.VEX_SIMD_F2;
- break;
- case 0xF3:
- pre = VexSimdPrefix.VEX_SIMD_F3;
- break;
- default:
- pre = VexSimdPrefix.VEX_SIMD_NONE;
- break;
- }
- switch (prefix2) {
- case P_0F:
- opc = VexOpcode.VEX_OPCODE_0F;
- break;
- case P_0F38:
- opc = VexOpcode.VEX_OPCODE_0F_38;
- break;
- case P_0F3A:
- opc = VexOpcode.VEX_OPCODE_0F_3A;
- break;
- default:
- throw GraalError.shouldNotReachHere("invalid VEX instruction prefix");
- }
- int encode;
- encode = asm.simdPrefixAndEncode(dst, nds, src, pre, opc, attributes);
- asm.emitByte(op);
- asm.emitByte(0xC0 | encode);
- }
-
- public final void emit(AMD64Assembler asm, OperandSize size, Register dst, Register nds, AMD64Address src) {
- assert verify(asm, size, dst, null);
- int pre;
- int opc;
- boolean rexVexW = (size == QWORD) ? true : false;
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, rexVexW, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, asm.target);
- int curPrefix = size.sizePrefix | prefix1;
- switch (curPrefix) {
- case 0x66:
- pre = VexSimdPrefix.VEX_SIMD_66;
- break;
- case 0xF2:
- pre = VexSimdPrefix.VEX_SIMD_F2;
- break;
- case 0xF3:
- pre = VexSimdPrefix.VEX_SIMD_F3;
- break;
- default:
- pre = VexSimdPrefix.VEX_SIMD_NONE;
- break;
- }
- switch (prefix2) {
- case P_0F:
- opc = VexOpcode.VEX_OPCODE_0F;
- break;
- case P_0F38:
- opc = VexOpcode.VEX_OPCODE_0F_38;
- break;
- case P_0F3A:
- opc = VexOpcode.VEX_OPCODE_0F_3A;
- break;
- default:
- throw GraalError.shouldNotReachHere("invalid VEX instruction prefix");
- }
- asm.simdPrefix(dst, nds, src, pre, opc, attributes);
- asm.emitByte(op);
- asm.emitOperandHelper(dst, src, 0);
- }
- }
-
- /**
* Opcode with operand order of MR.
*/
public static class AMD64MROp extends AMD64RROp {
@@ -1185,64 +562,20 @@
@Override
public final void emit(AMD64Assembler asm, OperandSize size, Register dst, Register src) {
assert verify(asm, size, src, dst);
- boolean isSimd = false;
- boolean noNds = false;
-
- switch (op) {
- case 0x7E:
- isSimd = true;
- noNds = true;
- break;
- case 0x11:
- isSimd = true;
- break;
- }
-
- int opc = 0;
- if (isSimd) {
- switch (prefix2) {
- case P_0F:
- opc = VexOpcode.VEX_OPCODE_0F;
- break;
- case P_0F38:
- opc = VexOpcode.VEX_OPCODE_0F_38;
- break;
- case P_0F3A:
- opc = VexOpcode.VEX_OPCODE_0F_3A;
+ if (isSSEInstruction()) {
+ Register nds = Register.None;
+ switch (op) {
+ case 0x11:
+ if ((size == SS) || (size == SD)) {
+ nds = src;
+ }
break;
default:
- isSimd = false;
break;
}
- }
-
- if (isSimd) {
- int pre;
- boolean rexVexW = (size == QWORD) ? true : false;
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, rexVexW, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, asm.target);
- int curPrefix = size.sizePrefix | prefix1;
- switch (curPrefix) {
- case 0x66:
- pre = VexSimdPrefix.VEX_SIMD_66;
- break;
- case 0xF2:
- pre = VexSimdPrefix.VEX_SIMD_F2;
- break;
- case 0xF3:
- pre = VexSimdPrefix.VEX_SIMD_F3;
- break;
- default:
- pre = VexSimdPrefix.VEX_SIMD_NONE;
- break;
- }
- int encode;
- if (noNds) {
- encode = asm.simdPrefixAndEncode(src, Register.None, dst, pre, opc, attributes);
- } else {
- encode = asm.simdPrefixAndEncode(src, src, dst, pre, opc, attributes);
- }
+ asm.simdPrefix(src, nds, dst, size, prefix1, prefix2, size == QWORD);
asm.emitByte(op);
- asm.emitByte(0xC0 | encode);
+ asm.emitModRM(src, dst);
} else {
emitOpcode(asm, size, getRXB(src, dst), src.encoding, dst.encoding);
asm.emitModRM(src, dst);
@@ -1250,60 +583,14 @@
}
public final void emit(AMD64Assembler asm, OperandSize size, AMD64Address dst, Register src) {
- assert verify(asm, size, null, src);
- boolean isSimd = false;
-
- switch (op) {
- case 0x7E:
- case 0x11:
- isSimd = true;
- break;
- }
-
- int opc = 0;
- if (isSimd) {
- switch (prefix2) {
- case P_0F:
- opc = VexOpcode.VEX_OPCODE_0F;
- break;
- case P_0F38:
- opc = VexOpcode.VEX_OPCODE_0F_38;
- break;
- case P_0F3A:
- opc = VexOpcode.VEX_OPCODE_0F_3A;
- break;
- default:
- isSimd = false;
- break;
- }
- }
-
- if (isSimd) {
- int pre;
- boolean rexVexW = (size == QWORD) ? true : false;
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, rexVexW, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, asm.target);
- int curPrefix = size.sizePrefix | prefix1;
- switch (curPrefix) {
- case 0x66:
- pre = VexSimdPrefix.VEX_SIMD_66;
- break;
- case 0xF2:
- pre = VexSimdPrefix.VEX_SIMD_F2;
- break;
- case 0xF3:
- pre = VexSimdPrefix.VEX_SIMD_F3;
- break;
- default:
- pre = VexSimdPrefix.VEX_SIMD_NONE;
- break;
- }
- asm.simdPrefix(src, Register.None, dst, pre, opc, attributes);
+ assert verify(asm, size, src, null);
+ if (isSSEInstruction()) {
+ asm.simdPrefix(src, Register.None, dst, size, prefix1, prefix2, size == QWORD);
asm.emitByte(op);
- asm.emitOperandHelper(src, dst, 0);
} else {
emitOpcode(asm, size, getRXB(src, dst), src.encoding, 0);
- asm.emitOperandHelper(src, dst, 0);
}
+ asm.emitOperandHelper(src, dst, 0);
}
}
@@ -1382,17 +669,37 @@
}
public final void emit(AMD64Assembler asm, OperandSize size, Register dst, int imm) {
+ emit(asm, size, dst, imm, false);
+ }
+
+ public final void emit(AMD64Assembler asm, OperandSize size, Register dst, int imm, boolean annotateImm) {
assert verify(asm, size, dst, null);
+ int insnPos = asm.position();
emitOpcode(asm, size, getRXB(null, dst), 0, dst.encoding);
asm.emitModRM(ext, dst);
+ int immPos = asm.position();
emitImmediate(asm, size, imm);
+ int nextInsnPos = asm.position();
+ if (annotateImm && asm.codePatchingAnnotationConsumer != null) {
+ asm.codePatchingAnnotationConsumer.accept(new ImmediateOperandAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos));
+ }
}
public final void emit(AMD64Assembler asm, OperandSize size, AMD64Address dst, int imm) {
+ emit(asm, size, dst, imm, false);
+ }
+
+ public final void emit(AMD64Assembler asm, OperandSize size, AMD64Address dst, int imm, boolean annotateImm) {
assert verify(asm, size, null, null);
+ int insnPos = asm.position();
emitOpcode(asm, size, getRXB(null, dst), 0, 0);
asm.emitOperandHelper(ext, dst, immediateSize(size));
+ int immPos = asm.position();
emitImmediate(asm, size, imm);
+ int nextInsnPos = asm.position();
+ if (annotateImm && asm.codePatchingAnnotationConsumer != null) {
+ asm.codePatchingAnnotationConsumer.accept(new ImmediateOperandAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos));
+ }
}
}
@@ -1406,153 +713,66 @@
// @formatter:off
public static final AMD64RMIOp IMUL = new AMD64RMIOp("IMUL", false, 0x69);
public static final AMD64RMIOp IMUL_SX = new AMD64RMIOp("IMUL", true, 0x6B);
- public static final AMD64RMIOp ROUNDSS = new AMD64RMIOp("ROUNDSS", true, P_0F3A, 0x0A, OpAssertion.PackedDoubleAssertion);
- public static final AMD64RMIOp ROUNDSD = new AMD64RMIOp("ROUNDSD", true, P_0F3A, 0x0B, OpAssertion.PackedDoubleAssertion);
+ public static final AMD64RMIOp ROUNDSS = new AMD64RMIOp("ROUNDSS", true, P_0F3A, 0x0A, OpAssertion.PackedDoubleAssertion, CPUFeature.SSE4_1);
+ public static final AMD64RMIOp ROUNDSD = new AMD64RMIOp("ROUNDSD", true, P_0F3A, 0x0B, OpAssertion.PackedDoubleAssertion, CPUFeature.SSE4_1);
// @formatter:on
protected AMD64RMIOp(String opcode, boolean immIsByte, int op) {
- this(opcode, immIsByte, 0, op, OpAssertion.WordOrLargerAssertion);
+ this(opcode, immIsByte, 0, op, OpAssertion.WordOrLargerAssertion, null);
}
- protected AMD64RMIOp(String opcode, boolean immIsByte, int prefix, int op, OpAssertion assertion) {
- super(opcode, immIsByte, prefix, op, assertion);
+ protected AMD64RMIOp(String opcode, boolean immIsByte, int prefix, int op, OpAssertion assertion, CPUFeature feature) {
+ super(opcode, immIsByte, prefix, op, assertion, feature);
}
public final void emit(AMD64Assembler asm, OperandSize size, Register dst, Register src, int imm) {
assert verify(asm, size, dst, src);
- boolean isSimd = false;
- boolean noNds = false;
-
- switch (op) {
- case 0x0A:
- case 0x0B:
- isSimd = true;
- noNds = true;
- break;
- }
-
- int opc = 0;
- if (isSimd) {
- switch (prefix2) {
- case P_0F:
- opc = VexOpcode.VEX_OPCODE_0F;
- break;
- case P_0F38:
- opc = VexOpcode.VEX_OPCODE_0F_38;
- break;
- case P_0F3A:
- opc = VexOpcode.VEX_OPCODE_0F_3A;
+ if (isSSEInstruction()) {
+ Register nds = Register.None;
+ switch (op) {
+ case 0x0A:
+ case 0x0B:
+ nds = dst;
break;
default:
- isSimd = false;
break;
}
- }
-
- if (isSimd) {
- int pre;
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, asm.target);
- int curPrefix = size.sizePrefix | prefix1;
- switch (curPrefix) {
- case 0x66:
- pre = VexSimdPrefix.VEX_SIMD_66;
- break;
- case 0xF2:
- pre = VexSimdPrefix.VEX_SIMD_F2;
- break;
- case 0xF3:
- pre = VexSimdPrefix.VEX_SIMD_F3;
- break;
- default:
- pre = VexSimdPrefix.VEX_SIMD_NONE;
- break;
- }
- int encode;
- if (noNds) {
- encode = asm.simdPrefixAndEncode(dst, Register.None, src, pre, opc, attributes);
- } else {
- encode = asm.simdPrefixAndEncode(dst, dst, src, pre, opc, attributes);
- }
+ asm.simdPrefix(dst, nds, src, size, prefix1, prefix2, false);
asm.emitByte(op);
- asm.emitByte(0xC0 | encode);
- emitImmediate(asm, size, imm);
+ asm.emitModRM(dst, src);
} else {
emitOpcode(asm, size, getRXB(dst, src), dst.encoding, src.encoding);
asm.emitModRM(dst, src);
- emitImmediate(asm, size, imm);
}
+ emitImmediate(asm, size, imm);
}
public final void emit(AMD64Assembler asm, OperandSize size, Register dst, AMD64Address src, int imm) {
assert verify(asm, size, dst, null);
-
- boolean isSimd = false;
- boolean noNds = false;
-
- switch (op) {
- case 0x0A:
- case 0x0B:
- isSimd = true;
- noNds = true;
- break;
- }
-
- int opc = 0;
- if (isSimd) {
- switch (prefix2) {
- case P_0F:
- opc = VexOpcode.VEX_OPCODE_0F;
- break;
- case P_0F38:
- opc = VexOpcode.VEX_OPCODE_0F_38;
- break;
- case P_0F3A:
- opc = VexOpcode.VEX_OPCODE_0F_3A;
+ if (isSSEInstruction()) {
+ Register nds = Register.None;
+ switch (op) {
+ case 0x0A:
+ case 0x0B:
+ nds = dst;
break;
default:
- isSimd = false;
break;
}
- }
-
- if (isSimd) {
- int pre;
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, asm.target);
- int curPrefix = size.sizePrefix | prefix1;
- switch (curPrefix) {
- case 0x66:
- pre = VexSimdPrefix.VEX_SIMD_66;
- break;
- case 0xF2:
- pre = VexSimdPrefix.VEX_SIMD_F2;
- break;
- case 0xF3:
- pre = VexSimdPrefix.VEX_SIMD_F3;
- break;
- default:
- pre = VexSimdPrefix.VEX_SIMD_NONE;
- break;
- }
- if (noNds) {
- asm.simdPrefix(dst, Register.None, src, pre, opc, attributes);
- } else {
- asm.simdPrefix(dst, dst, src, pre, opc, attributes);
- }
+ asm.simdPrefix(dst, nds, src, size, prefix1, prefix2, false);
asm.emitByte(op);
- asm.emitOperandHelper(dst, src, immediateSize(size));
- emitImmediate(asm, size, imm);
} else {
emitOpcode(asm, size, getRXB(dst, src), dst.encoding, 0);
- asm.emitOperandHelper(dst, src, immediateSize(size));
- emitImmediate(asm, size, imm);
}
+ asm.emitOperandHelper(dst, src, immediateSize(size));
+ emitImmediate(asm, size, imm);
}
}
public static class SSEOp extends AMD64RMOp {
// @formatter:off
public static final SSEOp CVTSI2SS = new SSEOp("CVTSI2SS", 0xF3, P_0F, 0x2A, OpAssertion.IntToFloatAssertion);
- public static final SSEOp CVTSI2SD = new SSEOp("CVTSI2SS", 0xF2, P_0F, 0x2A, OpAssertion.IntToFloatAssertion);
+ public static final SSEOp CVTSI2SD = new SSEOp("CVTSI2SD", 0xF2, P_0F, 0x2A, OpAssertion.IntToFloatAssertion);
public static final SSEOp CVTTSS2SI = new SSEOp("CVTTSS2SI", 0xF3, P_0F, 0x2C, OpAssertion.FloatToIntAssertion);
public static final SSEOp CVTTSD2SI = new SSEOp("CVTTSD2SI", 0xF2, P_0F, 0x2C, OpAssertion.FloatToIntAssertion);
public static final SSEOp UCOMIS = new SSEOp("UCOMIS", P_0F, 0x2E, OpAssertion.PackedFloatAssertion);
@@ -1584,33 +804,6 @@
}
}
- public static class AVXOp extends AMD64RRMOp {
- // @formatter:off
- public static final AVXOp AND = new AVXOp("AND", P_0F, 0x54, OpAssertion.PackedFloatAssertion);
- public static final AVXOp ANDN = new AVXOp("ANDN", P_0F, 0x55, OpAssertion.PackedFloatAssertion);
- public static final AVXOp OR = new AVXOp("OR", P_0F, 0x56, OpAssertion.PackedFloatAssertion);
- public static final AVXOp XOR = new AVXOp("XOR", P_0F, 0x57, OpAssertion.PackedFloatAssertion);
- public static final AVXOp ADD = new AVXOp("ADD", P_0F, 0x58);
- public static final AVXOp MUL = new AVXOp("MUL", P_0F, 0x59);
- public static final AVXOp SUB = new AVXOp("SUB", P_0F, 0x5C);
- public static final AVXOp MIN = new AVXOp("MIN", P_0F, 0x5D);
- public static final AVXOp DIV = new AVXOp("DIV", P_0F, 0x5E);
- public static final AVXOp MAX = new AVXOp("MAX", P_0F, 0x5F);
- // @formatter:on
-
- protected AVXOp(String opcode, int prefix, int op) {
- this(opcode, prefix, op, OpAssertion.FloatAssertion);
- }
-
- protected AVXOp(String opcode, int prefix, int op, OpAssertion assertion) {
- this(opcode, 0, prefix, op, assertion);
- }
-
- protected AVXOp(String opcode, int mandatoryPrefix, int prefix, int op, OpAssertion assertion) {
- super(opcode, mandatoryPrefix, prefix, op, assertion, CPUFeature.AVX);
- }
- }
-
/**
* Arithmetic operation with operand order of RM, MR or MI.
*/
@@ -1700,6 +893,661 @@
}
}
+ private enum AVXOpAssertion {
+ AVX1(CPUFeature.AVX, CPUFeature.AVX),
+ AVX1_2(CPUFeature.AVX, CPUFeature.AVX2),
+ AVX2(CPUFeature.AVX2, CPUFeature.AVX2),
+ AVX1_128ONLY(CPUFeature.AVX, null),
+ AVX1_256ONLY(null, CPUFeature.AVX),
+ AVX2_256ONLY(null, CPUFeature.AVX2),
+ XMM_CPU(CPUFeature.AVX, null, XMM, null, CPU, null),
+ XMM_XMM_CPU(CPUFeature.AVX, null, XMM, XMM, CPU, null),
+ CPU_XMM(CPUFeature.AVX, null, CPU, null, XMM, null),
+ AVX1_2_CPU_XMM(CPUFeature.AVX, CPUFeature.AVX2, CPU, null, XMM, null);
+
+ private final CPUFeature avx128feature;
+ private final CPUFeature avx256feature;
+
+ private final RegisterCategory rCategory;
+ private final RegisterCategory vCategory;
+ private final RegisterCategory mCategory;
+ private final RegisterCategory imm8Category;
+
+ AVXOpAssertion(CPUFeature avx128feature, CPUFeature avx256feature) {
+ this(avx128feature, avx256feature, XMM, XMM, XMM, XMM);
+ }
+
+ AVXOpAssertion(CPUFeature avx128feature, CPUFeature avx256feature, RegisterCategory rCategory, RegisterCategory vCategory, RegisterCategory mCategory, RegisterCategory imm8Category) {
+ this.avx128feature = avx128feature;
+ this.avx256feature = avx256feature;
+ this.rCategory = rCategory;
+ this.vCategory = vCategory;
+ this.mCategory = mCategory;
+ this.imm8Category = imm8Category;
+ }
+
+ public boolean check(AMD64 arch, AVXSize size, Register r, Register v, Register m) {
+ return check(arch, size, r, v, m, null);
+ }
+
+ public boolean check(AMD64 arch, AVXSize size, Register r, Register v, Register m, Register imm8) {
+ switch (size) {
+ case XMM:
+ assert avx128feature != null && arch.getFeatures().contains(avx128feature) : "emitting illegal 128 bit instruction";
+ break;
+ case YMM:
+ assert avx256feature != null && arch.getFeatures().contains(avx256feature) : "emitting illegal 256 bit instruction";
+ break;
+ }
+ if (r != null) {
+ assert r.getRegisterCategory().equals(rCategory);
+ }
+ if (v != null) {
+ assert v.getRegisterCategory().equals(vCategory);
+ }
+ if (m != null) {
+ assert m.getRegisterCategory().equals(mCategory);
+ }
+ if (imm8 != null) {
+ assert imm8.getRegisterCategory().equals(imm8Category);
+ }
+ return true;
+ }
+
+ public boolean supports(EnumSet<CPUFeature> features, AVXSize avxSize) {
+ switch (avxSize) {
+ case XMM:
+ return avx128feature != null && features.contains(avx128feature);
+ case YMM:
+ return avx256feature != null && features.contains(avx256feature);
+ default:
+ throw GraalError.shouldNotReachHere();
+ }
+ }
+ }
+
+ /**
+ * Base class for VEX-encoded instructions.
+ */
+ public static class VexOp {
+ protected final int pp;
+ protected final int mmmmm;
+ protected final int w;
+ protected final int op;
+
+ private final String opcode;
+ protected final AVXOpAssertion assertion;
+
+ protected VexOp(String opcode, int pp, int mmmmm, int w, int op, AVXOpAssertion assertion) {
+ this.pp = pp;
+ this.mmmmm = mmmmm;
+ this.w = w;
+ this.op = op;
+ this.opcode = opcode;
+ this.assertion = assertion;
+ }
+
+ public boolean isSupported(AMD64Assembler vasm, AMD64Kind kind) {
+ return assertion.supports(((AMD64) vasm.target.arch).getFeatures(), AVXKind.getRegisterSize(kind));
+ }
+
+ public final boolean isSupported(AMD64Assembler vasm, AVXSize size) {
+ return assertion.supports(((AMD64) vasm.target.arch).getFeatures(), size);
+ }
+
+ @Override
+ public String toString() {
+ return opcode;
+ }
+ }
+
+ /**
+ * VEX-encoded instructions with an operand order of RM, but the M operand must be a register.
+ */
+ public static class VexRROp extends VexOp {
+ // @formatter:off
+ public static final VexRROp VMASKMOVDQU = new VexRROp("VMASKMOVDQU", P_66, M_0F, WIG, 0xF7, AVXOpAssertion.AVX1_128ONLY);
+ // @formatter:on
+
+ protected VexRROp(String opcode, int pp, int mmmmm, int w, int op) {
+ this(opcode, pp, mmmmm, w, op, AVXOpAssertion.AVX1);
+ }
+
+ protected VexRROp(String opcode, int pp, int mmmmm, int w, int op, AVXOpAssertion assertion) {
+ super(opcode, pp, mmmmm, w, op, assertion);
+ }
+
+ public void emit(AMD64Assembler asm, AVXSize size, Register dst, Register src) {
+ assert assertion.check((AMD64) asm.target.arch, size, dst, null, src);
+ assert op != 0x1A || op != 0x5A;
+ asm.vexPrefix(dst, Register.None, src, size, pp, mmmmm, w);
+ asm.emitByte(op);
+ asm.emitModRM(dst, src);
+ }
+ }
+
+ /**
+ * VEX-encoded instructions with an operand order of RM.
+ */
+ public static class VexRMOp extends VexRROp {
+ // @formatter:off
+ public static final VexRMOp VCVTTSS2SI = new VexRMOp("VCVTTSS2SI", P_F3, M_0F, W0, 0x2C, AVXOpAssertion.CPU_XMM);
+ public static final VexRMOp VCVTTSS2SQ = new VexRMOp("VCVTTSS2SQ", P_F3, M_0F, W1, 0x2C, AVXOpAssertion.CPU_XMM);
+ public static final VexRMOp VCVTTSD2SI = new VexRMOp("VCVTTSD2SI", P_F2, M_0F, W0, 0x2C, AVXOpAssertion.CPU_XMM);
+ public static final VexRMOp VCVTTSD2SQ = new VexRMOp("VCVTTSD2SQ", P_F2, M_0F, W1, 0x2C, AVXOpAssertion.CPU_XMM);
+ public static final VexRMOp VCVTPS2PD = new VexRMOp("VCVTPS2PD", P_, M_0F, WIG, 0x5A);
+ public static final VexRMOp VCVTPD2PS = new VexRMOp("VCVTPD2PS", P_66, M_0F, WIG, 0x5A);
+ public static final VexRMOp VCVTDQ2PS = new VexRMOp("VCVTDQ2PS", P_, M_0F, WIG, 0x5B);
+ public static final VexRMOp VCVTTPS2DQ = new VexRMOp("VCVTTPS2DQ", P_F3, M_0F, WIG, 0x5B);
+ public static final VexRMOp VCVTTPD2DQ = new VexRMOp("VCVTTPD2DQ", P_66, M_0F, WIG, 0xE6);
+ public static final VexRMOp VCVTDQ2PD = new VexRMOp("VCVTDQ2PD", P_F3, M_0F, WIG, 0xE6);
+ public static final VexRMOp VBROADCASTSS = new VexRMOp("VBROADCASTSS", P_66, M_0F38, W0, 0x18);
+ public static final VexRMOp VBROADCASTSD = new VexRMOp("VBROADCASTSD", P_66, M_0F38, W0, 0x19, AVXOpAssertion.AVX1_256ONLY);
+ public static final VexRMOp VBROADCASTF128 = new VexRMOp("VBROADCASTF128", P_66, M_0F38, W0, 0x1A, AVXOpAssertion.AVX1_256ONLY);
+ public static final VexRMOp VPBROADCASTI128 = new VexRMOp("VPBROADCASTI128", P_66, M_0F38, W0, 0x5A, AVXOpAssertion.AVX2_256ONLY);
+ public static final VexRMOp VPBROADCASTB = new VexRMOp("VPBROADCASTB", P_66, M_0F38, W0, 0x78, AVXOpAssertion.AVX2);
+ public static final VexRMOp VPBROADCASTW = new VexRMOp("VPBROADCASTW", P_66, M_0F38, W0, 0x79, AVXOpAssertion.AVX2);
+ public static final VexRMOp VPBROADCASTD = new VexRMOp("VPBROADCASTD", P_66, M_0F38, W0, 0x58, AVXOpAssertion.AVX2);
+ public static final VexRMOp VPBROADCASTQ = new VexRMOp("VPBROADCASTQ", P_66, M_0F38, W0, 0x59, AVXOpAssertion.AVX2);
+ public static final VexRMOp VPMOVMSKB = new VexRMOp("VPMOVMSKB", P_66, M_0F, WIG, 0xD7, AVXOpAssertion.AVX1_2_CPU_XMM);
+ public static final VexRMOp VPMOVSXBW = new VexRMOp("VPMOVSXBW", P_66, M_0F38, WIG, 0x20);
+ public static final VexRMOp VPMOVSXBD = new VexRMOp("VPMOVSXBD", P_66, M_0F38, WIG, 0x21);
+ public static final VexRMOp VPMOVSXBQ = new VexRMOp("VPMOVSXBQ", P_66, M_0F38, WIG, 0x22);
+ public static final VexRMOp VPMOVSXWD = new VexRMOp("VPMOVSXWD", P_66, M_0F38, WIG, 0x23);
+ public static final VexRMOp VPMOVSXWQ = new VexRMOp("VPMOVSXWQ", P_66, M_0F38, WIG, 0x24);
+ public static final VexRMOp VPMOVSXDQ = new VexRMOp("VPMOVSXDQ", P_66, M_0F38, WIG, 0x25);
+ public static final VexRMOp VPMOVZXBW = new VexRMOp("VPMOVZXBW", P_66, M_0F38, WIG, 0x30);
+ public static final VexRMOp VPMOVZXBD = new VexRMOp("VPMOVZXBD", P_66, M_0F38, WIG, 0x31);
+ public static final VexRMOp VPMOVZXBQ = new VexRMOp("VPMOVZXBQ", P_66, M_0F38, WIG, 0x32);
+ public static final VexRMOp VPMOVZXWD = new VexRMOp("VPMOVZXWD", P_66, M_0F38, WIG, 0x33);
+ public static final VexRMOp VPMOVZXWQ = new VexRMOp("VPMOVZXWQ", P_66, M_0F38, WIG, 0x34);
+ public static final VexRMOp VPMOVZXDQ = new VexRMOp("VPMOVZXDQ", P_66, M_0F38, WIG, 0x35);
+ public static final VexRMOp VPTEST = new VexRMOp("VPTEST", P_66, M_0F38, WIG, 0x17);
+ public static final VexRMOp VSQRTPD = new VexRMOp("VSQRTPD", P_66, M_0F, WIG, 0x51);
+ public static final VexRMOp VSQRTPS = new VexRMOp("VSQRTPS", P_, M_0F, WIG, 0x51);
+ public static final VexRMOp VSQRTSD = new VexRMOp("VSQRTSD", P_F2, M_0F, WIG, 0x51);
+ public static final VexRMOp VSQRTSS = new VexRMOp("VSQRTSS", P_F3, M_0F, WIG, 0x51);
+ public static final VexRMOp VUCOMISS = new VexRMOp("VUCOMISS", P_, M_0F, WIG, 0x2E);
+ public static final VexRMOp VUCOMISD = new VexRMOp("VUCOMISD", P_66, M_0F, WIG, 0x2E);
+ // @formatter:on
+
+ protected VexRMOp(String opcode, int pp, int mmmmm, int w, int op) {
+ this(opcode, pp, mmmmm, w, op, AVXOpAssertion.AVX1);
+ }
+
+ protected VexRMOp(String opcode, int pp, int mmmmm, int w, int op, AVXOpAssertion assertion) {
+ super(opcode, pp, mmmmm, w, op, assertion);
+ }
+
+ public void emit(AMD64Assembler asm, AVXSize size, Register dst, AMD64Address src) {
+ assert assertion.check((AMD64) asm.target.arch, size, dst, null, null);
+ asm.vexPrefix(dst, Register.None, src, size, pp, mmmmm, w);
+ asm.emitByte(op);
+ asm.emitOperandHelper(dst, src, 0);
+ }
+ }
+
+ /**
+ * VEX-encoded move instructions.
+ * <p>
+ * These instructions have two opcodes: op is the forward move instruction with an operand order
+ * of RM, and opReverse is the reverse move instruction with an operand order of MR.
+ */
+ public static final class VexMoveOp extends VexRMOp {
+ // @formatter:off
+ public static final VexMoveOp VMOVDQA = new VexMoveOp("VMOVDQA", P_66, M_0F, WIG, 0x6F, 0x7F);
+ public static final VexMoveOp VMOVDQU = new VexMoveOp("VMOVDQU", P_F3, M_0F, WIG, 0x6F, 0x7F);
+ public static final VexMoveOp VMOVAPS = new VexMoveOp("VMOVAPS", P_, M_0F, WIG, 0x28, 0x29);
+ public static final VexMoveOp VMOVAPD = new VexMoveOp("VMOVAPD", P_66, M_0F, WIG, 0x28, 0x29);
+ public static final VexMoveOp VMOVUPS = new VexMoveOp("VMOVUPS", P_, M_0F, WIG, 0x10, 0x11);
+ public static final VexMoveOp VMOVUPD = new VexMoveOp("VMOVUPD", P_66, M_0F, WIG, 0x10, 0x11);
+ public static final VexMoveOp VMOVSS = new VexMoveOp("VMOVSS", P_F3, M_0F, WIG, 0x10, 0x11);
+ public static final VexMoveOp VMOVSD = new VexMoveOp("VMOVSD", P_F2, M_0F, WIG, 0x10, 0x11);
+ public static final VexMoveOp VMOVD = new VexMoveOp("VMOVD", P_66, M_0F, W0, 0x6E, 0x7E, AVXOpAssertion.XMM_CPU);
+ public static final VexMoveOp VMOVQ = new VexMoveOp("VMOVQ", P_66, M_0F, W1, 0x6E, 0x7E, AVXOpAssertion.XMM_CPU);
+ // @formatter:on
+
+ private final int opReverse;
+
+ private VexMoveOp(String opcode, int pp, int mmmmm, int w, int op, int opReverse) {
+ this(opcode, pp, mmmmm, w, op, opReverse, AVXOpAssertion.AVX1);
+ }
+
+ private VexMoveOp(String opcode, int pp, int mmmmm, int w, int op, int opReverse, AVXOpAssertion assertion) {
+ super(opcode, pp, mmmmm, w, op, assertion);
+ this.opReverse = opReverse;
+ }
+
+ public void emit(AMD64Assembler asm, AVXSize size, AMD64Address dst, Register src) {
+ assert assertion.check((AMD64) asm.target.arch, size, src, null, null);
+ asm.vexPrefix(src, Register.None, dst, size, pp, mmmmm, w);
+ asm.emitByte(opReverse);
+ asm.emitOperandHelper(src, dst, 0);
+ }
+
+ public void emitReverse(AMD64Assembler asm, AVXSize size, Register dst, Register src) {
+ assert assertion.check((AMD64) asm.target.arch, size, src, null, dst);
+ asm.vexPrefix(src, Register.None, dst, size, pp, mmmmm, w);
+ asm.emitByte(opReverse);
+ asm.emitModRM(src, dst);
+ }
+ }
+
+ public interface VexRRIOp {
+ void emit(AMD64Assembler asm, AVXSize size, Register dst, Register src, int imm8);
+ }
+
+ /**
+ * VEX-encoded instructions with an operand order of RMI.
+ */
+ public static final class VexRMIOp extends VexOp implements VexRRIOp {
+ // @formatter:off
+ public static final VexRMIOp VPERMQ = new VexRMIOp("VPERMQ", P_66, M_0F3A, W1, 0x00, AVXOpAssertion.AVX2_256ONLY);
+ public static final VexRMIOp VPSHUFLW = new VexRMIOp("VPSHUFLW", P_F2, M_0F, WIG, 0x70, AVXOpAssertion.AVX1_2);
+ public static final VexRMIOp VPSHUFHW = new VexRMIOp("VPSHUFHW", P_F3, M_0F, WIG, 0x70, AVXOpAssertion.AVX1_2);
+ public static final VexRMIOp VPSHUFD = new VexRMIOp("VPSHUFD", P_66, M_0F, WIG, 0x70, AVXOpAssertion.AVX1_2);
+ // @formatter:on
+
+ private VexRMIOp(String opcode, int pp, int mmmmm, int w, int op, AVXOpAssertion assertion) {
+ super(opcode, pp, mmmmm, w, op, assertion);
+ }
+
+ @Override
+ public void emit(AMD64Assembler asm, AVXSize size, Register dst, Register src, int imm8) {
+ assert assertion.check((AMD64) asm.target.arch, size, dst, null, src);
+ asm.vexPrefix(dst, Register.None, src, size, pp, mmmmm, w);
+ asm.emitByte(op);
+ asm.emitModRM(dst, src);
+ asm.emitByte(imm8);
+ }
+
+ public void emit(AMD64Assembler asm, AVXSize size, Register dst, AMD64Address src, int imm8) {
+ assert assertion.check((AMD64) asm.target.arch, size, dst, null, null);
+ asm.vexPrefix(dst, Register.None, src, size, pp, mmmmm, w);
+ asm.emitByte(op);
+ asm.emitOperandHelper(dst, src, 1);
+ asm.emitByte(imm8);
+ }
+ }
+
+ /**
+ * VEX-encoded instructions with an operand order of MRI.
+ */
+ public static final class VexMRIOp extends VexOp implements VexRRIOp {
+ // @formatter:off
+ public static final VexMRIOp VEXTRACTF128 = new VexMRIOp("VEXTRACTF128", P_66, M_0F3A, W0, 0x19, AVXOpAssertion.AVX1_256ONLY);
+ public static final VexMRIOp VEXTRACTI128 = new VexMRIOp("VEXTRACTI128", P_66, M_0F3A, W0, 0x39, AVXOpAssertion.AVX2_256ONLY);
+ public static final VexMRIOp VPEXTRB = new VexMRIOp("VPEXTRB", P_66, M_0F3A, W0, 0x14, AVXOpAssertion.XMM_CPU);
+ public static final VexMRIOp VPEXTRW = new VexMRIOp("VPEXTRW", P_66, M_0F3A, W0, 0x15, AVXOpAssertion.XMM_CPU);
+ public static final VexMRIOp VPEXTRD = new VexMRIOp("VPEXTRD", P_66, M_0F3A, W0, 0x16, AVXOpAssertion.XMM_CPU);
+ public static final VexMRIOp VPEXTRQ = new VexMRIOp("VPEXTRQ", P_66, M_0F3A, W1, 0x16, AVXOpAssertion.XMM_CPU);
+ // @formatter:on
+
+ private VexMRIOp(String opcode, int pp, int mmmmm, int w, int op, AVXOpAssertion assertion) {
+ super(opcode, pp, mmmmm, w, op, assertion);
+ }
+
+ @Override
+ public void emit(AMD64Assembler asm, AVXSize size, Register dst, Register src, int imm8) {
+ assert assertion.check((AMD64) asm.target.arch, size, src, null, dst);
+ asm.vexPrefix(src, Register.None, dst, size, pp, mmmmm, w);
+ asm.emitByte(op);
+ asm.emitModRM(src, dst);
+ asm.emitByte(imm8);
+ }
+
+ public void emit(AMD64Assembler asm, AVXSize size, AMD64Address dst, Register src, int imm8) {
+ assert assertion.check((AMD64) asm.target.arch, size, src, null, null);
+ asm.vexPrefix(src, Register.None, dst, size, pp, mmmmm, w);
+ asm.emitByte(op);
+ asm.emitOperandHelper(src, dst, 1);
+ asm.emitByte(imm8);
+ }
+ }
+
+ /**
+ * VEX-encoded instructions with an operand order of RVMR.
+ */
+ public static class VexRVMROp extends VexOp {
+ // @formatter:off
+ public static final VexRVMROp VPBLENDVB = new VexRVMROp("VPBLENDVB", P_66, M_0F3A, W0, 0x4C, AVXOpAssertion.AVX1_2);
+ public static final VexRVMROp VPBLENDVPS = new VexRVMROp("VPBLENDVPS", P_66, M_0F3A, W0, 0x4A, AVXOpAssertion.AVX1);
+ public static final VexRVMROp VPBLENDVPD = new VexRVMROp("VPBLENDVPD", P_66, M_0F3A, W0, 0x4B, AVXOpAssertion.AVX1);
+ // @formatter:on
+
+ protected VexRVMROp(String opcode, int pp, int mmmmm, int w, int op, AVXOpAssertion assertion) {
+ super(opcode, pp, mmmmm, w, op, assertion);
+ }
+
+ public void emit(AMD64Assembler asm, AVXSize size, Register dst, Register mask, Register src1, Register src2) {
+ assert assertion.check((AMD64) asm.target.arch, size, dst, mask, src1, src2);
+ asm.vexPrefix(dst, src1, src2, size, pp, mmmmm, w);
+ asm.emitByte(op);
+ asm.emitModRM(dst, src2);
+ asm.emitByte(mask.encoding() << 4);
+ }
+
+ public void emit(AMD64Assembler asm, AVXSize size, Register dst, Register mask, Register src1, AMD64Address src2) {
+ assert assertion.check((AMD64) asm.target.arch, size, dst, mask, src1, null);
+ asm.vexPrefix(dst, src1, src2, size, pp, mmmmm, w);
+ asm.emitByte(op);
+ asm.emitOperandHelper(dst, src2, 0);
+ asm.emitByte(mask.encoding() << 4);
+ }
+ }
+
+ /**
+ * VEX-encoded instructions with an operand order of RVM.
+ */
+ public static class VexRVMOp extends VexOp {
+ // @formatter:off
+ public static final VexRVMOp VANDPS = new VexRVMOp("VANDPS", P_, M_0F, WIG, 0x54);
+ public static final VexRVMOp VANDPD = new VexRVMOp("VANDPD", P_66, M_0F, WIG, 0x54);
+ public static final VexRVMOp VANDNPS = new VexRVMOp("VANDNPS", P_, M_0F, WIG, 0x55);
+ public static final VexRVMOp VANDNPD = new VexRVMOp("VANDNPD", P_66, M_0F, WIG, 0x55);
+ public static final VexRVMOp VORPS = new VexRVMOp("VORPS", P_, M_0F, WIG, 0x56);
+ public static final VexRVMOp VORPD = new VexRVMOp("VORPD", P_66, M_0F, WIG, 0x56);
+ public static final VexRVMOp VXORPS = new VexRVMOp("VXORPS", P_, M_0F, WIG, 0x57);
+ public static final VexRVMOp VXORPD = new VexRVMOp("VXORPD", P_66, M_0F, WIG, 0x57);
+ public static final VexRVMOp VADDPS = new VexRVMOp("VADDPS", P_, M_0F, WIG, 0x58);
+ public static final VexRVMOp VADDPD = new VexRVMOp("VADDPD", P_66, M_0F, WIG, 0x58);
+ public static final VexRVMOp VADDSS = new VexRVMOp("VADDSS", P_F3, M_0F, WIG, 0x58);
+ public static final VexRVMOp VADDSD = new VexRVMOp("VADDSD", P_F2, M_0F, WIG, 0x58);
+ public static final VexRVMOp VMULPS = new VexRVMOp("VMULPS", P_, M_0F, WIG, 0x59);
+ public static final VexRVMOp VMULPD = new VexRVMOp("VMULPD", P_66, M_0F, WIG, 0x59);
+ public static final VexRVMOp VMULSS = new VexRVMOp("VMULSS", P_F3, M_0F, WIG, 0x59);
+ public static final VexRVMOp VMULSD = new VexRVMOp("VMULSD", P_F2, M_0F, WIG, 0x59);
+ public static final VexRVMOp VSUBPS = new VexRVMOp("VSUBPS", P_, M_0F, WIG, 0x5C);
+ public static final VexRVMOp VSUBPD = new VexRVMOp("VSUBPD", P_66, M_0F, WIG, 0x5C);
+ public static final VexRVMOp VSUBSS = new VexRVMOp("VSUBSS", P_F3, M_0F, WIG, 0x5C);
+ public static final VexRVMOp VSUBSD = new VexRVMOp("VSUBSD", P_F2, M_0F, WIG, 0x5C);
+ public static final VexRVMOp VMINPS = new VexRVMOp("VMINPS", P_, M_0F, WIG, 0x5D);
+ public static final VexRVMOp VMINPD = new VexRVMOp("VMINPD", P_66, M_0F, WIG, 0x5D);
+ public static final VexRVMOp VMINSS = new VexRVMOp("VMINSS", P_F3, M_0F, WIG, 0x5D);
+ public static final VexRVMOp VMINSD = new VexRVMOp("VMINSD", P_F2, M_0F, WIG, 0x5D);
+ public static final VexRVMOp VDIVPS = new VexRVMOp("VDIVPS", P_, M_0F, WIG, 0x5E);
+ public static final VexRVMOp VDIVPD = new VexRVMOp("VDIVPD", P_66, M_0F, WIG, 0x5E);
+ public static final VexRVMOp VDIVSS = new VexRVMOp("VDIVPS", P_F3, M_0F, WIG, 0x5E);
+ public static final VexRVMOp VDIVSD = new VexRVMOp("VDIVPD", P_F2, M_0F, WIG, 0x5E);
+ public static final VexRVMOp VMAXPS = new VexRVMOp("VMAXPS", P_, M_0F, WIG, 0x5F);
+ public static final VexRVMOp VMAXPD = new VexRVMOp("VMAXPD", P_66, M_0F, WIG, 0x5F);
+ public static final VexRVMOp VMAXSS = new VexRVMOp("VMAXSS", P_F3, M_0F, WIG, 0x5F);
+ public static final VexRVMOp VMAXSD = new VexRVMOp("VMAXSD", P_F2, M_0F, WIG, 0x5F);
+ public static final VexRVMOp VADDSUBPS = new VexRVMOp("VADDSUBPS", P_F2, M_0F, WIG, 0xD0);
+ public static final VexRVMOp VADDSUBPD = new VexRVMOp("VADDSUBPD", P_66, M_0F, WIG, 0xD0);
+ public static final VexRVMOp VPAND = new VexRVMOp("VPAND", P_66, M_0F, WIG, 0xDB, AVXOpAssertion.AVX1_2);
+ public static final VexRVMOp VPOR = new VexRVMOp("VPOR", P_66, M_0F, WIG, 0xEB, AVXOpAssertion.AVX1_2);
+ public static final VexRVMOp VPXOR = new VexRVMOp("VPXOR", P_66, M_0F, WIG, 0xEF, AVXOpAssertion.AVX1_2);
+ public static final VexRVMOp VPADDB = new VexRVMOp("VPADDB", P_66, M_0F, WIG, 0xFC, AVXOpAssertion.AVX1_2);
+ public static final VexRVMOp VPADDW = new VexRVMOp("VPADDW", P_66, M_0F, WIG, 0xFD, AVXOpAssertion.AVX1_2);
+ public static final VexRVMOp VPADDD = new VexRVMOp("VPADDD", P_66, M_0F, WIG, 0xFE, AVXOpAssertion.AVX1_2);
+ public static final VexRVMOp VPADDQ = new VexRVMOp("VPADDQ", P_66, M_0F, WIG, 0xD4, AVXOpAssertion.AVX1_2);
+ public static final VexRVMOp VPMULHUW = new VexRVMOp("VPMULHUW", P_66, M_0F, WIG, 0xE4, AVXOpAssertion.AVX1_2);
+ public static final VexRVMOp VPMULHW = new VexRVMOp("VPMULHW", P_66, M_0F, WIG, 0xE5, AVXOpAssertion.AVX1_2);
+ public static final VexRVMOp VPMULLW = new VexRVMOp("VPMULLW", P_66, M_0F, WIG, 0xD5, AVXOpAssertion.AVX1_2);
+ public static final VexRVMOp VPMULLD = new VexRVMOp("VPMULLD", P_66, M_0F38, WIG, 0x40, AVXOpAssertion.AVX1_2);
+ public static final VexRVMOp VPSUBB = new VexRVMOp("VPSUBB", P_66, M_0F, WIG, 0xF8, AVXOpAssertion.AVX1_2);
+ public static final VexRVMOp VPSUBW = new VexRVMOp("VPSUBW", P_66, M_0F, WIG, 0xF9, AVXOpAssertion.AVX1_2);
+ public static final VexRVMOp VPSUBD = new VexRVMOp("VPSUBD", P_66, M_0F, WIG, 0xFA, AVXOpAssertion.AVX1_2);
+ public static final VexRVMOp VPSUBQ = new VexRVMOp("VPSUBQ", P_66, M_0F, WIG, 0xFB, AVXOpAssertion.AVX1_2);
+ public static final VexRVMOp VPSHUFB = new VexRVMOp("VPSHUFB", P_66, M_0F38, WIG, 0x00, AVXOpAssertion.AVX1_2);
+ public static final VexRVMOp VCVTSD2SS = new VexRVMOp("VCVTSD2SS", P_F2, M_0F, WIG, 0x5A);
+ public static final VexRVMOp VCVTSS2SD = new VexRVMOp("VCVTSS2SD", P_F3, M_0F, WIG, 0x5A);
+ public static final VexRVMOp VCVTSI2SD = new VexRVMOp("VCVTSI2SD", P_F2, M_0F, W0, 0x2A, AVXOpAssertion.XMM_XMM_CPU);
+ public static final VexRVMOp VCVTSQ2SD = new VexRVMOp("VCVTSQ2SD", P_F2, M_0F, W1, 0x2A, AVXOpAssertion.XMM_XMM_CPU);
+ public static final VexRVMOp VCVTSI2SS = new VexRVMOp("VCVTSI2SS", P_F3, M_0F, W0, 0x2A, AVXOpAssertion.XMM_XMM_CPU);
+ public static final VexRVMOp VCVTSQ2SS = new VexRVMOp("VCVTSQ2SS", P_F3, M_0F, W1, 0x2A, AVXOpAssertion.XMM_XMM_CPU);
+ public static final VexRVMOp VPCMPEQB = new VexRVMOp("VPCMPEQB", P_66, M_0F, WIG, 0x74, AVXOpAssertion.AVX1_2);
+ public static final VexRVMOp VPCMPEQW = new VexRVMOp("VPCMPEQW", P_66, M_0F, WIG, 0x75, AVXOpAssertion.AVX1_2);
+ public static final VexRVMOp VPCMPEQD = new VexRVMOp("VPCMPEQD", P_66, M_0F, WIG, 0x76, AVXOpAssertion.AVX1_2);
+ public static final VexRVMOp VPCMPEQQ = new VexRVMOp("VPCMPEQQ", P_66, M_0F38, WIG, 0x29, AVXOpAssertion.AVX1_2);
+ public static final VexRVMOp VPCMPGTB = new VexRVMOp("VPCMPGTB", P_66, M_0F, WIG, 0x64, AVXOpAssertion.AVX1_2);
+ public static final VexRVMOp VPCMPGTW = new VexRVMOp("VPCMPGTW", P_66, M_0F, WIG, 0x65, AVXOpAssertion.AVX1_2);
+ public static final VexRVMOp VPCMPGTD = new VexRVMOp("VPCMPGTD", P_66, M_0F, WIG, 0x66, AVXOpAssertion.AVX1_2);
+ public static final VexRVMOp VPCMPGTQ = new VexRVMOp("VPCMPGTQ", P_66, M_0F38, WIG, 0x37, AVXOpAssertion.AVX1_2);
+ // @formatter:on
+
+ private VexRVMOp(String opcode, int pp, int mmmmm, int w, int op) {
+ this(opcode, pp, mmmmm, w, op, AVXOpAssertion.AVX1);
+ }
+
+ protected VexRVMOp(String opcode, int pp, int mmmmm, int w, int op, AVXOpAssertion assertion) {
+ super(opcode, pp, mmmmm, w, op, assertion);
+ }
+
+ public void emit(AMD64Assembler asm, AVXSize size, Register dst, Register src1, Register src2) {
+ assert assertion.check((AMD64) asm.target.arch, size, dst, src1, src2);
+ asm.vexPrefix(dst, src1, src2, size, pp, mmmmm, w);
+ asm.emitByte(op);
+ asm.emitModRM(dst, src2);
+ }
+
+ public void emit(AMD64Assembler asm, AVXSize size, Register dst, Register src1, AMD64Address src2) {
+ assert assertion.check((AMD64) asm.target.arch, size, dst, src1, null);
+ asm.vexPrefix(dst, src1, src2, size, pp, mmmmm, w);
+ asm.emitByte(op);
+ asm.emitOperandHelper(dst, src2, 0);
+ }
+ }
+
+ /**
+ * VEX-encoded shift instructions with an operand order of either RVM or VMI.
+ */
+ public static final class VexShiftOp extends VexRVMOp implements VexRRIOp {
+ // @formatter:off
+ public static final VexShiftOp VPSRLW = new VexShiftOp("VPSRLW", P_66, M_0F, WIG, 0xD1, 0x71, 2);
+ public static final VexShiftOp VPSRLD = new VexShiftOp("VPSRLD", P_66, M_0F, WIG, 0xD2, 0x72, 2);
+ public static final VexShiftOp VPSRLQ = new VexShiftOp("VPSRLQ", P_66, M_0F, WIG, 0xD3, 0x73, 2);
+ public static final VexShiftOp VPSRAW = new VexShiftOp("VPSRAW", P_66, M_0F, WIG, 0xE1, 0x71, 4);
+ public static final VexShiftOp VPSRAD = new VexShiftOp("VPSRAD", P_66, M_0F, WIG, 0xE2, 0x72, 4);
+ public static final VexShiftOp VPSLLW = new VexShiftOp("VPSLLW", P_66, M_0F, WIG, 0xF1, 0x71, 6);
+ public static final VexShiftOp VPSLLD = new VexShiftOp("VPSLLD", P_66, M_0F, WIG, 0xF2, 0x72, 6);
+ public static final VexShiftOp VPSLLQ = new VexShiftOp("VPSLLQ", P_66, M_0F, WIG, 0xF3, 0x73, 6);
+ // @formatter:on
+
+ private final int immOp;
+ private final int r;
+
+ private VexShiftOp(String opcode, int pp, int mmmmm, int w, int op, int immOp, int r) {
+ super(opcode, pp, mmmmm, w, op, AVXOpAssertion.AVX1_2);
+ this.immOp = immOp;
+ this.r = r;
+ }
+
+ @Override
+ public void emit(AMD64Assembler asm, AVXSize size, Register dst, Register src, int imm8) {
+ assert assertion.check((AMD64) asm.target.arch, size, null, dst, src);
+ asm.vexPrefix(null, dst, src, size, pp, mmmmm, w);
+ asm.emitByte(immOp);
+ asm.emitModRM(r, src);
+ asm.emitByte(imm8);
+ }
+ }
+
+ public static final class VexMaskMoveOp extends VexOp {
+ // @formatter:off
+ public static final VexMaskMoveOp VMASKMOVPS = new VexMaskMoveOp("VMASKMOVPS", P_66, M_0F38, W0, 0x2C, 0x2E);
+ public static final VexMaskMoveOp VMASKMOVPD = new VexMaskMoveOp("VMASKMOVPD", P_66, M_0F38, W0, 0x2D, 0x2F);
+ public static final VexMaskMoveOp VPMASKMOVD = new VexMaskMoveOp("VPMASKMOVD", P_66, M_0F38, W0, 0x8C, 0x8E, AVXOpAssertion.AVX2);
+ public static final VexMaskMoveOp VPMASKMOVQ = new VexMaskMoveOp("VPMASKMOVQ", P_66, M_0F38, W1, 0x8C, 0x8E, AVXOpAssertion.AVX2);
+ // @formatter:on
+
+ private final int opReverse;
+
+ private VexMaskMoveOp(String opcode, int pp, int mmmmm, int w, int op, int opReverse) {
+ this(opcode, pp, mmmmm, w, op, opReverse, AVXOpAssertion.AVX1);
+ }
+
+ private VexMaskMoveOp(String opcode, int pp, int mmmmm, int w, int op, int opReverse, AVXOpAssertion assertion) {
+ super(opcode, pp, mmmmm, w, op, assertion);
+ this.opReverse = opReverse;
+ }
+
+ public void emit(AMD64Assembler asm, AVXSize size, Register dst, Register mask, AMD64Address src) {
+ assert assertion.check((AMD64) asm.target.arch, size, dst, mask, null);
+ asm.vexPrefix(dst, mask, src, size, pp, mmmmm, w);
+ asm.emitByte(op);
+ asm.emitOperandHelper(dst, src, 0);
+ }
+
+ public void emit(AMD64Assembler asm, AVXSize size, AMD64Address dst, Register mask, Register src) {
+ assert assertion.check((AMD64) asm.target.arch, size, src, mask, null);
+ asm.vexPrefix(src, mask, dst, size, pp, mmmmm, w);
+ asm.emitByte(opReverse);
+ asm.emitOperandHelper(src, dst, 0);
+ }
+ }
+
+ /**
+ * VEX-encoded instructions with an operand order of RVMI.
+ */
+ public static final class VexRVMIOp extends VexOp {
+ // @formatter:off
+ public static final VexRVMIOp VSHUFPS = new VexRVMIOp("VSHUFPS", P_, M_0F, WIG, 0xC6);
+ public static final VexRVMIOp VSHUFPD = new VexRVMIOp("VSHUFPD", P_66, M_0F, WIG, 0xC6);
+ public static final VexRVMIOp VINSERTF128 = new VexRVMIOp("VINSERTF128", P_66, M_0F3A, W0, 0x18, AVXOpAssertion.AVX1_256ONLY);
+ public static final VexRVMIOp VINSERTI128 = new VexRVMIOp("VINSERTI128", P_66, M_0F3A, W0, 0x38, AVXOpAssertion.AVX2_256ONLY);
+ // @formatter:on
+
+ private VexRVMIOp(String opcode, int pp, int mmmmm, int w, int op) {
+ this(opcode, pp, mmmmm, w, op, AVXOpAssertion.AVX1);
+ }
+
+ private VexRVMIOp(String opcode, int pp, int mmmmm, int w, int op, AVXOpAssertion assertion) {
+ super(opcode, pp, mmmmm, w, op, assertion);
+ }
+
+ public void emit(AMD64Assembler asm, AVXSize size, Register dst, Register src1, Register src2, int imm8) {
+ assert assertion.check((AMD64) asm.target.arch, size, dst, src1, src2);
+ assert (imm8 & 0xFF) == imm8;
+ asm.vexPrefix(dst, src1, src2, size, pp, mmmmm, w);
+ asm.emitByte(op);
+ asm.emitModRM(dst, src2);
+ asm.emitByte(imm8);
+ }
+
+ public void emit(AMD64Assembler asm, AVXSize size, Register dst, Register src1, AMD64Address src2, int imm8) {
+ assert assertion.check((AMD64) asm.target.arch, size, dst, src1, null);
+ assert (imm8 & 0xFF) == imm8;
+ asm.vexPrefix(dst, src1, src2, size, pp, mmmmm, w);
+ asm.emitByte(op);
+ asm.emitOperandHelper(dst, src2, 1);
+ asm.emitByte(imm8);
+ }
+ }
+
+ /**
+ * VEX-encoded comparison operation with an operand order of RVMI. The immediate operand is a
+ * comparison operator.
+ */
+ public static final class VexFloatCompareOp extends VexOp {
+ // @formatter:off
+ public static final VexFloatCompareOp VCMPPS = new VexFloatCompareOp("VCMPPS", P_, M_0F, WIG, 0xC2);
+ public static final VexFloatCompareOp VCMPPD = new VexFloatCompareOp("VCMPPD", P_66, M_0F, WIG, 0xC2);
+ public static final VexFloatCompareOp VCMPSS = new VexFloatCompareOp("VCMPSS", P_F2, M_0F, WIG, 0xC2);
+ public static final VexFloatCompareOp VCMPSD = new VexFloatCompareOp("VCMPSD", P_F2, M_0F, WIG, 0xC2);
+ // @formatter:on
+
+ public enum Predicate {
+ EQ_OQ(0x00),
+ LT_OS(0x01),
+ LE_OS(0x02),
+ UNORD_Q(0x03),
+ NEQ_UQ(0x04),
+ NLT_US(0x05),
+ NLE_US(0x06),
+ ORD_Q(0x07),
+ EQ_UQ(0x08),
+ NGE_US(0x09),
+ NGT_US(0x0a),
+ FALSE_OQ(0x0b),
+ NEQ_OQ(0x0c),
+ GE_OS(0x0d),
+ GT_OS(0x0e),
+ TRUE_UQ(0x0f),
+ EQ_OS(0x10),
+ LT_OQ(0x11),
+ LE_OQ(0x12),
+ UNORD_S(0x13),
+ NEQ_US(0x14),
+ NLT_UQ(0x15),
+ NLE_UQ(0x16),
+ ORD_S(0x17),
+ EQ_US(0x18),
+ NGE_UQ(0x19),
+ NGT_UQ(0x1a),
+ FALSE_OS(0x1b),
+ NEQ_OS(0x1c),
+ GE_OQ(0x1d),
+ GT_OQ(0x1e),
+ TRUE_US(0x1f);
+
+ private int imm8;
+
+ Predicate(int imm8) {
+ this.imm8 = imm8;
+ }
+
+ public static Predicate getPredicate(Condition condition, boolean unorderedIsTrue) {
+ if (unorderedIsTrue) {
+ switch (condition) {
+ case EQ:
+ return EQ_UQ;
+ case NE:
+ return NEQ_UQ;
+ case LT:
+ return NGE_UQ;
+ case LE:
+ return NGT_UQ;
+ case GT:
+ return NLE_UQ;
+ case GE:
+ return NLT_UQ;
+ default:
+ throw GraalError.shouldNotReachHere();
+ }
+ } else {
+ switch (condition) {
+ case EQ:
+ return EQ_OQ;
+ case NE:
+ return NEQ_OQ;
+ case LT:
+ return LT_OQ;
+ case LE:
+ return LE_OQ;
+ case GT:
+ return GT_OQ;
+ case GE:
+ return GE_OQ;
+ default:
+ throw GraalError.shouldNotReachHere();
+ }
+ }
+ }
+ }
+
+ private VexFloatCompareOp(String opcode, int pp, int mmmmm, int w, int op) {
+ super(opcode, pp, mmmmm, w, op, AVXOpAssertion.AVX1);
+ }
+
+ public void emit(AMD64Assembler asm, AVXSize size, Register dst, Register src1, Register src2, Predicate p) {
+ assert assertion.check((AMD64) asm.target.arch, size, dst, src1, src2);
+ asm.vexPrefix(dst, src1, src2, size, pp, mmmmm, w);
+ asm.emitByte(op);
+ asm.emitModRM(dst, src2);
+ asm.emitByte(p.imm8);
+ }
+
+ public void emit(AMD64Assembler asm, AVXSize size, Register dst, Register src1, AMD64Address src2, Predicate p) {
+ assert assertion.check((AMD64) asm.target.arch, size, dst, src1, null);
+ asm.vexPrefix(dst, src1, src2, size, pp, mmmmm, w);
+ asm.emitByte(op);
+ asm.emitOperandHelper(dst, src2, 1);
+ asm.emitByte(p.imm8);
+ }
+ }
+
public final void addl(AMD64Address dst, int imm32) {
ADD.getMIOpcode(DWORD, isByte(imm32)).emit(this, DWORD, dst, imm32);
}
@@ -1713,35 +1561,19 @@
}
public final void addpd(Register dst, Register src) {
- assert dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(dst, dst, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
- emitByte(0x58);
- emitByte(0xC0 | encode);
+ SSEOp.ADD.emit(this, PD, dst, src);
}
public final void addpd(Register dst, AMD64Address src) {
- assert dst.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- simdPrefix(dst, dst, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
- emitByte(0x58);
- emitOperandHelper(dst, src, 0);
+ SSEOp.ADD.emit(this, PD, dst, src);
}
public final void addsd(Register dst, Register src) {
- assert dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(dst, dst, src, VexSimdPrefix.VEX_SIMD_F2, VexOpcode.VEX_OPCODE_0F, attributes);
- emitByte(0x58);
- emitByte(0xC0 | encode);
+ SSEOp.ADD.emit(this, SD, dst, src);
}
public final void addsd(Register dst, AMD64Address src) {
- assert dst.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- simdPrefix(dst, dst, src, VexSimdPrefix.VEX_SIMD_F2, VexOpcode.VEX_OPCODE_0F, attributes);
- emitByte(0x58);
- emitOperandHelper(dst, src, 0);
+ SSEOp.ADD.emit(this, SD, dst, src);
}
private void addrNop4() {
@@ -1787,39 +1619,31 @@
}
public final void andpd(Register dst, Register src) {
- assert dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(dst, dst, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
- emitByte(0x54);
- emitByte(0xC0 | encode);
+ SSEOp.AND.emit(this, PD, dst, src);
}
public final void andpd(Register dst, AMD64Address src) {
- assert dst.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- simdPrefix(dst, dst, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
- emitByte(0x54);
- emitOperandHelper(dst, src, 0);
+ SSEOp.AND.emit(this, PD, dst, src);
}
public final void bsfq(Register dst, Register src) {
- int encode = prefixqAndEncode(dst.encoding(), src.encoding());
+ prefixq(dst, src);
emitByte(0x0F);
emitByte(0xBC);
- emitByte(0xC0 | encode);
+ emitModRM(dst, src);
}
public final void bsrl(Register dst, Register src) {
- int encode = prefixAndEncode(dst.encoding(), src.encoding());
+ prefix(dst, src);
emitByte(0x0F);
emitByte(0xBD);
- emitByte(0xC0 | encode);
+ emitModRM(dst, src);
}
public final void bswapl(Register reg) {
- int encode = prefixAndEncode(reg.encoding);
+ prefix(reg);
emitByte(0x0F);
- emitByte(0xC8 | encode);
+ emitModRM(1, reg);
}
public final void cdql() {
@@ -1827,10 +1651,10 @@
}
public final void cmovl(ConditionFlag cc, Register dst, Register src) {
- int encode = prefixAndEncode(dst.encoding, src.encoding);
+ prefix(dst, src);
emitByte(0x0F);
emitByte(0x40 | cc.getValue());
- emitByte(0xC0 | encode);
+ emitModRM(dst, src);
}
public final void cmovl(ConditionFlag cc, Register dst, AMD64Address src) {
@@ -1894,53 +1718,21 @@
}
public final void cvtsi2sdl(Register dst, Register src) {
- assert dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.CPU);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(dst, dst, src, VexSimdPrefix.VEX_SIMD_F2, VexOpcode.VEX_OPCODE_0F, attributes);
- emitByte(0x2A);
- emitByte(0xC0 | encode);
+ SSEOp.CVTSI2SD.emit(this, DWORD, dst, src);
}
public final void cvttsd2sil(Register dst, Register src) {
- assert dst.getRegisterCategory().equals(AMD64.CPU) && src.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(dst, Register.None, src, VexSimdPrefix.VEX_SIMD_F2, VexOpcode.VEX_OPCODE_0F, attributes);
- emitByte(0x2C);
- emitByte(0xC0 | encode);
+ SSEOp.CVTTSD2SI.emit(this, DWORD, dst, src);
}
- protected final void decl(AMD64Address dst) {
+ public final void decl(AMD64Address dst) {
prefix(dst);
emitByte(0xFF);
emitOperandHelper(1, dst, 0);
}
public final void divsd(Register dst, Register src) {
- assert dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(dst, dst, src, VexSimdPrefix.VEX_SIMD_F2, VexOpcode.VEX_OPCODE_0F, attributes);
- emitByte(0x5E);
- emitByte(0xC0 | encode);
- }
-
- public final void evmovdquq(Register dst, AMD64Address src, int vectorLen) {
- assert supports(CPUFeature.AVX512F);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(vectorLen, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true, target);
- attributes.setAddressAttributes(/* tuple_type */ EvexTupleType.EVEX_FVM, /* input_size_in_bits */ EvexInputSizeInBits.EVEX_NObit);
- attributes.setIsEvexInstruction();
- vexPrefix(src, Register.None, dst, VexSimdPrefix.VEX_SIMD_F3, VexOpcode.VEX_OPCODE_0F, attributes);
- emitByte(0x6F);
- emitOperandHelper(dst, src, 0);
- }
-
- public final void evpcmpeqb(Register kdst, Register nds, AMD64Address src, int vectorLen) {
- assert supports(CPUFeature.AVX512BW);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(vectorLen, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false, target);
- attributes.setIsEvexInstruction();
- attributes.setAddressAttributes(/* tuple_type */ EvexTupleType.EVEX_FVM, /* input_size_in_bits */ EvexInputSizeInBits.EVEX_NObit);
- vexPrefix(src, nds, kdst, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
- emitByte(0x74);
- emitOperandHelper(kdst, src, 0);
+ SSEOp.DIV.emit(this, SD, dst, src);
}
public final void hlt() {
@@ -1955,7 +1747,7 @@
}
}
- protected final void incl(AMD64Address dst) {
+ public final void incl(AMD64Address dst) {
prefix(dst);
emitByte(0xFF);
emitOperandHelper(0, dst, 0);
@@ -2041,15 +1833,15 @@
}
public final void jmp(Register entry) {
- int encode = prefixAndEncode(entry.encoding);
+ prefix(entry);
emitByte(0xFF);
- emitByte(0xE0 | encode);
+ emitModRM(4, entry);
}
public final void jmp(AMD64Address adr) {
prefix(adr);
emitByte(0xFF);
- emitOperandHelper(rsp, adr, 0);
+ emitOperandHelper(AMD64.rsp, adr, 0);
}
public final void jmpb(Label l) {
@@ -2068,32 +1860,6 @@
}
}
- // This instruction produces ZF or CF flags
- public final void kortestql(Register src1, Register src2) {
- assert supports(CPUFeature.AVX512BW);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rex_w */ true, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false, target);
- int encode = vexPrefixAndEncode(src1, Register.None, src2, VexSimdPrefix.VEX_SIMD_NONE, VexOpcode.VEX_OPCODE_0F, attributes);
- emitByte(0x98);
- emitByte(0xC0 | encode);
- }
-
- public final void kmovql(Register dst, Register src) {
- assert supports(CPUFeature.AVX512BW);
- if (src.getRegisterCategory().equals(AMD64.MASK)) {
- // kmovql(KRegister dst, KRegister src)
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rex_w */ true, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false, target);
- int encode = vexPrefixAndEncode(dst, Register.None, src, VexSimdPrefix.VEX_SIMD_NONE, VexOpcode.VEX_OPCODE_0F, attributes);
- emitByte(0x90);
- emitByte(0xC0 | encode);
- } else {
- // kmovql(KRegister dst, Register src)
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rex_w */ true, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false, target);
- int encode = vexPrefixAndEncode(dst, Register.None, src, VexSimdPrefix.VEX_SIMD_F2, VexOpcode.VEX_OPCODE_0F, attributes);
- emitByte(0x92);
- emitByte(0xC0 | encode);
- }
- }
-
public final void lead(Register dst, AMD64Address src) {
prefix(src, dst);
emitByte(0x8D);
@@ -2115,19 +1881,17 @@
}
public final void movapd(Register dst, Register src) {
- assert dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(dst, Register.None, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
+ assert dst.getRegisterCategory().equals(XMM) && src.getRegisterCategory().equals(XMM);
+ simdPrefix(dst, Register.None, src, PD, P_0F, false);
emitByte(0x28);
- emitByte(0xC0 | encode);
+ emitModRM(dst, src);
}
public final void movaps(Register dst, Register src) {
- assert dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(dst, Register.None, src, VexSimdPrefix.VEX_SIMD_NONE, VexOpcode.VEX_OPCODE_0F, attributes);
+ assert dst.getRegisterCategory().equals(XMM) && src.getRegisterCategory().equals(XMM);
+ simdPrefix(dst, Register.None, src, PS, P_0F, false);
emitByte(0x28);
- emitByte(0xC0 | encode);
+ emitModRM(dst, src);
}
public final void movb(AMD64Address dst, int imm8) {
@@ -2138,22 +1902,32 @@
}
public final void movb(AMD64Address dst, Register src) {
- assert src.getRegisterCategory().equals(AMD64.CPU) : "must have byte register";
+ assert src.getRegisterCategory().equals(CPU) : "must have byte register";
prefixb(dst, src);
emitByte(0x88);
emitOperandHelper(src, dst, 0);
}
public final void movl(Register dst, int imm32) {
- int encode = prefixAndEncode(dst.encoding);
- emitByte(0xB8 | encode);
+ movl(dst, imm32, false);
+ }
+
+ public final void movl(Register dst, int imm32, boolean annotateImm) {
+ int insnPos = position();
+ prefix(dst);
+ emitByte(0xB8 + encode(dst));
+ int immPos = position();
emitInt(imm32);
+ int nextInsnPos = position();
+ if (annotateImm && codePatchingAnnotationConsumer != null) {
+ codePatchingAnnotationConsumer.accept(new ImmediateOperandAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos));
+ }
}
public final void movl(Register dst, Register src) {
- int encode = prefixAndEncode(dst.encoding, src.encoding);
+ prefix(dst, src);
emitByte(0x8B);
- emitByte(0xC0 | encode);
+ emitModRM(dst, src);
}
public final void movl(Register dst, AMD64Address src) {
@@ -2191,19 +1965,17 @@
* {@link AMD64MacroAssembler#movflt(Register, Register)}.
*/
public final void movlpd(Register dst, AMD64Address src) {
- assert dst.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- simdPrefix(dst, dst, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
+ assert dst.getRegisterCategory().equals(XMM);
+ simdPrefix(dst, dst, src, PD, P_0F, false);
emitByte(0x12);
emitOperandHelper(dst, src, 0);
}
public final void movlhps(Register dst, Register src) {
- assert dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(dst, src, src, VexSimdPrefix.VEX_SIMD_NONE, VexOpcode.VEX_OPCODE_0F, attributes);
+ assert dst.getRegisterCategory().equals(XMM) && src.getRegisterCategory().equals(XMM);
+ simdPrefix(dst, src, src, PS, P_0F, false);
emitByte(0x16);
- emitByte(0xC0 | encode);
+ emitModRM(dst, src);
}
public final void movq(Register dst, AMD64Address src) {
@@ -2211,9 +1983,8 @@
}
public final void movq(Register dst, AMD64Address src, boolean wide) {
- if (dst.getRegisterCategory().equals(AMD64.XMM)) {
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ wide, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- simdPrefix(dst, Register.None, src, VexSimdPrefix.VEX_SIMD_F3, VexOpcode.VEX_OPCODE_0F, attributes);
+ if (dst.getRegisterCategory().equals(XMM)) {
+ simdPrefix(dst, Register.None, src, SS, P_0F, false);
emitByte(0x7E);
emitOperandHelper(dst, src, wide, 0);
} else {
@@ -2225,15 +1996,14 @@
}
public final void movq(Register dst, Register src) {
- int encode = prefixqAndEncode(dst.encoding, src.encoding);
+ prefixq(dst, src);
emitByte(0x8B);
- emitByte(0xC0 | encode);
+ emitModRM(dst, src);
}
public final void movq(AMD64Address dst, Register src) {
- if (src.getRegisterCategory().equals(AMD64.XMM)) {
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ true, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- simdPrefix(src, Register.None, dst, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
+ if (src.getRegisterCategory().equals(XMM)) {
+ simdPrefix(src, Register.None, dst, PD, P_0F, true);
emitByte(0xD6);
emitOperandHelper(src, dst, 0);
} else {
@@ -2252,10 +2022,10 @@
}
public final void movsbl(Register dst, Register src) {
- int encode = prefixAndEncode(dst.encoding, false, src.encoding, true);
+ prefix(dst, false, src, true);
emitByte(0x0F);
emitByte(0xBE);
- emitByte(0xC0 | encode);
+ emitModRM(dst, src);
}
public final void movsbq(Register dst, AMD64Address src) {
@@ -2266,98 +2036,54 @@
}
public final void movsbq(Register dst, Register src) {
- int encode = prefixqAndEncode(dst.encoding, src.encoding);
+ prefixq(dst, src);
emitByte(0x0F);
emitByte(0xBE);
- emitByte(0xC0 | encode);
+ emitModRM(dst, src);
}
public final void movsd(Register dst, Register src) {
- assert dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(dst, dst, src, VexSimdPrefix.VEX_SIMD_F2, VexOpcode.VEX_OPCODE_0F, attributes);
- emitByte(0x10);
- emitByte(0xC0 | encode);
+ AMD64RMOp.MOVSD.emit(this, SD, dst, src);
}
public final void movsd(Register dst, AMD64Address src) {
- assert dst.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- simdPrefix(dst, Register.None, src, VexSimdPrefix.VEX_SIMD_F2, VexOpcode.VEX_OPCODE_0F, attributes);
- emitByte(0x10);
- emitOperandHelper(dst, src, 0);
+ AMD64RMOp.MOVSD.emit(this, SD, dst, src);
}
public final void movsd(AMD64Address dst, Register src) {
- assert src.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- simdPrefix(src, Register.None, dst, VexSimdPrefix.VEX_SIMD_F2, VexOpcode.VEX_OPCODE_0F, attributes);
- emitByte(0x11);
- emitOperandHelper(src, dst, 0);
+ AMD64MROp.MOVSD.emit(this, SD, dst, src);
}
public final void movss(Register dst, Register src) {
- assert dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(dst, dst, src, VexSimdPrefix.VEX_SIMD_F3, VexOpcode.VEX_OPCODE_0F, attributes);
- emitByte(0x10);
- emitByte(0xC0 | encode);
+ AMD64RMOp.MOVSS.emit(this, SS, dst, src);
}
public final void movss(Register dst, AMD64Address src) {
- assert dst.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- simdPrefix(dst, Register.None, src, VexSimdPrefix.VEX_SIMD_F3, VexOpcode.VEX_OPCODE_0F, attributes);
- emitByte(0x10);
- emitOperandHelper(dst, src, 0);
+ AMD64RMOp.MOVSS.emit(this, SS, dst, src);
}
public final void movss(AMD64Address dst, Register src) {
- assert src.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- simdPrefix(src, Register.None, dst, VexSimdPrefix.VEX_SIMD_F3, VexOpcode.VEX_OPCODE_0F, attributes);
- emitByte(0x11);
- emitOperandHelper(src, dst, 0);
+ AMD64MROp.MOVSS.emit(this, SS, dst, src);
}
public final void mulpd(Register dst, Register src) {
- assert dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(dst, dst, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
- emitByte(0x59);
- emitByte(0xC0 | encode);
+ SSEOp.MUL.emit(this, PD, dst, src);
}
public final void mulpd(Register dst, AMD64Address src) {
- assert dst.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- simdPrefix(dst, dst, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
- emitByte(0x59);
- emitOperandHelper(dst, src, 0);
+ SSEOp.MUL.emit(this, PD, dst, src);
}
public final void mulsd(Register dst, Register src) {
- assert dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(dst, dst, src, VexSimdPrefix.VEX_SIMD_F2, VexOpcode.VEX_OPCODE_0F, attributes);
- emitByte(0x59);
- emitByte(0xC0 | encode);
+ SSEOp.MUL.emit(this, SD, dst, src);
}
public final void mulsd(Register dst, AMD64Address src) {
- assert dst.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- simdPrefix(dst, dst, src, VexSimdPrefix.VEX_SIMD_F2, VexOpcode.VEX_OPCODE_0F, attributes);
- emitByte(0x59);
- emitOperandHelper(dst, src, 0);
+ SSEOp.MUL.emit(this, SD, dst, src);
}
public final void mulss(Register dst, Register src) {
- assert dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(dst, dst, src, VexSimdPrefix.VEX_SIMD_F3, VexOpcode.VEX_OPCODE_0F, attributes);
- emitByte(0x59);
- emitByte(0xC0 | encode);
+ SSEOp.MUL.emit(this, SS, dst, src);
}
public final void movswl(Register dst, AMD64Address src) {
@@ -2390,11 +2116,11 @@
}
public final void movzbl(Register dst, Register src) {
- AMD64RMOp.MOVZXB.emit(this, OperandSize.DWORD, dst, src);
+ AMD64RMOp.MOVZXB.emit(this, DWORD, dst, src);
}
public final void movzbq(Register dst, Register src) {
- AMD64RMOp.MOVZXB.emit(this, OperandSize.QWORD, dst, src);
+ AMD64RMOp.MOVZXB.emit(this, QWORD, dst, src);
}
public final void movzwl(Register dst, AMD64Address src) {
@@ -2639,8 +2365,8 @@
}
public final void pop(Register dst) {
- int encode = prefixAndEncode(dst.encoding);
- emitByte(0x58 | encode);
+ prefix(dst);
+ emitByte(0x58 + encode(dst));
}
public void popfq() {
@@ -2649,26 +2375,32 @@
public final void ptest(Register dst, Register src) {
assert supports(CPUFeature.SSE4_1);
- assert dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(dst, Register.None, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F_38, attributes);
+ assert dst.getRegisterCategory().equals(XMM) && src.getRegisterCategory().equals(XMM);
+ simdPrefix(dst, Register.None, src, PD, P_0F38, false);
emitByte(0x17);
- emitByte(0xC0 | encode);
+ emitModRM(dst, src);
}
- public final void vptest(Register dst, Register src) {
- assert supports(CPUFeature.AVX);
- assert dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_256bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = vexPrefixAndEncode(dst, Register.None, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F_38, attributes);
- emitByte(0x17);
- emitByte(0xC0 | encode);
+ public final void pcmpeqb(Register dst, Register src) {
+ assert supports(CPUFeature.SSE2);
+ assert dst.getRegisterCategory().equals(XMM) && src.getRegisterCategory().equals(XMM);
+ simdPrefix(dst, dst, src, PD, P_0F, false);
+ emitByte(0x74);
+ emitModRM(dst, src);
+ }
+
+ public final void pcmpeqw(Register dst, Register src) {
+ assert supports(CPUFeature.SSE2);
+ assert dst.getRegisterCategory().equals(XMM) && src.getRegisterCategory().equals(XMM);
+ simdPrefix(dst, dst, src, PD, P_0F, false);
+ emitByte(0x75);
+ emitModRM(dst, src);
}
public final void pcmpestri(Register dst, AMD64Address src, int imm8) {
assert supports(CPUFeature.SSE4_2);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- simdPrefix(dst, Register.None, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F_3A, attributes);
+ assert dst.getRegisterCategory().equals(XMM);
+ simdPrefix(dst, Register.None, src, PD, P_0F3A, false);
emitByte(0x61);
emitOperandHelper(dst, src, 0);
emitByte(imm8);
@@ -2676,36 +2408,33 @@
public final void pcmpestri(Register dst, Register src, int imm8) {
assert supports(CPUFeature.SSE4_2);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(dst, Register.None, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F_3A, attributes);
+ assert dst.getRegisterCategory().equals(XMM) && src.getRegisterCategory().equals(XMM);
+ simdPrefix(dst, Register.None, src, PD, P_0F3A, false);
emitByte(0x61);
- emitByte(0xC0 | encode);
+ emitModRM(dst, src);
emitByte(imm8);
}
+ public final void pmovmskb(Register dst, Register src) {
+ assert supports(CPUFeature.SSE2);
+ assert dst.getRegisterCategory().equals(CPU) && src.getRegisterCategory().equals(XMM);
+ simdPrefix(dst, Register.None, src, PD, P_0F, false);
+ emitByte(0xD7);
+ emitModRM(dst, src);
+ }
+
public final void pmovzxbw(Register dst, AMD64Address src) {
assert supports(CPUFeature.SSE4_2);
+ assert dst.getRegisterCategory().equals(XMM);
// XXX legacy_mode should be: _legacy_mode_bw
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false, target);
- attributes.setAddressAttributes(/* tuple_type */ EvexTupleType.EVEX_HVM, /* input_size_in_bits */ EvexInputSizeInBits.EVEX_NObit);
- simdPrefix(dst, Register.None, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F_38, attributes);
- emitByte(0x30);
- emitOperandHelper(dst, src, 0);
- }
-
- public final void vpmovzxbw(Register dst, AMD64Address src, int vectorLen) {
- assert supports(CPUFeature.AVX);
- // XXX legacy_mode should be: _legacy_mode_bw
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(vectorLen, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false, target);
- attributes.setAddressAttributes(/* tuple_type */ EvexTupleType.EVEX_HVM, /* input_size_in_bits */ EvexInputSizeInBits.EVEX_NObit);
- vexPrefix(src, Register.None, dst, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F_38, attributes);
+ simdPrefix(dst, Register.None, src, PD, P_0F38, false);
emitByte(0x30);
emitOperandHelper(dst, src, 0);
}
public final void push(Register src) {
- int encode = prefixAndEncode(src.encoding);
- emitByte(0x50 | encode);
+ prefix(src);
+ emitByte(0x50 + encode(src));
}
public void pushfq() {
@@ -2713,178 +2442,161 @@
}
public final void paddd(Register dst, Register src) {
- assert dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(dst, dst, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
+ assert dst.getRegisterCategory().equals(XMM) && src.getRegisterCategory().equals(XMM);
+ simdPrefix(dst, dst, src, PD, P_0F, false);
emitByte(0xFE);
- emitByte(0xC0 | encode);
+ emitModRM(dst, src);
}
public final void paddq(Register dst, Register src) {
- assert dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(dst, dst, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
+ assert dst.getRegisterCategory().equals(XMM) && src.getRegisterCategory().equals(XMM);
+ simdPrefix(dst, dst, src, PD, P_0F, false);
emitByte(0xD4);
- emitByte(0xC0 | encode);
+ emitModRM(dst, src);
}
public final void pextrw(Register dst, Register src, int imm8) {
- assert dst.getRegisterCategory().equals(AMD64.CPU) && src.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(dst, Register.None, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
+ assert dst.getRegisterCategory().equals(CPU) && src.getRegisterCategory().equals(XMM);
+ simdPrefix(dst, Register.None, src, PD, P_0F, false);
emitByte(0xC5);
- emitByte(0xC0 | encode);
+ emitModRM(dst, src);
emitByte(imm8);
}
public final void pinsrw(Register dst, Register src, int imm8) {
- assert dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.CPU);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(dst, dst, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
+ assert dst.getRegisterCategory().equals(XMM) && src.getRegisterCategory().equals(CPU);
+ simdPrefix(dst, dst, src, PD, P_0F, false);
emitByte(0xC4);
- emitByte(0xC0 | encode);
+ emitModRM(dst, src);
emitByte(imm8);
}
public final void por(Register dst, Register src) {
- assert dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(dst, dst, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
+ assert dst.getRegisterCategory().equals(XMM) && src.getRegisterCategory().equals(XMM);
+ simdPrefix(dst, dst, src, PD, P_0F, false);
emitByte(0xEB);
- emitByte(0xC0 | encode);
+ emitModRM(dst, src);
}
public final void pand(Register dst, Register src) {
- assert dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(dst, dst, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
+ assert dst.getRegisterCategory().equals(XMM) && src.getRegisterCategory().equals(XMM);
+ simdPrefix(dst, dst, src, PD, P_0F, false);
emitByte(0xDB);
- emitByte(0xC0 | encode);
+ emitModRM(dst, src);
}
public final void pxor(Register dst, Register src) {
- assert dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(dst, dst, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
+ assert dst.getRegisterCategory().equals(XMM) && src.getRegisterCategory().equals(XMM);
+ simdPrefix(dst, dst, src, PD, P_0F, false);
emitByte(0xEF);
- emitByte(0xC0 | encode);
- }
-
- public final void vpxor(Register dst, Register nds, Register src) {
- assert supports(CPUFeature.AVX);
- assert dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_256bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = vexPrefixAndEncode(dst, nds, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
- emitByte(0xEF);
- emitByte(0xC0 | encode);
- }
-
- public final void vpxor(Register dst, Register nds, AMD64Address src) {
- assert supports(CPUFeature.AVX);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_256bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true, target);
- attributes.setAddressAttributes(/* tuple_type */ EvexTupleType.EVEX_FV, /* input_size_in_bits */ EvexInputSizeInBits.EVEX_32bit);
- vexPrefix(src, nds, dst, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
- emitByte(0xEF);
- emitOperandHelper(dst, src, 0);
+ emitModRM(dst, src);
}
public final void pslld(Register dst, int imm8) {
assert isUByte(imm8) : "invalid value";
- assert dst.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
+ assert dst.getRegisterCategory().equals(XMM);
// XMM6 is for /6 encoding: 66 0F 72 /6 ib
- int encode = simdPrefixAndEncode(AMD64.xmm6, dst, dst, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
+ simdPrefix(AMD64.xmm6, dst, dst, PD, P_0F, false);
emitByte(0x72);
- emitByte(0xC0 | encode);
+ emitModRM(6, dst);
emitByte(imm8 & 0xFF);
}
public final void psllq(Register dst, Register shift) {
- assert dst.getRegisterCategory().equals(AMD64.XMM) && shift.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(dst, dst, shift, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
+ assert dst.getRegisterCategory().equals(XMM) && shift.getRegisterCategory().equals(XMM);
+ simdPrefix(dst, dst, shift, PD, P_0F, false);
emitByte(0xF3);
- emitByte(0xC0 | encode);
+ emitModRM(dst, shift);
}
public final void psllq(Register dst, int imm8) {
assert isUByte(imm8) : "invalid value";
- assert dst.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
+ assert dst.getRegisterCategory().equals(XMM);
// XMM6 is for /6 encoding: 66 0F 73 /6 ib
- int encode = simdPrefixAndEncode(AMD64.xmm6, dst, dst, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
+ simdPrefix(AMD64.xmm6, dst, dst, PD, P_0F, false);
emitByte(0x73);
- emitByte(0xC0 | encode);
+ emitModRM(6, dst);
emitByte(imm8);
}
public final void psrad(Register dst, int imm8) {
assert isUByte(imm8) : "invalid value";
- assert dst.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- // XMM4 is for /2 encoding: 66 0F 72 /4 ib
- int encode = simdPrefixAndEncode(AMD64.xmm4, dst, dst, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
+ assert dst.getRegisterCategory().equals(XMM);
+ // XMM4 is for /4 encoding: 66 0F 72 /4 ib
+ simdPrefix(AMD64.xmm4, dst, dst, PD, P_0F, false);
emitByte(0x72);
- emitByte(0xC0 | encode);
+ emitModRM(4, dst);
emitByte(imm8);
}
public final void psrld(Register dst, int imm8) {
assert isUByte(imm8) : "invalid value";
- assert dst.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
+ assert dst.getRegisterCategory().equals(XMM);
// XMM2 is for /2 encoding: 66 0F 72 /2 ib
- int encode = simdPrefixAndEncode(AMD64.xmm2, dst, dst, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
+ simdPrefix(AMD64.xmm2, dst, dst, PD, P_0F, false);
emitByte(0x72);
- emitByte(0xC0 | encode);
+ emitModRM(2, dst);
emitByte(imm8);
}
public final void psrlq(Register dst, int imm8) {
assert isUByte(imm8) : "invalid value";
- assert dst.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
+ assert dst.getRegisterCategory().equals(XMM);
// XMM2 is for /2 encoding: 66 0F 73 /2 ib
- int encode = simdPrefixAndEncode(AMD64.xmm2, dst, dst, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
+ simdPrefix(AMD64.xmm2, dst, dst, PD, P_0F, false);
emitByte(0x73);
- emitByte(0xC0 | encode);
+ emitModRM(2, dst);
emitByte(imm8);
}
public final void psrldq(Register dst, int imm8) {
assert isUByte(imm8) : "invalid value";
- assert dst.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(AMD64.xmm3, dst, dst, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
+ assert dst.getRegisterCategory().equals(XMM);
+ simdPrefix(AMD64.xmm3, dst, dst, PD, P_0F, false);
emitByte(0x73);
- emitByte(0xC0 | encode);
+ emitModRM(3, dst);
+ emitByte(imm8);
+ }
+
+ public final void pshufb(Register dst, Register src) {
+ assert supports(CPUFeature.SSSE3);
+ assert dst.getRegisterCategory().equals(XMM) && src.getRegisterCategory().equals(XMM);
+ simdPrefix(dst, dst, src, PD, P_0F38, false);
+ emitByte(0x00);
+ emitModRM(dst, src);
+ }
+
+ public final void pshuflw(Register dst, Register src, int imm8) {
+ assert supports(CPUFeature.SSE2);
+ assert isUByte(imm8) : "invalid value";
+ assert dst.getRegisterCategory().equals(XMM) && src.getRegisterCategory().equals(XMM);
+ simdPrefix(dst, Register.None, src, SD, P_0F, false);
+ emitByte(0x70);
+ emitModRM(dst, src);
emitByte(imm8);
}
public final void pshufd(Register dst, Register src, int imm8) {
assert isUByte(imm8) : "invalid value";
- assert dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(dst, Register.None, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
+ assert dst.getRegisterCategory().equals(XMM) && src.getRegisterCategory().equals(XMM);
+ simdPrefix(dst, Register.None, src, PD, P_0F, false);
emitByte(0x70);
- emitByte(0xC0 | encode);
+ emitModRM(dst, src);
emitByte(imm8);
}
public final void psubd(Register dst, Register src) {
- assert dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(dst, dst, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
+ assert dst.getRegisterCategory().equals(XMM) && src.getRegisterCategory().equals(XMM);
+ simdPrefix(dst, dst, src, PD, P_0F, false);
emitByte(0xFA);
- emitByte(0xC0 | encode);
+ emitModRM(dst, src);
}
public final void rcpps(Register dst, Register src) {
- assert dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ true, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(dst, Register.None, src, VexSimdPrefix.VEX_SIMD_NONE, VexOpcode.VEX_OPCODE_0F, attributes);
+ assert dst.getRegisterCategory().equals(XMM) && src.getRegisterCategory().equals(XMM);
+ simdPrefix(dst, Register.None, src, PS, P_0F, false);
emitByte(0x53);
- emitByte(0xC0 | encode);
+ emitModRM(dst, src);
}
public final void ret(int imm16) {
@@ -2897,49 +2609,51 @@
}
public final void sarl(Register dst, int imm8) {
- int encode = prefixAndEncode(dst.encoding);
+ prefix(dst);
assert isShiftCount(imm8 >> 1) : "illegal shift count";
if (imm8 == 1) {
emitByte(0xD1);
- emitByte(0xF8 | encode);
+ emitModRM(7, dst);
} else {
emitByte(0xC1);
- emitByte(0xF8 | encode);
+ emitModRM(7, dst);
emitByte(imm8);
}
}
public final void shll(Register dst, int imm8) {
assert isShiftCount(imm8 >> 1) : "illegal shift count";
- int encode = prefixAndEncode(dst.encoding);
+ prefix(dst);
if (imm8 == 1) {
emitByte(0xD1);
- emitByte(0xE0 | encode);
+ emitModRM(4, dst);
} else {
emitByte(0xC1);
- emitByte(0xE0 | encode);
+ emitModRM(4, dst);
emitByte(imm8);
}
}
public final void shll(Register dst) {
- int encode = prefixAndEncode(dst.encoding);
+ // Multiply dst by 2, CL times.
+ prefix(dst);
emitByte(0xD3);
- emitByte(0xE0 | encode);
+ emitModRM(4, dst);
}
public final void shrl(Register dst, int imm8) {
assert isShiftCount(imm8 >> 1) : "illegal shift count";
- int encode = prefixAndEncode(dst.encoding);
+ prefix(dst);
emitByte(0xC1);
- emitByte(0xE8 | encode);
+ emitModRM(5, dst);
emitByte(imm8);
}
public final void shrl(Register dst) {
- int encode = prefixAndEncode(dst.encoding);
+ // Unsigned divide dst by 2, CL times.
+ prefix(dst);
emitByte(0xD3);
- emitByte(0xE8 | encode);
+ emitModRM(5, dst);
}
public final void subl(AMD64Address dst, int imm32) {
@@ -2955,48 +2669,35 @@
}
public final void subpd(Register dst, Register src) {
- assert dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(dst, dst, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
- emitByte(0x5C);
- emitByte(0xC0 | encode);
+ SSEOp.SUB.emit(this, PD, dst, src);
}
public final void subsd(Register dst, Register src) {
- assert dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(dst, dst, src, VexSimdPrefix.VEX_SIMD_F2, VexOpcode.VEX_OPCODE_0F, attributes);
- emitByte(0x5C);
- emitByte(0xC0 | encode);
+ SSEOp.SUB.emit(this, SD, dst, src);
}
public final void subsd(Register dst, AMD64Address src) {
- assert dst.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- simdPrefix(dst, dst, src, VexSimdPrefix.VEX_SIMD_F2, VexOpcode.VEX_OPCODE_0F, attributes);
- emitByte(0x5C);
- emitOperandHelper(dst, src, 0);
+ SSEOp.SUB.emit(this, SD, dst, src);
}
public final void testl(Register dst, int imm32) {
// not using emitArith because test
// doesn't support sign-extension of
// 8bit operands
- int encode = dst.encoding;
- if (encode == 0) {
+ if (dst.encoding == 0) {
emitByte(0xA9);
} else {
- encode = prefixAndEncode(encode);
+ prefix(dst);
emitByte(0xF7);
- emitByte(0xC0 | encode);
+ emitModRM(0, dst);
}
emitInt(imm32);
}
public final void testl(Register dst, Register src) {
- int encode = prefixAndEncode(dst.encoding, src.encoding);
+ prefix(dst, src);
emitByte(0x85);
- emitByte(0xC0 | encode);
+ emitModRM(dst, src);
}
public final void testl(Register dst, AMD64Address src) {
@@ -3006,19 +2707,17 @@
}
public final void unpckhpd(Register dst, Register src) {
- assert dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(dst, dst, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
+ assert dst.getRegisterCategory().equals(XMM) && src.getRegisterCategory().equals(XMM);
+ simdPrefix(dst, dst, src, PD, P_0F, false);
emitByte(0x15);
- emitByte(0xC0 | encode);
+ emitModRM(dst, src);
}
public final void unpcklpd(Register dst, Register src) {
- assert dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(dst, dst, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
+ assert dst.getRegisterCategory().equals(XMM) && src.getRegisterCategory().equals(XMM);
+ simdPrefix(dst, dst, src, PD, P_0F, false);
emitByte(0x14);
- emitByte(0xC0 | encode);
+ emitModRM(dst, src);
}
public final void xorl(Register dst, Register src) {
@@ -3026,335 +2725,25 @@
}
public final void xorpd(Register dst, Register src) {
- assert dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(dst, dst, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
- emitByte(0x57);
- emitByte(0xC0 | encode);
+ SSEOp.XOR.emit(this, PD, dst, src);
}
public final void xorps(Register dst, Register src) {
- assert dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(dst, dst, src, VexSimdPrefix.VEX_SIMD_NONE, VexOpcode.VEX_OPCODE_0F, attributes);
- emitByte(0x57);
- emitByte(0xC0 | encode);
+ SSEOp.XOR.emit(this, PS, dst, src);
}
protected final void decl(Register dst) {
// Use two-byte form (one-byte form is a REX prefix in 64-bit mode)
- int encode = prefixAndEncode(dst.encoding);
+ prefix(dst);
emitByte(0xFF);
- emitByte(0xC8 | encode);
+ emitModRM(1, dst);
}
protected final void incl(Register dst) {
// Use two-byte form (one-byte from is a REX prefix in 64-bit mode)
- int encode = prefixAndEncode(dst.encoding);
+ prefix(dst);
emitByte(0xFF);
- emitByte(0xC0 | encode);
- }
-
- private int prefixAndEncode(int regEnc) {
- return prefixAndEncode(regEnc, false);
- }
-
- private int prefixAndEncode(int regEnc, boolean byteinst) {
- if (regEnc >= 8) {
- emitByte(Prefix.REXB);
- return regEnc - 8;
- } else if (byteinst && regEnc >= 4) {
- emitByte(Prefix.REX);
- }
- return regEnc;
- }
-
- private int prefixqAndEncode(int regEnc) {
- if (regEnc < 8) {
- emitByte(Prefix.REXW);
- return regEnc;
- } else {
- emitByte(Prefix.REXWB);
- return regEnc - 8;
- }
- }
-
- private int prefixAndEncode(int dstEnc, int srcEnc) {
- return prefixAndEncode(dstEnc, false, srcEnc, false);
- }
-
- private int prefixAndEncode(int dstEncoding, boolean dstIsByte, int srcEncoding, boolean srcIsByte) {
- int srcEnc = srcEncoding;
- int dstEnc = dstEncoding;
- if (dstEnc < 8) {
- if (srcEnc >= 8) {
- emitByte(Prefix.REXB);
- srcEnc -= 8;
- } else if ((srcIsByte && srcEnc >= 4) || (dstIsByte && dstEnc >= 4)) {
- emitByte(Prefix.REX);
- }
- } else {
- if (srcEnc < 8) {
- emitByte(Prefix.REXR);
- } else {
- emitByte(Prefix.REXRB);
- srcEnc -= 8;
- }
- dstEnc -= 8;
- }
- return dstEnc << 3 | srcEnc;
- }
-
- /**
- * Creates prefix and the encoding of the lower 6 bits of the ModRM-Byte. It emits an operand
- * prefix. If the given operands exceed 3 bits, the 4th bit is encoded in the prefix.
- *
- * @param regEncoding the encoding of the register part of the ModRM-Byte
- * @param rmEncoding the encoding of the r/m part of the ModRM-Byte
- * @return the lower 6 bits of the ModRM-Byte that should be emitted
- */
- private int prefixqAndEncode(int regEncoding, int rmEncoding) {
- int rmEnc = rmEncoding;
- int regEnc = regEncoding;
- if (regEnc < 8) {
- if (rmEnc < 8) {
- emitByte(Prefix.REXW);
- } else {
- emitByte(Prefix.REXWB);
- rmEnc -= 8;
- }
- } else {
- if (rmEnc < 8) {
- emitByte(Prefix.REXWR);
- } else {
- emitByte(Prefix.REXWRB);
- rmEnc -= 8;
- }
- regEnc -= 8;
- }
- return regEnc << 3 | rmEnc;
- }
-
- private void vexPrefix(int rxb, int ndsEncoding, int pre, int opc, AMD64InstructionAttr attributes) {
- int vectorLen = attributes.getVectorLen();
- boolean vexW = attributes.isRexVexW();
- boolean isXorB = ((rxb & 0x3) > 0);
- if (isXorB || vexW || (opc == VexOpcode.VEX_OPCODE_0F_38) || (opc == VexOpcode.VEX_OPCODE_0F_3A)) {
- emitByte(Prefix.VEX_3BYTES);
-
- int byte1 = (rxb << 5);
- byte1 = ((~byte1) & 0xE0) | opc;
- emitByte(byte1);
-
- int byte2 = ((~ndsEncoding) & 0xf) << 3;
- byte2 |= (vexW ? VexPrefix.VEX_W : 0) | ((vectorLen > 0) ? 4 : 0) | pre;
- emitByte(byte2);
- } else {
- emitByte(Prefix.VEX_2BYTES);
-
- int byte1 = ((rxb & 0x4) > 0) ? VexPrefix.VEX_R : 0;
- byte1 = (~byte1) & 0x80;
- byte1 |= ((~ndsEncoding) & 0xf) << 3;
- byte1 |= ((vectorLen > 0) ? 4 : 0) | pre;
- emitByte(byte1);
- }
- }
-
- private void vexPrefix(AMD64Address adr, Register nds, Register src, int pre, int opc, AMD64InstructionAttr attributes) {
- int rxb = getRXB(src, adr);
- int ndsEncoding = nds.isValid() ? nds.encoding : 0;
- vexPrefix(rxb, ndsEncoding, pre, opc, attributes);
- setCurAttributes(attributes);
- }
-
- private int vexPrefixAndEncode(Register dst, Register nds, Register src, int pre, int opc, AMD64InstructionAttr attributes) {
- int rxb = getRXB(dst, src);
- int ndsEncoding = nds.isValid() ? nds.encoding : 0;
- vexPrefix(rxb, ndsEncoding, pre, opc, attributes);
- // return modrm byte components for operands
- return (((dst.encoding & 7) << 3) | (src.encoding & 7));
- }
-
- private void simdPrefix(Register xreg, Register nds, AMD64Address adr, int pre, int opc, AMD64InstructionAttr attributes) {
- if (supports(CPUFeature.AVX)) {
- vexPrefix(adr, nds, xreg, pre, opc, attributes);
- } else {
- switch (pre) {
- case VexSimdPrefix.VEX_SIMD_66:
- emitByte(0x66);
- break;
- case VexSimdPrefix.VEX_SIMD_F2:
- emitByte(0xF2);
- break;
- case VexSimdPrefix.VEX_SIMD_F3:
- emitByte(0xF3);
- break;
- }
- if (attributes.isRexVexW()) {
- prefixq(adr, xreg);
- } else {
- prefix(adr, xreg);
- }
- switch (opc) {
- case VexOpcode.VEX_OPCODE_0F:
- emitByte(0x0F);
- break;
- case VexOpcode.VEX_OPCODE_0F_38:
- emitByte(0x0F);
- emitByte(0x38);
- break;
- case VexOpcode.VEX_OPCODE_0F_3A:
- emitByte(0x0F);
- emitByte(0x3A);
- break;
- }
- }
- }
-
- private int simdPrefixAndEncode(Register dst, Register nds, Register src, int pre, int opc, AMD64InstructionAttr attributes) {
- if (supports(CPUFeature.AVX)) {
- return vexPrefixAndEncode(dst, nds, src, pre, opc, attributes);
- } else {
- switch (pre) {
- case VexSimdPrefix.VEX_SIMD_66:
- emitByte(0x66);
- break;
- case VexSimdPrefix.VEX_SIMD_F2:
- emitByte(0xF2);
- break;
- case VexSimdPrefix.VEX_SIMD_F3:
- emitByte(0xF3);
- break;
- }
- int encode;
- int dstEncoding = dst.encoding;
- int srcEncoding = src.encoding;
- if (attributes.isRexVexW()) {
- encode = prefixqAndEncode(dstEncoding, srcEncoding);
- } else {
- encode = prefixAndEncode(dstEncoding, srcEncoding);
- }
- switch (opc) {
- case VexOpcode.VEX_OPCODE_0F:
- emitByte(0x0F);
- break;
- case VexOpcode.VEX_OPCODE_0F_38:
- emitByte(0x0F);
- emitByte(0x38);
- break;
- case VexOpcode.VEX_OPCODE_0F_3A:
- emitByte(0x0F);
- emitByte(0x3A);
- break;
- }
- return encode;
- }
- }
-
- private static boolean needsRex(Register reg) {
- return reg.encoding >= MinEncodingNeedsRex;
- }
-
- private void prefix(AMD64Address adr) {
- if (needsRex(adr.getBase())) {
- if (needsRex(adr.getIndex())) {
- emitByte(Prefix.REXXB);
- } else {
- emitByte(Prefix.REXB);
- }
- } else {
- if (needsRex(adr.getIndex())) {
- emitByte(Prefix.REXX);
- }
- }
- }
-
- private void prefixq(AMD64Address adr) {
- if (needsRex(adr.getBase())) {
- if (needsRex(adr.getIndex())) {
- emitByte(Prefix.REXWXB);
- } else {
- emitByte(Prefix.REXWB);
- }
- } else {
- if (needsRex(adr.getIndex())) {
- emitByte(Prefix.REXWX);
- } else {
- emitByte(Prefix.REXW);
- }
- }
- }
-
- private void prefixb(AMD64Address adr, Register reg) {
- prefix(adr, reg, true);
- }
-
- private void prefix(AMD64Address adr, Register reg) {
- prefix(adr, reg, false);
- }
-
- private void prefix(AMD64Address adr, Register reg, boolean byteinst) {
- if (reg.encoding < 8) {
- if (needsRex(adr.getBase())) {
- if (needsRex(adr.getIndex())) {
- emitByte(Prefix.REXXB);
- } else {
- emitByte(Prefix.REXB);
- }
- } else {
- if (needsRex(adr.getIndex())) {
- emitByte(Prefix.REXX);
- } else if (byteinst && reg.encoding >= 4) {
- emitByte(Prefix.REX);
- }
- }
- } else {
- if (needsRex(adr.getBase())) {
- if (needsRex(adr.getIndex())) {
- emitByte(Prefix.REXRXB);
- } else {
- emitByte(Prefix.REXRB);
- }
- } else {
- if (needsRex(adr.getIndex())) {
- emitByte(Prefix.REXRX);
- } else {
- emitByte(Prefix.REXR);
- }
- }
- }
- }
-
- private void prefixq(AMD64Address adr, Register src) {
- if (src.encoding < 8) {
- if (needsRex(adr.getBase())) {
- if (needsRex(adr.getIndex())) {
- emitByte(Prefix.REXWXB);
- } else {
- emitByte(Prefix.REXWB);
- }
- } else {
- if (needsRex(adr.getIndex())) {
- emitByte(Prefix.REXWX);
- } else {
- emitByte(Prefix.REXW);
- }
- }
- } else {
- if (needsRex(adr.getBase())) {
- if (needsRex(adr.getIndex())) {
- emitByte(Prefix.REXWRXB);
- } else {
- emitByte(Prefix.REXWRB);
- }
- } else {
- if (needsRex(adr.getIndex())) {
- emitByte(Prefix.REXWRX);
- } else {
- emitByte(Prefix.REXWR);
- }
- }
- }
+ emitModRM(0, dst);
}
public final void addq(Register dst, int imm32) {
@@ -3378,35 +2767,35 @@
}
public final void bsrq(Register dst, Register src) {
- int encode = prefixqAndEncode(dst.encoding(), src.encoding());
+ prefixq(dst, src);
emitByte(0x0F);
emitByte(0xBD);
- emitByte(0xC0 | encode);
+ emitModRM(dst, src);
}
public final void bswapq(Register reg) {
- int encode = prefixqAndEncode(reg.encoding);
+ prefixq(reg);
emitByte(0x0F);
- emitByte(0xC8 | encode);
+ emitByte(0xC8 + encode(reg));
}
public final void cdqq() {
- emitByte(Prefix.REXW);
+ rexw();
emitByte(0x99);
}
public final void cmovq(ConditionFlag cc, Register dst, Register src) {
- int encode = prefixqAndEncode(dst.encoding, src.encoding);
+ prefixq(dst, src);
emitByte(0x0F);
emitByte(0x40 | cc.getValue());
- emitByte(0xC0 | encode);
+ emitModRM(dst, src);
}
public final void setb(ConditionFlag cc, Register dst) {
- int encode = prefixAndEncode(dst.encoding, true);
+ prefix(dst, true);
emitByte(0x0F);
emitByte(0x90 | cc.getValue());
- emitByte(0xC0 | encode);
+ emitModRM(0, dst);
}
public final void cmovq(ConditionFlag cc, Register dst, AMD64Address src) {
@@ -3436,42 +2825,32 @@
}
public final void cvtdq2pd(Register dst, Register src) {
- assert dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(dst, Register.None, src, VexSimdPrefix.VEX_SIMD_F3, VexOpcode.VEX_OPCODE_0F, attributes);
+ assert dst.getRegisterCategory().equals(XMM) && src.getRegisterCategory().equals(XMM);
+ simdPrefix(dst, Register.None, src, SS, P_0F, false);
emitByte(0xE6);
- emitByte(0xC0 | encode);
+ emitModRM(dst, src);
}
public final void cvtsi2sdq(Register dst, Register src) {
- assert dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.CPU);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ true, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(dst, dst, src, VexSimdPrefix.VEX_SIMD_F2, VexOpcode.VEX_OPCODE_0F, attributes);
- emitByte(0x2A);
- emitByte(0xC0 | encode);
+ SSEOp.CVTSI2SD.emit(this, QWORD, dst, src);
}
public final void cvttsd2siq(Register dst, Register src) {
- assert dst.getRegisterCategory().equals(AMD64.CPU) && src.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ true, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(dst, Register.None, src, VexSimdPrefix.VEX_SIMD_F2, VexOpcode.VEX_OPCODE_0F, attributes);
- emitByte(0x2C);
- emitByte(0xC0 | encode);
+ SSEOp.CVTTSD2SI.emit(this, QWORD, dst, src);
}
public final void cvttpd2dq(Register dst, Register src) {
- assert dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(dst, Register.None, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
+ assert dst.getRegisterCategory().equals(XMM) && src.getRegisterCategory().equals(XMM);
+ simdPrefix(dst, Register.None, src, PD, P_0F, false);
emitByte(0xE6);
- emitByte(0xC0 | encode);
+ emitModRM(dst, src);
}
- protected final void decq(Register dst) {
+ public final void decq(Register dst) {
// Use two-byte form (one-byte from is a REX prefix in 64-bit mode)
- int encode = prefixqAndEncode(dst.encoding);
+ prefixq(dst);
emitByte(0xFF);
- emitByte(0xC8 | encode);
+ emitModRM(1, dst);
}
public final void decq(AMD64Address dst) {
@@ -3479,18 +2858,18 @@
}
public final void imulq(Register dst, Register src) {
- int encode = prefixqAndEncode(dst.encoding, src.encoding);
+ prefixq(dst, src);
emitByte(0x0F);
emitByte(0xAF);
- emitByte(0xC0 | encode);
+ emitModRM(dst, src);
}
public final void incq(Register dst) {
// Don't use it directly. Use Macroincrementq() instead.
// Use two-byte form (one-byte from is a REX prefix in 64-bit mode)
- int encode = prefixqAndEncode(dst.encoding);
+ prefixq(dst);
emitByte(0xFF);
- emitByte(0xC0 | encode);
+ emitModRM(0, dst);
}
public final void incq(AMD64Address dst) {
@@ -3498,115 +2877,80 @@
}
public final void movq(Register dst, long imm64) {
- int encode = prefixqAndEncode(dst.encoding);
- emitByte(0xB8 | encode);
+ movq(dst, imm64, false);
+ }
+
+ public final void movq(Register dst, long imm64, boolean annotateImm) {
+ int insnPos = position();
+ prefixq(dst);
+ emitByte(0xB8 + encode(dst));
+ int immPos = position();
emitLong(imm64);
+ int nextInsnPos = position();
+ if (annotateImm && codePatchingAnnotationConsumer != null) {
+ codePatchingAnnotationConsumer.accept(new ImmediateOperandAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos));
+ }
}
public final void movslq(Register dst, int imm32) {
- int encode = prefixqAndEncode(dst.encoding);
+ prefixq(dst);
emitByte(0xC7);
- emitByte(0xC0 | encode);
+ emitModRM(0, dst);
emitInt(imm32);
}
public final void movdq(Register dst, AMD64Address src) {
- assert dst.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ true, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- simdPrefix(dst, Register.None, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
- emitByte(0x6E);
- emitOperandHelper(dst, src, 0);
+ AMD64RMOp.MOVQ.emit(this, QWORD, dst, src);
}
public final void movdq(AMD64Address dst, Register src) {
- assert src.getRegisterCategory().equals(AMD64.XMM);
- // swap src/dst to get correct prefix
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ true, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- simdPrefix(src, Register.None, dst, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
- emitByte(0x7E);
- emitOperandHelper(src, dst, 0);
+ AMD64MROp.MOVQ.emit(this, QWORD, dst, src);
}
public final void movdq(Register dst, Register src) {
- if (dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.CPU)) {
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ true, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(dst, Register.None, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
- emitByte(0x6E);
- emitByte(0xC0 | encode);
- } else if (src.getRegisterCategory().equals(AMD64.XMM) && dst.getRegisterCategory().equals(AMD64.CPU)) {
- // swap src/dst to get correct prefix
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ true, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(src, Register.None, dst, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
- emitByte(0x7E);
- emitByte(0xC0 | encode);
+ if (dst.getRegisterCategory().equals(XMM) && src.getRegisterCategory().equals(CPU)) {
+ AMD64RMOp.MOVQ.emit(this, QWORD, dst, src);
+ } else if (src.getRegisterCategory().equals(XMM) && dst.getRegisterCategory().equals(CPU)) {
+ AMD64MROp.MOVQ.emit(this, QWORD, dst, src);
} else {
throw new InternalError("should not reach here");
}
}
public final void movdl(Register dst, Register src) {
- if (dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.CPU)) {
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(dst, Register.None, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
- emitByte(0x6E);
- emitByte(0xC0 | encode);
- } else if (src.getRegisterCategory().equals(AMD64.XMM) && dst.getRegisterCategory().equals(AMD64.CPU)) {
- // swap src/dst to get correct prefix
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(src, Register.None, dst, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
- emitByte(0x7E);
- emitByte(0xC0 | encode);
+ if (dst.getRegisterCategory().equals(XMM) && src.getRegisterCategory().equals(CPU)) {
+ AMD64RMOp.MOVD.emit(this, DWORD, dst, src);
+ } else if (src.getRegisterCategory().equals(XMM) && dst.getRegisterCategory().equals(CPU)) {
+ AMD64MROp.MOVD.emit(this, DWORD, dst, src);
} else {
throw new InternalError("should not reach here");
}
}
public final void movdl(Register dst, AMD64Address src) {
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- simdPrefix(dst, Register.None, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
- emitByte(0x6E);
- emitOperandHelper(dst, src, 0);
+ AMD64RMOp.MOVD.emit(this, DWORD, dst, src);
}
public final void movddup(Register dst, Register src) {
assert supports(CPUFeature.SSE3);
- assert dst.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(dst, Register.None, src, VexSimdPrefix.VEX_SIMD_F2, VexOpcode.VEX_OPCODE_0F, attributes);
+ assert dst.getRegisterCategory().equals(XMM) && src.getRegisterCategory().equals(XMM);
+ simdPrefix(dst, Register.None, src, SD, P_0F, false);
emitByte(0x12);
- emitByte(0xC0 | encode);
+ emitModRM(dst, src);
}
public final void movdqu(Register dst, AMD64Address src) {
- assert dst.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- simdPrefix(dst, Register.None, src, VexSimdPrefix.VEX_SIMD_F3, VexOpcode.VEX_OPCODE_0F, attributes);
+ assert dst.getRegisterCategory().equals(XMM);
+ simdPrefix(dst, Register.None, src, SS, P_0F, false);
emitByte(0x6F);
emitOperandHelper(dst, src, 0);
}
public final void movdqu(Register dst, Register src) {
- assert dst.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- int encode = simdPrefixAndEncode(dst, Register.None, src, VexSimdPrefix.VEX_SIMD_F3, VexOpcode.VEX_OPCODE_0F, attributes);
+ assert dst.getRegisterCategory().equals(XMM) && src.getRegisterCategory().equals(XMM);
+ simdPrefix(dst, Register.None, src, SS, P_0F, false);
emitByte(0x6F);
- emitByte(0xC0 | encode);
- }
-
- public final void vmovdqu(Register dst, AMD64Address src) {
- assert supports(CPUFeature.AVX);
- assert dst.getRegisterCategory().equals(AMD64.XMM);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_256bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- vexPrefix(src, Register.None, dst, VexSimdPrefix.VEX_SIMD_F3, VexOpcode.VEX_OPCODE_0F, attributes);
- emitByte(0x6F);
- emitOperandHelper(dst, src, 0);
- }
-
- public final void vzeroupper() {
- assert supports(CPUFeature.AVX);
- AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
- vexPrefixAndEncode(AMD64.xmm0, AMD64.xmm0, AMD64.xmm0, VexSimdPrefix.VEX_SIMD_NONE, VexOpcode.VEX_OPCODE_0F, attributes);
- emitByte(0x77);
+ emitModRM(dst, src);
}
public final void movslq(AMD64Address dst, int imm32) {
@@ -3623,15 +2967,15 @@
}
public final void movslq(Register dst, Register src) {
- int encode = prefixqAndEncode(dst.encoding, src.encoding);
+ prefixq(dst, src);
emitByte(0x63);
- emitByte(0xC0 | encode);
+ emitModRM(dst, src);
}
public final void negq(Register dst) {
- int encode = prefixqAndEncode(dst.encoding);
+ prefixq(dst);
emitByte(0xF7);
- emitByte(0xD8 | encode);
+ emitModRM(3, dst);
}
public final void orq(Register dst, Register src) {
@@ -3640,40 +2984,42 @@
public final void shlq(Register dst, int imm8) {
assert isShiftCount(imm8 >> 1) : "illegal shift count";
- int encode = prefixqAndEncode(dst.encoding);
+ prefixq(dst);
if (imm8 == 1) {
emitByte(0xD1);
- emitByte(0xE0 | encode);
+ emitModRM(4, dst);
} else {
emitByte(0xC1);
- emitByte(0xE0 | encode);
+ emitModRM(4, dst);
emitByte(imm8);
}
}
public final void shlq(Register dst) {
- int encode = prefixqAndEncode(dst.encoding);
+ // Multiply dst by 2, CL times.
+ prefixq(dst);
emitByte(0xD3);
- emitByte(0xE0 | encode);
+ emitModRM(4, dst);
}
public final void shrq(Register dst, int imm8) {
assert isShiftCount(imm8 >> 1) : "illegal shift count";
- int encode = prefixqAndEncode(dst.encoding);
+ prefixq(dst);
if (imm8 == 1) {
emitByte(0xD1);
- emitByte(0xE8 | encode);
+ emitModRM(5, dst);
} else {
emitByte(0xC1);
- emitByte(0xE8 | encode);
+ emitModRM(5, dst);
emitByte(imm8);
}
}
public final void shrq(Register dst) {
- int encode = prefixqAndEncode(dst.encoding);
+ prefixq(dst);
emitByte(0xD3);
- emitByte(0xE8 | encode);
+ // Unsigned divide dst by 2, CL times.
+ emitModRM(5, dst);
}
public final void sbbq(Register dst, Register src) {
@@ -3698,16 +3044,16 @@
}
public final void testq(Register dst, Register src) {
- int encode = prefixqAndEncode(dst.encoding, src.encoding);
+ prefixq(dst, src);
emitByte(0x85);
- emitByte(0xC0 | encode);
+ emitModRM(dst, src);
}
public final void btrq(Register src, int imm8) {
- int encode = prefixqAndEncode(src.encoding);
+ prefixq(src);
emitByte(0x0F);
emitByte(0xBA);
- emitByte(0xF0 | encode);
+ emitModRM(6, src);
emitByte(imm8);
}
@@ -3778,7 +3124,7 @@
// the code where this idiom is used, in particular the
// orderAccess code.
lock();
- addl(new AMD64Address(rsp, 0), 0); // Assert the lock# signal here
+ addl(new AMD64Address(AMD64.rsp, 0), 0); // Assert the lock# signal here
}
}
}
@@ -3842,18 +3188,15 @@
* responsible to add the call address to the appropriate patching tables.
*/
public final void call() {
- if (codePatchingAnnotationConsumer != null) {
- int pos = position();
- codePatchingAnnotationConsumer.accept(new ImmediateOperandAnnotation(pos, pos + 1, 4, pos + 5));
- }
+ annotatePatchingImmediate(1, 4);
emitByte(0xE8);
emitInt(0);
}
public final void call(Register src) {
- int encode = prefixAndEncode(src.encoding);
+ prefix(src);
emitByte(0xFF);
- emitByte(0xD0 | encode);
+ emitModRM(2, src);
}
public final void int3() {
@@ -3965,7 +3308,7 @@
@Override
public AMD64Address getPlaceholder(int instructionStartPosition) {
- return new AMD64Address(rip, Register.None, Scale.Times1, 0, instructionStartPosition);
+ return new AMD64Address(AMD64.rip, Register.None, Scale.Times1, 0, instructionStartPosition);
}
private void prefetchPrefix(AMD64Address src) {
@@ -4034,6 +3377,93 @@
emitByte(0x0f);
emitByte(0xae);
emitByte(0xe8);
-
+ }
+
+ public final void vptest(Register dst, Register src) {
+ VexRMOp.VPTEST.emit(this, AVXSize.YMM, dst, src);
+ }
+
+ public final void vpxor(Register dst, Register nds, Register src) {
+ VexRVMOp.VPXOR.emit(this, AVXSize.YMM, dst, nds, src);
+ }
+
+ public final void vpxor(Register dst, Register nds, AMD64Address src) {
+ VexRVMOp.VPXOR.emit(this, AVXSize.YMM, dst, nds, src);
+ }
+
+ public final void vmovdqu(Register dst, AMD64Address src) {
+ VexMoveOp.VMOVDQU.emit(this, AVXSize.YMM, dst, src);
+ }
+
+ public final void vpmovzxbw(Register dst, AMD64Address src) {
+ VexRMOp.VPMOVZXBW.emit(this, AVXSize.YMM, dst, src);
+ }
+
+ public final void vzeroupper() {
+ emitVEX(L128, P_, M_0F, W0, 0, 0);
+ emitByte(0x77);
+ }
+
+ // This instruction produces ZF or CF flags
+ public final void kortestq(Register src1, Register src2) {
+ assert supports(CPUFeature.AVX512BW);
+ assert src1.getRegisterCategory().equals(MASK) && src2.getRegisterCategory().equals(MASK);
+ vexPrefix(src1, Register.None, src2, AVXSize.XMM, P_, M_0F, W1);
+ emitByte(0x98);
+ emitModRM(src1, src2);
+ }
+
+ public final void kmovq(Register dst, Register src) {
+ assert supports(CPUFeature.AVX512BW);
+ assert dst.getRegisterCategory().equals(MASK) || dst.getRegisterCategory().equals(CPU);
+ assert src.getRegisterCategory().equals(MASK) || src.getRegisterCategory().equals(CPU);
+ assert !(dst.getRegisterCategory().equals(CPU) && src.getRegisterCategory().equals(CPU));
+
+ if (dst.getRegisterCategory().equals(MASK)) {
+ if (src.getRegisterCategory().equals(MASK)) {
+ // kmovq(KRegister dst, KRegister src)
+ vexPrefix(dst, Register.None, src, AVXSize.XMM, P_, M_0F, W1);
+ emitByte(0x90);
+ emitModRM(dst, src);
+ } else {
+ // kmovq(KRegister dst, Register src)
+ vexPrefix(dst, Register.None, src, AVXSize.XMM, P_F2, M_0F, W1);
+ emitByte(0x92);
+ emitModRM(dst, src);
+ }
+ } else {
+ if (src.getRegisterCategory().equals(MASK)) {
+ // kmovq(Register dst, KRegister src)
+ vexPrefix(dst, Register.None, src, AVXSize.XMM, P_F2, M_0F, W1);
+ emitByte(0x93);
+ emitModRM(dst, src);
+ } else {
+ throw GraalError.shouldNotReachHere();
+ }
+ }
+ }
+
+ public final void evmovdqu64(Register dst, AMD64Address src) {
+ assert supports(CPUFeature.AVX512F);
+ assert dst.getRegisterCategory().equals(XMM);
+ evexPrefix(dst, Register.None, Register.None, src, AVXSize.ZMM, P_F3, M_0F, W1, Z0, B0);
+ emitByte(0x6F);
+ emitEVEXOperandHelper(dst, src, 0, EVEXTuple.FVM.getDisp8ScalingFactor(AVXSize.ZMM));
+ }
+
+ public final void evpmovzxbw(Register dst, AMD64Address src) {
+ assert supports(CPUFeature.AVX512BW);
+ assert dst.getRegisterCategory().equals(XMM);
+ evexPrefix(dst, Register.None, Register.None, src, AVXSize.ZMM, P_66, M_0F38, WIG, Z0, B0);
+ emitByte(0x30);
+ emitEVEXOperandHelper(dst, src, 0, EVEXTuple.HVM.getDisp8ScalingFactor(AVXSize.ZMM));
+ }
+
+ public final void evpcmpeqb(Register kdst, Register nds, AMD64Address src) {
+ assert supports(CPUFeature.AVX512BW);
+ assert kdst.getRegisterCategory().equals(MASK) && nds.getRegisterCategory().equals(XMM);
+ evexPrefix(kdst, Register.None, nds, src, AVXSize.ZMM, P_66, M_0F, WIG, Z0, B0);
+ emitByte(0x74);
+ emitEVEXOperandHelper(kdst, src, 0, EVEXTuple.FVM.getDisp8ScalingFactor(AVXSize.ZMM));
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64BaseAssembler.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,1077 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.asm.amd64;
+
+import static jdk.vm.ci.amd64.AMD64.MASK;
+import static jdk.vm.ci.amd64.AMD64.XMM;
+import static jdk.vm.ci.amd64.AMD64.r12;
+import static jdk.vm.ci.amd64.AMD64.r13;
+import static jdk.vm.ci.amd64.AMD64.rbp;
+import static jdk.vm.ci.amd64.AMD64.rsp;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.EVEXPrefixConfig.B0;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.EVEXPrefixConfig.B1;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.EVEXPrefixConfig.L512;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.EVEXPrefixConfig.Z0;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.EVEXPrefixConfig.Z1;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.VEXPrefixConfig.L128;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.VEXPrefixConfig.L256;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.VEXPrefixConfig.LIG;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.VEXPrefixConfig.M_0F;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.VEXPrefixConfig.M_0F38;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.VEXPrefixConfig.M_0F3A;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.VEXPrefixConfig.P_;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.VEXPrefixConfig.P_66;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.VEXPrefixConfig.P_F2;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.VEXPrefixConfig.P_F3;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.VEXPrefixConfig.W0;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.VEXPrefixConfig.W1;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.VEXPrefixConfig.WIG;
+import static org.graalvm.compiler.core.common.NumUtil.isByte;
+
+import org.graalvm.compiler.asm.Assembler;
+import org.graalvm.compiler.asm.amd64.AMD64Address.Scale;
+import org.graalvm.compiler.asm.amd64.AVXKind.AVXSize;
+import org.graalvm.compiler.debug.GraalError;
+
+import jdk.vm.ci.amd64.AMD64;
+import jdk.vm.ci.amd64.AMD64.CPUFeature;
+import jdk.vm.ci.amd64.AMD64Kind;
+import jdk.vm.ci.code.Register;
+import jdk.vm.ci.code.TargetDescription;
+import jdk.vm.ci.meta.PlatformKind;
+
+/**
+ * This class implements an assembler that can encode most X86 instructions.
+ */
+public abstract class AMD64BaseAssembler extends Assembler {
+
+ private final SIMDEncoder simdEncoder;
+
+ /**
+ * Constructs an assembler for the AMD64 architecture.
+ */
+ public AMD64BaseAssembler(TargetDescription target) {
+ super(target);
+
+ if (supports(CPUFeature.AVX)) {
+ simdEncoder = new VEXEncoderImpl();
+ } else {
+ simdEncoder = new SSEEncoderImpl();
+ }
+ }
+
+ /**
+ * The x86 operand sizes.
+ */
+ public enum OperandSize {
+ BYTE(1, AMD64Kind.BYTE) {
+ @Override
+ protected void emitImmediate(AMD64BaseAssembler asm, int imm) {
+ assert imm == (byte) imm;
+ asm.emitByte(imm);
+ }
+
+ @Override
+ protected int immediateSize() {
+ return 1;
+ }
+ },
+
+ WORD(2, AMD64Kind.WORD, 0x66) {
+ @Override
+ protected void emitImmediate(AMD64BaseAssembler asm, int imm) {
+ assert imm == (short) imm;
+ asm.emitShort(imm);
+ }
+
+ @Override
+ protected int immediateSize() {
+ return 2;
+ }
+ },
+
+ DWORD(4, AMD64Kind.DWORD) {
+ @Override
+ protected void emitImmediate(AMD64BaseAssembler asm, int imm) {
+ asm.emitInt(imm);
+ }
+
+ @Override
+ protected int immediateSize() {
+ return 4;
+ }
+ },
+
+ QWORD(8, AMD64Kind.QWORD) {
+ @Override
+ protected void emitImmediate(AMD64BaseAssembler asm, int imm) {
+ asm.emitInt(imm);
+ }
+
+ @Override
+ protected int immediateSize() {
+ return 4;
+ }
+ },
+
+ SS(4, AMD64Kind.SINGLE, 0xF3, true),
+
+ SD(8, AMD64Kind.DOUBLE, 0xF2, true),
+
+ PS(16, AMD64Kind.V128_SINGLE, true),
+
+ PD(16, AMD64Kind.V128_DOUBLE, 0x66, true);
+
+ private final int sizePrefix;
+ private final int bytes;
+ private final boolean xmm;
+ private final AMD64Kind kind;
+
+ OperandSize(int bytes, AMD64Kind kind) {
+ this(bytes, kind, 0);
+ }
+
+ OperandSize(int bytes, AMD64Kind kind, int sizePrefix) {
+ this(bytes, kind, sizePrefix, false);
+ }
+
+ OperandSize(int bytes, AMD64Kind kind, boolean xmm) {
+ this(bytes, kind, 0, xmm);
+ }
+
+ OperandSize(int bytes, AMD64Kind kind, int sizePrefix, boolean xmm) {
+ this.sizePrefix = sizePrefix;
+ this.bytes = bytes;
+ this.kind = kind;
+ this.xmm = xmm;
+ }
+
+ public int getSizePrefix() {
+ return sizePrefix;
+ }
+
+ public int getBytes() {
+ return bytes;
+ }
+
+ public boolean isXmmType() {
+ return xmm;
+ }
+
+ public AMD64Kind getKind() {
+ return kind;
+ }
+
+ public static OperandSize get(PlatformKind kind) {
+ for (OperandSize operandSize : OperandSize.values()) {
+ if (operandSize.kind.equals(kind)) {
+ return operandSize;
+ }
+ }
+ throw GraalError.shouldNotReachHere("Unexpected kind: " + kind.toString());
+ }
+
+ /**
+ * Emit an immediate of this size. Note that immediate {@link #QWORD} operands are encoded
+ * as sign-extended 32-bit values.
+ *
+ * @param asm
+ * @param imm
+ */
+ protected void emitImmediate(AMD64BaseAssembler asm, int imm) {
+ throw new UnsupportedOperationException();
+ }
+
+ protected int immediateSize() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ public abstract static class OperandDataAnnotation extends CodeAnnotation {
+ /**
+ * The position (bytes from the beginning of the method) of the operand.
+ */
+ public final int operandPosition;
+ /**
+ * The size of the operand, in bytes.
+ */
+ public final int operandSize;
+ /**
+ * The position (bytes from the beginning of the method) of the next instruction. On AMD64,
+ * RIP-relative operands are relative to this position.
+ */
+ public final int nextInstructionPosition;
+
+ OperandDataAnnotation(int instructionPosition, int operandPosition, int operandSize, int nextInstructionPosition) {
+ super(instructionPosition);
+
+ this.operandPosition = operandPosition;
+ this.operandSize = operandSize;
+ this.nextInstructionPosition = nextInstructionPosition;
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + " instruction [" + instructionPosition + ", " + nextInstructionPosition + "[ operand at " + operandPosition + " size " + operandSize;
+ }
+ }
+
+ /**
+ * Annotation that stores additional information about the displacement of a
+ * {@link Assembler#getPlaceholder placeholder address} that needs patching.
+ */
+ protected static class AddressDisplacementAnnotation extends OperandDataAnnotation {
+ AddressDisplacementAnnotation(int instructionPosition, int operandPosition, int operandSize, int nextInstructionPosition) {
+ super(instructionPosition, operandPosition, operandSize, nextInstructionPosition);
+ }
+ }
+
+ /**
+ * Annotation that stores additional information about the immediate operand, e.g., of a call
+ * instruction, that needs patching.
+ */
+ protected static class ImmediateOperandAnnotation extends OperandDataAnnotation {
+ ImmediateOperandAnnotation(int instructionPosition, int operandPosition, int operandSize, int nextInstructionPosition) {
+ super(instructionPosition, operandPosition, operandSize, nextInstructionPosition);
+ }
+ }
+
+ protected void annotatePatchingImmediate(int operandOffset, int operandSize) {
+ if (codePatchingAnnotationConsumer != null) {
+ int pos = position();
+ codePatchingAnnotationConsumer.accept(new ImmediateOperandAnnotation(pos, pos + operandOffset, operandSize, pos + operandOffset + operandSize));
+ }
+ }
+
+ public final boolean supports(CPUFeature feature) {
+ return ((AMD64) target.arch).getFeatures().contains(feature);
+ }
+
+ protected static int encode(Register r) {
+ assert r.encoding >= 0 && (r.getRegisterCategory().equals(XMM) ? r.encoding < 32 : r.encoding < 16) : "encoding out of range: " + r.encoding;
+ return r.encoding & 0x7;
+ }
+
+ private static final int MinEncodingNeedsRex = 8;
+
+ /**
+ * Constants for X86 prefix bytes.
+ */
+ private static class Prefix {
+ private static final int REX = 0x40;
+ private static final int REXB = 0x41;
+ private static final int REXX = 0x42;
+ private static final int REXXB = 0x43;
+ private static final int REXR = 0x44;
+ private static final int REXRB = 0x45;
+ private static final int REXRX = 0x46;
+ private static final int REXRXB = 0x47;
+ private static final int REXW = 0x48;
+ private static final int REXWB = 0x49;
+ private static final int REXWX = 0x4A;
+ private static final int REXWXB = 0x4B;
+ private static final int REXWR = 0x4C;
+ private static final int REXWRB = 0x4D;
+ private static final int REXWRX = 0x4E;
+ private static final int REXWRXB = 0x4F;
+ }
+
+ protected final void rexw() {
+ emitByte(Prefix.REXW);
+ }
+
+ protected final void prefix(Register reg) {
+ prefix(reg, false);
+ }
+
+ protected final void prefix(Register reg, boolean byteinst) {
+ int regEnc = reg.encoding;
+ if (regEnc >= 8) {
+ emitByte(Prefix.REXB);
+ } else if (byteinst && regEnc >= 4) {
+ emitByte(Prefix.REX);
+ }
+ }
+
+ protected final void prefixq(Register reg) {
+ if (reg.encoding < 8) {
+ emitByte(Prefix.REXW);
+ } else {
+ emitByte(Prefix.REXWB);
+ }
+ }
+
+ protected final void prefix(Register dst, Register src) {
+ prefix(dst, false, src, false);
+ }
+
+ protected final void prefix(Register dst, boolean dstIsByte, Register src, boolean srcIsByte) {
+ int dstEnc = dst.encoding;
+ int srcEnc = src.encoding;
+ if (dstEnc < 8) {
+ if (srcEnc >= 8) {
+ emitByte(Prefix.REXB);
+ } else if ((srcIsByte && srcEnc >= 4) || (dstIsByte && dstEnc >= 4)) {
+ emitByte(Prefix.REX);
+ }
+ } else {
+ if (srcEnc < 8) {
+ emitByte(Prefix.REXR);
+ } else {
+ emitByte(Prefix.REXRB);
+ }
+ }
+ }
+
+ /**
+ * Creates prefix for the operands. If the given operands exceed 3 bits, the 4th bit is encoded
+ * in the prefix.
+ */
+ protected final void prefixq(Register reg, Register rm) {
+ int regEnc = reg.encoding;
+ int rmEnc = rm.encoding;
+ if (regEnc < 8) {
+ if (rmEnc < 8) {
+ emitByte(Prefix.REXW);
+ } else {
+ emitByte(Prefix.REXWB);
+ }
+ } else {
+ if (rmEnc < 8) {
+ emitByte(Prefix.REXWR);
+ } else {
+ emitByte(Prefix.REXWRB);
+ }
+ }
+ }
+
+ private static boolean needsRex(Register reg) {
+ return reg.encoding >= MinEncodingNeedsRex;
+ }
+
+ protected final void prefix(AMD64Address adr) {
+ if (needsRex(adr.getBase())) {
+ if (needsRex(adr.getIndex())) {
+ emitByte(Prefix.REXXB);
+ } else {
+ emitByte(Prefix.REXB);
+ }
+ } else {
+ if (needsRex(adr.getIndex())) {
+ emitByte(Prefix.REXX);
+ }
+ }
+ }
+
+ protected final void prefixq(AMD64Address adr) {
+ if (needsRex(adr.getBase())) {
+ if (needsRex(adr.getIndex())) {
+ emitByte(Prefix.REXWXB);
+ } else {
+ emitByte(Prefix.REXWB);
+ }
+ } else {
+ if (needsRex(adr.getIndex())) {
+ emitByte(Prefix.REXWX);
+ } else {
+ emitByte(Prefix.REXW);
+ }
+ }
+ }
+
+ protected void prefixb(AMD64Address adr, Register reg) {
+ prefix(adr, reg, true);
+ }
+
+ protected void prefix(AMD64Address adr, Register reg) {
+ prefix(adr, reg, false);
+ }
+
+ protected void prefix(AMD64Address adr, Register reg, boolean byteinst) {
+ if (reg.encoding < 8) {
+ if (needsRex(adr.getBase())) {
+ if (needsRex(adr.getIndex())) {
+ emitByte(Prefix.REXXB);
+ } else {
+ emitByte(Prefix.REXB);
+ }
+ } else {
+ if (needsRex(adr.getIndex())) {
+ emitByte(Prefix.REXX);
+ } else if (byteinst && reg.encoding >= 4) {
+ emitByte(Prefix.REX);
+ }
+ }
+ } else {
+ if (needsRex(adr.getBase())) {
+ if (needsRex(adr.getIndex())) {
+ emitByte(Prefix.REXRXB);
+ } else {
+ emitByte(Prefix.REXRB);
+ }
+ } else {
+ if (needsRex(adr.getIndex())) {
+ emitByte(Prefix.REXRX);
+ } else {
+ emitByte(Prefix.REXR);
+ }
+ }
+ }
+ }
+
+ protected void prefixq(AMD64Address adr, Register src) {
+ if (src.encoding < 8) {
+ if (needsRex(adr.getBase())) {
+ if (needsRex(adr.getIndex())) {
+ emitByte(Prefix.REXWXB);
+ } else {
+ emitByte(Prefix.REXWB);
+ }
+ } else {
+ if (needsRex(adr.getIndex())) {
+ emitByte(Prefix.REXWX);
+ } else {
+ emitByte(Prefix.REXW);
+ }
+ }
+ } else {
+ if (needsRex(adr.getBase())) {
+ if (needsRex(adr.getIndex())) {
+ emitByte(Prefix.REXWRXB);
+ } else {
+ emitByte(Prefix.REXWRB);
+ }
+ } else {
+ if (needsRex(adr.getIndex())) {
+ emitByte(Prefix.REXWRX);
+ } else {
+ emitByte(Prefix.REXWR);
+ }
+ }
+ }
+ }
+
+ /**
+ * Get RXB bits for register-register instruction. In that encoding, ModRM.rm contains a
+ * register index. The R bit extends the ModRM.reg field and the B bit extends the ModRM.rm
+ * field. The X bit must be 0.
+ */
+ protected static int getRXB(Register reg, Register rm) {
+ int rxb = (reg == null ? 0 : reg.encoding & 0x08) >> 1;
+ rxb |= (rm == null ? 0 : rm.encoding & 0x08) >> 3;
+ return rxb;
+ }
+
+ /**
+ * Get RXB bits for register-memory instruction. The R bit extends the ModRM.reg field. There
+ * are two cases for the memory operand:<br>
+ * ModRM.rm contains the base register: In that case, B extends the ModRM.rm field and X = 0.
+ * <br>
+ * There is an SIB byte: In that case, X extends SIB.index and B extends SIB.base.
+ */
+ protected static int getRXB(Register reg, AMD64Address rm) {
+ int rxb = (reg == null ? 0 : reg.encoding & 0x08) >> 1;
+ if (!rm.getIndex().equals(Register.None)) {
+ rxb |= (rm.getIndex().encoding & 0x08) >> 2;
+ }
+ if (!rm.getBase().equals(Register.None)) {
+ rxb |= (rm.getBase().encoding & 0x08) >> 3;
+ }
+ return rxb;
+ }
+
+ /**
+ * Emit the ModR/M byte for one register operand and an opcode extension in the R field.
+ * <p>
+ * Format: [ 11 reg r/m ]
+ */
+ protected final void emitModRM(int reg, Register rm) {
+ assert (reg & 0x07) == reg;
+ emitByte(0xC0 | (reg << 3) | (rm.encoding & 0x07));
+ }
+
+ /**
+ * Emit the ModR/M byte for two register operands.
+ * <p>
+ * Format: [ 11 reg r/m ]
+ */
+ protected final void emitModRM(Register reg, Register rm) {
+ emitModRM(reg.encoding & 0x07, rm);
+ }
+
+ /**
+ * Emits the ModR/M byte and optionally the SIB byte for one register and one memory operand.
+ *
+ * @param force4Byte use 4 byte encoding for displacements that would normally fit in a byte
+ */
+ protected final void emitOperandHelper(Register reg, AMD64Address addr, boolean force4Byte, int additionalInstructionSize) {
+ assert !reg.equals(Register.None);
+ emitOperandHelper(encode(reg), addr, force4Byte, additionalInstructionSize, 1);
+ }
+
+ protected final void emitOperandHelper(int reg, AMD64Address addr, int additionalInstructionSize) {
+ emitOperandHelper(reg, addr, false, additionalInstructionSize, 1);
+ }
+
+ protected final void emitOperandHelper(Register reg, AMD64Address addr, int additionalInstructionSize) {
+ assert !reg.equals(Register.None);
+ emitOperandHelper(encode(reg), addr, false, additionalInstructionSize, 1);
+ }
+
+ protected final void emitEVEXOperandHelper(Register reg, AMD64Address addr, int additionalInstructionSize, int evexDisp8Scale) {
+ assert !reg.equals(Register.None);
+ emitOperandHelper(encode(reg), addr, false, additionalInstructionSize, evexDisp8Scale);
+ }
+
+ /**
+ * Emits the ModR/M byte and optionally the SIB byte for one memory operand and an opcode
+ * extension in the R field.
+ *
+ * @param force4Byte use 4 byte encoding for displacements that would normally fit in a byte
+ * @param additionalInstructionSize the number of bytes that will be emitted after the operand,
+ * so that the start position of the next instruction can be computed even though
+ * this instruction has not been completely emitted yet.
+ * @param evexDisp8Scale the scaling factor for computing the compressed displacement of
+ * EVEX-encoded instructions. This scaling factor only matters when the emitted
+ * instruction uses one-byte-displacement form.
+ */
+ private void emitOperandHelper(int reg, AMD64Address addr, boolean force4Byte, int additionalInstructionSize, int evexDisp8Scale) {
+ assert (reg & 0x07) == reg;
+ int regenc = reg << 3;
+
+ Register base = addr.getBase();
+ Register index = addr.getIndex();
+
+ Scale scale = addr.getScale();
+ int disp = addr.getDisplacement();
+
+ if (base.equals(AMD64.rip)) { // also matches addresses returned by getPlaceholder()
+ // [00 000 101] disp32
+ assert index.equals(Register.None) : "cannot use RIP relative addressing with index register";
+ emitByte(0x05 | regenc);
+ if (codePatchingAnnotationConsumer != null && addr.instructionStartPosition >= 0) {
+ codePatchingAnnotationConsumer.accept(new AddressDisplacementAnnotation(addr.instructionStartPosition, position(), 4, position() + 4 + additionalInstructionSize));
+ }
+ emitInt(disp);
+ } else if (base.isValid()) {
+ boolean overriddenForce4Byte = force4Byte;
+ int baseenc = base.isValid() ? encode(base) : 0;
+
+ if (index.isValid()) {
+ int indexenc = encode(index) << 3;
+ // [base + indexscale + disp]
+ if (disp == 0 && !base.equals(rbp) && !base.equals(r13)) {
+ // [base + indexscale]
+ // [00 reg 100][ss index base]
+ assert !index.equals(rsp) : "illegal addressing mode";
+ emitByte(0x04 | regenc);
+ emitByte(scale.log2 << 6 | indexenc | baseenc);
+ } else {
+ if (evexDisp8Scale > 1 && !overriddenForce4Byte) {
+ if (disp % evexDisp8Scale == 0) {
+ int newDisp = disp / evexDisp8Scale;
+ if (isByte(newDisp)) {
+ disp = newDisp;
+ assert isByte(disp) && !overriddenForce4Byte;
+ }
+ } else {
+ overriddenForce4Byte = true;
+ }
+ }
+ if (isByte(disp) && !overriddenForce4Byte) {
+ // [base + indexscale + imm8]
+ // [01 reg 100][ss index base] imm8
+ assert !index.equals(rsp) : "illegal addressing mode";
+ emitByte(0x44 | regenc);
+ emitByte(scale.log2 << 6 | indexenc | baseenc);
+ emitByte(disp & 0xFF);
+ } else {
+ // [base + indexscale + disp32]
+ // [10 reg 100][ss index base] disp32
+ assert !index.equals(rsp) : "illegal addressing mode";
+ emitByte(0x84 | regenc);
+ emitByte(scale.log2 << 6 | indexenc | baseenc);
+ emitInt(disp);
+ }
+ }
+ } else if (base.equals(rsp) || base.equals(r12)) {
+ // [rsp + disp]
+ if (disp == 0) {
+ // [rsp]
+ // [00 reg 100][00 100 100]
+ emitByte(0x04 | regenc);
+ emitByte(0x24);
+ } else {
+ if (evexDisp8Scale > 1 && !overriddenForce4Byte) {
+ if (disp % evexDisp8Scale == 0) {
+ int newDisp = disp / evexDisp8Scale;
+ if (isByte(newDisp)) {
+ disp = newDisp;
+ assert isByte(disp) && !overriddenForce4Byte;
+ }
+ } else {
+ overriddenForce4Byte = true;
+ }
+ }
+ if (isByte(disp) && !overriddenForce4Byte) {
+ // [rsp + imm8]
+ // [01 reg 100][00 100 100] disp8
+ emitByte(0x44 | regenc);
+ emitByte(0x24);
+ emitByte(disp & 0xFF);
+ } else {
+ // [rsp + imm32]
+ // [10 reg 100][00 100 100] disp32
+ emitByte(0x84 | regenc);
+ emitByte(0x24);
+ emitInt(disp);
+ }
+ }
+ } else {
+ // [base + disp]
+ assert !base.equals(rsp) && !base.equals(r12) : "illegal addressing mode";
+ if (disp == 0 && !base.equals(rbp) && !base.equals(r13)) {
+ // [base]
+ // [00 reg base]
+ emitByte(0x00 | regenc | baseenc);
+ } else {
+ if (evexDisp8Scale > 1 && !overriddenForce4Byte) {
+ if (disp % evexDisp8Scale == 0) {
+ int newDisp = disp / evexDisp8Scale;
+ if (isByte(newDisp)) {
+ disp = newDisp;
+ assert isByte(disp) && !overriddenForce4Byte;
+ }
+ } else {
+ overriddenForce4Byte = true;
+ }
+ }
+ if (isByte(disp) && !overriddenForce4Byte) {
+ // [base + disp8]
+ // [01 reg base] disp8
+ emitByte(0x40 | regenc | baseenc);
+ emitByte(disp & 0xFF);
+ } else {
+ // [base + disp32]
+ // [10 reg base] disp32
+ emitByte(0x80 | regenc | baseenc);
+ emitInt(disp);
+ }
+ }
+ }
+ } else {
+ if (index.isValid()) {
+ int indexenc = encode(index) << 3;
+ // [indexscale + disp]
+ // [00 reg 100][ss index 101] disp32
+ assert !index.equals(rsp) : "illegal addressing mode";
+ emitByte(0x04 | regenc);
+ emitByte(scale.log2 << 6 | indexenc | 0x05);
+ emitInt(disp);
+ } else {
+ // [disp] ABSOLUTE
+ // [00 reg 100][00 100 101] disp32
+ emitByte(0x04 | regenc);
+ emitByte(0x25);
+ emitInt(disp);
+ }
+ }
+ }
+
+ private interface SIMDEncoder {
+
+ void simdPrefix(Register xreg, Register nds, AMD64Address adr, int sizePrefix, int opcodeEscapePrefix, boolean isRexW);
+
+ void simdPrefix(Register dst, Register nds, Register src, int sizePrefix, int opcodeEscapePrefix, boolean isRexW);
+
+ }
+
+ private class SSEEncoderImpl implements SIMDEncoder {
+
+ @Override
+ public void simdPrefix(Register xreg, Register nds, AMD64Address adr, int sizePrefix, int opcodeEscapePrefix, boolean isRexW) {
+ if (sizePrefix > 0) {
+ emitByte(sizePrefix);
+ }
+ if (isRexW) {
+ prefixq(adr, xreg);
+ } else {
+ prefix(adr, xreg);
+ }
+ if (opcodeEscapePrefix > 0xFF) {
+ emitShort(opcodeEscapePrefix);
+ } else if (opcodeEscapePrefix > 0) {
+ emitByte(opcodeEscapePrefix);
+ }
+ }
+
+ @Override
+ public void simdPrefix(Register dst, Register nds, Register src, int sizePrefix, int opcodeEscapePrefix, boolean isRexW) {
+ if (sizePrefix > 0) {
+ emitByte(sizePrefix);
+ }
+ if (isRexW) {
+ prefixq(dst, src);
+ } else {
+ prefix(dst, src);
+ }
+ if (opcodeEscapePrefix > 0xFF) {
+ emitShort(opcodeEscapePrefix);
+ } else if (opcodeEscapePrefix > 0) {
+ emitByte(opcodeEscapePrefix);
+ }
+ }
+ }
+
+ public static final class VEXPrefixConfig {
+ public static final int L128 = 0;
+ public static final int L256 = 1;
+ public static final int LIG = 0;
+
+ public static final int W0 = 0;
+ public static final int W1 = 1;
+ public static final int WIG = 0;
+
+ public static final int P_ = 0x0;
+ public static final int P_66 = 0x1;
+ public static final int P_F3 = 0x2;
+ public static final int P_F2 = 0x3;
+
+ public static final int M_0F = 0x1;
+ public static final int M_0F38 = 0x2;
+ public static final int M_0F3A = 0x3;
+
+ private VEXPrefixConfig() {
+ }
+ }
+
+ private class VEXEncoderImpl implements SIMDEncoder {
+
+ private int sizePrefixToPP(int sizePrefix) {
+ switch (sizePrefix) {
+ case 0x66:
+ return P_66;
+ case 0xF2:
+ return P_F2;
+ case 0xF3:
+ return P_F3;
+ default:
+ return P_;
+ }
+ }
+
+ private int opcodeEscapePrefixToMMMMM(int opcodeEscapePrefix) {
+ switch (opcodeEscapePrefix) {
+ case 0x0F:
+ return M_0F;
+ case 0x380F:
+ return M_0F38;
+ case 0x3A0F:
+ return M_0F3A;
+ default:
+ return 0;
+ }
+ }
+
+ @Override
+ public void simdPrefix(Register reg, Register nds, AMD64Address rm, int sizePrefix, int opcodeEscapePrefix, boolean isRexW) {
+ emitVEX(L128, sizePrefixToPP(sizePrefix), opcodeEscapePrefixToMMMMM(opcodeEscapePrefix), isRexW ? W1 : W0, getRXB(reg, rm), nds.isValid() ? nds.encoding : 0);
+ }
+
+ @Override
+ public void simdPrefix(Register dst, Register nds, Register src, int sizePrefix, int opcodeEscapePrefix, boolean isRexW) {
+ emitVEX(L128, sizePrefixToPP(sizePrefix), opcodeEscapePrefixToMMMMM(opcodeEscapePrefix), isRexW ? W1 : W0, getRXB(dst, src), nds.isValid() ? nds.encoding : 0);
+ }
+ }
+
+ protected final void simdPrefix(Register xreg, Register nds, AMD64Address adr, OperandSize size, int overriddenSizePrefix, int opcodeEscapePrefix, boolean isRexW) {
+ simdEncoder.simdPrefix(xreg, nds, adr, overriddenSizePrefix != 0 ? overriddenSizePrefix : size.sizePrefix, opcodeEscapePrefix, isRexW);
+ }
+
+ protected final void simdPrefix(Register xreg, Register nds, AMD64Address adr, OperandSize size, int opcodeEscapePrefix, boolean isRexW) {
+ simdEncoder.simdPrefix(xreg, nds, adr, size.sizePrefix, opcodeEscapePrefix, isRexW);
+ }
+
+ protected final void simdPrefix(Register dst, Register nds, Register src, OperandSize size, int overriddenSizePrefix, int opcodeEscapePrefix, boolean isRexW) {
+ simdEncoder.simdPrefix(dst, nds, src, overriddenSizePrefix != 0 ? overriddenSizePrefix : size.sizePrefix, opcodeEscapePrefix, isRexW);
+ }
+
+ protected final void simdPrefix(Register dst, Register nds, Register src, OperandSize size, int opcodeEscapePrefix, boolean isRexW) {
+ simdEncoder.simdPrefix(dst, nds, src, size.sizePrefix, opcodeEscapePrefix, isRexW);
+ }
+
+ /**
+ * Low-level function to encode and emit the VEX prefix.
+ * <p>
+ * 2 byte form: [1100 0101] [R vvvv L pp]<br>
+ * 3 byte form: [1100 0100] [RXB m-mmmm] [W vvvv L pp]
+ * <p>
+ * The RXB and vvvv fields are stored in 1's complement in the prefix encoding. This function
+ * performs the 1s complement conversion, the caller is expected to pass plain unencoded
+ * arguments.
+ * <p>
+ * The pp field encodes an extension to the opcode:<br>
+ * 00: no extension<br>
+ * 01: 66<br>
+ * 10: F3<br>
+ * 11: F2
+ * <p>
+ * The m-mmmm field encodes the leading bytes of the opcode:<br>
+ * 00001: implied 0F leading opcode byte (default in 2-byte encoding)<br>
+ * 00010: implied 0F 38 leading opcode bytes<br>
+ * 00011: implied 0F 3A leading opcode bytes
+ * <p>
+ * This function automatically chooses the 2 or 3 byte encoding, based on the XBW flags and the
+ * m-mmmm field.
+ */
+ protected final void emitVEX(int l, int pp, int mmmmm, int w, int rxb, int vvvv) {
+ assert ((AMD64) target.arch).getFeatures().contains(CPUFeature.AVX) : "emitting VEX prefix on a CPU without AVX support";
+
+ assert l == L128 || l == L256 || l == LIG : "invalid value for VEX.L";
+ assert pp == P_ || pp == P_66 || pp == P_F3 || pp == P_F2 : "invalid value for VEX.pp";
+ assert mmmmm == M_0F || mmmmm == M_0F38 || mmmmm == M_0F3A : "invalid value for VEX.m-mmmm";
+ assert w == W0 || w == W1 || w == WIG : "invalid value for VEX.W";
+
+ assert (rxb & 0x07) == rxb : "invalid value for VEX.RXB";
+ assert (vvvv & 0x0F) == vvvv : "invalid value for VEX.vvvv";
+
+ int rxb1s = rxb ^ 0x07;
+ int vvvv1s = vvvv ^ 0x0F;
+ if ((rxb & 0x03) == 0 && w == WIG && mmmmm == M_0F) {
+ // 2 byte encoding
+ int byte2 = 0;
+ byte2 |= (rxb1s & 0x04) << 5;
+ byte2 |= vvvv1s << 3;
+ byte2 |= l << 2;
+ byte2 |= pp;
+
+ emitByte(0xC5);
+ emitByte(byte2);
+ } else {
+ // 3 byte encoding
+ int byte2 = 0;
+ byte2 = (rxb1s & 0x07) << 5;
+ byte2 |= mmmmm;
+
+ int byte3 = 0;
+ byte3 |= w << 7;
+ byte3 |= vvvv1s << 3;
+ byte3 |= l << 2;
+ byte3 |= pp;
+
+ emitByte(0xC4);
+ emitByte(byte2);
+ emitByte(byte3);
+ }
+ }
+
+ private static int getLFlag(AVXSize size) {
+ switch (size) {
+ case XMM:
+ return L128;
+ case YMM:
+ return L256;
+ case ZMM:
+ return L512;
+ default:
+ return LIG;
+ }
+ }
+
+ public final void vexPrefix(Register dst, Register nds, Register src, AVXSize size, int pp, int mmmmm, int w) {
+ emitVEX(getLFlag(size), pp, mmmmm, w, getRXB(dst, src), nds.isValid() ? nds.encoding() : 0);
+ }
+
+ public final void vexPrefix(Register dst, Register nds, AMD64Address src, AVXSize size, int pp, int mmmmm, int w) {
+ emitVEX(getLFlag(size), pp, mmmmm, w, getRXB(dst, src), nds.isValid() ? nds.encoding() : 0);
+ }
+
+ protected static final class EVEXPrefixConfig {
+ public static final int L512 = 2;
+
+ public static final int Z0 = 0x0;
+ public static final int Z1 = 0x1;
+
+ public static final int B0 = 0x0;
+ public static final int B1 = 0x1;
+
+ private EVEXPrefixConfig() {
+ }
+ }
+
+ private static final int NOT_SUPPORTED_VECTOR_LENGTH = -1;
+
+ /**
+ * EVEX-encoded instructions use a compressed displacement scheme by multiplying disp8 with a
+ * scaling factor N depending on the tuple type and the vector length.
+ *
+ * Reference: Intel Software Developer's Manual Volume 2, Section 2.6.5
+ */
+ protected enum EVEXTuple {
+ FV_NO_BROADCAST_32BIT(16, 32, 64),
+ FV_BROADCAST_32BIT(4, 4, 4),
+ FV_NO_BROADCAST_64BIT(16, 32, 64),
+ FV_BROADCAST_64BIT(8, 8, 8),
+ HV_NO_BROADCAST_32BIT(8, 16, 32),
+ HV_BROADCAST_32BIT(4, 4, 4),
+ FVM(16, 32, 64),
+ T1S_8BIT(1, 1, 1),
+ T1S_16BIT(2, 2, 2),
+ T1S_32BIT(4, 4, 4),
+ T1S_64BIT(8, 8, 8),
+ T1F_32BIT(4, 4, 4),
+ T1F_64BIT(8, 8, 8),
+ T2_32BIT(8, 8, 8),
+ T2_64BIT(NOT_SUPPORTED_VECTOR_LENGTH, 16, 16),
+ T4_32BIT(NOT_SUPPORTED_VECTOR_LENGTH, 16, 16),
+ T4_64BIT(NOT_SUPPORTED_VECTOR_LENGTH, NOT_SUPPORTED_VECTOR_LENGTH, 32),
+ T8_32BIT(NOT_SUPPORTED_VECTOR_LENGTH, NOT_SUPPORTED_VECTOR_LENGTH, 32),
+ HVM(8, 16, 32),
+ QVM(4, 8, 16),
+ OVM(2, 4, 8),
+ M128(16, 16, 16),
+ DUP(8, 32, 64);
+
+ private final int scalingFactorVL128;
+ private final int scalingFactorVL256;
+ private final int scalingFactorVL512;
+
+ EVEXTuple(int scalingFactorVL128, int scalingFactorVL256, int scalingFactorVL512) {
+ this.scalingFactorVL128 = scalingFactorVL128;
+ this.scalingFactorVL256 = scalingFactorVL256;
+ this.scalingFactorVL512 = scalingFactorVL512;
+ }
+
+ private static int verifyScalingFactor(int scalingFactor) {
+ if (scalingFactor == NOT_SUPPORTED_VECTOR_LENGTH) {
+ throw GraalError.shouldNotReachHere("Invalid scaling factor.");
+ }
+ return scalingFactor;
+ }
+
+ public int getDisp8ScalingFactor(AVXSize size) {
+ switch (size) {
+ case XMM:
+ return verifyScalingFactor(scalingFactorVL128);
+ case YMM:
+ return verifyScalingFactor(scalingFactorVL256);
+ case ZMM:
+ return verifyScalingFactor(scalingFactorVL512);
+ default:
+ throw GraalError.shouldNotReachHere("Unsupported vector size.");
+ }
+ }
+ }
+
+ /**
+ * Low-level function to encode and emit the EVEX prefix.
+ * <p>
+ * 62 [0 1 1 0 0 0 1 0]<br>
+ * P1 [R X B R'0 0 m m]<br>
+ * P2 [W v v v v 1 p p]<br>
+ * P3 [z L'L b V'a a a]
+ * <p>
+ * The pp field encodes an extension to the opcode:<br>
+ * 00: no extension<br>
+ * 01: 66<br>
+ * 10: F3<br>
+ * 11: F2
+ * <p>
+ * The mm field encodes the leading bytes of the opcode:<br>
+ * 01: implied 0F leading opcode byte<br>
+ * 10: implied 0F 38 leading opcode bytes<br>
+ * 11: implied 0F 3A leading opcode bytes
+ * <p>
+ * The z field encodes the merging mode (merge or zero).
+ * <p>
+ * The b field encodes the source broadcast or data rounding modes.
+ * <p>
+ * The aaa field encodes the operand mask register.
+ */
+ private void emitEVEX(int l, int pp, int mm, int w, int rxb, int reg, int vvvvv, int z, int b, int aaa) {
+ assert ((AMD64) target.arch).getFeatures().contains(CPUFeature.AVX512F) : "emitting EVEX prefix on a CPU without AVX512 support";
+
+ assert l == L128 || l == L256 || l == L512 || l == LIG : "invalid value for EVEX.L'L";
+ assert pp == P_ || pp == P_66 || pp == P_F3 || pp == P_F2 : "invalid value for EVEX.pp";
+ assert mm == M_0F || mm == M_0F38 || mm == M_0F3A : "invalid value for EVEX.mm";
+ assert w == W0 || w == W1 || w == WIG : "invalid value for EVEX.W";
+
+ assert (rxb & 0x07) == rxb : "invalid value for EVEX.RXB";
+ assert (reg & 0x1F) == reg : "invalid value for EVEX.R'";
+ assert (vvvvv & 0x1F) == vvvvv : "invalid value for EVEX.vvvvv";
+
+ assert z == Z0 || z == Z1 : "invalid value for EVEX.z";
+ assert b == B0 || b == B1 : "invalid value for EVEX.b";
+ assert (aaa & 0x07) == aaa : "invalid value for EVEX.aaa";
+
+ emitByte(0x62);
+ int p1 = 0;
+ p1 |= ((rxb ^ 0x07) & 0x07) << 5;
+ p1 |= reg < 16 ? 0x10 : 0;
+ p1 |= mm;
+ emitByte(p1);
+
+ int p2 = 0;
+ p2 |= w << 7;
+ p2 |= ((vvvvv ^ 0x0F) & 0x0F) << 3;
+ p2 |= 0x4;
+ p2 |= pp;
+ emitByte(p2);
+
+ int p3 = 0;
+ p3 |= z << 7;
+ p3 |= l << 5;
+ p3 |= b << 4;
+ p3 |= vvvvv < 16 ? 0x08 : 0;
+ p3 |= aaa;
+ emitByte(p3);
+ }
+
+ private static int getRXBForEVEX(Register reg, Register rm) {
+ int rxb = (reg == null ? 0 : reg.encoding & 0x08) >> 1;
+ rxb |= (rm == null ? 0 : rm.encoding & 0x018) >> 3;
+ return rxb;
+ }
+
+ /**
+ * Helper method for emitting EVEX prefix in the form of RRRR.
+ */
+ protected final void evexPrefix(Register dst, Register mask, Register nds, Register src, AVXSize size, int pp, int mm, int w, int z, int b) {
+ assert !mask.isValid() || mask.getRegisterCategory().equals(MASK);
+ emitEVEX(getLFlag(size), pp, mm, w, getRXBForEVEX(dst, src), dst.encoding, nds.isValid() ? nds.encoding() : 0, z, b, mask.isValid() ? mask.encoding : 0);
+ }
+
+ /**
+ * Helper method for emitting EVEX prefix in the form of RRRM. Because the memory addressing in
+ * EVEX-encoded instructions employ a compressed displacement scheme when using disp8 form, the
+ * user of this API should make sure to encode the operands using
+ * {@link #emitEVEXOperandHelper(Register, AMD64Address, int, int)}.
+ */
+ protected final void evexPrefix(Register dst, Register mask, Register nds, AMD64Address src, AVXSize size, int pp, int mm, int w, int z, int b) {
+ assert !mask.isValid() || mask.getRegisterCategory().equals(MASK);
+ emitEVEX(getLFlag(size), pp, mm, w, getRXB(dst, src), dst.encoding, nds.isValid() ? nds.encoding() : 0, z, b, mask.isValid() ? mask.encoding : 0);
+ }
+
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64InstructionAttr.java Fri Aug 10 14:56:29 2018 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,187 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package org.graalvm.compiler.asm.amd64;
-
-import jdk.vm.ci.amd64.AMD64;
-import jdk.vm.ci.amd64.AMD64.CPUFeature;
-import jdk.vm.ci.code.TargetDescription;
-
-/**
- * Attributes for instructions for SSE through EVEX, also including address components.
- */
-public class AMD64InstructionAttr {
- AMD64InstructionAttr(
- int inVectorLen,
- boolean inRexVexW,
- boolean inLegacyMode,
- boolean inNoRegMask,
- boolean inUsesVl,
- TargetDescription target) {
- avxVectorLen = inVectorLen;
- rexVexW = inRexVexW;
- this.target = target;
- legacyMode = (!supports(CPUFeature.AVX512F)) ? true : inLegacyMode;
- noRegMask = inNoRegMask;
- usesVl = inUsesVl;
- rexVexWReverted = false;
- tupleType = 0;
- inputSizeInBits = 0;
- isEvexInstruction = false;
- evexEncoding = 0;
- isClearContext = false;
- isExtendedContext = false;
- }
-
- private TargetDescription target;
- private int avxVectorLen;
- private boolean rexVexW;
- private boolean rexVexWReverted;
- private boolean legacyMode;
- private boolean noRegMask;
- private boolean usesVl;
- private int tupleType;
- private int inputSizeInBits;
- private boolean isEvexInstruction;
- private int evexEncoding;
- private boolean isClearContext;
- private boolean isExtendedContext;
-
- public int getVectorLen() {
- return avxVectorLen;
- }
-
- public boolean isRexVexW() {
- return rexVexW;
- }
-
- public boolean isRexVexWReverted() {
- return rexVexWReverted;
- }
-
- public boolean isLegacyMode() {
- return legacyMode;
- }
-
- public boolean isNoRegMask() {
- return noRegMask;
- }
-
- public boolean usesVl() {
- return usesVl;
- }
-
- public int getTupleType() {
- return tupleType;
- }
-
- public int getInputSize() {
- return inputSizeInBits;
- }
-
- public boolean isEvexInstruction() {
- return isEvexInstruction;
- }
-
- public int getEvexEncoding() {
- return evexEncoding;
- }
-
- public boolean isClearContext() {
- return isClearContext;
- }
-
- public boolean isExtendedContext() {
- return isExtendedContext;
- }
-
- /**
- * Set the vector length of a given instruction.
- *
- * @param vectorLen
- */
- public void setVectorLen(int vectorLen) {
- avxVectorLen = vectorLen;
- }
-
- /**
- * In EVEX it is possible in blended code generation to revert the encoding width for AVX.
- */
- public void setRexVexWReverted() {
- rexVexWReverted = true;
- }
-
- /**
- * Alter the current encoding width.
- *
- * @param state
- */
- public void setRexVexW(boolean state) {
- rexVexW = state;
- }
-
- /**
- * Alter the current instructions legacy mode. Blended code generation will use this.
- */
- public void setLegacyMode() {
- legacyMode = true;
- }
-
- /**
- * During emit or during definition of an instruction, mark if it is EVEX.
- */
- public void setIsEvexInstruction() {
- isEvexInstruction = true;
- }
-
- /**
- * Set the current encoding attributes to be used in address calculations for EVEX.
- *
- * @param value
- */
- public void setEvexEncoding(int value) {
- evexEncoding = value;
- }
-
- /**
- * Use clear context for this instruction in EVEX, defaults is merge(false).
- */
- public void setIsClearContext() {
- isClearContext = true;
- }
-
- /**
- * Set the address attributes for configuring displacement calculations in EVEX.
- */
- public void setAddressAttributes(int inTupleType, int inInputSizeInBits) {
- if (supports(CPUFeature.AVX512F)) {
- tupleType = inTupleType;
- inputSizeInBits = inInputSizeInBits;
- }
- }
-
- private boolean supports(CPUFeature feature) {
- return ((AMD64) target.arch).getFeatures().contains(feature);
- }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64MacroAssembler.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64MacroAssembler.java Thu Aug 23 11:09:16 2018 -0400
@@ -24,16 +24,10 @@
package org.graalvm.compiler.asm.amd64;
-import static jdk.vm.ci.amd64.AMD64.rax;
-import static jdk.vm.ci.amd64.AMD64.rcx;
-import static jdk.vm.ci.amd64.AMD64.rdx;
-import static jdk.vm.ci.amd64.AMD64.rsp;
import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseIncDec;
import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseXmmLoadAndClearUpper;
import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseXmmRegToRegMoveAll;
-import org.graalvm.compiler.asm.Label;
-import org.graalvm.compiler.asm.amd64.AMD64Address.Scale;
import org.graalvm.compiler.core.common.NumUtil;
import jdk.vm.ci.amd64.AMD64;
@@ -280,7 +274,6 @@
movl(dst, (int) (src & 0xFFFFFFFF));
movl(high, (int) (src >> 32));
}
-
}
public final void setl(ConditionFlag cc, Register dst) {
@@ -344,433 +337,4 @@
addq(AMD64.rsp, AMD64Kind.DOUBLE.getSizeInBytes());
}
- // IndexOf for constant substrings with size >= 8 chars
- // which don't need to be loaded through stack.
- public void stringIndexofC8(Register str1, Register str2,
- Register cnt1, Register cnt2,
- int intCnt2, Register result,
- Register vec, Register tmp) {
- // assert(UseSSE42Intrinsics, "SSE4.2 is required");
-
- // This method uses pcmpestri inxtruction with bound registers
- // inputs:
- // xmm - substring
- // rax - substring length (elements count)
- // mem - scanned string
- // rdx - string length (elements count)
- // 0xd - mode: 1100 (substring search) + 01 (unsigned shorts)
- // outputs:
- // rcx - matched index in string
- assert cnt1.equals(rdx) && cnt2.equals(rax) && tmp.equals(rcx) : "pcmpestri";
-
- Label reloadSubstr = new Label();
- Label scanToSubstr = new Label();
- Label scanSubstr = new Label();
- Label retFound = new Label();
- Label retNotFound = new Label();
- Label exit = new Label();
- Label foundSubstr = new Label();
- Label matchSubstrHead = new Label();
- Label reloadStr = new Label();
- Label foundCandidate = new Label();
-
- // Note, inline_string_indexOf() generates checks:
- // if (substr.count > string.count) return -1;
- // if (substr.count == 0) return 0;
- assert intCnt2 >= 8 : "this code isused only for cnt2 >= 8 chars";
-
- // Load substring.
- movdqu(vec, new AMD64Address(str2, 0));
- movl(cnt2, intCnt2);
- movq(result, str1); // string addr
-
- if (intCnt2 > 8) {
- jmpb(scanToSubstr);
-
- // Reload substr for rescan, this code
- // is executed only for large substrings (> 8 chars)
- bind(reloadSubstr);
- movdqu(vec, new AMD64Address(str2, 0));
- negq(cnt2); // Jumped here with negative cnt2, convert to positive
-
- bind(reloadStr);
- // We came here after the beginning of the substring was
- // matched but the rest of it was not so we need to search
- // again. Start from the next element after the previous match.
-
- // cnt2 is number of substring reminding elements and
- // cnt1 is number of string reminding elements when cmp failed.
- // Restored cnt1 = cnt1 - cnt2 + int_cnt2
- subl(cnt1, cnt2);
- addl(cnt1, intCnt2);
- movl(cnt2, intCnt2); // Now restore cnt2
-
- decrementl(cnt1, 1); // Shift to next element
- cmpl(cnt1, cnt2);
- jccb(ConditionFlag.Negative, retNotFound); // Left less then substring
-
- addq(result, 2);
-
- } // (int_cnt2 > 8)
-
- // Scan string for start of substr in 16-byte vectors
- bind(scanToSubstr);
- pcmpestri(vec, new AMD64Address(result, 0), 0x0d);
- jccb(ConditionFlag.Below, foundCandidate); // CF == 1
- subl(cnt1, 8);
- jccb(ConditionFlag.LessEqual, retNotFound); // Scanned full string
- cmpl(cnt1, cnt2);
- jccb(ConditionFlag.Negative, retNotFound); // Left less then substring
- addq(result, 16);
- jmpb(scanToSubstr);
-
- // Found a potential substr
- bind(foundCandidate);
- // Matched whole vector if first element matched (tmp(rcx) == 0).
- if (intCnt2 == 8) {
- jccb(ConditionFlag.Overflow, retFound); // OF == 1
- } else { // int_cnt2 > 8
- jccb(ConditionFlag.Overflow, foundSubstr);
- }
- // After pcmpestri tmp(rcx) contains matched element index
- // Compute start addr of substr
- leaq(result, new AMD64Address(result, tmp, Scale.Times2, 0));
-
- // Make sure string is still long enough
- subl(cnt1, tmp);
- cmpl(cnt1, cnt2);
- if (intCnt2 == 8) {
- jccb(ConditionFlag.GreaterEqual, scanToSubstr);
- } else { // int_cnt2 > 8
- jccb(ConditionFlag.GreaterEqual, matchSubstrHead);
- }
- // Left less then substring.
-
- bind(retNotFound);
- movl(result, -1);
- jmpb(exit);
-
- if (intCnt2 > 8) {
- // This code is optimized for the case when whole substring
- // is matched if its head is matched.
- bind(matchSubstrHead);
- pcmpestri(vec, new AMD64Address(result, 0), 0x0d);
- // Reload only string if does not match
- jccb(ConditionFlag.NoOverflow, reloadStr); // OF == 0
-
- Label contScanSubstr = new Label();
- // Compare the rest of substring (> 8 chars).
- bind(foundSubstr);
- // First 8 chars are already matched.
- negq(cnt2);
- addq(cnt2, 8);
-
- bind(scanSubstr);
- subl(cnt1, 8);
- cmpl(cnt2, -8); // Do not read beyond substring
- jccb(ConditionFlag.LessEqual, contScanSubstr);
- // Back-up strings to avoid reading beyond substring:
- // cnt1 = cnt1 - cnt2 + 8
- addl(cnt1, cnt2); // cnt2 is negative
- addl(cnt1, 8);
- movl(cnt2, 8);
- negq(cnt2);
- bind(contScanSubstr);
- if (intCnt2 < 1024 * 1024 * 1024) {
- movdqu(vec, new AMD64Address(str2, cnt2, Scale.Times2, intCnt2 * 2));
- pcmpestri(vec, new AMD64Address(result, cnt2, Scale.Times2, intCnt2 * 2), 0x0d);
- } else {
- // calculate index in register to avoid integer overflow (int_cnt2*2)
- movl(tmp, intCnt2);
- addq(tmp, cnt2);
- movdqu(vec, new AMD64Address(str2, tmp, Scale.Times2, 0));
- pcmpestri(vec, new AMD64Address(result, tmp, Scale.Times2, 0), 0x0d);
- }
- // Need to reload strings pointers if not matched whole vector
- jcc(ConditionFlag.NoOverflow, reloadSubstr); // OF == 0
- addq(cnt2, 8);
- jcc(ConditionFlag.Negative, scanSubstr);
- // Fall through if found full substring
-
- } // (int_cnt2 > 8)
-
- bind(retFound);
- // Found result if we matched full small substring.
- // Compute substr offset
- subq(result, str1);
- shrl(result, 1); // index
- bind(exit);
-
- } // string_indexofC8
-
- // Small strings are loaded through stack if they cross page boundary.
- public void stringIndexOf(Register str1, Register str2,
- Register cnt1, Register cnt2,
- int intCnt2, Register result,
- Register vec, Register tmp, int vmPageSize) {
- //
- // int_cnt2 is length of small (< 8 chars) constant substring
- // or (-1) for non constant substring in which case its length
- // is in cnt2 register.
- //
- // Note, inline_string_indexOf() generates checks:
- // if (substr.count > string.count) return -1;
- // if (substr.count == 0) return 0;
- //
- assert intCnt2 == -1 || (0 < intCnt2 && intCnt2 < 8) : "should be != 0";
-
- // This method uses pcmpestri instruction with bound registers
- // inputs:
- // xmm - substring
- // rax - substring length (elements count)
- // mem - scanned string
- // rdx - string length (elements count)
- // 0xd - mode: 1100 (substring search) + 01 (unsigned shorts)
- // outputs:
- // rcx - matched index in string
- assert cnt1.equals(rdx) && cnt2.equals(rax) && tmp.equals(rcx) : "pcmpestri";
-
- Label reloadSubstr = new Label();
- Label scanToSubstr = new Label();
- Label scanSubstr = new Label();
- Label adjustStr = new Label();
- Label retFound = new Label();
- Label retNotFound = new Label();
- Label cleanup = new Label();
- Label foundSubstr = new Label();
- Label foundCandidate = new Label();
-
- int wordSize = 8;
- // We don't know where these strings are located
- // and we can't read beyond them. Load them through stack.
- Label bigStrings = new Label();
- Label checkStr = new Label();
- Label copySubstr = new Label();
- Label copyStr = new Label();
-
- movq(tmp, rsp); // save old SP
-
- if (intCnt2 > 0) { // small (< 8 chars) constant substring
- if (intCnt2 == 1) { // One char
- movzwl(result, new AMD64Address(str2, 0));
- movdl(vec, result); // move 32 bits
- } else if (intCnt2 == 2) { // Two chars
- movdl(vec, new AMD64Address(str2, 0)); // move 32 bits
- } else if (intCnt2 == 4) { // Four chars
- movq(vec, new AMD64Address(str2, 0)); // move 64 bits
- } else { // cnt2 = { 3, 5, 6, 7 }
- // Array header size is 12 bytes in 32-bit VM
- // + 6 bytes for 3 chars == 18 bytes,
- // enough space to load vec and shift.
- movdqu(vec, new AMD64Address(str2, (intCnt2 * 2) - 16));
- psrldq(vec, 16 - (intCnt2 * 2));
- }
- } else { // not constant substring
- cmpl(cnt2, 8);
- jccb(ConditionFlag.AboveEqual, bigStrings); // Both strings are big enough
-
- // We can read beyond string if str+16 does not cross page boundary
- // since heaps are aligned and mapped by pages.
- assert vmPageSize < 1024 * 1024 * 1024 : "default page should be small";
- movl(result, str2); // We need only low 32 bits
- andl(result, (vmPageSize - 1));
- cmpl(result, (vmPageSize - 16));
- jccb(ConditionFlag.BelowEqual, checkStr);
-
- // Move small strings to stack to allow load 16 bytes into vec.
- subq(rsp, 16);
- int stackOffset = wordSize - 2;
- push(cnt2);
-
- bind(copySubstr);
- movzwl(result, new AMD64Address(str2, cnt2, Scale.Times2, -2));
- movw(new AMD64Address(rsp, cnt2, Scale.Times2, stackOffset), result);
- decrementl(cnt2, 1);
- jccb(ConditionFlag.NotZero, copySubstr);
-
- pop(cnt2);
- movq(str2, rsp); // New substring address
- } // non constant
-
- bind(checkStr);
- cmpl(cnt1, 8);
- jccb(ConditionFlag.AboveEqual, bigStrings);
-
- // Check cross page boundary.
- movl(result, str1); // We need only low 32 bits
- andl(result, (vmPageSize - 1));
- cmpl(result, (vmPageSize - 16));
- jccb(ConditionFlag.BelowEqual, bigStrings);
-
- subq(rsp, 16);
- int stackOffset = -2;
- if (intCnt2 < 0) { // not constant
- push(cnt2);
- stackOffset += wordSize;
- }
- movl(cnt2, cnt1);
-
- bind(copyStr);
- movzwl(result, new AMD64Address(str1, cnt2, Scale.Times2, -2));
- movw(new AMD64Address(rsp, cnt2, Scale.Times2, stackOffset), result);
- decrementl(cnt2, 1);
- jccb(ConditionFlag.NotZero, copyStr);
-
- if (intCnt2 < 0) { // not constant
- pop(cnt2);
- }
- movq(str1, rsp); // New string address
-
- bind(bigStrings);
- // Load substring.
- if (intCnt2 < 0) { // -1
- movdqu(vec, new AMD64Address(str2, 0));
- push(cnt2); // substr count
- push(str2); // substr addr
- push(str1); // string addr
- } else {
- // Small (< 8 chars) constant substrings are loaded already.
- movl(cnt2, intCnt2);
- }
- push(tmp); // original SP
- // Finished loading
-
- // ========================================================
- // Start search
- //
-
- movq(result, str1); // string addr
-
- if (intCnt2 < 0) { // Only for non constant substring
- jmpb(scanToSubstr);
-
- // SP saved at sp+0
- // String saved at sp+1*wordSize
- // Substr saved at sp+2*wordSize
- // Substr count saved at sp+3*wordSize
-
- // Reload substr for rescan, this code
- // is executed only for large substrings (> 8 chars)
- bind(reloadSubstr);
- movq(str2, new AMD64Address(rsp, 2 * wordSize));
- movl(cnt2, new AMD64Address(rsp, 3 * wordSize));
- movdqu(vec, new AMD64Address(str2, 0));
- // We came here after the beginning of the substring was
- // matched but the rest of it was not so we need to search
- // again. Start from the next element after the previous match.
- subq(str1, result); // Restore counter
- shrl(str1, 1);
- addl(cnt1, str1);
- decrementl(cnt1); // Shift to next element
- cmpl(cnt1, cnt2);
- jccb(ConditionFlag.Negative, retNotFound); // Left less then substring
-
- addq(result, 2);
- } // non constant
-
- // Scan string for start of substr in 16-byte vectors
- bind(scanToSubstr);
- assert cnt1.equals(rdx) && cnt2.equals(rax) && tmp.equals(rcx) : "pcmpestri";
- pcmpestri(vec, new AMD64Address(result, 0), 0x0d);
- jccb(ConditionFlag.Below, foundCandidate); // CF == 1
- subl(cnt1, 8);
- jccb(ConditionFlag.LessEqual, retNotFound); // Scanned full string
- cmpl(cnt1, cnt2);
- jccb(ConditionFlag.Negative, retNotFound); // Left less then substring
- addq(result, 16);
-
- bind(adjustStr);
- cmpl(cnt1, 8); // Do not read beyond string
- jccb(ConditionFlag.GreaterEqual, scanToSubstr);
- // Back-up string to avoid reading beyond string.
- leaq(result, new AMD64Address(result, cnt1, Scale.Times2, -16));
- movl(cnt1, 8);
- jmpb(scanToSubstr);
-
- // Found a potential substr
- bind(foundCandidate);
- // After pcmpestri tmp(rcx) contains matched element index
-
- // Make sure string is still long enough
- subl(cnt1, tmp);
- cmpl(cnt1, cnt2);
- jccb(ConditionFlag.GreaterEqual, foundSubstr);
- // Left less then substring.
-
- bind(retNotFound);
- movl(result, -1);
- jmpb(cleanup);
-
- bind(foundSubstr);
- // Compute start addr of substr
- leaq(result, new AMD64Address(result, tmp, Scale.Times2));
-
- if (intCnt2 > 0) { // Constant substring
- // Repeat search for small substring (< 8 chars)
- // from new point without reloading substring.
- // Have to check that we don't read beyond string.
- cmpl(tmp, 8 - intCnt2);
- jccb(ConditionFlag.Greater, adjustStr);
- // Fall through if matched whole substring.
- } else { // non constant
- assert intCnt2 == -1 : "should be != 0";
-
- addl(tmp, cnt2);
- // Found result if we matched whole substring.
- cmpl(tmp, 8);
- jccb(ConditionFlag.LessEqual, retFound);
-
- // Repeat search for small substring (<= 8 chars)
- // from new point 'str1' without reloading substring.
- cmpl(cnt2, 8);
- // Have to check that we don't read beyond string.
- jccb(ConditionFlag.LessEqual, adjustStr);
-
- Label checkNext = new Label();
- Label contScanSubstr = new Label();
- Label retFoundLong = new Label();
- // Compare the rest of substring (> 8 chars).
- movq(str1, result);
-
- cmpl(tmp, cnt2);
- // First 8 chars are already matched.
- jccb(ConditionFlag.Equal, checkNext);
-
- bind(scanSubstr);
- pcmpestri(vec, new AMD64Address(str1, 0), 0x0d);
- // Need to reload strings pointers if not matched whole vector
- jcc(ConditionFlag.NoOverflow, reloadSubstr); // OF == 0
-
- bind(checkNext);
- subl(cnt2, 8);
- jccb(ConditionFlag.LessEqual, retFoundLong); // Found full substring
- addq(str1, 16);
- addq(str2, 16);
- subl(cnt1, 8);
- cmpl(cnt2, 8); // Do not read beyond substring
- jccb(ConditionFlag.GreaterEqual, contScanSubstr);
- // Back-up strings to avoid reading beyond substring.
- leaq(str2, new AMD64Address(str2, cnt2, Scale.Times2, -16));
- leaq(str1, new AMD64Address(str1, cnt2, Scale.Times2, -16));
- subl(cnt1, cnt2);
- movl(cnt2, 8);
- addl(cnt1, 8);
- bind(contScanSubstr);
- movdqu(vec, new AMD64Address(str2, 0));
- jmpb(scanSubstr);
-
- bind(retFoundLong);
- movq(str1, new AMD64Address(rsp, wordSize));
- } // non constant
-
- bind(retFound);
- // Compute substr offset
- subq(result, str1);
- shrl(result, 1); // index
-
- bind(cleanup);
- pop(rsp); // restore SP
-
- }
-
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64VectorAssembler.java Fri Aug 10 14:56:29 2018 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,853 +0,0 @@
-/*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package org.graalvm.compiler.asm.amd64;
-
-import java.util.EnumSet;
-
-import org.graalvm.compiler.core.common.calc.Condition;
-import org.graalvm.compiler.debug.GraalError;
-
-import org.graalvm.compiler.asm.amd64.AVXKind.AVXSize;
-
-import jdk.vm.ci.amd64.AMD64;
-import jdk.vm.ci.amd64.AMD64.CPUFeature;
-import jdk.vm.ci.amd64.AMD64Kind;
-import jdk.vm.ci.code.Register;
-import jdk.vm.ci.code.Register.RegisterCategory;
-import jdk.vm.ci.code.TargetDescription;
-
-/**
- * This class extends the AMD64 assembler with functions that emit instructions from the AVX
- * extension.
- */
-public class AMD64VectorAssembler extends AMD64MacroAssembler {
-
- public AMD64VectorAssembler(TargetDescription target) {
- super(target);
- assert ((AMD64) target.arch).getFeatures().contains(CPUFeature.AVX);
- }
-
- private static final int L128 = 0;
- private static final int L256 = 1;
- private static final int LIG = 0;
-
- private static final int W0 = 0;
- private static final int W1 = 1;
- private static final int WIG = 0;
-
- private static final int P_ = 0x0;
- private static final int P_66 = 0x1;
- private static final int P_F3 = 0x2;
- private static final int P_F2 = 0x3;
-
- private static final int M_0F = 0x1;
- private static final int M_0F38 = 0x2;
- private static final int M_0F3A = 0x3;
-
- /**
- * Low-level function to encode and emit the VEX prefix.
- * <p>
- * 2 byte form: [1100 0101] [R vvvv L pp]<br>
- * 3 byte form: [1100 0100] [RXB m-mmmm] [W vvvv L pp]
- * <p>
- * The RXB and vvvv fields are stored in 1's complement in the prefix encoding. This function
- * performs the 1s complement conversion, the caller is expected to pass plain unencoded
- * arguments.
- * <p>
- * The pp field encodes an extension to the opcode:<br>
- * 00: no extension<br>
- * 01: 66<br>
- * 10: F3<br>
- * 11: F2
- * <p>
- * The m-mmmm field encodes the leading bytes of the opcode:<br>
- * 00001: implied 0F leading opcode byte (default in 2-byte encoding)<br>
- * 00010: implied 0F 38 leading opcode bytes<br>
- * 00011: implied 0F 3A leading opcode bytes
- * <p>
- * This function automatically chooses the 2 or 3 byte encoding, based on the XBW flags and the
- * m-mmmm field.
- */
- private void emitVEX(int l, int pp, int mmmmm, int w, int rxb, int vvvv) {
- assert ((AMD64) target.arch).getFeatures().contains(CPUFeature.AVX) : "emitting VEX prefix on a CPU without AVX support";
-
- assert l == L128 || l == L256 || l == LIG : "invalid value for VEX.L";
- assert pp == P_ || pp == P_66 || pp == P_F3 || pp == P_F2 : "invalid value for VEX.pp";
- assert mmmmm == M_0F || mmmmm == M_0F38 || mmmmm == M_0F3A : "invalid value for VEX.m-mmmm";
- assert w == W0 || w == W1 || w == WIG : "invalid value for VEX.W";
-
- assert (rxb & 0x07) == rxb : "invalid value for VEX.RXB";
- assert (vvvv & 0x0F) == vvvv : "invalid value for VEX.vvvv";
-
- int rxb1s = rxb ^ 0x07;
- int vvvv1s = vvvv ^ 0x0F;
- if ((rxb & 0x03) == 0 && w == WIG && mmmmm == M_0F) {
- // 2 byte encoding
- int byte2 = 0;
- byte2 |= (rxb1s & 0x04) << 5;
- byte2 |= vvvv1s << 3;
- byte2 |= l << 2;
- byte2 |= pp;
-
- emitByte(0xC5);
- emitByte(byte2);
- } else {
- // 3 byte encoding
- int byte2 = 0;
- byte2 = (rxb1s & 0x07) << 5;
- byte2 |= mmmmm;
-
- int byte3 = 0;
- byte3 |= w << 7;
- byte3 |= vvvv1s << 3;
- byte3 |= l << 2;
- byte3 |= pp;
-
- emitByte(0xC4);
- emitByte(byte2);
- emitByte(byte3);
- }
- }
-
- private static int getLFlag(AVXSize size) {
- switch (size) {
- case XMM:
- return L128;
- case YMM:
- return L256;
- default:
- return LIG;
- }
- }
-
- /**
- * Emit instruction with VEX prefix and two register operands.
- * <p>
- * Format: [VEX] [Opcode] [ModR/M]
- */
- private void emitVexOp(int l, int pp, int mmmmm, int w, int op, Register reg, Register rm) {
- emitVEX(l, pp, mmmmm, w, getRXB(reg, rm), 0);
- emitByte(op);
- emitModRM(reg, rm);
- }
-
- /**
- * Emit instruction with VEX prefix and three register operands.
- * <p>
- * Format: [VEX] [Opcode] [ModR/M]
- */
- private void emitVexOp(int l, int pp, int mmmmm, int w, int op, Register reg, Register vvvv, Register rm) {
- emitVEX(l, pp, mmmmm, w, getRXB(reg, rm), vvvv.encoding());
- emitByte(op);
- emitModRM(reg, rm);
- }
-
- /**
- * Emit instruction with VEX prefix and four register operands.
- * <p>
- * Format: [VEX] [Opcode] [ModR/M] [Imm8[7:4]]
- */
- private void emitVexOp(int l, int pp, int mmmmm, int w, int op, Register reg, Register vvvv, Register rm, Register imm8) {
- emitVEX(l, pp, mmmmm, w, getRXB(reg, rm), vvvv.encoding());
- emitByte(op);
- emitModRM(reg, rm);
- emitByte(imm8.encoding() << 4);
- }
-
- /**
- * Emit instruction with VEX prefix and three register operands and one memory operand.
- * <p>
- * Format: [VEX] [Opcode] [ModR/M] [Imm8[7:4]]
- */
- private void emitVexOp(int l, int pp, int mmmmm, int w, int op, Register reg, Register vvvv, AMD64Address rm, Register imm8, int additionalInstructionSize) {
- emitVEX(l, pp, mmmmm, w, getRXB(reg, rm), vvvv.encoding());
- emitByte(op);
- emitOperandHelper(reg, rm, additionalInstructionSize);
- emitByte(imm8.encoding() << 4);
- }
-
- /**
- * Emit instruction with VEX prefix and two register operands and an opcode extension in the r
- * field.
- * <p>
- * Format: [VEX] [Opcode] [ModR/M]
- */
- private void emitVexOp(int l, int pp, int mmmmm, int w, int op, int r, Register vvvv, Register rm) {
- emitVEX(l, pp, mmmmm, w, getRXB(null, rm), vvvv.encoding());
- emitByte(op);
- emitModRM(r, rm);
- }
-
- /**
- * Emit instruction with VEX prefix, one register operand and one memory operand.
- * <p>
- * Format: [VEX] [Opcode] [ModR/M] [SIB] [Disp]
- */
- private void emitVexOp(int l, int pp, int mmmmm, int w, int op, Register reg, AMD64Address rm, int additionalInstructionSize) {
- emitVEX(l, pp, mmmmm, w, getRXB(reg, rm), 0);
- emitByte(op);
- emitOperandHelper(reg, rm, additionalInstructionSize);
- }
-
- /**
- * Emit instruction with VEX prefix, two register operands and one memory operand.
- * <p>
- * Format: [VEX] [Opcode] [ModR/M] [SIB] [Disp]
- */
- private void emitVexOp(int l, int pp, int mmmmm, int w, int op, Register reg, Register vvvv, AMD64Address rm, int additionalInstructionSize) {
- emitVEX(l, pp, mmmmm, w, getRXB(reg, rm), vvvv.encoding());
- emitByte(op);
- emitOperandHelper(reg, rm, additionalInstructionSize);
- }
-
- private static final OpAssertion AVX1 = new OpAssertion(CPUFeature.AVX, CPUFeature.AVX);
- private static final OpAssertion AVX1_2 = new OpAssertion(CPUFeature.AVX, CPUFeature.AVX2);
- private static final OpAssertion AVX2 = new OpAssertion(CPUFeature.AVX2, CPUFeature.AVX2);
-
- private static final OpAssertion AVX1_128ONLY = new OpAssertion(CPUFeature.AVX, null);
- private static final OpAssertion AVX1_256ONLY = new OpAssertion(null, CPUFeature.AVX);
- private static final OpAssertion AVX2_256ONLY = new OpAssertion(null, CPUFeature.AVX2);
-
- private static final OpAssertion XMM_CPU = new OpAssertion(CPUFeature.AVX, null, AMD64.XMM, null, AMD64.CPU, null);
- private static final OpAssertion XMM_XMM_CPU = new OpAssertion(CPUFeature.AVX, null, AMD64.XMM, AMD64.XMM, AMD64.CPU, null);
- private static final OpAssertion CPU_XMM = new OpAssertion(CPUFeature.AVX, null, AMD64.CPU, null, AMD64.XMM, null);
-
- private static final class OpAssertion {
- private final CPUFeature avx128feature;
- private final CPUFeature avx256feature;
-
- private final RegisterCategory rCategory;
- private final RegisterCategory vCategory;
- private final RegisterCategory mCategory;
- private final RegisterCategory imm8Category;
-
- private OpAssertion(CPUFeature avx128feature, CPUFeature avx256feature) {
- this(avx128feature, avx256feature, AMD64.XMM, AMD64.XMM, AMD64.XMM, AMD64.XMM);
- }
-
- private OpAssertion(CPUFeature avx128feature, CPUFeature avx256feature, RegisterCategory rCategory, RegisterCategory vCategory, RegisterCategory mCategory, RegisterCategory imm8Category) {
- this.avx128feature = avx128feature;
- this.avx256feature = avx256feature;
- this.rCategory = rCategory;
- this.vCategory = vCategory;
- this.mCategory = mCategory;
- this.imm8Category = imm8Category;
- }
-
- public boolean check(AMD64 arch, AVXSize size, Register r, Register v, Register m) {
- return check(arch, size, r, v, m, null);
- }
-
- public boolean check(AMD64 arch, AVXSize size, Register r, Register v, Register m, Register imm8) {
- switch (size) {
- case XMM:
- assert avx128feature != null && arch.getFeatures().contains(avx128feature) : "emitting illegal 128 bit instruction";
- break;
- case YMM:
- assert avx256feature != null && arch.getFeatures().contains(avx256feature) : "emitting illegal 256 bit instruction";
- break;
- }
- if (r != null) {
- assert r.getRegisterCategory().equals(rCategory);
- }
- if (v != null) {
- assert v.getRegisterCategory().equals(vCategory);
- }
- if (m != null) {
- assert m.getRegisterCategory().equals(mCategory);
- }
- if (imm8 != null) {
- assert imm8.getRegisterCategory().equals(imm8Category);
- }
- return true;
- }
-
- public boolean supports(EnumSet<CPUFeature> features, AVXSize avxSize) {
- switch (avxSize) {
- case XMM:
- return features.contains(avx128feature);
- case YMM:
- return features.contains(avx256feature);
- default:
- throw GraalError.shouldNotReachHere();
- }
- }
- }
-
- /**
- * Base class for VEX-encoded instructions.
- */
- private static class VexOp {
- protected final int pp;
- protected final int mmmmm;
- protected final int w;
- protected final int op;
-
- private final String opcode;
- protected final OpAssertion assertion;
-
- protected VexOp(String opcode, int pp, int mmmmm, int w, int op, OpAssertion assertion) {
- this.pp = pp;
- this.mmmmm = mmmmm;
- this.w = w;
- this.op = op;
- this.opcode = opcode;
- this.assertion = assertion;
- }
-
- public boolean isSupported(AMD64VectorAssembler vasm, AMD64Kind kind) {
- return assertion.supports(((AMD64) vasm.target.arch).getFeatures(), AVXKind.getRegisterSize(kind));
- }
-
- @Override
- public String toString() {
- return opcode;
- }
- }
-
- /**
- * VEX-encoded instructions with an operand order of RM, but the M operand must be a register.
- */
- public static class VexRROp extends VexOp {
- // @formatter:off
- public static final VexRROp VMASKMOVDQU = new VexRROp("VMASKMOVDQU", P_66, M_0F, WIG, 0xF7, AVX1_128ONLY);
- // @formatter:on
-
- protected VexRROp(String opcode, int pp, int mmmmm, int w, int op) {
- this(opcode, pp, mmmmm, w, op, AVX1);
- }
-
- protected VexRROp(String opcode, int pp, int mmmmm, int w, int op, OpAssertion assertion) {
- super(opcode, pp, mmmmm, w, op, assertion);
- }
-
- public void emit(AMD64VectorAssembler asm, AVXSize size, Register dst, Register src) {
- assert assertion.check((AMD64) asm.target.arch, size, dst, null, src);
- asm.emitVexOp(getLFlag(size), pp, mmmmm, w, op, dst, src);
- }
- }
-
- /**
- * VEX-encoded instructions with an operand order of RM.
- */
- public static class VexRMOp extends VexRROp {
- // @formatter:off
- public static final VexRMOp VCVTTSS2SI = new VexRMOp("VCVTTSS2SI", P_F3, M_0F, W0, 0x2C, CPU_XMM);
- public static final VexRMOp VCVTTSS2SQ = new VexRMOp("VCVTTSS2SQ", P_F3, M_0F, W1, 0x2C, CPU_XMM);
- public static final VexRMOp VCVTTSD2SI = new VexRMOp("VCVTTSD2SI", P_F2, M_0F, W0, 0x2C, CPU_XMM);
- public static final VexRMOp VCVTTSD2SQ = new VexRMOp("VCVTTSD2SQ", P_F2, M_0F, W1, 0x2C, CPU_XMM);
- public static final VexRMOp VCVTPS2PD = new VexRMOp("VCVTPS2PD", P_, M_0F, WIG, 0x5A);
- public static final VexRMOp VCVTPD2PS = new VexRMOp("VCVTPD2PS", P_66, M_0F, WIG, 0x5A);
- public static final VexRMOp VCVTDQ2PS = new VexRMOp("VCVTDQ2PS", P_, M_0F, WIG, 0x5B);
- public static final VexRMOp VCVTTPS2DQ = new VexRMOp("VCVTTPS2DQ", P_F3, M_0F, WIG, 0x5B);
- public static final VexRMOp VCVTTPD2DQ = new VexRMOp("VCVTTPD2DQ", P_66, M_0F, WIG, 0xE6);
- public static final VexRMOp VCVTDQ2PD = new VexRMOp("VCVTDQ2PD", P_F3, M_0F, WIG, 0xE6);
- public static final VexRMOp VBROADCASTSS = new VexRMOp("VBROADCASTSS", P_66, M_0F38, W0, 0x18);
- public static final VexRMOp VBROADCASTSD = new VexRMOp("VBROADCASTSD", P_66, M_0F38, W0, 0x19, AVX1_256ONLY);
- public static final VexRMOp VBROADCASTF128 = new VexRMOp("VBROADCASTF128", P_66, M_0F38, W0, 0x1A, AVX1_256ONLY);
- public static final VexRMOp VBROADCASTI128 = new VexRMOp("VBROADCASTI128", P_66, M_0F38, W0, 0x5A, AVX2_256ONLY);
- public static final VexRMOp VPBROADCASTB = new VexRMOp("VPBROADCASTB", P_66, M_0F38, W0, 0x78, AVX2);
- public static final VexRMOp VPBROADCASTW = new VexRMOp("VPBROADCASTW", P_66, M_0F38, W0, 0x79, AVX2);
- public static final VexRMOp VPBROADCASTD = new VexRMOp("VPBROADCASTD", P_66, M_0F38, W0, 0x58, AVX2);
- public static final VexRMOp VPBROADCASTQ = new VexRMOp("VPBROADCASTQ", P_66, M_0F38, W0, 0x59, AVX2);
- public static final VexRMOp VPMOVSXBW = new VexRMOp("VPMOVSXBW", P_66, M_0F38, WIG, 0x20);
- public static final VexRMOp VPMOVSXBD = new VexRMOp("VPMOVSXBD", P_66, M_0F38, WIG, 0x21);
- public static final VexRMOp VPMOVSXBQ = new VexRMOp("VPMOVSXBQ", P_66, M_0F38, WIG, 0x22);
- public static final VexRMOp VPMOVSXWD = new VexRMOp("VPMOVSXWD", P_66, M_0F38, WIG, 0x23);
- public static final VexRMOp VPMOVSXWQ = new VexRMOp("VPMOVSXWQ", P_66, M_0F38, WIG, 0x24);
- public static final VexRMOp VPMOVSXDQ = new VexRMOp("VPMOVSXDQ", P_66, M_0F38, WIG, 0x25);
- public static final VexRMOp VPMOVZXBW = new VexRMOp("VPMOVZXBW", P_66, M_0F38, WIG, 0x30);
- public static final VexRMOp VPMOVZXBD = new VexRMOp("VPMOVZXBD", P_66, M_0F38, WIG, 0x31);
- public static final VexRMOp VPMOVZXBQ = new VexRMOp("VPMOVZXBQ", P_66, M_0F38, WIG, 0x32);
- public static final VexRMOp VPMOVZXWD = new VexRMOp("VPMOVZXWD", P_66, M_0F38, WIG, 0x33);
- public static final VexRMOp VPMOVZXWQ = new VexRMOp("VPMOVZXWQ", P_66, M_0F38, WIG, 0x34);
- public static final VexRMOp VPMOVZXDQ = new VexRMOp("VPMOVZXDQ", P_66, M_0F38, WIG, 0x35);
- public static final VexRMOp VSQRTPD = new VexRMOp("VSQRTPD", P_66, M_0F, WIG, 0x51);
- public static final VexRMOp VSQRTPS = new VexRMOp("VSQRTPS", P_, M_0F, WIG, 0x51);
- public static final VexRMOp VSQRTSD = new VexRMOp("VSQRTSD", P_F2, M_0F, WIG, 0x51);
- public static final VexRMOp VSQRTSS = new VexRMOp("VSQRTSS", P_F3, M_0F, WIG, 0x51);
- public static final VexRMOp VUCOMISS = new VexRMOp("VUCOMISS", P_, M_0F, WIG, 0x2E);
- public static final VexRMOp VUCOMISD = new VexRMOp("VUCOMISD", P_66, M_0F, WIG, 0x2E);
- // @formatter:on
-
- protected VexRMOp(String opcode, int pp, int mmmmm, int w, int op) {
- this(opcode, pp, mmmmm, w, op, AVX1);
- }
-
- protected VexRMOp(String opcode, int pp, int mmmmm, int w, int op, OpAssertion assertion) {
- super(opcode, pp, mmmmm, w, op, assertion);
- }
-
- public void emit(AMD64VectorAssembler asm, AVXSize size, Register dst, AMD64Address src) {
- assert assertion.check((AMD64) asm.target.arch, size, dst, null, null);
- asm.emitVexOp(getLFlag(size), pp, mmmmm, w, op, dst, src, 0);
- }
- }
-
- /**
- * VEX-encoded move instructions.
- * <p>
- * These instructions have two opcodes: op is the forward move instruction with an operand order
- * of RM, and opReverse is the reverse move instruction with an operand order of MR.
- */
- public static final class VexMoveOp extends VexRMOp {
- // @formatter:off
- public static final VexMoveOp VMOVDQA = new VexMoveOp("VMOVDQA", P_66, M_0F, WIG, 0x6F, 0x7F);
- public static final VexMoveOp VMOVDQU = new VexMoveOp("VMOVDQU", P_F3, M_0F, WIG, 0x6F, 0x7F);
- public static final VexMoveOp VMOVAPS = new VexMoveOp("VMOVAPS", P_, M_0F, WIG, 0x28, 0x29);
- public static final VexMoveOp VMOVAPD = new VexMoveOp("VMOVAPD", P_66, M_0F, WIG, 0x28, 0x29);
- public static final VexMoveOp VMOVUPS = new VexMoveOp("VMOVUPS", P_, M_0F, WIG, 0x10, 0x11);
- public static final VexMoveOp VMOVUPD = new VexMoveOp("VMOVUPD", P_66, M_0F, WIG, 0x10, 0x11);
- public static final VexMoveOp VMOVSS = new VexMoveOp("VMOVSS", P_F3, M_0F, WIG, 0x10, 0x11);
- public static final VexMoveOp VMOVSD = new VexMoveOp("VMOVSD", P_F2, M_0F, WIG, 0x10, 0x11);
- public static final VexMoveOp VMOVD = new VexMoveOp("VMOVD", P_66, M_0F, W0, 0x6E, 0x7E, XMM_CPU);
- public static final VexMoveOp VMOVQ = new VexMoveOp("VMOVQ", P_66, M_0F, W1, 0x6E, 0x7E, XMM_CPU);
- // @formatter:on
-
- private final int opReverse;
-
- private VexMoveOp(String opcode, int pp, int mmmmm, int w, int op, int opReverse) {
- this(opcode, pp, mmmmm, w, op, opReverse, AVX1);
- }
-
- private VexMoveOp(String opcode, int pp, int mmmmm, int w, int op, int opReverse, OpAssertion assertion) {
- super(opcode, pp, mmmmm, w, op, assertion);
- this.opReverse = opReverse;
- }
-
- public void emit(AMD64VectorAssembler asm, AVXSize size, AMD64Address dst, Register src) {
- assert assertion.check((AMD64) asm.target.arch, size, src, null, null);
- asm.emitVexOp(getLFlag(size), pp, mmmmm, w, opReverse, src, dst, 0);
- }
-
- public void emitReverse(AMD64VectorAssembler asm, AVXSize size, Register dst, Register src) {
- assert assertion.check((AMD64) asm.target.arch, size, src, null, dst);
- asm.emitVexOp(getLFlag(size), pp, mmmmm, w, opReverse, src, dst);
- }
- }
-
- public interface VexRRIOp {
- void emit(AMD64VectorAssembler asm, AVXSize size, Register dst, Register src, int imm8);
- }
-
- /**
- * VEX-encoded instructions with an operand order of RMI.
- */
- public static final class VexRMIOp extends VexOp implements VexRRIOp {
- // @formatter:off
- public static final VexRMIOp VPERMQ = new VexRMIOp("VPERMQ", P_66, M_0F3A, W1, 0x00, AVX2_256ONLY);
- public static final VexRMIOp VPSHUFLW = new VexRMIOp("VPSHUFLW", P_F2, M_0F, WIG, 0x70, AVX1_2);
- public static final VexRMIOp VPSHUFHW = new VexRMIOp("VPSHUFHW", P_F3, M_0F, WIG, 0x70, AVX1_2);
- public static final VexRMIOp VPSHUFD = new VexRMIOp("VPSHUFD", P_66, M_0F, WIG, 0x70, AVX1_2);
- // @formatter:on
-
- private VexRMIOp(String opcode, int pp, int mmmmm, int w, int op, OpAssertion assertion) {
- super(opcode, pp, mmmmm, w, op, assertion);
- }
-
- @Override
- public void emit(AMD64VectorAssembler asm, AVXSize size, Register dst, Register src, int imm8) {
- assert assertion.check((AMD64) asm.target.arch, size, dst, null, src);
- asm.emitVexOp(getLFlag(size), pp, mmmmm, w, op, dst, src);
- asm.emitByte(imm8);
- }
-
- public void emit(AMD64VectorAssembler asm, AVXSize size, Register dst, AMD64Address src, int imm8) {
- assert assertion.check((AMD64) asm.target.arch, size, dst, null, null);
- asm.emitVexOp(getLFlag(size), pp, mmmmm, w, op, dst, src, 1);
- asm.emitByte(imm8);
- }
- }
-
- /**
- * VEX-encoded instructions with an operand order of MRI.
- */
- public static final class VexMRIOp extends VexOp implements VexRRIOp {
- // @formatter:off
- public static final VexMRIOp VEXTRACTF128 = new VexMRIOp("VEXTRACTF128", P_66, M_0F3A, W0, 0x19, AVX1_256ONLY);
- public static final VexMRIOp VEXTRACTI128 = new VexMRIOp("VEXTRACTI128", P_66, M_0F3A, W0, 0x39, AVX2_256ONLY);
- public static final VexMRIOp VPEXTRB = new VexMRIOp("VPEXTRB", P_66, M_0F3A, W0, 0x14, XMM_CPU);
- public static final VexMRIOp VPEXTRW = new VexMRIOp("VPEXTRW", P_66, M_0F3A, W0, 0x15, XMM_CPU);
- public static final VexMRIOp VPEXTRD = new VexMRIOp("VPEXTRD", P_66, M_0F3A, W0, 0x16, XMM_CPU);
- public static final VexMRIOp VPEXTRQ = new VexMRIOp("VPEXTRQ", P_66, M_0F3A, W1, 0x16, XMM_CPU);
- // @formatter:on
-
- private VexMRIOp(String opcode, int pp, int mmmmm, int w, int op, OpAssertion assertion) {
- super(opcode, pp, mmmmm, w, op, assertion);
- }
-
- @Override
- public void emit(AMD64VectorAssembler asm, AVXSize size, Register dst, Register src, int imm8) {
- assert assertion.check((AMD64) asm.target.arch, size, src, null, dst);
- asm.emitVexOp(getLFlag(size), pp, mmmmm, w, op, src, dst);
- asm.emitByte(imm8);
- }
-
- public void emit(AMD64VectorAssembler asm, AVXSize size, AMD64Address dst, Register src, int imm8) {
- assert assertion.check((AMD64) asm.target.arch, size, src, null, null);
- asm.emitVexOp(getLFlag(size), pp, mmmmm, w, op, src, dst, 1);
- asm.emitByte(imm8);
- }
- }
-
- /**
- * VEX-encoded instructions with an operand order of RVMR.
- */
- public static class VexRVMROp extends VexOp {
- // @formatter:off
- public static final VexRVMROp VPBLENDVB = new VexRVMROp("VPBLENDVB", P_66, M_0F3A, W0, 0x4C, AVX1_2);
- public static final VexRVMROp VPBLENDVPS = new VexRVMROp("VPBLENDVPS", P_66, M_0F3A, W0, 0x4A, AVX1);
- public static final VexRVMROp VPBLENDVPD = new VexRVMROp("VPBLENDVPD", P_66, M_0F3A, W0, 0x4B, AVX1);
- // @formatter:on
-
- protected VexRVMROp(String opcode, int pp, int mmmmm, int w, int op, OpAssertion assertion) {
- super(opcode, pp, mmmmm, w, op, assertion);
- }
-
- public void emit(AMD64VectorAssembler asm, AVXSize size, Register dst, Register mask, Register src1, Register src2) {
- assert assertion.check((AMD64) asm.target.arch, size, dst, mask, src1, src2);
- asm.emitVexOp(getLFlag(size), pp, mmmmm, w, op, dst, src1, src2, mask);
- }
-
- public void emit(AMD64VectorAssembler asm, AVXSize size, Register dst, Register mask, Register src1, AMD64Address src2) {
- assert assertion.check((AMD64) asm.target.arch, size, dst, mask, src1, null);
- asm.emitVexOp(getLFlag(size), pp, mmmmm, w, op, dst, src1, src2, mask, 0);
- }
- }
-
- /**
- * VEX-encoded instructions with an operand order of RVM.
- */
- public static class VexRVMOp extends VexOp {
- // @formatter:off
- public static final VexRVMOp VANDPS = new VexRVMOp("VANDPS", P_, M_0F, WIG, 0x54);
- public static final VexRVMOp VANDPD = new VexRVMOp("VANDPD", P_66, M_0F, WIG, 0x54);
- public static final VexRVMOp VORPS = new VexRVMOp("VORPS", P_, M_0F, WIG, 0x56);
- public static final VexRVMOp VORPD = new VexRVMOp("VORPD", P_66, M_0F, WIG, 0x56);
- public static final VexRVMOp VADDPS = new VexRVMOp("VADDPS", P_, M_0F, WIG, 0x58);
- public static final VexRVMOp VADDPD = new VexRVMOp("VADDPD", P_66, M_0F, WIG, 0x58);
- public static final VexRVMOp VADDSS = new VexRVMOp("VADDSS", P_F3, M_0F, WIG, 0x58);
- public static final VexRVMOp VADDSD = new VexRVMOp("VADDSD", P_F2, M_0F, WIG, 0x58);
- public static final VexRVMOp VXORPS = new VexRVMOp("VXORPS", P_, M_0F, WIG, 0x57);
- public static final VexRVMOp VXORPD = new VexRVMOp("VXORPD", P_66, M_0F, WIG, 0x57);
- public static final VexRVMOp VMULPS = new VexRVMOp("VMULPS", P_, M_0F, WIG, 0x59);
- public static final VexRVMOp VMULPD = new VexRVMOp("VMULPD", P_66, M_0F, WIG, 0x59);
- public static final VexRVMOp VMULSS = new VexRVMOp("VMULSS", P_F3, M_0F, WIG, 0x59);
- public static final VexRVMOp VMULSD = new VexRVMOp("VMULSD", P_F2, M_0F, WIG, 0x59);
- public static final VexRVMOp VSUBPS = new VexRVMOp("VSUBPS", P_, M_0F, WIG, 0x5C);
- public static final VexRVMOp VSUBPD = new VexRVMOp("VSUBPD", P_66, M_0F, WIG, 0x5C);
- public static final VexRVMOp VSUBSS = new VexRVMOp("VSUBSS", P_F3, M_0F, WIG, 0x5C);
- public static final VexRVMOp VSUBSD = new VexRVMOp("VSUBSD", P_F2, M_0F, WIG, 0x5C);
- public static final VexRVMOp VDIVPS = new VexRVMOp("VDIVPS", P_, M_0F, WIG, 0x5E);
- public static final VexRVMOp VDIVPD = new VexRVMOp("VDIVPD", P_66, M_0F, WIG, 0x5E);
- public static final VexRVMOp VDIVSS = new VexRVMOp("VDIVPS", P_F3, M_0F, WIG, 0x5E);
- public static final VexRVMOp VDIVSD = new VexRVMOp("VDIVPD", P_F2, M_0F, WIG, 0x5E);
- public static final VexRVMOp VADDSUBPS = new VexRVMOp("VADDSUBPS", P_F2, M_0F, WIG, 0xD0);
- public static final VexRVMOp VADDSUBPD = new VexRVMOp("VADDSUBPD", P_66, M_0F, WIG, 0xD0);
- public static final VexRVMOp VPAND = new VexRVMOp("VPAND", P_66, M_0F, WIG, 0xDB, AVX1_2);
- public static final VexRVMOp VPOR = new VexRVMOp("VPOR", P_66, M_0F, WIG, 0xEB, AVX1_2);
- public static final VexRVMOp VPXOR = new VexRVMOp("VPXOR", P_66, M_0F, WIG, 0xEF, AVX1_2);
- public static final VexRVMOp VPADDB = new VexRVMOp("VPADDB", P_66, M_0F, WIG, 0xFC, AVX1_2);
- public static final VexRVMOp VPADDW = new VexRVMOp("VPADDW", P_66, M_0F, WIG, 0xFD, AVX1_2);
- public static final VexRVMOp VPADDD = new VexRVMOp("VPADDD", P_66, M_0F, WIG, 0xFE, AVX1_2);
- public static final VexRVMOp VPADDQ = new VexRVMOp("VPADDQ", P_66, M_0F, WIG, 0xD4, AVX1_2);
- public static final VexRVMOp VPMULHUW = new VexRVMOp("VPMULHUW", P_66, M_0F, WIG, 0xE4, AVX1_2);
- public static final VexRVMOp VPMULHW = new VexRVMOp("VPMULHW", P_66, M_0F, WIG, 0xE5, AVX1_2);
- public static final VexRVMOp VPMULLW = new VexRVMOp("VPMULLW", P_66, M_0F, WIG, 0xD5, AVX1_2);
- public static final VexRVMOp VPMULLD = new VexRVMOp("VPMULLD", P_66, M_0F38, WIG, 0x40, AVX1_2);
- public static final VexRVMOp VPSUBB = new VexRVMOp("VPSUBB", P_66, M_0F, WIG, 0xF8, AVX1_2);
- public static final VexRVMOp VPSUBW = new VexRVMOp("VPSUBW", P_66, M_0F, WIG, 0xF9, AVX1_2);
- public static final VexRVMOp VPSUBD = new VexRVMOp("VPSUBD", P_66, M_0F, WIG, 0xFA, AVX1_2);
- public static final VexRVMOp VPSUBQ = new VexRVMOp("VPSUBQ", P_66, M_0F, WIG, 0xFB, AVX1_2);
- public static final VexRVMOp VPSHUFB = new VexRVMOp("VPSHUFB", P_66, M_0F38, WIG, 0x00, AVX1_2);
- public static final VexRVMOp VCVTSD2SS = new VexRVMOp("VCVTSD2SS", P_F2, M_0F, WIG, 0x5A);
- public static final VexRVMOp VCVTSS2SD = new VexRVMOp("VCVTSS2SD", P_F3, M_0F, WIG, 0x5A);
- public static final VexRVMOp VCVTSI2SD = new VexRVMOp("VCVTSI2SD", P_F2, M_0F, W0, 0x2A, XMM_XMM_CPU);
- public static final VexRVMOp VCVTSQ2SD = new VexRVMOp("VCVTSQ2SD", P_F2, M_0F, W1, 0x2A, XMM_XMM_CPU);
- public static final VexRVMOp VCVTSI2SS = new VexRVMOp("VCVTSI2SS", P_F3, M_0F, W0, 0x2A, XMM_XMM_CPU);
- public static final VexRVMOp VCVTSQ2SS = new VexRVMOp("VCVTSQ2SS", P_F3, M_0F, W1, 0x2A, XMM_XMM_CPU);
- public static final VexRVMOp VPCMPEQB = new VexRVMOp("VPCMPEQB", P_66, M_0F, WIG, 0x74, AVX1_2);
- public static final VexRVMOp VPCMPEQW = new VexRVMOp("VPCMPEQW", P_66, M_0F, WIG, 0x75, AVX1_2);
- public static final VexRVMOp VPCMPEQD = new VexRVMOp("VPCMPEQD", P_66, M_0F, WIG, 0x76, AVX1_2);
- public static final VexRVMOp VPCMPEQQ = new VexRVMOp("VPCMPEQQ", P_66, M_0F38, WIG, 0x76, AVX1_2);
- public static final VexRVMOp VPCMPGTB = new VexRVMOp("VPCMPGTB", P_66, M_0F, WIG, 0x64, AVX1_2);
- public static final VexRVMOp VPCMPGTW = new VexRVMOp("VPCMPGTW", P_66, M_0F, WIG, 0x65, AVX1_2);
- public static final VexRVMOp VPCMPGTD = new VexRVMOp("VPCMPGTD", P_66, M_0F, WIG, 0x66, AVX1_2);
- public static final VexRVMOp VPCMPGTQ = new VexRVMOp("VPCMPGTQ", P_66, M_0F38, WIG, 0x37, AVX1_2);
- // @formatter:on
-
- private VexRVMOp(String opcode, int pp, int mmmmm, int w, int op) {
- this(opcode, pp, mmmmm, w, op, AVX1);
- }
-
- protected VexRVMOp(String opcode, int pp, int mmmmm, int w, int op, OpAssertion assertion) {
- super(opcode, pp, mmmmm, w, op, assertion);
- }
-
- public void emit(AMD64VectorAssembler asm, AVXSize size, Register dst, Register src1, Register src2) {
- assert assertion.check((AMD64) asm.target.arch, size, dst, src1, src2);
- asm.emitVexOp(getLFlag(size), pp, mmmmm, w, op, dst, src1, src2);
- }
-
- public void emit(AMD64VectorAssembler asm, AVXSize size, Register dst, Register src1, AMD64Address src2) {
- assert assertion.check((AMD64) asm.target.arch, size, dst, src1, null);
- asm.emitVexOp(getLFlag(size), pp, mmmmm, w, op, dst, src1, src2, 0);
- }
- }
-
- /**
- * VEX-encoded shift instructions with an operand order of either RVM or VMI.
- */
- public static final class VexShiftOp extends VexRVMOp implements VexRRIOp {
- // @formatter:off
- public static final VexShiftOp VPSRLW = new VexShiftOp("VPSRLW", P_66, M_0F, WIG, 0xD1, 0x71, 2);
- public static final VexShiftOp VPSRLD = new VexShiftOp("VPSRLD", P_66, M_0F, WIG, 0xD2, 0x72, 2);
- public static final VexShiftOp VPSRLQ = new VexShiftOp("VPSRLQ", P_66, M_0F, WIG, 0xD3, 0x73, 2);
- public static final VexShiftOp VPSRAW = new VexShiftOp("VPSRAW", P_66, M_0F, WIG, 0xE1, 0x71, 4);
- public static final VexShiftOp VPSRAD = new VexShiftOp("VPSRAD", P_66, M_0F, WIG, 0xE2, 0x72, 4);
- public static final VexShiftOp VPSLLW = new VexShiftOp("VPSLLW", P_66, M_0F, WIG, 0xF1, 0x71, 6);
- public static final VexShiftOp VPSLLD = new VexShiftOp("VPSLLD", P_66, M_0F, WIG, 0xF2, 0x72, 6);
- public static final VexShiftOp VPSLLQ = new VexShiftOp("VPSLLQ", P_66, M_0F, WIG, 0xF3, 0x73, 6);
- // @formatter:on
-
- private final int immOp;
- private final int r;
-
- private VexShiftOp(String opcode, int pp, int mmmmm, int w, int op, int immOp, int r) {
- super(opcode, pp, mmmmm, w, op, AVX1_2);
- this.immOp = immOp;
- this.r = r;
- }
-
- @Override
- public void emit(AMD64VectorAssembler asm, AVXSize size, Register dst, Register src, int imm8) {
- assert assertion.check((AMD64) asm.target.arch, size, null, dst, src);
- asm.emitVexOp(getLFlag(size), pp, mmmmm, w, immOp, r, dst, src);
- asm.emitByte(imm8);
- }
- }
-
- public static final class VexMaskMoveOp extends VexOp {
- // @formatter:off
- public static final VexMaskMoveOp VMASKMOVPS = new VexMaskMoveOp("VMASKMOVPS", P_66, M_0F38, W0, 0x2C, 0x2E);
- public static final VexMaskMoveOp VMASKMOVPD = new VexMaskMoveOp("VMASKMOVPD", P_66, M_0F38, W0, 0x2D, 0x2F);
- public static final VexMaskMoveOp VPMASKMOVD = new VexMaskMoveOp("VPMASKMOVD", P_66, M_0F38, W0, 0x8C, 0x8E, AVX2);
- public static final VexMaskMoveOp VPMASKMOVQ = new VexMaskMoveOp("VPMASKMOVQ", P_66, M_0F38, W1, 0x8C, 0x8E, AVX2);
- // @formatter:on
-
- private final int opReverse;
-
- private VexMaskMoveOp(String opcode, int pp, int mmmmm, int w, int op, int opReverse) {
- this(opcode, pp, mmmmm, w, op, opReverse, AVX1);
- }
-
- private VexMaskMoveOp(String opcode, int pp, int mmmmm, int w, int op, int opReverse, OpAssertion assertion) {
- super(opcode, pp, mmmmm, w, op, assertion);
- this.opReverse = opReverse;
- }
-
- public void emit(AMD64VectorAssembler asm, AVXSize size, Register dst, Register mask, AMD64Address src) {
- assert assertion.check((AMD64) asm.target.arch, size, dst, mask, null);
- asm.emitVexOp(getLFlag(size), pp, mmmmm, w, op, dst, mask, src, 0);
- }
-
- public void emit(AMD64VectorAssembler asm, AVXSize size, AMD64Address dst, Register mask, Register src) {
- assert assertion.check((AMD64) asm.target.arch, size, src, mask, null);
- asm.emitVexOp(getLFlag(size), pp, mmmmm, w, opReverse, src, mask, dst, 0);
- }
- }
-
- /**
- * VEX-encoded instructions with an operand order of RVMI.
- */
- public static final class VexRVMIOp extends VexOp {
- // @formatter:off
- public static final VexRVMIOp VSHUFPS = new VexRVMIOp("VSHUFPS", P_, M_0F, WIG, 0xC6);
- public static final VexRVMIOp VSHUFPD = new VexRVMIOp("VSHUFPD", P_66, M_0F, WIG, 0xC6);
- public static final VexRVMIOp VINSERTF128 = new VexRVMIOp("VINSERTF128", P_66, M_0F3A, W0, 0x18, AVX1_256ONLY);
- public static final VexRVMIOp VINSERTI128 = new VexRVMIOp("VINSERTI128", P_66, M_0F3A, W0, 0x38, AVX2_256ONLY);
- // @formatter:on
-
- private VexRVMIOp(String opcode, int pp, int mmmmm, int w, int op) {
- this(opcode, pp, mmmmm, w, op, AVX1);
- }
-
- private VexRVMIOp(String opcode, int pp, int mmmmm, int w, int op, OpAssertion assertion) {
- super(opcode, pp, mmmmm, w, op, assertion);
- }
-
- public void emit(AMD64VectorAssembler asm, AVXSize size, Register dst, Register src1, Register src2, int imm8) {
- assert assertion.check((AMD64) asm.target.arch, size, dst, src1, src2);
- assert (imm8 & 0xFF) == imm8;
- asm.emitVexOp(getLFlag(size), pp, mmmmm, w, op, dst, src1, src2);
- asm.emitByte(imm8);
- }
-
- public void emit(AMD64VectorAssembler asm, AVXSize size, Register dst, Register src1, AMD64Address src2, int imm8) {
- assert assertion.check((AMD64) asm.target.arch, size, dst, src1, null);
- assert (imm8 & 0xFF) == imm8;
- asm.emitVexOp(getLFlag(size), pp, mmmmm, w, op, dst, src1, src2, 1);
- asm.emitByte(imm8);
- }
- }
-
- /**
- * VEX-encoded comparison operation with an operand order of RVMI. The immediate operand is a
- * comparison operator.
- */
- public static final class VexFloatCompareOp extends VexOp {
- // @formatter:off
- public static final VexFloatCompareOp VCMPPS = new VexFloatCompareOp("VCMPPS", P_, M_0F, WIG, 0xC2);
- public static final VexFloatCompareOp VCMPPD = new VexFloatCompareOp("VCMPPD", P_66, M_0F, WIG, 0xC2);
- public static final VexFloatCompareOp VCMPSS = new VexFloatCompareOp("VCMPSS", P_F2, M_0F, WIG, 0xC2);
- public static final VexFloatCompareOp VCMPSD = new VexFloatCompareOp("VCMPSD", P_F2, M_0F, WIG, 0xC2);
- // @formatter:on
-
- public enum Predicate {
- EQ_OQ(0x00),
- LT_OS(0x01),
- LE_OS(0x02),
- UNORD_Q(0x03),
- NEQ_UQ(0x04),
- NLT_US(0x05),
- NLE_US(0x06),
- ORD_Q(0x07),
- EQ_UQ(0x08),
- NGE_US(0x09),
- NGT_US(0x0a),
- FALSE_OQ(0x0b),
- NEQ_OQ(0x0c),
- GE_OS(0x0d),
- GT_OS(0x0e),
- TRUE_UQ(0x0f),
- EQ_OS(0x10),
- LT_OQ(0x11),
- LE_OQ(0x12),
- UNORD_S(0x13),
- NEQ_US(0x14),
- NLT_UQ(0x15),
- NLE_UQ(0x16),
- ORD_S(0x17),
- EQ_US(0x18),
- NGE_UQ(0x19),
- NGT_UQ(0x1a),
- FALSE_OS(0x1b),
- NEQ_OS(0x1c),
- GE_OQ(0x1d),
- GT_OQ(0x1e),
- TRUE_US(0x1f);
-
- private int imm8;
-
- Predicate(int imm8) {
- this.imm8 = imm8;
- }
-
- public static Predicate getPredicate(Condition condition, boolean unorderedIsTrue) {
- if (unorderedIsTrue) {
- switch (condition) {
- case EQ:
- return EQ_UQ;
- case NE:
- return NEQ_UQ;
- case LT:
- return NGE_UQ;
- case LE:
- return NGT_UQ;
- case GT:
- return NLE_UQ;
- case GE:
- return NLT_UQ;
- default:
- throw GraalError.shouldNotReachHere();
- }
- } else {
- switch (condition) {
- case EQ:
- return EQ_OQ;
- case NE:
- return NEQ_OQ;
- case LT:
- return LT_OQ;
- case LE:
- return LE_OQ;
- case GT:
- return GT_OQ;
- case GE:
- return GE_OQ;
- default:
- throw GraalError.shouldNotReachHere();
- }
- }
- }
- }
-
- private VexFloatCompareOp(String opcode, int pp, int mmmmm, int w, int op) {
- super(opcode, pp, mmmmm, w, op, AVX1);
- }
-
- public void emit(AMD64VectorAssembler asm, AVXSize size, Register dst, Register src1, Register src2, Predicate p) {
- assert assertion.check((AMD64) asm.target.arch, size, dst, src1, src2);
- asm.emitVexOp(getLFlag(size), pp, mmmmm, w, op, dst, src1, src2);
- asm.emitByte(p.imm8);
- }
-
- public void emit(AMD64VectorAssembler asm, AVXSize size, Register dst, Register src1, AMD64Address src2, Predicate p) {
- assert assertion.check((AMD64) asm.target.arch, size, dst, src1, null);
- asm.emitVexOp(getLFlag(size), pp, mmmmm, w, op, dst, src1, src2, 1);
- asm.emitByte(p.imm8);
- }
- }
-
- @Override
- public void movflt(Register dst, Register src) {
- VexMoveOp.VMOVAPS.emit(this, AVXSize.XMM, dst, src);
- }
-
- @Override
- public void movflt(Register dst, AMD64Address src) {
- VexMoveOp.VMOVSS.emit(this, AVXSize.XMM, dst, src);
- }
-
- @Override
- public void movflt(AMD64Address dst, Register src) {
- VexMoveOp.VMOVSS.emit(this, AVXSize.XMM, dst, src);
- }
-
- @Override
- public void movdbl(Register dst, Register src) {
- VexMoveOp.VMOVAPD.emit(this, AVXSize.XMM, dst, src);
- }
-
- @Override
- public void movdbl(Register dst, AMD64Address src) {
- VexMoveOp.VMOVSD.emit(this, AVXSize.XMM, dst, src);
- }
-
- @Override
- public void movdbl(AMD64Address dst, Register src) {
- VexMoveOp.VMOVSD.emit(this, AVXSize.XMM, dst, src);
- }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AVXKind.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AVXKind.java Thu Aug 23 11:09:16 2018 -0400
@@ -28,6 +28,7 @@
import static org.graalvm.compiler.asm.amd64.AVXKind.AVXSize.QWORD;
import static org.graalvm.compiler.asm.amd64.AVXKind.AVXSize.XMM;
import static org.graalvm.compiler.asm.amd64.AVXKind.AVXSize.YMM;
+import static org.graalvm.compiler.asm.amd64.AVXKind.AVXSize.ZMM;
import jdk.vm.ci.meta.Value;
import org.graalvm.compiler.debug.GraalError;
@@ -43,7 +44,8 @@
DWORD,
QWORD,
XMM,
- YMM;
+ YMM,
+ ZMM;
public int getBytes() {
switch (this) {
@@ -55,6 +57,8 @@
return 16;
case YMM:
return 32;
+ case ZMM:
+ return 64;
default:
return 0;
}
@@ -84,6 +88,8 @@
return XMM;
case 32:
return YMM;
+ case 64:
+ return ZMM;
default:
throw GraalError.shouldNotReachHere("unsupported kind: " + kind);
}
@@ -91,7 +97,10 @@
public static AVXSize getRegisterSize(AMD64Kind kind) {
assert kind.isXMM() : "unexpected kind " + kind;
- if (kind.getSizeInBytes() > 16) {
+ int size = kind.getSizeInBytes();
+ if (size > 32) {
+ return ZMM;
+ } else if (size > 16) {
return YMM;
} else {
return XMM;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.sparc/src/org/graalvm/compiler/asm/sparc/SPARCAssembler.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.sparc/src/org/graalvm/compiler/asm/sparc/SPARCAssembler.java Thu Aug 23 11:09:16 2018 -0400
@@ -1173,7 +1173,7 @@
public static final Sethi SETHI = new Sethi();
public static final FMOVcc FMOVSCC = new FMOVcc(OpfLow.Fmovscc);
public static final FMOVcc FMOVDCC = new FMOVcc(OpfLow.Fmovdcc);
- public static final MOVicc MOVicc = new MOVicc();
+ public static final MOVicc MOVICC = new MOVicc();
public static final OpfOp OPF = new OpfOp();
public static final Op3Op OP3 = new Op3Op();
public static final SPARCOp LDST = new SPARCOp(Ops.LdstOp);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java Thu Aug 23 11:09:16 2018 -0400
@@ -53,14 +53,14 @@
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64Shift.SAR;
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64Shift.SHL;
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64Shift.SHR;
-import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.BYTE;
-import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.DWORD;
-import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.PD;
-import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.PS;
-import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.QWORD;
-import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.SD;
-import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.SS;
-import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.WORD;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.BYTE;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.DWORD;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.PD;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.PS;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.QWORD;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.SD;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.SS;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.WORD;
import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
import static org.graalvm.compiler.lir.LIRValueUtil.asConstantValue;
import static org.graalvm.compiler.lir.LIRValueUtil.asJavaConstant;
@@ -82,11 +82,9 @@
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MROp;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMIOp;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp;
-import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RRMOp;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64Shift;
-import org.graalvm.compiler.asm.amd64.AMD64Assembler.AVXOp;
-import org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.SSEOp;
+import org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.NumUtil;
import org.graalvm.compiler.core.common.calc.FloatConvert;
@@ -112,12 +110,10 @@
import org.graalvm.compiler.lir.gen.LIRGenerator;
import jdk.vm.ci.amd64.AMD64;
-import jdk.vm.ci.amd64.AMD64.CPUFeature;
import jdk.vm.ci.amd64.AMD64Kind;
import jdk.vm.ci.code.CodeUtil;
import jdk.vm.ci.code.Register;
import jdk.vm.ci.code.RegisterValue;
-import jdk.vm.ci.code.TargetDescription;
import jdk.vm.ci.meta.AllocatableValue;
import jdk.vm.ci.meta.Constant;
import jdk.vm.ci.meta.JavaConstant;
@@ -174,8 +170,6 @@
public Variable emitNegate(Value inputVal) {
AllocatableValue input = asAllocatable(inputVal);
Variable result = getLIRGen().newVariable(LIRKind.combine(input));
- TargetDescription target = getLIRGen().target();
- boolean isAvx = ((AMD64) target.arch).getFeatures().contains(CPUFeature.AVX);
switch ((AMD64Kind) input.getPlatformKind()) {
case DWORD:
getLIRGen().append(new AMD64Unary.MOp(NEG, DWORD, result, input));
@@ -184,18 +178,10 @@
getLIRGen().append(new AMD64Unary.MOp(NEG, QWORD, result, input));
break;
case SINGLE:
- if (isAvx) {
- getLIRGen().append(new AMD64Binary.DataThreeOp(AVXOp.XOR, PS, result, input, JavaConstant.forFloat(Float.intBitsToFloat(0x80000000)), 16));
- } else {
- getLIRGen().append(new AMD64Binary.DataTwoOp(SSEOp.XOR, PS, result, input, JavaConstant.forFloat(Float.intBitsToFloat(0x80000000)), 16));
- }
+ getLIRGen().append(new AMD64Binary.DataTwoOp(SSEOp.XOR, PS, result, input, JavaConstant.forFloat(Float.intBitsToFloat(0x80000000)), 16));
break;
case DOUBLE:
- if (isAvx) {
- getLIRGen().append(new AMD64Binary.DataThreeOp(AVXOp.XOR, PD, result, input, JavaConstant.forDouble(Double.longBitsToDouble(0x8000000000000000L)), 16));
- } else {
- getLIRGen().append(new AMD64Binary.DataTwoOp(SSEOp.XOR, PD, result, input, JavaConstant.forDouble(Double.longBitsToDouble(0x8000000000000000L)), 16));
- }
+ getLIRGen().append(new AMD64Binary.DataTwoOp(SSEOp.XOR, PD, result, input, JavaConstant.forDouble(Double.longBitsToDouble(0x8000000000000000L)), 16));
break;
default:
throw GraalError.shouldNotReachHere(input.getPlatformKind().toString());
@@ -240,16 +226,6 @@
}
}
- private Variable emitBinary(LIRKind resultKind, AMD64RRMOp op, OperandSize size, boolean commutative, Value a, Value b) {
- if (isJavaConstant(b)) {
- return emitBinaryConst(resultKind, op, size, asAllocatable(a), asJavaConstant(b));
- } else if (commutative && isJavaConstant(a)) {
- return emitBinaryConst(resultKind, op, size, asAllocatable(b), asJavaConstant(a));
- } else {
- return emitBinaryVar(resultKind, op, size, commutative, asAllocatable(a), asAllocatable(b));
- }
- }
-
private Variable emitBinaryConst(LIRKind resultKind, AMD64BinaryArithmetic op, OperandSize size, boolean commutative, AllocatableValue a, ConstantValue b, boolean setFlags) {
long value = b.getJavaConstant().asLong();
if (NumUtil.isInt(value)) {
@@ -296,12 +272,6 @@
return result;
}
- private Variable emitBinaryConst(LIRKind resultKind, AMD64RRMOp op, OperandSize size, AllocatableValue a, JavaConstant b) {
- Variable result = getLIRGen().newVariable(resultKind);
- getLIRGen().append(new AMD64Binary.DataThreeOp(op, size, result, a, b));
- return result;
- }
-
private Variable emitBinaryVar(LIRKind resultKind, AMD64RMOp op, OperandSize size, boolean commutative, AllocatableValue a, AllocatableValue b) {
Variable result = getLIRGen().newVariable(resultKind);
if (commutative) {
@@ -312,16 +282,6 @@
return result;
}
- private Variable emitBinaryVar(LIRKind resultKind, AMD64RRMOp op, OperandSize size, boolean commutative, AllocatableValue a, AllocatableValue b) {
- Variable result = getLIRGen().newVariable(resultKind);
- if (commutative) {
- getLIRGen().append(new AMD64Binary.CommutativeThreeOp(op, size, result, a, b));
- } else {
- getLIRGen().append(new AMD64Binary.ThreeOp(op, size, result, a, b));
- }
- return result;
- }
-
@Override
protected boolean isNumericInteger(PlatformKind kind) {
return ((AMD64Kind) kind).isInteger();
@@ -336,8 +296,6 @@
@Override
public Variable emitAdd(LIRKind resultKind, Value a, Value b, boolean setFlags) {
- TargetDescription target = getLIRGen().target();
- boolean isAvx = ((AMD64) target.arch).getFeatures().contains(CPUFeature.AVX);
switch ((AMD64Kind) a.getPlatformKind()) {
case DWORD:
if (isJavaConstant(b) && !setFlags) {
@@ -356,17 +314,9 @@
}
return emitBinary(resultKind, ADD, QWORD, true, a, b, setFlags);
case SINGLE:
- if (isAvx) {
- return emitBinary(resultKind, AVXOp.ADD, SS, true, a, b);
- } else {
- return emitBinary(resultKind, SSEOp.ADD, SS, true, a, b);
- }
+ return emitBinary(resultKind, SSEOp.ADD, SS, true, a, b);
case DOUBLE:
- if (isAvx) {
- return emitBinary(resultKind, AVXOp.ADD, SD, true, a, b);
- } else {
- return emitBinary(resultKind, SSEOp.ADD, SD, true, a, b);
- }
+ return emitBinary(resultKind, SSEOp.ADD, SD, true, a, b);
default:
throw GraalError.shouldNotReachHere();
}
@@ -374,25 +324,15 @@
@Override
public Variable emitSub(LIRKind resultKind, Value a, Value b, boolean setFlags) {
- TargetDescription target = getLIRGen().target();
- boolean isAvx = ((AMD64) target.arch).getFeatures().contains(CPUFeature.AVX);
switch ((AMD64Kind) a.getPlatformKind()) {
case DWORD:
return emitBinary(resultKind, SUB, DWORD, false, a, b, setFlags);
case QWORD:
return emitBinary(resultKind, SUB, QWORD, false, a, b, setFlags);
case SINGLE:
- if (isAvx) {
- return emitBinary(resultKind, AVXOp.SUB, SS, false, a, b);
- } else {
- return emitBinary(resultKind, SSEOp.SUB, SS, false, a, b);
- }
+ return emitBinary(resultKind, SSEOp.SUB, SS, false, a, b);
case DOUBLE:
- if (isAvx) {
- return emitBinary(resultKind, AVXOp.SUB, SD, false, a, b);
- } else {
- return emitBinary(resultKind, SSEOp.SUB, SD, false, a, b);
- }
+ return emitBinary(resultKind, SSEOp.SUB, SD, false, a, b);
default:
throw GraalError.shouldNotReachHere();
}
@@ -430,25 +370,15 @@
@Override
public Variable emitMul(Value a, Value b, boolean setFlags) {
LIRKind resultKind = LIRKind.combine(a, b);
- TargetDescription target = getLIRGen().target();
- boolean isAvx = ((AMD64) target.arch).getFeatures().contains(CPUFeature.AVX);
switch ((AMD64Kind) a.getPlatformKind()) {
case DWORD:
return emitIMUL(DWORD, a, b);
case QWORD:
return emitIMUL(QWORD, a, b);
case SINGLE:
- if (isAvx) {
- return emitBinary(resultKind, AVXOp.MUL, SS, true, a, b);
- } else {
- return emitBinary(resultKind, SSEOp.MUL, SS, true, a, b);
- }
+ return emitBinary(resultKind, SSEOp.MUL, SS, true, a, b);
case DOUBLE:
- if (isAvx) {
- return emitBinary(resultKind, AVXOp.MUL, SD, true, a, b);
- } else {
- return emitBinary(resultKind, SSEOp.MUL, SD, true, a, b);
- }
+ return emitBinary(resultKind, SSEOp.MUL, SD, true, a, b);
default:
throw GraalError.shouldNotReachHere();
}
@@ -495,12 +425,6 @@
return result;
}
- public Value emitBinaryMemory(AMD64RRMOp op, OperandSize size, AllocatableValue a, AMD64AddressValue location, LIRFrameState state) {
- Variable result = getLIRGen().newVariable(LIRKind.combine(a));
- getLIRGen().append(new AMD64Binary.MemoryThreeOp(op, size, result, a, location, state));
- return result;
- }
-
protected Value emitConvertMemoryOp(PlatformKind kind, AMD64RMOp op, OperandSize size, AMD64AddressValue address, LIRFrameState state) {
Variable result = getLIRGen().newVariable(LIRKind.value(kind));
getLIRGen().append(new AMD64Unary.MemoryOp(op, size, result, address, state));
@@ -578,8 +502,6 @@
@Override
public Value emitDiv(Value a, Value b, LIRFrameState state) {
- TargetDescription target = getLIRGen().target();
- boolean isAvx = ((AMD64) target.arch).getFeatures().contains(CPUFeature.AVX);
LIRKind resultKind = LIRKind.combine(a, b);
switch ((AMD64Kind) a.getPlatformKind()) {
case DWORD:
@@ -589,17 +511,9 @@
AMD64MulDivOp lop = emitIDIV(QWORD, a, b, state);
return getLIRGen().emitMove(lop.getQuotient());
case SINGLE:
- if (isAvx) {
- return emitBinary(resultKind, AVXOp.DIV, SS, false, a, b);
- } else {
- return emitBinary(resultKind, SSEOp.DIV, SS, false, a, b);
- }
+ return emitBinary(resultKind, SSEOp.DIV, SS, false, a, b);
case DOUBLE:
- if (isAvx) {
- return emitBinary(resultKind, AVXOp.DIV, SD, false, a, b);
- } else {
- return emitBinary(resultKind, SSEOp.DIV, SD, false, a, b);
- }
+ return emitBinary(resultKind, SSEOp.DIV, SD, false, a, b);
default:
throw GraalError.shouldNotReachHere();
}
@@ -664,25 +578,15 @@
@Override
public Variable emitAnd(Value a, Value b) {
LIRKind resultKind = LIRKind.combine(a, b);
- TargetDescription target = getLIRGen().target();
- boolean isAvx = ((AMD64) target.arch).getFeatures().contains(CPUFeature.AVX);
switch ((AMD64Kind) a.getPlatformKind()) {
case DWORD:
return emitBinary(resultKind, AND, DWORD, true, a, b, false);
case QWORD:
return emitBinary(resultKind, AND, QWORD, true, a, b, false);
case SINGLE:
- if (isAvx) {
- return emitBinary(resultKind, AVXOp.AND, PS, true, a, b);
- } else {
- return emitBinary(resultKind, SSEOp.AND, PS, true, a, b);
- }
+ return emitBinary(resultKind, SSEOp.AND, PS, true, a, b);
case DOUBLE:
- if (isAvx) {
- return emitBinary(resultKind, AVXOp.AND, PD, true, a, b);
- } else {
- return emitBinary(resultKind, SSEOp.AND, PD, true, a, b);
- }
+ return emitBinary(resultKind, SSEOp.AND, PD, true, a, b);
default:
throw GraalError.shouldNotReachHere();
}
@@ -691,25 +595,15 @@
@Override
public Variable emitOr(Value a, Value b) {
LIRKind resultKind = LIRKind.combine(a, b);
- TargetDescription target = getLIRGen().target();
- boolean isAvx = ((AMD64) target.arch).getFeatures().contains(CPUFeature.AVX);
switch ((AMD64Kind) a.getPlatformKind()) {
case DWORD:
return emitBinary(resultKind, OR, DWORD, true, a, b, false);
case QWORD:
return emitBinary(resultKind, OR, QWORD, true, a, b, false);
case SINGLE:
- if (isAvx) {
- return emitBinary(resultKind, AVXOp.OR, PS, true, a, b);
- } else {
- return emitBinary(resultKind, SSEOp.OR, PS, true, a, b);
- }
+ return emitBinary(resultKind, SSEOp.OR, PS, true, a, b);
case DOUBLE:
- if (isAvx) {
- return emitBinary(resultKind, AVXOp.OR, PD, true, a, b);
- } else {
- return emitBinary(resultKind, SSEOp.OR, PD, true, a, b);
- }
+ return emitBinary(resultKind, SSEOp.OR, PD, true, a, b);
default:
throw GraalError.shouldNotReachHere();
}
@@ -718,25 +612,15 @@
@Override
public Variable emitXor(Value a, Value b) {
LIRKind resultKind = LIRKind.combine(a, b);
- TargetDescription target = getLIRGen().target();
- boolean isAvx = ((AMD64) target.arch).getFeatures().contains(CPUFeature.AVX);
switch ((AMD64Kind) a.getPlatformKind()) {
case DWORD:
return emitBinary(resultKind, XOR, DWORD, true, a, b, false);
case QWORD:
return emitBinary(resultKind, XOR, QWORD, true, a, b, false);
case SINGLE:
- if (isAvx) {
- return emitBinary(resultKind, AVXOp.XOR, PS, true, a, b);
- } else {
- return emitBinary(resultKind, SSEOp.XOR, PS, true, a, b);
- }
+ return emitBinary(resultKind, SSEOp.XOR, PS, true, a, b);
case DOUBLE:
- if (isAvx) {
- return emitBinary(resultKind, AVXOp.XOR, PD, true, a, b);
- } else {
- return emitBinary(resultKind, SSEOp.XOR, PD, true, a, b);
- }
+ return emitBinary(resultKind, SSEOp.XOR, PD, true, a, b);
default:
throw GraalError.shouldNotReachHere();
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java Thu Aug 23 11:09:16 2018 -0400
@@ -29,10 +29,10 @@
import static jdk.vm.ci.code.ValueUtil.isAllocatableValue;
import static jdk.vm.ci.code.ValueUtil.isRegister;
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.CMP;
-import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.DWORD;
-import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.PD;
-import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.PS;
-import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.QWORD;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.DWORD;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.PD;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.PS;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.QWORD;
import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
import static org.graalvm.compiler.lir.LIRValueUtil.asConstant;
import static org.graalvm.compiler.lir.LIRValueUtil.asConstantValue;
@@ -45,7 +45,7 @@
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag;
-import org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize;
+import org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.SSEOp;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.NumUtil;
@@ -66,6 +66,7 @@
import org.graalvm.compiler.lir.amd64.AMD64ArithmeticLIRGeneratorTool;
import org.graalvm.compiler.lir.amd64.AMD64ArrayCompareToOp;
import org.graalvm.compiler.lir.amd64.AMD64ArrayEqualsOp;
+import org.graalvm.compiler.lir.amd64.AMD64ArrayIndexOfOp;
import org.graalvm.compiler.lir.amd64.AMD64Binary;
import org.graalvm.compiler.lir.amd64.AMD64BinaryConsumer;
import org.graalvm.compiler.lir.amd64.AMD64ByteSwapOp;
@@ -566,6 +567,13 @@
}
@Override
+ public Variable emitArrayIndexOf(JavaKind kind, Value arrayPointer, Value arrayLength, Value charValue) {
+ Variable result = newVariable(LIRKind.value(AMD64Kind.DWORD));
+ append(new AMD64ArrayIndexOfOp(kind, getVMPageSize(), this, result, asAllocatable(arrayPointer), asAllocatable(arrayLength), asAllocatable(charValue)));
+ return result;
+ }
+
+ @Override
public void emitReturn(JavaKind kind, Value input) {
AllocatableValue operand = Value.ILLEGAL;
if (input != null) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactoryBase.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactoryBase.java Thu Aug 23 11:09:16 2018 -0400
@@ -25,8 +25,8 @@
package org.graalvm.compiler.core.amd64;
-import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.QWORD;
-import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.WORD;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.QWORD;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.WORD;
import jdk.internal.vm.compiler.collections.EconomicMap;
import jdk.internal.vm.compiler.collections.Equivalence;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java Thu Aug 23 11:09:16 2018 -0400
@@ -33,17 +33,15 @@
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp.MOVSX;
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp.MOVSXB;
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp.MOVSXD;
-import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.DWORD;
-import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.QWORD;
-import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.SD;
-import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.SS;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.DWORD;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.QWORD;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.SD;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.SS;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp;
-import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RRMOp;
-import org.graalvm.compiler.asm.amd64.AMD64Assembler.AVXOp;
-import org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.SSEOp;
+import org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.NumUtil;
import org.graalvm.compiler.core.common.calc.CanonicalCondition;
@@ -80,10 +78,7 @@
import org.graalvm.compiler.nodes.memory.WriteNode;
import org.graalvm.compiler.nodes.util.GraphUtil;
-import jdk.vm.ci.amd64.AMD64;
-import jdk.vm.ci.amd64.AMD64.CPUFeature;
import jdk.vm.ci.amd64.AMD64Kind;
-import jdk.vm.ci.code.TargetDescription;
import jdk.vm.ci.meta.AllocatableValue;
import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.PlatformKind;
@@ -390,23 +385,12 @@
getState(access));
}
- private ComplexMatchResult binaryRead(AMD64RRMOp op, OperandSize size, ValueNode value, LIRLowerableAccess access) {
- return builder -> getArithmeticLIRGenerator().emitBinaryMemory(op, size, getLIRGeneratorTool().asAllocatable(operand(value)), (AMD64AddressValue) operand(access.getAddress()),
- getState(access));
- }
-
@MatchRule("(Add value Read=access)")
@MatchRule("(Add value FloatingRead=access)")
public ComplexMatchResult addMemory(ValueNode value, LIRLowerableAccess access) {
OperandSize size = getMemorySize(access);
if (size.isXmmType()) {
- TargetDescription target = getLIRGeneratorTool().target();
- boolean isAvx = ((AMD64) target.arch).getFeatures().contains(CPUFeature.AVX);
- if (isAvx) {
- return binaryRead(AVXOp.ADD, size, value, access);
- } else {
- return binaryRead(SSEOp.ADD, size, value, access);
- }
+ return binaryRead(SSEOp.ADD, size, value, access);
} else {
return binaryRead(ADD.getRMOpcode(size), size, value, access);
}
@@ -417,13 +401,7 @@
public ComplexMatchResult subMemory(ValueNode value, LIRLowerableAccess access) {
OperandSize size = getMemorySize(access);
if (size.isXmmType()) {
- TargetDescription target = getLIRGeneratorTool().target();
- boolean isAvx = ((AMD64) target.arch).getFeatures().contains(CPUFeature.AVX);
- if (isAvx) {
- return binaryRead(AVXOp.SUB, size, value, access);
- } else {
- return binaryRead(SSEOp.SUB, size, value, access);
- }
+ return binaryRead(SSEOp.SUB, size, value, access);
} else {
return binaryRead(SUB.getRMOpcode(size), size, value, access);
}
@@ -434,13 +412,7 @@
public ComplexMatchResult mulMemory(ValueNode value, LIRLowerableAccess access) {
OperandSize size = getMemorySize(access);
if (size.isXmmType()) {
- TargetDescription target = getLIRGeneratorTool().target();
- boolean isAvx = ((AMD64) target.arch).getFeatures().contains(CPUFeature.AVX);
- if (isAvx) {
- return binaryRead(AVXOp.MUL, size, value, access);
- } else {
- return binaryRead(SSEOp.MUL, size, value, access);
- }
+ return binaryRead(SSEOp.MUL, size, value, access);
} else {
return binaryRead(AMD64RMOp.IMUL, size, value, access);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/NumUtil.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/NumUtil.java Thu Aug 23 11:09:16 2018 -0400
@@ -110,6 +110,11 @@
return (short) v;
}
+ public static int safeToInt(long v) {
+ assert isInt(v);
+ return (int) v;
+ }
+
public static int roundUp(int number, int mod) {
return ((number + mod - 1) / mod) * mod;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/IntList.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/IntList.java Thu Aug 23 11:09:16 2018 -0400
@@ -147,9 +147,9 @@
/**
* Adjusts the {@linkplain #size() size} of this int list.
*
- * If {@code newSize < size()}, the size is changed to {@code newSize}. If
- * {@code newSize > size()}, sufficient 0 elements are {@linkplain #add(int) added} until
- * {@code size() == newSize}.
+ * If {@code newSize > size()}, sufficient 0 elements are {@linkplain #add(int) added} until
+ * {@code size() == newSize}. If {@code newSize < size()}, the size is changed to
+ * {@code newSize}.
*
* @param newSize the new size of this int list
*/
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCLIRGenerator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCLIRGenerator.java Thu Aug 23 11:09:16 2018 -0400
@@ -27,7 +27,7 @@
import static org.graalvm.compiler.asm.sparc.SPARCAssembler.FMOVDCC;
import static org.graalvm.compiler.asm.sparc.SPARCAssembler.FMOVSCC;
-import static org.graalvm.compiler.asm.sparc.SPARCAssembler.MOVicc;
+import static org.graalvm.compiler.asm.sparc.SPARCAssembler.MOVICC;
import static org.graalvm.compiler.asm.sparc.SPARCAssembler.CC.Fcc0;
import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Subcc;
import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fcmpd;
@@ -287,7 +287,7 @@
} else if (valueKind.isInteger()) {
actualTrueValue = loadSimm11(trueValue);
actualFalseValue = loadSimm11(falseValue);
- cmove = MOVicc;
+ cmove = MOVICC;
} else {
throw GraalError.shouldNotReachHere();
}
@@ -368,7 +368,7 @@
Variable result = newVariable(trueValue.getValueKind());
ConditionFlag flag = SPARCControlFlow.fromCondition(true, Condition.EQ, false);
CC cc = CC.forKind(left.getPlatformKind());
- append(new CondMoveOp(MOVicc, cc, flag, loadSimm11(trueValue), loadSimm11(falseValue), result));
+ append(new CondMoveOp(MOVICC, cc, flag, loadSimm11(trueValue), loadSimm11(falseValue), result));
return result;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java Thu Aug 23 11:09:16 2018 -0400
@@ -142,7 +142,30 @@
}
protected boolean shouldLoadClass(String className) {
- return !className.equals("module-info") && !className.startsWith("META-INF.versions.");
+ if (className.equals("module-info") || className.startsWith("META-INF.versions.")) {
+ return false;
+ }
+ if (!Java8OrEarlier) {
+ // @formatter:off
+ /*
+ * Work around to prevent:
+ *
+ * org.graalvm.compiler.debug.GraalError: java.lang.IllegalAccessError: class org.graalvm.compiler.serviceprovider.GraalServices$Lazy (in module
+ * jdk.internal.vm.compiler) cannot access class java.lang.management.ManagementFactory (in module java.management) because module
+ * jdk.internal.vm.compiler does not read module java.management
+ * at jdk.internal.vm.compiler/org.graalvm.compiler.debug.GraalError.shouldNotReachHere(GraalError.java:55)
+ * at org.graalvm.compiler.core.test.CheckGraalInvariants$InvariantsTool.handleClassLoadingException(CheckGraalInvariants.java:149)
+ * at org.graalvm.compiler.core.test.CheckGraalInvariants.initializeClasses(CheckGraalInvariants.java:321)
+ * at org.graalvm.compiler.core.test.CheckGraalInvariants.runTest(CheckGraalInvariants.java:239)
+ *
+ * which occurs because JDK8 overlays are in modular jars. They are never used normally.
+ */
+ // @formatter:on
+ if (className.equals("org.graalvm.compiler.serviceprovider.GraalServices$Lazy")) {
+ return false;
+ }
+ }
+ return true;
}
protected void handleClassLoadingException(Throwable t) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConcreteSubtypeTest.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConcreteSubtypeTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -24,12 +24,9 @@
package org.graalvm.compiler.core.test;
-import jdk.vm.ci.meta.Assumptions.Assumption;
-import jdk.vm.ci.meta.Assumptions.ConcreteSubtype;
-
import org.junit.Test;
-import org.graalvm.compiler.nodes.StructuredGraph;
+import jdk.vm.ci.meta.Assumptions.ConcreteSubtype;
/**
* Ensure that abstract classes with a single implementor are properly optimized and that loading a
@@ -57,12 +54,6 @@
object.check();
}
- @Override
- protected void checkGraph(Assumption expectedAssumption, StructuredGraph graph) {
- super.checkGraph(expectedAssumption, graph);
- assertTrue(graph.isTrivial());
- }
-
/**
* Test that {@link #callAbstractType} gets compiled into an empty method with a
* {@link ConcreteSubtype} assumption on {@link AbstractBase} and {@link Subclass}. Then ensures
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/EnumValuesTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2018, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.core.test;
+
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.concurrent.TimeUnit;
+
+public class EnumValuesTest extends GraalCompilerTest {
+
+ private static final int NANOS_INDEX = Arrays.asList(TimeUnit.values()).indexOf(TimeUnit.NANOSECONDS);
+
+ @SuppressWarnings("unused")
+ public static void iterateUnits() {
+ for (TimeUnit unit : TimeUnit.values()) {
+ // nop
+ }
+ }
+
+ public static void empty() {
+ }
+
+ @Test
+ public void test0() {
+ assertEquals(getFinalGraph("empty"), getFinalGraph("iterateUnits"));
+ }
+
+ public static TimeUnit getNanosValues() {
+ return TimeUnit.values()[NANOS_INDEX];
+ }
+
+ public static TimeUnit getNanos() {
+ return TimeUnit.NANOSECONDS;
+ }
+
+ @Test
+ public void test1() {
+ assertEquals(getFinalGraph("getNanos"), getFinalGraph("getNanosValues"));
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FinalizableSubclassTest.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FinalizableSubclassTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -63,6 +63,7 @@
public static final class WithFinalizerAAAA extends NoFinalizerYetAAAA {
+ @SuppressWarnings("deprecation")
@Override
protected void finalize() throws Throwable {
super.finalize();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1063,6 +1063,20 @@
}
}
+ protected StructuredGraph getFinalGraph(String method) {
+ return getFinalGraph(getResolvedJavaMethod(method));
+ }
+
+ protected StructuredGraph getFinalGraph(ResolvedJavaMethod method) {
+ StructuredGraph graph = parseForCompile(method);
+ applyFrontEnd(graph);
+ return graph;
+ }
+
+ protected void applyFrontEnd(StructuredGraph graph) {
+ GraalCompiler.emitFrontEnd(getProviders(), getBackend(), graph, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL, graph.getProfilingInfo(), createSuites(graph.getOptions()));
+ }
+
protected StructuredGraph lastCompiledGraph;
protected SpeculationLog getSpeculationLog() {
@@ -1108,6 +1122,7 @@
return methodMap.get(javaMethod);
}
+ @SuppressWarnings("deprecation")
protected Object invoke(ResolvedJavaMethod javaMethod, Object receiver, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {
Executable method = lookupMethod(javaMethod);
Assert.assertTrue(method != null);
@@ -1443,13 +1458,4 @@
protected boolean isArchitecture(String name) {
return name.equals(backend.getTarget().arch.getName());
}
-
- /**
- * This method should be called in "timeout" tests which JUnit runs in a different thread.
- */
- public static void initializeForTimeout() {
- // timeout tests run in a separate thread which needs the DebugEnvironment to be
- // initialized
- // DebugEnvironment.ensureInitialized(getInitialOptions());
- }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/HashCodeTest.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/HashCodeTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -25,6 +25,7 @@
package org.graalvm.compiler.core.test;
import java.util.HashMap;
+import java.util.List;
import org.graalvm.compiler.core.phases.HighTier;
import org.graalvm.compiler.core.phases.MidTier;
@@ -36,7 +37,9 @@
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.OptimisticOptimizations;
import org.graalvm.compiler.phases.tiers.MidTierContext;
+import org.graalvm.compiler.test.SubprocessUtil;
import org.junit.Assert;
+import org.junit.Assume;
import org.junit.Test;
public class HashCodeTest extends GraalCompilerTest {
@@ -141,6 +144,11 @@
@Test
public void test08() {
+ // This test requires profiling information which does not work reliable across platforms
+ // when running with -Xcomp
+ List<String> commandLine = SubprocessUtil.getVMCommandLine();
+ Assume.assumeTrue(commandLine != null);
+ Assume.assumeFalse(commandLine.contains("-Xcomp"));
initialize(Appendable.class);
checkForGuardedIntrinsicPattern("hashCodeInterface");
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/HashMapGetTest.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/HashMapGetTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -48,7 +48,7 @@
map.put(i, i);
mapGet(map, i);
}
- test(get, null, map, new Integer(0));
+ test(get, null, map, 0);
for (IfNode ifNode : lastCompiledGraph.getNodes(IfNode.TYPE)) {
LogicNode condition = ifNode.condition();
if (ifNode.getTrueSuccessorProbability() < 0.4 && condition instanceof ObjectEqualsNode) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InterfaceMethodHandleTest.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InterfaceMethodHandleTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -98,8 +98,8 @@
}
@Test
- public void testInvokeInterface02() throws InstantiationException, IllegalAccessException, ClassNotFoundException {
- test("invokeInterfaceHandle", loader.findClass(NAME).newInstance());
+ public void testInvokeInterface02() throws Exception {
+ test("invokeInterfaceHandle", loader.findClass(NAME).getDeclaredConstructor().newInstance());
}
public static Object invokeInterfaceHandle2(I o, int a, int b, int c, int d, int e, int f, int g, int h, int i, int j) throws Throwable {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InvocationPluginsTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2018, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.core.test;
+
+import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
+import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
+import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin.Receiver;
+import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
+import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.LateRegistration;
+import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration;
+import org.junit.Test;
+
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
+public class InvocationPluginsTest extends GraalCompilerTest {
+
+ private static void assertNotIsEmpty(InvocationPlugins invocationPlugins) {
+ InvocationPlugins childInvocationPlugins = new InvocationPlugins(invocationPlugins);
+ assertFalse(invocationPlugins.isEmpty());
+ assertFalse(childInvocationPlugins.isEmpty());
+
+ invocationPlugins.closeRegistration();
+ assertFalse(invocationPlugins.isEmpty());
+ assertFalse(childInvocationPlugins.isEmpty());
+ }
+
+ @Test
+ public void testIsEmptyWithNormalRegistration() {
+ InvocationPlugins invocationPlugins = new InvocationPlugins();
+ assertTrue(invocationPlugins.isEmpty());
+
+ Registration r = new Registration(invocationPlugins, Class.class);
+ r.register1("isAnonymousClass", Receiver.class, new InvocationPlugin() {
+ @Override
+ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
+ return false;
+ }
+ });
+
+ assertNotIsEmpty(invocationPlugins);
+ }
+
+ @Test
+ public void testIsEmptyWithDeferredRegistration() {
+ InvocationPlugins invocationPlugins = new InvocationPlugins();
+ assertTrue(invocationPlugins.isEmpty());
+ invocationPlugins.defer(new Runnable() {
+
+ @Override
+ public void run() {
+ Registration r = new Registration(invocationPlugins, Class.class);
+ r.register1("isAnonymousClass", Receiver.class, new InvocationPlugin() {
+ @Override
+ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
+ return false;
+ }
+ });
+ }
+ });
+
+ assertNotIsEmpty(invocationPlugins);
+ }
+
+ @Test
+ public void testIsEmptyWithLateRegistration() {
+ InvocationPlugins invocationPlugins = new InvocationPlugins();
+ assertTrue(invocationPlugins.isEmpty());
+
+ try (LateRegistration lr = new LateRegistration(invocationPlugins, Class.class)) {
+ lr.register(new InvocationPlugin() {
+ @Override
+ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
+ return false;
+ }
+ }, "isAnonymousClass", Receiver.class);
+ }
+ assertNotIsEmpty(invocationPlugins);
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnsafeReadEliminationTest.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnsafeReadEliminationTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -60,14 +60,16 @@
longArrayBaseOffset = UNSAFE.arrayBaseOffset(long[].class);
}
+ private static final long ARRAY_LONG_BASE_OFFSET = Unsafe.ARRAY_LONG_BASE_OFFSET;
+
public static long test1Snippet(double a) {
final Object m = Memory;
if (a > 0) {
- UNSAFE.putDouble(m, (long) Unsafe.ARRAY_LONG_BASE_OFFSET, a);
+ UNSAFE.putDouble(m, ARRAY_LONG_BASE_OFFSET, a);
} else {
- SideEffectL = UNSAFE.getLong(m, (long) Unsafe.ARRAY_LONG_BASE_OFFSET);
+ SideEffectL = UNSAFE.getLong(m, ARRAY_LONG_BASE_OFFSET);
}
- return UNSAFE.getLong(m, (long) Unsafe.ARRAY_LONG_BASE_OFFSET);
+ return UNSAFE.getLong(m, ARRAY_LONG_BASE_OFFSET);
}
public static class A {
@@ -80,14 +82,14 @@
if (c != 0) {
long[][] r = a.o;
phi = r;
- UNSAFE.putDouble(r, (long) Unsafe.ARRAY_LONG_BASE_OFFSET, 12d);
+ UNSAFE.putDouble(r, ARRAY_LONG_BASE_OFFSET, 12d);
} else {
long[][] r = a.p;
phi = r;
- UNSAFE.putLong(r, (long) Unsafe.ARRAY_LONG_BASE_OFFSET, 123);
+ UNSAFE.putLong(r, ARRAY_LONG_BASE_OFFSET, 123);
}
GraalDirectives.controlFlowAnchor();
- SideEffectD = UNSAFE.getDouble(phi, (long) Unsafe.ARRAY_LONG_BASE_OFFSET);
+ SideEffectD = UNSAFE.getDouble(phi, ARRAY_LONG_BASE_OFFSET);
return phi;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EscapeAnalysisTest.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EscapeAnalysisTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -57,6 +57,7 @@
testEscapeAnalysis("test1Snippet", JavaConstant.forInt(101), false);
}
+ @SuppressWarnings("deprecation")
public static int test1Snippet() {
Integer x = new Integer(101);
return x.intValue();
@@ -87,6 +88,7 @@
testEscapeAnalysis("testMonitorSnippet", JavaConstant.forInt(0), false);
}
+ @SuppressWarnings("deprecation")
public static int testMonitorSnippet() {
Integer x = new Integer(0);
Double y = new Double(0);
@@ -110,6 +112,7 @@
* This test case differs from the last one in that it requires inlining within a synchronized
* region.
*/
+ @SuppressWarnings("deprecation")
public static int testMonitor2Snippet() {
Integer x = new Integer(0);
Double y = new Double(0);
@@ -331,6 +334,7 @@
public volatile Object field;
+ @SuppressWarnings("deprecation")
public int testChangeHandlingSnippet(int a) {
Object obj;
Integer one = 1;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PEAAssertionsTest.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PEAAssertionsTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -45,6 +45,7 @@
public static Object field;
+ @SuppressWarnings("deprecation")
public static void snippet1(int i) {
Integer object = new Integer(i);
GraalDirectives.ensureVirtualized(object);
@@ -55,6 +56,7 @@
test("snippet1", 1);
}
+ @SuppressWarnings("deprecation")
public static void snippet2(int i) {
Integer object = new Integer(i);
GraalDirectives.ensureVirtualized(object);
@@ -66,6 +68,7 @@
test("snippet2", 1);
}
+ @SuppressWarnings("deprecation")
public static void snippet3(int i) {
Integer object = new Integer(i);
field = object;
@@ -77,6 +80,7 @@
test("snippet3", 1);
}
+ @SuppressWarnings("deprecation")
public static void snippetHere1(int i) {
Integer object = new Integer(i);
GraalDirectives.ensureVirtualizedHere(object);
@@ -87,6 +91,7 @@
test("snippetHere1", 1);
}
+ @SuppressWarnings("deprecation")
public static void snippetHere2(int i) {
Integer object = new Integer(i);
GraalDirectives.ensureVirtualizedHere(object);
@@ -98,6 +103,7 @@
test("snippetHere2", 1);
}
+ @SuppressWarnings("deprecation")
public static void snippetHere3(int i) {
Integer object = new Integer(i);
field = object;
@@ -130,6 +136,7 @@
test("snippetBoxing2", 1);
}
+ @SuppressWarnings("deprecation")
public static void snippetControlFlow1(boolean b, int i) {
Integer object = new Integer(i);
if (b) {
@@ -144,6 +151,7 @@
test("snippetControlFlow1", true, 1);
}
+ @SuppressWarnings("deprecation")
public static void snippetControlFlow2(boolean b, int i) {
Integer object = new Integer(i);
if (b) {
@@ -160,6 +168,7 @@
test("snippetControlFlow2", true, 1);
}
+ @SuppressWarnings("deprecation")
public static void snippetControlFlow3(boolean b, int i) {
Integer object = new Integer(i);
GraalDirectives.ensureVirtualized(object);
@@ -177,6 +186,7 @@
test("snippetControlFlow3", true, 1);
}
+ @SuppressWarnings("deprecation")
public static void snippetControlFlow4(boolean b, int i) {
Integer object = new Integer(i);
if (b) {
@@ -192,6 +202,7 @@
test("snippetControlFlow4", true, 1);
}
+ @SuppressWarnings("deprecation")
public static void snippetControlFlow5(boolean b, int i) {
Integer object = new Integer(i);
if (b) {
@@ -212,6 +223,7 @@
Object b;
}
+ @SuppressWarnings("deprecation")
public static void snippetIndirect1(boolean b, int i) {
Integer object = new Integer(i);
TestClass t = new TestClass();
@@ -230,6 +242,7 @@
test("snippetIndirect1", true, 1);
}
+ @SuppressWarnings("deprecation")
public static void snippetIndirect2(boolean b, int i) {
Integer object = new Integer(i);
TestClass t = new TestClass();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PartialEscapeAnalysisIterationTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.core.test.ea;
+
+import java.lang.ref.WeakReference;
+import java.util.List;
+
+import org.graalvm.compiler.nodes.extended.BoxNode;
+import org.graalvm.compiler.nodes.extended.UnboxNode;
+import org.graalvm.compiler.nodes.java.StoreFieldNode;
+import org.graalvm.compiler.nodes.virtual.CommitAllocationNode;
+import org.graalvm.compiler.phases.common.CanonicalizerPhase;
+import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class PartialEscapeAnalysisIterationTest extends EATestBase {
+
+ // remember boxing nodes from before PEA
+ private List<BoxNode> boxNodes;
+
+ @Override
+ protected void canonicalizeGraph() {
+ super.canonicalizeGraph();
+ boxNodes = graph.getNodes().filter(BoxNode.class).snapshot();
+ }
+
+ private static final class AllocatedObject {
+ private int value;
+
+ AllocatedObject(int value) {
+ this.value = value;
+ }
+
+ AllocatedObject() {
+ // empty
+ }
+ }
+
+ public static volatile Object obj1;
+ public static volatile Double object1 = (double) 123;
+ public static volatile AllocatedObject object2 = new AllocatedObject(123);
+
+ public static String moveIntoBranchBox(int id) {
+ Double box = object1 + 1;
+ if (id == 0) {
+ obj1 = new WeakReference<>(box);
+ }
+ return "value";
+ }
+
+ public static String moveIntoBranch(int id) {
+ AllocatedObject box = new AllocatedObject(object2.value + 1);
+ if (id == 0) {
+ obj1 = new WeakReference<>(box);
+ }
+ return "value";
+ }
+
+ @Test
+ public void testJMHBlackholePattern() {
+ /*
+ * The overall number of allocations in this methods does not change during PEA, but the
+ * effects still need to be applied since they move the allocation between blocks.
+ */
+
+ // test with a boxing object
+ prepareGraph("moveIntoBranchBox", false);
+ Assert.assertEquals(1, graph.getNodes().filter(UnboxNode.class).count());
+ Assert.assertEquals(1, graph.getNodes().filter(BoxNode.class).count());
+ // the boxing needs to be moved into the branch
+ Assert.assertTrue(graph.getNodes().filter(BoxNode.class).first().next() instanceof StoreFieldNode);
+
+ // test with a normal object
+ prepareGraph("moveIntoBranch", false);
+ Assert.assertEquals(1, graph.getNodes().filter(CommitAllocationNode.class).count());
+ // the allocation needs to be moved into the branch
+ Assert.assertTrue(graph.getNodes().filter(CommitAllocationNode.class).first().next() instanceof StoreFieldNode);
+ }
+
+ public static String noLoopIterationBox(int id) {
+ Double box = object1 + 1;
+ for (int i = 0; i < 100; i++) {
+ if (id == i) {
+ obj1 = new WeakReference<>(box);
+ }
+ }
+ return "value";
+ }
+
+ public static String noLoopIteration(int id) {
+ AllocatedObject box = new AllocatedObject(object2.value + 1);
+ for (int i = 0; i < 100; i++) {
+ if (id == i) {
+ obj1 = new WeakReference<>(box);
+ }
+ }
+ return "value";
+ }
+
+ public static String noLoopIterationEmpty(int id) {
+ AllocatedObject box = new AllocatedObject();
+ for (int i = 0; i < 100; i++) {
+ if (id == i) {
+ obj1 = new WeakReference<>(box);
+ }
+ }
+ return "value";
+ }
+
+ @Test
+ public void testNoLoopIteration() {
+ /*
+ * PEA should not apply any effects on this method, since it cannot move the allocation into
+ * the branch anyway (it needs to stay outside the loop).
+ */
+
+ // test with a boxing object
+ prepareGraph("noLoopIterationBox", true);
+ Assert.assertEquals(1, boxNodes.size());
+ Assert.assertTrue(boxNodes.get(0).isAlive());
+
+ // test with a normal object (needs one iteration to replace NewInstance with
+ // CommitAllocation)
+ for (String name : new String[]{"noLoopIterationEmpty", "noLoopIteration"}) {
+ prepareGraph(name, false);
+ List<CommitAllocationNode> allocations = graph.getNodes().filter(CommitAllocationNode.class).snapshot();
+ new PartialEscapePhase(true, false, new CanonicalizerPhase(), null, graph.getOptions()).apply(graph, context);
+ Assert.assertEquals(1, allocations.size());
+ Assert.assertTrue(allocations.get(0).isAlive());
+ }
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PartialEscapeAnalysisTest.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PartialEscapeAnalysisTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -118,6 +118,7 @@
testPartialEscapeAnalysis("test3Snippet", 0.5, 1, StoreFieldNode.class, LoadFieldNode.class);
}
+ @SuppressWarnings("deprecation")
public static Object test3Snippet(int a) {
if (a < 0) {
TestObject obj = new TestObject(1, 2);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/InliningTest.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/InliningTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -480,7 +480,7 @@
private static final class StaticFinalFields {
- private static final Number NumberStaticFinalField = new Integer(1);
+ private static final Number NumberStaticFinalField = Integer.valueOf(1);
private static final SuperClass SuperClassStaticFinalField = new SubClassA(2);
private static final FinalSubClass FinalSubClassStaticFinalField = new FinalSubClass(3);
private static final SingleImplementorInterface SingleImplementorStaticFinalField = new SubClassA(4);
@@ -492,7 +492,7 @@
private static final class FinalFields {
- private final Number numberFinalField = new Integer(1);
+ private final Number numberFinalField = Integer.valueOf(1);
private final SuperClass superClassFinalField = new SubClassA(2);
private final FinalSubClass finalSubClassFinalField = new FinalSubClass(3);
private final SingleImplementorInterface singleImplementorFinalField = new SubClassA(4);
@@ -504,7 +504,7 @@
private static final class Fields {
- private Number numberField = new Integer(1);
+ private Number numberField = Integer.valueOf(1);
private SuperClass superClassField = new SubClassA(2);
private FinalSubClass finalSubClassField = new FinalSubClass(3);
private SingleImplementorInterface singleImplementorField = new SubClassA(4);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/NestedLoopEffectsPhaseComplexityTest.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/NestedLoopEffectsPhaseComplexityTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,10 @@
import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.graalvm.compiler.virtual.phases.ea.EarlyReadEliminationPhase;
import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase;
+
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.TestRule;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import sun.misc.Unsafe;
@@ -57,7 +60,8 @@
public static int[] Memory = new int[]{0};
public static void recursiveLoopMethodUnsafeLoad(int a) {
- if (UNSAFE.getInt(Memory, (long) Unsafe.ARRAY_INT_BASE_OFFSET) == 0) {
+ long arrayIntBaseOffset = Unsafe.ARRAY_INT_BASE_OFFSET;
+ if (UNSAFE.getInt(Memory, arrayIntBaseOffset) == 0) {
return;
}
for (int i = 0; i < a; i++) {
@@ -87,17 +91,19 @@
private static int InliningCountLowerBound = 1;
private static int InliningCountUpperBound = 32;
- @Test(timeout = 120_000)
+ @Rule public TestRule timeout = createTimeoutSeconds(120);
+
+ @Test
public void inlineDirectRecursiveLoopCallUnsafeLoad() {
testAndTime("recursiveLoopMethodUnsafeLoad");
}
- @Test(timeout = 120_000)
+ @Test
public void inlineDirectRecursiveLoopCallFieldLoad() {
testAndTime("recursiveLoopMethodFieldLoad");
}
- @Test(timeout = 120_000)
+ @Test
public void inlineDirectRecursiveLoopCallNoReads() {
testAndTime("recursiveLoopMethod");
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/StaticAnalysisTests.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/StaticAnalysisTests.java Thu Aug 23 11:09:16 2018 -0400
@@ -120,6 +120,7 @@
assertEquals(m(sa, B.class, "foo").getFormalReturn(), t(Data.class));
}
+ @SuppressWarnings("deprecation")
static void test03Entry() {
Data data = new Data();
data.f = new Integer(42);
@@ -147,6 +148,7 @@
assertEquals(m(sa, B.class, "foo").getFormalReturn(), t(Data.class), t(Integer.class));
}
+ @SuppressWarnings("deprecation")
static void test04Entry() {
Data data = null;
for (int i = 0; i < 2; i++) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilationWrapper.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilationWrapper.java Thu Aug 23 11:09:16 2018 -0400
@@ -84,6 +84,8 @@
*/
ExitVM;
+ private static final ExceptionAction[] VALUES = values();
+
/**
* Gets the action that is one level less verbose than this action, bottoming out at the
* least verbose action.
@@ -91,7 +93,7 @@
ExceptionAction quieter() {
assert ExceptionAction.Silent.ordinal() == 0;
int index = Math.max(ordinal() - 1, 0);
- return values()[index];
+ return VALUES[index];
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java Thu Aug 23 11:09:16 2018 -0400
@@ -71,7 +71,6 @@
import org.graalvm.compiler.nodes.AbstractBeginNode;
import org.graalvm.compiler.nodes.AbstractEndNode;
import org.graalvm.compiler.nodes.AbstractMergeNode;
-import org.graalvm.compiler.nodes.ConstantNode;
import org.graalvm.compiler.nodes.DeoptimizingNode;
import org.graalvm.compiler.nodes.DirectCallTargetNode;
import org.graalvm.compiler.nodes.FixedNode;
@@ -284,13 +283,6 @@
return values.toArray(new Value[values.size()]);
}
- /**
- * @return {@code true} if object constant to stack moves are supported.
- */
- protected boolean allowObjectConstantToStackMove() {
- return true;
- }
-
private Value[] createPhiOut(AbstractMergeNode merge, AbstractEndNode pred) {
List<Value> values = new ArrayList<>();
for (PhiNode phi : merge.valuePhis()) {
@@ -303,7 +295,7 @@
* new Variable.
*/
value = gen.emitMove(value);
- } else if (!allowObjectConstantToStackMove() && node instanceof ConstantNode && !LIRKind.isValue(value)) {
+ } else if (node.isConstant() && !gen.getSpillMoveFactory().allowConstantToStackMove(node.asConstant()) && !LIRKind.isValue(value)) {
/*
* Some constants are not allowed as inputs for PHIs in certain backends. Explicitly
* create a copy of this value to force it into a register. The new variable is only
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TimerKeyImpl.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TimerKeyImpl.java Thu Aug 23 11:09:16 2018 -0400
@@ -109,7 +109,7 @@
return TimeUnit.NANOSECONDS;
}
- final class Timer extends CloseableCounter implements DebugCloseable {
+ static final class Timer extends CloseableCounter implements DebugCloseable {
final DebugContext debug;
Timer(AccumulatedKey counter, DebugContext debug) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/graphio/GraphSnippetTest.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/graphio/GraphSnippetTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -31,6 +31,7 @@
import org.junit.Test;
public class GraphSnippetTest {
+ @SuppressWarnings("deprecation")
@Test
public void dumpTheFile() throws Exception {
Class<?> snippets = null;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java Thu Aug 23 11:09:16 2018 -0400
@@ -1216,7 +1216,8 @@
// More strict node-type-specific check
if (performConsistencyCheck) {
- node.verifySourcePosition();
+ // Disabled due to GR-10445.
+ // node.verifySourcePosition();
}
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2018, 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
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotDeoptimizeCallerOp.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotDeoptimizeCallerOp.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotEpilogueOp.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotEpilogueOp.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotForeignCallsProvider.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotForeignCallsProvider.java Thu Aug 23 11:09:16 2018 -0400
@@ -29,6 +29,7 @@
import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.NativeCall;
import static jdk.vm.ci.meta.Value.ILLEGAL;
import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.JUMP_ADDRESS;
+import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Reexecutability.REEXECUTABLE_ONLY_AFTER_EXCEPTION;
import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS;
import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF;
import static org.graalvm.compiler.hotspot.replacements.CRC32CSubstitutions.UPDATE_BYTES_CRC32C;
@@ -75,15 +76,15 @@
RegisterValue exception = r0.asValue(LIRKind.reference(word));
RegisterValue exceptionPc = r3.asValue(LIRKind.value(word));
CallingConvention exceptionCc = new CallingConvention(0, ILLEGAL, exception, exceptionPc);
- register(new HotSpotForeignCallLinkageImpl(HotSpotBackend.EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF, exceptionCc, null, NOT_REEXECUTABLE, any()));
- register(new HotSpotForeignCallLinkageImpl(HotSpotBackend.EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF, exceptionCc, null, NOT_REEXECUTABLE, any()));
+ register(new HotSpotForeignCallLinkageImpl(HotSpotBackend.EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF, REEXECUTABLE_ONLY_AFTER_EXCEPTION, exceptionCc, null, any()));
+ register(new HotSpotForeignCallLinkageImpl(HotSpotBackend.EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF, REEXECUTABLE_ONLY_AFTER_EXCEPTION, exceptionCc, null, any()));
// These stubs do callee saving
if (config.useCRC32Intrinsics) {
- registerForeignCall(UPDATE_BYTES_CRC32, config.updateBytesCRC32Stub, NativeCall, PRESERVES_REGISTERS, LEAF, NOT_REEXECUTABLE, any());
+ registerForeignCall(UPDATE_BYTES_CRC32, config.updateBytesCRC32Stub, NativeCall, PRESERVES_REGISTERS, LEAF, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any());
}
if (config.useCRC32CIntrinsics) {
- registerForeignCall(UPDATE_BYTES_CRC32C, config.updateBytesCRC32C, NativeCall, PRESERVES_REGISTERS, LEAF, NOT_REEXECUTABLE, any());
+ registerForeignCall(UPDATE_BYTES_CRC32C, config.updateBytesCRC32C, NativeCall, PRESERVES_REGISTERS, LEAF, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any());
}
super.initialize(providers, options);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotJumpToExceptionHandlerInCallerOp.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotJumpToExceptionHandlerInCallerOp.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotReturnOp.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotReturnOp.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotUnwindOp.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotUnwindOp.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2018, 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
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/CompressedNullCheckTest.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/CompressedNullCheckTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -76,7 +76,7 @@
@Test
public void implicit() {
- testImplicit(new Integer(1));
+ testImplicit(Integer.valueOf(1));
}
@Test
@@ -86,7 +86,7 @@
@Test
public void explicit() {
- testExplicit(new Integer(1));
+ testExplicit(Integer.valueOf(1));
}
@Test
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/StubAVXTest.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/StubAVXTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -225,7 +225,7 @@
public void test() {
HotSpotProviders providers = (HotSpotProviders) getProviders();
HotSpotForeignCallsProviderImpl foreignCalls = (HotSpotForeignCallsProviderImpl) providers.getForeignCalls();
- HotSpotForeignCallLinkage linkage = foreignCalls.registerStubCall(TEST_STUB, true, HotSpotForeignCallLinkage.Transition.LEAF_NOFP);
+ HotSpotForeignCallLinkage linkage = foreignCalls.registerStubCall(TEST_STUB, HotSpotForeignCallLinkage.Transition.LEAF_NOFP, HotSpotForeignCallLinkage.Reexecutability.REEXECUTABLE);
linkage.setCompiledStub(new TestStub(getInitialOptions(), providers, linkage));
runTest("testStub");
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2018, 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
@@ -32,14 +32,12 @@
import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
import static org.graalvm.compiler.core.common.GraalOptions.ZapStackOnMethodEntry;
-import jdk.vm.ci.amd64.AMD64.CPUFeature;
import jdk.internal.vm.compiler.collections.EconomicSet;
import org.graalvm.compiler.asm.Assembler;
import org.graalvm.compiler.asm.Label;
import org.graalvm.compiler.asm.amd64.AMD64Address;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag;
import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
-import org.graalvm.compiler.asm.amd64.AMD64VectorAssembler;
import org.graalvm.compiler.code.CompilationResult;
import org.graalvm.compiler.core.amd64.AMD64NodeMatchRules;
import org.graalvm.compiler.core.common.CompilationIdentifier;
@@ -199,11 +197,7 @@
@Override
protected Assembler createAssembler(FrameMap frameMap) {
- if (((AMD64) getTarget().arch).getFeatures().contains(CPUFeature.AVX)) {
- return new AMD64VectorAssembler(getTarget());
- } else {
- return new AMD64MacroAssembler(getTarget());
- }
+ return new AMD64MacroAssembler(getTarget());
}
@Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java Thu Aug 23 11:09:16 2018 -0400
@@ -31,6 +31,8 @@
import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER;
import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER_IN_CALLER;
import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.JUMP_ADDRESS;
+import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Reexecutability.REEXECUTABLE;
+import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Reexecutability.REEXECUTABLE_ONLY_AFTER_EXCEPTION;
import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS;
import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF;
import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF_NOFP;
@@ -87,23 +89,23 @@
RegisterValue exception = rax.asValue(LIRKind.reference(word));
RegisterValue exceptionPc = rdx.asValue(LIRKind.value(word));
CallingConvention exceptionCc = new CallingConvention(0, ILLEGAL, exception, exceptionPc);
- register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF_NOFP, exceptionCc, null, NOT_REEXECUTABLE, any()));
- register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF_NOFP, exceptionCc, null, NOT_REEXECUTABLE, any()));
+ register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, exceptionCc, null, any()));
+ register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, exceptionCc, null, any()));
- link(new AMD64MathStub(ARITHMETIC_LOG_STUB, options, providers, registerStubCall(ARITHMETIC_LOG_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS)));
- link(new AMD64MathStub(ARITHMETIC_LOG10_STUB, options, providers, registerStubCall(ARITHMETIC_LOG10_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS)));
- link(new AMD64MathStub(ARITHMETIC_SIN_STUB, options, providers, registerStubCall(ARITHMETIC_SIN_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS)));
- link(new AMD64MathStub(ARITHMETIC_COS_STUB, options, providers, registerStubCall(ARITHMETIC_COS_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS)));
- link(new AMD64MathStub(ARITHMETIC_TAN_STUB, options, providers, registerStubCall(ARITHMETIC_TAN_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS)));
- link(new AMD64MathStub(ARITHMETIC_EXP_STUB, options, providers, registerStubCall(ARITHMETIC_EXP_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS)));
- link(new AMD64MathStub(ARITHMETIC_POW_STUB, options, providers, registerStubCall(ARITHMETIC_POW_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS)));
+ link(new AMD64MathStub(ARITHMETIC_LOG_STUB, options, providers, registerStubCall(ARITHMETIC_LOG_STUB, LEAF, REEXECUTABLE, NO_LOCATIONS)));
+ link(new AMD64MathStub(ARITHMETIC_LOG10_STUB, options, providers, registerStubCall(ARITHMETIC_LOG10_STUB, LEAF, REEXECUTABLE, NO_LOCATIONS)));
+ link(new AMD64MathStub(ARITHMETIC_SIN_STUB, options, providers, registerStubCall(ARITHMETIC_SIN_STUB, LEAF, REEXECUTABLE, NO_LOCATIONS)));
+ link(new AMD64MathStub(ARITHMETIC_COS_STUB, options, providers, registerStubCall(ARITHMETIC_COS_STUB, LEAF, REEXECUTABLE, NO_LOCATIONS)));
+ link(new AMD64MathStub(ARITHMETIC_TAN_STUB, options, providers, registerStubCall(ARITHMETIC_TAN_STUB, LEAF, REEXECUTABLE, NO_LOCATIONS)));
+ link(new AMD64MathStub(ARITHMETIC_EXP_STUB, options, providers, registerStubCall(ARITHMETIC_EXP_STUB, LEAF, REEXECUTABLE, NO_LOCATIONS)));
+ link(new AMD64MathStub(ARITHMETIC_POW_STUB, options, providers, registerStubCall(ARITHMETIC_POW_STUB, LEAF, REEXECUTABLE, NO_LOCATIONS)));
if (config.useCRC32Intrinsics) {
// This stub does callee saving
- registerForeignCall(UPDATE_BYTES_CRC32, config.updateBytesCRC32Stub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, any());
+ registerForeignCall(UPDATE_BYTES_CRC32, config.updateBytesCRC32Stub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any());
}
if (config.useCRC32CIntrinsics) {
- registerForeignCall(UPDATE_BYTES_CRC32C, config.updateBytesCRC32C, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, any());
+ registerForeignCall(UPDATE_BYTES_CRC32C, config.updateBytesCRC32C, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any());
}
super.initialize(providers, options);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackend.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackend.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2018, 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
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java Thu Aug 23 11:09:16 2018 -0400
@@ -33,6 +33,7 @@
import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER;
import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER_IN_CALLER;
import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.JUMP_ADDRESS;
+import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Reexecutability.REEXECUTABLE_ONLY_AFTER_EXCEPTION;
import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS;
import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF_NOFP;
import static org.graalvm.compiler.hotspot.replacements.CRC32CSubstitutions.UPDATE_BYTES_CRC32C;
@@ -83,15 +84,16 @@
RegisterValue incomingExceptionPc = i1.asValue(LIRKind.value(word));
CallingConvention outgoingExceptionCc = new CallingConvention(0, ILLEGAL, outgoingException, outgoingExceptionPc);
CallingConvention incomingExceptionCc = new CallingConvention(0, ILLEGAL, incomingException, incomingExceptionPc);
- register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF_NOFP, outgoingExceptionCc, incomingExceptionCc, NOT_REEXECUTABLE, any()));
- register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF_NOFP, outgoingExceptionCc, incomingExceptionCc, NOT_REEXECUTABLE, any()));
+ register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, outgoingExceptionCc, incomingExceptionCc, any()));
+ register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, outgoingExceptionCc,
+ incomingExceptionCc, any()));
if (config.useCRC32Intrinsics) {
// This stub does callee saving
- registerForeignCall(UPDATE_BYTES_CRC32, config.updateBytesCRC32Stub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, any());
+ registerForeignCall(UPDATE_BYTES_CRC32, config.updateBytesCRC32Stub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any());
}
if (config.useCRC32CIntrinsics) {
- registerForeignCall(UPDATE_BYTES_CRC32C, config.updateBytesCRC32C, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, any());
+ registerForeignCall(UPDATE_BYTES_CRC32C, config.updateBytesCRC32C, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any());
}
super.initialize(providers, options);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotLIRGenerator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotLIRGenerator.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotReturnOp.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotReturnOp.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ArrayCopyIntrinsificationTest.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ArrayCopyIntrinsificationTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -274,7 +274,7 @@
@Test
public void testCopyRows() {
Object[][] rows = {{"a1", "a2", "a3", "a4"}, {"b1", "b2", "b3", "b4"}, {"c1", "c2", "c3", "c4"}};
- test("copyRows", rows, 4, new Integer(rows.length));
+ test("copyRows", rows, 4, Integer.valueOf(rows.length));
}
public static Object[][] copyRows(Object[][] rows, int rowSize, Integer rowCount) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java Thu Aug 23 11:09:16 2018 -0400
@@ -343,14 +343,11 @@
add(toBeInvestigated,
"java/lang/StringCoding.hasNegatives([BII)Z",
"java/lang/StringCoding.implEncodeISOArray([BI[BII)I",
- "java/lang/StringLatin1.equals([B[B)Z",
- "java/lang/StringLatin1.indexOf([BI[BII)I",
"java/lang/StringLatin1.indexOf([B[B)I",
"java/lang/StringLatin1.inflate([BI[BII)V",
"java/lang/StringLatin1.inflate([BI[CII)V",
"java/lang/StringUTF16.compress([BI[BII)I",
"java/lang/StringUTF16.compress([CI[BII)I",
- "java/lang/StringUTF16.equals([B[B)Z",
"java/lang/StringUTF16.getChar([BI)C",
"java/lang/StringUTF16.getChars([BII[CI)V",
"java/lang/StringUTF16.indexOf([BI[BII)I",
@@ -360,6 +357,10 @@
"java/lang/StringUTF16.indexOfLatin1([B[B)I",
"java/lang/StringUTF16.putChar([BII)V",
"java/lang/StringUTF16.toBytes([CII)[B");
+ // These are handled through an intrinsic for String.equals itself
+ add(ignore,
+ "java/lang/StringLatin1.equals([B[B)Z",
+ "java/lang/StringUTF16.equals([B[B)Z");
}
if (isJDK10OrHigher()) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotMethodSubstitutionTest.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotMethodSubstitutionTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -231,7 +231,7 @@
*/
@Test
public void testCast() {
- test("testCastSnippet", 1, new Integer(1));
+ test("testCastSnippet", 1, Integer.valueOf(1));
}
/**
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotStackIntrospectionTest.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotStackIntrospectionTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,7 +28,9 @@
import org.graalvm.compiler.test.GraalTest;
import org.junit.Assume;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.TestRule;
import jdk.vm.ci.code.InstalledCode;
import jdk.vm.ci.code.InvalidInstalledCodeException;
@@ -44,6 +46,8 @@
*/
public class HotSpotStackIntrospectionTest extends HotSpotGraalCompilerTest {
+ @Rule public TestRule timeout = createTimeoutSeconds(20);
+
static StackIntrospection stackIntrospection = HotSpotJVMCIRuntime.runtime().getHostJVMCIBackend().getStackIntrospection();
static volatile int v;
@@ -74,14 +78,14 @@
return a;
}
- @Test(timeout = 20000)
+ @Test
public void run() throws InvalidInstalledCodeException {
// The JDK9 bits are currently broken
Assume.assumeTrue(GraalTest.Java8OrEarlier);
test("testSnippet");
}
- @Test(timeout = 20000)
+ @Test
public void runSynchronized() throws InvalidInstalledCodeException {
// The JDK9 bits are currently broken
Assume.assumeTrue(GraalTest.Java8OrEarlier);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierAdditionTest.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierAdditionTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -177,7 +177,7 @@
*/
@Test
public void test6() throws Exception {
- test2("testUnsafeLoad", UNSAFE, wr, new Long(referentOffset), null);
+ test2("testUnsafeLoad", UNSAFE, wr, Long.valueOf(referentOffset), null);
}
/**
@@ -186,7 +186,7 @@
*/
@Test
public void test7() throws Exception {
- test2("testUnsafeLoad", UNSAFE, con, new Long(referentOffset), null);
+ test2("testUnsafeLoad", UNSAFE, con, Long.valueOf(referentOffset), null);
}
/**
@@ -196,7 +196,7 @@
*/
@Test
public void test8() throws Exception {
- test2("testUnsafeLoad", UNSAFE, wr, new Long(config.useCompressedOops ? 20 : 32), null);
+ test2("testUnsafeLoad", UNSAFE, wr, Long.valueOf(config.useCompressedOops ? 20 : 32), null);
}
/**
@@ -206,7 +206,7 @@
*/
@Test
public void test10() throws Exception {
- test2("testUnsafeLoad", UNSAFE, wr, new Long(config.useCompressedOops ? 6 : 8), new Integer(config.useCompressedOops ? 6 : 8));
+ test2("testUnsafeLoad", UNSAFE, wr, Long.valueOf(config.useCompressedOops ? 6 : 8), Integer.valueOf(config.useCompressedOops ? 6 : 8));
}
/**
@@ -216,7 +216,7 @@
*/
@Test
public void test9() throws Exception {
- test2("testUnsafeLoad", UNSAFE, wr, new Long(config.useCompressedOops ? 10 : 16), new Integer(config.useCompressedOops ? 10 : 16));
+ test2("testUnsafeLoad", UNSAFE, wr, Long.valueOf(config.useCompressedOops ? 10 : 16), Integer.valueOf(config.useCompressedOops ? 10 : 16));
}
static Object[] src = new Object[1];
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java Thu Aug 23 11:09:16 2018 -0400
@@ -34,6 +34,7 @@
import java.util.stream.Collectors;
import jdk.internal.vm.compiler.collections.EconomicMap;
+import org.graalvm.compiler.core.common.SuppressFBWarnings;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.debug.TTY;
import org.graalvm.compiler.lir.phases.LIRPhase;
@@ -168,6 +169,7 @@
/**
* @return sorted list of {@link CompilerConfigurationFactory}s
*/
+ @SuppressFBWarnings(value = "DLS_DEAD_LOCAL_STORE", justification = "false positive on dead store to `candidates`")
private static List<CompilerConfigurationFactory> getAllCandidates() {
List<CompilerConfigurationFactory> candidates = new ArrayList<>();
for (CompilerConfigurationFactory candidate : GraalServices.load(CompilerConfigurationFactory.class)) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java Thu Aug 23 11:09:16 2018 -0400
@@ -575,8 +575,6 @@
public final boolean tlabStats = getFlag("TLABStats", Boolean.class);
- public final boolean useFastTLABRefill = versioned.useFastTLABRefill;
-
// FIXME This is only temporary until the GC code is changed.
public final boolean inlineContiguousAllocationSupported = getFieldValue("CompilerToVM::Data::_supports_inline_contig_alloc", Boolean.class);
public final long heapEndAddress = getFieldValue("CompilerToVM::Data::_heap_end_addr", Long.class, "HeapWord**");
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfigBase.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfigBase.java Thu Aug 23 11:09:16 2018 -0400
@@ -24,6 +24,9 @@
package org.graalvm.compiler.hotspot;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+
import org.graalvm.compiler.api.replacements.Fold;
import org.graalvm.compiler.api.replacements.Fold.InjectedParameter;
@@ -41,6 +44,20 @@
super(store);
assert this instanceof GraalHotSpotVMConfig;
versioned = new GraalHotSpotVMConfigVersioned(store);
+ assert checkVersioned();
+ }
+
+ private boolean checkVersioned() {
+ Class<? extends GraalHotSpotVMConfigVersioned> c = versioned.getClass();
+ for (Field field : c.getDeclaredFields()) {
+ int modifiers = field.getModifiers();
+ if (!Modifier.isStatic(modifiers)) {
+ // javac inlines non-static final fields which means
+ // versioned values are ignored in non-flattened Graal
+ assert !Modifier.isFinal(modifiers) : "Non-static field in " + c.getName() + " must not be final: " + field.getName();
+ }
+ }
+ return true;
}
/**
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfigVersioned.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfigVersioned.java Thu Aug 23 11:09:16 2018 -0400
@@ -48,45 +48,42 @@
}
// JSK-8132287
- final boolean inlineNotify = initInlineNotify();
+ boolean inlineNotify = initInlineNotify();
// JDK-8073583
- final boolean useCRC32CIntrinsics = getFlag("UseCRC32CIntrinsics", Boolean.class);
+ boolean useCRC32CIntrinsics = getFlag("UseCRC32CIntrinsics", Boolean.class);
// JDK-8046936
- final int javaThreadReservedStackActivationOffset = getFieldOffset("JavaThread::_reserved_stack_activation", Integer.class, "address");
- final int methodFlagsOffset = getFieldOffset("Method::_flags", Integer.class, "u2");
- final long throwDelayedStackOverflowErrorEntry = getFieldValue("StubRoutines::_throw_delayed_StackOverflowError_entry", Long.class, "address");
- final long enableStackReservedZoneAddress = getAddress("SharedRuntime::enable_stack_reserved_zone");
+ int javaThreadReservedStackActivationOffset = getFieldOffset("JavaThread::_reserved_stack_activation", Integer.class, "address");
+ int methodFlagsOffset = getFieldOffset("Method::_flags", Integer.class, "u2");
+ long throwDelayedStackOverflowErrorEntry = getFieldValue("StubRoutines::_throw_delayed_StackOverflowError_entry", Long.class, "address");
+ long enableStackReservedZoneAddress = getAddress("SharedRuntime::enable_stack_reserved_zone");
// JDK-8135085
- final int methodIntrinsicIdOffset = getFieldOffset("Method::_intrinsic_id", Integer.class, "u2");
+ int methodIntrinsicIdOffset = getFieldOffset("Method::_intrinsic_id", Integer.class, "u2");
// JDK-8151956
- final int methodCodeOffset = getFieldOffset("Method::_code", Integer.class, "CompiledMethod*");
+ int methodCodeOffset = getFieldOffset("Method::_code", Integer.class, "CompiledMethod*");
// JDK-8059606
- final int invocationCounterIncrement = getConstant("InvocationCounter::count_increment", Integer.class);
- final int invocationCounterShift = getConstant("InvocationCounter::count_shift", Integer.class);
+ int invocationCounterIncrement = getConstant("InvocationCounter::count_increment", Integer.class);
+ int invocationCounterShift = getConstant("InvocationCounter::count_shift", Integer.class);
// JDK-8195142
- final byte dirtyCardValue = getConstant("CardTable::dirty_card", Byte.class);
- final byte g1YoungCardValue = getConstant("G1CardTable::g1_young_gen", Byte.class);
+ byte dirtyCardValue = getConstant("CardTable::dirty_card", Byte.class);
+ byte g1YoungCardValue = getConstant("G1CardTable::g1_young_gen", Byte.class);
// JDK-8201318
- final int g1SATBQueueMarkingOffset = getConstant("G1ThreadLocalData::satb_mark_queue_active_offset", Integer.class);
- final int g1SATBQueueIndexOffset = getConstant("G1ThreadLocalData::satb_mark_queue_index_offset", Integer.class);
- final int g1SATBQueueBufferOffset = getConstant("G1ThreadLocalData::satb_mark_queue_buffer_offset", Integer.class);
- final int g1CardQueueIndexOffset = getConstant("G1ThreadLocalData::dirty_card_queue_index_offset", Integer.class);
- final int g1CardQueueBufferOffset = getConstant("G1ThreadLocalData::dirty_card_queue_buffer_offset", Integer.class);
+ int g1SATBQueueMarkingOffset = getConstant("G1ThreadLocalData::satb_mark_queue_active_offset", Integer.class);
+ int g1SATBQueueIndexOffset = getConstant("G1ThreadLocalData::satb_mark_queue_index_offset", Integer.class);
+ int g1SATBQueueBufferOffset = getConstant("G1ThreadLocalData::satb_mark_queue_buffer_offset", Integer.class);
+ int g1CardQueueIndexOffset = getConstant("G1ThreadLocalData::dirty_card_queue_index_offset", Integer.class);
+ int g1CardQueueBufferOffset = getConstant("G1ThreadLocalData::dirty_card_queue_buffer_offset", Integer.class);
// JDK-8033552
- final long heapTopAddress = getFieldValue("CompilerToVM::Data::_heap_top_addr", Long.class, "HeapWord* volatile*");
+ long heapTopAddress = getFieldValue("CompilerToVM::Data::_heap_top_addr", Long.class, "HeapWord* volatile*");
// JDK-8015774
- final long codeCacheLowBound = getFieldValue("CodeCache::_low_bound", Long.class, "address");
- final long codeCacheHighBound = getFieldValue("CodeCache::_high_bound", Long.class, "address");
-
- // JDK-8205105
- boolean useFastTLABRefill = false;
+ long codeCacheLowBound = getFieldValue("CodeCache::_low_bound", Long.class, "address");
+ long codeCacheHighBound = getFieldValue("CodeCache::_high_bound", Long.class, "address");
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkage.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkage.java Thu Aug 23 11:09:16 2018 -0400
@@ -83,12 +83,48 @@
}
/**
+ * Constants specifying when a foreign call or stub call is re-executable.
+ */
+ enum Reexecutability {
+ /**
+ * Denotes a call that cannot be re-executed. If an exception is raised, the call is
+ * deoptimized and the exception is passed on to be dispatched. If the call can throw an
+ * exception it needs to have a precise frame state.
+ */
+ NOT_REEXECUTABLE,
+
+ /**
+ * Denotes a call that can only be re-executed if it returns with a pending exception. This
+ * type of call models a function that may throw exceptions before any side effects happen.
+ * In this case if an exception is raised the call may be deoptimized and reexecuted. It
+ * also means that while the call has side effects and may deoptimize it doesn't necessarily
+ * need to have a precise frame state.
+ */
+ REEXECUTABLE_ONLY_AFTER_EXCEPTION,
+
+ /**
+ * Denotes a call that can always be re-executed. If an exception is raised by the call it
+ * may be cleared, compiled code deoptimized and reexecuted. Since the call has no side
+ * effects it is assumed that the same exception will be thrown.
+ */
+ REEXECUTABLE
+ }
+
+ /**
* Sentinel marker for a computed jump address.
*/
long JUMP_ADDRESS = 0xDEADDEADBEEFBEEFL;
+ /**
+ * Determines if the call has side effects.
+ */
boolean isReexecutable();
+ /**
+ * Determines if the call returning a pending exception implies it is side-effect free.
+ */
+ boolean isReexecutableOnlyAfterException();
+
LocationIdentity[] getKilledLocations();
void setCompiledStub(Stub stub);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkageImpl.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkageImpl.java Thu Aug 23 11:09:16 2018 -0400
@@ -90,7 +90,7 @@
*/
private final LocationIdentity[] killedLocations;
- private final boolean reexecutable;
+ private final Reexecutability reexecutability;
/**
* Creates a {@link HotSpotForeignCallLinkage}.
@@ -102,17 +102,18 @@
* @param outgoingCcType outgoing (caller) calling convention type
* @param incomingCcType incoming (callee) calling convention type (can be null)
* @param transition specifies if this is a {@linkplain #needsDebugInfo() leaf} call
- * @param reexecutable specifies if the call can be re-executed without (meaningful) side
+ * @param reexecutability specifies if the call can be re-executed without (meaningful) side
* effects. Deoptimization will not return to a point before a call that cannot be
* re-executed.
* @param killedLocations the memory locations killed by the call
*/
public static HotSpotForeignCallLinkage create(MetaAccessProvider metaAccess, CodeCacheProvider codeCache, WordTypes wordTypes, HotSpotForeignCallsProvider foreignCalls,
- ForeignCallDescriptor descriptor, long address, RegisterEffect effect, Type outgoingCcType, Type incomingCcType, Transition transition, boolean reexecutable,
+ ForeignCallDescriptor descriptor, long address, RegisterEffect effect, Type outgoingCcType, Type incomingCcType, Transition transition, Reexecutability reexecutability,
LocationIdentity... killedLocations) {
CallingConvention outgoingCc = createCallingConvention(metaAccess, codeCache, wordTypes, foreignCalls, descriptor, outgoingCcType);
CallingConvention incomingCc = incomingCcType == null ? null : createCallingConvention(metaAccess, codeCache, wordTypes, foreignCalls, descriptor, incomingCcType);
- HotSpotForeignCallLinkageImpl linkage = new HotSpotForeignCallLinkageImpl(descriptor, address, effect, transition, outgoingCc, incomingCc, reexecutable, killedLocations);
+ HotSpotForeignCallLinkageImpl linkage = new HotSpotForeignCallLinkageImpl(descriptor, address, effect, transition, reexecutability, outgoingCc, incomingCc,
+ killedLocations);
if (outgoingCcType == HotSpotCallingConventionType.NativeCall) {
linkage.temporaries = foreignCalls.getNativeABICallerSaveRegisters();
}
@@ -143,17 +144,17 @@
return javaType;
}
- public HotSpotForeignCallLinkageImpl(ForeignCallDescriptor descriptor, long address, RegisterEffect effect, Transition transition, CallingConvention outgoingCallingConvention,
- CallingConvention incomingCallingConvention, boolean reexecutable, LocationIdentity... killedLocations) {
+ public HotSpotForeignCallLinkageImpl(ForeignCallDescriptor descriptor, long address, RegisterEffect effect, Transition transition, Reexecutability reexecutability,
+ CallingConvention outgoingCallingConvention, CallingConvention incomingCallingConvention, LocationIdentity... killedLocations) {
super(address);
this.descriptor = descriptor;
this.address = address;
this.effect = effect;
this.transition = transition;
+ this.reexecutability = reexecutability;
assert outgoingCallingConvention != null : "only incomingCallingConvention can be null";
this.outgoingCallingConvention = outgoingCallingConvention;
this.incomingCallingConvention = incomingCallingConvention != null ? incomingCallingConvention : outgoingCallingConvention;
- this.reexecutable = reexecutable;
this.killedLocations = killedLocations;
}
@@ -174,7 +175,12 @@
@Override
public boolean isReexecutable() {
- return reexecutable;
+ return reexecutability == Reexecutability.REEXECUTABLE;
+ }
+
+ @Override
+ public boolean isReexecutableOnlyAfterException() {
+ return reexecutability == Reexecutability.REEXECUTABLE_ONLY_AFTER_EXCEPTION;
}
@Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java Thu Aug 23 11:09:16 2018 -0400
@@ -29,10 +29,6 @@
import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
import static org.graalvm.compiler.core.common.GraalOptions.HotSpotPrintInlining;
import static org.graalvm.compiler.debug.DebugContext.DEFAULT_LOG_STREAM;
-import static org.graalvm.compiler.hotspot.HotSpotGraalRuntime.HotSpotGC.CMS;
-import static org.graalvm.compiler.hotspot.HotSpotGraalRuntime.HotSpotGC.G1;
-import static org.graalvm.compiler.hotspot.HotSpotGraalRuntime.HotSpotGC.Parallel;
-import static org.graalvm.compiler.hotspot.HotSpotGraalRuntime.HotSpotGC.Serial;
import java.util.ArrayList;
import java.util.EnumMap;
@@ -135,40 +131,6 @@
private final Map<ExceptionAction, Integer> compilationProblemsPerAction;
/**
- * Constants denoting the GC algorithms available in HotSpot.
- */
- public enum HotSpotGC {
- Serial("UseSerialGC"),
- Parallel("UseParallelGC", "UseParallelOldGC", "UseParNewGC"),
- CMS("UseConcMarkSweepGC"),
- G1("UseG1GC"),
- Epsilon("UseEpsilonGC"),
- Z("UseZGC");
-
- HotSpotGC(String... flags) {
- this.flags = flags;
- }
-
- private final String[] flags;
-
- public boolean isSelected(GraalHotSpotVMConfig config) {
- for (String flag : flags) {
- final boolean notPresent = false;
- if (config.getFlag(flag, Boolean.class, notPresent)) {
- return true;
- }
- }
- return false;
- }
-
- }
-
- /**
- * Set of GCs supported by Graal.
- */
- private static final HotSpotGC[] SUPPORTED_GCS = {Serial, Parallel, CMS, G1};
-
- /**
* @param nameQualifier a qualifier to be added to this runtime's {@linkplain #getName() name}
* @param compilerConfigurationFactory factory for the compiler configuration
* {@link CompilerConfigurationFactory#selectFactory(String, OptionValues)}
@@ -187,24 +149,7 @@
}
OptionValues options = optionsRef.get();
- HotSpotGC selected = null;
- for (HotSpotGC gc : SUPPORTED_GCS) {
- if (gc.isSelected(config)) {
- selected = gc;
- break;
- }
- }
- if (selected == null) {
- for (HotSpotGC gc : HotSpotGC.values()) {
- if (gc.isSelected(config)) {
- selected = gc;
- break;
- }
- }
- String unsupportedGC = selected != null ? selected.name() : "<unknown>";
- throw new GraalError(unsupportedGC + " garbage collector is not supported by Graal");
- }
- garbageCollector = selected;
+ garbageCollector = getSelectedGC();
outputDirectory = new DiagnosticsOutputDirectory(options);
compilationProblemsPerAction = new EnumMap<>(ExceptionAction.class);
@@ -265,6 +210,54 @@
bootstrapJVMCI = config.getFlag("BootstrapJVMCI", Boolean.class);
}
+ /**
+ * Constants denoting the GC algorithms available in HotSpot.
+ */
+ public enum HotSpotGC {
+ // Supported GCs
+ Serial(true, "UseSerialGC"),
+ Parallel(true, "UseParallelGC", "UseParallelOldGC", "UseParNewGC"),
+ CMS(true, "UseConcMarkSweepGC"),
+ G1(true, "UseG1GC"),
+
+ // Unsupported GCs
+ Epsilon(false, "UseEpsilonGC"),
+ Z(false, "UseZGC");
+
+ HotSpotGC(boolean supported, String... flags) {
+ this.supported = supported;
+ this.flags = flags;
+ }
+
+ final boolean supported;
+ private final String[] flags;
+
+ public boolean isSelected(GraalHotSpotVMConfig config) {
+ for (String flag : flags) {
+ final boolean notPresent = false;
+ if (config.getFlag(flag, Boolean.class, notPresent)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ }
+
+ private HotSpotGC getSelectedGC() throws GraalError {
+ for (HotSpotGC gc : HotSpotGC.values()) {
+ if (gc.isSelected(config)) {
+ if (!gc.supported) {
+ throw new GraalError(gc.name() + " garbage collector is not supported by Graal");
+ }
+ return gc;
+ }
+ }
+ // As of JDK 9, exactly one GC flag is guaranteed to be selected.
+ // On JDK 8, the default GC is Serial when no GC flag is true.
+ return HotSpotGC.Serial;
+ }
+
private HotSpotBackend registerBackend(HotSpotBackend backend) {
Class<? extends Architecture> arch = backend.getTarget().arch.getClass();
HotSpotBackend oldValue = backends.put(arch, backend);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotHostBackend.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotHostBackend.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerationResult.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerationResult.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2018, 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
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java Thu Aug 23 11:09:16 2018 -0400
@@ -39,7 +39,7 @@
class JVMCIVersionCheck {
private static final int JVMCI8_MIN_MAJOR_VERSION = 0;
- private static final int JVMCI8_MIN_MINOR_VERSION = 29;
+ private static final int JVMCI8_MIN_MINOR_VERSION = 46;
private static void failVersionCheck(boolean exit, String reason, Object... args) {
Formatter errorMessage = new Formatter().format(reason, args);
@@ -52,7 +52,7 @@
if (System.getProperty("java.specification.version").compareTo("1.9") < 0) {
errorMessage.format("Download the latest JVMCI JDK 8 from http://www.oracle.com/technetwork/oracle-labs/program-languages/downloads/index.html");
} else {
- errorMessage.format("Download the latest JDK 9 build from https://jdk9.java.net/download/");
+ errorMessage.format("Download JDK 11 or later.");
}
String value = System.getenv("JVMCI_VERSION_CHECK");
if ("warn".equals(value)) {
@@ -69,8 +69,9 @@
static void check(boolean exitOnFailure) {
// Don't use regular expressions to minimize Graal startup time
+ String javaSpecVersion = System.getProperty("java.specification.version");
String vmVersion = System.getProperty("java.vm.version");
- if (System.getProperty("java.specification.version").compareTo("1.9") < 0) {
+ if (javaSpecVersion.compareTo("1.9") < 0) {
int start = vmVersion.indexOf("-jvmci-");
if (start >= 0) {
start += "-jvmci-".length();
@@ -107,18 +108,28 @@
}
failVersionCheck(exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal.%n" +
"Cannot read JVMCI version from java.vm.version property: %s.%n", vmVersion);
+ } else if (javaSpecVersion.compareTo("11") < 0) {
+ failVersionCheck(exitOnFailure, "Graal is not compatible with the JVMCI API in JDK 9 and 10.%n");
} else {
if (vmVersion.contains("SNAPSHOT")) {
- // The snapshot of http://hg.openjdk.java.net/jdk9/dev tip is expected to work
return;
}
if (vmVersion.contains("internal")) {
// Allow local builds
return;
}
- if (vmVersion.startsWith("9-ea")) {
- failVersionCheck(exitOnFailure, "This version of Graal is not compatible with JDK 9 Early Access builds.%n");
- return;
+ if (vmVersion.startsWith("11-ea+")) {
+ String buildString = vmVersion.substring("11-ea+".length());
+ try {
+ int build = Integer.parseInt(buildString);
+ if (build < 20) {
+ failVersionCheck(exitOnFailure, "Graal requires build 20 or later of JDK 11 early access binary, got build %d.%n", build);
+ return;
+ }
+ } catch (NumberFormatException e) {
+ failVersionCheck(exitOnFailure, "Could not parse the JDK 11 early access build number from java.vm.version property: %s.%n", vmVersion);
+ return;
+ }
} else {
// Graal is compatible with all JDK versions as of 9 GA.
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/PrintStreamOptionKey.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/PrintStreamOptionKey.java Thu Aug 23 11:09:16 2018 -0400
@@ -31,6 +31,7 @@
import java.io.PrintStream;
import java.util.List;
+import org.graalvm.compiler.core.common.SuppressFBWarnings;
import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.serviceprovider.GraalServices;
@@ -108,6 +109,7 @@
* Gets the print stream configured by this option. If no file is configured, the print stream
* will output to HotSpot's {@link HotSpotJVMCIRuntime#getLogStream() log} stream.
*/
+ @SuppressFBWarnings(value = "DLS_DEAD_LOCAL_STORE", justification = "false positive on dead store to `ps`")
public PrintStream getStream(OptionValues options) {
String nameTemplate = getValue(options);
if (nameTemplate != null) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java Thu Aug 23 11:09:16 2018 -0400
@@ -669,6 +669,8 @@
runtimeCalls.put(BytecodeExceptionKind.NULL_POINTER, new ForeignCallDescriptor("createNullPointerException", NullPointerException.class));
runtimeCalls.put(BytecodeExceptionKind.OUT_OF_BOUNDS, new ForeignCallDescriptor("createOutOfBoundsException", ArrayIndexOutOfBoundsException.class, int.class, int.class));
runtimeCalls.put(BytecodeExceptionKind.DIVISION_BY_ZERO, new ForeignCallDescriptor("createDivisionByZeroException", ArithmeticException.class));
+ runtimeCalls.put(BytecodeExceptionKind.INTEGER_EXACT_OVERFLOW, new ForeignCallDescriptor("createIntegerExactOverflowException", ArithmeticException.class));
+ runtimeCalls.put(BytecodeExceptionKind.LONG_EXACT_OVERFLOW, new ForeignCallDescriptor("createLongExactOverflowException", ArithmeticException.class));
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java Thu Aug 23 11:09:16 2018 -0400
@@ -36,6 +36,7 @@
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
+import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Reexecutability;
import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect;
import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition;
import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkageImpl;
@@ -102,14 +103,15 @@
* Creates and registers the details for linking a foreign call to a {@link Stub}.
*
* @param descriptor the signature of the call to the stub
- * @param reexecutable specifies if the stub call can be re-executed without (meaningful) side
- * effects. Deoptimization will not return to a point before a stub call that cannot
- * be re-executed.
* @param transition specifies if this is a {@linkplain Transition#LEAF leaf} call
+ * @param reexecutability specifies if the stub call can be re-executed without (meaningful)
+ * side effects. Deoptimization will not return to a point before a stub call that
+ * cannot be re-executed.
* @param killedLocations the memory locations killed by the stub call
*/
- public HotSpotForeignCallLinkage registerStubCall(ForeignCallDescriptor descriptor, boolean reexecutable, Transition transition, LocationIdentity... killedLocations) {
- return register(HotSpotForeignCallLinkageImpl.create(metaAccess, codeCache, wordTypes, this, descriptor, 0L, PRESERVES_REGISTERS, JavaCall, JavaCallee, transition, reexecutable,
+ public HotSpotForeignCallLinkage registerStubCall(ForeignCallDescriptor descriptor, Transition transition, Reexecutability reexecutability,
+ LocationIdentity... killedLocations) {
+ return register(HotSpotForeignCallLinkageImpl.create(metaAccess, codeCache, wordTypes, this, descriptor, 0L, PRESERVES_REGISTERS, JavaCall, JavaCallee, transition, reexecutability,
killedLocations));
}
@@ -122,17 +124,17 @@
* @param effect specifies if the call destroys or preserves all registers (apart from
* temporaries which are always destroyed)
* @param transition specifies if this is a {@linkplain Transition#LEAF leaf} call
- * @param reexecutable specifies if the foreign call can be re-executed without (meaningful)
+ * @param reexecutability specifies if the foreign call can be re-executed without (meaningful)
* side effects. Deoptimization will not return to a point before a foreign call that
* cannot be re-executed.
* @param killedLocations the memory locations killed by the foreign call
*/
public HotSpotForeignCallLinkage registerForeignCall(ForeignCallDescriptor descriptor, long address, CallingConvention.Type outgoingCcType, RegisterEffect effect, Transition transition,
- boolean reexecutable, LocationIdentity... killedLocations) {
+ Reexecutability reexecutability, LocationIdentity... killedLocations) {
Class<?> resultType = descriptor.getResultType();
assert address != 0;
assert transition != SAFEPOINT || resultType.isPrimitive() || Word.class.isAssignableFrom(resultType) : "non-leaf foreign calls must return objects in thread local storage: " + descriptor;
- return register(HotSpotForeignCallLinkageImpl.create(metaAccess, codeCache, wordTypes, this, descriptor, address, effect, outgoingCcType, null, transition, reexecutable, killedLocations));
+ return register(HotSpotForeignCallLinkageImpl.create(metaAccess, codeCache, wordTypes, this, descriptor, address, effect, outgoingCcType, null, transition, reexecutability, killedLocations));
}
/**
@@ -143,14 +145,14 @@
* @param prependThread true if the JavaThread value for the current thread is to be prepended
* to the arguments for the call to {@code address}
* @param transition specifies if this is a {@linkplain Transition#LEAF leaf} call
- * @param reexecutable specifies if the foreign call can be re-executed without (meaningful)
+ * @param reexecutability specifies if the foreign call can be re-executed without (meaningful)
* side effects. Deoptimization will not return to a point before a foreign call that
* cannot be re-executed.
* @param killedLocations the memory locations killed by the foreign call
*/
- public void linkForeignCall(OptionValues options, HotSpotProviders providers, ForeignCallDescriptor descriptor, long address, boolean prependThread, Transition transition, boolean reexecutable,
- LocationIdentity... killedLocations) {
- ForeignCallStub stub = new ForeignCallStub(options, jvmciRuntime, providers, address, descriptor, prependThread, transition, reexecutable, killedLocations);
+ public void linkForeignCall(OptionValues options, HotSpotProviders providers, ForeignCallDescriptor descriptor, long address, boolean prependThread, Transition transition,
+ Reexecutability reexecutability, LocationIdentity... killedLocations) {
+ ForeignCallStub stub = new ForeignCallStub(options, jvmciRuntime, providers, address, descriptor, prependThread, transition, reexecutability, killedLocations);
HotSpotForeignCallLinkage linkage = stub.getLinkage();
HotSpotForeignCallLinkage targetLinkage = stub.getTargetLinkage();
linkage.setCompiledStub(stub);
@@ -161,9 +163,6 @@
public static final boolean PREPEND_THREAD = true;
public static final boolean DONT_PREPEND_THREAD = !PREPEND_THREAD;
- public static final boolean REEXECUTABLE = true;
- public static final boolean NOT_REEXECUTABLE = !REEXECUTABLE;
-
public static final LocationIdentity[] NO_LOCATIONS = {};
@Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java Thu Aug 23 11:09:16 2018 -0400
@@ -59,6 +59,9 @@
import static org.graalvm.compiler.hotspot.HotSpotBackend.UNWIND_EXCEPTION_TO_CALLER;
import static org.graalvm.compiler.hotspot.HotSpotBackend.VM_ERROR;
import static org.graalvm.compiler.hotspot.HotSpotBackend.WRONG_METHOD_HANDLER;
+import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Reexecutability.REEXECUTABLE;
+import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Reexecutability.REEXECUTABLE_ONLY_AFTER_EXCEPTION;
+import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Reexecutability.NOT_REEXECUTABLE;
import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.DESTROYS_REGISTERS;
import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS;
import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF;
@@ -114,6 +117,8 @@
import org.graalvm.compiler.hotspot.stubs.CreateExceptionStub;
import org.graalvm.compiler.hotspot.stubs.DivisionByZeroExceptionStub;
import org.graalvm.compiler.hotspot.stubs.ExceptionHandlerStub;
+import org.graalvm.compiler.hotspot.stubs.IntegerExactOverflowExceptionStub;
+import org.graalvm.compiler.hotspot.stubs.LongExactOverflowExceptionStub;
import org.graalvm.compiler.hotspot.stubs.NewArrayStub;
import org.graalvm.compiler.hotspot.stubs.NewInstanceStub;
import org.graalvm.compiler.hotspot.stubs.NullPointerExceptionStub;
@@ -271,7 +276,7 @@
registerForeignCall(ARITHMETIC_FREM, c.fremAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
registerForeignCall(ARITHMETIC_DREM, c.dremAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
- registerForeignCall(LOAD_AND_CLEAR_EXCEPTION, c.loadAndClearExceptionAddress, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, any());
+ registerForeignCall(LOAD_AND_CLEAR_EXCEPTION, c.loadAndClearExceptionAddress, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any());
registerForeignCall(EXCEPTION_HANDLER_FOR_PC, c.exceptionHandlerForPcAddress, NativeCall, DESTROYS_REGISTERS, SAFEPOINT, REEXECUTABLE, any());
registerForeignCall(EXCEPTION_HANDLER_FOR_RETURN_ADDRESS, c.exceptionHandlerForReturnAddressAddress, NativeCall, DESTROYS_REGISTERS, SAFEPOINT, REEXECUTABLE, any());
@@ -287,33 +292,35 @@
registerForeignCall(VM_MESSAGE_C, c.vmMessageAddress, NativeCall, DESTROYS_REGISTERS, SAFEPOINT, REEXECUTABLE, NO_LOCATIONS);
registerForeignCall(ASSERTION_VM_MESSAGE_C, c.vmMessageAddress, NativeCall, PRESERVES_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
- link(new NewInstanceStub(options, providers, registerStubCall(NEW_INSTANCE, REEXECUTABLE, SAFEPOINT, TLAB_TOP_LOCATION, TLAB_END_LOCATION)));
- link(new NewArrayStub(options, providers, registerStubCall(NEW_ARRAY, REEXECUTABLE, SAFEPOINT, TLAB_TOP_LOCATION, TLAB_END_LOCATION)));
+ link(new NewInstanceStub(options, providers, registerStubCall(NEW_INSTANCE, SAFEPOINT, REEXECUTABLE, TLAB_TOP_LOCATION, TLAB_END_LOCATION)));
+ link(new NewArrayStub(options, providers, registerStubCall(NEW_ARRAY, SAFEPOINT, REEXECUTABLE, TLAB_TOP_LOCATION, TLAB_END_LOCATION)));
link(new ExceptionHandlerStub(options, providers, foreignCalls.get(EXCEPTION_HANDLER)));
- link(new UnwindExceptionToCallerStub(options, providers, registerStubCall(UNWIND_EXCEPTION_TO_CALLER, NOT_REEXECUTABLE, SAFEPOINT, any())));
- link(new VerifyOopStub(options, providers, registerStubCall(VERIFY_OOP, REEXECUTABLE, LEAF_NOFP, NO_LOCATIONS)));
+ link(new UnwindExceptionToCallerStub(options, providers, registerStubCall(UNWIND_EXCEPTION_TO_CALLER, SAFEPOINT, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any())));
+ link(new VerifyOopStub(options, providers, registerStubCall(VERIFY_OOP, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS)));
EnumMap<BytecodeExceptionKind, ForeignCallDescriptor> exceptionRuntimeCalls = DefaultHotSpotLoweringProvider.RuntimeCalls.runtimeCalls;
- link(new ArrayStoreExceptionStub(options, providers, registerStubCall(exceptionRuntimeCalls.get(BytecodeExceptionKind.ARRAY_STORE), REEXECUTABLE, SAFEPOINT, any())));
- link(new ClassCastExceptionStub(options, providers, registerStubCall(exceptionRuntimeCalls.get(BytecodeExceptionKind.CLASS_CAST), REEXECUTABLE, SAFEPOINT, any())));
- link(new NullPointerExceptionStub(options, providers, registerStubCall(exceptionRuntimeCalls.get(BytecodeExceptionKind.NULL_POINTER), REEXECUTABLE, SAFEPOINT, any())));
- link(new OutOfBoundsExceptionStub(options, providers, registerStubCall(exceptionRuntimeCalls.get(BytecodeExceptionKind.OUT_OF_BOUNDS), REEXECUTABLE, SAFEPOINT, any())));
- link(new DivisionByZeroExceptionStub(options, providers, registerStubCall(exceptionRuntimeCalls.get(BytecodeExceptionKind.DIVISION_BY_ZERO), REEXECUTABLE, SAFEPOINT, any())));
+ link(new ArrayStoreExceptionStub(options, providers, registerStubCall(exceptionRuntimeCalls.get(BytecodeExceptionKind.ARRAY_STORE), SAFEPOINT, REEXECUTABLE, any())));
+ link(new ClassCastExceptionStub(options, providers, registerStubCall(exceptionRuntimeCalls.get(BytecodeExceptionKind.CLASS_CAST), SAFEPOINT, REEXECUTABLE, any())));
+ link(new NullPointerExceptionStub(options, providers, registerStubCall(exceptionRuntimeCalls.get(BytecodeExceptionKind.NULL_POINTER), SAFEPOINT, REEXECUTABLE, any())));
+ link(new OutOfBoundsExceptionStub(options, providers, registerStubCall(exceptionRuntimeCalls.get(BytecodeExceptionKind.OUT_OF_BOUNDS), SAFEPOINT, REEXECUTABLE, any())));
+ link(new DivisionByZeroExceptionStub(options, providers, registerStubCall(exceptionRuntimeCalls.get(BytecodeExceptionKind.DIVISION_BY_ZERO), SAFEPOINT, REEXECUTABLE, any())));
+ link(new IntegerExactOverflowExceptionStub(options, providers, registerStubCall(exceptionRuntimeCalls.get(BytecodeExceptionKind.INTEGER_EXACT_OVERFLOW), SAFEPOINT, REEXECUTABLE, any())));
+ link(new LongExactOverflowExceptionStub(options, providers, registerStubCall(exceptionRuntimeCalls.get(BytecodeExceptionKind.LONG_EXACT_OVERFLOW), SAFEPOINT, REEXECUTABLE, any())));
- linkForeignCall(options, providers, IDENTITY_HASHCODE, c.identityHashCodeAddress, PREPEND_THREAD, SAFEPOINT, NOT_REEXECUTABLE, MARK_WORD_LOCATION);
- linkForeignCall(options, providers, REGISTER_FINALIZER, c.registerFinalizerAddress, PREPEND_THREAD, SAFEPOINT, NOT_REEXECUTABLE, any());
- linkForeignCall(options, providers, MONITORENTER, c.monitorenterAddress, PREPEND_THREAD, SAFEPOINT, NOT_REEXECUTABLE, any());
- linkForeignCall(options, providers, MONITOREXIT, c.monitorexitAddress, PREPEND_THREAD, STACK_INSPECTABLE_LEAF, NOT_REEXECUTABLE, any());
+ linkForeignCall(options, providers, IDENTITY_HASHCODE, c.identityHashCodeAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE_ONLY_AFTER_EXCEPTION, MARK_WORD_LOCATION);
+ linkForeignCall(options, providers, REGISTER_FINALIZER, c.registerFinalizerAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any());
+ linkForeignCall(options, providers, MONITORENTER, c.monitorenterAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any());
+ linkForeignCall(options, providers, MONITOREXIT, c.monitorexitAddress, PREPEND_THREAD, STACK_INSPECTABLE_LEAF, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any());
linkForeignCall(options, providers, NEW_MULTI_ARRAY, c.newMultiArrayAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, TLAB_TOP_LOCATION, TLAB_END_LOCATION);
- linkForeignCall(options, providers, NOTIFY, c.notifyAddress, PREPEND_THREAD, SAFEPOINT, NOT_REEXECUTABLE, any());
- linkForeignCall(options, providers, NOTIFY_ALL, c.notifyAllAddress, PREPEND_THREAD, SAFEPOINT, NOT_REEXECUTABLE, any());
+ linkForeignCall(options, providers, NOTIFY, c.notifyAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any());
+ linkForeignCall(options, providers, NOTIFY_ALL, c.notifyAllAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any());
linkForeignCall(options, providers, DYNAMIC_NEW_ARRAY, c.dynamicNewArrayAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE);
linkForeignCall(options, providers, DYNAMIC_NEW_INSTANCE, c.dynamicNewInstanceAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE);
linkForeignCall(options, providers, LOG_PRINTF, c.logPrintfAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS);
linkForeignCall(options, providers, LOG_OBJECT, c.logObjectAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS);
linkForeignCall(options, providers, LOG_PRIMITIVE, c.logPrimitiveAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS);
linkForeignCall(options, providers, VM_ERROR, c.vmErrorAddress, PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS);
- linkForeignCall(options, providers, OSR_MIGRATION_END, c.osrMigrationEndAddress, DONT_PREPEND_THREAD, LEAF_NOFP, NOT_REEXECUTABLE, NO_LOCATIONS);
+ linkForeignCall(options, providers, OSR_MIGRATION_END, c.osrMigrationEndAddress, DONT_PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NO_LOCATIONS);
linkForeignCall(options, providers, G1WBPRECALL, c.writeBarrierPreAddress, PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS);
linkForeignCall(options, providers, G1WBPOSTCALL, c.writeBarrierPostAddress, PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS);
linkForeignCall(options, providers, VALIDATE_OBJECT, c.validateObject, PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS);
@@ -325,13 +332,13 @@
linkForeignCall(options, providers, RESOLVE_DYNAMIC_INVOKE, cr.resolveDynamicInvoke, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, any());
linkForeignCall(options, providers, RESOLVE_KLASS_BY_SYMBOL, cr.resolveKlassBySymbol, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, any());
linkForeignCall(options, providers, RESOLVE_METHOD_BY_SYMBOL_AND_LOAD_COUNTERS, cr.resolveMethodBySymbolAndLoadCounters, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, NO_LOCATIONS);
- linkForeignCall(options, providers, INITIALIZE_KLASS_BY_SYMBOL, cr.initializeKlassBySymbol, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, any());
+ linkForeignCall(options, providers, INITIALIZE_KLASS_BY_SYMBOL, cr.initializeKlassBySymbol, PREPEND_THREAD, SAFEPOINT, NOT_REEXECUTABLE, any());
linkForeignCall(options, providers, INVOCATION_EVENT, cr.invocationEvent, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, NO_LOCATIONS);
linkForeignCall(options, providers, BACKEDGE_EVENT, cr.backedgeEvent, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, NO_LOCATIONS);
}
// Cannot be a leaf as VM acquires Thread_lock which requires thread_in_vm state
- linkForeignCall(options, providers, THREAD_IS_INTERRUPTED, c.threadIsInterruptedAddress, PREPEND_THREAD, SAFEPOINT, NOT_REEXECUTABLE, any());
+ linkForeignCall(options, providers, THREAD_IS_INTERRUPTED, c.threadIsInterruptedAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any());
linkForeignCall(options, providers, TEST_DEOPTIMIZE_CALL_INT, c.testDeoptimizeCallInt, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, any());
@@ -349,32 +356,35 @@
registerCheckcastArraycopyDescriptor(true, c.checkcastArraycopyUninit);
registerCheckcastArraycopyDescriptor(false, c.checkcastArraycopy);
- registerForeignCall(GENERIC_ARRAYCOPY, c.genericArraycopy, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, NamedLocationIdentity.any());
- registerForeignCall(UNSAFE_ARRAYCOPY, c.unsafeArraycopy, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, NamedLocationIdentity.any());
+ registerForeignCall(GENERIC_ARRAYCOPY, c.genericArraycopy, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NamedLocationIdentity.any());
+ registerForeignCall(UNSAFE_ARRAYCOPY, c.unsafeArraycopy, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NamedLocationIdentity.any());
if (c.useMultiplyToLenIntrinsic()) {
- registerForeignCall(MULTIPLY_TO_LEN, c.multiplyToLen, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, NamedLocationIdentity.getArrayLocation(JavaKind.Int));
+ registerForeignCall(MULTIPLY_TO_LEN, c.multiplyToLen, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION,
+ NamedLocationIdentity.getArrayLocation(JavaKind.Int));
}
if (c.useSHA1Intrinsics()) {
- registerForeignCall(SHA_IMPL_COMPRESS, c.sha1ImplCompress, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, NamedLocationIdentity.any());
+ registerForeignCall(SHA_IMPL_COMPRESS, c.sha1ImplCompress, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NamedLocationIdentity.any());
}
if (c.useSHA256Intrinsics()) {
- registerForeignCall(SHA2_IMPL_COMPRESS, c.sha256ImplCompress, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, NamedLocationIdentity.any());
+ registerForeignCall(SHA2_IMPL_COMPRESS, c.sha256ImplCompress, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NamedLocationIdentity.any());
}
if (c.useSHA512Intrinsics()) {
- registerForeignCall(SHA5_IMPL_COMPRESS, c.sha512ImplCompress, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, NamedLocationIdentity.any());
+ registerForeignCall(SHA5_IMPL_COMPRESS, c.sha512ImplCompress, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NamedLocationIdentity.any());
}
if (c.useMulAddIntrinsic()) {
- registerForeignCall(MUL_ADD, c.mulAdd, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, NamedLocationIdentity.getArrayLocation(JavaKind.Int));
+ registerForeignCall(MUL_ADD, c.mulAdd, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NamedLocationIdentity.getArrayLocation(JavaKind.Int));
}
if (c.useMontgomeryMultiplyIntrinsic()) {
- registerForeignCall(MONTGOMERY_MULTIPLY, c.montgomeryMultiply, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, NamedLocationIdentity.getArrayLocation(JavaKind.Int));
+ registerForeignCall(MONTGOMERY_MULTIPLY, c.montgomeryMultiply, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION,
+ NamedLocationIdentity.getArrayLocation(JavaKind.Int));
}
if (c.useMontgomerySquareIntrinsic()) {
- registerForeignCall(MONTGOMERY_SQUARE, c.montgomerySquare, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, NamedLocationIdentity.getArrayLocation(JavaKind.Int));
+ registerForeignCall(MONTGOMERY_SQUARE, c.montgomerySquare, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION,
+ NamedLocationIdentity.getArrayLocation(JavaKind.Int));
}
if (c.useSquareToLenIntrinsic()) {
- registerForeignCall(SQUARE_TO_LEN, c.squareToLen, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, NamedLocationIdentity.getArrayLocation(JavaKind.Int));
+ registerForeignCall(SQUARE_TO_LEN, c.squareToLen, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NamedLocationIdentity.getArrayLocation(JavaKind.Int));
}
if (c.useAESIntrinsics) {
@@ -385,9 +395,11 @@
*/
try {
// These stubs do callee saving
- registerForeignCall(ENCRYPT_BLOCK, c.aescryptEncryptBlockStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, NamedLocationIdentity.getArrayLocation(JavaKind.Byte));
- registerForeignCall(DECRYPT_BLOCK, c.aescryptDecryptBlockStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, NamedLocationIdentity.getArrayLocation(JavaKind.Byte));
- registerForeignCall(DECRYPT_BLOCK_WITH_ORIGINAL_KEY, c.aescryptDecryptBlockStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE,
+ registerForeignCall(ENCRYPT_BLOCK, c.aescryptEncryptBlockStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION,
+ NamedLocationIdentity.getArrayLocation(JavaKind.Byte));
+ registerForeignCall(DECRYPT_BLOCK, c.aescryptDecryptBlockStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION,
+ NamedLocationIdentity.getArrayLocation(JavaKind.Byte));
+ registerForeignCall(DECRYPT_BLOCK_WITH_ORIGINAL_KEY, c.aescryptDecryptBlockStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION,
NamedLocationIdentity.getArrayLocation(JavaKind.Byte));
} catch (GraalError e) {
if (!(e.getCause() instanceof ClassNotFoundException)) {
@@ -396,11 +408,11 @@
}
try {
// These stubs do callee saving
- registerForeignCall(ENCRYPT, c.cipherBlockChainingEncryptAESCryptStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE,
+ registerForeignCall(ENCRYPT, c.cipherBlockChainingEncryptAESCryptStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION,
NamedLocationIdentity.getArrayLocation(JavaKind.Byte));
- registerForeignCall(DECRYPT, c.cipherBlockChainingDecryptAESCryptStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE,
+ registerForeignCall(DECRYPT, c.cipherBlockChainingDecryptAESCryptStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION,
NamedLocationIdentity.getArrayLocation(JavaKind.Byte));
- registerForeignCall(DECRYPT_WITH_ORIGINAL_KEY, c.cipherBlockChainingDecryptAESCryptStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE,
+ registerForeignCall(DECRYPT_WITH_ORIGINAL_KEY, c.cipherBlockChainingDecryptAESCryptStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION,
NamedLocationIdentity.getArrayLocation(JavaKind.Byte));
} catch (GraalError e) {
if (!(e.getCause() instanceof ClassNotFoundException)) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/IntrinsificationPredicate.java Fri Aug 10 14:56:29 2018 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package org.graalvm.compiler.hotspot.meta;
-
-import java.lang.module.ModuleDescriptor.Requires;
-
-import jdk.internal.vm.compiler.collections.EconomicSet;
-import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
-
-/**
- * Determines if methods in a given class can be intrinsified.
- *
- * Only classes loaded from the module defining the compiler configuration or any of its transitive
- * dependencies can be intrinsified.
- *
- * This version of the class must be used on JDK 9 or later.
- */
-public final class IntrinsificationPredicate {
- /**
- * Set of modules composed of the module defining the compiler configuration and its transitive
- * dependencies.
- */
- private final EconomicSet<Module> trustedModules;
-
- IntrinsificationPredicate(CompilerConfiguration compilerConfiguration) {
- trustedModules = EconomicSet.create();
- Module compilerConfigurationModule = compilerConfiguration.getClass().getModule();
- if (compilerConfigurationModule.getDescriptor().isAutomatic()) {
- throw new IllegalArgumentException(String.format("The module '%s' defining the Graal compiler configuration class '%s' must not be an automatic module",
- compilerConfigurationModule.getName(), compilerConfiguration.getClass().getName()));
- }
- trustedModules.add(compilerConfigurationModule);
- for (Requires require : compilerConfigurationModule.getDescriptor().requires()) {
- for (Module module : compilerConfigurationModule.getLayer().modules()) {
- if (module.getName().equals(require.name())) {
- trustedModules.add(module);
- }
- }
- }
- }
-
- public boolean apply(Class<?> declaringClass) {
- Module module = declaringClass.getModule();
- return trustedModules.contains(module);
- }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ClassGetHubNode.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ClassGetHubNode.java Thu Aug 23 11:09:16 2018 -0400
@@ -93,7 +93,7 @@
if (allUsagesAvailable && self != null && self.hasNoUsages()) {
return null;
} else {
- if (clazz.isConstant()) {
+ if (clazz.isConstant() && !clazz.isNullConstant()) {
if (metaAccess != null) {
ResolvedJavaType exactType = constantReflection.asJavaType(clazz.asJavaConstant());
if (exactType.isPrimitive()) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java Thu Aug 23 11:09:16 2018 -0400
@@ -63,7 +63,6 @@
import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.internal.vm.compiler.word.WordFactory;
-import jdk.vm.ci.code.CodeUtil;
import jdk.vm.ci.code.Register;
import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
@@ -186,13 +185,6 @@
return config.threadTlabEndOffset();
}
- public static final LocationIdentity TLAB_START_LOCATION = NamedLocationIdentity.mutable("TlabStart");
-
- @Fold
- static int threadTlabStartOffset(@InjectedParameter GraalHotSpotVMConfig config) {
- return config.threadTlabStartOffset();
- }
-
public static final LocationIdentity PENDING_EXCEPTION_LOCATION = NamedLocationIdentity.mutable("PendingException");
/**
@@ -203,16 +195,6 @@
return config.pendingExceptionOffset;
}
- public static final LocationIdentity PENDING_DEOPTIMIZATION_LOCATION = NamedLocationIdentity.mutable("PendingDeoptimization");
-
- /**
- * @see GraalHotSpotVMConfig#pendingDeoptimizationOffset
- */
- @Fold
- static int threadPendingDeoptimizationOffset(@InjectedParameter GraalHotSpotVMConfig config) {
- return config.pendingDeoptimizationOffset;
- }
-
public static final LocationIdentity OBJECT_RESULT_LOCATION = NamedLocationIdentity.mutable("ObjectResult");
@Fold
@@ -250,21 +232,10 @@
return thread.readWord(threadTlabEndOffset(INJECTED_VMCONFIG), TLAB_END_LOCATION);
}
- public static Word readTlabStart(Word thread) {
- return thread.readWord(threadTlabStartOffset(INJECTED_VMCONFIG), TLAB_START_LOCATION);
- }
-
public static void writeTlabTop(Word thread, Word top) {
thread.writeWord(threadTlabTopOffset(INJECTED_VMCONFIG), top, TLAB_TOP_LOCATION);
}
- @SuppressFBWarnings(value = "NP_NULL_PARAM_DEREF_NONVIRTUAL", justification = "foldable method parameters are injected")
- public static void initializeTlab(Word thread, Word start, Word end) {
- thread.writeWord(threadTlabStartOffset(INJECTED_VMCONFIG), start, TLAB_START_LOCATION);
- thread.writeWord(threadTlabTopOffset(INJECTED_VMCONFIG), start, TLAB_TOP_LOCATION);
- thread.writeWord(threadTlabEndOffset(INJECTED_VMCONFIG), end, TLAB_END_LOCATION);
- }
-
/**
* Clears the pending exception for the given thread.
*
@@ -278,19 +249,13 @@
}
/**
- * Reads the pending deoptimization value for the given thread.
+ * Gets the pending exception for the given thread.
*
- * @return {@code true} if there was a pending deoptimization
+ * @return the pending exception, or null if there was none
*/
- public static int readPendingDeoptimization(Word thread) {
- return thread.readInt(threadPendingDeoptimizationOffset(INJECTED_VMCONFIG), PENDING_DEOPTIMIZATION_LOCATION);
- }
-
- /**
- * Writes the pending deoptimization value for the given thread.
- */
- public static void writePendingDeoptimization(Word thread, int value) {
- thread.writeInt(threadPendingDeoptimizationOffset(INJECTED_VMCONFIG), value, PENDING_DEOPTIMIZATION_LOCATION);
+ @SuppressFBWarnings(value = "NP_NULL_PARAM_DEREF_NONVIRTUAL", justification = "foldable method parameters are injected")
+ public static Object getPendingException(Word thread) {
+ return thread.readObject(threadPendingExceptionOffset(INJECTED_VMCONFIG), PENDING_EXCEPTION_LOCATION);
}
/**
@@ -342,11 +307,6 @@
return UNSAFE.pageSize();
}
- @Fold
- public static int heapWordSize(@InjectedParameter GraalHotSpotVMConfig config) {
- return config.heapWordSize;
- }
-
public static final LocationIdentity PROTOTYPE_MARK_WORD_LOCATION = NamedLocationIdentity.mutable("PrototypeMarkWord");
@Fold
@@ -354,11 +314,6 @@
return config.prototypeMarkWordOffset;
}
- @Fold
- public static long arrayPrototypeMarkWord(@InjectedParameter GraalHotSpotVMConfig config) {
- return config.arrayPrototypeMarkWord();
- }
-
public static final LocationIdentity KLASS_ACCESS_FLAGS_LOCATION = NamedLocationIdentity.immutable("Klass::_access_flags");
@Fold
@@ -389,11 +344,6 @@
}
};
- @Fold
- public static int klassLayoutHelperOffset(@InjectedParameter GraalHotSpotVMConfig config) {
- return config.klassLayoutHelperOffset;
- }
-
@NodeIntrinsic(value = KlassLayoutHelperNode.class)
public static native int readLayoutHelper(KlassPointer object);
@@ -707,16 +657,6 @@
}
@Fold
- public static boolean useG1GC(@InjectedParameter GraalHotSpotVMConfig config) {
- return config.useG1GC;
- }
-
- @Fold
- public static boolean useCMSIncrementalMode(@InjectedParameter GraalHotSpotVMConfig config) {
- return config.cmsIncrementalMode;
- }
-
- @Fold
public static boolean useCompressedOops(@InjectedParameter GraalHotSpotVMConfig config) {
return config.useCompressedOops;
}
@@ -788,11 +728,6 @@
@NodeIntrinsic(value = LoadHubNode.class)
public static native KlassPointer loadHubIntrinsic(Object object);
- @Fold
- public static int log2WordSize() {
- return CodeUtil.log2(wordSize());
- }
-
public static final LocationIdentity CLASS_STATE_LOCATION = NamedLocationIdentity.mutable("ClassState");
@Fold
@@ -832,11 +767,6 @@
}
};
- @Fold
- public static int klassOffset(@InjectedParameter GraalHotSpotVMConfig config) {
- return config.klassOffset;
- }
-
public static final LocationIdentity CLASS_ARRAY_KLASS_LOCATION = new HotSpotOptimizingLocationIdentity("Class._array_klass") {
@Override
public ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool) {
@@ -853,87 +783,6 @@
public static final LocationIdentity CLASS_MIRROR_HANDLE_LOCATION = NamedLocationIdentity.immutable("Klass::_java_mirror handle");
- public static final LocationIdentity HEAP_TOP_LOCATION = NamedLocationIdentity.mutable("HeapTop");
-
- @Fold
- public static long heapTopAddress(@InjectedParameter GraalHotSpotVMConfig config) {
- return config.heapTopAddress;
- }
-
- public static final LocationIdentity HEAP_END_LOCATION = NamedLocationIdentity.mutable("HeapEnd");
-
- @Fold
- public static long heapEndAddress(@InjectedParameter GraalHotSpotVMConfig config) {
- return config.heapEndAddress;
- }
-
- @Fold
- public static long tlabIntArrayMarkWord(@InjectedParameter GraalHotSpotVMConfig config) {
- return config.tlabIntArrayMarkWord();
- }
-
- @Fold
- public static boolean inlineContiguousAllocationSupported(@InjectedParameter GraalHotSpotVMConfig config) {
- return config.inlineContiguousAllocationSupported;
- }
-
- @Fold
- public static int tlabAlignmentReserveInHeapWords(@InjectedParameter GraalHotSpotVMConfig config) {
- return config.tlabAlignmentReserve;
- }
-
- public static final LocationIdentity TLAB_SIZE_LOCATION = NamedLocationIdentity.mutable("TlabSize");
-
- @Fold
- public static int threadTlabSizeOffset(@InjectedParameter GraalHotSpotVMConfig config) {
- return config.threadTlabSizeOffset();
- }
-
- public static final LocationIdentity TLAB_THREAD_ALLOCATED_BYTES_LOCATION = NamedLocationIdentity.mutable("TlabThreadAllocatedBytes");
-
- @Fold
- public static int threadAllocatedBytesOffset(@InjectedParameter GraalHotSpotVMConfig config) {
- return config.threadAllocatedBytesOffset;
- }
-
- public static final LocationIdentity TLAB_REFILL_WASTE_LIMIT_LOCATION = NamedLocationIdentity.mutable("RefillWasteLimit");
-
- @Fold
- public static int tlabRefillWasteLimitOffset(@InjectedParameter GraalHotSpotVMConfig config) {
- return config.tlabRefillWasteLimitOffset();
- }
-
- public static final LocationIdentity TLAB_NOF_REFILLS_LOCATION = NamedLocationIdentity.mutable("TlabNOfRefills");
-
- @Fold
- public static int tlabNumberOfRefillsOffset(@InjectedParameter GraalHotSpotVMConfig config) {
- return config.tlabNumberOfRefillsOffset();
- }
-
- public static final LocationIdentity TLAB_FAST_REFILL_WASTE_LOCATION = NamedLocationIdentity.mutable("TlabFastRefillWaste");
-
- @Fold
- public static int tlabFastRefillWasteOffset(@InjectedParameter GraalHotSpotVMConfig config) {
- return config.tlabFastRefillWasteOffset();
- }
-
- public static final LocationIdentity TLAB_SLOW_ALLOCATIONS_LOCATION = NamedLocationIdentity.mutable("TlabSlowAllocations");
-
- @Fold
- public static int tlabSlowAllocationsOffset(@InjectedParameter GraalHotSpotVMConfig config) {
- return config.tlabSlowAllocationsOffset();
- }
-
- @Fold
- public static int tlabRefillWasteIncrement(@InjectedParameter GraalHotSpotVMConfig config) {
- return config.tlabRefillWasteIncrement;
- }
-
- @Fold
- public static boolean tlabStats(@InjectedParameter GraalHotSpotVMConfig config) {
- return config.tlabStats;
- }
-
@Fold
public static int layoutHelperHeaderSizeShift(@InjectedParameter GraalHotSpotVMConfig config) {
return config.layoutHelperHeaderSizeShift;
@@ -964,20 +813,10 @@
return config.layoutHelperElementTypeMask;
}
- @Fold
- public static int layoutHelperElementTypePrimitiveInPlace(@InjectedParameter GraalHotSpotVMConfig config) {
- return config.layoutHelperElementTypePrimitiveInPlace();
- }
-
@NodeIntrinsic(ForeignCallNode.class)
public static native int identityHashCode(@ConstantNodeParameter ForeignCallDescriptor descriptor, Object object);
@Fold
- public static int verifiedEntryPointOffset(@InjectedParameter GraalHotSpotVMConfig config) {
- return config.nmethodEntryOffset;
- }
-
- @Fold
public static long gcTotalCollectionsAddress(@InjectedParameter GraalHotSpotVMConfig config) {
return config.gcTotalCollectionsAddress();
}
@@ -1023,9 +862,4 @@
public static final LocationIdentity METASPACE_ARRAY_LENGTH_LOCATION = NamedLocationIdentity.immutable("MetaspaceArrayLength");
public static final LocationIdentity SECONDARY_SUPERS_ELEMENT_LOCATION = NamedLocationIdentity.immutable("SecondarySupersElement");
-
- @Fold
- public static boolean useFastTLABRefill(@InjectedParameter GraalHotSpotVMConfig config) {
- return config.useFastTLABRefill;
- }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.java Thu Aug 23 11:09:16 2018 -0400
@@ -595,7 +595,7 @@
public static void traceObject(boolean enabled, String action, Object object, boolean enter, OptionValues options) {
if (doProfile(options)) {
- DynamicCounterNode.counter(action, enter ? "number of monitor enters" : "number of monitor exits", 1, PROFILE_CONTEXT);
+ DynamicCounterNode.counter(enter ? "number of monitor enters" : "number of monitor exits", action, 1, PROFILE_CONTEXT);
}
if (enabled) {
Log.print(action);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java Thu Aug 23 11:09:16 2018 -0400
@@ -177,8 +177,8 @@
String name = createName(path, typeContext, options);
boolean context = withContext(options);
- DynamicCounterNode.counter(name, "number of bytes allocated", size, context);
- DynamicCounterNode.counter(name, "number of allocations", 1, context);
+ DynamicCounterNode.counter("number of bytes allocated", name, size, context);
+ DynamicCounterNode.counter("number of allocations", name, 1, context);
}
}
@@ -276,6 +276,8 @@
*/
return allocateInstanceHelper(layoutHelper, nonNullHub, prototypeMarkWord, fillContents, threadRegister, false, "", options, counters);
}
+ } else {
+ DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
}
}
return dynamicNewInstanceStub(type);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ReflectionSubstitutions.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ReflectionSubstitutions.java Thu Aug 23 11:09:16 2018 -0400
@@ -37,7 +37,7 @@
import org.graalvm.compiler.hotspot.word.KlassPointer;
/**
- * Substitutions for {@link sun.reflect.Reflection} methods.
+ * Substitutions for {@code sun.reflect.Reflection} methods.
*/
@ClassSubstitution(className = {"jdk.internal.reflect.Reflection", "sun.reflect.Reflection"}, optional = true)
public class ReflectionSubstitutions {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/CreateExceptionStub.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/CreateExceptionStub.java Thu Aug 23 11:09:16 2018 -0400
@@ -25,9 +25,9 @@
package org.graalvm.compiler.hotspot.stubs;
import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.NativeCall;
+import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Reexecutability.REEXECUTABLE;
import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.DESTROYS_REGISTERS;
import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.SAFEPOINT;
-import static org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl.REEXECUTABLE;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.clearPendingException;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.registerAsWord;
import static jdk.internal.vm.compiler.word.LocationIdentity.any;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ForeignCallStub.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ForeignCallStub.java Thu Aug 23 11:09:16 2018 -0400
@@ -40,6 +40,7 @@
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.debug.JavaMethodContext;
import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
+import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Reexecutability;
import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition;
import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkageImpl;
import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
@@ -75,8 +76,8 @@
* deoptimization while the call is in progress. And since these are foreign/runtime calls on slow
* paths, we don't want to force the register allocator to spill around the call. As such, this stub
* saves and restores all allocatable registers. It also
- * {@linkplain StubUtil#handlePendingException(Word, boolean) handles} any exceptions raised during
- * the foreign call.
+ * {@linkplain StubUtil#handlePendingException(Word, boolean, boolean) handles} any exceptions
+ * raised during the foreign call.
*/
public class ForeignCallStub extends Stub {
@@ -100,23 +101,21 @@
* @param descriptor the signature of the call to this stub
* @param prependThread true if the JavaThread value for the current thread is to be prepended
* to the arguments for the call to {@code address}
- * @param reexecutable specifies if the stub call can be re-executed without (meaningful) side
- * effects. Deoptimization will not return to a point before a stub call that cannot
- * be re-executed.
+ * @param reexecutability specifies if the stub call can be re-executed without (meaningful)
+ * side effects. Deoptimization will not return to a point before a stub call that
+ * cannot be re-executed.
* @param killedLocations the memory locations killed by the stub call
*/
public ForeignCallStub(OptionValues options, HotSpotJVMCIRuntime runtime, HotSpotProviders providers, long address, ForeignCallDescriptor descriptor, boolean prependThread,
- Transition transition,
- boolean reexecutable,
- LocationIdentity... killedLocations) {
+ Transition transition, Reexecutability reexecutability, LocationIdentity... killedLocations) {
super(options, providers, HotSpotForeignCallLinkageImpl.create(providers.getMetaAccess(), providers.getCodeCache(), providers.getWordTypes(), providers.getForeignCalls(), descriptor, 0L,
- PRESERVES_REGISTERS, JavaCall, JavaCallee, transition, reexecutable, killedLocations));
+ PRESERVES_REGISTERS, JavaCall, JavaCallee, transition, reexecutability, killedLocations));
this.jvmciRuntime = runtime;
this.prependThread = prependThread;
Class<?>[] targetParameterTypes = createTargetParameters(descriptor);
ForeignCallDescriptor targetSig = new ForeignCallDescriptor(descriptor.getName() + ":C", descriptor.getResultType(), targetParameterTypes);
target = HotSpotForeignCallLinkageImpl.create(providers.getMetaAccess(), providers.getCodeCache(), providers.getWordTypes(), providers.getForeignCalls(), targetSig, address,
- DESTROYS_REGISTERS, NativeCall, NativeCall, transition, reexecutable, killedLocations);
+ DESTROYS_REGISTERS, NativeCall, NativeCall, transition, reexecutability, killedLocations);
}
/**
@@ -191,9 +190,9 @@
* <pre>
* Object foreignFunctionStub(args...) {
* foreignFunction(currentThread, args);
- * if (clearPendingException(thread())) {
+ * if ((shouldClearException && clearPendingException(thread())) || (!shouldClearException && hasPendingException(thread)) {
* getAndClearObjectResult(thread());
- * DeoptimizeCallerNode.deopt(InvalidateReprofile, RuntimeConstraint);
+ * DeoptimizeCallerNode.deopt(None, RuntimeConstraint);
* }
* return verifyObject(getAndClearObjectResult(thread()));
* }
@@ -205,8 +204,8 @@
* <pre>
* int foreignFunctionStub(args...) {
* int result = foreignFunction(currentThread, args);
- * if (clearPendingException(thread())) {
- * DeoptimizeCallerNode.deopt(InvalidateReprofile, RuntimeConstraint);
+ * if ((shouldClearException && clearPendingException(thread())) || (!shouldClearException && hasPendingException(thread)) {
+ * DeoptimizeCallerNode.deopt(None, RuntimeConstraint);
* }
* return result;
* }
@@ -217,8 +216,8 @@
* <pre>
* void foreignFunctionStub(args...) {
* foreignFunction(currentThread, args);
- * if (clearPendingException(thread())) {
- * DeoptimizeCallerNode.deopt(InvalidateReprofile, RuntimeConstraint);
+ * if ((shouldClearException && clearPendingException(thread())) || (!shouldClearException && hasPendingException(thread)) {
+ * DeoptimizeCallerNode.deopt(None, RuntimeConstraint);
* }
* }
* </pre>
@@ -232,7 +231,8 @@
WordTypes wordTypes = providers.getWordTypes();
Class<?>[] args = linkage.getDescriptor().getArgumentTypes();
boolean isObjectResult = !LIRKind.isValue(linkage.getOutgoingCallingConvention().getReturn());
-
+ // Do we want to clear the pending exception?
+ boolean shouldClearException = linkage.isReexecutable() || linkage.isReexecutableOnlyAfterException();
try {
ResolvedJavaMethod thisMethod = providers.getMetaAccess().lookupJavaMethod(ForeignCallStub.class.getDeclaredMethod("getGraph", DebugContext.class, CompilationIdentifier.class));
GraphKit kit = new GraphKit(debug, thisMethod, providers, wordTypes, providers.getGraphBuilderPlugins(), compilationId, toString());
@@ -240,7 +240,7 @@
ParameterNode[] params = createParameters(kit, args);
ReadRegisterNode thread = kit.append(new ReadRegisterNode(providers.getRegisters().getThreadRegister(), wordTypes.getWordKind(), true, false));
ValueNode result = createTargetCall(kit, params, thread);
- kit.createInvoke(StubUtil.class, "handlePendingException", thread, ConstantNode.forBoolean(isObjectResult, graph));
+ kit.createInvoke(StubUtil.class, "handlePendingException", thread, ConstantNode.forBoolean(shouldClearException, graph), ConstantNode.forBoolean(isObjectResult, graph));
if (isObjectResult) {
InvokeNode object = kit.createInvoke(HotSpotReplacementsUtil.class, "getAndClearObjectResult", thread);
result = kit.createInvoke(StubUtil.class, "verifyObject", object);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/IntegerExactOverflowExceptionStub.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.hotspot.stubs;
+
+import org.graalvm.compiler.api.replacements.Snippet;
+import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter;
+import org.graalvm.compiler.debug.GraalError;
+import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
+import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
+import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.replacements.nodes.CStringConstant;
+import org.graalvm.compiler.word.Word;
+
+import jdk.vm.ci.code.Register;
+
+public class IntegerExactOverflowExceptionStub extends CreateExceptionStub {
+ public IntegerExactOverflowExceptionStub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) {
+ super("createIntegerExactOverflowException", options, providers, linkage);
+ }
+
+ @Override
+ protected Object getConstantParameterValue(int index, String name) {
+ GraalError.guarantee(index == 0, "unknown parameter %s at index %d", name, index);
+ return providers.getRegisters().getThreadRegister();
+ }
+
+ @Snippet
+ private static Object createIntegerExactOverflowException(@ConstantParameter Register threadRegister) {
+ Word msg = CStringConstant.cstring("integer overflow");
+ return createException(threadRegister, ArithmeticException.class, msg);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/LongExactOverflowExceptionStub.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.hotspot.stubs;
+
+import org.graalvm.compiler.api.replacements.Snippet;
+import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter;
+import org.graalvm.compiler.debug.GraalError;
+import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
+import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
+import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.replacements.nodes.CStringConstant;
+import org.graalvm.compiler.word.Word;
+
+import jdk.vm.ci.code.Register;
+
+public class LongExactOverflowExceptionStub extends CreateExceptionStub {
+ public LongExactOverflowExceptionStub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) {
+ super("createLongExactOverflowException", options, providers, linkage);
+ }
+
+ @Override
+ protected Object getConstantParameterValue(int index, String name) {
+ GraalError.guarantee(index == 0, "unknown parameter %s at index %d", name, index);
+ return providers.getRegisters().getThreadRegister();
+ }
+
+ @Snippet
+ private static Object createLongExactOverflowException(@ConstantParameter Register threadRegister) {
+ Word msg = CStringConstant.cstring("long overflow");
+ return createException(threadRegister, ArithmeticException.class, msg);
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewArrayStub.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewArrayStub.java Thu Aug 23 11:09:16 2018 -0400
@@ -26,7 +26,6 @@
import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.arrayAllocationSize;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.arrayPrototypeMarkWord;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.getAndClearObjectResult;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.layoutHelperElementTypeMask;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.layoutHelperElementTypeShift;
@@ -36,11 +35,6 @@
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.layoutHelperLog2ElementSizeShift;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.readLayoutHelper;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.registerAsWord;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.useCMSIncrementalMode;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.useFastTLABRefill;
-import static org.graalvm.compiler.hotspot.replacements.NewObjectSnippets.MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH;
-import static org.graalvm.compiler.hotspot.replacements.NewObjectSnippets.formatArray;
-import static org.graalvm.compiler.hotspot.stubs.NewInstanceStub.refillAllocate;
import static org.graalvm.compiler.hotspot.stubs.StubUtil.handlePendingException;
import static org.graalvm.compiler.hotspot.stubs.StubUtil.newDescriptor;
import static org.graalvm.compiler.hotspot.stubs.StubUtil.printf;
@@ -54,18 +48,13 @@
import org.graalvm.compiler.graph.Node.NodeIntrinsic;
import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
-import org.graalvm.compiler.hotspot.nodes.GraalHotSpotVMConfigNode;
import org.graalvm.compiler.hotspot.nodes.StubForeignCallNode;
-import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp;
import org.graalvm.compiler.hotspot.replacements.NewObjectSnippets;
import org.graalvm.compiler.hotspot.word.KlassPointer;
-import org.graalvm.compiler.nodes.ConstantNode;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.word.Word;
-import jdk.internal.vm.compiler.word.WordFactory;
import jdk.vm.ci.code.Register;
-import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
/**
* Stub implementing the fast path for TLAB refill during instance class allocation. This stub is
@@ -81,15 +70,12 @@
@Override
protected Object[] makeConstArgs() {
- HotSpotResolvedObjectType intArrayType = (HotSpotResolvedObjectType) providers.getMetaAccess().lookupJavaType(int[].class);
int count = method.getSignature().getParameterCount(false);
Object[] args = new Object[count];
- assert checkConstArg(3, "intArrayHub");
- assert checkConstArg(4, "threadRegister");
- assert checkConstArg(5, "options");
- args[3] = ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), intArrayType.klass(), null);
- args[4] = providers.getRegisters().getThreadRegister();
- args[5] = options;
+ assert checkConstArg(2, "threadRegister");
+ assert checkConstArg(3, "options");
+ args[2] = providers.getRegisters().getThreadRegister();
+ args[3] = options;
return args;
}
@@ -104,12 +90,9 @@
*
* @param hub the hub of the object to be allocated
* @param length the length of the array
- * @param fillContents Should the array be filled with zeroes?
- * @param intArrayHub the hub for {@code int[].class}
*/
@Snippet
- private static Object newArray(KlassPointer hub, int length, boolean fillContents, @ConstantParameter KlassPointer intArrayHub, @ConstantParameter Register threadRegister,
- @ConstantParameter OptionValues options) {
+ private static Object newArray(KlassPointer hub, int length, @ConstantParameter Register threadRegister, @ConstantParameter OptionValues options) {
int layoutHelper = readLayoutHelper(hub);
int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift(INJECTED_VMCONFIG)) & layoutHelperLog2ElementSizeMask(INJECTED_VMCONFIG);
int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift(INJECTED_VMCONFIG)) & layoutHelperHeaderSizeMask(INJECTED_VMCONFIG);
@@ -122,26 +105,13 @@
printf("newArray: hub=%p\n", hub.asWord().rawValue());
}
- // check that array length is small enough for fast path.
Word thread = registerAsWord(threadRegister);
- boolean inlineContiguousAllocationSupported = GraalHotSpotVMConfigNode.inlineContiguousAllocationSupported();
- if (useFastTLABRefill(INJECTED_VMCONFIG) && inlineContiguousAllocationSupported && !useCMSIncrementalMode(INJECTED_VMCONFIG) && length >= 0 &&
- length <= MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH) {
- Word memory = refillAllocate(thread, intArrayHub, sizeInBytes, logging(options));
- if (memory.notEqual(0)) {
- if (logging(options)) {
- printf("newArray: allocated new array at %p\n", memory.rawValue());
- }
- return verifyObject(
- formatArray(hub, sizeInBytes, length, headerSize, memory, WordFactory.unsigned(arrayPrototypeMarkWord(INJECTED_VMCONFIG)), fillContents, false, null));
- }
- }
if (logging(options)) {
printf("newArray: calling new_array_c\n");
}
newArrayC(NEW_ARRAY_C, thread, hub, length);
- handlePendingException(thread, true);
+ handlePendingException(thread, true, true);
return verifyObject(getAndClearObjectResult(thread));
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewInstanceStub.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewInstanceStub.java Thu Aug 23 11:09:16 2018 -0400
@@ -24,50 +24,12 @@
package org.graalvm.compiler.hotspot.stubs;
-import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG;
-import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_METAACCESS;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.HEAP_END_LOCATION;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.HEAP_TOP_LOCATION;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.PROTOTYPE_MARK_WORD_LOCATION;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.TLAB_FAST_REFILL_WASTE_LOCATION;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.TLAB_NOF_REFILLS_LOCATION;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.TLAB_REFILL_WASTE_LIMIT_LOCATION;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.TLAB_SIZE_LOCATION;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.TLAB_SLOW_ALLOCATIONS_LOCATION;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.TLAB_THREAD_ALLOCATED_BYTES_LOCATION;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.getAndClearObjectResult;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.getArrayBaseOffset;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.initializeTlab;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.isInstanceKlassFullyInitialized;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.log2WordSize;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.prototypeMarkWordOffset;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.readLayoutHelper;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.readTlabEnd;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.readTlabStart;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.readTlabTop;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.registerAsWord;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.threadAllocatedBytesOffset;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.threadTlabSizeOffset;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.tlabAlignmentReserveInHeapWords;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.tlabFastRefillWasteOffset;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.tlabIntArrayMarkWord;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.tlabNumberOfRefillsOffset;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.tlabRefillWasteIncrement;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.tlabRefillWasteLimitOffset;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.tlabSlowAllocationsOffset;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.tlabStats;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.useCMSIncrementalMode;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.useFastTLABRefill;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.useG1GC;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.useTLAB;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.wordSize;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.writeTlabTop;
import static org.graalvm.compiler.hotspot.stubs.StubUtil.handlePendingException;
import static org.graalvm.compiler.hotspot.stubs.StubUtil.newDescriptor;
import static org.graalvm.compiler.hotspot.stubs.StubUtil.printf;
import static org.graalvm.compiler.hotspot.stubs.StubUtil.verifyObject;
-import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.FAST_PATH_PROBABILITY;
-import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability;
import org.graalvm.compiler.api.replacements.Fold;
import org.graalvm.compiler.api.replacements.Snippet;
@@ -77,19 +39,13 @@
import org.graalvm.compiler.graph.Node.NodeIntrinsic;
import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
-import org.graalvm.compiler.hotspot.nodes.GraalHotSpotVMConfigNode;
import org.graalvm.compiler.hotspot.nodes.StubForeignCallNode;
-import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp;
import org.graalvm.compiler.hotspot.replacements.NewObjectSnippets;
import org.graalvm.compiler.hotspot.word.KlassPointer;
-import org.graalvm.compiler.nodes.ConstantNode;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.word.Word;
-import jdk.internal.vm.compiler.word.WordFactory;
import jdk.vm.ci.code.Register;
-import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
-import jdk.vm.ci.meta.JavaKind;
/**
* Stub implementing the fast path for TLAB refill during instance class allocation. This stub is
@@ -105,33 +61,15 @@
@Override
protected Object[] makeConstArgs() {
- HotSpotResolvedObjectType intArrayType = (HotSpotResolvedObjectType) providers.getMetaAccess().lookupJavaType(int[].class);
int count = method.getSignature().getParameterCount(false);
Object[] args = new Object[count];
- assert checkConstArg(1, "intArrayHub");
- assert checkConstArg(2, "threadRegister");
- assert checkConstArg(3, "options");
- args[1] = ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), intArrayType.klass(), null);
- args[2] = providers.getRegisters().getThreadRegister();
- args[3] = options;
+ assert checkConstArg(1, "threadRegister");
+ assert checkConstArg(2, "options");
+ args[1] = providers.getRegisters().getThreadRegister();
+ args[2] = options;
return args;
}
- private static Word allocate(Word thread, int size) {
- Word top = readTlabTop(thread);
- Word end = readTlabEnd(thread);
- Word newTop = top.add(size);
- /*
- * this check might lead to problems if the TLAB is within 16GB of the address space end
- * (checked in c++ code)
- */
- if (probability(FAST_PATH_PROBABILITY, newTop.belowOrEqual(end))) {
- writeTlabTop(thread, newTop);
- return top;
- }
- return WordFactory.zero();
- }
-
@Fold
static boolean logging(OptionValues options) {
return StubOptions.TraceNewInstanceStub.getValue(options);
@@ -142,168 +80,23 @@
* -XX:-UseTLAB).
*
* @param hub the hub of the object to be allocated
- * @param intArrayHub the hub for {@code int[].class}
*/
@Snippet
- private static Object newInstance(KlassPointer hub, @ConstantParameter KlassPointer intArrayHub, @ConstantParameter Register threadRegister, @ConstantParameter OptionValues options) {
+ private static Object newInstance(KlassPointer hub, @ConstantParameter Register threadRegister, @ConstantParameter OptionValues options) {
/*
* The type is known to be an instance so Klass::_layout_helper is the instance size as a
* raw number
*/
Word thread = registerAsWord(threadRegister);
- boolean inlineContiguousAllocationSupported = GraalHotSpotVMConfigNode.inlineContiguousAllocationSupported();
- if (useFastTLABRefill(INJECTED_VMCONFIG) && !forceSlowPath(options) && inlineContiguousAllocationSupported && !useCMSIncrementalMode(INJECTED_VMCONFIG)) {
- if (isInstanceKlassFullyInitialized(hub)) {
- int sizeInBytes = readLayoutHelper(hub);
- Word memory = refillAllocate(thread, intArrayHub, sizeInBytes, logging(options));
- if (memory.notEqual(0)) {
- Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(INJECTED_VMCONFIG), PROTOTYPE_MARK_WORD_LOCATION);
- NewObjectSnippets.formatObjectForStub(hub, sizeInBytes, memory, prototypeMarkWord);
- return verifyObject(memory.toObject());
- }
- }
- }
-
if (logging(options)) {
printf("newInstance: calling new_instance_c\n");
}
newInstanceC(NEW_INSTANCE_C, thread, hub);
- handlePendingException(thread, true);
+ handlePendingException(thread, true, true);
return verifyObject(getAndClearObjectResult(thread));
}
- /**
- * Attempts to refill the current thread's TLAB and retries the allocation.
- *
- * @param intArrayHub the hub for {@code int[].class}
- * @param sizeInBytes the size of the allocation
- * @param log specifies if logging is enabled
- *
- * @return the newly allocated, uninitialized chunk of memory, or {@link WordFactory#zero()} if
- * the operation was unsuccessful
- */
- static Word refillAllocate(Word thread, KlassPointer intArrayHub, int sizeInBytes, boolean log) {
- // If G1 is enabled, the "eden" allocation space is not the same always
- // and therefore we have to go to slowpath to allocate a new TLAB.
- if (useG1GC(INJECTED_VMCONFIG)) {
- return WordFactory.zero();
- }
- if (!useTLAB(INJECTED_VMCONFIG)) {
- return edenAllocate(WordFactory.unsigned(sizeInBytes), log);
- }
- Word intArrayMarkWord = WordFactory.unsigned(tlabIntArrayMarkWord(INJECTED_VMCONFIG));
- int alignmentReserveInBytes = tlabAlignmentReserveInHeapWords(INJECTED_VMCONFIG) * wordSize();
-
- Word top = readTlabTop(thread);
- Word end = readTlabEnd(thread);
-
- // calculate amount of free space
- long tlabFreeSpaceInBytes = end.subtract(top).rawValue();
-
- if (log) {
- printf("refillTLAB: thread=%p\n", thread.rawValue());
- printf("refillTLAB: top=%p\n", top.rawValue());
- printf("refillTLAB: end=%p\n", end.rawValue());
- printf("refillTLAB: tlabFreeSpaceInBytes=%ld\n", tlabFreeSpaceInBytes);
- }
-
- long tlabFreeSpaceInWords = tlabFreeSpaceInBytes >>> log2WordSize();
-
- // Retain TLAB and allocate object in shared space if
- // the amount free in the TLAB is too large to discard.
- Word refillWasteLimit = thread.readWord(tlabRefillWasteLimitOffset(INJECTED_VMCONFIG), TLAB_REFILL_WASTE_LIMIT_LOCATION);
- if (tlabFreeSpaceInWords <= refillWasteLimit.rawValue()) {
- if (tlabStats(INJECTED_VMCONFIG)) {
- // increment number of refills
- thread.writeInt(tlabNumberOfRefillsOffset(INJECTED_VMCONFIG), thread.readInt(tlabNumberOfRefillsOffset(INJECTED_VMCONFIG), TLAB_NOF_REFILLS_LOCATION) + 1, TLAB_NOF_REFILLS_LOCATION);
- if (log) {
- printf("thread: %p -- number_of_refills %d\n", thread.rawValue(), thread.readInt(tlabNumberOfRefillsOffset(INJECTED_VMCONFIG), TLAB_NOF_REFILLS_LOCATION));
- }
- // accumulate wastage
- int wastage = thread.readInt(tlabFastRefillWasteOffset(INJECTED_VMCONFIG), TLAB_FAST_REFILL_WASTE_LOCATION) + (int) tlabFreeSpaceInWords;
- if (log) {
- printf("thread: %p -- accumulated wastage %d\n", thread.rawValue(), wastage);
- }
- thread.writeInt(tlabFastRefillWasteOffset(INJECTED_VMCONFIG), wastage, TLAB_FAST_REFILL_WASTE_LOCATION);
- }
-
- // if TLAB is currently allocated (top or end != null) then
- // fill [top, end + alignment_reserve) with array object
- if (top.notEqual(0)) {
- int headerSize = getArrayBaseOffset(INJECTED_METAACCESS, JavaKind.Int);
- // just like the HotSpot assembler stubs, assumes that tlabFreeSpaceInInts fits in
- // an int
- int tlabFreeSpaceInInts = (int) tlabFreeSpaceInBytes >>> 2;
- int length = ((alignmentReserveInBytes - headerSize) >>> 2) + tlabFreeSpaceInInts;
- NewObjectSnippets.formatArray(intArrayHub, 0, length, headerSize, top, intArrayMarkWord, false, false, null);
-
- long allocated = thread.readLong(threadAllocatedBytesOffset(INJECTED_VMCONFIG), TLAB_THREAD_ALLOCATED_BYTES_LOCATION);
- allocated = allocated + top.subtract(readTlabStart(thread)).rawValue();
- thread.writeLong(threadAllocatedBytesOffset(INJECTED_VMCONFIG), allocated, TLAB_THREAD_ALLOCATED_BYTES_LOCATION);
- }
-
- // refill the TLAB with an eden allocation
- Word tlabRefillSizeInWords = thread.readWord(threadTlabSizeOffset(INJECTED_VMCONFIG), TLAB_SIZE_LOCATION);
- Word tlabRefillSizeInBytes = tlabRefillSizeInWords.multiply(wordSize());
- // allocate new TLAB, address returned in top
- top = edenAllocate(tlabRefillSizeInBytes, log);
- if (top.notEqual(0)) {
- end = top.add(tlabRefillSizeInBytes.subtract(alignmentReserveInBytes));
- initializeTlab(thread, top, end);
-
- return NewInstanceStub.allocate(thread, sizeInBytes);
- } else {
- return WordFactory.zero();
- }
- } else {
- // Retain TLAB
- Word newRefillWasteLimit = refillWasteLimit.add(tlabRefillWasteIncrement(INJECTED_VMCONFIG));
- thread.writeWord(tlabRefillWasteLimitOffset(INJECTED_VMCONFIG), newRefillWasteLimit, TLAB_REFILL_WASTE_LIMIT_LOCATION);
- if (log) {
- printf("refillTLAB: retaining TLAB - newRefillWasteLimit=%p\n", newRefillWasteLimit.rawValue());
- }
-
- if (tlabStats(INJECTED_VMCONFIG)) {
- thread.writeInt(tlabSlowAllocationsOffset(INJECTED_VMCONFIG), thread.readInt(tlabSlowAllocationsOffset(INJECTED_VMCONFIG), TLAB_SLOW_ALLOCATIONS_LOCATION) + 1,
- TLAB_SLOW_ALLOCATIONS_LOCATION);
- }
-
- return edenAllocate(WordFactory.unsigned(sizeInBytes), log);
- }
- }
-
- /**
- * Attempts to allocate a chunk of memory from Eden space.
- *
- * @param sizeInBytes the size of the chunk to allocate
- * @param log specifies if logging is enabled
- * @return the allocated chunk or {@link WordFactory#zero()} if allocation fails
- */
- public static Word edenAllocate(Word sizeInBytes, boolean log) {
- final long heapTopRawAddress = GraalHotSpotVMConfigNode.heapTopAddress();
- final long heapEndRawAddress = GraalHotSpotVMConfigNode.heapEndAddress();
-
- Word heapTopAddress = WordFactory.unsigned(heapTopRawAddress);
- Word heapEndAddress = WordFactory.unsigned(heapEndRawAddress);
-
- while (true) {
- Word heapTop = heapTopAddress.readWord(0, HEAP_TOP_LOCATION);
- Word newHeapTop = heapTop.add(sizeInBytes);
- if (newHeapTop.belowOrEqual(heapTop)) {
- return WordFactory.zero();
- }
-
- Word heapEnd = heapEndAddress.readWord(0, HEAP_END_LOCATION);
- if (newHeapTop.aboveThan(heapEnd)) {
- return WordFactory.zero();
- }
- if (heapTopAddress.logicCompareAndSwapWord(0, heapTop, newHeapTop, HEAP_TOP_LOCATION)) {
- return heapTop;
- }
- }
- }
-
@Fold
static boolean forceSlowPath(OptionValues options) {
return StubOptions.ForceUseOfNewInstanceStub.getValue(options);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/StubUtil.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/StubUtil.java Thu Aug 23 11:09:16 2018 -0400
@@ -27,6 +27,7 @@
import static jdk.vm.ci.meta.DeoptimizationReason.RuntimeConstraint;
import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_VMCONFIG;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.clearPendingException;
+import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.getPendingException;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.getAndClearObjectResult;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.loadHubIntrinsic;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.verifyOops;
@@ -95,8 +96,8 @@
return new ForeignCallDescriptor(name, found.getReturnType(), cCallTypes);
}
- public static void handlePendingException(Word thread, boolean isObjectResult) {
- if (clearPendingException(thread) != null) {
+ public static void handlePendingException(Word thread, boolean shouldClearException, boolean isObjectResult) {
+ if ((shouldClearException && clearPendingException(thread) != null) || (!shouldClearException && getPendingException(thread) != null)) {
if (isObjectResult) {
getAndClearObjectResult(thread);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java Thu Aug 23 11:09:16 2018 -0400
@@ -1929,9 +1929,15 @@
}
boolean check(boolean pluginResult) {
- if (pluginResult == true) {
+ if (pluginResult) {
+ /*
+ * If lastInstr is null, even if this method has a non-void return type, the method
+ * doesn't return a value, it probably throws an exception.
+ */
int expectedStackSize = beforeStackSize + resultType.getSlotCount();
- assert expectedStackSize == frameState.stackSize() : error("plugin manipulated the stack incorrectly: expected=%d, actual=%d", expectedStackSize, frameState.stackSize());
+ assert lastInstr == null || expectedStackSize == frameState.stackSize() : error("plugin manipulated the stack incorrectly: expected=%d, actual=%d", expectedStackSize,
+ frameState.stackSize());
+
NodeIterable<Node> newNodes = graph.getNewNodes(mark);
assert !needsNullCheck || isPointerNonNull(args[0].stamp(NodeView.DEFAULT)) : error("plugin needs to null check the receiver of %s: receiver=%s", targetMethod.format("%H.%n(%p)"),
args[0]);
@@ -3544,6 +3550,11 @@
}
@Override
+ public ValueNode pop(JavaKind slotKind) {
+ return frameState.pop(slotKind);
+ }
+
+ @Override
public ConstantReflectionProvider getConstantReflection() {
return constantReflection;
}
@@ -4277,13 +4288,7 @@
JavaKind fieldKind = resolvedField.getJavaKind();
- if (resolvedField.isVolatile() && fieldRead instanceof LoadFieldNode) {
- StateSplitProxyNode readProxy = append(genVolatileFieldReadProxy(fieldRead));
- frameState.push(fieldKind, readProxy);
- readProxy.setStateAfter(frameState.create(stream.nextBCI(), readProxy));
- } else {
- frameState.push(fieldKind, fieldRead);
- }
+ pushLoadField(resolvedField, fieldRead, fieldKind);
}
/**
@@ -4334,10 +4339,8 @@
return needsExplicitException();
}
- /**
- * Returns true if an explicit exception check should be emitted.
- */
- protected boolean needsExplicitException() {
+ @Override
+ public boolean needsExplicitException() {
BytecodeExceptionMode exceptionMode = graphBuilderConfig.getBytecodeExceptionMode();
if (exceptionMode == BytecodeExceptionMode.CheckAll || StressExplicitExceptionCode.getValue(options)) {
return true;
@@ -4347,6 +4350,15 @@
return false;
}
+ @Override
+ public AbstractBeginNode genExplicitExceptionEdge(BytecodeExceptionKind exceptionKind) {
+ BytecodeExceptionNode exceptionNode = graph.add(new BytecodeExceptionNode(metaAccess, exceptionKind));
+ exceptionNode.setStateAfter(createFrameState(bci(), exceptionNode));
+ AbstractBeginNode exceptionDispatch = handleException(exceptionNode, bci(), false);
+ exceptionNode.setNext(exceptionDispatch);
+ return BeginNode.begin(exceptionNode);
+ }
+
protected void genPutField(int cpi, int opcode) {
JavaField field = lookupField(cpi, opcode);
genPutField(field);
@@ -4417,7 +4429,25 @@
}
}
- frameState.push(field.getJavaKind(), append(genLoadField(null, resolvedField)));
+ ValueNode fieldRead = append(genLoadField(null, resolvedField));
+ JavaKind fieldKind = resolvedField.getJavaKind();
+
+ pushLoadField(resolvedField, fieldRead, fieldKind);
+ }
+
+ /**
+ * Pushes a loaded field onto the stack. If the loaded field is volatile, a
+ * {@link StateSplitProxyNode} is appended so that deoptimization does not deoptimize to a point
+ * before the field load.
+ */
+ private void pushLoadField(ResolvedJavaField resolvedField, ValueNode fieldRead, JavaKind fieldKind) {
+ if (resolvedField.isVolatile() && fieldRead instanceof LoadFieldNode) {
+ StateSplitProxyNode readProxy = append(genVolatileFieldReadProxy(fieldRead));
+ frameState.push(fieldKind, readProxy);
+ readProxy.setStateAfter(frameState.create(stream.nextBCI(), readProxy));
+ } else {
+ frameState.push(fieldKind, fieldRead);
+ }
}
private ResolvedJavaField resolveStaticFieldAccess(JavaField field, ValueNode value) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/IntegerExactOpSpeculation.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.java;
+
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.SpeculationLog.SpeculationReason;
+
+public final class IntegerExactOpSpeculation implements SpeculationReason {
+
+ public enum IntegerExactOp {
+ INTEGER_ADD_EXACT,
+ INTEGER_INCREMENT_EXACT,
+ INTEGER_SUBTRACT_EXACT,
+ INTEGER_DECREMENT_EXACT,
+ INTEGER_MULTIPLY_EXACT
+ }
+
+ protected final String methodDescriptor;
+ protected final IntegerExactOp op;
+
+ public IntegerExactOpSpeculation(ResolvedJavaMethod method, IntegerExactOp op) {
+ this.methodDescriptor = method.format("%H.%n(%p)%R");
+ this.op = op;
+ }
+
+ @Override
+ public int hashCode() {
+ return methodDescriptor.hashCode() * 31 + op.ordinal();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof IntegerExactOpSpeculation) {
+ IntegerExactOpSpeculation other = (IntegerExactOpSpeculation) obj;
+ return op.equals(other.op) && methodDescriptor.equals(other.methodDescriptor);
+ }
+ return false;
+ }
+
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/backend/LargeConstantSectionTest.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/backend/LargeConstantSectionTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -127,12 +127,12 @@
for (int i = 0; i < labels.length; i++) {
mv.visitLabel(labels[i]);
mv.visitFrame(Opcodes.F_NEW, 1, new Object[]{Opcodes.INTEGER}, 0, new Object[]{});
- mv.visitLdcInsn(new Long(LARGE_CONSTANT + i));
+ mv.visitLdcInsn(Long.valueOf(LARGE_CONSTANT + i));
mv.visitInsn(LRETURN);
}
mv.visitLabel(defaultLabel);
mv.visitFrame(Opcodes.F_NEW, 1, new Object[]{Opcodes.INTEGER}, 0, new Object[]{});
- mv.visitLdcInsn(new Long(3L));
+ mv.visitLdcInsn(Long.valueOf(3L));
mv.visitInsn(LRETURN);
Label end = new Label();
mv.visitLabel(end);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/bytecode/BC_i2d.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/bytecode/BC_i2d.java Thu Aug 23 11:09:16 2018 -0400
@@ -68,7 +68,7 @@
@Test
public void run6() throws Throwable {
- runTest("test", new Integer(Short.MAX_VALUE));
+ runTest("test", Integer.valueOf(Short.MAX_VALUE));
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/except/UntrustedInterfaces.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/except/UntrustedInterfaces.java Thu Aug 23 11:09:16 2018 -0400
@@ -151,8 +151,8 @@
// Checkstyle: stop
@BeforeClass
- public static void setUp() throws InstantiationException, IllegalAccessException, ClassNotFoundException {
- poisonPill = (Pill) new PoisonLoader().findClass(PoisonLoader.POISON_IMPL_NAME).newInstance();
+ public static void setUp() throws Exception {
+ poisonPill = (Pill) new PoisonLoader().findClass(PoisonLoader.POISON_IMPL_NAME).getDeclaredConstructor().newInstance();
}
// Checkstyle: resume
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotpath/HP_allocate02.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotpath/HP_allocate02.java Thu Aug 23 11:09:16 2018 -0400
@@ -32,6 +32,7 @@
*/
public class HP_allocate02 extends JTTTest {
+ @SuppressWarnings("deprecation")
public static int test(int count) {
int sum = 0;
for (int i = 0; i < count; i++) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotspot/NotOnDebug.java Fri Aug 10 14:56:29 2018 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package org.graalvm.compiler.jtt.hotspot;
-
-import org.junit.rules.DisableOnDebug;
-import org.junit.rules.TestRule;
-import org.junit.rules.Timeout;
-
-public final class NotOnDebug {
- public static TestRule create(Timeout seconds) {
- try {
- return new DisableOnDebug(seconds);
- } catch (LinkageError ex) {
- return null;
- }
- }
-
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotspot/Test6823354.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotspot/Test6823354.java Thu Aug 23 11:09:16 2018 -0400
@@ -199,6 +199,7 @@
loadandrunclass(classname);
}
+ @SuppressWarnings("deprecation")
static void loadandrunclass(String classname) throws Exception {
Class<?> cl = Class.forName(classname);
URLClassLoader apploader = (URLClassLoader) cl.getClassLoader();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotspot/Test6959129.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotspot/Test6959129.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,11 +28,10 @@
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
-import org.junit.rules.Timeout;
public class Test6959129 extends JTTTest {
- @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
+ @Rule public TestRule timeout = createTimeoutSeconds(20);
public static long test() {
int min = Integer.MAX_VALUE - 30000;
@@ -82,7 +81,6 @@
@Test
public void run0() throws Throwable {
- initializeForTimeout();
runTest("test");
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/micro/ReferenceMap01.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/micro/ReferenceMap01.java Thu Aug 23 11:09:16 2018 -0400
@@ -32,24 +32,24 @@
*/
public class ReferenceMap01 extends JTTTest {
- public static Integer val1 = new Integer(3);
- public static Integer val2 = new Integer(4);
+ public static Integer val1 = Integer.valueOf(3);
+ public static Integer val2 = Integer.valueOf(4);
@SuppressWarnings("unused")
private static String foo(String[] a) {
String[] args = new String[]{"78"};
- Integer i1 = new Integer(1);
- Integer i2 = new Integer(2);
+ Integer i1 = Integer.valueOf(1);
+ Integer i2 = Integer.valueOf(2);
Integer i3 = val1;
Integer i4 = val2;
- Integer i5 = new Integer(5);
- Integer i6 = new Integer(6);
- Integer i7 = new Integer(7);
- Integer i8 = new Integer(8);
- Integer i9 = new Integer(9);
- Integer i10 = new Integer(10);
- Integer i11 = new Integer(11);
- Integer i12 = new Integer(12);
+ Integer i5 = Integer.valueOf(5);
+ Integer i6 = Integer.valueOf(6);
+ Integer i7 = Integer.valueOf(7);
+ Integer i8 = Integer.valueOf(8);
+ Integer i9 = Integer.valueOf(9);
+ Integer i10 = Integer.valueOf(10);
+ Integer i11 = Integer.valueOf(11);
+ Integer i12 = Integer.valueOf(12);
System.gc();
int sum = i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8 + i9 + i10 + i11 + i12;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/reflect/Class_newInstance01.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/reflect/Class_newInstance01.java Thu Aug 23 11:09:16 2018 -0400
@@ -32,6 +32,7 @@
public final class Class_newInstance01 extends JTTTest {
+ @SuppressWarnings("deprecation")
public static boolean test(int i) throws IllegalAccessException, InstantiationException {
if (i == 0) {
return Class_newInstance01.class.newInstance() != null;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/reflect/Class_newInstance02.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/reflect/Class_newInstance02.java Thu Aug 23 11:09:16 2018 -0400
@@ -32,6 +32,7 @@
public final class Class_newInstance02 extends JTTTest {
+ @SuppressWarnings("deprecation")
public static boolean test(int i) throws IllegalAccessException, InstantiationException {
if (i == 0) {
// note: we rely on the other class here.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/reflect/Class_newInstance03.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/reflect/Class_newInstance03.java Thu Aug 23 11:09:16 2018 -0400
@@ -35,6 +35,7 @@
public abstract static class AbstractClass {
}
+ @SuppressWarnings("deprecation")
public static boolean test(int i) throws IllegalAccessException, InstantiationException {
if (i == 0) {
return AbstractClass.class.newInstance() != null;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/reflect/Class_newInstance06.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/reflect/Class_newInstance06.java Thu Aug 23 11:09:16 2018 -0400
@@ -40,6 +40,7 @@
}
}
+ @SuppressWarnings("deprecation")
public static boolean test(int i) throws IllegalAccessException, InstantiationException {
if (i == 0) {
return Class_newInstance.class.newInstance() != null;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/reflect/Class_newInstance07.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/reflect/Class_newInstance07.java Thu Aug 23 11:09:16 2018 -0400
@@ -39,6 +39,7 @@
}
}
+ @SuppressWarnings("deprecation")
public static boolean test(int i) throws IllegalAccessException, InstantiationException {
if (i == 0) {
return Class_newInstance.class.newInstance() != null;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitor_contended01.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitor_contended01.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,15 +27,13 @@
package org.graalvm.compiler.jtt.threads;
import org.graalvm.compiler.jtt.JTTTest;
-import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
-import org.junit.rules.Timeout;
public final class Monitor_contended01 extends JTTTest {
- @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
+ @Rule public TestRule timeout = createTimeoutSeconds(20);
private static class TestClass implements Runnable {
boolean started = false;
@@ -84,7 +82,6 @@
@Test
public void run0() throws Throwable {
- initializeForTimeout();
runTest("test");
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitor_notowner01.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitor_notowner01.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,15 +27,13 @@
package org.graalvm.compiler.jtt.threads;
import org.graalvm.compiler.jtt.JTTTest;
-import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
-import org.junit.rules.Timeout;
public class Monitor_notowner01 extends JTTTest {
- @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
+ @Rule public TestRule timeout = createTimeoutSeconds(20);
static Object monitor = new Object();
static Object finished = new Object();
@@ -73,7 +71,6 @@
@Test
public void run0() throws Throwable {
- initializeForTimeout();
runTest("test");
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitorenter01.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitorenter01.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,15 +27,13 @@
package org.graalvm.compiler.jtt.threads;
import org.graalvm.compiler.jtt.JTTTest;
-import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
-import org.junit.rules.Timeout;
public final class Monitorenter01 extends JTTTest {
- @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
+ @Rule public TestRule timeout = createTimeoutSeconds(20);
static final Object object = new Object();
@@ -50,7 +48,6 @@
@Test
public void run0() throws Throwable {
- initializeForTimeout();
runTest("test");
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitorenter02.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitorenter02.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,15 +27,13 @@
package org.graalvm.compiler.jtt.threads;
import org.graalvm.compiler.jtt.JTTTest;
-import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
-import org.junit.rules.Timeout;
public final class Monitorenter02 extends JTTTest {
- @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
+ @Rule public TestRule timeout = createTimeoutSeconds(20);
static final Object object = new Object();
@@ -54,7 +52,6 @@
@Test
public void run0() throws Throwable {
- initializeForTimeout();
runTest("test");
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait01.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait01.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,15 +27,13 @@
package org.graalvm.compiler.jtt.threads;
import org.graalvm.compiler.jtt.JTTTest;
-import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
-import org.junit.rules.Timeout;
public class Object_wait01 extends JTTTest {
- @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
+ @Rule public TestRule timeout = createTimeoutSeconds(20);
private static class TestClass implements Runnable {
@Override
@@ -69,25 +67,21 @@
@Test
public void run0() throws Throwable {
- initializeForTimeout();
runTest("test", 0);
}
@Test
public void run1() throws Throwable {
- initializeForTimeout();
runTest("test", 1);
}
@Test
public void run2() throws Throwable {
- initializeForTimeout();
runTest("test", 3);
}
@Test
public void run3() throws Throwable {
- initializeForTimeout();
runTest("test", 15);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait02.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait02.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,15 +27,13 @@
package org.graalvm.compiler.jtt.threads;
import org.graalvm.compiler.jtt.JTTTest;
-import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
-import org.junit.rules.Timeout;
public class Object_wait02 extends JTTTest {
- @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
+ @Rule public TestRule timeout = createTimeoutSeconds(20);
private static class TestClass implements Runnable {
@Override
@@ -70,19 +68,16 @@
@Test
public void run0() throws Throwable {
- initializeForTimeout();
runTest("test", 0);
}
@Test
public void run1() throws Throwable {
- initializeForTimeout();
runTest("test", 1);
}
@Test
public void run2() throws Throwable {
- initializeForTimeout();
runTest("test", 2);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait03.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait03.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,10 +33,8 @@
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
-import org.junit.rules.Timeout;
import jdk.vm.ci.meta.ResolvedJavaMethod;
-import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
public class Object_wait03 extends JTTTest {
@@ -50,7 +48,7 @@
*/
static final long TIMEOUT_MS = COMPILATION_TIMEOUT_MS * 2;
- @Rule public TestRule timeout = NotOnDebug.create(Timeout.millis(TIMEOUT_MS));
+ @Rule public TestRule timeout = createTimeoutMillis(TIMEOUT_MS);
private static class TestClass implements Runnable {
@Override
@@ -121,7 +119,6 @@
}
private void run(int i) throws Throwable {
- initializeForTimeout();
try {
runTest("test", i);
} catch (CancellationBailoutException e) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait04.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait04.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,15 +27,13 @@
package org.graalvm.compiler.jtt.threads;
import org.graalvm.compiler.jtt.JTTTest;
-import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
-import org.junit.rules.Timeout;
public class Object_wait04 extends JTTTest {
- @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
+ @Rule public TestRule timeout = createTimeoutSeconds(20);
private static class TestClass implements Runnable {
@Override
@@ -80,37 +78,31 @@
@Test
public void run0() throws Throwable {
- initializeForTimeout();
runTest("test", 0);
}
@Test
public void run1() throws Throwable {
- initializeForTimeout();
runTest("test", 1);
}
@Test
public void run2() throws Throwable {
- initializeForTimeout();
runTest("test", 2);
}
@Test
public void run3() throws Throwable {
- initializeForTimeout();
runTest("test", 3);
}
@Test
public void run4() throws Throwable {
- initializeForTimeout();
runTest("test", 4);
}
@Test
public void run5() throws Throwable {
- initializeForTimeout();
runTest("test", 5);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/SynchronizedLoopExit01.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/SynchronizedLoopExit01.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,11 +27,9 @@
package org.graalvm.compiler.jtt.threads;
import org.graalvm.compiler.jtt.JTTTest;
-import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
-import org.junit.rules.Timeout;
/**
* Inspired by {@code com.sun.media.sound.DirectAudioDevice$DirectDL.drain()}.
@@ -41,7 +39,7 @@
*/
public final class SynchronizedLoopExit01 extends JTTTest {
- @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
+ @Rule public TestRule timeout = createTimeoutSeconds(20);
protected Object object = new Object();
protected volatile boolean drained = false;
@@ -62,7 +60,6 @@
@Test
public void run0() throws Throwable {
- initializeForTimeout();
runTest("test");
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted02.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted02.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,17 +29,15 @@
package org.graalvm.compiler.jtt.threads;
import org.graalvm.compiler.jtt.JTTTest;
-import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
-import org.junit.rules.Timeout;
//Test all, mainly monitors
public class Thread_isInterrupted02 extends JTTTest {
- @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
+ @Rule public TestRule timeout = createTimeoutSeconds(20);
private static final Object start = new Object();
private static final Object end = new Object();
@@ -112,13 +110,11 @@
@Test
public void run0() throws Throwable {
- initializeForTimeout();
runTest("test", 0, 0);
}
@Test
public void run1() throws Throwable {
- initializeForTimeout();
runTest("test", 1, 500);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted03.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted03.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,11 +25,9 @@
package org.graalvm.compiler.jtt.threads;
import org.graalvm.compiler.jtt.JTTTest;
-import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
-import org.junit.rules.Timeout;
/*
*/
@@ -37,7 +35,7 @@
// Interrupted while sleeping, throws an interrupted exception
public class Thread_isInterrupted03 extends JTTTest {
- @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
+ @Rule public TestRule timeout = createTimeoutSeconds(20);
public static boolean test() throws InterruptedException {
final Thread1 thread = new Thread1();
@@ -78,7 +76,6 @@
@Test
public void run0() throws Throwable {
- initializeForTimeout();
runTest("test");
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted05.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted05.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,11 +25,9 @@
package org.graalvm.compiler.jtt.threads;
import org.graalvm.compiler.jtt.JTTTest;
-import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
-import org.junit.rules.Timeout;
/*
*/
@@ -37,7 +35,7 @@
// Interrupted during wait, with interrupter joining
public class Thread_isInterrupted05 extends JTTTest {
- @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
+ @Rule public TestRule timeout = createTimeoutSeconds(20);
public static boolean test() throws InterruptedException {
final WaitInterruptee waitInterruptee = new WaitInterruptee();
@@ -76,7 +74,6 @@
@Test
public void run0() throws Throwable {
- initializeForTimeout();
runTest("test");
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join01.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join01.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,15 +27,13 @@
package org.graalvm.compiler.jtt.threads;
import org.graalvm.compiler.jtt.JTTTest;
-import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
-import org.junit.rules.Timeout;
public class Thread_join01 extends JTTTest {
- @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
+ @Rule public TestRule timeout = createTimeoutSeconds(20);
private static class TestClass implements Runnable {
@Override
@@ -56,7 +54,6 @@
@Test
public void run0() throws Throwable {
- initializeForTimeout();
runTest("test");
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join02.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join02.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,15 +30,13 @@
package org.graalvm.compiler.jtt.threads;
import org.graalvm.compiler.jtt.JTTTest;
-import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
-import org.junit.rules.Timeout;
public class Thread_join02 extends JTTTest {
- @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
+ @Rule public TestRule timeout = createTimeoutSeconds(20);
private static class TestClass implements Runnable {
@Override
@@ -63,7 +61,6 @@
@Test
public void run0() throws Throwable {
- initializeForTimeout();
runTest("test");
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join03.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join03.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,15 +30,13 @@
package org.graalvm.compiler.jtt.threads;
import org.graalvm.compiler.jtt.JTTTest;
-import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
-import org.junit.rules.Timeout;
public class Thread_join03 extends JTTTest {
- @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
+ @Rule public TestRule timeout = createTimeoutSeconds(20);
private static class TestClass implements Runnable {
@Override
@@ -60,7 +58,6 @@
@Test
public void run0() throws Throwable {
- initializeForTimeout();
runTest("test");
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_sleep01.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_sleep01.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,15 +27,13 @@
package org.graalvm.compiler.jtt.threads;
import org.graalvm.compiler.jtt.JTTTest;
-import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
-import org.junit.rules.Timeout;
public final class Thread_sleep01 extends JTTTest {
- @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
+ @Rule public TestRule timeout = createTimeoutSeconds(20);
public static boolean test(int i) throws InterruptedException {
final long before = System.currentTimeMillis();
@@ -45,19 +43,16 @@
@Test
public void run0() throws Throwable {
- initializeForTimeout();
runTest("test", 10);
}
@Test
public void run1() throws Throwable {
- initializeForTimeout();
runTest("test", 20);
}
@Test
public void run2() throws Throwable {
- initializeForTimeout();
runTest("test", 100);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_yield01.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_yield01.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,15 +27,13 @@
package org.graalvm.compiler.jtt.threads;
import org.graalvm.compiler.jtt.JTTTest;
-import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
-import org.junit.rules.Timeout;
public final class Thread_yield01 extends JTTTest {
- @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
+ @Rule public TestRule timeout = createTimeoutSeconds(20);
public static boolean test() {
Thread.yield();
@@ -44,7 +42,6 @@
@Test
public void run0() throws Throwable {
- initializeForTimeout();
runTest("test");
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArrayCompareToOp.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArrayCompareToOp.java Thu Aug 23 11:09:16 2018 -0400
@@ -28,9 +28,6 @@
import static jdk.vm.ci.code.ValueUtil.asRegister;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
-import java.lang.reflect.Array;
-import java.lang.reflect.Field;
-
import org.graalvm.compiler.asm.Label;
import org.graalvm.compiler.asm.aarch64.AArch64Address;
import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler;
@@ -44,7 +41,6 @@
import jdk.vm.ci.code.Register;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.Value;
-import sun.misc.Unsafe;
/**
* Emits code which compares two arrays lexicographically. If the CPU supports any vector
@@ -82,10 +78,8 @@
this.kind2 = kind2;
// Both offsets should be the same but better be safe than sorry.
- Class<?> array1Class = Array.newInstance(kind1.toJavaClass(), 0).getClass();
- Class<?> array2Class = Array.newInstance(kind2.toJavaClass(), 0).getClass();
- this.array1BaseOffset = UNSAFE.arrayBaseOffset(array1Class);
- this.array2BaseOffset = UNSAFE.arrayBaseOffset(array2Class);
+ this.array1BaseOffset = tool.getProviders().getArrayOffsetProvider().arrayBaseOffset(kind1);
+ this.array2BaseOffset = tool.getProviders().getArrayOffsetProvider().arrayBaseOffset(kind2);
this.resultValue = result;
@@ -111,22 +105,6 @@
this.temp6 = tool.newVariable(LIRKind.unknownReference(tool.target().arch.getWordKind()));
}
- private static final Unsafe UNSAFE = initUnsafe();
-
- private static Unsafe initUnsafe() {
- try {
- return Unsafe.getUnsafe();
- } catch (SecurityException se) {
- try {
- Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
- theUnsafe.setAccessible(true);
- return (Unsafe) theUnsafe.get(Unsafe.class);
- } catch (Exception e) {
- throw new RuntimeException("exception while trying to get Unsafe", e);
- }
- }
- }
-
@Override
protected void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64LIRFlagsVersioned.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64LIRFlagsVersioned.java Thu Aug 23 11:09:16 2018 -0400
@@ -34,4 +34,4 @@
AArch64 aarch64 = (AArch64) arch;
return aarch64.getFeatures().contains(CPUFeature.LSE) || aarch64.getFlags().contains(Flag.UseLSE);
}
-}
\ No newline at end of file
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayCompareToOp.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayCompareToOp.java Thu Aug 23 11:09:16 2018 -0400
@@ -32,13 +32,11 @@
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
-import java.lang.reflect.Array;
-import java.lang.reflect.Field;
+import java.util.EnumSet;
import org.graalvm.compiler.asm.Label;
import org.graalvm.compiler.asm.amd64.AMD64Address;
import org.graalvm.compiler.asm.amd64.AMD64Address.Scale;
-import org.graalvm.compiler.asm.amd64.AMD64Assembler.AvxVectorLen;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag;
import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
import org.graalvm.compiler.core.common.LIRKind;
@@ -54,7 +52,6 @@
import jdk.vm.ci.code.TargetDescription;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.Value;
-import sun.misc.Unsafe;
/**
* Emits code which compares two arrays lexicographically. If the CPU supports any vector
@@ -87,10 +84,8 @@
this.kind2 = kind2;
// Both offsets should be the same but better be safe than sorry.
- Class<?> array1Class = Array.newInstance(kind1.toJavaClass(), 0).getClass();
- Class<?> array2Class = Array.newInstance(kind2.toJavaClass(), 0).getClass();
- this.array1BaseOffset = UNSAFE.arrayBaseOffset(array1Class);
- this.array2BaseOffset = UNSAFE.arrayBaseOffset(array2Class);
+ this.array1BaseOffset = tool.getProviders().getArrayOffsetProvider().arrayBaseOffset(kind1);
+ this.array2BaseOffset = tool.getProviders().getArrayOffsetProvider().arrayBaseOffset(kind2);
this.resultValue = result;
this.array1Value = array1;
@@ -126,9 +121,9 @@
return arch.getFeatures().contains(CPUFeature.AVX2);
}
- private static boolean supportsAVX512VLBW(@SuppressWarnings("unused") TargetDescription target) {
- // TODO Add EVEX encoder in our assembler.
- return false;
+ private static boolean supportsAVX512VLBW(TargetDescription target) {
+ EnumSet<CPUFeature> features = ((AMD64) target.arch).getFeatures();
+ return features.contains(CPUFeature.AVX512BW) && features.contains(CPUFeature.AVX512VL);
}
@Override
@@ -326,15 +321,15 @@
masm.bind(COMPARE_WIDE_VECTORS_LOOP_AVX3); // the hottest loop
// if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
if (kind1 == kind2) {
- masm.evmovdquq(vec1, new AMD64Address(str1, result, scale), AvxVectorLen.AVX_512bit);
+ masm.evmovdqu64(vec1, new AMD64Address(str1, result, scale));
// k7 == 11..11, if operands equal, otherwise k7 has some 0
- masm.evpcmpeqb(k7, vec1, new AMD64Address(str2, result, scale), AvxVectorLen.AVX_512bit);
+ masm.evpcmpeqb(k7, vec1, new AMD64Address(str2, result, scale));
} else {
- masm.vpmovzxbw(vec1, new AMD64Address(str1, result, scale1), AvxVectorLen.AVX_512bit);
+ masm.evpmovzxbw(vec1, new AMD64Address(str1, result, scale1));
// k7 == 11..11, if operands equal, otherwise k7 has some 0
- masm.evpcmpeqb(k7, vec1, new AMD64Address(str2, result, scale2), AvxVectorLen.AVX_512bit);
+ masm.evpcmpeqb(k7, vec1, new AMD64Address(str2, result, scale2));
}
- masm.kortestql(k7, k7);
+ masm.kortestq(k7, k7);
masm.jcc(ConditionFlag.AboveEqual, COMPARE_WIDE_VECTORS_LOOP_FAILED); // miscompare
masm.addq(result, stride2x2); // update since we already compared at this addr
masm.subl(cnt2, stride2x2); // and sub the size too
@@ -350,7 +345,7 @@
masm.vmovdqu(vec1, new AMD64Address(str1, result, scale));
masm.vpxor(vec1, vec1, new AMD64Address(str2, result, scale));
} else {
- masm.vpmovzxbw(vec1, new AMD64Address(str1, result, scale1), AvxVectorLen.AVX_256bit);
+ masm.vpmovzxbw(vec1, new AMD64Address(str1, result, scale1));
masm.vpxor(vec1, vec1, new AMD64Address(str2, result, scale2));
}
masm.vptest(vec1, vec1);
@@ -532,7 +527,7 @@
if (supportsAVX512VLBW(crb.target)) {
masm.bind(COMPARE_WIDE_VECTORS_LOOP_FAILED);
- masm.kmovql(cnt1, k7);
+ masm.kmovq(cnt1, k7);
masm.notq(cnt1);
masm.bsfq(cnt2, cnt1);
// if (ae != StrIntrinsicNode::LL) {
@@ -584,20 +579,4 @@
masm.movzwl(elem2, new AMD64Address(str2, index, scale2, 0));
}
}
-
- private static final Unsafe UNSAFE = initUnsafe();
-
- private static Unsafe initUnsafe() {
- try {
- return Unsafe.getUnsafe();
- } catch (SecurityException se) {
- try {
- Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
- theUnsafe.setAccessible(true);
- return (Unsafe) theUnsafe.get(Unsafe.class);
- } catch (Exception e) {
- throw new RuntimeException("exception while trying to get Unsafe", e);
- }
- }
- }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayEqualsOp.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayEqualsOp.java Thu Aug 23 11:09:16 2018 -0400
@@ -32,8 +32,8 @@
import org.graalvm.compiler.asm.amd64.AMD64Address;
import org.graalvm.compiler.asm.amd64.AMD64Address.Scale;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag;
-import org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.SSEOp;
+import org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize;
import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.NumUtil;
@@ -277,7 +277,7 @@
Label loopCheck = new Label();
Label nanCheck = new Label();
- // Compare 16-byte vectors
+ // Compare 32-byte vectors
masm.andl(result, AVX_VECTOR_SIZE - 1); // tail count (in bytes)
masm.andl(length, ~(AVX_VECTOR_SIZE - 1)); // vector count (in bytes)
masm.jcc(ConditionFlag.Zero, compareTail);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayIndexOfOp.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,484 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.lir.amd64;
+
+import static jdk.vm.ci.code.ValueUtil.asRegister;
+import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL;
+import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
+
+import org.graalvm.compiler.asm.Label;
+import org.graalvm.compiler.asm.amd64.AMD64Address;
+import org.graalvm.compiler.asm.amd64.AMD64Assembler;
+import org.graalvm.compiler.asm.amd64.AMD64Assembler.VexMoveOp;
+import org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRMIOp;
+import org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRMOp;
+import org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp;
+import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
+import org.graalvm.compiler.asm.amd64.AVXKind;
+import org.graalvm.compiler.core.common.LIRKind;
+import org.graalvm.compiler.lir.LIRInstructionClass;
+import org.graalvm.compiler.lir.Opcode;
+import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
+import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
+
+import jdk.vm.ci.amd64.AMD64;
+import jdk.vm.ci.amd64.AMD64.CPUFeature;
+import jdk.vm.ci.amd64.AMD64Kind;
+import jdk.vm.ci.code.Register;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.Value;
+
+/**
+ */
+@Opcode("AMD64_ARRAY_INDEX_OF")
+public final class AMD64ArrayIndexOfOp extends AMD64LIRInstruction {
+ public static final LIRInstructionClass<AMD64ArrayIndexOfOp> TYPE = LIRInstructionClass.create(AMD64ArrayIndexOfOp.class);
+
+ private final JavaKind kind;
+ private final int vmPageSize;
+
+ @Def({REG}) protected Value resultValue;
+ @Alive({REG}) protected Value charArrayPtrValue;
+ @Use({REG}) protected Value charArrayLengthValue;
+ @Alive({REG}) protected Value searchCharValue;
+ @Temp({REG}) protected Value arraySlotsRemaining;
+ @Temp({REG}) protected Value comparisonResult1;
+ @Temp({REG}) protected Value comparisonResult2;
+ @Temp({REG}) protected Value comparisonResult3;
+ @Temp({REG}) protected Value comparisonResult4;
+ @Temp({REG, ILLEGAL}) protected Value vectorCompareVal;
+ @Temp({REG, ILLEGAL}) protected Value vectorArray1;
+ @Temp({REG, ILLEGAL}) protected Value vectorArray2;
+ @Temp({REG, ILLEGAL}) protected Value vectorArray3;
+ @Temp({REG, ILLEGAL}) protected Value vectorArray4;
+
+ public AMD64ArrayIndexOfOp(
+ JavaKind kind,
+ int vmPageSize, LIRGeneratorTool tool,
+ Value result,
+ Value arrayPtr,
+ Value arrayLength,
+ Value searchChar) {
+ super(TYPE);
+ this.kind = kind;
+ this.vmPageSize = vmPageSize;
+ assert byteMode() || charMode();
+ assert supports(tool, CPUFeature.SSSE3) || supports(tool, CPUFeature.AVX) || supportsAVX2(tool);
+ resultValue = result;
+ charArrayPtrValue = arrayPtr;
+ charArrayLengthValue = arrayLength;
+ searchCharValue = searchChar;
+
+ this.arraySlotsRemaining = tool.newVariable(LIRKind.value(AMD64Kind.DWORD));
+ this.comparisonResult1 = tool.newVariable(LIRKind.value(AMD64Kind.DWORD));
+ this.comparisonResult2 = tool.newVariable(LIRKind.value(AMD64Kind.DWORD));
+ this.comparisonResult3 = tool.newVariable(LIRKind.value(AMD64Kind.DWORD));
+ this.comparisonResult4 = tool.newVariable(LIRKind.value(AMD64Kind.DWORD));
+ AMD64Kind vectorKind = byteMode() ? supportsAVX2(tool) ? AMD64Kind.V256_BYTE : AMD64Kind.V128_BYTE : supportsAVX2(tool) ? AMD64Kind.V256_WORD : AMD64Kind.V128_WORD;
+ this.vectorCompareVal = tool.newVariable(LIRKind.value(vectorKind));
+ this.vectorArray1 = tool.newVariable(LIRKind.value(vectorKind));
+ this.vectorArray2 = tool.newVariable(LIRKind.value(vectorKind));
+ this.vectorArray3 = tool.newVariable(LIRKind.value(vectorKind));
+ this.vectorArray4 = tool.newVariable(LIRKind.value(vectorKind));
+ }
+
+ private boolean byteMode() {
+ return kind == JavaKind.Byte;
+ }
+
+ private boolean charMode() {
+ return kind == JavaKind.Char;
+ }
+
+ @Override
+ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler asm) {
+ Register arrayPtr = asRegister(charArrayPtrValue);
+ Register arrayLength = asRegister(charArrayLengthValue);
+ Register searchValue = asRegister(searchCharValue);
+ Register result = asRegister(resultValue);
+ Register vecCmp = asRegister(vectorCompareVal);
+ Register vecArray1 = asRegister(vectorArray1);
+ Register vecArray2 = asRegister(vectorArray2);
+ Register vecArray3 = asRegister(vectorArray3);
+ Register vecArray4 = asRegister(vectorArray4);
+ Register slotsRemaining = asRegister(arraySlotsRemaining);
+ Register cmpResult1 = asRegister(comparisonResult1);
+ Register cmpResult2 = asRegister(comparisonResult2);
+ Register cmpResult3 = asRegister(comparisonResult3);
+ Register cmpResult4 = asRegister(comparisonResult4);
+
+ Label bulkVectorLoop = new Label();
+ Label singleVectorLoop = new Label();
+ Label vectorFound1 = new Label();
+ Label vectorFound2 = new Label();
+ Label vectorFound3 = new Label();
+ Label vectorFound4 = new Label();
+ Label lessThanVectorSizeRemaining = new Label();
+ Label lessThanVectorSizeRemainingLoop = new Label();
+ Label retFound = new Label();
+ Label retNotFound = new Label();
+ Label end = new Label();
+
+ AVXKind.AVXSize vectorSize = asm.supports(CPUFeature.AVX2) ? AVXKind.AVXSize.YMM : AVXKind.AVXSize.XMM;
+ int nVectors = 4;
+ int bytesPerVector = vectorSize.getBytes();
+ int arraySlotsPerVector = vectorSize.getBytes() / kind.getByteCount();
+ int bulkSize = arraySlotsPerVector * nVectors;
+ int bulkSizeBytes = bytesPerVector * nVectors;
+ assert bulkSizeBytes >= 64;
+
+ // load array length
+ // important: this must be the first register manipulation, since charArrayLengthValue is
+ // annotated with @Use
+ asm.movl(slotsRemaining, arrayLength);
+ // move search value to vector
+ if (asm.supports(CPUFeature.AVX)) {
+ VexMoveOp.VMOVD.emit(asm, AVXKind.AVXSize.DWORD, vecCmp, searchValue);
+ } else {
+ asm.movdl(vecCmp, searchValue);
+ }
+ // load array pointer
+ asm.movq(result, arrayPtr);
+ // load copy of low part of array pointer
+ asm.movl(cmpResult1, arrayPtr);
+ // fill comparison vector with copies of the search value
+ emitBroadcast(asm, vecCmp, vecArray1, vectorSize);
+
+ // check if bulk vector load is in bounds
+ asm.cmpl(slotsRemaining, bulkSize);
+ asm.jcc(AMD64Assembler.ConditionFlag.Below, singleVectorLoop);
+
+ // check if array pointer is 64-byte aligned
+ asm.andl(cmpResult1, 63);
+ asm.jcc(AMD64Assembler.ConditionFlag.Zero, bulkVectorLoop);
+
+ // do one unaligned bulk comparison pass and adjust alignment afterwards
+ emitBulkCompare(asm, vectorSize, bytesPerVector, result, vecCmp, vecArray1, vecArray2, vecArray3, vecArray4, cmpResult1, cmpResult2, cmpResult3, cmpResult4,
+ vectorFound1, vectorFound2, vectorFound3, vectorFound4, false);
+ // load copy of low part of array pointer
+ asm.movl(cmpResult1, arrayPtr);
+ // adjust array pointer
+ asm.addq(result, bulkSizeBytes);
+ // adjust number of array slots remaining
+ asm.subl(slotsRemaining, bulkSize);
+ // get offset to 64-byte alignment
+ asm.andl(cmpResult1, 63);
+ emitBytesToArraySlots(asm, cmpResult1);
+ // adjust array pointer to 64-byte alignment
+ asm.andq(result, ~63);
+ // adjust number of array slots remaining
+ asm.addl(slotsRemaining, cmpResult1);
+ // check if there are enough array slots remaining for the bulk loop
+ asm.cmpl(slotsRemaining, bulkSize);
+ asm.jcc(AMD64Assembler.ConditionFlag.Below, singleVectorLoop);
+
+ emitAlign(crb, asm);
+ asm.bind(bulkVectorLoop);
+ // memory-aligned bulk comparison
+ emitBulkCompare(asm, vectorSize, bytesPerVector, result, vecCmp, vecArray1, vecArray2, vecArray3, vecArray4, cmpResult1, cmpResult2, cmpResult3, cmpResult4,
+ vectorFound1, vectorFound2, vectorFound3, vectorFound4, true);
+ // adjust number of array slots remaining
+ asm.subl(slotsRemaining, bulkSize);
+ // adjust array pointer
+ asm.addq(result, bulkSizeBytes);
+ // check if there are enough array slots remaining for the bulk loop
+ asm.cmpl(slotsRemaining, bulkSize);
+ asm.jcc(AMD64Assembler.ConditionFlag.Below, singleVectorLoop);
+ // continue loop
+ asm.jmpb(bulkVectorLoop);
+
+ emitAlign(crb, asm);
+ // same loop as bulkVectorLoop, with only one vector
+ asm.bind(singleVectorLoop);
+ // check if single vector load is in bounds
+ asm.cmpl(slotsRemaining, arraySlotsPerVector);
+ asm.jcc(AMD64Assembler.ConditionFlag.Below, lessThanVectorSizeRemaining);
+ // compare
+ emitSingleVectorCompare(asm, vectorSize, result, vecCmp, vecArray1, cmpResult1);
+
+ // check if a match was found
+ asm.testl(cmpResult1, cmpResult1);
+ asm.jcc(AMD64Assembler.ConditionFlag.NotZero, vectorFound1);
+ // adjust number of array slots remaining
+ asm.subl(slotsRemaining, arraySlotsPerVector);
+ // adjust array pointer
+ asm.addq(result, bytesPerVector);
+ // continue loop
+ asm.jmpb(singleVectorLoop);
+
+ asm.bind(lessThanVectorSizeRemaining);
+ // check if any array slots remain
+ asm.testl(slotsRemaining, slotsRemaining);
+ asm.jcc(AMD64Assembler.ConditionFlag.Zero, retNotFound);
+
+ // a vector compare will read out of bounds of the input array.
+ // check if the out-of-bounds read would cross a memory page boundary.
+ // load copy of low part of array pointer
+ asm.movl(cmpResult1, result);
+ // check if pointer + vector size would cross the page boundary
+ asm.andl(cmpResult1, (vmPageSize - 1));
+ asm.cmpl(cmpResult1, (vmPageSize - bytesPerVector));
+ // if the page boundary would be crossed, do byte/character-wise comparison instead.
+ asm.jccb(AMD64Assembler.ConditionFlag.Above, lessThanVectorSizeRemainingLoop);
+ // otherwise, do a vector compare that reads beyond array bounds
+ emitSingleVectorCompare(asm, vectorSize, result, vecCmp, vecArray1, cmpResult1);
+ // check if a match was found
+ asm.testl(cmpResult1, cmpResult1);
+ asm.jcc(AMD64Assembler.ConditionFlag.Zero, retNotFound);
+ // find match offset
+ asm.bsfq(cmpResult1, cmpResult1);
+ if (charMode()) {
+ // convert number of remaining characters to bytes
+ asm.shll(slotsRemaining, 1);
+ }
+ // adjust array pointer for match result
+ asm.addq(result, cmpResult1);
+ // check if offset of matched value is greater than number of bytes remaining / out of array
+ // bounds
+ asm.cmpl(cmpResult1, slotsRemaining);
+ // match is out of bounds, return no match
+ asm.jcc(AMD64Assembler.ConditionFlag.GreaterEqual, retNotFound);
+ // match is in bounds, return offset
+ asm.jmpb(retFound);
+
+ // compare remaining slots in the array one-by-one
+ asm.bind(lessThanVectorSizeRemainingLoop);
+ // check if any array slots remain
+ asm.testl(slotsRemaining, slotsRemaining);
+ asm.jcc(AMD64Assembler.ConditionFlag.Zero, retNotFound);
+ // load char / byte
+ AMD64Assembler.OperandSize operandSize = byteMode() ? AMD64Assembler.OperandSize.BYTE : AMD64Assembler.OperandSize.WORD;
+ if (byteMode()) {
+ AMD64Assembler.AMD64RMOp.MOVB.emit(asm, operandSize, cmpResult1, new AMD64Address(result));
+ } else {
+ AMD64Assembler.AMD64RMOp.MOV.emit(asm, operandSize, cmpResult1, new AMD64Address(result));
+ }
+ // check for match
+ AMD64Assembler.AMD64BinaryArithmetic.CMP.getRMOpcode(operandSize).emit(asm, operandSize, cmpResult1, searchValue);
+ asm.jcc(AMD64Assembler.ConditionFlag.Equal, retFound);
+ // adjust number of array slots remaining
+ asm.decrementl(slotsRemaining);
+ // adjust array pointer
+ asm.addq(result, kind.getByteCount());
+ // continue loop
+ asm.jmpb(lessThanVectorSizeRemainingLoop);
+
+ // return -1 (no match)
+ asm.bind(retNotFound);
+ asm.movl(result, -1);
+ asm.jmpb(end);
+
+ emitVectorFoundWithOffset(asm, bytesPerVector, result, cmpResult2, vectorFound2, retFound);
+ emitVectorFoundWithOffset(asm, bytesPerVector * 2, result, cmpResult3, vectorFound3, retFound);
+ emitVectorFoundWithOffset(asm, bytesPerVector * 3, result, cmpResult4, vectorFound4, retFound);
+
+ asm.bind(vectorFound1);
+ // find index of first set bit in bit mask
+ asm.bsfq(cmpResult1, cmpResult1);
+ // add offset to array pointer
+ asm.addq(result, cmpResult1);
+
+ asm.bind(retFound);
+ // convert array pointer to offset
+ asm.subq(result, arrayPtr);
+ emitBytesToArraySlots(asm, result);
+ asm.bind(end);
+ }
+
+ private static void emitAlign(CompilationResultBuilder crb, AMD64MacroAssembler asm) {
+ asm.align(crb.target.wordSize * 2);
+ }
+
+ /**
+ * Fills {@code vecDst} with copies of its lowest byte or word.
+ */
+ private void emitBroadcast(AMD64MacroAssembler asm, Register vecDst, Register vecTmp, AVXKind.AVXSize vectorSize) {
+ if (asm.supports(CPUFeature.AVX2)) {
+ if (byteMode()) {
+ VexRMOp.VPBROADCASTB.emit(asm, vectorSize, vecDst, vecDst);
+ } else {
+ VexRMOp.VPBROADCASTW.emit(asm, vectorSize, vecDst, vecDst);
+ }
+ } else if (asm.supports(CPUFeature.AVX)) {
+ if (byteMode()) {
+ // fill vecTmp with zeroes
+ VexRVMOp.VPXOR.emit(asm, vectorSize, vecTmp, vecTmp, vecTmp);
+ // broadcast loaded search value
+ VexRVMOp.VPSHUFB.emit(asm, vectorSize, vecDst, vecDst, vecTmp);
+ } else {
+ // fill low qword
+ VexRMIOp.VPSHUFLW.emit(asm, vectorSize, vecDst, vecDst, 0);
+ // copy low qword to high qword
+ VexRMIOp.VPSHUFD.emit(asm, vectorSize, vecDst, vecDst, 0);
+ }
+ } else {
+ // SSE version
+ if (byteMode()) {
+ // fill vecTmp with zeroes
+ asm.pxor(vecTmp, vecTmp);
+ // broadcast loaded search value
+ asm.pshufb(vecDst, vecTmp);
+ } else {
+ // fill low qword
+ asm.pshuflw(vecDst, vecDst, 0);
+ // copy low qword to high qword
+ asm.pshufd(vecDst, vecDst, 0);
+ }
+ }
+ }
+
+ /**
+ * Loads {@code vectorSize} bytes from the position pointed to by {@code arrayPtr} and compares
+ * them to the search value stored in {@code vecCmp}. {@code vecArray} is overwritten by this
+ * operation. The comparison result is stored in {@code cmpResult}.
+ */
+ private void emitSingleVectorCompare(AMD64MacroAssembler asm, AVXKind.AVXSize vectorSize,
+ Register arrayPtr, Register vecCmp, Register vecArray, Register cmpResult) {
+ // load array contents into vector
+ emitArrayLoad(asm, vectorSize, vecArray, arrayPtr, 0, false);
+ // compare all loaded bytes to the search value.
+ emitVectorCompare(asm, vectorSize, vecArray, vecCmp);
+ // create a 32-bit-mask from the most significant bit of every byte in the comparison
+ // result.
+ emitMOVMSK(asm, vectorSize, cmpResult, vecArray);
+ }
+
+ /**
+ * Convert a byte offset stored in {@code bytes} to an array index offset.
+ */
+ private void emitBytesToArraySlots(AMD64MacroAssembler asm, Register bytes) {
+ if (charMode()) {
+ asm.shrl(bytes, 1);
+ } else {
+ assert byteMode();
+ }
+ }
+
+ private void emitBulkCompare(AMD64MacroAssembler asm,
+ AVXKind.AVXSize vectorSize,
+ int bytesPerVector,
+ Register arrayPtr,
+ Register vecCmp,
+ Register vecArray1,
+ Register vecArray2,
+ Register vecArray3,
+ Register vecArray4,
+ Register cmpResult1,
+ Register cmpResult2,
+ Register cmpResult3,
+ Register cmpResult4,
+ Label vectorFound1,
+ Label vectorFound2,
+ Label vectorFound3,
+ Label vectorFound4,
+ boolean alignedLoad) {
+ // load array contents into vectors
+ emitArrayLoad(asm, vectorSize, vecArray1, arrayPtr, 0, alignedLoad);
+ emitArrayLoad(asm, vectorSize, vecArray2, arrayPtr, bytesPerVector, alignedLoad);
+ emitArrayLoad(asm, vectorSize, vecArray3, arrayPtr, bytesPerVector * 2, alignedLoad);
+ emitArrayLoad(asm, vectorSize, vecArray4, arrayPtr, bytesPerVector * 3, alignedLoad);
+ // compare all loaded bytes to the search value.
+ // matching bytes are set to 0xff, non-matching bytes are set to 0x00.
+ emitVectorCompare(asm, vectorSize, vecArray1, vecCmp);
+ emitVectorCompare(asm, vectorSize, vecArray2, vecCmp);
+ emitVectorCompare(asm, vectorSize, vecArray3, vecCmp);
+ emitVectorCompare(asm, vectorSize, vecArray4, vecCmp);
+ // create 32-bit-masks from the most significant bit of every byte in the comparison
+ // results.
+ emitMOVMSK(asm, vectorSize, cmpResult1, vecArray1);
+ emitMOVMSK(asm, vectorSize, cmpResult2, vecArray2);
+ emitMOVMSK(asm, vectorSize, cmpResult3, vecArray3);
+ emitMOVMSK(asm, vectorSize, cmpResult4, vecArray4);
+ // check if a match was found
+ asm.testl(cmpResult1, cmpResult1);
+ asm.jcc(AMD64Assembler.ConditionFlag.NotZero, vectorFound1);
+ asm.testl(cmpResult2, cmpResult2);
+ asm.jcc(AMD64Assembler.ConditionFlag.NotZero, vectorFound2);
+ asm.testl(cmpResult3, cmpResult3);
+ asm.jcc(AMD64Assembler.ConditionFlag.NotZero, vectorFound3);
+ asm.testl(cmpResult4, cmpResult4);
+ asm.jcc(AMD64Assembler.ConditionFlag.NotZero, vectorFound4);
+ }
+
+ private static void emitVectorFoundWithOffset(AMD64MacroAssembler asm, int resultOffset, Register result, Register cmpResult, Label entry, Label ret) {
+ asm.bind(entry);
+ if (resultOffset > 0) {
+ // adjust array pointer
+ asm.addq(result, resultOffset);
+ }
+ // find index of first set bit in bit mask
+ asm.bsfq(cmpResult, cmpResult);
+ // add offset to array pointer
+ asm.addq(result, cmpResult);
+ asm.jmpb(ret);
+ }
+
+ private static void emitArrayLoad(AMD64MacroAssembler asm, AVXKind.AVXSize vectorSize, Register vecDst, Register arrayPtr, int offset, boolean alignedLoad) {
+ AMD64Address src = new AMD64Address(arrayPtr, offset);
+ if (asm.supports(CPUFeature.AVX)) {
+ VexMoveOp loadOp = alignedLoad ? VexMoveOp.VMOVDQA : VexMoveOp.VMOVDQU;
+ loadOp.emit(asm, vectorSize, vecDst, src);
+ } else {
+ // SSE
+ asm.movdqu(vecDst, src);
+ }
+ }
+
+ private void emitVectorCompare(AMD64MacroAssembler asm, AVXKind.AVXSize vectorSize, Register vecArray, Register vecCmp) {
+ // compare all loaded bytes to the search value.
+ // matching bytes are set to 0xff, non-matching bytes are set to 0x00.
+ if (asm.supports(CPUFeature.AVX)) {
+ if (byteMode()) {
+ VexRVMOp.VPCMPEQB.emit(asm, vectorSize, vecArray, vecCmp, vecArray);
+ } else {
+ VexRVMOp.VPCMPEQW.emit(asm, vectorSize, vecArray, vecCmp, vecArray);
+ }
+ } else {
+ // SSE
+ if (byteMode()) {
+ asm.pcmpeqb(vecArray, vecCmp);
+ } else {
+ asm.pcmpeqw(vecArray, vecCmp);
+ }
+ }
+ }
+
+ private static void emitMOVMSK(AMD64MacroAssembler asm, AVXKind.AVXSize vectorSize, Register dst, Register vecSrc) {
+ if (asm.supports(CPUFeature.AVX)) {
+ VexRMOp.VPMOVMSKB.emit(asm, vectorSize, dst, vecSrc);
+ } else {
+ // SSE
+ asm.pmovmskb(dst, vecSrc);
+ }
+ }
+
+ private static boolean supportsAVX2(LIRGeneratorTool tool) {
+ return supports(tool, CPUFeature.AVX2);
+ }
+
+ private static boolean supports(LIRGeneratorTool tool, CPUFeature cpuFeature) {
+ return ((AMD64) tool.target().arch).getFeatures().contains(cpuFeature);
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Binary.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Binary.java Thu Aug 23 11:09:16 2018 -0400
@@ -24,25 +24,24 @@
package org.graalvm.compiler.lir.amd64;
+import static jdk.vm.ci.code.ValueUtil.asRegister;
+import static jdk.vm.ci.code.ValueUtil.isRegister;
+import static jdk.vm.ci.code.ValueUtil.isStackSlot;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.COMPOSITE;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK;
import static org.graalvm.compiler.lir.LIRValueUtil.differentRegisters;
import static org.graalvm.compiler.lir.LIRValueUtil.sameRegister;
-import static jdk.vm.ci.code.ValueUtil.asRegister;
-import static jdk.vm.ci.code.ValueUtil.isRegister;
-import static jdk.vm.ci.code.ValueUtil.isStackSlot;
-import org.graalvm.compiler.core.common.NumUtil;
import org.graalvm.compiler.asm.amd64.AMD64Address;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMIOp;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp;
-import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RRMOp;
-import org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize;
+import org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize;
import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
+import org.graalvm.compiler.core.common.NumUtil;
import org.graalvm.compiler.lir.LIRFrameState;
import org.graalvm.compiler.lir.LIRInstructionClass;
import org.graalvm.compiler.lir.Opcode;
@@ -99,40 +98,6 @@
}
/**
- * Instruction that has three {@link AllocatableValue} operands.
- */
- public static class ThreeOp extends AMD64LIRInstruction {
- public static final LIRInstructionClass<ThreeOp> TYPE = LIRInstructionClass.create(ThreeOp.class);
-
- @Opcode private final AMD64RRMOp opcode;
- private final OperandSize size;
-
- @Def({REG}) protected AllocatableValue result;
- @Use({REG}) protected AllocatableValue x;
- @Use({REG, STACK}) protected AllocatableValue y;
-
- public ThreeOp(AMD64RRMOp opcode, OperandSize size, AllocatableValue result, AllocatableValue x, AllocatableValue y) {
- super(TYPE);
- this.opcode = opcode;
- this.size = size;
-
- this.result = result;
- this.x = x;
- this.y = y;
- }
-
- @Override
- public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
- if (isRegister(y)) {
- opcode.emit(masm, size, asRegister(result), asRegister(x), asRegister(y));
- } else {
- assert isStackSlot(y);
- opcode.emit(masm, size, asRegister(result), asRegister(x), (AMD64Address) crb.asAddress(y));
- }
- }
- }
-
- /**
* Commutative instruction that has two {@link AllocatableValue} operands.
*/
public static class CommutativeTwoOp extends AMD64LIRInstruction {
@@ -175,40 +140,6 @@
}
/**
- * Commutative instruction that has three {@link AllocatableValue} operands.
- */
- public static class CommutativeThreeOp extends AMD64LIRInstruction {
- public static final LIRInstructionClass<CommutativeThreeOp> TYPE = LIRInstructionClass.create(CommutativeThreeOp.class);
-
- @Opcode private final AMD64RRMOp opcode;
- private final OperandSize size;
-
- @Def({REG}) protected AllocatableValue result;
- @Use({REG}) protected AllocatableValue x;
- @Use({REG, STACK}) protected AllocatableValue y;
-
- public CommutativeThreeOp(AMD64RRMOp opcode, OperandSize size, AllocatableValue result, AllocatableValue x, AllocatableValue y) {
- super(TYPE);
- this.opcode = opcode;
- this.size = size;
-
- this.result = result;
- this.x = x;
- this.y = y;
- }
-
- @Override
- public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
- if (isRegister(y)) {
- opcode.emit(masm, size, asRegister(result), asRegister(x), asRegister(y));
- } else {
- assert isStackSlot(y);
- opcode.emit(masm, size, asRegister(result), asRegister(x), (AMD64Address) crb.asAddress(y));
- }
- }
- }
-
- /**
* Instruction that has one {@link AllocatableValue} operand and one 32-bit immediate operand.
*/
public static class ConstOp extends AMD64LIRInstruction {
@@ -282,44 +213,6 @@
}
/**
- * Instruction that has two {@link AllocatableValue} operands and one
- * {@link DataSectionReference} operand.
- */
- public static class DataThreeOp extends AMD64LIRInstruction {
- public static final LIRInstructionClass<DataThreeOp> TYPE = LIRInstructionClass.create(DataThreeOp.class);
-
- @Opcode private final AMD64RRMOp opcode;
- private final OperandSize size;
-
- @Def({REG}) protected AllocatableValue result;
- @Use({REG}) protected AllocatableValue x;
- private final JavaConstant y;
-
- private final int alignment;
-
- public DataThreeOp(AMD64RRMOp opcode, OperandSize size, AllocatableValue result, AllocatableValue x, JavaConstant y) {
- this(opcode, size, result, x, y, y.getJavaKind().getByteCount());
- }
-
- public DataThreeOp(AMD64RRMOp opcode, OperandSize size, AllocatableValue result, AllocatableValue x, JavaConstant y, int alignment) {
- super(TYPE);
- this.opcode = opcode;
- this.size = size;
-
- this.result = result;
- this.x = x;
- this.y = y;
-
- this.alignment = alignment;
- }
-
- @Override
- public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
- opcode.emit(masm, size, asRegister(result), asRegister(x), (AMD64Address) crb.recordDataReferenceInCode(y, alignment));
- }
- }
-
- /**
* Instruction that has one {@link AllocatableValue} operand and one {@link AMD64AddressValue
* memory} operand.
*/
@@ -373,58 +266,6 @@
}
/**
- * Instruction that has one {@link AllocatableValue} operand and one {@link AMD64AddressValue
- * memory} operand.
- */
- public static class MemoryThreeOp extends AMD64LIRInstruction implements ImplicitNullCheck {
- public static final LIRInstructionClass<MemoryThreeOp> TYPE = LIRInstructionClass.create(MemoryThreeOp.class);
-
- @Opcode private final AMD64RRMOp opcode;
- private final OperandSize size;
-
- @Def({REG}) protected AllocatableValue result;
- @Use({REG}) protected AllocatableValue x;
- @Use({COMPOSITE}) protected AMD64AddressValue y;
-
- @State protected LIRFrameState state;
-
- public MemoryThreeOp(AMD64RRMOp opcode, OperandSize size, AllocatableValue result, AllocatableValue x, AMD64AddressValue y, LIRFrameState state) {
- super(TYPE);
- this.opcode = opcode;
- this.size = size;
-
- this.result = result;
- this.x = x;
- this.y = y;
-
- this.state = state;
- }
-
- @Override
- public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
- if (state != null) {
- crb.recordImplicitException(masm.position(), state);
- }
- opcode.emit(masm, size, asRegister(result), asRegister(x), y.toAddress());
- }
-
- @Override
- public void verify() {
- super.verify();
- assert differentRegisters(result, y) || sameRegister(x, y);
- }
-
- @Override
- public boolean makeNullCheckFor(Value value, LIRFrameState nullCheckState, int implicitNullCheckLimit) {
- if (state == null && y.isValidImplicitNullCheckFor(value, implicitNullCheckLimit)) {
- state = nullCheckState;
- return true;
- }
- return false;
- }
- }
-
- /**
* Instruction with a separate result operand, one {@link AllocatableValue} input and one 32-bit
* immediate input.
*/
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64BinaryConsumer.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64BinaryConsumer.java Thu Aug 23 11:09:16 2018 -0400
@@ -24,22 +24,22 @@
package org.graalvm.compiler.lir.amd64;
-import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.DWORD;
+import static jdk.vm.ci.code.ValueUtil.asRegister;
+import static jdk.vm.ci.code.ValueUtil.isRegister;
+import static jdk.vm.ci.code.ValueUtil.isStackSlot;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.DWORD;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.COMPOSITE;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK;
-import static jdk.vm.ci.code.ValueUtil.asRegister;
-import static jdk.vm.ci.code.ValueUtil.isRegister;
-import static jdk.vm.ci.code.ValueUtil.isStackSlot;
-import org.graalvm.compiler.core.common.NumUtil;
import org.graalvm.compiler.asm.amd64.AMD64Address;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MROp;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp;
-import org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize;
+import org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize;
import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
+import org.graalvm.compiler.core.common.NumUtil;
import org.graalvm.compiler.lir.LIRFrameState;
import org.graalvm.compiler.lir.LIRInstructionClass;
import org.graalvm.compiler.lir.Opcode;
@@ -121,12 +121,16 @@
@Override
public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
if (isRegister(x)) {
- opcode.emit(masm, size, asRegister(x), y);
+ opcode.emit(masm, size, asRegister(x), y, shouldAnnotate());
} else {
assert isStackSlot(x);
- opcode.emit(masm, size, (AMD64Address) crb.asAddress(x), y);
+ opcode.emit(masm, size, (AMD64Address) crb.asAddress(x), y, shouldAnnotate());
}
}
+
+ protected boolean shouldAnnotate() {
+ return false;
+ }
}
/**
@@ -148,6 +152,11 @@
crb.recordInlineDataInCode(c);
super.emitCode(crb, masm);
}
+
+ @Override
+ protected boolean shouldAnnotate() {
+ return true;
+ }
}
/**
@@ -313,7 +322,11 @@
if (state != null) {
crb.recordImplicitException(masm.position(), state);
}
- opcode.emit(masm, size, x.toAddress(), y);
+ opcode.emit(masm, size, x.toAddress(), y, shouldAnnotate());
+ }
+
+ protected boolean shouldAnnotate() {
+ return false;
}
@Override
@@ -349,5 +362,10 @@
crb.recordInlineDataInCode(c);
super.emitCode(crb, masm);
}
+
+ @Override
+ protected boolean shouldAnnotate() {
+ return true;
+ }
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ClearRegisterOp.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ClearRegisterOp.java Thu Aug 23 11:09:16 2018 -0400
@@ -24,12 +24,12 @@
package org.graalvm.compiler.lir.amd64;
+import static jdk.vm.ci.code.ValueUtil.asRegister;
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.XOR;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
-import static jdk.vm.ci.code.ValueUtil.asRegister;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp;
-import org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize;
+import org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize;
import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
import org.graalvm.compiler.lir.LIRInstructionClass;
import org.graalvm.compiler.lir.Opcode;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java Thu Aug 23 11:09:16 2018 -0400
@@ -46,7 +46,7 @@
import org.graalvm.compiler.asm.amd64.AMD64Address;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MOp;
-import org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize;
+import org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize;
import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
import org.graalvm.compiler.core.common.CompressEncoding;
import org.graalvm.compiler.core.common.LIRKind;
@@ -572,6 +572,7 @@
if (asRegister(input).equals(asRegister(result))) {
return;
}
+ assert asRegister(result).getRegisterCategory().equals(asRegister(input).getRegisterCategory());
switch (kind) {
case BYTE:
case WORD:
@@ -701,7 +702,7 @@
}
} else if (crb.target.inlineObjects) {
crb.recordInlineDataInCode(input);
- masm.movq(result, 0xDEADDEADDEADDEADL);
+ masm.movq(result, 0xDEADDEADDEADDEADL, true);
} else {
masm.movq(result, (AMD64Address) crb.recordDataReferenceInCode(input, 0));
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64MulDivOp.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64MulDivOp.java Thu Aug 23 11:09:16 2018 -0400
@@ -24,6 +24,10 @@
package org.graalvm.compiler.lir.amd64;
+import static jdk.vm.ci.code.ValueUtil.asRegister;
+import static jdk.vm.ci.code.ValueUtil.isIllegal;
+import static jdk.vm.ci.code.ValueUtil.isRegister;
+import static jdk.vm.ci.code.ValueUtil.isStackSlot;
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MOp.DIV;
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MOp.IDIV;
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MOp.IMUL;
@@ -31,14 +35,10 @@
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK;
-import static jdk.vm.ci.code.ValueUtil.asRegister;
-import static jdk.vm.ci.code.ValueUtil.isIllegal;
-import static jdk.vm.ci.code.ValueUtil.isRegister;
-import static jdk.vm.ci.code.ValueUtil.isStackSlot;
import org.graalvm.compiler.asm.amd64.AMD64Address;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MOp;
-import org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize;
+import org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize;
import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.lir.LIRFrameState;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ShiftOp.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ShiftOp.java Thu Aug 23 11:09:16 2018 -0400
@@ -24,13 +24,13 @@
package org.graalvm.compiler.lir.amd64;
+import static jdk.vm.ci.code.ValueUtil.asRegister;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK;
-import static jdk.vm.ci.code.ValueUtil.asRegister;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MOp;
-import org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize;
+import org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize;
import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
import org.graalvm.compiler.lir.LIRInstructionClass;
import org.graalvm.compiler.lir.Opcode;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64SignExtendOp.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64SignExtendOp.java Thu Aug 23 11:09:16 2018 -0400
@@ -24,12 +24,12 @@
package org.graalvm.compiler.lir.amd64;
-import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.DWORD;
-import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.QWORD;
+import static jdk.vm.ci.code.ValueUtil.asRegister;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.DWORD;
+import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.QWORD;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
-import static jdk.vm.ci.code.ValueUtil.asRegister;
-import org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize;
+import org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize;
import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.lir.LIRInstructionClass;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64StringIndexOfOp.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64StringIndexOfOp.java Thu Aug 23 11:09:16 2018 -0400
@@ -27,10 +27,15 @@
import static jdk.vm.ci.amd64.AMD64.rax;
import static jdk.vm.ci.amd64.AMD64.rcx;
import static jdk.vm.ci.amd64.AMD64.rdx;
+import static jdk.vm.ci.amd64.AMD64.rsp;
import static jdk.vm.ci.code.ValueUtil.asRegister;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
+import org.graalvm.compiler.asm.Label;
+import org.graalvm.compiler.asm.amd64.AMD64Address;
+import org.graalvm.compiler.asm.amd64.AMD64Address.Scale;
+import org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag;
import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
import org.graalvm.compiler.lir.LIRInstructionClass;
import org.graalvm.compiler.lir.Opcode;
@@ -96,9 +101,430 @@
Register vec = asRegister(vectorTemp1);
Register tmp = asRegister(temp1);
if (intCnt2 >= 8) {
- masm.stringIndexofC8(charPtr1, charPtr2, cnt1, cnt2, intCnt2, result, vec, tmp);
+ // IndexOf for constant substrings with size >= 8 chars which don't need to be loaded
+ // through stack.
+ stringIndexofC8(masm, charPtr1, charPtr2, cnt1, cnt2, result, vec, tmp);
} else {
- masm.stringIndexOf(charPtr1, charPtr2, cnt1, cnt2, intCnt2, result, vec, tmp, vmPageSize);
+ // Small strings are loaded through stack if they cross page boundary.
+ stringIndexOf(masm, charPtr1, charPtr2, cnt1, cnt2, result, vec, tmp);
}
}
+
+ private void stringIndexofC8(AMD64MacroAssembler masm, Register charPtr1, Register charPtr2, Register cnt1, Register cnt2, Register result, Register vec, Register tmp) {
+ // assert(UseSSE42Intrinsics, "SSE4.2 is required");
+
+ // This method uses pcmpestri inxtruction with bound registers
+ // inputs:
+ // xmm - substring
+ // rax - substring length (elements count)
+ // mem - scanned string
+ // rdx - string length (elements count)
+ // 0xd - mode: 1100 (substring search) + 01 (unsigned shorts)
+ // outputs:
+ // rcx - matched index in string
+ assert cnt1.equals(rdx) && cnt2.equals(rax) && tmp.equals(rcx) : "pcmpestri";
+
+ Label reloadSubstr = new Label();
+ Label scanToSubstr = new Label();
+ Label scanSubstr = new Label();
+ Label retFound = new Label();
+ Label retNotFound = new Label();
+ Label exit = new Label();
+ Label foundSubstr = new Label();
+ Label matchSubstrHead = new Label();
+ Label reloadStr = new Label();
+ Label foundCandidate = new Label();
+
+ // Note, inline_string_indexOf() generates checks:
+ // if (substr.count > string.count) return -1;
+ // if (substr.count == 0) return 0;
+ assert intCnt2 >= 8 : "this code isused only for cnt2 >= 8 chars";
+
+ // Load substring.
+ masm.movdqu(vec, new AMD64Address(charPtr2, 0));
+ masm.movl(cnt2, intCnt2);
+ masm.movq(result, charPtr1); // string addr
+
+ if (intCnt2 > 8) {
+ masm.jmpb(scanToSubstr);
+
+ // Reload substr for rescan, this code
+ // is executed only for large substrings (> 8 chars)
+ masm.bind(reloadSubstr);
+ masm.movdqu(vec, new AMD64Address(charPtr2, 0));
+ masm.negq(cnt2); // Jumped here with negative cnt2, convert to positive
+
+ masm.bind(reloadStr);
+ // We came here after the beginning of the substring was
+ // matched but the rest of it was not so we need to search
+ // again. Start from the next element after the previous match.
+
+ // cnt2 is number of substring reminding elements and
+ // cnt1 is number of string reminding elements when cmp failed.
+ // Restored cnt1 = cnt1 - cnt2 + int_cnt2
+ masm.subl(cnt1, cnt2);
+ masm.addl(cnt1, intCnt2);
+ masm.movl(cnt2, intCnt2); // Now restore cnt2
+
+ masm.decrementl(cnt1, 1); // Shift to next element
+ masm.cmpl(cnt1, cnt2);
+ masm.jccb(ConditionFlag.Negative, retNotFound); // Left less then substring
+
+ masm.addq(result, 2);
+
+ } // (int_cnt2 > 8)
+
+ // Scan string for start of substr in 16-byte vectors
+ masm.bind(scanToSubstr);
+ masm.pcmpestri(vec, new AMD64Address(result, 0), 0x0d);
+ masm.jccb(ConditionFlag.Below, foundCandidate); // CF == 1
+ masm.subl(cnt1, 8);
+ masm.jccb(ConditionFlag.LessEqual, retNotFound); // Scanned full string
+ masm.cmpl(cnt1, cnt2);
+ masm.jccb(ConditionFlag.Negative, retNotFound); // Left less then substring
+ masm.addq(result, 16);
+ masm.jmpb(scanToSubstr);
+
+ // Found a potential substr
+ masm.bind(foundCandidate);
+ // Matched whole vector if first element matched (tmp(rcx) == 0).
+ if (intCnt2 == 8) {
+ masm.jccb(ConditionFlag.Overflow, retFound); // OF == 1
+ } else { // int_cnt2 > 8
+ masm.jccb(ConditionFlag.Overflow, foundSubstr);
+ }
+ // After pcmpestri tmp(rcx) contains matched element index
+ // Compute start addr of substr
+ masm.leaq(result, new AMD64Address(result, tmp, Scale.Times2, 0));
+
+ // Make sure string is still long enough
+ masm.subl(cnt1, tmp);
+ masm.cmpl(cnt1, cnt2);
+ if (intCnt2 == 8) {
+ masm.jccb(ConditionFlag.GreaterEqual, scanToSubstr);
+ } else { // int_cnt2 > 8
+ masm.jccb(ConditionFlag.GreaterEqual, matchSubstrHead);
+ }
+ // Left less then substring.
+
+ masm.bind(retNotFound);
+ masm.movl(result, -1);
+ masm.jmpb(exit);
+
+ if (intCnt2 > 8) {
+ // This code is optimized for the case when whole substring
+ // is matched if its head is matched.
+ masm.bind(matchSubstrHead);
+ masm.pcmpestri(vec, new AMD64Address(result, 0), 0x0d);
+ // Reload only string if does not match
+ masm.jccb(ConditionFlag.NoOverflow, reloadStr); // OF == 0
+
+ Label contScanSubstr = new Label();
+ // Compare the rest of substring (> 8 chars).
+ masm.bind(foundSubstr);
+ // First 8 chars are already matched.
+ masm.negq(cnt2);
+ masm.addq(cnt2, 8);
+
+ masm.bind(scanSubstr);
+ masm.subl(cnt1, 8);
+ masm.cmpl(cnt2, -8); // Do not read beyond substring
+ masm.jccb(ConditionFlag.LessEqual, contScanSubstr);
+ // Back-up strings to avoid reading beyond substring:
+ // cnt1 = cnt1 - cnt2 + 8
+ masm.addl(cnt1, cnt2); // cnt2 is negative
+ masm.addl(cnt1, 8);
+ masm.movl(cnt2, 8);
+ masm.negq(cnt2);
+ masm.bind(contScanSubstr);
+ if (intCnt2 < 1024 * 1024 * 1024) {
+ masm.movdqu(vec, new AMD64Address(charPtr2, cnt2, Scale.Times2, intCnt2 * 2));
+ masm.pcmpestri(vec, new AMD64Address(result, cnt2, Scale.Times2, intCnt2 * 2), 0x0d);
+ } else {
+ // calculate index in register to avoid integer overflow (int_cnt2*2)
+ masm.movl(tmp, intCnt2);
+ masm.addq(tmp, cnt2);
+ masm.movdqu(vec, new AMD64Address(charPtr2, tmp, Scale.Times2, 0));
+ masm.pcmpestri(vec, new AMD64Address(result, tmp, Scale.Times2, 0), 0x0d);
+ }
+ // Need to reload strings pointers if not matched whole vector
+ masm.jcc(ConditionFlag.NoOverflow, reloadSubstr); // OF == 0
+ masm.addq(cnt2, 8);
+ masm.jcc(ConditionFlag.Negative, scanSubstr);
+ // Fall through if found full substring
+
+ } // (int_cnt2 > 8)
+
+ masm.bind(retFound);
+ // Found result if we matched full small substring.
+ // Compute substr offset
+ masm.subq(result, charPtr1);
+ masm.shrl(result, 1); // index
+ masm.bind(exit);
+ }
+
+ private void stringIndexOf(AMD64MacroAssembler masm, Register charPtr1, Register charPtr2, Register cnt1, Register cnt2, Register result, Register vec, Register tmp) {
+ //
+ // int_cnt2 is length of small (< 8 chars) constant substring
+ // or (-1) for non constant substring in which case its length
+ // is in cnt2 register.
+ //
+ // Note, inline_string_indexOf() generates checks:
+ // if (substr.count > string.count) return -1;
+ // if (substr.count == 0) return 0;
+ //
+ assert intCnt2 == -1 || (0 < intCnt2 && intCnt2 < 8) : "should be != 0";
+
+ // This method uses pcmpestri instruction with bound registers
+ // inputs:
+ // xmm - substring
+ // rax - substring length (elements count)
+ // mem - scanned string
+ // rdx - string length (elements count)
+ // 0xd - mode: 1100 (substring search) + 01 (unsigned shorts)
+ // outputs:
+ // rcx - matched index in string
+ assert cnt1.equals(rdx) && cnt2.equals(rax) && tmp.equals(rcx) : "pcmpestri";
+
+ Label reloadSubstr = new Label();
+ Label scanToSubstr = new Label();
+ Label scanSubstr = new Label();
+ Label adjustStr = new Label();
+ Label retFound = new Label();
+ Label retNotFound = new Label();
+ Label cleanup = new Label();
+ Label foundSubstr = new Label();
+ Label foundCandidate = new Label();
+
+ int wordSize = 8;
+ // We don't know where these strings are located
+ // and we can't read beyond them. Load them through stack.
+ Label bigStrings = new Label();
+ Label checkStr = new Label();
+ Label copySubstr = new Label();
+ Label copyStr = new Label();
+
+ masm.movq(tmp, rsp); // save old SP
+
+ if (intCnt2 > 0) { // small (< 8 chars) constant substring
+ if (intCnt2 == 1) { // One char
+ masm.movzwl(result, new AMD64Address(charPtr2, 0));
+ masm.movdl(vec, result); // move 32 bits
+ } else if (intCnt2 == 2) { // Two chars
+ masm.movdl(vec, new AMD64Address(charPtr2, 0)); // move 32 bits
+ } else if (intCnt2 == 4) { // Four chars
+ masm.movq(vec, new AMD64Address(charPtr2, 0)); // move 64 bits
+ } else { // cnt2 = { 3, 5, 6, 7 }
+ // Array header size is 12 bytes in 32-bit VM
+ // + 6 bytes for 3 chars == 18 bytes,
+ // enough space to load vec and shift.
+ masm.movdqu(vec, new AMD64Address(charPtr2, (intCnt2 * 2) - 16));
+ masm.psrldq(vec, 16 - (intCnt2 * 2));
+ }
+ } else { // not constant substring
+ masm.cmpl(cnt2, 8);
+ masm.jccb(ConditionFlag.AboveEqual, bigStrings); // Both strings are big enough
+
+ // We can read beyond string if str+16 does not cross page boundary
+ // since heaps are aligned and mapped by pages.
+ assert vmPageSize < 1024 * 1024 * 1024 : "default page should be small";
+ masm.movl(result, charPtr2); // We need only low 32 bits
+ masm.andl(result, (vmPageSize - 1));
+ masm.cmpl(result, (vmPageSize - 16));
+ masm.jccb(ConditionFlag.BelowEqual, checkStr);
+
+ // Move small strings to stack to allow load 16 bytes into vec.
+ masm.subq(rsp, 16);
+ int stackOffset = wordSize - 2;
+ masm.push(cnt2);
+
+ masm.bind(copySubstr);
+ masm.movzwl(result, new AMD64Address(charPtr2, cnt2, Scale.Times2, -2));
+ masm.movw(new AMD64Address(rsp, cnt2, Scale.Times2, stackOffset), result);
+ masm.decrementl(cnt2, 1);
+ masm.jccb(ConditionFlag.NotZero, copySubstr);
+
+ masm.pop(cnt2);
+ masm.movq(charPtr2, rsp); // New substring address
+ } // non constant
+
+ masm.bind(checkStr);
+ masm.cmpl(cnt1, 8);
+ masm.jccb(ConditionFlag.AboveEqual, bigStrings);
+
+ // Check cross page boundary.
+ masm.movl(result, charPtr1); // We need only low 32 bits
+ masm.andl(result, (vmPageSize - 1));
+ masm.cmpl(result, (vmPageSize - 16));
+ masm.jccb(ConditionFlag.BelowEqual, bigStrings);
+
+ masm.subq(rsp, 16);
+ int stackOffset = -2;
+ if (intCnt2 < 0) { // not constant
+ masm.push(cnt2);
+ stackOffset += wordSize;
+ }
+ masm.movl(cnt2, cnt1);
+
+ masm.bind(copyStr);
+ masm.movzwl(result, new AMD64Address(charPtr1, cnt2, Scale.Times2, -2));
+ masm.movw(new AMD64Address(rsp, cnt2, Scale.Times2, stackOffset), result);
+ masm.decrementl(cnt2, 1);
+ masm.jccb(ConditionFlag.NotZero, copyStr);
+
+ if (intCnt2 < 0) { // not constant
+ masm.pop(cnt2);
+ }
+ masm.movq(charPtr1, rsp); // New string address
+
+ masm.bind(bigStrings);
+ // Load substring.
+ if (intCnt2 < 0) { // -1
+ masm.movdqu(vec, new AMD64Address(charPtr2, 0));
+ masm.push(cnt2); // substr count
+ masm.push(charPtr2); // substr addr
+ masm.push(charPtr1); // string addr
+ } else {
+ // Small (< 8 chars) constant substrings are loaded already.
+ masm.movl(cnt2, intCnt2);
+ }
+ masm.push(tmp); // original SP
+ // Finished loading
+
+ // ========================================================
+ // Start search
+ //
+
+ masm.movq(result, charPtr1); // string addr
+
+ if (intCnt2 < 0) { // Only for non constant substring
+ masm.jmpb(scanToSubstr);
+
+ // SP saved at sp+0
+ // String saved at sp+1*wordSize
+ // Substr saved at sp+2*wordSize
+ // Substr count saved at sp+3*wordSize
+
+ // Reload substr for rescan, this code
+ // is executed only for large substrings (> 8 chars)
+ masm.bind(reloadSubstr);
+ masm.movq(charPtr2, new AMD64Address(rsp, 2 * wordSize));
+ masm.movl(cnt2, new AMD64Address(rsp, 3 * wordSize));
+ masm.movdqu(vec, new AMD64Address(charPtr2, 0));
+ // We came here after the beginning of the substring was
+ // matched but the rest of it was not so we need to search
+ // again. Start from the next element after the previous match.
+ masm.subq(charPtr1, result); // Restore counter
+ masm.shrl(charPtr1, 1);
+ masm.addl(cnt1, charPtr1);
+ masm.decrementl(cnt1); // Shift to next element
+ masm.cmpl(cnt1, cnt2);
+ masm.jccb(ConditionFlag.Negative, retNotFound); // Left less then substring
+
+ masm.addq(result, 2);
+ } // non constant
+
+ // Scan string for start of substr in 16-byte vectors
+ masm.bind(scanToSubstr);
+ assert cnt1.equals(rdx) && cnt2.equals(rax) && tmp.equals(rcx) : "pcmpestri";
+ masm.pcmpestri(vec, new AMD64Address(result, 0), 0x0d);
+ masm.jccb(ConditionFlag.Below, foundCandidate); // CF == 1
+ masm.subl(cnt1, 8);
+ masm.jccb(ConditionFlag.LessEqual, retNotFound); // Scanned full string
+ masm.cmpl(cnt1, cnt2);
+ masm.jccb(ConditionFlag.Negative, retNotFound); // Left less then substring
+ masm.addq(result, 16);
+
+ masm.bind(adjustStr);
+ masm.cmpl(cnt1, 8); // Do not read beyond string
+ masm.jccb(ConditionFlag.GreaterEqual, scanToSubstr);
+ // Back-up string to avoid reading beyond string.
+ masm.leaq(result, new AMD64Address(result, cnt1, Scale.Times2, -16));
+ masm.movl(cnt1, 8);
+ masm.jmpb(scanToSubstr);
+
+ // Found a potential substr
+ masm.bind(foundCandidate);
+ // After pcmpestri tmp(rcx) contains matched element index
+
+ // Make sure string is still long enough
+ masm.subl(cnt1, tmp);
+ masm.cmpl(cnt1, cnt2);
+ masm.jccb(ConditionFlag.GreaterEqual, foundSubstr);
+ // Left less then substring.
+
+ masm.bind(retNotFound);
+ masm.movl(result, -1);
+ masm.jmpb(cleanup);
+
+ masm.bind(foundSubstr);
+ // Compute start addr of substr
+ masm.leaq(result, new AMD64Address(result, tmp, Scale.Times2));
+
+ if (intCnt2 > 0) { // Constant substring
+ // Repeat search for small substring (< 8 chars)
+ // from new point without reloading substring.
+ // Have to check that we don't read beyond string.
+ masm.cmpl(tmp, 8 - intCnt2);
+ masm.jccb(ConditionFlag.Greater, adjustStr);
+ // Fall through if matched whole substring.
+ } else { // non constant
+ assert intCnt2 == -1 : "should be != 0";
+ masm.addl(tmp, cnt2);
+ // Found result if we matched whole substring.
+ masm.cmpl(tmp, 8);
+ masm.jccb(ConditionFlag.LessEqual, retFound);
+
+ // Repeat search for small substring (<= 8 chars)
+ // from new point 'str1' without reloading substring.
+ masm.cmpl(cnt2, 8);
+ // Have to check that we don't read beyond string.
+ masm.jccb(ConditionFlag.LessEqual, adjustStr);
+
+ Label checkNext = new Label();
+ Label contScanSubstr = new Label();
+ Label retFoundLong = new Label();
+ // Compare the rest of substring (> 8 chars).
+ masm.movq(charPtr1, result);
+
+ masm.cmpl(tmp, cnt2);
+ // First 8 chars are already matched.
+ masm.jccb(ConditionFlag.Equal, checkNext);
+
+ masm.bind(scanSubstr);
+ masm.pcmpestri(vec, new AMD64Address(charPtr1, 0), 0x0d);
+ // Need to reload strings pointers if not matched whole vector
+ masm.jcc(ConditionFlag.NoOverflow, reloadSubstr); // OF == 0
+
+ masm.bind(checkNext);
+ masm.subl(cnt2, 8);
+ masm.jccb(ConditionFlag.LessEqual, retFoundLong); // Found full substring
+ masm.addq(charPtr1, 16);
+ masm.addq(charPtr2, 16);
+ masm.subl(cnt1, 8);
+ masm.cmpl(cnt2, 8); // Do not read beyond substring
+ masm.jccb(ConditionFlag.GreaterEqual, contScanSubstr);
+ // Back-up strings to avoid reading beyond substring.
+ masm.leaq(charPtr2, new AMD64Address(charPtr2, cnt2, Scale.Times2, -16));
+ masm.leaq(charPtr1, new AMD64Address(charPtr1, cnt2, Scale.Times2, -16));
+ masm.subl(cnt1, cnt2);
+ masm.movl(cnt2, 8);
+ masm.addl(cnt1, 8);
+ masm.bind(contScanSubstr);
+ masm.movdqu(vec, new AMD64Address(charPtr2, 0));
+ masm.jmpb(scanSubstr);
+
+ masm.bind(retFoundLong);
+ masm.movq(charPtr1, new AMD64Address(rsp, wordSize));
+ } // non constant
+
+ masm.bind(retFound);
+ // Compute substr offset
+ masm.subq(result, charPtr1);
+ masm.shrl(result, 1); // index
+
+ masm.bind(cleanup);
+ masm.pop(rsp); // restore SP
+ }
+
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Unary.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Unary.java Thu Aug 23 11:09:16 2018 -0400
@@ -24,19 +24,19 @@
package org.graalvm.compiler.lir.amd64;
+import static jdk.vm.ci.code.ValueUtil.asRegister;
+import static jdk.vm.ci.code.ValueUtil.isRegister;
+import static jdk.vm.ci.code.ValueUtil.isStackSlot;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.COMPOSITE;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK;
-import static jdk.vm.ci.code.ValueUtil.asRegister;
-import static jdk.vm.ci.code.ValueUtil.isRegister;
-import static jdk.vm.ci.code.ValueUtil.isStackSlot;
import org.graalvm.compiler.asm.amd64.AMD64Address;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MOp;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MROp;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp;
-import org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize;
+import org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize;
import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
import org.graalvm.compiler.lir.LIRFrameState;
import org.graalvm.compiler.lir.LIRInstructionClass;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorBinary.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorBinary.java Thu Aug 23 11:09:16 2018 -0400
@@ -24,35 +24,39 @@
package org.graalvm.compiler.lir.amd64.vector;
-import jdk.vm.ci.meta.AllocatableValue;
-import org.graalvm.compiler.asm.amd64.AMD64Address;
-import org.graalvm.compiler.asm.amd64.AMD64VectorAssembler;
-import org.graalvm.compiler.asm.amd64.AVXKind;
-import org.graalvm.compiler.lir.LIRFrameState;
-import org.graalvm.compiler.lir.LIRInstructionClass;
-import org.graalvm.compiler.lir.Opcode;
-import org.graalvm.compiler.lir.amd64.AMD64AddressValue;
-import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
-
import static jdk.vm.ci.code.ValueUtil.asRegister;
import static jdk.vm.ci.code.ValueUtil.isRegister;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.COMPOSITE;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK;
+import org.graalvm.compiler.asm.amd64.AMD64Address;
+import org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRRIOp;
+import org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp;
+import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
+import org.graalvm.compiler.asm.amd64.AVXKind;
+import org.graalvm.compiler.lir.LIRFrameState;
+import org.graalvm.compiler.lir.LIRInstructionClass;
+import org.graalvm.compiler.lir.Opcode;
+import org.graalvm.compiler.lir.amd64.AMD64AddressValue;
+import org.graalvm.compiler.lir.amd64.AMD64LIRInstruction;
+import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
+
+import jdk.vm.ci.meta.AllocatableValue;
+
public class AMD64VectorBinary {
- public static final class AVXBinaryOp extends AMD64VectorLIRInstruction {
+ public static final class AVXBinaryOp extends AMD64LIRInstruction {
public static final LIRInstructionClass<AVXBinaryOp> TYPE = LIRInstructionClass.create(AVXBinaryOp.class);
- @Opcode private final AMD64VectorAssembler.VexRVMOp opcode;
+ @Opcode private final VexRVMOp opcode;
private final AVXKind.AVXSize size;
@Def({REG}) protected AllocatableValue result;
@Use({REG}) protected AllocatableValue x;
@Use({REG, STACK}) protected AllocatableValue y;
- public AVXBinaryOp(AMD64VectorAssembler.VexRVMOp opcode, AVXKind.AVXSize size, AllocatableValue result, AllocatableValue x, AllocatableValue y) {
+ public AVXBinaryOp(VexRVMOp opcode, AVXKind.AVXSize size, AllocatableValue result, AllocatableValue x, AllocatableValue y) {
super(TYPE);
this.opcode = opcode;
this.size = size;
@@ -62,27 +66,27 @@
}
@Override
- public void emitCode(CompilationResultBuilder crb, AMD64VectorAssembler vasm) {
+ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
if (isRegister(y)) {
- opcode.emit(vasm, size, asRegister(result), asRegister(x), asRegister(y));
+ opcode.emit(masm, size, asRegister(result), asRegister(x), asRegister(y));
} else {
- opcode.emit(vasm, size, asRegister(result), asRegister(x), (AMD64Address) crb.asAddress(y));
+ opcode.emit(masm, size, asRegister(result), asRegister(x), (AMD64Address) crb.asAddress(y));
}
}
}
- public static final class AVXBinaryConstOp extends AMD64VectorLIRInstruction {
+ public static final class AVXBinaryConstOp extends AMD64LIRInstruction {
public static final LIRInstructionClass<AVXBinaryConstOp> TYPE = LIRInstructionClass.create(AVXBinaryConstOp.class);
- @Opcode private final AMD64VectorAssembler.VexRRIOp opcode;
+ @Opcode private final VexRRIOp opcode;
private final AVXKind.AVXSize size;
@Def({REG}) protected AllocatableValue result;
@Use({REG}) protected AllocatableValue x;
protected int y;
- public AVXBinaryConstOp(AMD64VectorAssembler.VexRRIOp opcode, AVXKind.AVXSize size, AllocatableValue result, AllocatableValue x, int y) {
+ public AVXBinaryConstOp(VexRRIOp opcode, AVXKind.AVXSize size, AllocatableValue result, AllocatableValue x, int y) {
super(TYPE);
assert (y & 0xFF) == y;
this.opcode = opcode;
@@ -93,15 +97,15 @@
}
@Override
- public void emitCode(CompilationResultBuilder crb, AMD64VectorAssembler vasm) {
- opcode.emit(vasm, size, asRegister(result), asRegister(x), y);
+ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+ opcode.emit(masm, size, asRegister(result), asRegister(x), y);
}
}
- public static final class AVXBinaryMemoryOp extends AMD64VectorLIRInstruction {
+ public static final class AVXBinaryMemoryOp extends AMD64LIRInstruction {
public static final LIRInstructionClass<AVXBinaryMemoryOp> TYPE = LIRInstructionClass.create(AVXBinaryMemoryOp.class);
- @Opcode private final AMD64VectorAssembler.VexRVMOp opcode;
+ @Opcode private final VexRVMOp opcode;
private final AVXKind.AVXSize size;
@Def({REG}) protected AllocatableValue result;
@@ -109,7 +113,7 @@
@Use({COMPOSITE}) protected AMD64AddressValue y;
@State protected LIRFrameState state;
- public AVXBinaryMemoryOp(AMD64VectorAssembler.VexRVMOp opcode, AVXKind.AVXSize size, AllocatableValue result, AllocatableValue x, AMD64AddressValue y, LIRFrameState state) {
+ public AVXBinaryMemoryOp(VexRVMOp opcode, AVXKind.AVXSize size, AllocatableValue result, AllocatableValue x, AMD64AddressValue y, LIRFrameState state) {
super(TYPE);
this.opcode = opcode;
this.size = size;
@@ -120,11 +124,11 @@
}
@Override
- public void emitCode(CompilationResultBuilder crb, AMD64VectorAssembler vasm) {
+ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
if (state != null) {
- crb.recordImplicitException(vasm.position(), state);
+ crb.recordImplicitException(masm.position(), state);
}
- opcode.emit(vasm, size, asRegister(result), asRegister(x), y.toAddress());
+ opcode.emit(masm, size, asRegister(result), asRegister(x), y.toAddress());
}
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorClearOp.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorClearOp.java Thu Aug 23 11:09:16 2018 -0400
@@ -24,25 +24,25 @@
package org.graalvm.compiler.lir.amd64.vector;
-import static org.graalvm.compiler.asm.amd64.AMD64VectorAssembler.VexRVMOp.VPXOR;
-import static org.graalvm.compiler.asm.amd64.AMD64VectorAssembler.VexRVMOp.VXORPD;
-import static org.graalvm.compiler.asm.amd64.AMD64VectorAssembler.VexRVMOp.VXORPS;
+import static jdk.vm.ci.code.ValueUtil.asRegister;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp.VPXOR;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp.VXORPD;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp.VXORPS;
import static org.graalvm.compiler.asm.amd64.AVXKind.AVXSize.XMM;
-import static jdk.vm.ci.code.ValueUtil.asRegister;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
+import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
+import org.graalvm.compiler.asm.amd64.AVXKind;
import org.graalvm.compiler.lir.LIRInstruction;
import org.graalvm.compiler.lir.LIRInstructionClass;
+import org.graalvm.compiler.lir.amd64.AMD64LIRInstruction;
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
-import org.graalvm.compiler.asm.amd64.AMD64VectorAssembler;
-import org.graalvm.compiler.asm.amd64.AVXKind;
-
import jdk.vm.ci.amd64.AMD64Kind;
import jdk.vm.ci.code.Register;
import jdk.vm.ci.meta.AllocatableValue;
-public class AMD64VectorClearOp extends AMD64VectorLIRInstruction {
+public class AMD64VectorClearOp extends AMD64LIRInstruction {
public static final LIRInstructionClass<AMD64VectorClearOp> TYPE = LIRInstructionClass.create(AMD64VectorClearOp.class);
protected @LIRInstruction.Def({REG}) AllocatableValue result;
@@ -57,23 +57,23 @@
}
@Override
- public void emitCode(CompilationResultBuilder crb, AMD64VectorAssembler vasm) {
+ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
AMD64Kind kind = (AMD64Kind) result.getPlatformKind();
Register register = asRegister(result);
switch (kind.getScalar()) {
case SINGLE:
- VXORPS.emit(vasm, AVXKind.getRegisterSize(kind), register, register, register);
+ VXORPS.emit(masm, AVXKind.getRegisterSize(kind), register, register, register);
break;
case DOUBLE:
- VXORPD.emit(vasm, AVXKind.getRegisterSize(kind), register, register, register);
+ VXORPD.emit(masm, AVXKind.getRegisterSize(kind), register, register, register);
break;
default:
// on AVX1, YMM VPXOR is not supported - still it is possible to clear the whole YMM
// register as the upper 128-bit are implicitly cleared by the AVX1 instruction.
- VPXOR.emit(vasm, XMM, register, register, register);
+ VPXOR.emit(masm, XMM, register, register, register);
}
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorCompareOp.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorCompareOp.java Thu Aug 23 11:09:16 2018 -0400
@@ -24,21 +24,23 @@
package org.graalvm.compiler.lir.amd64.vector;
+import static jdk.vm.ci.code.ValueUtil.asRegister;
+import static jdk.vm.ci.code.ValueUtil.isRegister;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK;
-import static jdk.vm.ci.code.ValueUtil.asRegister;
-import static jdk.vm.ci.code.ValueUtil.isRegister;
-import jdk.vm.ci.meta.AllocatableValue;
import org.graalvm.compiler.asm.amd64.AMD64Address;
-import org.graalvm.compiler.asm.amd64.AMD64VectorAssembler;
-import org.graalvm.compiler.asm.amd64.AMD64VectorAssembler.VexRMOp;
+import org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRMOp;
+import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
+import org.graalvm.compiler.asm.amd64.AVXKind.AVXSize;
import org.graalvm.compiler.lir.LIRInstructionClass;
import org.graalvm.compiler.lir.Opcode;
+import org.graalvm.compiler.lir.amd64.AMD64LIRInstruction;
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
-import org.graalvm.compiler.asm.amd64.AVXKind.AVXSize;
-public final class AMD64VectorCompareOp extends AMD64VectorLIRInstruction {
+import jdk.vm.ci.meta.AllocatableValue;
+
+public final class AMD64VectorCompareOp extends AMD64LIRInstruction {
public static final LIRInstructionClass<AMD64VectorCompareOp> TYPE = LIRInstructionClass.create(AMD64VectorCompareOp.class);
@Opcode private final VexRMOp opcode;
@@ -53,11 +55,11 @@
}
@Override
- public void emitCode(CompilationResultBuilder crb, AMD64VectorAssembler vasm) {
+ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
if (isRegister(y)) {
- opcode.emit(vasm, AVXSize.XMM, asRegister(x), asRegister(y));
+ opcode.emit(masm, AVXSize.XMM, asRegister(x), asRegister(y));
} else {
- opcode.emit(vasm, AVXSize.XMM, asRegister(x), (AMD64Address) crb.asAddress(y));
+ opcode.emit(masm, AVXSize.XMM, asRegister(x), (AMD64Address) crb.asAddress(y));
}
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorLIRInstruction.java Fri Aug 10 14:56:29 2018 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package org.graalvm.compiler.lir.amd64.vector;
-
-import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
-import org.graalvm.compiler.asm.amd64.AMD64VectorAssembler;
-import org.graalvm.compiler.lir.LIRInstructionClass;
-import org.graalvm.compiler.lir.amd64.AMD64LIRInstruction;
-import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
-
-public abstract class AMD64VectorLIRInstruction extends AMD64LIRInstruction {
- public static final LIRInstructionClass<AMD64VectorLIRInstruction> TYPE = LIRInstructionClass.create(AMD64VectorLIRInstruction.class);
-
- protected AMD64VectorLIRInstruction(LIRInstructionClass<? extends AMD64LIRInstruction> c) {
- super(c);
- }
-
- @Override
- public final void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
- emitCode(crb, (AMD64VectorAssembler) masm);
- }
-
- public abstract void emitCode(CompilationResultBuilder crb, AMD64VectorAssembler vasm);
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorMove.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorMove.java Thu Aug 23 11:09:16 2018 -0400
@@ -27,14 +27,14 @@
import static jdk.vm.ci.code.ValueUtil.asRegister;
import static jdk.vm.ci.code.ValueUtil.isRegister;
import static jdk.vm.ci.code.ValueUtil.isStackSlot;
-import static org.graalvm.compiler.asm.amd64.AMD64VectorAssembler.VexMoveOp.VMOVD;
-import static org.graalvm.compiler.asm.amd64.AMD64VectorAssembler.VexMoveOp.VMOVDQU;
-import static org.graalvm.compiler.asm.amd64.AMD64VectorAssembler.VexMoveOp.VMOVQ;
-import static org.graalvm.compiler.asm.amd64.AMD64VectorAssembler.VexMoveOp.VMOVSD;
-import static org.graalvm.compiler.asm.amd64.AMD64VectorAssembler.VexMoveOp.VMOVSS;
-import static org.graalvm.compiler.asm.amd64.AMD64VectorAssembler.VexMoveOp.VMOVUPD;
-import static org.graalvm.compiler.asm.amd64.AMD64VectorAssembler.VexMoveOp.VMOVUPS;
-import static org.graalvm.compiler.asm.amd64.AMD64VectorAssembler.VexRVMOp.VXORPD;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexMoveOp.VMOVD;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexMoveOp.VMOVDQU;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexMoveOp.VMOVQ;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexMoveOp.VMOVSD;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexMoveOp.VMOVSS;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexMoveOp.VMOVUPD;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexMoveOp.VMOVUPS;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp.VXORPD;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.COMPOSITE;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
@@ -42,9 +42,8 @@
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.UNINITIALIZED;
import org.graalvm.compiler.asm.amd64.AMD64Address;
+import org.graalvm.compiler.asm.amd64.AMD64Assembler.VexMoveOp;
import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
-import org.graalvm.compiler.asm.amd64.AMD64VectorAssembler;
-import org.graalvm.compiler.asm.amd64.AMD64VectorAssembler.VexMoveOp;
import org.graalvm.compiler.asm.amd64.AVXKind;
import org.graalvm.compiler.asm.amd64.AVXKind.AVXSize;
import org.graalvm.compiler.debug.GraalError;
@@ -54,6 +53,7 @@
import org.graalvm.compiler.lir.StandardOp.LoadConstantOp;
import org.graalvm.compiler.lir.StandardOp.ValueMoveOp;
import org.graalvm.compiler.lir.amd64.AMD64AddressValue;
+import org.graalvm.compiler.lir.amd64.AMD64LIRInstruction;
import org.graalvm.compiler.lir.amd64.AMD64Move;
import org.graalvm.compiler.lir.amd64.AMD64RestoreRegistersOp;
import org.graalvm.compiler.lir.amd64.AMD64SaveRegistersOp;
@@ -71,7 +71,7 @@
public class AMD64VectorMove {
@Opcode("VMOVE")
- public static final class MoveToRegOp extends AMD64VectorLIRInstruction implements ValueMoveOp {
+ public static final class MoveToRegOp extends AMD64LIRInstruction implements ValueMoveOp {
public static final LIRInstructionClass<MoveToRegOp> TYPE = LIRInstructionClass.create(MoveToRegOp.class);
@Def({REG, HINT}) protected AllocatableValue result;
@@ -84,8 +84,8 @@
}
@Override
- public void emitCode(CompilationResultBuilder crb, AMD64VectorAssembler vasm) {
- move(crb, vasm, result, input);
+ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+ move(crb, masm, result, input);
}
@Override
@@ -100,7 +100,7 @@
}
@Opcode("VMOVE")
- public static final class MoveFromRegOp extends AMD64VectorLIRInstruction implements ValueMoveOp {
+ public static final class MoveFromRegOp extends AMD64LIRInstruction implements ValueMoveOp {
public static final LIRInstructionClass<MoveFromRegOp> TYPE = LIRInstructionClass.create(MoveFromRegOp.class);
@Def({REG, STACK}) protected AllocatableValue result;
@@ -113,8 +113,8 @@
}
@Override
- public void emitCode(CompilationResultBuilder crb, AMD64VectorAssembler vasm) {
- move(crb, vasm, result, input);
+ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+ move(crb, masm, result, input);
}
@Override
@@ -129,7 +129,7 @@
}
@Opcode("VMOVE")
- public static class MoveFromConstOp extends AMD64VectorLIRInstruction implements LoadConstantOp {
+ public static class MoveFromConstOp extends AMD64LIRInstruction implements LoadConstantOp {
public static final LIRInstructionClass<MoveFromConstOp> TYPE = LIRInstructionClass.create(MoveFromConstOp.class);
@Def({REG, STACK}) protected AllocatableValue result;
@@ -142,12 +142,12 @@
}
@Override
- public void emitCode(CompilationResultBuilder crb, AMD64VectorAssembler vasm) {
+ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
if (isRegister(result)) {
- const2reg(crb, vasm, (RegisterValue) result, input);
+ const2reg(crb, masm, (RegisterValue) result, input);
} else {
assert isStackSlot(result);
- AMD64Move.const2stack(crb, vasm, result, input);
+ AMD64Move.const2stack(crb, masm, result, input);
}
}
@@ -163,7 +163,7 @@
}
@Opcode("VSTACKMOVE")
- public static final class StackMoveOp extends AMD64VectorLIRInstruction implements ValueMoveOp {
+ public static final class StackMoveOp extends AMD64LIRInstruction implements ValueMoveOp {
public static final LIRInstructionClass<StackMoveOp> TYPE = LIRInstructionClass.create(StackMoveOp.class);
@Def({STACK}) protected AllocatableValue result;
@@ -191,7 +191,7 @@
}
@Override
- public void emitCode(CompilationResultBuilder crb, AMD64VectorAssembler masm) {
+ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
// backup scratch register
move(crb, masm, backupSlot, scratch.asValue(backupSlot.getValueKind()));
// move stack slot
@@ -203,7 +203,7 @@
}
}
- public abstract static class VectorMemOp extends AMD64VectorLIRInstruction {
+ public abstract static class VectorMemOp extends AMD64LIRInstruction {
protected final AVXSize size;
protected final VexMoveOp op;
@@ -219,14 +219,14 @@
this.state = state;
}
- protected abstract void emitMemAccess(AMD64VectorAssembler vasm);
+ protected abstract void emitMemAccess(AMD64MacroAssembler masm);
@Override
- public void emitCode(CompilationResultBuilder crb, AMD64VectorAssembler vasm) {
+ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
if (state != null) {
- crb.recordImplicitException(vasm.position(), state);
+ crb.recordImplicitException(masm.position(), state);
}
- emitMemAccess(vasm);
+ emitMemAccess(masm);
}
}
@@ -241,8 +241,8 @@
}
@Override
- public void emitMemAccess(AMD64VectorAssembler vasm) {
- op.emit(vasm, size, asRegister(result), address.toAddress());
+ public void emitMemAccess(AMD64MacroAssembler masm) {
+ op.emit(masm, size, asRegister(result), address.toAddress());
}
}
@@ -257,8 +257,8 @@
}
@Override
- public void emitMemAccess(AMD64VectorAssembler vasm) {
- op.emit(vasm, size, address.toAddress(), asRegister(input));
+ public void emitMemAccess(AMD64MacroAssembler masm) {
+ op.emit(masm, size, address.toAddress(), asRegister(input));
}
}
@@ -282,7 +282,7 @@
}
AMD64Address addr = (AMD64Address) crb.asAddress(result);
- op.emit((AMD64VectorAssembler) masm, AVXKind.getRegisterSize(kind), addr, register);
+ op.emit(masm, AVXKind.getRegisterSize(kind), addr, register);
} else {
super.saveRegister(crb, masm, result, register);
}
@@ -309,7 +309,7 @@
}
AMD64Address addr = (AMD64Address) crb.asAddress(input);
- op.emit((AMD64VectorAssembler) masm, AVXKind.getRegisterSize(kind), register, addr);
+ op.emit(masm, AVXKind.getRegisterSize(kind), register, addr);
} else {
super.restoreRegister(crb, masm, register, input);
}
@@ -349,7 +349,7 @@
}
}
- private static void move(CompilationResultBuilder crb, AMD64VectorAssembler vasm, AllocatableValue result, Value input) {
+ private static void move(CompilationResultBuilder crb, AMD64MacroAssembler masm, AllocatableValue result, Value input) {
VexMoveOp op;
AVXSize size;
AMD64Kind kind = (AMD64Kind) result.getPlatformKind();
@@ -372,23 +372,23 @@
if (isRegister(input)) {
if (isRegister(result)) {
if (!asRegister(input).equals(asRegister(result))) {
- op.emit(vasm, size, asRegister(result), asRegister(input));
+ op.emit(masm, size, asRegister(result), asRegister(input));
}
} else {
assert isStackSlot(result);
- op.emit(vasm, size, (AMD64Address) crb.asAddress(result), asRegister(input));
+ op.emit(masm, size, (AMD64Address) crb.asAddress(result), asRegister(input));
}
} else {
assert isStackSlot(input) && isRegister(result);
- op.emit(vasm, size, asRegister(result), (AMD64Address) crb.asAddress(input));
+ op.emit(masm, size, asRegister(result), (AMD64Address) crb.asAddress(input));
}
}
- private static void const2reg(CompilationResultBuilder crb, AMD64VectorAssembler vasm, RegisterValue result, JavaConstant input) {
+ private static void const2reg(CompilationResultBuilder crb, AMD64MacroAssembler masm, RegisterValue result, JavaConstant input) {
if (input.isDefaultForKind()) {
AMD64Kind kind = (AMD64Kind) result.getPlatformKind();
Register register = result.getRegister();
- VXORPD.emit(vasm, AVXKind.getRegisterSize(kind), register, register, register);
+ VXORPD.emit(masm, AVXKind.getRegisterSize(kind), register, register, register);
return;
}
@@ -406,10 +406,10 @@
throw GraalError.shouldNotReachHere();
}
VexMoveOp op = getScalarMoveOp((AMD64Kind) result.getPlatformKind());
- op.emit(vasm, AVXSize.XMM, asRegister(result), address);
+ op.emit(masm, AVXSize.XMM, asRegister(result), address);
}
- public static final class AVXMoveToIntOp extends AMD64VectorLIRInstruction {
+ public static final class AVXMoveToIntOp extends AMD64LIRInstruction {
public static final LIRInstructionClass<AVXMoveToIntOp> TYPE = LIRInstructionClass.create(AVXMoveToIntOp.class);
@Opcode private final VexMoveOp opcode;
@@ -425,11 +425,11 @@
}
@Override
- public void emitCode(CompilationResultBuilder crb, AMD64VectorAssembler vasm) {
+ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
if (isRegister(result)) {
- opcode.emitReverse(vasm, AVXSize.XMM, asRegister(result), asRegister(input));
+ opcode.emitReverse(masm, AVXSize.XMM, asRegister(result), asRegister(input));
} else {
- opcode.emit(vasm, AVXSize.XMM, (AMD64Address) crb.asAddress(result), asRegister(input));
+ opcode.emit(masm, AVXSize.XMM, (AMD64Address) crb.asAddress(result), asRegister(input));
}
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorShuffle.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorShuffle.java Thu Aug 23 11:09:16 2018 -0400
@@ -27,31 +27,32 @@
import static jdk.vm.ci.code.ValueUtil.asRegister;
import static jdk.vm.ci.code.ValueUtil.isRegister;
import static jdk.vm.ci.code.ValueUtil.isStackSlot;
-import static org.graalvm.compiler.asm.amd64.AMD64VectorAssembler.VexMRIOp.VEXTRACTF128;
-import static org.graalvm.compiler.asm.amd64.AMD64VectorAssembler.VexMRIOp.VEXTRACTI128;
-import static org.graalvm.compiler.asm.amd64.AMD64VectorAssembler.VexMRIOp.VPEXTRB;
-import static org.graalvm.compiler.asm.amd64.AMD64VectorAssembler.VexMRIOp.VPEXTRD;
-import static org.graalvm.compiler.asm.amd64.AMD64VectorAssembler.VexMRIOp.VPEXTRQ;
-import static org.graalvm.compiler.asm.amd64.AMD64VectorAssembler.VexMRIOp.VPEXTRW;
-import static org.graalvm.compiler.asm.amd64.AMD64VectorAssembler.VexMoveOp.VMOVD;
-import static org.graalvm.compiler.asm.amd64.AMD64VectorAssembler.VexMoveOp.VMOVQ;
-import static org.graalvm.compiler.asm.amd64.AMD64VectorAssembler.VexRVMIOp.VINSERTF128;
-import static org.graalvm.compiler.asm.amd64.AMD64VectorAssembler.VexRVMIOp.VINSERTI128;
-import static org.graalvm.compiler.asm.amd64.AMD64VectorAssembler.VexRVMIOp.VSHUFPD;
-import static org.graalvm.compiler.asm.amd64.AMD64VectorAssembler.VexRVMIOp.VSHUFPS;
-import static org.graalvm.compiler.asm.amd64.AMD64VectorAssembler.VexRVMOp.VPSHUFB;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexMRIOp.VEXTRACTF128;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexMRIOp.VEXTRACTI128;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexMRIOp.VPEXTRB;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexMRIOp.VPEXTRD;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexMRIOp.VPEXTRQ;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexMRIOp.VPEXTRW;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexMoveOp.VMOVD;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexMoveOp.VMOVQ;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMIOp.VINSERTF128;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMIOp.VINSERTI128;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMIOp.VSHUFPD;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMIOp.VSHUFPS;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp.VPSHUFB;
import static org.graalvm.compiler.asm.amd64.AVXKind.AVXSize.XMM;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK;
import org.graalvm.compiler.asm.amd64.AMD64Address;
-import org.graalvm.compiler.asm.amd64.AMD64VectorAssembler;
-import org.graalvm.compiler.asm.amd64.AMD64VectorAssembler.VexMRIOp;
-import org.graalvm.compiler.asm.amd64.AMD64VectorAssembler.VexRMIOp;
-import org.graalvm.compiler.asm.amd64.AMD64VectorAssembler.VexRVMIOp;
+import org.graalvm.compiler.asm.amd64.AMD64Assembler.VexMRIOp;
+import org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRMIOp;
+import org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMIOp;
+import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
import org.graalvm.compiler.asm.amd64.AVXKind;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.lir.LIRInstructionClass;
+import org.graalvm.compiler.lir.amd64.AMD64LIRInstruction;
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
import jdk.vm.ci.amd64.AMD64;
@@ -61,7 +62,7 @@
public class AMD64VectorShuffle {
- public static final class IntToVectorOp extends AMD64VectorLIRInstruction {
+ public static final class IntToVectorOp extends AMD64LIRInstruction {
public static final LIRInstructionClass<IntToVectorOp> TYPE = LIRInstructionClass.create(IntToVectorOp.class);
@Def({REG}) protected AllocatableValue result;
@@ -75,17 +76,17 @@
}
@Override
- public void emitCode(CompilationResultBuilder crb, AMD64VectorAssembler vasm) {
+ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
if (isRegister(value)) {
- VMOVD.emit(vasm, XMM, asRegister(result), asRegister(value));
+ VMOVD.emit(masm, XMM, asRegister(result), asRegister(value));
} else {
assert isStackSlot(value);
- VMOVD.emit(vasm, XMM, asRegister(result), (AMD64Address) crb.asAddress(value));
+ VMOVD.emit(masm, XMM, asRegister(result), (AMD64Address) crb.asAddress(value));
}
}
}
- public static final class LongToVectorOp extends AMD64VectorLIRInstruction {
+ public static final class LongToVectorOp extends AMD64LIRInstruction {
public static final LIRInstructionClass<LongToVectorOp> TYPE = LIRInstructionClass.create(LongToVectorOp.class);
@Def({REG}) protected AllocatableValue result;
@Use({REG, STACK}) protected AllocatableValue value;
@@ -98,17 +99,17 @@
}
@Override
- public void emitCode(CompilationResultBuilder crb, AMD64VectorAssembler vasm) {
+ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
if (isRegister(value)) {
- VMOVQ.emit(vasm, XMM, asRegister(result), asRegister(value));
+ VMOVQ.emit(masm, XMM, asRegister(result), asRegister(value));
} else {
assert isStackSlot(value);
- VMOVQ.emit(vasm, XMM, asRegister(result), (AMD64Address) crb.asAddress(value));
+ VMOVQ.emit(masm, XMM, asRegister(result), (AMD64Address) crb.asAddress(value));
}
}
}
- public static final class ShuffleBytesOp extends AMD64VectorLIRInstruction {
+ public static final class ShuffleBytesOp extends AMD64LIRInstruction {
public static final LIRInstructionClass<ShuffleBytesOp> TYPE = LIRInstructionClass.create(ShuffleBytesOp.class);
@Def({REG}) protected AllocatableValue result;
@Use({REG}) protected AllocatableValue source;
@@ -122,18 +123,18 @@
}
@Override
- public void emitCode(CompilationResultBuilder crb, AMD64VectorAssembler vasm) {
+ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
AMD64Kind kind = (AMD64Kind) result.getPlatformKind();
if (isRegister(selector)) {
- VPSHUFB.emit(vasm, AVXKind.getRegisterSize(kind), asRegister(result), asRegister(source), asRegister(selector));
+ VPSHUFB.emit(masm, AVXKind.getRegisterSize(kind), asRegister(result), asRegister(source), asRegister(selector));
} else {
assert isStackSlot(selector);
- VPSHUFB.emit(vasm, AVXKind.getRegisterSize(kind), asRegister(result), asRegister(source), (AMD64Address) crb.asAddress(selector));
+ VPSHUFB.emit(masm, AVXKind.getRegisterSize(kind), asRegister(result), asRegister(source), (AMD64Address) crb.asAddress(selector));
}
}
}
- public static final class ConstShuffleBytesOp extends AMD64VectorLIRInstruction {
+ public static final class ConstShuffleBytesOp extends AMD64LIRInstruction {
public static final LIRInstructionClass<ConstShuffleBytesOp> TYPE = LIRInstructionClass.create(ConstShuffleBytesOp.class);
@Def({REG}) protected AllocatableValue result;
@Use({REG}) protected AllocatableValue source;
@@ -148,14 +149,14 @@
}
@Override
- public void emitCode(CompilationResultBuilder crb, AMD64VectorAssembler vasm) {
+ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
AMD64Kind kind = (AMD64Kind) result.getPlatformKind();
AMD64Address address = (AMD64Address) crb.recordDataReferenceInCode(selector, selector.length);
- VPSHUFB.emit(vasm, AVXKind.getRegisterSize(kind), asRegister(result), asRegister(source), address);
+ VPSHUFB.emit(masm, AVXKind.getRegisterSize(kind), asRegister(result), asRegister(source), address);
}
}
- public static class ShuffleWordOp extends AMD64VectorLIRInstruction {
+ public static class ShuffleWordOp extends AMD64LIRInstruction {
public static final LIRInstructionClass<ShuffleWordOp> TYPE = LIRInstructionClass.create(ShuffleWordOp.class);
private final VexRMIOp op;
@Def({REG}) protected AllocatableValue result;
@@ -171,17 +172,17 @@
}
@Override
- public void emitCode(CompilationResultBuilder crb, AMD64VectorAssembler vasm) {
+ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
AMD64Kind kind = (AMD64Kind) source.getPlatformKind();
if (isRegister(source)) {
- op.emit(vasm, AVXKind.getRegisterSize(kind), asRegister(result), asRegister(source), selector);
+ op.emit(masm, AVXKind.getRegisterSize(kind), asRegister(result), asRegister(source), selector);
} else {
- op.emit(vasm, AVXKind.getRegisterSize(kind), asRegister(result), (AMD64Address) crb.asAddress(source), selector);
+ op.emit(masm, AVXKind.getRegisterSize(kind), asRegister(result), (AMD64Address) crb.asAddress(source), selector);
}
}
}
- public static class ShuffleFloatOp extends AMD64VectorLIRInstruction {
+ public static class ShuffleFloatOp extends AMD64LIRInstruction {
public static final LIRInstructionClass<ShuffleFloatOp> TYPE = LIRInstructionClass.create(ShuffleFloatOp.class);
@Def({REG}) protected AllocatableValue result;
@Use({REG}) protected AllocatableValue source1;
@@ -197,7 +198,7 @@
}
@Override
- public void emitCode(CompilationResultBuilder crb, AMD64VectorAssembler vasm) {
+ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
AMD64Kind kind = (AMD64Kind) result.getPlatformKind();
VexRVMIOp op;
@@ -213,15 +214,15 @@
}
if (isRegister(source2)) {
- op.emit(vasm, AVXKind.getRegisterSize(kind), asRegister(result), asRegister(source1), asRegister(source2), selector);
+ op.emit(masm, AVXKind.getRegisterSize(kind), asRegister(result), asRegister(source1), asRegister(source2), selector);
} else {
assert isStackSlot(source2);
- op.emit(vasm, AVXKind.getRegisterSize(kind), asRegister(result), asRegister(source1), (AMD64Address) crb.asAddress(source2), selector);
+ op.emit(masm, AVXKind.getRegisterSize(kind), asRegister(result), asRegister(source1), (AMD64Address) crb.asAddress(source2), selector);
}
}
}
- public static final class Extract128Op extends AMD64VectorLIRInstruction {
+ public static final class Extract128Op extends AMD64LIRInstruction {
public static final LIRInstructionClass<Extract128Op> TYPE = LIRInstructionClass.create(Extract128Op.class);
@Def({REG, STACK}) protected AllocatableValue result;
@Use({REG}) protected AllocatableValue source;
@@ -235,7 +236,7 @@
}
@Override
- public void emitCode(CompilationResultBuilder crb, AMD64VectorAssembler vasm) {
+ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
AMD64Kind kind = (AMD64Kind) source.getPlatformKind();
VexMRIOp op;
@@ -253,15 +254,15 @@
}
if (isRegister(result)) {
- op.emit(vasm, AVXKind.getRegisterSize(kind), asRegister(result), asRegister(source), selector);
+ op.emit(masm, AVXKind.getRegisterSize(kind), asRegister(result), asRegister(source), selector);
} else {
assert isStackSlot(result);
- op.emit(vasm, AVXKind.getRegisterSize(kind), (AMD64Address) crb.asAddress(result), asRegister(source), selector);
+ op.emit(masm, AVXKind.getRegisterSize(kind), (AMD64Address) crb.asAddress(result), asRegister(source), selector);
}
}
}
- public static final class Insert128Op extends AMD64VectorLIRInstruction {
+ public static final class Insert128Op extends AMD64LIRInstruction {
public static final LIRInstructionClass<Insert128Op> TYPE = LIRInstructionClass.create(Insert128Op.class);
@Def({REG}) protected AllocatableValue result;
@Use({REG}) protected AllocatableValue source1;
@@ -277,7 +278,7 @@
}
@Override
- public void emitCode(CompilationResultBuilder crb, AMD64VectorAssembler vasm) {
+ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
AMD64Kind kind = (AMD64Kind) result.getPlatformKind();
VexRVMIOp op;
@@ -296,15 +297,15 @@
}
if (isRegister(source2)) {
- op.emit(vasm, AVXKind.getRegisterSize(kind), asRegister(result), asRegister(source1), asRegister(source2), selector);
+ op.emit(masm, AVXKind.getRegisterSize(kind), asRegister(result), asRegister(source1), asRegister(source2), selector);
} else {
assert isStackSlot(source2);
- op.emit(vasm, AVXKind.getRegisterSize(kind), asRegister(result), asRegister(source1), (AMD64Address) crb.asAddress(source2), selector);
+ op.emit(masm, AVXKind.getRegisterSize(kind), asRegister(result), asRegister(source1), (AMD64Address) crb.asAddress(source2), selector);
}
}
}
- public static final class ExtractByteOp extends AMD64VectorLIRInstruction {
+ public static final class ExtractByteOp extends AMD64LIRInstruction {
public static final LIRInstructionClass<ExtractByteOp> TYPE = LIRInstructionClass.create(ExtractByteOp.class);
@Def({REG}) protected AllocatableValue result;
@Use({REG}) protected AllocatableValue vector;
@@ -320,12 +321,12 @@
}
@Override
- public void emitCode(CompilationResultBuilder crb, AMD64VectorAssembler vasm) {
- VPEXTRB.emit(vasm, XMM, asRegister(result), asRegister(vector), selector);
+ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+ VPEXTRB.emit(masm, XMM, asRegister(result), asRegister(vector), selector);
}
}
- public static final class ExtractShortOp extends AMD64VectorLIRInstruction {
+ public static final class ExtractShortOp extends AMD64LIRInstruction {
public static final LIRInstructionClass<ExtractShortOp> TYPE = LIRInstructionClass.create(ExtractShortOp.class);
@Def({REG}) protected AllocatableValue result;
@Use({REG}) protected AllocatableValue vector;
@@ -341,12 +342,12 @@
}
@Override
- public void emitCode(CompilationResultBuilder crb, AMD64VectorAssembler vasm) {
- VPEXTRW.emit(vasm, XMM, asRegister(result), asRegister(vector), selector);
+ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+ VPEXTRW.emit(masm, XMM, asRegister(result), asRegister(vector), selector);
}
}
- public static final class ExtractIntOp extends AMD64VectorLIRInstruction {
+ public static final class ExtractIntOp extends AMD64LIRInstruction {
public static final LIRInstructionClass<ExtractIntOp> TYPE = LIRInstructionClass.create(ExtractIntOp.class);
@Def({REG, STACK}) protected AllocatableValue result;
@Use({REG}) protected AllocatableValue vector;
@@ -362,25 +363,25 @@
}
@Override
- public void emitCode(CompilationResultBuilder crb, AMD64VectorAssembler vasm) {
+ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
if (isRegister(result)) {
if (selector == 0) {
- VMOVD.emitReverse(vasm, XMM, asRegister(result), asRegister(vector));
+ VMOVD.emitReverse(masm, XMM, asRegister(result), asRegister(vector));
} else {
- VPEXTRD.emit(vasm, XMM, asRegister(result), asRegister(vector), selector);
+ VPEXTRD.emit(masm, XMM, asRegister(result), asRegister(vector), selector);
}
} else {
assert isStackSlot(result);
if (selector == 0) {
- VMOVD.emit(vasm, XMM, (AMD64Address) crb.asAddress(result), asRegister(vector));
+ VMOVD.emit(masm, XMM, (AMD64Address) crb.asAddress(result), asRegister(vector));
} else {
- VPEXTRD.emit(vasm, XMM, (AMD64Address) crb.asAddress(result), asRegister(vector), selector);
+ VPEXTRD.emit(masm, XMM, (AMD64Address) crb.asAddress(result), asRegister(vector), selector);
}
}
}
}
- public static final class ExtractLongOp extends AMD64VectorLIRInstruction {
+ public static final class ExtractLongOp extends AMD64LIRInstruction {
public static final LIRInstructionClass<ExtractLongOp> TYPE = LIRInstructionClass.create(ExtractLongOp.class);
@Def({REG, STACK}) protected AllocatableValue result;
@Use({REG}) protected AllocatableValue vector;
@@ -396,19 +397,19 @@
}
@Override
- public void emitCode(CompilationResultBuilder crb, AMD64VectorAssembler vasm) {
+ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
if (isRegister(result)) {
if (selector == 0) {
- VMOVQ.emitReverse(vasm, XMM, asRegister(result), asRegister(vector));
+ VMOVQ.emitReverse(masm, XMM, asRegister(result), asRegister(vector));
} else {
- VPEXTRQ.emit(vasm, XMM, asRegister(result), asRegister(vector), selector);
+ VPEXTRQ.emit(masm, XMM, asRegister(result), asRegister(vector), selector);
}
} else {
assert isStackSlot(result);
if (selector == 0) {
- VMOVQ.emit(vasm, XMM, (AMD64Address) crb.asAddress(result), asRegister(vector));
+ VMOVQ.emit(masm, XMM, (AMD64Address) crb.asAddress(result), asRegister(vector));
} else {
- VPEXTRQ.emit(vasm, XMM, (AMD64Address) crb.asAddress(result), asRegister(vector), selector);
+ VPEXTRQ.emit(masm, XMM, (AMD64Address) crb.asAddress(result), asRegister(vector), selector);
}
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorUnary.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorUnary.java Thu Aug 23 11:09:16 2018 -0400
@@ -24,17 +24,6 @@
package org.graalvm.compiler.lir.amd64.vector;
-import jdk.vm.ci.meta.AllocatableValue;
-import jdk.vm.ci.meta.Value;
-import org.graalvm.compiler.asm.amd64.AMD64Address;
-import org.graalvm.compiler.asm.amd64.AMD64VectorAssembler;
-import org.graalvm.compiler.asm.amd64.AVXKind;
-import org.graalvm.compiler.lir.LIRFrameState;
-import org.graalvm.compiler.lir.LIRInstructionClass;
-import org.graalvm.compiler.lir.Opcode;
-import org.graalvm.compiler.lir.amd64.AMD64AddressValue;
-import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
-
import static jdk.vm.ci.code.ValueUtil.asRegister;
import static jdk.vm.ci.code.ValueUtil.isRegister;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.COMPOSITE;
@@ -44,18 +33,33 @@
import static org.graalvm.compiler.lir.LIRValueUtil.asConstant;
import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue;
+import org.graalvm.compiler.asm.amd64.AMD64Address;
+import org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRMOp;
+import org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp;
+import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
+import org.graalvm.compiler.asm.amd64.AVXKind;
+import org.graalvm.compiler.lir.LIRFrameState;
+import org.graalvm.compiler.lir.LIRInstructionClass;
+import org.graalvm.compiler.lir.Opcode;
+import org.graalvm.compiler.lir.amd64.AMD64AddressValue;
+import org.graalvm.compiler.lir.amd64.AMD64LIRInstruction;
+import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
+
+import jdk.vm.ci.meta.AllocatableValue;
+import jdk.vm.ci.meta.Value;
+
public class AMD64VectorUnary {
- public static final class AVXUnaryOp extends AMD64VectorLIRInstruction {
+ public static final class AVXUnaryOp extends AMD64LIRInstruction {
public static final LIRInstructionClass<AVXUnaryOp> TYPE = LIRInstructionClass.create(AVXUnaryOp.class);
- @Opcode private final AMD64VectorAssembler.VexRMOp opcode;
+ @Opcode private final VexRMOp opcode;
private final AVXKind.AVXSize size;
@Def({REG}) protected AllocatableValue result;
@Use({REG, STACK}) protected AllocatableValue input;
- public AVXUnaryOp(AMD64VectorAssembler.VexRMOp opcode, AVXKind.AVXSize size, AllocatableValue result, AllocatableValue input) {
+ public AVXUnaryOp(VexRMOp opcode, AVXKind.AVXSize size, AllocatableValue result, AllocatableValue input) {
super(TYPE);
this.opcode = opcode;
this.size = size;
@@ -64,26 +68,26 @@
}
@Override
- public void emitCode(CompilationResultBuilder crb, AMD64VectorAssembler vasm) {
+ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
if (isRegister(input)) {
- opcode.emit(vasm, size, asRegister(result), asRegister(input));
+ opcode.emit(masm, size, asRegister(result), asRegister(input));
} else {
- opcode.emit(vasm, size, asRegister(result), (AMD64Address) crb.asAddress(input));
+ opcode.emit(masm, size, asRegister(result), (AMD64Address) crb.asAddress(input));
}
}
}
- public static final class AVXUnaryMemoryOp extends AMD64VectorLIRInstruction {
+ public static final class AVXUnaryMemoryOp extends AMD64LIRInstruction {
public static final LIRInstructionClass<AVXUnaryMemoryOp> TYPE = LIRInstructionClass.create(AVXUnaryMemoryOp.class);
- @Opcode private final AMD64VectorAssembler.VexRMOp opcode;
+ @Opcode private final VexRMOp opcode;
private final AVXKind.AVXSize size;
@Def({REG}) protected AllocatableValue result;
@Use({COMPOSITE}) protected AMD64AddressValue input;
@State protected LIRFrameState state;
- public AVXUnaryMemoryOp(AMD64VectorAssembler.VexRMOp opcode, AVXKind.AVXSize size, AllocatableValue result, AMD64AddressValue input, LIRFrameState state) {
+ public AVXUnaryMemoryOp(VexRMOp opcode, AVXKind.AVXSize size, AllocatableValue result, AMD64AddressValue input, LIRFrameState state) {
super(TYPE);
this.opcode = opcode;
this.size = size;
@@ -93,24 +97,24 @@
}
@Override
- public void emitCode(CompilationResultBuilder crb, AMD64VectorAssembler vasm) {
+ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
if (state != null) {
- crb.recordImplicitException(vasm.position(), state);
+ crb.recordImplicitException(masm.position(), state);
}
- opcode.emit(vasm, size, asRegister(result), input.toAddress());
+ opcode.emit(masm, size, asRegister(result), input.toAddress());
}
}
- public static final class AVXBroadcastOp extends AMD64VectorLIRInstruction {
+ public static final class AVXBroadcastOp extends AMD64LIRInstruction {
public static final LIRInstructionClass<AVXBroadcastOp> TYPE = LIRInstructionClass.create(AVXBroadcastOp.class);
- @Opcode private final AMD64VectorAssembler.VexRMOp opcode;
+ @Opcode private final VexRMOp opcode;
private final AVXKind.AVXSize size;
@Def({REG}) protected AllocatableValue result;
@Use({REG, STACK, CONST}) protected Value input;
- public AVXBroadcastOp(AMD64VectorAssembler.VexRMOp opcode, AVXKind.AVXSize size, AllocatableValue result, Value input) {
+ public AVXBroadcastOp(VexRMOp opcode, AVXKind.AVXSize size, AllocatableValue result, Value input) {
super(TYPE);
this.opcode = opcode;
this.size = size;
@@ -119,30 +123,30 @@
}
@Override
- public void emitCode(CompilationResultBuilder crb, AMD64VectorAssembler vasm) {
+ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
if (isRegister(input)) {
- opcode.emit(vasm, size, asRegister(result), asRegister(input));
+ opcode.emit(masm, size, asRegister(result), asRegister(input));
} else if (isConstantValue(input)) {
int align = input.getPlatformKind().getSizeInBytes();
AMD64Address address = (AMD64Address) crb.recordDataReferenceInCode(asConstant(input), align);
- opcode.emit(vasm, size, asRegister(result), address);
+ opcode.emit(masm, size, asRegister(result), address);
} else {
- opcode.emit(vasm, size, asRegister(result), (AMD64Address) crb.asAddress(input));
+ opcode.emit(masm, size, asRegister(result), (AMD64Address) crb.asAddress(input));
}
}
}
- public static final class AVXConvertMemoryOp extends AMD64VectorLIRInstruction {
+ public static final class AVXConvertMemoryOp extends AMD64LIRInstruction {
public static final LIRInstructionClass<AVXConvertMemoryOp> TYPE = LIRInstructionClass.create(AVXConvertMemoryOp.class);
- @Opcode private final AMD64VectorAssembler.VexRVMOp opcode;
+ @Opcode private final VexRVMOp opcode;
private final AVXKind.AVXSize size;
@Def({REG}) protected AllocatableValue result;
@Use({COMPOSITE}) protected AMD64AddressValue input;
@State protected LIRFrameState state;
- public AVXConvertMemoryOp(AMD64VectorAssembler.VexRVMOp opcode, AVXKind.AVXSize size, AllocatableValue result, AMD64AddressValue input, LIRFrameState state) {
+ public AVXConvertMemoryOp(VexRVMOp opcode, AVXKind.AVXSize size, AllocatableValue result, AMD64AddressValue input, LIRFrameState state) {
super(TYPE);
this.opcode = opcode;
this.size = size;
@@ -152,22 +156,22 @@
}
@Override
- public void emitCode(CompilationResultBuilder crb, AMD64VectorAssembler vasm) {
+ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
if (state != null) {
- crb.recordImplicitException(vasm.position(), state);
+ crb.recordImplicitException(masm.position(), state);
}
- opcode.emit(vasm, size, asRegister(result), asRegister(result), input.toAddress());
+ opcode.emit(masm, size, asRegister(result), asRegister(result), input.toAddress());
}
}
- public static final class AVXConvertOp extends AMD64VectorLIRInstruction {
+ public static final class AVXConvertOp extends AMD64LIRInstruction {
public static final LIRInstructionClass<AVXConvertOp> TYPE = LIRInstructionClass.create(AVXConvertOp.class);
- @Opcode private final AMD64VectorAssembler.VexRVMOp opcode;
+ @Opcode private final VexRVMOp opcode;
@Def({REG}) protected AllocatableValue result;
@Use({REG, STACK}) protected AllocatableValue input;
- public AVXConvertOp(AMD64VectorAssembler.VexRVMOp opcode, AllocatableValue result, AllocatableValue input) {
+ public AVXConvertOp(VexRVMOp opcode, AllocatableValue result, AllocatableValue input) {
super(TYPE);
this.opcode = opcode;
this.result = result;
@@ -175,16 +179,16 @@
}
@Override
- public void emitCode(CompilationResultBuilder crb, AMD64VectorAssembler vasm) {
+ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
if (isRegister(input)) {
if (!asRegister(input).equals(asRegister(result))) {
// clear result register to avoid unnecessary dependency
- AMD64VectorAssembler.VexRVMOp.VXORPD.emit(vasm, AVXKind.AVXSize.XMM, asRegister(result), asRegister(result), asRegister(result));
+ VexRVMOp.VXORPD.emit(masm, AVXKind.AVXSize.XMM, asRegister(result), asRegister(result), asRegister(result));
}
- opcode.emit(vasm, AVXKind.AVXSize.XMM, asRegister(result), asRegister(result), asRegister(input));
+ opcode.emit(masm, AVXKind.AVXSize.XMM, asRegister(result), asRegister(result), asRegister(input));
} else {
- AMD64VectorAssembler.VexRVMOp.VXORPD.emit(vasm, AVXKind.AVXSize.XMM, asRegister(result), asRegister(result), asRegister(result));
- opcode.emit(vasm, AVXKind.AVXSize.XMM, asRegister(result), asRegister(result), (AMD64Address) crb.asAddress(input));
+ VexRVMOp.VXORPD.emit(masm, AVXKind.AVXSize.XMM, asRegister(result), asRegister(result), asRegister(result));
+ opcode.emit(masm, AVXKind.AVXSize.XMM, asRegister(result), asRegister(result), (AMD64Address) crb.asAddress(input));
}
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/SwitchStrategy.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/SwitchStrategy.java Thu Aug 23 11:09:16 2018 -0400
@@ -441,7 +441,7 @@
}
double probabilityStart = probabilitySums[left];
double probabilityMiddle = (probabilityStart + probabilitySums[right + 1]) / 2;
- assert probabilityStart >= probabilityStart;
+ assert probabilityMiddle >= probabilityStart;
int middle = left;
while (getSliceEnd(closure, middle + 1) < right && probabilitySums[getSliceEnd(closure, middle + 1)] < probabilityMiddle) {
middle = getSliceEnd(closure, middle + 1);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/GlobalLivenessAnalysisPhase.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/GlobalLivenessAnalysisPhase.java Thu Aug 23 11:09:16 2018 -0400
@@ -65,7 +65,7 @@
context.contextAdd(livenessInfo);
}
- private final class Analyser {
+ private static final class Analyser {
private static final int LOG_LEVEL = DebugContext.INFO_LEVEL;
@@ -129,7 +129,7 @@
return lir.numVariables();
}
- private int operandNumber(Value operand) {
+ private static int operandNumber(Value operand) {
if (isVariable(operand)) {
return asVariable(operand).index;
}
@@ -318,7 +318,7 @@
}
}
- private int[] bitSetToIntArray(BitSet live) {
+ private static int[] bitSetToIntArray(BitSet live) {
int[] vars = new int[live.cardinality()];
int cnt = 0;
for (int i = live.nextSetBit(0); i >= 0; i = live.nextSetBit(i + 1), cnt++) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGeneratorTool.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGeneratorTool.java Thu Aug 23 11:09:16 2018 -0400
@@ -24,7 +24,6 @@
package org.graalvm.compiler.lir.gen;
-import jdk.vm.ci.code.RegisterConfig;
import org.graalvm.compiler.core.common.CompressEncoding;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.calc.Condition;
@@ -44,6 +43,7 @@
import jdk.vm.ci.code.CodeCacheProvider;
import jdk.vm.ci.code.Register;
import jdk.vm.ci.code.RegisterAttributes;
+import jdk.vm.ci.code.RegisterConfig;
import jdk.vm.ci.code.TargetDescription;
import jdk.vm.ci.code.ValueKindFactory;
import jdk.vm.ci.meta.AllocatableValue;
@@ -268,6 +268,11 @@
throw GraalError.unimplemented("String.indexOf substitution is not implemented on this architecture");
}
+ @SuppressWarnings("unused")
+ default Variable emitArrayIndexOf(JavaKind kind, Value sourcePointer, Value sourceCount, Value charValue) {
+ throw GraalError.unimplemented("String.indexOf substitution is not implemented on this architecture");
+ }
+
void emitBlackhole(Value operand);
LIRKind getLIRKind(Stamp stamp);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/profiling/MethodProfilingPhase.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/profiling/MethodProfilingPhase.java Thu Aug 23 11:09:16 2018 -0400
@@ -51,7 +51,7 @@
new Analyzer(target, lirGenRes.getCompilationUnitName(), lirGenRes.getLIR(), context.diagnosticLirGenTool).run();
}
- private class Analyzer {
+ private static class Analyzer {
private final LIR lir;
private final DiagnosticLIRGeneratorTool diagnosticLirGenTool;
private final LIRInsertionBuffer buffer;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/profiling/MoveProfilingPhase.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/profiling/MoveProfilingPhase.java Thu Aug 23 11:09:16 2018 -0400
@@ -142,7 +142,7 @@
protected String createGroupName() {
if (Options.LIRDynMoveProfileMethod.getValue(lirGenRes.getLIR().getOptions())) {
- return new StringBuilder('"').append(MOVE_OPERATIONS).append(':').append(lirGenRes.getCompilationUnitName()).append('"').toString();
+ return new StringBuilder("\"").append(MOVE_OPERATIONS).append(':').append(lirGenRes.getCompilationUnitName()).append('"').toString();
}
return MOVE_OPERATIONS;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodeinfo/src/org/graalvm/compiler/nodeinfo/NodeCycles.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodeinfo/src/org/graalvm/compiler/nodeinfo/NodeCycles.java Thu Aug 23 11:09:16 2018 -0400
@@ -64,6 +64,8 @@
CYCLES_512(512),
CYCLES_1024(1024);
+ private static final NodeCycles[] VALUES = values();
+
public final int value;
NodeCycles(int value) {
@@ -83,10 +85,9 @@
}
assert base.ordinal() > CYCLES_0.ordinal();
int log2 = log2(base.value * opCount);
- NodeCycles[] values = values();
- for (int i = base.ordinal(); i < values.length; i++) {
- if (log2(values[i].value) == log2) {
- return values[i];
+ for (int i = base.ordinal(); i < VALUES.length; i++) {
+ if (log2(VALUES[i].value) == log2) {
+ return VALUES[i];
}
}
return CYCLES_1024;
@@ -97,13 +98,12 @@
if (rawValue == 0) {
return CYCLES_0;
}
- NodeCycles[] values = values();
- for (int i = CYCLES_0.ordinal(); i < values.length - 1; i++) {
- if (values[i].value >= rawValue && rawValue <= values[i + 1].value) {
- int r1 = values[i].value;
- int r2 = values[i + 1].value;
+ for (int i = CYCLES_0.ordinal(); i < VALUES.length - 1; i++) {
+ if (VALUES[i].value >= rawValue && rawValue <= VALUES[i + 1].value) {
+ int r1 = VALUES[i].value;
+ int r2 = VALUES[i + 1].value;
int diff = r2 - r1;
- return rawValue - r1 > diff / 2 ? values[i + 1] : values[i];
+ return rawValue - r1 > diff / 2 ? VALUES[i + 1] : VALUES[i];
}
}
return CYCLES_1024;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodeinfo/src/org/graalvm/compiler/nodeinfo/NodeSize.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodeinfo/src/org/graalvm/compiler/nodeinfo/NodeSize.java Thu Aug 23 11:09:16 2018 -0400
@@ -65,6 +65,8 @@
SIZE_512(512),
SIZE_1024(1024);
+ private static final NodeSize[] VALUES = values();
+
public final int value;
NodeSize(int value) {
@@ -80,10 +82,9 @@
}
assert base.ordinal() > SIZE_0.ordinal();
int log2 = log2(base.value * opCount);
- NodeSize[] values = values();
- for (int i = base.ordinal(); i < values.length; i++) {
- if (log2(values[i].value) == log2) {
- return values[i];
+ for (int i = base.ordinal(); i < VALUES.length; i++) {
+ if (log2(VALUES[i].value) == log2) {
+ return VALUES[i];
}
}
return SIZE_1024;
@@ -95,13 +96,12 @@
return SIZE_0;
}
assert rawValue > 0;
- NodeSize[] values = values();
- for (int i = SIZE_0.ordinal(); i < values.length - 1; i++) {
- if (values[i].value >= rawValue && rawValue <= values[i + 1].value) {
- int r1 = values[i].value;
- int r2 = values[i + 1].value;
+ for (int i = SIZE_0.ordinal(); i < VALUES.length - 1; i++) {
+ if (VALUES[i].value >= rawValue && rawValue <= VALUES[i + 1].value) {
+ int r1 = VALUES[i].value;
+ int r2 = VALUES[i + 1].value;
int diff = r2 - r1;
- return rawValue - r1 > diff / 2 ? values[i + 1] : values[i];
+ return rawValue - r1 > diff / 2 ? VALUES[i + 1] : VALUES[i];
}
}
return SIZE_1024;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/AbstractBeginNode.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/AbstractBeginNode.java Thu Aug 23 11:09:16 2018 -0400
@@ -112,7 +112,7 @@
};
}
- private class BlockNodeIterator implements Iterator<FixedNode> {
+ private static class BlockNodeIterator implements Iterator<FixedNode> {
private FixedNode current;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ConstantNode.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ConstantNode.java Thu Aug 23 11:09:16 2018 -0400
@@ -43,11 +43,13 @@
import org.graalvm.compiler.nodeinfo.NodeInfo;
import org.graalvm.compiler.nodeinfo.Verbosity;
import org.graalvm.compiler.nodes.calc.FloatingNode;
+import org.graalvm.compiler.nodes.spi.ArrayLengthProvider;
import org.graalvm.compiler.nodes.spi.LIRLowerable;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
import jdk.vm.ci.code.CodeUtil;
import jdk.vm.ci.meta.Constant;
+import jdk.vm.ci.meta.ConstantReflectionProvider;
import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.MetaAccessProvider;
@@ -57,7 +59,7 @@
* The {@code ConstantNode} represents a {@link Constant constant}.
*/
@NodeInfo(nameTemplate = "C({p#rawvalue}) {p#stampKind}", cycles = CYCLES_0, size = SIZE_1)
-public final class ConstantNode extends FloatingNode implements LIRLowerable {
+public final class ConstantNode extends FloatingNode implements LIRLowerable, ArrayLengthProvider {
public static final NodeClass<ConstantNode> TYPE = NodeClass.create(ConstantNode.class);
@@ -532,4 +534,16 @@
return super.toString(verbosity);
}
}
+
+ @Override
+ public ValueNode findLength(FindLengthMode mode, ConstantReflectionProvider constantReflection) {
+ if (constantReflection == null || !(value instanceof JavaConstant) || ((JavaConstant) value).isNull()) {
+ return null;
+ }
+ Integer length = constantReflection.readArrayLength((JavaConstant) value);
+ if (length == null) {
+ return null;
+ }
+ return ConstantNode.forInt(length);
+ }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FixedNode.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FixedNode.java Thu Aug 23 11:09:16 2018 -0400
@@ -38,7 +38,7 @@
@Override
public boolean verify() {
- assertTrue(this.successors().isNotEmpty() || this.predecessor() != null, "FixedNode should not float");
+ assertTrue(this.successors().isNotEmpty() || this.predecessor() != null, "FixedNode should not float: %s", this);
return super.verify();
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FrameState.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FrameState.java Thu Aug 23 11:09:16 2018 -0400
@@ -237,7 +237,8 @@
}
public void setOuterFrameState(FrameState x) {
- assert x == null || (!x.isDeleted() && x.bci >= 0);
+ assert x == null || (!x.isDeleted() && x.bci >= 0) : "cannot set outer frame state of:\n" + toString(this) +
+ "\nto:\n" + toString(x) + "\nisDeleted=" + x.isDeleted();
updateUsages(this.outerFrameState, x);
this.outerFrameState = x;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java Thu Aug 23 11:09:16 2018 -0400
@@ -826,7 +826,21 @@
if (this.graph().hasValueProxies()) {
if (trueSuccessor instanceof LoopExitNode && falseSuccessor instanceof LoopExitNode) {
assert ((LoopExitNode) trueSuccessor).loopBegin() == ((LoopExitNode) falseSuccessor).loopBegin();
- assert trueSuccessor.usages().isEmpty() && falseSuccessor.usages().isEmpty();
+ /*
+ * we can collapse all proxy nodes on one loop exit, the surviving one, which will
+ * be the true successor
+ */
+ if (falseSuccessor.anchored().isEmpty() && falseSuccessor.usages().isNotEmpty()) {
+ for (Node n : falseSuccessor.usages().snapshot()) {
+ assert n instanceof ProxyNode;
+ ((ProxyNode) n).setProxyPoint((LoopExitNode) trueSuccessor);
+ }
+ }
+ /*
+ * The true successor (surviving loop exit) can have usages, namely proxy nodes, the
+ * false successor however, must not have usages any more after the code above
+ */
+ assert trueSuccessor.anchored().isEmpty() && falseSuccessor.usages().isEmpty();
return this.graph().addOrUnique(new ValueProxyNode(replacement, (LoopExitNode) trueSuccessor));
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InliningLog.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InliningLog.java Thu Aug 23 11:09:16 2018 -0400
@@ -386,7 +386,7 @@
}
}
- public final class PlaceholderInvokable implements Invokable {
+ public static final class PlaceholderInvokable implements Invokable {
private int bci;
private ResolvedJavaMethod method;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PiArrayNode.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PiArrayNode.java Thu Aug 23 11:09:16 2018 -0400
@@ -27,6 +27,7 @@
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_0;
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_0;
+import jdk.vm.ci.meta.ConstantReflectionProvider;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.graph.NodeClass;
@@ -48,7 +49,7 @@
@Input ValueNode length;
@Override
- public ValueNode findLength(ArrayLengthProvider.FindLengthMode mode) {
+ public ValueNode findLength(FindLengthMode mode, ConstantReflectionProvider constantReflection) {
return length;
}
@@ -59,7 +60,7 @@
@Override
public Node canonical(CanonicalizerTool tool) {
- if (GraphUtil.arrayLength(object(), ArrayLengthProvider.FindLengthMode.SEARCH_ONLY) != length) {
+ if (GraphUtil.arrayLength(object(), ArrayLengthProvider.FindLengthMode.SEARCH_ONLY, tool.getConstantReflection()) != length) {
return this;
}
return super.canonical(tool);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ProxyNode.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ProxyNode.java Thu Aug 23 11:09:16 2018 -0400
@@ -53,6 +53,11 @@
public abstract ValueNode value();
+ public void setProxyPoint(LoopExitNode newProxyPoint) {
+ this.updateUsages(loopExit, newProxyPoint);
+ this.loopExit = newProxyPoint;
+ }
+
public LoopExitNode proxyPoint() {
return loopExit;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java Thu Aug 23 11:09:16 2018 -0400
@@ -46,7 +46,6 @@
import org.graalvm.compiler.core.common.cfg.BlockMap;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.debug.DebugContext;
-import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.debug.JavaMethodContext;
import org.graalvm.compiler.debug.TTY;
import org.graalvm.compiler.graph.Graph;
@@ -111,6 +110,10 @@
return this == FLOATING_GUARDS;
}
+ public boolean allowsGuardInsertion() {
+ return this.ordinal() <= FIXED_DEOPTS.ordinal();
+ }
+
public boolean areFrameStatesAtDeopts() {
return this == AFTER_FSA;
}
@@ -930,10 +933,9 @@
* Records that {@code method} was used to build this graph.
*/
public void recordMethod(ResolvedJavaMethod method) {
- if (methods == null) {
- throw new GraalError("inlined method recording not enabled for %s", this);
+ if (methods != null) {
+ methods.add(method);
}
- methods.add(method);
}
/**
@@ -941,14 +943,13 @@
* to build another graph.
*/
public void updateMethods(StructuredGraph other) {
- if (methods == null) {
- throw new GraalError("inlined method recording not enabled for %s", this);
- }
- if (other.rootMethod != null) {
- methods.add(other.rootMethod);
- }
- for (ResolvedJavaMethod m : other.methods) {
- methods.add(m);
+ if (methods != null) {
+ if (other.rootMethod != null) {
+ methods.add(other.rootMethod);
+ }
+ for (ResolvedJavaMethod m : other.methods) {
+ methods.add(m);
+ }
}
}
@@ -1006,14 +1007,6 @@
return res;
}
- /**
- *
- * @return true if the graph contains only a {@link StartNode} and {@link ReturnNode}
- */
- public boolean isTrivial() {
- return !(start.next() instanceof ReturnNode);
- }
-
@Override
public JavaMethod asJavaMethod() {
return method();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/debug/DynamicCounterNode.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/debug/DynamicCounterNode.java Thu Aug 23 11:09:16 2018 -0400
@@ -60,18 +60,18 @@
public static final NodeClass<DynamicCounterNode> TYPE = NodeClass.create(DynamicCounterNode.class);
@Input ValueNode increment;
+ protected final String group;
protected final String name;
- protected final String group;
protected final boolean withContext;
- public DynamicCounterNode(String name, String group, ValueNode increment, boolean withContext) {
- this(TYPE, name, group, increment, withContext);
+ public DynamicCounterNode(String group, String name, ValueNode increment, boolean withContext) {
+ this(TYPE, group, name, increment, withContext);
}
- protected DynamicCounterNode(NodeClass<? extends DynamicCounterNode> c, String name, String group, ValueNode increment, boolean withContext) {
+ protected DynamicCounterNode(NodeClass<? extends DynamicCounterNode> c, String group, String name, ValueNode increment, boolean withContext) {
super(c, StampFactory.forVoid());
+ this.group = group;
this.name = name;
- this.group = group;
this.increment = increment;
this.withContext = withContext;
}
@@ -94,11 +94,11 @@
public static void addCounterBefore(String group, String name, long increment, boolean withContext, FixedNode position) {
StructuredGraph graph = position.graph();
- graph.addBeforeFixed(position, position.graph().add(new DynamicCounterNode(name, group, ConstantNode.forLong(increment, position.graph()), withContext)));
+ graph.addBeforeFixed(position, position.graph().add(new DynamicCounterNode(group, name, ConstantNode.forLong(increment, position.graph()), withContext)));
}
@NodeIntrinsic
- public static native void counter(@ConstantNodeParameter String name, @ConstantNodeParameter String group, long increment, @ConstantNodeParameter boolean addContext);
+ public static native void counter(@ConstantNodeParameter String group, @ConstantNodeParameter String name, long increment, @ConstantNodeParameter boolean addContext);
@Override
public void generate(NodeLIRBuilderTool generator) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/debug/WeakCounterNode.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/debug/WeakCounterNode.java Thu Aug 23 11:09:16 2018 -0400
@@ -71,7 +71,7 @@
public static void addCounterBefore(String group, String name, long increment, boolean addContext, ValueNode checkedValue, FixedNode position) {
StructuredGraph graph = position.graph();
- WeakCounterNode counter = graph.add(new WeakCounterNode(name, group, ConstantNode.forLong(increment, graph), addContext, checkedValue));
+ WeakCounterNode counter = graph.add(new WeakCounterNode(group, name, ConstantNode.forLong(increment, graph), addContext, checkedValue));
graph.addBeforeFixed(position, counter);
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BytecodeExceptionNode.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BytecodeExceptionNode.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -63,7 +63,9 @@
OUT_OF_BOUNDS(2, ArrayIndexOutOfBoundsException.class),
CLASS_CAST(2, ClassCastException.class),
ARRAY_STORE(1, ArrayStoreException.class),
- DIVISION_BY_ZERO(0, ArithmeticException.class);
+ DIVISION_BY_ZERO(0, ArithmeticException.class),
+ INTEGER_EXACT_OVERFLOW(0, ArithmeticException.class),
+ LONG_EXACT_OVERFLOW(0, ArithmeticException.class);
final int numArguments;
final Class<? extends Throwable> exceptionClass;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/FixedValueAnchorNode.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/FixedValueAnchorNode.java Thu Aug 23 11:09:16 2018 -0400
@@ -66,7 +66,7 @@
@Override
public boolean inferStamp() {
if (predefinedStamp == null) {
- return updateStamp(object.stamp(NodeView.DEFAULT));
+ return updateStamp(stamp.join(object.stamp(NodeView.DEFAULT)));
} else {
return false;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderContext.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderContext.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -35,6 +35,8 @@
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.core.common.type.StampPair;
+import org.graalvm.compiler.debug.GraalError;
+import org.graalvm.compiler.nodes.AbstractBeginNode;
import org.graalvm.compiler.nodes.AbstractMergeNode;
import org.graalvm.compiler.nodes.CallTargetNode;
import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind;
@@ -49,6 +51,7 @@
import org.graalvm.compiler.nodes.calc.NarrowNode;
import org.graalvm.compiler.nodes.calc.SignExtendNode;
import org.graalvm.compiler.nodes.calc.ZeroExtendNode;
+import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode.BytecodeExceptionKind;
import org.graalvm.compiler.nodes.type.StampTool;
import jdk.vm.ci.code.BailoutException;
@@ -77,6 +80,16 @@
void push(JavaKind kind, ValueNode value);
/**
+ * Pops a value from the frame state stack using an explicit kind.
+ *
+ * @param slotKind the kind to use when type checking this operation
+ * @return the value on the top of the stack
+ */
+ default ValueNode pop(JavaKind slotKind) {
+ throw GraalError.unimplemented();
+ }
+
+ /**
* Adds a node to the graph. If the node is in the graph, returns immediately. If the node is a
* {@link StateSplit} with a null {@linkplain StateSplit#stateAfter() frame state}, the frame
* state is initialized.
@@ -319,6 +332,24 @@
return append(SignExtendNode.create(narrow, 32, NodeView.DEFAULT));
}
}
+
+ /**
+ * @return true if an explicit exception check should be emitted.
+ */
+ default boolean needsExplicitException() {
+ return false;
+ }
+
+ /**
+ * Generates an exception edge for the current bytecode. When {@link #needsExplicitException()}
+ * returns true, this method should return non-null begin nodes.
+ *
+ * @param exceptionKind the type of exception to be created.
+ * @return a begin node that precedes the actual exception instantiation code.
+ */
+ default AbstractBeginNode genExplicitExceptionEdge(@SuppressWarnings("ununsed") BytecodeExceptionKind exceptionKind) {
+ return null;
+ }
}
class GraphBuilderContextUtil {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java Thu Aug 23 11:09:16 2018 -0400
@@ -442,6 +442,7 @@
* {@code declaringClass}
*/
public void register(InvocationPlugin plugin, String name, Type... argumentTypes) {
+ assert plugins != null : String.format("Late registrations of invocation plugins for %s is already closed", declaringType);
boolean isStatic = argumentTypes.length == 0 || argumentTypes[0] != InvocationPlugin.Receiver.class;
if (!isStatic) {
argumentTypes[0] = declaringType;
@@ -567,7 +568,7 @@
/**
* Maps method names to binding lists.
*/
- private final EconomicMap<String, Binding> bindings = EconomicMap.create(Equivalence.DEFAULT);
+ final EconomicMap<String, Binding> bindings = EconomicMap.create(Equivalence.DEFAULT);
/**
* Gets the invocation plugin for a given method.
@@ -883,11 +884,33 @@
flushDeferrables();
}
+ /**
+ * Determines if this object currently contains any plugins (in any state of registration). If
+ * this object has any {@link #defer(Runnable) deferred registrations}, it is assumed that
+ * executing them will result in at least one plugin being registered.
+ */
public boolean isEmpty() {
- if (resolvedRegistrations != null) {
- return resolvedRegistrations.isEmpty();
+ if (parent != null && !parent.isEmpty()) {
+ return false;
+ }
+ UnmodifiableEconomicMap<ResolvedJavaMethod, InvocationPlugin> resolvedRegs = resolvedRegistrations;
+ if (resolvedRegs != null) {
+ if (!resolvedRegs.isEmpty()) {
+ return false;
+ }
}
- return registrations.size() == 0 && lateRegistrations == null;
+ List<Runnable> deferred = deferredRegistrations;
+ if (deferred != null) {
+ if (!deferred.isEmpty()) {
+ return false;
+ }
+ }
+ for (LateClassPlugins late = lateRegistrations; late != null; late = late.next) {
+ if (!late.bindings.isEmpty()) {
+ return false;
+ }
+ }
+ return registrations.size() == 0;
}
/**
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AbstractNewArrayNode.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AbstractNewArrayNode.java Thu Aug 23 11:09:16 2018 -0400
@@ -24,6 +24,7 @@
package org.graalvm.compiler.nodes.java;
+import jdk.vm.ci.meta.ConstantReflectionProvider;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.nodeinfo.NodeInfo;
@@ -45,7 +46,7 @@
}
@Override
- public ValueNode findLength(ArrayLengthProvider.FindLengthMode mode) {
+ public ValueNode findLength(FindLengthMode mode, ConstantReflectionProvider constantReflection) {
return length;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/ArrayLengthNode.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/ArrayLengthNode.java Thu Aug 23 11:09:16 2018 -0400
@@ -44,7 +44,6 @@
import org.graalvm.compiler.nodes.virtual.VirtualArrayNode;
import jdk.vm.ci.meta.ConstantReflectionProvider;
-import jdk.vm.ci.meta.JavaConstant;
/**
* The {@code ArrayLength} instruction gets the length of an array.
@@ -75,7 +74,7 @@
return newArray.length();
}
- ValueNode length = readArrayLengthConstant(forValue, constantReflection);
+ ValueNode length = readArrayLength(forValue, constantReflection);
if (length != null) {
return length;
}
@@ -97,25 +96,7 @@
* @return a node representing the length of {@code array} or null if it is not available
*/
public static ValueNode readArrayLength(ValueNode originalArray, ConstantReflectionProvider constantReflection) {
- ValueNode length = GraphUtil.arrayLength(originalArray, ArrayLengthProvider.FindLengthMode.CANONICALIZE_READ);
- if (length != null) {
- return length;
- }
- return readArrayLengthConstant(originalArray, constantReflection);
- }
-
- private static ValueNode readArrayLengthConstant(ValueNode originalArray, ConstantReflectionProvider constantReflection) {
- ValueNode array = GraphUtil.unproxify(originalArray);
- if (constantReflection != null && array.isConstant() && !array.isNullConstant()) {
- JavaConstant constantValue = array.asJavaConstant();
- if (constantValue != null && constantValue.isNonNull()) {
- Integer constantLength = constantReflection.readArrayLength(constantValue);
- if (constantLength != null) {
- return ConstantNode.forInt(constantLength);
- }
- }
- }
- return null;
+ return GraphUtil.arrayLength(originalArray, ArrayLengthProvider.FindLengthMode.CANONICALIZE_READ, constantReflection);
}
@Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoadFieldNode.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoadFieldNode.java Thu Aug 23 11:09:16 2018 -0400
@@ -38,10 +38,12 @@
import org.graalvm.compiler.nodeinfo.NodeInfo;
import org.graalvm.compiler.nodes.ConstantNode;
import org.graalvm.compiler.nodes.DeoptimizeNode;
+import org.graalvm.compiler.nodes.FixedGuardNode;
import org.graalvm.compiler.nodes.NodeView;
import org.graalvm.compiler.nodes.PhiNode;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.ValuePhiNode;
+import org.graalvm.compiler.nodes.calc.IsNullNode;
import org.graalvm.compiler.nodes.spi.UncheckedInterfaceProvider;
import org.graalvm.compiler.nodes.spi.Virtualizable;
import org.graalvm.compiler.nodes.spi.VirtualizerTool;
@@ -110,8 +112,13 @@
@Override
public ValueNode canonical(CanonicalizerTool tool, ValueNode forObject) {
NodeView view = NodeView.from(tool);
- if (tool.allUsagesAvailable() && hasNoUsages() && !isVolatile() && (isStatic() || StampTool.isPointerNonNull(forObject.stamp(view)))) {
- return null;
+ if (tool.allUsagesAvailable() && hasNoUsages() && !isVolatile()) {
+ if (isStatic() || StampTool.isPointerNonNull(forObject.stamp(view))) {
+ return null;
+ }
+ if (graph().getGuardsStage().allowsGuardInsertion()) {
+ return new FixedGuardNode(new IsNullNode(forObject), DeoptimizationReason.NullCheckException, DeoptimizationAction.InvalidateReprofile, true, getNodeSourcePosition());
+ }
}
return canonical(this, StampPair.create(stamp, uncheckedStamp), forObject, field, tool.getConstantFieldProvider(),
tool.getConstantReflection(), tool.getOptions(), tool.getMetaAccess(), tool.canonicalizeReads(), tool.allUsagesAvailable());
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoadIndexedNode.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoadIndexedNode.java Thu Aug 23 11:09:16 2018 -0400
@@ -27,6 +27,7 @@
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_8;
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_8;
+import org.graalvm.compiler.core.common.calc.CanonicalCondition;
import org.graalvm.compiler.core.common.type.ObjectStamp;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.core.common.type.StampFactory;
@@ -35,10 +36,16 @@
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.graph.spi.Canonicalizable;
import org.graalvm.compiler.graph.spi.CanonicalizerTool;
+import org.graalvm.compiler.graph.spi.Simplifiable;
+import org.graalvm.compiler.graph.spi.SimplifierTool;
import org.graalvm.compiler.nodeinfo.NodeInfo;
import org.graalvm.compiler.nodes.ConstantNode;
+import org.graalvm.compiler.nodes.FixedGuardNode;
+import org.graalvm.compiler.nodes.FixedWithNextNode;
+import org.graalvm.compiler.nodes.LogicNode;
import org.graalvm.compiler.nodes.NodeView;
import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.calc.CompareNode;
import org.graalvm.compiler.nodes.extended.GuardingNode;
import org.graalvm.compiler.nodes.spi.Virtualizable;
import org.graalvm.compiler.nodes.spi.VirtualizerTool;
@@ -48,6 +55,8 @@
import jdk.vm.ci.meta.Assumptions;
import jdk.vm.ci.meta.ConstantReflectionProvider;
+import jdk.vm.ci.meta.DeoptimizationAction;
+import jdk.vm.ci.meta.DeoptimizationReason;
import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.MetaAccessProvider;
@@ -57,7 +66,7 @@
* The {@code LoadIndexedNode} represents a read from an element of an array.
*/
@NodeInfo(cycles = CYCLES_8, size = SIZE_8)
-public class LoadIndexedNode extends AccessIndexedNode implements Virtualizable, Canonicalizable {
+public class LoadIndexedNode extends AccessIndexedNode implements Virtualizable, Canonicalizable, Simplifiable {
public static final NodeClass<LoadIndexedNode> TYPE = NodeClass.create(LoadIndexedNode.class);
@@ -138,6 +147,30 @@
return this;
}
+ @Override
+ public void simplify(SimplifierTool tool) {
+ if (tool.allUsagesAvailable() && hasNoUsages()) {
+ NodeView view = NodeView.from(tool);
+ ValueNode arrayLength = ArrayLengthNode.create(array, tool.getConstantReflection());
+ LogicNode boundsCheck = CompareNode.createCompareNode(CanonicalCondition.BT, index, arrayLength, tool.getConstantReflection(), view);
+ if (boundsCheck.isTautology()) {
+ return;
+ }
+ if (graph().getGuardsStage().allowsGuardInsertion()) {
+ if (!arrayLength.isAlive()) {
+ arrayLength = graph().addOrUniqueWithInputs(arrayLength);
+ if (arrayLength instanceof FixedWithNextNode) {
+ FixedWithNextNode fixedArrayLength = (FixedWithNextNode) arrayLength;
+ graph().addBeforeFixed(this, fixedArrayLength);
+ }
+ }
+ boundsCheck = graph().addOrUniqueWithInputs(boundsCheck);
+ FixedGuardNode fixedGuard = new FixedGuardNode(boundsCheck, DeoptimizationReason.BoundsCheckException, DeoptimizationAction.InvalidateReprofile, false, getNodeSourcePosition());
+ graph().replaceFixedWithFixed(this, graph().add(fixedGuard));
+ }
+ }
+ }
+
private static ValueNode tryConstantFold(ValueNode array, ValueNode index, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection) {
if (array.isConstant() && !array.isNullConstant() && index.isConstant()) {
JavaConstant arrayConstant = array.asJavaConstant();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/NewMultiArrayNode.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/NewMultiArrayNode.java Thu Aug 23 11:09:16 2018 -0400
@@ -27,6 +27,7 @@
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_8;
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_8;
+import jdk.vm.ci.meta.ConstantReflectionProvider;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.core.common.type.TypeReference;
import org.graalvm.compiler.graph.NodeClass;
@@ -89,7 +90,7 @@
}
@Override
- public ValueNode findLength(ArrayLengthProvider.FindLengthMode mode) {
+ public ValueNode findLength(FindLengthMode mode, ConstantReflectionProvider constantReflection) {
return dimension(0);
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/ReadNode.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/ReadNode.java Thu Aug 23 11:09:16 2018 -0400
@@ -125,7 +125,7 @@
}
}
if (locationIdentity.equals(ARRAY_LENGTH_LOCATION)) {
- ValueNode length = GraphUtil.arrayLength(object, ArrayLengthProvider.FindLengthMode.CANONICALIZE_READ);
+ ValueNode length = GraphUtil.arrayLength(object, ArrayLengthProvider.FindLengthMode.CANONICALIZE_READ, tool.getConstantReflection());
if (length != null) {
return length;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/ArrayLengthProvider.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/ArrayLengthProvider.java Thu Aug 23 11:09:16 2018 -0400
@@ -24,6 +24,7 @@
package org.graalvm.compiler.nodes.spi;
+import jdk.vm.ci.meta.ConstantReflectionProvider;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.ValuePhiNode;
import org.graalvm.compiler.nodes.ValueProxyNode;
@@ -65,5 +66,5 @@
*
* This method should not be called directly. Use {@link GraphUtil#arrayLength} instead.
*/
- ValueNode findLength(FindLengthMode mode);
+ ValueNode findLength(FindLengthMode mode, ConstantReflectionProvider constantReflection);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java Thu Aug 23 11:09:16 2018 -0400
@@ -677,7 +677,7 @@
* @param mode The mode as documented in {@link FindLengthMode}.
* @return The array length if one was found, or null otherwise.
*/
- public static ValueNode arrayLength(ValueNode value, ArrayLengthProvider.FindLengthMode mode) {
+ public static ValueNode arrayLength(ValueNode value, FindLengthMode mode, ConstantReflectionProvider constantReflection) {
Objects.requireNonNull(mode);
ValueNode current = value;
@@ -687,14 +687,14 @@
* ArrayLengthProvider, therefore we check this case first.
*/
if (current instanceof ArrayLengthProvider) {
- return ((ArrayLengthProvider) current).findLength(mode);
+ return ((ArrayLengthProvider) current).findLength(mode, constantReflection);
} else if (current instanceof ValuePhiNode) {
- return phiArrayLength((ValuePhiNode) current, mode);
+ return phiArrayLength((ValuePhiNode) current, mode, constantReflection);
} else if (current instanceof ValueProxyNode) {
ValueProxyNode proxy = (ValueProxyNode) current;
- ValueNode length = arrayLength(proxy.getOriginalNode(), mode);
+ ValueNode length = arrayLength(proxy.getOriginalNode(), mode, constantReflection);
if (mode == ArrayLengthProvider.FindLengthMode.CANONICALIZE_READ && length != null && !length.isConstant()) {
length = new ValueProxyNode(length, proxy.proxyPoint());
}
@@ -710,7 +710,7 @@
} while (true);
}
- private static ValueNode phiArrayLength(ValuePhiNode phi, ArrayLengthProvider.FindLengthMode mode) {
+ private static ValueNode phiArrayLength(ValuePhiNode phi, ArrayLengthProvider.FindLengthMode mode, ConstantReflectionProvider constantReflection) {
if (phi.merge() instanceof LoopBeginNode) {
/* Avoid cycle detection by not processing phi functions that could introduce cycles. */
return null;
@@ -719,7 +719,7 @@
ValueNode singleLength = null;
for (int i = 0; i < phi.values().count(); i++) {
ValueNode input = phi.values().get(i);
- ValueNode length = arrayLength(input, mode);
+ ValueNode length = arrayLength(input, mode, constantReflection);
if (length == null) {
return null;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/AllocatedObjectNode.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/AllocatedObjectNode.java Thu Aug 23 11:09:16 2018 -0400
@@ -28,6 +28,7 @@
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_0;
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_0;
+import jdk.vm.ci.meta.ConstantReflectionProvider;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.core.common.type.TypeReference;
import org.graalvm.compiler.graph.NodeClass;
@@ -74,7 +75,7 @@
}
@Override
- public ValueNode findLength(ArrayLengthProvider.FindLengthMode mode) {
- return GraphUtil.arrayLength(virtualObject, mode);
+ public ValueNode findLength(FindLengthMode mode, ConstantReflectionProvider constantReflection) {
+ return GraphUtil.arrayLength(virtualObject, mode, constantReflection);
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/VirtualArrayNode.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/VirtualArrayNode.java Thu Aug 23 11:09:16 2018 -0400
@@ -26,6 +26,7 @@
import java.nio.ByteOrder;
+import jdk.vm.ci.meta.ConstantReflectionProvider;
import org.graalvm.compiler.core.common.spi.ArrayOffsetProvider;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.nodeinfo.NodeInfo;
@@ -138,7 +139,7 @@
}
@Override
- public ValueNode findLength(ArrayLengthProvider.FindLengthMode mode) {
+ public ValueNode findLength(FindLengthMode mode, ConstantReflectionProvider constantReflection) {
return ConstantNode.forInt(length);
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/EnumOptionKey.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/EnumOptionKey.java Thu Aug 23 11:09:16 2018 -0400
@@ -31,13 +31,12 @@
public class EnumOptionKey<T extends Enum<T>> extends OptionKey<T> {
final Class<T> enumClass;
- @SuppressWarnings("unchecked")
public EnumOptionKey(T value) {
super(value);
if (value == null) {
throw new IllegalArgumentException("Value must not be null");
}
- this.enumClass = (Class<T>) value.getClass();
+ this.enumClass = value.getDeclaringClass();
}
/**
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FloatingReadPhase.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FloatingReadPhase.java Thu Aug 23 11:09:16 2018 -0400
@@ -308,7 +308,7 @@
processAccess((MemoryAccess) node, state);
}
- if (createFloatingReads & node instanceof FloatableAccessNode) {
+ if (createFloatingReads && node instanceof FloatableAccessNode) {
processFloatable((FloatableAccessNode) node, state);
} else if (node instanceof MemoryCheckpoint.Single) {
processCheckpoint((MemoryCheckpoint.Single) node, state);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/elem/InlineableGraph.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/elem/InlineableGraph.java Thu Aug 23 11:09:16 2018 -0400
@@ -192,7 +192,7 @@
private static StructuredGraph parseBytecodes(ResolvedJavaMethod method, HighTierContext context, CanonicalizerPhase canonicalizer, StructuredGraph caller, boolean trackNodeSourcePosition) {
DebugContext debug = caller.getDebug();
StructuredGraph newGraph = new StructuredGraph.Builder(caller.getOptions(), debug, AllowAssumptions.ifNonNull(caller.getAssumptions())).method(method).trackNodeSourcePosition(
- trackNodeSourcePosition).build();
+ trackNodeSourcePosition).useProfilingInfo(caller.useProfilingInfo()).build();
try (DebugContext.Scope s = debug.scope("InlineGraph", newGraph)) {
if (!caller.isUnsafeAccessTrackingEnabled()) {
newGraph.disableUnsafeAccessTracking();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/BasePhase.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/BasePhase.java Thu Aug 23 11:09:16 2018 -0400
@@ -260,7 +260,7 @@
return false;
}
- private final class GraphChangeListener extends NodeEventListener {
+ private static final class GraphChangeListener extends NodeEventListener {
boolean changed;
private StructuredGraph graph;
private Mark mark;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64ArrayIndexOfNode.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.replacements.amd64;
+
+import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_512;
+
+import org.graalvm.compiler.core.common.type.StampFactory;
+import org.graalvm.compiler.graph.NodeClass;
+import org.graalvm.compiler.nodeinfo.InputType;
+import org.graalvm.compiler.nodeinfo.NodeCycles;
+import org.graalvm.compiler.nodeinfo.NodeInfo;
+import org.graalvm.compiler.nodes.FixedWithNextNode;
+import org.graalvm.compiler.nodes.NamedLocationIdentity;
+import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.ValueNodeUtil;
+import org.graalvm.compiler.nodes.memory.MemoryAccess;
+import org.graalvm.compiler.nodes.memory.MemoryNode;
+import org.graalvm.compiler.nodes.spi.LIRLowerable;
+import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.Pointer;
+
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.Value;
+
+@NodeInfo(size = SIZE_512, cycles = NodeCycles.CYCLES_UNKNOWN)
+public class AMD64ArrayIndexOfNode extends FixedWithNextNode implements LIRLowerable, MemoryAccess {
+
+ public static final NodeClass<AMD64ArrayIndexOfNode> TYPE = NodeClass.create(AMD64ArrayIndexOfNode.class);
+
+ private final JavaKind kind;
+
+ @Input private ValueNode arrayPointer;
+ @Input private ValueNode arrayLength;
+ @Input private ValueNode searchValue;
+
+ @OptionalInput(InputType.Memory) private MemoryNode lastLocationAccess;
+
+ public AMD64ArrayIndexOfNode(ValueNode arrayPointer, ValueNode arrayLength, ValueNode searchValue, @ConstantNodeParameter JavaKind kind) {
+ super(TYPE, StampFactory.forKind(JavaKind.Int));
+ this.kind = kind;
+ this.arrayPointer = arrayPointer;
+ this.arrayLength = arrayLength;
+ this.searchValue = searchValue;
+ }
+
+ @Override
+ public LocationIdentity getLocationIdentity() {
+ return NamedLocationIdentity.getArrayLocation(kind);
+ }
+
+ @Override
+ public void generate(NodeLIRBuilderTool gen) {
+ Value result = gen.getLIRGeneratorTool().emitArrayIndexOf(kind, gen.operand(arrayPointer), gen.operand(arrayLength), gen.operand(searchValue));
+ gen.setResult(this, result);
+ }
+
+ @Override
+ public MemoryNode getLastLocationAccess() {
+ return lastLocationAccess;
+ }
+
+ @Override
+ public void setLastLocationAccess(MemoryNode lla) {
+ updateUsages(ValueNodeUtil.asNode(lastLocationAccess), ValueNodeUtil.asNode(lla));
+ lastLocationAccess = lla;
+ }
+
+ @NodeIntrinsic
+ public static native int optimizedArrayIndexOf(Pointer arrayPointer, int arrayLength, char searchValue, @ConstantNodeParameter JavaKind kind);
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java Thu Aug 23 11:09:16 2018 -0400
@@ -80,8 +80,8 @@
new JavaKind[]{JavaKind.Int, JavaKind.Long, JavaKind.Object, JavaKind.Boolean, JavaKind.Byte, JavaKind.Short, JavaKind.Char, JavaKind.Float, JavaKind.Double});
registerUnsafePlugins(invocationPlugins, replacementsBytecodeProvider, explicitUnsafeNullChecks);
registerStringPlugins(invocationPlugins, arch, replacementsBytecodeProvider);
- registerStringLatin1Plugins(invocationPlugins, replacementsBytecodeProvider);
- registerStringUTF16Plugins(invocationPlugins, replacementsBytecodeProvider);
+ registerStringLatin1Plugins(invocationPlugins, arch, replacementsBytecodeProvider);
+ registerStringUTF16Plugins(invocationPlugins, arch, replacementsBytecodeProvider);
registerMathPlugins(invocationPlugins, arch, arithmeticStubs, replacementsBytecodeProvider);
registerArraysEqualsPlugins(invocationPlugins, replacementsBytecodeProvider);
}
@@ -198,25 +198,34 @@
r.registerMethodSubstitution(AMD64StringSubstitutions.class, "indexOf", char[].class, int.class,
int.class, char[].class, int.class, int.class, int.class);
}
+ if (arch.getFeatures().contains(CPUFeature.SSSE3)) {
+ r.registerMethodSubstitution(AMD64StringSubstitutions.class, "indexOf", Receiver.class, int.class, int.class);
+ }
r.registerMethodSubstitution(AMD64StringSubstitutions.class, "compareTo", Receiver.class, String.class);
}
}
- private static void registerStringLatin1Plugins(InvocationPlugins plugins, BytecodeProvider replacementsBytecodeProvider) {
+ private static void registerStringLatin1Plugins(InvocationPlugins plugins, AMD64 arch, BytecodeProvider replacementsBytecodeProvider) {
if (JAVA_SPECIFICATION_VERSION >= 9) {
Registration r = new Registration(plugins, "java.lang.StringLatin1", replacementsBytecodeProvider);
r.setAllowOverwrite(true);
r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "compareTo", byte[].class, byte[].class);
r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "compareToUTF16", byte[].class, byte[].class);
+ if (arch.getFeatures().contains(CPUFeature.SSSE3)) {
+ r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "indexOf", byte[].class, int.class, int.class);
+ }
}
}
- private static void registerStringUTF16Plugins(InvocationPlugins plugins, BytecodeProvider replacementsBytecodeProvider) {
+ private static void registerStringUTF16Plugins(InvocationPlugins plugins, AMD64 arch, BytecodeProvider replacementsBytecodeProvider) {
if (JAVA_SPECIFICATION_VERSION >= 9) {
Registration r = new Registration(plugins, "java.lang.StringUTF16", replacementsBytecodeProvider);
r.setAllowOverwrite(true);
r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "compareTo", byte[].class, byte[].class);
r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "compareToLatin1", byte[].class, byte[].class);
+ if (arch.getFeatures().contains(CPUFeature.SSSE3)) {
+ r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "indexOfCharUnsafe", byte[].class, int.class, int.class, int.class);
+ }
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringLatin1Substitutions.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringLatin1Substitutions.java Thu Aug 23 11:09:16 2018 -0400
@@ -24,11 +24,15 @@
package org.graalvm.compiler.replacements.amd64;
+import jdk.vm.ci.meta.JavaKind;
import org.graalvm.compiler.api.replacements.ClassSubstitution;
+import org.graalvm.compiler.api.replacements.Fold;
+import org.graalvm.compiler.api.replacements.Fold.InjectedParameter;
import org.graalvm.compiler.api.replacements.MethodSubstitution;
+import org.graalvm.compiler.core.common.spi.ArrayOffsetProvider;
import org.graalvm.compiler.replacements.nodes.ArrayCompareToNode;
-
-import jdk.vm.ci.meta.JavaKind;
+import org.graalvm.compiler.word.Word;
+import jdk.internal.vm.compiler.word.Pointer;
// JaCoCo Exclude
@@ -40,6 +44,14 @@
@ClassSubstitution(className = "java.lang.StringLatin1", optional = true)
public class AMD64StringLatin1Substitutions {
+ @Fold
+ static int byteArrayBaseOffset(@InjectedParameter ArrayOffsetProvider arrayOffsetProvider) {
+ return arrayOffsetProvider.arrayBaseOffset(JavaKind.Byte);
+ }
+
+ /** Marker value for the {@link InjectedParameter} injected parameter. */
+ static final ArrayOffsetProvider INJECTED = null;
+
/**
* @param value is byte[]
* @param other is byte[]
@@ -58,4 +70,25 @@
return ArrayCompareToNode.compareTo(value, other, value.length, other.length, JavaKind.Byte, JavaKind.Char);
}
+ @MethodSubstitution(optional = true)
+ public static int indexOf(byte[] value, int ch, int origFromIndex) {
+ int fromIndex = origFromIndex;
+ if (ch >>> 8 != 0) {
+ // search value must be a byte value
+ return -1;
+ }
+ int length = value.length;
+ if (fromIndex < 0) {
+ fromIndex = 0;
+ } else if (fromIndex >= length) {
+ // Note: fromIndex might be near -1>>>1.
+ return -1;
+ }
+ Pointer sourcePointer = Word.objectToTrackedPointer(value).add(byteArrayBaseOffset(INJECTED)).add(fromIndex);
+ int result = AMD64ArrayIndexOfNode.optimizedArrayIndexOf(sourcePointer, length - fromIndex, (char) ch, JavaKind.Byte);
+ if (result != -1) {
+ return result + fromIndex;
+ }
+ return result;
+ }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringSubstitutions.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringSubstitutions.java Thu Aug 23 11:09:16 2018 -0400
@@ -92,6 +92,33 @@
return result;
}
+ // Only exists in JDK <= 8
+ @MethodSubstitution(isStatic = false, optional = true)
+ public static int indexOf(String source, int ch, int origFromIndex) {
+ int fromIndex = origFromIndex;
+ final int sourceCount = source.length();
+ if (fromIndex >= sourceCount) {
+ // Note: fromIndex might be near -1>>>1.
+ return -1;
+ }
+ if (fromIndex < 0) {
+ fromIndex = 0;
+ }
+
+ if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
+ char[] sourceArray = StringSubstitutions.getValue(source);
+
+ Pointer sourcePointer = Word.objectToTrackedPointer(sourceArray).add(charArrayBaseOffset(INJECTED)).add(fromIndex * charArrayIndexScale(INJECTED));
+ int result = AMD64ArrayIndexOfNode.optimizedArrayIndexOf(sourcePointer, sourceCount - fromIndex, (char) ch, JavaKind.Char);
+ if (result != -1) {
+ return result + fromIndex;
+ }
+ return result;
+ } else {
+ return indexOf(source, ch, origFromIndex);
+ }
+ }
+
@MethodSubstitution(isStatic = false)
@SuppressFBWarnings(value = "ES_COMPARING_PARAMETER_STRING_WITH_EQ", justification = "reference equality on the receiver is what we want")
public static int compareTo(String receiver, String anotherString) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringUTF16Substitutions.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringUTF16Substitutions.java Thu Aug 23 11:09:16 2018 -0400
@@ -25,10 +25,15 @@
package org.graalvm.compiler.replacements.amd64;
import org.graalvm.compiler.api.replacements.ClassSubstitution;
+import org.graalvm.compiler.api.replacements.Fold;
+import org.graalvm.compiler.api.replacements.Fold.InjectedParameter;
import org.graalvm.compiler.api.replacements.MethodSubstitution;
+import org.graalvm.compiler.core.common.spi.ArrayOffsetProvider;
import org.graalvm.compiler.replacements.nodes.ArrayCompareToNode;
import jdk.vm.ci.meta.JavaKind;
+import org.graalvm.compiler.word.Word;
+import jdk.internal.vm.compiler.word.Pointer;
// JaCoCo Exclude
@@ -40,6 +45,19 @@
@ClassSubstitution(className = "java.lang.StringUTF16", optional = true)
public class AMD64StringUTF16Substitutions {
+ @Fold
+ static int byteArrayBaseOffset(@InjectedParameter ArrayOffsetProvider arrayOffsetProvider) {
+ return arrayOffsetProvider.arrayBaseOffset(JavaKind.Byte);
+ }
+
+ @Fold
+ static int charArrayIndexScale(@InjectedParameter ArrayOffsetProvider arrayOffsetProvider) {
+ return arrayOffsetProvider.arrayScalingFactor(JavaKind.Char);
+ }
+
+ /** Marker value for the {@link InjectedParameter} injected parameter. */
+ static final ArrayOffsetProvider INJECTED = null;
+
/**
* @param value is char[]
* @param other is char[]
@@ -62,4 +80,13 @@
return ArrayCompareToNode.compareTo(other, value, other.length, value.length, JavaKind.Char, JavaKind.Byte);
}
+ @MethodSubstitution(optional = true)
+ public static int indexOfCharUnsafe(byte[] value, int ch, int fromIndex, int max) {
+ Pointer sourcePointer = Word.objectToTrackedPointer(value).add(byteArrayBaseOffset(INJECTED)).add(fromIndex * charArrayIndexScale(INJECTED));
+ int result = AMD64ArrayIndexOfNode.optimizedArrayIndexOf(sourcePointer, max - fromIndex, (char) ch, JavaKind.Char);
+ if (result != -1) {
+ return result + fromIndex;
+ }
+ return result;
+ }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/GeneratedPlugin.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/GeneratedPlugin.java Thu Aug 23 11:09:16 2018 -0400
@@ -51,7 +51,8 @@
public GeneratedPlugin(ExecutableElement intrinsicMethod) {
this.intrinsicMethod = intrinsicMethod;
this.needInjectionProvider = false;
- this.pluginName = intrinsicMethod.getEnclosingElement().getSimpleName() + "_" + intrinsicMethod.getSimpleName();
+ // Lets keep generated class names short to mitigate hitting file name length limits.
+ this.pluginName = intrinsicMethod.getSimpleName().toString();
}
protected abstract TypeElement getAnnotationClass(AbstractProcessor processor);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/PluginGenerator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/PluginGenerator.java Thu Aug 23 11:09:16 2018 -0400
@@ -38,13 +38,6 @@
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.PackageElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.element.VariableElement;
-import javax.lang.model.type.ArrayType;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.TypeMirror;
-import javax.lang.model.type.TypeVariable;
-import javax.lang.model.type.WildcardType;
import javax.tools.Diagnostic;
import javax.tools.JavaFileObject;
@@ -106,49 +99,12 @@
}
}
- private static void appendSimpleTypeName(StringBuilder ret, TypeMirror type) {
- switch (type.getKind()) {
- case DECLARED:
- DeclaredType declared = (DeclaredType) type;
- TypeElement element = (TypeElement) declared.asElement();
- ret.append(element.getSimpleName());
- break;
- case TYPEVAR:
- appendSimpleTypeName(ret, ((TypeVariable) type).getUpperBound());
- break;
- case WILDCARD:
- appendSimpleTypeName(ret, ((WildcardType) type).getExtendsBound());
- break;
- case ARRAY:
- appendSimpleTypeName(ret, ((ArrayType) type).getComponentType());
- ret.append("Array");
- break;
- default:
- ret.append(type);
- }
- }
-
private static void disambiguateNames(List<GeneratedPlugin> plugins) {
- // if we have more than one method with the same name, disambiguate with the argument types
- disambiguateWith(plugins, plugin -> {
- StringBuilder ret = new StringBuilder(plugin.getPluginName());
- for (VariableElement param : plugin.intrinsicMethod.getParameters()) {
- ret.append('_');
- appendSimpleTypeName(ret, param.asType());
- }
- return ret.toString();
- });
-
- // since we're using simple names for argument types, we could still have a collision
- disambiguateWith(plugins, new Function<GeneratedPlugin, String>() {
-
- private int idx = 0;
-
- @Override
- public String apply(GeneratedPlugin plugin) {
- return plugin.getPluginName() + "_" + (idx++);
- }
- });
+ // If we have more than one method with the same name, disambiguate with a numeric suffix.
+ // We use this instead of a suffix based on argument types to mitigate hitting file name
+ // length limits. We start the suffix with "__" to make it visually stick out.
+ int[] nextId = {0};
+ disambiguateWith(plugins, plugin -> plugin.getPluginName() + "__" + nextId[0]++);
}
private static void createPluginFactory(AbstractProcessor processor, Element topLevelClass, List<GeneratedPlugin> plugins) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/DeoptimizeOnExceptionTest.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/DeoptimizeOnExceptionTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -83,7 +83,7 @@
ClassLoader testCl = new MyClassLoader();
@SuppressWarnings("unchecked")
Class<Runnable> c = (Class<Runnable>) testCl.loadClass(name);
- Runnable r = c.newInstance();
+ Runnable r = c.getDeclaredConstructor().newInstance();
ct = Long.MAX_VALUE;
// warmup
for (int i = 0; i < 100; i++) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/DeoptimizeOnIntegerExactTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.replacements.test;
+
+import jdk.vm.ci.meta.SpeculationLog;
+import org.graalvm.compiler.code.CompilationResult;
+import org.graalvm.compiler.core.test.GraalCompilerTest;
+import org.graalvm.compiler.debug.DebugContext;
+import org.junit.Test;
+
+import jdk.vm.ci.code.InstalledCode;
+import jdk.vm.ci.code.InvalidInstalledCodeException;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
+public class DeoptimizeOnIntegerExactTest extends GraalCompilerTest {
+
+ private final SpeculationLog speculationLog;
+
+ static boolean highlyLikely = true;
+ static boolean highlyUnlikely = false;
+
+ public DeoptimizeOnIntegerExactTest() {
+ speculationLog = getCodeCache().createSpeculationLog();
+ }
+
+ public static int testAddExactSnippet(int x, int y) {
+ if (highlyLikely) {
+ return highlyUnlikely ? Math.addExact(x, y) : x;
+ } else {
+ return highlyUnlikely ? y : Math.addExact(x, y);
+ }
+ }
+
+ public static int testSubtractExactSnippet(int x, int y) {
+ if (highlyLikely) {
+ return highlyUnlikely ? Math.subtractExact(x, y) : x;
+ } else {
+ return highlyUnlikely ? y : Math.subtractExact(x, y);
+ }
+ }
+
+ public static int testMultiplyExactSnippet(int x, int y) {
+ if (highlyLikely) {
+ return highlyUnlikely ? Math.multiplyExact(x, y) : x;
+ } else {
+ return highlyUnlikely ? y : Math.multiplyExact(x, y);
+ }
+ }
+
+ public static int testIncrementExactSnippet(int x, int y) {
+ if (highlyLikely) {
+ return highlyUnlikely ? Math.incrementExact(x) : x;
+ } else {
+ return highlyUnlikely ? y : Math.incrementExact(x);
+ }
+ }
+
+ public static int testDecrementExactSnippet(int x, int y) {
+ if (highlyLikely) {
+ return highlyUnlikely ? Math.decrementExact(x) : x;
+ } else {
+ return highlyUnlikely ? y : Math.decrementExact(x);
+ }
+ }
+
+ public void testAgainIfDeopt(String methodName, int x, int y) throws InvalidInstalledCodeException {
+ ResolvedJavaMethod method = getResolvedJavaMethod(methodName);
+ // We speculate on the first compilation. The global value numbering will merge the two
+ // floating integer exact operation nodes.
+ InstalledCode code = getCode(method);
+ code.executeVarargs(x, y);
+ if (!code.isValid()) {
+ // At the recompilation, we anchor the floating integer exact operation nodes at their
+ // corresponding branches.
+ code = getCode(method);
+ code.executeVarargs(x, y);
+ // The recompiled code should not get deoptimized.
+ assertTrue(code.isValid());
+ }
+ }
+
+ @Test
+ public void testAddExact() throws InvalidInstalledCodeException {
+ testAgainIfDeopt("testAddExactSnippet", Integer.MAX_VALUE, 1);
+ }
+
+ @Test
+ public void testSubtractExact() throws InvalidInstalledCodeException {
+ testAgainIfDeopt("testSubtractExactSnippet", 0, Integer.MIN_VALUE);
+ }
+
+ @Test
+ public void testMultiplyExact() throws InvalidInstalledCodeException {
+ testAgainIfDeopt("testMultiplyExactSnippet", Integer.MAX_VALUE, 2);
+ }
+
+ @Test
+ public void testIncrementExact() throws InvalidInstalledCodeException {
+ testAgainIfDeopt("testIncrementExactSnippet", Integer.MAX_VALUE, 1);
+ }
+
+ @Test
+ public void testDecrementExact() throws InvalidInstalledCodeException {
+ testAgainIfDeopt("testDecrementExactSnippet", Integer.MIN_VALUE, 1);
+ }
+
+ @Override
+ protected SpeculationLog getSpeculationLog() {
+ speculationLog.collectFailedSpeculations();
+ return speculationLog;
+ }
+
+ @Override
+ protected InstalledCode addMethod(DebugContext debug, final ResolvedJavaMethod method, final CompilationResult compilationResult) {
+ return getBackend().createInstalledCode(debug, method, compilationResult, speculationLog, null, false);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/IntegerExactExceptionTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.replacements.test;
+
+import org.graalvm.compiler.core.test.GraalCompilerTest;
+import org.junit.Test;
+
+import jdk.vm.ci.code.InstalledCode;
+import jdk.vm.ci.code.InvalidInstalledCodeException;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
+public class IntegerExactExceptionTest extends GraalCompilerTest {
+
+ static int intCounter = 32;
+
+ public void testIntegerExactOverflowSnippet(int input) {
+ try {
+ intCounter = Math.addExact(intCounter, input);
+ } catch (ArithmeticException e) {
+ intCounter = intCounter / 2;
+ }
+ }
+
+ @Test
+ public void testIntegerExact() throws InvalidInstalledCodeException {
+ ResolvedJavaMethod method = getResolvedJavaMethod("testIntegerExactOverflowSnippet");
+ InstalledCode code = getCode(method);
+ code.executeVarargs(this, Integer.MAX_VALUE);
+
+ if (!code.isValid()) {
+ code = getCode(method);
+ code.executeVarargs(this, Integer.MAX_VALUE);
+ assertTrue(code.isValid());
+ }
+ }
+
+ public void testIntegerExactOverflowWithoutHandlerSnippetW(int input) {
+ try {
+ intCounter = Math.addExact(intCounter, input);
+ } finally {
+ intCounter = intCounter / 2;
+ }
+ }
+
+ @Test
+ public void testIntegerExactWithoutHandler() throws InvalidInstalledCodeException {
+ ResolvedJavaMethod method = getResolvedJavaMethod("testIntegerExactOverflowWithoutHandlerSnippetW");
+ InstalledCode code = getCode(method);
+
+ try {
+ code.executeVarargs(this, Integer.MAX_VALUE);
+ } catch (ArithmeticException e) {
+ // An ArithmeticException is expected to be thrown.
+ }
+
+ if (!code.isValid()) {
+ code = getCode(method);
+ try {
+ code.executeVarargs(this, Integer.MAX_VALUE);
+ } catch (ArithmeticException e) {
+ // An ArithmeticException is expected to be thrown.
+ }
+ assertTrue(code.isValid());
+ }
+ }
+
+ static long longCounter = 10;
+
+ public void testLongExactOverflowSnippet(long input) {
+ try {
+ longCounter = Math.addExact(longCounter, input);
+ } catch (ArithmeticException e) {
+ longCounter = longCounter / 2;
+ }
+ }
+
+ @Test
+ public void testLongExact() throws InvalidInstalledCodeException {
+ ResolvedJavaMethod method = getResolvedJavaMethod("testLongExactOverflowSnippet");
+ InstalledCode code = getCode(method);
+ code.executeVarargs(this, Long.MAX_VALUE);
+
+ if (!code.isValid()) {
+ code = getCode(method);
+ code.executeVarargs(this, Long.MAX_VALUE);
+ assertTrue(code.isValid());
+ }
+ }
+
+ public void testLongExactWithoutHandlerSnippet(long input) {
+ try {
+ longCounter = Math.addExact(longCounter, input);
+ } finally {
+ longCounter = longCounter / 2;
+ }
+ }
+
+ @Test
+ public void testLongExactWithoutHandler() throws InvalidInstalledCodeException {
+ ResolvedJavaMethod method = getResolvedJavaMethod("testLongExactWithoutHandlerSnippet");
+ InstalledCode code = getCode(method);
+
+ try {
+ code.executeVarargs(this, Long.MAX_VALUE);
+ } catch (ArithmeticException e) {
+ // An ArithmeticException is expected to be thrown.
+ }
+
+ if (!code.isValid()) {
+ code = getCode(method);
+ try {
+ code.executeVarargs(this, Long.MAX_VALUE);
+ } catch (ArithmeticException e) {
+ // An ArithmeticException is expected to be thrown.
+ }
+ assertTrue(code.isValid());
+ }
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/MethodSubstitutionTest.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/MethodSubstitutionTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -35,6 +35,7 @@
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
import org.graalvm.compiler.nodes.spi.LoweringTool;
+import org.graalvm.compiler.phases.BasePhase;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase;
import org.graalvm.compiler.phases.common.LoweringPhase;
@@ -57,6 +58,11 @@
return testGraph(snippet, null);
}
+ @SuppressWarnings("unused")
+ public BasePhase<HighTierContext> createInliningPhase(StructuredGraph graph) {
+ return new InliningPhase(new CanonicalizerPhase());
+ }
+
@SuppressWarnings("try")
protected StructuredGraph testGraph(final String snippet, String name) {
DebugContext debug = getDebugContext();
@@ -64,7 +70,7 @@
StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES, debug);
HighTierContext context = getDefaultHighTierContext();
debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph");
- new InliningPhase(new CanonicalizerPhase()).apply(graph, context);
+ createInliningPhase(graph).apply(graph, context);
debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph");
new CanonicalizerPhase().apply(graph, context);
new DeadCodeEliminationPhase().apply(graph);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringCompareToTest.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringCompareToTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -24,69 +24,19 @@
package org.graalvm.compiler.replacements.test;
-import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.replacements.nodes.ArrayCompareToNode;
-import org.junit.Assert;
-import org.junit.Assume;
import org.junit.Test;
-import jdk.vm.ci.amd64.AMD64;
-import jdk.vm.ci.aarch64.AArch64;
-import jdk.vm.ci.code.InstalledCode;
-import jdk.vm.ci.meta.ResolvedJavaMethod;
-
/**
* Tests compareTo method intrinsic.
*/
-public class StringCompareToTest extends MethodSubstitutionTest {
-
- private ResolvedJavaMethod realMethod = null;
- private ResolvedJavaMethod testMethod = null;
- private InstalledCode testCode = null;
-
- private final String[] testData = new String[]{
- "A", "\uFF21", "AB", "A", "a", "Ab", "AA", "\uFF21",
- "A\uFF21", "ABC", "AB", "ABcD", "ABCD\uFF21\uFF21", "ABCD\uFF21", "ABCDEFG\uFF21", "ABCD",
- "ABCDEFGH\uFF21\uFF21", "\uFF22", "\uFF21\uFF22", "\uFF21A",
- "\uFF21\uFF21",
- "\u043c\u0430\u043c\u0430\u0020\u043c\u044b\u043b\u0430\u0020\u0440\u0430\u043c\u0443\u002c\u0020\u0440\u0430\u043c\u0430\u0020\u0441\u044a\u0435\u043b\u0430\u0020\u043c\u0430\u043c\u0443",
- "crazy dog jumps over laszy fox",
- "some-string\0xff",
- "XMM-XMM-YMM-YMM-ZMM-ZMM-ZMM-ZMM-",
- "XMM-XMM+YMM-YMM-ZMM-ZMM-ZMM-ZMM-",
- "XMM-XMM-YMM-YMM+ZMM-ZMM-ZMM-ZMM-",
- "XMM-XMM-YMM-YMM-ZMM-ZMM-ZMM-ZMM+",
- "XMM-XMM-XMM-XMM-YMM-YMM-YMM-YMM-ZMM-ZMM-ZMM-ZMM-ZMM-ZMM-ZMM-ZMM-",
- "XMM-XMM-XMM-XMM+YMM-YMM-YMM-YMM-ZMM-ZMM-ZMM-ZMM-ZMM-ZMM-ZMM-ZMM-",
- "XMM-XMM-XMM-XMM-YMM-YMM-YMM-YMM+ZMM-ZMM-ZMM-ZMM-ZMM-ZMM-ZMM-ZMM-",
- "XMM-XMM-XMM-XMM-YMM-YMM-YMM-YMM-ZMM-ZMM-ZMM-ZMM-ZMM-ZMM-ZMM-ZMM+",
- ""
- };
+public class StringCompareToTest extends StringSubstitutionTestBase {
public StringCompareToTest() {
- Assume.assumeTrue((getTarget().arch instanceof AMD64) || (getTarget().arch instanceof AArch64));
-
- realMethod = getResolvedJavaMethod(String.class, "compareTo", String.class);
- testMethod = getResolvedJavaMethod("stringCompareTo");
- StructuredGraph graph = testGraph("stringCompareTo");
-
- // Check to see if the resulting graph contains the expected node
- StructuredGraph replacement = getReplacements().getSubstitution(realMethod, -1, false, null);
- if (replacement == null) {
- assertInGraph(graph, ArrayCompareToNode.class);
- }
-
- // Force compilation
- testCode = getCode(testMethod);
- Assert.assertNotNull(testCode);
- }
-
- private void executeStringCompareTo(String s0, String s1) {
- Object expected = invokeSafe(realMethod, s0, s1);
- // Verify that the original method and the substitution produce the same value
- assertDeepEquals(expected, invokeSafe(testMethod, null, s0, s1));
- // Verify that the generated code and the original produce the same value
- assertDeepEquals(expected, executeVarargsSafe(testCode, s0, s1));
+ initSubstitution(
+ getResolvedJavaMethod(String.class, "compareTo", String.class),
+ getResolvedJavaMethod("stringCompareTo"),
+ ArrayCompareToNode.class);
}
public static int stringCompareTo(String a, String b) {
@@ -94,36 +44,20 @@
}
@Test
+ @Override
public void testEqualString() {
- String s = "equal-string";
- executeStringCompareTo(s, new String(s.toCharArray()));
+ super.testEqualString();
}
@Test
+ @Override
public void testDifferentString() {
- // Smoke test for primary cases
- executeStringCompareTo("AAAAAAAA", "");
- // LL
- executeStringCompareTo("some-stringA", "some-string\0xff");
- // UU
- executeStringCompareTo("\u2241AAAAAAAB", "\u2241\u0041\u0041\u0041\u0041\u0041\u0041\u0041\uFF41");
- // LU
- executeStringCompareTo("AAAAAAAAB", "\u0041\u0041\u0041\u0041\u0041\u0041\u0041\u0041\uFF41");
+ super.testDifferentString();
}
@Test
+ @Override
public void testAllStrings() {
- for (String s0 : testData) {
- for (String s1 : testData) {
- try {
- executeStringCompareTo(s0, s1);
- } catch (AssertionError ex) {
- System.out.println("FAIL: '" + ex + "'");
- System.out.println(" ***: s0 '" + s0 + "'");
- System.out.println(" ***: s1 '" + s1 + "'");
- throw ex;
- }
- }
- }
+ super.testAllStrings();
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringEqualsTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.replacements.test;
+
+import org.graalvm.compiler.replacements.nodes.ArrayEqualsNode;
+import org.junit.Test;
+
+/**
+ * Tests compareTo method intrinsic.
+ */
+public class StringEqualsTest extends StringSubstitutionTestBase {
+
+ public StringEqualsTest() {
+ initSubstitution(
+ getResolvedJavaMethod(String.class, "equals"),
+ getResolvedJavaMethod("stringEquals"),
+ ArrayEqualsNode.class);
+ }
+
+ public static boolean stringEquals(String a, String b) {
+ return a.equals(b);
+ }
+
+ @Test
+ @Override
+ public void testEqualString() {
+ super.testEqualString();
+ }
+
+ @Test
+ @Override
+ public void testDifferentString() {
+ super.testDifferentString();
+ }
+
+ @Test
+ @Override
+ public void testAllStrings() {
+ super.testAllStrings();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringIndexOfCharTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2018, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.replacements.test;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.graalvm.compiler.core.test.GraalCompilerTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(value = Parameterized.class)
+public class StringIndexOfCharTest extends GraalCompilerTest {
+ @Parameterized.Parameter(value = 0) public String sourceString;
+ @Parameterized.Parameter(value = 1) public int constantChar;
+ @Parameterized.Parameter(value = 2) public int fromIndex;
+
+ @Parameterized.Parameters(name = "{0},{1},{2}")
+ public static Collection<Object[]> data() {
+ ArrayList<Object[]> tests = new ArrayList<>();
+ String longString = "ab";
+ for (int i = 0; i < 15; i++) {
+ longString = longString + longString;
+ }
+ longString = longString + "xx";
+ String longUTF16String = "\u03bb" + longString;
+ String mediumString = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaax" +
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
+ String mediumUTF16String = "\u03bbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaax" +
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
+ String[] targets = new String[]{"foobar", "foo", "bar", "\u03bbfoobar", mediumString, mediumUTF16String, longString, longUTF16String};
+ int[] targetChars = new int[]{'f', 'o', 'r', 'x', Character.MIN_SUPPLEMENTARY_CODE_POINT};
+ int[] targetOffsets = new int[18];
+ for (int i = 0; i < 18; i++) {
+ targetOffsets[i] = i - 1;
+ }
+ for (String source : targets) {
+ for (int targetChar : targetChars) {
+ for (int offset : targetOffsets) {
+ tests.add(new Object[]{source, targetChar, offset});
+ }
+ }
+ }
+
+ return tests;
+ }
+
+ public int testStringIndexOf(String a, int b) {
+ return a.indexOf(b);
+ }
+
+ public int testStringIndexOfOffset(String a, int b, int offset) {
+ return a.indexOf(b, offset);
+ }
+
+ @Test
+ public void testStringIndexOfConstant() {
+ test("testStringIndexOf", this.sourceString, this.constantChar);
+ }
+
+ @Test
+ public void testStringIndexOfConstantOffset() {
+ test("testStringIndexOfOffset", this.sourceString, this.constantChar, this.fromIndex);
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringIndexOfConstantTest.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringIndexOfConstantTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -24,15 +24,14 @@
package org.graalvm.compiler.replacements.test;
+import jdk.vm.ci.code.InstalledCode;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.replacements.ConstantBindingParameterPlugin;
import org.junit.Test;
-import jdk.vm.ci.code.InstalledCode;
-import jdk.vm.ci.meta.ResolvedJavaMethod;
-
public class StringIndexOfConstantTest extends StringIndexOfTestBase {
/*
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringIndexOfTestBase.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringIndexOfTestBase.java Thu Aug 23 11:09:16 2018 -0400
@@ -41,6 +41,13 @@
public static Collection<Object[]> data() {
ArrayList<Object[]> tests = new ArrayList<>();
String[] targets = new String[]{"foobar", "foo", "bar"};
+ String[] utf16targets = new String[]{"grga " + ((char) 0x10D) + "varak", "grga", ((char) 0x10D) + "varak"};
+ addTargets(tests, targets);
+ addTargets(tests, utf16targets);
+ return tests;
+ }
+
+ private static void addTargets(ArrayList<Object[]> tests, String[] targets) {
for (String source : targets) {
for (String target : targets) {
tests.add(new Object[]{source, target});
@@ -60,7 +67,6 @@
tests.add(new Object[]{s.substring(0, s.length() - 1) + s, s});
}
}
- return tests;
}
public int testStringIndexOf(String a, String b) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringSubstitutionTestBase.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.replacements.test;
+
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.junit.Assert;
+import org.junit.Assume;
+
+import jdk.vm.ci.amd64.AMD64;
+import jdk.vm.ci.aarch64.AArch64;
+import jdk.vm.ci.code.InstalledCode;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
+/**
+ * Tests compareTo method intrinsic.
+ */
+public class StringSubstitutionTestBase extends MethodSubstitutionTest {
+
+ private ResolvedJavaMethod realMethod = null;
+ private ResolvedJavaMethod testMethod = null;
+ private InstalledCode testCode = null;
+
+ protected final String[] testData = new String[]{
+ "A", "\uFF21", "AB", "A", "a", "Ab", "AA", "\uFF21",
+ "A\uFF21", "ABC", "AB", "ABcD", "ABCD\uFF21\uFF21", "ABCD\uFF21", "ABCDEFG\uFF21", "ABCD",
+ "ABCDEFGH\uFF21\uFF21", "\uFF22", "\uFF21\uFF22", "\uFF21A",
+ "\uFF21\uFF21",
+ "\u043c\u0430\u043c\u0430\u0020\u043c\u044b\u043b\u0430\u0020\u0440\u0430\u043c\u0443\u002c\u0020\u0440\u0430\u043c\u0430\u0020\u0441\u044a\u0435\u043b\u0430\u0020\u043c\u0430\u043c\u0443",
+ "crazy dog jumps over laszy fox",
+ "some-string\0xff",
+ "XMM-XMM-YMM-YMM-ZMM-ZMM-ZMM-ZMM-",
+ "XMM-XMM+YMM-YMM-ZMM-ZMM-ZMM-ZMM-",
+ "XMM-XMM-YMM-YMM+ZMM-ZMM-ZMM-ZMM-",
+ "XMM-XMM-YMM-YMM-ZMM-ZMM-ZMM-ZMM+",
+ "XMM-XMM-XMM-XMM-YMM-YMM-YMM-YMM-ZMM-ZMM-ZMM-ZMM-ZMM-ZMM-ZMM-ZMM-",
+ "XMM-XMM-XMM-XMM+YMM-YMM-YMM-YMM-ZMM-ZMM-ZMM-ZMM-ZMM-ZMM-ZMM-ZMM-",
+ "XMM-XMM-XMM-XMM-YMM-YMM-YMM-YMM+ZMM-ZMM-ZMM-ZMM-ZMM-ZMM-ZMM-ZMM-",
+ "XMM-XMM-XMM-XMM-YMM-YMM-YMM-YMM-ZMM-ZMM-ZMM-ZMM-ZMM-ZMM-ZMM-ZMM+",
+ ""
+ };
+
+ protected void initSubstitution(ResolvedJavaMethod theRealMethod,
+ ResolvedJavaMethod theTestMethod, Class<?> expectedNode) {
+ Assume.assumeTrue((getTarget().arch instanceof AMD64) || (getTarget().arch instanceof AArch64));
+
+ realMethod = theRealMethod;
+ testMethod = theTestMethod;
+
+ StructuredGraph graph = testGraph(testMethod.getName());
+
+ // Check to see if the resulting graph contains the expected node
+ StructuredGraph replacement = getReplacements().getSubstitution(realMethod, -1, false, null);
+ if (replacement == null) {
+ assertInGraph(graph, expectedNode);
+ }
+
+ // Force compilation
+ testCode = getCode(testMethod);
+ Assert.assertNotNull(testCode);
+ }
+
+ private void executeSubstitution(String s0, String s1) {
+ Object expected = invokeSafe(realMethod, s0, s1);
+ // Verify that the original method and the substitution produce the same value
+ assertDeepEquals(expected, invokeSafe(testMethod, null, s0, s1));
+ // Verify that the generated code and the original produce the same value
+ assertDeepEquals(expected, executeVarargsSafe(testCode, s0, s1));
+ }
+
+ protected void testEqualString() {
+ String s = "equal-string";
+ executeSubstitution(s, new String(s.toCharArray()));
+ }
+
+ protected void testDifferentString() {
+ // Smoke test for primary cases
+ executeSubstitution("AAAAAAAA", "");
+ // LL
+ executeSubstitution("some-stringA", "some-string\0xff");
+ // UU
+ executeSubstitution("\u2241AAAAAAAB", "\u2241\u0041\u0041\u0041\u0041\u0041\u0041\u0041\uFF41");
+ // LU
+ executeSubstitution("AAAAAAAAB", "\u0041\u0041\u0041\u0041\u0041\u0041\u0041\u0041\uFF41");
+ }
+
+ protected void testAllStrings() {
+ for (String s0 : testData) {
+ for (String s1 : testData) {
+ try {
+ executeSubstitution(s0, s1);
+ } catch (AssertionError ex) {
+ System.out.println("FAIL: '" + ex + "'");
+ System.out.println(" ***: s0 '" + s0 + "'");
+ System.out.println(" ***: s1 '" + s1 + "'");
+ throw ex;
+ }
+ }
+ }
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringSubstitutionsTest.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringSubstitutionsTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -102,4 +102,44 @@
return a.equals(b);
}
+ @Test
+ public void testIndexOfConstant() {
+ test("indexOfConstant");
+ }
+
+ public int indexOfConstant() {
+ String foobar = "foobar";
+ String bar = "bar";
+ return foobar.indexOf(bar);
+ }
+
+ @Test
+ public void testIndexOfConstantUTF16() {
+ test("indexOfConstantUTF16case1");
+ test("indexOfConstantUTF16case2");
+ test("indexOfConstantUTF16case3");
+ }
+
+ public int indexOfConstantUTF16case1() {
+ return ("grga " + ((char) 0x10D) + "varak").indexOf(((char) 0x10D) + "varak");
+ }
+
+ public int indexOfConstantUTF16case2() {
+ int index = ("grga " + ((char) 0xD) + "varak").indexOf(((char) 0x10D) + "varak");
+ return index;
+ }
+
+ public int indexOfConstantUTF16case3() {
+ int index = ("grga " + ((char) 0x100) + "varak").indexOf(((char) 0x10D) + "varak");
+ return index;
+ }
+
+ @Test
+ public void testCompareTo() {
+ test("compareTo");
+ }
+
+ public int compareTo() {
+ return "ofar".compareTo("rafo");
+ }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/classfile/RedefineIntrinsicTest.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/classfile/RedefineIntrinsicTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -198,6 +198,7 @@
}
}
+ @SuppressWarnings("deprecation")
public static boolean loadAgent(Path agent) throws Exception {
String vmName = ManagementFactory.getRuntimeMXBean().getName();
int p = vmName.indexOf('@');
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ConstantStringIndexOfSnippets.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ConstantStringIndexOfSnippets.java Thu Aug 23 11:09:16 2018 -0400
@@ -49,6 +49,8 @@
public static class Templates extends AbstractTemplates {
private final SnippetInfo indexOfConstant = snippet(ConstantStringIndexOfSnippets.class, "indexOfConstant");
+ private final SnippetInfo latin1IndexOfConstant = snippet(ConstantStringIndexOfSnippets.class, "latin1IndexOfConstant");
+ private final SnippetInfo utf16IndexOfConstant = snippet(ConstantStringIndexOfSnippets.class, "utf16IndexOfConstant");
public Templates(OptionValues options, Iterable<DebugHandlersFactory> factories, Providers providers, SnippetReflectionProvider snippetReflection, TargetDescription target) {
super(options, factories, providers, snippetReflection, target);
@@ -69,6 +71,34 @@
args.addConst("cache", computeCache(targetCharArray));
template(stringIndexOf, args).instantiate(providers.getMetaAccess(), stringIndexOf, DEFAULT_REPLACER, args);
}
+
+ public void lowerLatin1(SnippetLowerableMemoryNode latin1IndexOf, LoweringTool tool) {
+ StructuredGraph graph = latin1IndexOf.graph();
+ Arguments args = new Arguments(latin1IndexOfConstant, graph.getGuardsStage(), tool.getLoweringStage());
+ args.add("source", latin1IndexOf.getArgument(0));
+ args.add("sourceCount", latin1IndexOf.getArgument(1));
+ args.addConst("target", latin1IndexOf.getArgument(2));
+ args.add("targetCount", latin1IndexOf.getArgument(3));
+ args.add("origFromIndex", latin1IndexOf.getArgument(4));
+ byte[] targetByteArray = snippetReflection.asObject(byte[].class, latin1IndexOf.getArgument(2).asJavaConstant());
+ args.addConst("md2", md2(targetByteArray));
+ args.addConst("cache", computeCache(targetByteArray));
+ template(latin1IndexOf, args).instantiate(providers.getMetaAccess(), latin1IndexOf, DEFAULT_REPLACER, args);
+ }
+
+ public void lowerUTF16(SnippetLowerableMemoryNode utf16IndexOf, LoweringTool tool) {
+ StructuredGraph graph = utf16IndexOf.graph();
+ Arguments args = new Arguments(utf16IndexOfConstant, graph.getGuardsStage(), tool.getLoweringStage());
+ args.add("source", utf16IndexOf.getArgument(0));
+ args.add("sourceCount", utf16IndexOf.getArgument(1));
+ args.addConst("target", utf16IndexOf.getArgument(2));
+ args.add("targetCount", utf16IndexOf.getArgument(3));
+ args.add("origFromIndex", utf16IndexOf.getArgument(4));
+ byte[] targetByteArray = snippetReflection.asObject(byte[].class, utf16IndexOf.getArgument(2).asJavaConstant());
+ args.addConst("md2", md2Utf16(targetByteArray));
+ args.addConst("cache", computeCacheUtf16(targetByteArray));
+ template(utf16IndexOf, args).instantiate(providers.getMetaAccess(), utf16IndexOf, DEFAULT_REPLACER, args);
+ }
}
static int md2(char[] target) {
@@ -96,6 +126,65 @@
return cache;
}
+ static int md2(byte[] target) {
+ int c = target.length;
+ if (c == 0) {
+ return 0;
+ }
+ byte lastByte = target[c - 1];
+ int md2 = c;
+ for (int i = 0; i < c - 1; i++) {
+ if (target[i] == lastByte) {
+ md2 = (c - 1) - i;
+ }
+ }
+ return md2;
+ }
+
+ static long computeCache(byte[] s) {
+ int c = s.length;
+ int cache = 0;
+ int i;
+ for (i = 0; i < c - 1; i++) {
+ cache |= (1 << (s[i] & 63));
+ }
+ return cache;
+ }
+
+ static int md2Utf16(byte[] target) {
+ int c = target.length / 2;
+ if (c == 0) {
+ return 0;
+ }
+ long base = UnsafeAccess.UNSAFE.arrayBaseOffset(byte[].class);
+ char lastChar = UnsafeAccess.UNSAFE.getChar(target, base + (c - 1) * 2);
+ int md2 = c;
+ for (int i = 0; i < c - 1; i++) {
+ char currChar = UnsafeAccess.UNSAFE.getChar(target, base + i * 2);
+ if (currChar == lastChar) {
+ md2 = (c - 1) - i;
+ }
+ }
+ return md2;
+ }
+
+ static long computeCacheUtf16(byte[] s) {
+ int c = s.length / 2;
+ int cache = 0;
+ int i;
+ long base = UnsafeAccess.UNSAFE.arrayBaseOffset(byte[].class);
+ for (i = 0; i < c - 1; i++) {
+ char currChar = UnsafeAccess.UNSAFE.getChar(s, base + i * 2);
+ cache |= (1 << (currChar & 63));
+ }
+ return cache;
+ }
+
+ @Fold
+ static int byteArrayBaseOffset(@InjectedParameter ArrayOffsetProvider arrayOffsetProvider) {
+ return arrayOffsetProvider.arrayBaseOffset(JavaKind.Byte);
+ }
+
@Fold
static int charArrayBaseOffset(@InjectedParameter ArrayOffsetProvider arrayOffsetProvider) {
return arrayOffsetProvider.arrayBaseOffset(JavaKind.Char);
@@ -161,4 +250,120 @@
}
return -1;
}
+
+ @Snippet
+ public static int utf16IndexOfConstant(byte[] source, int sourceCount,
+ @ConstantParameter byte[] target, int targetCount,
+ int origFromIndex, @ConstantParameter int md2, @ConstantParameter long cache) {
+ int fromIndex = origFromIndex;
+ if (fromIndex >= sourceCount) {
+ return (targetCount == 0 ? sourceCount : -1);
+ }
+ if (fromIndex < 0) {
+ fromIndex = 0;
+ }
+ if (targetCount == 0) {
+ return fromIndex;
+ }
+
+ int targetCountLess1 = targetCount - 1;
+ int sourceEnd = sourceCount - targetCountLess1;
+
+ long base = byteArrayBaseOffset(INJECTED);
+ int lastChar = UnsafeAccess.UNSAFE.getChar(target, base + targetCountLess1 * 2);
+
+ outer_loop: for (long i = fromIndex; i < sourceEnd;) {
+ int src = UnsafeAccess.UNSAFE.getChar(source, base + (i + targetCountLess1) * 2);
+ if (src == lastChar) {
+ // With random strings and a 4-character alphabet,
+ // reverse matching at this point sets up 0.8% fewer
+ // frames, but (paradoxically) makes 0.3% more probes.
+ // Since those probes are nearer the lastChar probe,
+ // there is may be a net D$ win with reverse matching.
+ // But, reversing loop inhibits unroll of inner loop
+ // for unknown reason. So, does running outer loop from
+ // (sourceOffset - targetCountLess1) to (sourceOffset + sourceCount)
+ if (targetCount <= 8) {
+ ExplodeLoopNode.explodeLoop();
+ }
+ for (long j = 0; j < targetCountLess1; j++) {
+ char sourceChar = UnsafeAccess.UNSAFE.getChar(source, base + (i + j) * 2);
+ if (UnsafeAccess.UNSAFE.getChar(target, base + j * 2) != sourceChar) {
+ if ((cache & (1 << sourceChar)) == 0) {
+ if (md2 < j + 1) {
+ i += j + 1;
+ continue outer_loop;
+ }
+ }
+ i += md2;
+ continue outer_loop;
+ }
+ }
+ return (int) i;
+ }
+ if ((cache & (1 << src)) == 0) {
+ i += targetCountLess1;
+ }
+ i++;
+ }
+ return -1;
+ }
+
+ @Snippet
+ public static int latin1IndexOfConstant(byte[] source, int sourceCount,
+ @ConstantParameter byte[] target, int targetCount,
+ int origFromIndex, @ConstantParameter int md2, @ConstantParameter long cache) {
+ int fromIndex = origFromIndex;
+ if (fromIndex >= sourceCount) {
+ return (targetCount == 0 ? sourceCount : -1);
+ }
+ if (fromIndex < 0) {
+ fromIndex = 0;
+ }
+ if (targetCount == 0) {
+ return fromIndex;
+ }
+
+ int targetCountLess1 = targetCount - 1;
+ int sourceEnd = sourceCount - targetCountLess1;
+
+ long base = byteArrayBaseOffset(INJECTED);
+ int lastByte = UnsafeAccess.UNSAFE.getByte(target, base + targetCountLess1);
+
+ outer_loop: for (long i = fromIndex; i < sourceEnd;) {
+ int src = UnsafeAccess.UNSAFE.getByte(source, base + i + targetCountLess1);
+ if (src == lastByte) {
+ // With random strings and a 4-character alphabet,
+ // reverse matching at this point sets up 0.8% fewer
+ // frames, but (paradoxically) makes 0.3% more probes.
+ // Since those probes are nearer the lastByte probe,
+ // there is may be a net D$ win with reverse matching.
+ // But, reversing loop inhibits unroll of inner loop
+ // for unknown reason. So, does running outer loop from
+ // (sourceOffset - targetCountLess1) to (sourceOffset + sourceCount)
+ if (targetCount <= 8) {
+ ExplodeLoopNode.explodeLoop();
+ }
+ for (long j = 0; j < targetCountLess1; j++) {
+ byte sourceByte = UnsafeAccess.UNSAFE.getByte(source, base + i + j);
+ if (UnsafeAccess.UNSAFE.getByte(target, base + j) != sourceByte) {
+ if ((cache & (1 << sourceByte)) == 0) {
+ if (md2 < j + 1) {
+ i += j + 1;
+ continue outer_loop;
+ }
+ }
+ i += md2;
+ continue outer_loop;
+ }
+ }
+ return (int) i;
+ }
+ if ((cache & (1 << src)) == 0) {
+ i += targetCountLess1;
+ }
+ i++;
+ }
+ return -1;
+ }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java Thu Aug 23 11:09:16 2018 -0400
@@ -239,6 +239,10 @@
lowerBinaryMath((BinaryMathIntrinsicNode) n, tool);
} else if (n instanceof StringIndexOfNode) {
lowerIndexOf((StringIndexOfNode) n);
+ } else if (n instanceof StringLatin1IndexOfNode) {
+ lowerLatin1IndexOf((StringLatin1IndexOfNode) n);
+ } else if (n instanceof StringUTF16IndexOfNode) {
+ lowerUTF16IndexOf((StringUTF16IndexOfNode) n);
} else if (n instanceof UnpackEndianHalfNode) {
lowerSecondHalf((UnpackEndianHalfNode) n);
} else {
@@ -269,6 +273,40 @@
}
}
+ private void lowerLatin1IndexOf(StringLatin1IndexOfNode n) {
+ if (n.getArgument(2).isConstant()) {
+ SnippetLowering lowering = new SnippetLowering() {
+ @Override
+ public void lower(SnippetLowerableMemoryNode node, LoweringTool tool) {
+ if (tool.getLoweringStage() != LoweringTool.StandardLoweringStage.LOW_TIER) {
+ return;
+ }
+ indexOfSnippets.lowerLatin1(node, tool);
+ }
+ };
+ SnippetLowerableMemoryNode snippetLower = new SnippetLowerableMemoryNode(lowering, NamedLocationIdentity.getArrayLocation(JavaKind.Byte), n.stamp(NodeView.DEFAULT), n.toArgumentArray());
+ n.graph().add(snippetLower);
+ n.graph().replaceFixedWithFixed(n, snippetLower);
+ }
+ }
+
+ private void lowerUTF16IndexOf(StringUTF16IndexOfNode n) {
+ if (n.getArgument(2).isConstant()) {
+ SnippetLowering lowering = new SnippetLowering() {
+ @Override
+ public void lower(SnippetLowerableMemoryNode node, LoweringTool tool) {
+ if (tool.getLoweringStage() != LoweringTool.StandardLoweringStage.LOW_TIER) {
+ return;
+ }
+ indexOfSnippets.lowerUTF16(node, tool);
+ }
+ };
+ SnippetLowerableMemoryNode snippetLower = new SnippetLowerableMemoryNode(lowering, NamedLocationIdentity.getArrayLocation(JavaKind.Byte), n.stamp(NodeView.DEFAULT), n.toArgumentArray());
+ n.graph().add(snippetLower);
+ n.graph().replaceFixedWithFixed(n, snippetLower);
+ }
+ }
+
private void lowerBinaryMath(BinaryMathIntrinsicNode math, LoweringTool tool) {
if (tool.getLoweringStage() == LoweringTool.StandardLoweringStage.HIGH_TIER) {
return;
@@ -762,7 +800,7 @@
barrierType = fieldInitializationBarrier(entryKind);
}
} else {
- address = createOffsetAddress(graph, newObject, tool.getMetaAccess().getArrayBaseOffset(entryKind) + i * arrayScalingFactor(entryKind));
+ address = createOffsetAddress(graph, newObject, arrayBaseOffset(entryKind) + i * arrayScalingFactor(entryKind));
barrierType = arrayInitializationBarrier(entryKind);
}
if (address != null) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/InlineDuringParsingPlugin.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/InlineDuringParsingPlugin.java Thu Aug 23 11:09:16 2018 -0400
@@ -55,7 +55,7 @@
method.canBeInlined()) {
// Test force inlining first
- if (method.shouldBeInlined()) {
+ if (method.shouldBeInlined() && checkInliningDepth(b)) {
return createStandardInlineInfo(method);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/JDK9StringSubstitutions.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.replacements;
+
+import org.graalvm.compiler.api.replacements.ClassSubstitution;
+import org.graalvm.compiler.api.replacements.MethodSubstitution;
+import org.graalvm.compiler.core.common.SuppressFBWarnings;
+import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
+import org.graalvm.compiler.nodes.java.LoadFieldNode;
+import org.graalvm.compiler.replacements.nodes.ArrayEqualsNode;
+
+// JaCoCo Exclude
+
+/**
+ * Substitutions for {@link String} methods for JDK9 and later.
+ *
+ * {@link String} changed in JDK9 to contain a byte array instead of a char array. We therefore need
+ * new substitutions for the related methods.
+ */
+@ClassSubstitution(String.class)
+public class JDK9StringSubstitutions {
+
+ @MethodSubstitution(isStatic = false)
+ @SuppressFBWarnings(value = "ES_COMPARING_PARAMETER_STRING_WITH_EQ", justification = "reference equality on the receiver is what we want")
+ public static boolean equals(final String thisString, Object obj) {
+ if (thisString == obj) {
+ return true;
+ }
+ if (!(obj instanceof String)) {
+ return false;
+ }
+ String thatString = (String) obj;
+ if (thisString.length() != thatString.length()) {
+ return false;
+ }
+
+ if (thisString.length() == 0) {
+ return true;
+ }
+ if (getCoder(thisString) != getCoder(thatString)) {
+ return false;
+ }
+
+ final byte[] array1 = getValue(thisString);
+ final byte[] array2 = getValue(thatString);
+
+ return ArrayEqualsNode.equals(array1, array2, array1.length);
+ }
+
+ /**
+ * Will be intrinsified with an {@link InvocationPlugin} to a {@link LoadFieldNode}.
+ */
+ public static native byte[] getValue(String s);
+
+ public static native int getCoder(String s);
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java Thu Aug 23 11:09:16 2018 -0400
@@ -779,6 +779,9 @@
}
protected LoopScope doInline(PEMethodScope methodScope, LoopScope loopScope, InvokeData invokeData, InlineInfo inlineInfo, ValueNode[] arguments) {
+ if (!invokeData.invoke.useForInlining()) {
+ return null;
+ }
ResolvedJavaMethod inlineMethod = inlineInfo.getMethodToInline();
EncodedGraph graphToInline = lookupEncodedGraph(inlineMethod, inlineInfo.getOriginalMethod(), inlineInfo.getIntrinsicBytecodeProvider(), graph.trackNodeSourcePosition());
if (graphToInline == null) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java Thu Aug 23 11:09:16 2018 -0400
@@ -49,6 +49,7 @@
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Predicate;
+import jdk.vm.ci.meta.ConstantReflectionProvider;
import jdk.internal.vm.compiler.collections.EconomicMap;
import jdk.internal.vm.compiler.collections.EconomicSet;
import jdk.internal.vm.compiler.collections.Equivalence;
@@ -515,7 +516,7 @@
}
@Override
- public ValueNode findLength(ArrayLengthProvider.FindLengthMode mode) {
+ public ValueNode findLength(FindLengthMode mode, ConstantReflectionProvider constantReflection) {
return ConstantNode.forInt(varargs.length);
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java Thu Aug 23 11:09:16 2018 -0400
@@ -53,6 +53,10 @@
import org.graalvm.compiler.graph.Edges;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.graph.NodeList;
+import org.graalvm.compiler.java.IntegerExactOpSpeculation;
+import org.graalvm.compiler.java.IntegerExactOpSpeculation.IntegerExactOp;
+import org.graalvm.compiler.nodes.AbstractBeginNode;
+import org.graalvm.compiler.nodes.BeginNode;
import org.graalvm.compiler.nodes.ConstantNode;
import org.graalvm.compiler.nodes.DeoptimizeNode;
import org.graalvm.compiler.nodes.EndNode;
@@ -87,6 +91,7 @@
import org.graalvm.compiler.nodes.debug.SpillRegistersNode;
import org.graalvm.compiler.nodes.extended.BoxNode;
import org.graalvm.compiler.nodes.extended.BranchProbabilityNode;
+import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode.BytecodeExceptionKind;
import org.graalvm.compiler.nodes.extended.GetClassNode;
import org.graalvm.compiler.nodes.extended.MembarNode;
import org.graalvm.compiler.nodes.extended.RawLoadNode;
@@ -113,8 +118,13 @@
import org.graalvm.compiler.replacements.nodes.ReverseBytesNode;
import org.graalvm.compiler.replacements.nodes.VirtualizableInvokeMacroNode;
import org.graalvm.compiler.replacements.nodes.arithmetic.IntegerAddExactNode;
+import org.graalvm.compiler.replacements.nodes.arithmetic.IntegerAddExactSplitNode;
+import org.graalvm.compiler.replacements.nodes.arithmetic.IntegerExactArithmeticNode;
+import org.graalvm.compiler.replacements.nodes.arithmetic.IntegerExactArithmeticSplitNode;
import org.graalvm.compiler.replacements.nodes.arithmetic.IntegerMulExactNode;
+import org.graalvm.compiler.replacements.nodes.arithmetic.IntegerMulExactSplitNode;
import org.graalvm.compiler.replacements.nodes.arithmetic.IntegerSubExactNode;
+import org.graalvm.compiler.replacements.nodes.arithmetic.IntegerSubExactSplitNode;
import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.code.BytecodePosition;
@@ -128,6 +138,7 @@
import jdk.vm.ci.meta.ResolvedJavaType;
import jdk.vm.ci.meta.SpeculationLog;
import jdk.vm.ci.meta.SpeculationLog.Speculation;
+import jdk.vm.ci.meta.SpeculationLog.SpeculationReason;
import sun.misc.Unsafe;
/**
@@ -161,13 +172,19 @@
}
private static final Field STRING_VALUE_FIELD;
+ private static final Field STRING_CODER_FIELD;
static {
+ Field coder = null;
try {
STRING_VALUE_FIELD = String.class.getDeclaredField("value");
+ if (!Java8OrEarlier) {
+ coder = String.class.getDeclaredField("coder");
+ }
} catch (NoSuchFieldException e) {
throw new GraalError(e);
}
+ STRING_CODER_FIELD = coder;
}
private static void registerStringPlugins(InvocationPlugins plugins, BytecodeProvider bytecodeProvider, SnippetReflectionProvider snippetReflection) {
@@ -186,6 +203,7 @@
if (Java8OrEarlier) {
r.registerMethodSubstitution(StringSubstitutions.class, "equals", Receiver.class, Object.class);
+
r.register7("indexOf", char[].class, int.class, int.class, char[].class, int.class, int.class, int.class, new StringIndexOfConstantPlugin());
Registration sr = new Registration(plugins, StringSubstitutions.class);
@@ -198,6 +216,34 @@
return true;
}
});
+ } else {
+ r.registerMethodSubstitution(JDK9StringSubstitutions.class, "equals", Receiver.class, Object.class);
+
+ final Registration latin1r = new Registration(plugins, "java.lang.StringLatin1", bytecodeProvider);
+ latin1r.register5("indexOf", byte[].class, int.class, byte[].class, int.class, int.class, new StringLatin1IndexOfConstantPlugin());
+
+ final Registration utf16r = new Registration(plugins, "java.lang.StringUTF16", bytecodeProvider);
+ utf16r.register5("indexOfUnsafe", byte[].class, int.class, byte[].class, int.class, int.class, new StringUTF16IndexOfConstantPlugin());
+
+ Registration sr = new Registration(plugins, JDK9StringSubstitutions.class);
+ sr.register1("getValue", String.class, new InvocationPlugin() {
+ @Override
+ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) {
+ ResolvedJavaField field = b.getMetaAccess().lookupJavaField(STRING_VALUE_FIELD);
+ b.addPush(JavaKind.Object, LoadFieldNode.create(b.getConstantFieldProvider(), b.getConstantReflection(), b.getMetaAccess(),
+ b.getOptions(), b.getAssumptions(), value, field, false, false));
+ return true;
+ }
+ });
+ sr.register1("getCoder", String.class, new InvocationPlugin() {
+ @Override
+ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) {
+ ResolvedJavaField field = b.getMetaAccess().lookupJavaField(STRING_CODER_FIELD);
+ b.addPush(JavaKind.Int, LoadFieldNode.create(b.getConstantFieldProvider(), b.getConstantReflection(), b.getMetaAccess(),
+ b.getOptions(), b.getAssumptions(), value, field, false, false));
+ return true;
+ }
+ });
}
}
@@ -466,6 +512,59 @@
});
}
+ private static ValueNode createIntegerExactArithmeticNode(ValueNode x, ValueNode y, SpeculationReason speculation, IntegerExactOp op) {
+ switch (op) {
+ case INTEGER_ADD_EXACT:
+ case INTEGER_INCREMENT_EXACT:
+ return new IntegerAddExactNode(x, y, speculation);
+ case INTEGER_SUBTRACT_EXACT:
+ case INTEGER_DECREMENT_EXACT:
+ return new IntegerSubExactNode(x, y, speculation);
+ case INTEGER_MULTIPLY_EXACT:
+ return new IntegerMulExactNode(x, y, speculation);
+ default:
+ throw GraalError.shouldNotReachHere("Unknown integer exact operation.");
+ }
+ }
+
+ private static IntegerExactArithmeticSplitNode createIntegerExactSplit(ValueNode x, ValueNode y, AbstractBeginNode exceptionEdge, IntegerExactOp op) {
+ switch (op) {
+ case INTEGER_ADD_EXACT:
+ case INTEGER_INCREMENT_EXACT:
+ return new IntegerAddExactSplitNode(x.stamp(NodeView.DEFAULT).unrestricted(), x, y, null, exceptionEdge);
+ case INTEGER_SUBTRACT_EXACT:
+ case INTEGER_DECREMENT_EXACT:
+ return new IntegerSubExactSplitNode(x.stamp(NodeView.DEFAULT).unrestricted(), x, y, null, exceptionEdge);
+ case INTEGER_MULTIPLY_EXACT:
+ return new IntegerMulExactSplitNode(x.stamp(NodeView.DEFAULT).unrestricted(), x, y, null, exceptionEdge);
+ default:
+ throw GraalError.shouldNotReachHere("Unknown integer exact operation.");
+ }
+ }
+
+ private static void createIntegerExactOperation(GraphBuilderContext b, JavaKind kind, ValueNode x, ValueNode y, IntegerExactOp op) {
+ if (b.needsExplicitException()) {
+ BytecodeExceptionKind exceptionKind = kind == JavaKind.Int ? BytecodeExceptionKind.INTEGER_EXACT_OVERFLOW : BytecodeExceptionKind.LONG_EXACT_OVERFLOW;
+ AbstractBeginNode exceptionEdge = b.genExplicitExceptionEdge(exceptionKind);
+ IntegerExactArithmeticSplitNode split = b.addPush(kind, createIntegerExactSplit(x, y, exceptionEdge, op));
+ split.setNext(b.add(new BeginNode()));
+ } else {
+ SpeculationLog log = b.getGraph().getSpeculationLog();
+ if (log == null || (x.isConstant() && y.isConstant())) {
+ b.addPush(kind, createIntegerExactArithmeticNode(x, y, null, op));
+ } else {
+ SpeculationReason speculation = new IntegerExactOpSpeculation(b.getMethod(), op);
+ if (log.maySpeculate(speculation)) {
+ b.addPush(kind, createIntegerExactArithmeticNode(x, y, speculation, op));
+ } else {
+ BeginNode begin = b.add(new BeginNode());
+ IntegerExactArithmeticNode node = (IntegerExactArithmeticNode) b.addPush(kind, createIntegerExactArithmeticNode(x, y, null, op));
+ node.setAnchor(begin);
+ }
+ }
+ }
+ }
+
private static void registerMathPlugins(InvocationPlugins plugins, boolean allowDeoptimization) {
Registration r = new Registration(plugins, Math.class);
if (allowDeoptimization) {
@@ -475,7 +574,8 @@
r.register1("decrementExact", type, new InvocationPlugin() {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode x) {
- b.addPush(kind, new IntegerSubExactNode(x, ConstantNode.forIntegerKind(kind, 1)));
+ ConstantNode y = b.add(ConstantNode.forIntegerKind(kind, 1));
+ createIntegerExactOperation(b, kind, x, y, IntegerExactOp.INTEGER_DECREMENT_EXACT);
return true;
}
});
@@ -483,7 +583,8 @@
r.register1("incrementExact", type, new InvocationPlugin() {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode x) {
- b.addPush(kind, new IntegerAddExactNode(x, ConstantNode.forIntegerKind(kind, 1)));
+ ConstantNode y = b.add(ConstantNode.forIntegerKind(kind, 1));
+ createIntegerExactOperation(b, kind, x, y, IntegerExactOp.INTEGER_INCREMENT_EXACT);
return true;
}
});
@@ -491,7 +592,7 @@
r.register2("addExact", type, type, new InvocationPlugin() {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode x, ValueNode y) {
- b.addPush(kind, new IntegerAddExactNode(x, y));
+ createIntegerExactOperation(b, kind, x, y, IntegerExactOp.INTEGER_ADD_EXACT);
return true;
}
});
@@ -499,7 +600,7 @@
r.register2("subtractExact", type, type, new InvocationPlugin() {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode x, ValueNode y) {
- b.addPush(kind, new IntegerSubExactNode(x, y));
+ createIntegerExactOperation(b, kind, x, y, IntegerExactOp.INTEGER_SUBTRACT_EXACT);
return true;
}
});
@@ -507,7 +608,7 @@
r.register2("multiplyExact", type, type, new InvocationPlugin() {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode x, ValueNode y) {
- b.addPush(kind, new IntegerMulExactNode(x, y));
+ createIntegerExactOperation(b, kind, x, y, IntegerExactOp.INTEGER_MULTIPLY_EXACT);
return true;
}
});
@@ -555,6 +656,42 @@
}
}
+ public static final class StringLatin1IndexOfConstantPlugin implements InvocationPlugin {
+ @Override
+ public boolean inlineOnly() {
+ return true;
+ }
+
+ @Override
+ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver,
+ ValueNode source, ValueNode sourceCount, ValueNode target, ValueNode targetCount, ValueNode origFromIndex) {
+ if (target.isConstant()) {
+ b.addPush(JavaKind.Int, new StringLatin1IndexOfNode(b.getInvokeKind(), targetMethod, b.bci(), b.getInvokeReturnStamp(b.getAssumptions()),
+ source, sourceCount, target, targetCount, origFromIndex));
+ return true;
+ }
+ return false;
+ }
+ }
+
+ public static final class StringUTF16IndexOfConstantPlugin implements InvocationPlugin {
+ @Override
+ public boolean inlineOnly() {
+ return true;
+ }
+
+ @Override
+ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver,
+ ValueNode source, ValueNode sourceCount, ValueNode target, ValueNode targetCount, ValueNode origFromIndex) {
+ if (target.isConstant()) {
+ b.addPush(JavaKind.Int, new StringUTF16IndexOfNode(b.getInvokeKind(), targetMethod, b.bci(), b.getInvokeReturnStamp(b.getAssumptions()),
+ source, sourceCount, target, targetCount, origFromIndex));
+ return true;
+ }
+ return false;
+ }
+ }
+
public static class UnsignedMathPlugin implements InvocationPlugin {
private final Condition condition;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StringLatin1IndexOfNode.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.replacements;
+
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import org.graalvm.compiler.core.common.type.StampPair;
+import org.graalvm.compiler.graph.NodeClass;
+import org.graalvm.compiler.nodeinfo.NodeInfo;
+import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind;
+import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.spi.LoweringTool;
+import org.graalvm.compiler.replacements.nodes.MacroStateSplitNode;
+
+import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_256;
+import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_64;
+
+@NodeInfo(size = SIZE_64, cycles = CYCLES_256)
+public class StringLatin1IndexOfNode extends MacroStateSplitNode {
+ public static final NodeClass<StringLatin1IndexOfNode> TYPE = NodeClass.create(StringLatin1IndexOfNode.class);
+
+ public StringLatin1IndexOfNode(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, int bci, StampPair returnStamp, ValueNode... arguments) {
+ super(TYPE, invokeKind, targetMethod, bci, returnStamp, arguments);
+ }
+
+ @Override
+ public void lower(LoweringTool tool) {
+ tool.getLowerer().lower(this, tool);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StringUTF16IndexOfNode.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.replacements;
+
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import org.graalvm.compiler.core.common.type.StampPair;
+import org.graalvm.compiler.graph.NodeClass;
+import org.graalvm.compiler.nodeinfo.NodeInfo;
+import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind;
+import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.spi.LoweringTool;
+import org.graalvm.compiler.replacements.nodes.MacroStateSplitNode;
+
+import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_256;
+import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_64;
+
+@NodeInfo(size = SIZE_64, cycles = CYCLES_256)
+public class StringUTF16IndexOfNode extends MacroStateSplitNode {
+ public static final NodeClass<StringUTF16IndexOfNode> TYPE = NodeClass.create(StringUTF16IndexOfNode.class);
+
+ public StringUTF16IndexOfNode(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, int bci, StampPair returnStamp, ValueNode... arguments) {
+ super(TYPE, invokeKind, targetMethod, bci, returnStamp, arguments);
+ }
+
+ @Override
+ public void lower(LoweringTool tool) {
+ tool.getLowerer().lower(this, tool);
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ArrayEqualsNode.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ArrayEqualsNode.java Thu Aug 23 11:09:16 2018 -0400
@@ -190,7 +190,7 @@
}
@NodeIntrinsic
- public static native boolean equals(Object array1, Object array2, int length, @ConstantNodeParameter JavaKind kind);
+ static native boolean equals(Object array1, Object array2, int length, @ConstantNodeParameter JavaKind kind);
public static boolean equals(boolean[] array1, boolean[] array2, int length) {
return equals(array1, array2, length, JavaKind.Boolean);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicObjectCloneNode.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicObjectCloneNode.java Thu Aug 23 11:09:16 2018 -0400
@@ -36,18 +36,23 @@
import org.graalvm.compiler.nodeinfo.NodeCycles;
import org.graalvm.compiler.nodeinfo.NodeInfo;
import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind;
+import org.graalvm.compiler.nodes.ConstantNode;
import org.graalvm.compiler.nodes.NodeView;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.java.LoadFieldNode;
+import org.graalvm.compiler.nodes.java.LoadIndexedNode;
import org.graalvm.compiler.nodes.java.MonitorIdNode;
import org.graalvm.compiler.nodes.spi.ArrayLengthProvider;
import org.graalvm.compiler.nodes.spi.VirtualizableAllocation;
import org.graalvm.compiler.nodes.spi.VirtualizerTool;
import org.graalvm.compiler.nodes.util.GraphUtil;
+import org.graalvm.compiler.nodes.virtual.VirtualArrayNode;
import org.graalvm.compiler.nodes.virtual.VirtualInstanceNode;
import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
import jdk.vm.ci.meta.Assumptions;
+import jdk.vm.ci.meta.ConstantReflectionProvider;
+import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.ResolvedJavaField;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaType;
@@ -104,6 +109,10 @@
return LoadFieldNode.create(assumptions, originalAlias, field);
}
+ protected LoadIndexedNode genLoadIndexedNode(Assumptions assumptions, ValueNode originalAlias, ValueNode index, JavaKind elementKind) {
+ return new LoadIndexedNode(assumptions, originalAlias, index, null, elementKind);
+ }
+
@Override
public void virtualize(VirtualizerTool tool) {
ValueNode originalAlias = tool.getAlias(getObject());
@@ -120,18 +129,45 @@
}
} else {
ResolvedJavaType type = getConcreteType(originalAlias.stamp(NodeView.DEFAULT));
- if (type != null && !type.isArray()) {
+ if (type == null) {
+ return;
+ }
+ if (!type.isArray()) {
VirtualInstanceNode newVirtual = createVirtualInstanceNode(type, true);
ResolvedJavaField[] fields = newVirtual.getFields();
ValueNode[] state = new ValueNode[fields.length];
- final LoadFieldNode[] loads = new LoadFieldNode[fields.length];
for (int i = 0; i < fields.length; i++) {
- state[i] = loads[i] = genLoadFieldNode(graph().getAssumptions(), originalAlias, fields[i]);
- tool.addNode(loads[i]);
+ LoadFieldNode load = genLoadFieldNode(graph().getAssumptions(), originalAlias, fields[i]);
+ state[i] = load;
+ tool.addNode(load);
}
tool.createVirtualObject(newVirtual, state, Collections.<MonitorIdNode> emptyList(), false);
tool.replaceWithVirtual(newVirtual);
+ } else {
+ ValueNode length = findLength(FindLengthMode.SEARCH_ONLY, tool.getConstantReflectionProvider());
+ if (length == null) {
+ return;
+ }
+ ValueNode lengthAlias = tool.getAlias(length);
+ if (!lengthAlias.isConstant()) {
+ return;
+ }
+ int constantLength = lengthAlias.asJavaConstant().asInt();
+ if (constantLength >= 0 && constantLength < tool.getMaximumEntryCount()) {
+ ValueNode[] state = new ValueNode[constantLength];
+ ResolvedJavaType componentType = type.getComponentType();
+ for (int i = 0; i < constantLength; i++) {
+ ConstantNode index = ConstantNode.forInt(i);
+ LoadIndexedNode load = genLoadIndexedNode(graph().getAssumptions(), originalAlias, index, componentType.getJavaKind());
+ state[i] = load;
+ tool.addNode(index);
+ tool.addNode(load);
+ }
+ VirtualObjectNode virtualObject = new VirtualArrayNode(componentType, constantLength);
+ tool.createVirtualObject(virtualObject, state, Collections.<MonitorIdNode> emptyList(), false);
+ tool.replaceWithVirtual(virtualObject);
+ }
}
}
}
@@ -141,7 +177,7 @@
}
@Override
- public ValueNode findLength(ArrayLengthProvider.FindLengthMode mode) {
- return GraphUtil.arrayLength(getObject(), mode);
+ public ValueNode findLength(FindLengthMode mode, ConstantReflectionProvider constantReflection) {
+ return GraphUtil.arrayLength(getObject(), mode, constantReflection);
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerAddExactNode.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerAddExactNode.java Thu Aug 23 11:09:16 2018 -0400
@@ -35,17 +35,20 @@
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.graph.spi.CanonicalizerTool;
+import org.graalvm.compiler.nodeinfo.InputType;
import org.graalvm.compiler.nodeinfo.NodeInfo;
import org.graalvm.compiler.nodes.AbstractBeginNode;
import org.graalvm.compiler.nodes.ConstantNode;
import org.graalvm.compiler.nodes.NodeView;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.calc.AddNode;
+import org.graalvm.compiler.nodes.extended.AnchoringNode;
import org.graalvm.compiler.nodes.spi.LoweringTool;
import jdk.vm.ci.code.CodeUtil;
import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.SpeculationLog.SpeculationReason;
/**
* Node representing an exact integer addition that will throw an {@link ArithmeticException} in
@@ -55,10 +58,14 @@
public final class IntegerAddExactNode extends AddNode implements IntegerExactArithmeticNode {
public static final NodeClass<IntegerAddExactNode> TYPE = NodeClass.create(IntegerAddExactNode.class);
- public IntegerAddExactNode(ValueNode x, ValueNode y) {
+ @OptionalInput(InputType.Anchor) protected AnchoringNode anchor;
+ protected final SpeculationReason speculation;
+
+ public IntegerAddExactNode(ValueNode x, ValueNode y, SpeculationReason speculation) {
super(TYPE, x, y);
setStamp(x.stamp(NodeView.DEFAULT).unrestricted());
assert x.stamp(NodeView.DEFAULT).isCompatible(y.stamp(NodeView.DEFAULT)) && x.stamp(NodeView.DEFAULT) instanceof IntegerStamp;
+ this.speculation = speculation;
}
@Override
@@ -122,7 +129,7 @@
@Override
public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
if (forX.isConstant() && !forY.isConstant()) {
- return new IntegerAddExactNode(forY, forX).canonical(tool);
+ return new IntegerAddExactNode(forY, forX, speculation).canonical(tool);
}
if (forX.isConstant()) {
ConstantNode constantNode = canonicalXconstant(forX, forY);
@@ -166,6 +173,22 @@
}
@Override
+ public SpeculationReason getSpeculation() {
+ return speculation;
+ }
+
+ @Override
+ public AnchoringNode getAnchor() {
+ return anchor;
+ }
+
+ @Override
+ public void setAnchor(AnchoringNode x) {
+ updateUsagesInterface(this.anchor, x);
+ this.anchor = x;
+ }
+
+ @Override
public void lower(LoweringTool tool) {
IntegerExactArithmeticSplitNode.lower(tool, this);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerExactArithmeticNode.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerExactArithmeticNode.java Thu Aug 23 11:09:16 2018 -0400
@@ -25,9 +25,19 @@
package org.graalvm.compiler.replacements.nodes.arithmetic;
import org.graalvm.compiler.nodes.AbstractBeginNode;
+import org.graalvm.compiler.nodes.extended.AnchoringNode;
import org.graalvm.compiler.nodes.spi.Lowerable;
+import jdk.vm.ci.meta.SpeculationLog.SpeculationReason;
+
public interface IntegerExactArithmeticNode extends Lowerable {
IntegerExactArithmeticSplitNode createSplit(AbstractBeginNode next, AbstractBeginNode deopt);
+
+ SpeculationReason getSpeculation();
+
+ AnchoringNode getAnchor();
+
+ void setAnchor(AnchoringNode x);
+
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerExactArithmeticSplitNode.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerExactArithmeticSplitNode.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,6 +46,7 @@
import jdk.vm.ci.meta.DeoptimizationAction;
import jdk.vm.ci.meta.DeoptimizationReason;
+import jdk.vm.ci.meta.SpeculationLog;
import jdk.vm.ci.meta.Value;
@NodeInfo(cycles = CYCLES_2, cyclesRationale = "add+cmp", size = SIZE_2)
@@ -90,6 +91,16 @@
return overflowSuccessor;
}
+ public void setNext(AbstractBeginNode next) {
+ updatePredecessor(this.next, next);
+ this.next = next;
+ }
+
+ public void setOverflowSuccessor(AbstractBeginNode overflowSuccessor) {
+ updatePredecessor(this.overflowSuccessor, overflowSuccessor);
+ this.overflowSuccessor = overflowSuccessor;
+ }
+
public ValueNode getX() {
return x;
}
@@ -112,8 +123,10 @@
FixedWithNextNode previous = tool.lastFixedNode();
FixedNode next = previous.next();
previous.setNext(null);
- DeoptimizeNode deopt = floatingNode.graph().add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.ArithmeticException));
- AbstractBeginNode normalBegin = floatingNode.graph().add(new BeginNode());
+ StructuredGraph graph = floatingNode.graph();
+ DeoptimizeNode deopt = graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.ArithmeticException,
+ node.getSpeculation() == null ? SpeculationLog.NO_SPECULATION : graph.getSpeculationLog().speculate(node.getSpeculation())));
+ AbstractBeginNode normalBegin = graph.add(new BeginNode());
normalBegin.setNext(next);
IntegerExactArithmeticSplitNode split = node.createSplit(normalBegin, BeginNode.begin(deopt));
previous.setNext(split);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerMulExactNode.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerMulExactNode.java Thu Aug 23 11:09:16 2018 -0400
@@ -30,16 +30,19 @@
import org.graalvm.compiler.core.common.type.IntegerStamp;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.graph.spi.CanonicalizerTool;
+import org.graalvm.compiler.nodeinfo.InputType;
import org.graalvm.compiler.nodeinfo.NodeInfo;
import org.graalvm.compiler.nodes.AbstractBeginNode;
import org.graalvm.compiler.nodes.ConstantNode;
import org.graalvm.compiler.nodes.NodeView;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.calc.MulNode;
+import org.graalvm.compiler.nodes.extended.AnchoringNode;
import org.graalvm.compiler.nodes.spi.LoweringTool;
import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.SpeculationLog.SpeculationReason;
/**
* Node representing an exact integer multiplication that will throw an {@link ArithmeticException}
@@ -49,10 +52,14 @@
public final class IntegerMulExactNode extends MulNode implements IntegerExactArithmeticNode {
public static final NodeClass<IntegerMulExactNode> TYPE = NodeClass.create(IntegerMulExactNode.class);
- public IntegerMulExactNode(ValueNode x, ValueNode y) {
+ @OptionalInput(InputType.Anchor) protected AnchoringNode anchor;
+ protected final SpeculationReason speculation;
+
+ public IntegerMulExactNode(ValueNode x, ValueNode y, SpeculationReason speculation) {
super(TYPE, x, y);
setStamp(x.stamp(NodeView.DEFAULT).unrestricted());
assert x.stamp(NodeView.DEFAULT).isCompatible(y.stamp(NodeView.DEFAULT)) && x.stamp(NodeView.DEFAULT) instanceof IntegerStamp;
+ this.speculation = speculation;
}
@Override
@@ -69,7 +76,7 @@
@Override
public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
if (forX.isConstant() && !forY.isConstant()) {
- return new IntegerMulExactNode(forY, forX).canonical(tool);
+ return new IntegerMulExactNode(forY, forX, speculation).canonical(tool);
}
if (forX.isConstant()) {
return canonicalXconstant(forX, forY);
@@ -111,6 +118,22 @@
}
@Override
+ public SpeculationReason getSpeculation() {
+ return speculation;
+ }
+
+ @Override
+ public AnchoringNode getAnchor() {
+ return anchor;
+ }
+
+ @Override
+ public void setAnchor(AnchoringNode x) {
+ updateUsagesInterface(this.anchor, x);
+ this.anchor = x;
+ }
+
+ @Override
public void lower(LoweringTool tool) {
IntegerExactArithmeticSplitNode.lower(tool, this);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerSubExactNode.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerSubExactNode.java Thu Aug 23 11:09:16 2018 -0400
@@ -30,17 +30,20 @@
import org.graalvm.compiler.core.common.type.IntegerStamp;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.graph.spi.CanonicalizerTool;
+import org.graalvm.compiler.nodeinfo.InputType;
import org.graalvm.compiler.nodeinfo.NodeInfo;
import org.graalvm.compiler.nodes.AbstractBeginNode;
import org.graalvm.compiler.nodes.ConstantNode;
import org.graalvm.compiler.nodes.NodeView;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.calc.SubNode;
+import org.graalvm.compiler.nodes.extended.AnchoringNode;
import org.graalvm.compiler.nodes.spi.LoweringTool;
import org.graalvm.compiler.nodes.util.GraphUtil;
import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.SpeculationLog.SpeculationReason;
/**
* Node representing an exact integer substraction that will throw an {@link ArithmeticException} in
@@ -50,10 +53,14 @@
public final class IntegerSubExactNode extends SubNode implements IntegerExactArithmeticNode {
public static final NodeClass<IntegerSubExactNode> TYPE = NodeClass.create(IntegerSubExactNode.class);
- public IntegerSubExactNode(ValueNode x, ValueNode y) {
+ @OptionalInput(InputType.Anchor) protected AnchoringNode anchor;
+ protected final SpeculationReason speculation;
+
+ public IntegerSubExactNode(ValueNode x, ValueNode y, SpeculationReason speculation) {
super(TYPE, x, y);
setStamp(x.stamp(NodeView.DEFAULT).unrestricted());
assert x.stamp(NodeView.DEFAULT).isCompatible(y.stamp(NodeView.DEFAULT)) && x.stamp(NodeView.DEFAULT) instanceof IntegerStamp;
+ this.speculation = speculation;
}
@Override
@@ -109,6 +116,22 @@
}
@Override
+ public SpeculationReason getSpeculation() {
+ return speculation;
+ }
+
+ @Override
+ public AnchoringNode getAnchor() {
+ return anchor;
+ }
+
+ @Override
+ public void setAnchor(AnchoringNode x) {
+ updateUsagesInterface(this.anchor, x);
+ this.anchor = x;
+ }
+
+ @Override
public void lower(LoweringTool tool) {
IntegerExactArithmeticSplitNode.lower(tool, this);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/GraalServices.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/GraalServices.java Thu Aug 23 11:09:16 2018 -0400
@@ -206,27 +206,6 @@
}
/**
- * Access to thread specific information made available via Java Management Extensions (JMX).
- * Using this abstraction enables avoiding a dependency to the {@code java.management} and
- * {@code jdk.management} modules on JDK 9 and later.
- */
- public abstract static class JMXService {
- protected abstract long getThreadAllocatedBytes(long id);
-
- protected abstract long getCurrentThreadCpuTime();
-
- protected abstract boolean isThreadAllocatedMemorySupported();
-
- protected abstract boolean isCurrentThreadCpuTimeSupported();
-
- protected abstract List<String> getInputArguments();
-
- // Placing this static field in JMXService (instead of GraalServices)
- // allows for lazy initialization.
- static final JMXService instance = loadSingle(JMXService.class, false);
- }
-
- /**
* Returns an approximation of the total amount of memory, in bytes, allocated in heap memory
* for the thread of the specified ID. The returned value is an approximation because some Java
* virtual machine implementations may use object allocation mechanisms that result in a delay
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/JMXService.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2018, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.serviceprovider;
+
+import java.util.List;
+
+/* This class lives in the "base" project even if it is only useful for JDK9
+ * because javac only links against classes from the "base".
+ */
+
+/**
+ * Access to thread specific information made available via Java Management Extensions (JMX). Using
+ * this abstraction enables avoiding a dependency to the {@code java.management} and
+ * {@code jdk.management} modules on JDK 9 and later.
+ */
+public abstract class JMXService {
+ protected abstract long getThreadAllocatedBytes(long id);
+
+ protected abstract long getCurrentThreadCpuTime();
+
+ protected abstract boolean isThreadAllocatedMemorySupported();
+
+ protected abstract boolean isCurrentThreadCpuTimeSupported();
+
+ protected abstract List<String> getInputArguments();
+
+ // Placing this static field in JMXService (instead of GraalServices)
+ // allows for lazy initialization.
+ static final JMXService instance = GraalServices.loadSingle(JMXService.class, false);
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/GraalTest.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/GraalTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -35,6 +35,7 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.concurrent.TimeUnit;
import java.util.List;
import org.graalvm.compiler.debug.DebugContext;
@@ -47,6 +48,9 @@
import org.junit.Assert;
import org.junit.internal.ComparisonCriteria;
import org.junit.internal.ExactComparisonCriteria;
+import org.junit.rules.DisableOnDebug;
+import org.junit.rules.TestRule;
+import org.junit.rules.Timeout;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import sun.misc.Unsafe;
@@ -453,4 +457,35 @@
}
}
}
+
+ private static final double TIMEOUT_SCALING_FACTOR = Double.parseDouble(System.getProperty("graaltest.timeout.factor", "1.0"));
+
+ /**
+ * Creates a {@link TestRule} that applies a given timeout.
+ *
+ * A test harness can scale {@code length} with a factor specified by the
+ * {@code graaltest.timeout.factor} system property.
+ */
+ public static TestRule createTimeout(long length, TimeUnit timeUnit) {
+ Timeout timeout = new Timeout((long) (length * TIMEOUT_SCALING_FACTOR), timeUnit);
+ try {
+ return new DisableOnDebug(timeout);
+ } catch (LinkageError ex) {
+ return timeout;
+ }
+ }
+
+ /**
+ * @see #createTimeout
+ */
+ public static TestRule createTimeoutSeconds(int seconds) {
+ return createTimeout(seconds, TimeUnit.SECONDS);
+ }
+
+ /**
+ * @see #createTimeout
+ */
+ public static TestRule createTimeoutMillis(long milliseconds) {
+ return createTimeout(milliseconds, TimeUnit.MILLISECONDS);
+ }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapeClosure.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapeClosure.java Thu Aug 23 11:09:16 2018 -0400
@@ -115,22 +115,18 @@
/*
* If there is a mismatch between the number of materializations and the number of
* virtualizations, we need to apply effects, even if there were no other significant
- * changes to the graph.
+ * changes to the graph. This applies to each block, since moving from one block to the
+ * other can also be important (if the probabilities of the block differ).
*/
- int delta = 0;
for (Block block : cfg.getBlocks()) {
GraphEffectList effects = blockEffects.get(block);
if (effects != null) {
- delta += effects.getVirtualizationDelta();
+ if (effects.getVirtualizationDelta() != 0) {
+ return true;
+ }
}
}
- for (Loop<Block> loop : cfg.getLoops()) {
- GraphEffectList effects = loopMergeEffects.get(loop);
- if (effects != null) {
- delta += effects.getVirtualizationDelta();
- }
- }
- return delta != 0;
+ return false;
}
private final class CollectVirtualObjectsClosure extends NodeClosure<ValueNode> {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/WordCastNode.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/WordCastNode.java Thu Aug 23 11:09:16 2018 -0400
@@ -28,6 +28,7 @@
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1;
import org.graalvm.compiler.core.common.LIRKind;
+import org.graalvm.compiler.core.common.type.AbstractObjectStamp;
import org.graalvm.compiler.core.common.type.AbstractPointerStamp;
import org.graalvm.compiler.core.common.type.IntegerStamp;
import org.graalvm.compiler.core.common.type.ObjectStamp;
@@ -45,6 +46,7 @@
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.spi.LIRLowerable;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
+import org.graalvm.compiler.nodes.type.NarrowOopStamp;
import jdk.vm.ci.meta.AllocatableValue;
import jdk.vm.ci.meta.JavaConstant;
@@ -76,6 +78,10 @@
return new WordCastNode(StampFactory.objectNonNull(), input);
}
+ public static WordCastNode wordToNarrowObject(ValueNode input, NarrowOopStamp stamp) {
+ return new WordCastNode(stamp, input);
+ }
+
public static WordCastNode addressToWord(ValueNode input, JavaKind wordKind) {
assert input.stamp(NodeView.DEFAULT) instanceof AbstractPointerStamp;
return new WordCastNode(StampFactory.forKind(wordKind), input);
@@ -91,6 +97,11 @@
return new WordCastNode(StampFactory.forKind(wordKind), input, false);
}
+ public static WordCastNode narrowOopToUntrackedWord(ValueNode input, JavaKind wordKind) {
+ assert input.stamp(NodeView.DEFAULT) instanceof NarrowOopStamp;
+ return new WordCastNode(StampFactory.forKind(wordKind), input, false);
+ }
+
private WordCastNode(Stamp stamp, ValueNode input) {
this(stamp, input, true);
}
@@ -172,7 +183,7 @@
AllocatableValue result = generator.getLIRGeneratorTool().newVariable(kind);
if (stamp.equals(StampFactory.object())) {
generator.getLIRGeneratorTool().emitConvertZeroToNull(result, value);
- } else if (!trackedPointer && !((ObjectStamp) input.stamp(NodeView.DEFAULT)).nonNull()) {
+ } else if (!trackedPointer && !((AbstractObjectStamp) input.stamp(NodeView.DEFAULT)).nonNull()) {
generator.getLIRGeneratorTool().emitConvertNullToZero(result, value);
} else {
generator.getLIRGeneratorTool().emitMove(result, value);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.micro.benchmarks/src/micro/benchmarks/StringBenchmark.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.micro.benchmarks/src/micro/benchmarks/StringBenchmark.java Thu Aug 23 11:09:16 2018 -0400
@@ -41,10 +41,21 @@
@State(Scope.Benchmark)
public static class BenchState {
char ch1 = 'Q';
+ String ch1string = "Q";
char ch2 = 'X';
String s1 = "Qu";
String s2 = "ne";
+ String longString;
+
+ public BenchState() {
+ String str = "ab";
+ for (int i = 0; i < 15; i++) {
+ str = str + str;
+ }
+ longString = str + "xx";
+ }
+
// Checkstyle: stop
String lorem = "Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat. Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";
String loremLastChar = "Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat. Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum?";
@@ -59,6 +70,18 @@
@Benchmark
@Warmup(iterations = 5)
+ public int indexOfSingleCharString(BenchState state) {
+ return state.lorem.indexOf(state.ch1string);
+ }
+
+ @Benchmark
+ @Warmup(iterations = 5)
+ public int indexOfSingleCharStringLong(BenchState state) {
+ return state.longString.indexOf('x');
+ }
+
+ @Benchmark
+ @Warmup(iterations = 5)
public int indexOfCharNotFound(BenchState state) {
return state.lorem.indexOf(state.ch2);
}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FrameOutputWriter.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FrameOutputWriter.java Thu Aug 23 11:09:16 2018 -0400
@@ -131,7 +131,7 @@
DocType htmlDocType = DocType.forVersion(configuration.htmlVersion);
Content htmlComment = contents.newPage;
Head head = new Head(path, configuration.htmlVersion, configuration.docletVersion)
- .setTimestamp(!configuration.notimestamp, false)
+ .setTimestamp(!configuration.notimestamp)
.setTitle(title)
.setCharset(configuration.charset)
.setStylesheets(configuration.getMainStylesheet(), configuration.getAdditionalStylesheets())
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexRedirectWriter.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexRedirectWriter.java Thu Aug 23 11:09:16 2018 -0400
@@ -75,7 +75,7 @@
DocType htmlDocType = DocType.forVersion(configuration.htmlVersion);
Content htmlComment = contents.newPage;
Head head = new Head(path, configuration.htmlVersion, configuration.docletVersion)
- .setTimestamp(true, false)
+ .setTimestamp(true)
.addDefaultScript(false);
String title = (configuration.windowtitle.length() > 0)
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Head.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Head.java Thu Aug 23 11:09:16 2018 -0400
@@ -58,8 +58,6 @@
private String charset;
private final List<String> keywords;
private boolean showTimestamp;
- private boolean showGeneratedBy; // temporary: for compatibility
- private boolean showMetaCreated; // temporary: for compatibility
private boolean useModuleDirectories;
private DocFile mainStylesheetFile;
private List<DocFile> additionalStylesheetFiles = Collections.emptyList();
@@ -140,26 +138,6 @@
// no 'Generated by javadoc' comment will be added.
public Head setTimestamp(boolean timestamp) {
showTimestamp = timestamp;
- showGeneratedBy = true;
- showMetaCreated = timestamp;
- return this;
- }
-
- /**
- * Sets whether or not timestamps should be recorded in the HEAD element.
- * The timestamp will be recorded in a comment, and possibly in an appropriate META
- * element, depending on the HTML version specified when this object was created.
- *
- * @param timestamp true if timestamps should be be added.
- * @param metaCreated true if a META element should be added containing the timestamp
- * @return this object
- */
- // This method is for temporary compatibility. In time, all clients should use
- // {@code setTimestamp(boolean)}.
- public Head setTimestamp(boolean timestamp, boolean metaCreated) {
- showTimestamp = timestamp;
- showGeneratedBy = true;
- showMetaCreated = metaCreated;
return this;
}
@@ -258,16 +236,14 @@
Date now = showTimestamp ? calendar.getTime() : null;
HtmlTree tree = new HtmlTree(HtmlTag.HEAD);
- if (showGeneratedBy) {
- tree.addContent(getGeneratedBy(showTimestamp, now));
- }
+ tree.addContent(getGeneratedBy(showTimestamp, now));
tree.addContent(HtmlTree.TITLE(title));
if (charset != null) { // compatibility; should this be allowed?
tree.addContent(HtmlTree.META("Content-Type", "text/html", charset));
}
- if (showMetaCreated) {
+ if (showTimestamp) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
tree.addContent(HtmlTree.META(
(htmlVersion == HtmlVersion.HTML5) ? "dc.created" : "date",
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java Thu Aug 23 11:09:16 2018 -0400
@@ -54,6 +54,7 @@
import com.sun.tools.javac.api.JavacTrees;
import com.sun.tools.javac.file.BaseFileManager;
import com.sun.tools.javac.file.JavacFileManager;
+import com.sun.tools.javac.jvm.Target;
import com.sun.tools.javac.main.Arguments;
import com.sun.tools.javac.main.CommandLine;
import com.sun.tools.javac.main.OptionHelper;
@@ -549,6 +550,11 @@
((BaseFileManager) fileManager).handleOptions(fileManagerOpts);
}
+ if (fileManager.isSupportedOption(MULTIRELEASE.primaryName) == 1) {
+ Target target = Target.instance(context);
+ List<String> list = List.of(target.multiReleaseValue());
+ fileManager.handleOption(MULTIRELEASE.primaryName, list.iterator());
+ }
compOpts.notifyListeners();
List<String> modules = (List<String>) jdtoolOpts.computeIfAbsent(ToolOption.MODULE,
s -> Collections.EMPTY_LIST);
--- a/src/jdk.localedata/share/classes/sun/util/cldr/resources/common/main/my.xml Fri Aug 10 14:56:29 2018 -0700
+++ b/src/jdk.localedata/share/classes/sun/util/cldr/resources/common/main/my.xml Thu Aug 23 11:09:16 2018 -0400
@@ -1446,14 +1446,17 @@
<pattern>z HH:mm:ss</pattern>
</timeFormat>
</timeFormatLength>
+ <!--Pattern for medium and short replaced with CLDR 29's patterns
+ as character 'B' is currently not supported in SimpleDateFormat and java.time.DateTimeFormatter
+ classes. This is a restriction until JDK-8209175 is resolved.-->
<timeFormatLength type="medium">
<timeFormat>
- <pattern>B HH:mm:ss</pattern>
+ <pattern>HH:mm:ss</pattern>
</timeFormat>
</timeFormatLength>
<timeFormatLength type="short">
<timeFormat>
- <pattern>B H:mm</pattern>
+ <pattern>H:mm</pattern>
</timeFormat>
</timeFormatLength>
</timeFormats>
--- a/test/failure_handler/src/share/classes/jdk/test/failurehandler/GathererFactory.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/failure_handler/src/share/classes/jdk/test/failurehandler/GathererFactory.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -55,7 +55,8 @@
Properties osProperty = Utils.getProperties(osName);
try {
ActionHelper helper = new ActionHelper(workdir, "config", osProperty, jdks);
- return new ToolKit(helper, log, osName, "common");
+ // os-specific action set must be last, b/c they can kill the process
+ return new ToolKit(helper, log, "common", osName);
} catch (InvalidValueException e) {
throw new IllegalStateException("can't create tool kit", e);
}
--- a/test/failure_handler/src/share/classes/jdk/test/failurehandler/ToolKit.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/failure_handler/src/share/classes/jdk/test/failurehandler/ToolKit.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,9 +56,6 @@
pids.add(pid);
for (Long p = pids.poll(); p != null; p = pids.poll()) {
HtmlSection pidSection = section.createChildren("" + p);
- for (ActionSet set : actions) {
- set.gatherProcessInfo(pidSection, p);
- }
List<Long> children = helper.getChildren(pidSection, p);
if (!children.isEmpty()) {
HtmlSection s = pidSection.createChildren("children");
@@ -67,6 +64,9 @@
}
pids.addAll(children);
}
+ for (ActionSet set : actions) {
+ set.gatherProcessInfo(pidSection, p);
+ }
}
}
}
--- a/test/failure_handler/src/share/conf/linux.properties Fri Aug 10 14:56:29 2018 -0700
+++ b/test/failure_handler/src/share/conf/linux.properties Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
# 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,9 +52,9 @@
native.stack.args.delimiter=\0
native.stack.params.repeat=6
-native.core.app=gcore
-native.core.args=-o ./core.%p %p
-native.core.params.timeout=3600000
+# has to be the last command
+native.core.app=kill
+native.core.args=-ABRT %p
################################################################################
# environment info to gather
################################################################################
--- a/test/failure_handler/src/share/conf/mac.properties Fri Aug 10 14:56:29 2018 -0700
+++ b/test/failure_handler/src/share/conf/mac.properties Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -61,11 +61,9 @@
native.stack.params.repeat=6
native.stack.args=-c\0DevToolsSecurity --status | grep -q enabled && lldb -o 'attach %p' -o 'thread backtrace all' -o 'detach' -o 'quit'
-native.core.app=bash
-native.core.delimiter=\0
-native.core.args=-c\0gcore -o ./core.%p %p || \
- (DevToolsSecurity --status | grep -q enabled && lldb --batch -o 'attach %p' -o 'process save-core core.%p' -o 'detach' -o 'quit')
-native.core.params.timeout=3600000
+# has to be the last command
+native.core.app=kill
+native.core.args=-ABRT %p
################################################################################
# environment info to gather
################################################################################
--- a/test/failure_handler/src/share/conf/solaris.properties Fri Aug 10 14:56:29 2018 -0700
+++ b/test/failure_handler/src/share/conf/solaris.properties Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -51,9 +51,9 @@
native.stack.args=-F %p
native.stack.params.repeat=6
-native.core.app=gcore
-native.core.args=-F -o ./core %p
-native.core.params.timeout=3600000
+# has to be the last command
+native.core.app=kill
+native.core.args=-ABRT %p
################################################################################
# environment info to gather
################################################################################
--- a/test/hotspot/gtest/classfile/test_symbolTable.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/test/hotspot/gtest/classfile/test_symbolTable.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -139,7 +139,7 @@
st[i]->doit();
}
- for (int i = 0; i < 4; i++) {
+ for (int i = 0; i < SYM_TEST_THREAD_COUNT; i++) {
done.wait();
}
}
--- a/test/hotspot/gtest/memory/test_metaspace_allocation.cpp Fri Aug 10 14:56:29 2018 -0700
+++ b/test/hotspot/gtest/memory/test_metaspace_allocation.cpp Thu Aug 23 11:09:16 2018 -0400
@@ -102,9 +102,9 @@
_spaces[i].lock = new Mutex(Monitor::native, "gtest-MetaspaceAllocationTest-lock", false, Monitor::_safepoint_check_never);
ASSERT_TRUE(_spaces[i].lock != NULL);
}
- // Let every ~10th space be an anonymous one to test different allocation patterns.
+ // Let every ~10th space be an unsafe anonymous one to test different allocation patterns.
const Metaspace::MetaspaceType msType = (os::random() % 100 < 10) ?
- Metaspace::AnonymousMetaspaceType : Metaspace::StandardMetaspaceType;
+ Metaspace::UnsafeAnonymousMetaspaceType : Metaspace::StandardMetaspaceType;
{
// Pull lock during space creation, since this is what happens in the VM too
// (see ClassLoaderData::metaspace_non_null(), which we mimick here).
--- a/test/hotspot/jtreg/ProblemList-graal.txt Fri Aug 10 14:56:29 2018 -0700
+++ b/test/hotspot/jtreg/ProblemList-graal.txt Thu Aug 23 11:09:16 2018 -0400
@@ -43,9 +43,6 @@
compiler/jvmci/SecurityRestrictionsTest.java 8181837 generic-all
-compiler/jvmci/TestValidateModules.java 8194942 generic-all
-gc/arguments/TestVerifyBeforeAndAfterGCFlags.java 8194942 generic-all
-
compiler/unsafe/UnsafeGetConstantField.java 8181833 generic-all
compiler/unsafe/UnsafeGetStableArrayElement.java 8181833 generic-all
compiler/unsafe/UnsafeOffHeapBooleanTest.java 8181833 generic-all
@@ -56,6 +53,7 @@
compiler/whitebox/MakeMethodNotCompilableTest.java 8181831 generic-all
gc/arguments/TestNewSizeFlags.java 8196611 generic-all
+gc/arguments/TestVerifyBeforeAndAfterGCFlags.java 8196611 generic-all
gc/g1/TestConcurrentSystemGC.java 8196611 generic-all
vmTestbase/gc/lock/malloc/malloclock03/TestDescription.java 8196611 macosx-all
@@ -64,12 +62,8 @@
gc/g1/plab/TestPLABPromotion.java 8191048 generic-all
gc/g1/plab/TestPLABResize.java 8191048 generic-all
-gc/TestNUMAPageSize.java 8194949 generic-all
-
compiler/compilercontrol/directives/LogTest.java 8181753 generic-all
-gc/g1/ihop/TestIHOPStatic.java 8199486 generic-all
-
gc/parallel/TestPrintGCDetailsVerbose.java 8200186 macosx-all
compiler/jvmci/compilerToVM/ReprofileTest.java 8201333 generic-all
@@ -142,9 +136,26 @@
vmTestbase/nsk/jvmti/ForceEarlyReturn/ForceEarlyReturn001/TestDescription.java 8195674 generic-all
vmTestbase/nsk/jvmti/ForceEarlyReturn/ForceEarlyReturn002/TestDescription.java 8195674 generic-all
-vmTestbase/nsk/jvmti/unit/FollowReferences/followref003/TestDescription.java 8202342 generic-all
+runtime/appcds/cacheObject/RedefineClassTest.java 8204506 macosx-all
+vmTestbase/nsk/jvmti/scenarios/hotswap/HS102/hs102t001/TestDescription.java 8204506 macosx-all
+vmTestbase/nsk/jvmti/scenarios/hotswap/HS102/hs102t002/TestDescription.java 8204506 macosx-all
+
+vmTestbase/nsk/jvmti/PopFrame/popframe001/TestDescription.java 8207013 generic-all
+vmTestbase/nsk/jvmti/PopFrame/popframe003/TestDescription.java 8207013 generic-all
+vmTestbase/nsk/jvmti/PopFrame/popframe005/TestDescription.java 8207013 generic-all
+vmTestbase/nsk/jvmti/StopThread/stopthrd007/TestDescription.java 8207013 generic-all
-vmTestbase/nsk/jvmti/scenarios/hotswap/HS102/hs102t002/TestDescription.java 8204506 macosx-all
+vmTestbase/nsk/jvmti/scenarios/sampling/SP02/sp02t003/TestDescription.java 8051349 generic-all
+
+vmTestbase/nsk/jvmti/scenarios/sampling/SP02/sp02t001/TestDescription.java 8209585 generic-all
+vmTestbase/nsk/jvmti/scenarios/sampling/SP02/sp02t002/TestDescription.java 8209585 generic-all
+vmTestbase/nsk/jvmti/scenarios/sampling/SP06/sp06t001/TestDescription.java 8209585 generic-all
+vmTestbase/nsk/jvmti/scenarios/sampling/SP06/sp06t002/TestDescription.java 8209585 generic-all
+
+runtime/appcds/cacheObject/ArchivedModuleCompareTest.java 8209534 generic-all
+runtime/appcds/cacheObject/ArchivedModuleComboTest.java 8209534 generic-all
+
+serviceability/jvmti/FieldAccessWatch/FieldAccessWatch.java 8202482 generic-all
compiler/stable/TestStableBoolean.java 8204347 generic-all
compiler/stable/TestStableByte.java 8204347 generic-all
--- a/test/hotspot/jtreg/ProblemList.txt Fri Aug 10 14:56:29 2018 -0700
+++ b/test/hotspot/jtreg/ProblemList.txt Thu Aug 23 11:09:16 2018 -0400
@@ -72,6 +72,7 @@
gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterMinorGC.java 8177765 generic-all
gc/stress/TestJNIBlockFullGC/TestJNIBlockFullGC.java 8192647 generic-all
gc/logging/TestUnifiedLoggingSwitchStress.java 8208778 macosx-x64
+gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java 8193639 solaris-all
#############################################################################
@@ -88,7 +89,7 @@
# :hotspot_serviceability
serviceability/sa/ClhsdbAttach.java 8193639 solaris-all
-serviceability/sa/ClhsdbCDSCore.java 8207832 linux-x64
+serviceability/sa/ClhsdbCDSCore.java 8193639 solaris-all
serviceability/sa/ClhsdbCDSJstackPrintAll.java 8193639 solaris-all
serviceability/sa/ClhsdbField.java 8193639 solaris-all
serviceability/sa/ClhsdbFindPC.java 8193639 solaris-all
@@ -113,16 +114,22 @@
serviceability/sa/ClhsdbWhere.java 8193639 solaris-all
serviceability/sa/DeadlockDetectionTest.java 8193639 solaris-all
serviceability/sa/JhsdbThreadInfoTest.java 8193639 solaris-all
+serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java 8193639 solaris-all
serviceability/sa/sadebugd/SADebugDTest.java 8163805 generic-all
serviceability/sa/TestClassDump.java 8193639 solaris-all
+serviceability/sa/TestClhsdbJstackLock.java 8193639 solaris-all
serviceability/sa/TestCpoolForInvokeDynamic.java 8193639 solaris-all
serviceability/sa/TestDefaultMethods.java 8193639 solaris-all
serviceability/sa/TestG1HeapRegion.java 8193639 solaris-all
serviceability/sa/TestHeapDumpForInvokeDynamic.java 8193639 solaris-all
serviceability/sa/TestHeapDumpForLargeArray.java 8193639 solaris-all
+serviceability/sa/TestInstanceKlassSize.java 8193639 solaris-all
serviceability/sa/TestInstanceKlassSizeForInterface.java 8193639 solaris-all
serviceability/sa/TestIntConstant.java 8193639 solaris-all
serviceability/sa/TestJhsdbJstackLock.java 8193639 solaris-all
+serviceability/sa/TestJmapCore.java 8193639 solaris-all
+serviceability/sa/TestJmapCoreMetaspace.java 8193639 solaris-all
+serviceability/sa/TestPrintMdo.java 8193639 solaris-all
serviceability/sa/TestRevPtrsForInvokeDynamic.java 8191270 generic-all
serviceability/sa/TestType.java 8193639 solaris-all
serviceability/sa/TestUniverse.java#id0 8193639 solaris-all
--- a/test/hotspot/jtreg/compiler/codegen/aes/TestAESMain.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/hotspot/jtreg/compiler/codegen/aes/TestAESMain.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,65 +29,95 @@
* @library /test/lib /
* @modules java.base/jdk.internal.misc
* java.management
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission
*
* @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true -Dmode=CBC
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
* compiler.codegen.aes.TestAESMain
* @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true -Dmode=CBC -DencInputOffset=1
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
* compiler.codegen.aes.TestAESMain
* @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true -Dmode=CBC -DencOutputOffset=1
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
* compiler.codegen.aes.TestAESMain
* @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true -Dmode=CBC -DdecOutputOffset=1
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
* compiler.codegen.aes.TestAESMain
* @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true -Dmode=CBC -DencInputOffset=1 -DencOutputOffset=1
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
* compiler.codegen.aes.TestAESMain
* @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true -Dmode=CBC -DencInputOffset=1 -DencOutputOffset=1 -DdecOutputOffset=1
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
* compiler.codegen.aes.TestAESMain
* @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true -Dmode=CBC -DencInputOffset=1 -DencOutputOffset=1 -DdecOutputOffset=1 -DpaddingStr=NoPadding -DmsgSize=640
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
* compiler.codegen.aes.TestAESMain
*
* @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true -Dmode=ECB
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
* compiler.codegen.aes.TestAESMain
* @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true -Dmode=ECB -DencInputOffset=1
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
* compiler.codegen.aes.TestAESMain
* @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true -Dmode=ECB -DencOutputOffset=
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
* compiler.codegen.aes.TestAESMain
* @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true -Dmode=ECB -DdecOutputOffset=1
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
* compiler.codegen.aes.TestAESMain
* @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true -Dmode=ECB -DencInputOffset=1 -DencOutputOffset=1
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
* compiler.codegen.aes.TestAESMain
* @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true -Dmode=ECB -DencInputOffset=1 -DencOutputOffset=1 -DdecOutputOffset=1
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
* compiler.codegen.aes.TestAESMain
* @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true -Dmode=ECB -DencInputOffset=1 -DencOutputOffset=1 -DdecOutputOffset=1 -DpaddingStr=NoPadding -DmsgSize=640
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
* compiler.codegen.aes.TestAESMain
*
* @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true -Dmode=GCM
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
* compiler.codegen.aes.TestAESMain
* @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true -Dmode=GCM -DencInputOffset=1
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
* compiler.codegen.aes.TestAESMain
* @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true -Dmode=GCM -DencOutputOffset=1
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
* compiler.codegen.aes.TestAESMain
* @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true -Dmode=GCM -DdecOutputOffset=1
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
* compiler.codegen.aes.TestAESMain
* @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true -Dmode=GCM -DencInputOffset=1 -DencOutputOffset=1
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
* compiler.codegen.aes.TestAESMain
* @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true -Dmode=GCM -DencInputOffset=1 -DencOutputOffset=1 -DdecOutputOffset=1
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
* compiler.codegen.aes.TestAESMain
* @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true -Dmode=GCM -DencInputOffset=1 -DencOutputOffset=1 -DdecOutputOffset=1 -DpaddingStr=NoPadding -DmsgSize=640
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
* compiler.codegen.aes.TestAESMain
*
* @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true -Dmode=CTR
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
* compiler.codegen.aes.TestAESMain
* @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true -Dmode=CTR -DencInputOffset=1
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
* compiler.codegen.aes.TestAESMain
* @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true -Dmode=CTR -DencOutputOffset=1
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
* compiler.codegen.aes.TestAESMain
* @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true -Dmode=CTR -DdecOutputOffset=1
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
* compiler.codegen.aes.TestAESMain
* @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true -Dmode=CTR -DencInputOffset=1 -DencOutputOffset=1
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
* compiler.codegen.aes.TestAESMain
* @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true -Dmode=CTR -DencInputOffset=1 -DencOutputOffset=1 -DdecOutputOffset=1
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
* compiler.codegen.aes.TestAESMain
* @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true -Dmode=CTR -DencInputOffset=1 -DencOutputOffset=1 -DdecOutputOffset=1 -DpaddingStr=NoPadding -DmsgSize=640
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
* compiler.codegen.aes.TestAESMain
*
* @author Tom Deneau
@@ -95,9 +125,26 @@
package compiler.codegen.aes;
+import compiler.whitebox.CompilerWhiteBoxTest;
+import sun.hotspot.code.Compiler;
+import jtreg.SkippedException;
+
public class TestAESMain {
public static void main(String[] args) {
- int iters = (args.length > 0 ? Integer.valueOf(args[0]) : 1000000);
+ String mode = System.getProperty("mode", "CBC");
+ if ((mode.equals("CBC") || mode.equals("ECB")) &&
+ !Compiler.isIntrinsicAvailable(CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION, "com.sun.crypto.provider.AESCrypt", "implEncryptBlock", byte[].class, int.class, byte[].class, int.class)) {
+ throw new SkippedException("AES intrinsic is not available");
+ }
+ if (mode.equals("GCM") &&
+ !Compiler.isIntrinsicAvailable(CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION, "com.sun.crypto.provider.GHASH", "processBlocks", byte[].class, int.class, int.class, long[].class, long[].class)) {
+ throw new SkippedException("GHASH intrinsic is not available");
+ }
+ if (mode.equals("CTR") &&
+ !Compiler.isIntrinsicAvailable(CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION, "com.sun.crypto.provider.CounterMode", "implCrypt", byte[].class, int.class, int.class, byte[].class, int.class)) {
+ throw new SkippedException("AES-CTR intrinsic is not available");
+ }
+ int iters = (args.length > 0 ? Integer.valueOf(args[0]) : 100000);
int warmupIters = (args.length > 1 ? Integer.valueOf(args[1]) : 20000);
System.out.println(iters + " iterations");
TestAESEncode etest = new TestAESEncode();
--- a/test/hotspot/jtreg/compiler/intrinsics/base64/TestBase64.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/hotspot/jtreg/compiler/intrinsics/base64/TestBase64.java Thu Aug 23 11:09:16 2018 -0400
@@ -25,8 +25,12 @@
* @test
* @author Eric Wang <yiming.wang@oracle.com>
* @summary tests java.util.Base64
+ * @library /test/lib /
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission
*
* @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
* compiler.intrinsics.base64.TestBase64
*/
@@ -45,12 +49,18 @@
import java.util.Objects;
import java.util.Random;
+import compiler.whitebox.CompilerWhiteBoxTest;
+import sun.hotspot.code.Compiler;
+import jtreg.SkippedException;
public class TestBase64 {
static boolean checkOutput = Boolean.getBoolean("checkOutput");
public static void main(String[] args) throws Exception {
- int iters = (args.length > 0 ? Integer.valueOf(args[0]) : 1000000);
+ if (!Compiler.isIntrinsicAvailable(CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION, "java.util.Base64$Encoder", "encodeBlock", byte[].class, int.class, int.class, byte[].class, int.class, boolean.class)) {
+ throw new SkippedException("Base64 intrinsic is not available");
+ }
+ int iters = (args.length > 0 ? Integer.valueOf(args[0]) : 100000);
System.out.println(iters + " iterations");
test0(Base64Type.BASIC, Base64.getEncoder(), Base64.getDecoder(),"plain.txt", "baseEncode.txt", iters);
--- a/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA1Intrinsics.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA1Intrinsics.java Thu Aug 23 11:09:16 2018 -0400
@@ -60,7 +60,7 @@
public class TestSHA1Intrinsics {
public static void main(String args[]) throws Exception {
- new SHASanityTestBase(IntrinsicPredicates.SHA1_INTRINSICS_AVAILABLE,
+ new SHASanityTestBase(IntrinsicPredicates.isSHA1IntrinsicAvailable(),
SHASanityTestBase.SHA1_INTRINSIC_ID).test();
}
}
--- a/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA1MultiBlockIntrinsics.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA1MultiBlockIntrinsics.java Thu Aug 23 11:09:16 2018 -0400
@@ -68,7 +68,7 @@
public class TestSHA1MultiBlockIntrinsics {
public static void main(String args[]) throws Exception {
- new SHASanityTestBase(IntrinsicPredicates.SHA1_INTRINSICS_AVAILABLE,
+ new SHASanityTestBase(IntrinsicPredicates.isSHA1IntrinsicAvailable(),
SHASanityTestBase.MB_INTRINSIC_ID).test();
}
}
--- a/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA256Intrinsics.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA256Intrinsics.java Thu Aug 23 11:09:16 2018 -0400
@@ -79,7 +79,7 @@
public class TestSHA256Intrinsics {
public static void main(String args[]) throws Exception {
- new SHASanityTestBase(IntrinsicPredicates.SHA256_INTRINSICS_AVAILABLE,
+ new SHASanityTestBase(IntrinsicPredicates.isSHA256IntrinsicAvailable(),
SHASanityTestBase.SHA256_INTRINSIC_ID).test();
}
}
--- a/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA256MultiBlockIntrinsics.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA256MultiBlockIntrinsics.java Thu Aug 23 11:09:16 2018 -0400
@@ -95,7 +95,7 @@
public class TestSHA256MultiBlockIntrinsics {
public static void main(String args[]) throws Exception {
- new SHASanityTestBase(IntrinsicPredicates.SHA256_INTRINSICS_AVAILABLE,
+ new SHASanityTestBase(IntrinsicPredicates.isSHA256IntrinsicAvailable(),
SHASanityTestBase.MB_INTRINSIC_ID).test();
}
}
--- a/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA512Intrinsics.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA512Intrinsics.java Thu Aug 23 11:09:16 2018 -0400
@@ -79,7 +79,7 @@
public class TestSHA512Intrinsics {
public static void main(String args[]) throws Exception {
- new SHASanityTestBase(IntrinsicPredicates.SHA512_INTRINSICS_AVAILABLE,
+ new SHASanityTestBase(IntrinsicPredicates.isSHA512IntrinsicAvailable(),
SHASanityTestBase.SHA512_INTRINSIC_ID).test();
}
}
--- a/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA512MultiBlockIntrinsics.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA512MultiBlockIntrinsics.java Thu Aug 23 11:09:16 2018 -0400
@@ -96,7 +96,7 @@
public class TestSHA512MultiBlockIntrinsics {
public static void main(String args[]) throws Exception {
- new SHASanityTestBase(IntrinsicPredicates.SHA512_INTRINSICS_AVAILABLE,
+ new SHASanityTestBase(IntrinsicPredicates.isSHA512IntrinsicAvailable(),
SHASanityTestBase.MB_INTRINSIC_ID).test();
}
}
--- a/test/hotspot/jtreg/compiler/jvmci/compilerToVM/AllocateCompileIdTest.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/hotspot/jtreg/compiler/jvmci/compilerToVM/AllocateCompileIdTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -35,6 +35,7 @@
*
* @build jdk.internal.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.parser.DiagnosticCommand
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @run main/othervm -Xbootclasspath/a:.
* -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/loopopts/TestOneIterationStripMined.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * 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 8208275
+ * @summary Test removal of strip mined loop with only one iteration.
+ * @run main/othervm -XX:-TieredCompilation -Xcomp
+ * -XX:CompileCommand=compileonly,compiler.loopopts.TestOneIterationStripMined::test*
+ * compiler.loopopts.TestOneIterationStripMined
+ */
+
+package compiler.loopopts;
+
+public class TestOneIterationStripMined {
+ static int iField;
+ static volatile Object oField;
+
+ public static void test1(int val) {
+ iField = 0; // Do something
+ // This loop is strip mined and then removed because it has only one iteration.
+ for (int i = 0; i < 1; ++i) {
+ // Trigger split-if optimization
+ if (val == 0) {
+ break;
+ }
+ val = 0;
+ }
+ }
+
+ // Same as test1 but with a volatile Object field
+ // (will trigger a different failure mode)
+ public static void test2(int val) {
+ oField = null;
+ for (int i = 0; i < 1; ++i) {
+ if (val == 0) {
+ break;
+ }
+ val = 0;
+ }
+ }
+
+ // Same as test1 but without any code outside loop body
+ // (will trigger a different failure mode)
+ public static void test3(int val) {
+ for (int i = 0; i < 1; ++i) {
+ if (val == 0) {
+ break;
+ }
+ val = 0;
+ }
+ }
+
+ public static void main(String[] args) {
+ test1(0);
+ test2(0);
+ test3(0);
+ }
+}
--- a/test/hotspot/jtreg/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/hotspot/jtreg/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java Thu Aug 23 11:09:16 2018 -0400
@@ -100,17 +100,20 @@
IntrinsicPredicates.SHA256_INSTRUCTION_AVAILABLE,
IntrinsicPredicates.SHA512_INSTRUCTION_AVAILABLE));
- public static final BooleanSupplier SHA1_INTRINSICS_AVAILABLE
- = new AndPredicate(IntrinsicPredicates.COMPILABLE_BY_C2,
- IntrinsicPredicates.isIntrinsicAvailable("sun.security.provider.SHA", "implCompress0"));
+ public static BooleanSupplier isSHA1IntrinsicAvailable() {
+ return new AndPredicate(IntrinsicPredicates.COMPILABLE_BY_C2,
+ IntrinsicPredicates.isIntrinsicAvailable("sun.security.provider.SHA", "implCompress0"));
+ }
- public static final BooleanSupplier SHA256_INTRINSICS_AVAILABLE
- = new AndPredicate(IntrinsicPredicates.COMPILABLE_BY_C2,
- IntrinsicPredicates.isIntrinsicAvailable("sun.security.provider.SHA2", "implCompress0"));
+ public static BooleanSupplier isSHA256IntrinsicAvailable() {
+ return new AndPredicate(IntrinsicPredicates.COMPILABLE_BY_C2,
+ IntrinsicPredicates.isIntrinsicAvailable("sun.security.provider.SHA2", "implCompress0"));
+ }
- public static final BooleanSupplier SHA512_INTRINSICS_AVAILABLE
- = new AndPredicate(IntrinsicPredicates.COMPILABLE_BY_C2,
- IntrinsicPredicates.isIntrinsicAvailable("sun.security.provider.SHA5", "implCompress0"));
+ public static BooleanSupplier isSHA512IntrinsicAvailable() {
+ return new AndPredicate(IntrinsicPredicates.COMPILABLE_BY_C2,
+ IntrinsicPredicates.isIntrinsicAvailable("sun.security.provider.SHA5", "implCompress0"));
+ }
private static BooleanSupplier isIntrinsicAvailable(String klass, String method) {
try {
--- a/test/hotspot/jtreg/gc/TestNUMAPageSize.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/hotspot/jtreg/gc/TestNUMAPageSize.java Thu Aug 23 11:09:16 2018 -0400
@@ -27,7 +27,8 @@
* @summary Make sure that start up with NUMA support does not cause problems.
* @bug 8061467
* @requires vm.opt.AggressiveOpts != true
- * @run main/othervm -Xmx128m -XX:+UseNUMA TestNUMAPageSize
+ * @requires vm.gc != "Z"
+ * @run main/othervm -Xmx128m -XX:+UseNUMA -XX:+UseLargePages TestNUMAPageSize
*/
public class TestNUMAPageSize {
--- a/test/hotspot/jtreg/gc/epsilon/TestMemoryMXBeans.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/hotspot/jtreg/gc/epsilon/TestMemoryMXBeans.java Thu Aug 23 11:09:16 2018 -0400
@@ -67,28 +67,37 @@
}
}
- public static void testAllocs() {
+ public static void testAllocs() throws Exception {
MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
- // Do lazy inits first:
- long heapUsed1 = memoryMXBean.getHeapMemoryUsage().getUsed();
- sink = new int[1024*1024];
- long heapUsed2 = memoryMXBean.getHeapMemoryUsage().getUsed();
+ // Try multiple times, to capture either APIs we call allocate lazily, or the background threads allocating
+ int maxTries = 10;
+ int tries = 0;
- // Compute how much we waste during the calls themselves:
- heapUsed1 = memoryMXBean.getHeapMemoryUsage().getUsed();
- heapUsed2 = memoryMXBean.getHeapMemoryUsage().getUsed();
- long adj = heapUsed2 - heapUsed1;
+ while (true) {
+ // Compute how much we waste during the calls themselves:
+ long heapUsed1 = memoryMXBean.getHeapMemoryUsage().getUsed();
+ long heapUsed2 = memoryMXBean.getHeapMemoryUsage().getUsed();
+ long adj = heapUsed2 - heapUsed1;
+
+ heapUsed1 = memoryMXBean.getHeapMemoryUsage().getUsed();
+ sink = new int[1024*1024];
+ heapUsed2 = memoryMXBean.getHeapMemoryUsage().getUsed();
- heapUsed1 = memoryMXBean.getHeapMemoryUsage().getUsed();
- sink = new int[1024*1024];
- heapUsed2 = memoryMXBean.getHeapMemoryUsage().getUsed();
+ long diff = heapUsed2 - heapUsed1 - adj;
+ long min = 8 + 4*1024*1024;
+ long max = 16 + 4*1024*1024;
+ if ((min <= diff && diff <= max)) {
+ // Success
+ return;
+ }
- long diff = heapUsed2 - heapUsed1 - adj;
- long min = 8 + 4*1024*1024;
- long max = 16 + 4*1024*1024;
- if (!(min <= diff && diff <= max)) {
- throw new IllegalStateException("Allocation did not change used space right: " + diff + " should be in [" + min + ", " + max + "]");
+ if (tries++ > maxTries) {
+ throw new IllegalStateException("Allocation did not change used space right: " + diff + " should be in [" + min + ", " + max + "]");
+ }
+
+ // Wait and try again
+ Thread.sleep(1000);
}
}
--- a/test/hotspot/jtreg/gc/g1/TestStringSymbolTableStats.java Fri Aug 10 14:56:29 2018 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*
- * 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
- * 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 TestStringSymbolTableStats.java
- * @bug 8027476 8027455
- * @summary Ensure that the G1TraceStringSymbolTableScrubbing prints the expected message.
- * @key gc
- * @requires vm.gc.G1
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * java.management
- */
-
-import jdk.test.lib.process.OutputAnalyzer;
-import jdk.test.lib.process.ProcessTools;
-
-public class TestStringSymbolTableStats {
- public static void main(String[] args) throws Exception {
-
- ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
- "-XX:+UnlockExperimentalVMOptions",
- "-Xlog:gc+stringtable=trace",
- SystemGCTest.class.getName());
-
- OutputAnalyzer output = new OutputAnalyzer(pb.start());
-
- System.out.println("Output:\n" + output.getOutput());
-
- output.shouldMatch("GC\\(\\d+\\) Cleaned string and symbol table");
- output.shouldHaveExitValue(0);
- }
-
- static class SystemGCTest {
- public static void main(String [] args) {
- System.out.println("Calling System.gc()");
- System.gc();
- }
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/gc/g1/TestStringTableStats.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,60 @@
+/*
+ * 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
+ * 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 TestStringTableStats.java
+ * @bug 8027476 8027455
+ * @summary Ensure that the G1TraceStringTableScrubbing prints the expected message.
+ * @key gc
+ * @requires vm.gc.G1
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * java.management
+ */
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+
+public class TestStringTableStats {
+ public static void main(String[] args) throws Exception {
+
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
+ "-XX:+UnlockExperimentalVMOptions",
+ "-Xlog:gc+stringtable=trace",
+ SystemGCTest.class.getName());
+
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+
+ System.out.println("Output:\n" + output.getOutput());
+
+ output.shouldMatch("GC\\(\\d+\\) Cleaned string table");
+ output.shouldHaveExitValue(0);
+ }
+
+ static class SystemGCTest {
+ public static void main(String [] args) {
+ System.out.println("Calling System.gc()");
+ System.gc();
+ }
+ }
+}
--- a/test/hotspot/jtreg/gc/g1/ihop/TestIHOPStatic.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/hotspot/jtreg/gc/g1/ihop/TestIHOPStatic.java Thu Aug 23 11:09:16 2018 -0400
@@ -28,6 +28,7 @@
* @requires vm.gc.G1
* @requires !vm.flightRecorder
* @requires vm.opt.ExplicitGCInvokesConcurrent != true
+ * @requires !(vm.graal.enabled & vm.compMode == "Xcomp")
* @library /test/lib /
* @modules java.base/jdk.internal.misc
* @modules java.management
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/BootstrapMethod/TestLambdaExceptionInInitializer.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * 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 8208172
+ * @library /test/lib
+ * @compile TestPkg/LambdaMetafactory.java
+ * @compile TestPkg/Lambda.jasm
+ * @run main TestLambdaExceptionInInitializer
+ */
+
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.process.OutputAnalyzer;
+
+public class TestLambdaExceptionInInitializer {
+ public static void main(String args[]) throws Throwable {
+
+ // Run Lamba class
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("TestPkg.Lambda");
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+
+ output.shouldContain("Exception in thread \"main\" java.lang.ExceptionInInitializerError");
+
+ output.shouldContain("Caused by: java.lang.NullPointerException");
+ output.shouldContain("at TestPkg.LambdaMetafactory.throwNpe(LambdaMetafactory.java:34)");
+ output.shouldContain("at TestPkg.LambdaMetafactory.<clinit>(LambdaMetafactory.java:30)");
+ output.shouldHaveExitValue(1);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/BootstrapMethod/TestPkg/Lambda.jasm Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * 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.
+ */
+
+// Generated file to call Metafactory that gets NPE in initializer while
+// calling the bootstrap method.
+
+package TestPkg;
+
+super public final class Lambda
+ version 52:0
+{
+
+
+public Method "<init>":"()V"
+ stack 1 locals 1
+{
+ aload_0;
+ invokespecial Method java/lang/Object."<init>":"()V";
+ return;
+}
+
+public Method test:"()V"
+ stack 1 locals 2
+{
+ invokedynamic InvokeDynamic REF_invokeStatic: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;":run:"()Ljava/lang/Runnable;" MethodType "()V", MethodHandle REF_invokeStatic:Lambda.lambda$test$0:"()V", MethodType "()V";
+ astore_1;
+ return;
+}
+
+private static synthetic Method lambda$test$0:"()V"
+ stack 0 locals 0
+{
+ return;
+}
+
+public static Method main:"([Ljava/lang/String;)V"
+ stack 2 locals 1
+{
+ new class Lambda;
+ dup;
+ invokespecial Method "<init>":"()V";
+ invokevirtual Method test:"()V";
+ return;
+}
+
+} // end Class Lambda
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/BootstrapMethod/TestPkg/LambdaMetafactory.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * 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 TestPkg;
+
+import java.lang.invoke.LambdaConversionException;
+
+public class LambdaMetafactory {
+ static {
+ throwNpe(); // ExceptionInInitializerError
+ }
+
+ static void throwNpe(){
+ throw new NullPointerException();
+ }
+
+ public static java.lang.invoke.CallSite metafactory(java.lang.invoke.MethodHandles.Lookup owner,
+ String invokedName,
+ java.lang.invoke.MethodType invokedType,
+ java.lang.invoke.MethodType samMethodType,
+ java.lang.invoke.MethodHandle implMethod,
+ java.lang.invoke.MethodType instantiatedMethodType)
+ throws LambdaConversionException {
+ return java.lang.invoke.LambdaMetafactory.metafactory(owner,
+ invokedName,
+ invokedType,
+ samMethodType,
+ implMethod,
+ instantiatedMethodType);
+ }
+}
--- a/test/hotspot/jtreg/runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/hotspot/jtreg/runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java Thu Aug 23 11:09:16 2018 -0400
@@ -23,6 +23,7 @@
/*
* @test
+ * @bug 8205633
* @summary Test VM Options with ranges
* @library /test/lib /runtime/CommandLine/OptionsValidation/common
* @modules java.base/jdk.internal.misc
@@ -108,6 +109,7 @@
excludeTestMaxRange("NewSize");
excludeTestMaxRange("OldSize");
excludeTestMaxRange("ParallelGCThreads");
+ excludeTestMaxRange("TLABSize");
/*
* Remove parameters controlling the code cache. As these
--- a/test/hotspot/jtreg/runtime/SharedArchiveFile/ArchiveDoesNotExist.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/hotspot/jtreg/runtime/SharedArchiveFile/ArchiveDoesNotExist.java Thu Aug 23 11:09:16 2018 -0400
@@ -51,18 +51,16 @@
// -Xshare=on
OutputAnalyzer out = CDSTestUtils.runWithArchive(opts);
- if (!CDSTestUtils.isUnableToMap(out)) {
- out.shouldContain("Specified shared archive not found")
- .shouldHaveExitValue(1);
- }
+ CDSTestUtils.checkMappingFailure(out);
+ out.shouldContain("Specified shared archive not found")
+ .shouldHaveExitValue(1);
// -Xshare=auto
opts.setXShareMode("auto");
out = CDSTestUtils.runWithArchive(opts);
- if (!CDSTestUtils.isUnableToMap(out)) {
- out.shouldMatch("(java|openjdk) version")
- .shouldNotContain("sharing")
- .shouldHaveExitValue(0);
- }
+ CDSTestUtils.checkMappingFailure(out);
+ out.shouldMatch("(java|openjdk) version")
+ .shouldNotContain("sharing")
+ .shouldHaveExitValue(0);
}
}
--- a/test/hotspot/jtreg/runtime/SharedArchiveFile/CdsDifferentCompactStrings.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/hotspot/jtreg/runtime/SharedArchiveFile/CdsDifferentCompactStrings.java Thu Aug 23 11:09:16 2018 -0400
@@ -50,10 +50,10 @@
CDSTestUtils.checkDump(out);
out = CDSTestUtils.runWithArchive(loadCompactStringsArgument);
- if (!CDSTestUtils.isUnableToMap(out)) {
- out.shouldMatch("The shared archive file's CompactStrings " +
- "setting .* does not equal the current CompactStrings setting")
- .shouldHaveExitValue(1);
- }
+ CDSTestUtils.checkMappingFailure(out);
+
+ out.shouldMatch("The shared archive file's CompactStrings " +
+ "setting .* does not equal the current CompactStrings setting")
+ .shouldHaveExitValue(1);
}
}
--- a/test/hotspot/jtreg/runtime/SharedArchiveFile/NonBootLoaderClasses.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/hotspot/jtreg/runtime/SharedArchiveFile/NonBootLoaderClasses.java Thu Aug 23 11:09:16 2018 -0400
@@ -35,7 +35,6 @@
import jdk.test.lib.cds.CDSTestUtils;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
-import java.io.File;
public class NonBootLoaderClasses {
public static void main(String[] args) throws Exception {
@@ -56,11 +55,11 @@
"-XX:+UnlockDiagnosticVMOptions", "-XX:SharedArchiveFile=./" + archiveName,
"-XX:+PrintSharedArchiveAndExit", "-XX:+PrintSharedDictionary");
OutputAnalyzer out = CDSTestUtils.executeAndLog(pb, "print-shared-archive");
- if (!CDSTestUtils.isUnableToMap(out)) {
- out.shouldContain("archive is valid")
- .shouldHaveExitValue(0) // Should report success in error code.
- .shouldContain(PLATFORM_CLASS.replace('/', '.'))
- .shouldContain(APP_CLASS.replace('/', '.'));
- }
+ CDSTestUtils.checkMappingFailure(out);
+
+ out.shouldContain("archive is valid")
+ .shouldHaveExitValue(0) // Should report success in error code.
+ .shouldContain(PLATFORM_CLASS.replace('/', '.'))
+ .shouldContain(APP_CLASS.replace('/', '.'));
}
}
--- a/test/hotspot/jtreg/runtime/SharedArchiveFile/PrintSharedArchiveAndExit.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/hotspot/jtreg/runtime/SharedArchiveFile/PrintSharedArchiveAndExit.java Thu Aug 23 11:09:16 2018 -0400
@@ -36,7 +36,6 @@
import jdk.test.lib.process.ProcessTools;
import jdk.test.lib.process.OutputAnalyzer;
-
public class PrintSharedArchiveAndExit {
public static void main(String[] args) throws Exception {
String archiveName = "PrintSharedArchiveAndExit.jsa";
@@ -49,20 +48,19 @@
"-XX:+UnlockDiagnosticVMOptions", "-XX:SharedArchiveFile=./" + archiveName,
"-XX:+PrintSharedArchiveAndExit", "-version");
out = CDSTestUtils.executeAndLog(pb, "print-shared-archive-and-version");
- if (!CDSTestUtils.isUnableToMap(out)) {
- out.shouldContain("archive is valid")
- .shouldNotContain("java version") // Should not print JVM version
- .shouldHaveExitValue(0); // Should report success in error code.
- }
+ CDSTestUtils.checkMappingFailure(out);
+
+ out.shouldContain("archive is valid")
+ .shouldNotContain("java version") // Should not print JVM version
+ .shouldHaveExitValue(0); // Should report success in error code.
pb = ProcessTools.createJavaProcessBuilder(
"-XX:+UnlockDiagnosticVMOptions", "-XX:SharedArchiveFile=./" + archiveName,
"-XX:+PrintSharedArchiveAndExit");
out = CDSTestUtils.executeAndLog(pb, "print-shared-archive");
- if (!CDSTestUtils.isUnableToMap(out)) {
- out.shouldContain("archive is valid")
- .shouldNotContain("Usage:") // Should not print JVM help message
- .shouldHaveExitValue(0); // Should report success in error code.
- }
+ CDSTestUtils.checkMappingFailure(out);
+ out.shouldContain("archive is valid")
+ .shouldNotContain("Usage:") // Should not print JVM help message
+ .shouldHaveExitValue(0); // Should report success in error code.
}
}
--- a/test/hotspot/jtreg/runtime/SharedArchiveFile/SharedSymbolTableBucketSize.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/hotspot/jtreg/runtime/SharedArchiveFile/SharedSymbolTableBucketSize.java Thu Aug 23 11:09:16 2018 -0400
@@ -42,15 +42,14 @@
CDSTestUtils.createArchive("-XX:SharedSymbolTableBucketSize="
+ Integer.valueOf(bucket_size));
CDSTestUtils.checkDump(output);
+ CDSTestUtils.checkMappingFailure(output);
- if (!CDSTestUtils.isUnableToMap(output)) {
- String s = output.firstMatch("Average bucket size : .*");
- Float f = Float.parseFloat(s.substring(25));
- int size = Math.round(f);
- if (size != bucket_size) {
- throw new Exception("FAILED: incorrect bucket size " + size +
- ", expect " + bucket_size);
- }
+ String s = output.firstMatch("Average bucket size : .*");
+ Float f = Float.parseFloat(s.substring(25));
+ int size = Math.round(f);
+ if (size != bucket_size) {
+ throw new Exception("FAILED: incorrect bucket size " + size +
+ ", expect " + bucket_size);
}
// Invalid SharedSymbolTableBucketSize input
--- a/test/hotspot/jtreg/runtime/SharedArchiveFile/serviceability/transformRelatedClasses/TransformTestCommon.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/hotspot/jtreg/runtime/SharedArchiveFile/serviceability/transformRelatedClasses/TransformTestCommon.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,6 @@
import jdk.test.lib.cds.CDSTestUtils;
import jdk.test.lib.process.OutputAnalyzer;
-
// This class contains methods common to all transformation test cases
public class TransformTestCommon {
@@ -101,8 +100,7 @@
// If we were not able to map an archive,
// then do not perform other checks, since
// there was no sharing at all
- if (CDSTestUtils.isUnableToMap(out))
- return;
+ CDSTestUtils.checkMappingFailure(out);
String childVmName = child.replace('.', '/');
String parentVmName = parent.replace('.', '/');
--- a/test/hotspot/jtreg/runtime/appcds/DirClasspathTest.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/hotspot/jtreg/runtime/appcds/DirClasspathTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -27,12 +27,14 @@
* @summary Handling of directories in -cp is based on the classlist
* @requires vm.cds
* @library /test/lib
+ * @compile test-classes/Hello.java
* @run main DirClasspathTest
*/
import jdk.test.lib.Platform;
import jdk.test.lib.process.OutputAnalyzer;
import java.io.File;
+import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
@@ -87,13 +89,28 @@
/////////////////////////////////////////////////////////////////
String appClassList[] = {"java/lang/Object", "com/sun/tools/javac/Main"};
- // Non-empty dir in -cp: should report error
+ // Non-empty dir in -cp: should be OK (as long as no classes were loaded from there)
output = TestCommon.dump(dir.getPath(), appClassList, "-Xlog:class+path=info");
+ TestCommon.checkDump(output);
+
+ // Long path to non-empty dir in -cp: should be OK (as long as no classes were loaded from there)
+ output = TestCommon.dump(longDir.getPath(), appClassList, "-Xlog:class+path=info");
+ TestCommon.checkDump(output);
+
+ /////////////////////////////////////////////////////////////////
+ // Loading an app class from a directory
+ /////////////////////////////////////////////////////////////////
+ String appClassList2[] = {"Hello", "java/lang/Object", "com/sun/tools/javac/Main"};
+ // Non-empty dir in -cp: should report error if a class is loaded from it
+ output = TestCommon.dump(classDir.toString(), appClassList2, "-Xlog:class+path=info");
output.shouldNotHaveExitValue(0);
output.shouldContain("Cannot have non-empty directory in paths");
- // Long path to non-empty dir in -cp: should report error
- output = TestCommon.dump(longDir.getPath(), appClassList, "-Xlog:class+path=info");
+ // Long path to non-empty dir in -cp: should report error if a class is loaded from it
+ File srcClass = new File(classDir.toFile(), "Hello.class");
+ File destClass = new File(longDir, "Hello.class");
+ Files.copy(srcClass.toPath(), destClass.toPath());
+ output = TestCommon.dump(longDir.getPath(), appClassList2, "-Xlog:class+path=info");
output.shouldNotHaveExitValue(0);
output.shouldContain("Cannot have non-empty directory in paths");
}
--- a/test/hotspot/jtreg/runtime/appcds/PrintSharedArchiveAndExit.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/hotspot/jtreg/runtime/appcds/PrintSharedArchiveAndExit.java Thu Aug 23 11:09:16 2018 -0400
@@ -65,7 +65,7 @@
String cp = appJar + File.pathSeparator + appJar2;
String lastCheckMsg = "checking shared classpath entry: " + appJar2; // the last JAR to check
- TestCommon.testDump(cp, TestCommon.list("Hello"));
+ TestCommon.testDump(cp, TestCommon.list("Hello", "HelloMore"));
log("Normal execution -- all the JAR paths should be checked");
TestCommon.run(
--- a/test/hotspot/jtreg/runtime/appcds/SharedArchiveConsistency.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/hotspot/jtreg/runtime/appcds/SharedArchiveConsistency.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -62,11 +62,11 @@
public class SharedArchiveConsistency {
public static WhiteBox wb;
public static int offset_magic; // FileMapHeader::_magic
- public static int sp_offset_crc; // FileMapHeader::space_info::_crc
+ public static int sp_offset_crc; // CDSFileMapRegion::_crc
public static int file_header_size = -1;// total size of header, variant, need calculation
- public static int space_info_size; // size of space_info
- public static int sp_offset; // offset of FileMapHeader::space_info
- public static int sp_used_offset; // offset of space_info::_used
+ public static int CDSFileMapRegion_size; // size of CDSFileMapRegion
+ public static int sp_offset; // offset of CDSFileMapRegion
+ public static int sp_used_offset; // offset of CDSFileMapRegion::_used
public static int size_t_size; // size of size_t
public static File jsa; // will be updated during test
@@ -83,7 +83,7 @@
public static void getFileOffsetInfo() throws Exception {
wb = WhiteBox.getWhiteBox();
offset_magic = wb.getOffsetForName("FileMapHeader::_magic");
- sp_offset_crc = wb.getOffsetForName("space_info::_crc");
+ sp_offset_crc = wb.getOffsetForName("CDSFileMapRegion::_crc");
try {
int nonExistOffset = wb.getOffsetForName("FileMapHeader::_non_exist_offset");
System.exit(-1); // should fail
@@ -92,9 +92,9 @@
}
sp_offset = wb.getOffsetForName("FileMapHeader::_space[0]") - offset_magic;
- sp_used_offset = wb.getOffsetForName("space_info::_used") - sp_offset_crc;
+ sp_used_offset = wb.getOffsetForName("CDSFileMapRegion::_used") - sp_offset_crc;
size_t_size = wb.getOffsetForName("size_t_size");
- space_info_size = wb.getOffsetForName("space_info_size");
+ CDSFileMapRegion_size = wb.getOffsetForName("CDSFileMapRegion_size");
}
public static int getFileHeaderSize(FileChannel fc) throws Exception {
@@ -166,7 +166,7 @@
System.out.printf("%-12s%-12s%-12s%-12s%-12s\n", "Space Name", "Offset", "Used bytes", "Reg Start", "Random Offset");
start0 = getFileHeaderSize(fc);
for (int i = 0; i < num_regions; i++) {
- used_offset = sp_offset + space_info_size * i + sp_used_offset;
+ used_offset = sp_offset + CDSFileMapRegion_size * i + sp_used_offset;
// read 'used'
used[i] = readInt(fc, used_offset, size_t_size);
start = start0;
@@ -199,7 +199,7 @@
long[] used = new long[num_regions];
System.out.printf("%-12s%-12s\n", "Space name", "Used bytes");
for (int i = 0; i < num_regions; i++) {
- used_offset = sp_offset + space_info_size* i + sp_used_offset;
+ used_offset = sp_offset + CDSFileMapRegion_size* i + sp_used_offset;
// read 'used'
used[i] = readInt(fc, used_offset, size_t_size);
System.out.printf("%-12s%-12d\n", shared_region_name[i], used[i]);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/UnusedCPDuringDump.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * 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 8209385
+ * @summary non-empty dir in -cp should be fine during dump time if only classes
+ * from the system modules are being loaded even though some are
+ * defined to the PlatformClassLoader and AppClassLoader.
+ * @requires vm.cds
+ * @library /test/lib
+ * @modules jdk.jartool/sun.tools.jar
+ * @compile test-classes/Hello.java
+ * @run main/othervm -Dtest.cds.copy.child.stdout=false UnusedCPDuringDump
+ */
+
+import java.io.File;
+import jdk.test.lib.process.OutputAnalyzer;
+
+public class UnusedCPDuringDump {
+
+ public static void main(String[] args) throws Exception {
+ File dir = new File(System.getProperty("user.dir"));
+ File emptydir = new File(dir, "emptydir");
+ emptydir.mkdir();
+ String appJar = JarBuilder.getOrCreateHelloJar();
+
+ OutputAnalyzer output = TestCommon.dump(dir.getPath(),
+ TestCommon.list("sun/util/resources/cldr/provider/CLDRLocaleDataMetaInfo",
+ "com/sun/tools/sjavac/client/ClientMain"),
+ "-Xlog:class+path=info,class+load=debug");
+ TestCommon.checkDump(output,
+ "[class,load] sun.util.resources.cldr.provider.CLDRLocaleDataMetaInfo",
+ "for instance a 'jdk/internal/loader/ClassLoaders$PlatformClassLoader'",
+ "[class,load] com.sun.tools.sjavac.client.ClientMain",
+ "for instance a 'jdk/internal/loader/ClassLoaders$AppClassLoader'");
+
+ String jsaOpt = "-XX:SharedArchiveFile=" + TestCommon.getCurrentArchiveName();
+ TestCommon.run("-cp", appJar, jsaOpt, "-Xlog:class+path=info,class+load=debug", "Hello")
+ .assertNormalExit("Hello World");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/cacheObject/ArchivedIntegerCacheTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/*
+ * @test
+ * @summary Test IntegerCache integrity in various scenarios
+ * @requires vm.cds.archived.java.heap
+ * @library /test/jdk/lib/testlibrary /test/lib /test/hotspot/jtreg/runtime/appcds
+ * @modules java.base/jdk.internal.misc
+ * java.management
+ * jdk.jartool/sun.tools.jar
+ * @build sun.hotspot.WhiteBox
+ * @compile CheckIntegerCacheApp.java
+ * @run driver ClassFileInstaller -jar integer.jar CheckIntegerCacheApp
+ * @run driver ClassFileInstaller -jar WhiteBox.jar sun.hotspot.WhiteBox
+ * @run main ArchivedIntegerCacheTest
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import jdk.test.lib.process.OutputAnalyzer;
+
+public class ArchivedIntegerCacheTest {
+
+ public static void main(String[] args) throws Exception {
+ String wbJar = ClassFileInstaller.getJarPath("WhiteBox.jar");
+ String use_whitebox_jar = "-Xbootclasspath/a:" + wbJar;
+ String appJar = ClassFileInstaller.getJarPath("integer.jar");
+
+ Path userDir = Paths.get(System.getProperty("user.dir"));
+ Path moduleDir = Files.createTempDirectory(userDir, "mods");
+
+ //
+ // Dump default archive
+ //
+ OutputAnalyzer output = TestCommon.dump(appJar,
+ TestCommon.list("CheckIntegerCacheApp"),
+ use_whitebox_jar);
+ TestCommon.checkDump(output);
+
+ // Test case 1)
+ // - Default options
+ System.out.println("----------------------- Test case 1 ----------------------");
+ output = TestCommon.exec(appJar, use_whitebox_jar,
+ "-XX:+UnlockDiagnosticVMOptions",
+ "-XX:+WhiteBoxAPI",
+ "CheckIntegerCacheApp",
+ "127",
+ "true");
+ TestCommon.checkExec(output);
+
+ // Test case 2)
+ // - Default archive
+ // - Larger -XX:AutoBoxCacheMax
+ System.out.println("----------------------- Test case 2 ----------------------");
+ output = TestCommon.exec(appJar, use_whitebox_jar,
+ "-XX:+UnlockDiagnosticVMOptions",
+ "-XX:+WhiteBoxAPI",
+ "-XX:AutoBoxCacheMax=20000",
+ "CheckIntegerCacheApp",
+ "20000",
+ "false");
+ TestCommon.checkExec(output);
+
+ //
+ // Dump with -XX:AutoBoxCacheMax specified
+ //
+ output = TestCommon.dump(appJar,
+ TestCommon.list("CheckIntegerCacheApp"),
+ "-XX:AutoBoxCacheMax=20000",
+ use_whitebox_jar);
+ TestCommon.checkDump(output);
+
+ // Test case 3)
+ // - Large archived cache
+ // - Default options
+ System.out.println("----------------------- Test case 3 ----------------------");
+ output = TestCommon.exec(appJar, use_whitebox_jar,
+ "--module-path",
+ moduleDir.toString(),
+ "-XX:+UnlockDiagnosticVMOptions",
+ "-XX:+WhiteBoxAPI",
+ "CheckIntegerCacheApp",
+ "127",
+ "true");
+ TestCommon.checkExec(output);
+
+
+ // Test case 4)
+ // - Large archived cache
+ // - Matching options
+ System.out.println("----------------------- Test case 4 ----------------------");
+ output = TestCommon.exec(appJar, use_whitebox_jar,
+ "--module-path",
+ moduleDir.toString(),
+ "-XX:+UnlockDiagnosticVMOptions",
+ "-XX:+WhiteBoxAPI",
+ "-XX:AutoBoxCacheMax=20000",
+ "CheckIntegerCacheApp",
+ "20000",
+ "true");
+ TestCommon.checkExec(output);
+
+ // Test case 5)
+ // - Large archived cache
+ // - Larger requested cache
+ System.out.println("----------------------- Test case 5 ----------------------");
+ output = TestCommon.exec(appJar, use_whitebox_jar,
+ "--module-path",
+ moduleDir.toString(),
+ "-XX:+UnlockDiagnosticVMOptions",
+ "-XX:+WhiteBoxAPI",
+ "-XX:AutoBoxCacheMax=30000",
+ "CheckIntegerCacheApp",
+ "30000",
+ "false");
+ TestCommon.checkExec(output);
+
+ // Test case 6)
+ // - Cache is too large to archive
+ output = TestCommon.dump(appJar,
+ TestCommon.list("CheckIntegerCacheApp"),
+ "-XX:AutoBoxCacheMax=2000000",
+ "-Xmx1g",
+ "-XX:NewSize=1g",
+ "-Xlog:cds+heap=info",
+ use_whitebox_jar);
+ TestCommon.checkDump(output,
+ "Cannot archive the sub-graph referenced from [Ljava.lang.Integer; object");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/cacheObject/CheckIntegerCacheApp.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+import sun.hotspot.WhiteBox;
+
+//
+// Help test archived integer cache consistency.
+//
+// Takes two arguments:
+// 0: the expected AutoBoxCacheMax setting
+// 1: if the values are expected to be retrieved from the archive or not
+//
+public class CheckIntegerCacheApp {
+ static WhiteBox wb;
+
+ public static void main(String[] args) throws Exception {
+ wb = WhiteBox.getWhiteBox();
+
+ if (!wb.areOpenArchiveHeapObjectsMapped()) {
+ System.out.println("This may happen during normal operation. Test Skipped.");
+ return;
+ }
+
+ if (args.length != 2) {
+ throw new RuntimeException(
+ "FAILED. Incorrect argument length: " + args.length);
+ }
+
+ boolean archivedExpected = Boolean.parseBoolean(args[1]);
+
+ // Base JLS compliance check
+ for (int i = -128; i <= 127; i++) {
+ if (Integer.valueOf(i) != Integer.valueOf(i)) {
+ throw new RuntimeException(
+ "FAILED. All values in range [-128, 127] should be interned in cache: " + i);
+ }
+ checkArchivedAsExpected(archivedExpected, i);
+ }
+
+ int high = Integer.parseInt(args[0]);
+ if (Integer.valueOf(high) != Integer.valueOf(high)) {
+ throw new RuntimeException(
+ "FAILED. Value expected to be retrieved from cache: " + high);
+ }
+ checkArchivedAsExpected(archivedExpected, Integer.valueOf(high));
+
+ if (Integer.valueOf(high + 1) == Integer.valueOf(high + 1)) {
+ throw new RuntimeException(
+ "FAILED. Value not expected to be retrieved from cache: " + high);
+ }
+ checkArchivedAsExpected(false, Integer.valueOf(high + 1));
+ }
+
+ private static void checkArchivedAsExpected(boolean archivedExpected, Integer value) {
+ if (archivedExpected) {
+ if (!wb.isShared(Integer.valueOf(value))) {
+ throw new RuntimeException(
+ "FAILED. Value expected to be archived: " + value);
+ }
+ } else {
+ if (wb.isShared(Integer.valueOf(value))) {
+ throw new RuntimeException(
+ "FAILED. Value not expected to be archived: " + value);
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/cacheObject/DifferentHeapSizes.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/*
+ * @test
+ * @summary Test automatic relocation of archive heap regions dur to heap size changes.
+ * @requires vm.cds.archived.java.heap
+ * @requires (vm.gc=="null")
+ * @library /test/lib /test/hotspot/jtreg/runtime/appcds
+ * @modules jdk.jartool/sun.tools.jar
+ * @compile ../test-classes/Hello.java
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. DifferentHeapSizes
+ */
+
+import jdk.test.lib.process.OutputAnalyzer;
+import sun.hotspot.WhiteBox;
+import jdk.test.lib.cds.CDSTestUtils;
+
+public class DifferentHeapSizes {
+ static class Scenario {
+ int dumpSize; // in MB
+ int runSizes[]; // in MB
+ Scenario(int ds, int... rs) {
+ dumpSize = ds;
+ runSizes = rs;
+ }
+ }
+
+ static Scenario[] scenarios = {
+ // dump -Xmx , run -Xmx
+ new Scenario( 32, 32, 64, 512, 2048, 4097, 16374, 31000),
+ new Scenario( 128, 32, 64, 512, 2048, 4097, 16374, 31000, 40000),
+ new Scenario( 2048, 32, 512, 2600, 4097, 8500, 31000, 40000),
+ new Scenario( 17000, 32, 512, 2048, 4097, 8500, 31000, 40000),
+ new Scenario( 31000, 32, 512, 2048, 4097, 8500, 17000, 40000)
+ };
+
+ public static void main(String[] args) throws Exception {
+ String dedup = "-XX:+UseStringDeduplication"; // This increases code coverage.
+ JarBuilder.getOrCreateHelloJar();
+ String appJar = TestCommon.getTestJar("hello.jar");
+ String appClasses[] = TestCommon.list("Hello");
+
+ for (Scenario s : scenarios) {
+ String dumpXmx = "-Xmx" + s.dumpSize + "m";
+ OutputAnalyzer output = TestCommon.dump(appJar, appClasses, dumpXmx);
+
+ for (int runSize : s.runSizes) {
+ String runXmx = "-Xmx" + runSize + "m";
+ CDSTestUtils.Result result = TestCommon.run("-cp", appJar, "-showversion",
+ "-Xlog:cds", runXmx, dedup, "Hello");
+ if (runSize < 32768) {
+ result
+ .assertNormalExit("Hello World")
+ .assertNormalExit(out -> {
+ out.shouldNotContain(CDSTestUtils.MSG_RANGE_NOT_WITHIN_HEAP);
+ out.shouldNotContain(CDSTestUtils.MSG_RANGE_ALREADT_IN_USE);
+ });
+ } else {
+ result.assertAbnormalExit("Unable to use shared archive: UseCompressedOops and UseCompressedClassPointers must be on for UseSharedSpaces.");
+ }
+ }
+ }
+ String flag = "HeapBaseMinAddress";
+ String xxflag = "-XX:" + flag + "=";
+ String mx = "-Xmx128m";
+ long base = WhiteBox.getWhiteBox().getSizeTVMFlag(flag).longValue();
+
+ TestCommon.dump(appJar, appClasses, mx, xxflag + base);
+ TestCommon.run("-cp", appJar, "-showversion", "-Xlog:cds", mx, xxflag + (base + 256 * 1024 * 1024), dedup, "Hello")
+ .assertNormalExit("Hello World")
+ .assertNormalExit(out -> {
+ out.shouldNotContain(CDSTestUtils.MSG_RANGE_NOT_WITHIN_HEAP);
+ out.shouldNotContain(CDSTestUtils.MSG_RANGE_ALREADT_IN_USE);
+ });
+ }
+}
--- a/test/hotspot/jtreg/runtime/appcds/cacheObject/RangeNotWithinHeap.java Fri Aug 10 14:56:29 2018 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-/*
- * @test
- * @summary Shared classes can still be used when archived heap regions cannot be
- * mapped due to out of range, and -Xshare:on should not fail. Test on
- * linux 64-bit only since the HeapBaseMinAddress value is platform specific.
- * The value used in the test may cause different behavior on other platforms.
- * @requires vm.cds.archived.java.heap
- * @requires os.family == "linux"
- * @library /test/lib /test/hotspot/jtreg/runtime/appcds
- * @modules java.base/jdk.internal.misc
- * @modules java.management
- * jdk.jartool/sun.tools.jar
- * @compile ../test-classes/Hello.java
- * @run main RangeNotWithinHeap
- */
-
-import jdk.test.lib.process.OutputAnalyzer;
-
-public class RangeNotWithinHeap {
- public static void main(String[] args) throws Exception {
- JarBuilder.getOrCreateHelloJar();
- String appJar = TestCommon.getTestJar("hello.jar");
- String appClasses[] = TestCommon.list("Hello");
-
- OutputAnalyzer output = TestCommon.dump(appJar, appClasses,
- "-XX:HeapBaseMinAddress=0x600000000", "-Xmx6G", "-Xlog:gc+heap=trace");
- TestCommon.checkDump(output, "oa0 space:");
-
- // Force archive region out of runtime java heap
- output = TestCommon.exec(appJar, "Hello");
- TestCommon.checkExec(output, "Hello World");
- output = TestCommon.exec(appJar,
- "-XX:HeapBaseMinAddress=0x600000000", "-Xmx2G", "-Xlog:gc+heap=trace,cds", "Hello");
- TestCommon.checkExec(output, "Hello World");
- try {
- output.shouldContain(
- "UseSharedSpaces: Unable to allocate region, range is not within java heap.");
- } catch (Exception e) {
- // In rare case the heap data is not used.
- if (output.getOutput().contains("Cached heap data from the CDS archive is being ignored")) {
- return;
- }
- // Check for common shared class data mapping failures.
- TestCommon.checkCommonExecExceptions(output, e);
- }
- }
-}
--- a/test/hotspot/jtreg/runtime/appcds/sharedStrings/IncompatibleOptions.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/hotspot/jtreg/runtime/appcds/sharedStrings/IncompatibleOptions.java Thu Aug 23 11:09:16 2018 -0400
@@ -141,10 +141,10 @@
// main class param, and fails with "Could not find or load main class"
if (!extraOption.isEmpty()) {
output = TestCommon.exec(appJar, "-XX:+UseCompressedOops",
- collectorOption, extraOption, "HelloString");
+ collectorOption, "-Xlog:cds", extraOption, "HelloString");
} else {
output = TestCommon.exec(appJar, "-XX:+UseCompressedOops",
- collectorOption, "HelloString");
+ collectorOption, "-Xlog:cds", "HelloString");
}
if (expectedWarning != null)
--- a/test/hotspot/jtreg/runtime/appcds/sharedStrings/InvalidFileFormat.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/hotspot/jtreg/runtime/appcds/sharedStrings/InvalidFileFormat.java Thu Aug 23 11:09:16 2018 -0400
@@ -36,8 +36,9 @@
* @run main/othervm -XX:-CompactStrings InvalidFileFormat
*/
+import java.io.File;
+import jdk.test.lib.cds.CDSTestUtils;
import jdk.test.lib.process.OutputAnalyzer;
-import java.io.File;
// Checking most common error use cases
// This file is not an exhastive test of various shared data file corruption
@@ -65,8 +66,8 @@
OutputAnalyzer out = SharedStringsUtils.dumpWithoutChecks(TestCommon.list("HelloString"),
"invalidFormat" + File.separator + dataFileName);
- if (!TestCommon.isUnableToMap(out))
- out.shouldContain(expectedWarning).shouldHaveExitValue(1);
+ CDSTestUtils.checkMappingFailure(out);
+ out.shouldContain(expectedWarning).shouldHaveExitValue(1);
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/symboltable/ShortLivedSymbolCleanup.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * 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 8195100
+ * @summary a short lived Symbol should be cleaned up
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * java.management
+ * @requires (vm.debug == true)
+ */
+
+import jdk.test.lib.Platform;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+import java.util.Scanner;
+
+public class ShortLivedSymbolCleanup {
+
+ static int getSymbolTableSize(ProcessBuilder pb) throws Exception {
+ int size = 0;
+
+ OutputAnalyzer analyzer = new OutputAnalyzer(pb.start());
+ String output = analyzer.getStdout();
+ analyzer.shouldHaveExitValue(0);
+
+ // Split string into lines using platform independent end of line marker.
+ String[] lines = output.split("\\R");
+ for (String line : lines) {
+ if (line.contains("Start size")) {
+ // ex. "[0.023s][trace][symboltable] Start size: 32768 (15)"
+ Scanner scanner = new Scanner(line);
+ scanner.next(); // skip "[0.023s][trace][symboltable]"
+ scanner.next(); // skip "Start"
+ scanner.next(); // skip "size:"
+ size = Integer.parseInt(scanner.next()); // process "32768"
+ scanner.close();
+ }
+ }
+
+ return size;
+ }
+
+ static void analyzeOutputOn(int size, ProcessBuilder pb) throws Exception {
+ OutputAnalyzer analyzer = new OutputAnalyzer(pb.start());
+ String output = analyzer.getStdout();
+ analyzer.shouldHaveExitValue(0);
+
+ // Split string into lines using platform independent end of line marker.
+ String[] lines = output.split("\\R");
+ for (String line : lines) {
+ if (line.startsWith(" Total removed")) {
+ // ex. "Total removed 13309"
+ Scanner scanner = new Scanner(line);
+ scanner.next(); // skip "Total"
+ scanner.next(); // skip "removed"
+ int removed = Integer.parseInt(scanner.next()); // process "13309"
+ scanner.close();
+
+ if (removed < (size/2)) {
+ System.out.println(output);
+ // We should have removed at least half of the temporary Symbols
+ throw new RuntimeException("Did not clean dead temporary Symbols [removed:"+removed+", size:"+size+"]");
+ }
+ }
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+
+ if (Platform.isDebugBuild()) {
+ {
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:symboltable=trace",
+ "-version");
+ int size = getSymbolTableSize(pb);
+
+ pb = ProcessTools.createJavaProcessBuilder("-XX:+PrintSymbolTableSizeHistogram",
+ LotsOfTempSymbols.class.getName(),
+ Integer.toString(size));
+ analyzeOutputOn(size, pb);
+ }
+ }
+ }
+
+ static class LotsOfTempSymbols {
+ public static void main(String [] args) {
+ int size = 2*Integer.parseInt(args[0]);
+ // Create enough temporary Symbols, that we are
+ // guranteed to insert into every bucket twice,
+ // and therefore have the table check for dead entries
+ for (int i=0; i<size; i++) {
+ try {
+ Class.forName(String.format("%05d", i), false, null);
+ } catch (java.lang.ClassNotFoundException e) {}
+ }
+ }
+ }
+}
\ No newline at end of file
--- a/test/hotspot/jtreg/serviceability/sa/ClhsdbCDSCore.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbCDSCore.java Thu Aug 23 11:09:16 2018 -0400
@@ -201,6 +201,7 @@
.get();
stringWithLocation = stringWithLocation.substring(stringWithLocation
.indexOf(LOCATIONS_STRING) + LOCATIONS_STRING.length());
+ System.out.println("getCoreFileLocation found stringWithLocation = " + stringWithLocation);
String coreWithPid;
if (stringWithLocation.contains("or ")) {
Matcher m = Pattern.compile("or.* ([^ ]+[^\\)])\\)?").matcher(stringWithLocation);
--- a/test/hotspot/jtreg/serviceability/sa/TestIntConstant.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/hotspot/jtreg/serviceability/sa/TestIntConstant.java Thu Aug 23 11:09:16 2018 -0400
@@ -114,7 +114,7 @@
{"CollectedHeap::G1 4",
"RUNNABLE 2",
"Deoptimization::Reason_class_check 4",
- "InstanceKlass::_misc_is_anonymous 32",
+ "InstanceKlass::_misc_is_unsafe_anonymous 32",
"Generation::ParNew 1",
"_thread_uninitialized 0"};
String[] tempConstantString = {"intConstant _temp_constant 45"};
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/unit/FollowReferences/followref003/followref003.c Fri Aug 10 14:56:29 2018 -0700
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/unit/FollowReferences/followref003/followref003.c Thu Aug 23 11:09:16 2018 -0400
@@ -770,10 +770,13 @@
break;
case JVMTI_HEAP_REFERENCE_STACK_LOCAL:
- thr_idx = registerThread(thr_id, thr_tag);
- meth_idx = registerFrame(thr_id, depth, method, ref_kind);
- if (meth_idx > 0) {
- jint loc_idx = registerLocal(meth_idx, location, slot, tag);
+ // Skip local references from non-main (e.g. compiler) threads.
+ if (thr_tag == TARG_THREAD_TAG) {
+ thr_idx = registerThread(thr_id, thr_tag);
+ meth_idx = registerFrame(thr_id, depth, method, ref_kind);
+ if (meth_idx > 0) {
+ jint loc_idx = registerLocal(meth_idx, location, slot, tag);
+ }
}
/* This part is kind of hack. It has some expectations about stack layout */
if (thr_tag == TARG_THREAD_TAG &&
@@ -811,10 +814,13 @@
nsk_jvmti_setFailStatus();
}
}
- /* Fall through */
+ break;
case JVMTI_HEAP_REFERENCE_JNI_LOCAL:
- thr_idx = registerThread(thr_id, thr_tag);
- meth_idx = registerFrame(thr_id, depth, method, ref_kind);
+ // Skip JNI local references from non-main (e.g. compiler) threads.
+ if (thr_tag == TARG_THREAD_TAG) {
+ thr_idx = registerThread(thr_id, thr_tag);
+ meth_idx = registerFrame(thr_id, depth, method, ref_kind);
+ }
break;
case JVMTI_REFERENCE_ARRAY_ELEMENT:
--- a/test/jdk/ProblemList.txt Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/ProblemList.txt Thu Aug 23 11:09:16 2018 -0400
@@ -147,7 +147,7 @@
java/awt/EventQueue/6980209/bug6980209.java 8198615 macosx-all
java/awt/Frame/ExceptionOnSetExtendedStateTest/ExceptionOnSetExtendedStateTest.java 8198237 macosx-all
java/awt/Frame/ShapeNotSetSometimes/ShapeNotSetSometimes.java 8144030 macosx-all
-java/awt/Frame/UnfocusableMaximizedFrameResizablity/UnfocusableMaximizedFrameResizablity.java 7158623 macosx-all
+java/awt/Frame/UnfocusableMaximizedFrameResizablity/UnfocusableMaximizedFrameResizablity.java 8208290 macosx-all
java/awt/grab/EmbeddedFrameTest1/EmbeddedFrameTest1.java 7080150 macosx-all
java/awt/event/InputEvent/EventWhenTest/EventWhenTest.java 8168646 generic-all
java/awt/KeyboardFocusmanager/TypeAhead/EnqueueWithDialogButtonTest/EnqueueWithDialogButtonTest.java 8198623 macosx-all
@@ -639,7 +639,7 @@
sun/security/pkcs11/KeyGenerator/DESParity.java 8204203 windows-all
sun/security/pkcs11/KeyGenerator/TestKeyGenerator.java 8204203 windows-all
sun/security/pkcs11/KeyPairGenerator/TestDH2048.java 8204203 windows-all
-sun/security/pkcs11/KeyStore/SecretKeysBasic.sh 8204203 windows-all
+sun/security/pkcs11/KeyStore/SecretKeysBasic.sh 8204203,8209398 generic-all
sun/security/pkcs11/Mac/MacKAT.java 8204203 windows-all
sun/security/pkcs11/Mac/MacSameTest.java 8204203 windows-all
sun/security/pkcs11/Mac/ReinitMac.java 8204203 windows-all
@@ -867,6 +867,8 @@
# svc_tools
sun/tools/jstat/jstatClassloadOutput1.sh 8173942 generic-all
+sun/tools/jhsdb/BasicLauncherTest.java 8193639 solaris-all
+sun/tools/jhsdb/HeapDumpTest.java 8193639 solaris-all
############################################################################
--- a/test/jdk/TEST.ROOT Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/TEST.ROOT Thu Aug 23 11:09:16 2018 -0400
@@ -31,8 +31,8 @@
# Source files for classes that will be used at the beginning of each test suite run,
# to determine additional characteristics of the system for use with the @requires tag.
# Note: compiled bootlibs code will be located in the folder 'bootClasses'
-requires.extraPropDefns = ../../test/jtreg-ext/requires/VMProps.java [../../closed/test/jtreg-ext/requires/VMPropsExt.java]
-requires.extraPropDefns.bootlibs = ../../test/lib/sun ../../test/lib/jdk/test/lib/Platform.java
+requires.extraPropDefns = ../jtreg-ext/requires/VMProps.java
+requires.extraPropDefns.bootlibs = ../lib/sun ../lib/jdk/test/lib/Platform.java
requires.extraPropDefns.vmOpts = -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:bootClasses
requires.properties= \
sun.arch.data.model \
--- a/test/jdk/com/sun/crypto/provider/Cipher/PBE/PKCS12Cipher.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/com/sun/crypto/provider/Cipher/PBE/PKCS12Cipher.java Thu Aug 23 11:09:16 2018 -0400
@@ -106,7 +106,7 @@
this.salt = salt;
this.iCount = iCount;
}
- public char[] getPassword() { return passwd; }
+ public char[] getPassword() { return passwd.clone(); }
public byte[] getSalt() { return salt; }
public int getIterationCount() { return iCount; }
public String getAlgorithm() { return "PBE"; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/com/sun/jdi/ArrayLengthDumpTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
+ * 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 4422141 4695338
+ * @summary TTY: .length field for arrays in print statements in jdb not recognized
+ * TTY: dump <ArrayReference> command not implemented.
+ * @comment converted from test/jdk/com/sun/jdi/ArrayLengthDumpTest.sh
+ *
+ * @library /test/lib
+ * @build ArrayLengthDumpTest
+ * @run main/othervm ArrayLengthDumpTest
+ */
+
+import lib.jdb.JdbCommand;
+import lib.jdb.JdbTest;
+import jdk.test.lib.process.OutputAnalyzer;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+
+class ArrayLengthDumpTarg {
+ static final int [] i = {0,1,2,3,4,5,6};
+ String [] s = {"zero", "one", "two", "three", "four"};
+ String [][] t = {s, s, s, s, s, s, s, s, s, s, s};
+ int length = 5;
+
+ private void bar() {
+ }
+
+ private void foo() {
+ ArrayLengthDumpTarg u[] = { new ArrayLengthDumpTarg(),
+ new ArrayLengthDumpTarg(),
+ new ArrayLengthDumpTarg(),
+ new ArrayLengthDumpTarg(),
+ new ArrayLengthDumpTarg(),
+ new ArrayLengthDumpTarg() };
+ int k = u.length;
+ System.out.println(" u.length is: " + k);
+ k = this.s.length;
+ System.out.println(" this.s.length is: " + k);
+ k = this.t.length;
+ System.out.println(" this.t.length is: " + k);
+ k = this.t[1].length;
+ System.out.println("this.t[1].length is: " + k);
+ k = i.length;
+ System.out.println(" i.length is: " + k);
+ bar(); // @1 breakpoint
+ }
+
+ public static void main(String[] args) {
+ ArrayLengthDumpTarg my = new ArrayLengthDumpTarg();
+ my.foo();
+ }
+}
+
+public class ArrayLengthDumpTest extends JdbTest {
+ public static void main(String argv[]) {
+ new ArrayLengthDumpTest().run();
+ }
+
+ public ArrayLengthDumpTest() {
+ super(DEBUGGEE_CLASS);
+ }
+
+ private static final String DEBUGGEE_CLASS = ArrayLengthDumpTarg.class.getName();
+
+ @Override
+ protected void runCases() {
+ setBreakpoints(System.getProperty("test.src") + "/ArrayLengthDumpTest.java", 1);
+
+ // Run to breakpoint #1
+ jdb.command(JdbCommand.run());
+
+ List<String> reply = new LinkedList<>();
+ reply.addAll(jdb.command(JdbCommand.dump("this")));
+ reply.addAll(jdb.command(JdbCommand.dump("this.s.length")));
+ reply.addAll(jdb.command(JdbCommand.dump("this.s")));
+ reply.addAll(jdb.command(JdbCommand.dump("this.t.length")));
+ reply.addAll(jdb.command(JdbCommand.dump("this.t[1].length")));
+ reply.addAll(jdb.command(JdbCommand.dump("ArrayLengthDumpTarg.i.length")));
+ reply.addAll(jdb.command(JdbCommand.dump("this.length")));
+
+ new OutputAnalyzer(reply.stream().collect(Collectors.joining(lineSeparator)))
+ // Test the fix for 4690242:
+ .shouldNotContain("No instance field or method with the name length in")
+ .shouldNotContain("No static field or method with the name length")
+ // Test the fix for 4695338:
+ .shouldContain("\"zero\", \"one\", \"two\", \"three\", \"four\"");
+
+ jdb.contToExit(1);
+ }
+
+}
--- a/test/jdk/com/sun/jdi/ArrayLengthDumpTest.sh Fri Aug 10 14:56:29 2018 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,122 +0,0 @@
-#!/bin/sh
-
-#
-# Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
-# 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 4422141 4695338
-# @summary TTY: .length field for arrays in print statements in jdb not recognized
-# TTY: dump <ArrayReference> command not implemented.
-# @author Tim Bell
-#
-# @key intermittent
-# @run shell ArrayLengthDumpTest.sh
-#
-classname=ArrayLengthDumpTarg
-
-createJavaFile()
-{
- cat <<EOF > $classname.java.1
-class $classname {
- static final int [] i = {0,1,2,3,4,5,6};
- String [] s = {"zero", "one", "two", "three", "four"};
- String [][] t = {s, s, s, s, s, s, s, s, s, s, s};
- int length = 5;
-
- public void bar() {
- }
-
- public void foo() {
- ArrayLengthDumpTarg u[] = { new ArrayLengthDumpTarg(),
- new ArrayLengthDumpTarg(),
- new ArrayLengthDumpTarg(),
- new ArrayLengthDumpTarg(),
- new ArrayLengthDumpTarg(),
- new ArrayLengthDumpTarg() };
- int k = u.length;
- System.out.println(" u.length is: " + k);
- k = this.s.length;
- System.out.println(" this.s.length is: " + k);
- k = this.t.length;
- System.out.println(" this.t.length is: " + k);
- k = this.t[1].length;
- System.out.println("this.t[1].length is: " + k);
- k = i.length;
- System.out.println(" i.length is: " + k);
- bar(); // @1 breakpoint
- }
-
- public static void main(String[] args) {
- ArrayLengthDumpTarg my = new ArrayLengthDumpTarg();
- my.foo();
- }
-}
-EOF
-}
-
-# This is called to feed cmds to jdb.
-dojdbCmds()
-{
- setBkpts @1
- runToBkpt @1
- cmd dump this
- cmd dump this.s.length
- cmd dump this.s
- cmd dump this.t.length
- cmd dump this.t[1].length
- cmd dump ArrayLengthDumpTarg.i.length
- cmd dump this.length
- cmd allowExit cont
-}
-
-mysetup()
-{
- if [ -z "$TESTSRC" ] ; then
- TESTSRC=.
- fi
-
- for ii in . $TESTSRC $TESTSRC/.. ; do
- if [ -r "$ii/ShellScaffold.sh" ] ; then
- . $ii/ShellScaffold.sh
- break
- fi
- done
-}
-
-
-# You could replace this next line with the contents
-# of ShellScaffold.sh and this script will run just the same.
-mysetup
-
-runit
-#
-# Test the fix for 4690242:
-#
-jdbFailIfPresent "No instance field or method with the name length in" 50
-jdbFailIfPresent "No static field or method with the name length" 50
-#
-# Test the fix for 4695338:
-#
-jdbFailIfNotPresent "\"zero\", \"one\", \"two\", \"three\", \"four\"" 50
-pass
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/com/sun/jdi/BreakpointWithFullGC.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
+ * 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 6862295
+ * @summary Verify breakpoints still work after a full GC.
+ * @comment converted from test/jdk/com/sun/jdi/BreakpointWithFullGC.sh
+ *
+ * @library /test/lib
+ * @compile -g BreakpointWithFullGC.java
+ * @run main/othervm BreakpointWithFullGC
+ */
+
+import jdk.test.lib.process.OutputAnalyzer;
+import lib.jdb.Jdb;
+import lib.jdb.JdbCommand;
+import lib.jdb.JdbTest;
+
+import java.util.ArrayList;
+import java.util.List;
+
+class BreakpointWithFullGCTarg {
+ public static List<Object> objList = new ArrayList<>();
+
+ private static void init(int numObjs) {
+ for (int i = 0; i < numObjs; i++) {
+ objList.add(new Object());
+ }
+ }
+
+ public static void main(String[] args) {
+ for (int i = 0; i < 10; i++) {
+ System.out.println("top of loop"); // @1 breakpoint
+ init(500000);
+ objList.clear();
+ System.gc();
+ System.out.println("bottom of loop"); // @1 breakpoint
+ }
+ System.out.println("end of test"); // @1 breakpoint
+ }
+}
+
+public class BreakpointWithFullGC extends JdbTest {
+ public static void main(String argv[]) {
+ new BreakpointWithFullGC().run();
+ }
+
+ private BreakpointWithFullGC() {
+ super(new Jdb.LaunchOptions(DEBUGGEE_CLASS)
+ .addDebuggeeOptions(DEBUGGEE_OPTIONS));
+ }
+
+ private static final String DEBUGGEE_CLASS = BreakpointWithFullGCTarg.class.getName();
+ // We don't specify "-Xmx" for debuggee as we have full GCs with any value.
+ private static final String[] DEBUGGEE_OPTIONS = {"-verbose:gc"};
+
+ @Override
+ protected void runCases() {
+ setBreakpoints(System.getProperty("test.src") + "/BreakpointWithFullGC.java", 1);
+
+ // get to the first loop breakpoint
+ jdb.command(JdbCommand.run());
+ // 19 "cont" commands gets us through all the loop breakpoints.
+ for (int i = 1; i <= 19; i++) {
+ jdb.command(JdbCommand.cont());
+ }
+ // get to the last breakpoint
+ jdb.command(JdbCommand.cont());
+
+ jdb.contToExit(1);
+
+ new OutputAnalyzer(jdb.getJdbOutput())
+ // make sure we hit the first breakpoint at least once
+ .stdoutShouldMatch("System\\..*top of loop")
+ // make sure we hit the second breakpoint at least once
+ .stdoutShouldMatch("System\\..*bottom of loop")
+ // make sure we hit the last breakpoint
+ .stdoutShouldMatch("System\\..*end of test");
+ new OutputAnalyzer(jdb.getDebuggeeOutput())
+ // check for error message due to thread ID change
+ .stderrShouldNotContain("Exception in thread \"event-handler\" java.lang.NullPointerException");
+ }
+}
--- a/test/jdk/com/sun/jdi/BreakpointWithFullGC.sh Fri Aug 10 14:56:29 2018 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,131 +0,0 @@
-#!/bin/sh
-
-#
-# Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-# @test
-# @bug 6862295
-# @summary Verify breakpoints still work after a full GC.
-# @author dcubed (based on the test program posted to the following
-# Eclipse thread https://bugs.eclipse.org/bugs/show_bug.cgi?id=279137)
-#
-# @key intermittent
-# @run shell BreakpointWithFullGC.sh
-
-compileOptions=-g
-# Hijacking the mode parameter to make sure we use a small amount
-# of memory and can see what GC is doing.
-mode="-Xmx32m -verbose:gc"
-# Force use of a GC framework collector to see the original failure.
-#mode="$mode -XX:+UseSerialGC"
-
-# Uncomment this to see the JDI trace
-#jdbOptions=-dbgtrace
-
-createJavaFile()
-{
- cat <<EOF > $1.java.1
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class $1 {
- public static List<Object> objList = new ArrayList<Object>();
-
- private static void init(int numObjs) {
- for (int i = 0; i < numObjs; i++) {
- objList.add(new Object());
- }
- }
-
- public static void main(String[] args) {
- for (int i = 0; i < 10; i++) {
- System.out.println("top of loop"); // @1 breakpoint
- init(500000);
- objList.clear();
- System.gc();
- System.out.println("bottom of loop"); // @1 breakpoint
- }
- System.out.println("end of test"); // @1 breakpoint
- }
-}
-
-EOF
-}
-
-# This is called to feed cmds to jdb.
-dojdbCmds()
-{
- setBkpts @1
-
- # get to the first loop breakpoint
- runToBkpt
- # 19 "cont" commands gets us through all the loop breakpoints.
- # Use for-loop instead of while-loop to avoid creating processes
- # for '[' and 'expr'.
- for ii in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19; do
- contToBkpt
- done
- # get to the last breakpoint
- contToBkpt
-}
-
-
-mysetup()
-{
- if [ -z "$TESTSRC" ] ; then
- TESTSRC=.
- fi
-
- for ii in . $TESTSRC $TESTSRC/.. ; do
- if [ -r "$ii/ShellScaffold.sh" ] ; then
- . $ii/ShellScaffold.sh
- break
- fi
- done
-}
-
-# You could replace this next line with the contents
-# of ShellScaffold.sh and this script will run just the same.
-mysetup
-
-runit
-
-# make sure we hit the first breakpoint at least once
-jdbFailIfNotPresent 'System\..*top of loop'
-
-# make sure we hit the second breakpoint at least once
-jdbFailIfNotPresent 'System\..*bottom of loop'
-
-# make sure we hit the last breakpoint
-jdbFailIfNotPresent 'System\..*end of test'
-
-# make sure we had at least one full GC
-# Prior to JDK9-B95, the pattern was 'Full GC'
-debuggeeMatchRegexp '^.*?\bPause Full\b\(System.gc\(\)\)\b.*?$'
-
-# check for error message due to thread ID change
-debuggeeFailIfPresent \
- 'Exception in thread "event-handler" java.lang.NullPointerException'
-
-pass
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/com/sun/jdi/lib/jdb/Jdb.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,391 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * 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 lib.jdb;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import jdk.test.lib.JDKToolFinder;
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.process.StreamPumper;
+
+public class Jdb {
+
+ public static class LaunchOptions {
+ public final String debuggeeClass;
+ public final List<String> debuggeeOptions = new LinkedList<>();
+
+ public LaunchOptions(String debuggeeClass) {
+ this.debuggeeClass = debuggeeClass;
+ }
+ public LaunchOptions addDebuggeeOption(String option) {
+ debuggeeOptions.add(option);
+ return this;
+ }
+ public LaunchOptions addDebuggeeOptions(String[] options) {
+ debuggeeOptions.addAll(Arrays.asList(options));
+ return this;
+ }
+ }
+
+ public static Jdb launchLocal(LaunchOptions options) {
+ return new Jdb(options);
+ }
+
+ public static Jdb launchLocal(String debuggeeClass) {
+ return new Jdb(new LaunchOptions(debuggeeClass));
+ }
+
+ public Jdb(LaunchOptions options) {
+ /* run debuggee as:
+ java -agentlib:jdwp=transport=dt_socket,address=0,server=n,suspend=y <debuggeeClass>
+ it reports something like : Listening for transport dt_socket at address: 60810
+ after that connect jdb by:
+ jdb -connect com.sun.jdi.SocketAttach:port=60810
+ */
+ // launch debuggee
+ List<String> debuggeeArgs = new LinkedList<>();
+ // specify address=0 to automatically select free port
+ debuggeeArgs.add("-agentlib:jdwp=transport=dt_socket,address=0,server=y,suspend=y");
+ debuggeeArgs.addAll(options.debuggeeOptions);
+ debuggeeArgs.add(options.debuggeeClass);
+ ProcessBuilder pbDebuggee = ProcessTools.createJavaProcessBuilder(true, debuggeeArgs.toArray(new String[0]));
+
+ // debuggeeListen[0] - transport, debuggeeListen[1] - address
+ String[] debuggeeListen = new String[2];
+ Pattern listenRegexp = Pattern.compile("Listening for transport \\b(.+)\\b at address: \\b(\\d+)\\b");
+ try {
+ debuggee = ProcessTools.startProcess("debuggee", pbDebuggee,
+ s -> debuggeeOutput.add(s), // output consumer
+ s -> { // warm-up predicate
+ Matcher m = listenRegexp.matcher(s);
+ if (!m.matches()) {
+ return false;
+ }
+ debuggeeListen[0] = m.group(1);
+ debuggeeListen[1] = m.group(2);
+ return true;
+ },
+ 30, TimeUnit.SECONDS);
+ } catch (IOException | InterruptedException | TimeoutException ex) {
+ throw new RuntimeException("failed to launch debuggee", ex);
+ }
+
+ // launch jdb
+ try {
+ ProcessBuilder pb = new ProcessBuilder(JDKToolFinder.getTestJDKTool("jdb"));
+ pb.command().add("-connect");
+ pb.command().add("com.sun.jdi.SocketAttach:port=" + debuggeeListen[1]);
+ System.out.println("Launching jdb:" + pb.command().stream().collect(Collectors.joining(" ")));
+ try {
+ jdb = pb.start();
+ } catch (IOException ex) {
+ throw new RuntimeException("failed to launch pdb", ex);
+ }
+ StreamPumper stdout = new StreamPumper(jdb.getInputStream());
+ StreamPumper stderr = new StreamPumper(jdb.getErrorStream());
+
+ stdout.addPump(new StreamPumper.StreamPump(outputHandler));
+ stderr.addPump(new StreamPumper.StreamPump(outputHandler));
+
+ stdout.process();
+ stderr.process();
+
+ inputWriter = new PrintWriter(jdb.getOutputStream(), true);
+ } catch (Throwable ex) {
+ // terminate debuggee if something went wrong
+ debuggee.destroy();
+ throw ex;
+ }
+ }
+
+ private final Process jdb;
+ private final Process debuggee;
+ private final OutputHandler outputHandler = new OutputHandler();
+ private final PrintWriter inputWriter;
+ // contains all jdb output (to be used by getJdbOutput())
+ private final List<String> jdbOutput = new LinkedList<>();
+ private final List<String> debuggeeOutput = new LinkedList<>();
+
+ private static final String lineSeparator = System.getProperty("line.separator");
+ // wait time before check jdb output (in ms)
+ private static long sleepTime = 1000;
+ // max time to wait for jdb output (in ms)
+ private static long timeout = 60000;
+
+ // jdb prompt when debuggee is not started nor suspended after breakpoint
+ public static final String SIMPLE_PROMPT = "> ";
+ // pattern for message of a breakpoint hit
+ public static final String BREAKPOINT_HIT = "Breakpoint hit:";
+ // pattern for message of an application exit
+ public static final String APPLICATION_EXIT = "The application exited";
+ // pattern for message of an application disconnect
+ public static final String APPLICATION_DISCONNECTED = "The application has been disconnected";
+
+
+ // waits until the process shutdown or crash
+ public boolean waitFor(long timeout, TimeUnit unit) {
+ try {
+ return jdb.waitFor(timeout, unit);
+ } catch (InterruptedException e) {
+ return false;
+ }
+ }
+
+ public void shutdown() {
+ // shutdown jdb
+ if (jdb.isAlive()) {
+ try {
+ quit();
+ // wait some time after the command for the process termination
+ waitFor(10, TimeUnit.SECONDS);
+ } finally {
+ if (jdb.isAlive()) {
+ jdb.destroy();
+ }
+ }
+ }
+ // shutdown debuggee
+ if (debuggee.isAlive()) {
+ try {
+ debuggee.waitFor(10, TimeUnit.SECONDS);
+ } catch (InterruptedException e) {
+ // ignore
+ } finally {
+ if (debuggee.isAlive()) {
+ debuggee.destroy();
+ }
+ }
+ }
+ }
+
+
+ // waits until string {@pattern} appears in the jdb output, within the last {@code lines} lines.
+ /* Comment from original /test/jdk/com/sun/jdi/ShellScaffold.sh
+ # Now we have to wait for the next jdb prompt. We wait for a pattern
+ # to appear in the last line of jdb output. Normally, the prompt is
+ #
+ # 1) ^main[89] @
+ #
+ # where ^ means start of line, and @ means end of file with no end of line
+ # and 89 is the current command counter. But we have complications e.g.,
+ # the following jdb output can appear:
+ #
+ # 2) a[89] = 10
+ #
+ # The above form is an array assignment and not a prompt.
+ #
+ # 3) ^main[89] main[89] ...
+ #
+ # This occurs if the next cmd is one that causes no jdb output, e.g.,
+ # 'trace methods'.
+ #
+ # 4) ^main[89] [main[89]] .... > @
+ #
+ # jdb prints a > as a prompt after something like a cont.
+ # Thus, even though the above is the last 'line' in the file, it
+ # isn't the next prompt we are waiting for after the cont completes.
+ # HOWEVER, sometimes we see this for a cont command:
+ #
+ # ^main[89] $
+ # <lines output for hitting a bkpt>
+ #
+ # 5) ^main[89] > @
+ #
+ # i.e., the > prompt comes out AFTER the prompt we we need to wait for.
+ */
+ // compile regexp once
+ private final String promptPattern = "[a-zA-Z0-9_-][a-zA-Z0-9_-]*\\[[1-9][0-9]*\\] [ >]*$";
+ private final Pattern promptRegexp = Pattern.compile(promptPattern);
+ public List<String> waitForPrompt(int lines, boolean allowExit) {
+ long startTime = System.currentTimeMillis();
+ while (System.currentTimeMillis() - startTime < timeout) {
+ try {
+ Thread.sleep(sleepTime);
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ synchronized (outputHandler) {
+ if (!outputHandler.updated()) {
+ try {
+ outputHandler.wait(sleepTime);
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ } else {
+ // if something appeared in the jdb output, reset the timeout
+ startTime = System.currentTimeMillis();
+ }
+ }
+ List<String> reply = outputHandler.get();
+ for (String line: reply.subList(Math.max(0, reply.size() - lines), reply.size())) {
+ if (promptRegexp.matcher(line).find()) {
+ logJdb(reply);
+ return outputHandler.reset();
+ }
+ }
+ if (!jdb.isAlive()) {
+ // ensure we get the whole output
+ reply = outputHandler.reset();
+ logJdb(reply);
+ if (!allowExit) {
+ throw new RuntimeException("waitForPrompt timed out after " + (timeout/1000)
+ + " seconds, looking for '" + promptPattern + "', in " + lines + " lines");
+ }
+ return reply;
+ }
+ }
+ // timeout
+ logJdb(outputHandler.get());
+ throw new RuntimeException("waitForPrompt timed out after " + (timeout/1000)
+ + " seconds, looking for '" + promptPattern + "', in " + lines + " lines");
+ }
+
+ public List<String> command(JdbCommand cmd) {
+ if (!jdb.isAlive()) {
+ if (cmd.allowExit) {
+ // return remaining output
+ return outputHandler.reset();
+ }
+ throw new RuntimeException("Attempt to send command '" + cmd.cmd + "' to terminated jdb");
+ }
+
+ System.out.println("> " + cmd.cmd);
+
+ inputWriter.println(cmd.cmd);
+
+ if (inputWriter.checkError()) {
+ throw new RuntimeException("Unexpected IO error while writing command '" + cmd.cmd + "' to jdb stdin stream");
+ }
+
+ return waitForPrompt(1, cmd.allowExit);
+ }
+
+ public List<String> command(String cmd) {
+ return command(new JdbCommand(cmd));
+ }
+
+ // sends "cont" command up to maxTimes until debuggee exit
+ public void contToExit(int maxTimes) {
+ boolean exited = false;
+ JdbCommand cont = JdbCommand.cont().allowExit();
+ for (int i = 0; i < maxTimes && jdb.isAlive(); i++) {
+ String reply = command(cont).stream().collect(Collectors.joining(lineSeparator));
+ if (reply.contains(APPLICATION_EXIT)) {
+ exited = true;
+ break;
+ }
+ }
+ if (!exited && jdb.isAlive()) {
+ throw new RuntimeException("Debuggee did not exit after " + maxTimes + " <cont> commands");
+ }
+ }
+
+ // quits jdb by using "quit" command
+ public void quit() {
+ command(JdbCommand.quit());
+ }
+
+ private void log(String s) {
+ System.out.println(s);
+ }
+
+ private void logJdb(List<String> reply) {
+ jdbOutput.addAll(reply);
+ reply.forEach(s -> System.out.println("[jdb] " + s));
+ }
+
+ // returns the whole jdb output as a string
+ public String getJdbOutput() {
+ return jdbOutput.stream().collect(Collectors.joining(lineSeparator));
+ }
+
+ // returns the whole debuggee output as a string
+ public String getDebuggeeOutput() {
+ return debuggeeOutput.stream().collect(Collectors.joining(lineSeparator));
+ }
+
+ // handler for out/err of the pdb process
+ private class OutputHandler extends OutputStream {
+ // there are 2 buffers:
+ // outStream - data from the process stdout/stderr after last get() call
+ // cachedData - data collected at get(), cleared by reset()
+
+ private final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+ // if the last line in the reply had EOL, the list's last element is empty
+ private final List<String> cachedData = new ArrayList<>();
+
+ @Override
+ public synchronized void write(int b) throws IOException {
+ outStream.write((byte)(b & 0xFF));
+ notifyAll();
+ }
+ @Override
+ public synchronized void write(byte b[], int off, int len) throws IOException {
+ outStream.write(b, off, len);
+ notifyAll();
+ }
+
+ // gets output after the last {@ reset}.
+ // returned data becomes invalid after {@reset}.
+ public synchronized List<String> get() {
+ if (updated()) {
+ // we don't want to discard empty lines
+ String[] newLines = outStream.toString().split("\\R", -1);
+ if (!cachedData.isEmpty()) {
+ // concat the last line if previous data had no EOL
+ newLines[0] = cachedData.remove(cachedData.size()-1) + newLines[0];
+ }
+ cachedData.addAll(Arrays.asList(newLines));
+ outStream.reset();
+ }
+ return Collections.unmodifiableList(cachedData);
+ }
+
+ // clears last replay (does not touch replyStream)
+ // returns list as the last get()
+ public synchronized List<String> reset() {
+ List<String> result = new ArrayList<>(cachedData);
+ cachedData.clear();
+ return result;
+ }
+
+ // tests if there are some new data after the last lastReply() call
+ public synchronized boolean updated() {
+ return outStream.size() > 0;
+ }
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/com/sun/jdi/lib/jdb/JdbCommand.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
+ * 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 lib.jdb;
+
+import java.util.Arrays;
+import java.util.stream.Collectors;
+
+/**
+ * Represents list of commands of <code>jdb</code> from JDK1.4:
+ *
+ * run [class [args]] -- start execution of application's main class
+ *
+ * threads [threadgroup] -- list threads
+ * thread <thread id> -- set default thread
+ * suspend [thread id(s)] -- suspend threads (default: all)
+ * resume [thread id(s)] -- resume threads (default: all)
+ * where [thread id] | all -- dump a thread's stack
+ * wherei [thread id] | all -- dump a thread's stack, with pc info
+ * up [n frames] -- move up a thread's stack
+ * down [n frames] -- move down a thread's stack
+ * kill <thread> <expr> -- kill a thread with the given exception object
+ * interrupt <thread> -- interrupt a thread
+ *
+ * print <expr> -- print value of expression
+ * dump <expr> -- print all object information
+ * eval <expr> -- evaluate expression (same as print)
+ * set <lvalue> = <expr> -- assign new value to field/variable/array element
+ * locals -- print all local variables in current stack frame
+ *
+ * classes -- list currently known classes
+ * class <class id> -- show details of named class
+ * methods <class id> -- list a class's methods
+ * fields <class id> -- list a class's fields
+ *
+ * threadgroups -- list threadgroups
+ * threadgroup <name> -- set current threadgroup
+ *
+ * stop in <class id>.<method>[(argument_type,...)]
+ * -- set a breakpoint in a method
+ * stop at <class id>:<line> -- set a breakpoint at a line
+ * clear <class id>.<method>[(argument_type,...)]
+ * -- clear a breakpoint in a method
+ * clear <class id>:<line> -- clear a breakpoint at a line
+ * clear -- list breakpoints
+ * catch <class id> -- break when specified exception thrown
+ * ignore <class id> -- cancel 'catch' for the specified exception
+ * watch [access|all] <class id>.<field name>
+ * -- watch access/modifications to a field
+ * unwatch [access|all] <class id>.<field name>
+ * -- discontinue watching access/modifications to a field
+ * trace methods [thread] -- trace method entry and exit
+ * untrace methods [thread] -- stop tracing method entry and exit
+ * step -- execute current line
+ * step up -- execute until the current method returns to its caller
+ * stepi -- execute current instruction
+ * next -- step one line (step OVER calls)
+ * cont -- continue execution from breakpoint
+ *
+ * list [line number|method] -- print source code
+ * use (or sourcepath) [source file path]
+ * -- display or change the source path
+ * exclude [class id ... | "none"]
+ * -- do not report step or method events for specified classes
+ * classpath -- print classpath info from target VM
+ *
+ * monitor <command> -- execute command each time the program stops
+ * monitor -- list monitors
+ * unmonitor <monitor#> -- delete a monitor
+ * read <filename> -- read and execute a command file
+ *
+ * lock <expr> -- print lock info for an object
+ * threadlocks [thread id] -- print lock info for a thread
+ *
+ * pop -- pop the stack through and including the current frame
+ * reenter -- same as pop, but current frame is reentered
+ * redefine <class id> <class file name>
+ * -- redefine the code for a class
+ *
+ * disablegc <expr> -- prevent garbage collection of an object
+ * enablegc <expr> -- permit garbage collection of an object
+ *
+ * !! -- repeat last command
+ * <n> <command> -- repeat command n times
+ * help (or ?) -- list commands
+ * version -- print version information
+ * exit (or quit) -- exit debugger
+ *
+ * <class id>: full class name with package qualifiers or a
+ * pattern with a leading or trailing wildcard ('*').
+ * <thread id>: thread number as reported in the 'threads' command
+ * <expr>: a Java(tm) Programming Language expression.
+ * Most common syntax is supported.
+ *
+ * Startup commands can be placed in either "jdb.ini" or ".jdbrc"
+ * in user.home or user.dir
+ */
+public class JdbCommand {
+ final String cmd;
+ boolean allowExit = false;
+
+ public JdbCommand(String cmd) {
+ this.cmd = cmd.endsWith(ls) ? cmd.substring(0, cmd.length() - 1) : cmd;
+ }
+
+ public JdbCommand allowExit() {
+ allowExit = true;
+ return this;
+ }
+
+
+ private static final String ls = System.getProperty("line.separator");
+
+ public static JdbCommand run(String ... params) {
+ return new JdbCommand("run " + Arrays.stream(params).collect(Collectors.joining(" ")));
+ }
+ public static JdbCommand cont() {
+ return new JdbCommand("cont");
+ }
+ public static JdbCommand dump(String what) {
+ return new JdbCommand("dump " + what);
+ }
+ public static JdbCommand quit() {
+ // the command suppose jdb terminates
+ return new JdbCommand("quit").allowExit();
+ }
+ public static JdbCommand stopAt(String targetClass, int lineNum) {
+ return new JdbCommand("stop at " + targetClass + ":" + lineNum);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/com/sun/jdi/lib/jdb/JdbTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * 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 lib.jdb;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public abstract class JdbTest {
+
+ public JdbTest(Jdb.LaunchOptions jdbOptions) {
+ this.jdbOptions= jdbOptions;
+ debuggeeClass = jdbOptions.debuggeeClass;
+ }
+ public JdbTest(String debuggeeClass) {
+ this(new Jdb.LaunchOptions(debuggeeClass));
+ }
+
+ private final Jdb.LaunchOptions jdbOptions;
+ protected Jdb jdb;
+ protected final String debuggeeClass; // shortland for jdbOptions.debuggeeClass
+
+ public void run() {
+ try {
+ setup();
+ runCases();
+ } finally {
+ shutdown();
+ }
+ }
+
+ protected void setup() {
+ jdb = Jdb.launchLocal(jdbOptions);
+ // wait while jdb is initialized
+ jdb.waitForPrompt(1, false);
+
+ }
+
+ protected abstract void runCases();
+
+ protected void shutdown() {
+ if (jdb != null) {
+ jdb.shutdown();
+ }
+ }
+
+ protected static final String lineSeparator = System.getProperty("line.separator");
+
+
+ // Parses the specified source file for "@{id} breakpoint" tags and returns
+ // list of the line numbers containing the tag.
+ // Example:
+ // System.out.println("BP is here"); // @1 breakpoint
+ public static List<Integer> parseBreakpoints(String filePath, int id) {
+ final String pattern = "@" + id + " breakpoint";
+ int lineNum = 1;
+ List<Integer> result = new LinkedList<>();
+ try {
+ for (String line: Files.readAllLines(Paths.get(filePath))) {
+ if (line.contains(pattern)) {
+ result.add(lineNum);
+ }
+ lineNum++;
+ }
+ } catch (IOException ex) {
+ throw new RuntimeException("failed to parse " + filePath, ex);
+ }
+ return result;
+ }
+
+ // sets breakpoints to the lines parsed by {@code parseBreakpoints}
+ // returns number of the breakpoints set.
+ public static int setBreakpoints(Jdb jdb, String debuggeeClass, String sourcePath, int id) {
+ List<Integer> bps = parseBreakpoints(sourcePath, id);
+ for (int bp : bps) {
+ String reply = jdb.command(JdbCommand.stopAt(debuggeeClass, bp)).stream()
+ .collect(Collectors.joining("\n"));
+ if (reply.contains("Unable to set")) {
+ throw new RuntimeException("jdb failed to set breakpoint at " + debuggeeClass + ":" + bp);
+ }
+
+ }
+ return bps.size();
+ }
+
+ protected int setBreakpoints(String debuggeeSourcePath, int id) {
+ return setBreakpoints(jdb, debuggeeClass, debuggeeSourcePath, id);
+ }
+
+}
--- a/test/jdk/java/awt/Frame/UnfocusableMaximizedFrameResizablity/UnfocusableMaximizedFrameResizablity.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/java/awt/Frame/UnfocusableMaximizedFrameResizablity/UnfocusableMaximizedFrameResizablity.java Thu Aug 23 11:09:16 2018 -0400
@@ -24,7 +24,7 @@
/*
@test
@key headful
- @bug 4980161 7158623 8204860
+ @bug 4980161 7158623 8204860 8208125
@summary Setting focusable window state to false makes the maximized frame resizable
@compile UnfocusableMaximizedFrameResizablity.java
@run main UnfocusableMaximizedFrameResizablity
@@ -36,13 +36,10 @@
import java.awt.AWTException;
import java.awt.event.InputEvent;
import java.awt.Robot;
-import javax.swing.JFrame;
-import javax.swing.SwingUtilities;
public class UnfocusableMaximizedFrameResizablity {
private static Frame frame;
- private static JFrame jframe;
private static Robot robot;
private static boolean isProgInterruption = false;
private static Thread mainThread = null;
@@ -55,65 +52,13 @@
return;
}
- //Case 1: Setting frame resizable to true followed by focusable to false
- frame = createFrame("Resizable Unfocusable frame");
- frame.setResizable(true);
- frame.setFocusableWindowState(false);
- tryToResizeFrame(frame);
-
- //Case 2: Setting frame focusable to false followed by resizable to true
- frame = createFrame("Unfocusable Resizable frame");
- frame.setFocusableWindowState(false);
- frame.setResizable(true);
- tryToResizeFrame(frame);
-
- //Case 3: Testing JFrame fullscreen behaviour only on Mac OS
- if (System.getProperty("os.name").toLowerCase().startsWith("mac")) {
- SwingUtilities.invokeAndWait(new Runnable() {
-
- Override
- public void run() {
- jframe = createJFrame("Unfocusable Resizable JFrame");
- jframe.setFocusableWindowState(false);
- jframe.setResizable(true);
- Object prop1 = jframe.getRootPane().getClientProperty("apple.awt.fullscreenable");
- jframe.setVisible(false);
- jframe.setVisible(true);
- Object prop2 = jframe.getRootPane().getClientProperty("apple.awt.fullscreenable");
-
- if((prop1 != null && prop2 != null) && (!prop1.equals(prop2))) {
- jframe.dispose();
- cleanup();
- throw new RuntimeException("Non-focusable resizable JFrame is fullscreenable!!");
- }
- }
- });
- }
-
- cleanup();
- }
-
- private static JFrame createJFrame(String title) {
- JFrame jframe = new JFrame(title);
- jframe.setMaximizedBounds(new Rectangle(0, 0, 300, 300));
- jframe.setSize(200, 200);
- jframe.setVisible(true);
- jframe.setExtendedState(Frame.MAXIMIZED_BOTH);
-
- return jframe;
- }
-
- private static Frame createFrame(String title) {
- Frame frame = new Frame(title);
+ frame = new Frame("Unfocusable frame");
frame.setMaximizedBounds(new Rectangle(0, 0, 300, 300));
frame.setSize(200, 200);
frame.setVisible(true);
frame.setExtendedState(Frame.MAXIMIZED_BOTH);
+ frame.setFocusableWindowState(false);
- return frame;
- }
-
- private static void tryToResizeFrame(Frame frame) {
try {
robot = new Robot();
} catch (AWTException e) {
@@ -144,11 +89,11 @@
cleanup();
throw new RuntimeException("The maximized unfocusable frame can be resized.");
}
-
- frame.dispose();
+ cleanup();
}
private static void cleanup() {
+ frame.dispose();
isProgInterruption = true;
mainThread.interrupt();
}
--- a/test/jdk/java/lang/ProcessBuilder/Basic.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/java/lang/ProcessBuilder/Basic.java Thu Aug 23 11:09:16 2018 -0400
@@ -2421,6 +2421,7 @@
public void run() {
try {
aboutToWaitFor.countDown();
+ Thread.currentThread().interrupt();
boolean result = p.waitFor(30L * 1000L, TimeUnit.MILLISECONDS);
fail("waitFor() wasn't interrupted, its return value was: " + result);
} catch (InterruptedException success) {
@@ -2430,7 +2431,38 @@
thread.start();
aboutToWaitFor.await();
- Thread.sleep(1000);
+ thread.interrupt();
+ thread.join(10L * 1000L);
+ check(millisElapsedSince(start) < 10L * 1000L);
+ check(!thread.isAlive());
+ p.destroy();
+ } catch (Throwable t) { unexpected(t); }
+
+ //----------------------------------------------------------------
+ // Check that Process.waitFor(Long.MAX_VALUE, TimeUnit.MILLISECONDS)
+ // interrupt works as expected, if interrupted while waiting.
+ //----------------------------------------------------------------
+ try {
+ List<String> childArgs = new ArrayList<String>(javaChildArgs);
+ childArgs.add("sleep");
+ final Process p = new ProcessBuilder(childArgs).start();
+ final long start = System.nanoTime();
+ final CountDownLatch aboutToWaitFor = new CountDownLatch(1);
+
+ final Thread thread = new Thread() {
+ public void run() {
+ try {
+ aboutToWaitFor.countDown();
+ Thread.currentThread().interrupt();
+ boolean result = p.waitFor(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
+ fail("waitFor() wasn't interrupted, its return value was: " + result);
+ } catch (InterruptedException success) {
+ } catch (Throwable t) { unexpected(t); }
+ }
+ };
+
+ thread.start();
+ aboutToWaitFor.await();
thread.interrupt();
thread.join(10L * 1000L);
check(millisElapsedSince(start) < 10L * 1000L);
--- a/test/jdk/java/net/httpclient/CookieHeaderTest.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/java/net/httpclient/CookieHeaderTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -35,6 +35,7 @@
* @build Http2TestServer
* @build jdk.testlibrary.SimpleSSLContext
* @run testng/othervm
+ * -Djdk.tls.acknowledgeCloseNotify=true
* -Djdk.httpclient.HttpClient.log=trace,headers,requests
* CookieHeaderTest
*/
--- a/test/jdk/java/net/httpclient/EncodedCharsInURI.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/java/net/httpclient/EncodedCharsInURI.java Thu Aug 23 11:09:16 2018 -0400
@@ -33,6 +33,7 @@
* java.net.http/jdk.internal.net.http.frame
* java.net.http/jdk.internal.net.http.hpack
* @run testng/othervm
+ * -Djdk.tls.acknowledgeCloseNotify=true
* -Djdk.internal.httpclient.debug=true
* -Djdk.httpclient.HttpClient.log=headers,errors EncodedCharsInURI
*/
--- a/test/jdk/java/net/httpclient/ServerCloseTest.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/java/net/httpclient/ServerCloseTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -31,7 +31,7 @@
* java.net.http/jdk.internal.net.http.common
* java.net.http/jdk.internal.net.http.frame
* java.net.http/jdk.internal.net.http.hpack
- * @run testng/othervm ServerCloseTest
+ * @run testng/othervm -Djdk.tls.acknowledgeCloseNotify=true ServerCloseTest
*/
//* -Djdk.internal.httpclient.debug=true
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/UnknownBodyLengthTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.URI;
+import java.net.SocketTimeoutException;
+import java.time.Duration;
+import javax.net.ssl.SSLServerSocketFactory;
+import javax.net.ServerSocketFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLParameters;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import jdk.testlibrary.SimpleSSLContext;
+
+/**
+ * @test
+ * @bug 8207966
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.SimpleSSLContext
+ * @run main/othervm -Djdk.tls.acknowledgeCloseNotify=true UnknownBodyLengthTest plain false
+ * @run main/othervm -Djdk.tls.acknowledgeCloseNotify=true UnknownBodyLengthTest SSL false
+ * @run main/othervm -Djdk.tls.acknowledgeCloseNotify=true UnknownBodyLengthTest plain true
+ * @run main/othervm -Djdk.tls.acknowledgeCloseNotify=true UnknownBodyLengthTest SSL true
+ */
+
+public class UnknownBodyLengthTest {
+ static final byte[] BUF = new byte[32 * 10234 + 2];
+
+ volatile SSLContext ctx;
+ volatile ServerSocketFactory factory;
+ volatile String clientURL;
+ volatile int port;
+ final ServerSocket ss;
+
+ UnknownBodyLengthTest(boolean useSSL) throws Exception {
+ ctx = new SimpleSSLContext().get();
+ SSLContext.setDefault(ctx);
+ factory = useSSL ? SSLServerSocketFactory.getDefault()
+ : ServerSocketFactory.getDefault();
+ ss = factory.createServerSocket();
+ ss.setReuseAddress(true);
+ ss.bind(new InetSocketAddress("127.0.0.1", 0));
+ System.out.println("ServerSocket = " + ss.getClass() + " " + ss);
+ port = ss.getLocalPort();
+ clientURL = (useSSL ? "https" : "http") + "://localhost:"
+ + Integer.toString(port) + "/test";
+ }
+
+ static void fillBuf(byte[] buf) {
+ for (int i=0; i<buf.length; i++)
+ buf[i] = (byte)i;
+ }
+
+ static void checkBuf(byte[] buf) {
+ if (buf.length != BUF.length)
+ throw new RuntimeException("buffer lengths not the same");
+ for (int i=0; i<buf.length; i++)
+ if (buf[i] != BUF[i])
+ throw new RuntimeException("error at position " + i);
+ }
+
+ void server(final boolean withContentLength) {
+ fillBuf(BUF);
+ try {
+ Socket s = ss.accept();
+ s.setTcpNoDelay(true);
+ s.setSoLinger(true, 1);
+ System.out.println("Accepted: "+s.getRemoteSocketAddress());
+ System.out.println("Accepted: "+s);
+ OutputStream os = s.getOutputStream();
+ InputStream is = s.getInputStream();
+ boolean done = false;
+ byte[] buf = new byte[1024];
+ String rsp = "";
+ while (!done) {
+ int c = is.read(buf);
+ if (c < 0) break;
+ String s1 = new String(buf, 0, c, "ISO-8859-1");
+ rsp += s1;
+ done = rsp.endsWith("!#!#");
+ }
+ String r = "HTTP/1.0 200 OK\r\nConnection: close\r\nContent-Type:" +
+ " text/xml; charset=UTF-8\r\n";
+ os.write(r.getBytes());
+ String chdr = "Content-Length: " + Integer.toString(BUF.length) +
+ "\r\n";
+ System.out.println(chdr);
+ if(withContentLength)
+ os.write(chdr.getBytes());
+ os.write("\r\n".getBytes());
+ os.write(BUF);
+ if (is.available() > 0)
+ is.read(buf);
+ os.flush();
+ os.close();
+ s.shutdownOutput();
+ s.close();
+ } catch(final Throwable t) {
+ t.printStackTrace();
+ } finally {
+ try {ss.close(); } catch (Exception e) {}
+ }
+ }
+
+ void client(boolean useSSL) throws Exception {
+ SSLContext ctx = SSLContext.getDefault();
+ HttpClient.Builder clientB = HttpClient.newBuilder()
+ .version(HttpClient.Version.HTTP_2);
+ if (useSSL) {
+ clientB = clientB.sslContext(ctx)
+ .sslParameters(ctx.getSupportedSSLParameters());
+ }
+ final HttpClient client = clientB.build();
+
+ System.out.println("URL: " + clientURL);
+ final HttpResponse<byte[]> response = client
+ .send(HttpRequest
+ .newBuilder(new URI(clientURL))
+ .timeout(Duration.ofMillis(120_000))
+ .POST(HttpRequest.BodyPublishers.ofString("body!#!#"))
+ .build(), HttpResponse.BodyHandlers.ofByteArray());
+
+ System.out.println("Received reply: " + response.statusCode());
+ byte[] bb = response.body();
+ checkBuf(bb);
+ }
+
+ public static void main(final String[] args) throws Exception {
+ boolean ssl = args[0].equals("SSL");
+ boolean fixedlen = args[1].equals("true");
+ UnknownBodyLengthTest test = new UnknownBodyLengthTest(ssl);
+ test.run(ssl, fixedlen);
+ }
+
+ public void run(boolean ssl, boolean fixedlen) throws Exception {
+ new Thread(()->server(fixedlen)).start();
+ client(ssl);
+ }
+}
--- a/test/jdk/java/nio/file/Files/ReadWriteString.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/java/nio/file/Files/ReadWriteString.java Thu Aug 23 11:09:16 2018 -0400
@@ -35,6 +35,7 @@
import java.nio.file.Paths;
import static java.nio.file.StandardOpenOption.APPEND;
import static java.nio.file.StandardOpenOption.CREATE;
+import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.Callable;
import static org.testng.Assert.assertTrue;
@@ -45,7 +46,7 @@
import org.testng.annotations.Test;
/* @test
- * @bug 8201276 8205058
+ * @bug 8201276 8205058 8209576
* @build ReadWriteString PassThroughFileSystem
* @run testng ReadWriteString
* @summary Unit test for methods for Files readString and write methods.
@@ -55,8 +56,10 @@
public class ReadWriteString {
// data for text files
- private static final String EN_STRING = "The quick brown fox jumps over the lazy dog";
+ final String TEXT_UNICODE = "\u201CHello\u201D";
+ final String TEXT_ASCII = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\n abcdefghijklmnopqrstuvwxyz\n 1234567890\n";
private static final String JA_STRING = "\u65e5\u672c\u8a9e\u6587\u5b57\u5217";
+
// malformed input: a high surrogate without the low surrogate
static char[] illChars = {
'\u00fa', '\ud800'
@@ -80,9 +83,8 @@
}
}
- // file used by most tests
- private Path tmpfile;
-
+ // file used by testReadWrite, testReadString and testWriteString
+ private Path[] testFiles = new Path[3];
/*
* DataProvider for malformed write test. Provides the following fields:
@@ -112,14 +114,48 @@
};
}
+ /*
+ * DataProvider for writeString test
+ * Writes the data using both the existing and new method and compares the results.
+ */
+ @DataProvider(name = "testWriteString")
+ public Object[][] getWriteString() throws IOException {
+
+ return new Object[][]{
+ {testFiles[1], testFiles[2], TEXT_ASCII, US_ASCII, null},
+ {testFiles[1], testFiles[2], TEXT_ASCII, US_ASCII, US_ASCII},
+ {testFiles[1], testFiles[2], TEXT_UNICODE, UTF_8, null},
+ {testFiles[1], testFiles[2], TEXT_UNICODE, UTF_8, UTF_8}
+ };
+ }
+
+ /*
+ * DataProvider for readString test
+ * Reads the file using both the existing and new method and compares the results.
+ */
+ @DataProvider(name = "testReadString")
+ public Object[][] getReadString() throws IOException {
+ Path path = Files.createTempFile("readString_file1", null);
+ return new Object[][]{
+ {testFiles[1], TEXT_ASCII, US_ASCII, US_ASCII},
+ {testFiles[1], TEXT_ASCII, US_ASCII, UTF_8},
+ {testFiles[1], TEXT_UNICODE, UTF_8, null},
+ {testFiles[1], TEXT_UNICODE, UTF_8, UTF_8}
+ };
+ }
+
@BeforeClass
void setup() throws IOException {
- tmpfile = Files.createTempFile("readWriteString", null);
+ testFiles[0] = Files.createTempFile("readWriteString", null);
+ testFiles[1] = Files.createTempFile("writeString_file1", null);
+ testFiles[2] = Files.createTempFile("writeString_file2", null);
}
@AfterClass
void cleanup() throws IOException {
- Files.deleteIfExists(tmpfile);
+ for (Path path : testFiles) {
+ Files.deleteIfExists(path);
+ }
}
/**
@@ -162,6 +198,42 @@
}
/**
+ * Verifies fix for @bug 8209576 that the writeString method converts the
+ * bytes properly.
+ * This method compares the results written by the existing write method and
+ * the writeString method added since 11.
+ */
+ @Test(dataProvider = "testWriteString")
+ public void testWriteString(Path path, Path path2, String text, Charset cs, Charset cs2) throws IOException {
+ Files.write(path, text.getBytes(cs));
+
+ // writeString @since 11
+ if (cs2 == null) {
+ Files.writeString(path2, text);
+ } else {
+ Files.writeString(path2, text, cs2);
+ }
+ byte[] bytes = Files.readAllBytes(path);
+ byte[] bytes2 = Files.readAllBytes(path2);
+ assertTrue((Arrays.compare(bytes, bytes2) == 0), "The bytes should be the same");
+ }
+
+ /**
+ * Verifies that the readString method added since 11 behaves the same as
+ * constructing a string from the existing readAllBytes method.
+ */
+ @Test(dataProvider = "testReadString")
+ public void testReadString(Path path, String text, Charset cs, Charset cs2) throws IOException {
+ Files.write(path, text.getBytes(cs));
+ String str = new String(Files.readAllBytes(path), cs);
+
+ // readString @since 11
+ String str2 = (cs2 == null) ? Files.readString(path) :
+ Files.readString(path, cs2);
+ assertTrue((str.equals(str2)), "The strings should be the same");
+ }
+
+ /**
* Verifies that IOException is thrown (as specified) when giving a malformed
* string input.
*
@@ -218,20 +290,20 @@
String str = generateString(size);
Path result;
if (cs == null) {
- result = Files.writeString(tmpfile, str);
+ result = Files.writeString(testFiles[0], str);
} else {
- result = Files.writeString(tmpfile, str, cs);
+ result = Files.writeString(testFiles[0], str, cs);
}
//System.out.println(result.toUri().toASCIIString());
- assertTrue(result == tmpfile);
+ assertTrue(result == testFiles[0]);
if (append) {
if (cs == null) {
- Files.writeString(tmpfile, str, APPEND);
+ Files.writeString(testFiles[0], str, APPEND);
} else {
- Files.writeString(tmpfile, str, cs, APPEND);
+ Files.writeString(testFiles[0], str, cs, APPEND);
}
- assertTrue(Files.size(tmpfile) == size * 2);
+ assertTrue(Files.size(testFiles[0]) == size * 2);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/text/Format/DateFormat/Bug8209047.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * 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 8209047
+ * @modules jdk.localedata
+ * @summary Check that DateFormat's getDateInstance, getTimeInstance and getDateTimeInstance works with all locales.
+ */
+import java.text.DateFormat;
+import java.util.Arrays;
+import java.util.Locale;
+import java.util.Set;
+
+public class Bug8209047 {
+
+ public static void main(String[] args) {
+ Set<Integer> styles = Set.of(DateFormat.FULL, DateFormat.LONG, DateFormat.MEDIUM, DateFormat.SHORT);
+ Arrays.stream(Locale.getAvailableLocales()).forEach(locale -> {
+ styles.forEach(style -> {
+ try {
+ DateFormat.getDateInstance(style, locale);
+ DateFormat.getTimeInstance(style, locale);
+ DateFormat.getDateTimeInstance(style, style, locale);
+ } catch (IllegalArgumentException ex) {
+ throw new RuntimeException("Getting DateFormat instance failed for locale " + locale, ex);
+ }
+ });
+ });
+ }
+}
--- a/test/jdk/javax/net/ssl/ALPN/SSLEngineAlpnTest.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/javax/net/ssl/ALPN/SSLEngineAlpnTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -191,6 +191,7 @@
if (debug) {
System.setProperty("javax.net.debug", "all");
}
+ System.setProperty("jdk.tls.acknowledgeCloseNotify", "true");
System.out.println("Test args: " + Arrays.toString(args));
// Validate parameters
@@ -358,6 +359,7 @@
log("\tClosing clientEngine's *OUTBOUND*...");
clientEngine.closeOutbound();
+ // serverEngine.closeOutbound();
dataDone = true;
}
}
--- a/test/jdk/javax/net/ssl/SSLEngine/Arrays.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/javax/net/ssl/SSLEngine/Arrays.java Thu Aug 23 11:09:16 2018 -0400
@@ -25,7 +25,14 @@
* @test
* @bug 5019096
* @summary Add scatter/gather APIs for SSLEngine
- *
+ * @run main/othervm Arrays SSL
+ * @run main/othervm Arrays TLS
+ * @run main/othervm Arrays SSLv3
+ * @run main/othervm Arrays TLSv1
+ * @run main/othervm Arrays TLSv1.1
+ * @run main/othervm Arrays TLSv1.2
+ * @run main/othervm Arrays TLSv1.3
+ * @run main/othervm -Djdk.tls.acknowledgeCloseNotify=true Arrays TLSv1.3
*/
import javax.net.ssl.*;
@@ -37,6 +44,8 @@
public class Arrays {
private static boolean debug = false;
+ private static boolean acknowledgeCloseNotify =
+ "true".equals(System.getProperty("jdk.tls.acknowledgeCloseNotify"));
private SSLContext sslc;
private SSLEngine ssle1; // client
@@ -131,11 +140,13 @@
for (int i = 0; i < appOutArray1.length; i++) {
if (appOutArray1[i].remaining() != 0) {
+ log("1st out not done");
done = false;
}
}
if (appOut2.remaining() != 0) {
+ log("2nd out not done");
done = false;
}
@@ -145,6 +156,19 @@
appOutArray1[i].rewind();
}
ssle1.closeOutbound();
+ String protocol = ssle2.getSession().getProtocol();
+ if (!acknowledgeCloseNotify) {
+ switch (ssle2.getSession().getProtocol()) {
+ case "SSLv3":
+ case "TLSv1":
+ case "TLSv1.1":
+ case "TLSv1.2":
+ break;
+ default: // TLSv1.3
+ // TLS 1.3, half-close only.
+ ssle2.closeOutbound();
+ }
+ }
dataDone = true;
}
}
@@ -155,7 +179,9 @@
checkTransfer(appInArray1, appOut2);
}
+ private static String contextVersion;
public static void main(String args[]) throws Exception {
+ contextVersion = args[0];
Arrays test;
@@ -165,7 +191,7 @@
test.runTest();
- System.out.println("Test Passed.");
+ System.err.println("Test Passed.");
}
/*
@@ -198,7 +224,7 @@
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(ts);
- SSLContext sslCtx = SSLContext.getInstance("TLS");
+ SSLContext sslCtx = SSLContext.getInstance(contextVersion);
sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
@@ -288,7 +314,7 @@
private static void log(String str) {
if (debug) {
- System.out.println(str);
+ System.err.println(str);
}
}
}
--- a/test/jdk/javax/net/ssl/SSLEngine/ExtendedKeyEngine.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/javax/net/ssl/SSLEngine/ExtendedKeyEngine.java Thu Aug 23 11:09:16 2018 -0400
@@ -26,6 +26,8 @@
* @bug 4981697
* @summary Rework the X509KeyManager to avoid incompatibility issues
* @author Brad R. Wetmore
+ *
+ * @run main/othervm -Djdk.tls.acknowledgeCloseNotify=true ExtendedKeyEngine
*/
import javax.net.ssl.*;
--- a/test/jdk/javax/net/ssl/TLSCommon/SSLEngineTestCase.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/javax/net/ssl/TLSCommon/SSLEngineTestCase.java Thu Aug 23 11:09:16 2018 -0400
@@ -936,6 +936,7 @@
case SUPPORTED_NON_KRB_NON_SHA_CIPHERS:
case SUPPORTED_KRB_CIPHERS:
case ENABLED_NON_KRB_NOT_ANON_CIPHERS:
+ case TLS13_CIPHERS:
if (error != null) {
System.out.println("Test Failed: " + cs);
System.err.println("Test Exception for " + cs);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/net/ssl/TLSv12/TLSEnginesClosureTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * 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 8207009
+ * @summary Testing TLS engines closing using each of the supported
+ * cipher suites.
+ * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
+ * @modules java.security.jgss
+ * jdk.security.auth
+ * java.security.jgss/sun.security.jgss.krb5
+ * java.security.jgss/sun.security.krb5:+open
+ * java.security.jgss/sun.security.krb5.internal:+open
+ * java.security.jgss/sun.security.krb5.internal.ccache
+ * java.security.jgss/sun.security.krb5.internal.crypto
+ * java.security.jgss/sun.security.krb5.internal.ktab
+ * java.base/sun.security.util
+ * @run main/othervm -Dtest.security.protocol=TLSv1.2
+ * -Dtest.mode=norm TLSEnginesClosureTest
+ * @run main/othervm -Dtest.security.protocol=TLSv1.2
+ * -Dtest.mode=norm_sni TLSEnginesClosureTest
+ * @run main/othervm -Dtest.security.protocol=TLSv1.2
+ * -Dtest.mode=krb TLSEnginesClosureTest
+ */
+
+/**
+ * Testing TLS engines closing using each of the supported cipher suites.
+ */
+public class TLSEnginesClosureTest {
+ public static void main(String[] args) {
+ EnginesClosureTest.main(args);
+ }
+}
--- a/test/jdk/javax/swing/JRadioButton/8033699/bug8033699.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/javax/swing/JRadioButton/8033699/bug8033699.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +26,7 @@
* @key headful
* @library ../../regtesthelpers
* @build Util
- * @bug 8033699 8154043 8167160
+ * @bug 8033699 8154043 8167160 8208640
* @summary Incorrect radio button behavior when pressing tab key
* @run main bug8033699
*/
@@ -59,12 +59,9 @@
private static JRadioButton radioBtnSingle;
public static void main(String args[]) throws Throwable {
- SwingUtilities.invokeAndWait(new Runnable() {
- @Override
- public void run() {
+ SwingUtilities.invokeAndWait(() -> {
changeLAF();
createAndShowGUI();
- }
});
robot = new Robot();
@@ -96,19 +93,14 @@
// down key circle back to first button in grouped radio button
runTest8();
- SwingUtilities.invokeAndWait(new Runnable() {
- @Override
- public void run() {
- mainFrame.dispose();
- }
- });
+ SwingUtilities.invokeAndWait(() -> mainFrame.dispose());
}
private static void changeLAF() {
String currentLAF = UIManager.getLookAndFeel().toString();
System.out.println(currentLAF);
currentLAF = currentLAF.toLowerCase();
- if (currentLAF.contains("aqua") || currentLAF.contains("nimbus")) {
+ if (currentLAF.contains("nimbus")) {
try {
UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
} catch (Exception ex) {
@@ -167,13 +159,10 @@
hitKey(robot, KeyEvent.VK_TAB);
hitKey(robot, KeyEvent.VK_TAB);
- SwingUtilities.invokeAndWait(new Runnable() {
- @Override
- public void run() {
- if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != radioBtnSingle) {
- System.out.println("Radio Button Group Go To Next Component through Tab Key failed");
- throw new RuntimeException("Focus is not on Radio Button Single as Expected");
- }
+ SwingUtilities.invokeAndWait(() -> {
+ if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != radioBtnSingle) {
+ System.out.println("Radio Button Group Go To Next Component through Tab Key failed");
+ throw new RuntimeException("Focus is not on Radio Button Single as Expected");
}
});
}
@@ -181,13 +170,10 @@
// Non-Grouped Radio button as a single component when traversing through tab key
private static void runTest2() throws Exception {
hitKey(robot, KeyEvent.VK_TAB);
- SwingUtilities.invokeAndWait(new Runnable() {
- @Override
- public void run() {
- if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != btnEnd) {
- System.out.println("Non Grouped Radio Button Go To Next Component through Tab Key failed");
- throw new RuntimeException("Focus is not on Button End as Expected");
- }
+ SwingUtilities.invokeAndWait(() -> {
+ if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != btnEnd) {
+ System.out.println("Non Grouped Radio Button Go To Next Component through Tab Key failed");
+ throw new RuntimeException("Focus is not on Button End as Expected");
}
});
}
@@ -197,13 +183,10 @@
hitKey(robot, KeyEvent.VK_SHIFT, KeyEvent.VK_TAB);
hitKey(robot, KeyEvent.VK_SHIFT, KeyEvent.VK_TAB);
hitKey(robot, KeyEvent.VK_SHIFT, KeyEvent.VK_TAB);
- SwingUtilities.invokeAndWait(new Runnable() {
- @Override
- public void run() {
- if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != radioBtn1) {
- System.out.println("Radio button Group/Non Grouped Radio Button SHIFT-Tab Key Test failed");
- throw new RuntimeException("Focus is not on Radio Button A as Expected");
- }
+ SwingUtilities.invokeAndWait(() -> {
+ if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != radioBtn1) {
+ System.out.println("Radio button Group/Non Grouped Radio Button SHIFT-Tab Key Test failed");
+ throw new RuntimeException("Focus is not on Radio Button A as Expected");
}
});
}
@@ -212,13 +195,10 @@
private static void runTest4() throws Exception {
hitKey(robot, KeyEvent.VK_DOWN);
hitKey(robot, KeyEvent.VK_RIGHT);
- SwingUtilities.invokeAndWait(new Runnable() {
- @Override
- public void run() {
- if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != radioBtn3) {
- System.out.println("Radio button Group UP/LEFT Arrow Key Move Focus Failed");
- throw new RuntimeException("Focus is not on Radio Button C as Expected");
- }
+ SwingUtilities.invokeAndWait(() -> {
+ if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != radioBtn3) {
+ System.out.println("Radio button Group UP/LEFT Arrow Key Move Focus Failed");
+ throw new RuntimeException("Focus is not on Radio Button C as Expected");
}
});
}
@@ -226,13 +206,10 @@
private static void runTest5() throws Exception {
hitKey(robot, KeyEvent.VK_UP);
hitKey(robot, KeyEvent.VK_LEFT);
- SwingUtilities.invokeAndWait(new Runnable() {
- @Override
- public void run() {
- if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != radioBtn1) {
- System.out.println("Radio button Group Left/Up Arrow Key Move Focus Failed");
- throw new RuntimeException("Focus is not on Radio Button A as Expected");
- }
+ SwingUtilities.invokeAndWait(() -> {
+ if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != radioBtn1) {
+ System.out.println("Radio button Group Left/Up Arrow Key Move Focus Failed");
+ throw new RuntimeException("Focus is not on Radio Button A as Expected");
}
});
}
@@ -240,39 +217,30 @@
private static void runTest6() throws Exception {
hitKey(robot, KeyEvent.VK_UP);
hitKey(robot, KeyEvent.VK_UP);
- SwingUtilities.invokeAndWait(new Runnable() {
- @Override
- public void run() {
- if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != radioBtn2) {
- System.out.println("Radio button Group Circle Back To First Button Test");
- throw new RuntimeException("Focus is not on Radio Button B as Expected");
- }
+ SwingUtilities.invokeAndWait(() -> {
+ if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != radioBtn2) {
+ System.out.println("Radio button Group Circle Back To First Button Test");
+ throw new RuntimeException("Focus is not on Radio Button B as Expected");
}
});
}
private static void runTest7() throws Exception {
hitKey(robot, KeyEvent.VK_TAB);
- SwingUtilities.invokeAndWait(new Runnable() {
- @Override
- public void run() {
- if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != btnMiddle) {
- System.out.println("Separate Component added in button group layout");
- throw new RuntimeException("Focus is not on Middle Button as Expected");
- }
+ SwingUtilities.invokeAndWait(() -> {
+ if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != btnMiddle) {
+ System.out.println("Separate Component added in button group layout");
+ throw new RuntimeException("Focus is not on Middle Button as Expected");
}
});
}
private static void runTest8() throws Exception {
hitKey(robot, KeyEvent.VK_TAB);
- SwingUtilities.invokeAndWait(new Runnable() {
- @Override
- public void run() {
- if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != radioBtnSingle) {
- System.out.println("Separate Component added in button group layout");
- throw new RuntimeException("Focus is not on Radio Button Single as Expected");
- }
+ SwingUtilities.invokeAndWait(() -> {
+ if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != radioBtnSingle) {
+ System.out.println("Separate Component added in button group layout");
+ throw new RuntimeException("Focus is not on Radio Button Single as Expected");
}
});
}
--- a/test/jdk/jdk/internal/jrtfs/remote/RemoteRuntimeImageTest.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/jdk/internal/jrtfs/remote/RemoteRuntimeImageTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,6 @@
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
-import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -55,7 +54,7 @@
return;
}
- Path jdk8Path = getJdk8Path(jdk8Home);
+ Path jdk8Path = Paths.get(jdk8Home);
if (!isJdk8(jdk8Path)) {
System.err.println("This test is only for JDK 8. Skip testing");
return;
@@ -102,16 +101,14 @@
}
}
- private static Path getJdk8Path(String jdk8Home) {
- Path jdk8Path = Paths.get(jdk8Home);
- // It is possible to point to the path of java executable by ${JT_JAVA}
- return Files.isDirectory(jdk8Path)? jdk8Path : jdk8Path.getParent().getParent();
- }
-
- private static boolean isJdk8(Path jdk8Home) throws FileNotFoundException, IOException {
- File file = jdk8Home.resolve("release").toFile();
+ private static boolean isJdk8(Path jdk8HomePath) throws IOException {
+ File releaseFile = jdk8HomePath.resolve("release").toFile();
+ if (!releaseFile.exists()) {
+ throw new RuntimeException(releaseFile.getPath() +
+ " doesn't exist");
+ }
Properties props = new Properties();
- try (FileInputStream in = new FileInputStream(file)) {
+ try (FileInputStream in = new FileInputStream(releaseFile)) {
props.load(in);
}
--- a/test/jdk/jdk/jfr/event/runtime/TestClassLoaderStatsEvent.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/jdk/jfr/event/runtime/TestClassLoaderStatsEvent.java Thu Aug 23 11:09:16 2018 -0400
@@ -76,9 +76,9 @@
Events.assertField(event, "classCount").equal(1L);
Events.assertField(event, "chunkSize").above(1L);
Events.assertField(event, "blockSize").above(1L);
- Events.assertField(event, "anonymousClassCount").equal(1L);
- Events.assertField(event, "anonymousChunkSize").above(1L);
- Events.assertField(event, "anonymousBlockSize").above(1L);
+ Events.assertField(event, "unsafeAnonymousClassCount").equal(1L);
+ Events.assertField(event, "unsafeAnonymousChunkSize").above(1L);
+ Events.assertField(event, "unsafeAnonymousBlockSize").above(1L);
isAnyFound = true;
}
}
--- a/test/jdk/lib/security/cacerts/VerifyCACerts.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/lib/security/cacerts/VerifyCACerts.java Thu Aug 23 11:09:16 2018 -0400
@@ -24,7 +24,8 @@
/**
* @test
- * @bug 8189131 8198240 8191844 8189949 8191031 8196141 8204923 8195774 8199779
+ * @bug 8189131 8198240 8191844 8189949 8191031 8196141 8204923 8195774 8199779 8209452
+ * 8209506
* @summary Check root CA entries in cacerts file
*/
import java.io.File;
@@ -41,7 +42,7 @@
+ File.separator + "security" + File.separator + "cacerts";
// The numbers of certs now.
- private static final int COUNT = 90;
+ private static final int COUNT = 92;
// map of cert alias to SHA-256 fingerprint
private static final Map<String, String> FINGERPRINT_MAP
@@ -227,10 +228,15 @@
"CB:B5:22:D7:B7:F1:27:AD:6A:01:13:86:5B:DF:1C:D4:10:2E:7D:07:59:AF:63:5A:7C:F4:72:0D:C9:63:C5:3B");
put("globalsigneccrootcar5 [jdk]",
"17:9F:BC:14:8A:3D:D0:0F:D2:4E:A1:34:58:CC:43:BF:A7:F5:9C:81:82:D7:83:A5:13:F6:EB:EC:10:0C:89:24");
+ put("globalsigneccrootcar4 [jdk]",
+ "BE:C9:49:11:C2:95:56:76:DB:6C:0A:55:09:86:D7:6E:3B:A0:05:66:7C:44:2C:97:62:B4:FB:B7:73:DE:22:8C");
+ put("globalsignr2ca [jdk]",
+ "CA:42:DD:41:74:5F:D0:B8:1E:B9:02:36:2C:F9:D8:BF:71:9D:A1:BD:1B:1E:FC:94:6F:5B:4C:99:F4:2C:1B:9E");
}
};
// Exception list to 90 days expiry policy
+ // No error will be reported if certificate in this list expires
private static final HashSet<String> EXPIRY_EXC_ENTRIES
= new HashSet<String>(Arrays.asList(
"gtecybertrustglobalca [jdk]"
@@ -293,8 +299,10 @@
try {
cert.checkValidity();
} catch (CertificateExpiredException cee) {
- atLeastOneFailed = true;
- System.err.println("ERROR: cert is expired");
+ if (!EXPIRY_EXC_ENTRIES.contains(alias)) {
+ atLeastOneFailed = true;
+ System.err.println("ERROR: cert is expired");
+ }
} catch (CertificateNotYetValidException cne) {
atLeastOneFailed = true;
System.err.println("ERROR: cert is not yet valid");
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/Action.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/Action.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/ActionProducer.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/ActionProducer.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/Bundle.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/Bundle.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/BundleManager.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/BundleManager.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/CharBindingMap.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/CharBindingMap.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/ClassReference.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/ClassReference.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/ComponentChooser.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/ComponentChooser.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/ComponentIsNotFocusedException.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/ComponentIsNotFocusedException.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/ComponentIsNotVisibleException.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/ComponentIsNotVisibleException.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/ComponentSearcher.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/ComponentSearcher.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/DefaultCharBindingMap.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/DefaultCharBindingMap.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/DialogWaiter.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/DialogWaiter.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/EventDispatcher.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/EventDispatcher.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/EventTool.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/EventTool.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/FrameWaiter.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/FrameWaiter.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/JemmyException.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/JemmyException.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/JemmyInputException.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/JemmyInputException.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/JemmyProperties.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/JemmyProperties.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,10 +1,12 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
* 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.
+ * 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
@@ -39,6 +41,7 @@
import org.netbeans.jemmy.drivers.DriverInstaller;
import org.netbeans.jemmy.drivers.InputDriverInstaller;
import org.netbeans.jemmy.explorer.GUIBrowser;
+import org.netbeans.jemmy.util.Platform;
/**
*
@@ -809,7 +812,7 @@
getCurrentOutput().printStackTrace(e);
}
if (installer == null) {
- if (System.getProperty("os.name").startsWith("Mac OS X")) {
+ if (Platform.isOSX()) {
installer = new APIDriverInstaller((model & SHORTCUT_MODEL_MASK) != 0);
} else {
installer = new DefaultDriverInstaller((model & SHORTCUT_MODEL_MASK) != 0);
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/NoComponentUnderMouseException.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/NoComponentUnderMouseException.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/ObjectBrowser.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/ObjectBrowser.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/Outputable.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/Outputable.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/QueueTool.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/QueueTool.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/Scenario.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/Scenario.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/Test.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/Test.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/TestCompletedException.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/TestCompletedException.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/TestOut.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/TestOut.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/Timeout.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/Timeout.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/TimeoutExpiredException.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/TimeoutExpiredException.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/Timeoutable.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/Timeoutable.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/Timeouts.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/Timeouts.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/Waitable.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/Waitable.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/Waiter.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/Waiter.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/WindowWaiter.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/WindowWaiter.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/accessibility/AccessibilityChooser.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/accessibility/AccessibilityChooser.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/accessibility/AccessibleDescriptionChooser.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/accessibility/AccessibleDescriptionChooser.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/accessibility/AccessibleNameChooser.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/accessibility/AccessibleNameChooser.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/APIDriverInstaller.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/APIDriverInstaller.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,10 +1,12 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
* 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.
+ * 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
@@ -47,8 +49,8 @@
import org.netbeans.jemmy.drivers.text.SwingTextKeyboardDriver;
import org.netbeans.jemmy.drivers.trees.JTreeAPIDriver;
import org.netbeans.jemmy.drivers.windows.DefaultFrameDriver;
-import org.netbeans.jemmy.drivers.windows.DefaultInternalFrameDriver;
import org.netbeans.jemmy.drivers.windows.DefaultWindowDriver;
+import org.netbeans.jemmy.drivers.windows.InternalFrameAPIDriver;
/**
* Installs all necessary drivers for Jemmy operators except low-level drivers
@@ -119,9 +121,9 @@
new ChoiceDriver(),
new DefaultFrameDriver(),
new DefaultWindowDriver(),
- new DefaultInternalFrameDriver(),
- new DefaultInternalFrameDriver(),
- new DefaultInternalFrameDriver(),
+ new InternalFrameAPIDriver(),
+ new InternalFrameAPIDriver(),
+ new InternalFrameAPIDriver(),
new APIFocusDriver(),
new MouseFocusDriver(),
(shortcutEvents ? new QueueJMenuDriver() : new DefaultJMenuDriver()),
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/ArrayDriverInstaller.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/ArrayDriverInstaller.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/ButtonDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/ButtonDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/DefaultDriverInstaller.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/DefaultDriverInstaller.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/DescriptablePathChooser.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/DescriptablePathChooser.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/Driver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/Driver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/DriverInstaller.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/DriverInstaller.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/DriverManager.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/DriverManager.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/EditorDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/EditorDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/FocusDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/FocusDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/FrameDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/FrameDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/InputDriverInstaller.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/InputDriverInstaller.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/InternalFrameDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/InternalFrameDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/KeyDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/KeyDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/LightDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/LightDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/LightSupportiveDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/LightSupportiveDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/ListDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/ListDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/MenuDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/MenuDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/MouseDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/MouseDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/MultiSelListDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/MultiSelListDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/OrderedListDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/OrderedListDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/PathChooser.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/PathChooser.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/ScrollDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/ScrollDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/SupportiveDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/SupportiveDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/TableDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/TableDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/TextDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/TextDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/TreeDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/TreeDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/UnsupportedOperatorException.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/UnsupportedOperatorException.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/WindowDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/WindowDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/buttons/ButtonMouseDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/buttons/ButtonMouseDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/buttons/package-info.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/buttons/package-info.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/focus/APIFocusDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/focus/APIFocusDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/focus/MouseFocusDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/focus/MouseFocusDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/focus/package-info.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/focus/package-info.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/input/EventDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/input/EventDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/input/KeyEventDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/input/KeyEventDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/input/KeyRobotDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/input/KeyRobotDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/input/MouseEventDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/input/MouseEventDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/input/MouseRobotDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/input/MouseRobotDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/input/RobotDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/input/RobotDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/input/package-info.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/input/package-info.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/lists/ChoiceDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/lists/ChoiceDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/lists/JComboMouseDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/lists/JComboMouseDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/lists/JListMouseDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/lists/JListMouseDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/lists/JTabAPIDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/lists/JTabAPIDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/lists/JTabMouseDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/lists/JTabMouseDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/lists/JTableHeaderDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/lists/JTableHeaderDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/lists/ListAPIDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/lists/ListAPIDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/lists/ListKeyboardDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/lists/ListKeyboardDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/lists/package-info.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/lists/package-info.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/menus/APIJMenuDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/menus/APIJMenuDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/menus/AppleMenuDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/menus/AppleMenuDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/menus/DefaultJMenuDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/menus/DefaultJMenuDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/menus/QueueJMenuDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/menus/QueueJMenuDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/menus/package-info.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/menus/package-info.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/package-info.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/package-info.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/scrolling/AWTScrollDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/scrolling/AWTScrollDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/scrolling/AbstractScrollDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/scrolling/AbstractScrollDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/scrolling/JScrollBarAPIDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/scrolling/JScrollBarAPIDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/scrolling/JScrollBarDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/scrolling/JScrollBarDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/scrolling/JSliderAPIDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/scrolling/JSliderAPIDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/scrolling/JSliderDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/scrolling/JSliderDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/scrolling/JSpinnerDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/scrolling/JSpinnerDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/scrolling/JSplitPaneDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/scrolling/JSplitPaneDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/scrolling/KeyboardJSliderScrollDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/scrolling/KeyboardJSliderScrollDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/scrolling/ScrollAdjuster.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/scrolling/ScrollAdjuster.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/scrolling/ScrollPaneDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/scrolling/ScrollPaneDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/scrolling/ScrollbarDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/scrolling/ScrollbarDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/scrolling/package-info.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/scrolling/package-info.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/tables/JTableMouseDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/tables/JTableMouseDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/tables/package-info.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/tables/package-info.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/text/AWTTextAPIDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/text/AWTTextAPIDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/text/AWTTextKeyboardDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/text/AWTTextKeyboardDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/text/DownKey.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/text/DownKey.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/text/EndKey.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/text/EndKey.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/text/GoAndBackKey.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/text/GoAndBackKey.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/text/HomeKey.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/text/HomeKey.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/text/NavigationKey.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/text/NavigationKey.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/text/OffsetKey.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/text/OffsetKey.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/text/SwingTextAPIDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/text/SwingTextAPIDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/text/SwingTextKeyboardDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/text/SwingTextKeyboardDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/text/TextAPIDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/text/TextAPIDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/text/TextKeyboardDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/text/TextKeyboardDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/text/UpKey.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/text/UpKey.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/text/package-info.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/text/package-info.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/trees/JTreeAPIDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/trees/JTreeAPIDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/trees/JTreeMouseDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/trees/JTreeMouseDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/trees/package-info.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/trees/package-info.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/windows/DefaultFrameDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/windows/DefaultFrameDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/windows/DefaultInternalFrameDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/windows/DefaultInternalFrameDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/windows/DefaultWindowDriver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/windows/DefaultWindowDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/windows/InternalFrameAPIDriver.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * 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 org.netbeans.jemmy.drivers.windows;
+
+import java.awt.Component;
+
+import org.netbeans.jemmy.drivers.FrameDriver;
+import org.netbeans.jemmy.drivers.InternalFrameDriver;
+import org.netbeans.jemmy.drivers.LightSupportiveDriver;
+import org.netbeans.jemmy.drivers.WindowDriver;
+import org.netbeans.jemmy.operators.ComponentOperator;
+import org.netbeans.jemmy.operators.JInternalFrameOperator;
+
+/**
+ * InternalFrameDriver to do all actions using internal frame APIs.
+ *
+ * Note: There is no API to get title component, so this driver throws
+ * UnsupportedOperationException for all title component related APIs.
+ */
+public class InternalFrameAPIDriver extends LightSupportiveDriver
+ implements WindowDriver, FrameDriver, InternalFrameDriver {
+
+ public InternalFrameAPIDriver() {
+ super(new String[]{"org.netbeans.jemmy.operators.JInternalFrameOperator"});
+ }
+
+ @Override
+ public void activate(ComponentOperator oper) {
+ checkSupported(oper);
+ ((JInternalFrameOperator) oper).moveToFront();
+ ((JInternalFrameOperator) oper).setSelected(true);
+ }
+
+ @Override
+ public void maximize(ComponentOperator oper) {
+ checkSupported(oper);
+ if (!((JInternalFrameOperator) oper).isSelected()) {
+ activate(oper);
+ }
+ ((JInternalFrameOperator) oper).setMaximum(true);
+ }
+
+ @Override
+ public void demaximize(ComponentOperator oper) {
+ checkSupported(oper);
+ if (!((JInternalFrameOperator) oper).isSelected()) {
+ activate(oper);
+ }
+ ((JInternalFrameOperator) oper).setMaximum(false);
+ }
+
+ @Override
+ public void iconify(ComponentOperator oper) {
+ checkSupported(oper);
+ ((JInternalFrameOperator) oper).setIcon(true);
+ }
+
+ @Override
+ public void deiconify(ComponentOperator oper) {
+ checkSupported(oper);
+ ((JInternalFrameOperator) oper).setIcon(false);
+ }
+
+ @Override
+ public void requestClose(ComponentOperator oper) {
+ checkSupported(oper);
+ ((JInternalFrameOperator) oper).setClosed(true);
+ }
+
+ @Override
+ public void move(ComponentOperator oper, int x, int y) {
+ checkSupported(oper);
+ oper.setLocation(x, y);
+ }
+
+ @Override
+ public void resize(ComponentOperator oper, int width, int height) {
+ checkSupported(oper);
+ oper.setSize(width, height);
+ }
+
+ @Override
+ public Component getTitlePane(ComponentOperator oper) {
+ throw new UnsupportedOperationException(
+ "There is no way to get title pane of an internal frame.");
+ }
+
+ @Override
+ public void requestCloseAndThenHide(ComponentOperator oper) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void close(ComponentOperator oper) {
+ requestClose(oper);
+ }
+}
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/windows/package-info.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/windows/package-info.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/explorer/GUIBrowser.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/explorer/GUIBrowser.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/explorer/TrialListenerManager.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/explorer/TrialListenerManager.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/explorer/package-info.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/explorer/package-info.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/image/ColorImageComparator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/image/ColorImageComparator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/image/FileImageComparator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/image/FileImageComparator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/image/ImageComparator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/image/ImageComparator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/image/ImageFinder.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/image/ImageFinder.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/image/ImageLoader.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/image/ImageLoader.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/image/ImageSaver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/image/ImageSaver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/image/ImageTool.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/image/ImageTool.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/image/PNGImageLoader.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/image/PNGImageLoader.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/image/PNGImageSaver.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/image/PNGImageSaver.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/image/RoughImageComparator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/image/RoughImageComparator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/image/RoughImageFinder.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/image/RoughImageFinder.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/image/StrictImageComparator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/image/StrictImageComparator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/image/StrictImageFinder.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/image/StrictImageFinder.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/image/package-info.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/image/package-info.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/AbstractButtonOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/AbstractButtonOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/ButtonOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/ButtonOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/CheckboxOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/CheckboxOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/ChoiceOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/ChoiceOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/ComponentOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/ComponentOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/ContainerOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/ContainerOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/DialogOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/DialogOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/FrameOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/FrameOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JButtonOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JButtonOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JCheckBoxMenuItemOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JCheckBoxMenuItemOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JCheckBoxOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JCheckBoxOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JColorChooserOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JColorChooserOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JComboBoxOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JComboBoxOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JComponentOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JComponentOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JDialogOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JDialogOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JEditorPaneOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JEditorPaneOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,10 +1,12 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
* 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.
+ * 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
@@ -23,18 +25,27 @@
package org.netbeans.jemmy.operators;
import java.awt.Container;
+import java.awt.IllegalComponentStateException;
+import java.awt.Point;
+import java.awt.Rectangle;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Hashtable;
import javax.swing.JEditorPane;
+import javax.swing.JScrollPane;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
+import javax.swing.text.Document;
import javax.swing.text.EditorKit;
+import javax.swing.text.html.HTML;
+import javax.swing.text.html.HTMLDocument;
import org.netbeans.jemmy.ComponentChooser;
+import org.netbeans.jemmy.ComponentSearcher;
import org.netbeans.jemmy.TimeoutExpiredException;
+import org.netbeans.jemmy.util.EmptyVisualizer;
/**
* Class provides basic functions to operate with JEditorPane (selection,
@@ -293,6 +304,72 @@
return result;
}
+ /**
+ * Clicks on a named reference location
+ *
+ * @param reference the named location to click
+ */
+ public void clickOnReference(String reference) {
+ int expectedCaretPos = getCaretPositionOfReference(reference);
+ Rectangle viewBounds = modelToView(expectedCaretPos);
+ Point expectedCaretPosLoc = new Point(viewBounds.x, viewBounds.y);
+ //TODO Extend DefaultVisualizer to show a portion of component and use
+ // that in here
+ JScrollPane scroll = (JScrollPane) getContainer(
+ new JScrollPaneOperator.JScrollPaneFinder(
+ ComponentSearcher.getTrueChooser("JScrollPane")));
+ if (scroll != null) {
+ JScrollPaneOperator scroller = new JScrollPaneOperator(scroll);
+ scroller.copyEnvironment(this);
+ scroller.setVisualizer(new EmptyVisualizer());
+ scroller.scrollToComponentRectangle(getSource(),
+ (int) viewBounds.getX(), (int) viewBounds.getY(),
+ (int) viewBounds.getWidth(), (int) viewBounds.getHeight());
+ setCaretPosition(expectedCaretPos);
+ } else if (getVisibleRect().contains(expectedCaretPosLoc)) {
+ scrollToReference(reference);
+ } else {
+ throw new IllegalComponentStateException("Component doesn't "
+ + "contain JScrollPane and Reference is out of"
+ + " visible area");
+ }
+
+ waitStateOnQueue(comp -> expectedCaretPosLoc.equals(
+ ((JEditorPane)comp).getCaret().getMagicCaretPosition()));
+ waitCaretPosition(expectedCaretPos);
+ clickMouse(viewBounds.x, viewBounds.y, 1);
+ }
+
+ /**
+ * Gets the starting caret position of a named reference location
+ *
+ * @param reference the named location
+ * @return starting caret position of the named reference location
+ * @throws IllegalArgumentException if the named reference doesn't
+ * exist in the document
+ */
+ private int getCaretPositionOfReference(String reference)
+ throws IllegalArgumentException {
+ int pos = -1;
+ Document doc = getDocument();
+ if (doc instanceof HTMLDocument) {
+ HTMLDocument.Iterator iter =
+ ((HTMLDocument) doc).getIterator(HTML.Tag.A);
+ for (;iter.isValid();iter.next()) {
+ String nameAttr = (String) iter.getAttributes().
+ getAttribute(HTML.Attribute.NAME);
+ if (reference.equals(nameAttr)) {
+ pos = iter.getStartOffset();
+ }
+ }
+ }
+ if(pos ==-1) {
+ throw new IllegalArgumentException("Reference " + reference +
+ " doesn't exist in the document " + doc + ".");
+ }
+ return pos;
+ }
+
////////////////////////////////////////////////////////
//Mapping //
/**
@@ -455,6 +532,18 @@
});
}
+ /**
+ * Maps {@code JEditorPane.scrollToReference(String)} through queue
+ */
+ public void scrollToReference(String reference) {
+ runMapping(new MapVoidAction("scrollToReference") {
+ @Override
+ public void map() throws IOException {
+ ((JEditorPane) getSource()).scrollToReference(reference);
+ }
+ });
+ }
+
//End of mapping //
////////////////////////////////////////////////////////
/**
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JFileChooserOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JFileChooserOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
@@ -37,6 +39,7 @@
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JList;
+import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.JToggleButton;
import javax.swing.ListModel;
@@ -44,6 +47,7 @@
import javax.swing.filechooser.FileSystemView;
import javax.swing.filechooser.FileView;
import javax.swing.plaf.FileChooserUI;
+import javax.swing.table.TableModel;
import org.netbeans.jemmy.ComponentChooser;
import org.netbeans.jemmy.ComponentSearcher;
@@ -59,6 +63,7 @@
/**
*
* Class provides methods to cover main JFileChooser component functionality.
+ * Supports choosers using either JList or JTable as the component showing files.
*
* @author Alexandre Iline (alexandre.iline@oracle.com)
*
@@ -330,29 +335,29 @@
}
/**
- * Returns file list.
+ * Returns either a JList or JTable, depending on the implementation.
*
- * @return a list being used to display directory content.
+ * @return a component being used to display directory content.
*/
- public JList<?> getFileList() {
- return ((JList) innerSearcher.
+ public Component getFileList() {
+ return innerSearcher.
findComponent(new ComponentChooser() {
@Override
public boolean checkComponent(Component comp) {
return (comp != null
- && comp instanceof JList);
+ && (comp instanceof JList || comp instanceof JTable));
}
@Override
public String getDescription() {
- return "JList";
+ return "JList or JTable used to show list of files";
}
@Override
public String toString() {
return "JFileChooserOperator.getFileList.ComponentChooser{description = " + getDescription() + '}';
}
- }));
+ });
}
/**
@@ -445,14 +450,23 @@
public void clickOnFile(int index, int clickCount) {
getQueueTool().waitEmpty();
output.printTrace("Click " + Integer.toString(clickCount)
- + "times on " + Integer.toString(index)
+ + " times on " + Integer.toString(index)
+ "`th file in JFileChooser\n : "
+ toStringSource());
- JListOperator listOper = new JListOperator(getFileList());
waitPainted(index);
- listOper.copyEnvironment(this);
- listOper.setOutput(output.createErrorOutput());
- listOper.clickOnItem(index, clickCount);
+ Component list = getFileList();
+ if(list instanceof JList) {
+ JListOperator listOper = new JListOperator((JList) list);
+ listOper.copyEnvironment(this);
+ listOper.setOutput(output.createErrorOutput());
+ listOper.clickOnItem(index, clickCount);
+ } else if(list instanceof JTable) {
+ JTableOperator tableOper = new JTableOperator((JTable) list);
+ tableOper.copyEnvironment(this);
+ tableOper.setOutput(output.createErrorOutput());
+ tableOper.clickOnCell(index, 0, clickCount);
+ } else
+ throw new IllegalStateException("Wrong component type");
}
/**
@@ -464,7 +478,7 @@
*/
public void clickOnFile(String file, StringComparator comparator, int clickCount) {
output.printTrace("Click " + Integer.toString(clickCount)
- + "times on \"" + file
+ + " times on \"" + file
+ "\" file in JFileChooser\n : "
+ toStringSource());
clickOnFile(findFileIndex(file, comparator), clickCount);
@@ -589,11 +603,19 @@
public void selectFile(String file, StringComparator comparator) {
getQueueTool().waitEmpty();
int index = findFileIndex(file, comparator);
- JListOperator listOper = new JListOperator(getFileList());
- waitPainted(index);
- listOper.copyEnvironment(this);
- listOper.setOutput(output.createErrorOutput());
- listOper.setSelectedIndex(index);
+ Component list = getFileList();
+ if(list instanceof JList) {
+ JListOperator listOper = new JListOperator((JList) list);
+ listOper.copyEnvironment(this);
+ listOper.setOutput(output.createErrorOutput());
+ listOper.setSelectedIndex(index);
+ } else if(list instanceof JTable){
+ JTableOperator tableOper = new JTableOperator((JTable) list);
+ tableOper.copyEnvironment(this);
+ tableOper.setOutput(output.createErrorOutput());
+ tableOper.changeSelection(index, 0, false, false);
+ } else
+ throw new IllegalStateException("Wrong component type");
}
/**
@@ -749,7 +771,13 @@
*/
public int getFileCount() {
waitPainted(-1);
- return getFileList().getModel().getSize();
+ Component list = getFileList();
+ if(list instanceof JList)
+ return ((JList)list).getModel().getSize();
+ else if(list instanceof JTable)
+ return ((JTable)list).getModel().getRowCount();
+ else
+ throw new IllegalStateException("Wrong component type");
}
/**
@@ -759,12 +787,23 @@
*/
public File[] getFiles() {
waitPainted(-1);
- ListModel<?> listModel = getFileList().getModel();
- File[] result = new File[listModel.getSize()];
- for (int i = 0; i < listModel.getSize(); i++) {
- result[i] = (File) listModel.getElementAt(i);
- }
- return result;
+ Component list = getFileList();
+ if(list instanceof JList) {
+ ListModel<?> listModel = ((JList)list).getModel();
+ File[] result = new File[listModel.getSize()];
+ for (int i = 0; i < listModel.getSize(); i++) {
+ result[i] = (File) listModel.getElementAt(i);
+ }
+ return result;
+ } else if(list instanceof JTable){
+ TableModel listModel = ((JTable)list).getModel();
+ File[] result = new File[listModel.getRowCount()];
+ for (int i = 0; i < listModel.getRowCount(); i++) {
+ result[i] = (File) listModel.getValueAt(i, 0);
+ }
+ return result;
+ } else
+ throw new IllegalStateException("Wrong component type");
}
/**
@@ -1487,18 +1526,31 @@
Waiter<Rectangle, Integer> drawingWaiter = new Waiter<>(new Waitable<Rectangle, Integer>() {
@Override
public Rectangle actionProduced(Integer param) {
- JList<?> list = getFileList();
- int last_one = list.getModel().getSize() - 1;
- if (last_one == -1) {
+ Component list = getFileList();
+ int size;
+ if(list instanceof JList)
+ size = ((JList) list).getModel().getSize();
+ else if(list instanceof JTable)
+ size = ((JTable)list).getModel().getRowCount();
+ else
+ throw new IllegalStateException("Wrong component type");
+ if (size == 0) {
return new Rectangle();
}
int current = (param != null) ? param : 0;
try {
- if (list.getCellBounds(current, current) != null) {
- return list.getCellBounds(last_one, last_one);
- } else {
- return null;
- }
+ if(list instanceof JList)
+ if (((JList) list).getCellBounds(current, current) != null)
+ return ((JList) list).getCellBounds(size - 1, size - 1);
+ else
+ return null;
+ else if(list instanceof JTable)
+ if (((JTable)list).getCellRect(current, 0, false) != null)
+ return ((JTable)list).getCellRect(size - 1, 0, false);
+ else
+ return null;
+ else
+ throw new IllegalStateException("Wrong component type");
} catch (NullPointerException e) {
//sometimes thrown from list.getCellBounds when item exists but not painted
return null;
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JFrameOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JFrameOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JInternalFrameOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JInternalFrameOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
@@ -55,6 +57,7 @@
import org.netbeans.jemmy.drivers.InternalFrameDriver;
import org.netbeans.jemmy.drivers.WindowDriver;
import org.netbeans.jemmy.util.EmptyVisualizer;
+import org.netbeans.jemmy.util.Platform;
/**
* Class provides necessary functionality to operate with
@@ -680,7 +683,11 @@
* @return an icon operator.
*/
public JDesktopIconOperator getIconOperator() {
- initOperators();
+ if(Platform.isOSX()) {
+ initIconOperator();
+ } else {
+ initOperators();
+ }
return iconOperator;
}
@@ -1369,20 +1376,32 @@
}
/**
+ * Initialize icon operator
+ */
+ protected void initIconOperator() {
+ iconOperator = new JDesktopIconOperator(((JInternalFrame) getSource()).getDesktopIcon());
+ iconOperator.copyEnvironment(this);
+ }
+
+ /**
* Initiaites suboperators.
*/
protected void initOperators() {
- iconOperator = new JDesktopIconOperator(((JInternalFrame) getSource()).getDesktopIcon());
- iconOperator.copyEnvironment(this);
- Container titlePane = findTitlePane();
- if (!isIcon() && titlePane != null) {
- if (titleOperator == null) {
- titleOperator = new ContainerOperator<>(titlePane);
- if (getContainer(new ComponentChooser() {
- @Override
- public boolean checkComponent(Component comp) {
- return comp instanceof JDesktopPane;
- }
+ initIconOperator();
+ if(Platform.isOSX()) {
+ throw new UnsupportedOperationException(
+ "Jemmy doesn't support getting or initializing title"
+ + " related operators on Mac OSx");
+ } else {
+ Container titlePane = findTitlePane();
+ if (!isIcon() && titlePane != null) {
+ if (titleOperator == null) {
+ titleOperator = new ContainerOperator<>(titlePane);
+ if (getContainer(new ComponentChooser() {
+ @Override
+ public boolean checkComponent(Component comp) {
+ return comp instanceof JDesktopPane;
+ }
@Override
public String getDescription() {
@@ -1418,6 +1437,7 @@
minOper = null;
maxOper = null;
closeOper = null;
+ }
}
}
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JLabelOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JLabelOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JListOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JListOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JMenuBarOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JMenuBarOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,10 +1,12 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
* 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.
+ * 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
@@ -49,6 +51,7 @@
import org.netbeans.jemmy.Timeouts;
import org.netbeans.jemmy.drivers.DriverManager;
import org.netbeans.jemmy.drivers.MenuDriver;
+import org.netbeans.jemmy.util.Platform;
/**
* <BR><BR>Timeouts used: <BR>
@@ -598,7 +601,7 @@
}
JMenuItemOperator result;
// isVisible() on items returns false on mac, so we need a special searcher.
- if (System.getProperty("os.name").toLowerCase().indexOf("mac") > -1) { // NOI18N
+ if (Platform.isOSX()) {
ComponentSearcher searcher = new ComponentSearcher((Container) menuCont.getSource());
searcher.setOutput(output);
Component c = searcher.findComponent(new JMenuItemOperator.JMenuItemByLabelFinder(path[path.length - 1], getComparator()));
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JMenuItemOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JMenuItemOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JMenuOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JMenuOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JPasswordFieldOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JPasswordFieldOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JPopupMenuOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JPopupMenuOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JProgressBarOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JProgressBarOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JRadioButtonMenuItemOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JRadioButtonMenuItemOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JRadioButtonOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JRadioButtonOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JScrollBarOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JScrollBarOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JScrollPaneOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JScrollPaneOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JSliderOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JSliderOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JSpinnerOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JSpinnerOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JSplitPaneOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JSplitPaneOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JTabbedPaneOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JTabbedPaneOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JTableHeaderOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JTableHeaderOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JTableOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JTableOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
@@ -1289,6 +1291,18 @@
}
/**
+ * Maps {@code JTable.changeSelection(int, int, boolean, boolean)} through queue
+ */
+ public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend) {
+ runMapping(new MapVoidAction("clearSelection") {
+ @Override
+ public void map() {
+ ((JTable) getSource()).changeSelection(rowIndex, columnIndex, toggle, extend);
+ }
+ });
+ }
+
+ /**
* Maps {@code JTable.clearSelection()} through queue
*/
public void clearSelection() {
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JTextAreaOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JTextAreaOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JTextComponentOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JTextComponentOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JTextFieldOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JTextFieldOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JTextPaneOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JTextPaneOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JToggleButtonOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JToggleButtonOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JTreeOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JTreeOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/LabelOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/LabelOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/ListOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/ListOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/Operator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/Operator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
@@ -47,6 +49,7 @@
import org.netbeans.jemmy.Waiter;
import org.netbeans.jemmy.util.DefaultVisualizer;
import org.netbeans.jemmy.util.MouseVisualizer;
+import org.netbeans.jemmy.util.Platform;
/**
* Keeps all environment and low-level methods.
@@ -301,10 +304,9 @@
//Linux - new MouseVisualizer(MouseVisualizer.TOP, 0.5, 10, false)
//solaris - new MouseVisualizer()
//others - new DefaultVisualizer()
- String os = System.getProperty("os.name").toUpperCase();
- if (os.startsWith("LINUX")) {
+ if (Platform.isLinux()) {
setDefaultComponentVisualizer(new MouseVisualizer(MouseVisualizer.TOP, 0.5, 10, false));
- } else if (os.startsWith("SUNOS")) {
+ } else if (Platform.isSolaris()) {
setDefaultComponentVisualizer(new MouseVisualizer());
} else {
setDefaultComponentVisualizer(new DefaultVisualizer());
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/ScrollPaneOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/ScrollPaneOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/ScrollbarOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/ScrollbarOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/TextAreaOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/TextAreaOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/TextComponentOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/TextComponentOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/TextFieldOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/TextFieldOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/WindowOperator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/WindowOperator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/package-info.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/package-info.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/package-info.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/package-info.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/util/AbstractTextStyleChooser.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/util/AbstractTextStyleChooser.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/util/DefaultVisualizer.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/util/DefaultVisualizer.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/util/DumpController.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/util/DumpController.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/util/Dumper.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/util/Dumper.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/util/EmptyVisualizer.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/util/EmptyVisualizer.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/util/MouseVisualizer.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/util/MouseVisualizer.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/util/NameComponentChooser.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/util/NameComponentChooser.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/util/PNGDecoder.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/util/PNGDecoder.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/util/PNGEncoder.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/util/PNGEncoder.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/util/Platform.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * 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 org.netbeans.jemmy.util;
+
+/**
+ * Class to provide platform related utility APIs
+ */
+public class Platform {
+
+ private static final String osName = System.getProperty("os.name");
+
+ /**
+ * Checking whether the platform is linux
+ * @return
+ */
+ public static boolean isLinux() {
+ return isOs("linux");
+ }
+
+ /**
+ * Checking whether the platform is OSX
+ * @return
+ */
+ public static boolean isOSX() {
+ return isOs("mac");
+ }
+
+ /**
+ * Checking whether the platform is Solaris
+ * @return
+ */
+ public static boolean isSolaris() {
+ return isOs("sunos");
+ }
+
+ /**
+ * Checking whether the platform is Windows
+ * @return
+ */
+ public static boolean isWindows() {
+ return isOs("win");
+ }
+
+ private static boolean isOs(String osname) {
+ return osName.toLowerCase().startsWith(osname.toLowerCase());
+ }
+}
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/util/PropChooser.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/util/PropChooser.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/util/RegExComparator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/util/RegExComparator.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/util/StringPropChooser.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/util/StringPropChooser.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/util/TextStyleChooser.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/util/TextStyleChooser.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/util/WindowJob.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/util/WindowJob.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/util/WindowManager.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/util/WindowManager.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/util/package-info.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/util/package-info.java Thu Aug 23 11:09:16 2018 -0400
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/version_info Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/version_info Thu Aug 23 11:09:16 2018 -0400
@@ -1,6 +1,6 @@
Manifest-version: 1.0
Main-Class: org.netbeans.jemmy.JemmyProperties
Jemmy-MajorVersion: 3.0
-Jemmy-MinorVersion: 1.0
+Jemmy-MinorVersion: 3.0
Jemmy-Build: @BUILD_NUMBER@
--- a/test/jdk/sun/security/ec/TestEC.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/ec/TestEC.java Thu Aug 23 11:09:16 2018 -0400
@@ -30,6 +30,7 @@
* @test
* @bug 6840752 8168078
* @summary Provide out-of-the-box support for ECC algorithms
+ * @library /test/lib
* @library ../pkcs11
* @library ../pkcs11/ec
* @library ../pkcs11/sslecc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/security/krb5/auto/SpnegoUnknownMech.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * 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 8186186 8209829
+ * @library /test/lib
+ * @compile -XDignore.symbol.file SpnegoUnknownMech.java
+ * @run main jdk.test.lib.FileInstaller TestHosts TestHosts
+ * @run main/othervm/fail -Djdk.net.hosts.file=TestHosts SpnegoUnknownMech
+ */
+
+import sun.security.jgss.GSSUtil;
+
+public class SpnegoUnknownMech {
+
+ public static void main(String[] args) throws Exception {
+
+ new OneKDC(null).writeJAASConf();
+
+ Context c, s;
+ c = Context.fromJAAS("client");
+ s = Context.fromJAAS("server");
+
+ c.startAsClient(OneKDC.SERVER, GSSUtil.GSS_SPNEGO_MECH_OID);
+ s.startAsServer(GSSUtil.GSS_SPNEGO_MECH_OID);
+
+ byte[] init = c.take(new byte[0]);
+ // Modify the krb5 mech OID inside NegTokenInit to something else
+ init[0x20] = 10;
+ s.take(init);
+
+ s.dispose();
+ c.dispose();
+ }
+}
--- a/test/jdk/sun/security/pkcs11/Cipher/JNICheck.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/Cipher/JNICheck.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
* 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 8063700
+ * @library /test/lib
* @run main/othervm -Xcheck:jni JNICheck
*/
--- a/test/jdk/sun/security/pkcs11/Cipher/ReinitCipher.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/Cipher/ReinitCipher.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +26,7 @@
* @bug 4856966
* @summary
* @author Andreas Sterbenz
- * @library ..
+ * @library /test/lib ..
* @key randomness
* @modules jdk.crypto.cryptoki
* @run main/othervm ReinitCipher
--- a/test/jdk/sun/security/pkcs11/Cipher/TestPKCS5PaddingError.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/Cipher/TestPKCS5PaddingError.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +26,7 @@
* @bug 6687725
* @summary Test internal PKCS5Padding impl with various error conditions.
* @author Valerie Peng
- * @library ..
+ * @library /test/lib ..
* @modules jdk.crypto.cryptoki
* @run main/othervm TestPKCS5PaddingError
* @run main/othervm TestPKCS5PaddingError sm
--- a/test/jdk/sun/security/pkcs11/Cipher/TestRSACipher.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/Cipher/TestRSACipher.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +26,7 @@
* @bug 4898468 6994008
* @summary basic test for RSA cipher
* @author Andreas Sterbenz
- * @library ..
+ * @library /test/lib ..
* @key randomness
* @modules jdk.crypto.cryptoki
* @run main/othervm TestRSACipher
--- a/test/jdk/sun/security/pkcs11/Cipher/TestRSACipherWrap.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/Cipher/TestRSACipherWrap.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +26,7 @@
* @bug 6572331 6994008
* @summary basic test for RSA cipher key wrapping functionality
* @author Valerie Peng
- * @library ..
+ * @library /test/lib ..
* @modules jdk.crypto.cryptoki
* @run main/othervm TestRSACipherWrap
* @run main/othervm TestRSACipherWrap sm
--- a/test/jdk/sun/security/pkcs11/Cipher/TestRawRSACipher.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/Cipher/TestRawRSACipher.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +26,7 @@
* @bug 6994008
* @summary basic test for RSA/ECB/NoPadding cipher
* @author Valerie Peng
- * @library ..
+ * @library /test/lib ..
* @key randomness
* @modules jdk.crypto.cryptoki
* @run main/othervm TestRawRSACipher
--- a/test/jdk/sun/security/pkcs11/Cipher/TestSymmCiphers.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/Cipher/TestSymmCiphers.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +26,7 @@
* @bug 4898461 6604496
* @summary basic test for symmetric ciphers with padding
* @author Valerie Peng
- * @library ..
+ * @library /test/lib ..
* @key randomness
* @modules jdk.crypto.cryptoki
* @run main/othervm TestSymmCiphers
--- a/test/jdk/sun/security/pkcs11/Cipher/TestSymmCiphersNoPad.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/Cipher/TestSymmCiphersNoPad.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +26,7 @@
* @bug 4898484 6604496 8001284
* @summary basic test for symmetric ciphers with no padding
* @author Valerie Peng
- * @library ..
+ * @library /test/lib ..
* @key randomness
* @modules jdk.crypto.cryptoki
* @run main/othervm TestSymmCiphersNoPad
--- a/test/jdk/sun/security/pkcs11/Config/ReadConfInUTF16Env.sh Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/Config/ReadConfInUTF16Env.sh Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
# 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 8187023
# @summary Pkcs11 config file should be assumed in ISO-8859-1
+# @library /test/lib
# @build ReadConfInUTF16Env
# @run shell ReadConfInUTF16Env.sh
--- a/test/jdk/sun/security/pkcs11/KeyAgreement/SupportedDHKeys.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/KeyAgreement/SupportedDHKeys.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
* 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 8072452
* @summary Support DHE sizes up to 8192-bits and DSA sizes up to 3072-bits
- * @library ..
+ * @library /test/lib ..
* @modules jdk.crypto.cryptoki
* @run main/othervm SupportedDHKeys
* @run main/othervm SupportedDHKeys sm
--- a/test/jdk/sun/security/pkcs11/KeyAgreement/TestDH.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/KeyAgreement/TestDH.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +26,7 @@
* @bug 4921804 6324825
* @summary Verify that DH works properly
* @author Andreas Sterbenz
- * @library ..
+ * @library /test/lib ..
* @modules jdk.crypto.cryptoki
* @run main/othervm -Djdk.crypto.KeyAgreement.legacyKDF=true TestDH
* @run main/othervm -Djdk.crypto.KeyAgreement.legacyKDF=true TestDH sm
--- a/test/jdk/sun/security/pkcs11/KeyAgreement/TestInterop.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/KeyAgreement/TestInterop.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
* 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 7146728
* @summary Interop test for DH with secret that has a leading 0x00 byte
- * @library ..
+ * @library /test/lib ..
* @modules jdk.crypto.cryptoki
* @run main/othervm TestInterop
* @run main/othervm TestInterop sm
--- a/test/jdk/sun/security/pkcs11/KeyAgreement/TestShort.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/KeyAgreement/TestShort.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +26,7 @@
* @bug 4942494 7146728
* @summary KAT test for DH (normal and with secret that has leading a 0x00 byte)
* @author Andreas Sterbenz
- * @library ..
+ * @library /test/lib ..
* @modules jdk.crypto.cryptoki
* @run main/othervm TestShort
* @run main/othervm TestShort sm
--- a/test/jdk/sun/security/pkcs11/KeyAgreement/UnsupportedDHKeys.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/KeyAgreement/UnsupportedDHKeys.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
* 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 8072452
* @summary Support DHE sizes up to 8192-bits and DSA sizes up to 3072-bits
- * @library ..
+ * @library /test/lib ..
* @modules jdk.crypto.cryptoki
* @run main/othervm UnsupportedDHKeys
* @run main/othervm UnsupportedDHKeys sm
--- a/test/jdk/sun/security/pkcs11/KeyGenerator/DESParity.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/KeyGenerator/DESParity.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +26,7 @@
* @bug 4898479
* @summary Verify that the parity bits are set correctly
* @author Andreas Sterbenz
- * @library ..
+ * @library /test/lib ..
* @key randomness
* @modules jdk.crypto.cryptoki
* @run main/othervm DESParity
--- a/test/jdk/sun/security/pkcs11/KeyGenerator/TestKeyGenerator.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/KeyGenerator/TestKeyGenerator.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +26,7 @@
* @bug 4917233 6461727 6490213 6720456
* @summary test the KeyGenerator
* @author Andreas Sterbenz
- * @library ..
+ * @library /test/lib ..
* @modules jdk.crypto.cryptoki
* @run main/othervm TestKeyGenerator
* @run main/othervm TestKeyGenerator sm
--- a/test/jdk/sun/security/pkcs11/KeyPairGenerator/TestDH2048.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/KeyPairGenerator/TestDH2048.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +26,7 @@
* @bug 7196382 8072452
* @summary Ensure that DH key pairs can be generated for 512 - 8192 bits
* @author Valerie Peng
- * @library ..
+ * @library /test/lib ..
* @modules jdk.crypto.cryptoki
* @run main/othervm TestDH2048
* @run main/othervm TestDH2048 sm
--- a/test/jdk/sun/security/pkcs11/KeyStore/Basic.sh Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/KeyStore/Basic.sh Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
# 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,6 +23,7 @@
# @test
# @bug 4938185
+# @library /test/lib
# @summary KeyStore support for NSS cert/key databases
#
# @run shell Basic.sh
@@ -60,7 +61,8 @@
echo TESTSRC=${TESTSRC}
echo TESTCLASSES=${TESTCLASSES}
echo TESTJAVA=${TESTJAVA}
-echo echo COMPILEJAVA=${COMPILEJAVA}
+echo COMPILEJAVA=${COMPILEJAVA}
+echo CPAPPEND=${CPAPPEND}
echo ""
# get command from input args -
@@ -168,16 +170,17 @@
if [ "${RECOMPILE}" = "yes" ] ; then
${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} \
- -classpath ${TESTSRC}${FS}..${PS}${TESTSRC}${FS}loader.jar \
- -d ${TESTCLASSES} \
- ${TESTSRC}${FS}Basic.java \
- ${TESTSRC}${FS}..${FS}PKCS11Test.java
+ -classpath ${TESTSRC}${FS}..${PS}${TESTSRC}${FS}loader.jar \
+ -d ${TESTCLASSES} \
+ ${TESTSRC}${FS}..${FS}..${FS}..${FS}..${FS}..${FS}lib${FS}jdk${FS}test${FS}lib${FS}artifacts${FS}*.java \
+ ${TESTSRC}${FS}Basic.java \
+ ${TESTSRC}${FS}..${FS}PKCS11Test.java
fi
# run test
${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} \
- -classpath ${TESTCLASSES}${PS}${TESTSRC}${FS}loader.jar \
+ -classpath ${TESTCLASSES}${PS}${TESTSRC}${FS}loader.jar${PS}${CPAPPEND} \
-DDIR=${TESTSRC}${FS}BasicData \
-DCUSTOM_DB_DIR=${TESTCLASSES} \
-DCUSTOM_P11_CONFIG=${TESTSRC}${FS}BasicData${FS}p11-${TOKEN}.txt \
--- a/test/jdk/sun/security/pkcs11/KeyStore/ClientAuth.sh Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/KeyStore/ClientAuth.sh Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
# 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 @@
# @bug 4938185 7106773
# @summary KeyStore support for NSS cert/key databases
# 512 bits RSA key cannot work with SHA384 and SHA512
-#
+# @library /test/lib
# @run shell ClientAuth.sh
# set a few environment variables so that the shell-script can run stand-alone
@@ -47,6 +47,7 @@
echo TESTCLASSES=${TESTCLASSES}
echo TESTJAVA=${TESTJAVA}
echo COMPILEJAVA=${COMPILEJAVA}
+echo CPAPPEND=${CPAPPEND}
echo ""
OS=`uname -s`
@@ -128,13 +129,14 @@
${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} \
-classpath ${TESTSRC} \
-d ${TESTCLASSES} \
+ ${TESTSRC}${FS}..${FS}..${FS}..${FS}..${FS}..${FS}lib${FS}jdk${FS}test${FS}lib${FS}artifacts${FS}*.java \
${TESTSRC}${FS}ClientAuth.java \
${TESTSRC}${FS}..${FS}PKCS11Test.java
# run test
echo "Run ClientAuth TLSv1 ..."
${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} \
- -classpath ${TESTCLASSES} \
+ -classpath ${TESTCLASSES}${PS}${CPAPPEND} \
-DDIR=${TESTSRC}${FS}ClientAuthData${FS} \
-DCUSTOM_DB_DIR=${TESTCLASSES} \
-DCUSTOM_P11_CONFIG=${TESTSRC}${FS}ClientAuthData${FS}p11-nss.txt \
@@ -155,7 +157,7 @@
# run test
echo "Run ClientAuth TLSv1.1 ..."
${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} \
- -classpath ${TESTCLASSES} \
+ -classpath ${TESTCLASSES}${PS}${CPAPPEND} \
-DDIR=${TESTSRC}${FS}ClientAuthData${FS} \
-DCUSTOM_DB_DIR=${TESTCLASSES} \
-DCUSTOM_P11_CONFIG=${TESTSRC}${FS}ClientAuthData${FS}p11-nss.txt \
@@ -176,7 +178,7 @@
# run test with specified TLS protocol and cipher suite
echo "Run ClientAuth TLSv1.2 TLS_DHE_RSA_WITH_AES_128_CBC_SHA"
${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} \
- -classpath ${TESTCLASSES} \
+ -classpath ${TESTCLASSES}${PS}${CPAPPEND} \
-DDIR=${TESTSRC}${FS}ClientAuthData${FS} \
-DCUSTOM_DB_DIR=${TESTCLASSES} \
-DCUSTOM_P11_CONFIG=${TESTSRC}${FS}ClientAuthData${FS}p11-nss.txt \
--- a/test/jdk/sun/security/pkcs11/KeyStore/SecretKeysBasic.sh Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/KeyStore/SecretKeysBasic.sh Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
# 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 @@
# @bug 6599979
# @summary Ensure that re-assigning the alias works
#
-# @library ..
+# @library /test/lib ..
# @build SecretKeysBasic
# @run shell SecretKeysBasic.sh
#
@@ -52,6 +52,7 @@
echo TESTSRC=${TESTSRC}
echo TESTCLASSES=${TESTCLASSES}
echo TESTJAVA=${TESTJAVA}
+echo CPAPPEND=${CPAPPEND}
echo ""
#DEBUG=sunpkcs11,pkcs11keystore
@@ -130,9 +131,9 @@
${MKDIR} ${TESTCLASSES}${FS}pkcs11_softtoken${FS}public
echo ${CP} ${TESTSRC}${FS}BasicData${FS}pkcs11_softtoken${FS}objstore_info \
- ${TESTCLASSES}${FS}pkcs11_softtoken
+ ${TESTCLASSES}${FS}pkcs11_softtoken
${CP} ${TESTSRC}${FS}BasicData${FS}pkcs11_softtoken${FS}objstore_info \
- ${TESTCLASSES}${FS}pkcs11_softtoken
+ ${TESTCLASSES}${FS}pkcs11_softtoken
echo ${CHMOD} +w ${TESTCLASSES}${FS}pkcs11_softtoken${FS}objstore_info
${CHMOD} 600 ${TESTCLASSES}${FS}pkcs11_softtoken${FS}objstore_info
@@ -142,16 +143,16 @@
# run test
cd ${TESTSRC}
${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} \
- -DDIR=${TESTSRC}${FS}BasicData${FS} \
+ -DDIR=${TESTSRC}${FS}BasicData${FS} \
-classpath \
- ${TESTCLASSES}${PS}${TESTCLASSES}${FS}..${PS}${TESTSRC}${FS}loader.jar \
+ ${TESTCLASSES}${PS}${TESTCLASSES}${FS}..${PS}${TESTSRC}${FS}loader.jar${PS}${CPAPPEND} \
-DCUSTOM_DB_DIR=${TESTCLASSES} \
-DCUSTOM_P11_CONFIG=${TESTSRC}${FS}BasicData${FS}p11-${token}.txt \
- -DNO_DEFAULT=true \
- -DNO_DEIMOS=true \
- -DTOKEN=${token} \
- -Djava.security.debug=${DEBUG} \
- SecretKeysBasic
+ -DNO_DEFAULT=true \
+ -DNO_DEIMOS=true \
+ -DTOKEN=${token} \
+ -Djava.security.debug=${DEBUG} \
+ SecretKeysBasic
# -DCUSTOM_P11_CONFIG=${TESTSRC}${FS}BasicData${FS}p11-${token}.txt \
--- a/test/jdk/sun/security/pkcs11/KeyStore/Solaris.sh Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/KeyStore/Solaris.sh Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved.
# 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,6 +23,7 @@
# @test
# @bug 5038659
+# @library /test/lib
# @summary Enable PKCS#11 KeyStore for SunPKCS11-Solaris
#
# @run shell Solaris.sh
@@ -138,17 +139,18 @@
cd ${TESTCLASSES}
${RM} *.class
${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} \
- -classpath ${TESTSRC}${FS}..${PS}${TESTSRC}${FS}loader.jar \
- -d ${TESTCLASSES} \
- ${TESTSRC}${FS}Basic.java \
- ${TESTSRC}${FS}..${FS}PKCS11Test.java
+ -classpath ${TESTSRC}${FS}..${PS}${TESTSRC}${FS}loader.jar \
+ -d ${TESTCLASSES} \
+ ${TESTSRC}${FS}..${FS}..${FS}..${FS}..${FS}..${FS}lib${FS}jdk${FS}test${FS}lib${FS}artifacts${FS}*.java \
+ ${TESTSRC}${FS}Basic.java \
+ ${TESTSRC}${FS}..${FS}PKCS11Test.java
fi
# run test
cd ${TESTSRC}
${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} \
- -classpath ${TESTCLASSES}${PS}${TESTSRC}${FS}loader.jar \
+ -classpath ${TESTCLASSES}${PS}${TESTSRC}${FS}loader.jar${PS}${CPAPPEND} \
-DDIR=${TESTSRC}${FS}BasicData${FS} \
-DCUSTOM_P11_CONFIG=${TESTSRC}${FS}BasicData${FS}p11-solaris.txt \
-DNO_DEFAULT=true \
--- a/test/jdk/sun/security/pkcs11/Mac/MacKAT.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/Mac/MacKAT.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +26,7 @@
* @bug 4846410 6313661 4963723
* @summary Basic known-answer-test for Hmac algorithms
* @author Andreas Sterbenz
- * @library ..
+ * @library /test/lib ..
* @modules jdk.crypto.cryptoki
* @run main/othervm MacKAT
* @run main/othervm MacKAT sm
--- a/test/jdk/sun/security/pkcs11/Mac/MacSameTest.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/Mac/MacSameTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +26,7 @@
* @bug 8048603
* @summary Check if doFinal and update operation result in same Mac
* @author Yu-Ching Valerie Peng, Bill Situ, Alexander Fomin
- * @library ..
+ * @library /test/lib ..
* @modules jdk.crypto.cryptoki
* @run main/othervm MacSameTest
* @run main/othervm MacSameTest sm
--- a/test/jdk/sun/security/pkcs11/Mac/ReinitMac.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/Mac/ReinitMac.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +26,7 @@
* @bug 4856966
* @summary
* @author Andreas Sterbenz
- * @library ..
+ * @library /test/lib ..
* @key randomness
* @modules jdk.crypto.cryptoki
* @run main/othervm ReinitMac
--- a/test/jdk/sun/security/pkcs11/MessageDigest/ByteBuffers.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/MessageDigest/ByteBuffers.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +26,7 @@
* @bug 4856966
* @summary Test the MessageDigest.update(ByteBuffer) method
* @author Andreas Sterbenz
- * @library ..
+ * @library /test/lib ..
* @key randomness
* @modules jdk.crypto.cryptoki
* @run main/othervm ByteBuffers
--- a/test/jdk/sun/security/pkcs11/MessageDigest/DigestKAT.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/MessageDigest/DigestKAT.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +26,7 @@
* @bug 4856966
* @summary Basic known-answer-test for all our MessageDigest algorithms
* @author Andreas Sterbenz
- * @library ..
+ * @library /test/lib ..
* @modules jdk.crypto.cryptoki
* @run main/othervm DigestKAT
* @run main/othervm DigestKAT sm
--- a/test/jdk/sun/security/pkcs11/MessageDigest/ReinitDigest.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/MessageDigest/ReinitDigest.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +26,7 @@
* @bug 4856966
* @summary
* @author Andreas Sterbenz
- * @library ..
+ * @library /test/lib ..
* @key randomness
* @modules jdk.crypto.cryptoki
* @run main/othervm ReinitDigest
--- a/test/jdk/sun/security/pkcs11/MessageDigest/TestCloning.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/MessageDigest/TestCloning.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +26,7 @@
* @bug 6414899
* @summary Ensure the cloning functionality works.
* @author Valerie Peng
- * @library ..
+ * @library /test/lib ..
* @key randomness
* @modules jdk.crypto.cryptoki
* @run main/othervm TestCloning
--- a/test/jdk/sun/security/pkcs11/PKCS11Test.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/PKCS11Test.java Thu Aug 23 11:09:16 2018 -0400
@@ -53,6 +53,10 @@
import java.util.ServiceLoader;
import java.util.Set;
+import jdk.test.lib.artifacts.Artifact;
+import jdk.test.lib.artifacts.ArtifactResolver;
+import jdk.test.lib.artifacts.ArtifactResolverException;
+
public abstract class PKCS11Test {
private boolean enableSM = false;
@@ -300,15 +304,8 @@
}
static String getNSSLibDir(String library) throws Exception {
- String osName = props.getProperty("os.name");
- if (osName.startsWith("Win")) {
- osName = "Windows";
- } else if (osName.equals("Mac OS X")) {
- osName = "MacOSX";
- }
- String osid = osName + "-"
- + props.getProperty("os.arch") + "-" + props.getProperty("sun.arch.data.model");
- String[] nssLibDirs = osMap.get(osid);
+ String osid = getOsId();
+ String[] nssLibDirs = getNssLibPaths(osid);
if (nssLibDirs == null) {
System.out.println("Warning: unsupported OS: " + osid
+ ", please initialize NSS librarys location firstly, skipping test");
@@ -323,6 +320,7 @@
if (new File(dir).exists() &&
new File(dir + System.mapLibraryName(library)).exists()) {
nssLibDir = dir;
+ System.out.println("nssLibDir: " + nssLibDir);
System.setProperty("pkcs11test.nss.libdir", nssLibDir);
break;
}
@@ -334,6 +332,18 @@
return nssLibDir;
}
+ private static String getOsId() {
+ String osName = props.getProperty("os.name");
+ if (osName.startsWith("Win")) {
+ osName = "Windows";
+ } else if (osName.equals("Mac OS X")) {
+ osName = "MacOSX";
+ }
+ String osid = osName + "-" + props.getProperty("os.arch") + "-"
+ + props.getProperty("sun.arch.data.model");
+ return osid;
+ }
+
static boolean isBadNSSVersion(Provider p) {
double nssVersion = getNSSVersion();
if (isNSS(p) && nssVersion >= 3.11 && nssVersion < 3.12) {
@@ -644,34 +654,74 @@
return false;
}
- private static final Map<String,String[]> osMap;
+ private static Map<String,String[]> osMap;
// Location of the NSS libraries on each supported platform
- static {
+ private static Map<String, String[]> getOsMap() {
+ if (osMap != null) {
+ return osMap;
+ }
+
osMap = new HashMap<>();
- osMap.put("SunOS-sparc-32", new String[]{"/usr/lib/mps/"});
- osMap.put("SunOS-sparcv9-64", new String[]{"/usr/lib/mps/64/"});
- osMap.put("SunOS-x86-32", new String[]{"/usr/lib/mps/"});
- osMap.put("SunOS-amd64-64", new String[]{"/usr/lib/mps/64/"});
- osMap.put("Linux-i386-32", new String[]{
- "/usr/lib/i386-linux-gnu/", "/usr/lib32/", "/usr/lib/"});
- osMap.put("Linux-amd64-64", new String[]{
- "/usr/lib/x86_64-linux-gnu/", "/usr/lib/x86_64-linux-gnu/nss/",
- "/usr/lib64/"});
- osMap.put("Linux-ppc64-64", new String[]{"/usr/lib64/"});
- osMap.put("Linux-ppc64le-64", new String[]{"/usr/lib64/"});
- osMap.put("Linux-s390x-64", new String[]{"/usr/lib64/"});
- osMap.put("Windows-x86-32", new String[]{
- PKCS11_BASE + "/nss/lib/windows-i586/".replace('/', SEP)});
- osMap.put("Windows-amd64-64", new String[]{
- PKCS11_BASE + "/nss/lib/windows-amd64/".replace('/', SEP)});
- osMap.put("MacOSX-x86_64-64", new String[]{
- PKCS11_BASE + "/nss/lib/macosx-x86_64/"});
- osMap.put("Linux-arm-32", new String[]{
- "/usr/lib/arm-linux-gnueabi/nss/",
- "/usr/lib/arm-linux-gnueabihf/nss/"});
- osMap.put("Linux-aarch64-64", new String[]{
- "/usr/lib/aarch64-linux-gnu/", "/usr/lib/aarch64-linux-gnu/nss/"});
+ osMap.put("SunOS-sparc-32", new String[] { "/usr/lib/mps/" });
+ osMap.put("SunOS-sparcv9-64", new String[] { "/usr/lib/mps/64/" });
+ osMap.put("SunOS-x86-32", new String[] { "/usr/lib/mps/" });
+ osMap.put("SunOS-amd64-64", new String[] { "/usr/lib/mps/64/" });
+ osMap.put("Linux-i386-32", new String[] {
+ "/usr/lib/i386-linux-gnu/",
+ "/usr/lib32/",
+ "/usr/lib/" });
+ osMap.put("Linux-amd64-64", new String[] {
+ "/usr/lib/x86_64-linux-gnu/",
+ "/usr/lib/x86_64-linux-gnu/nss/",
+ "/usr/lib64/" });
+ osMap.put("Linux-ppc64-64", new String[] { "/usr/lib64/" });
+ osMap.put("Linux-ppc64le-64", new String[] { "/usr/lib64/" });
+ osMap.put("Linux-s390x-64", new String[] { "/usr/lib64/" });
+ osMap.put("Windows-x86-32", new String[] {});
+ osMap.put("Windows-amd64-64", new String[] {});
+ osMap.put("MacOSX-x86_64-64", new String[] {});
+ osMap.put("Linux-arm-32", new String[] {
+ "/usr/lib/arm-linux-gnueabi/nss/",
+ "/usr/lib/arm-linux-gnueabihf/nss/" });
+ osMap.put("Linux-aarch64-64", new String[] {
+ "/usr/lib/aarch64-linux-gnu/",
+ "/usr/lib/aarch64-linux-gnu/nss/" });
+ return osMap;
+ }
+
+ private static String[] getNssLibPaths(String osId) {
+ String[] preferablePaths = getPreferableNssLibPaths(osId);
+ if (preferablePaths.length != 0) {
+ return preferablePaths;
+ } else {
+ return getOsMap().get(osId);
+ }
+ }
+
+ private static String[] getPreferableNssLibPaths(String osId) {
+ List<String> nssLibPaths = new ArrayList<>();
+
+ String customNssLibPaths = System.getProperty("test.nss.lib.paths");
+ if (customNssLibPaths == null) {
+ // If custom local NSS lib path is not provided,
+ // try to download NSS libs from artifactory
+ String path = fetchNssLib(osId);
+ if (path != null) {
+ nssLibPaths.add(path);
+ }
+ } else {
+ String[] paths = customNssLibPaths.split(",");
+ for (String path : paths) {
+ if (!path.endsWith(File.separator)) {
+ nssLibPaths.add(path + File.separator);
+ } else {
+ nssLibPaths.add(path);
+ }
+ }
+ }
+
+ return nssLibPaths.toArray(new String[nssLibPaths.size()]);
}
private final static char[] hexDigits = "0123456789abcdef".toCharArray();
@@ -797,4 +847,60 @@
}
return data;
}
+
+ private static String fetchNssLib(String osId) {
+ switch (osId) {
+ case "Windows-x86-32":
+ return fetchNssLib(WINDOWS_X86.class);
+
+ case "Windows-amd64-64":
+ return fetchNssLib(WINDOWS_X64.class);
+
+ case "MacOSX-x86_64-64":
+ return fetchNssLib(MACOSX_X64.class);
+
+ default:
+ return null;
+ }
+ }
+
+ private static String fetchNssLib(Class<?> clazz) {
+ String path = null;
+ try {
+ path = ArtifactResolver.resolve(clazz).entrySet().stream()
+ .findAny().get().getValue() + File.separator + "nsslib"
+ + File.separator;
+ } catch (ArtifactResolverException e) {
+ Throwable cause = e.getCause();
+ if (cause == null) {
+ System.out.println("Cannot resolve artifact, "
+ + "please check if JIB jar is present in classpath.");
+ } else {
+ throw new RuntimeException("Fetch artifact failed: " + clazz
+ + "\nPlease make sure the artifact is available.");
+ }
+ }
+ return path;
+ }
+
+ @Artifact(
+ organization = "jpg.tests.jdk.nsslib",
+ name = "nsslib-windows_x64",
+ revision = "3.35",
+ extension = "zip")
+ private static class WINDOWS_X64 { }
+
+ @Artifact(
+ organization = "jpg.tests.jdk.nsslib",
+ name = "nsslib-windows_x86",
+ revision = "3.35",
+ extension = "zip")
+ private static class WINDOWS_X86 { }
+
+ @Artifact(
+ organization = "jpg.tests.jdk.nsslib",
+ name = "nsslib-macosx_x64",
+ revision = "3.35",
+ extension = "zip")
+ private static class MACOSX_X64 { }
}
--- a/test/jdk/sun/security/pkcs11/Provider/Absolute.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/Provider/Absolute.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
* 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 7003952 7191662
- * @library ..
+ * @library /test/lib ..
* @modules jdk.crypto.cryptoki
* @summary load DLLs and launch executables using fully qualified path
*/
--- a/test/jdk/sun/security/pkcs11/Provider/ConfigQuotedString.sh Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/Provider/ConfigQuotedString.sh Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -48,6 +48,7 @@
echo TESTCLASSES=${TESTCLASSES}
echo TESTJAVA=${TESTJAVA}
echo COMPILEJAVA=${COMPILEJAVA}
+echo CPAPPEND=${CPAPPEND}
echo ""
# let java test exit if platform unsupported
@@ -105,13 +106,14 @@
${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} \
-classpath ${TESTSRC}${FS}.. \
-d ${TESTCLASSES} \
+ ${TESTSRC}${FS}..${FS}..${FS}..${FS}..${FS}..${FS}lib${FS}jdk${FS}test${FS}lib${FS}artifacts${FS}*.java \
${TESTSRC}${FS}ConfigQuotedString.java \
${TESTSRC}${FS}..${FS}PKCS11Test.java
# run test
${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} \
- -classpath ${TESTCLASSES} \
+ -classpath ${TESTCLASSES}${PS}${CPAPPEND} \
-DCUSTOM_P11_CONFIG=${TESTSRC}${FS}ConfigQuotedString-nss.txt \
-Dtest.src=${TESTSRC} \
-Dtest.classes=${TESTCLASSES} \
--- a/test/jdk/sun/security/pkcs11/Provider/Login.sh Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/Provider/Login.sh Thu Aug 23 11:09:16 2018 -0400
@@ -49,6 +49,7 @@
echo TESTCLASSES=${TESTCLASSES}
echo TESTJAVA=${TESTJAVA}
echo COMPILEJAVA=${COMPILEJAVA}
+echo CPAPPEND=${CPAPPEND}
echo ""
# let java test exit if platform unsupported
@@ -114,13 +115,14 @@
${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} \
-classpath ${TESTSRC}${FS}.. \
-d ${TESTCLASSES} \
+ ${TESTSRC}${FS}..${FS}..${FS}..${FS}..${FS}..${FS}lib${FS}jdk${FS}test${FS}lib${FS}artifacts${FS}*.java \
${TESTSRC}${FS}Login.java \
${TESTSRC}${FS}..${FS}PKCS11Test.java
# run test
${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} \
- -classpath ${TESTCLASSES} \
+ -classpath ${TESTCLASSES}${PS}${CPAPPEND} \
-DCUSTOM_DB_DIR=${TESTCLASSES} \
-DCUSTOM_P11_CONFIG=${TESTSRC}${FS}Login-nss.txt \
-DNO_DEFAULT=true \
--- a/test/jdk/sun/security/pkcs11/README Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/README Thu Aug 23 11:09:16 2018 -0400
@@ -1,13 +1,33 @@
This README is to keep a list facts and known workaround for the pkcs11 java tests
perform as a result of bugs or features in NSS or other pkcs11 libraries.
+- How to get NSS libraries?
+The libraries come from the following sources.
+
+1. Specified by system property test.nss.lib.paths
+System property test.nss.lib.paths can specify a set of absolute paths to
+the local NSS library directories. The paths are separated by comma.
+
+2. Pre-built NSS libraries from artifactory server
+If the value of system property test.nss.lib.paths is not set, the tests will try
+to download pre-built NSS libraries from artifactory server. Currently, the
+tests only looks for libraries for Windows and MacOSX platforms on artifactory.
+Please note that JIB jar MUST be present in classpath when downloading the
+libraries.
+
+3. System NSS libraries
+If both of the above sources are not available, the tests will try to search
+for the libraries in some system paths. The paths are platform-specific. Note
+that, there is no such system path on Windows and MacOSX platforms. On these
+platforms, it has to use source 1 or 2.
+
- NSS ECC None/Basic/Extended
The tests detect the NSS library support for Elliptic Curves as to not
report incorrect failures. PKCS11 reports back CKR_DOMAIN_PARAMS_INVALID
when the curve is not supported.
- Default libsoftokn3.so
-By default PKCS11Test.java will look for libsoftokn3.so. There are a number of
+By default PKCS11Test.java will look for libsoftokn3.so. There are a number of
tests, particularly in Secmod, that need libnss3.so. The method useNSS() in
PKCS11test.java is to change the search and version checking to libnss3.
@@ -17,6 +37,6 @@
read incorrectly. KeyStore/SecretKeysBasic.java tiggers this bug and
knows to avoid it.
-- A number of EC tests fail because of a DER bug in NSS 3.11. The best guess
+- A number of EC tests fail because of a DER bug in NSS 3.11. The best guess
is Mozilla bug 480280. Those tests that abort execution with a PASS result
are: TestECDH2, TestECDSA, TestECDSA2 and TestECGenSpec.
--- a/test/jdk/sun/security/pkcs11/SampleTest.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/SampleTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +26,7 @@
* @bug 4000000
* @summary XXX todo
* @author Andreas Sterbenz
- * @library ..
+ * @library /test/lib ..
* @modules jdk.crypto.cryptoki
*/
--- a/test/jdk/sun/security/pkcs11/Secmod/AddPrivateKey.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/Secmod/AddPrivateKey.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +26,7 @@
* @bug 6414980
* @summary Test that the PKCS#11 KeyStore handles RSA, DSA, and EC keys
* @author Andreas Sterbenz
- * @library ..
+ * @library /test/lib ..
* @modules jdk.crypto.cryptoki
* @run main/othervm AddPrivateKey
* @run main/othervm AddPrivateKey sm policy
@@ -63,6 +63,11 @@
private static final byte[] DATA = generateData(DATA_LENGTH);
public static void main(String[] args) throws Exception {
+ if (args.length > 1 && "sm".equals(args[0])) {
+ System.setProperty("java.security.policy",
+ BASE + File.separator + args[1]);
+ }
+
if (initSecmod() == false) {
return;
}
@@ -77,8 +82,6 @@
Security.addProvider(p);
if (args.length > 1 && "sm".equals(args[0])) {
- System.setProperty("java.security.policy",
- BASE + File.separator + args[1]);
System.setSecurityManager(new SecurityManager());
}
--- a/test/jdk/sun/security/pkcs11/Secmod/AddTrustedCert.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/Secmod/AddTrustedCert.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +26,7 @@
* @bug 6298106
* @summary make sure we can add a trusted cert to the NSS KeyStore module
* @author Andreas Sterbenz
- * @library ..
+ * @library /test/lib ..
* @modules jdk.crypto.cryptoki
* @run main/othervm AddTrustedCert
* @run main/othervm AddTrustedCert sm policy
@@ -48,6 +48,11 @@
public class AddTrustedCert extends SecmodTest {
public static void main(String[] args) throws Exception {
+ if (args.length > 1 && "sm".equals(args[0])) {
+ System.setProperty("java.security.policy",
+ BASE + File.separator + args[1]);
+ }
+
if (initSecmod() == false) {
return;
}
--- a/test/jdk/sun/security/pkcs11/Secmod/Crypto.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/Secmod/Crypto.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +26,7 @@
* @bug 6329006
* @summary verify that NSS no-db mode works correctly
* @author Andreas Sterbenz
- * @library ..
+ * @library /test/lib ..
* @modules jdk.crypto.cryptoki
* @run main/othervm Crypto
* @run main/othervm Crypto sm policy
--- a/test/jdk/sun/security/pkcs11/Secmod/GetPrivateKey.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/Secmod/GetPrivateKey.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +27,7 @@
* @summary make sure we can access the NSS softtoken KeyStore
* and use a private key
* @author Andreas Sterbenz
- * @library ..
+ * @library /test/lib ..
* @modules jdk.crypto.cryptoki
* @run main/othervm GetPrivateKey
* @run main/othervm GetPrivateKey sm policy
@@ -47,6 +47,11 @@
public class GetPrivateKey extends SecmodTest {
public static void main(String[] args) throws Exception {
+ if (args.length > 1 && "sm".equals(args[0])) {
+ System.setProperty("java.security.policy",
+ BASE + File.separator + args[1]);
+ }
+
if (initSecmod() == false) {
return;
}
@@ -58,8 +63,6 @@
Security.addProvider(p);
if (args.length > 1 && "sm".equals(args[0])) {
- System.setProperty("java.security.policy",
- BASE + File.separator + args[1]);
System.setSecurityManager(new SecurityManager());
}
--- a/test/jdk/sun/security/pkcs11/Secmod/JksSetPrivateKey.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/Secmod/JksSetPrivateKey.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +26,7 @@
* @bug 6269847
* @summary store a NSS PKCS11 PrivateKeyEntry to JKS KeyStore throws confusing NPE
* @author Wang Weijun
- * @library ..
+ * @library /test/lib ..
* @modules jdk.crypto.cryptoki
* @run main/othervm JksSetPrivateKey
* @run main/othervm JksSetPrivateKey sm policy
@@ -46,6 +46,11 @@
public class JksSetPrivateKey extends SecmodTest {
public static void main(String[] args) throws Exception {
+ if (args.length > 1 && "sm".equals(args[0])) {
+ System.setProperty("java.security.policy",
+ BASE + File.separator + args[1]);
+ }
+
if (initSecmod() == false) {
return;
}
@@ -57,8 +62,6 @@
Security.addProvider(p);
if (args.length > 1 && "sm".equals(args[0])) {
- System.setProperty("java.security.policy",
- BASE + File.separator + args[1]);
System.setSecurityManager(new SecurityManager());
}
--- a/test/jdk/sun/security/pkcs11/Secmod/LoadKeystore.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/Secmod/LoadKeystore.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
* 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 8048622 8134232
* @summary Checks that PKCS#11 keystore can't be loaded with wrong password
- * @library ../
+ * @library /test/lib ../
* @modules jdk.crypto.cryptoki
* @run main/othervm LoadKeystore
* @run main/othervm LoadKeystore sm policy
@@ -43,6 +43,11 @@
public class LoadKeystore extends SecmodTest {
public static void main(String[] args) throws Exception {
+ if (args.length > 1 && "sm".equals(args[0])) {
+ System.setProperty("java.security.policy",
+ BASE + File.separator + args[1]);
+ }
+
if (!initSecmod()) {
return;
}
@@ -55,8 +60,6 @@
Security.addProvider(p);
if (args.length > 1 && "sm".equals(args[0])) {
- System.setProperty("java.security.policy",
- BASE + File.separator + args[1]);
System.setSecurityManager(new SecurityManager());
}
--- a/test/jdk/sun/security/pkcs11/Secmod/TestNssDbSqlite.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/Secmod/TestNssDbSqlite.java Thu Aug 23 11:09:16 2018 -0400
@@ -28,7 +28,7 @@
* @summary Test NSS DB Sqlite
* @comment There is no NSS on Aix.
* @requires os.family != "aix"
- * @library ../
+ * @library /test/lib ../
* @modules java.base/sun.security.rsa
* java.base/sun.security.provider
* java.base/sun.security.jca
--- a/test/jdk/sun/security/pkcs11/Secmod/TrustAnchors.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/Secmod/TrustAnchors.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +26,7 @@
* @bug 6298106 6275523 6420252 8059627
* @summary make sure we can access the NSS trust anchor module
* @author Andreas Sterbenz
- * @library ..
+ * @library /test/lib ..
* @modules jdk.crypto.cryptoki
* @run main/othervm TrustAnchors
* @run main/othervm TrustAnchors sm policy
--- a/test/jdk/sun/security/pkcs11/SecureRandom/Basic.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/SecureRandom/Basic.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +26,7 @@
* @bug 6246411
* @summary basic test for PKCS#11 SecureRandom
* @author Andreas Sterbenz
- * @library ..
+ * @library /test/lib ..
* @key randomness
* @modules jdk.crypto.cryptoki
* @run main/othervm Basic
--- a/test/jdk/sun/security/pkcs11/SecureRandom/TestDeserialization.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/SecureRandom/TestDeserialization.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
* 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 6837847
* @summary Ensure a deserialized PKCS#11 SecureRandom is functional.
- * @library ..
+ * @library /test/lib ..
* @modules jdk.crypto.cryptoki
*/
--- a/test/jdk/sun/security/pkcs11/Serialize/SerializeProvider.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/Serialize/SerializeProvider.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +26,7 @@
* @bug 4921802
* @summary Test that the SunPKCS11 provider can be serialized
* @author Andreas Sterbenz
- * @library ..
+ * @library /test/lib ..
* @modules jdk.crypto.cryptoki
*/
--- a/test/jdk/sun/security/pkcs11/Signature/ByteBuffers.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/Signature/ByteBuffers.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +26,7 @@
* @bug 4856966
* @summary Test the Signature.update(ByteBuffer) method
* @author Andreas Sterbenz
- * @library ..
+ * @library /test/lib ..
* @key randomness
* @modules jdk.crypto.cryptoki
* @run main/othervm ByteBuffers
--- a/test/jdk/sun/security/pkcs11/Signature/ReinitSignature.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/Signature/ReinitSignature.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +26,7 @@
* @bug 4856966
* @summary test that reinitializing Signatures works correctly
* @author Andreas Sterbenz
- * @library ..
+ * @library /test/lib ..
* @key randomness
* @modules jdk.crypto.cryptoki
* @run main ReinitSignature
--- a/test/jdk/sun/security/pkcs11/Signature/TestDSA.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/Signature/TestDSA.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +26,7 @@
* @bug 4856966
* @summary basic test of SHA1withDSA and RawDSA signing/verifying
* @author Andreas Sterbenz
- * @library ..
+ * @library /test/lib ..
* @key randomness
* @modules jdk.crypto.cryptoki
* @run main/othervm TestDSA
--- a/test/jdk/sun/security/pkcs11/Signature/TestDSAKeyLength.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/Signature/TestDSAKeyLength.java Thu Aug 23 11:09:16 2018 -0400
@@ -26,7 +26,7 @@
* @bug 7200306 8029158
* @summary verify that P11Signature impl will error out when initialized
* with unsupported key sizes
- * @library ..
+ * @library /test/lib ..
* @key randomness
* @modules jdk.crypto.cryptoki
* @run main/othervm TestDSAKeyLength
--- a/test/jdk/sun/security/pkcs11/Signature/TestRSAKeyLength.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/Signature/TestRSAKeyLength.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +26,7 @@
* @bug 6695485
* @summary Make sure initSign/initVerify() check RSA key lengths
* @author Yu-Ching Valerie Peng
- * @library ..
+ * @library /test/lib ..
* @modules jdk.crypto.cryptoki
* @run main/othervm TestRSAKeyLength
* @run main/othervm TestRSAKeyLength sm
--- a/test/jdk/sun/security/pkcs11/ec/ReadCertificates.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/ec/ReadCertificates.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +27,7 @@
* @summary Make sure that we can parse certificates using various named curves
* and verify their signatures
* @author Andreas Sterbenz
- * @library ..
+ * @library /test/lib ..
* @library ../../../../java/security/testlibrary
* @modules jdk.crypto.cryptoki
* @run main/othervm ReadCertificates
--- a/test/jdk/sun/security/pkcs11/ec/ReadPKCS12.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/ec/ReadPKCS12.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +26,7 @@
* @bug 6405536
* @summary Verify that we can parse ECPrivateKeys from PKCS#12 and use them
* @author Andreas Sterbenz
- * @library ..
+ * @library /test/lib ..
* @library ../../../../java/security/testlibrary
* @key randomness
* @modules jdk.crypto.cryptoki
--- a/test/jdk/sun/security/pkcs11/ec/TestCurves.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/ec/TestCurves.java Thu Aug 23 11:09:16 2018 -0400
@@ -26,7 +26,7 @@
* @bug 6405536 6414980
* @summary Basic consistency test for all curves using ECDSA and ECDH
* @author Andreas Sterbenz
- * @library ..
+ * @library /test/lib ..
* @modules jdk.crypto.cryptoki/sun.security.pkcs11.wrapper
* @run main/othervm TestCurves
* @run main/othervm TestCurves sm
--- a/test/jdk/sun/security/pkcs11/ec/TestECDH.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/ec/TestECDH.java Thu Aug 23 11:09:16 2018 -0400
@@ -26,7 +26,7 @@
* @bug 6405536
* @summary Basic known answer test for ECDH
* @author Andreas Sterbenz
- * @library ..
+ * @library /test/lib ..
* @library ../../../../java/security/testlibrary
* @modules jdk.crypto.cryptoki
* @run main/othervm TestECDH
--- a/test/jdk/sun/security/pkcs11/ec/TestECDH2.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/ec/TestECDH2.java Thu Aug 23 11:09:16 2018 -0400
@@ -26,7 +26,7 @@
* @bug 6405536
* @summary basic test of ECDSA signatures for P-256 and P-384 from the
* example data in "Suite B Implementer's Guide to FIPS 186-3".
- * @library ..
+ * @library /test/lib ..
* @library ../../../../java/security/testlibrary
* @modules java.base/sun.security.util
* jdk.crypto.cryptoki
--- a/test/jdk/sun/security/pkcs11/ec/TestECDSA.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/ec/TestECDSA.java Thu Aug 23 11:09:16 2018 -0400
@@ -26,7 +26,7 @@
* @bug 6405536 8042967
* @summary basic test of SHA1withECDSA and NONEwithECDSA signing/verifying
* @author Andreas Sterbenz
- * @library ..
+ * @library /test/lib ..
* @library ../../../../java/security/testlibrary
* @key randomness
* @modules jdk.crypto.cryptoki
--- a/test/jdk/sun/security/pkcs11/ec/TestECDSA2.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/ec/TestECDSA2.java Thu Aug 23 11:09:16 2018 -0400
@@ -26,7 +26,7 @@
* @bug 6405536
* @summary basic test of ECDSA signatures for P-256 and P-384 from the
* example data in "Suite B Implementer's Guide to FIPS 186-3".
- * @library ..
+ * @library /test/lib ..
* @library ../../../../java/security/testlibrary
* @modules java.base/sun.security.util
* jdk.crypto.cryptoki
--- a/test/jdk/sun/security/pkcs11/ec/TestECGenSpec.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/ec/TestECGenSpec.java Thu Aug 23 11:09:16 2018 -0400
@@ -26,7 +26,7 @@
* @bug 6405536
* @summary Verify that we can use ECGenParameterSpec
* @author Andreas Sterbenz
- * @library ..
+ * @library /test/lib ..
* @modules jdk.crypto.cryptoki
* @run main/othervm TestECGenSpec
* @run main/othervm TestECGenSpec sm
--- a/test/jdk/sun/security/pkcs11/ec/TestKeyFactory.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/ec/TestKeyFactory.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +26,7 @@
* @bug 6405536
* @summary Test the P11ECKeyFactory
* @author Andreas Sterbenz
- * @library ..
+ * @library /test/lib ..
* @modules jdk.crypto.cryptoki
* @run main/othervm TestKeyFactory
* @run main/othervm TestKeyFactory sm
--- a/test/jdk/sun/security/pkcs11/fips/ClientJSSEServerJSSE.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/fips/ClientJSSEServerJSSE.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
* 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 6313675 6323647 8028192
* @summary Verify that all ciphersuites work in FIPS mode
- * @library ..
+ * @library /test/lib ..
* @author Andreas Sterbenz
* @modules java.base/com.sun.net.ssl.internal.ssl
* @run main/manual ClientJSSEServerJSSE
--- a/test/jdk/sun/security/pkcs11/fips/TrustManagerTest.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/fips/TrustManagerTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +26,7 @@
* @bug 6323647
* @summary Verify that the SunJSSE trustmanager works correctly in FIPS mode
* @author Andreas Sterbenz
- * @library ..
+ * @library /test/lib ..
* @modules java.base/com.sun.net.ssl.internal.ssl
* @run main/othervm TrustManagerTest
* @run main/othervm TrustManagerTest sm TrustManagerTest.policy
Binary file test/jdk/sun/security/pkcs11/nss/lib/macosx-x86_64/libfreebl3.dylib has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/macosx-x86_64/libnspr4.dylib has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/macosx-x86_64/libnss3.dylib has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/macosx-x86_64/libnssckbi.dylib has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/macosx-x86_64/libnssdbm3.dylib has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/macosx-x86_64/libnssutil3.dylib has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/macosx-x86_64/libplc4.dylib has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/macosx-x86_64/libplds4.dylib has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/macosx-x86_64/libsoftokn3.dylib has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/macosx-x86_64/libsqlite3.dylib has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/macosx-x86_64/libssl3.dylib has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/windows-amd64/freebl3.chk has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/windows-amd64/freebl3.dll has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/windows-amd64/nspr4.dll has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/windows-amd64/nspr4.lib has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/windows-amd64/nss3.dll has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/windows-amd64/nss3.lib has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/windows-amd64/nssckbi.dll has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/windows-amd64/nssdbm3.chk has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/windows-amd64/nssdbm3.dll has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/windows-amd64/nssutil3.dll has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/windows-amd64/nssutil3.lib has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/windows-amd64/plc4.dll has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/windows-amd64/plc4.lib has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/windows-amd64/plds4.dll has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/windows-amd64/plds4.lib has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/windows-amd64/softokn3.chk has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/windows-amd64/softokn3.dll has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/windows-amd64/sqlite3.dll has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/windows-amd64/ssl3.dll has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/windows-amd64/ssl3.lib has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/windows-i586/freebl3.chk has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/windows-i586/freebl3.dll has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/windows-i586/nspr4.dll has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/windows-i586/nspr4.lib has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/windows-i586/nss3.dll has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/windows-i586/nss3.lib has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/windows-i586/nssckbi.dll has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/windows-i586/nssdbm3.chk has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/windows-i586/nssdbm3.dll has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/windows-i586/nssutil3.dll has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/windows-i586/nssutil3.lib has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/windows-i586/plc4.dll has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/windows-i586/plc4.lib has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/windows-i586/plds4.dll has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/windows-i586/plds4.lib has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/windows-i586/softokn3.chk has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/windows-i586/softokn3.dll has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/windows-i586/sqlite3.dll has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/windows-i586/ssl3.dll has changed
Binary file test/jdk/sun/security/pkcs11/nss/lib/windows-i586/ssl3.lib has changed
--- a/test/jdk/sun/security/pkcs11/rsa/KeyWrap.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/rsa/KeyWrap.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +26,7 @@
* @bug 6231216
* @summary Verify key wrapping (of extractable keys) works for RSA/PKCS1
* @author Andreas Sterbenz
- * @library ..
+ * @library /test/lib ..
* @key randomness
* @modules jdk.crypto.cryptoki
* @run main/othervm KeyWrap
--- a/test/jdk/sun/security/pkcs11/rsa/TestCACerts.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/rsa/TestCACerts.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +26,7 @@
* @bug 4856966
* @summary Test the new RSA provider can verify all the RSA certs in the cacerts file
* @author Andreas Sterbenz
- * @library ..
+ * @library /test/lib ..
* @library ../../../../java/security/testlibrary
* @modules jdk.crypto.cryptoki
* @run main/othervm TestCACerts
--- a/test/jdk/sun/security/pkcs11/rsa/TestKeyFactory.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/rsa/TestKeyFactory.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +26,7 @@
* @bug 4856966
* @summary Test KeyFactory of the new RSA provider
* @author Andreas Sterbenz
- * @library ..
+ * @library /test/lib ..
* @modules jdk.crypto.cryptoki
* @run main/othervm TestKeyFactory
* @run main/othervm TestKeyFactory sm rsakeys.ks.policy
--- a/test/jdk/sun/security/pkcs11/rsa/TestSignatures.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/rsa/TestSignatures.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +26,7 @@
* @bug 4856966
* @summary Test signing/verifying using all the signature algorithms
* @author Andreas Sterbenz
- * @library ..
+ * @library /test/lib ..
* @key randomness
* @modules jdk.crypto.cryptoki
* @run main/othervm TestSignatures
--- a/test/jdk/sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java Thu Aug 23 11:09:16 2018 -0400
@@ -31,7 +31,7 @@
* @bug 6405536
* @summary Verify that all ciphersuites work (incl. ECC using NSS crypto)
* @author Andreas Sterbenz
- * @library .. ../../../../javax/net/ssl/TLSCommon
+ * @library /test/lib .. ../../../../javax/net/ssl/TLSCommon
* @library ../../../../java/security/testlibrary
* @modules jdk.crypto.cryptoki
* @run main/othervm -Djdk.tls.namedGroups="secp256r1,sect193r1"
--- a/test/jdk/sun/security/pkcs11/tls/TestKeyMaterial.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/tls/TestKeyMaterial.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +26,7 @@
* @bug 6316539 8136355
* @summary Known-answer-test for TlsKeyMaterial generator
* @author Andreas Sterbenz
- * @library ..
+ * @library /test/lib ..
* @modules java.base/sun.security.internal.spec
* jdk.crypto.cryptoki
* @run main/othervm TestKeyMaterial
--- a/test/jdk/sun/security/pkcs11/tls/TestLeadingZeroesP11.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/tls/TestLeadingZeroesP11.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* 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 8014618
* @summary Need to strip leading zeros in TlsPremasterSecret of DHKeyAgreement
- * @library ..
+ * @library /test/lib ..
* @author Pasi Eronen
* @modules jdk.crypto.cryptoki
* @run main/othervm TestLeadingZeroesP11
--- a/test/jdk/sun/security/pkcs11/tls/TestMasterSecret.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/tls/TestMasterSecret.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +26,7 @@
* @bug 6316539 8136355
* @summary Known-answer-test for TlsMasterSecret generator
* @author Andreas Sterbenz
- * @library ..
+ * @library /test/lib ..
* @modules java.base/sun.security.internal.interfaces
* java.base/sun.security.internal.spec
* jdk.crypto.cryptoki
--- a/test/jdk/sun/security/pkcs11/tls/TestPRF.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/tls/TestPRF.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +26,7 @@
* @bug 6316539 6345251
* @summary Basic known-answer-test for TlsPrf
* @author Andreas Sterbenz
- * @library ..
+ * @library /test/lib ..
* @modules java.base/sun.security.internal.spec
* jdk.crypto.cryptoki
* @run main/othervm TestPRF
--- a/test/jdk/sun/security/pkcs11/tls/TestPremaster.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/tls/TestPremaster.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,7 +26,7 @@
* @bug 6316539 8136355
* @summary Basic tests for TlsRsaPremasterSecret generator
* @author Andreas Sterbenz
- * @library ..
+ * @library /test/lib ..
* @modules java.base/sun.security.internal.spec
* jdk.crypto.cryptoki
* @run main/othervm TestPremaster
--- a/test/jdk/sun/security/ssl/AppInputStream/ReadBlocksClose.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/ssl/AppInputStream/ReadBlocksClose.java Thu Aug 23 11:09:16 2018 -0400
@@ -21,14 +21,16 @@
* questions.
*/
+//
+// SunJSSE does not support dynamic system properties, no way to re-use
+// system properties in samevm/agentvm mode.
+//
+
/*
* @test
* @bug 4814140
* @summary AppInputStream: read can block a close
- * @run main/othervm ReadBlocksClose
- *
- * SunJSSE does not support dynamic system properties, no way to re-use
- * system properties in samevm/agentvm mode.
+ * @run main/othervm -Djdk.tls.acknowledgeCloseNotify=true ReadBlocksClose
* @author Brad Wetmore
*/
@@ -141,7 +143,8 @@
System.out.println("Closing Thread started");
Thread.sleep(3000);
System.out.println("Closing Thread closing");
- sslIS.close();
+ sslOS.close();
+ System.out.println("Closing Thread closed");
} catch (Exception e) {
RuntimeException rte =
new RuntimeException("Check this out");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/security/ssl/CipherSuite/NoDesRC4CiphSuite.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,346 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * 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 8208350
+ * @summary Disable all DES cipher suites
+ * @run main/othervm NoDesRC4CiphSuite
+ */
+
+/*
+ * SunJSSE does not support dynamic system properties, no way to re-use
+ * system properties in samevm/agentvm mode.
+ */
+
+import java.security.Security;
+import javax.net.ssl.*;
+import javax.net.ssl.SSLEngineResult.HandshakeStatus;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.security.GeneralSecurityException;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+public class NoDesRC4CiphSuite {
+
+ private static final boolean DEBUG = false;
+
+ private static final byte RECTYPE_HS = 0x16;
+ private static final byte HSMSG_CLIHELLO = 0x01;
+
+ // These are some groups of Cipher Suites by names and IDs
+ private static final List<Integer> DES_CS_LIST = Arrays.asList(
+ 0x0009, 0x0015, 0x0012, 0x001A, 0x0008, 0x0014, 0x0011, 0x0019
+ );
+ private static final String[] DES_CS_LIST_NAMES = new String[] {
+ "SSL_RSA_WITH_DES_CBC_SHA",
+ "SSL_DHE_RSA_WITH_DES_CBC_SHA",
+ "SSL_DHE_DSS_WITH_DES_CBC_SHA",
+ "SSL_DH_anon_WITH_DES_CBC_SHA",
+ "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
+ "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
+ "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA",
+ "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA"
+ };
+ private static final List<Integer> RC4_CS_LIST = Arrays.asList(
+ 0xC007, 0xC011, 0x0005, 0xC002, 0xC00C, 0x0004, 0xC016, 0x0018,
+ 0x0003, 0x0017
+ );
+ private static final String[] RC4_CS_LIST_NAMES = new String[] {
+ "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
+ "TLS_ECDHE_RSA_WITH_RC4_128_SHA",
+ "SSL_RSA_WITH_RC4_128_SHA",
+ "TLS_ECDH_ECDSA_WITH_RC4_128_SHA",
+ "TLS_ECDH_RSA_WITH_RC4_128_SHA",
+ "SSL_RSA_WITH_RC4_128_MD5",
+ "TLS_ECDH_anon_WITH_RC4_128_SHA",
+ "SSL_DH_anon_WITH_RC4_128_MD5",
+ "SSL_RSA_EXPORT_WITH_RC4_40_MD5",
+ "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5"
+ };
+
+ private static final ByteBuffer CLIOUTBUF =
+ ByteBuffer.wrap("Client Side".getBytes());
+
+ public static void main(String[] args) throws Exception {
+ boolean allGood = true;
+ String disAlg = Security.getProperty("jdk.tls.disabledAlgorithms");
+ System.err.println("Disabled Algs: " + disAlg);
+
+ // Disabled DES tests
+ allGood &= testDefaultCase(DES_CS_LIST);
+ allGood &= testEngAddDisabled(DES_CS_LIST_NAMES, DES_CS_LIST);
+ allGood &= testEngOnlyDisabled(DES_CS_LIST_NAMES);
+
+ // Disabled RC4 tests
+ allGood &= testDefaultCase(RC4_CS_LIST);
+ allGood &= testEngAddDisabled(RC4_CS_LIST_NAMES, RC4_CS_LIST);
+ allGood &= testEngOnlyDisabled(RC4_CS_LIST_NAMES);
+
+ if (allGood) {
+ System.err.println("All tests passed");
+ } else {
+ throw new RuntimeException("One or more tests failed");
+ }
+ }
+
+ /**
+ * Create an engine with the default set of cipher suites enabled and make
+ * sure none of the disabled suites are present in the client hello.
+ *
+ * @param disabledSuiteIds the {@code List} of disabled cipher suite IDs
+ * to be checked for.
+ *
+ * @return true if the test passed (No disabled suites), false otherwise
+ */
+ private static boolean testDefaultCase(List<Integer> disabledSuiteIds)
+ throws Exception {
+ System.err.println("\nTest: Default SSLEngine suite set");
+ SSLEngine ssle = makeEngine();
+ if (DEBUG) {
+ listCiphers("Suite set upon creation", ssle);
+ }
+ SSLEngineResult clientResult;
+ ByteBuffer cTOs = makeClientBuf(ssle);
+ clientResult = ssle.wrap(CLIOUTBUF, cTOs);
+ if (DEBUG) {
+ dumpResult("ClientHello: ", clientResult);
+ }
+ cTOs.flip();
+ boolean foundSuite = areSuitesPresentCH(cTOs, disabledSuiteIds);
+ if (foundSuite) {
+ System.err.println("FAIL: Found disabled suites!");
+ return false;
+ } else {
+ System.err.println("PASS: No disabled suites found.");
+ return true;
+ }
+ }
+
+ /**
+ * Create an engine and set only disabled cipher suites.
+ * The engine should not create the client hello message since the only
+ * available suites to assert in the client hello are disabled ones.
+ *
+ * @param disabledSuiteNames an array of cipher suite names that
+ * should be disabled cipher suites.
+ *
+ * @return true if the engine throws SSLHandshakeException during client
+ * hello creation, false otherwise.
+ */
+ private static boolean testEngOnlyDisabled(String[] disabledSuiteNames)
+ throws Exception {
+ System.err.println(
+ "\nTest: SSLEngine configured with only disabled suites");
+ try {
+ SSLEngine ssle = makeEngine();
+ ssle.setEnabledCipherSuites(disabledSuiteNames);
+ if (DEBUG) {
+ listCiphers("Suite set upon creation", ssle);
+ }
+ SSLEngineResult clientResult;
+ ByteBuffer cTOs = makeClientBuf(ssle);
+ clientResult = ssle.wrap(CLIOUTBUF, cTOs);
+ if (DEBUG) {
+ dumpResult("ClientHello: ", clientResult);
+ }
+ cTOs.flip();
+ } catch (SSLHandshakeException shse) {
+ System.err.println("PASS: Caught expected exception: " + shse);
+ return true;
+ }
+ System.err.println("FAIL: Expected SSLHandshakeException not thrown");
+ return false;
+ }
+
+ /**
+ * Create an engine and add some disabled suites to the default
+ * set of cipher suites. Make sure none of the disabled suites show up
+ * in the client hello even though they were explicitly added.
+ *
+ * @param disabledSuiteNames an array of cipher suite names that
+ * should be disabled cipher suites.
+ * @param disabledIds the {@code List} of disabled cipher suite IDs
+ * to be checked for.
+ *
+ * @return true if the test passed (No disabled suites), false otherwise
+ */
+ private static boolean testEngAddDisabled(String[] disabledNames,
+ List<Integer> disabledIds) throws Exception {
+ System.err.println("\nTest: SSLEngine with disabled suites added");
+ SSLEngine ssle = makeEngine();
+
+ // Add disabled suites to the existing engine's set of enabled suites
+ String[] initialSuites = ssle.getEnabledCipherSuites();
+ String[] plusDisSuites = Arrays.copyOf(initialSuites,
+ initialSuites.length + disabledNames.length);
+ System.arraycopy(disabledNames, 0, plusDisSuites,
+ initialSuites.length, disabledNames.length);
+ ssle.setEnabledCipherSuites(plusDisSuites);
+
+ if (DEBUG) {
+ listCiphers("Suite set upon creation", ssle);
+ }
+ SSLEngineResult clientResult;
+ ByteBuffer cTOs = makeClientBuf(ssle);
+ clientResult = ssle.wrap(CLIOUTBUF, cTOs);
+ if (DEBUG) {
+ dumpResult("ClientHello: ", clientResult);
+ }
+ cTOs.flip();
+ boolean foundDisabled = areSuitesPresentCH(cTOs, disabledIds);
+ if (foundDisabled) {
+ System.err.println("FAIL: Found disabled suites!");
+ return false;
+ } else {
+ System.err.println("PASS: No disabled suites found.");
+ return true;
+ }
+ }
+
+ private static SSLEngine makeEngine() throws GeneralSecurityException {
+ SSLContext ctx = SSLContext.getInstance("TLSv1.2");
+ ctx.init(null, null, null);
+ return ctx.createSSLEngine();
+ }
+
+ private static ByteBuffer makeClientBuf(SSLEngine ssle) {
+ ssle.setUseClientMode(true);
+ ssle.setNeedClientAuth(false);
+ SSLSession sess = ssle.getSession();
+ ByteBuffer cTOs = ByteBuffer.allocateDirect(sess.getPacketBufferSize());
+ return cTOs;
+ }
+
+ private static void listCiphers(String prefix, SSLEngine ssle) {
+ System.err.println(prefix + "\n---------------");
+ String[] suites = ssle.getEnabledCipherSuites();
+ for (String suite : suites) {
+ System.err.println(suite);
+ }
+ System.err.println("---------------");
+ }
+
+ /**
+ * Walk a TLS 1.2 or earlier ClientHello looking for any of the suites
+ * in the suiteIdList.
+ *
+ * @param clientHello a ByteBuffer containing the ClientHello message as
+ * a complete TLS record. The position of the buffer should be
+ * at the first byte of the TLS record header.
+ * @param suiteIdList a List of integer values corresponding to
+ * TLS cipher suite identifiers.
+ *
+ * @return true if at least one of the suites in {@code suiteIdList}
+ * is found in the ClientHello's cipher suite list
+ *
+ * @throws IOException if the data in the {@code clientHello}
+ * buffer is not a TLS handshake message or is not a client hello.
+ */
+ private static boolean areSuitesPresentCH(ByteBuffer clientHello,
+ List<Integer> suiteIdList) throws IOException {
+ byte val;
+
+ // Process the TLS Record
+ val = clientHello.get();
+ if (val != RECTYPE_HS) {
+ throw new IOException(
+ "Not a handshake record, type = " + val);
+ }
+
+ // Just skip over the version and length
+ clientHello.position(clientHello.position() + 4);
+
+ // Check the handshake message type
+ val = clientHello.get();
+ if (val != HSMSG_CLIHELLO) {
+ throw new IOException(
+ "Not a ClientHello handshake message, type = " + val);
+ }
+
+ // Skip over the length
+ clientHello.position(clientHello.position() + 3);
+
+ // Skip over the protocol version (2) and random (32);
+ clientHello.position(clientHello.position() + 34);
+
+ // Skip past the session ID (variable length <= 32)
+ int len = Byte.toUnsignedInt(clientHello.get());
+ if (len > 32) {
+ throw new IOException("Session ID is too large, len = " + len);
+ }
+ clientHello.position(clientHello.position() + len);
+
+ // Finally, we are at the cipher suites. Walk the list and place them
+ // into a List.
+ int csLen = Short.toUnsignedInt(clientHello.getShort());
+ if (csLen % 2 != 0) {
+ throw new IOException("CipherSuite length is invalid, len = " +
+ csLen);
+ }
+ int csCount = csLen / 2;
+ List<Integer> csSuiteList = new ArrayList<>(csCount);
+ log("Found following suite IDs in hello:");
+ for (int i = 0; i < csCount; i++) {
+ int curSuite = Short.toUnsignedInt(clientHello.getShort());
+ log(String.format("Suite ID: 0x%04x", curSuite));
+ csSuiteList.add(curSuite);
+ }
+
+ // Now check to see if any of the suites passed in match what is in
+ // the suite list.
+ boolean foundMatch = false;
+ for (Integer cs : suiteIdList) {
+ if (csSuiteList.contains(cs)) {
+ System.err.format("Found match for suite ID 0x%04x\n", cs);
+ foundMatch = true;
+ break;
+ }
+ }
+
+ // We don't care about the rest of the ClientHello message.
+ // Rewind and return whether we found a match or not.
+ clientHello.rewind();
+ return foundMatch;
+ }
+
+ private static void dumpResult(String str, SSLEngineResult result) {
+ System.err.println("The format of the SSLEngineResult is: \n" +
+ "\t\"getStatus() / getHandshakeStatus()\" +\n" +
+ "\t\"bytesConsumed() / bytesProduced()\"\n");
+ HandshakeStatus hsStatus = result.getHandshakeStatus();
+ System.err.println(str + result.getStatus() + "/" + hsStatus + ", " +
+ result.bytesConsumed() + "/" + result.bytesProduced() + " bytes");
+ if (hsStatus == HandshakeStatus.FINISHED) {
+ System.err.println("\t...ready for application data");
+ }
+ }
+
+ private static void log(String str) {
+ if (DEBUG) {
+ System.err.println(str);
+ }
+ }
+}
--- a/test/jdk/sun/security/ssl/SSLContextImpl/CustomizedCipherSuites.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/ssl/SSLContextImpl/CustomizedCipherSuites.java Thu Aug 23 11:09:16 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
* 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,47 +31,47 @@
* @run main/othervm
* CustomizedCipherSuites Default true
* TLS_RSA_WITH_AES_128_CBC_SHA
- * SSL_RSA_WITH_DES_CBC_SHA
+ * TLS_ECDH_anon_WITH_AES_128_CBC_SHA
* @run main/othervm
* -Djdk.tls.client.cipherSuites="unknown"
* CustomizedCipherSuites Default true
* TLS_RSA_WITH_AES_128_CBC_SHA
- * SSL_RSA_WITH_DES_CBC_SHA
+ * TLS_ECDH_anon_WITH_AES_128_CBC_SHA
* @run main/othervm
* -Djdk.tls.client.cipherSuites=""
* CustomizedCipherSuites Default true
* TLS_RSA_WITH_AES_128_CBC_SHA
- * SSL_RSA_WITH_DES_CBC_SHA
+ * TLS_ECDH_anon_WITH_AES_128_CBC_SHA
* @run main/othervm
- * -Djdk.tls.client.cipherSuites="SSL_RSA_WITH_DES_CBC_SHA"
+ * -Djdk.tls.client.cipherSuites="TLS_ECDH_anon_WITH_AES_128_CBC_SHA"
* CustomizedCipherSuites Default true
- * SSL_RSA_WITH_DES_CBC_SHA
+ * TLS_ECDH_anon_WITH_AES_128_CBC_SHA
* TLS_RSA_WITH_AES_128_CBC_SHA
* @run main/othervm
- * -Djdk.tls.server.cipherSuites="SSL_RSA_WITH_DES_CBC_SHA"
+ * -Djdk.tls.server.cipherSuites="TLS_ECDH_anon_WITH_AES_128_CBC_SHA"
* CustomizedCipherSuites Default false
- * SSL_RSA_WITH_DES_CBC_SHA
+ * TLS_ECDH_anon_WITH_AES_128_CBC_SHA
* TLS_RSA_WITH_AES_128_CBC_SHA
* @run main/othervm
- * -Djdk.tls.client.cipherSuites="TLS_RSA_WITH_AES_128_CBC_SHA,unknown,SSL_RSA_WITH_DES_CBC_SHA"
+ * -Djdk.tls.client.cipherSuites="TLS_RSA_WITH_AES_128_CBC_SHA,unknown,TLS_ECDH_anon_WITH_AES_128_CBC_SHA"
* CustomizedCipherSuites Default true
- * SSL_RSA_WITH_DES_CBC_SHA
+ * TLS_ECDH_anon_WITH_AES_128_CBC_SHA
* ""
* @run main/othervm
- * -Djdk.tls.server.cipherSuites="TLS_RSA_WITH_AES_128_CBC_SHA,unknown,SSL_RSA_WITH_DES_CBC_SHA"
+ * -Djdk.tls.server.cipherSuites="TLS_RSA_WITH_AES_128_CBC_SHA,unknown,TLS_ECDH_anon_WITH_AES_128_CBC_SHA"
* CustomizedCipherSuites Default false
* TLS_RSA_WITH_AES_128_CBC_SHA
* ""
* @run main/othervm
- * -Djdk.tls.server.cipherSuites="SSL_RSA_WITH_DES_CBC_SHA"
+ * -Djdk.tls.server.cipherSuites="TLS_ECDH_anon_WITH_AES_128_CBC_SHA"
* CustomizedCipherSuites Default true
* TLS_RSA_WITH_AES_128_CBC_SHA
- * SSL_RSA_WITH_DES_CBC_SHA
+ * TLS_ECDH_anon_WITH_AES_128_CBC_SHA
* @run main/othervm
- * -Djdk.tls.client.cipherSuites="SSL_RSA_WITH_DES_CBC_SHA"
+ * -Djdk.tls.client.cipherSuites="TLS_ECDH_anon_WITH_AES_128_CBC_SHA"
* CustomizedCipherSuites Default false
* TLS_RSA_WITH_AES_128_CBC_SHA
- * SSL_RSA_WITH_DES_CBC_SHA
+ * TLS_ECDH_anon_WITH_AES_128_CBC_SHA
*/
import javax.net.ssl.*;
@@ -79,7 +79,7 @@
/**
* Test the customized default cipher suites.
*
- * This test is based on the behavior that SSL_RSA_WITH_DES_CBC_SHA is
+ * This test is based on the behavior that TLS_ECDH_anon_WITH_AES_128_CBC_SHA is
* disabled by default, and TLS_RSA_WITH_AES_128_CBC_SHA is enabled by
* default in JDK. If the behavior is changed in the future, please
* update the test cases above accordingly.
--- a/test/jdk/sun/security/ssl/SSLEngineImpl/CloseStart.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/ssl/SSLEngineImpl/CloseStart.java Thu Aug 23 11:09:16 2018 -0400
@@ -68,11 +68,6 @@
}
}
- private static void runTest1(SSLEngine ssle) throws Exception {
- ssle.closeInbound();
- checkDone(ssle);
- }
-
private static void runTest2(SSLEngine ssle) throws Exception {
ssle.closeOutbound();
checkDone(ssle);
@@ -81,10 +76,16 @@
public static void main(String args[]) throws Exception {
SSLEngine ssle = createSSLEngine(keyFilename, trustFilename);
- runTest1(ssle);
+ ssle.closeInbound();
+ if (!ssle.isInboundDone()) {
+ throw new Exception("isInboundDone isn't done");
+ }
ssle = createSSLEngine(keyFilename, trustFilename);
- runTest2(ssle);
+ ssle.closeOutbound();
+ if (!ssle.isOutboundDone()) {
+ throw new Exception("isOutboundDone isn't done");
+ }
System.out.println("Test Passed.");
}
--- a/test/jdk/sun/security/ssl/SSLEngineImpl/SSLEngineDeadlock.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/ssl/SSLEngineImpl/SSLEngineDeadlock.java Thu Aug 23 11:09:16 2018 -0400
@@ -280,6 +280,7 @@
log("\tClosing clientEngine's *OUTBOUND*...");
clientEngine.closeOutbound();
+ serverEngine.closeOutbound();
dataDone = true;
}
}
--- a/test/jdk/sun/security/ssl/SSLEngineImpl/SSLEngineKeyLimit.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/ssl/SSLEngineImpl/SSLEngineKeyLimit.java Thu Aug 23 11:09:16 2018 -0400
@@ -127,8 +127,7 @@
output.shouldNotContain("KeyUpdate: write key updated");
output.shouldNotContain("KeyUpdate: read key updated");
} else {
- output.shouldContain("KeyUpdate: triggered, read side");
- output.shouldContain("KeyUpdate: triggered, write side");
+ output.shouldContain("trigger key update");
output.shouldContain("KeyUpdate: write key updated");
output.shouldContain("KeyUpdate: read key updated");
}
--- a/test/jdk/sun/security/ssl/SSLEngineImpl/TLS13BeginHandshake.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/ssl/SSLEngineImpl/TLS13BeginHandshake.java Thu Aug 23 11:09:16 2018 -0400
@@ -106,11 +106,11 @@
checkTransfer(clientOut, serverIn);
System.out.println("\tClosing...");
clientEngine.closeOutbound();
+ serverEngine.closeOutbound();
done++;
continue;
}
}
-
}
private static boolean isEngineClosed(SSLEngine engine) {
--- a/test/jdk/sun/security/ssl/SSLSocketImpl/AsyncSSLSocketClose.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/ssl/SSLSocketImpl/AsyncSSLSocketClose.java Thu Aug 23 11:09:16 2018 -0400
@@ -36,6 +36,7 @@
import javax.net.ssl.*;
import java.io.*;
+import java.net.SocketException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -123,6 +124,9 @@
os.write(ba);
System.out.println(count + " bytes written");
}
+ } catch (SocketException se) {
+ // the closing may be in progress
+ System.out.println("interrupted? " + se);
} catch (Exception e) {
if (socket.isClosed() || socket.isOutputShutdown()) {
System.out.println("interrupted, the socket is closed");
--- a/test/jdk/sun/security/ssl/SSLSocketImpl/SSLSocketKeyLimit.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/ssl/SSLSocketImpl/SSLSocketKeyLimit.java Thu Aug 23 11:09:16 2018 -0400
@@ -119,7 +119,7 @@
System.setProperty("test.java.opts",
"-Dtest.src=" + System.getProperty("test.src") +
" -Dtest.jdk=" + System.getProperty("test.jdk") +
- " -Djavax.net.debug=ssl,handshake " +
+ " -Djavax.net.debug=ssl,handshake" +
" -Djava.security.properties=" + f.getName());
System.out.println("test.java.opts: " +
@@ -134,8 +134,7 @@
output.shouldNotContain("KeyUpdate: write key updated");
output.shouldNotContain("KeyUpdate: read key updated");
} else {
- output.shouldContain("KeyUpdate: triggered, read side");
- output.shouldContain("KeyUpdate: triggered, write side");
+ output.shouldContain("trigger key update");
output.shouldContain("KeyUpdate: write key updated");
output.shouldContain("KeyUpdate: read key updated");
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/security/ssl/SSLSocketImpl/ServerRenegoWithTwoVersions.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,329 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * 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 8208642
+ * @summary Server initiated TLSv1.2 renegotiation fails if Java
+ * client allows TLSv1.3
+ * @run main/othervm ServerRenegoWithTwoVersions TLSv1 SSLv3
+ * @run main/othervm ServerRenegoWithTwoVersions TLSv1 TLSv1.1
+ * @run main/othervm ServerRenegoWithTwoVersions TLSv1.2 TLSv1.1
+ * @run main/othervm ServerRenegoWithTwoVersions TLSv1.3 TLSv1.2
+ */
+
+import java.io.*;
+import java.net.*;
+import java.security.Security;
+import javax.net.ssl.*;
+
+public class ServerRenegoWithTwoVersions implements
+ HandshakeCompletedListener {
+
+ static byte handshakesCompleted = 0;
+
+ /*
+ * Define what happens when handshaking is completed
+ */
+ public void handshakeCompleted(HandshakeCompletedEvent event) {
+ synchronized (this) {
+ handshakesCompleted++;
+ System.out.println("Session: " + event.getSession().toString());
+ System.out.println("Seen handshake completed #" +
+ handshakesCompleted);
+ }
+ }
+
+ /*
+ * =============================================================
+ * 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;
+
+ SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept();
+ sslSocket.setEnabledProtocols(new String[] { serverProtocol });
+ sslSocket.addHandshakeCompletedListener(this);
+ InputStream sslIS = sslSocket.getInputStream();
+ OutputStream sslOS = sslSocket.getOutputStream();
+
+ for (int i = 0; i < 10; i++) {
+ sslIS.read();
+ sslOS.write(85);
+ sslOS.flush();
+ }
+
+ System.out.println("invalidating");
+ sslSocket.getSession().invalidate();
+ System.out.println("starting new handshake");
+ sslSocket.startHandshake();
+
+ for (int i = 0; i < 10; i++) {
+ System.out.println("sending/receiving data, iteration: " + i);
+ sslIS.read();
+ sslOS.write(85);
+ sslOS.flush();
+ }
+
+ sslSocket.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);
+ sslSocket.setEnabledProtocols(
+ new String[] { serverProtocol, clientProtocol });
+
+ InputStream sslIS = sslSocket.getInputStream();
+ OutputStream sslOS = sslSocket.getOutputStream();
+
+ for (int i = 0; i < 10; i++) {
+ sslOS.write(280);
+ sslOS.flush();
+ sslIS.read();
+ }
+
+ for (int i = 0; i < 10; i++) {
+ sslOS.write(280);
+ sslOS.flush();
+ sslIS.read();
+ }
+
+ 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;
+
+ // the specified protocol
+ private static String clientProtocol;
+ private static String serverProtocol;
+
+ 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");
+ }
+
+ Security.setProperty("jdk.tls.disabledAlgorithms", "");
+
+ clientProtocol = args[0];
+ serverProtocol = args[1];
+
+ /*
+ * Start the tests.
+ */
+ new ServerRenegoWithTwoVersions();
+ }
+
+ Thread clientThread = null;
+ Thread serverThread = null;
+
+ /*
+ * Primary constructor, used to drive remainder of the test.
+ *
+ * Fork off the other side, then do your work.
+ */
+ ServerRenegoWithTwoVersions() throws Exception {
+ if (separateServerThread) {
+ startServer(true);
+ startClient(false);
+ } else {
+ startClient(true);
+ startServer(false);
+ }
+
+ /*
+ * Wait for other side to close down.
+ */
+ if (separateServerThread) {
+ serverThread.join();
+ } else {
+ clientThread.join();
+ }
+
+ /*
+ * When we get here, the test is pretty much over.
+ *
+ * If the main thread excepted, that propagates back
+ * immediately. If the other thread threw an exception, we
+ * should report back.
+ */
+ if (serverException != null) {
+ System.out.print("Server Exception:");
+ throw serverException;
+ }
+ if (clientException != null) {
+ System.out.print("Client Exception:");
+ throw clientException;
+ }
+
+ /*
+ * Give the Handshaker Thread a chance to run
+ */
+ Thread.sleep(1000);
+
+ synchronized (this) {
+ if (handshakesCompleted != 2) {
+ throw new Exception("Didn't see 2 handshake completed events.");
+ }
+ }
+ }
+
+ void startServer(boolean newThread) throws Exception {
+ if (newThread) {
+ serverThread = new Thread() {
+ 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 {
+ doServerSide();
+ }
+ }
+
+ void startClient(boolean newThread) throws Exception {
+ if (newThread) {
+ clientThread = new Thread() {
+ public void run() {
+ try {
+ doClientSide();
+ } catch (Exception e) {
+ /*
+ * Our client thread just died.
+ */
+ System.err.println("Client died...");
+ clientException = e;
+ }
+ }
+ };
+ clientThread.start();
+ } else {
+ doClientSide();
+ }
+ }
+}
--- a/test/jdk/sun/security/tools/keytool/autotest.sh Fri Aug 10 14:56:29 2018 -0700
+++ b/test/jdk/sun/security/tools/keytool/autotest.sh Thu Aug 23 11:09:16 2018 -0400
@@ -86,9 +86,6 @@
"/usr/lib/nss/libsoftokn3.so"`
fi
;;
- Darwin )
- LIBNAME="$TESTSRC/../../pkcs11/nss/lib/macosx-x86_64/libsoftokn3.dylib"
- ;;
* )
echo "Will not run test on: ${OS}"
exit 0;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testHeadTag/TestHeadTag.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * 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 8203792
+ * @summary Remove "compatibility" features from Head.java
+ * @library /tools/lib ../lib
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
+ * @build JavadocTester toolbox.ToolBox builder.ClassBuilder
+ * @run main TestHeadTag
+ */
+
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.time.LocalDate;
+
+import builder.ClassBuilder;
+import toolbox.ToolBox;
+
+public class TestHeadTag extends JavadocTester {
+
+ final ToolBox tb;
+
+ public static void main(String... args) throws Exception {
+ TestHeadTag tester = new TestHeadTag();
+ tester.runTests(m -> new Object[]{Paths.get(m.getName())});
+ }
+
+ TestHeadTag() {
+ tb = new ToolBox();
+ }
+
+ @Test
+ void test(Path base) throws Exception {
+ Path srcDir = base.resolve("src");
+ createTestClass(srcDir);
+
+ Path outDir = base.resolve("out");
+ javadoc("-d", outDir.toString(),
+ "-sourcepath", srcDir.toString(),
+ "pkg");
+
+ checkExit(Exit.OK);
+
+ checkOrder("pkg/A.html",
+ "Generated by javadoc",
+ "<meta name=\"dc.created\"");
+ }
+
+ @Test
+ void testWithNoTimestamp(Path base) throws Exception {
+ Path srcDir = base.resolve("src");
+ createTestClass(srcDir);
+
+ Path outDir = base.resolve("out-1");
+ javadoc("-d", outDir.toString(),
+ "-notimestamp",
+ "-sourcepath", srcDir.toString(),
+ "pkg");
+
+ checkExit(Exit.OK);
+
+ checkOutput("pkg/A.html", true,
+ "<!-- Generated by javadoc -->");
+ checkOutput("pkg/A.html", false,
+ "<meta name=\"dc.created\"");
+ }
+
+ void createTestClass(Path srcDir) throws Exception {
+ new ClassBuilder(tb, "pkg.A")
+ .setModifiers("public", "class")
+ .write(srcDir);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/jdk/javadoc/tool/MultiReleaseJar/TestMultiRelease.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * 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 8208269
+ * @summary Verify module-infos are read from the correct place in multi-release jars
+ * @library /tools/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.main
+ * jdk.javadoc/jdk.javadoc.internal.api
+ * jdk.javadoc/jdk.javadoc.internal.tool
+ * @build toolbox.JavacTask toolbox.JavadocTask toolbox.TestRunner toolbox.ToolBox
+ * @run main TestMultiRelease
+ */
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+
+import toolbox.JarTask;
+import toolbox.JavacTask;
+import toolbox.JavadocTask;
+import toolbox.Task.Expect;
+import toolbox.TestRunner;
+import toolbox.ToolBox;
+
+public class TestMultiRelease extends TestRunner {
+
+ public static void main(String... args) throws Exception {
+ TestMultiRelease t = new TestMultiRelease();
+ t.runTests(m -> new Object[] { Paths.get(m.getName()) });
+ }
+
+ private final ToolBox tb = new ToolBox();
+
+ TestMultiRelease() throws IOException {
+ super(System.err);
+ }
+
+ @Test
+ public void testMultiReleaseModule(Path base) throws Exception {
+ Files.createDirectory(base);
+
+ Path module = base.resolve("module");
+ Path moduleSrc = module.resolve("src");
+ Path moduleCls = module.resolve("classes");
+
+ tb.writeJavaFiles(moduleSrc, "module test.module { }");
+
+ Files.createDirectories(moduleCls);
+
+ new JavacTask(tb)
+ .outdir(moduleCls)
+ .files(tb.findJavaFiles(moduleSrc))
+ .run()
+ .writeAll();
+
+ Path moduleJarDir = module.resolve("jar-dir");
+ Path versions = moduleJarDir.resolve("META-INF/versions/10");
+
+ Files.createDirectories(versions);
+
+ Files.copy(moduleCls.resolve("module-info.class"),
+ versions.resolve("module-info.class"));
+
+ Path moduleJar = module.resolve("module.jar");
+
+ new JarTask(tb, moduleJar)
+ .baseDir(moduleJarDir)
+ .files(Arrays.stream(tb.findFiles("class", moduleJarDir))
+ .map(p -> moduleJarDir.relativize(p).toString())
+ .toArray(s -> new String[s]))
+ .manifest("Multi-Release: true\n\n")
+ .run();
+
+ Path src = base.resolve("src");
+
+ tb.writeJavaFiles(src,
+ "module m { requires test.module; exports api; }",
+ "package api; public class Api { }");
+ Path out = base.resolve("out");
+ Files.createDirectory(out);
+
+ JavadocTask task = new JavadocTask(tb);
+ task.outdir(out)
+ .options("--module-path", moduleJar.toString(),
+ "-source", "10")
+ .files(tb.findJavaFiles(src))
+ .run(Expect.SUCCESS);
+
+ task.outdir(out)
+ .options("--module-path", moduleJar.toString(),
+ "-source", "9")
+ .files(tb.findJavaFiles(src))
+ .run(Expect.FAIL);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/T8207320/IntersectionOrderTest.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * 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 8207320
+ * @summary Wrong type order for intersection lambdas with multiple abstract methods
+ */
+
+public class IntersectionOrderTest {
+ interface A {
+ void a();
+ }
+
+ interface AB extends A {
+ default void a() {
+ System.out.println("A");
+ }
+ default void b() {
+ System.out.println("B");
+ }
+ }
+
+ public static void main(String... args) {
+ Object o = new AB() {};
+ Runnable r = ((A & AB) o)::b;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/T8207320/IntersectionOrderTest2.java Thu Aug 23 11:09:16 2018 -0400
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * 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 8207320
+ * @summary Wrong type order for intersection lambdas with multiple abstract methods
+ */
+
+public class IntersectionOrderTest2 {
+ interface A {
+ void a();
+ }
+
+ interface B {
+ void b();
+ }
+
+ interface C {
+ void c();
+ }
+
+ interface AB extends A, B {
+ @Override
+ default void a() {
+ System.out.println("A");
+ }
+
+ @Override
+ default void b() {
+ System.out.println("B");
+ }
+ }
+
+ public static void main(String[] args) {
+ Runnable a = ((A & B & AB & C) () -> System.out.println("Called"))::b;
+ a.run();
+ }
+}
--- a/test/lib/jdk/test/lib/Utils.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/lib/jdk/test/lib/Utils.java Thu Aug 23 11:09:16 2018 -0400
@@ -612,7 +612,7 @@
* @param runnable what we run
* @param expectedException expected exception
*/
- public static void runAndCheckException(Runnable runnable, Class<? extends Throwable> expectedException) {
+ public static void runAndCheckException(ThrowingRunnable runnable, Class<? extends Throwable> expectedException) {
runAndCheckException(runnable, t -> {
if (t == null) {
if (expectedException != null) {
@@ -635,13 +635,14 @@
* @param runnable what we run
* @param checkException a consumer which checks that we got expected exception and raises a new exception otherwise
*/
- public static void runAndCheckException(Runnable runnable, Consumer<Throwable> checkException) {
+ public static void runAndCheckException(ThrowingRunnable runnable, Consumer<Throwable> checkException) {
+ Throwable throwable = null;
try {
runnable.run();
- checkException.accept(null);
} catch (Throwable t) {
- checkException.accept(t);
+ throwable = t;
}
+ checkException.accept(throwable);
}
/**
--- a/test/lib/jdk/test/lib/cds/CDSTestUtils.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/lib/jdk/test/lib/cds/CDSTestUtils.java Thu Aug 23 11:09:16 2018 -0400
@@ -32,10 +32,15 @@
import jdk.test.lib.Utils;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
-
+import jtreg.SkippedException;
// This class contains common test utilities for testing CDS
public class CDSTestUtils {
+ public static final String MSG_RANGE_NOT_WITHIN_HEAP =
+ "UseSharedSpaces: Unable to allocate region, range is not within java heap.";
+ public static final String MSG_RANGE_ALREADT_IN_USE =
+ "Unable to allocate region, java heap range is already in use.";
+
public interface Checker {
public void check(OutputAnalyzer output) throws Exception;
}
@@ -114,17 +119,14 @@
public static class Result {
private final OutputAnalyzer output;
private final CDSOptions options;
- private final boolean hasMappingFailure;
- private final boolean hasAbnormalExit;
private final boolean hasNormalExit;
private final String CDS_DISABLED = "warning: CDS is disabled when the";
public Result(CDSOptions opts, OutputAnalyzer out) throws Exception {
- options = opts;
- output = out;
- hasMappingFailure = CDSTestUtils.checkCommonExecExceptions(output);
- hasAbnormalExit = (!hasMappingFailure) && (output.getExitValue() != 0);
- hasNormalExit = (!hasMappingFailure) && (output.getExitValue() == 0);
+ checkMappingFailure(out);
+ this.options = opts;
+ this.output = out;
+ hasNormalExit = (output.getExitValue() == 0);
if (hasNormalExit) {
if ("on".equals(options.xShareMode) &&
@@ -138,30 +140,22 @@
}
public Result assertNormalExit(Checker checker) throws Exception {
- if (!hasMappingFailure) {
- checker.check(output);
- output.shouldHaveExitValue(0);
- }
+ checker.check(output);
+ output.shouldHaveExitValue(0);
return this;
}
public Result assertAbnormalExit(Checker checker) throws Exception {
- if (!hasMappingFailure) {
- checker.check(output);
- output.shouldNotHaveExitValue(0);
- }
+ checker.check(output);
+ output.shouldNotHaveExitValue(0);
return this;
}
// When {--limit-modules, --patch-module, and/or --upgrade-module-path}
// are specified, CDS is silently disabled for both -Xshare:auto and -Xshare:on.
public Result assertSilentlyDisabledCDS(Checker checker) throws Exception {
- if (hasMappingFailure) {
- throw new RuntimeException("Unexpected mapping failure");
- }
// this comes from a JVM warning message.
output.shouldContain(CDS_DISABLED);
-
checker.check(output);
return this;
}
@@ -181,34 +175,27 @@
}
public Result ifAbnormalExit(Checker checker) throws Exception {
- if (hasAbnormalExit) {
+ if (!hasNormalExit) {
checker.check(output);
}
return this;
}
public Result ifNoMappingFailure(Checker checker) throws Exception {
- if (!hasMappingFailure) {
- checker.check(output);
- }
+ checker.check(output);
return this;
}
public Result assertNormalExit(String... matches) throws Exception {
- if (!hasMappingFailure) {
- checkMatches(output, matches);
- output.shouldHaveExitValue(0);
- }
+ checkMatches(output, matches);
+ output.shouldHaveExitValue(0);
return this;
}
public Result assertAbnormalExit(String... matches) throws Exception {
- if (!hasMappingFailure) {
- checkMatches(output, matches);
- output.shouldNotHaveExitValue(0);
- }
-
+ checkMatches(output, matches);
+ output.shouldNotHaveExitValue(0);
return this;
}
}
@@ -223,7 +210,7 @@
public static final String TestTimeoutFactor = System.getProperty("test.timeout.factor", "1.0");
public static final String UnableToMapMsg =
- "Unable to map shared archive: test did not complete; assumed PASS";
+ "Unable to map shared archive: test did not complete";
// Create bootstrap CDS archive,
// use extra JVM command line args as a prefix.
@@ -295,7 +282,7 @@
// of exceptions and common errors.
// Exception e argument - an exception to be re-thrown if none of the common
// exceptions match. Pass null if you wish not to re-throw any exception.
- public static boolean checkCommonExecExceptions(OutputAnalyzer output, Exception e)
+ public static void checkCommonExecExceptions(OutputAnalyzer output, Exception e)
throws Exception {
if (output.getStdout().contains("http://bugreport.java.com/bugreport/crash.jsp")) {
throw new RuntimeException("Hotspot crashed");
@@ -303,9 +290,6 @@
if (output.getStdout().contains("TEST FAILED")) {
throw new RuntimeException("Test Failed");
}
- if (output.getOutput().contains("shared class paths mismatch")) {
-// throw new RuntimeException("shared class paths mismatch");
- }
if (output.getOutput().contains("Unable to unmap shared space")) {
throw new RuntimeException("Unable to unmap shared space");
}
@@ -314,18 +298,16 @@
// at given address. This behavior is platform-specific, machine config-specific
// and can be random (see ASLR).
if (isUnableToMap(output)) {
- System.out.println(UnableToMapMsg);
- return true;
+ throw new SkippedException(UnableToMapMsg);
}
if (e != null) {
throw e;
}
- return false;
}
- public static boolean checkCommonExecExceptions(OutputAnalyzer output) throws Exception {
- return checkCommonExecExceptions(output, null);
+ public static void checkCommonExecExceptions(OutputAnalyzer output) throws Exception {
+ checkCommonExecExceptions(output, null);
}
@@ -358,6 +340,12 @@
return false;
}
+ public static void checkMappingFailure(OutputAnalyzer out) throws SkippedException {
+ if (isUnableToMap(out)) {
+ throw new SkippedException(UnableToMapMsg);
+ }
+ }
+
public static Result run(String... cliPrefix) throws Exception {
CDSOptions opts = new CDSOptions();
opts.setArchiveName(getDefaultArchiveName());
@@ -446,8 +434,7 @@
int expectedExitValue,
String... extraMatches) throws Exception {
if (isUnableToMap(output)) {
- System.out.println(UnableToMapMsg);
- return output;
+ throw new SkippedException(UnableToMapMsg);
}
output.shouldHaveExitValue(expectedExitValue);
--- a/test/lib/jtreg/SkippedException.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/lib/jtreg/SkippedException.java Thu Aug 23 11:09:16 2018 -0400
@@ -24,7 +24,7 @@
package jtreg;
/**
- * {@code SkippedException} is an exception treaded by jtreg as an indication
+ * {@code SkippedException} is an exception treated by jtreg as an indication
* of skipped status.
*/
public final class SkippedException extends RuntimeException {
--- a/test/lib/sun/hotspot/code/Compiler.java Fri Aug 10 14:56:29 2018 -0700
+++ b/test/lib/sun/hotspot/code/Compiler.java Thu Aug 23 11:09:16 2018 -0400
@@ -23,6 +23,7 @@
package sun.hotspot.code;
+import java.lang.reflect.Executable;
import sun.hotspot.WhiteBox;
/**
@@ -54,11 +55,6 @@
if (useJvmciComp == null || !useJvmciComp) {
return false;
}
- // This check might be redundant but let's keep it for now.
- String jvmciCompiler = System.getProperty("jvmci.Compiler");
- if (jvmciCompiler == null || !jvmciCompiler.equals("graal")) {
- return false;
- }
Boolean tieredCompilation = WB.getBooleanVMFlag("TieredCompilation");
Long compLevel = WB.getIntxVMFlag("TieredStopAtLevel");
@@ -133,4 +129,20 @@
}
return true;
}
+
+ /*
+ * Determine if the compiler corresponding to the compilation level 'compLevel'
+ * provides an intrinsic for 'class'.'method'.
+ */
+ public static boolean isIntrinsicAvailable(int compLevel, String klass, String method, Class<?>... parameterTypes) {
+ Executable intrinsicMethod;
+ try {
+ intrinsicMethod = Class.forName(klass).getDeclaredMethod(method, parameterTypes);
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException("Test bug, '" + method + "' method unavailable. " + e);
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException("Test bug, '" + klass + "' class unavailable. " + e);
+ }
+ return WB.isIntrinsicAvailable(intrinsicMethod, compLevel);
+ }
}