This commit is contained in:
J. Duke 2017-08-24 16:28:25 +02:00
commit 5ca6754939
19 changed files with 2816 additions and 1725 deletions

@ -432,3 +432,6 @@ b94be69cbb1d2943b886bf2d458745756df146e4 jdk-10+9
8d4ed1e06fe184c9cb08c5b708e7d6f5c066644f jdk-10+12
8f7227c6012b0051ea4e0bcee040c627bf699b88 jdk-9+175
d67a3f1f057f7e31e12f33ebe3667cb73d252268 jdk-10+13
1fd5901544acc50bb30fde9388c8e53cb7c449e4 jdk-10+14
84777531d994ef70163d35078ec9c4127f2eadb5 jdk-9+176
a4371edb589c60db01142e45c317adb9ccbcb083 jdk-9+177

@ -615,6 +615,8 @@ var getJibProfilesProfiles = function (input, common, data) {
}
var testOnlyProfilesPrebuilt = {
"run-test-prebuilt": {
target_os: input.build_os,
target_cpu: input.build_cpu,
src: "src.conf",
dependencies: [ "jtreg", "gnumake", "boot_jdk", testedProfile + ".jdk",
testedProfile + ".test", "src.full"
@ -635,13 +637,14 @@ var getJibProfilesProfiles = function (input, common, data) {
if (input.profile == "run-test-prebuilt") {
if (profiles[testedProfile] == null) {
error("testedProfile is not defined: " + testedProfile);
} else {
testOnlyProfilesPrebuilt["run-test-prebuilt"]["target_os"]
= profiles[testedProfile]["target_os"];
testOnlyProfilesPrebuilt["run-test-prebuilt"]["target_cpu"]
= profiles[testedProfile]["target_cpu"];
}
}
if (profiles[testedProfile] != null) {
testOnlyProfilesPrebuilt["run-test-prebuilt"]["target_os"]
= profiles[testedProfile]["target_os"];
testOnlyProfilesPrebuilt["run-test-prebuilt"]["target_cpu"]
= profiles[testedProfile]["target_cpu"];
}
profiles = concatObjects(profiles, testOnlyProfilesPrebuilt);
// On macosx add the devkit bin dir to the path in all the run-test profiles.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -6,7 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
<title>Testing OpenJDK</title>
<style type="text/css">code{white-space: pre;}</style>
<link rel="stylesheet" href="../../jdk/make/data/docs-resources/specs/resources/jdk-default.css">
<link rel="stylesheet" href="../../jdk/make/data/docs-resources/resources/jdk-default.css">
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
<![endif]-->

@ -592,3 +592,6 @@ e64b1cb48d6e7703928a9d1da106fc27f8cb65fd jdk-9+173
070aa7a2eb14c4645f7eb31384cba0a2ba72a4b5 jdk-10+12
8f04d457168b9f1f4a1b2c37f49e0513ca9d33a7 jdk-9+175
a9da03357f190807591177fe9846d6e68ad64fc0 jdk-10+13
e920b4d008d914f3414bd4630b58837cf0b7f08d jdk-10+14
2ab74e5dbdc2b6a962c865500cafd23cf387dc60 jdk-9+176
1ca8f038fceb88c640badf9bd18905205bc63b43 jdk-9+177

@ -748,41 +748,3 @@ bool ArrayCopyNode::modifies(intptr_t offset_lo, intptr_t offset_hi, PhaseTransf
return false;
}
// We try to replace a load from the destination of an arraycopy with
// a load from the source so the arraycopy has a chance to be
// eliminated. It's only valid if the arraycopy doesn't change the
// element that would be loaded from the source array.
bool ArrayCopyNode::can_replace_dest_load_with_src_load(intptr_t offset_lo, intptr_t offset_hi, PhaseTransform* phase) const {
assert(_kind == ArrayCopy || _kind == CopyOf || _kind == CopyOfRange, "only for real array copies");
Node* src = in(Src);
Node* dest = in(Dest);
// Check whether, assuming source and destination are the same
// array, the arraycopy modifies the element from the source we
// would load.
if ((src != dest && in(SrcPos) == in(DestPos)) || !modifies(offset_lo, offset_hi, phase, false)) {
// if not the transformation is legal
return true;
}
AllocateNode* src_alloc = AllocateNode::Ideal_allocation(src, phase);
AllocateNode* dest_alloc = AllocateNode::Ideal_allocation(dest, phase);
// Check whether source and destination can be proved to be
// different arrays
const TypeOopPtr* t_src = phase->type(src)->isa_oopptr();
const TypeOopPtr* t_dest = phase->type(dest)->isa_oopptr();
if (t_src != NULL && t_dest != NULL &&
(t_src->is_known_instance() || t_dest->is_known_instance()) &&
t_src->instance_id() != t_dest->instance_id()) {
return true;
}
if (MemNode::detect_ptr_independence(src->uncast(), src_alloc, dest->uncast(), dest_alloc, phase)) {
return true;
}
return false;
}

@ -168,7 +168,6 @@ public:
static bool may_modify(const TypeOopPtr *t_oop, MemBarNode* mb, PhaseTransform *phase, ArrayCopyNode*& ac);
bool modifies(intptr_t offset_lo, intptr_t offset_hi, PhaseTransform* phase, bool must_modify) const;
bool can_replace_dest_load_with_src_load(intptr_t offset_lo, intptr_t offset_hi, PhaseTransform* phase) const;
#ifndef PRODUCT
virtual void dump_spec(outputStream *st) const;

@ -5171,6 +5171,10 @@ bool LibraryCallKit::inline_arraycopy() {
Deoptimization::Action_make_not_entrant);
assert(stopped(), "Should be stopped");
}
const TypeKlassPtr* dest_klass_t = _gvn.type(dest_klass)->is_klassptr();
const Type *toop = TypeOopPtr::make_from_klass(dest_klass_t->klass());
src = _gvn.transform(new CheckCastPPNode(control(), src, toop));
}
arraycopy_move_allocation_here(alloc, dest, saved_jvms, saved_reexecute_sp, new_idx);

@ -885,7 +885,7 @@ static bool skip_through_membars(Compile::AliasType* atp, const TypeInstPtr* tp,
// Is the value loaded previously stored by an arraycopy? If so return
// a load node that reads from the source array so we may be able to
// optimize out the ArrayCopy node later.
Node* LoadNode::can_see_arraycopy_value(Node* st, PhaseTransform* phase) const {
Node* LoadNode::can_see_arraycopy_value(Node* st, PhaseGVN* phase) const {
Node* ld_adr = in(MemNode::Address);
intptr_t ld_off = 0;
AllocateNode* ld_alloc = AllocateNode::Ideal_allocation(ld_adr, phase, ld_off);
@ -893,23 +893,27 @@ Node* LoadNode::can_see_arraycopy_value(Node* st, PhaseTransform* phase) const {
if (ac != NULL) {
assert(ac->is_ArrayCopy(), "what kind of node can this be?");
Node* ld = clone();
Node* mem = ac->in(TypeFunc::Memory);
Node* ctl = ac->in(0);
Node* src = ac->in(ArrayCopyNode::Src);
if (!ac->as_ArrayCopy()->is_clonebasic() && !phase->type(src)->isa_aryptr()) {
return NULL;
}
LoadNode* ld = clone()->as_Load();
Node* addp = in(MemNode::Address)->clone();
if (ac->as_ArrayCopy()->is_clonebasic()) {
assert(ld_alloc != NULL, "need an alloc");
Node* addp = in(MemNode::Address)->clone();
assert(addp->is_AddP(), "address must be addp");
assert(addp->in(AddPNode::Base) == ac->in(ArrayCopyNode::Dest)->in(AddPNode::Base), "strange pattern");
assert(addp->in(AddPNode::Address) == ac->in(ArrayCopyNode::Dest)->in(AddPNode::Address), "strange pattern");
addp->set_req(AddPNode::Base, ac->in(ArrayCopyNode::Src)->in(AddPNode::Base));
addp->set_req(AddPNode::Address, ac->in(ArrayCopyNode::Src)->in(AddPNode::Address));
ld->set_req(MemNode::Address, phase->transform(addp));
if (in(0) != NULL) {
assert(ld_alloc->in(0) != NULL, "alloc must have control");
ld->set_req(0, ld_alloc->in(0));
}
addp->set_req(AddPNode::Base, src->in(AddPNode::Base));
addp->set_req(AddPNode::Address, src->in(AddPNode::Address));
} else {
Node* src = ac->in(ArrayCopyNode::Src);
Node* addp = in(MemNode::Address)->clone();
assert(ac->as_ArrayCopy()->is_arraycopy_validated() ||
ac->as_ArrayCopy()->is_copyof_validated() ||
ac->as_ArrayCopy()->is_copyofrange_validated(), "only supported cases");
assert(addp->in(AddPNode::Base) == addp->in(AddPNode::Address), "should be");
addp->set_req(AddPNode::Base, src);
addp->set_req(AddPNode::Address, src);
@ -927,21 +931,17 @@ Node* LoadNode::can_see_arraycopy_value(Node* st, PhaseTransform* phase) const {
Node* offset = phase->transform(new AddXNode(addp->in(AddPNode::Offset), diff));
addp->set_req(AddPNode::Offset, offset);
ld->set_req(MemNode::Address, phase->transform(addp));
const TypeX *ld_offs_t = phase->type(offset)->isa_intptr_t();
if (!ac->as_ArrayCopy()->can_replace_dest_load_with_src_load(ld_offs_t->_lo, ld_offs_t->_hi, phase)) {
return NULL;
}
if (in(0) != NULL) {
assert(ac->in(0) != NULL, "alloc must have control");
ld->set_req(0, ac->in(0));
}
}
addp = phase->transform(addp);
#ifdef ASSERT
const TypePtr* adr_type = phase->type(addp)->is_ptr();
ld->_adr_type = adr_type;
#endif
ld->set_req(MemNode::Address, addp);
ld->set_req(0, ctl);
ld->set_req(MemNode::Memory, mem);
// load depends on the tests that validate the arraycopy
ld->as_Load()->_control_dependency = Pinned;
ld->_control_dependency = Pinned;
return ld;
}
return NULL;

@ -270,7 +270,7 @@ protected:
const Type* load_array_final_field(const TypeKlassPtr *tkls,
ciKlass* klass) const;
Node* can_see_arraycopy_value(Node* st, PhaseTransform* phase) const;
Node* can_see_arraycopy_value(Node* st, PhaseGVN* phase) const;
// depends_only_on_test is almost always true, and needs to be almost always
// true to enable key hoisting & commoning optimizations. However, for the

@ -0,0 +1,86 @@
/*
* Copyright (c) 2017, Red Hat, Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* 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 8181742
* @summary Loads that bypass arraycopy ends up with wrong memory state
*
* @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:+UnlockDiagnosticVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+StressGCM -XX:+StressLCM TestLoadBypassACWithWrongMem
*
*/
import java.util.Arrays;
public class TestLoadBypassACWithWrongMem {
static int test1(int[] src) {
int[] dst = new int[10];
System.arraycopy(src, 0, dst, 0, 10);
src[1] = 0x42;
// dst[1] is transformed to src[1], src[1] must use the
// correct memory state (not the store above).
return dst[1];
}
static int test2(int[] src) {
int[] dst = (int[])src.clone();
src[1] = 0x42;
// Same as above for clone
return dst[1];
}
static Object test5_src = null;
static int test3() {
int[] dst = new int[10];
System.arraycopy(test5_src, 0, dst, 0, 10);
((int[])test5_src)[1] = 0x42;
System.arraycopy(test5_src, 0, dst, 0, 10);
// dst[1] is transformed to test5_src[1]. test5_src is Object
// but test5_src[1] must be on the slice for int[] not
// Object+some offset.
return dst[1];
}
static public void main(String[] args) {
int[] src = new int[10];
for (int i = 0; i < 20000; i++) {
Arrays.fill(src, 0);
int res = test1(src);
if (res != 0) {
throw new RuntimeException("bad result: " + res + " != " + 0);
}
Arrays.fill(src, 0);
res = test2(src);
if (res != 0) {
throw new RuntimeException("bad result: " + res + " != " + 0);
}
Arrays.fill(src, 0);
test5_src = src;
res = test3();
if (res != 0x42) {
throw new RuntimeException("bad result: " + res + " != " + 0x42);
}
}
}
}

@ -108,8 +108,8 @@ public class TestAnonymousClassUnloading {
*/
static public void main(String[] args) throws Exception {
// (1) Load an anonymous version of this class using the corresponding Unsafe method
URL classUrl = TestAnonymousClassUnloading.class.getResource(
TestAnonymousClassUnloading.class.getName().replace('.', '/') + ".class");
String rn = TestAnonymousClassUnloading.class.getSimpleName() + ".class";
URL classUrl = TestAnonymousClassUnloading.class.getResource(rn);
URLConnection connection = classUrl.openConnection();
int length = connection.getContentLength();

@ -74,7 +74,7 @@ public class ClassLoadUnloadTest {
List<String> argsList = new ArrayList<>();
Collections.addAll(argsList, args);
Collections.addAll(argsList, "-Xmn8m");
Collections.addAll(argsList, "-Dtest.classes=" + System.getProperty("test.classes","."));
Collections.addAll(argsList, "-Dtest.class.path=" + System.getProperty("test.class.path", "."));
Collections.addAll(argsList, ClassUnloadTestMain.class.getName());
return ProcessTools.createJavaProcessBuilder(argsList.toArray(new String[argsList.size()]));
}

@ -31,8 +31,10 @@ import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.stream.Stream;
public class ClassUnloadCommon {
public static class TestFailure extends RuntimeException {
@ -61,14 +63,45 @@ public class ClassUnloadCommon {
System.gc();
}
/**
* Creates a class loader that loads classes from {@code ${test.class.path}}
* before delegating to the system class loader.
*/
public static ClassLoader newClassLoader() {
try {
return new URLClassLoader(new URL[] {
Paths.get(System.getProperty("test.classes",".") + File.separatorChar + "classes").toUri().toURL(),
}, null);
} catch (MalformedURLException e){
throw new RuntimeException("Unexpected URL conversion failure", e);
}
String cp = System.getProperty("test.class.path", ".");
URL[] urls = Stream.of(cp.split(File.pathSeparator))
.map(Paths::get)
.map(ClassUnloadCommon::toURL)
.toArray(URL[]::new);
return new URLClassLoader(urls) {
@Override
public Class<?> loadClass(String cn, boolean resolve)
throws ClassNotFoundException
{
synchronized (getClassLoadingLock(cn)) {
Class<?> c = findLoadedClass(cn);
if (c == null) {
try {
c = findClass(cn);
} catch (ClassNotFoundException e) {
c = getParent().loadClass(cn);
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
}
};
}
static URL toURL(Path path) {
try {
return path.toUri().toURL();
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
}

@ -158,7 +158,7 @@ JAVADOC_TOP := \
JDK_SHORT_NAME := Java SE $(VERSION_SPECIFICATION) &amp; JDK $(VERSION_SPECIFICATION)
JDK_LONG_NAME := Java<sup>&reg;</sup> Platform, Standard Edition \
<span style="white-space: nowrap;">&amp; Java Development Kit</span>
&amp;&nbsp;Java&nbsp;Development&nbsp;Kit
################################################################################
# Java SE javadoc titles/text snippets
@ -206,10 +206,10 @@ define create_overview_file
#
$1_OVERVIEW_TEXT += $$(foreach g, $$($1_GROUPS), \
<dt style="margin-top: 8px;"><a href="\#$$g">$$($$g_GROUP_NAME)</a></dt> \
<dd style="margin-top: 8px;">$$($$g_GROUP_DESCRIPTION)</dt> \
<dd style="margin-top: 8px;">$$($$g_GROUP_DESCRIPTION)</dd> \
)
$1_OVERVIEW_TEXT += \
</dl><blockquote> \
</dl></blockquote> \
#
endif
$1_OVERVIEW_TEXT += \

@ -329,7 +329,7 @@ else # HAS_SPEC=true
$(call PrintFailureReports)
$(call PrintBuildLogFailures)
$(call ReportProfileTimes)
$(PRINTF) "Hint: If caused by a warning, try configure --disable-warnings-as-errors.\n\n"
$(PRINTF) "Hint: See common/doc/building.html#troubleshooting for assistance.\n\n"
ifneq ($(COMPARE_BUILD), )
$(call CleanupCompareBuild)
endif

@ -39,7 +39,7 @@ ifeq ($(PANDOC), )
$(error Cannot continue)
endif
GLOBAL_SPECS_DEFAULT_CSS_FILE := $(JDK_TOPDIR)/make/data/docs-resources/specs/resources/jdk-default.css
GLOBAL_SPECS_DEFAULT_CSS_FILE := $(JDK_TOPDIR)/make/data/docs-resources/resources/jdk-default.css
################################################################################
@ -49,6 +49,7 @@ $(eval $(call SetupProcessMarkdown, building, \
FILES := $(DOCS_DIR)/building.md, \
DEST := $(DOCS_DIR), \
CSS := $(GLOBAL_SPECS_DEFAULT_CSS_FILE), \
OPTIONS := --toc, \
))
TARGETS += $(building)

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -72,6 +72,19 @@ public class VMProps implements Callable<Map<String, String>> {
return map;
}
/**
* Prints a stack trace before returning null.
* Used by the various helper functions which parse information from
* VM properties in the case where they don't find an expected property
* or a propoerty doesn't conform to an expected format.
*
* @return null
*/
private String nullWithException(String message) {
new Exception(message).printStackTrace();
return null;
}
/**
* @return vm.simpleArch value of "os.simpleArch" property of tested JDK.
*/
@ -96,7 +109,7 @@ public class VMProps implements Callable<Map<String, String>> {
// E.g. "Java HotSpot(TM) 64-Bit Server VM"
String vmName = System.getProperty("java.vm.name");
if (vmName == null) {
return null;
return nullWithException("Can't get 'java.vm.name' property");
}
Pattern startP = Pattern.compile(".* (\\S+) VM");
@ -104,7 +117,7 @@ public class VMProps implements Callable<Map<String, String>> {
if (m.matches()) {
return m.group(1).toLowerCase();
}
return null;
return nullWithException("Can't get VM flavor from 'java.vm.name'");
}
/**
@ -114,18 +127,16 @@ public class VMProps implements Callable<Map<String, String>> {
// E.g. "mixed mode"
String vmInfo = System.getProperty("java.vm.info");
if (vmInfo == null) {
return null;
return nullWithException("Can't get 'java.vm.info' property");
}
int k = vmInfo.toLowerCase().indexOf(" mode");
if (k < 0) {
return null;
}
vmInfo = vmInfo.substring(0, k);
switch (vmInfo) {
case "mixed" : return "Xmixed";
case "compiled" : return "Xcomp";
case "interpreted" : return "Xint";
default: return null;
if (vmInfo.toLowerCase().indexOf("mixed mode") != -1) {
return "Xmixed";
} else if (vmInfo.toLowerCase().indexOf("compiled mode") != -1) {
return "Xcomp";
} else if (vmInfo.toLowerCase().indexOf("interpreted mode") != -1) {
return "Xint";
} else {
return nullWithException("Can't get compilation mode from 'java.vm.info'");
}
}
@ -133,7 +144,12 @@ public class VMProps implements Callable<Map<String, String>> {
* @return VM bitness, the value of the "sun.arch.data.model" property.
*/
protected String vmBits() {
return System.getProperty("sun.arch.data.model");
String dataModel = System.getProperty("sun.arch.data.model");
if (dataModel != null) {
return dataModel;
} else {
return nullWithException("Can't get 'sun.arch.data.model' property");
}
}
/**
@ -158,7 +174,12 @@ public class VMProps implements Callable<Map<String, String>> {
* @return debug level value extracted from the "jdk.debug" property.
*/
protected String vmDebug() {
return "" + System.getProperty("jdk.debug").contains("debug");
String debug = System.getProperty("jdk.debug");
if (debug != null) {
return "" + debug.contains("debug");
} else {
return nullWithException("Can't get 'jdk.debug' property");
}
}
/**